Compare commits

..

20 Commits

Author SHA1 Message Date
fddec0d82c . 2020-05-30 09:42:19 +01:00
e7e69263c7 tweaks 2020-05-29 15:16:34 +01:00
d6cb2c15d7 portable database location 2020-05-29 14:10:58 +01:00
4043fbd1e6 dump database 2020-05-29 13:50:59 +01:00
f2264d03c3 set property for db location 2020-05-29 13:50:51 +01:00
de4ab195ab Save input and grids to a database 2020-05-29 13:50:41 +01:00
ff53d97775 twiddle with classpath 2020-05-29 13:49:59 +01:00
5afcd67470 Increase maxtries to 5000 2020-05-29 11:12:20 +01:00
eb7a8d2801 add url footer 2020-05-29 11:00:00 +01:00
bca2d9b867 minor css tweak 2020-05-29 10:59:12 +01:00
4761199617 Improve formatting 2020-04-05 13:26:37 +01:00
cb87f5cbd5 More ignorance 2020-04-05 13:26:08 +01:00
f92d4df210 Add extra starter method 2020-04-05 13:25:51 +01:00
ce1e7a2fe5 fix makefile 2020-04-05 13:25:37 +01:00
87577944fb makefile 2020-04-05 12:25:43 +01:00
3fdd9c33ba removed C code as moved to another repo 2018-08-18 15:50:12 +01:00
55029b8b6f stash 2018-08-18 15:49:51 +01:00
2dece494e4 stash 2018-08-18 15:49:51 +01:00
foo
c10693ed17 new test case 2018-08-18 15:49:51 +01:00
911ab0006d
Create LICENSE 2018-03-18 16:14:17 +00:00
27 changed files with 274 additions and 452 deletions

2
.gitignore vendored Normal file → Executable file
View File

@ -1,3 +1,5 @@
.DS_Store
._.DS_Store
*.class
wordsearch.war
wordsearch.jar

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2018 Matthew Slowe
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

39
Makefile Executable file → Normal file
View File

@ -1,31 +1,34 @@
JAVA = /usr/bin/java
# JAVAFLAGS = -version # -classpath $(LIBS)
LIBS = .:war/WEB-INF/lib/commons-lang.jar:war/WEB-INF/lib/sqlite-jdbc.jar
JAVAC = /usr/bin/javac
JFLAGS = -g # -classpath $(LIBS)
JFLAGS = -g -classpath $(LIBS)
SRCS = uk/org/mafoo/wordsearch/GridFactory.java \
uk/org/mafoo/wordsearch/Bounds.java \
uk/org/mafoo/wordsearch/CouldNotPlaceWordException.java \
uk/org/mafoo/wordsearch/Direction.java \
uk/org/mafoo/wordsearch/DistributedRandomNumberGenerator.java
SRCS = uk/org/mafoo/wordsearch/CouldNotPlaceWordException.java \
uk/org/mafoo/wordsearch/Bounds.java \
uk/org/mafoo/wordsearch/GridFactory.java \
uk/org/mafoo/wordsearch/DistributedRandomNumberGenerator.java \
uk/org/mafoo/wordsearch/Direction.java
JSPS = $(wildcard war/*.jsp war/*.css war/WEB-INF/jspf/*.jspf)
OBJS = ${SRCS:.java=.class}
.SUFFIXES: .java .class
all: build wordsearch.jar
run: all
$(JAVA) uk.org.mafoo.wordsearch.GridFactory 30 30
.java.class:
$(JAVAC) $(JFLAGS) $<
build: $(OBJS)
.PHONY: default clean
default: wordsearch.war
clean:
rm -f $(OBJS) wordsearch.jar wordsearch.war
wordsearch.jar: build
.java.class:
$(JAVAC) $(JFLAGS) $<
wordsearch.jar: $(OBJS)
jar cf $@ $(OBJS)
cp wordsearch.jar war/WEB-INF/lib
war/WEB-INF/lib/wordsearch.jar: wordsearch.jar
cp $< $@
wordsearch.war: war/WEB-INF/lib/wordsearch.jar $(JSPS)
jar -cvf $@ -C war .

11
README.md Normal file → Executable file
View File

@ -12,15 +12,4 @@ A simple ```Makefile``` is provided:
$ make
```
Once built, you need to make a "war" file to deploy to your J2EE container (tested on Tomcat)
```
$ cd war && jar cfv ../wordsearch.war .
```
Then deploy your war file :-)
Alternatively you can test-run the engine...
```
$ make run <wordlist.txt
```

1
schema.sql Normal file
View File

@ -0,0 +1 @@
CREATE TABLE grids (id integer primary key, ts timestamp default current_timestamp, remotehost varchar, input, size_x int, size_y int, simple tinyint, result varchar);

View File

@ -1,12 +0,0 @@
CC=gcc
CFLAGS=-DDEBUG_GRID_MAIN -std=c99 -g
DEPS=dir.o rnd.o grid.o
wordsearch: $(DEPS)
$(CC) -o wordsearch $(DEPS) $(CFLAGS)
%.o: %.c
$(CC) -c -o $@ $< $(CFLAGS)
clean:
rm $(DEPS)

View File

@ -1,39 +0,0 @@
#include "dir.h"
#include "rnd.h"
int directions[] = {
DIRECTION_N,
DIRECTION_NE,
DIRECTION_E,
DIRECTION_SE,
DIRECTION_S,
DIRECTION_SW,
DIRECTION_W,
DIRECTION_NW
};
int get_direction(int simple)
{
if (simple) {
if (random_number(0, 1) == 0) {
return DIRECTION_E;
} else {
return DIRECTION_S;
}
} else {
return directions[random_number(0, NUM_DIRECTIONS)];
}
}
#ifdef DEBUG_DIR_MAIN
#include <stdio.h>
int main()
{
int n = 32;
while (--n > 0) {
printf("%d\n", get_direction(1));
}
return 0;
}
#endif

View File

@ -1,19 +0,0 @@
#ifndef WORDSEARCH_DIR
#define WORDSEARCH_DIR
enum direction {
DIRECTION_N,
DIRECTION_NE,
DIRECTION_E,
DIRECTION_SE,
DIRECTION_S,
DIRECTION_SW,
DIRECTION_W,
DIRECTION_NW
};
#define NUM_DIRECTIONS 8
int get_direction(int simple);
#endif

View File

@ -1,197 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <ctype.h>
#include "rnd.h"
#include "dir.h"
#include "grid.h"
enum exitcodes {
EXIT_WORDTOOLONG,
};
bounds *get_bounds(int height, int width, enum direction direction, int length)
{
if (length > height || length > width) {
return NULL;
}
length--;
bounds *b = (bounds *) malloc(sizeof(bounds));
b->min_x = 0;
b->max_x = width-1;
b->min_y = 0;
b->max_y = height-1;
if (direction == DIRECTION_N ||
direction == DIRECTION_NE || direction == DIRECTION_NW) {
b->min_y = length;
}
if (direction == DIRECTION_W ||
direction == DIRECTION_NW || direction == DIRECTION_SW) {
b->min_x = length;
}
if (direction == DIRECTION_E ||
direction == DIRECTION_NE || direction == DIRECTION_SE) {
b->max_x = width - length;
}
if (direction == DIRECTION_S ||
direction == DIRECTION_SW || direction == DIRECTION_SE) {
b->max_y = height - length;
}
return b;
}
int move_x(int x, enum direction d) {
if(
d == DIRECTION_E ||
d == DIRECTION_NE ||
d == DIRECTION_SE
) {
x++;
} else if (
d == DIRECTION_W ||
d == DIRECTION_NW ||
d == DIRECTION_SW
) {
x--;
}
return x;
}
int move_y(int y, enum direction d) {
if(
d == DIRECTION_N ||
d == DIRECTION_NE ||
d == DIRECTION_NW
) {
y--;
} else if (
d == DIRECTION_S ||
d == DIRECTION_SE ||
d == DIRECTION_SW
) {
y++;
}
return y;
}
char **make_grid(char **words, int height, int width, int simple, int count)
{
char **grid = init_grid(NULL, height, width);
for(int i=0; i<count; i++) {
int tries = 0;
int placed = 0;
while(tries++ < WORDSEARCH_MAXTRIES && placed == 0) {
if(place_word(words[i], grid, height, width, simple)) {
placed = 1;
}
}
}
return grid;
}
int place_word(char *word, char **grid, int height, int width, int simple)
{
int dir = get_direction(simple);
bounds *b;
if (b = get_bounds(height, width, dir, strlen(word))) {
/* word will probably fit... */
int x, y;
x = random_number(b->min_x, b->max_x);
y = random_number(b->min_y, b->max_y);
char** tempgrid = init_grid(grid, height, width);
/* Now we have two copies of the grid, try to place the word... */
int i;
for(i=0; i<strlen(word); i++) {
if(!isalpha(word[i])) continue;
if(tempgrid[y][x] != '_') {
if(tempgrid[y][x] != word[i]) {
/* Failed to place word */
free_grid(tempgrid, height);
return 0;
} else {
/* word crossed ok! */
}
} else {
tempgrid[y][x] = word[i];
}
x = move_x(x, dir);
y = move_y(y, dir);
}
free_grid(grid, height);
free(b);
grid = tempgrid;
return 1;
} else {
/* word can't fit */
printf("[ERR] Word too long to place in this grid: %s\n", word);
exit(EXIT_WORDTOOLONG);
}
}
/* Clones or creates an empty grid - pass NULL in as old to get an empty grid */
char **init_grid(char** old, int height, int width)
{
int row, cell;
char **new = malloc(height * sizeof(char*));
for (row=0; row < height; row++) {
new[row] = malloc(width * sizeof(char));
for (cell=0; cell < width; cell++) {
if(old) {
new[row][cell] = old[row][cell];
} else {
new[row][cell] = '_';
}
}
}
return new;
}
void free_grid(char** grid, int height) {
for (int i=0; i<height; i++) {
free(grid[i]);
}
free(grid);
}
void print_grid(char** grid, int height) {
for(int i=0; i<height; i++) {
if(grid[i] == NULL) {
printf("row error\n");
} else {
printf("%s\n", grid[i]);
}
}
}
#ifdef DEBUG_GRID_MAIN
#include <stdio.h>
int main()
{
char *words[4] = {
"test",
"word",
"longer",
"verylong"
};
char **grid = make_grid(words, 10, 10, 0, 4);
print_grid(grid, 4);
}
#endif

View File

@ -1,26 +0,0 @@
#ifndef WORDSEARCH_GRID
#define WORDSEARCH_GRID
#define WORDSEARCH_MAXTRIES 500
char **make_grid(char **words, int height, int width, int simple, int count);
typedef struct bounds {
int min_y;
int max_y;
int min_x;
int max_x;
} bounds;
/* returns NULL if cannot fit word; caller needs to free() the response */
bounds *get_bounds(int height, int width, enum direction direction, int length);
int place_word(char *word, char **grid, int height, int width, int simple);
char **init_grid(char** old, int height, int width);
void free_grid(char** grid, int height);
int move_x(int x, enum direction d);
int move_y(int y, enum direction d);
void print_grid(char** grid, int height);
#endif

View File

@ -1,90 +0,0 @@
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "rnd.h"
/* https://www.math.cornell.edu/~mec/2003-2004/cryptography/subs/frequencies.html */
#define ALPHABET_SIZE 26
#define RND_MAXINT 10000
struct letter_frequency {
int p; /* pegged to 10000 rather than 1 */
char c;
} letter_frequencies[] = {
{
7, 'Z'}, {
10, 'J'}, {
11, 'Q'}, {
17, 'X'}, {
69, 'K'}, {
111, 'V'}, {
149, 'B'}, {
182, 'P'}, {
203, 'G'}, {
209, 'W'}, {
211, 'Y'}, {
230, 'F'}, {
261, 'M'}, {
271, 'C'}, {
288, 'U'}, {
398, 'L'}, {
432, 'D'}, {
592, 'H'}, {
602, 'R'}, {
628, 'S'}, {
695, 'N'}, {
731, 'I'}, {
768, 'O'}, {
812, 'A'}, {
910, 'T'}, {
1202, 'E'},};
/* from http://stackoverflow.com/questions/822323/how-to-generate-a-random-number-in-c */
int random_number(int min_num, int max_num)
{
static int initialised = 0;
int result = 0;
int low_num = 0;
int hi_num = 0;
if (min_num < max_num) {
low_num = min_num;
hi_num = max_num + 1; // this is done to include max_num in output.
} else {
low_num = max_num + 1; // this is done to include max_num in output.
hi_num = min_num;
}
if (!initialised) {
srand(time(NULL));
initialised = 1;
}
result = (rand() % (hi_num - low_num)) + low_num;
return result;
}
char get_random_letter()
{
int rnd = random_number(0, RND_MAXINT);
for (int i = 0; i < ALPHABET_SIZE; i++) {
if (rnd < letter_frequencies[i].p) {
return letter_frequencies[i].c;
}
rnd -= letter_frequencies[i].p;
}
return '\0';
}
#ifdef DEBUG_RND_MAIN
#include <stdio.h>
int main()
{
int n = 32;
while (--n > 0) {
printf("%c", get_random_letter());
}
return 0;
}
#endif

View File

@ -1,7 +0,0 @@
#ifndef WORDSEARCH_RND
#define WORDSEARCH_RND
char get_random_letter();
int random_number(int min_num, int max_num);
#endif

9
test.txt Executable file
View File

@ -0,0 +1,9 @@
Kitchen
Lounge
Study
Ballroom
Conservatory
Billiard Room
Library
Hall
Dining Room

0
uk/org/mafoo/wordsearch/Direction.java Normal file → Executable file
View File

View File

@ -6,7 +6,7 @@ import java.util.*;
public class GridFactory {
static Random rnd = new Random();
static final int MAX_TRIES = 500;
static final int MAX_TRIES = 5000;
/* https://www.math.cornell.edu/~mec/2003-2004/cryptography/subs/frequencies.html */
static DistributedRandomNumberGenerator drng = new DistributedRandomNumberGenerator();
@ -37,7 +37,7 @@ public class GridFactory {
drng.addNumber(23, 0.0017d); // X
drng.addNumber(24, 0.0211d); // Y
drng.addNumber(25, 0.0007d); // Z
}
}
private static char[] chars = new char[] {
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'
@ -77,10 +77,10 @@ public class GridFactory {
Bounds b = new Bounds(0, height, 0, width);
length--; // arrays, duh
if(
direction == Direction.N ||
direction == Direction.NE ||
direction == Direction.N ||
direction == Direction.NE ||
direction == Direction.NW
) {
b.min_y = length;
@ -158,6 +158,10 @@ public class GridFactory {
return makeGrid(words, height, width, false, true);
}
public static char[][] makeGrid(List<String> words, int height, int width, boolean simple) {
return makeGrid(words, height, width, simple, true);
}
public static char[][] makeGrid(List<String> words, int height, int width, boolean simple, boolean fill) {
char[][] grid = new char[height][width];
@ -184,7 +188,7 @@ public class GridFactory {
if(fill) {
for (int y=0; y<height; y++) {
for (int x=0; x<width; x++) {
if (grid[y][x] == Character.UNASSIGNED)
if (grid[y][x] == Character.UNASSIGNED)
// grid[y][x] = '_';
grid[y][x] = getRandomChar();
}
@ -198,7 +202,7 @@ public class GridFactory {
Direction direction = getDirection(simple);
Bounds b = getBounds(grid.length, grid[0].length, direction, word.length());
// System.out.println("[" + word + "] bounds: " + b);
int x = rnd.nextInt(b.max_x - b.min_x) + b.min_x;
int y = rnd.nextInt(b.max_y - b.min_y) + b.min_y;
@ -216,7 +220,7 @@ public class GridFactory {
tempgrid[y][x] = c;
x = move_x(x, direction);
y = move_y(y, direction);
}
return tempgrid;
}

View File

@ -0,0 +1,3 @@
<div id="footer">
Generated at: https://bombadil.mafoo.org.uk/wordsearch/
</div>

0
war/WEB-INF/lib/commons-lang.jar Normal file → Executable file
View File

0
war/WEB-INF/lib/json-simple-1.1.1.jar Normal file → Executable file
View File

View File

@ -10,4 +10,20 @@
Wordsearch building app
</description>
</web-app>
<context-param>
<param-name>sqlite_db</param-name>
<param-value>/tmp/wordsearch.db</param-value>
</context-param>
<security-constraint>
<web-resource-collection>
<web-resource-name>dump</web-resource-name>
<url-pattern>/dump.jsp</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>admin</role-name>
</auth-constraint>
</security-constraint>
</web-app>

View File

@ -3,6 +3,7 @@
<head>
<title>Wordsearch Builder: About</title>
<link rel="stylesheet" type="text/css" href="base.css" />
<link href="https://fonts.googleapis.com/css2?family=Fira+Mono:wght@400;500&family=Roboto:wght@500&display=swap" rel="stylesheet">
</head>
<body>

0
war/api.jsp Normal file → Executable file
View File

20
war/base.css Normal file → Executable file
View File

@ -1,5 +1,5 @@
body {
font-family: sans-serif;
body {
font-family: 'Roboto', sans-serif;
}
.tooltip {
@ -14,17 +14,16 @@ table, th, td {
}
table#grid td {
font-family: monospace;
font-size: 22px;
font-family: 'Fira Mono', monospace;
font-size: 14pt;
}
#wrapper {
width: 80%;
margin: 0 auto 60px auto;
align-content: center;
}
#wordsearch {
float: left;
margin-bottom: 24px;
}
#words {
@ -35,8 +34,11 @@ table#grid td {
#footer {
position:absolute;
bottom:0;
width:100%;
height:60px; /* Height of the footer */
}
textarea#textarea_words {
font-family: 'Fira Mono', monospace;
font-size: 10pt;
}
@media only print {

View File

@ -3,11 +3,15 @@
<head>
<title>Wordsearch builder</title>
<link rel="stylesheet" type="text/css" href="base.css" />
<link href="https://fonts.googleapis.com/css2?family=Fira+Mono:wght@400;500&family=Roboto:wght@500&display=swap" rel="stylesheet">
</head>
<%@ page import="uk.org.mafoo.wordsearch.*" %>
<%@ page import="java.util.*" %>
<%@ page import="org.apache.commons.lang.StringUtils" %>
<%@ page import="org.apache.commons.lang.StringEscapeUtils" %>
<%@ page import="java.sql.*" %>
<%@ page import="org.sqlite.*" %>
<%@ page errorPage="error.jsp" %>
<%
@ -21,24 +25,55 @@
List<String> words = new ArrayList<String>();
for ( String line : request.getParameter("words").split("\r\n")) {
words.add(line.trim());
words.add(line.trim().toLowerCase());
}
Collections.sort(words);
Collections.sort(words);
char[][] grid = GridFactory.makeGrid(words, height, width, simple);
Connection conn = DriverManager.getConnection(
"jdbc:sqlite:" + getServletContext().getRealPath("/WEB-INF/files/database.sqlite"));
PreparedStatement stmt = conn.prepareStatement(
"INSERT INTO grids (remotehost, input, size_x, size_y, simple) VALUES (?, ?, ?, ?, ?)",
Statement.RETURN_GENERATED_KEYS);
// PreparedStatement getlastid = conn.prepareStatement("select last_insert_rowid();");
PreparedStatement stmt2 = conn.prepareStatement("UPDATE grids SET result=? WHERE id=?");
String csv = "";
stmt.setString(1, request.getRemoteHost());
stmt.setString(2, words.toString());
stmt.setInt(3, height);
stmt.setInt(4, width);
stmt.setBoolean(5, simple);
stmt.executeUpdate();
ResultSet record_id_rs = stmt.getGeneratedKeys();
int record_id = -1;
if(record_id_rs.next()){
record_id = record_id_rs.getInt(1);
}
// Actually generate the grid
char[][] grid = GridFactory.makeGrid(words, height, width, simple);
StringBuilder _csv = new StringBuilder();
for (char[] cs : grid) {
for(char c : cs) {
_csv.append(c);
_csv.append(",");
}
_csv.append("\r\n");
}
String csv = _csv.toString();
stmt2.setString(1, csv);
stmt2.setInt(2, record_id);
stmt2.executeUpdate();
conn.close();
%>
<body>
<h1><%= name %></h1>
<div class="noprint">
[ <a href="index.jsp">Start again</a> | <a id='csvdownload'>Download CSV</a> ]
[ <a href="index.jsp">Start again</a> | <a id='csvdownload' href="data:text/csv;base64,<%= Base64.getEncoder().encodeToString(csv.getBytes()) %>">Download CSV</a> ]
</div>
<script>
var csv = '<%= csv %>';
var csvdownload = document.getElementById('csvdownload');
csvdownload.href='data:text/csv;base64,' + btoa(csv);
</script>
</div>
<div id="wrapper">
@ -47,18 +82,18 @@
<table id="grid">
<% for(char[] row : grid) { %>
<tr>
<% for(char c : row) {
<% for(char c : row) {
csv += "" + c + ',';
%>
<td class="cell"><%= c %></td>
<% } %>
</tr>
<%
<%
csv += "\\n";
}
%>
</table>
</div> <!-- end wordsearch -->
</div> <!-- end wordsearch -->
<div id="words">
<h2>Words</h2>
@ -68,7 +103,7 @@
<% } %>
</ul>
</div> <!-- end words -->
</div> <!-- end wrapper -->
</div> <!-- end wrapper -->
<br />
<br />
<%@include file="/WEB-INF/jspf/footer.jspf" %>

53
war/db.jsp Normal file
View File

@ -0,0 +1,53 @@
<%@ page contentType="text/html" %>
<%@ page import="java.sql.*" %>
<%@ page import="org.sqlite.*" %>
<!DOCTYPE html>
<html lang="en">
<head>
<title>Database dump</title>
</head>
<body>
<h1>Database stats</h1>
<%
Connection conn =
DriverManager.getConnection("jdbc:sqlite:" + getServletContext().getRealPath("/WEB-INF/files/database.sqlite"));
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from sqlite_master where type='table' and name='grids';");
if(rs.next()) {
// we have a row and are probably ok
} else {
// Initialise the schema
PreparedStatement pstmt = conn.prepareStatement("CREATE TABLE grids (id integer primary key, ts timestamp default current_timestamp, remotehost varchar, input, size_x int, size_y int, simple tinyint, result varchar);");
pstmt.execute();
}
rs.close();
PreparedStatement ps_count = conn.prepareStatement("SELECT COUNT(*) FROM grids");
PreparedStatement ps_last = conn.prepareStatement("SELECT max(ts) FROM grids;");
ResultSet rs_count = ps_count.executeQuery();
ResultSet rs_last = ps_last.executeQuery();
int count = -1;
String last = "unknown";
if(rs_count.next()) {
count = rs_count.getInt(1);
}
if(rs_last.next()) {
last = rs_last.getString(1);
}
rs_count.close();
rs_last.close();
%>
<ul>
<li>Number of grids generated: <%= count %></li>
<li>Last grid generated at: <%= last %></li>
<li>Path to db: <pre><%= getServletContext().getRealPath("/WEB-INF/files/database.sqlite") %></pre></li>
</ul>
</body>
<%
conn.close();
%>
</html>

50
war/dump.jsp Normal file
View File

@ -0,0 +1,50 @@
<%@ page contentType="text/html" %>
<%@ page import="java.sql.*" %>
<%@ page import="org.sqlite.*" %>
<!DOCTYPE html>
<html lang="en">
<head>
<title>Database dump</title>
</head>
<body>
<table border="1">
<thead>
<th>id</th>
<th>timestamp</th>
<th>remotehost</th>
<th>input</th>
<th>size_x</th>
<th>size_y</th>
<th>simple</th>
<th>result</th>
</thead>
<tbody>
<%
Connection conn =
DriverManager.getConnection("jdbc:sqlite:" + getServletContext().getInitParameter("sqlite_db"));
Statement stat = conn.createStatement();
ResultSet rs = stat.executeQuery("select * from grids;");
while (rs.next()) {
out.println("<tr>");
out.println("<td>" + rs.getString("id") + "</td>");
out.println("<td>" + rs.getString("ts") + "</td>");
out.println("<td>" + rs.getString("remotehost") + "</td>");
out.println("<td><pre>" + rs.getString("input") + "</pre></td>");
out.println("<td>" + rs.getInt("size_x") + "</td>");
out.println("<td>" + rs.getInt("size_y") + "</td>");
out.println("<td>" + rs.getInt("simple") + "</td>");
out.println("<td><pre>" + rs.getString("result") + "</pre></td>");
out.println("</tr>");
}
rs.close();
conn.close();
%>
</tbody>
</table>
</body>
</html>

22
war/env.jsp Normal file
View File

@ -0,0 +1,22 @@
<!DOCTYPE html>
<html>
<head></head>
<body>
<h1>Environment</h1>
<ul>
<li>You are connecting from: <%= request.getRemoteHost() %> (<%= request.getRemoteAddr() %>)</li>
<li>If present your X-Forwarded-For header is: <%= request.getHeader("X-Forwarded-For") %></li>
</ul>
<h2>Header dump</h2>
<pre>
<%
for (java.util.Enumeration<String> headers = request.getHeaderNames(); headers.hasMoreElements(); ) {
String h = headers.nextElement();
%>
<%= h %>=<%= request.getHeader(h) %>
<%
}
%>
</pre>
</body>

View File

@ -3,6 +3,7 @@
<head>
<title>Wordsearch Builder</title>
<link rel="stylesheet" type="text/css" href="base.css" />
<link href="https://fonts.googleapis.com/css2?family=Fira+Mono:wght@400;500&family=Roboto:wght@500&display=swap" rel="stylesheet">
</head>
<body>
<h1>Wordsearch Builder</h1>
@ -11,7 +12,7 @@
<h2>Words</h2>
<form action="build.jsp" method="post">
Name: <input type="text" size="25" name="name" value="Wordsearch"><br />
<textarea name="words" rows="10">
<textarea id="textarea_words" name="words" rows="10">
Kitchen
Lounge
Study