/** * @see \wcf\system\worker\IWorker::validate() */ public function validate() { WCF::getSession()->checkPermissions(array('admin.system.canImportData')); if (!isset($this->parameters['objectType'])) { throw new SystemException("parameter 'objectType' missing"); } // get import data $this->importData = WCF::getSession()->getVar('importData'); if ($this->importData === null) { throw new SystemException("import data missing"); } // get exporter $this->exporter = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.exporter', $this->importData['exporterName'])->getProcessor(); // set data $this->exporter->setData($this->importData['dbHost'], $this->importData['dbUser'], $this->importData['dbPassword'], $this->importData['dbName'], $this->importData['dbPrefix'], $this->importData['fileSystemPath'], $this->importData['additionalData']); $this->exporter->init(); // set user merge mode ImportHandler::getInstance()->setUserMergeMode($this->importData['userMergeMode']); // set import hash ImportHandler::getInstance()->setImportHash(substr(StringUtil::getHash($this->importData['dbHost'] . $this->importData['dbName'] . $this->importData['dbPrefix']), 0, 8)); }
/** * Writes an error to log file. */ protected function logError() { $logFile = WCF_DIR . 'log/' . date('Y-m-d', TIME_NOW) . '.txt'; // try to create file @touch($logFile); // validate if file exists and is accessible for us if (!file_exists($logFile) || !is_writable($logFile)) { /* We cannot recover if we reached this point, the server admin is urged to fix his pretty much broken configuration. GLaDOS: Look at you, sailing through the air majestically, like an eagle... piloting a blimp. */ return; } $e = ($this->getPrevious() ?: $this); $message = date('r', TIME_NOW)."\n". 'Message: '.$e->getMessage()."\n". 'File: '.$e->getFile().' ('.$e->getLine().")\n". 'PHP version: '.phpversion()."\n". 'WCF version: '.WCF_VERSION."\n". 'Request URI: '.(isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '')."\n". 'Referrer: '.(isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '')."\n". "Stacktrace: \n ".implode("\n ", explode("\n", $e->getTraceAsString()))."\n"; // calculate Exception-ID $id = StringUtil::getHash($message); $message = "<<<<<<<<".$id."<<<<\n".$message."<<<<\n\n"; // append @file_put_contents($logFile, $message, FILE_APPEND); return $id; }
/** * @see wcf\action\IAction::execute() */ public function execute() { //parent::execute(); //!!! $this->readParameters(); //!!! // set active menu item (for error messages) //PageMenu::getInstance()->setActiveMenuItem('wbb.header.menu.board'); // build conditions $sql = ''; $conditionBuilder = new PreparedStatementConditionBuilder(); switch ($this->mode) { case 'unreadPosts': $conditionBuilder->add('thread.boardID IN (?)', array($this->boardIDs)); $conditionBuilder->add('thread.lastPostTime > ?', array(VisitTracker::getInstance()->getVisitTime('com.woltlab.wbb.thread'))); $conditionBuilder->add('thread.isDeleted = 0'); $conditionBuilder->add('thread.isDisabled = 0'); $conditionBuilder->add('thread.movedThreadID IS NULL'); $conditionBuilder->add('(thread.lastPostTime > tracked_thread_visit.visitTime OR tracked_thread_visit.visitTime IS NULL)'); $conditionBuilder->add('(thread.lastPostTime > tracked_board_visit.visitTime OR tracked_board_visit.visitTime IS NULL)'); if (LanguageFactory::getInstance()->multilingualismEnabled() && count(WCF::getUser()->getLanguageIDs())) { $conditionBuilder->add('(thread.languageID IN (?) OR thread.languageID IS NULL)', array(WCF::getUser()->getLanguageIDs())); } $conditionBuilder->add('thread.isAnnouncement = 0'); //!!! $sql = "SELECT\t\tthread.threadID\n\t\t\t\t\tFROM\t\twbb" . WCF_N . "_thread thread\n\t\t\t\t\tLEFT JOIN\twcf" . WCF_N . "_tracked_visit tracked_thread_visit\n\t\t\t\t\tON\t\t(tracked_thread_visit.objectTypeID = " . VisitTracker::getInstance()->getObjectTypeID('com.woltlab.wbb.thread') . " AND tracked_thread_visit.objectID = thread.threadID AND tracked_thread_visit.userID = " . WCF::getUser()->userID . ")\n\t\t\t\t\tLEFT JOIN\twcf" . WCF_N . "_tracked_visit tracked_board_visit\n\t\t\t\t\tON\t\t(tracked_board_visit.objectTypeID = " . VisitTracker::getInstance()->getObjectTypeID('com.woltlab.wbb.board') . " AND tracked_board_visit.objectID = thread.boardID AND tracked_board_visit.userID = " . WCF::getUser()->userID . ")\n\t\t\t\t\t" . $conditionBuilder . "\n\t\t\t\t\tORDER BY\tthread.lastPostTime DESC"; $exttMbqSqlCount = "SELECT\t\tcount(thread.threadID) as totalNum\n\t\t\t\t\tFROM\t\twbb" . WCF_N . "_thread thread\n\t\t\t\t\tLEFT JOIN\twcf" . WCF_N . "_tracked_visit tracked_thread_visit\n\t\t\t\t\tON\t\t(tracked_thread_visit.objectTypeID = " . VisitTracker::getInstance()->getObjectTypeID('com.woltlab.wbb.thread') . " AND tracked_thread_visit.objectID = thread.threadID AND tracked_thread_visit.userID = " . WCF::getUser()->userID . ")\n\t\t\t\t\tLEFT JOIN\twcf" . WCF_N . "_tracked_visit tracked_board_visit\n\t\t\t\t\tON\t\t(tracked_board_visit.objectTypeID = " . VisitTracker::getInstance()->getObjectTypeID('com.woltlab.wbb.board') . " AND tracked_board_visit.objectID = thread.boardID AND tracked_board_visit.userID = " . WCF::getUser()->userID . ")\n\t\t\t\t\t" . $conditionBuilder; break; /* case 'undoneThreads': $boardIDs = array(); foreach ($this->boardIDs as $boardID) { if (BoardCache::getInstance()->getBoard($boardID)->enableMarkingAsDone) $boardIDs[] = $boardID; } if (empty($boardIDs)) { throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.search.error.noMatches', array('query' => ''))); } $conditionBuilder->add('thread.boardID IN (?)', array($boardIDs)); $conditionBuilder->add('thread.isDone = 0'); $conditionBuilder->add('thread.isDeleted = 0'); $conditionBuilder->add('thread.isDisabled = 0'); $conditionBuilder->add('thread.movedThreadID IS NULL'); if (LanguageFactory::getInstance()->multilingualismEnabled() && count(WCF::getUser()->getLanguageIDs())) { $conditionBuilder->add('(thread.languageID IN (?) OR thread.languageID IS NULL)', array(WCF::getUser()->getLanguageIDs())); } $sql = "SELECT thread.threadID FROM wbb".WCF_N."_thread thread ".$conditionBuilder." ORDER BY thread.lastPostTime DESC"; break; */ } // build search hash $searchHash = StringUtil::getHash($sql); // execute query $matches = array(); $statement = WCF::getDB()->prepareStatement($sql, $this->exttMbqNumPerPage, $this->exttMbqStartNum); $statement->execute($conditionBuilder->getParameters()); while ($row = $statement->fetchArray()) { $matches[] = array('objectID' => $row['threadID'], 'objectType' => 'com.woltlab.wbb.post'); } //get total count $exttMbqStatementCount = WCF::getDB()->prepareStatement($exttMbqSqlCount); $exttMbqStatementCount->execute($conditionBuilder->getParameters()); while ($exttMbqRecord = $exttMbqStatementCount->fetchArray()) { $exttMbqTotal = $exttMbqRecord['totalNum']; } // check result /* if (!count($matches)) { throw new NamedUserException(WCF::getLanguage()->getDynamicVariable('wcf.search.error.noMatches', array('query' => ''))); } */ // save result in database $searchData = array('packageID' => PACKAGE_ID, 'query' => '', 'results' => $matches, 'additionalData' => array('com.woltlab.wbb.post' => array('findThreads' => 1)), 'sortOrder' => 'DESC', 'sortField' => 'time', 'objectTypes' => array('com.woltlab.wbb.post')); $searchData = serialize($searchData); $search = SearchEditor::create(array('userID' => WCF::getUser()->userID ?: null, 'searchData' => $searchData, 'searchTime' => TIME_NOW, 'searchType' => 'messages', 'searchHash' => $searchHash)); // forward to result page //HeaderUtil::redirect(LinkHandler::getInstance()->getLink('SearchResult', array('id' => $search->searchID))); //exit; $exttMbqRetIds = array(); foreach ($matches as $exttMbqTopicId) { $exttMbqRetIds[] = $exttMbqTopicId['objectID']; } return array('total' => $exttMbqTotal, 'topicIds' => $exttMbqRetIds); }
/** * @see \wcf\form\IForm::validate() */ public function validate() { parent::validate(); // get search conditions $this->getConditions(); // check query and author if (empty($this->query) && empty($this->username) && !$this->userID) { throw new UserInputException('q'); } // build search hash $this->searchHash = StringUtil::getHash(serialize(array($this->query, $this->selectedObjectTypes, !$this->subjectOnly, $this->searchIndexCondition, $this->additionalConditions, $this->sortField . ' ' . $this->sortOrder, PACKAGE_ID))); // check search hash if (!empty($this->query)) { $parameters = array($this->searchHash, 'messages', TIME_NOW - 1800); if (WCF::getUser()->userID) { $parameters[] = WCF::getUser()->userID; } $sql = "SELECT\tsearchID\n\t\t\t\tFROM\twcf" . WCF_N . "_search\n\t\t\t\tWHERE\tsearchHash = ?\n\t\t\t\t\tAND searchType = ?\n\t\t\t\t\tAND searchTime > ?\n\t\t\t\t\t" . (WCF::getUser()->userID ? 'AND userID = ?' : 'AND userID IS NULL'); $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($parameters); $row = $statement->fetchArray(); if ($row !== false) { HeaderUtil::redirect(LinkHandler::getInstance()->getLink('SearchResult', array('id' => $row['searchID']), 'highlight=' . urlencode($this->query))); exit; } } // do search $this->results = SearchEngine::getInstance()->search($this->query, $this->selectedObjectTypes, $this->subjectOnly, $this->searchIndexCondition, $this->additionalConditions, $this->sortField . ' ' . $this->sortOrder); // result is empty if (empty($this->results)) { $this->throwNoMatchesException(); } }
/** * Returns the hash for an matched code bbcode in the message. * * @param array $matches * @return string */ protected function cacheCodesCallback($matches) { // create hash $hash = '@@' . StringUtil::getHash(uniqid(microtime()) . $matches[3]) . '@@'; // build tag $tag = $this->buildTag($matches[1]); $tag['content'] = $matches[3]; // save tag $this->cachedCodes[$hash] = $tag; return $hash; }
/** * Exports labels. */ public function exportLabels($offset, $limit) { $prefixMap = array(); // get global prefixes $globalPrefixes = ''; $sql = "SELECT\toptionValue\n\t\t\tFROM\twcf" . $this->dbNo . "_option\n\t\t\tWHERE\toptionName = ?"; $statement = $this->database->prepareStatement($sql); $statement->execute(array('thread_default_prefixes')); $row = $statement->fetchArray(); if ($row !== false) { $globalPrefixes = $row['optionValue']; } // get boards if (substr($this->getPackageVersion('com.woltlab.wcf'), 0, 3) == '1.1') { $sql = "SELECT\t\tboardID, prefixes, prefixMode\n\t\t\t\tFROM\t\twbb" . $this->dbNo . "_" . $this->instanceNo . "_board\n\t\t\t\tWHERE\t\tprefixMode > ?"; $statement = $this->database->prepareStatement($sql); $statement->execute(array(0)); } else { $sql = "SELECT\t\tboardID, prefixes, 2 AS prefixMode\n\t\t\t\tFROM\t\twbb" . $this->dbNo . "_" . $this->instanceNo . "_board\n\t\t\t\tWHERE\t\tprefixes <> ?"; $statement = $this->database->prepareStatement($sql); $statement->execute(array('')); } while ($row = $statement->fetchArray()) { $prefixes = ''; switch ($row['prefixMode']) { case 1: $prefixes = $globalPrefixes; break; case 2: $prefixes = $row['prefixes']; break; case 3: $prefixes = $globalPrefixes . "\n" . $row['prefixes']; break; } $prefixes = StringUtil::trim(StringUtil::unifyNewlines($prefixes)); if ($prefixes) { $key = StringUtil::getHash($prefixes); if (!isset($prefixMap[$key])) { $prefixMap[$key] = array('prefixes' => $prefixes, 'boardIDs' => array()); } $boardID = ImportHandler::getInstance()->getNewID('com.woltlab.wbb.board', $row['boardID']); if ($boardID) { $prefixMap[$key]['boardIDs'][] = $boardID; } } } // save prefixes if (!empty($prefixMap)) { $i = 1; $objectType = ObjectTypeCache::getInstance()->getObjectTypeByName('com.woltlab.wcf.label.objectType', 'com.woltlab.wbb.board'); foreach ($prefixMap as $key => $data) { // import label group ImportHandler::getInstance()->getImporter('com.woltlab.wcf.label.group')->import($key, array('groupName' => 'labelgroup' . $i), array('objects' => array($objectType->objectTypeID => $data['boardIDs']))); // import labels $labels = explode("\n", $data['prefixes']); foreach ($labels as $label) { ImportHandler::getInstance()->getImporter('com.woltlab.wcf.label')->import($key . '-' . $label, array('groupID' => $key, 'label' => mb_substr($label, 0, 80))); } $i++; } } }
/** * Sends the mail notification. * * @param \wcf\data\user\notification\UserNotification $notification * @param \wcf\data\user\User $user * @param \wcf\system\user\notification\event\IUserNotificationEvent $event */ public function sendInstantMailNotification(UserNotification $notification, User $user, IUserNotificationEvent $event) { // no notifications for disabled or banned users if ($user->activationCode) { return; } if ($user->banned) { return; } // recipient's language $event->setLanguage($user->getLanguage()); // add mail header $message = $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.header', array('user' => $user)) . "\n\n"; // get message $message .= $event->getEmailMessage(); // append notification mail footer $token = $user->notificationMailToken; if (!$token) { // generate token if not present $token = mb_substr(StringUtil::getHash(serialize(array($user->userID, StringUtil::getRandomID()))), 0, 20); $editor = new UserEditor($user); $editor->update(array('notificationMailToken' => $token)); } $message .= "\n\n" . $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.footer', array('user' => $user, 'token' => $token, 'notification' => $notification)); // build mail $mail = new Mail(array($user->username => $user->email), $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.subject', array('title' => $event->getEmailTitle())), $message); $mail->setLanguage($user->getLanguage()); $mail->send(); }
/** * Creates a conversation id out of the old rootLevel * and the participants. * * This ensures that only the actual receivers of a pm * are able to see it after import, while minimizing the * number of conversations. */ private function getConversationID($rootLevel, array $participants) { $conversationID = $rootLevel; $participants = array_unique($participants); sort($participants); $conversationID .= '-' . implode(',', $participants); return StringUtil::getHash($conversationID); }
/** * Loads group data from cache. */ protected function loadGroupData() { if ($this->groupData !== null) { return; } // work-around for setup process (package wcf does not exist yet) if (!PACKAGE_ID) { $groupIDs = array(); $sql = "SELECT\tgroupID\n\t\t\t\tFROM\twcf" . WCF_N . "_user_to_group\n\t\t\t\tWHERE\tuserID = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array($this->user->userID)); while ($row = $statement->fetchArray()) { $groupIDs[] = $row['groupID']; } } else { $groupIDs = $this->user->getGroupIDs(); } $groups = implode(',', $groupIDs); $groupsFileName = StringUtil::getHash($groups); // register cache resource $cacheName = 'groups-' . PACKAGE_ID . '-' . $groups; CacheHandler::getInstance()->addResource($cacheName, WCF_DIR . 'cache/cache.groups-' . PACKAGE_ID . '-' . $groupsFileName . '.php', 'wcf\\system\\cache\\builder\\UserGroupPermissionCacheBuilder'); // get group data from cache $this->groupData = CacheHandler::getInstance()->get($cacheName); if (isset($this->groupData['groupIDs']) && $this->groupData['groupIDs'] != $groups) { $this->groupData = array(); } }
/** * Returns the hash for an matched e-mail in the message. * * @param array $matches * @return string */ protected function cacheEmailsCallback($matches) { $hash = '@@' . StringUtil::getHash(uniqid(microtime()) . $matches[0]) . '@@'; $this->cachedEmails[$hash] = $matches[0]; return $hash; }
/** * @see \wcf\system\bbcode\IBBCode::getParsedTag() */ public function getParsedTag(array $openingTag, $content, array $closingTag, BBCodeParser $parser) { // copyright TeraliosBBCodesCopyright::callCopyright(); $content = StringUtil::trim($content); // check controller for parsing foot notes. if (static::$parse == null) { static::parseFootnotes(); } // footnote and fn parse. if ($openingTag['name'] == 'fn') { if (self::$parse == true) { // no content and no index for content tag: drop footnote. $content = StringUtil::trim($content); if (empty($content) && !isset($openingTag['attributes'][0])) { return ''; } // build hash from content or use index for content attribute $hash = !empty($content) ? StringUtil::getHash($content) : StringUtil::getHash($openingTag['attributes'][0]); // check footnotes for existing. if (!isset(static::$footnotes[$hash])) { // check for buffred content. if (empty($content) && isset(static::$footnoteContent[$hash])) { $content = static::$footnoteContent[$hash]; } $footnoteIndex = FootnoteMap::getInstance()->add($content, Footnote::TYPE_BBCODE); static::$footnotes[$hash] = $footnoteIndex; } else { $footnoteIndex = static::$footnotes[$hash]; } // get index for tag attribute. $footnoteTagIndex = Footnote::getTagIndex($footnoteIndex); } else { $footnoteTagIndex = ''; $footnoteIndex = static::$indexNoParse; ++static::$indexNoParse; } WCF::getTPL()->assign(array('footnoteTagID' => $footnoteTagIndex, 'footnoteIndex' => $footnoteIndex)); return WCF::getTPL()->fetch('footnoteBBCode'); } else { if ($openingTag['name'] == 'fnc') { if (static::$parse == false) { return ''; } $contentIndex = StringUtil::getHash($openingTag['attributes'][0]); // set content or buffered. if (isset(static::$footnotes[$contentIndex])) { $index = static::$footnotes[$contentIndex]; $footnote = FootnoteMap::getInstance()->getFootnote($index); if ($footnote != false) { $footnote->setText(StringUtil::trim($content), Footnote::TYPE_HTML); } } else { static::$footnoteContent[$contentIndex] = $content; } return ''; } } }
/** * @see \wcf\system\cronjob\ICronjob::execute() */ public function execute(Cronjob $cronjob) { parent::execute($cronjob); // get user ids $userIDs = array(); $sql = "SELECT\tDISTINCT userID\n\t\t\tFROM\twcf" . WCF_N . "_user_notification\n\t\t\tWHERE\tmailNotified = ?\n\t\t\t\tAND time < ?\n\t\t\t\tAND confirmTime = ?"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute(array(0, TIME_NOW - 3600 * 23, 0)); while ($row = $statement->fetchArray()) { $userIDs[] = $row['userID']; } if (empty($userIDs)) { return; } // get users $userList = new UserList(); $userList->setObjectIDs($userIDs); $userList->readObjects(); $users = $userList->getObjects(); // get notifications $conditions = new PreparedStatementConditionBuilder(); $conditions->add("notification.userID IN (?)", array($userIDs)); $conditions->add("notification.mailNotified = ?", array(0)); $conditions->add("notification.confirmTime = ?", array(0)); $sql = "SELECT\t\tnotification.*, notification_event.eventID, object_type.objectType\n\t\t\tFROM\t\twcf" . WCF_N . "_user_notification notification\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_user_notification_event notification_event\n\t\t\tON\t\t(notification_event.eventID = notification.eventID)\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_object_type object_type\n\t\t\tON\t\t(object_type.objectTypeID = notification_event.objectTypeID)\n\t\t\t" . $conditions . "\n\t\t\tORDER BY\tnotification.time"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); // mark notifications as done $conditions = new PreparedStatementConditionBuilder(); $conditions->add("userID IN (?)", array($userIDs)); $conditions->add("mailNotified = ?", array(0)); $sql = "UPDATE\twcf" . WCF_N . "_user_notification\n\t\t\tSET\tmailNotified = 1\n\t\t\t" . $conditions; $statement2 = WCF::getDB()->prepareStatement($sql); $statement2->execute($conditions->getParameters()); // collect data $eventsToUser = $objectTypes = $eventIDs = $notificationObjects = array(); $availableObjectTypes = UserNotificationHandler::getInstance()->getAvailableObjectTypes(); while ($row = $statement->fetchArray()) { if (!isset($eventsToUser[$row['userID']])) { $eventsToUser[$row['userID']] = array(); } $eventsToUser[$row['userID']][] = $row['notificationID']; // cache object types if (!isset($objectTypes[$row['objectType']])) { $objectTypes[$row['objectType']] = array('objectType' => $availableObjectTypes[$row['objectType']], 'objectIDs' => array(), 'objects' => array()); } $objectTypes[$row['objectType']]['objectIDs'][] = $row['objectID']; $eventIDs[] = $row['eventID']; $notificationObjects[$row['notificationID']] = new UserNotification(null, $row); } // load authors $conditions = new PreparedStatementConditionBuilder(); $conditions->add("notificationID IN (?)", array(array_keys($notificationObjects))); $sql = "SELECT\t\tnotificationID, authorID\n\t\t\tFROM\t\twcf" . WCF_N . "_user_notification_author\n\t\t\t" . $conditions . "\n\t\t\tORDER BY\ttime ASC"; $statement = WCF::getDB()->prepareStatement($sql); $statement->execute($conditions->getParameters()); $authorIDs = $authorToNotification = array(); while ($row = $statement->fetchArray()) { if ($row['authorID']) { $authorIDs[] = $row['authorID']; } if (!isset($authorToNotification[$row['notificationID']])) { $authorToNotification[$row['notificationID']] = array(); } $authorToNotification[$row['notificationID']][] = $row['authorID']; } // load authors $authors = UserProfile::getUserProfiles($authorIDs); $unknownAuthor = new UserProfile(new User(null, array('userID' => null, 'username' => WCF::getLanguage()->get('wcf.user.guest')))); // load objects associated with each object type foreach ($objectTypes as $objectType => $objectData) { $objectTypes[$objectType]['objects'] = $objectData['objectType']->getObjectsByIDs($objectData['objectIDs']); } // load required events $eventList = new UserNotificationEventList(); $eventList->getConditionBuilder()->add("user_notification_event.eventID IN (?)", array($eventIDs)); $eventList->readObjects(); $eventObjects = $eventList->getObjects(); foreach ($eventsToUser as $userID => $events) { if (!isset($users[$userID])) { continue; } $user = $users[$userID]; // no notifications for disabled or banned users if ($user->activationCode) { continue; } if ($user->banned) { continue; } // add mail header $message = $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.header', array('user' => $user)); foreach ($events as $notificationID) { $notification = $notificationObjects[$notificationID]; $className = $eventObjects[$notification->eventID]->className; $class = new $className($eventObjects[$notification->eventID]); $class->setObject($notification, $objectTypes[$notification->objectType]['objects'][$notification->objectID], isset($authors[$notification->authorID]) ? $authors[$notification->authorID] : $unknownAuthor, $notification->additionalData); $class->setLanguage($user->getLanguage()); if (isset($authorToNotification[$notification->notificationID])) { $eventAuthors = array(); foreach ($authorToNotification[$notification->notificationID] as $userID) { if (!$userID) { $eventAuthors[0] = $unknownAuthor; } else { if (isset($authors[$userID])) { $eventAuthors[$userID] = $authors[$userID]; } } } if (!empty($eventAuthors)) { $class->setAuthors($eventAuthors); } } $message .= "\n\n"; $message .= $class->getEmailMessage('daily'); } // append notification mail footer $token = $user->notificationMailToken; if (!$token) { // generate token if not present $token = mb_substr(StringUtil::getHash(serialize(array($user->userID, StringUtil::getRandomID()))), 0, 20); $editor = new UserEditor($user); $editor->update(array('notificationMailToken' => $token)); } $message .= "\n\n"; $message .= $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.daily.footer', array('user' => $user, 'token' => $token)); // build mail $mail = new Mail(array($user->username => $user->email), $user->getLanguage()->getDynamicVariable('wcf.user.notification.mail.daily.subject', array('count' => count($events))), $message); $mail->setLanguage($user->getLanguage()); $mail->send(); } }
/** * Returns a string with all line numbers * * @param string $code * @param integer $start * @return string */ protected static function makeLineNumbers($code, $start, $split = "\n") { $lines = explode($split, $code); $lineNumbers = array(); $i = -1; // find an unused codeID do { $codeID = mb_substr(StringUtil::getHash($code), 0, 6) . (++$i ? '_' . $i : ''); } while (isset(self::$codeIDs[$codeID])); // mark codeID as used self::$codeIDs[$codeID] = true; for ($i = $start, $j = count($lines) + $start; $i < $j; $i++) { $lineNumbers[$i] = 'codeLine_' . $i . '_' . $codeID; } return $lineNumbers; }