#define PUZZLE_MENU_TITLE "Edit Puzzle"
#define MAIN_MENU_TITLE "Main Menu"
#define INPUT_GRID_SIZE "Number of rows/columns: "
+#define INPUT_PASSWORD "Enter the password: "
#define INPUT_EXPORT_ANSWERS "Export as solution (y/N): "
#define INPUT_CHOICE "Your Choice: "
#define EXCEED_MAX_GRID_SIZE "Exceeds max puzzle size"
#define ERROR_READING_FILE "Error reading file"
#define INVALID_WORD "Word contains illegal characters. Only alphabets allowed!"
#define FILE_SAVED "File saved successfully"
+#define PASSWORD_SET "Password set successfully"
+#define PASSWORD_RESET "Password reset successfully. Puzzle is no longer \
+password protected!"
+#define WRONG_PASSWORD "Wrong password!"
#define NO_WORD_INDEX "No such word with specified index"
#define INPUT_CONFIRM_EXIT "Are you sure you wish to exit? \
Unsaved changes will be lost [y/N]"
"7. Set Clue - Across Word",
"8. Set Clue - Down Word",
"9. Save puzzle",
- "10.Reset entire grid",
- "11.Export puzzle as PNG image",
- "12.Export clues to text file",
- "13.Return to main menu" };
+ "10.Set puzzle password",
+ "11.Reset entire grid",
+ "12.Export puzzle as PNG image",
+ "13.Export clues to text file",
+ "14.Return to main menu" };
#endif
fgets (conf, 3, stdin);
if (toupper (conf[0]) == 'Y')
init_puzzle (p, grid_size);
+
+ print_puzzle (p);
+ char ch = getchar ();
+}
+
+/* set the password for the puzzle */
+void do_set_password (Puzzle *p)
+{
+ printf (INPUT_PASSWORD);
+ char password[256];
+ fgets (password, 256, stdin);
+ /* if empty reset the password to nothing */
+ if (strlen (password) == 1)
+ {
+ set_puzzle_password (p, "\0");
+ printf (PASSWORD_RESET);
+ char ch = getchar ();
+ }
+ /* set the password */
+ else
+ {
+ char *passwd = strtok (password, "\n");
+
+ set_puzzle_password (p, (const char* )passwd);
+ printf (PASSWORD_SET);
+ char ch = getchar ();
+ }
}
/* set clue for a word - only for frozen grid */
bool loop = true;
while (loop)
{
- print_menu (WHITE, BLUE, PUZZLE_MENU_TITLE, PUZZLE_EDIT_MENU, 13, 50);
+ print_menu (WHITE, BLUE, PUZZLE_MENU_TITLE, PUZZLE_EDIT_MENU, 14, 50);
printf (INPUT_CHOICE);
int ch = get_num ();
switch (ch)
printf ("%s\n",FILE_SAVED);
ch = getchar ();
break;
- case 10: do_reset_puzzle (p);
- print_puzzle (p);
- ch = getchar ();
+ case 10: do_set_password (p);
+ break;
+ case 11: do_reset_puzzle (p);
break;
- case 11: do_export_puzzle (p);
+ case 12: do_export_puzzle (p);
break;
- case 12: do_export_clues (p);
+ case 13: do_export_clues (p);
break;
- case 13: loop = ! do_confirm_exit ();
+ case 14: loop = ! do_confirm_exit ();
break;
}
}
}
/* open an existing puzzle */
-void do_open_puzzle ()
+void do_open_puzzle (const char *filename)
{
Puzzle p;
- printf (INPUT_FILE);
- char fname[256];
- fgets(fname, 256, stdin);
- if (strlen (fname) == 1)
- return;
- char* filename = strtok (fname, "\n");
+ /* if no filename is provided, get it from command line */
+ if (filename == NULL)
+ {
+ printf (INPUT_FILE);
+ char fname[256];
+ fgets(fname, 256, stdin);
+ if (strlen (fname) == 1)
+ return;
+ filename = strtok (fname, "\n");
+ }
+
p = load_puzzle (filename);
- puzzle_editor_loop (&p, filename);
+
+ if (strcmp (p.hashed_password, "\0") != 0)
+ {
+ char passwd[256];
+ printf (INPUT_PASSWORD);
+ fgets (passwd, 256, stdin);
+ if (strlen (passwd) == 1)
+ return;
+ char *pwd = strtok (passwd, "\n");
+
+ if (verify_password (&p, (const char*) pwd))
+ puzzle_editor_loop (&p, filename);
+ else
+ {
+ printf (WRONG_PASSWORD);
+ char ch = getchar ();
+ }
+ }
+ else
+ puzzle_editor_loop (&p, filename);
}
/* create a new blank puzzle */
-void do_new_puzzle ()
+void do_new_puzzle (char *filename, int size)
{
Puzzle p;
- printf (INPUT_FILE);
- char fname[256];
- fgets (fname, 256, stdin);
- if (strlen (fname) == 1)
- return;
- char* filename = strtok (fname, "\n");
- printf (INPUT_GRID_SIZE);
- int size;
- size = get_num ();
+ /* if filename is not provided get it from command line */
+ if (filename == NULL)
+ {
+ printf (INPUT_FILE);
+ char fname[256];
+ fgets (fname, 256, stdin);
+ if (strlen (fname) == 1)
+ return;
+ filename = strtok (fname, "\n");
+ }
+ /* if no size is specified get it from command line */
+ if (size == -1)
+ {
+ printf (INPUT_GRID_SIZE);
+ size = get_num ();
+ }
+
if (size > MAX_PUZZLE_SIZE)
{
printf (EXCEED_MAX_GRID_SIZE);
int ch = get_num ();
switch (ch)
{
- case 1: do_new_puzzle ();
+ case 1: do_new_puzzle (NULL, -1);
break;
- case 2: do_open_puzzle ();
+ case 2: do_open_puzzle (NULL);
break;
case 3: exit (0);
}
Puzzle p;
switch (argc)
{
- case 2 : p = load_puzzle (argv[1]);
- puzzle_editor_loop (&p, argv[1]);
+ case 2 : do_open_puzzle (argv[1]);
break;
case 4 : if (strcmp (argv[2], "new") == 0)
{
int grid_size = atoi (argv[3]);
- init_puzzle (&p, grid_size);
- puzzle_editor_loop (&p, argv[1]);
+ do_new_puzzle (argv[1], grid_size);
break;
}
default: fprintf (stderr, USAGE_LINE_1, argv[0]);
#ifndef __WORDBLOX_H
#define __WORDBLOX_H
-
+#define _XOPEN_SOURCE
+#include <unistd.h>
#include <gd.h>
#include <gdfontmb.h>
#include <gdfontg.h>
String clue_down[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE];
int grid_size;
bool grid_frozen;
+ char hashed_password[256];
+ char salt[256];
} Puzzle;
/* get a number from the user */
return n;
}
+/* verify password */
+bool verify_password (Puzzle *p, const char* password)
+{
+ /* no password set */
+ if (strcmp (p->hashed_password, "\0") == 0)
+ return true;
+
+ /* hash the user input password and compare it with the stored password */
+ char* hashed_password = crypt (password, (const char *)p->salt);
+
+ if (strcmp (p->hashed_password, hashed_password) == 0)
+ return true;
+
+ return false;
+}
+
+/* Set or reset password for puzzle */
+void set_puzzle_password (Puzzle *p, const char *password)
+{
+ /* if it is a null string, reset the password */
+ if (strcmp (password, "\0") == 0)
+ {
+ strcpy (p->hashed_password, "\0");
+ strcpy (p->salt, "\0");
+ }
+ else
+ {
+ srand (time(NULL));
+ char salt[256];
+ sprintf (salt, "puzzle%d", rand()%1000);
+ char* hashedpwd = crypt (password, (const char*)salt);
+ strcpy (p->hashed_password, hashedpwd);
+ strcpy (p->salt, salt);
+ }
+}
+
/* Output the clues to text file */
void export_clues (Puzzle *p, const char *filename)
{
strcpy (p->clue_down[i][j], "");
}
}
+ strcpy (p->hashed_password, "\0");
+ strcpy (p->salt, "\0");
+
}
-/* save the puzzle */
+/* save the puzzle to a file */
void save_puzzle (Puzzle *puzzle, const char* file) {
FILE *outfile;
- outfile = fopen (file, "wb");
+ outfile = fopen (file, "w");
if (outfile == NULL)
{
fprintf (stderr, "%s\n", ERROR_WRITING_FILE);
exit (1);
}
- fwrite (puzzle, sizeof (*puzzle), 1, outfile);
+ fprintf (outfile, "%d\n", puzzle->grid_size);
+ fprintf (outfile, "%d\n", puzzle->grid_frozen);
+ fprintf (outfile, "%s\n", puzzle->hashed_password);
+ fprintf (outfile, "%s\n", puzzle->salt);
+ for (int i = 0; i < puzzle->grid_size; i ++)
+ {
+ for (int j = 0; j < puzzle->grid_size; j ++)
+ fprintf (outfile, "%c", puzzle->chars[i][j]);
+ fprintf (outfile, "\n");
+ }
+ for (int i = 0; i < puzzle->grid_size; i ++)
+ {
+ for (int j = 0; j < puzzle->grid_size; j++)
+ {
+ fprintf (outfile, "%d ", puzzle->start_across_word[i][j]);
+ fprintf (outfile, "%d ", puzzle->start_down_word[i][j]);
+ }
+ fprintf (outfile, "\n");
+ }
+ fprintf (outfile, "ACROSS\n");
+ for (int i = 0; i < puzzle->grid_size; i ++)
+ {
+ for (int j = 0; j < puzzle->grid_size; j++)
+ {
+ if (puzzle->start_across_word[i][j] != -1)
+ fprintf (outfile, "%d\t%s\n", puzzle->start_across_word[i][j],
+ puzzle->clue_across[i][j]);
+ }
+ }
+ fprintf (outfile, "DOWN\n");
+ for (int i = 0; i < puzzle->grid_size; i ++)
+ {
+ for (int j = 0; j < puzzle->grid_size; j++)
+ {
+ if (puzzle->start_down_word[i][j] != -1)
+ fprintf (outfile, "%d\t%s\n", puzzle->start_down_word[i][j],
+ puzzle->clue_down[i][j]);
+ }
+ }
+
fclose (outfile);
}
-/* read the puzzle */
+/* read the puzzle from a file */
Puzzle load_puzzle (const char* file) {
FILE *infile;
Puzzle p;
fprintf (stderr, "%s\n", ERROR_READING_FILE);
exit (1);
}
- fread (&p, sizeof(p), 1, infile);
+ char line[MAX_CLUE_LENGTH+10];
+ fgets (line, MAX_CLUE_LENGTH + 10, infile);
+ p.grid_size = atoi (line);
+ fgets (line, MAX_CLUE_LENGTH + 10, infile);
+ p.grid_frozen = atoi (line) == 0 ? false : true ;
+ fgets (line, MAX_CLUE_LENGTH + 10, infile);
+ if (strlen (line) != 1)
+ strcpy (p.hashed_password, strtok (line, "\n"));
+ else
+ strcpy (p.hashed_password, "\0");
+ fgets (line, MAX_CLUE_LENGTH + 10, infile);
+ if (strlen (line) != 1)
+ strcpy (p.salt, strtok (line, "\n"));
+ else
+ strcpy (p.salt, "\0");
+
+ /* read each character of the grid */
+ for (int i = 0; i < p.grid_size; i ++ )
+ {
+ fgets (line, MAX_CLUE_LENGTH + 10, infile);
+ for (int j = 0; j < p.grid_size; j ++)
+ p.chars[i][j] = line[j];
+ }
+ /* read the word numbers */
+ for (int i = 0; i < p.grid_size; i ++)
+ {
+ fgets (line, MAX_CLUE_LENGTH + 10, infile);
+ char *token = strtok (line, " ");
+ for (int j = 0; j < p.grid_size; j ++)
+ {
+ if (token != NULL)
+ p.start_across_word[i][j] = atoi (token);
+ token = strtok (NULL, " ");
+ if (token != NULL)
+ p.start_down_word[i][j] = atoi (token);
+ token = strtok (NULL, " ");
+ }
+ }
+ /* read the clues */
+ fgets (line, MAX_CLUE_LENGTH + 10, infile);
+
+ /* across clues */
+ char clues[100][MAX_CLUE_LENGTH];
+ int word_num[100];
+ int c = 0;
+ /* first read the across clues from file */
+ while (1)
+ {
+ fgets (line, MAX_CLUE_LENGTH + 10, infile);
+ /* if reached the end of across clues */
+ if (strcmp (line, "DOWN\n") == 0)
+ break;
+ word_num[c] = atoi (strtok (line, "\t"));
+ char *cl = strtok (NULL, "\n");
+ if (cl != NULL)
+ strcpy (clues[c], cl);
+ else
+ strcpy (clues[c], "\0");
+ c++;
+ }
+ /* set the clue to the correct cell in grid */
+ for (int i = 0; i < p.grid_size; i ++)
+ {
+ for (int j = 0; j < p.grid_size; j ++)
+ {
+ for (int r = 0; r < c; r ++)
+ if (p.start_across_word[i][j] == word_num[r])
+ strcpy (p.clue_across[i][j], clues[r]);
+ }
+ }
+
+ /* down clues */
+ c = 0;
+ while (fgets (line, MAX_CLUE_LENGTH + 10, infile))
+ {
+ word_num[c] = atoi (strtok (line, "\t"));
+ char* cl = strtok (NULL, "\n");
+ if (cl != NULL)
+ strcpy (clues[c], cl);
+ else
+ strcpy (clues[c], "\0");
+ c++;
+ }
+ for (int i = 0; i < p.grid_size; i ++)
+ {
+ for (int j = 0; j < p.grid_size; j ++)
+ {
+ for (int r = 0; r < c; r ++)
+ if (p.start_down_word[i][j] == word_num[r])
+ strcpy (p.clue_down[i][j], clues[r]);
+ }
+ }
+
fclose (infile);
return p;
}