diff --git a/NEWS b/NEWS index 1c7b4b8f5e8ed..98d9c37492162 100644 --- a/NEWS +++ b/NEWS @@ -57,6 +57,8 @@ PHP NEWS (Girgias) . Fixed bug GH-19577 (Avoid integer overflow when using a small offset and PHP_INT_MAX with LimitIterator). (alexandre-daubois) + . Implement GH-19188: Add support for new INI mail.cr_lf_mode. + (alexandre-daubois) - Streams: . Fixed bug GH-14506 (Closing a userspace stream inside a userspace handler diff --git a/ext/standard/mail.c b/ext/standard/mail.c index 4263656a515e4..fb9db686124e8 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -494,7 +494,27 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c MAIL_RET(false); } - char *line_sep = PG(mail_mixed_lf_and_crlf) ? "\n" : "\r\n"; + char *line_sep; + const char *cr_lf_mode = PG(mail_cr_lf_mode); + + if (cr_lf_mode && strcmp(cr_lf_mode, "crlf") != 0) { + if (strcmp(cr_lf_mode, "lf") == 0) { + line_sep = "\n"; + } else if (strcmp(cr_lf_mode, "mixed") == 0) { + line_sep = "\n"; + } else if (strcmp(cr_lf_mode, "os") == 0) { +#ifdef PHP_WIN32 + line_sep = "\r\n"; +#else + line_sep = "\n"; +#endif + } else { + ZEND_ASSERT(0 && "Unexpected cr_lf_mode value"); + } + } else { + /* CRLF is default mode, but respect mail.mixed_lf_and_crlf for backward compatibility */ + line_sep = PG(mail_mixed_lf_and_crlf) ? "\n" : "\r\n"; + } if (PG(mail_x_header)) { const char *tmp = zend_get_executed_filename(); @@ -586,7 +606,43 @@ PHPAPI bool php_mail(const char *to, const char *subject, const char *message, c if (hdr != NULL) { fprintf(sendmail, "%s%s", hdr, line_sep); } - fprintf(sendmail, "%s%s%s", line_sep, message, line_sep); + + fprintf(sendmail, "%s", line_sep); + + if (cr_lf_mode && strcmp(cr_lf_mode, "lf") == 0) { + char *converted_message = NULL; + size_t msg_len = strlen(message); + size_t new_len = 0; + + for (size_t i = 0; i < msg_len - 1; ++i) { + if (message[i] == '\r' && message[i + 1] == '\n') { + ++new_len; + } + } + + if (new_len == 0) { + fprintf(sendmail, "%s", message); + } else { + converted_message = emalloc(msg_len - new_len + 1); + size_t j = 0; + for (size_t i = 0; i < msg_len; ++i) { + if (i < msg_len - 1 && message[i] == '\r' && message[i + 1] == '\n') { + converted_message[j++] = '\n'; + ++i; /* skip LF part */ + } else { + converted_message[j++] = message[i]; + } + } + + converted_message[j] = '\0'; + fprintf(sendmail, "%s", converted_message); + efree(converted_message); + } + } else { + fprintf(sendmail, "%s", message); + } + + fprintf(sendmail, "%s", line_sep); #ifdef PHP_WIN32 ret = pclose(sendmail); diff --git a/ext/standard/tests/mail/gh19188_cr_lf_mode.phpt b/ext/standard/tests/mail/gh19188_cr_lf_mode.phpt new file mode 100644 index 0000000000000..15c9aa2aa28ff --- /dev/null +++ b/ext/standard/tests/mail/gh19188_cr_lf_mode.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-19188: new INI mail.cr_lf_mode +--INI-- +sendmail_path={MAIL:gh19188_cr_lf_mode.out} +mail.cr_lf_mode=crlf +--FILE-- + +--CLEAN-- + +--EXPECT-- +bool(true) +CRLF mode: +int(5) +int(0) diff --git a/ext/standard/tests/mail/gh19188_invalid_mode.phpt b/ext/standard/tests/mail/gh19188_invalid_mode.phpt new file mode 100644 index 0000000000000..fb1baa3d4702d --- /dev/null +++ b/ext/standard/tests/mail/gh19188_invalid_mode.phpt @@ -0,0 +1,26 @@ +--TEST-- +GH-19188: mail.cr_lf_mode runtime changes should fail +--FILE-- + +--EXPECT-- +bool(false) +string(4) "crlf" +bool(false) +string(4) "crlf" +bool(false) +string(4) "crlf" +bool(false) +string(4) "crlf" diff --git a/ext/standard/tests/mail/gh19188_lf_mode.phpt b/ext/standard/tests/mail/gh19188_lf_mode.phpt new file mode 100644 index 0000000000000..bd69cc42b62df --- /dev/null +++ b/ext/standard/tests/mail/gh19188_lf_mode.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-19188: mail.cr_lf_mode=lf +--INI-- +sendmail_path={MAIL:gh19188_lf_mode.out} +mail.cr_lf_mode=lf +--FILE-- + +--CLEAN-- + +--EXPECT-- +bool(true) +LF mode: +int(0) +int(6) diff --git a/ext/standard/tests/mail/gh19188_mixed_mode.phpt b/ext/standard/tests/mail/gh19188_mixed_mode.phpt new file mode 100644 index 0000000000000..fa5eb63bd4fe7 --- /dev/null +++ b/ext/standard/tests/mail/gh19188_mixed_mode.phpt @@ -0,0 +1,20 @@ +--TEST-- +GH-19188: mail.cr_lf_mode=mixed +--INI-- +sendmail_path={MAIL:gh19188_mixed_mode.out} +mail.cr_lf_mode=mixed +--FILE-- + +--CLEAN-- + +--EXPECT-- +bool(true) +Mixed mode: +int(5) diff --git a/ext/standard/tests/mail/gh19188_os_mode_unix.phpt b/ext/standard/tests/mail/gh19188_os_mode_unix.phpt new file mode 100644 index 0000000000000..b365e3a671b03 --- /dev/null +++ b/ext/standard/tests/mail/gh19188_os_mode_unix.phpt @@ -0,0 +1,30 @@ +--TEST-- +GH-19188: mail.cr_lf_mode=os (Unix) +--SKIPIF-- + +--INI-- +sendmail_path={MAIL:gh19188_os_mode.out} +mail.cr_lf_mode=os +--FILE-- + +--CLEAN-- + +--EXPECT-- +bool(true) +OS mode: +CRLF count: int(0) +LF-only count: int(5) diff --git a/ext/standard/tests/mail/gh19188_os_mode_windows.phpt b/ext/standard/tests/mail/gh19188_os_mode_windows.phpt new file mode 100644 index 0000000000000..c3c3e7c08ee9d --- /dev/null +++ b/ext/standard/tests/mail/gh19188_os_mode_windows.phpt @@ -0,0 +1,31 @@ +--TEST-- +GH-19188: mail.cr_lf_mode=os (Windows) +--SKIPIF-- + +--INI-- +sendmail_path={MAIL:gh19188_os_mode.out} +mail.cr_lf_mode=os +--FILE-- + +--CLEAN-- + +--EXPECT-- +bool(true) +OS mode: +CRLF count: int(5) +LF-only count: int(0) diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index 3aff91efc6588..68204aa532d0b 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -330,16 +330,33 @@ static zend_result pass_errors_by_ref_and_free(zval *errors_zv, zval *errors) } ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri( - INTERNAL_FUNCTION_PARAMETERS, const uri_parser_t *uri_parser, const zend_string *uri_str, const zend_object *base_url_object, + INTERNAL_FUNCTION_PARAMETERS, const zend_string *uri_str, const zend_object *base_url_object, bool should_throw, bool should_update_this_object, zval *errors_zv ) { + + uri_object_t *uri_object; + if (should_update_this_object) { + uri_object = Z_URI_OBJECT_P(ZEND_THIS); + } else { + if (EX(func)->common.fn_flags & ZEND_ACC_STATIC) { + object_init_ex(return_value, Z_CE_P(ZEND_THIS)); + } else { + object_init_ex(return_value, Z_OBJCE_P(ZEND_THIS)); + } + uri_object = Z_URI_OBJECT_P(return_value); + } + + const uri_parser_t *uri_parser = uri_object->internal.parser; + zval errors; ZVAL_UNDEF(&errors); void *base_url = NULL; if (base_url_object != NULL) { + ZEND_ASSERT(base_url_object->ce == uri_object->std.ce); uri_internal_t *internal_base_url = uri_internal_from_obj(base_url_object); URI_ASSERT_INITIALIZATION(internal_base_url); + ZEND_ASSERT(internal_base_url->parser == uri_parser); base_url = internal_base_url->uri; } @@ -352,6 +369,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri( if (pass_errors_by_ref_and_free(errors_zv, &errors) == FAILURE) { RETURN_THROWS(); } + zval_ptr_dtor(return_value); RETURN_NULL(); } } @@ -361,19 +379,6 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri( RETURN_THROWS(); } - uri_object_t *uri_object; - if (should_update_this_object) { - uri_object = Z_URI_OBJECT_P(ZEND_THIS); - } else { - if (EX(func)->common.fn_flags & ZEND_ACC_STATIC) { - object_init_ex(return_value, Z_CE_P(ZEND_THIS)); - } else { - object_init_ex(return_value, Z_OBJCE_P(ZEND_THIS)); - } - uri_object = Z_URI_OBJECT_P(return_value); - } - - uri_object->internal.parser = uri_parser; uri_object->internal.uri = uri; } @@ -388,7 +393,7 @@ static void create_rfc3986_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor Z_PARAM_OBJ_OF_CLASS_OR_NULL(base_url_object, uri_rfc3986_uri_ce) ZEND_PARSE_PARAMETERS_END(); - php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, &php_uri_parser_rfc3986, uri_str, base_url_object, is_constructor, is_constructor, NULL); + php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, uri_str, base_url_object, is_constructor, is_constructor, NULL); } PHP_METHOD(Uri_Rfc3986_Uri, parse) @@ -475,7 +480,7 @@ static void create_whatwg_uri(INTERNAL_FUNCTION_PARAMETERS, bool is_constructor) Z_PARAM_ZVAL(errors) ZEND_PARSE_PARAMETERS_END(); - php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, &php_uri_parser_whatwg, uri_str, base_url_object, is_constructor, is_constructor, errors); + php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, uri_str, base_url_object, is_constructor, is_constructor, errors); } PHP_METHOD(Uri_WhatWg_Url, parse) @@ -756,11 +761,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, resolve) Z_PARAM_PATH_STR(uri_str) ZEND_PARSE_PARAMETERS_END(); - zend_object *this_object = Z_OBJ_P(ZEND_THIS); - uri_internal_t *internal_uri = uri_internal_from_obj(this_object); - URI_ASSERT_INITIALIZATION(internal_uri); - - php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, internal_uri->parser, uri_str, this_object, true, false, NULL); + php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, uri_str, Z_OBJ_P(ZEND_THIS), true, false, NULL); } PHP_METHOD(Uri_Rfc3986_Uri, __serialize) @@ -793,7 +794,7 @@ PHP_METHOD(Uri_Rfc3986_Uri, __serialize) zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &arr); } -static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *uri_parser_name) +static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS) { HashTable *data; @@ -829,7 +830,6 @@ static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *uri_parser } uri_internal_t *internal_uri = uri_internal_from_obj(object); - internal_uri->parser = uri_parser_by_name(uri_parser_name, strlen(uri_parser_name)); if (internal_uri->uri != NULL) { internal_uri->parser->free_uri(internal_uri->uri); } @@ -855,7 +855,7 @@ static void uri_unserialize(INTERNAL_FUNCTION_PARAMETERS, const char *uri_parser PHP_METHOD(Uri_Rfc3986_Uri, __unserialize) { - uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PARSER_RFC3986); + uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU); } PHP_METHOD(Uri_Rfc3986_Uri, __debugInfo) @@ -949,11 +949,7 @@ PHP_METHOD(Uri_WhatWg_Url, resolve) Z_PARAM_ZVAL(errors) ZEND_PARSE_PARAMETERS_END(); - zend_object *this_object = Z_OBJ_P(ZEND_THIS); - uri_internal_t *internal_uri = uri_internal_from_obj(this_object); - URI_ASSERT_INITIALIZATION(internal_uri); - - php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, internal_uri->parser, uri_str, this_object, true, false, errors); + php_uri_instantiate_uri(INTERNAL_FUNCTION_PARAM_PASSTHRU, uri_str, Z_OBJ_P(ZEND_THIS), true, false, errors); } PHP_METHOD(Uri_WhatWg_Url, __serialize) @@ -988,7 +984,7 @@ PHP_METHOD(Uri_WhatWg_Url, __serialize) PHP_METHOD(Uri_WhatWg_Url, __unserialize) { - uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU, PHP_URI_PARSER_WHATWG); + uri_unserialize(INTERNAL_FUNCTION_PARAM_PASSTHRU); } PHP_METHOD(Uri_WhatWg_Url, __debugInfo) @@ -1000,17 +996,32 @@ PHP_METHOD(Uri_WhatWg_Url, __debugInfo) RETURN_ARR(uri_get_debug_properties(object)); } -static zend_object *uri_create_object_handler(zend_class_entry *class_type) +PHPAPI uri_object_t *php_uri_object_create(zend_class_entry *class_type, const uri_parser_t *parser) { uri_object_t *uri_object = zend_object_alloc(sizeof(*uri_object), class_type); zend_object_std_init(&uri_object->std, class_type); object_properties_init(&uri_object->std, class_type); - return &uri_object->std; + uri_object->internal = (uri_internal_t){ + .parser = parser, + .uri = NULL, + }; + + return uri_object; +} + +static zend_object *php_uri_object_create_rfc3986(zend_class_entry *ce) +{ + return &php_uri_object_create(ce, &php_uri_parser_rfc3986)->std; } -static void uri_free_obj_handler(zend_object *object) +static zend_object *php_uri_object_create_whatwg(zend_class_entry *ce) +{ + return &php_uri_object_create(ce, &php_uri_parser_whatwg)->std; +} + +PHPAPI void php_uri_object_handler_free(zend_object *object) { uri_object_t *uri_object = uri_object_from_obj(object); @@ -1023,18 +1034,15 @@ static void uri_free_obj_handler(zend_object *object) zend_object_std_dtor(&uri_object->std); } -static zend_object *uri_clone_obj_handler(zend_object *object) +PHPAPI zend_object *php_uri_object_handler_clone(zend_object *object) { uri_object_t *uri_object = uri_object_from_obj(object); uri_internal_t *internal_uri = uri_internal_from_obj(object); URI_ASSERT_INITIALIZATION(internal_uri); - zend_object *new_object = uri_create_object_handler(object->ce); - ZEND_ASSERT(new_object != NULL); - uri_object_t *new_uri_object = uri_object_from_obj(new_object); - - new_uri_object->internal.parser = internal_uri->parser; + uri_object_t *new_uri_object = uri_object_from_obj(object->ce->create_object(object->ce)); + ZEND_ASSERT(new_uri_object->internal.parser == internal_uri->parser); void *uri = internal_uri->parser->clone_uri(internal_uri->uri); ZEND_ASSERT(uri != NULL); @@ -1046,16 +1054,6 @@ static zend_object *uri_clone_obj_handler(zend_object *object) return &new_uri_object->std; } -ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zend_object_handlers *object_handlers) -{ - ce->create_object = uri_create_object_handler; - ce->default_object_handlers = object_handlers; - memcpy(object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - object_handlers->offset = XtOffsetOf(uri_object_t, std); - object_handlers->free_obj = uri_free_obj_handler; - object_handlers->clone_obj = uri_clone_obj_handler; -} - PHPAPI zend_result php_uri_parser_register(const uri_parser_t *uri_parser) { zend_string *key = zend_string_init_interned(uri_parser->name, strlen(uri_parser->name), true); @@ -1076,10 +1074,20 @@ PHPAPI zend_result php_uri_parser_register(const uri_parser_t *uri_parser) static PHP_MINIT_FUNCTION(uri) { uri_rfc3986_uri_ce = register_class_Uri_Rfc3986_Uri(); - php_uri_implementation_set_object_handlers(uri_rfc3986_uri_ce, &uri_rfc3986_uri_object_handlers); + uri_rfc3986_uri_ce->create_object = php_uri_object_create_rfc3986; + uri_rfc3986_uri_ce->default_object_handlers = &uri_rfc3986_uri_object_handlers; + memcpy(&uri_rfc3986_uri_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + uri_rfc3986_uri_object_handlers.offset = XtOffsetOf(uri_object_t, std); + uri_rfc3986_uri_object_handlers.free_obj = php_uri_object_handler_free; + uri_rfc3986_uri_object_handlers.clone_obj = php_uri_object_handler_clone; uri_whatwg_url_ce = register_class_Uri_WhatWg_Url(); - php_uri_implementation_set_object_handlers(uri_whatwg_url_ce, &uri_whatwg_uri_object_handlers); + uri_whatwg_url_ce->create_object = php_uri_object_create_whatwg; + uri_whatwg_url_ce->default_object_handlers = &uri_whatwg_uri_object_handlers; + memcpy(&uri_whatwg_uri_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + uri_whatwg_uri_object_handlers.offset = XtOffsetOf(uri_object_t, std); + uri_whatwg_uri_object_handlers.free_obj = php_uri_object_handler_free; + uri_whatwg_uri_object_handlers.clone_obj = php_uri_object_handler_clone; uri_comparison_mode_ce = register_class_Uri_UriComparisonMode(); uri_exception_ce = register_class_Uri_UriException(zend_ce_exception); diff --git a/ext/uri/php_uri.h b/ext/uri/php_uri.h index 19ba97dc4f386..f570d5150ffa6 100644 --- a/ext/uri/php_uri.h +++ b/ext/uri/php_uri.h @@ -205,10 +205,8 @@ ZEND_ATTRIBUTE_NONNULL PHPAPI php_uri *php_uri_parse_to_struct( ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_struct_free(php_uri *uri); ZEND_ATTRIBUTE_NONNULL_ARGS(1, 2) PHPAPI void php_uri_instantiate_uri( - INTERNAL_FUNCTION_PARAMETERS, const uri_parser_t *uri_parser, const zend_string *uri_str, const zend_object *base_url_object, + INTERNAL_FUNCTION_PARAMETERS, const zend_string *uri_str, const zend_object *base_url_object, bool should_throw, bool should_update_this_object, zval *errors_zv ); -ZEND_ATTRIBUTE_NONNULL PHPAPI void php_uri_implementation_set_object_handlers(zend_class_entry *ce, zend_object_handlers *object_handlers); - #endif diff --git a/ext/uri/php_uri_common.h b/ext/uri/php_uri_common.h index 0b2b4ddbe7973..999dca0e53ac4 100644 --- a/ext/uri/php_uri_common.h +++ b/ext/uri/php_uri_common.h @@ -159,6 +159,10 @@ static inline uri_internal_t *uri_internal_from_obj(const zend_object *object) { #define Z_URI_OBJECT_P(zv) uri_object_from_obj(Z_OBJ_P((zv))) #define Z_URI_INTERNAL_P(zv) uri_internal_from_obj(Z_OBJ_P((zv))) +PHPAPI uri_object_t *php_uri_object_create(zend_class_entry *class_type, const uri_parser_t *parser); +PHPAPI void php_uri_object_handler_free(zend_object *object); +PHPAPI zend_object *php_uri_object_handler_clone(zend_object *object); + #define PHP_URI_PARSER_RFC3986 "Uri\\Rfc3986\\Uri" #define PHP_URI_PARSER_WHATWG "Uri\\WhatWg\\Url" #define PHP_URI_PARSER_PHP_PARSE_URL "parse_url" diff --git a/main/main.c b/main/main.c index a48dd14b7f287..a1515911fbfeb 100644 --- a/main/main.c +++ b/main/main.c @@ -721,6 +721,36 @@ static PHP_INI_MH(OnUpdateMailLog) } /* }}} */ +/* {{{ PHP_INI_MH */ +static PHP_INI_MH(OnUpdateMailCrLfMode) +{ + if (new_value) { + const char *val = ZSTR_VAL(new_value); + if (ZSTR_LEN(new_value) > 0 && + strcmp(val, "crlf") != 0 && + strcmp(val, "lf") != 0 && + strcmp(val, "mixed") != 0 && + strcmp(val, "os") != 0) { + int err_type; + + if (stage == ZEND_INI_STAGE_RUNTIME) { + err_type = E_WARNING; + } else { + err_type = E_ERROR; + } + + if (stage != ZEND_INI_STAGE_DEACTIVATE) { + php_error_docref(NULL, err_type, "Invalid value \"%s\" for mail.cr_lf_mode. Must be one of: \"crlf\", \"lf\", \"mixed\", \"os\"", val); + } + + return FAILURE; + } + } + OnUpdateString(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); + return SUCCESS; +} +/* }}} */ + /* {{{ PHP_INI_MH */ static PHP_INI_MH(OnChangeMailForceExtra) { @@ -826,6 +856,7 @@ PHP_INI_BEGIN() PHP_INI_ENTRY("smtp_port", "25", PHP_INI_ALL, NULL) STD_PHP_INI_BOOLEAN("mail.add_x_header", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, mail_x_header, php_core_globals, core_globals) STD_PHP_INI_BOOLEAN("mail.mixed_lf_and_crlf", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, mail_mixed_lf_and_crlf, php_core_globals, core_globals) + STD_PHP_INI_ENTRY("mail.cr_lf_mode", "crlf", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateMailCrLfMode, mail_cr_lf_mode, php_core_globals, core_globals) STD_PHP_INI_ENTRY("mail.log", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateMailLog, mail_log, php_core_globals, core_globals) PHP_INI_ENTRY("browscap", NULL, PHP_INI_SYSTEM, OnChangeBrowscap) diff --git a/main/php_globals.h b/main/php_globals.h index 61df82ac99f5f..028089ab43c69 100644 --- a/main/php_globals.h +++ b/main/php_globals.h @@ -154,6 +154,7 @@ struct _php_core_globals { char *mail_log; bool mail_x_header; bool mail_mixed_lf_and_crlf; + char *mail_cr_lf_mode; bool in_error_log; diff --git a/php.ini-development b/php.ini-development index 6a217d30cb7ae..0fd6920c2fb30 100644 --- a/php.ini-development +++ b/php.ini-development @@ -1086,6 +1086,14 @@ mail.add_x_header = Off ; RFC 2822 non conformant MTA. mail.mixed_lf_and_crlf = Off +; Control line ending mode for mail messages and headers. +; Possible values: "crlf" (default), "lf", "mixed", "os" +; - crlf: Use CRLF line endings +; - lf: Use LF line endings only (converts CRLF in message to LF) +; - mixed: Same as mail.mixed_lf_and_crlf = On +; - os: Use CRLF on Windows, LF on other systems +mail.cr_lf_mode = crlf + ; The path to a log file that will log all mail() calls. Log entries include ; the full path of the script, line number, To address and headers. ;mail.log = diff --git a/php.ini-production b/php.ini-production index 09c048a1efe25..d555eb9ff7495 100644 --- a/php.ini-production +++ b/php.ini-production @@ -1088,6 +1088,14 @@ mail.add_x_header = Off ; RFC 2822 non conformant MTA. mail.mixed_lf_and_crlf = Off +; Control line ending mode for mail messages and headers. +; Possible values: "crlf" (default), "lf", "mixed", "os" +; - crlf: Use CRLF line endings +; - lf: Use LF line endings only (converts CRLF in message to LF) +; - mixed: Same as mail.mixed_lf_and_crlf = On +; - os: Use CRLF on Windows, LF on other systems +mail.cr_lf_mode = crlf + ; The path to a log file that will log all mail() calls. Log entries include ; the full path of the script, line number, To address and headers. ;mail.log =