@@ -38,6 +38,61 @@ namespace RequestBodyProcessor {
3838static const char * mime_charset_special = " !#$%&+-^_`{}~" ;
3939static const char * attr_char_special = " !#$&+-.^_`~" ;
4040
41+ MultipartPartTmpFile::~MultipartPartTmpFile () {
42+ if (!m_tmp_file_name.empty () && m_delete) {
43+ /* make sure it is closed first */
44+ if (m_tmp_file_fd > 0 ) {
45+ Close ();
46+ }
47+
48+ const int unlink_rc = unlink (m_tmp_file_name.c_str ());
49+ if (unlink_rc < 0 ) {
50+ ms_dbg_a (m_transaction, 1 , " Multipart: Failed to delete file (part) \" " \
51+ + m_tmp_file_name + " \" because " \
52+ + std::to_string (errno) + " (" \
53+ + strerror (errno) + " )" );
54+ } else {
55+ ms_dbg_a (m_transaction, 4 , " Multipart: file deleted successfully (part) \" " \
56+ + m_tmp_file_name + " \" " );
57+ }
58+
59+ }
60+ }
61+
62+ void MultipartPartTmpFile::Open () {
63+ struct tm timeinfo;
64+ char tstr[300 ];
65+ time_t tt = time (NULL );
66+
67+ localtime_r (&tt, &timeinfo);
68+
69+ memset (tstr, ' \0 ' , 300 );
70+ strftime (tstr, 299 , " /%Y%m%d-%H%M%S" , &timeinfo);
71+
72+ std::string path = m_transaction->m_rules ->m_uploadDirectory .m_value ;
73+ path = path + tstr + " -" + *m_transaction->m_id .get ();
74+ path += " -file-XXXXXX" ;
75+
76+ char * tmp = strdup (path.c_str ());
77+ m_tmp_file_fd = mkstemp (tmp);
78+ m_tmp_file_name.assign (tmp);
79+ free (tmp);
80+ ms_dbg_a (m_transaction, 4 , " MultipartPartTmpFile: Create filename= " + m_tmp_file_name);
81+
82+ int mode = m_transaction->m_rules ->m_uploadFileMode .m_value ;
83+ if ((m_tmp_file_fd != -1 ) && (mode != 0 )) {
84+ if (fchmod (m_tmp_file_fd, mode) == -1 ) {
85+ m_tmp_file_fd = -1 ;
86+ }
87+ }
88+ }
89+
90+ void MultipartPartTmpFile::Close () {
91+ close (m_tmp_file_fd);
92+ m_tmp_file_fd = -1 ;
93+ }
94+
95+
4196Multipart::Multipart (const std::string &header, Transaction *transaction)
4297 : m_reqbody_no_files_length(0 ),
4398 m_nfiles (0 ),
@@ -80,30 +135,14 @@ Multipart::~Multipart() {
80135 if (m_transaction->m_rules ->m_uploadKeepFiles
81136 != RulesSetProperties::TrueConfigBoolean) {
82137 for (MultipartPart *m : m_parts) {
83- if (m->m_type == MULTIPART_FILE) {
84- if (!m->m_tmp_file_name .empty ()) {
85- /* make sure it is closed first */
86- if (m->m_tmp_file_fd > 0 ) {
87- close (m->m_tmp_file_fd );
88- m->m_tmp_file_fd = -1 ;
89- }
90- const int unlink_rc =
91- unlink (m->m_tmp_file_name .c_str ());
92-
93- if (unlink_rc < 0 ) {
94- ms_dbg_a (m_transaction, 1 ,
95- " Multipart: Failed to delete file (part) \" " \
96- + m->m_tmp_file_name + " \" because " \
97- + std::to_string (errno) + " (" \
98- + strerror (errno) + " )" );
99- } else {
100- ms_dbg_a (m_transaction, 4 ,
101- " Multipart: file deleted successfully (part) \" " \
102- + m->m_tmp_file_name + " \" " );
103- }
104-
105- }
138+ if ((m->m_type == MULTIPART_FILE) && (m->m_tmp_file )) {
139+ // only mark for deletion for now; the file should stay on disk until
140+ // the transaction is complete
141+ ms_dbg_a (m_transaction, 9 , " Multipart: Marking temporary file for deletion: " \
142+ + m->m_tmp_file ->getFilename ());
143+ m->m_tmp_file ->setDelete ();
106144 }
145+
107146 }
108147 }
109148
@@ -432,7 +471,7 @@ int Multipart::parse_content_disposition(const char *c_d_value, int offset) {
432471 + std::to_string (strlen (p)) + " bytes" );
433472 m_flag_invalid_quoting = 1 ;
434473 }
435- p++;
474+ /* p++; */
436475 return -12 ;
437476 }
438477 p++; /* move over the semi-colon */
@@ -453,40 +492,6 @@ int Multipart::parse_content_disposition(const char *c_d_value, int offset) {
453492}
454493
455494
456- int Multipart::tmp_file_name (std::string *filename) const {
457- std::string path;
458- struct tm timeinfo;
459- char tstr[300 ];
460- char *tmp;
461- int fd;
462- int mode;
463- time_t tt = time (NULL );
464-
465- localtime_r (&tt, &timeinfo);
466-
467- path = m_transaction->m_rules ->m_uploadDirectory .m_value ;
468- mode = m_transaction->m_rules ->m_uploadFileMode .m_value ;
469-
470- memset (tstr, ' \0 ' , 300 );
471- strftime (tstr, 299 , " /%Y%m%d-%H%M%S" , &timeinfo);
472- path = path + tstr + " -" + *m_transaction->m_id .get ();
473- path = path + " -file-XXXXXX" ;
474-
475- tmp = strdup (path.c_str ());
476-
477- fd = mkstemp (tmp);
478- filename->assign (tmp);
479- free (tmp);
480- if ((fd != -1 ) && (mode != 0 )) {
481- if (fchmod (fd, mode) == -1 ) {
482- return -1 ;
483- }
484- }
485-
486- return fd;
487- }
488-
489-
490495int Multipart::process_part_data (std::string *error, size_t offset) {
491496 char *p = m_buf + (MULTIPART_BUF_SIZE - m_bufleft);
492497 char localreserve[2 ] = { ' \0 ' , ' \0 ' }; /* initialized to quiet warning */
@@ -546,20 +551,18 @@ int Multipart::process_part_data(std::string *error, size_t offset) {
546551 */
547552 if (extract) {
548553 /* first create a temporary file if we don't have it already */
549- if (m_mpp->m_tmp_file_fd == 0 ) {
550- std::string path;
551- m_mpp->m_tmp_file_fd = tmp_file_name (&path);
552-
553- /* construct temporary file name */
554- m_mpp->m_tmp_file_name = path;
554+ if (!m_mpp->m_tmp_file || !m_mpp->m_tmp_file ->isValid ()) {
555+ m_mpp->m_tmp_file = std::make_shared<RequestBodyProcessor::MultipartPartTmpFile>(m_transaction);
556+ m_transaction->m_multipartPartTmpFiles .push_back (m_mpp->m_tmp_file );
557+ m_mpp->m_tmp_file ->Open ();
555558
556559 /* do we have an opened file? */
557- if (m_mpp->m_tmp_file_fd < 0 ) {
560+ if (! m_mpp->m_tmp_file || m_mpp-> m_tmp_file -> getFd () < 0 ) {
558561 ms_dbg_a (m_transaction, 1 ,
559562 " Multipart: Failed to create file: " \
560- + m_mpp->m_tmp_file_name );
563+ + m_mpp->m_tmp_file -> getFilename () );
561564 error->assign (" Multipart: Failed to create file: " \
562- + m_mpp->m_tmp_file_name );
565+ + m_mpp->m_tmp_file -> getFilename () );
563566 return -1 ;
564567 }
565568 /* keep track of the files count */
@@ -569,18 +572,18 @@ int Multipart::process_part_data(std::string *error, size_t offset) {
569572 ms_dbg_a (m_transaction, 4 ,
570573 " Multipart: Created temporary file " \
571574 + std::to_string (m_nfiles) + " (mode o" + std::to_string (m_transaction->m_rules ->m_uploadFileMode .m_value ) + " ): " \
572- + m_mpp->m_tmp_file_name );
575+ + m_mpp->m_tmp_file -> getFilename () );
573576 }
574577
575578 /* write the reserve first */
576579 if (m_reserve[0 ] != 0 ) {
577- if (write (m_mpp->m_tmp_file_fd , &m_reserve[1 ], m_reserve[0 ])
580+ if (write (m_mpp->m_tmp_file -> getFd () , &m_reserve[1 ], m_reserve[0 ])
578581 != m_reserve[0 ]) {
579582 ms_dbg_a (m_transaction, 1 ,
580583 " Multipart: writing to \" " \
581- + m_mpp->m_tmp_file_name + " \" failed" );
584+ + m_mpp->m_tmp_file -> getFilename () + " \" failed" );
582585 error->assign (" Multipart: writing to \" " \
583- + m_mpp->m_tmp_file_name + " \" failed" );
586+ + m_mpp->m_tmp_file -> getFilename () + " \" failed" );
584587 return -1 ;
585588 }
586589
@@ -594,14 +597,14 @@ int Multipart::process_part_data(std::string *error, size_t offset) {
594597
595598 /* write data to the file */
596599
597- if (write (m_mpp->m_tmp_file_fd , m_buf,
600+ if (write (m_mpp->m_tmp_file -> getFd () , m_buf,
598601 MULTIPART_BUF_SIZE - m_bufleft)
599602 != (MULTIPART_BUF_SIZE - m_bufleft)) {
600603 ms_dbg_a (m_transaction, 1 ,
601604 " Multipart: writing to \" " \
602- + m_mpp->m_tmp_file_name + " \" failed" );
605+ + m_mpp->m_tmp_file -> getFilename () + " \" failed" );
603606 error->assign (" Multipart: writing to \" " \
604- + m_mpp->m_tmp_file_name + " \" failed" );
607+ + m_mpp->m_tmp_file -> getFilename () + " \" failed" );
605608 return -1 ;
606609 }
607610
@@ -911,11 +914,9 @@ int Multipart::process_boundary(int last_part) {
911914 /* if there was a part being built finish it */
912915 if (m_mpp != NULL ) {
913916 /* close the temp file */
914- if ((m_mpp->m_type == MULTIPART_FILE)
915- && (!m_mpp->m_tmp_file_name .empty ())
916- && (m_mpp->m_tmp_file_fd != 0 )) {
917- close (m_mpp->m_tmp_file_fd );
918- m_mpp->m_tmp_file_fd = -1 ;
917+ if ((m_mpp->m_type == MULTIPART_FILE) && (m_mpp->m_tmp_file )
918+ && (m_mpp->m_tmp_file ->isValid ())) {
919+ m_mpp->m_tmp_file ->Close ();
919920 }
920921
921922 if (m_mpp->m_type != MULTIPART_FILE) {
@@ -1128,8 +1129,10 @@ int Multipart::multipart_complete(std::string *error) {
11281129 if (m->m_type == MULTIPART_FILE) {
11291130 std::string tmp_name;
11301131 std::string name;
1131- if (!m->m_tmp_file_name .empty ()) {
1132- tmp_name.assign (m->m_tmp_file_name );
1132+ if (m->m_tmp_file && !m->m_tmp_file ->getFilename ().empty ()) {
1133+ tmp_name.assign (m->m_tmp_file ->getFilename ());
1134+ m_transaction->m_variableFilesTmpNames .set (m->m_tmp_file ->getFilename (),
1135+ m->m_tmp_file ->getFilename (), m->m_filenameOffset );
11331136 }
11341137 if (!m->m_filename .empty ()) {
11351138 name.assign (m->m_filename );
@@ -1149,9 +1152,6 @@ int Multipart::multipart_complete(std::string *error) {
11491152 m_transaction->m_variableFilesTmpContent .set (m->m_filename ,
11501153 m->m_value , m->m_valueOffset );
11511154
1152- m_transaction->m_variableFilesTmpNames .set (m->m_tmp_file_name ,
1153- m->m_tmp_file_name , m->m_filenameOffset );
1154-
11551155 file_combined_size = file_combined_size + m->m_tmp_file_size .first ;
11561156
11571157 m_transaction->m_variableFilesCombinedSize .set (
0 commit comments