/** * @brief Get a specified chunk (mime part) of a multipart mime message. * @param message a managed string containing the mime message to be parsed. * @param boundary a managed string containing the boundary used to split the multipart mime message. * @param chunk the one-index based chunk to be retrieved from the multipart message * @return NULL on failure or a placer containing the specified chunk on success. */ stringer_t * mail_get_chunk(stringer_t *message, stringer_t *boundary, int_t chunk) { int_t found = 0; stringer_t *result; size_t start = 0, length = 0, input = 0; while (chunk != 0) { // So on repeats we don't have to start all over again. if (length != 0) { start += length - 1; } found = 0; while (found == 0) { // Get the start of the MIME message part. if (!st_search_cs(PLACER(st_char_get(message) + start, st_length_get(message) - start), boundary, &input)) { log_pedantic("The boundary doesn't appear to be part of this message."); return NULL; } // Skip the boundary before searching again. start += input + st_length_get(boundary); // This will detect the section ending. if (st_length_get(message) - start >= 2 && mm_cmp_cs_eq(st_char_get(message) + start, "--", 2) == 1) { return NULL; } // Some broken implementations use similar boundaries. This should detect those. else if (st_length_get(message) - start > 0 && (*(st_char_get(message) + start) < '!' || *(st_char_get(message) + start) > '~')) { found = 1; } } found = 0; while (found == 0) { // Get the end. if (!st_search_cs(PLACER(st_char_get(message) + start, st_length_get(message) - start), boundary, &length)) { length = st_length_get(message) - start; found = 1; } else if (st_length_get(message) - start - length > 0 && (*(st_char_get(message) + start) < '!' || *(st_char_get(message) + start) > '~')) { found = 1; } } chunk--; } // Setup a placer with the chunk. result = PLACER(st_char_get(message) + start, length); return result; }
/** * @brief Retrieve a specified string-split token from a null-terminated string. * @param block a pointer to the block of memory to be tokenized. * @param length the maximum number of characters to be scanned from the input data. * @param token the token string that will be used to split the data. * @param toklen the length, in bytes, of the token string. * @param fragment the zero-indexed token number to be extracted from the data. * @param value a pointer to a placer that will receive the value of the extracted token on success, or pl_null() on failure. * @return -1 on failure, 0 on success, or 1 if the token was extracted successfully, but was the last one in the string. */ int str_tok_get_bl(char *block, size_t length, chr_t *token, size_t toklen, uint64_t fragment, placer_t *value) { placer_t haystack, needle; size_t hptr, skipped = 0; bool_t found; // We can't search NULL pointers or empty strings. if (!value || mm_empty(block, length) || mm_empty(token, toklen)) { *value = pl_null(); return -1; } haystack = pl_init(block, length); needle = pl_init(token, toklen); while (fragment) { if (!(found = st_search_cs(&haystack, &needle, &hptr))) { *value = pl_null(); return -1; } // Haystack becomes the entire block after the token. skipped += pl_length_get (needle) + hptr; haystack = pl_init(pl_char_get(haystack) + skipped, length-skipped); fragment--; } // If no more tokens are present, return everything we have left if (!st_search_cs(&haystack, &needle, &hptr)) { *value = haystack; return 1; } *value = pl_init(pl_char_get(haystack), hptr); return 0; }
/** * @brief Count the number of times a string token is found in a specified block of memory. * @param block a pointer to a block of memory to be scanned. * @param length the length, in bytes, of the block of memory to be scanned. * @param token a pointer to the string token being used to split the input data. * @param toklen the length, in bytes, of the specified token. * @return the number of times the string token was found in the block of memory, or 0 on failure. */ uint64_t str_tok_get_count_bl(void *block, size_t length, chr_t *token, size_t toklen) { uint64_t count = 0; placer_t haystack, needle; size_t hptr, skipped = 0; // We can't search NULL pointers or empty strings. if (mm_empty(block, length) || mm_empty(token, toklen)) { return 0; } haystack = pl_init(block, length); needle = pl_init(token, toklen); while ((skipped < length) && st_search_cs(&haystack, &needle, &hptr)) { skipped += pl_length_get (needle) + hptr; haystack = pl_init((char *) block + skipped, length-skipped); count++; } return count; }