Merge branch '2015.11' into 2015.11-develop
authorPhilipp Schüle <p.schuele@metaways.de>
Wed, 26 Oct 2016 12:46:32 +0000 (14:46 +0200)
committerPhilipp Schüle <p.schuele@metaways.de>
Wed, 26 Oct 2016 12:46:32 +0000 (14:46 +0200)
1  2 
tests/tine20/Felamimail/Frontend/JsonTest.php
tine20/Felamimail/js/sieve/RulesGridPanel.js
tine20/Tinebase/Container.php
tine20/Tinebase/Model/Filter/FilterGroup.php

@@@ -570,13 -570,12 +570,13 @@@ class Felamimail_Frontend_JsonTest exte
          $messageToSend = $this->_getMessageData($this->_account->email);
          $invalidEmail = 'invaliduser@' . $this->_mailDomain;
          $messageToSend['to'] = array($invalidEmail);
 +        $translation = Tinebase_Translation::getTranslation('Felamimail');
          
          try {
              $returned = $this->_json->saveMessage($messageToSend);
              $this->fail('Tinebase_Exception_SystemGeneric expected');
          } catch (Tinebase_Exception_SystemGeneric $tesg) {
 -            $this->assertContains('550 5.1.1 <' . $invalidEmail . '>: Recipient address rejected', $tesg->getMessage(),
 +            $this->assertContains('<' . $invalidEmail . '>: ' . $translation->_('Recipient address rejected'), $tesg->getMessage(),
                  'exception message did not match: ' . $tesg->getMessage());
          }
      }
          $fullMessage = $this->_json->getMessage($message['id']);
          $this->assertTrue(empty($fullMessage->preparedParts));
      }
 -    
 +
 +    /**
 +     * testSendMailveopeAPIMessage
 +     *
 +     * - envolpe amored message into PGP MIME structure
 +     */
 +    public function testSendMailveopeAPIMessage()
 +    {
 +        $subject = 'testSendMailveopeAPIMessage';
 +        $messageData = $this->_getMessageData('', $subject);
 +        $messageData['body'] = '-----BEGIN PGP MESSAGE-----
 +Version: Mailvelope v1.3.3
 +Comment: https://www.mailvelope.com
 +
 +wcFMA/0LJF28pDbGAQ//YgtsmEZN+pgIJiBDb7iYwPEOchDRIEjGOx543KF6
 +5YigW9p39pfcJgvGfT8x9cUIrYGxyw5idPSOEftYXyjjGaOYGaKpRSR4hI83
 +OcJSlEHKq72xhg04mNpCjjJ8dLBstPcQ7tDtsA8Nfb4PwkUYB9IhIBnARg+n
 +NvrN8mSA2UnY9ElFCvf30sar8EuM5swAjbk64C8TIypMy/Bg4T93zRdxwik6
 +7BCcbOpm/2PTsiVYBOTcU4+XdG5eyTENXH58M6UTxTD4/g7Qi5PjN+PxyXqf
 +v2Y1k9F49Y1egf2QJ2r4PX0EWS8SaynSHiIoBsp1xb07nLwZwCdMPG1QNPpF
 +l2FqlS4dEuQTdkv0deMvd7gtiNynRTAVcJc1ZC6RuWJ+EH2jA49XWkn14eRC
 +e5jMtPPudkhubnN9Je5lwatGKbJGyuXh+IaM0E0WQMZ3dm8+ST1l4WpVuGbw
 +KozLUiTRJP9UoxWOcwpQOnzcSlc4rHmWdtF0y3usM9u9GPREqpNUWkEyEEuv
 +XdZE7rKKj22dJHLCXxAQEh3m29Y2WVaq50YbtEZ+SwwbrHhxP4+FJEru+byh
 +fiZ47sVW2KvYGJPvbFoSZHiSvMecxDg8BVwe+naZXww/Rwa/TlaX4bYyzpUG
 +KeJUAzWEfFpJ0+yAvMGQEC7psIJ9NCx149C4ujiQmajSwhUB3XANcmCGB0wm
 +JjcqC4AHvc7/t4MrQZm0F/W+nrMmNqbZk+gylVrPs9rFEqu7wbjwTmsFA3sS
 +LkenvQIxBali6uzCR+nd09REqcYirG9cLti39DW048lhhG/ml+gAxxNEaSpG
 +NbIoV/3w8n7sAIM1fjuHne8bX0gWG43TTjU8MwSMryG7tCOG5u+Cebh6TAoY
 +NzbX2dpDhOYq5zXdCgKU4P3eh0csSs4UrqFT3TdAxIGrQJ7KrXvB6+N8gRZo
 +FcUaR+zrRPJjPUZfi46ecP5SG/tM5ea1hqvkwEnEpqjLmCUxqB+rfxx46USX
 +hMZd2ukUv6kEKv3EUDsRYu1SlDLhDLhWNx8RJae5XkMR+eUUMyNNVwbeMQbB
 +VAcMcaPITTk84sH7XElr9eF6sCUN4V79OSBRPGY/aNGrcwcoDSD4Hwu+Lw9w
 +Q+1n8EQ66gAkbJzCNd5GaYMZR9echkBaD/rdWDS3ktcrMehra+h44MTQONV9
 +8W+RI+IT5jaIXtB4jePmGjsJjbC9aEhTRBRkUnPA7phgknc52dD74AY/6lzK
 +yd4uZ6S3vhurJW0Vt4iBWJzhFNiSODh5PzteeNzCVAkGMsQvy1IHk0d3uzcE
 +0tEuSh8fZOFGB4fvMx9Mk8oAU92wfj4J7AVpSo5oRdxMqAXfaYKqfr2Gn++q
 +E5LClhVIBbFXclCoe0RYNz4wtxjeeYbP40Bq5g0JvPutD/dBMp8hz8Qt+yyG
 +d8X4/KmQIXyFZ8aP17GMckE5GVVvY9y89eWnWuTUJdwM540hB/EJNeHHTE5y
 +N2FSLGcmNkvE+3H7BczQ2ZI1SZDhof+umbUst0qoQW+hHmY3CSma48yGAVox
 +52u2t7hosHCfpf631Ve/6fcICo8vJ2Qfufu2BGIMlSfx4WzUuaMQBynuxFSa
 +IbVx8ZTO7dJRKrg72aFmWTf0uNla7vicAhpiLWobyNYcZbIjrAGDfg==
 +=BaAn
 +-----END PGP MESSAGE-----';
 +
 +        $this->_foldersToClear[] = 'INBOX';
 +        $this->_json->saveMessage($messageData);
 +
 +        $message = $this->_searchForMessageBySubject(Tinebase_Core::filterInputForDatabase($subject));
 +        $fullMessage = $this->_json->getMessage($message['id']);
 +
 +        $this->assertContains('multipart/encrypted', $fullMessage['headers']['content-type']);
 +        $this->assertContains('protocol="application/pgp-encrypted"', $fullMessage['headers']['content-type']);
 +        $this->assertCount(2, $fullMessage['structure']['parts']);
 +        $this->assertEquals('application/pgp-encrypted', $fullMessage['structure']['parts'][1]['contentType']);
 +        $this->assertEquals('application/octet-stream', $fullMessage['structure']['parts'][2]['contentType']);
 +
 +        return $fullMessage;
 +    }
 +
 +    /**
 +     * testMessagePGPMime
 +     *
 +     * - prepare amored part of PGP MIME structure
 +     */
 +    public function testMessagePGPMime()
 +    {
 +        $fullMessage = $this->testSendMailveopeAPIMessage();
 +
 +        $this->assertEquals('application/pgp-encrypted', $fullMessage['preparedParts'][0]['contentType']);
 +        $this->assertContains('-----BEGIN PGP MESSAGE-----', $fullMessage['preparedParts'][0]['preparedData']);
 +    }
 +
 +    public function testMessagePGPInline()
 +    {
 +        $inbox = $this->_getFolder('INBOX');
 +        $mailAsString = file_get_contents(dirname(__FILE__) . '/../files/multipart_alternative_pgp_inline.eml');
 +        Felamimail_Controller_Message::getInstance()->appendMessage($inbox, $mailAsString);
 +
 +        $this->_foldersToClear = array('INBOX');
 +        $message = $this->_searchForMessageBySubject('Re: mailvelope und tine20');
 +
 +        $fullMessage = $this->_json->getMessage($message['id']);
 +        $this->assertFalse(empty($fullMessage['preparedParts']));
 +    }
 +
      /*********************** sieve tests ****************************/
      
      /**
          $ruleData[0]['enabled'] = 0;
          $this->_sieveTestHelper($ruleData);
      }
-     
+     /**
+      * @see 0006222: Keep a copy from mails forwarded to another emailaddress
+      */
+     public function testSetForwardRuleWithCopy()
+     {
+         $ruleData = array(array(
+             'id'            => 1,
+             'action_type'   => Felamimail_Sieve_Rule_Action::REDIRECT,
+             'action_argument' => array(
+                 'emails' => 'someaccount@example.org',
+                 'copy'   => 1,
+             ),
+             'conjunction'     => 'allof',
+             'conditions'    => array(array(
+                 'test'          => Felamimail_Sieve_Rule_Condition::TEST_ADDRESS,
+                 'comperator'    => Felamimail_Sieve_Rule_Condition::COMPERATOR_CONTAINS,
+                 'header'        => 'From',
+                 'key'           => 'info@example.org',
+             )),
+             'enabled'       => 1,
+         ));
+         $this->_sieveTestHelper($ruleData);
+     }
+     /**
+      * @see 0006222: Keep a copy from mails forwarded to another emailaddress
+      */
+     public function testSetForwardRuleWithoutCopy()
+     {
+         $ruleData = array(array(
+             'id'            => 1,
+             'action_type'   => Felamimail_Sieve_Rule_Action::REDIRECT,
+             'action_argument' => array(
+                 'emails' => 'someaccount@example.org',
+                 'copy'   => 0,
+             ),
+             'conjunction'     => 'allof',
+             'conditions'    => array(array(
+                 'test'          => Felamimail_Sieve_Rule_Condition::TEST_ADDRESS,
+                 'comperator'    => Felamimail_Sieve_Rule_Condition::COMPERATOR_CONTAINS,
+                 'header'        => 'From',
+                 'key'           => 'info@example.org',
+             )),
+             'enabled'       => 1,
+         ));
+         $this->_sieveTestHelper($ruleData);
+     }
      /**
       * testGetVacationTemplates
       *
@@@ -266,16 -266,19 +266,19 @@@ Tine.Felamimail.sieve.RulesGridPanel = 
       */
      actionRenderer: function(type, metadata, record) {
          var types = Tine.Felamimail.sieve.RuleEditDialog.getActionTypes(this.app),
-             result = type;
-         
+             result = type,
+             action_argument = record.get('action_argument');
          for (i=0; i < types.length; i++) {
              if (types[i][0] == type) {
                  result = types[i][1];
              }
          }
          
-         if (record.get('action_argument') && record.get('action_argument') != '') {
-             result += ' ' + record.get('action_argument');
+         if (action_argument && action_argument != '') {
+             result += Ext.isObject(action_argument)
+                 ? ': '  + action_argument.emails + (action_argument.copy ? ' (' + this.app.i18n._('Keep a copy') + ')' : '')
+                 : action_argument;
          }
              
          return Ext.util.Format.htmlEncode(result);
                  if (condition.header == filterModel.field) {
                      header = filterModel.label;
                      if (condition.header == 'size') {
 -                        comperator = (condition.comperator == 'over') ? _('is greater than') : _('is less than');
 +                        comperator = (condition.comperator == 'over') ? i18n._('is greater than') : i18n._('is less than');
                      } else {
 -                        comperator = _(condition.comperator);
 +                        comperator = i18n._(condition.comperator);
                      }
                      found = true;
                  }
@@@ -841,14 -841,10 +841,14 @@@ class Tinebase_Container extends Tineba
              )
              
              ->where("{$this->_db->quoteIdentifier('container.application_id')} = ?", $application->getId())
 -            ->where("{$this->_db->quoteIdentifier('container.type')} = ?", Tinebase_Model_Container::TYPE_SHARED)
 -            
 -            ->order('container.name');
 -        
 +            ->where("{$this->_db->quoteIdentifier('container.type')} = ?", Tinebase_Model_Container::TYPE_SHARED);
 +
 +        // TODO maybe this could be removed or changed to a preference later
 +        $sortOrder = Tinebase_Config::getInstance()->featureEnabled(Tinebase_Config::FEATURE_CONTAINER_CUSTOM_SORT)
 +            ? array('container.order', 'container.name')
 +            : 'container.name';
 +        $select->order($sortOrder);
 +
          $this->addGrantsSql($select, $accountId, $grant, 'container_acl', $_andGrants, __CLASS__ . '::addGrantsSqlCallback');
          
          $stmt = $this->_db->query('/*' . __FUNCTION__ . '*/' . $select);
              $acl = $controller->doContainerACLChecks(FALSE);
          }
          if ($controller && class_exists($filterName)) {
-             Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__
-                 . ' Delete ' . $model . ' records in container ' . $container->getId());
  
-             $filter = new $filterName(array(array(
-                 'field'    => 'container_id',
-                 'operator' => 'equals',
-                 'value'    => intval($container->id)
-             )), Tinebase_Model_Filter_FilterGroup::CONDITION_AND, array('ignoreAcl' => $_ignoreAcl));
+             // workaround to fix Filemanager as Tinebase_Filesystem does not implement search
+             $backend = $controller::getInstance()->getBackend();
+             if (method_exists($backend, 'search')) {
+                 Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__
+                     . ' Delete ' . $model . ' records in container ' . $container->getId());
  
-             if ($_ignoreAcl) {
-                 $backend = $controller::getInstance()->getBackend();
-                 $idsToDelete = $backend->search($filter, null, /* $_onlyIds */ true);
-                 $controller::getInstance()->delete($idsToDelete);
-             } else {
-                 $controller::getInstance()->deleteByFilter($filter);
+                 $filter = new $filterName(array(array(
+                     'field' => 'container_id',
+                     'operator' => 'equals',
+                     'value' => intval($container->id)
+                 )), Tinebase_Model_Filter_FilterGroup::CONDITION_AND, array('ignoreAcl' => $_ignoreAcl));
+                 if ($_ignoreAcl) {
+                     $idsToDelete = $backend->search($filter, null, /* $_onlyIds */
+                         true);
+                     $controller::getInstance()->delete($idsToDelete);
+                 } else {
+                     $controller::getInstance()->deleteByFilter($filter);
+                 }
              }
          }
  
@@@ -169,7 -169,7 +169,7 @@@ class Tinebase_Model_Filter_FilterGrou
      protected $_filterObjects = array();
      
      /**
 -     * @var array spechial options
 +     * @var array special options
       */
      protected $_options = NULL;
      
              $m = $this->_configuredModel;
              $filterConfig = $m::getConfiguration()->getFilterModel();
  
 -            if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' 
 +            if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' '
                  . ' Filter config: ' . print_r($filterConfig, TRUE));
 -            
 +
              foreach ($filterConfig as $prop => $val) {
                  $this->{$prop} = $val;
              }
              $this->_modelName = $this->_applicationName . '_Model_' . $this->_modelName;
          }
      }
 -    
 +
      /**
       * clone filters after creating clone of filter group
       */
                  if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' ' 
                      . ' Adding FilterGroup: ' . $this->_className);
                  
 -                if (empty($this->_className)) {
 +                if (empty($this->_className) || ! class_exists($this->_className)) {
                      $this->_className = get_class($this);
                      if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' ' 
                          . ' _className was not set, using get_class: ' . $this->_className);
                  $model = new $this->_modelName();
                  $filterData['options']['related_model'] = $modelName;
                  $filterData['options']['idProperty'] = $model->getIdProperty();
+                 if (isset($_filterData['options']) && isset($_filterData['options']['own_model'])) {
+                     $filterData['options']['own_model'] = $_filterData['options']['own_model'];
+                 }
                  $filter = new Tinebase_Model_Filter_Relation($filterData);
                  break;
  
      {
          $this->_label = $_label;
      }
 +
 +    /**
 +     * set configured model
 +     *
 +     * @param $configuredModel
 +     */
 +    public function setConfiguredModel($configuredModel)
 +    {
 +        $this->_configuredModel = $configuredModel;
 +
 +        $this->_createFromModelConfiguration();
 +    }
      
      /**
       * returns id