⚝
One Hat Cyber Team
⚝
Your IP:
216.73.216.19
Server IP:
178.33.27.10
Server:
Linux cpanel.dev-unit.com 3.10.0-1160.108.1.el7.x86_64 #1 SMP Thu Jan 25 16:17:31 UTC 2024 x86_64
Server Software:
Apache/2.4.57 (Unix) OpenSSL/1.0.2k-fips
PHP Version:
8.2.11
Buat File
|
Buat Folder
Eksekusi
Dir :
~
/
proc
/
self
/
root
/
usr
/
local
/
src
/
mailparse-3.1.8
/
View File Name :
php_mailparse_mime.c
/* +----------------------------------------------------------------------+ | Copyright (c) The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | http://www.php.net/license/3_01.txt. | | If you did not receive a copy of the PHP license and are unable to | | obtain it through the world-wide-web, please send a note to | | license@php.net so we can mail you a copy immediately. | +----------------------------------------------------------------------+ | Author: Wez Furlong <wez@thebrainroom.com> | +----------------------------------------------------------------------+ */ #include "php.h" #include "php_mailparse.h" #include "php_mailparse_mime.h" #include "php_mailparse_rfc822.h" #define MAXLEVELS 20 #define MAXPARTS 300 #define IS_MIME_1(part) (((part)->mime_version && strcmp("1.0", (part)->mime_version) == 0) || ((part)->parent)) #define CONTENT_TYPE_IS(part, contenttypevalue) ((part)->content_type && strcasecmp((part)->content_type->value, contenttypevalue) == 0) #define CONTENT_TYPE_ISL(part, contenttypevalue, len) ((part)->content_type && strncasecmp((part)->content_type->value, contenttypevalue, len) == 0) #define STR_FREE(ptr) if (ptr) { efree(ptr); } #define mailparse_fetch_mimepart_resource(rfcvar, zvalarg) rfcvar = (php_mimepart *)zend_fetch_resource(Z_RES_P(zvalarg), php_mailparse_msg_name(), php_mailparse_le_mime_part()) static void php_mimeheader_free(struct php_mimeheader_with_attributes *attr) { STR_FREE(attr->value); zval_ptr_dtor(&attr->attributes); efree(attr); } static struct php_mimeheader_with_attributes * php_mimeheader_alloc(char *value) { struct php_mimeheader_with_attributes *attr; attr = ecalloc(1, sizeof(struct php_mimeheader_with_attributes)); array_init(&attr->attributes); attr->value = estrdup(value); return attr; } void rfc2231_to_mime(smart_string* value_buf, char* value, int charset_p, int prevcharset_p) { char *strp, *startofvalue = NULL; int quotes = 0; /* Process string, get positions and replace */ /* Set to start of buffer*/ if (charset_p) { /* Previous charset already set so only convert %nn to =nn*/ if (prevcharset_p) { quotes=2; } strp = value; while (*strp) { /* Quote handling*/ if (*strp == '\'') { if (quotes <= 1) { /* End of charset*/ if (quotes == 0) { *strp=0; } else { startofvalue = strp+1; } quotes++; } } else { /* Replace % with = - quoted printable*/ if (*strp == '%' && quotes==2) { *strp = '='; } } strp++; } } /* If first encoded token*/ if (charset_p && !prevcharset_p && startofvalue) { smart_string_appends(value_buf, "=?"); smart_string_appends(value_buf, value); smart_string_appends(value_buf, "?Q?"); smart_string_appends(value_buf, startofvalue); } /* If last encoded token*/ if (prevcharset_p && !charset_p) { smart_string_appends(value_buf, "?="); } /* Append value*/ if ((!charset_p || (prevcharset_p && charset_p)) && value) { smart_string_appends(value_buf, value); } } static struct php_mimeheader_with_attributes *php_mimeheader_alloc_from_tok(php_rfc822_tokenized_t *toks) { struct php_mimeheader_with_attributes *attr; int i, first_semi, next_semi, comments_before_semi, netscape_bug = 0; char *name_buf = NULL; smart_string value_buf = {0}; int is_rfc2231_name = 0; char *check_name; int charset_p, prevcharset_p = 0; int namechanged, currentencoded = 0; attr = ecalloc(1, sizeof(struct php_mimeheader_with_attributes)); array_init(&attr->attributes); /* php_rfc822_print_tokens(toks); */ /* look for optional ; which separates optional attributes from the main value */ for (first_semi = 2; first_semi < toks->ntokens; first_semi++) if (toks->tokens[first_semi].token == ';') { break; } attr->value = php_rfc822_recombine_tokens(toks, 2, first_semi - 2, PHP_RFC822_RECOMBINE_STRTOLOWER | PHP_RFC822_RECOMBINE_IGNORE_COMMENTS); if (first_semi < toks->ntokens) { first_semi++; } /* Netscape Bug: Messenger sometimes omits the semi when wrapping the * the header. * That means we have to be even more clever than the spec says that * we need to :-/ * */ while (first_semi < toks->ntokens) { /* find the next ; */ comments_before_semi = 0; for (next_semi = first_semi; next_semi < toks->ntokens; next_semi++) { if (toks->tokens[next_semi].token == ';') { break; } if (toks->tokens[next_semi].token == '(') { comments_before_semi++; } } i = first_semi; if (i < next_semi) { i++; /* ignore comments */ while (i < next_semi && toks->tokens[i].token == '(') i++; if (i < next_semi && toks->tokens[i].token == '=') { char *name, *value; /* Here, next_semi --> "name" and i --> "=", so skip "=" sign */ i++; /* count those tokens; we expect "token = token" (3 tokens); if there are * more than that, then something is quite possibly wrong - Netscape Bug! */ if (next_semi < toks->ntokens && toks->tokens[next_semi].token != ';' && next_semi - first_semi - comments_before_semi > 3) { next_semi = i + 1; netscape_bug = 1; } name = php_rfc822_recombine_tokens(toks, first_semi, 1, PHP_RFC822_RECOMBINE_STRTOLOWER|PHP_RFC822_RECOMBINE_IGNORE_COMMENTS); value = php_rfc822_recombine_tokens(toks, i, next_semi - i, PHP_RFC822_RECOMBINE_IGNORE_COMMENTS); /* support rfc2231 mime parameter value * * Parameter Value Continuations: * * Content-Type: message/external-body; access-type=URL; * URL*0="ftp://"; * URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar" * * is semantically identical to * * Content-Type: message/external-body; access-type=URL; * URL="ftp://cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar" * * Original rfc2231 support by IceWarp Ltd. <info@icewarp.com> */ check_name = strchr(name, '*'); if (check_name) { currentencoded = 1; /* Is last char * - charset encoding */ charset_p = *(name+strlen(name)-1) == '*'; /* Leave only attribute name without * */ *check_name = 0; /* New item or continuous */ if (NULL == name_buf) { namechanged = 0; name_buf = name; } else { namechanged = (strcmp(name_buf, name) != 0); if (!namechanged) { efree(name); name = 0; } } /* Check if name changed*/ if (!namechanged) { /* Append string to buffer - check if to be encoded... */ rfc2231_to_mime(&value_buf, value, charset_p, prevcharset_p); /* Mark previous */ prevcharset_p = charset_p; } is_rfc2231_name = 1; } /* Last item was encoded */ if (1 == is_rfc2231_name) { /* Name not null and name differs with new name*/ if (name && strcmp(name_buf, name) != 0) { /* Finalize packet */ rfc2231_to_mime(&value_buf, NULL, 0, prevcharset_p); add_assoc_stringl(&attr->attributes, name_buf, value_buf.c, value_buf.len); efree(name_buf); smart_string_free(&value_buf); prevcharset_p = 0; is_rfc2231_name = 0; name_buf = NULL; /* New non encoded name*/ if (!currentencoded) { /* Add string*/ add_assoc_string(&attr->attributes, name, value); efree(name); } else { /* Encoded name changed*/ if (namechanged) { /* Append string to buffer - check if to be encoded... */ rfc2231_to_mime(&value_buf, value, charset_p, prevcharset_p); /* Mark */ is_rfc2231_name = 1; name_buf = name; prevcharset_p = charset_p; } } namechanged = 0; } } else { add_assoc_string(&attr->attributes, name, value); efree(name); } efree(value); } } if (next_semi < toks->ntokens && !netscape_bug) { next_semi++; } first_semi = next_semi; netscape_bug = 0; } if (1 == is_rfc2231_name) { /* Finalize packet */ rfc2231_to_mime(&value_buf, NULL, 0, prevcharset_p); add_assoc_stringl(&attr->attributes, name_buf, value_buf.c, value_buf.len); efree(name_buf); smart_string_free(&value_buf); } return attr; } PHP_MAILPARSE_API php_mimepart *php_mimepart_alloc() { php_mimepart *part = ecalloc(1, sizeof(php_mimepart)); part->part_index = 1; zend_hash_init(&part->children, 0, NULL, NULL, 0); array_init(&part->headerhash); ZVAL_NULL(&part->source.zval); /* begin in header parsing mode */ part->parsedata.in_header = 1; part->rsrc = zend_register_resource(part, php_mailparse_le_mime_part()); return part; } PHP_MAILPARSE_API void php_mimepart_free(php_mimepart *part) { /* free contained parts */ zend_hash_destroy(&part->children); STR_FREE(part->mime_version); STR_FREE(part->content_transfer_encoding); STR_FREE(part->charset); STR_FREE(part->boundary); STR_FREE(part->content_base); STR_FREE(part->content_location); if (part->content_type) { php_mimeheader_free(part->content_type); part->content_type = NULL; } if (part->content_disposition) { php_mimeheader_free(part->content_disposition); part->content_disposition = NULL; } smart_string_free(&part->parsedata.workbuf); smart_string_free(&part->parsedata.headerbuf); zval_ptr_dtor(&part->source.zval); zval_ptr_dtor(&part->headerhash); efree(part); } static void php_mimepart_update_positions(php_mimepart *part, size_t newendpos, size_t newbodyend, size_t deltanlines) { while(part) { part->endpos = newendpos; part->bodyend = newbodyend; part->nlines += deltanlines; if (!part->parsedata.in_header) { part->nbodylines += deltanlines; } part = part->parent; } } PHP_MAILPARSE_API char *php_mimepart_attribute_get(struct php_mimeheader_with_attributes *attr, char *attrname) { zval *attrval; zend_string *hash_key; hash_key = zend_string_init(attrname, strlen(attrname), 0); attrval = zend_hash_find(Z_ARRVAL_P(&attr->attributes), hash_key); zend_string_release(hash_key); if (attrval != NULL) { return Z_STRVAL_P(attrval); } return NULL; } #define STR_SET_REPLACE(ptr, newval) do { STR_FREE(ptr); ptr = estrdup(newval); } while(0) static int php_mimepart_process_header(php_mimepart *part) { php_rfc822_tokenized_t *toks; char *header_key, *header_val, *header_val_stripped; zval *zheaderval; zend_string *header_zstring; if (part->parsedata.headerbuf.len == 0) { return SUCCESS; } smart_string_0(&part->parsedata.headerbuf); /* parse the header line */ toks = php_mailparse_rfc822_tokenize((const char*)part->parsedata.headerbuf.c, 0); /* valid headers consist of at least three tokens, with the first being a string and the * second token being a ':' */ if (toks->ntokens < 2 || toks->tokens[0].token != 0 || toks->tokens[1].token != ':') { part->parsedata.headerbuf.len = 0; php_rfc822_tokenize_free(toks); return FAILURE; } /* get a lower-case version of the first token */ header_key = php_rfc822_recombine_tokens(toks, 0, 1, PHP_RFC822_RECOMBINE_IGNORE_COMMENTS|PHP_RFC822_RECOMBINE_STRTOLOWER); header_val = strchr(part->parsedata.headerbuf.c, ':'); header_val_stripped = php_rfc822_recombine_tokens(toks, 2, toks->ntokens-2, PHP_RFC822_RECOMBINE_IGNORE_COMMENTS|PHP_RFC822_RECOMBINE_STRTOLOWER); if (header_val) { header_val++; while (isspace(*header_val)) header_val++; /* add the header to the hash. * join multiple To: or Cc: lines together */ header_zstring = zend_string_init(header_key, strlen(header_key), 0); if ((strcmp(header_key, "to") == 0 || strcmp(header_key, "cc") == 0) && (zheaderval = zend_hash_find(Z_ARRVAL_P(&part->headerhash), header_zstring)) != NULL) { int newlen; char *newstr; newlen = strlen(header_val) + Z_STRLEN_P(zheaderval) + 3; newstr = emalloc(newlen); strcpy(newstr, Z_STRVAL_P(zheaderval)); strcat(newstr, ", "); strcat(newstr, header_val); add_assoc_string(&part->headerhash, header_key, newstr); efree(newstr); } else { if((zheaderval = zend_hash_find(Z_ARRVAL_P(&part->headerhash), header_zstring)) != NULL) { if(Z_TYPE_P(zheaderval) == IS_ARRAY) { add_next_index_string(zheaderval, header_val); } else { /* Create a nested array if there is more than one of the same header */ zval zarr; array_init(&zarr); Z_ADDREF_P(zheaderval); add_next_index_zval(&zarr, zheaderval); add_next_index_string(&zarr, header_val); add_assoc_zval(&part->headerhash, header_key, &zarr); } } else { add_assoc_string(&part->headerhash, header_key, header_val); } } zend_string_release(header_zstring); /* if it is useful, keep a pointer to it in the mime part */ if (strcmp(header_key, "mime-version") == 0) { STR_SET_REPLACE(part->mime_version, header_val_stripped); } if (strcmp(header_key, "content-location") == 0) { STR_FREE(part->content_location); part->content_location = php_rfc822_recombine_tokens(toks, 2, toks->ntokens-2, PHP_RFC822_RECOMBINE_IGNORE_COMMENTS); } if (strcmp(header_key, "content-base") == 0) { STR_FREE(part->content_base); part->content_base = php_rfc822_recombine_tokens(toks, 2, toks->ntokens-2, PHP_RFC822_RECOMBINE_IGNORE_COMMENTS); } if (strcmp(header_key, "content-transfer-encoding") == 0) { STR_SET_REPLACE(part->content_transfer_encoding, header_val_stripped); } if (strcmp(header_key, "content-type") == 0) { char *charset, *boundary; if (part->content_type) { php_mimeheader_free(part->content_type); part->content_type = NULL; } part->content_type = php_mimeheader_alloc_from_tok(toks); boundary = php_mimepart_attribute_get(part->content_type, "boundary"); if (boundary) { part->boundary = estrdup(boundary); } charset = php_mimepart_attribute_get(part->content_type, "charset"); if (charset) { STR_SET_REPLACE(part->charset, charset); } } if (strcmp(header_key, "content-disposition") == 0) { if (part->content_disposition) { php_mimeheader_free(part->content_disposition); part->content_disposition = NULL; } part->content_disposition = php_mimeheader_alloc_from_tok(toks); } } STR_FREE(header_key); STR_FREE(header_val_stripped); php_rfc822_tokenize_free(toks); /* zero the buffer size */ part->parsedata.headerbuf.len = 0; return SUCCESS; } static php_mimepart *alloc_new_child_part(php_mimepart *parentpart, size_t startpos, int inherit) { php_mimepart *child = php_mimepart_alloc(); zval child_z; parentpart->parsedata.lastpart = child; child->parent = parentpart; child->source.kind = parentpart->source.kind; if (parentpart->source.kind != mpNONE) { child->source.zval = parentpart->source.zval; zval_copy_ctor(&child->source.zval); } ZVAL_RES(&child_z, child->rsrc); zend_hash_next_index_insert(&parentpart->children, &child_z); child->startpos = child->endpos = child->bodystart = child->bodyend = startpos; if (inherit) { if (parentpart->content_transfer_encoding) { child->content_transfer_encoding = estrdup(parentpart->content_transfer_encoding); } if (parentpart->charset) { child->charset = estrdup(parentpart->charset); } } return child; } PHP_MAILPARSE_API void php_mimepart_get_offsets(php_mimepart *part, off_t *start, off_t *end, off_t *start_body, int *nlines, int *nbodylines) { *start = part->startpos; *end = part->endpos; *nlines = part->nlines; *nbodylines = part->nbodylines; *start_body = part->bodystart; /* Adjust for newlines in mime parts */ if (part->parent) { *end = part->bodyend; if (*nlines) { --*nlines; } if (*nbodylines) { --*nbodylines; } } } static int php_mimepart_process_line(php_mimepart *workpart) { size_t origcount, linelen; char *c; /* sanity check */ if (zend_hash_num_elements(&workpart->children) > MAXPARTS) { php_error_docref(NULL, E_WARNING, "MIME message too complex"); return FAILURE; } c = workpart->parsedata.workbuf.c; smart_string_0(&workpart->parsedata.workbuf); /* strip trailing \r\n -- we always have a trailing \n */ origcount = workpart->parsedata.workbuf.len; linelen = origcount - 1; if (linelen && c[linelen-1] == '\r') { --linelen; } /* Discover which part we were last working on */ while (workpart->parsedata.lastpart) { size_t bound_len; php_mimepart *lastpart = workpart->parsedata.lastpart; if (lastpart->parsedata.completed) { php_mimepart_update_positions(workpart, workpart->endpos + origcount, workpart->endpos + origcount, 1); return SUCCESS; } if (workpart->boundary == NULL || workpart->parsedata.in_header) { workpart = lastpart; continue; } bound_len = strlen(workpart->boundary); /* Look for a boundary */ if (c[0] == '-' && c[1] == '-' && linelen >= 2+bound_len && strncasecmp(workpart->boundary, c+2, bound_len) == 0) { php_mimepart *newpart; /* is it the final boundary ? */ if (linelen >= 4 + bound_len && strncmp(c+2+bound_len, "--", 2) == 0) { lastpart->parsedata.completed = 1; php_mimepart_update_positions(workpart, workpart->endpos + origcount, workpart->endpos + origcount, 1); return SUCCESS; } newpart = alloc_new_child_part(workpart, workpart->endpos + origcount, 1); php_mimepart_update_positions(workpart, workpart->endpos + origcount, workpart->endpos + linelen, 1); if (workpart->mime_version) { newpart->mime_version = estrdup(workpart->mime_version); } newpart->parsedata.in_header = 1; return SUCCESS; } workpart = lastpart; } if (!workpart->parsedata.in_header) { if (!workpart->parsedata.completed && !workpart->parsedata.lastpart) { /* update the body/part end positions. * For multipart messages, the final newline belongs to the boundary. * Otherwise it belongs to the body * */ if (workpart->parent && CONTENT_TYPE_ISL(workpart->parent, "multipart/", 10)) { php_mimepart_update_positions(workpart, workpart->endpos + origcount, workpart->endpos + linelen, 1); } else { php_mimepart_update_positions(workpart, workpart->endpos + origcount, workpart->endpos + origcount, 1); } } } else { if (linelen > 0) { php_mimepart_update_positions(workpart, workpart->endpos + origcount, workpart->endpos + linelen, 1); if (*c == ' ' || *c == '\t') { /* This doesn't technically confirm to rfc2822, as we're replacing \t with \s, but this seems to fix * cases where clients incorrectly fold by inserting a \t character. */ smart_string_appendl(&workpart->parsedata.headerbuf, " ", 1); c++; linelen--; } else { php_mimepart_process_header(workpart); } /* save header for possible continuation */ smart_string_appendl(&workpart->parsedata.headerbuf, c, linelen); } else { /* end of headers */ php_mimepart_process_header(workpart); /* start of body */ workpart->parsedata.in_header = 0; workpart->bodystart = workpart->endpos + origcount; php_mimepart_update_positions(workpart, workpart->bodystart, workpart->bodystart, 1); --workpart->nbodylines; /* some broken mailers include the content-type header but not a mime-version header. * some others may use a MIME version other than 1.0. * Let's relax and pretend they said they were mime 1.0 compatible */ if (!IS_MIME_1(workpart) && workpart->content_type != NULL) { if (workpart->mime_version != NULL) { efree(workpart->mime_version); } workpart->mime_version = estrdup("1.0"); } if (!IS_MIME_1(workpart)) { /* if we don't understand the MIME version, discard the content-type and * boundary */ if (workpart->content_disposition) { php_mimeheader_free(workpart->content_disposition); workpart->content_disposition = NULL; } if (workpart->boundary) { efree(workpart->boundary); workpart->boundary = NULL; } if (workpart->content_type) { php_mimeheader_free(workpart->content_type); workpart->content_type = NULL; } workpart->content_type = php_mimeheader_alloc("text/plain"); } /* if there is no content type, default to text/plain, but use multipart/digest when in * a multipart/rfc822 message */ if (IS_MIME_1(workpart) && workpart->content_type == NULL) { char *def_type = "text/plain"; if (workpart->parent && CONTENT_TYPE_IS(workpart->parent, "multipart/digest")) { def_type = "message/rfc822"; } workpart->content_type = php_mimeheader_alloc(def_type); } /* if no charset had previously been set, either through inheritance or by an * explicit content-type header, default to us-ascii */ if (workpart->charset == NULL) { workpart->charset = estrdup(MAILPARSEG(def_charset)); } if (CONTENT_TYPE_IS(workpart, "message/rfc822")) { workpart = alloc_new_child_part(workpart, workpart->bodystart, 0); workpart->parsedata.in_header = 1; return SUCCESS; } /* create a section for the preamble that precedes the first boundary */ if (workpart->boundary) { workpart = alloc_new_child_part(workpart, workpart->bodystart, 1); workpart->parsedata.in_header = 0; workpart->parsedata.is_dummy = 1; return SUCCESS; } return SUCCESS; } } return SUCCESS; } PHP_MAILPARSE_API int php_mimepart_parse(php_mimepart *part, const char *buf, size_t bufsize) { size_t len; while(bufsize > 0) { /* look for EOL */ for (len = 0; len < bufsize; len++) if (buf[len] == '\n') { break; } if (len < bufsize && buf[len] == '\n') { ++len; smart_string_appendl(&part->parsedata.workbuf, buf, len); if (php_mimepart_process_line(part) == FAILURE) { /* php_mimepart_process_line() only returns FAILURE in case the count of children * have exceeded MAXPARTS and doing so at the very begining, without doing any work. * It'd do this for all of the following lines, since the exceeded state won't change. * As no additional work have been done since the last php_mimepart_process_line() call, * it is safe to break the loop now not caring about the rest of the code. * * Known issues: * - some callers aren't obeying the returned value, but that's in the mailmessage * object which is not documented and seemingly otdated/unfinished anyway */ return FAILURE; }; part->parsedata.workbuf.len = 0; } else { smart_string_appendl(&part->parsedata.workbuf, buf, len); } buf += len; bufsize -= len; } return SUCCESS; } static int enum_parts_recurse(php_mimepart_enumerator *top, php_mimepart_enumerator **child, php_mimepart *part, mimepart_enumerator_func callback, void *ptr) { php_mimepart_enumerator next; php_mimepart *childpart; zval *childpart_z; HashPosition pos; *child = NULL; if (FAILURE == (*callback)(part, top, ptr)) { return FAILURE; } *child = &next; next.id = 1; if (CONTENT_TYPE_ISL(part, "multipart/", 10)) { next.id = 0; } zend_hash_internal_pointer_reset_ex(&part->children, &pos); while ((childpart_z = zend_hash_get_current_data_ex(&part->children, &pos)) != NULL) { mailparse_fetch_mimepart_resource(childpart, childpart_z); if (next.id) { if (FAILURE == enum_parts_recurse(top, &next.next, childpart, callback, ptr)) { return FAILURE; } } next.id++; zend_hash_move_forward_ex(&part->children, &pos); } return SUCCESS; } PHP_MAILPARSE_API void php_mimepart_enum_parts(php_mimepart *part, mimepart_enumerator_func callback, void *ptr) { php_mimepart_enumerator top; top.id = 1; enum_parts_recurse(&top, &top.next, part, callback, ptr); } PHP_MAILPARSE_API void php_mimepart_enum_child_parts(php_mimepart *part, mimepart_child_enumerator_func callback, void *ptr) { HashPosition pos; php_mimepart *childpart; zval *childpart_z; int index = 0; zend_hash_internal_pointer_reset_ex(&part->children, &pos); while ((childpart_z = zend_hash_get_current_data_ex(&part->children, &pos)) != NULL) { mailparse_fetch_mimepart_resource(childpart, childpart_z); if (FAILURE == (*callback)(part, childpart, index, ptr)) { return; } zend_hash_move_forward_ex(&part->children, &pos); index++; } } struct find_part_struct { const char *searchfor; php_mimepart *foundpart; }; static int find_part_callback(php_mimepart *part, php_mimepart_enumerator *id, void *ptr) { struct find_part_struct *find = ptr; const unsigned char *num = (const unsigned char*)find->searchfor; unsigned int n; while (id) { if (!isdigit((int)*num)) { return SUCCESS; } /* convert from decimal to int */ n = 0; while (isdigit((int)*num)) { n = (n * 10) + (*num++ - '0'); } if (*num) { if (*num != '.') { return SUCCESS; } num++; } if (n != (unsigned int)id->id) { return SUCCESS; } id = id->next; } if (*num == 0) { find->foundpart = part; } return SUCCESS; } PHP_MAILPARSE_API php_mimepart *php_mimepart_find_by_name(php_mimepart *parent, const char *name) { struct find_part_struct find; find.searchfor = name; find.foundpart = NULL; php_mimepart_enum_parts(parent, find_part_callback, &find); return find.foundpart; } PHP_MAILPARSE_API php_mimepart *php_mimepart_find_child_by_position(php_mimepart *parent, int position) { HashPosition pos; php_mimepart *childpart = NULL; zval *childpart_z; zend_hash_internal_pointer_reset_ex(&parent->children, &pos); while(position-- > 0) if (FAILURE == zend_hash_move_forward_ex(&parent->children, &pos)) { return NULL; } if ((childpart_z = zend_hash_get_current_data_ex(&parent->children, &pos)) != NULL) { mailparse_fetch_mimepart_resource(childpart, childpart_z); if(childpart) { return childpart; } } return NULL; } static int filter_into_work_buffer(int c, void *dat) { php_mimepart *part = dat; smart_string_appendc(&part->parsedata.workbuf, c); if (part->parsedata.workbuf.len >= 4096) { part->extract_func(part, part->extract_context, part->parsedata.workbuf.c, part->parsedata.workbuf.len); part->parsedata.workbuf.len = 0; } return c; } PHP_MAILPARSE_API void php_mimepart_decoder_prepare(php_mimepart *part, int do_decode, php_mimepart_extract_func_t decoder, void *ptr) { const mbfl_encoding *encoding; enum mbfl_no_encoding from = mbfl_no_encoding_8bit; if (do_decode && part->content_transfer_encoding) { encoding = mbfl_name2encoding(part->content_transfer_encoding); if (encoding) { from = encoding->no_encoding; } else { if (strcasecmp("binary", part->content_transfer_encoding) != 0) { zend_error(E_WARNING, "%s(): mbstring doesn't know how to decode %s transfer encoding!", get_active_function_name(), part->content_transfer_encoding); } from = mbfl_no_encoding_8bit; } } part->extract_func = decoder; part->extract_context = ptr; part->parsedata.workbuf.len = 0; if (do_decode) { if (from == mbfl_no_encoding_8bit || from == mbfl_no_encoding_7bit) { part->extract_filter = NULL; } else { part->extract_filter = mbfl_convert_filter_new( mbfl_no2encoding(from), mbfl_no2encoding(mbfl_no_encoding_8bit), filter_into_work_buffer, NULL, part ); } } } PHP_MAILPARSE_API void php_mimepart_decoder_finish(php_mimepart *part) { if (part->extract_filter) { mbfl_convert_filter_flush(part->extract_filter); mbfl_convert_filter_delete(part->extract_filter); } if (part->extract_func && part->parsedata.workbuf.len > 0) { part->extract_func(part, part->extract_context, part->parsedata.workbuf.c, part->parsedata.workbuf.len); part->parsedata.workbuf.len = 0; } } PHP_MAILPARSE_API int php_mimepart_decoder_feed(php_mimepart *part, const char *buf, size_t bufsize) { if (buf && bufsize) { size_t i; if (part->extract_filter) { for (i = 0; i < bufsize; i++) { if (mbfl_convert_filter_feed(buf[i], part->extract_filter) < 0) { zend_error(E_WARNING, "%s() - filter conversion failed. Input message is probably incorrectly encoded\n", get_active_function_name()); return -1; } } } else { return part->extract_func(part, part->extract_context, buf, bufsize); } } return 0; } PHP_MAILPARSE_API void php_mimepart_remove_from_parent(php_mimepart *part) { php_mimepart *parent = part->parent; HashPosition pos; php_mimepart *childpart; zval *childpart_z; if (parent == NULL) { return; } part->parent = NULL; zend_hash_internal_pointer_reset_ex(&parent->children, &pos); while((childpart_z = zend_hash_get_current_data_ex(&parent->children, &pos)) != NULL) { if ((childpart_z = zend_hash_get_current_data_ex(&parent->children, &pos)) != NULL) { mailparse_fetch_mimepart_resource(childpart, childpart_z); if (childpart == part) { zend_ulong h; zend_hash_get_current_key_ex(&parent->children, NULL, &h, &pos); zend_hash_index_del(&parent->children, h); break; } } zend_hash_move_forward_ex(&parent->children, &pos); } } PHP_MAILPARSE_API void php_mimepart_add_child(php_mimepart *part, php_mimepart *child) { }