make sure that caldav attachments filenames are decoded
authorPhilipp Schüle <p.schuele@metaways.de>
Mon, 8 Dec 2014 11:15:40 +0000 (12:15 +0100)
committerPhilipp Schüle <p.schuele@metaways.de>
Thu, 11 Dec 2014 10:14:29 +0000 (11:14 +0100)
* always (raw)urldecode attachment filenames before saving them in Tine
2.0 vfs
* adjusts regex for utf-8 dispositions

Change-Id: I894e53f02792c52b965133d03a39747ce4d7d4c0
Reviewed-on: http://gerrit.tine20.com/customers/1424
Tested-by: Jenkins CI (http://ci.tine20.com/)
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
tests/tine20/Calendar/Frontend/CalDAV/PluginManagedAttachmentsTest.php
tine20/Calendar/Convert/Event/VCalendar/Abstract.php
tine20/Calendar/Frontend/CalDAV/PluginManagedAttachments.php

index 2d29b4b..3755328 100644 (file)
@@ -104,13 +104,13 @@ class Calendar_Frontend_CalDAV_PluginManagedAttachmentsTest extends TestCase
     /**
      * test testAddAttachment 
      */
-    public function testAddAttachment()
+    public function testAddAttachment($disposition = 'attachment;filename="agenda.txt"', $filename = 'agenda.txt')
     {
         $event = $this->calDAVTests->testCreateRepeatingEventAndPutExdate();
         
         $request = new Sabre\HTTP\Request(array(
             'HTTP_CONTENT_TYPE' => 'text/plain',
-            'HTTP_CONTENT_DISPOSITION' => 'attachment;filename="agenda.txt"',
+            'HTTP_CONTENT_DISPOSITION' => $disposition,
             'REQUEST_METHOD' => 'POST',
             'REQUEST_URI'    => '/calendars/' . 
                 Tinebase_Core::getUser()->contact_id . '/'. 
@@ -127,7 +127,6 @@ class Calendar_Frontend_CalDAV_PluginManagedAttachmentsTest extends TestCase
         $this->server->exec();
         
         $vcalendar = stream_get_contents($this->response->body);
-//         echo $vcalendar;
         
         $baseAttachments = Tinebase_FileSystem_RecordAttachments::getInstance()
             ->getRecordAttachments($event->getRecord());
@@ -137,9 +136,16 @@ class Calendar_Frontend_CalDAV_PluginManagedAttachmentsTest extends TestCase
         $this->assertEquals('HTTP/1.1 201 Created', $this->response->status);
         $this->assertContains('ATTACH;MANAGED-ID='. sha1($agenda), $vcalendar, $vcalendar);
         $this->assertEquals(1, $baseAttachments->count());
-        $this->assertEquals('agenda.txt', $baseAttachments[0]->name);
+        $this->assertEquals($filename, $baseAttachments[0]->name);
         $this->assertEquals(1, $exdateAttachments->count());
-        $this->assertEquals('agenda.txt', $exdateAttachments[0]->name);
+        $this->assertEquals($filename, $exdateAttachments[0]->name);
+    }
+    
+    public function testAddAttachmentWithUmlauts()
+    {
+        //$filename = 'Reservierungsbestätigung : OTTER.txt';
+        $disposition = "filename=\"Reservierungsbesta?tigung _ OTTER.txt\";filename*=utf-8''Reservierungsbesta%CC%88tigung%20_%20OTTER.txt";
+        $this->testAddAttachment($disposition, 'Reservierungsbestätigung _ OTTER.txt');
     }
     
     /**
index df129f2..5f8510c 100644 (file)
@@ -979,7 +979,7 @@ class Calendar_Convert_Event_VCalendar_Abstract extends Tinebase_Convert_VCalend
                                 Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' attachment found that could not be imported due to missing managed id');
                     }
                     
-                    if($readFromURL) {
+                    if ($readFromURL) {
                         if (preg_match('#^(https?://)(.*)$#', str_replace(array("\n","\r"), '', $url), $matches)) {
                             // we are client and found an external hosted attachment that we need to import
                             $user = Tinebase_Core::getUser();
@@ -993,7 +993,7 @@ class Calendar_Convert_Event_VCalendar_Abstract extends Tinebase_Convert_VCalend
                                 
                                 $stream = fopen($url, 'r');
                                 $attachment = new Tinebase_Model_Tree_Node(array(
-                                    'name'         => $name,
+                                    'name'         => rawurldecode($name),
                                     'type'         => Tinebase_Model_Tree_Node::TYPE_FILE,
                                     'contenttype'  => (string) $property['FMTTYPE'],
                                     'tempFile'     => $stream,
index e37d22b..f6a54e2 100644 (file)
@@ -143,12 +143,21 @@ class Calendar_Frontend_CalDAV_PluginManagedAttachments extends \Sabre\DAV\Serve
         $name = 'NO NAME';
         $disposition = $this->server->httpRequest->getHeader('Content-Disposition');
         $contentType = $this->server->httpRequest->getHeader('Content-Type');
+        
+        if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG))
+             Tinebase_Core::getLogger()->DEBUG(__METHOD__ . '::' . __LINE__ .
+            " disposition/contentType: " . $disposition . ' / '. $contentType);
+        
         $managedId = isset($getVars['managed-id']) ? $getVars['managed-id'] : NULL;
         $rid = $this->getRecurranceIds($getVars);
         list($contentType) = explode(';', $contentType);
-        if (preg_match('/filename=(.*)[ ;]{0,1}/', $disposition, $matches)) {
-            $name = trim($matches[1], " \t\n\r\0\x0B\"'");
+        if (preg_match("/filename\*=utf-8''(.*)/", $disposition, $matches)) {
+            // handle utf-8 dispositions (like this: filename=\"Reservierungsbesta?tigung _ OTTER.txt\";filename*=utf-8''Reservierungsbesta%CC%88tigung%20_%20OTTER.txt)
+            $name = $matches[1];
+        } else if (preg_match('/filename=(.*)[ ;]{0,1}/', $disposition, $matches)) {
+            $name = $matches[1];
         }
+        $name = trim($name, " \t\n\r\0\x0B\"'");
         
         // NOTE inputstream can not be rewinded
         $inputStream = fopen('php://temp','r+');
@@ -161,7 +170,7 @@ class Calendar_Frontend_CalDAV_PluginManagedAttachments extends \Sabre\DAV\Serve
             case 'attachment-add':
                 
                 $attachment = new Tinebase_Model_Tree_Node(array(
-                    'name'         => $name,
+                    'name'         => rawurldecode($name),
                     'type'         => Tinebase_Model_Tree_Node::TYPE_FILE,
                     'contenttype'  => $contentType,
                     'hash'         => $attachmentId,