/**
  * @see Action::execute()
  */
 public function execute()
 {
     parent::execute();
     // check permission
     WCF::getUser()->checkPermission('admin.user.canMailUser');
     // sql condition
     $condition = '';
     if ($this->userMailData['action'] == '') {
         $condition = "WHERE user.userID IN (" . $this->userMailData['userIDs'] . ")";
     }
     if ($this->userMailData['action'] == 'group') {
         $condition = "WHERE user.userID IN (SELECT userID FROM wcf" . WCF_N . "_user_to_groups WHERE groupID IN (" . $this->userMailData['groupIDs'] . "))";
     }
     // count users
     $sql = "SELECT\tCOUNT(*) AS count\n\t\t\tFROM\twcf" . WCF_N . "_user user\n\t\t\t" . $condition;
     $row = WCF::getDB()->getFirstRow($sql);
     $count = $row['count'];
     if ($count <= $this->limit * $this->loop) {
         // unmark users
         UserEditor::unmarkAll();
         // clear session
         $userMailData = WCF::getSession()->getVar('userMailData');
         unset($userMailData[$this->mailID]);
         WCF::getSession()->register('userMailData', $userMailData);
         $this->calcProgress();
         $this->finish();
     }
     // get users
     $sql = "SELECT\t\tuser_option.*, user.*\n\t\t\tFROM\t\twcf" . WCF_N . "_user user\n\t\t\tLEFT JOIN\twcf" . WCF_N . "_user_option_value user_option\n\t\t\tON\t\t(user_option.userID = user.userID)\n\t\t\t" . $condition . "\n\t\t\tORDER BY\tuser.userID";
     $result = WCF::getDB()->sendQuery($sql, $this->limit, $this->limit * $this->loop);
     while ($row = WCF::getDB()->fetchArray($result)) {
         $user = new User(null, $row);
         $adminCanMail = $user->adminCanMail;
         if ($adminCanMail === null || $adminCanMail == 1) {
             $this->sendMail($user);
         }
     }
     $this->executed();
     $this->calcProgress($this->limit * $this->loop, $count);
     $this->nextLoop('wcf.acp.worker.progress.working', 'index.php?action=' . $this->action . '&mailID=' . $this->mailID . '&limit=' . $this->limit . '&loop=' . ($this->loop + 1) . '&packageID=' . PACKAGE_ID . SID_ARG_2ND_NOT_ENCODED);
 }
 /**
  * @see Action::execute()
  */
 public function execute()
 {
     parent::execute();
     // export is not finished. export further
     if (empty($this->downloadFile)) {
         // get session data
         $sessionData = WCF::getSession()->getVar('databaseExportData');
         $loopTimeLimit = $sessionData['loopTimeLimit'];
         $isGzip = $sessionData['isGzip'];
         $limit = $sessionData['limit'];
         $tableName = $sessionData['tableName'];
         $offset = $sessionData['offset'];
         $importErrors = '';
         $stepInfo = array();
         // start export operations
         $loopStart = time();
         $backupFile = $sessionData['backupFile'];
         $tables = $sessionData['tables'];
         // TODO: check if file could be opened (e.g. if directory exists)
         // open backupfile
         if ($isGzip) {
             $file = new ZipFile($backupFile, $offset == -1 ? 'wb' : 'ab');
         } else {
             $file = new File($backupFile, $offset == -1 ? 'wb' : 'ab');
         }
         // export database operations (only up to $limit)
         $stepInfo = DatabaseDumper::export($file, $tables, $limit, $loopTimeLimit, $loopStart, $offset, $tableName);
         // delete completed tables from session
         foreach ($stepInfo['completedTables'] as $table) {
             $key = array_search($table, $sessionData['tables']);
             if ($key !== false) {
                 unset($sessionData['tables'][$key]);
             }
         }
         $loopEnd = time();
         $duration = $loopEnd - $loopStart;
         // check if limit should be changed (more or less db-operations per loop)
         if ($stepInfo['resetLimit']) {
             $sessionData['limit'] = 250;
         } elseif ($duration != $loopTimeLimit) {
             // higher export step size
             if ($duration > 0) {
                 $sessionData['limit'] = round($limit * ($loopTimeLimit / $duration), 0);
             } else {
                 $sessionData['limit'] = $limit * 10;
             }
         }
         // refresh session data
         $sessionData['tableName'] = $stepInfo['tableName'];
         $sessionData['offset'] = $stepInfo['offset'];
         $sessionData['remain'] -= $stepInfo['done'];
         // show finish
         if ($sessionData['remain'] <= 0) {
             // cleanup session data. save backupFile to session
             WCF::getSession()->register('databaseExportData', $backupFile);
             WCF::getTPL()->assign(array('export' => true, 'success' => true, 'totalTables' => $sessionData['tableCount'], 'totalRecords' => $sessionData['rowCount'], 'backupFile' => $backupFile));
             WCF::getTPL()->append('message', WCF::getTPL()->fetch('dbMessage'));
             $title = 'wcf.acp.db.progress.finish';
             $this->calcProgress($sessionData['count'] - $sessionData['remain'], $sessionData['count']);
             $this->finish($title, 'index.php?form=DatabaseExport&packageID=' . PACKAGE_ID . SID_ARG_2ND_NOT_ENCODED);
         }
         WCF::getSession()->register('databaseExportData', $sessionData);
         // refresh progressbar and go to the next step
         $title = 'wcf.acp.db.export.progress.working';
         $this->calcProgress($sessionData['count'] - $sessionData['remain'], $sessionData['count']);
         $this->nextLoop($title);
     } else {
         $fileName = basename($this->downloadFile);
         $backupFile = WCF::getSession()->getVar('databaseExportData');
         WCF::getSession()->unregister('databaseExportData');
         if ($this->downloadFile == $backupFile) {
             // file type
             header('Content-Type: application/octet-stream');
             // file name
             header('Content-Disposition: attachment; filename="' . $fileName . '"');
             // send file size
             header('Content-Length: ' . filesize($this->downloadFile));
             // no cache headers
             header('Pragma: no-cache');
             header('Expires: 0');
             // send file
             readfile($this->downloadFile);
         } else {
             throw new SystemException("Expected parameter for download file: " . $this->downloadFile, 102000);
         }
     }
 }
 /**
  * @see Action::execute()
  */
 public function execute()
 {
     parent::execute();
     // get session data
     $sessionData = WCF::getSession()->getVar('databaseImportData');
     $filesize = $sessionData['filesize'];
     $isGzip = $sessionData['isGzip'];
     $extendedCommand = $sessionData['extendedCommand'];
     $offset = $sessionData['offset'];
     $charset = $sessionData['importCharset'];
     $ignoreErrors = $sessionData['ignoreErrors'];
     $importErrors = '';
     $stepInfo = array();
     // start export operations
     $loopStart = time();
     $importFile = $sessionData['importFile'];
     if ($isGzip) {
         $file = new ZipFile($importFile, 'rb');
     } else {
         $file = new File($importFile, 'rb');
     }
     // import database operations (only up to $this->limit)
     $loopInfo = DatabaseDumper::import($file, $filesize, $isGzip, $this->limit, $loopStart, $offset, $charset, $extendedCommand, $ignoreErrors);
     $file->close();
     // store charset
     if (!empty($loopInfo['charset']) && $loopInfo['charset'] != $sessionData['wcfCharset']) {
         $sessionData['importCharset'] = $loopInfo['charset'];
     }
     // delete aftereffected erros (no insert errors will be displayed if the table caused an error before)
     $tableErrors = $sessionData['tableErrors'];
     foreach ($loopInfo['errors']['messages'] as $key => $message) {
         if (preg_match("/CREATE TABLE `?(\\w+)`?/i", $message, $match)) {
             $tableErrors[] = $match[1];
         } elseif (preg_match("/(INSERT|REPLACE).*?INTO `?(\\w+)`?/i", $message, $match)) {
             if (in_array($match[1], $tableErrors)) {
                 unset($loopInfo['errors']['messages'][$key]);
                 unset($loopInfo['errors']['errorDescriptions'][$key]);
             } else {
                 $tableErrors[] = $match[1];
             }
         }
     }
     // save errors
     $errors = array('messages' => array_merge($sessionData['errors']['messages'], $loopInfo['errors']['messages']), 'errorDescriptions' => array_merge($sessionData['errors']['errorDescriptions'], $loopInfo['errors']['errorDescriptions']));
     $sessionData['errors'] = $errors;
     $sessionData['tableErrors'] = $tableErrors;
     // refresh session data
     $sessionData['extendedCommand'] = $loopInfo['extendedCommand'];
     $sessionData['offset'] = $loopInfo['offset'];
     $sessionData['remain'] -= $loopInfo['done'];
     $sessionData['commandCount'] += $loopInfo['commandCount'];
     // calculate progressbar
     $this->calcProgress($sessionData['count'] - $sessionData['remain'], $sessionData['count']);
     // show finish
     if ($sessionData['remain'] <= 0) {
         // reset charset for database connection
         if (!empty($sessionData['importCharset'])) {
             WCF::getDB()->setCharset($sessionData['wcfCharset']);
         }
         // cleanup session data
         WCF::getSession()->unregister('databaseImportData');
         // delete imported upload/remote file
         if ($sessionData['isTmpFile']) {
             @unlink($importFile);
         }
         // clear all standalone caches
         // get standalone package directories
         $sql = "SELECT\tpackageDir \n\t\t\t\tFROM\twcf" . WCF_N . "_package\n\t\t\t\tWHERE\tstandalone = 1\n\t\t\t\t\tAND packageDir <> ''";
         $result = WCF::getDB()->sendQuery($sql);
         while ($row = WCF::getDB()->fetchArray($result)) {
             // check if standalone package got cache directory
             $realPackageDir = FileUtil::addTrailingSlash(FileUtil::getRealPath(WCF_DIR . $row['packageDir']));
             if (file_exists($realPackageDir . 'cache')) {
                 // delete all cache files
                 WCF::getCache()->clear($realPackageDir . 'cache', '*.php', true);
             }
         }
         // clear wcf cache
         WCF::getCache()->clear(WCF_DIR . 'cache', '*.php', true);
         // delete all language files
         LanguageEditor::updateAll();
         // set data for template
         WCF::getTPL()->assign(array('import' => true, 'success' => empty($errors['messages']) && $sessionData['commandCount'] > 0, 'commandCount' => $sessionData['commandCount'], 'errors' => $errors));
         WCF::getTPL()->append('message', WCF::getTPL()->fetch('dbMessage'));
         // show finish template
         $title = 'wcf.acp.db.progress.finish';
         $this->finish($title, 'index.php?form=DatabaseImport&packageID=' . PACKAGE_ID . SID_ARG_2ND_NOT_ENCODED);
     }
     WCF::getSession()->register('databaseImportData', $sessionData);
     // next loop
     $title = 'wcf.acp.db.import.progress.working';
     $this->nextLoop($title);
 }
 /**
  * Shows the worker finish page.
  */
 protected function finish($title = '', $url = '')
 {
     parent::finish('wcf.acp.worker.progress.finish', 'index.php?form=UpdateCounters&packageID=' . PACKAGE_ID . SID_ARG_2ND_NOT_ENCODED);
 }
 /**
  * @see Action::execute()
  */
 public function execute()
 {
     parent::execute();
     // check permission
     WCF::getUser()->checkPermission('admin.user.canPMToUserGroups');
     $sql = "SELECT COUNT(DISTINCT u.userID) AS cnt" . "\n  FROM wcf" . WCF_N . "_user u" . "\n  LEFT JOIN wcf" . WCF_N . "_user_to_groups g ON (g.userID = u.userID)" . "\n  LEFT JOIN wcf" . WCF_N . "_group_option_value v ON (v.groupID = g.groupID)" . "\n  LEFT JOIN wcf" . WCF_N . "_group_option o ON (o.optionID = v.optionID)" . "\n WHERE o.optionName = 'user.pm.canUsePm'" . "\n   AND v.optionValue = '1'" . "\n   AND u.userID != " . $this->userID . "\n   AND g.groupID IN (" . $this->pmData['groupIDs'] . ")";
     $row = WCF::getDB()->getFirstRow($sql);
     $count = $row['cnt'];
     if (!$count > 0) {
         // clear session
         if (isset($this->pmData)) {
             $pmData = WCF::getSession()->getVar('pmData');
             unset($pmData[$this->pmSessionID]);
             WCF::getSession()->register('pmData', $pmData);
         }
         $this->finish('wcf.pmToUgrps.error.noRecipients', 'index.php?form=PMToUserGroups&packageID=' . PACKAGE_ID . SID_ARG_2ND_NOT_ENCODED);
     }
     if ($count <= $this->limit * $this->loop) {
         $endTime = TIME_NOW;
         $lf = "\n";
         // remove from outbox
         $sql = "UPDATE wcf" . WCF_N . "_pm" . "\n   SET saveInOutbox = 0" . "\n WHERE pmID = " . $this->pmID;
         WCF::getDB()->sendQuery($sql);
         // groups...
         $groups = '';
         $sql = "SELECT groupName" . "\n  FROM wcf" . WCF_N . "_group" . "\n WHERE groupID IN (" . $this->pmData['groupIDs'] . ")" . "\n ORDER BY groupName";
         $result = WCF::getDB()->sendQuery($sql);
         while ($row = WCF::getDB()->fetchArray($result)) {
             if (!empty($groups)) {
                 $groups .= ', ';
             }
             $groups .= StringUtil::decodeHTML($row['groupName']);
         }
         // log...
         $log = '';
         $subject = WCF::getLanguage()->get('wcf.pmToUgrps.log.subject', array('$pmID' => $this->pmID)) . ' ' . $this->pmData['subject'];
         if ($this->pmData['enableHtml']) {
             $log .= '<pre>';
         }
         $log .= WCF::getLanguage()->get('wcf.pmToUgrps.log.started', array('$startTime' => DateUtil::formatDate('%d.%m.%Y %H:%M:%S', $this->pmData['startTime']))) . $lf;
         $log .= WCF::getLanguage()->get('wcf.pmToUgrps.log.finished', array('$endTime' => DateUtil::formatDate('%d.%m.%Y %H:%M:%S', $endTime))) . $lf;
         $log .= WCF::getLanguage()->get('wcf.pmToUgrps.log.recipients', array('$groups' => $groups, '$count' => StringUtil::decodeHTML(StringUtil::formatInteger($count)))) . $lf;
         $log .= str_repeat('-', 60) . $lf;
         if ($this->pmData['enableHtml']) {
             $log .= '</pre>' . $lf;
         }
         $log .= $this->pmData['text'];
         $this->recipientArray = $this->blindCopyArray = array();
         $this->recipientArray[0]['userID'] = $this->userID;
         $this->recipientArray[0]['username'] = $this->username;
         PMEditor::create($this->draft, $this->recipientArray, $this->blindCopyArray, $subject, $log, $this->userID, $this->username, array('enableSmilies' => $this->pmData['enableSmilies'], 'enableHtml' => $this->pmData['enableHtml'], 'enableBBCodes' => $this->pmData['enableBBCodes'], 'showSignature' => false));
         // clear session
         $pmData = WCF::getSession()->getVar('pmData');
         unset($pmData[$this->pmSessionID]);
         WCF::getSession()->register('pmData', $pmData);
         $this->calcProgress();
         $msg = WCF::getLanguage()->get('wcf.pmToUgrps.finish', array('$count' => StringUtil::decodeHTML(StringUtil::formatInteger($count)), '$startTime' => DateUtil::formatShortTime('%H:%M:%S', $this->pmData['startTime']), '$endTime' => DateUtil::formatShortTime('%H:%M:%S', $endTime)));
         $this->finish($msg, 'index.php?form=PMToUserGroups&packageID=' . PACKAGE_ID . SID_ARG_2ND_NOT_ENCODED);
     }
     // get users
     $sql = "SELECT DISTINCT u.userID, u.username" . "\n  FROM wcf" . WCF_N . "_user u" . "\n  LEFT JOIN wcf" . WCF_N . "_user_to_groups g ON (g.userID = u.userID)" . "\n  LEFT JOIN wcf" . WCF_N . "_group_option_value v ON (v.groupID = g.groupID)" . "\n  LEFT JOIN wcf" . WCF_N . "_group_option o ON (o.optionID = v.optionID)" . "\n WHERE o.optionName = 'user.pm.canUsePm'" . "\n   AND v.optionValue = '1'" . "\n   AND u.userID != " . $this->userID . "\n   AND g.groupID IN (" . $this->pmData['groupIDs'] . ")" . "\n ORDER BY u.userID";
     $this->blindCopyArray = array();
     $i = 0;
     $result = WCF::getDB()->sendQuery($sql, $this->limit, $this->limit * $this->loop);
     while ($row = WCF::getDB()->fetchArray($result)) {
         $this->blindCopyArray[$i]['userID'] = $row['userID'];
         $this->blindCopyArray[$i]['username'] = $row['username'];
         $i++;
     }
     if (count($this->blindCopyArray)) {
         if (empty($this->pmID)) {
             $tmp = PMEditor::create($this->draft, $this->recipientArray, $this->blindCopyArray, $this->pmData['subject'], $this->pmData['text'], $this->userID, $this->username, array('enableSmilies' => $this->pmData['enableSmilies'], 'enableHtml' => $this->pmData['enableHtml'], 'enableBBCodes' => $this->pmData['enableBBCodes'], 'showSignature' => $this->pmData['showSignature']));
             if ($tmp->pmID) {
                 $this->pmID = intval($tmp->pmID);
                 $pmData = WCF::getSession()->getVar('pmData');
                 $pmData[$this->pmSessionID]['pmID'] = $this->pmID;
                 WCF::getSession()->register('pmData', $pmData);
                 $mlt = intval($this->pmData['maxLifeTime']);
                 if ($mlt > 0) {
                     $mlt = $this->pmData['startTime'] + 86400 * $mlt;
                 } else {
                     $mlt = 0;
                 }
                 $sql = "INSERT IGNORE INTO wcf" . WCF_N . "_pm_bulk_mailing" . "\n       (pmID, elapsedTime, time, userID)" . "\nVALUES (" . $this->pmID . ", " . $mlt . ", " . $this->pmData['startTime'] . ", " . $this->userID . ")";
                 WCF::getDB()->sendQuery($sql);
             }
         } else {
             $recipientIDs = $inserts = '';
             foreach ($this->blindCopyArray as $k => $v) {
                 $username = WCF::getDB()->escapeString($this->blindCopyArray[$k]['username']);
                 if (!empty($recipientIDs)) {
                     $recipientIDs .= ',';
                 }
                 $recipientIDs .= $this->blindCopyArray[$k]['userID'];
                 if (!empty($inserts)) {
                     $inserts .= ',';
                 }
                 $inserts .= "\n       (" . $this->pmID . ", " . intval($this->blindCopyArray[$k]['userID']) . ", '" . $username . "', 1)";
             }
             if (!empty($recipientIDs) && !empty($inserts)) {
                 $sql = "INSERT IGNORE INTO wcf" . WCF_N . "_pm_to_user" . "\n       (pmID, recipientID, recipient, isBlindCopy)" . "\nVALUES " . $inserts;
                 WCF::getDB()->sendQuery($sql);
                 PMEditor::updateUnreadMessageCount($recipientIDs);
                 PMEditor::updateTotalMessageCount($recipientIDs);
                 Session::resetSessions($recipientIDs, true, false);
             }
         }
     }
     $this->executed();
     $this->calcProgress($this->limit * $this->loop, $count);
     $msg = WCF::getLanguage()->get('wcf.pmToUgrps.progress', array('$loop' => StringUtil::decodeHTML(StringUtil::formatInteger($this->limit * $this->loop)), '$count' => StringUtil::decodeHTML(StringUtil::formatInteger($count))));
     $this->nextLoop($msg, 'index.php?action=' . $this->action . '&pmSessionID=' . $this->pmSessionID . '&limit=' . $this->limit . '&loop=' . ($this->loop + 1) . '&packageID=' . PACKAGE_ID . SID_ARG_2ND_NOT_ENCODED);
 }