error_t httpServerUriNotFoundCallback(HttpConnection *connection, const char_t *uri) { error_t error; size_t n; char_t *buffer; //Process data.xml file? if(!strcasecmp(uri, "/data.xml")) { //Point to the scratch buffer buffer = connection->buffer + 384; //Format XML data n = sprintf(buffer, "<data>\r\n"); n += sprintf(buffer + n, " <ax>%d</ax>\r\n", ax); n += sprintf(buffer + n, " <ay>%d</ay>\r\n", ay); n += sprintf(buffer + n, " <az>%d</az>\r\n", az); n += sprintf(buffer + n, " <adc>%u</adc>\r\n", adcValue); n += sprintf(buffer + n, " <joystick>%u</joystick>\r\n", joystickState); //End of XML data n += sprintf(buffer + n, "</data>\r\n"); //Format HTTP response header connection->response.version = connection->request.version; connection->response.statusCode = 200; connection->response.keepAlive = connection->request.keepAlive; connection->response.noCache = TRUE; connection->response.contentType = mimeGetType(".xml"); connection->response.chunkedEncoding = FALSE; connection->response.contentLength = n; //Send the header to the client error = httpWriteHeader(connection); //Any error to report? if(error) return error; //Send response body error = httpWriteStream(connection, buffer, n); //Any error to report? if(error) return error; //Properly close output stream error = httpCloseStream(connection); //Return status code return error; } //Process send_mail.xml file? else if(!strcasecmp(uri, "/send_mail.xml")) { char_t *separator; char_t *property; char_t *value; char_t *p; SmtpAuthInfo authInfo; SmtpMail mail; SmtpMailAddr recipients[4]; //Initialize structures to zero memset(&authInfo, 0, sizeof(authInfo)); memset(&mail, 0, sizeof(mail)); memset(recipients, 0, sizeof(recipients)); //Set the relevant PRNG algorithm to be used authInfo.prngAlgo = YARROW_PRNG_ALGO; authInfo.prngContext = &yarrowContext; //Set email recipients mail.recipients = recipients; //Point to the scratch buffer buffer = connection->buffer; //Start of exception handling block do { //Process HTTP request body while(1) { //Read the HTTP request body until an ampersand is encountered error = httpReadStream(connection, buffer, HTTP_SERVER_BUFFER_SIZE - 1, &n, HTTP_FLAG_BREAK('&')); //End of stream detected? if(error) break; //Properly terminate the string with a NULL character buffer[n] = '\0'; //Remove the trailing ampersand if(n > 0 && buffer[n - 1] == '&') buffer[--n] = '\0'; //Decode the percent-encoded string httpDecodePercentEncodedString(buffer, buffer, HTTP_SERVER_BUFFER_SIZE); //Check whether a separator is present separator = strchr(buffer, '='); //Separator found? if(separator) { //Split the line *separator = '\0'; //Get property name and value property = strTrimWhitespace(buffer); value = strTrimWhitespace(separator + 1); //Check property name if(!strcasecmp(property, "server")) { //Save server name authInfo.serverName = strDuplicate(value); } else if(!strcasecmp(property, "port")) { //Save the server port to be used authInfo.serverPort = atoi(value); } else if(!strcasecmp(property, "userName")) { //Save user name authInfo.userName = strDuplicate(value); } else if(!strcasecmp(property, "password")) { //Save password authInfo.password = strDuplicate(value); } else if(!strcasecmp(property, "useTls")) { //Open a secure SSL/TLS session? authInfo.useTls = TRUE; } else if(!strcasecmp(property, "recipient")) { //Split the recipient address list value = strtok_r(value, ", ", &p); //Loop through the list while(value != NULL) { //Save recipient address recipients[mail.recipientCount].name = NULL; recipients[mail.recipientCount].addr = strDuplicate(value); recipients[mail.recipientCount].type = SMTP_RCPT_TYPE_TO; //Get the next item in the list value = strtok_r(NULL, ", ", &p); //Increment the number of recipients if(++mail.recipientCount >= arraysize(recipients)) break; } } else if(!strcasecmp(property, "from")) { //Save sender address mail.from.name = NULL; mail.from.addr = strDuplicate(value); } else if(!strcasecmp(property, "date")) { //Save current time mail.dateTime = strDuplicate(value); } else if(!strcasecmp(property, "subject")) { //Save mail subject mail.subject = strDuplicate(value); } else if(!strcasecmp(property, "body")) { //Save mail body mail.body = strDuplicate(value); } } } //Propagate exception if necessary if(error != ERROR_END_OF_STREAM) break; //Send mail error = smtpSendMail(&authInfo, &mail); //Point to the scratch buffer buffer = connection->buffer + 384; //Format XML data n = sprintf(buffer, "<data>\r\n <status>"); if(error == NO_ERROR) n += sprintf(buffer + n, "Mail successfully sent!\r\n"); else if(error == ERROR_NAME_RESOLUTION_FAILED) n += sprintf(buffer + n, "Cannot resolve SMTP server name!\r\n"); else if(error == ERROR_AUTHENTICATION_FAILED) n += sprintf(buffer + n, "Authentication failed!\r\n"); else if(error == ERROR_UNEXPECTED_RESPONSE) n += sprintf(buffer + n, "Unexpected response from SMTP server!\r\n"); else n += sprintf(buffer + n, "Failed to send mail (error %d)!\r\n", error); n += sprintf(buffer + n, "</status>\r\n</data>\r\n"); //Format HTTP response header connection->response.version = connection->request.version; connection->response.statusCode = 200; connection->response.keepAlive = connection->request.keepAlive; connection->response.noCache = TRUE; connection->response.contentType = mimeGetType(".xml"); connection->response.chunkedEncoding = FALSE; connection->response.contentLength = n; //Send the header to the client error = httpWriteHeader(connection); //Any error to report? if(error) break; //Send response body error = httpWriteStream(connection, buffer, n); //Any error to report? if(error) break; //Properly close output stream error = httpCloseStream(connection); //Any error to report? if(error) break; //End of exception handling block } while(0); //Free previously allocated memory osFreeMem((void *) authInfo.serverName); osFreeMem((void *) authInfo.userName); osFreeMem((void *) authInfo.password); osFreeMem((void *) recipients[0].addr); osFreeMem((void *) mail.from.addr); osFreeMem((void *) mail.dateTime); osFreeMem((void *) mail.subject); osFreeMem((void *) mail.body); //Return status code return error; } else { return ERROR_NOT_FOUND; } }
error_t httpServerProcessSetConfig(HttpConnection *connection) { error_t error; uint_t i; size_t n; char_t *p; char_t *buffer; char_t *separator; char_t *property; char_t *value; Settings *newSettings; //Point to the scratch buffer buffer = connection->buffer; //Allocate a memory buffer to hold the new configuration newSettings = osAllocMem(sizeof(Settings)); //Failed to allocate memory? if(!newSettings) return ERROR_OUT_OF_MEMORY; //Start of exception handling block do { //Retrieve default settings error = getDefaultSettings(newSettings); //Any error to report? if(error) break; //Process HTTP request body while(1) { //Read the HTTP request body until an ampersand is encountered error = httpReadStream(connection, buffer, HTTP_SERVER_BUFFER_SIZE - 1, &n, HTTP_FLAG_BREAK('&')); //End of stream detected? if(error) break; //Properly terminate the string with a NULL character buffer[n] = '\0'; //Remove the trailing ampersand if(n > 0 && buffer[n - 1] == '&') buffer[--n] = '\0'; //Decode the percent-encoded string error = httpDecodePercentEncodedString(buffer, buffer, HTTP_SERVER_BUFFER_SIZE); //Any error detected? if(error) break; //Check whether a separator is present separator = strchr(buffer, '='); //Separator found? if(separator) { //Split the line *separator = '\0'; //Get property name and value property = strTrimWhitespace(buffer); value = strTrimWhitespace(separator + 1); //Debug message TRACE_DEBUG("[%s]=%s\r\n", property, value); //Icecast settings if(!strcasecmp(property, "icecastSettingsUrl")) { //Check resource length if(strlen(value) >= sizeof(newSettings->icecast.url)) { //Report an error error = ERROR_INVALID_SYNTAX; break; } //Save resource strcpy(newSettings->icecast.url, value); } else if(!strcasecmp(property, "icecastSettingsPort")) { //Save Icecast server port newSettings->icecast.port = strtoul(value, &p, 10); //Invalid port number? if(*p != '\0') { //Report an error error = ERROR_INVALID_SYNTAX; break; } } //LAN settings else if(!strcasecmp(property, "lanSettingsMacAddr")) { //Save MAC address error = macStringToAddr(value, &newSettings->lan.macAddr); //Invalid address? if(error) break; } else if(!strcasecmp(property, "lanSettingsHostName")) { //Check the length of the host name if(strlen(value) >= sizeof(newSettings->lan.hostname)) { //Report an error error = ERROR_INVALID_SYNTAX; break; } //Save host name strcpy(newSettings->lan.hostname, value); } else if(!strcasecmp(property, "lanSettingsEnableDhcp")) { //Check flag value if(!strcasecmp(value, "off")) { //DHCP client is disabled newSettings->lan.enableDhcp = FALSE; } else if(!strcasecmp(value, "on")) { //DHCP client is enabled newSettings->lan.enableDhcp = TRUE; } else { //Invalid value error = ERROR_INVALID_SYNTAX; break; } } else if(!strcasecmp(property, "lanSettingsHostAddr")) { //Save IPv4 host address error = ipv4StringToAddr(value, &newSettings->lan.hostAddr); //Invalid address? if(error) break; } else if(!strcasecmp(property, "lanSettingsSubnetMask")) { //Save subnet mask error = ipv4StringToAddr(value, &newSettings->lan.subnetMask); //Invalid mask? if(error) break; } else if(!strcasecmp(property, "lanSettingsDefaultGateway")) { //Save default gateway error = ipv4StringToAddr(value, &newSettings->lan.defaultGateway); //Invalid address? if(error) break; } else if(!strcasecmp(property, "lanSettingsPrimaryDns")) { //Save primary DNS error = ipv4StringToAddr(value, &newSettings->lan.primaryDns); //Invalid address? if(error) break; } else if(!strcasecmp(property, "lanSettingsSecondaryDns")) { //Save secondary DNS error = ipv4StringToAddr(value, &newSettings->lan.secondaryDns); //Invalid address? if(error) break; } //Proxy settings else if(!strcasecmp(property, "proxySettingsEnable")) { //Check flag value if(!strcasecmp(value, "off")) { //Proxy server is disabled newSettings->proxy.enable = FALSE; } else if(!strcasecmp(value, "on")) { //Proxy server is enabled newSettings->proxy.enable = TRUE; } else { //Invalid value error = ERROR_INVALID_SYNTAX; break; } } else if(!strcasecmp(property, "proxySettingsName")) { //Check the length of proxy server name if(strlen(value) >= sizeof(newSettings->proxy.name)) { //Report an error error = ERROR_INVALID_SYNTAX; break; } //Save proxy server name strcpy(newSettings->proxy.name, value); } else if(!strcasecmp(property, "proxySettingsPort")) { //Save proxy server port newSettings->proxy.port = strtoul(value, &p, 10); //Invalid port number? if(*p != '\0') { //Report an error error = ERROR_INVALID_SYNTAX; break; } } } } //Check status code if(error == NO_ERROR || error == ERROR_END_OF_STREAM) { //Commit changes appSettings = *newSettings; //Write settings to non-volatile memory error = saveSettings(newSettings); } else if(error != ERROR_INVALID_SYNTAX) { //Propagate exception break; } //Point to the scratch buffer buffer = connection->buffer + 384; //Format XML data n = sprintf(buffer, "<data>\r\n <status>"); if(error == ERROR_INVALID_SYNTAX) n += sprintf(buffer + n, "Invalid configuration!\r\n"); else if(error != NO_ERROR) n += sprintf(buffer + n, "Failed to save settings to non-volatile memory!\r\n"); else n += sprintf(buffer + n, "Settings successfully saved. Please reboot the board.\r\n"); //Terminate XML data n += sprintf(buffer + n, "</status>\r\n</data>\r\n"); //Format HTTP response header connection->response.version = connection->request.version; connection->response.statusCode = 200; connection->response.keepAlive = connection->request.keepAlive; connection->response.noCache = TRUE; connection->response.contentType = mimeGetType(".xml"); connection->response.chunkedEncoding = FALSE; connection->response.contentLength = n; //Send the header to the client error = httpWriteHeader(connection); //Any error to report? if(error) break; //Send response body error = httpWriteStream(connection, buffer, n); //Any error to report? if(error) break; //Properly close output stream error = httpCloseStream(connection); //Any error to report? if(error) break; //End of exception handling block } while(0); //Free previously allocated memory osFreeMem(newSettings); //Return status code return error; }