int AddPageVar(PageVar *varlist, char *cmd) { char *name = strchr(cmd, ':') + 1; char *value = strchr(name, ':') + 1; char *end = strchr(cmd, ']'); if (value - name > sizeof(varlist->name)) { // Invalid name length return -1; } PageVar *pagevar = GetPageVar(varlist, name, value -1); if (pagevar != NULL) { // Special case, variable already exists if (pagevar->value != NULL) { free(pagevar->value); } } else { // Add new variable to end of list pagevar = varlist; while (pagevar->next != NULL) { pagevar = pagevar->next; } pagevar->next = calloc(sizeof(PageVar), 1); VerifyPointerOrTerminate(pagevar->next, "New PageVar"); pagevar = pagevar->next; } cgc_memcpy(pagevar->name, name, value - 1 - name); #ifdef PATCHED if (end - value <= 0) { return -1; } #endif pagevar->value = calloc(end - value + 1, 1); VerifyPointerOrTerminate(pagevar->value, "PageVar->value"); cgc_memcpy(pagevar->value, value, end - value); return 1; }
// Initializes the server by loading pages into memory int InitializeTree() { TreeNode *ptr; for (int i = 0; i < NUM_INITIAL_PAGES; ++i) { TreeNode *node = calloc(sizeof(TreeNode), 1); VerifyPointerOrTerminate(node, "TreeNode during initialization"); strncpy(node->name, InitialInfo[i].name, sizeof(node->name)); node->page_size = strlen(InitialInfo[i].data) + 1; node->page = calloc(node->page_size, 1); VerifyPointerOrTerminate(node->page, "node->page during initialization"); memcpy(node->page, InitialInfo[i].data, node->page_size); if (InsertNodeInTree(node) != 0) { free(node->page); free(node); return -1; } } return 0; }
int InsertNodeInTree(TreeNode *node) { if (root == NULL) { TreeNode *node = calloc(sizeof(TreeNode), 1); VerifyPointerOrTerminate(node, "root TreeNode during insert"); node->name[0] = '.'; root = node; } // Make sure node doesn't exist if (LookupNode(node->name) != NULL) { printf("ERROR: node already exists\n"); return -1; } // Make sure name isn't blank if (node->name[0] == '\0') { printf("ERROR: Name cannot be blank\n"); return -1; } // Lookup parent node char local_name[64]; memcpy(local_name, node->name, sizeof(local_name)); char *last_part = strrchr(local_name, '.'); TreeNode *insert_location = root; // If no subparts in name, insert as child to root if (last_part == NULL) { if (insert_location->child == NULL) { insert_location->child = node; } else { insert_location = insert_location->child; while (insert_location->peer != NULL) { insert_location = insert_location->peer; } insert_location->peer = node; } return 0; } // Strip leading portion of name strncpy(node->name, last_part + 1, sizeof(node->name)); last_part[0] = '\0'; insert_location = LookupNode(local_name); if (insert_location == NULL) { printf("ERROR: Parent node doesn't exist: @s\n", local_name); return -1; } if (insert_location->child == NULL) { insert_location->child = node; return 0; } else { insert_location = insert_location->child; while (insert_location->peer != NULL) { insert_location = insert_location->peer; } insert_location->peer = node; return 0; } }
// Processes user supplied variable definitions and then serves the requested // page using those variables. // Variable definitions are in the same syntax as those scripted in a page // eg. [var:name:value][var:name2:value2] int InteractWithPage(char *page, int page_size, char *override_data) { #ifdef PATCHED if (override_data == NULL) { return ServePageWithOverride(page, page_size, NULL); } #endif PageVar *override_list = calloc(sizeof(PageVar), 1); VerifyPointerOrTerminate(override_list, "Override_list initialization"); // Process override variable definitions while(*override_data != '\0' && *override_data != ']') { // Check for start of var definition if (*override_data != '[') { break; } // Process var definition AddPageVar(override_list, override_data); // Locate end of var definition char *end_of_var = strchr(override_data, ']'); if (end_of_var == NULL) { break; } // Step over var definition override_data = end_of_var + 1; } // Serve page with overridden variables return ServePageWithOverride(page, page_size, override_list); }
// Serves a page by interpreting command codes, processing script commands, // and handling variable substitution. Any variables provided in the override_list // will take precedence over variables of the same name defined in the page. int ServePageWithOverride(char *page, int page_size, PageVar *override_list) { // Initialize varlist PageVar *varlist = calloc(sizeof(PageVar), 1); VerifyPointerOrTerminate(varlist, "VarList initialization"); in_a_box = 0; cgc_memset(line, '\0', sizeof(line)); line_length = 0; #ifdef PATCHED if (page == NULL) { goto error; } #endif while ((*page != '\0')&&(page < page + page_size)) { if (*page == '~') { // Command character, process command page++; switch (*page) { case 't': { for (int i=0; i<4; i++) { OutputChar(' '); } break; } case 'n': { FlushOutput(); break; } case '[': { OutputChar('['); break; } case ']': { OutputChar(']'); break; } case '~': { OutputChar('~'); break; } case '#': { OutputChar('#'); break; } default: { printf("ERROR: Invalid control code\n"); goto error; } } page++; } else if (*page == '[') { // Script tag, find closing tag and process script char *close = ++page; while (*close != ']' && *close != '\0') close++; if (*close == '\0') { goto error; } // Process script commands if (strncmp(page, "line", cgc_strlen("line")) == 0) { page += cgc_strlen("line"); if (*page != ':') { goto error; } char c = *(++page); if (*(++page) != ':') { goto error; } int length = atoi(++page); for (int i = 0; i < length; i++) { OutputChar(c); } page = close + 1; } else if (strncmp(page, "var", cgc_strlen("var")) == 0) { AddPageVar(varlist, page); page = close + 1; } else if (strncmp(page, "box", cgc_strlen("box")) == 0) { in_a_box = 1; FlushOutput(); for (int i = 0; i < 80; i++) { putc('*'); } printf("\n"); page += 4; } } else if (*page == ']') { page++; if (in_a_box) { in_a_box = 0; FlushOutput(); for (int i = 0; i < 80; i++) { putc('*'); } printf("\n"); } else { goto error; } } else if (*page == '#') { // Variable substitution char *end = ++page; while (*end != '\0' && *end != '#') { end++; } if (*end != '#') { goto error; } PageVar *var = NULL; // Check for overridden variables if (override_list != NULL) { var = GetPageVar(override_list, page, end); } // Fall back to default values if override doesn't exist if (var == NULL) { var = GetPageVar(varlist, page, end); } // If a value has been found, output it if (var != NULL) { OutputStr(var->value); } page = end + 1; } else { // Normal character, send to output OutputChar(*page); page++; } } if (line_length != 0) { FlushOutput(); } DestroyVarList(varlist); DestroyVarList(override_list); return 0; error: printf("ERROR: Invalid syntax\n"); DestroyVarList(varlist); DestroyVarList(override_list); return -1; }