Webserver+3d print

Dependents:   Nucleo

Committer:
Sergunb
Date:
Sat Feb 04 18:15:49 2017 +0000
Revision:
0:8918a71cdbe9
nothing else

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Sergunb 0:8918a71cdbe9 1 /**
Sergunb 0:8918a71cdbe9 2 * @file ssi.c
Sergunb 0:8918a71cdbe9 3 * @brief SSI (Server Side Includes)
Sergunb 0:8918a71cdbe9 4 *
Sergunb 0:8918a71cdbe9 5 * @section License
Sergunb 0:8918a71cdbe9 6 *
Sergunb 0:8918a71cdbe9 7 * Copyright (C) 2010-2017 Oryx Embedded SARL. All rights reserved.
Sergunb 0:8918a71cdbe9 8 *
Sergunb 0:8918a71cdbe9 9 * This file is part of CycloneTCP Open.
Sergunb 0:8918a71cdbe9 10 *
Sergunb 0:8918a71cdbe9 11 * This program is free software; you can redistribute it and/or
Sergunb 0:8918a71cdbe9 12 * modify it under the terms of the GNU General Public License
Sergunb 0:8918a71cdbe9 13 * as published by the Free Software Foundation; either version 2
Sergunb 0:8918a71cdbe9 14 * of the License, or (at your option) any later version.
Sergunb 0:8918a71cdbe9 15 *
Sergunb 0:8918a71cdbe9 16 * This program is distributed in the hope that it will be useful,
Sergunb 0:8918a71cdbe9 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Sergunb 0:8918a71cdbe9 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Sergunb 0:8918a71cdbe9 19 * GNU General Public License for more details.
Sergunb 0:8918a71cdbe9 20 *
Sergunb 0:8918a71cdbe9 21 * You should have received a copy of the GNU General Public License
Sergunb 0:8918a71cdbe9 22 * along with this program; if not, write to the Free Software Foundation,
Sergunb 0:8918a71cdbe9 23 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
Sergunb 0:8918a71cdbe9 24 *
Sergunb 0:8918a71cdbe9 25 * @section Description
Sergunb 0:8918a71cdbe9 26 *
Sergunb 0:8918a71cdbe9 27 * Server Side Includes (SSI) is a simple interpreted server-side scripting
Sergunb 0:8918a71cdbe9 28 * language used to generate dynamic content to web pages
Sergunb 0:8918a71cdbe9 29 *
Sergunb 0:8918a71cdbe9 30 * @author Oryx Embedded SARL (www.oryx-embedded.com)
Sergunb 0:8918a71cdbe9 31 * @version 1.7.6
Sergunb 0:8918a71cdbe9 32 **/
Sergunb 0:8918a71cdbe9 33
Sergunb 0:8918a71cdbe9 34 //Switch to the appropriate trace level
Sergunb 0:8918a71cdbe9 35 #define TRACE_LEVEL HTTP_TRACE_LEVEL
Sergunb 0:8918a71cdbe9 36
Sergunb 0:8918a71cdbe9 37 //Dependencies
Sergunb 0:8918a71cdbe9 38 #include "core/net.h"
Sergunb 0:8918a71cdbe9 39 #include "http/http_server.h"
Sergunb 0:8918a71cdbe9 40 #include "http/http_server_misc.h"
Sergunb 0:8918a71cdbe9 41 #include "http/mime.h"
Sergunb 0:8918a71cdbe9 42 #include "http/ssi.h"
Sergunb 0:8918a71cdbe9 43 #include "str.h"
Sergunb 0:8918a71cdbe9 44 #include "debug.h"
Sergunb 0:8918a71cdbe9 45
Sergunb 0:8918a71cdbe9 46 //File system support?
Sergunb 0:8918a71cdbe9 47 #if (HTTP_SERVER_FS_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 48 #include "fs_port.h"
Sergunb 0:8918a71cdbe9 49 #else
Sergunb 0:8918a71cdbe9 50 #include "resource_manager.h"
Sergunb 0:8918a71cdbe9 51 #endif
Sergunb 0:8918a71cdbe9 52
Sergunb 0:8918a71cdbe9 53 //Check TCP/IP stack configuration
Sergunb 0:8918a71cdbe9 54 #if (HTTP_SERVER_SUPPORT == ENABLED && HTTP_SERVER_SSI_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 55
Sergunb 0:8918a71cdbe9 56
Sergunb 0:8918a71cdbe9 57 /**
Sergunb 0:8918a71cdbe9 58 * @brief Execute SSI script
Sergunb 0:8918a71cdbe9 59 * @param[in] connection Structure representing an HTTP connection
Sergunb 0:8918a71cdbe9 60 * @param[in] uri NULL-terminated string containing the file to process
Sergunb 0:8918a71cdbe9 61 * @param[in] level Current level of recursion
Sergunb 0:8918a71cdbe9 62 * @return Error code
Sergunb 0:8918a71cdbe9 63 **/
Sergunb 0:8918a71cdbe9 64
Sergunb 0:8918a71cdbe9 65 error_t ssiExecuteScript(HttpConnection *connection, const char_t *uri, uint_t level)
Sergunb 0:8918a71cdbe9 66 {
Sergunb 0:8918a71cdbe9 67 error_t error;
Sergunb 0:8918a71cdbe9 68 size_t length;
Sergunb 0:8918a71cdbe9 69
Sergunb 0:8918a71cdbe9 70 #if (HTTP_SERVER_FS_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 71 bool_t more;
Sergunb 0:8918a71cdbe9 72 uint_t pos;
Sergunb 0:8918a71cdbe9 73 uint_t n;
Sergunb 0:8918a71cdbe9 74 char_t *buffer;
Sergunb 0:8918a71cdbe9 75 FsFile *file;
Sergunb 0:8918a71cdbe9 76 #else
Sergunb 0:8918a71cdbe9 77 uint_t i;
Sergunb 0:8918a71cdbe9 78 uint_t j;
Sergunb 0:8918a71cdbe9 79 char_t *data;
Sergunb 0:8918a71cdbe9 80 #endif
Sergunb 0:8918a71cdbe9 81
Sergunb 0:8918a71cdbe9 82 //Recursion limit exceeded?
Sergunb 0:8918a71cdbe9 83 if(level >= HTTP_SERVER_SSI_MAX_RECURSION)
Sergunb 0:8918a71cdbe9 84 return NO_ERROR;
Sergunb 0:8918a71cdbe9 85
Sergunb 0:8918a71cdbe9 86 //Retrieve the full pathname
Sergunb 0:8918a71cdbe9 87 httpGetAbsolutePath(connection, uri,
Sergunb 0:8918a71cdbe9 88 connection->buffer, HTTP_SERVER_BUFFER_SIZE);
Sergunb 0:8918a71cdbe9 89
Sergunb 0:8918a71cdbe9 90 #if (HTTP_SERVER_FS_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 91 //Open the file for reading
Sergunb 0:8918a71cdbe9 92 file = fsOpenFile(connection->buffer, FS_FILE_MODE_READ);
Sergunb 0:8918a71cdbe9 93 //Failed to open the file?
Sergunb 0:8918a71cdbe9 94 if(file == NULL)
Sergunb 0:8918a71cdbe9 95 return ERROR_NOT_FOUND;
Sergunb 0:8918a71cdbe9 96
Sergunb 0:8918a71cdbe9 97 //Allocate a memory buffer
Sergunb 0:8918a71cdbe9 98 buffer = osAllocMem(HTTP_SERVER_BUFFER_SIZE);
Sergunb 0:8918a71cdbe9 99 //Failed to allocate memory?
Sergunb 0:8918a71cdbe9 100 if(buffer == NULL)
Sergunb 0:8918a71cdbe9 101 {
Sergunb 0:8918a71cdbe9 102 //Close the file
Sergunb 0:8918a71cdbe9 103 fsCloseFile(file);
Sergunb 0:8918a71cdbe9 104 //Report an error
Sergunb 0:8918a71cdbe9 105 return ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 106 }
Sergunb 0:8918a71cdbe9 107 #else
Sergunb 0:8918a71cdbe9 108 //Get the resource data associated with the URI
Sergunb 0:8918a71cdbe9 109 error = resGetData(connection->buffer, (uint8_t **) &data, &length);
Sergunb 0:8918a71cdbe9 110 //The specified URI cannot be found?
Sergunb 0:8918a71cdbe9 111 if(error)
Sergunb 0:8918a71cdbe9 112 return error;
Sergunb 0:8918a71cdbe9 113 #endif
Sergunb 0:8918a71cdbe9 114
Sergunb 0:8918a71cdbe9 115 //Send the HTTP response header before executing the script
Sergunb 0:8918a71cdbe9 116 if(!level)
Sergunb 0:8918a71cdbe9 117 {
Sergunb 0:8918a71cdbe9 118 //Format HTTP response header
Sergunb 0:8918a71cdbe9 119 connection->response.statusCode = 200;
Sergunb 0:8918a71cdbe9 120 connection->response.contentType = mimeGetType(uri);
Sergunb 0:8918a71cdbe9 121 connection->response.chunkedEncoding = TRUE;
Sergunb 0:8918a71cdbe9 122
Sergunb 0:8918a71cdbe9 123 //Send the header to the client
Sergunb 0:8918a71cdbe9 124 error = httpWriteHeader(connection);
Sergunb 0:8918a71cdbe9 125 //Any error to report?
Sergunb 0:8918a71cdbe9 126 if(error)
Sergunb 0:8918a71cdbe9 127 {
Sergunb 0:8918a71cdbe9 128 #if (HTTP_SERVER_FS_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 129 //Close the file
Sergunb 0:8918a71cdbe9 130 fsCloseFile(file);
Sergunb 0:8918a71cdbe9 131 //Release memory buffer
Sergunb 0:8918a71cdbe9 132 osFreeMem(buffer);
Sergunb 0:8918a71cdbe9 133 #endif
Sergunb 0:8918a71cdbe9 134 //Return status code
Sergunb 0:8918a71cdbe9 135 return error;
Sergunb 0:8918a71cdbe9 136 }
Sergunb 0:8918a71cdbe9 137 }
Sergunb 0:8918a71cdbe9 138
Sergunb 0:8918a71cdbe9 139 #if (HTTP_SERVER_FS_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 140 //Point to the beginning of the buffer
Sergunb 0:8918a71cdbe9 141 pos = 0;
Sergunb 0:8918a71cdbe9 142 length = 0;
Sergunb 0:8918a71cdbe9 143
Sergunb 0:8918a71cdbe9 144 //This flag indicates whether data should be read
Sergunb 0:8918a71cdbe9 145 more = TRUE;
Sergunb 0:8918a71cdbe9 146
Sergunb 0:8918a71cdbe9 147 //Parse the specified file
Sergunb 0:8918a71cdbe9 148 while(1)
Sergunb 0:8918a71cdbe9 149 {
Sergunb 0:8918a71cdbe9 150 //Read more data if needed
Sergunb 0:8918a71cdbe9 151 if(more)
Sergunb 0:8918a71cdbe9 152 {
Sergunb 0:8918a71cdbe9 153 //Check whether the current position is aligned on 32-bit boundaries
Sergunb 0:8918a71cdbe9 154 n = 4 - ((pos + length) % 4);
Sergunb 0:8918a71cdbe9 155
Sergunb 0:8918a71cdbe9 156 //Maintain proper alignment
Sergunb 0:8918a71cdbe9 157 if(n != 4)
Sergunb 0:8918a71cdbe9 158 {
Sergunb 0:8918a71cdbe9 159 memmove(buffer + pos + n, buffer + pos, length);
Sergunb 0:8918a71cdbe9 160 pos += n;
Sergunb 0:8918a71cdbe9 161 }
Sergunb 0:8918a71cdbe9 162
Sergunb 0:8918a71cdbe9 163 //Read data from the specified file
Sergunb 0:8918a71cdbe9 164 error = fsReadFile(file, buffer + pos + length,
Sergunb 0:8918a71cdbe9 165 HTTP_SERVER_BUFFER_SIZE - (pos + length), &n);
Sergunb 0:8918a71cdbe9 166
Sergunb 0:8918a71cdbe9 167 //End of input stream?
Sergunb 0:8918a71cdbe9 168 if(error)
Sergunb 0:8918a71cdbe9 169 {
Sergunb 0:8918a71cdbe9 170 //Purge data buffer
Sergunb 0:8918a71cdbe9 171 error = httpWriteStream(connection, buffer + pos, length);
Sergunb 0:8918a71cdbe9 172 //Exit immediately
Sergunb 0:8918a71cdbe9 173 break;
Sergunb 0:8918a71cdbe9 174 }
Sergunb 0:8918a71cdbe9 175
Sergunb 0:8918a71cdbe9 176 //Adjust the length of the buffer
Sergunb 0:8918a71cdbe9 177 length += n;
Sergunb 0:8918a71cdbe9 178 //Clear flag
Sergunb 0:8918a71cdbe9 179 more = FALSE;
Sergunb 0:8918a71cdbe9 180 }
Sergunb 0:8918a71cdbe9 181
Sergunb 0:8918a71cdbe9 182 //Search for any SSI tags
Sergunb 0:8918a71cdbe9 183 error = ssiSearchTag(buffer + pos, length, "<!--#", 5, &n);
Sergunb 0:8918a71cdbe9 184
Sergunb 0:8918a71cdbe9 185 //Full match?
Sergunb 0:8918a71cdbe9 186 if(error == NO_ERROR)
Sergunb 0:8918a71cdbe9 187 {
Sergunb 0:8918a71cdbe9 188 //Send the part of the file that precedes the tag
Sergunb 0:8918a71cdbe9 189 error = httpWriteStream(connection, buffer + pos, n);
Sergunb 0:8918a71cdbe9 190 //Failed to send data?
Sergunb 0:8918a71cdbe9 191 if(error)
Sergunb 0:8918a71cdbe9 192 break;
Sergunb 0:8918a71cdbe9 193
Sergunb 0:8918a71cdbe9 194 //Advance data pointer
Sergunb 0:8918a71cdbe9 195 pos += n;
Sergunb 0:8918a71cdbe9 196 length -= n;
Sergunb 0:8918a71cdbe9 197
Sergunb 0:8918a71cdbe9 198 //Search for the comment terminator
Sergunb 0:8918a71cdbe9 199 error = ssiSearchTag(buffer + pos + 5, length - 5, "-->", 3, &n);
Sergunb 0:8918a71cdbe9 200
Sergunb 0:8918a71cdbe9 201 //Full match?
Sergunb 0:8918a71cdbe9 202 if(error == NO_ERROR)
Sergunb 0:8918a71cdbe9 203 {
Sergunb 0:8918a71cdbe9 204 //Advance data pointer over the opening identifier
Sergunb 0:8918a71cdbe9 205 pos += 5;
Sergunb 0:8918a71cdbe9 206 length -= 5;
Sergunb 0:8918a71cdbe9 207
Sergunb 0:8918a71cdbe9 208 //Process SSI directive
Sergunb 0:8918a71cdbe9 209 error = ssiProcessCommand(connection, buffer + pos, n, uri, level);
Sergunb 0:8918a71cdbe9 210 //Any error to report?
Sergunb 0:8918a71cdbe9 211 if(error)
Sergunb 0:8918a71cdbe9 212 break;
Sergunb 0:8918a71cdbe9 213
Sergunb 0:8918a71cdbe9 214 //Advance data pointer over the SSI tag
Sergunb 0:8918a71cdbe9 215 pos += n + 3;
Sergunb 0:8918a71cdbe9 216 length -= n + 3;
Sergunb 0:8918a71cdbe9 217 }
Sergunb 0:8918a71cdbe9 218 //No match or partial match?
Sergunb 0:8918a71cdbe9 219 else
Sergunb 0:8918a71cdbe9 220 {
Sergunb 0:8918a71cdbe9 221 if(pos > 0)
Sergunb 0:8918a71cdbe9 222 {
Sergunb 0:8918a71cdbe9 223 //Move the remaining bytes to the start of the buffer
Sergunb 0:8918a71cdbe9 224 memmove(buffer, buffer + pos, length);
Sergunb 0:8918a71cdbe9 225 //Rewind to the beginning of the buffer
Sergunb 0:8918a71cdbe9 226 pos = 0;
Sergunb 0:8918a71cdbe9 227 //More data are needed
Sergunb 0:8918a71cdbe9 228 more = TRUE;
Sergunb 0:8918a71cdbe9 229 }
Sergunb 0:8918a71cdbe9 230 else
Sergunb 0:8918a71cdbe9 231 {
Sergunb 0:8918a71cdbe9 232 //Send data to the client
Sergunb 0:8918a71cdbe9 233 error = httpWriteStream(connection, buffer + pos, length);
Sergunb 0:8918a71cdbe9 234 //Any error to report?
Sergunb 0:8918a71cdbe9 235 if(error)
Sergunb 0:8918a71cdbe9 236 break;
Sergunb 0:8918a71cdbe9 237
Sergunb 0:8918a71cdbe9 238 //Rewind to the beginning of the buffer
Sergunb 0:8918a71cdbe9 239 pos = 0;
Sergunb 0:8918a71cdbe9 240 length = 0;
Sergunb 0:8918a71cdbe9 241 //More data are needed
Sergunb 0:8918a71cdbe9 242 more = TRUE;
Sergunb 0:8918a71cdbe9 243 }
Sergunb 0:8918a71cdbe9 244 }
Sergunb 0:8918a71cdbe9 245 }
Sergunb 0:8918a71cdbe9 246 //Partial match?
Sergunb 0:8918a71cdbe9 247 else if(error == ERROR_PARTIAL_MATCH)
Sergunb 0:8918a71cdbe9 248 {
Sergunb 0:8918a71cdbe9 249 //Send the part of the file that precedes the tag
Sergunb 0:8918a71cdbe9 250 error = httpWriteStream(connection, buffer + pos, n);
Sergunb 0:8918a71cdbe9 251 //Failed to send data?
Sergunb 0:8918a71cdbe9 252 if(error)
Sergunb 0:8918a71cdbe9 253 break;
Sergunb 0:8918a71cdbe9 254
Sergunb 0:8918a71cdbe9 255 //Advance data pointer
Sergunb 0:8918a71cdbe9 256 pos += n;
Sergunb 0:8918a71cdbe9 257 length -= n;
Sergunb 0:8918a71cdbe9 258
Sergunb 0:8918a71cdbe9 259 //Move the remaining bytes to the start of the buffer
Sergunb 0:8918a71cdbe9 260 memmove(buffer, buffer + pos, length);
Sergunb 0:8918a71cdbe9 261 //Rewind to the beginning of the buffer
Sergunb 0:8918a71cdbe9 262 pos = 0;
Sergunb 0:8918a71cdbe9 263 //More data are needed
Sergunb 0:8918a71cdbe9 264 more = TRUE;
Sergunb 0:8918a71cdbe9 265 }
Sergunb 0:8918a71cdbe9 266 //No match?
Sergunb 0:8918a71cdbe9 267 else
Sergunb 0:8918a71cdbe9 268 {
Sergunb 0:8918a71cdbe9 269 //Send data to the client
Sergunb 0:8918a71cdbe9 270 error = httpWriteStream(connection, buffer + pos, length);
Sergunb 0:8918a71cdbe9 271 //Any error to report?
Sergunb 0:8918a71cdbe9 272 if(error)
Sergunb 0:8918a71cdbe9 273 break;
Sergunb 0:8918a71cdbe9 274
Sergunb 0:8918a71cdbe9 275 //Rewind to the beginning of the buffer
Sergunb 0:8918a71cdbe9 276 pos = 0;
Sergunb 0:8918a71cdbe9 277 length = 0;
Sergunb 0:8918a71cdbe9 278 //More data are needed
Sergunb 0:8918a71cdbe9 279 more = TRUE;
Sergunb 0:8918a71cdbe9 280 }
Sergunb 0:8918a71cdbe9 281 }
Sergunb 0:8918a71cdbe9 282
Sergunb 0:8918a71cdbe9 283 //Close the file
Sergunb 0:8918a71cdbe9 284 fsCloseFile(file);
Sergunb 0:8918a71cdbe9 285 //Release memory buffer
Sergunb 0:8918a71cdbe9 286 osFreeMem(buffer);
Sergunb 0:8918a71cdbe9 287
Sergunb 0:8918a71cdbe9 288 //Properly close the output stream
Sergunb 0:8918a71cdbe9 289 if(!level && error == NO_ERROR)
Sergunb 0:8918a71cdbe9 290 error = httpCloseStream(connection);
Sergunb 0:8918a71cdbe9 291 #else
Sergunb 0:8918a71cdbe9 292 //Parse the specified file
Sergunb 0:8918a71cdbe9 293 while(length > 0)
Sergunb 0:8918a71cdbe9 294 {
Sergunb 0:8918a71cdbe9 295 //Search for any SSI tags
Sergunb 0:8918a71cdbe9 296 error = ssiSearchTag(data, length, "<!--#", 5, &i);
Sergunb 0:8918a71cdbe9 297
Sergunb 0:8918a71cdbe9 298 //Opening identifier found?
Sergunb 0:8918a71cdbe9 299 if(!error)
Sergunb 0:8918a71cdbe9 300 {
Sergunb 0:8918a71cdbe9 301 //Search for the comment terminator
Sergunb 0:8918a71cdbe9 302 error = ssiSearchTag(data + i + 5, length - i - 5, "-->", 3, &j);
Sergunb 0:8918a71cdbe9 303 }
Sergunb 0:8918a71cdbe9 304
Sergunb 0:8918a71cdbe9 305 //Check whether a valid SSI tag has been found?
Sergunb 0:8918a71cdbe9 306 if(!error)
Sergunb 0:8918a71cdbe9 307 {
Sergunb 0:8918a71cdbe9 308 //Send the part of the file that precedes the tag
Sergunb 0:8918a71cdbe9 309 error = httpWriteStream(connection, data, i);
Sergunb 0:8918a71cdbe9 310 //Failed to send data?
Sergunb 0:8918a71cdbe9 311 if(error)
Sergunb 0:8918a71cdbe9 312 return error;
Sergunb 0:8918a71cdbe9 313
Sergunb 0:8918a71cdbe9 314 //Advance data pointer over the opening identifier
Sergunb 0:8918a71cdbe9 315 data += i + 5;
Sergunb 0:8918a71cdbe9 316 length -= i + 5;
Sergunb 0:8918a71cdbe9 317
Sergunb 0:8918a71cdbe9 318 //Process SSI directive
Sergunb 0:8918a71cdbe9 319 error = ssiProcessCommand(connection, data, j, uri, level);
Sergunb 0:8918a71cdbe9 320 //Any error to report?
Sergunb 0:8918a71cdbe9 321 if(error)
Sergunb 0:8918a71cdbe9 322 return error;
Sergunb 0:8918a71cdbe9 323
Sergunb 0:8918a71cdbe9 324 //Advance data pointer over the SSI tag
Sergunb 0:8918a71cdbe9 325 data += j + 3;
Sergunb 0:8918a71cdbe9 326 length -= j + 3;
Sergunb 0:8918a71cdbe9 327 }
Sergunb 0:8918a71cdbe9 328 else
Sergunb 0:8918a71cdbe9 329 {
Sergunb 0:8918a71cdbe9 330 //Send the rest of the file
Sergunb 0:8918a71cdbe9 331 error = httpWriteStream(connection, data, length);
Sergunb 0:8918a71cdbe9 332 //Failed to send data?
Sergunb 0:8918a71cdbe9 333 if(error)
Sergunb 0:8918a71cdbe9 334 return error;
Sergunb 0:8918a71cdbe9 335
Sergunb 0:8918a71cdbe9 336 //Advance data pointer
Sergunb 0:8918a71cdbe9 337 data += length;
Sergunb 0:8918a71cdbe9 338 length = 0;
Sergunb 0:8918a71cdbe9 339 }
Sergunb 0:8918a71cdbe9 340 }
Sergunb 0:8918a71cdbe9 341
Sergunb 0:8918a71cdbe9 342 //Properly close the output stream
Sergunb 0:8918a71cdbe9 343 if(!level)
Sergunb 0:8918a71cdbe9 344 error = httpCloseStream(connection);
Sergunb 0:8918a71cdbe9 345 #endif
Sergunb 0:8918a71cdbe9 346
Sergunb 0:8918a71cdbe9 347 //Return status code
Sergunb 0:8918a71cdbe9 348 return error;
Sergunb 0:8918a71cdbe9 349 }
Sergunb 0:8918a71cdbe9 350
Sergunb 0:8918a71cdbe9 351
Sergunb 0:8918a71cdbe9 352 /**
Sergunb 0:8918a71cdbe9 353 * @brief Process SSI directive
Sergunb 0:8918a71cdbe9 354 * @param[in] connection Structure representing an HTTP connection
Sergunb 0:8918a71cdbe9 355 * @param[in] tag Pointer to the SSI tag
Sergunb 0:8918a71cdbe9 356 * @param[in] length Total length of the SSI tag
Sergunb 0:8918a71cdbe9 357 * @param[in] uri NULL-terminated string containing the file being processed
Sergunb 0:8918a71cdbe9 358 * @param[in] level Current level of recursion
Sergunb 0:8918a71cdbe9 359 * @return Error code
Sergunb 0:8918a71cdbe9 360 **/
Sergunb 0:8918a71cdbe9 361
Sergunb 0:8918a71cdbe9 362 error_t ssiProcessCommand(HttpConnection *connection,
Sergunb 0:8918a71cdbe9 363 const char_t *tag, size_t length, const char_t *uri, uint_t level)
Sergunb 0:8918a71cdbe9 364 {
Sergunb 0:8918a71cdbe9 365 error_t error;
Sergunb 0:8918a71cdbe9 366
Sergunb 0:8918a71cdbe9 367 //Include command found?
Sergunb 0:8918a71cdbe9 368 if(length > 7 && !strncasecmp(tag, "include", 7))
Sergunb 0:8918a71cdbe9 369 {
Sergunb 0:8918a71cdbe9 370 //Process SSI include directive
Sergunb 0:8918a71cdbe9 371 error = ssiProcessIncludeCommand(connection, tag, length, uri, level);
Sergunb 0:8918a71cdbe9 372 }
Sergunb 0:8918a71cdbe9 373 //Echo command found?
Sergunb 0:8918a71cdbe9 374 else if(length > 4 && !strncasecmp(tag, "echo", 4))
Sergunb 0:8918a71cdbe9 375 {
Sergunb 0:8918a71cdbe9 376 //Process SSI echo directive
Sergunb 0:8918a71cdbe9 377 error = ssiProcessEchoCommand(connection, tag, length);
Sergunb 0:8918a71cdbe9 378 }
Sergunb 0:8918a71cdbe9 379 //Exec command found?
Sergunb 0:8918a71cdbe9 380 else if(length > 4 && !strncasecmp(tag, "exec", 4))
Sergunb 0:8918a71cdbe9 381 {
Sergunb 0:8918a71cdbe9 382 //Process SSI exec directive
Sergunb 0:8918a71cdbe9 383 error = ssiProcessExecCommand(connection, tag, length);
Sergunb 0:8918a71cdbe9 384 }
Sergunb 0:8918a71cdbe9 385 //Unknown command?
Sergunb 0:8918a71cdbe9 386 else
Sergunb 0:8918a71cdbe9 387 {
Sergunb 0:8918a71cdbe9 388 //The server is unable to decode the SSI tag
Sergunb 0:8918a71cdbe9 389 error = ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 390 }
Sergunb 0:8918a71cdbe9 391
Sergunb 0:8918a71cdbe9 392 //Invalid SSI directive?
Sergunb 0:8918a71cdbe9 393 if(error == ERROR_INVALID_TAG)
Sergunb 0:8918a71cdbe9 394 {
Sergunb 0:8918a71cdbe9 395 //Report a warning to the user
Sergunb 0:8918a71cdbe9 396 error = httpWriteStream(connection, "Warning: Invalid SSI Tag", 24);
Sergunb 0:8918a71cdbe9 397 }
Sergunb 0:8918a71cdbe9 398
Sergunb 0:8918a71cdbe9 399 //Return status code
Sergunb 0:8918a71cdbe9 400 return error;
Sergunb 0:8918a71cdbe9 401 }
Sergunb 0:8918a71cdbe9 402
Sergunb 0:8918a71cdbe9 403
Sergunb 0:8918a71cdbe9 404 /**
Sergunb 0:8918a71cdbe9 405 * @brief Process SSI include directive
Sergunb 0:8918a71cdbe9 406 *
Sergunb 0:8918a71cdbe9 407 * This include directive allows the content of one document to be included
Sergunb 0:8918a71cdbe9 408 * in another. The file parameter defines the included file as relative to
Sergunb 0:8918a71cdbe9 409 * the document path. The virtual parameter defines the included file as
Sergunb 0:8918a71cdbe9 410 * relative to the document root
Sergunb 0:8918a71cdbe9 411 *
Sergunb 0:8918a71cdbe9 412 * @param[in] connection Structure representing an HTTP connection
Sergunb 0:8918a71cdbe9 413 * @param[in] tag Pointer to the SSI tag
Sergunb 0:8918a71cdbe9 414 * @param[in] length Total length of the SSI tag
Sergunb 0:8918a71cdbe9 415 * @param[in] uri NULL-terminated string containing the file being processed
Sergunb 0:8918a71cdbe9 416 * @param[in] level Current level of recursion
Sergunb 0:8918a71cdbe9 417 * @return Error code
Sergunb 0:8918a71cdbe9 418 **/
Sergunb 0:8918a71cdbe9 419
Sergunb 0:8918a71cdbe9 420 error_t ssiProcessIncludeCommand(HttpConnection *connection,
Sergunb 0:8918a71cdbe9 421 const char_t *tag, size_t length, const char_t *uri, uint_t level)
Sergunb 0:8918a71cdbe9 422 {
Sergunb 0:8918a71cdbe9 423 error_t error;
Sergunb 0:8918a71cdbe9 424 char_t *separator;
Sergunb 0:8918a71cdbe9 425 char_t *attribute;
Sergunb 0:8918a71cdbe9 426 char_t *value;
Sergunb 0:8918a71cdbe9 427 char_t *path;
Sergunb 0:8918a71cdbe9 428 char_t *p;
Sergunb 0:8918a71cdbe9 429
Sergunb 0:8918a71cdbe9 430 //Discard invalid SSI directives
Sergunb 0:8918a71cdbe9 431 if(length < 7 || length >= HTTP_SERVER_BUFFER_SIZE)
Sergunb 0:8918a71cdbe9 432 return ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 433
Sergunb 0:8918a71cdbe9 434 //Skip the SSI include command (7 bytes)
Sergunb 0:8918a71cdbe9 435 memcpy(connection->buffer, tag + 7, length - 7);
Sergunb 0:8918a71cdbe9 436 //Ensure the resulting string is NULL-terminated
Sergunb 0:8918a71cdbe9 437 connection->buffer[length - 7] = '\0';
Sergunb 0:8918a71cdbe9 438
Sergunb 0:8918a71cdbe9 439 //Check whether a separator is present
Sergunb 0:8918a71cdbe9 440 separator = strchr(connection->buffer, '=');
Sergunb 0:8918a71cdbe9 441 //Separator not found?
Sergunb 0:8918a71cdbe9 442 if(!separator)
Sergunb 0:8918a71cdbe9 443 return ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 444
Sergunb 0:8918a71cdbe9 445 //Split the tag
Sergunb 0:8918a71cdbe9 446 *separator = '\0';
Sergunb 0:8918a71cdbe9 447
Sergunb 0:8918a71cdbe9 448 //Get attribute name and value
Sergunb 0:8918a71cdbe9 449 attribute = strTrimWhitespace(connection->buffer);
Sergunb 0:8918a71cdbe9 450 value = strTrimWhitespace(separator + 1);
Sergunb 0:8918a71cdbe9 451
Sergunb 0:8918a71cdbe9 452 //Remove leading simple or double quote
Sergunb 0:8918a71cdbe9 453 if(value[0] == '\'' || value[0] == '\"')
Sergunb 0:8918a71cdbe9 454 value++;
Sergunb 0:8918a71cdbe9 455
Sergunb 0:8918a71cdbe9 456 //Get the length of the attribute value
Sergunb 0:8918a71cdbe9 457 length = strlen(value);
Sergunb 0:8918a71cdbe9 458
Sergunb 0:8918a71cdbe9 459 //Remove trailing simple or double quote
Sergunb 0:8918a71cdbe9 460 if(length > 0)
Sergunb 0:8918a71cdbe9 461 {
Sergunb 0:8918a71cdbe9 462 if(value[length - 1] == '\'' || value[length - 1] == '\"')
Sergunb 0:8918a71cdbe9 463 value[length - 1] = '\0';
Sergunb 0:8918a71cdbe9 464 }
Sergunb 0:8918a71cdbe9 465
Sergunb 0:8918a71cdbe9 466 //Check the length of the filename
Sergunb 0:8918a71cdbe9 467 if(strlen(value) > HTTP_SERVER_URI_MAX_LEN)
Sergunb 0:8918a71cdbe9 468 return ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 469
Sergunb 0:8918a71cdbe9 470 //The file parameter defines the included file as relative to the document path
Sergunb 0:8918a71cdbe9 471 if(!strcasecmp(attribute, "file"))
Sergunb 0:8918a71cdbe9 472 {
Sergunb 0:8918a71cdbe9 473 //Allocate a buffer to hold the path to the file to be included
Sergunb 0:8918a71cdbe9 474 path = osAllocMem(strlen(uri) + strlen(value) + 1);
Sergunb 0:8918a71cdbe9 475 //Failed to allocate memory?
Sergunb 0:8918a71cdbe9 476 if(path == NULL)
Sergunb 0:8918a71cdbe9 477 return ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 478
Sergunb 0:8918a71cdbe9 479 //Copy the path identifying the script file being processed
Sergunb 0:8918a71cdbe9 480 strcpy(path, uri);
Sergunb 0:8918a71cdbe9 481 //Search for the last slash character
Sergunb 0:8918a71cdbe9 482 p = strrchr(path, '/');
Sergunb 0:8918a71cdbe9 483
Sergunb 0:8918a71cdbe9 484 //Remove the filename from the path if applicable
Sergunb 0:8918a71cdbe9 485 if(p)
Sergunb 0:8918a71cdbe9 486 strcpy(p + 1, value);
Sergunb 0:8918a71cdbe9 487 else
Sergunb 0:8918a71cdbe9 488 strcpy(path, value);
Sergunb 0:8918a71cdbe9 489 }
Sergunb 0:8918a71cdbe9 490 //The virtual parameter defines the included file as relative to the document root
Sergunb 0:8918a71cdbe9 491 else if(!strcasecmp(attribute, "virtual"))
Sergunb 0:8918a71cdbe9 492 {
Sergunb 0:8918a71cdbe9 493 //Copy the absolute path
Sergunb 0:8918a71cdbe9 494 path = strDuplicate(value);
Sergunb 0:8918a71cdbe9 495 //Failed to duplicate the string?
Sergunb 0:8918a71cdbe9 496 if(path == NULL)
Sergunb 0:8918a71cdbe9 497 return ERROR_OUT_OF_MEMORY;
Sergunb 0:8918a71cdbe9 498 }
Sergunb 0:8918a71cdbe9 499 //Unknown parameter...
Sergunb 0:8918a71cdbe9 500 else
Sergunb 0:8918a71cdbe9 501 {
Sergunb 0:8918a71cdbe9 502 //Report an error
Sergunb 0:8918a71cdbe9 503 return ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 504 }
Sergunb 0:8918a71cdbe9 505
Sergunb 0:8918a71cdbe9 506 //Use server-side scripting to dynamically generate HTML code?
Sergunb 0:8918a71cdbe9 507 if(httpCompExtension(value, ".stm") ||
Sergunb 0:8918a71cdbe9 508 httpCompExtension(value, ".shtm") ||
Sergunb 0:8918a71cdbe9 509 httpCompExtension(value, ".shtml"))
Sergunb 0:8918a71cdbe9 510 {
Sergunb 0:8918a71cdbe9 511 //SSI processing (Server Side Includes)
Sergunb 0:8918a71cdbe9 512 error = ssiExecuteScript(connection, path, level + 1);
Sergunb 0:8918a71cdbe9 513 }
Sergunb 0:8918a71cdbe9 514 else
Sergunb 0:8918a71cdbe9 515 {
Sergunb 0:8918a71cdbe9 516 #if (HTTP_SERVER_FS_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 517 FsFile *file;
Sergunb 0:8918a71cdbe9 518
Sergunb 0:8918a71cdbe9 519 //Retrieve the full pathname
Sergunb 0:8918a71cdbe9 520 httpGetAbsolutePath(connection, path,
Sergunb 0:8918a71cdbe9 521 connection->buffer, HTTP_SERVER_BUFFER_SIZE);
Sergunb 0:8918a71cdbe9 522
Sergunb 0:8918a71cdbe9 523 //Open the file for reading
Sergunb 0:8918a71cdbe9 524 file = fsOpenFile(connection->buffer, FS_FILE_MODE_READ);
Sergunb 0:8918a71cdbe9 525
Sergunb 0:8918a71cdbe9 526 //Successful operation?
Sergunb 0:8918a71cdbe9 527 if(file)
Sergunb 0:8918a71cdbe9 528 {
Sergunb 0:8918a71cdbe9 529 //Send the contents of the requested file
Sergunb 0:8918a71cdbe9 530 while(1)
Sergunb 0:8918a71cdbe9 531 {
Sergunb 0:8918a71cdbe9 532 //Read data from the specified file
Sergunb 0:8918a71cdbe9 533 error = fsReadFile(file, connection->buffer, HTTP_SERVER_BUFFER_SIZE, &length);
Sergunb 0:8918a71cdbe9 534 //End of input stream?
Sergunb 0:8918a71cdbe9 535 if(error)
Sergunb 0:8918a71cdbe9 536 break;
Sergunb 0:8918a71cdbe9 537
Sergunb 0:8918a71cdbe9 538 //Send data to the client
Sergunb 0:8918a71cdbe9 539 error = httpWriteStream(connection, connection->buffer, length);
Sergunb 0:8918a71cdbe9 540 //Any error to report?
Sergunb 0:8918a71cdbe9 541 if(error)
Sergunb 0:8918a71cdbe9 542 break;
Sergunb 0:8918a71cdbe9 543 }
Sergunb 0:8918a71cdbe9 544
Sergunb 0:8918a71cdbe9 545 //Close the file
Sergunb 0:8918a71cdbe9 546 fsCloseFile(file);
Sergunb 0:8918a71cdbe9 547
Sergunb 0:8918a71cdbe9 548 //Successful file transfer?
Sergunb 0:8918a71cdbe9 549 if(error == ERROR_END_OF_FILE)
Sergunb 0:8918a71cdbe9 550 error = NO_ERROR;
Sergunb 0:8918a71cdbe9 551 }
Sergunb 0:8918a71cdbe9 552 else
Sergunb 0:8918a71cdbe9 553 {
Sergunb 0:8918a71cdbe9 554 //The specified URI cannot be found
Sergunb 0:8918a71cdbe9 555 error = ERROR_NOT_FOUND;
Sergunb 0:8918a71cdbe9 556 }
Sergunb 0:8918a71cdbe9 557 #else
Sergunb 0:8918a71cdbe9 558 uint8_t *data;
Sergunb 0:8918a71cdbe9 559
Sergunb 0:8918a71cdbe9 560 //Retrieve the full pathname
Sergunb 0:8918a71cdbe9 561 httpGetAbsolutePath(connection, path,
Sergunb 0:8918a71cdbe9 562 connection->buffer, HTTP_SERVER_BUFFER_SIZE);
Sergunb 0:8918a71cdbe9 563
Sergunb 0:8918a71cdbe9 564 //Get the resource data associated with the file
Sergunb 0:8918a71cdbe9 565 error = resGetData(connection->buffer, &data, &length);
Sergunb 0:8918a71cdbe9 566
Sergunb 0:8918a71cdbe9 567 //Send the contents of the requested file
Sergunb 0:8918a71cdbe9 568 if(!error)
Sergunb 0:8918a71cdbe9 569 error = httpWriteStream(connection, data, length);
Sergunb 0:8918a71cdbe9 570 #endif
Sergunb 0:8918a71cdbe9 571 }
Sergunb 0:8918a71cdbe9 572
Sergunb 0:8918a71cdbe9 573 //Cannot found the specified resource?
Sergunb 0:8918a71cdbe9 574 if(error == ERROR_NOT_FOUND)
Sergunb 0:8918a71cdbe9 575 error = ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 576
Sergunb 0:8918a71cdbe9 577 //Release previously allocated memory
Sergunb 0:8918a71cdbe9 578 osFreeMem(path);
Sergunb 0:8918a71cdbe9 579 //return status code
Sergunb 0:8918a71cdbe9 580 return error;
Sergunb 0:8918a71cdbe9 581 }
Sergunb 0:8918a71cdbe9 582
Sergunb 0:8918a71cdbe9 583
Sergunb 0:8918a71cdbe9 584 /**
Sergunb 0:8918a71cdbe9 585 * @brief Process SSI echo directive
Sergunb 0:8918a71cdbe9 586 *
Sergunb 0:8918a71cdbe9 587 * This echo directive displays the contents of a specified
Sergunb 0:8918a71cdbe9 588 * HTTP environment variable
Sergunb 0:8918a71cdbe9 589 *
Sergunb 0:8918a71cdbe9 590 * @param[in] connection Structure representing an HTTP connection
Sergunb 0:8918a71cdbe9 591 * @param[in] tag Pointer to the SSI tag
Sergunb 0:8918a71cdbe9 592 * @param[in] length Total length of the SSI tag
Sergunb 0:8918a71cdbe9 593 * @return Error code
Sergunb 0:8918a71cdbe9 594 **/
Sergunb 0:8918a71cdbe9 595
Sergunb 0:8918a71cdbe9 596 error_t ssiProcessEchoCommand(HttpConnection *connection, const char_t *tag, size_t length)
Sergunb 0:8918a71cdbe9 597 {
Sergunb 0:8918a71cdbe9 598 error_t error;
Sergunb 0:8918a71cdbe9 599 char_t *separator;
Sergunb 0:8918a71cdbe9 600 char_t *attribute;
Sergunb 0:8918a71cdbe9 601 char_t *value;
Sergunb 0:8918a71cdbe9 602
Sergunb 0:8918a71cdbe9 603 //Discard invalid SSI directives
Sergunb 0:8918a71cdbe9 604 if(length < 4 || length >= HTTP_SERVER_BUFFER_SIZE)
Sergunb 0:8918a71cdbe9 605 return ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 606
Sergunb 0:8918a71cdbe9 607 //Skip the SSI echo command (4 bytes)
Sergunb 0:8918a71cdbe9 608 memcpy(connection->buffer, tag + 4, length - 4);
Sergunb 0:8918a71cdbe9 609 //Ensure the resulting string is NULL-terminated
Sergunb 0:8918a71cdbe9 610 connection->buffer[length - 4] = '\0';
Sergunb 0:8918a71cdbe9 611
Sergunb 0:8918a71cdbe9 612 //Check whether a separator is present
Sergunb 0:8918a71cdbe9 613 separator = strchr(connection->buffer, '=');
Sergunb 0:8918a71cdbe9 614 //Separator not found?
Sergunb 0:8918a71cdbe9 615 if(!separator)
Sergunb 0:8918a71cdbe9 616 return ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 617
Sergunb 0:8918a71cdbe9 618 //Split the tag
Sergunb 0:8918a71cdbe9 619 *separator = '\0';
Sergunb 0:8918a71cdbe9 620
Sergunb 0:8918a71cdbe9 621 //Get attribute name and value
Sergunb 0:8918a71cdbe9 622 attribute = strTrimWhitespace(connection->buffer);
Sergunb 0:8918a71cdbe9 623 value = strTrimWhitespace(separator + 1);
Sergunb 0:8918a71cdbe9 624
Sergunb 0:8918a71cdbe9 625 //Remove leading simple or double quote
Sergunb 0:8918a71cdbe9 626 if(value[0] == '\'' || value[0] == '\"')
Sergunb 0:8918a71cdbe9 627 value++;
Sergunb 0:8918a71cdbe9 628
Sergunb 0:8918a71cdbe9 629 //Get the length of the attribute value
Sergunb 0:8918a71cdbe9 630 length = strlen(value);
Sergunb 0:8918a71cdbe9 631
Sergunb 0:8918a71cdbe9 632 //Remove trailing simple or double quote
Sergunb 0:8918a71cdbe9 633 if(length > 0)
Sergunb 0:8918a71cdbe9 634 {
Sergunb 0:8918a71cdbe9 635 if(value[length - 1] == '\'' || value[length - 1] == '\"')
Sergunb 0:8918a71cdbe9 636 value[length - 1] = '\0';
Sergunb 0:8918a71cdbe9 637 }
Sergunb 0:8918a71cdbe9 638
Sergunb 0:8918a71cdbe9 639 //Enforce attribute name
Sergunb 0:8918a71cdbe9 640 if(strcasecmp(attribute, "var"))
Sergunb 0:8918a71cdbe9 641 return ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 642
Sergunb 0:8918a71cdbe9 643 //Remote address?
Sergunb 0:8918a71cdbe9 644 if(!strcasecmp(value, "REMOTE_ADDR"))
Sergunb 0:8918a71cdbe9 645 {
Sergunb 0:8918a71cdbe9 646 //The IP address of the host making this request
Sergunb 0:8918a71cdbe9 647 ipAddrToString(&connection->socket->remoteIpAddr, connection->buffer);
Sergunb 0:8918a71cdbe9 648 }
Sergunb 0:8918a71cdbe9 649 //Remote port?
Sergunb 0:8918a71cdbe9 650 else if(!strcasecmp(value, "REMOTE_PORT"))
Sergunb 0:8918a71cdbe9 651 {
Sergunb 0:8918a71cdbe9 652 //The port number used by the remote host when making this request
Sergunb 0:8918a71cdbe9 653 sprintf(connection->buffer, "%" PRIu16, connection->socket->remotePort);
Sergunb 0:8918a71cdbe9 654 }
Sergunb 0:8918a71cdbe9 655 //Server address?
Sergunb 0:8918a71cdbe9 656 else if(!strcasecmp(value, "SERVER_ADDR"))
Sergunb 0:8918a71cdbe9 657 {
Sergunb 0:8918a71cdbe9 658 //The IP address of the server for this URL
Sergunb 0:8918a71cdbe9 659 ipAddrToString(&connection->socket->localIpAddr, connection->buffer);
Sergunb 0:8918a71cdbe9 660 }
Sergunb 0:8918a71cdbe9 661 //Server port?
Sergunb 0:8918a71cdbe9 662 else if(!strcasecmp(value, "SERVER_PORT"))
Sergunb 0:8918a71cdbe9 663 {
Sergunb 0:8918a71cdbe9 664 //The port number on this server to which this request was directed
Sergunb 0:8918a71cdbe9 665 sprintf(connection->buffer, "%" PRIu16, connection->socket->localPort);
Sergunb 0:8918a71cdbe9 666 }
Sergunb 0:8918a71cdbe9 667 //Request method?
Sergunb 0:8918a71cdbe9 668 else if(!strcasecmp(value, "REQUEST_METHOD"))
Sergunb 0:8918a71cdbe9 669 {
Sergunb 0:8918a71cdbe9 670 //The method used for this HTTP request
Sergunb 0:8918a71cdbe9 671 strcpy(connection->buffer, connection->request.method);
Sergunb 0:8918a71cdbe9 672 }
Sergunb 0:8918a71cdbe9 673 //Document root?
Sergunb 0:8918a71cdbe9 674 else if(!strcasecmp(value, "DOCUMENT_ROOT"))
Sergunb 0:8918a71cdbe9 675 {
Sergunb 0:8918a71cdbe9 676 //The root directory
Sergunb 0:8918a71cdbe9 677 strcpy(connection->buffer, connection->settings->rootDirectory);
Sergunb 0:8918a71cdbe9 678 }
Sergunb 0:8918a71cdbe9 679 //Document URI?
Sergunb 0:8918a71cdbe9 680 else if(!strcasecmp(value, "DOCUMENT_URI"))
Sergunb 0:8918a71cdbe9 681 {
Sergunb 0:8918a71cdbe9 682 //The URI for this request relative to the root directory
Sergunb 0:8918a71cdbe9 683 strcpy(connection->buffer, connection->request.uri);
Sergunb 0:8918a71cdbe9 684 }
Sergunb 0:8918a71cdbe9 685 //Document name?
Sergunb 0:8918a71cdbe9 686 else if(!strcasecmp(value, "DOCUMENT_NAME"))
Sergunb 0:8918a71cdbe9 687 {
Sergunb 0:8918a71cdbe9 688 //The full physical path and filename of the document requested
Sergunb 0:8918a71cdbe9 689 httpGetAbsolutePath(connection, connection->request.uri,
Sergunb 0:8918a71cdbe9 690 connection->buffer, HTTP_SERVER_BUFFER_SIZE);
Sergunb 0:8918a71cdbe9 691 }
Sergunb 0:8918a71cdbe9 692 //Query string?
Sergunb 0:8918a71cdbe9 693 else if(!strcasecmp(value, "QUERY_STRING"))
Sergunb 0:8918a71cdbe9 694 {
Sergunb 0:8918a71cdbe9 695 //The information following the "?" in the URL for this request
Sergunb 0:8918a71cdbe9 696 strcpy(connection->buffer, connection->request.queryString);
Sergunb 0:8918a71cdbe9 697 }
Sergunb 0:8918a71cdbe9 698 //User name?
Sergunb 0:8918a71cdbe9 699 else if(!strcasecmp(value, "AUTH_USER"))
Sergunb 0:8918a71cdbe9 700 {
Sergunb 0:8918a71cdbe9 701 #if (HTTP_SERVER_BASIC_AUTH_SUPPORT == ENABLED || HTTP_SERVER_DIGEST_AUTH_SUPPORT == ENABLED)
Sergunb 0:8918a71cdbe9 702 //The username provided by the user to the server
Sergunb 0:8918a71cdbe9 703 strcpy(connection->buffer, connection->request.auth.user);
Sergunb 0:8918a71cdbe9 704 #else
Sergunb 0:8918a71cdbe9 705 //Basic access authentication is not supported
Sergunb 0:8918a71cdbe9 706 connection->buffer[0] = '\0';
Sergunb 0:8918a71cdbe9 707 #endif
Sergunb 0:8918a71cdbe9 708 }
Sergunb 0:8918a71cdbe9 709 //GMT time?
Sergunb 0:8918a71cdbe9 710 else if(!strcasecmp(value, "DATE_GMT"))
Sergunb 0:8918a71cdbe9 711 {
Sergunb 0:8918a71cdbe9 712 //The current date and time in Greenwich Mean Time
Sergunb 0:8918a71cdbe9 713 connection->buffer[0] = '\0';
Sergunb 0:8918a71cdbe9 714 }
Sergunb 0:8918a71cdbe9 715 //Local time?
Sergunb 0:8918a71cdbe9 716 else if(!strcasecmp(value, "DATE_LOCAL"))
Sergunb 0:8918a71cdbe9 717 {
Sergunb 0:8918a71cdbe9 718 //The current date and time in the local timezone
Sergunb 0:8918a71cdbe9 719 connection->buffer[0] = '\0';
Sergunb 0:8918a71cdbe9 720 }
Sergunb 0:8918a71cdbe9 721 //Unknown variable?
Sergunb 0:8918a71cdbe9 722 else
Sergunb 0:8918a71cdbe9 723 {
Sergunb 0:8918a71cdbe9 724 //Report an error
Sergunb 0:8918a71cdbe9 725 return ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 726 }
Sergunb 0:8918a71cdbe9 727
Sergunb 0:8918a71cdbe9 728 //Get the length of the resulting string
Sergunb 0:8918a71cdbe9 729 length = strlen(connection->buffer);
Sergunb 0:8918a71cdbe9 730
Sergunb 0:8918a71cdbe9 731 //Send the contents of the specified environment variable
Sergunb 0:8918a71cdbe9 732 error = httpWriteStream(connection, connection->buffer, length);
Sergunb 0:8918a71cdbe9 733 //Failed to send data?
Sergunb 0:8918a71cdbe9 734 if(error)
Sergunb 0:8918a71cdbe9 735 return error;
Sergunb 0:8918a71cdbe9 736
Sergunb 0:8918a71cdbe9 737 //Successful processing
Sergunb 0:8918a71cdbe9 738 return NO_ERROR;
Sergunb 0:8918a71cdbe9 739 }
Sergunb 0:8918a71cdbe9 740
Sergunb 0:8918a71cdbe9 741
Sergunb 0:8918a71cdbe9 742 /**
Sergunb 0:8918a71cdbe9 743 * @brief Process SSI exec directive
Sergunb 0:8918a71cdbe9 744 *
Sergunb 0:8918a71cdbe9 745 * This exec directive executes a program, script, or shell command on
Sergunb 0:8918a71cdbe9 746 * the server. The cmd parameter specifies a server-side command. The
Sergunb 0:8918a71cdbe9 747 * cgi parameter specifies the path to a CGI script
Sergunb 0:8918a71cdbe9 748 *
Sergunb 0:8918a71cdbe9 749 * @param[in] connection Structure representing an HTTP connection
Sergunb 0:8918a71cdbe9 750 * @param[in] tag Pointer to the SSI tag
Sergunb 0:8918a71cdbe9 751 * @param[in] length Total length of the SSI tag
Sergunb 0:8918a71cdbe9 752 * @return Error code
Sergunb 0:8918a71cdbe9 753 **/
Sergunb 0:8918a71cdbe9 754
Sergunb 0:8918a71cdbe9 755 error_t ssiProcessExecCommand(HttpConnection *connection, const char_t *tag, size_t length)
Sergunb 0:8918a71cdbe9 756 {
Sergunb 0:8918a71cdbe9 757 char_t *separator;
Sergunb 0:8918a71cdbe9 758 char_t *attribute;
Sergunb 0:8918a71cdbe9 759 char_t *value;
Sergunb 0:8918a71cdbe9 760
Sergunb 0:8918a71cdbe9 761 //First, check whether CGI is supported by the server
Sergunb 0:8918a71cdbe9 762 if(connection->settings->cgiCallback == NULL)
Sergunb 0:8918a71cdbe9 763 return ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 764
Sergunb 0:8918a71cdbe9 765 //Discard invalid SSI directives
Sergunb 0:8918a71cdbe9 766 if(length < 4 || length >= HTTP_SERVER_BUFFER_SIZE)
Sergunb 0:8918a71cdbe9 767 return ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 768
Sergunb 0:8918a71cdbe9 769 //Skip the SSI exec command (4 bytes)
Sergunb 0:8918a71cdbe9 770 memcpy(connection->buffer, tag + 4, length - 4);
Sergunb 0:8918a71cdbe9 771 //Ensure the resulting string is NULL-terminated
Sergunb 0:8918a71cdbe9 772 connection->buffer[length - 4] = '\0';
Sergunb 0:8918a71cdbe9 773
Sergunb 0:8918a71cdbe9 774 //Check whether a separator is present
Sergunb 0:8918a71cdbe9 775 separator = strchr(connection->buffer, '=');
Sergunb 0:8918a71cdbe9 776 //Separator not found?
Sergunb 0:8918a71cdbe9 777 if(!separator)
Sergunb 0:8918a71cdbe9 778 return ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 779
Sergunb 0:8918a71cdbe9 780 //Split the tag
Sergunb 0:8918a71cdbe9 781 *separator = '\0';
Sergunb 0:8918a71cdbe9 782
Sergunb 0:8918a71cdbe9 783 //Get attribute name and value
Sergunb 0:8918a71cdbe9 784 attribute = strTrimWhitespace(connection->buffer);
Sergunb 0:8918a71cdbe9 785 value = strTrimWhitespace(separator + 1);
Sergunb 0:8918a71cdbe9 786
Sergunb 0:8918a71cdbe9 787 //Remove leading simple or double quote
Sergunb 0:8918a71cdbe9 788 if(value[0] == '\'' || value[0] == '\"')
Sergunb 0:8918a71cdbe9 789 value++;
Sergunb 0:8918a71cdbe9 790
Sergunb 0:8918a71cdbe9 791 //Get the length of the attribute value
Sergunb 0:8918a71cdbe9 792 length = strlen(value);
Sergunb 0:8918a71cdbe9 793
Sergunb 0:8918a71cdbe9 794 //Remove trailing simple or double quote
Sergunb 0:8918a71cdbe9 795 if(length > 0)
Sergunb 0:8918a71cdbe9 796 {
Sergunb 0:8918a71cdbe9 797 if(value[length - 1] == '\'' || value[length - 1] == '\"')
Sergunb 0:8918a71cdbe9 798 value[length - 1] = '\0';
Sergunb 0:8918a71cdbe9 799 }
Sergunb 0:8918a71cdbe9 800
Sergunb 0:8918a71cdbe9 801 //Enforce attribute name
Sergunb 0:8918a71cdbe9 802 if(strcasecmp(attribute, "cgi") && strcasecmp(attribute, "cmd") && strcasecmp(attribute, "cmd_argument"))
Sergunb 0:8918a71cdbe9 803 return ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 804 //Check the length of the CGI parameter
Sergunb 0:8918a71cdbe9 805 if(strlen(value) > HTTP_SERVER_CGI_PARAM_MAX_LEN)
Sergunb 0:8918a71cdbe9 806 return ERROR_INVALID_TAG;
Sergunb 0:8918a71cdbe9 807
Sergunb 0:8918a71cdbe9 808 //The scratch buffer may be altered by the user-defined callback.
Sergunb 0:8918a71cdbe9 809 //So the CGI parameter must be copied prior to function invocation
Sergunb 0:8918a71cdbe9 810 strcpy(connection->cgiParam, value);
Sergunb 0:8918a71cdbe9 811
Sergunb 0:8918a71cdbe9 812 //Invoke user-defined callback
Sergunb 0:8918a71cdbe9 813 return connection->settings->cgiCallback(connection, connection->cgiParam);
Sergunb 0:8918a71cdbe9 814 }
Sergunb 0:8918a71cdbe9 815
Sergunb 0:8918a71cdbe9 816
Sergunb 0:8918a71cdbe9 817 /**
Sergunb 0:8918a71cdbe9 818 * @brief Search a string for a given tag
Sergunb 0:8918a71cdbe9 819 * @param[in] s String to search
Sergunb 0:8918a71cdbe9 820 * @param[in] sLen Length of the string to search
Sergunb 0:8918a71cdbe9 821 * @param[in] tag String containing the tag to search for
Sergunb 0:8918a71cdbe9 822 * @param[in] tagLen Length of the tag
Sergunb 0:8918a71cdbe9 823 * @param[out] pos The index of the first occurrence of the tag in the string,
Sergunb 0:8918a71cdbe9 824 * @retval NO_ERROR if the specified tag has been found
Sergunb 0:8918a71cdbe9 825 * @retval ERROR_PARTIAL_MATCH if a partial match occurs
Sergunb 0:8918a71cdbe9 826 * @retval ERROR_NO_MATCH if the tag does not appear in the string
Sergunb 0:8918a71cdbe9 827 **/
Sergunb 0:8918a71cdbe9 828
Sergunb 0:8918a71cdbe9 829 error_t ssiSearchTag(const char_t *s, size_t sLen, const char_t *tag, size_t tagLen, uint_t *pos)
Sergunb 0:8918a71cdbe9 830 {
Sergunb 0:8918a71cdbe9 831 uint_t i;
Sergunb 0:8918a71cdbe9 832 uint_t j;
Sergunb 0:8918a71cdbe9 833
Sergunb 0:8918a71cdbe9 834 //Parse the input string
Sergunb 0:8918a71cdbe9 835 for(i = 0; i <= sLen; i++)
Sergunb 0:8918a71cdbe9 836 {
Sergunb 0:8918a71cdbe9 837 //Compare current substring with the given tag
Sergunb 0:8918a71cdbe9 838 for(j = 0; (i + j) < sLen && j < tagLen; j++)
Sergunb 0:8918a71cdbe9 839 {
Sergunb 0:8918a71cdbe9 840 if(s[i + j] != tag[j])
Sergunb 0:8918a71cdbe9 841 break;
Sergunb 0:8918a71cdbe9 842 }
Sergunb 0:8918a71cdbe9 843
Sergunb 0:8918a71cdbe9 844 //Check whether a full match occurred
Sergunb 0:8918a71cdbe9 845 if(j == tagLen)
Sergunb 0:8918a71cdbe9 846 {
Sergunb 0:8918a71cdbe9 847 //Save the position of the first character
Sergunb 0:8918a71cdbe9 848 *pos = i;
Sergunb 0:8918a71cdbe9 849 //The specified tag has been found
Sergunb 0:8918a71cdbe9 850 return NO_ERROR;
Sergunb 0:8918a71cdbe9 851 }
Sergunb 0:8918a71cdbe9 852 //Check whether a partial match occurred
Sergunb 0:8918a71cdbe9 853 else if((i + j) == sLen && j > 0)
Sergunb 0:8918a71cdbe9 854 {
Sergunb 0:8918a71cdbe9 855 //Save the position of the first character
Sergunb 0:8918a71cdbe9 856 *pos = i;
Sergunb 0:8918a71cdbe9 857 //The beginning of the tag matches the end of the string
Sergunb 0:8918a71cdbe9 858 return ERROR_PARTIAL_MATCH;
Sergunb 0:8918a71cdbe9 859 }
Sergunb 0:8918a71cdbe9 860 }
Sergunb 0:8918a71cdbe9 861
Sergunb 0:8918a71cdbe9 862 //The tag does not appear in the string
Sergunb 0:8918a71cdbe9 863 return ERROR_NO_MATCH;
Sergunb 0:8918a71cdbe9 864 }
Sergunb 0:8918a71cdbe9 865
Sergunb 0:8918a71cdbe9 866 #endif
Sergunb 0:8918a71cdbe9 867