From 300e3f04404e771de89351e410699e447759175a Mon Sep 17 00:00:00 2001 From: Petr Heralecky Date: Fri, 10 Jan 2014 11:49:11 +0100 Subject: Added Email::attach_cid() returning CID --- system/libraries/Email.php | 87 +++++++++++++++++++------------ user_guide_src/source/changelog.rst | 2 + user_guide_src/source/libraries/email.rst | 24 ++++++++- 3 files changed, 79 insertions(+), 34 deletions(-) diff --git a/system/libraries/Email.php b/system/libraries/Email.php index efdbfd7c1..b84518bbd 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -718,14 +718,63 @@ class CI_Email { */ public function attach($filename, $disposition = '', $newname = NULL, $mime = '') { + if ($mime === '') + { + if ( ! file_exists($filename)) + { + $this->_set_error_message('lang:email_attachment_missing', $filename); + return FALSE; + } + + if ( ! $fp = fopen($filename, FOPEN_READ)) + { + $this->_set_error_message('lang:email_attachment_unreadable', $filename); + return FALSE; + } + $file_content = stream_get_contents($fp); + $mime = $this->_mime_types(pathinfo($filename, PATHINFO_EXTENSION)); + } + else + { + $file_content =& $filename; // buffered file + } + $this->_attachments[] = array( 'name' => array($filename, $newname), 'disposition' => empty($disposition) ? 'attachment' : $disposition, // Can also be 'inline' Not sure if it matters - 'type' => $mime + 'type' => $mime, + 'content' => chunk_split(base64_encode($file_content)) ); - + + fclose($fp); + return $this; } + + // -------------------------------------------------------------------- + + /** + * Sets and return id of attachment (useful for attached inline pictures) + * + * @param string + * @return string + */ + public function attach_cid($filename) + { + if($this->multipart != 'related') + { + $this->multipart = 'related'; // Thunderbird need this for inline images + } + foreach($this->_attachments as $ind => $attach) + { + if($attach['name'][0] == $filename) + { + $this->_attachments[$ind]['cid'] = uniqid(basename($this->_attachments[$ind]['name'][0]) . "@"); + return $this->_attachments[$ind]['cid']; + } + } + return FALSE; + } // -------------------------------------------------------------------- @@ -1361,41 +1410,15 @@ class CI_Email { $filename = $this->_attachments[$i]['name'][0]; $basename = ($this->_attachments[$i]['name'][1] === NULL) ? basename($filename) : $this->_attachments[$i]['name'][1]; - $ctype = $this->_attachments[$i]['type']; - $file_content = ''; - - if ($ctype === '') - { - if ( ! file_exists($filename)) - { - $this->_set_error_message('lang:email_attachment_missing', $filename); - return FALSE; - } - - $file = filesize($filename) +1; - - if ( ! $fp = fopen($filename, FOPEN_READ)) - { - $this->_set_error_message('lang:email_attachment_unreadable', $filename); - return FALSE; - } - - $ctype = $this->_mime_types(pathinfo($filename, PATHINFO_EXTENSION)); - $file_content = fread($fp, $file); - fclose($fp); - } - else - { - $file_content =& $this->_attachments[$i]['name'][0]; - } $attachment[$z++] = '--'.$this->_atc_boundary.$this->newline - .'Content-type: '.$ctype.'; ' + .'Content-type: '.$this->_attachments[$i]['type'].'; ' .'name="'.$basename.'"'.$this->newline .'Content-Disposition: '.$this->_attachments[$i]['disposition'].';'.$this->newline - .'Content-Transfer-Encoding: base64'.$this->newline; + .'Content-Transfer-Encoding: base64'.$this->newline + .(!empty($this->_attachments[$i]['cid']) ? "Content-ID: <".$this->_attachments[$i]['cid'].">".$this->newline : ''); - $attachment[$z++] = chunk_split(base64_encode($file_content)); + $attachment[$z++] = $this->_attachments[$i]['content']; } $body .= implode($this->newline, $attachment).$this->newline.'--'.$this->_atc_boundary.'--'; diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 0488d9d4a..e8dc880e8 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -334,6 +334,8 @@ Release Date: Not Released - Added custom filename to ``Email::attach()`` as ``$this->email->attach($filename, $disposition, $newname)``. - Added possibility to send attachment as buffer string in ``Email::attach()`` as ``$this->email->attach($buffer, $disposition, $newname, $mime)``. + - Email attachments are creating in function Email::attach() - it's faster for sending many emails with same attachments + - Added method Email::attach_cid() returning CID which enables to embed an attachment to html. - Added dsn (delivery status notification) option. - Renamed method _set_header() to set_header() and made it public to enable adding custom headers in the :doc:`Email Library `. - Successfully sent emails will automatically clear the parameters. diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst index 39629ece1..90b71142b 100644 --- a/user_guide_src/source/libraries/email.rst +++ b/user_guide_src/source/libraries/email.rst @@ -247,8 +247,8 @@ $this->email->attach() ---------------------- Enables you to send an attachment. Put the file path/name in the first -parameter. Note: Use a file path, not a URL. For multiple attachments -use the method multiple times. For example:: +parameter. For multiple attachments use the method multiple times. +For example:: $this->email->attach('/path/to/photo1.jpg'); $this->email->attach('/path/to/photo2.jpg'); @@ -269,6 +269,26 @@ parameter as mime-type:: $this->email->attach($buffer, 'attachment', 'report.pdf', 'application/pdf'); +$this->email->attach_cid() + -------------------------- + + Returns CID which enables to embed an attachment to html. First parameter + must be attached file. + + :: + + $filename = '/img/photo1.jpg'; + $this->email->attach($filename); + foreach ($list as $address) + { + $this->email->to($address); + $cid = $this->email->attach_cid($filename); + $this->email->message('photo1'); + $this->email->send(); + } + + CID for each Email have to be create again to be unique. + $this->email->print_debugger() ------------------------------ -- cgit v1.2.3-24-g4f1b From de88615b7245f00d086d97a9fb5ea8b307d34c4f Mon Sep 17 00:00:00 2001 From: Petr Heralecky Date: Fri, 10 Jan 2014 12:52:56 +0100 Subject: styleguided --- system/libraries/Email.php | 26 ++++++++++++++++---------- user_guide_src/source/changelog.rst | 3 +-- user_guide_src/source/libraries/email.rst | 18 +++++++++--------- 3 files changed, 26 insertions(+), 21 deletions(-) diff --git a/system/libraries/Email.php b/system/libraries/Email.php index b84518bbd..20eac72fc 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -731,8 +731,10 @@ class CI_Email { $this->_set_error_message('lang:email_attachment_unreadable', $filename); return FALSE; } + $file_content = stream_get_contents($fp); $mime = $this->_mime_types(pathinfo($filename, PATHINFO_EXTENSION)); + fclose($fp); } else { @@ -746,7 +748,7 @@ class CI_Email { 'content' => chunk_split(base64_encode($file_content)) ); - fclose($fp); + return $this; } @@ -754,25 +756,29 @@ class CI_Email { // -------------------------------------------------------------------- /** - * Sets and return id of attachment (useful for attached inline pictures) + * Set and return id of attachment + * + * useful for attached inline pictures * - * @param string - * @return string + * @param string $filename + * @return string */ public function attach_cid($filename) { - if($this->multipart != 'related') + if ($this->multipart !== 'related') { $this->multipart = 'related'; // Thunderbird need this for inline images } - foreach($this->_attachments as $ind => $attach) + + for ($i = 0, $c = count($this->_attachments); $i < $c; $i++) { - if($attach['name'][0] == $filename) + if ($attach['name'][0] === $filename) { - $this->_attachments[$ind]['cid'] = uniqid(basename($this->_attachments[$ind]['name'][0]) . "@"); - return $this->_attachments[$ind]['cid']; + $this->_attachments[$ind]['cid'] = uniqid(basename($this->_attachments[$i]['name'][0]).'@'); + return $this->_attachments[$i]['cid']; } } + return FALSE; } @@ -1416,7 +1422,7 @@ class CI_Email { .'name="'.$basename.'"'.$this->newline .'Content-Disposition: '.$this->_attachments[$i]['disposition'].';'.$this->newline .'Content-Transfer-Encoding: base64'.$this->newline - .(!empty($this->_attachments[$i]['cid']) ? "Content-ID: <".$this->_attachments[$i]['cid'].">".$this->newline : ''); + .(empty($this->_attachments[$i]['cid']) ? '' : 'Content-ID: <'.$this->_attachments[$i]['cid'].'>'.$this->newline); $attachment[$z++] = $this->_attachments[$i]['content']; } diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index e8dc880e8..34eff5d57 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -334,8 +334,7 @@ Release Date: Not Released - Added custom filename to ``Email::attach()`` as ``$this->email->attach($filename, $disposition, $newname)``. - Added possibility to send attachment as buffer string in ``Email::attach()`` as ``$this->email->attach($buffer, $disposition, $newname, $mime)``. - - Email attachments are creating in function Email::attach() - it's faster for sending many emails with same attachments - - Added method Email::attach_cid() returning CID which enables to embed an attachment to html. + - Added method ``Email::attach_cid()`` returning CID which enables to embed an attachment to html. - Added dsn (delivery status notification) option. - Renamed method _set_header() to set_header() and made it public to enable adding custom headers in the :doc:`Email Library `. - Successfully sent emails will automatically clear the parameters. diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst index 90b71142b..274d88d46 100644 --- a/user_guide_src/source/libraries/email.rst +++ b/user_guide_src/source/libraries/email.rst @@ -277,15 +277,15 @@ $this->email->attach_cid() :: - $filename = '/img/photo1.jpg'; - $this->email->attach($filename); - foreach ($list as $address) - { - $this->email->to($address); - $cid = $this->email->attach_cid($filename); - $this->email->message('photo1'); - $this->email->send(); - } + $filename = '/img/photo1.jpg'; + $this->email->attach($filename); + foreach ($list as $address) + { + $this->email->to($address); + $cid = $this->email->attach_cid($filename); + $this->email->message('photo1'); + $this->email->send(); + } CID for each Email have to be create again to be unique. -- cgit v1.2.3-24-g4f1b From 230fca38f3f7481686d9d9c2989ad7d0a1a4874f Mon Sep 17 00:00:00 2001 From: Petr Heralecky Date: Fri, 10 Jan 2014 12:55:57 +0100 Subject: styleguided 2 --- system/libraries/Email.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 20eac72fc..01dbfbe19 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -748,8 +748,6 @@ class CI_Email { 'content' => chunk_split(base64_encode($file_content)) ); - - return $this; } @@ -774,7 +772,7 @@ class CI_Email { { if ($attach['name'][0] === $filename) { - $this->_attachments[$ind]['cid'] = uniqid(basename($this->_attachments[$i]['name'][0]).'@'); + $this->_attachments[$i]['cid'] = uniqid(basename($this->_attachments[$i]['name'][0]).'@'); return $this->_attachments[$i]['cid']; } } -- cgit v1.2.3-24-g4f1b From 9ad2fff4492e1e216aad0b03714ddfcb7a06d697 Mon Sep 17 00:00:00 2001 From: Petr Heralecky Date: Fri, 10 Jan 2014 13:25:34 +0100 Subject: variable repair --- system/libraries/Email.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 01dbfbe19..a41884f7d 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -747,7 +747,7 @@ class CI_Email { 'type' => $mime, 'content' => chunk_split(base64_encode($file_content)) ); - + return $this; } @@ -770,7 +770,7 @@ class CI_Email { for ($i = 0, $c = count($this->_attachments); $i < $c; $i++) { - if ($attach['name'][0] === $filename) + if ($this->_attachments[$i]['name'][0] === $filename) { $this->_attachments[$i]['cid'] = uniqid(basename($this->_attachments[$i]['name'][0]).'@'); return $this->_attachments[$i]['cid']; -- cgit v1.2.3-24-g4f1b From c809726558cc5364713e49c7404e43989203c4af Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Fri, 10 Jan 2014 14:45:31 +0200 Subject: Further changes related to PR #2807 --- system/libraries/Email.php | 23 ++++++++++++----------- user_guide_src/source/changelog.rst | 10 +++++----- user_guide_src/source/libraries/email.rst | 14 +++++++------- 3 files changed, 24 insertions(+), 23 deletions(-) diff --git a/system/libraries/Email.php b/system/libraries/Email.php index a41884f7d..739b76ccb 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -725,13 +725,13 @@ class CI_Email { $this->_set_error_message('lang:email_attachment_missing', $filename); return FALSE; } - + if ( ! $fp = fopen($filename, FOPEN_READ)) { $this->_set_error_message('lang:email_attachment_unreadable', $filename); return FALSE; } - + $file_content = stream_get_contents($fp); $mime = $this->_mime_types(pathinfo($filename, PATHINFO_EXTENSION)); fclose($fp); @@ -740,7 +740,7 @@ class CI_Email { { $file_content =& $filename; // buffered file } - + $this->_attachments[] = array( 'name' => array($filename, $newname), 'disposition' => empty($disposition) ? 'attachment' : $disposition, // Can also be 'inline' Not sure if it matters @@ -750,24 +750,24 @@ class CI_Email { return $this; } - + // -------------------------------------------------------------------- - + /** - * Set and return id of attachment - * - * useful for attached inline pictures + * Set and return attachment Content-ID + * + * Useful for attached inline pictures * * @param string $filename * @return string */ - public function attach_cid($filename) + public function attachment_cid($filename) { if ($this->multipart !== 'related') { $this->multipart = 'related'; // Thunderbird need this for inline images } - + for ($i = 0, $c = count($this->_attachments); $i < $c; $i++) { if ($this->_attachments[$i]['name'][0] === $filename) @@ -776,7 +776,7 @@ class CI_Email { return $this->_attachments[$i]['cid']; } } - + return FALSE; } @@ -1429,6 +1429,7 @@ class CI_Email { $this->_finalbody = ($this->_get_protocol() === 'mail') ? $body : $hdr.$this->newline.$this->newline.$body; + return TRUE; } diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 34eff5d57..b112da5b4 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -332,11 +332,11 @@ Release Date: Not Released - :doc:`Email Library ` changes include: - - Added custom filename to ``Email::attach()`` as ``$this->email->attach($filename, $disposition, $newname)``. - - Added possibility to send attachment as buffer string in ``Email::attach()`` as ``$this->email->attach($buffer, $disposition, $newname, $mime)``. - - Added method ``Email::attach_cid()`` returning CID which enables to embed an attachment to html. + - Added a custom filename parameter to ``attach()`` as ``$this->email->attach($filename, $disposition, $newname)``. + - Added possibility to send attachment as buffer string in ``attach()`` as ``$this->email->attach($buffer, $disposition, $newname, $mime)``. + - Added method ``attachment_cid()`` to enable embedding inline attachments into HTML. - Added dsn (delivery status notification) option. - - Renamed method _set_header() to set_header() and made it public to enable adding custom headers in the :doc:`Email Library `. + - Renamed method ``_set_header()`` to ``set_header()`` and made it public to enable adding custom headers. - Successfully sent emails will automatically clear the parameters. - Added a *return_path* parameter to the ``from()`` method. - Removed the second parameter (character limit) from internal method ``_prep_quoted_printable()`` as it is never used. @@ -345,7 +345,7 @@ Release Date: Not Released - Removed unused protected method ``_get_ip()`` (:doc:`Input Library `'s ``ip_address()`` should be used anyway). - Internal method ``_prep_q_encoding()`` now utilizes PHP's *mbstring* and *iconv* extensions (when available) and no longer has a second (``$from``) argument. - Added an optional parameter to ``print_debugger()`` to allow specifying which parts of the message should be printed ('headers', 'subject', 'body'). - - Added SMTP keepalive option to avoid opening the connection for each ``Email::send()``. Accessible as ``$smtp_keepalive``. + - Added SMTP keepalive option to avoid opening the connection for each ``send()`` call. Accessible as ``$smtp_keepalive``. - Public method ``set_header()`` now filters the input by removing all "\\r" and "\\n" characters. - :doc:`Pagination Library ` changes include: diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst index 274d88d46..8e3800306 100644 --- a/user_guide_src/source/libraries/email.rst +++ b/user_guide_src/source/libraries/email.rst @@ -269,13 +269,13 @@ parameter as mime-type:: $this->email->attach($buffer, 'attachment', 'report.pdf', 'application/pdf'); -$this->email->attach_cid() - -------------------------- +$this->email->attachment_cid() +------------------------------ - Returns CID which enables to embed an attachment to html. First parameter - must be attached file. +Sets and returns an attachment's Content-ID, which enables your to embed an inline +(picture) attachment into HTML. First parameter must be attached file. - :: +:: $filename = '/img/photo1.jpg'; $this->email->attach($filename); @@ -286,8 +286,8 @@ $this->email->attach_cid() $this->email->message('photo1'); $this->email->send(); } - - CID for each Email have to be create again to be unique. + +CID for each Email have to be create again to be unique. $this->email->print_debugger() ------------------------------ -- cgit v1.2.3-24-g4f1b From 232ea658e1f31d6c82a9ed9dae1bb3b292b6eb24 Mon Sep 17 00:00:00 2001 From: Petr Heralecky Date: Fri, 10 Jan 2014 15:21:18 +0100 Subject: attach files by absolute url --- system/libraries/Email.php | 20 ++++++++++---------- user_guide_src/source/changelog.rst | 1 + user_guide_src/source/libraries/email.rst | 4 ++++ 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 739b76ccb..71edc3b41 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -710,39 +710,39 @@ class CI_Email { /** * Assign file attachments * - * @param string $filename + * @param string $src can be path, url or buffered content * @param string $disposition = 'attachment' * @param string $newname = NULL * @param string $mime = '' * @return CI_Email */ - public function attach($filename, $disposition = '', $newname = NULL, $mime = '') + public function attach($src, $disposition = '', $newname = NULL, $mime = '') { if ($mime === '') { - if ( ! file_exists($filename)) + if (strpos($src,'http://')!==0 && ! file_exists($src) ) { - $this->_set_error_message('lang:email_attachment_missing', $filename); + $this->_set_error_message('lang:email_attachment_missing', $src); return FALSE; } - if ( ! $fp = fopen($filename, FOPEN_READ)) + if ( ! $fp = @fopen($src, FOPEN_READ)) { - $this->_set_error_message('lang:email_attachment_unreadable', $filename); + $this->_set_error_message('lang:email_attachment_unreadable', $src); return FALSE; } - + $file_content = stream_get_contents($fp); - $mime = $this->_mime_types(pathinfo($filename, PATHINFO_EXTENSION)); + $mime = $this->_mime_types(pathinfo($src, PATHINFO_EXTENSION)); fclose($fp); } else { - $file_content =& $filename; // buffered file + $file_content =& $src; // buffered file } $this->_attachments[] = array( - 'name' => array($filename, $newname), + 'name' => array($src, $newname), 'disposition' => empty($disposition) ? 'attachment' : $disposition, // Can also be 'inline' Not sure if it matters 'type' => $mime, 'content' => chunk_split(base64_encode($file_content)) diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index b112da5b4..cb70627d4 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -334,6 +334,7 @@ Release Date: Not Released - Added a custom filename parameter to ``attach()`` as ``$this->email->attach($filename, $disposition, $newname)``. - Added possibility to send attachment as buffer string in ``attach()`` as ``$this->email->attach($buffer, $disposition, $newname, $mime)``. + - Added possibility attach remote file by absolute url - Added method ``attachment_cid()`` to enable embedding inline attachments into HTML. - Added dsn (delivery status notification) option. - Renamed method ``_set_header()`` to ``set_header()`` and made it public to enable adding custom headers. diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst index 8e3800306..476f1131d 100644 --- a/user_guide_src/source/libraries/email.rst +++ b/user_guide_src/source/libraries/email.rst @@ -259,6 +259,10 @@ otherwise use a custom disposition:: $this->email->attach('image.jpg', 'inline'); +You can use absolute url:: + + $this->email->attach('http://example.com/filename.pdf'); + If you'd like to use a custom file name, you can use the third paramater:: $this->email->attach('filename.pdf', 'attachment', 'report.pdf'); -- cgit v1.2.3-24-g4f1b From ceb03af631c145d0694ef6f72e84517e18b7b092 Mon Sep 17 00:00:00 2001 From: Petr Heralecky Date: Fri, 10 Jan 2014 16:40:54 +0100 Subject: rename src to file --- system/libraries/Email.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 71edc3b41..37a628259 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -710,39 +710,39 @@ class CI_Email { /** * Assign file attachments * - * @param string $src can be path, url or buffered content + * @param string $file can be path, url or buffered content * @param string $disposition = 'attachment' * @param string $newname = NULL * @param string $mime = '' * @return CI_Email */ - public function attach($src, $disposition = '', $newname = NULL, $mime = '') + public function attach($file, $disposition = '', $newname = NULL, $mime = '') { if ($mime === '') { - if (strpos($src,'http://')!==0 && ! file_exists($src) ) + if (strpos($file,'http://')!==0 && ! file_exists($file) ) { - $this->_set_error_message('lang:email_attachment_missing', $src); + $this->_set_error_message('lang:email_attachment_missing', $file); return FALSE; } - if ( ! $fp = @fopen($src, FOPEN_READ)) + if ( ! $fp = @fopen($file, FOPEN_READ)) { - $this->_set_error_message('lang:email_attachment_unreadable', $src); + $this->_set_error_message('lang:email_attachment_unreadable', $file); return FALSE; } $file_content = stream_get_contents($fp); - $mime = $this->_mime_types(pathinfo($src, PATHINFO_EXTENSION)); + $mime = $this->_mime_types(pathinfo($file, PATHINFO_EXTENSION)); fclose($fp); } else { - $file_content =& $src; // buffered file + $file_content =& $file; // buffered file } $this->_attachments[] = array( - 'name' => array($src, $newname), + 'name' => array($file, $newname), 'disposition' => empty($disposition) ? 'attachment' : $disposition, // Can also be 'inline' Not sure if it matters 'type' => $mime, 'content' => chunk_split(base64_encode($file_content)) -- cgit v1.2.3-24-g4f1b From 63f07cbd62ba885f003995dc7ad74bbdb28942c9 Mon Sep 17 00:00:00 2001 From: Petr Heralecky Date: Fri, 10 Jan 2014 16:50:49 +0100 Subject: documentation repairs --- user_guide_src/source/changelog.rst | 2 +- user_guide_src/source/libraries/email.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index cb70627d4..07dee5dbd 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -334,7 +334,7 @@ Release Date: Not Released - Added a custom filename parameter to ``attach()`` as ``$this->email->attach($filename, $disposition, $newname)``. - Added possibility to send attachment as buffer string in ``attach()`` as ``$this->email->attach($buffer, $disposition, $newname, $mime)``. - - Added possibility attach remote file by absolute url + - Added possibility to attach remote files by passing a URL. - Added method ``attachment_cid()`` to enable embedding inline attachments into HTML. - Added dsn (delivery status notification) option. - Renamed method ``_set_header()`` to ``set_header()`` and made it public to enable adding custom headers. diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst index 476f1131d..86f440a74 100644 --- a/user_guide_src/source/libraries/email.rst +++ b/user_guide_src/source/libraries/email.rst @@ -259,7 +259,7 @@ otherwise use a custom disposition:: $this->email->attach('image.jpg', 'inline'); -You can use absolute url:: +You can use URL:: $this->email->attach('http://example.com/filename.pdf'); -- cgit v1.2.3-24-g4f1b From 1dbdf72c555d0ea4d7c526e56e79472331eedc2a Mon Sep 17 00:00:00 2001 From: Petr Heralecky Date: Fri, 10 Jan 2014 16:54:51 +0100 Subject: condition repair and comments --- system/libraries/Email.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 37a628259..7e80ffbca 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -710,7 +710,7 @@ class CI_Email { /** * Assign file attachments * - * @param string $file can be path, url or buffered content + * @param string $file Can be local path, URL or buffered content * @param string $disposition = 'attachment' * @param string $newname = NULL * @param string $mime = '' @@ -720,7 +720,7 @@ class CI_Email { { if ($mime === '') { - if (strpos($file,'http://')!==0 && ! file_exists($file) ) + if (strpos($file, '://') === FALSE && ! file_exists($file)) { $this->_set_error_message('lang:email_attachment_missing', $file); return FALSE; @@ -731,7 +731,7 @@ class CI_Email { $this->_set_error_message('lang:email_attachment_unreadable', $file); return FALSE; } - + $file_content = stream_get_contents($fp); $mime = $this->_mime_types(pathinfo($file, PATHINFO_EXTENSION)); fclose($fp); -- cgit v1.2.3-24-g4f1b From 4e6c5281a3258b3ff530a43580d1b8dc8e34dd59 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Fri, 10 Jan 2014 19:29:49 +0200 Subject: Finally get rid of the CI_Router::_set_overrides() calls --- system/core/CodeIgniter.php | 6 ---- system/core/Router.php | 55 ++++++++++++++++--------------------- user_guide_src/source/changelog.rst | 1 + 3 files changed, 24 insertions(+), 38 deletions(-) diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php index 45c3485bf..cc12f149f 100644 --- a/system/core/CodeIgniter.php +++ b/system/core/CodeIgniter.php @@ -163,12 +163,6 @@ defined('BASEPATH') OR exit('No direct script access allowed'); */ $RTR =& load_class('Router', 'core'); - // Set any routing overrides that may exist in the main index file - if (isset($routing)) - { - $RTR->_set_overrides($routing); - } - /* * ------------------------------------------------------ * Instantiate the output class diff --git a/system/core/Router.php b/system/core/Router.php index d467d60fd..cb44a3ce9 100644 --- a/system/core/Router.php +++ b/system/core/Router.php @@ -102,9 +102,32 @@ class CI_Router { */ public function __construct() { + global $routing; + $this->config =& load_class('Config', 'core'); $this->uri =& load_class('URI', 'core'); $this->_set_routing(); + + // Set any routing overrides that may exist in the main index file + if (isset($routing) && is_array($routing)) + { + if (isset($routing['directory'])) + { + $this->set_directory($routing['directory']); + } + + if ( ! empty($routing['controller'])) + { + $this->set_class($routing['controller']); + } + + if (isset($routing['function'])) + { + $routing['function'] = empty($routing['function']) ? 'index' : $routing['function']; + $this->set_method($routing['function']); + } + } + log_message('debug', 'Router Class Initialized'); } @@ -519,38 +542,6 @@ class CI_Router { return $this->directory; } - // -------------------------------------------------------------------- - - /** - * Set controller overrides - * - * @param array $routing Route overrides - * @return void - */ - public function _set_overrides($routing) - { - if ( ! is_array($routing)) - { - return; - } - - if (isset($routing['directory'])) - { - $this->set_directory($routing['directory']); - } - - if ( ! empty($routing['controller'])) - { - $this->set_class($routing['controller']); - } - - if (isset($routing['function'])) - { - $routing['function'] = empty($routing['function']) ? 'index' : $routing['function']; - $this->set_method($routing['function']); - } - } - } /* End of file Router.php */ diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index b112da5b4..5da707086 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -461,6 +461,7 @@ Release Date: Not Released - Added possibility to route requests using callbacks. - Added a new reserved route (*translate_uri_dashes*) to allow usage of dashes in the controller and method URI segments. - Deprecated methods ``fetch_directory()``, ``fetch_class()`` and ``fetch_method()`` in favor of their respective public properties. + - Removed method ``_set_overrides()`` and moved its logic to the class constructor. - :doc:`Language Library ` changes include: -- cgit v1.2.3-24-g4f1b From 0c234d06d24294b57c3c25474e6486a22324e59c Mon Sep 17 00:00:00 2001 From: Dionysis Arvanitis Date: Sat, 11 Jan 2014 17:41:23 +0200 Subject: IE11 User Agent support added --- application/config/user_agents.php | 1 + 1 file changed, 1 insertion(+) diff --git a/application/config/user_agents.php b/application/config/user_agents.php index 2af70bf9c..a5d132904 100644 --- a/application/config/user_agents.php +++ b/application/config/user_agents.php @@ -90,6 +90,7 @@ $browsers = array( 'Opera' => 'Opera', 'MSIE' => 'Internet Explorer', 'Internet Explorer' => 'Internet Explorer', + 'rv' => 'Internet Explorer', 'Shiira' => 'Shiira', 'Firefox' => 'Firefox', 'Chimera' => 'Chimera', -- cgit v1.2.3-24-g4f1b From 9765472d1388c631ad57f4bd0dd4dd424f79e5e0 Mon Sep 17 00:00:00 2001 From: Fred Emmott Date: Mon, 13 Jan 2014 14:48:22 -0800 Subject: Don't throw in mock autoloader This behavior doesn't appear to be used at all. This fixes HHVM compatibility: HHVM optimizes class_exists() to a dedicated bytecode - as it's not a function call, it doesn't show up in the backtrace. 100% of the tests pass with this change. --- tests/mocks/autoloader.php | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/tests/mocks/autoloader.php b/tests/mocks/autoloader.php index 3d216da1f..cc0a2e2f7 100644 --- a/tests/mocks/autoloader.php +++ b/tests/mocks/autoloader.php @@ -89,21 +89,7 @@ function autoload($class) if ( ! file_exists($file)) { - $trace = debug_backtrace(); - - if ($trace[2]['function'] === 'class_exists' OR $trace[2]['function'] === 'file_exists') - { - // If the autoload call came from `class_exists` or `file_exists`, - // we skipped and return FALSE - return FALSE; - } - elseif (($autoloader = spl_autoload_functions()) && end($autoloader) !== __FUNCTION__) - { - // If there was other custom autoloader, passed away - return FALSE; - } - - throw new InvalidArgumentException("Unable to load {$class}."); + return FALSE; } include_once($file); -- cgit v1.2.3-24-g4f1b From c75cb6981076dbe88db55250e6e5c9c7fbbb84e3 Mon Sep 17 00:00:00 2001 From: Fred Emmott Date: Tue, 14 Jan 2014 10:29:36 -0800 Subject: Enable HHVM on travis-ci --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index fa9d5e563..bc1361209 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ php: - 5.3 - 5.4 - 5.5 + - hhvm env: - DB=mysql -- cgit v1.2.3-24-g4f1b From 2e8ee6e5c4a4355d4330918b4a6a362e92956eae Mon Sep 17 00:00:00 2001 From: Fred Emmott Date: Tue, 14 Jan 2014 11:12:35 -0800 Subject: Dont break the build if tests only fail on HHVM --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index bc1361209..27fe3c670 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,10 @@ before_script: script: phpunit --coverage-text --configuration tests/travis/$DB.phpunit.xml +matrix: + allow_failures: + - php: hhvm + branches: only: - develop -- cgit v1.2.3-24-g4f1b From 3d215207ceff44193e3c1888b868fc3f691718c0 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Wed, 15 Jan 2014 11:08:47 +0200 Subject: Fix incorrect checks for the fwrite() return value ! fwrite() could trigger false-positives as it is possible for it to return 0 instead of boolean FALSE. (issue #2822) Also removed an unnecessary log level check that caused an extra space to be inserted for the INFO level. (proposed in PR #2821) --- system/core/Log.php | 2 +- system/libraries/Email.php | 2 +- system/libraries/Xmlrpc.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/system/core/Log.php b/system/core/Log.php index b2327b8f0..ff3c63568 100644 --- a/system/core/Log.php +++ b/system/core/Log.php @@ -175,7 +175,7 @@ class CI_Log { return FALSE; } - $message .= $level.' '.($level === 'INFO' ? ' -' : '-').' '.date($this->_date_fmt).' --> '.$msg."\n"; + $message .= $level.' - '.date($this->_date_fmt).' --> '.$msg."\n"; flock($fp, LOCK_EX); fwrite($fp, $message); diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 7e80ffbca..9487ad486 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -2097,7 +2097,7 @@ class CI_Email { */ protected function _send_data($data) { - if ( ! fwrite($this->_smtp_connect, $data.$this->newline)) + if (fwrite($this->_smtp_connect, $data.$this->newline) === FALSE) { $this->_set_error_message('lang:email_smtp_data_failure', $data); return FALSE; diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php index 2fd12599e..1f93e6981 100644 --- a/system/libraries/Xmlrpc.php +++ b/system/libraries/Xmlrpc.php @@ -724,7 +724,7 @@ class XML_RPC_Client extends CI_Xmlrpc .'Content-Length: '.strlen($msg->payload).$r.$r .$msg->payload; - if ( ! fwrite($fp, $op, strlen($op))) + if (fwrite($fp, $op, strlen($op)) === FALSE) { error_log($this->xmlrpcstr['http_error']); return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']); -- cgit v1.2.3-24-g4f1b From de14aa5a29b1b122bfd536f979dfda7f2fd9f53d Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Wed, 15 Jan 2014 15:51:08 +0200 Subject: CI_URI changes related to the 'permitted_uri_chars' setting - Initialize and cache the value in the class constructor instead of searching for it every time - Removed the preg_quote() call from _filter_uri() to allow more fine-tuning from configuration - Renamed _filter_uri() to filter_uri() - it was public anyway and using it cannot break anything Related: issue #2799 --- application/config/config.php | 9 ++++++--- system/core/Router.php | 6 +++--- system/core/URI.php | 35 +++++++++++++++++++++++------------ tests/codeigniter/core/URI_test.php | 15 ++++++--------- tests/mocks/core/uri.php | 15 +++++++++++++-- user_guide_src/source/changelog.rst | 1 + 6 files changed, 52 insertions(+), 29 deletions(-) diff --git a/application/config/config.php b/application/config/config.php index cd2ca479b..5240f6c26 100644 --- a/application/config/config.php +++ b/application/config/config.php @@ -141,15 +141,18 @@ $config['subclass_prefix'] = 'MY_'; | Allowed URL Characters |-------------------------------------------------------------------------- | -| This lets you specify with a regular expression which characters are permitted -| within your URLs. When someone tries to submit a URL with disallowed -| characters they will get a warning message. +| This lets you specify which characters are permitted within your URLs. +| When someone tries to submit a URL with disallowed characters they will +| get a warning message. | | As a security measure you are STRONGLY encouraged to restrict URLs to | as few characters as possible. By default only these are allowed: a-z 0-9~%.:_- | | Leave blank to allow all characters -- but only if you are insane. | +| The configured value is actually a regular expression character group +| and it will be executed as: ! preg_match('/^[]+$/i +| | DO NOT CHANGE THIS UNLESS YOU FULLY UNDERSTAND THE REPERCUSSIONS!! | */ diff --git a/system/core/Router.php b/system/core/Router.php index cb44a3ce9..71530ff07 100644 --- a/system/core/Router.php +++ b/system/core/Router.php @@ -154,16 +154,16 @@ class CI_Router { { if (isset($_GET[$this->config->item('directory_trigger')]) && is_string($_GET[$this->config->item('directory_trigger')])) { - $this->set_directory(trim($this->uri->_filter_uri($_GET[$this->config->item('directory_trigger')]))); + $this->set_directory(trim($this->uri->filter_uri($_GET[$this->config->item('directory_trigger')]))); $segments[] = $this->directory; } - $this->set_class(trim($this->uri->_filter_uri($_GET[$this->config->item('controller_trigger')]))); + $this->set_class(trim($this->uri->filter_uri($_GET[$this->config->item('controller_trigger')]))); $segments[] = $this->class; if ( ! empty($_GET[$this->config->item('function_trigger')]) && is_string($_GET[$this->config->item('function_trigger')])) { - $this->set_method(trim($this->uri->_filter_uri($_GET[$this->config->item('function_trigger')]))); + $this->set_method(trim($this->uri->filter_uri($_GET[$this->config->item('function_trigger')]))); $segments[] = $this->method; } } diff --git a/system/core/URI.php b/system/core/URI.php index 5e4c80a00..3d6d202c0 100644 --- a/system/core/URI.php +++ b/system/core/URI.php @@ -69,6 +69,15 @@ class CI_URI { */ public $rsegments = array(); + /** + * Permitted URI chars + * + * PCRE character group allowed in URI segments + * + * @var string + */ + protected $_permitted_uri_chars; + /** * Class constructor * @@ -81,6 +90,12 @@ class CI_URI { public function __construct() { $this->config =& load_class('Config', 'core'); + + if ($this->config->item('enable_query_strings') !== TRUE OR is_cli()) + { + $this->_permitted_uri_chars = $this->config->item('permitted_uri_chars'); + } + log_message('debug', 'URI Class Initialized'); } @@ -303,23 +318,19 @@ class CI_URI { * @param string $str * @return string */ - public function _filter_uri($str) + public function filter_uri($str) { - if ($str !== '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') === FALSE) + if ( ! empty($str) && ! empty($this->_permitted_uri_chars) && ! preg_match('/^['.$this->_permitted_uri_chars.']+$/i', $str)) { - // preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards - // compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern - if ( ! preg_match('|^['.str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-')).']+$|i', $str)) - { - show_error('The URI you submitted has disallowed characters.', 400); - } + show_error('The URI you submitted has disallowed characters.', 400); } // Convert programatic characters to entities and return return str_replace( - array('$', '(', ')', '%28', '%29'), // Bad - array('$', '(', ')', '(', ')'), // Good - $str); + array('$', '(', ')', '%28', '%29'), // Bad + array('$', '(', ')', '(', ')'), // Good + $str + ); } // -------------------------------------------------------------------- @@ -365,7 +376,7 @@ class CI_URI { foreach (explode('/', preg_replace('|/*(.+?)/*$|', '\\1', $this->uri_string)) as $val) { // Filter segments for security - $val = trim($this->_filter_uri($val)); + $val = trim($this->filter_uri($val)); if ($val !== '') { diff --git a/tests/codeigniter/core/URI_test.php b/tests/codeigniter/core/URI_test.php index 7fa0e6265..99d79bbd2 100644 --- a/tests/codeigniter/core/URI_test.php +++ b/tests/codeigniter/core/URI_test.php @@ -112,11 +112,10 @@ class URI_test extends CI_TestCase { public function test_filter_uri() { - $this->uri->config->set_item('enable_query_strings', FALSE); - $this->uri->config->set_item('permitted_uri_chars', 'a-z 0-9~%.:_\-'); + $this->uri->_set_permitted_uri_chars('a-z 0-9~%.:_\-'); $str_in = 'abc01239~%.:_-'; - $str = $this->uri->_filter_uri($str_in); + $str = $this->uri->filter_uri($str_in); $this->assertEquals($str, $str_in); } @@ -126,11 +125,9 @@ class URI_test extends CI_TestCase { public function test_filter_uri_escaping() { // ensure escaping even if dodgey characters are permitted + $this->uri->_set_permitted_uri_chars('a-z 0-9~%.:_\-()$'); - $this->uri->config->set_item('enable_query_strings', FALSE); - $this->uri->config->set_item('permitted_uri_chars', 'a-z 0-9~%.:_\-()$'); - - $str = $this->uri->_filter_uri('$destroy_app(foo)'); + $str = $this->uri->filter_uri('$destroy_app(foo)'); $this->assertEquals($str, '$destroy_app(foo)'); } @@ -142,8 +139,8 @@ class URI_test extends CI_TestCase { $this->setExpectedException('RuntimeException'); $this->uri->config->set_item('enable_query_strings', FALSE); - $this->uri->config->set_item('permitted_uri_chars', 'a-z 0-9~%.:_\-'); - $this->uri->_filter_uri('$this()'); + $this->uri->_set_permitted_uri_chars('a-z 0-9~%.:_\-'); + $this->uri->filter_uri('$this()'); } // -------------------------------------------------------------------- diff --git a/tests/mocks/core/uri.php b/tests/mocks/core/uri.php index 11078587b..96ec5afa1 100644 --- a/tests/mocks/core/uri.php +++ b/tests/mocks/core/uri.php @@ -10,12 +10,23 @@ class Mock_Core_URI extends CI_URI { // set predictable config values $test->ci_set_config(array( 'index_page' => 'index.php', - 'base_url' => 'http://example.com/', - 'subclass_prefix' => 'MY_' + 'base_url' => 'http://example.com/', + 'subclass_prefix' => 'MY_', + 'enable_query_strings' => FALSE, + 'permitted_uri_chars' => 'a-z 0-9~%.:_\-' )); $this->config = new $cls; + if ($this->config->item('enable_query_strings') !== TRUE OR is_cli()) + { + $this->_permitted_uri_chars = $this->config->item('permitted_uri_chars'); + } + } + + public function _set_permitted_uri_chars($value) + { + $this->_permitted_uri_chars = $value; } } \ No newline at end of file diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 43e7be41f..77378521b 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -391,6 +391,7 @@ Release Date: Not Released - :doc:`URI Library ` changes include: + - Renamed method ``_filter_uri()`` to ``filter_uri()`` and removed the ``preg_quote()`` call from it. - Changed private methods to protected so that MY_URI can override them. - Renamed internal method ``_parse_cli_args()`` to ``_parse_argv()``. - Renamed internal method ``_detect_uri()`` to ``_parse_request_uri()``. -- cgit v1.2.3-24-g4f1b From 2cdd50e98373327c72f6a38ba1016abafe496018 Mon Sep 17 00:00:00 2001 From: Dionysis Arvanitis Date: Wed, 15 Jan 2014 16:24:15 +0200 Subject: Trident prefix added to avoid potential false positives. --- application/config/user_agents.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/application/config/user_agents.php b/application/config/user_agents.php index a5d132904..819e42b69 100644 --- a/application/config/user_agents.php +++ b/application/config/user_agents.php @@ -90,7 +90,7 @@ $browsers = array( 'Opera' => 'Opera', 'MSIE' => 'Internet Explorer', 'Internet Explorer' => 'Internet Explorer', - 'rv' => 'Internet Explorer', + 'Trident.* rv' => 'Internet Explorer', 'Shiira' => 'Shiira', 'Firefox' => 'Firefox', 'Chimera' => 'Chimera', -- cgit v1.2.3-24-g4f1b From d8b1ad31cf7ee205ddf3cf396b1d1bfa45af49fa Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Wed, 15 Jan 2014 17:42:52 +0200 Subject: Fix #2822: Incorrect usage of fwrite() We only used to check (and not always) if the return value of fwrite() is boolean FALSE, while it is possible that the otherwise returned bytecount is less than the length of data that we're trying to write. This allowed incomplete writes over network streams and possibly a few other edge cases. --- system/core/Log.php | 12 ++++++++-- system/core/Output.php | 44 ++++++++++++++++++++++++++----------- system/helpers/file_helper.php | 12 ++++++++-- system/libraries/Email.php | 11 +++++++++- system/libraries/Xmlrpc.php | 10 ++++++++- system/libraries/Zip.php | 12 ++++++++-- user_guide_src/source/changelog.rst | 1 + 7 files changed, 81 insertions(+), 21 deletions(-) diff --git a/system/core/Log.php b/system/core/Log.php index ff3c63568..63fef2088 100644 --- a/system/core/Log.php +++ b/system/core/Log.php @@ -178,7 +178,15 @@ class CI_Log { $message .= $level.' - '.date($this->_date_fmt).' --> '.$msg."\n"; flock($fp, LOCK_EX); - fwrite($fp, $message); + + for ($written = 0, $length = strlen($message); $written < $length; $written += $result) + { + if (($result = fwrite($fp, substr($message, $written))) === FALSE) + { + break; + } + } + flock($fp, LOCK_UN); fclose($fp); @@ -187,7 +195,7 @@ class CI_Log { @chmod($filepath, FILE_WRITE_MODE); } - return TRUE; + return is_int($result); } } diff --git a/system/core/Output.php b/system/core/Output.php index 10332f0d8..a7680b3d0 100644 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -542,17 +542,26 @@ class CI_Output { return; } - $expire = time() + ($this->cache_expiration * 60); - - // Put together our serialized info. - $cache_info = serialize(array( - 'expire' => $expire, - 'headers' => $this->headers - )); - if (flock($fp, LOCK_EX)) { - fwrite($fp, $cache_info.'ENDCI--->'.$output); + $expire = time() + ($this->cache_expiration * 60); + + // Put together our serialized info. + $cache_info = serialize(array( + 'expire' => $expire, + 'headers' => $this->headers + )); + + $output = $cache_info.'ENDCI--->'.$output; + + for ($written = 0, $length = strlen($output); $written < $length; $written += $result) + { + if (($result = fwrite($fp, substr($output, $written))) === FALSE) + { + break; + } + } + flock($fp, LOCK_UN); } else @@ -560,13 +569,22 @@ class CI_Output { log_message('error', 'Unable to secure a file lock for file at: '.$cache_path); return; } + fclose($fp); - @chmod($cache_path, FILE_WRITE_MODE); - log_message('debug', 'Cache file written: '.$cache_path); + if (is_int($result)) + { + @chmod($cache_path, FILE_WRITE_MODE); + log_message('debug', 'Cache file written: '.$cache_path); - // Send HTTP cache-control headers to browser to match file cache settings. - $this->set_cache_header($_SERVER['REQUEST_TIME'], $expire); + // Send HTTP cache-control headers to browser to match file cache settings. + $this->set_cache_header($_SERVER['REQUEST_TIME'], $expire); + } + else + { + @unlink($cache_path); + log_message('error', 'Unable to write the complete cache content at: '.$cache_path); + } } // -------------------------------------------------------------------- diff --git a/system/helpers/file_helper.php b/system/helpers/file_helper.php index 4b45a62d0..0587740b1 100644 --- a/system/helpers/file_helper.php +++ b/system/helpers/file_helper.php @@ -79,11 +79,19 @@ if ( ! function_exists('write_file')) } flock($fp, LOCK_EX); - fwrite($fp, $data); + + for ($written = 0, $length = strlen($data); $written < $length; $written += $result) + { + if (($result = fwrite($fp, substr($data, $written))) === FALSE) + { + break; + } + } + flock($fp, LOCK_UN); fclose($fp); - return TRUE; + return is_int($result); } } diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 9487ad486..f4efff882 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -2097,7 +2097,16 @@ class CI_Email { */ protected function _send_data($data) { - if (fwrite($this->_smtp_connect, $data.$this->newline) === FALSE) + $data .= $this->newline; + for ($written = 0, $length = strlen($data); $written < $length; $written += $result) + { + if (($result = fwrite($this->_smtp_connect, substr($data, $written))) === FALSE) + { + break; + } + } + + if ($result === FALSE) { $this->_set_error_message('lang:email_smtp_data_failure', $data); return FALSE; diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php index 1f93e6981..ab907e706 100644 --- a/system/libraries/Xmlrpc.php +++ b/system/libraries/Xmlrpc.php @@ -724,7 +724,15 @@ class XML_RPC_Client extends CI_Xmlrpc .'Content-Length: '.strlen($msg->payload).$r.$r .$msg->payload; - if (fwrite($fp, $op, strlen($op)) === FALSE) + for ($written = 0, $length = strlen($op); $written < $length; $written += $result) + { + if (($result = fwrite($fp, substr($op, $written))) === FALSE) + { + break; + } + } + + if ($result === FALSE) { error_log($this->xmlrpcstr['http_error']); return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']); diff --git a/system/libraries/Zip.php b/system/libraries/Zip.php index 250ee02cd..b10b0bb0f 100644 --- a/system/libraries/Zip.php +++ b/system/libraries/Zip.php @@ -403,11 +403,19 @@ class CI_Zip { } flock($fp, LOCK_EX); - fwrite($fp, $this->get_zip()); + + for ($written = 0, $data = $this->get_zip(), $length = strlen($data); $written < $length; $written += $result) + { + if (($result = fwrite($fp, substr($data, $written))) === FALSE) + { + break; + } + } + flock($fp, LOCK_UN); fclose($fp); - return TRUE; + return is_int($result); } // -------------------------------------------------------------------- diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst index 77378521b..a1dc3c1d1 100644 --- a/user_guide_src/source/changelog.rst +++ b/user_guide_src/source/changelog.rst @@ -669,6 +669,7 @@ Bug fixes for 3.0 - Fixed a bug (#346) - with ``$config['global_xss_filtering']`` turned on, the ``$_GET``, ``$_POST``, ``$_COOKIE`` and ``$_SERVER`` superglobals were overwritten during initialization time, resulting in XSS filtering being either performed twice or there was no possible way to get the original data, even though options for this do exist. - Fixed an edge case (#555) - incorrect browser version was reported for Opera 10+ due to a non-standard user-agent string. - Fixed a bug (#133) - :doc:`Text Helper ` :func:`ascii_to_entities()` stripped the last character if it happens to be in the extended ASCII group. +- Fixed a bug (#2822) - ``fwrite()`` was used incorrectly throughout the whole framework, allowing incomplete writes when writing to a network stream and possibly a few other edge cases. Version 2.1.4 ============= -- cgit v1.2.3-24-g4f1b