error_t ssiProcessExecCommand(HttpConnection *connection, const char_t *tag, size_t length) { char_t *separator; char_t *attribute; char_t *value; //First, check whether CGI is supported by the server if(connection->settings->cgiCallback == NULL) return ERROR_INVALID_TAG; //Discard invalid SSI directives if(length < 4 || length >= HTTP_SERVER_BUFFER_SIZE) return ERROR_INVALID_TAG; //Skip the SSI exec command (4 bytes) memcpy(connection->buffer, tag + 4, length - 4); //Ensure the resulting string is NULL-terminated connection->buffer[length - 4] = '\0'; //Check whether a separator is present separator = strchr(connection->buffer, '='); //Separator not found? if(!separator) return ERROR_INVALID_TAG; //Split the tag *separator = '\0'; //Get attribute name and value attribute = strTrimWhitespace(connection->buffer); value = strTrimWhitespace(separator + 1); //Remove leading simple or double quote if(value[0] == '\'' || value[0] == '\"') value++; //Get the length of the attribute value length = strlen(value); //Remove trailing simple or double quote if(length > 0) { if(value[length - 1] == '\'' || value[length - 1] == '\"') value[length - 1] = '\0'; } //Enforce attribute name if(strcasecmp(attribute, "cgi") && strcasecmp(attribute, "cmd") && strcasecmp(attribute, "cmd_argument")) return ERROR_INVALID_TAG; //Check the length of the CGI parameter if(strlen(value) > HTTP_SERVER_CGI_PARAM_MAX_LEN) return ERROR_INVALID_TAG; //The scratch buffer may be altered by the user-defined callback. //So the CGI parameter must be copied prior to function invocation strcpy(connection->cgiParam, value); //Invoke user-defined callback return connection->settings->cgiCallback(connection, connection->cgiParam); }
void httpParseContentTypeField(HttpConnection *connection, char_t *value) { #if (HTTP_SERVER_MULTIPART_TYPE_SUPPORT == ENABLED) size_t n; char_t *p; char_t *token; //Retrieve type token = strtok_r(value, "/", &p); //Any parsing error? if(token == NULL) return; //The boundary parameter makes sense only for the multipart content-type if(!strcasecmp(token, "multipart")) { //Skip subtype token = strtok_r(NULL, ";", &p); //Any parsing error? if(token == NULL) return; //Retrieve parameter name token = strtok_r(NULL, "=", &p); //Any parsing error? if(token == NULL) return; //Trim whitespace characters token = strTrimWhitespace(token); //Check parameter name if(!strcasecmp(token, "boundary")) { //Retrieve parameter value token = strtok_r(NULL, ";", &p); //Any parsing error? if(token == NULL) return; //Trim whitespace characters token = strTrimWhitespace(token); //Get the length of the boundary string n = strlen(token); //Check the length of the boundary string if(n < HTTP_SERVER_BOUNDARY_MAX_LEN) { //Copy the boundary string strncpy(connection->request.boundary, token, n); //Properly terminate the string connection->request.boundary[n] = '\0'; //Save the length of the boundary string connection->request.boundaryLength = n; } } } #endif }
void WordGenerator (CXMLElement *pCmdLine) { int i; // Load input file CString sFilespec = pCmdLine->GetAttribute(CONSTLIT("input")); if (sFilespec.IsBlank()) { printf("ERROR: input filename expected.\n"); return; } CFileReadBlock InputFile(sFilespec); if (InputFile.Open() != NOERROR) { printf("ERROR: Unable to open file: %s\n", sFilespec.GetASCIIZPointer()); return; } // "Novel" means that we only generate words that are not // in the input file. bool bNovelWordsOnly = pCmdLine->GetAttributeBool(NOVEL_ATTRIB); // Build up a word generator CMarkovWordGenerator Generator; TMap<CString, DWORD> InputWords; // Read each line of the file char *pPos = InputFile.GetPointer(0); char *pEndPos = pPos + InputFile.GetLength(); while (pPos < pEndPos) { // Skip whitespace while (pPos < pEndPos && (strIsWhitespace(pPos) || *pPos < ' ')) pPos++; // Parse the line char *pStart = pPos; while (pPos < pEndPos && *pPos != '\r' && *pPos != '\n' && *pPos >= ' ') pPos++; CString sWord(pStart, pPos - pStart); // Add the word to the generator if (!sWord.IsBlank()) { Generator.AddSample(strTrimWhitespace(sWord)); // If we are looking for novel words we need to keep a map // of all words in the input file. if (bNovelWordsOnly) InputWords.Insert(sWord); } } // If we have a count, then output a list of random words int iCount; if (pCmdLine->FindAttributeInteger(COUNT_ATTRIB, &iCount)) { if (iCount > 0) { TArray<CString> Result; Generator.GenerateUnique(iCount, &Result); for (i = 0; i < Result.GetCount(); i++) if (InputWords.Find(Result[i])) { Result.Delete(i); i--; } Result.Sort(); for (i = 0; i < Result.GetCount(); i++) printf("%s\n", Result[i].GetASCIIZPointer()); } } // Otherwise, output the generator as XML else { CMemoryWriteStream Output; if (Output.Create() != NOERROR) { printf("ERROR: Out of memory.\n"); return; } if (Generator.WriteAsXML(&Output) != NOERROR) { printf("ERROR: Unable to output generator as XML.\n"); return; } Output.Write("\0", 1); printf(Output.GetPointer()); } }
void httpParseAuthField(HttpConnection *connection, char_t *value) { char_t *p; char_t *token; //Retrieve the authentication scheme token = strtok_r(value, " \t", &p); //Any parsing error? if(token == NULL) { //Exit immediately return; } #if (HTTP_SERVER_BASIC_AUTH_SUPPORT == ENABLED) //Basic access authentication? else if(!strcasecmp(token, "Basic")) { error_t error; size_t n; char_t *separator; //Use the relevant authentication scheme connection->request.auth.mode = HTTP_AUTH_MODE_BASIC; //Retrieve the credentials token = strtok_r(NULL, " \t", &p); //Any parsing error? if(token != NULL) { //Decrypt the Base64 encoded string error = base64Decode(token, strlen(token), token, &n); //Successful decoding? if(!error) { //Properly terminate the string token[n] = '\0'; //Check whether a separator is present separator = strchr(token, ':'); //Separator found? if(separator != NULL) { //Split the line *separator = '\0'; //Save user name strSafeCopy(connection->request.auth.user, token, HTTP_SERVER_USERNAME_MAX_LEN); //Point to the password token = separator + 1; //Save password connection->request.auth.password = token; } } } //Debug message TRACE_DEBUG("Authorization header:\r\n"); TRACE_DEBUG(" username: %s\r\n", connection->request.auth.user); TRACE_DEBUG(" password: %s\r\n", connection->request.auth.password); } #endif #if (HTTP_SERVER_DIGEST_AUTH_SUPPORT == ENABLED) //Digest access authentication? else if(!strcasecmp(token, "Digest")) { size_t n; char_t *separator; char_t *name; //Use the relevant authentication scheme connection->request.auth.mode = HTTP_AUTH_MODE_DIGEST; //Get the first parameter token = strtok_r(NULL, ",", &p); //Parse the Authorization field while(token != NULL) { //Check whether a separator is present separator = strchr(token, '='); //Separator found? if(separator != NULL) { //Split the string *separator = '\0'; //Get field name and value name = strTrimWhitespace(token); value = strTrimWhitespace(separator + 1); //Retrieve the length of the value field n = strlen(value); //Discard the surrounding quotes if(n > 0 && value[n - 1] == '\"') value[n - 1] = '\0'; if(value[0] == '\"') value++; //Check parameter name if(!strcasecmp(name, "username")) { //Save user name strSafeCopy(connection->request.auth.user, value, HTTP_SERVER_USERNAME_MAX_LEN); } else if(!strcasecmp(name, "realm")) { //Save realm connection->request.auth.realm = value; } else if(!strcasecmp(name, "nonce")) { //Save nonce parameter connection->request.auth.nonce = value; } else if(!strcasecmp(name, "uri")) { //Save uri parameter connection->request.auth.uri = value; } else if(!strcasecmp(name, "qop")) { //Save qop parameter connection->request.auth.qop = value; } else if(!strcasecmp(name, "nc")) { //Save nc parameter connection->request.auth.nc = value; } else if(!strcasecmp(name, "cnonce")) { //Save cnonce parameter connection->request.auth.cnonce = value; } else if(!strcasecmp(name, "response")) { //Save response parameter connection->request.auth.response = value; } else if(!strcasecmp(name, "opaque")) { //Save opaque parameter connection->request.auth.opaque = value; } //Get next parameter token = strtok_r(NULL, ",", &p); } } //Debug message TRACE_DEBUG("Authorization header:\r\n"); TRACE_DEBUG(" username: %s\r\n", connection->request.auth.user); TRACE_DEBUG(" realm: %s\r\n", connection->request.auth.realm); TRACE_DEBUG(" nonce: %s\r\n", connection->request.auth.nonce); TRACE_DEBUG(" uri: %s\r\n", connection->request.auth.uri); TRACE_DEBUG(" qop: %s\r\n", connection->request.auth.qop); TRACE_DEBUG(" nc: %s\r\n", connection->request.auth.nc); TRACE_DEBUG(" cnonce: %s\r\n", connection->request.auth.cnonce); TRACE_DEBUG(" response: %s\r\n", connection->request.auth.response); TRACE_DEBUG(" opaque: %s\r\n", connection->request.auth.opaque); } #endif else { //The specified authentication scheme is not supported return; } #if (HTTP_SERVER_BASIC_AUTH_SUPPORT == ENABLED || HTTP_SERVER_DIGEST_AUTH_SUPPORT == ENABLED) //The Authorization header has been found connection->request.auth.found = TRUE; //Invoke user-defined callback, if any if(connection->settings->authCallback != NULL) { //Check whether the access to the specified URI is authorized connection->status = connection->settings->authCallback(connection, connection->request.auth.user, connection->request.uri); } else { //Access to the specified URI is allowed connection->status = HTTP_ACCESS_ALLOWED; } #endif }
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 httpReadHeader(HttpConnection *connection) { error_t error; size_t length; char_t *token; char_t *p; char_t *s; //Set the maximum time the server will wait for an HTTP //request before closing the connection error = socketSetTimeout(connection->socket, HTTP_SERVER_IDLE_TIMEOUT); //Any error to report? if(error) return error; //Read the first line of the request error = httpReceive(connection, connection->buffer, HTTP_SERVER_BUFFER_SIZE - 1, &length, SOCKET_FLAG_BREAK_CRLF); //Unable to read any data? if(error) return error; //Revert to default timeout error = socketSetTimeout(connection->socket, HTTP_SERVER_TIMEOUT); //Any error to report? if(error) return error; //Properly terminate the string with a NULL character connection->buffer[length] = '\0'; //Debug message TRACE_INFO("%s", connection->buffer); //The Request-Line begins with a method token token = strtok_r(connection->buffer, " \r\n", &p); //Unable to retrieve the method? if(!token) return ERROR_INVALID_REQUEST; //The Method token indicates the method to be performed on the //resource identified by the Request-URI error = strSafeCopy(connection->request.method, token, HTTP_SERVER_METHOD_MAX_LEN); //Any error to report? if(error) return ERROR_INVALID_REQUEST; //The Request-URI is following the method token token = strtok_r(NULL, " \r\n", &p); //Unable to retrieve the Request-URI? if(!token) return ERROR_INVALID_REQUEST; //Check whether a query string is present s = strchr(token, '?'); //Query string found? if(s != NULL) { //Split the string *s = '\0'; //Save the Request-URI error = httpDecodePercentEncodedString(token, connection->request.uri, HTTP_SERVER_URI_MAX_LEN); //Any error to report? if(error) return ERROR_INVALID_REQUEST; //Check the length of the query string if(strlen(s + 1) > HTTP_SERVER_QUERY_STRING_MAX_LEN) return ERROR_INVALID_REQUEST; //Save the query string strcpy(connection->request.queryString, s + 1); } else { //Save the Request-URI error = httpDecodePercentEncodedString(token, connection->request.uri, HTTP_SERVER_URI_MAX_LEN); //Any error to report? if(error) return ERROR_INVALID_REQUEST; //No query string connection->request.queryString[0] = '\0'; } //Redirect to the default home page if necessary if(!strcasecmp(connection->request.uri, "/")) strcpy(connection->request.uri, connection->settings->defaultDocument); //Clean the resulting path pathCanonicalize(connection->request.uri); //The protocol version is following the Request-URI token = strtok_r(NULL, " \r\n", &p); //HTTP version 0.9? if(!token) { //Save version number connection->request.version = HTTP_VERSION_0_9; //Persistent connections are not supported connection->request.keepAlive = FALSE; } //HTTP version 1.0? else if(!strcasecmp(token, "HTTP/1.0")) { //Save version number connection->request.version = HTTP_VERSION_1_0; //By default connections are not persistent connection->request.keepAlive = FALSE; } //HTTP version 1.1? else if(!strcasecmp(token, "HTTP/1.1")) { //Save version number connection->request.version = HTTP_VERSION_1_1; //HTTP 1.1 makes persistent connections the default connection->request.keepAlive = TRUE; } //HTTP version not supported? else { return ERROR_INVALID_REQUEST; } //Default value for properties connection->request.chunkedEncoding = FALSE; connection->request.contentLength = 0; //HTTP 0.9 does not support Full-Request if(connection->request.version >= HTTP_VERSION_1_0) { //Local variables char_t firstChar; char_t *separator; char_t *name; char_t *value; //This variable is used to decode header fields that span multiple lines firstChar = '\0'; //Parse the header fields of the HTTP request while(1) { //Decode multiple-line header field error = httpReadHeaderField(connection, connection->buffer, HTTP_SERVER_BUFFER_SIZE, &firstChar); //Any error to report? if(error) return error; //Debug message TRACE_DEBUG("%s", connection->buffer); //An empty line indicates the end of the header fields if(!strcmp(connection->buffer, "\r\n")) break; //Check whether a separator is present separator = strchr(connection->buffer, ':'); //Separator found? if(separator != NULL) { //Split the line *separator = '\0'; //Get field name and value name = strTrimWhitespace(connection->buffer); value = strTrimWhitespace(separator + 1); //Connection field found? if(!strcasecmp(name, "Connection")) { //Check whether persistent connections are supported or not if(!strcasecmp(value, "keep-alive")) connection->request.keepAlive = TRUE; else if(!strcasecmp(value, "close")) connection->request.keepAlive = FALSE; } //Transfer-Encoding field found? else if(!strcasecmp(name, "Transfer-Encoding")) { //Check whether chunked encoding is used if(!strcasecmp(value, "chunked")) connection->request.chunkedEncoding = TRUE; } //Content-Type field found? else if(!strcasecmp(name, "Content-Type")) { //Parse Content-Type field httpParseContentTypeField(connection, value); } //Content-Length field found? else if(!strcasecmp(name, "Content-Length")) { //Get the length of the body data connection->request.contentLength = atoi(value); } //Authorization field found? else if(!strcasecmp(name, "Authorization")) { //Parse Authorization field httpParseAuthField(connection, value); } } } } //Prepare to read the HTTP request body if(connection->request.chunkedEncoding) { connection->request.byteCount = 0; connection->request.firstChunk = TRUE; connection->request.lastChunk = FALSE; } else { connection->request.byteCount = connection->request.contentLength; } //The request header has been successfully parsed return NO_ERROR; }
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; }
void CGTextArea::PaintText (CG32bitImage &Dest, const RECT &rcRect) // PaintText // // Paint plain text { // Paint the text if (m_pFont) { // If we haven't justified the text for this size, do it now if (m_cxJustifyWidth != RectWidth(rcRect)) { m_cxJustifyWidth = RectWidth(rcRect); m_Lines.DeleteAll(); m_pFont->BreakText(m_sText, m_cxJustifyWidth, &m_Lines, CG16bitFont::SmartQuotes); } // Compute the rect within which we draw the text RECT rcText = rcRect; if (m_bEditable) { int iVSpacing = (RectHeight(rcRect) - m_pFont->GetHeight()) / 2; rcText.left += iVSpacing; rcText.right -= iVSpacing; rcText.top += iVSpacing; rcText.bottom -= iVSpacing; } // Clip to text rect RECT rcOldClip = Dest.GetClipRect(); Dest.SetClipRect(rcText); // Figure out how many lines fit in the rect int iMaxLineCount = RectHeight(rcText) / m_pFont->GetHeight(); // If there are too many lines, and we're editable, start at the end int iStart = 0; if (m_bEditable && iMaxLineCount < m_Lines.GetCount()) iStart = m_Lines.GetCount() - iMaxLineCount; // Paint each line int x = rcText.left; int y = rcText.top; for (int i = iStart; i < m_Lines.GetCount(); i++) { CString sLine = m_Lines[i]; // Trim the last space in the line, if necessary char *pPos = sLine.GetASCIIZPointer(); if (sLine.GetLength() > 0 && pPos[sLine.GetLength() - 1] == ' ') sLine = strTrimWhitespace(sLine); // Alignment int xLine; if (m_dwStyles & alignCenter) { int cxWidth = m_pFont->MeasureText(sLine); xLine = x + (RectWidth(rcText) - cxWidth) / 2; } else if (m_dwStyles & alignRight) { int cxWidth = m_pFont->MeasureText(sLine); xLine = x + (RectWidth(rcRect) - cxWidth); } else xLine = x; // Paint if (HasEffects()) m_pFont->DrawTextEffect(Dest, xLine, y, m_rgbColor, sLine, GetEffectCount(), GetEffects()); else Dest.DrawText(xLine, y, *m_pFont, m_rgbColor, sLine); // Next y += m_pFont->GetHeight() + m_cyLineSpacing; if (y >= rcText.bottom) break; } // Paint the cursor if (m_bEditable && m_iCursorLine >= iStart) { int cxPos = (m_iCursorLine < m_Lines.GetCount() ? m_pFont->MeasureText(CString(m_Lines[m_iCursorLine].GetASCIIZPointer(), m_iCursorPos, true)) : 0); int y = rcText.top + (m_iCursorLine - iStart) * (m_pFont->GetHeight() + m_cyLineSpacing); int x = rcText.left; if (m_dwStyles & alignCenter) { int cxWidth = (m_iCursorLine < m_Lines.GetCount() ? m_pFont->MeasureText(m_Lines[m_iCursorLine]) : 0); x += ((RectWidth(rcText) - cxWidth) / 2) + cxPos; } else if (m_dwStyles & alignRight) { int cxWidth = (m_iCursorLine < m_Lines.GetCount() ? m_pFont->MeasureText(m_Lines[m_iCursorLine]) : 0); x += (RectWidth(rcText) - cxWidth) + cxPos; } else x += cxPos; if (((m_iTick / 30) % 2) > 0) { Dest.Fill(x, y, 2, m_pFont->GetHeight(), RGB_CURSOR); } } // Restore clip Dest.SetClipRect(rcOldClip); } }
error_t smtpSendCommand(SmtpClientContext *context, const char_t *command, uint_t *replyCode, SmtpReplyCallback callback) { error_t error; size_t length; char_t *line; //Any command line to send? if(command) { //Debug message TRACE_DEBUG("SMTP client: %s", command); //Send the command to the SMTP server error = smtpWrite(context, command, strlen(command), SOCKET_FLAG_WAIT_ACK); //Failed to send command? if(error) return error; } //Multiline replies are allowed for any command while(1) { //Wait for a response from the server error = smtpRead(context, context->buffer, SMTP_MAX_LINE_LENGTH - 1, &length, SOCKET_FLAG_BREAK_CRLF); //The remote server did not respond as expected? if(error) return error; //Properly terminate the string with a NULL character context->buffer[length] = '\0'; //Remove all leading and trailing whitespace from the response line = strTrimWhitespace(context->buffer); //Debug message TRACE_DEBUG("SMTP server: %s\r\n", line); //Check the length of the response if(strlen(line) < 3) return ERROR_INVALID_SYNTAX; //All replies begin with a three digit numeric code if(!isdigit((uint8_t) line[0]) || !isdigit((uint8_t) line[1]) || !isdigit((uint8_t) line[2])) return ERROR_INVALID_SYNTAX; //A hyphen or a space character must follow the response code if(line[3] != '-' && line[3] != ' ' && line[3] != '\0') return ERROR_INVALID_SYNTAX; //Get the server response code *replyCode = strtoul(line, NULL, 10); //Any callback function to call? if(callback) { //Invoke callback function to parse the response line error = callback(context, line, *replyCode); //Check status code if(error) return error; } //A hyphen follows the response code for all but the last line if(line[3] != '-') break; } //Successful processing return NO_ERROR; }
error_t ssiProcessEchoCommand(HttpConnection *connection, const char_t *tag, size_t length) { error_t error; char_t *separator; char_t *attribute; char_t *value; //Discard invalid SSI directives if(length < 4 || length >= HTTP_SERVER_BUFFER_SIZE) return ERROR_INVALID_TAG; //Skip the SSI echo command (4 bytes) memcpy(connection->buffer, tag + 4, length - 4); //Ensure the resulting string is NULL-terminated connection->buffer[length - 4] = '\0'; //Check whether a separator is present separator = strchr(connection->buffer, '='); //Separator not found? if(!separator) return ERROR_INVALID_TAG; //Split the tag *separator = '\0'; //Get attribute name and value attribute = strTrimWhitespace(connection->buffer); value = strTrimWhitespace(separator + 1); //Remove leading simple or double quote if(value[0] == '\'' || value[0] == '\"') value++; //Get the length of the attribute value length = strlen(value); //Remove trailing simple or double quote if(length > 0) { if(value[length - 1] == '\'' || value[length - 1] == '\"') value[length - 1] = '\0'; } //Enforce attribute name if(strcasecmp(attribute, "var")) return ERROR_INVALID_TAG; //Remote address? if(!strcasecmp(value, "REMOTE_ADDR")) { //The IP address of the host making this request ipAddrToString(&connection->socket->remoteIpAddr, connection->buffer); } //Remote port? else if(!strcasecmp(value, "REMOTE_PORT")) { //The port number used by the remote host when making this request sprintf(connection->buffer, "%" PRIu16, connection->socket->remotePort); } //Server address? else if(!strcasecmp(value, "SERVER_ADDR")) { //The IP address of the server for this URL ipAddrToString(&connection->socket->localIpAddr, connection->buffer); } //Server port? else if(!strcasecmp(value, "SERVER_PORT")) { //The port number on this server to which this request was directed sprintf(connection->buffer, "%" PRIu16, connection->socket->localPort); } //Request method? else if(!strcasecmp(value, "REQUEST_METHOD")) { //The method used for this HTTP request strcpy(connection->buffer, connection->request.method); } //Document root? else if(!strcasecmp(value, "DOCUMENT_ROOT")) { //The root directory strcpy(connection->buffer, connection->settings->rootDirectory); } //Document URI? else if(!strcasecmp(value, "DOCUMENT_URI")) { //The URI for this request relative to the root directory strcpy(connection->buffer, connection->request.uri); } //Document name? else if(!strcasecmp(value, "DOCUMENT_NAME")) { //The full physical path and filename of the document requested httpGetAbsolutePath(connection, connection->request.uri, connection->buffer, HTTP_SERVER_BUFFER_SIZE); } //Query string? else if(!strcasecmp(value, "QUERY_STRING")) { //The information following the "?" in the URL for this request strcpy(connection->buffer, connection->request.queryString); } //User name? else if(!strcasecmp(value, "AUTH_USER")) { #if (HTTP_SERVER_BASIC_AUTH_SUPPORT == ENABLED || HTTP_SERVER_DIGEST_AUTH_SUPPORT == ENABLED) //The username provided by the user to the server strcpy(connection->buffer, connection->request.auth.user); #else //Basic access authentication is not supported connection->buffer[0] = '\0'; #endif } //GMT time? else if(!strcasecmp(value, "DATE_GMT")) { //The current date and time in Greenwich Mean Time connection->buffer[0] = '\0'; } //Local time? else if(!strcasecmp(value, "DATE_LOCAL")) { //The current date and time in the local timezone connection->buffer[0] = '\0'; } //Unknown variable? else { //Report an error return ERROR_INVALID_TAG; } //Get the length of the resulting string length = strlen(connection->buffer); //Send the contents of the specified environment variable error = httpWriteStream(connection, connection->buffer, length); //Failed to send data? if(error) return error; //Successful processing return NO_ERROR; }
error_t ssiProcessIncludeCommand(HttpConnection *connection, const char_t *tag, size_t length, const char_t *uri, uint_t level) { error_t error; char_t *separator; char_t *attribute; char_t *value; char_t *path; char_t *p; //Discard invalid SSI directives if(length < 7 || length >= HTTP_SERVER_BUFFER_SIZE) return ERROR_INVALID_TAG; //Skip the SSI include command (7 bytes) memcpy(connection->buffer, tag + 7, length - 7); //Ensure the resulting string is NULL-terminated connection->buffer[length - 7] = '\0'; //Check whether a separator is present separator = strchr(connection->buffer, '='); //Separator not found? if(!separator) return ERROR_INVALID_TAG; //Split the tag *separator = '\0'; //Get attribute name and value attribute = strTrimWhitespace(connection->buffer); value = strTrimWhitespace(separator + 1); //Remove leading simple or double quote if(value[0] == '\'' || value[0] == '\"') value++; //Get the length of the attribute value length = strlen(value); //Remove trailing simple or double quote if(length > 0) { if(value[length - 1] == '\'' || value[length - 1] == '\"') value[length - 1] = '\0'; } //Check the length of the filename if(strlen(value) > HTTP_SERVER_URI_MAX_LEN) return ERROR_INVALID_TAG; //The file parameter defines the included file as relative to the document path if(!strcasecmp(attribute, "file")) { //Allocate a buffer to hold the path to the file to be included path = osAllocMem(strlen(uri) + strlen(value) + 1); //Failed to allocate memory? if(!path) return ERROR_OUT_OF_MEMORY; //Copy the path identifying the script file being processed strcpy(path, uri); //Search for the last slash character p = strrchr(path, '/'); //Remove the filename from the path if applicable if(p) strcpy(p + 1, value); else strcpy(path, value); } //The virtual parameter defines the included file as relative to the document root else if(!strcasecmp(attribute, "virtual")) { //Copy the absolute path path = strDuplicate(value); //Failed to duplicate the string? if(!path) return ERROR_OUT_OF_MEMORY; } //Unknown parameter... else { //Report an error return ERROR_INVALID_TAG; } //Use server-side scripting to dynamically generate HTML code? if(httpCompExtension(value, ".stm") || httpCompExtension(value, ".shtm") || httpCompExtension(value, ".shtml")) { //SSI processing (Server Side Includes) error = ssiExecuteScript(connection, path, level + 1); } else { #if (HTTP_SERVER_FS_SUPPORT == ENABLED) FsFile *file; //Retrieve the full pathname httpGetAbsolutePath(connection, path, connection->buffer, HTTP_SERVER_BUFFER_SIZE); //Open the file for reading file = fsOpenFile(connection->buffer, FS_FILE_MODE_READ); //Successful operation? if(file) { //Send the contents of the requested file while(1) { //Read data from the specified file error = fsReadFile(file, connection->buffer, HTTP_SERVER_BUFFER_SIZE, &length); //End of input stream? if(error) break; //Send data to the client error = httpWriteStream(connection, connection->buffer, length); //Any error to report? if(error) break; } //Close the file fsCloseFile(file); //Successful file transfer? if(error == ERROR_END_OF_STREAM) error = NO_ERROR; } else { //The specified URI cannot be found error = ERROR_NOT_FOUND; } #else uint8_t *data; //Retrieve the full pathname httpGetAbsolutePath(connection, path, connection->buffer, HTTP_SERVER_BUFFER_SIZE); //Get the resource data associated with the file error = resGetData(connection->buffer, &data, &length); //Send the contents of the requested file if(!error) error = httpWriteStream(connection, data, length); #endif } //Cannot found the specified resource? if(error == ERROR_NOT_FOUND) error = ERROR_INVALID_TAG; //Release previously allocated memory osFreeMem(path); //return status code return error; }
error_t icecastClientConnect(IcecastClientContext *context) { error_t error; size_t length; IpAddr serverIpAddr; //Icecast request template const char_t requestTemplate[] = "GET /%s HTTP/1.1\r\n" "Host: %s\r\n" "User-agent: UserAgent\r\n" "Icy-MetaData: 1\r\n" "Connection: close\r\n" "\r\n"; //The specified Icecast server can be either an IP or a host name error = getHostByName(context->settings.interface, context->settings.serverName, &serverIpAddr, 1, NULL, 0); //Unable to resolve server name? if(error) return error; //Open a TCP socket context->socket = socketOpen(SOCKET_TYPE_STREAM, SOCKET_PROTOCOL_TCP); //Failed to open socket? if(!context->socket) return ERROR_OUT_OF_RESOURCES; //Start of exception handling block do { //Adjust receive timeout error = socketSetTimeout(context->socket, ICECAST_CLIENT_TIMEOUT); //Any error to report? if(error) return error; //Connect to the specified Icecast server error = socketConnect(context->socket, &serverIpAddr, context->settings.serverPort); //Connection with server failed? if(error) return error; //Format Icecast request length = sprintf(context->buffer, requestTemplate, context->settings.resource, context->settings.serverName); //Debug message TRACE_DEBUG(context->buffer); //Send Icecast request error = socketSend(context->socket, context->buffer, length, NULL, SOCKET_FLAG_WAIT_ACK); //Failed to send the request? if(error) return error; //Parse response header while(1) { char_t *separator; char_t *property; char_t *value; //Read a line from the response header error = socketReceive(context->socket, context->buffer, ICECAST_CLIENT_METADATA_MAX_SIZE, &length, SOCKET_FLAG_BREAK_CRLF); //Failed to read data? if(error) break; //Properly terminate the string with a NULL character context->buffer[length] = '\0'; //The end of the header has been reached? if(!strcmp(context->buffer, "\r\n")) break; //Check whether a separator is present separator = strchr(context->buffer, ':'); //Separator found? if(separator) { //Split the line *separator = '\0'; //Get property name and value property = strTrimWhitespace(context->buffer); value = strTrimWhitespace(separator + 1); //Debug message TRACE_INFO("<%s>=<%s>\r\n", property, value); //Icy-Metaint property found? if(!strcasecmp(property, "Icy-Metaint")) context->blockSize = atoi(value); } } //End of exception handling block } while(0); //Check whether an error occurred if(error) { //Clean up side effects socketClose(context->socket); } //Return status code return error; }
bool CPlayerDisplay::OnChar (char chChar) // OnChar // // Handle character { if (!m_bEditing) return false; switch (chChar) { case SDLK_BACKSPACE: { if (m_bClearAll) m_sEditBuffer = CString(); else { if (!m_sEditBuffer.IsBlank()) m_sEditBuffer = strSubString(m_sEditBuffer, 0, m_sEditBuffer.GetLength() - 1); } m_bInvalid = true; m_bClearAll = false; break; } case SDLK_RETURN: { m_sEditBuffer = strTrimWhitespace(m_sEditBuffer); if (!m_sEditBuffer.IsBlank()) { m_sName = m_sEditBuffer; m_pTrans->SetPlayerName(m_sName); } m_bEditing = false; m_bInvalid = true; break; } case SDLK_ESCAPE: { m_bEditing = false; m_bInvalid = true; break; } // Characters default: { if (!isprint(chChar)) break; if (m_bClearAll) m_sEditBuffer = CString(&chChar, 1); else m_sEditBuffer.Append(CString(&chChar, 1)); m_bInvalid = true; m_bClearAll = false; } } return true; }