/** * Returns either a cached list of twitter accounts for a user, or * the accounts out of the database which will immediately be validated * against the twitter service (network access) * * @param array $options An associative array with the following * key value/pairs: * - userId: the id of the user to fetch al twitter accounts for * @param Conjoon_BeanContext_Decoratable $model * * @return Array anr array with instances of * Conjoon_Modules_Service_Twitter_Account_Model_Account */ protected function _build(array $options, Conjoon_BeanContext_Decoratable $model) { $userId = $options['userId']; /** * @see Conjoon_BeanContext_Decorator */ require_once 'Conjoon/BeanContext/Decorator.php'; $decoratedModel = new Conjoon_BeanContext_Decorator($model); $accounts = $decoratedModel->getAccountsForUserAsDto($userId); /** * @see Conjoon_Service_Twitter */ require_once 'Conjoon/Service/Twitter.php'; /** * @see Conjoon_Modules_Default_Registry_Facade */ require_once 'Conjoon/Modules/Default/Registry/Facade.php'; $protocolContext = Conjoon_Modules_Default_Registry_Facade::getInstance()->getValueForKeyAndUserId('/server/environment/protocol', $userId); for ($i = 0, $len = count($accounts); $i < $len; $i++) { $dto =& $accounts[$i]; try { /** * @todo move to separate model */ /** * @see Zend_Oauth_Token_Access */ require_once 'Zend/Oauth/Token/Access.php'; $accessToken = new Zend_Oauth_Token_Access(); $accessToken->setParams(array('oauth_token' => $dto->oauthToken, 'oauth_token_secret' => $dto->oauthTokenSecret, 'user_id' => $dto->twitterId, 'screen_name' => $dto->name)); $twitter = new Conjoon_Service_Twitter(array('username' => $dto->name, 'accessToken' => $accessToken)); $response = $twitter->userShow($dto->name); $dto->twitterId = $response->id_str; $dto->twitterName = $response->name; $dto->twitterScreenName = $response->screen_name; $dto->twitterLocation = $response->location; $dto->twitterProfileImageUrl = $protocolContext === 'https' ? $response->profile_image_url_https : $response->profile_image_url; $dto->twitterUrl = $response->url; $dto->twitterProtected = $response->protected; $dto->twitterDescription = $response->description; $dto->twitterFollowersCount = $response->followers_count; } catch (Exception $e) { Conjoon_Log::log("Could not retrieve account information for twitter " . "account: \"" . $e->getMessage() . "\"", Zend_Log::INFO); // ignore } $dto->oauthTokenSecret = str_pad("", strlen($dto->oauthTokenSecret), '*'); } return $accounts; }
/** * Checks whether a connection is available. If this class has not been * configured using "setConfig()", this method will always return true. * This method will also return true if the enabled config option for this * class has been set to 0/false. * * @return boolean Whether or not it can be assumed that network * connections to other resources can be established */ public function isConnectionAvailable() { if (empty(self::$_config)) { /** * @see Conjoon_Log */ require_once 'Conjoon/Log.php'; Conjoon_Log::log("Connection check for \"" . get_class($this->getActionController()) . "::" . $this->getRequest()->getActionName() . "\" not configured", Zend_Log::INFO); return true; } $c =& self::$_config; if (!$c['enabled']) { return true; } $errno = ""; $errstr = ""; $fp = @fsockopen($c['ip'], $c['port'], $errno, $errstr, $c['timeout']); if (!$fp) { /** * @see Conjoon_Log */ require_once 'Conjoon/Log.php'; Conjoon_Log::log("Connection check for \"" . get_class($this->getActionController()) . "::" . $this->getRequest()->getActionName() . "\" returned: \"{$errno}\", \"{$errstr}\"", Zend_Log::INFO); return false; } @fclose($fp); return true; }
/** * Returns an array of Conjoon_Modules_Groupware_Feeds_Item_Dto * and also reads out new feed items and returns them along with * items out of the data storage. * If $removeold is set to true, the emthod will alos delete old * feed items out of the data storage. * * @param integer $userId * @param boolean $removeold * @param integer $timeout The timeout for the http connection that is * responsible for querying accounts for new feed items. Depending on * the number of accounts that have to be queried, this should be set to * a high enough value. * * @return array Conjoon_Modules_Groupware:Feeds_Item_Dto */ public function syncAndGetFeedItemsForUser($userId, $removeOld, $timeout) { /** * @see Conjoon_Modules_Groupware_Feeds_ImportHelper */ require_once 'Conjoon/Modules/Groupware/Feeds/ImportHelper.php'; $time = time(); $accounts = $this->_getAccountFacade()->getAccountsToUpdate($userId, $time); Conjoon_Log::log(count($accounts) . " need to be updated at " . date("Y-m-d H:i:s"), Zend_Log::INFO); $insertedItems = array(); $len = count($accounts); $secTimeout = $timeout / 1000; $defTimeout = -1; // compute the timeout for the connections. Filter should have set the default // timeout to 30000 ms if the timeout param was not submitted // we need to compare this with the max_execution_time of the php installation // and take action in case the requestTimeout exceeds it, so each account will have // a reduced timeout, just in case (the configured timeout won't be considered then) if ($len > 0 && $secTimeout >= ini_get('max_execution_time')) { $defTimeout = (int) round(ini_get('max_execution_time') / $len); // if $defTimeout is less than 1, we will not try to load any feeds, or else // no response will ge through to the client if ($defTimeout < 1) { $len = 0; } } for ($i = 0; $i < $len; $i++) { Conjoon_Log::log($accounts[$i]->name . " needs to be queried at " . date("Y-m-d H:i:s"), Zend_Log::INFO); // set requestTimeout to default if necessary if ($defTimeout != -1) { $accounts[$i]->requestTimeout = $defTimeout; } try { $fetched = $this->importAndAddFeedItems($accounts[$i]->id, $userId, true, true); $insertedItems = array_merge($insertedItems, $fetched); Conjoon_Log::log($accounts[$i]->name . " has been updated with " . count($fetched) . " items", Zend_Log::INFO); } catch (Exception $e) { throw $e; } } if ($removeOld) { $this->deleteOldFeedItems($userId); $items = $this->getFeedItemsForUser($userId); } else { // return all items that where added during this request $items = $insertedItems; } return $items; }
/** * @ticket CN-849 */ public function testIsConfigured() { $this->assertFalse(Conjoon_Log::isConfigured()); Conjoon_Log::init(array('enabled' => false)); $this->assertTrue(Conjoon_Log::isConfigured()); }
/** * Inits this logger with the configuration provided * from $options. * * @param Array $options An configuration array with * the following properties: * - enabled: 1/0 1 for enabled, otherwise 0 * - writer: the type of write to use. Available writers: * - firebug: to write directly to the firebug console * * @throws Conjoon_Exception if init was already called, * assuming this method may only be called once. */ public static function init(array $options) { if (self::isConfigured()) { /** * @see Conjoon_Exception */ require_once 'Conjoon/Exception.php'; throw new Conjoon_Exception("init may only be called once."); } if (!$options['enabled']) { self::$_initCalled = true; return; } self::$_log = new Zend_Log(); switch ($options['writer']) { case 'firebug': /** * @see Zend_Log_Writer_Firebug */ require_once 'Zend/Log/Writer/Firebug.php'; self::addWriter(new Zend_Log_Writer_Firebug()); break; } self::$_initCalled = true; }
// set the default timezone here // if the configured timezone is not valid, we will gracefully // fall back to $LOCALE_DEFAULT_TIMEZONE as the default timezone, // which was configured during the installation process $tz = $config->application->locale->date->timezone; if ($tz) { $tzres = @date_default_timezone_set($tz); if ($tzres !== true) { /*@REMOVE@*/ $deftz = 'Europe/Berlin'; /*@REMOVE@*/ /*@BUILD_ACTIVE@ $deftz = $LOCALE_DEFAULT_TIMEZONE; @BUILD_ACTIVE@*/ if ($config->log) { Conjoon_Log::log("\"date_default_timezone_set()\" failed to set application's " . "default timezone \"" . $config->application->locale->date->timezone . "\"; " . " Falling back to \"" . $deftz . "\" instead.", Zend_Log::NOTICE); } // last resort $lr = @date_default_timezone_set($deftz); if ($lr !== true) { // failed? Exit. die("I could not start up the application due to an error that " . "occurred during setting the default timezone. Sorry. I tried " . "to gracefully fall back to an alternative timezone, " . "but I failed. You should take care of this issue " . "before you continue working with conjoon."); } } } // +---------------------------------------------------------------------------- // | Set up the controller // +---------------------------------------------------------------------------- $controller = Zend_Controller_Front::getInstance(); $controller->throwExceptions(false)->addModuleDirectory($config->environment->application_path . '/modules')->setBaseUrl($config->environment->base_url); // add the plugins
/** * Saves a draft and moves it into the outbox folder. The draft can either * already be existing - in case the passed id id available in * groupware_email_items_outbox - or new, in which case a whole new record * will be created. * If the type is anything but new or an empty string, the referenced message * will be saved in the reference-table, but still with the flag is_pending * set to true, which will be set to false once the email is sent. * * @param Conjoon_Modules_Groupware_Email_Draft $draft The draft object to save * @param Conjoon_Modules_Groupware_Email_Account $account The account which was used writing * the draft * @param integer $userId The id of the user for whom the draft gets saved. * @param string $type The context in which the draft was moved to the outbox, * either 'reply', 'reply_all', 'forward' or 'new' (or empty string) * @param array $postedAttachments A list of attachments, key/value pairs according to * com.conjoon.cudgets.data.FileRecord * @param array a list of attachment ids to remove from a list of existing attachments * belonging to the draft * * @return array the data from groupware_email_item associated with * the newly saved entry */ public function moveDraftToOutbox(Conjoon_Modules_Groupware_Email_Draft $draft, Conjoon_Modules_Groupware_Email_Account $account, $userId, $type = '', $referencesId = -1, $postedAttachments, $removeAttachmentIds) { $emailRecipientsToStringFilter = new Conjoon_Filter_EmailRecipientsToString(); $emailRecipientsFilter = new Conjoon_Filter_EmailRecipients(); $folderModel = new Conjoon_Modules_Groupware_Email_Folder_Model_Folder(); $outboxModel = new Conjoon_Modules_Groupware_Email_Item_Model_Outbox(); $referencesModel = new Conjoon_Modules_Groupware_Email_Item_Model_References(); $referenceId = $referencesId < 0 ? 0 : $referencesId; // prepare data to insert or update $outboxUpdate = array('sent_timestamp' => 0, 'raw_header' => '', 'raw_body' => '', 'groupware_email_accounts_id' => $account->getId()); // get the outbox folder. $outboxId = $folderModel->getOutboxFolderId($account->getId(), $userId); if ($outboxId == 0) { return null; } $date = new Zend_Date($draft->getDate()); $to = $draft->getTo(); $cc = $draft->getCc(); $bcc = $draft->getBcc(); $fromAddress = new Conjoon_Modules_Groupware_Email_Address(array($account->getAddress(), $account->getUserName())); $toString = array(); foreach ($to as $recipient) { $toString[] = $recipient->__toString(); } $toString = implode(', ', $toString); $ccString = array(); foreach ($cc as $recipient) { $ccString[] = $recipient->__toString(); } $ccString = implode(', ', $ccString); $bccString = array(); foreach ($bcc as $recipient) { $bccString[] = $recipient->__toString(); } $bccString = implode(', ', $bccString); /** * @see Conjoon_Filter_DateToUtc */ require_once 'Conjoon/Filter/DateToUtc.php'; $toUtcFilter = new Conjoon_Filter_DateToUtc(); $itemUpdate = array('date' => $toUtcFilter->filter($date->get(Zend_Date::ISO_8601)), 'subject' => $draft->getSubject(), 'from' => $fromAddress->__toString(), 'reply_to' => $account->getReplyAddress(), 'to' => $toString, 'cc' => $ccString, 'bcc' => $bccString, 'sender' => $emailRecipientsToStringFilter->filter($emailRecipientsFilter->filter(array($fromAddress->__toString()))), 'recipients' => $emailRecipientsToStringFilter->filter($emailRecipientsFilter->filter(array($toString, $ccString, $bccString))), 'references' => $draft->getReferences(), 'in_reply_to' => $draft->getInReplyTo(), 'content_text_html' => $draft->getContentTextHtml(), 'content_text_plain' => $draft->getContentTextPlain(), 'groupware_email_folders_id' => $outboxId); $adapter = $this->getAdapter(); $adapter->beginTransaction(); $id = $draft->getId(); try { if ($id > 0) { // update! move from drafts to outbox $itemWhere = $this->getAdapter()->quoteInto('id = ?', $id); $this->update($itemUpdate, $itemWhere); Conjoon_Util_Array::apply($outboxUpdate, array('groupware_email_items_id' => $id)); $outboxWhere = $outboxModel->getAdapter()->quoteInto('groupware_email_items_id = ?', $id); $outboxModel->update($outboxUpdate, $outboxWhere); } else { // insert! $id = $this->insert($itemUpdate); $draft->setId($id); Conjoon_Util_Array::apply($outboxUpdate, array('groupware_email_items_id' => $id)); $outboxModel->insert($outboxUpdate); $flagUpdate = array('groupware_email_items_id' => $id, 'user_id' => $userId, 'is_read' => 1, 'is_spam' => 0, 'is_deleted' => 0); $flagModel = new Conjoon_Modules_Groupware_Email_Item_Model_Flag(); $flagModel->insert($flagUpdate); } $this->saveAttachmentsForDraft($draft, $postedAttachments, $removeAttachmentIds); switch ($type) { case Conjoon_Modules_Groupware_Email_Keys::REFERENCE_TYPE_REPLY: case Conjoon_Modules_Groupware_Email_Keys::REFERENCE_TYPE_REPLY_ALL: case Conjoon_Modules_Groupware_Email_Keys::REFERENCE_TYPE_FORWARD: if ($referenceId != 0) { $referencesUpdate = array('groupware_email_items_id' => $id, 'user_id' => $userId, 'reference_items_id' => $referenceId, 'reference_type' => $type, 'is_pending' => 1); $referencesModel->insert($referencesUpdate); } break; } $adapter->commit(); } catch (Exception $e) { /** * @see Conjoon_Log */ require_once 'Conjoon/Log.php'; Conjoon_Log::log($e, Zend_Log::ERROR); $adapter->rollBack(); return null; } return $this->getItemForUser($id, $userId); }
/** * Parses the configuration file and sets the include path if found in the * configuration file. * */ function conjoon_parseConfig() { // config failed to init, so we assume we have to load the config and parse it $initialConfig = parse_ini_file('./config.ini.php', true); // check if the library_path is set, and adjust the include_path if necessary if (($incPath = $initialConfig['environment']['include_path']) != null) { set_include_path(get_include_path() . PATH_SEPARATOR . $incPath); } // check whether we need the logging options if (isset($initialConfig['log']) && !$initialConfig['log']['enabled']) { unset($initialConfig['log']); } else { if (isset($initialConfig['log'])) { /** * @see Conjoon_Log */ include_once 'Conjoon/Log.php'; // load Zend/Log for log constants so we don't have to // require this later on /** * @see Zend_Log */ include_once 'Zend/Log.php'; Conjoon_Log::init($initialConfig['log']); } } /*@REMOVE@*/ // check whether we need the application.connection options if (isset($initialConfig['application']) && !$initialConfig['application']['connection_check.enabled']) { unset($initialConfig['application']['connection_check.ip']); unset($initialConfig['application']['connection_check.timeout']); unset($initialConfig['application']['connection_check.port']); } /*@REMOVE@*/ // take care of doctrine cache settings. make sure we void // caching if apc, memcache or memcached are selected, // but extensions are not loaded if (isset($initialConfig['application']) && isset($initialConfig['application']['doctrine.cache.enabled']) && $initialConfig['application']['doctrine.cache.enabled']) { $doctrineApp =& $initialConfig['application']; $doctrineTypes = array('metadata_cache', 'query_cache'); $disableDoctrineCache = true; foreach ($doctrineTypes as $doctrineCacheType) { $doctrineEnabledKey = 'doctrine.cache.' . $doctrineCacheType . '.enabled'; $doctrineCacheTypeKey = 'doctrine.cache.' . $doctrineCacheType . '.type'; if ($doctrineApp[$doctrineEnabledKey] && $doctrineApp[$doctrineCacheTypeKey] != 'file') { if (!extension_loaded($doctrineApp[$doctrineCacheTypeKey])) { $doctrineApp[$doctrineEnabledKey] = false; if ($initialConfig['log'] && $initialConfig['log']['enabled']) { Conjoon_Log::log("\"" . $doctrineApp[$doctrineCacheTypeKey] . "\" for " . "Doctrine Cache {$doctrineCacheType} selected, but " . "extension is not available", Zend_Log::WARN); } } else { // dont disable cache is extension was loaded $disableDoctrineCache = false; } } else { // dont disable cache if cache type is file $disableDoctrineCache = false; } } // disable doctrine cache if loading extensions for each setting failed $initialConfig['application']['doctrine.cache.enabled'] = $disableDoctrineCache ? 0 : 1; } // take care of default cache if (isset($initialConfig['cache'])) { if (!$initialConfig['cache']['default.caching']) { unset($initialConfig['cache']); } else { $defaults = array(); // extract defaults foreach ($initialConfig['cache'] as $key => $value) { if (strpos($key, 'default.') === 0) { $defaults[substr($key, 8)] = $initialConfig['cache'][$key]; unset($initialConfig['cache'][$key]); } } // get the cache namespaces $cacheBlocks =& $initialConfig['cache']; $namespaces = array(); $unsets = array(); foreach ($cacheBlocks as $key => $value) { $ns = explode(".", $key, 3); if (array_key_exists($ns[0] . '.' . $ns[1], $unsets)) { continue; } if ($ns[2] == 'caching' && !$value) { $unsets[$ns[0] . '.' . $ns[1]] = true; } else { $namespaces[$ns[0] . '.' . $ns[1]] = true; } } // first off, unset all cache blocks that have caching set to 0 foreach ($unsets as $key => $value) { foreach ($cacheBlocks as $ckey => $cvalue) { if (strpos($ckey, $key) === 0) { unset($cacheBlocks[$ckey]); } } } foreach ($namespaces as $key => $value) { foreach ($defaults as $defaultKey => $defaultValue) { $m = $key . '.' . $defaultKey; if (!array_key_exists($m, $cacheBlocks)) { $cacheBlocks[$m] = $defaultValue; } } // compute cache_dir backend HERE! // check whether the cache-dir for the backend options is relative or // absolute. This is a very simple check and may be error-prone, // but its okay for now $ck = $key . '.backend.cache_dir'; if (array_key_exists($ck, $cacheBlocks)) { $cacheDir = $cacheBlocks[$ck]; if (strpos($cacheDir, '/') !== 0 && strpos($cacheDir, ':') !== 1) { $cacheBlocks[$ck] = $initialConfig['environment']['application_path'] . DIRECTORY_SEPARATOR . $cacheDir; } } } } } // take care of files if (isset($initialConfig['files'])) { // get the cache namespaces $cacheBlocks =& $initialConfig['files']; $namespaces = array(); foreach ($cacheBlocks as $key => $value) { $ns = explode(".", $key, 4); if (!isset($ns[2])) { continue; } $namespaces[$ns[0] . '.' . $ns[1] . '.' . $ns[2]] = true; } foreach ($namespaces as $key => $value) { $ck = $key . '.dir'; if (array_key_exists($ck, $cacheBlocks)) { $cacheDir = $cacheBlocks[$ck]; if ($cacheDir && strpos($cacheDir, '/') !== 0 && strpos($cacheDir, ':') !== 1) { $cacheBlocks[$ck] = $initialConfig['environment']['application_path'] . DIRECTORY_SEPARATOR . $cacheDir; } } } } return $initialConfig; }
private static function _processResources(array $config) { if (self::$_lock) { /** * @see Conjoon_Log */ require_once 'Conjoon/Log.php'; Conjoon_Log::log("Conjoon_Modules_Groupware_Feeds_ImportHelper::_processResources " . "- possible race condition", Zend_Log::INFO); } self::$_lock = true; $uri = $config['uri']; $requestTimeout = $config['requestTimeout']; $useCache = $config['useCache']; $useConditionalGet = $config['useConditionalGet']; $callback = $config['callback']; /** * @see Zend_Feed_Reader */ require_once 'Zend/Feed/Reader.php'; if ($useCache !== false) { // set the reader's cache here /** * @see Conjoon_Cache_Factory */ require_once 'Conjoon/Cache/Factory.php'; /** * @see Conjoon_Keys */ require_once 'Conjoon/Keys.php'; $frCache = Conjoon_Cache_Factory::getCache(Conjoon_Keys::CACHE_FEED_READER, Zend_Registry::get(Conjoon_Keys::REGISTRY_CONFIG_OBJECT)->toArray()); if ($frCache) { Zend_Feed_Reader::setCache($frCache); if ($useConditionalGet !== false) { Zend_Feed_Reader::useHttpConditionalGet(); } } } Zend_Feed_Reader::getHttpClient()->setConfig(array('timeout' => $requestTimeout)); $result = self::$callback($uri); Zend_Feed_Reader::reset(); self::$_lock = false; return $result; }
/** * Updates a single account with the data from $data for the specified * $userId. * * @param integer $accountId the id of the account to update. * @param Array $data * @param integer $userId * * @return boolean true, if updating the account was successfull, otherwise * false * * @throws Exception */ public function updateAccount($accountId, array $data, $userId) { $accountId = (int) $accountId; $userId = (int) $userId; if ($userId <= 0 || $accountId <= 0) { throw new InvalidArgumentException("Invalid argument supplied, userId was \"{$userId}\", " . "accountId was \"{$accountId}\""); } $filter = $this->_getUpdateAccountFilter(); $filter->setData($data); try { $data = $filter->getProcessedData(); } catch (Zend_Filter_Exception $e) { /** * @see Conjoon_Error */ require_once 'Conjoon/Error.php'; Conjoon_Log::log(Conjoon_Error::fromFilter($filter, $e), Zend_Log::ERR); return false; } if (array_key_exists('id', $data)) { unset($data['id']); } /** * @see Conjoon_Util_Array */ require_once 'Conjoon/Util/Array.php'; Conjoon_Util_Array::underscoreKeys($data); $affected = $this->_getAccountModel()->updateAccount($accountId, $data); if ($affected === true) { $this->_getBuilder()->remove(array('accountId' => $accountId)); $this->_getListBuilder()->cleanCacheForTags(array('userId' => $userId)); } return $affected === true ? true : false; }
/** * Saves the email and it's attachments. Uses the default db adapter as * configured by the application. If an exception occurs, the exception's * message will be stored in an array (together with other exceptions that * may have occured) and returned later on. Any db operation that failed will * be rolled back. * * @param array $emailItem An associative array with the data to insert into the * different tables. All attachments will be stored in the key/value pair "attachments", * which is itself a numeric array * * @return mixed Return the id of the last inserted email item, or an * error message if an error occured. */ private function _saveEmail(array $emailItem) { $filterAttachment = $this->_filterAttachment; $filterFlag = $this->_filterFlag; $filterItem = $this->_filterItem; $filterInbox = $this->_filterInbox; $modelAttachment = $this->_modelAttachment; $modelFlag = $this->_modelFlag; $modelItem = $this->_modelItem; $modelInbox = $this->_modelInbox; $dbAdapter = Zend_Db_Table::getDefaultAdapter(); if (!$this->_maxAllowedPacket) { $config = Zend_Registry::get(Conjoon_Keys::REGISTRY_CONFIG_OBJECT); $this->_maxAllowedPacket = $config->database->variables->max_allowed_packet; if (!$this->_maxAllowedPacket) { $this->_maxAllowedPacket = Conjoon_Db_Util::getMaxAllowedPacket($dbAdapter); } } $this->_setPlainFromHtml($emailItem); // filter and insert into groupware_email_items $filterItem->setData($emailItem); $itemData = $filterItem->getProcessedData(); if ($this->_maxAllowedPacket < strlen($emailItem['rawBody'])) { return 'Could not save message with subject "' . $itemData['subject'] . '" - message is larger than available packet size (' . $this->_maxAllowedPacket . ' bytes).'; } $dbAdapter->beginTransaction(); $currFilter = null; try { Conjoon_Util_Array::underscoreKeys($itemData); try { $id = (int) $modelItem->insert($itemData); } catch (Zend_Db_Statement_Exception $zdse) { // in very rare cases, there are 4-byte characters in a utf-8 // string, and mysql cannot handle them right since we use // utf-8 collations. We'll strip those 4-byte characters away. // see CN-619 $content = $itemData['content_text_plain']; $i = 0; $len = strlen($content); $fourByteDetected = false; while ($i < $len) { $ord = ord($content[$i]); switch (true) { case $ord <= 127: $i += 1; break; case $ord < 224: $i += 2; break; case $ord < 240: $i += 3; break; default: $fourByteDetected = true; $content = substr($content, 0, $i) . substr($content, $i + 4); $len -= 4; break; } } if ($fourByteDetected === true) { $lastResortData = $emailItem; $lastResortData['contentTextPlain'] = $content; $filterItem->setData($lastResortData); $lastResortItemData = $filterItem->getProcessedData(); Conjoon_Util_Array::underscoreKeys($lastResortItemData); $id = (int) $modelItem->insert($lastResortItemData); /** * @see Conjoon_Log */ require_once 'Conjoon/Log.php'; Conjoon_Log::log("Detected 4-byte character in content_text_plain for " . "Email message with id {$id}", Zend_Log::NOTICE); } } if ($id <= 0) { return null; } // assign needed (reference) keys $emailItem['isRead'] = 0; $emailItem['id'] = $id; $emailItem['groupwareEmailItemsId'] = $id; // filter and insert into groupware_email_items_inbox $currFilter = $filterInbox; $filterInbox->setData($emailItem); $itemData = $filterInbox->getProcessedData(); Conjoon_Util_Array::underscoreKeys($itemData); $modelInbox->addInboxData($itemData); // filter and insert into groupware_email_items_flag $currFilter = $filterFlag; $filterFlag->setData($emailItem); $itemData = $filterFlag->getProcessedData(); Conjoon_Util_Array::underscoreKeys($itemData); $modelFlag->insert($itemData); // loop through attachments and insert into groupware_email_items_attachments $attachmentCount = count($emailItem['attachments']); $currFilter = $filterAttachment; for ($i = 0; $i < $attachmentCount; $i++) { $emailItem['attachments'][$i]['groupwareEmailItemsId'] = $id; $filterAttachment->setData($emailItem['attachments'][$i]); $itemData = $filterAttachment->getProcessedData(); Conjoon_Util_Array::underscoreKeys($itemData); $modelAttachment->addAttachmentForItem($itemData, $id); } $dbAdapter->commit(); return $id; } catch (Exception $e) { if ($e instanceof Zend_Filter_Exception) { $error = Conjoon_Error::fromFilter($currFilter, $e); $error = $error->getMessage(); } else { $error = $e->getMessage(); } try { $dbAdapter->rollBack(); } catch (Exception $m) { $error .= '; ' . $m->getMessage(); } return $error; } }