mhd_post_parser.h (16453B)
1 /* SPDX-License-Identifier: LGPL-2.1-or-later OR (GPL-2.0-or-later WITH eCos-exception-2.0) */ 2 /* 3 This file is part of GNU libmicrohttpd. 4 Copyright (C) 2024 Evgeny Grin (Karlson2k) 5 6 GNU libmicrohttpd is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 GNU libmicrohttpd is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 Alternatively, you can redistribute GNU libmicrohttpd and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of 19 the License, or (at your option) any later version, together 20 with the eCos exception, as follows: 21 22 As a special exception, if other files instantiate templates or 23 use macros or inline functions from this file, or you compile this 24 file and link it with other works to produce a work based on this 25 file, this file does not by itself cause the resulting work to be 26 covered by the GNU General Public License. However the source code 27 for this file must still be made available in accordance with 28 section (3) of the GNU General Public License v2. 29 30 This exception does not invalidate any other reasons why a work 31 based on this file might be covered by the GNU General Public 32 License. 33 34 You should have received copies of the GNU Lesser General Public 35 License and the GNU General Public License along with this library; 36 if not, see <https://www.gnu.org/licenses/>. 37 */ 38 39 /** 40 * @file src/mhd2/mhd_post_parser.h 41 * @brief The definition of the post parsers data structures 42 * @author Karlson2k (Evgeny Grin) 43 */ 44 45 #ifndef MHD_POST_PARSER_H 46 #define MHD_POST_PARSER_H 1 47 48 #include "mhd_sys_options.h" 49 50 #include "sys_base_types.h" 51 #include "sys_bool_type.h" 52 53 #include "http_post_enc.h" 54 #include "mhd_post_result.h" 55 #include "mhd_buffer.h" 56 57 #ifdef SIZE_MAX 58 # define mhd_POST_INVALID_POS SIZE_MAX 59 #else 60 # define mhd_POST_INVALID_POS ((size_t) (~((size_t) (0)))) 61 #endif 62 63 /** 64 * The states of the "application/x-www-form-urlencoded" field parsing 65 */ 66 enum MHD_FIXED_ENUM_ mhd_PostUrlEncState 67 { 68 /** 69 * The field processing has not been started 70 */ 71 mhd_POST_UENC_ST_NOT_STARTED = 0 72 , 73 /** 74 * Processing name of the field 75 */ 76 mhd_POST_UENC_ST_NAME 77 , 78 /** 79 * At the '=' character after the name. 80 * This is an intermediate state, should be processed and switched to the next 81 * state immediately. 82 * Should not be used outside processing loop. 83 */ 84 mhd_POST_UENC_ST_AT_EQ 85 , 86 /** 87 * The '=' character after the name has been found. 88 * Looking for the first value character. 89 */ 90 mhd_POST_UENC_ST_EQ_FOUND 91 , 92 /** 93 * Processing the value of the field. 94 */ 95 mhd_POST_UENC_ST_VALUE 96 , 97 /** 98 * At the ampersand '&' character. 99 * Means that full field is found. 100 * This is an intermediate state, should be processed and switched to the next 101 * state immediately. 102 * Should not be used outside processing loop. 103 */ 104 mhd_POST_UENC_ST_AT_AMPRSND 105 , 106 /** 107 * Full field found. 108 * This is an intermediate state, should be processed and switched to the next 109 * state immediately. 110 * Should not be used outside processing loop. 111 */ 112 mhd_POST_UENC_ST_FULL_FIELD_FOUND 113 }; 114 115 /** 116 * The "application/x-www-form-urlencoded" parsing data 117 */ 118 struct mhd_PostParserUrlEncData 119 { 120 /** 121 * The parsing state 122 */ 123 enum mhd_PostUrlEncState st; 124 125 /** 126 * The index of the start of the name. 127 */ 128 size_t name_idx; 129 130 /** 131 * The length of the name of the current field, not including 132 * the terminating zero. 133 * Zero until the length is found. 134 */ 135 size_t name_len; 136 137 /** 138 * The index of the start of the value. 139 * Zero until the value is found. 140 * Cannot be zero if any (including zero-length) value available. 141 */ 142 size_t value_idx; 143 144 /** 145 * The length of the value of the current field, not including 146 * the terminating zero. 147 * Zero until the length is found. 148 * If @a st is #mhd_POST_UENC_ST_VALUE and @a value_len is not zero, 149 * then it is the length of the partial (decoded) value provided previously 150 * to the "stream" processing callback (which responded with a "suspend" 151 * action). 152 */ 153 size_t value_len; 154 155 /** 156 * The index of the last percent ('%') character found. 157 * Set to #mhd_POST_INVALID_POS when no '%' char found. 158 * Used for two proposes: 159 * + indicates that "name" or "value" needs persent-deconding 160 * + helps to detect incomplete percent-encoded char for stream processing 161 */ 162 size_t last_pct_idx; 163 }; 164 165 166 /** 167 * The states of the "multipart/form-data" parsing 168 */ 169 enum MHD_FIXED_ENUM_ mhd_PostMPartState 170 { 171 /** 172 * The parsing has not been started 173 * Should not be used outside processing loop except initial initialisation. 174 */ 175 mhd_POST_MPART_ST_NOT_STARTED = 0 176 , 177 /** 178 * Check for delimiter failed, continuing processing of the preabmle 179 * This is an intermediate state, should be processed and switched to the next 180 * state immediately. 181 * Should not be used outside processing loop. 182 */ 183 mhd_POST_MPART_ST_BACK_TO_PREAMBL 184 , 185 /** 186 * Processing preabmle 187 */ 188 mhd_POST_MPART_ST_PREAMBL 189 , 190 /** 191 * Found CR char in the preamble 192 */ 193 mhd_POST_MPART_ST_PREAMBL_CR_FOUND 194 , 195 /** 196 * Found LF char in the preamble (after CR or just bare LF if allowed) 197 * This is an intermediate state, should be processed and switched to the next 198 * state immediately. 199 * Should not be used outside processing loop. 200 */ 201 mhd_POST_MPART_ST_PREAMBL_LINE_START 202 , 203 /** 204 * Checking for potential delimiter marker at the start of the string 205 */ 206 mhd_POST_MPART_ST_PREAMBL_CHECKING_FOR_DELIM 207 , 208 /** 209 * Found the first delimiter. 210 * Need to find the end of the delimiter string and check for possible "final" 211 * delimiter. 212 */ 213 mhd_POST_MPART_ST_FIRST_DELIM_FOUND 214 , 215 /** 216 * Found start of the first "part" 217 * This is an intermediate state, should be processed and switched to the next 218 * state immediately. 219 */ 220 mhd_POST_MPART_ST_FIRST_PART_START 221 , 222 /** 223 * Found start of the "part" (after the delimiter) 224 * This is an intermediate state, should be processed and switched to the next 225 * state immediately. 226 */ 227 mhd_POST_MPART_ST_PART_START 228 , 229 /** 230 * Starting processing of embedded header line 231 */ 232 mhd_POST_MPART_ST_HEADER_LINE_START 233 , 234 /** 235 * Processing embedded header line 236 */ 237 mhd_POST_MPART_ST_HEADER_LINE 238 , 239 /** 240 * Found CR char in the embedded header line 241 */ 242 mhd_POST_MPART_ST_HEADER_LINE_CR_FOUND 243 , 244 /** 245 * Found complete embedded header line, at the final character. 246 * This is an intermediate state, should be processed and switched to the next 247 * state immediately. 248 * Should not be used outside processing loop. 249 */ 250 mhd_POST_MPART_ST_HEADER_LINE_END 251 , 252 /** 253 * Starting processing of the "value" 254 * This is an intermediate state, should be processed and switched to the next 255 * state immediately. 256 */ 257 mhd_POST_MPART_ST_VALUE_START 258 , 259 /** 260 * Check for delimiter failed, continuing processing of the "value" 261 * This is an intermediate state, should be processed and switched to the next 262 * state immediately. 263 * Can be used outside processing loop if streaming partial value. 264 */ 265 mhd_POST_MPART_ST_BACK_TO_VALUE 266 , 267 /** 268 * Processing "value" 269 */ 270 mhd_POST_MPART_ST_VALUE 271 , 272 /** 273 * Found CR char in the "value" 274 */ 275 mhd_POST_MPART_ST_VALUE_CR_FOUND 276 , 277 /** 278 * Found LF char in the "value" 279 */ 280 mhd_POST_MPART_ST_VALUE_LINE_START 281 , 282 /** 283 * Checking for potential delimiter marker at the start of the string 284 */ 285 mhd_POST_MPART_ST_VALUE_CHECKING_FOR_DELIM 286 , 287 /** 288 * Found the delimiter. 289 * Need to find the end of the delimiter string and check for possible "final" 290 * delimiter. 291 */ 292 mhd_POST_MPART_ST_DELIM_FOUND 293 , 294 /** 295 * Found the end of the "value" 296 * This is an intermediate state, should be processed and switched to the next 297 * state immediately. 298 * Should not be used outside processing loop. 299 */ 300 mhd_POST_MPART_ST_VALUE_END_FOUND 301 , 302 /** 303 * Found the end of the "value" closed by the "final" delimiter 304 * This is an intermediate state, should be processed and switched to the next 305 * state immediately. 306 * Should not be used outside processing loop. 307 */ 308 mhd_POST_MPART_ST_VALUE_END_FOUND_FINAL 309 , 310 /** 311 * Found the complete field 312 */ 313 mhd_POST_MPART_ST_FULL_FIELD_FOUND 314 , 315 /** 316 * Found the complete field closed by the "final" delimiter 317 */ 318 mhd_POST_MPART_ST_FULL_FIELD_FOUND_FINAL 319 , 320 /** 321 * Processing "epilogue" 322 */ 323 mhd_POST_MPART_ST_EPILOGUE 324 , 325 /** 326 * The format of the input data is invalid 327 */ 328 mhd_POST_MPART_ST_FORMAT_ERROR 329 }; 330 331 332 /** 333 * The "multipart/form-data" field parsing data 334 */ 335 struct mhd_PostParserMPartFieldData 336 { 337 /** 338 * The index of the start of the name. 339 */ 340 size_t name_idx; 341 /** 342 * The length of the name of the current field, not including 343 * the terminating zero. 344 * Zero until the length is found. 345 */ 346 size_t name_len; 347 /** 348 * The index of the start of the value. 349 * Zero until the value is found. 350 * Cannot be zero if any (including zero-length) value available. 351 */ 352 size_t value_idx; 353 /** 354 * The length of the value of the current field, not including 355 * the terminating zero. 356 * Zero until the length is found. 357 */ 358 size_t value_len; 359 /** 360 * The index of the start of the filename of the current field. 361 * Zero until the value is found. 362 * Cannot be zero if any (including zero-length) filename available. 363 */ 364 size_t filename_idx; 365 /** 366 * The length of the filename of the current field, not including 367 * the terminating zero. 368 * Zero until the length is found. 369 */ 370 size_t filename_len; 371 /** 372 * The index of the start of the value of the Content-Type of the current 373 * field. 374 * Zero until the value is found. 375 * Cannot be zero if any (including zero-length) filename available. 376 */ 377 size_t cntn_type_idx; 378 /** 379 * The length of the filename of the value of the Content-Type of the current 380 * field, not including the terminating zero. 381 * Zero until the length is found. 382 */ 383 size_t cntn_type_len; 384 /** 385 * The index of the start of the value of the Content-Encoding of the current 386 * field. 387 * Zero until the value is found. 388 * Cannot be zero if any (including zero-length) filename available. 389 */ 390 size_t enc_idx; 391 /** 392 * The length of the filename of the value of the Content-Encoding of 393 * the current field, not including the terminating zero. 394 * Zero until the length is found. 395 */ 396 size_t enc_len; 397 }; 398 399 /** 400 * The "multipart/form-data" parsing data 401 */ 402 struct mhd_PostParserMPartFormData 403 { 404 /** 405 * The parsing state 406 */ 407 enum mhd_PostMPartState st; 408 409 /** 410 * The field parsing data 411 */ 412 struct mhd_PostParserMPartFieldData f; 413 414 /** 415 * Position of the first character when checking for the delimiter or for 416 * the embedded header 417 */ 418 size_t line_start; 419 420 /** 421 * The first position where the check for the delimiter has been started. 422 * Should be CR char (or bare LR if allowed). 423 * If delimiter is not found, re-interpreted as part of the filed "value". 424 * If delimiter is found, this position can be moved to the second character 425 * if the first position of the delimiter is used to put zero-termination 426 * of previous field "value". 427 */ 428 size_t delim_check_start; 429 430 /** 431 * Multi-part delimited. 432 * Consists of CRLF + "--" + boundary marker. 433 */ 434 struct mhd_BufferConst delim; 435 }; 436 437 438 /** 439 * The states of the "text/plain" parsing 440 */ 441 enum MHD_FIXED_ENUM_ mhd_PostTextState 442 { 443 /** 444 * The line processing has not been started yet 445 */ 446 mhd_POST_TEXT_ST_NOT_STARTED = 0 447 , 448 /** 449 * Processing name of the field 450 */ 451 mhd_POST_TEXT_ST_NAME 452 , 453 /** 454 * At the '=' character after the name. 455 * This is an intermediate state, should be processed and switched to the next 456 * state immediately. 457 * Should not be used outside processing loop. 458 */ 459 mhd_POST_TEXT_ST_AT_EQ 460 , 461 /** 462 * The '=' character after the name has been found. 463 * Looking for the first value character. 464 */ 465 mhd_POST_TEXT_ST_EQ_FOUND 466 , 467 /** 468 * Processing the value of the field. 469 */ 470 mhd_POST_TEXT_ST_VALUE 471 , 472 /** 473 * At the CR character. 474 * This is an intermediate state, should be processed and switched to the next 475 * state immediately. 476 * Should not be used outside processing loop. 477 */ 478 mhd_POST_TEXT_ST_AT_CR 479 , 480 /** 481 * Looking for LF character after CR character. 482 */ 483 mhd_POST_TEXT_ST_CR_FOUND 484 , 485 /** 486 * At the LF character without preceding CR character. 487 * This is an intermediate state, should be processed and switched to the next 488 * state immediately. 489 * Should not be used outside processing loop. 490 */ 491 mhd_POST_TEXT_ST_AT_LF_BARE 492 , 493 /** 494 * End of the line found. 495 * This is an intermediate state, should be processed and switched to the next 496 * state immediately. 497 * Should not be used outside processing loop. 498 */ 499 mhd_POST_TEXT_ST_FULL_LINE_FOUND 500 }; 501 502 /** 503 * The "text/plain" parsing data 504 */ 505 struct mhd_PostParserTextData 506 { 507 /** 508 * The parsing state 509 */ 510 enum mhd_PostTextState st; 511 512 /** 513 * The index of the start of the name. 514 */ 515 size_t name_idx; 516 517 /** 518 * The length of the name of the current field, not including 519 * the terminating zero. 520 * Zero until the length is found. 521 */ 522 size_t name_len; 523 524 /** 525 * The index of the start of the value. 526 * Zero until the value is found. 527 * Cannot be zero if any (including zero-length) value available. 528 */ 529 size_t value_idx; 530 531 /** 532 * The length of the value of the current field, not including 533 * the terminating zero. 534 * Zero until the length is found. 535 */ 536 size_t value_len; 537 }; 538 539 540 /** 541 * The encoding-specific parsing data 542 */ 543 union mhd_PostParserDetailedData 544 { 545 /** 546 * The "application/x-www-form-urlencoded" parsing data 547 */ 548 struct mhd_PostParserUrlEncData u_enc; 549 550 /** 551 * The "multipart/form-data" parsing data 552 */ 553 struct mhd_PostParserMPartFormData m_form; 554 555 /** 556 * The "text/plain" parsing data 557 */ 558 struct mhd_PostParserTextData text; 559 }; 560 561 // TODO: remove? 562 /** 563 * The type of partially processed data in the buffer 564 */ 565 enum MHD_FIXED_ENUM_ mhd_PostParserPartProcType 566 { 567 /** 568 * No data in the buffer 569 */ 570 mhd_POST_PARSER_PART_PROC_TYPE_NONE = 0 571 , 572 /** 573 * The data is partially processed name 574 */ 575 mhd_POST_PARSER_PART_PROC_TYPE_NAME 576 , 577 /** 578 * The data is partially processed value 579 */ 580 mhd_POST_PARSER_PART_PROC_TYPE_VALUE 581 }; 582 583 // TODO: remove? 584 /** 585 * Buffered partially processed data 586 */ 587 struct mhd_PostParserPartProcessedData 588 { 589 /** 590 * Partially processed data, left from previous upload data portion 591 */ 592 struct mhd_Buffer data; 593 594 /** 595 * The type of partially processed data in the @a data buffer 596 */ 597 enum mhd_PostParserPartProcType d_type; 598 }; 599 600 /** 601 * The POST parsing data 602 */ 603 struct mhd_PostParserData 604 { 605 /** 606 * The result of parsing POST data 607 */ 608 enum MHD_PostParseResult parse_result; 609 610 /** 611 * The type of POSE encoding is used. 612 * Active member of @a e_d depends on this type. 613 */ 614 enum MHD_HTTP_PostEncoding enc; 615 616 /** 617 * The encoding-specific parsing data 618 */ 619 union mhd_PostParserDetailedData e_d; 620 621 /** 622 * The size of the data currently in the @a lbuf 623 */ 624 size_t lbuf_used; 625 626 /** 627 * The maximum possible lbuf allocation size 628 */ 629 size_t lbuf_limit; 630 631 /** 632 * True if any POST data was parsed successfully. 633 */ 634 bool some_data_provided; 635 636 /** 637 * The start index of the current field. 638 * If the field is processed by incremental callback, buffer can be freed or 639 * reused up to this position (inclusive). 640 */ 641 size_t field_start; 642 643 /** 644 * 'true' if current filed 'value' must be "streamed". 645 */ 646 bool force_streamed; 647 648 /** 649 * The offset in the current value data. 650 * Used when value is processed incrementally otherwise it is zero. 651 */ 652 size_t value_off; 653 654 /** 655 * The position of the next character to be parsed 656 */ 657 size_t next_parse_pos; 658 }; 659 660 #endif /* ! MHD_POST_PARSER_H */