= __('Orphan Request') ?>: = __('Request a package to be disowned, e.g. when the maintainer is inactive and the package has been flagged out-of-date for a long time.') ?>
-
= __('Deletion Request') ?>: = __('Request a package to be removed from the Arch User Repository. Please do not use this if a package is broken and can be fixed easily. Instead, contact the package maintainer and file orphan request if necessary.') ?>
-
= __('Merge Request') ?>: = __('Request a package to be merged into another one. Can be used when a package needs to be renamed or replaced by a split package.') ?>
-
-
- ',
- ''
- );
- ?>
-
-
-
= __('Submitting Packages') ?>
-
-
- ',
- ''
- );
- ?>
-
-
-
- = __('The following SSH fingerprints are used for the AUR:') ?>
-
= __('Check your e-mail for the confirmation link.') ?>
-
-
= __('Your password has been reset successfully.') ?>
-
-
-
= $error ?>
-
-
-
-
= __('If you have forgotten the user name and the primary e-mail address you used to register, please send a message to the %saur-general%s mailing list.',
- '',
- ''); ?>
- = __('Use this form to disown the package base %s%s%s which includes the following packages: ',
- '', htmlspecialchars($pkgbase_name), ''); ?>
-
-
-
-
= htmlspecialchars($pkgname) ?>
-
-
-
-
-
- = __("By selecting the checkbox, you confirm that you want to no longer be a package co-maintainer.") ?>
- 0 && !has_credential(CRED_PKGBASE_DISOWN)): ?>
- = __('By selecting the checkbox, you confirm that you want to disown the package and transfer ownership to %s%s%s.',
- '', $comaintainers[0], ''); ?>
-
- = __('By selecting the checkbox, you confirm that you want to disown the package.') ?>
-
-
- = __('Use this form to flag the package base %s%s%s and the following packages out-of-date: ',
- '', htmlspecialchars($pkgbase_name), ''); ?>
-
-
-
-
= htmlspecialchars($pkgname) ?>
-
-
-
-
- This seems to be a VCS package. Please do not
- flag it out-of-date if the package version in the AUR does not
- match the most recent commit. Flagging this package should only
- be done if the sources moved or changes in the PKGBUILD are
- required because of recent upstream changes.
-
-
-
- = __('Please do %snot%s use this form to report bugs. Use the package comments instead.',
- '', ''); ?>
- = __('Enter details on why the package is out-of-date below, preferably including links to the release announcement or the new release tarball.'); ?>
-
- = __('Use this form to merge the package base %s%s%s into another package. ',
- '', htmlspecialchars($pkgbase_name), ''); ?>
- = __('The following packages will be deleted: '); ?>
-
-
-
-
= htmlspecialchars($pkgname) ?>
-
-
-
- = __('Once the package has been merged it cannot be reversed. '); ?>
- = __('Enter the package name you wish to merge the package into. '); ?>
- = __('Select the checkbox to confirm action.') ?>
-
\n";
-
- if ($send_resetkey) {
- send_resetkey($email, true);
- $message .= __("A password reset key has been sent to your e-mail address.");
- $message .= "
\n";
- } else {
- $message .= __("Click on the Login link above to use your account.");
- $message .= "
\n";
- }
- } else {
- /* Modify an existing account. */
- $q = "SELECT InactivityTS FROM Users WHERE ";
- $q.= "ID = " . intval($UID);
- $result = $dbh->query($q);
- $row = $result->fetch(PDO::FETCH_NUM);
- if ($row[0] && $J) {
- $inactivity_ts = $row[0];
- } elseif ($J) {
- $inactivity_ts = time();
- } else {
- $inactivity_ts = 0;
- }
-
- $q = "UPDATE Users SET ";
- $q.= "Username = " . $dbh->quote($U);
- if ($T) {
- $q.= ", AccountTypeID = ".intval($T);
- }
- if ($S) {
- /* Ensure suspended users can't keep an active session */
- delete_user_sessions($UID);
- $q.= ", Suspended = 1";
- } else {
- $q.= ", Suspended = 0";
- }
- $q.= ", Email = " . $dbh->quote($E);
- $q.= ", BackupEmail = " . $dbh->quote($BE);
- if ($H) {
- $q.= ", HideEmail = 1";
- } else {
- $q.= ", HideEmail = 0";
- }
- if ($P) {
- $hash = password_hash($P, PASSWORD_DEFAULT);
- $q .= ", Passwd = " . $dbh->quote($hash);
- }
- $q.= ", RealName = " . $dbh->quote($R);
- $q.= ", LangPreference = " . $dbh->quote($L);
- $q.= ", Timezone = " . $dbh->quote($TZ);
- $q.= ", Homepage = " . $dbh->quote($HP);
- $q.= ", IRCNick = " . $dbh->quote($I);
- $q.= ", PGPKey = " . $dbh->quote(str_replace(" ", "", $K));
- $q.= ", InactivityTS = " . $inactivity_ts;
- $q.= ", CommentNotify = " . ($CN ? "1" : "0");
- $q.= ", UpdateNotify = " . ($UN ? "1" : "0");
- $q.= ", OwnershipNotify = " . ($ON ? "1" : "0");
- $q.= " WHERE ID = ".intval($UID);
- $result = $dbh->exec($q);
-
- if (isset($ssh_keys) && count($ssh_keys) > 0) {
- $ssh_key_result = account_set_ssh_keys($UID, $ssh_keys, $ssh_fingerprints);
- } else {
- $ssh_key_result = true;
- }
-
- if (isset($_COOKIE["AURTZ"]) && ($_COOKIE["AURTZ"] != $TZ)) {
- /* set new cookie for timezone */
- $timeout = intval(config_get("options", "persistent_cookie_timeout"));
- $cookie_time = time() + $timeout;
- setcookie("AURTZ", $TZ, $cookie_time, "/");
- }
-
- if (isset($_COOKIE["AURLANG"]) && ($_COOKIE["AURLANG"] != $L)) {
- /* set new cookie for language */
- $timeout = intval(config_get("options", "persistent_cookie_timeout"));
- $cookie_time = time() + $timeout;
- setcookie("AURLANG", $L, $cookie_time, "/");
- }
-
- if ($result === false || $ssh_key_result === false) {
- $message = __("No changes were made to the account, %s%s%s.",
- "", htmlspecialchars($U,ENT_QUOTES), "");
- } else {
- $message = __("The account, %s%s%s, has been successfully modified.",
- "", htmlspecialchars($U,ENT_QUOTES), "");
- }
- }
-
- return array(true, $message);
-}
-
-/**
- * Display the search results page
- *
- * @param string $O The offset for the results page
- * @param string $SB The column to sort the results page by
- * @param string $U The username search criteria
- * @param string $T The account type search criteria
- * @param string $S Whether the account is suspended search criteria
- * @param string $E The e-mail address search criteria
- * @param string $R The real name search criteria
- * @param string $I The IRC nickname search criteria
- * @param string $K The PGP key fingerprint search criteria
- *
- * @return void
- */
-function search_results_page($O=0,$SB="",$U="",$T="",
- $S="",$E="",$R="",$I="",$K="") {
-
- $HITS_PER_PAGE = 50;
- if ($O) {
- $OFFSET = intval($O);
- } else {
- $OFFSET = 0;
- }
- if ($OFFSET < 0) {
- $OFFSET = 0;
- }
- $search_vars = array();
-
- $dbh = DB::connect();
-
- $q = "SELECT Users.*, AccountTypes.AccountType ";
- $q.= "FROM Users, AccountTypes ";
- $q.= "WHERE AccountTypes.ID = Users.AccountTypeID ";
- if ($T == "u") {
- $q.= "AND AccountTypes.ID = 1 ";
- $search_vars[] = "T";
- } elseif ($T == "t") {
- $q.= "AND AccountTypes.ID = 2 ";
- $search_vars[] = "T";
- } elseif ($T == "d") {
- $q.= "AND AccountTypes.ID = 3 ";
- $search_vars[] = "T";
- } elseif ($T == "td") {
- $q.= "AND AccountTypes.ID = 4 ";
- $search_vars[] = "T";
- }
- if ($S) {
- $q.= "AND Users.Suspended = 1 ";
- $search_vars[] = "S";
- }
- if ($U) {
- $U = "%" . addcslashes($U, '%_') . "%";
- $q.= "AND Username LIKE " . $dbh->quote($U) . " ";
- $search_vars[] = "U";
- }
- if ($E) {
- $E = "%" . addcslashes($E, '%_') . "%";
- $q.= "AND Email LIKE " . $dbh->quote($E) . " ";
- $search_vars[] = "E";
- }
- if ($R) {
- $R = "%" . addcslashes($R, '%_') . "%";
- $q.= "AND RealName LIKE " . $dbh->quote($R) . " ";
- $search_vars[] = "R";
- }
- if ($I) {
- $I = "%" . addcslashes($I, '%_') . "%";
- $q.= "AND IRCNick LIKE " . $dbh->quote($I) . " ";
- $search_vars[] = "I";
- }
- if ($K) {
- $K = "%" . addcslashes(str_replace(" ", "", $K), '%_') . "%";
- $q.= "AND PGPKey LIKE " . $dbh->quote($K) . " ";
- $search_vars[] = "K";
- }
- switch ($SB) {
- case 't':
- $q.= "ORDER BY AccountTypeID, Username ";
- break;
- case 'r':
- $q.= "ORDER BY RealName, AccountTypeID ";
- break;
- case 'i':
- $q.= "ORDER BY IRCNick, AccountTypeID ";
- break;
- default:
- $q.= "ORDER BY Username, AccountTypeID ";
- break;
- }
- $search_vars[] = "SB";
- $q.= "LIMIT " . $HITS_PER_PAGE . " OFFSET " . $OFFSET;
-
- $dbh = DB::connect();
-
- $result = $dbh->query($q);
-
- $userinfo = array();
- if ($result) {
- while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
- $userinfo[] = $row;
- }
- }
-
- include("account_search_results.php");
- return;
-}
-
-/**
- * Attempt to login and generate a session
- *
- * @return array Session ID for user, error message if applicable
- */
-function try_login() {
- $login_error = "";
- $new_sid = "";
- $userID = null;
-
- if (!isset($_REQUEST['user']) && !isset($_REQUEST['passwd'])) {
- return array('SID' => '', 'error' => null);
- }
-
- if (is_ipbanned()) {
- $login_error = __('The login form is currently disabled ' .
- 'for your IP address, probably due ' .
- 'to sustained spam attacks. Sorry for the ' .
- 'inconvenience.');
- return array('SID' => '', 'error' => $login_error);
- }
-
- $dbh = DB::connect();
- $userID = uid_from_loginname($_REQUEST['user']);
-
- if (user_suspended($userID)) {
- $login_error = __('Account suspended');
- return array('SID' => '', 'error' => $login_error);
- }
-
- switch (check_passwd($userID, $_REQUEST['passwd'])) {
- case -1:
- $login_error = __('Your password has been reset. ' .
- 'If you just created a new account, please ' .
- 'use the link from the confirmation email ' .
- 'to set an initial password. Otherwise, ' .
- 'please request a reset key on the %s' .
- 'Password Reset%s page.', '',
- '');
- return array('SID' => '', 'error' => $login_error);
- case 0:
- $login_error = __("Bad username or password.");
- return array('SID' => '', 'error' => $login_error);
- case 1:
- break;
- }
-
- $logged_in = 0;
- $num_tries = 0;
-
- /* Generate a session ID and store it. */
- while (!$logged_in && $num_tries < 5) {
- $new_sid = new_sid();
- $q = "INSERT INTO Sessions (UsersID, SessionID, LastUpdateTS)"
- ." VALUES (" . $userID . ", '" . $new_sid . "', " . strval(time()) . ")";
- $result = $dbh->exec($q);
-
- /* Query will fail if $new_sid is not unique. */
- if ($result) {
- $logged_in = 1;
- break;
- }
-
- $num_tries++;
- }
-
- if (!$logged_in) {
- $login_error = __('An error occurred trying to generate a user session.');
- return array('SID' => $new_sid, 'error' => $login_error);
- }
-
- $q = "UPDATE Users SET LastLogin = " . strval(time()) . ", ";
- $q.= "LastLoginIPAddress = " . $dbh->quote($_SERVER['REMOTE_ADDR']) . " ";
- $q.= "WHERE ID = $userID";
- $dbh->exec($q);
-
- /* Set the SID cookie. */
- if (isset($_POST['remember_me']) && $_POST['remember_me'] == "on") {
- /* Set cookies for 30 days. */
- $timeout = config_get_int('options', 'persistent_cookie_timeout');
- $cookie_time = time() + $timeout;
-
- /* Set session for 30 days. */
- $q = "UPDATE Sessions SET LastUpdateTS = $cookie_time ";
- $q.= "WHERE SessionID = '$new_sid'";
- $dbh->exec($q);
- } else {
- $cookie_time = 0;
- }
-
- setcookie("AURSID", $new_sid, $cookie_time, "/", null, !empty($_SERVER['HTTPS']), true);
-
- $referer = in_request('referer');
- if (strpos($referer, aur_location()) !== 0) {
- $referer = '/';
- }
- header("Location: " . get_uri($referer));
- $login_error = "";
- return array('SID' => $new_sid, 'error' => null);
-}
-
-/**
- * Determine if the user is using a banned IP address
- *
- * @return bool True if IP address is banned, otherwise false
- */
-function is_ipbanned() {
- $dbh = DB::connect();
-
- $q = "SELECT * FROM Bans WHERE IPAddress = " . $dbh->quote($_SERVER['REMOTE_ADDR']);
- $result = $dbh->query($q);
-
- return ($result->fetchColumn() ? true : false);
-}
-
-/**
- * Validate a username against a collection of rules
- *
- * The username must be longer or equal to the configured minimum length. It
- * must be shorter or equal to the configured maximum length. It must start and
- * end with either a letter or a number. It can contain one period, hypen, or
- * underscore. Returns boolean of whether name is valid.
- *
- * @param string $user Username to validate
- *
- * @return bool True if username meets criteria, otherwise false
- */
-function valid_username($user) {
- $length_min = config_get_int('options', 'username_min_len');
- $length_max = config_get_int('options', 'username_max_len');
-
- if (strlen($user) < $length_min || strlen($user) > $length_max) {
- return false;
- } else if (!preg_match("/^[a-z0-9]+[.\-_]?[a-z0-9]+$/Di", $user)) {
- return false;
- }
-
- return true;
-}
-
-/**
- * Determine if a user already has a proposal open about themselves
- *
- * @param string $user Username to checkout for open proposal
- *
- * @return bool True if there is an open proposal about the user, otherwise false
- */
-function open_user_proposals($user) {
- $dbh = DB::connect();
- $q = "SELECT * FROM TU_VoteInfo WHERE User = " . $dbh->quote($user) . " ";
- $q.= "AND End > " . strval(time());
- $result = $dbh->query($q);
-
- return ($result->fetchColumn() ? true : false);
-}
-
-/**
- * Add a new Trusted User proposal to the database
- *
- * @param string $agenda The agenda of the vote
- * @param string $user The use the vote is about
- * @param int $votelength The length of time for the vote to last
- * @param string $submitteruid The user ID of the individual who submitted the proposal
- *
- * @return void
- */
-function add_tu_proposal($agenda, $user, $votelength, $quorum, $submitteruid) {
- $dbh = DB::connect();
-
- $q = "SELECT COUNT(*) FROM Users WHERE (AccountTypeID = 2 OR AccountTypeID = 4)";
- $result = $dbh->query($q);
- $row = $result->fetch(PDO::FETCH_NUM);
- $active_tus = $row[0];
-
- $q = "INSERT INTO TU_VoteInfo (Agenda, User, Submitted, End, Quorum, ";
- $q.= "SubmitterID, ActiveTUs) VALUES ";
- $q.= "(" . $dbh->quote($agenda) . ", " . $dbh->quote($user) . ", ";
- $q.= strval(time()) . ", " . strval(time()) . " + " . $dbh->quote($votelength);
- $q.= ", " . $dbh->quote($quorum) . ", " . $submitteruid . ", ";
- $q.= $active_tus . ")";
- $result = $dbh->exec($q);
-}
-
-/**
- * Add a reset key to the database for a specified user
- *
- * @param string $resetkey A password reset key to be stored in database
- * @param string $uid The user ID to store the reset key for
- *
- * @return void
- */
-function create_resetkey($resetkey, $uid) {
- $dbh = DB::connect();
- $q = "UPDATE Users ";
- $q.= "SET ResetKey = '" . $resetkey . "' ";
- $q.= "WHERE ID = " . $uid;
- $dbh->exec($q);
-}
-
-/**
- * Send a reset key to a specific e-mail address
- *
- * @param string $user User name or email address of the user
- * @param bool $welcome Whether to use the welcome message
- *
- * @return void
- */
-function send_resetkey($user, $welcome=false) {
- $uid = uid_from_loginname($user);
- if ($uid == null) {
- return;
- }
-
- /* We (ab)use new_sid() to get a random 32 characters long string. */
- $resetkey = new_sid();
- create_resetkey($resetkey, $uid);
-
- /* Send e-mail with confirmation link. */
- notify(array($welcome ? 'welcome' : 'send-resetkey', $uid));
-}
-
-/**
- * Change a user's password in the database if reset key and e-mail are correct
- *
- * @param string $password The new password
- * @param string $resetkey Code e-mailed to a user to reset a password
- * @param string $user User name or email address of the user
- *
- * @return string|void Redirect page if successful, otherwise return error message
- */
-function password_reset($password, $resetkey, $user) {
- $hash = password_hash($password, PASSWORD_DEFAULT);
-
- $dbh = DB::connect();
- $q = "UPDATE Users SET ";
- $q.= "Passwd = " . $dbh->quote($hash) . ", ";
- $q.= "ResetKey = '' ";
- $q.= "WHERE ResetKey != '' ";
- $q.= "AND ResetKey = " . $dbh->quote($resetkey) . " ";
- $q.= "AND (Email = " . $dbh->quote($user) . " OR ";
- $q.= "UserName = " . $dbh->quote($user) . ")";
- $result = $dbh->exec($q);
-
- if (!$result) {
- $error = __('Invalid e-mail and reset key combination.');
- return $error;
- } else {
- header('Location: ' . get_uri('/passreset/') . '?step=complete');
- exit();
- }
-}
-
-/**
- * Determine if the password is longer than the minimum length
- *
- * @param string $passwd The password to check
- *
- * @return bool True if longer than minimum length, otherwise false
- */
-function good_passwd($passwd) {
- $length_min = config_get_int('options', 'passwd_min_len');
- return (strlen($passwd) >= $length_min);
-}
-
-/**
- * Determine if the password is correct and salt it if it hasn't been already
- *
- * @param int $user_id The user ID to check the password against
- * @param string $passwd The password the visitor sent
- *
- * @return int Positive if password is correct, negative if password is unset
- */
-function check_passwd($user_id, $passwd) {
- $dbh = DB::connect();
-
- /* Get password hash and salt. */
- $q = "SELECT Passwd, Salt FROM Users WHERE ID = " . intval($user_id);
- $result = $dbh->query($q);
- if (!$result) {
- return 0;
- }
- $row = $result->fetch(PDO::FETCH_ASSOC);
- if (!$row) {
- return 0;
- }
- $hash = $row['Passwd'];
- $salt = $row['Salt'];
- if (!$hash) {
- return -1;
- }
-
- /* Verify the password hash. */
- if (!password_verify($passwd, $hash)) {
- /* Invalid password, fall back to MD5. */
- if (md5($salt . $passwd) != $hash) {
- return 0;
- }
- }
-
- /* Password correct, migrate the hash if necessary. */
- if (password_needs_rehash($hash, PASSWORD_DEFAULT)) {
- $hash = password_hash($passwd, PASSWORD_DEFAULT);
-
- $q = "UPDATE Users SET Passwd = " . $dbh->quote($hash) . " ";
- $q.= "WHERE ID = " . intval($user_id);
- $dbh->query($q);
- }
-
- return 1;
-}
-
-/**
- * Determine if the PGP key fingerprint is valid (must be 40 hexadecimal digits)
- *
- * @param string $fingerprint PGP fingerprint to check if valid
- *
- * @return bool True if the fingerprint is 40 hexadecimal digits, otherwise false
- */
-function valid_pgp_fingerprint($fingerprint) {
- $fingerprint = str_replace(" ", "", $fingerprint);
- return (strlen($fingerprint) == 40 && ctype_xdigit($fingerprint));
-}
-
-/**
- * Determine if the SSH public key is valid
- *
- * @param string $pubkey SSH public key to check
- *
- * @return bool True if the SSH public key is valid, otherwise false
- */
-function valid_ssh_pubkey($pubkey) {
- $valid_prefixes = explode(' ', config_get('auth', 'valid-keytypes'));
-
- $has_valid_prefix = false;
- foreach ($valid_prefixes as $prefix) {
- if (strpos($pubkey, $prefix . " ") === 0) {
- $has_valid_prefix = true;
- break;
- }
- }
- if (!$has_valid_prefix) {
- return false;
- }
-
- $tokens = explode(" ", $pubkey);
- if (empty($tokens[1])) {
- return false;
- }
-
- return (base64_encode(base64_decode($tokens[1], true)) == $tokens[1]);
-}
-
-/**
- * Determine if the user account has been suspended
- *
- * @param string $id The ID of user to check if suspended
- *
- * @return bool True if the user is suspended, otherwise false
- */
-function user_suspended($id) {
- $dbh = DB::connect();
- if (!$id) {
- return false;
- }
- $q = "SELECT Suspended FROM Users WHERE ID = " . $id;
- $result = $dbh->query($q);
- if ($result) {
- $row = $result->fetch(PDO::FETCH_NUM);
- if ($row[0]) {
- return true;
- }
- }
- return false;
-}
-
-/**
- * Delete a specified user account from the database
- *
- * @param int $id The user ID of the account to be deleted
- *
- * @return void
- */
-function user_delete($id) {
- $dbh = DB::connect();
- $id = intval($id);
-
- /*
- * These are normally already taken care of by propagation constraints
- * but it is better to be explicit here.
- */
- $fields_delete = array(
- array("Sessions", "UsersID"),
- array("PackageVotes", "UsersID"),
- array("PackageNotifications", "UserID")
- );
-
- $fields_set_null = array(
- array("PackageBases", "SubmitterUID"),
- array("PackageBases", "MaintainerUID"),
- array("PackageBases", "PackagerUID"),
- array("PackageComments", "UsersID"),
- array("PackageComments", "DelUsersID"),
- array("PackageRequests", "UsersID"),
- array("TU_VoteInfo", "SubmitterID"),
- array("TU_Votes", "UserID")
- );
-
- foreach($fields_delete as list($table, $field)) {
- $q = "DELETE FROM " . $table . " ";
- $q.= "WHERE " . $field . " = " . $id;
- $dbh->query($q);
- }
-
- foreach($fields_set_null as list($table, $field)) {
- $q = "UPDATE " . $table . " SET " . $field . " = NULL ";
- $q.= "WHERE " . $field . " = " . $id;
- $dbh->query($q);
- }
-
- $q = "DELETE FROM Users WHERE ID = " . $id;
- $dbh->query($q);
- return;
-}
-
-/**
- * Remove the session from the database on logout
- *
- * @param string $sid User's session ID
- *
- * @return void
- */
-function delete_session_id($sid) {
- $dbh = DB::connect();
-
- $q = "DELETE FROM Sessions WHERE SessionID = " . $dbh->quote($sid);
- $dbh->query($q);
-}
-
-/**
- * Remove all sessions belonging to a particular user
- *
- * @param int $uid ID of user to remove all sessions for
- *
- * @return void
- */
-function delete_user_sessions($uid) {
- $dbh = DB::connect();
-
- $q = "DELETE FROM Sessions WHERE UsersID = " . intval($uid);
- $dbh->exec($q);
-}
-
-/**
- * Remove sessions from the database that have exceed the timeout
- *
- * @return void
- */
-function clear_expired_sessions() {
- $dbh = DB::connect();
-
- $timeout = config_get_int('options', 'login_timeout');
- $q = "DELETE FROM Sessions WHERE LastUpdateTS < (" . strval(time()) . " - " . $timeout . ")";
- $dbh->query($q);
-
- return;
-}
-
-/**
- * Get account details for a specific user
- *
- * @param string $uid The User ID of account to get information for
- * @param string $username The username of the account to get for
- *
- * @return array Account details for the specified user
- */
-function account_details($uid, $username) {
- $dbh = DB::connect();
- $q = "SELECT Users.*, AccountTypes.AccountType ";
- $q.= "FROM Users, AccountTypes ";
- $q.= "WHERE AccountTypes.ID = Users.AccountTypeID ";
- if (!empty($uid)) {
- $q.= "AND Users.ID = ".intval($uid);
- } else {
- $q.= "AND Users.Username = " . $dbh->quote($username);
- }
- $result = $dbh->query($q);
-
- if ($result) {
- $row = $result->fetch(PDO::FETCH_ASSOC);
- }
-
- return $row;
-}
-
-/**
- * Determine if a user has already voted on a specific proposal
- *
- * @param string $voteid The ID of the Trusted User proposal
- * @param string $uid The ID to check if the user already voted
- *
- * @return bool True if the user has already voted, otherwise false
- */
-function tu_voted($voteid, $uid) {
- $dbh = DB::connect();
-
- $q = "SELECT COUNT(*) FROM TU_Votes ";
- $q.= "WHERE VoteID = " . intval($voteid) . " AND UserID = " . intval($uid);
- $result = $dbh->query($q);
- if ($result->fetchColumn() > 0) {
- return true;
- }
- else {
- return false;
- }
-}
-
-/**
- * Get all current Trusted User proposals from the database
- *
- * @param string $order Ascending or descending order for the proposal listing
- *
- * @return array The details for all current Trusted User proposals
- */
-function current_proposal_list($order) {
- $dbh = DB::connect();
-
- $q = "SELECT * FROM TU_VoteInfo WHERE End > " . time() . " ORDER BY Submitted " . $order;
- $result = $dbh->query($q);
-
- $details = array();
- while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
- $details[] = $row;
- }
-
- return $details;
-}
-
-/**
- * Get a subset of all past Trusted User proposals from the database
- *
- * @param string $order Ascending or descending order for the proposal listing
- * @param string $lim The number of proposals to list with the offset
- *
- * @return array The details for the subset of past Trusted User proposals
- */
-function past_proposal_list($order, $lim) {
- $dbh = DB::connect();
-
- $q = "SELECT * FROM TU_VoteInfo WHERE End < " . time() . " ORDER BY Submitted " . $order . $lim;
- $result = $dbh->query($q);
-
- $details = array();
- while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
- $details[] = $row;
- }
-
- return $details;
-}
-
-/**
- * Get the vote ID of the last vote of all Trusted Users
- *
- * @return array The vote ID of the last vote of each Trusted User
- */
-function last_votes_list() {
- $dbh = DB::connect();
-
- $q = "SELECT UserID, MAX(VoteID) AS LastVote FROM TU_Votes, ";
- $q .= "TU_VoteInfo, Users WHERE TU_VoteInfo.ID = TU_Votes.VoteID AND ";
- $q .= "TU_VoteInfo.End < " . strval(time()) . " AND ";
- $q .= "Users.ID = TU_Votes.UserID AND (Users.AccountTypeID = 2 OR Users.AccountTypeID = 4) ";
- $q .= "GROUP BY UserID ORDER BY LastVote DESC, UserName ASC";
- $result = $dbh->query($q);
-
- $details = array();
- while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
- $details[] = $row;
- }
-
- return $details;
-}
-
-/**
- * Determine the total number of Trusted User proposals
- *
- * @return string The total number of Trusted User proposals
- */
-function proposal_count() {
- $dbh = DB::connect();
- $q = "SELECT COUNT(*) FROM TU_VoteInfo";
- $result = $dbh->query($q);
- $row = $result->fetch(PDO::FETCH_NUM);
-
- return $row[0];
-}
-
-/**
- * Get all details related to a specific vote from the database
- *
- * @param string $voteid The ID of the Trusted User proposal
- *
- * @return array All stored details for a specific vote
- */
-function vote_details($voteid) {
- $dbh = DB::connect();
-
- $q = "SELECT * FROM TU_VoteInfo ";
- $q.= "WHERE ID = " . intval($voteid);
-
- $result = $dbh->query($q);
- $row = $result->fetch(PDO::FETCH_ASSOC);
-
- return $row;
-}
-
-/**
- * Get an alphabetical list of users who voted for a proposal with HTML links
- *
- * @param string $voteid The ID of the Trusted User proposal
- *
- * @return array All users who voted for a specific proposal
- */
-function voter_list($voteid) {
- $dbh = DB::connect();
-
- $whovoted = array();
-
- $q = "SELECT tv.UserID,U.Username ";
- $q.= "FROM TU_Votes tv, Users U ";
- $q.= "WHERE tv.VoteID = " . intval($voteid);
- $q.= " AND tv.UserID = U.ID ";
- $q.= "ORDER BY Username";
-
- $result = $dbh->query($q);
- if ($result) {
- while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
- $whovoted[] = $row['Username'];
- }
- }
- return $whovoted;
-}
-
-/**
- * Cast a vote for a specific user proposal
- *
- * @param string $voteid The ID of the proposal being voted on
- * @param string $uid The user ID of the individual voting
- * @param string $vote Vote position, either "Yes", "No", or "Abstain"
- * @param int $newtotal The total number of votes after the user has voted
- *
- * @return void
- */
-function cast_proposal_vote($voteid, $uid, $vote, $newtotal) {
- $dbh = DB::connect();
-
- $q = "UPDATE TU_VoteInfo SET " . $vote . " = (" . $newtotal . ") WHERE ID = " . $voteid;
- $result = $dbh->exec($q);
-
- $q = "INSERT INTO TU_Votes (VoteID, UserID) VALUES (" . intval($voteid) . ", " . intval($uid) . ")";
- $result = $dbh->exec($q);
-}
-
-/**
- * Verify a user has the proper permissions to edit an account
- *
- * @param array $acctinfo User account information for edited account
- *
- * @return bool True if permission to edit the account, otherwise false
- */
-function can_edit_account($acctinfo) {
- if ($acctinfo['AccountType'] == 'Developer' ||
- $acctinfo['AccountType'] == 'Trusted User & Developer') {
- return has_credential(CRED_ACCOUNT_EDIT_DEV);
- }
-
- $uid = $acctinfo['ID'];
- return has_credential(CRED_ACCOUNT_EDIT, array($uid));
-}
-
-/*
- * Compute the fingerprint of an SSH key.
- *
- * @param string $ssh_key The SSH public key to retrieve the fingerprint for
- *
- * @return string The SSH key fingerprint
- */
-function ssh_key_fingerprint($ssh_key) {
- $tmpfile = tempnam(sys_get_temp_dir(), "aurweb");
- file_put_contents($tmpfile, $ssh_key);
-
- /*
- * The -l option of ssh-keygen can be used to show the fingerprint of
- * the specified public key file. Expected output format:
- *
- * 2048 SHA256:uBBTXmCNjI2CnLfkuz9sG8F+e9/T4C+qQQwLZWIODBY user@host (RSA)
- *
- * ... where 2048 is the key length, the second token is the actual
- * fingerprint, followed by the key comment and the key type.
- */
-
- $cmd = "/usr/bin/ssh-keygen -l -f " . escapeshellarg($tmpfile);
- exec($cmd, $out, $ret);
- if ($ret !== 0 || count($out) !== 1) {
- return false;
- }
-
- unlink($tmpfile);
-
- $tokens = explode(' ', $out[0]);
- if (count($tokens) < 4) {
- return false;
- }
-
- $tokens = explode(':', $tokens[1]);
- if (count($tokens) != 2 || $tokens[0] != 'SHA256') {
- return false;
- }
-
- return $tokens[1];
-}
-
-/*
- * Get the SSH public keys associated with an account.
- *
- * @param int $uid The user ID of the account to retrieve the keys for.
- *
- * @return array An array representing the keys
- */
-function account_get_ssh_keys($uid) {
- $dbh = DB::connect();
- $q = "SELECT PubKey FROM SSHPubKeys WHERE UserID = " . intval($uid);
- $result = $dbh->query($q);
-
- if ($result) {
- return $result->fetchAll(PDO::FETCH_COLUMN, 0);
- } else {
- return array();
- }
-}
-
-/*
- * Set the SSH public keys associated with an account.
- *
- * @param int $uid The user ID of the account to assign the keys to.
- * @param array $ssh_keys The SSH public keys.
- * @param array $ssh_fingerprints The corresponding SSH key fingerprints.
- *
- * @return bool Boolean flag indicating success or failure.
- */
-function account_set_ssh_keys($uid, $ssh_keys, $ssh_fingerprints) {
- $dbh = DB::connect();
-
- $q = sprintf("DELETE FROM SSHPubKeys WHERE UserID = %d", $uid);
- $dbh->exec($q);
-
- $ssh_fingerprint = reset($ssh_fingerprints);
- foreach ($ssh_keys as $ssh_key) {
- $q = sprintf(
- "INSERT INTO SSHPubKeys (UserID, Fingerprint, PubKey) " .
- "VALUES (%d, %s, %s)", $uid,
- $dbh->quote($ssh_fingerprint), $dbh->quote($ssh_key)
- );
- $dbh->exec($q);
- $ssh_fingerprint = next($ssh_fingerprints);
- }
-
- return true;
-}
-
-/*
- * Invoke the email notification script.
- *
- * @param string $params Command line parameters for the script.
- *
- * @return void
- */
-function notify($params) {
- $cmd = config_get('notifications', 'notify-cmd');
- foreach ($params as $param) {
- $cmd .= ' ' . escapeshellarg($param);
- }
-
- $descspec = array(
- 0 => array('pipe', 'r'),
- 1 => array('pipe', 'w'),
- );
-
- $p = proc_open($cmd, $descspec, $pipes);
-
- if (!is_resource($p)) {
- return false;
- }
-
- fclose($pipes[0]);
- fclose($pipes[1]);
-
- return proc_close($p);
-}
-
-/*
- * Obtain a list of terms a given user has not yet accepted.
- *
- * @param int $uid The ID of the user to obtain terms for.
- *
- * @return array A list of terms the user has not yet accepted.
- */
-function fetch_updated_terms($uid) {
- $dbh = DB::connect();
-
- $q = "SELECT ID, Terms.Revision, Description, URL ";
- $q .= "FROM Terms LEFT JOIN AcceptedTerms ";
- $q .= "ON AcceptedTerms.TermsID = Terms.ID ";
- $q .= "AND AcceptedTerms.UsersID = " . intval($uid) . " ";
- $q .= "WHERE AcceptedTerms.Revision IS NULL OR ";
- $q .= "AcceptedTerms.Revision < Terms.Revision";
-
- $result = $dbh->query($q);
-
- if ($result) {
- return $result->fetchAll();
- } else {
- return array();
- }
-}
-
-/*
- * Accept a list of given terms.
- *
- * @param int $uid The ID of the user to accept the terms.
- * @param array $termrev An array mapping each term to the accepted revision.
- *
- * @return void
- */
-function accept_terms($uid, $termrev) {
- $dbh = DB::connect();
-
- $q = "SELECT TermsID, Revision FROM AcceptedTerms ";
- $q .= "WHERE UsersID = " . intval($uid);
-
- $result = $dbh->query($q);
-
- if (!$result) {
- return;
- }
-
- $termrev_update = array();
- while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
- $id = $row['TermsID'];
- if (!array_key_exists($id, $termrev)) {
- continue;
- }
- if ($row['Revision'] < $termrev[$id]) {
- $termrev_update[$id] = $termrev[$id];
- }
- }
- $termrev_add = array_diff_key($termrev, $termrev_update);
-
- foreach ($termrev_add as $id => $rev) {
- $q = "INSERT INTO AcceptedTerms (TermsID, UsersID, Revision) ";
- $q .= "VALUES (" . intval($id) . ", " . intval($uid) . ", ";
- $q .= intval($rev) . ")";
- $dbh->exec($q);
- }
-
- foreach ($termrev_update as $id => $rev) {
- $q = "UPDATE AcceptedTerms ";
- $q .= "SET Revision = " . intval($rev) . " ";
- $q .= "WHERE TermsID = " . intval($id) . " AND ";
- $q .= "UsersID = " . intval($uid);
- $dbh->exec($q);
- }
-}
-
-function account_comments($uid, $limit, $offset=0) {
- $dbh = DB::connect();
- $q = "SELECT PackageComments.ID, Comments, UsersID, ";
- $q.= "PackageBaseId, CommentTS, DelTS, EditedTS, B.UserName AS EditUserName, ";
- $q.= "PinnedTS, ";
- $q.= "C.UserName as DelUserName, RenderedComment, ";
- $q.= "PB.ID as PackageBaseID, PB.Name as PackageBaseName ";
- $q.= "FROM PackageComments ";
- $q.= "LEFT JOIN PackageBases PB ON PackageComments.PackageBaseID = PB.ID ";
- $q.= "LEFT JOIN Users A ON PackageComments.UsersID = A.ID ";
- $q.= "LEFT JOIN Users B ON PackageComments.EditedUsersID = B.ID ";
- $q.= "LEFT JOIN Users C ON PackageComments.DelUsersID = C.ID ";
- $q.= "WHERE A.ID = " . $dbh->quote($uid) . " ";
- $q.= "ORDER BY CommentTS DESC";
-
- if ($limit > 0) {
- $q.=" LIMIT " . intval($limit);
- }
-
- if ($offset > 0) {
- $q.=" OFFSET " . intval($offset);
- }
-
- $result = $dbh->query($q);
- if (!$result) {
- return null;
- }
-
- return $result->fetchAll();
-}
-
-function account_comments_count($uid) {
- $dbh = DB::connect();
- $q = "SELECT COUNT(*) ";
- $q.= "FROM PackageComments ";
- $q.= "LEFT JOIN Users A ON PackageComments.UsersID = A.ID ";
- $q.= "WHERE A.ID = " . $dbh->quote($uid);
-
- $result = $dbh->query($q);
- return $result->fetchColumn();
-}
-
-/*
- * Compute the list of active CAPTCHA salts. The salt changes based on the
- * number of registered users. This ensures that new users always use a
- * different salt and protects against hardcoding the CAPTCHA response.
- *
- * The first CAPTCHA in the list is the most recent one and should be used for
- * new CAPTCHA challenges. The other ones are slightly outdated but may still
- * be valid for recent challenges that were created before the number of users
- * increased. The current implementation ensures that we can still use our
- * CAPTCHA salt, even if five new users registered since the CAPTCHA challenge
- * was created.
- *
- * @return string The list of active salts, the first being the most recent
- * one.
- */
-function get_captcha_salts() {
- $dbh = DB::connect();
- $q = "SELECT count(*) FROM Users";
- $result = $dbh->query($q);
- $user_count = $result->fetchColumn();
-
- $ret = array();
- for ($i = 0; $i <= 5; $i++) {
- array_push($ret, 'aurweb-' . ($user_count - $i));
- }
- return $ret;
-}
-
-/*
- * Return the CAPTCHA challenge for a given salt.
- *
- * @param string $salt The salt to be used for the CAPTCHA computation.
- *
- * @return string The challenge as a string.
- */
-function get_captcha_challenge($salt) {
- $token = substr(md5($salt), 0, 3);
- return "LC_ALL=C pacman -V|sed -r 's#[0-9]+#" . $token . "#g'|md5sum|cut -c1-6";
-}
-
-/*
- * Compute CAPTCHA answer for a given salt.
- *
- * @param string $salt The salt to be used for the CAPTCHA computation.
- *
- * @return string The correct answer as a string.
- */
-function get_captcha_answer($salt) {
- $token = substr(md5($salt), 0, 3);
- $text = <<query($q);
- $row = $result->fetch(PDO::FETCH_NUM);
-
- if (!$row) {
- # Invalid SessionID - hacker alert!
- #
- $failed = 1;
- } else {
- $last_update = $row[0];
- if ($last_update + $timeout <= $row[1]) {
- $failed = 2;
- }
- }
-
- if ($failed == 1) {
- # clear out the hacker's cookie, and send them to a naughty page
- # why do you have to be so harsh on these people!?
- #
- setcookie("AURSID", "", 1, "/", null, !empty($_SERVER['HTTPS']), true);
- unset($_COOKIE['AURSID']);
- } elseif ($failed == 2) {
- # session id timeout was reached and they must login again.
- #
- delete_session_id($_COOKIE["AURSID"]);
-
- setcookie("AURSID", "", 1, "/", null, !empty($_SERVER['HTTPS']), true);
- unset($_COOKIE['AURSID']);
- } else {
- # still logged in and haven't reached the timeout, go ahead
- # and update the idle timestamp
-
- # Only update the timestamp if it is less than the
- # current time plus $timeout.
- #
- # This keeps 'remembered' sessions from being
- # overwritten.
- if ($last_update < time() + $timeout) {
- $q = "UPDATE Sessions SET LastUpdateTS = " . strval(time()) . " ";
- $q.= "WHERE SessionID = " . $dbh->quote($_COOKIE["AURSID"]);
- $dbh->exec($q);
- }
- }
- }
- return;
-}
-
-/**
- * Redirect user to the Terms of Service agreement if there are updated terms.
- *
- * @return void
- */
-function check_tos() {
- if (!isset($_COOKIE["AURSID"])) {
- return;
- }
-
- $path = $_SERVER['PATH_INFO'];
- $route = get_route($path);
- if (!$route || $route == "tos.php") {
- return;
- }
-
- if (count(fetch_updated_terms(uid_from_sid($_COOKIE["AURSID"]))) > 0) {
- header('Location: ' . get_uri('/tos'));
- exit();
- }
-}
-
-/**
- * Verify the supplied CSRF token matches expected token
- *
- * @return bool True if the CSRF token is the same as the cookie SID, otherwise false
- */
-function check_token() {
- if (isset($_POST['token']) && isset($_COOKIE['AURSID'])) {
- return ($_POST['token'] == $_COOKIE['AURSID']);
- } else {
- return false;
- }
-}
-
-/**
- * Verify a user supplied e-mail against RFC 3696 and DNS records
- *
- * @param string $addy E-mail address being validated in foo@example.com format
- *
- * @return bool True if e-mail passes validity checks, otherwise false
- */
-function valid_email($addy) {
- // check against RFC 3696
- if (filter_var($addy, FILTER_VALIDATE_EMAIL) === false) {
- return false;
- }
-
- // check dns for mx, a, aaaa records
- list($local, $domain) = explode('@', $addy);
- if (!(checkdnsrr($domain, 'MX') || checkdnsrr($domain, 'A') || checkdnsrr($domain, 'AAAA'))) {
- return false;
- }
-
- return true;
-}
-
-/**
- * Verify that a given URL is valid and uses the HTTP(s) protocol
- *
- * @param string $url URL of the home page to be validated
- *
- * @return bool True if URL passes validity checks, false otherwise
- */
-function valid_homepage($url) {
- if (filter_var($url, FILTER_VALIDATE_URL) === false) {
- return false;
- }
-
- $url_components = parse_url($url);
- if (!in_array($url_components['scheme'], array('http', 'https'))) {
- return false;
- }
-
- return true;
-}
-
-/**
- * Generate a unique session ID
- *
- * @return string MD5 hash of the concatenated user IP, random number, and current time
- */
-function new_sid() {
- return md5($_SERVER['REMOTE_ADDR'] . uniqid(mt_rand(), true));
-}
-
-/**
- * Determine the user's username in the database using a user ID
- *
- * @param string $id User's ID
- *
- * @return string Username if it exists, otherwise null
- */
-function username_from_id($id) {
- $id = intval($id);
-
- $dbh = DB::connect();
- $q = "SELECT Username FROM Users WHERE ID = " . $dbh->quote($id);
- $result = $dbh->query($q);
- if (!$result) {
- return null;
- }
-
- $row = $result->fetch(PDO::FETCH_NUM);
- if ($row) {
- return $row[0];
- }
-}
-
-/**
- * Determine the user's username in the database using a session ID
- *
- * @param string $sid User's session ID
- *
- * @return string Username of the visitor
- */
-function username_from_sid($sid="") {
- if (!$sid) {
- return "";
- }
- $dbh = DB::connect();
- $q = "SELECT Username ";
- $q.= "FROM Users, Sessions ";
- $q.= "WHERE Users.ID = Sessions.UsersID ";
- $q.= "AND Sessions.SessionID = " . $dbh->quote($sid);
- $result = $dbh->query($q);
- if (!$result) {
- return "";
- }
- $row = $result->fetch(PDO::FETCH_NUM);
-
- if ($row) {
- return $row[0];
- }
-}
-
-/**
- * Format a user name for inclusion in HTML data
- *
- * @param string $username The user name to format
- *
- * @return string The generated HTML code for the account link
- */
-function html_format_username($username) {
- $username_fmt = $username ? htmlspecialchars($username, ENT_QUOTES) : __("None");
-
- if ($username && isset($_COOKIE["AURSID"])) {
- $link = '' . $username_fmt . '';
- return $link;
- } else {
- return $username_fmt;
- }
-}
-
-/**
- * Format the maintainer and co-maintainers for inclusion in HTML data
- *
- * @param string $maintainer The user name of the maintainer
- * @param array $comaintainers The list of co-maintainer user names
- *
- * @return string The generated HTML code for the account links
- */
-function html_format_maintainers($maintainer, $comaintainers) {
- $code = html_format_username($maintainer);
-
- if (count($comaintainers) > 0) {
- $code .= ' (';
- foreach ($comaintainers as $comaintainer) {
- $code .= html_format_username($comaintainer);
- if ($comaintainer !== end($comaintainers)) {
- $code .= ', ';
- }
- }
- $code .= ')';
- }
-
- return $code;
-}
-
-/**
- * Format a link in the package actions box
- *
- * @param string $uri The link target
- * @param string $inner The HTML code to use for the link label
- *
- * @return string The generated HTML code for the action link
- */
-function html_action_link($uri, $inner) {
- if (isset($_COOKIE["AURSID"])) {
- $code = '';
- } else {
- $code = '';
- }
- $code .= $inner . '';
-
- return $code;
-}
-
-/**
- * Format a form in the package actions box
- *
- * @param string $uri The link target
- * @param string $action The action name (passed as HTTP POST parameter)
- * @param string $inner The HTML code to use for the link label
- *
- * @return string The generated HTML code for the action link
- */
-function html_action_form($uri, $action, $inner) {
- if (isset($_COOKIE["AURSID"])) {
- $code = '';
- $code .= '';
- $code .= '';
- } else {
- $code = '';
- $code .= $inner . '';
- }
-
- return $code;
-}
-
-/**
- * Determine the user's e-mail address in the database using a session ID
- *
- * @param string $sid User's session ID
- *
- * @return string User's e-mail address as given during registration
- */
-function email_from_sid($sid="") {
- if (!$sid) {
- return "";
- }
- $dbh = DB::connect();
- $q = "SELECT Email ";
- $q.= "FROM Users, Sessions ";
- $q.= "WHERE Users.ID = Sessions.UsersID ";
- $q.= "AND Sessions.SessionID = " . $dbh->quote($sid);
- $result = $dbh->query($q);
- if (!$result) {
- return "";
- }
- $row = $result->fetch(PDO::FETCH_NUM);
-
- if ($row) {
- return $row[0];
- }
-}
-
-/**
- * Determine the user's account type in the database using a session ID
- *
- * @param string $sid User's session ID
- *
- * @return string Account type of user ("User", "Trusted User", or "Developer")
- */
-function account_from_sid($sid="") {
- if (!$sid) {
- return "";
- }
- $dbh = DB::connect();
- $q = "SELECT AccountType ";
- $q.= "FROM Users, AccountTypes, Sessions ";
- $q.= "WHERE Users.ID = Sessions.UsersID ";
- $q.= "AND AccountTypes.ID = Users.AccountTypeID ";
- $q.= "AND Sessions.SessionID = " . $dbh->quote($sid);
- $result = $dbh->query($q);
- if (!$result) {
- return "";
- }
- $row = $result->fetch(PDO::FETCH_NUM);
-
- if ($row) {
- return $row[0];
- }
-}
-
-/**
- * Determine the user's ID in the database using a session ID
- *
- * @param string $sid User's session ID
- *
- * @return string|int The user's name, 0 on query failure
- */
-function uid_from_sid($sid="") {
- if (!$sid) {
- return "";
- }
- $dbh = DB::connect();
- $q = "SELECT Users.ID ";
- $q.= "FROM Users, Sessions ";
- $q.= "WHERE Users.ID = Sessions.UsersID ";
- $q.= "AND Sessions.SessionID = " . $dbh->quote($sid);
- $result = $dbh->query($q);
- if (!$result) {
- return 0;
- }
- $row = $result->fetch(PDO::FETCH_NUM);
-
- if ($row) {
- return $row[0];
- }
-}
-
-/**
- * Common AUR header displayed on all pages
- *
- * @global string $LANG Language selected by the visitor
- * @global array $SUPPORTED_LANGS Languages that are supported by the AUR
- * @param string $title Name of the AUR page to be displayed on browser
- *
- * @return void
- */
-function html_header($title="", $details=array()) {
- global $LANG;
- global $SUPPORTED_LANGS;
-
- include('header.php');
- return;
-}
-
-/**
- * Common AUR footer displayed on all pages
- *
- * @param string $ver The AUR version
- *
- * @return void
- */
-function html_footer($ver="") {
- include('footer.php');
- return;
-}
-
-/**
- * Determine if a user has permission to submit a package
- *
- * @param string $name Name of the package to be submitted
- * @param string $sid User's session ID
- *
- * @return int 0 if the user can't submit, 1 if the user can submit
- */
-function can_submit_pkgbase($name="", $sid="") {
- if (!$name || !$sid) {return 0;}
- $dbh = DB::connect();
- $q = "SELECT MaintainerUID ";
- $q.= "FROM PackageBases WHERE Name = " . $dbh->quote($name);
- $result = $dbh->query($q);
- $row = $result->fetch(PDO::FETCH_NUM);
-
- if (!$row[0]) {
- return 1;
- }
- $my_uid = uid_from_sid($sid);
-
- if ($row[0] === NULL || $row[0] == $my_uid) {
- return 1;
- }
-
- return 0;
-}
-
-/**
- * Determine if a package can be overwritten by some package base
- *
- * @param string $name Name of the package to be submitted
- * @param int $base_id The ID of the package base
- *
- * @return bool True if the package can be overwritten, false if not
- */
-function can_submit_pkg($name, $base_id) {
- $dbh = DB::connect();
- $q = "SELECT COUNT(*) FROM Packages WHERE ";
- $q.= "Name = " . $dbh->quote($name) . " AND ";
- $q.= "PackageBaseID <> " . intval($base_id);
- $result = $dbh->query($q);
-
- if (!$result) return false;
- return ($result->fetchColumn() == 0);
-}
-
-/**
- * Recursively delete a directory
- *
- * @param string $dirname Name of the directory to be removed
- *
- * @return void
- */
-function rm_tree($dirname) {
- if (empty($dirname) || !is_dir($dirname)) return;
-
- foreach (scandir($dirname) as $item) {
- if ($item != '.' && $item != '..') {
- $path = $dirname . '/' . $item;
- if (is_file($path) || is_link($path)) {
- unlink($path);
- }
- else {
- rm_tree($path);
- }
- }
- }
-
- rmdir($dirname);
-
- return;
-}
-
- /**
- * Determine the user's ID in the database using a username
- *
- * @param string $username The username of an account
- *
- * @return string Return user ID if exists for username, otherwise null
- */
-function uid_from_username($username) {
- $dbh = DB::connect();
- $q = "SELECT ID FROM Users WHERE Username = " . $dbh->quote($username);
- $result = $dbh->query($q);
- if (!$result) {
- return null;
- }
-
- $row = $result->fetch(PDO::FETCH_NUM);
- if ($row) {
- return $row[0];
- }
-}
-
-/**
- * Determine the user's ID in the database using a username or email address
- *
- * @param string $username The username or email address of an account
- *
- * @return string Return user ID if exists, otherwise null
- */
-function uid_from_loginname($loginname) {
- $uid = uid_from_username($loginname);
- if (!$uid) {
- $uid = uid_from_email($loginname);
- }
- return $uid;
-}
-
-/**
- * Determine the user's ID in the database using an e-mail address
- *
- * @param string $email An e-mail address in foo@example.com format
- *
- * @return string The user's ID
- */
-function uid_from_email($email) {
- $dbh = DB::connect();
- $q = "SELECT ID FROM Users WHERE Email = " . $dbh->quote($email);
- $result = $dbh->query($q);
- if (!$result) {
- return null;
- }
-
- $row = $result->fetch(PDO::FETCH_NUM);
- if ($row) {
- return $row[0];
- }
-}
-
-/**
- * Generate clean url with edited/added user values
- *
- * Makes a clean string of variables for use in URLs based on current $_GET and
- * list of values to edit/add to that. Any empty variables are discarded.
- *
- * @example print "http://example.com/test.php?" . mkurl("foo=bar&bar=baz")
- *
- * @param string $append string of variables and values formatted as in URLs
- *
- * @return string clean string of variables to append to URL, urlencoded
- */
-function mkurl($append) {
- $get = $_GET;
- $append = explode('&', $append);
- $uservars = array();
- $out = '';
-
- foreach ($append as $i) {
- $ex = explode('=', $i);
- $uservars[$ex[0]] = $ex[1];
- }
-
- foreach ($uservars as $k => $v) { $get[$k] = $v; }
-
- foreach ($get as $k => $v) {
- if ($v !== '') {
- $out .= '&' . urlencode($k) . '=' . urlencode($v);
- }
- }
-
- return substr($out, 5);
-}
-
-/**
- * Get a package comment
- *
- * @param int $comment_id The ID of the comment
- *
- * @return array The user ID and comment OR null, null in case of an error
- */
-function comment_by_id($comment_id) {
- $dbh = DB::connect();
- $q = "SELECT UsersID, Comments FROM PackageComments ";
- $q.= "WHERE ID = " . intval($comment_id);
- $result = $dbh->query($q);
- if (!$result) {
- return array(null, null);
- }
-
- return $result->fetch(PDO::FETCH_NUM);
-}
-
-/**
- * Process submitted comments so any links can be followed
- *
- * @param string $comment Raw user submitted package comment
- *
- * @return string User comment with links printed in HTML
- */
-function parse_comment($comment) {
- $url_pattern = '/(\b(?:https?|ftp):\/\/[\w\/\#~:.?+=&%@!\-;,]+?' .
- '(?=[.:?\-;,]*(?:[^\w\/\#~:.?+=&%@!\-;,]|$)))/iS';
-
- $matches = preg_split($url_pattern, $comment, -1,
- PREG_SPLIT_DELIM_CAPTURE);
-
- $html = '';
- for ($i = 0; $i < count($matches); $i++) {
- if ($i % 2) {
- # convert links
- $html .= '' . htmlspecialchars($matches[$i]) . '';
- }
- else {
- # convert everything else
- $html .= nl2br(htmlspecialchars($matches[$i]));
- }
- }
-
- return $html;
-}
-
-/**
- * Wrapper for beginning a database transaction
- */
-function begin_atomic_commit() {
- $dbh = DB::connect();
- $dbh->beginTransaction();
-}
-
-/**
- * Wrapper for committing a database transaction
- */
-function end_atomic_commit() {
- $dbh = DB::connect();
- $dbh->commit();
-}
-
-/**
- * Merge pkgbase and package options
- *
- * Merges entries of the first and the second array. If any key appears in both
- * arrays and the corresponding value in the second array is either a non-array
- * type or a non-empty array, the value from the second array replaces the
- * value from the first array. If the value from the second array is an array
- * containing a single empty string, the value in the resulting array becomes
- * an empty array instead. If the value in the second array is empty, the
- * resulting array contains the value from the first array.
- *
- * @param array $pkgbase_info Options from the pkgbase section
- * @param array $section_info Options from the package section
- *
- * @return array Merged information from both sections
- */
-function array_pkgbuild_merge($pkgbase_info, $section_info) {
- $pi = $pkgbase_info;
- foreach ($section_info as $opt_key => $opt_val) {
- if (is_array($opt_val)) {
- if ($opt_val == array('')) {
- $pi[$opt_key] = array();
- } elseif (count($opt_val) > 0) {
- $pi[$opt_key] = $opt_val;
- }
- } else {
- $pi[$opt_key] = $opt_val;
- }
- }
- return $pi;
-}
-
-/**
- * Bound an integer value between two values
- *
- * @param int $n Integer value to bound
- * @param int $min Lower bound
- * @param int $max Upper bound
- *
- * @return int Bounded integer value
- */
-function bound($n, $min, $max) {
- return min(max($n, $min), $max);
-}
-
-/**
- * Return the URL of the AUR root
- *
- * @return string The URL of the AUR root
- */
-function aur_location() {
- $location = config_get('options', 'aur_location');
- if (substr($location, -1) != '/') {
- $location .= '/';
- }
- return $location;
-}
-
-/**
- * Calculate pagination templates
- *
- * @return array The array of pagination templates, per page, and offset values
- */
-function calculate_pagination($total_comment_count) {
- /* Sanitize paging variables. */
- if (isset($_GET["O"])) {
- $_GET["O"] = max(intval($_GET["O"]), 0);
- } else {
- $_GET["O"] = 0;
- }
- $offset = $_GET["O"];
-
- if (isset($_GET["PP"])) {
- $_GET["PP"] = bound(intval($_GET["PP"]), 1, 250);
- } else {
- $_GET["PP"] = 10;
- }
- $per_page = $_GET["PP"];
-
- // Page offsets start at zero, so page 2 has offset 1, which means that we
- // need to add 1 to the offset to get the current page.
- $current_page = ceil($offset / $per_page) + 1;
- $num_pages = ceil($total_comment_count / $per_page);
- $pagination_templs = array();
-
- if ($current_page > 1) {
- $previous_page = $current_page - 1;
- $previous_offset = ($previous_page - 1) * $per_page;
- $pagination_templs['« ' . __('First')] = 0;
- $pagination_templs['‹ ' . __('Previous')] = $previous_offset;
- }
-
- if ($current_page - 5 > 1) {
- $pagination_templs["..."] = false;
- }
-
- for ($i = max($current_page - 5, 1); $i <= min($num_pages, $current_page + 5); $i++) {
- $pagination_templs[$i] = ($i - 1) * $per_page;
- }
-
- if ($current_page + 5 < $num_pages)
- $pagination_templs["... "] = false;
-
- if ($current_page < $num_pages) {
- $pagination_templs[__('Next') . ' ›'] = $current_page * $per_page;
- $pagination_templs[__('Last') . ' »'] = ($num_pages - 1) * $per_page;
- }
-
- return array($pagination_templs, $per_page, $offset);
-}
diff --git a/web/lib/aurjson.class.php b/web/lib/aurjson.class.php
deleted file mode 100644
index 81c27bd9..00000000
--- a/web/lib/aurjson.class.php
+++ /dev/null
@@ -1,710 +0,0 @@
-version = intval($http_data['v']);
- }
- if ($this->version < 1 || $this->version > 6) {
- return $this->json_error('Invalid version specified.');
- }
-
- if (!isset($http_data['type']) || !isset($http_data['arg'])) {
- return $this->json_error('No request type/data specified.');
- }
- if (!in_array($http_data['type'], self::$exposed_methods)) {
- return $this->json_error('Incorrect request type specified.');
- }
-
- if (isset($http_data['search_by']) && !isset($http_data['by'])) {
- $http_data['by'] = $http_data['search_by'];
- }
- if (isset($http_data['by']) && !in_array($http_data['by'], self::$exposed_fields)) {
- return $this->json_error('Incorrect by field specified.');
- }
-
- $this->dbh = DB::connect();
-
- if ($this->check_ratelimit($_SERVER['REMOTE_ADDR'])) {
- header("HTTP/1.1 429 Too Many Requests");
- return $this->json_error('Rate limit reached');
- }
-
- $type = str_replace('-', '_', $http_data['type']);
- if ($type == 'info' && $this->version >= 5) {
- $type = 'multiinfo';
- }
- $json = call_user_func(array(&$this, $type), $http_data);
-
- $etag = md5($json);
- header("Etag: \"$etag\"");
- /*
- * Make sure to strip a few things off the
- * if-none-match header. Stripping whitespace may not
- * be required, but removing the quote on the incoming
- * header is required to make the equality test.
- */
- $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ?
- trim($_SERVER['HTTP_IF_NONE_MATCH'], "\t\n\r\" ") : false;
- if ($if_none_match && $if_none_match == $etag) {
- header('HTTP/1.1 304 Not Modified');
- return;
- }
-
- if (isset($http_data['callback'])) {
- $callback = $http_data['callback'];
- if (!preg_match('/^[a-zA-Z0-9()_.]{1,128}$/D', $callback)) {
- return $this->json_error('Invalid callback name.');
- }
- header('content-type: text/javascript');
- return '/**/' . $callback . '(' . $json . ')';
- } else {
- header('content-type: application/json');
- return $json;
- }
- }
-
- /*
- * Check if an IP needs to be rate limited.
- *
- * @param $ip IP of the current request
- *
- * @return true if IP needs to be rate limited, false otherwise.
- */
- private function check_ratelimit($ip) {
- $limit = config_get("ratelimit", "request_limit");
- if ($limit == 0) {
- return false;
- }
-
- $this->update_ratelimit($ip);
-
- $status = false;
- $value = get_cache_value('ratelimit:' . $ip, $status);
- if (!$status) {
- $stmt = $this->dbh->prepare("
- SELECT Requests FROM ApiRateLimit
- WHERE IP = :ip");
- $stmt->bindParam(":ip", $ip);
- $result = $stmt->execute();
-
- if (!$result) {
- return false;
- }
-
- $row = $stmt->fetch(PDO::FETCH_ASSOC);
- $value = $row['Requests'];
- }
-
- return $value > $limit;
- }
-
- /*
- * Update a rate limit for an IP by increasing it's requests value by one.
- *
- * @param $ip IP of the current request
- *
- * @return void
- */
- private function update_ratelimit($ip) {
- $window_length = config_get("ratelimit", "window_length");
- $db_backend = config_get("database", "backend");
- $time = time();
- $deletion_time = $time - $window_length;
-
- /* Try to use the cache. */
- $status = false;
- $value = get_cache_value('ratelimit-ws:' . $ip, $status);
- if (!$status || ($status && $value < $deletion_time)) {
- if (set_cache_value('ratelimit-ws:' . $ip, $time, $window_length) &&
- set_cache_value('ratelimit:' . $ip, 1, $window_length)) {
- return;
- }
- } else {
- $value = get_cache_value('ratelimit:' . $ip, $status);
- if ($status && set_cache_value('ratelimit:' . $ip, $value + 1, $window_length))
- return;
- }
-
- /* Clean up old windows. */
- $stmt = $this->dbh->prepare("
- DELETE FROM ApiRateLimit
- WHERE WindowStart < :time");
- $stmt->bindParam(":time", $deletion_time);
- $stmt->execute();
-
- if ($db_backend == "mysql") {
- $stmt = $this->dbh->prepare("
- INSERT INTO ApiRateLimit
- (IP, Requests, WindowStart)
- VALUES (:ip, 1, :window_start)
- ON DUPLICATE KEY UPDATE Requests=Requests+1");
- $stmt->bindParam(":ip", $ip);
- $stmt->bindParam(":window_start", $time);
- $stmt->execute();
- } elseif ($db_backend == "sqlite") {
- $stmt = $this->dbh->prepare("
- INSERT OR IGNORE INTO ApiRateLimit
- (IP, Requests, WindowStart)
- VALUES (:ip, 0, :window_start);");
- $stmt->bindParam(":ip", $ip);
- $stmt->bindParam(":window_start", $time);
- $stmt->execute();
-
- $stmt = $this->dbh->prepare("
- UPDATE ApiRateLimit
- SET Requests = Requests + 1
- WHERE IP = :ip");
- $stmt->bindParam(":ip", $ip);
- $stmt->execute();
- } else {
- throw new RuntimeException("Unknown database backend");
- }
- }
-
- /*
- * Returns a JSON formatted error string.
- *
- * @param $msg The error string to return
- *
- * @return mixed A json formatted error response.
- */
- private function json_error($msg) {
- header('content-type: application/json');
- if ($this->version < 3) {
- return $this->json_results('error', 0, $msg, NULL);
- } elseif ($this->version >= 3) {
- return $this->json_results('error', 0, array(), $msg);
- }
- }
-
- /*
- * Returns a JSON formatted result data.
- *
- * @param $type The response method type.
- * @param $count The number of results to return
- * @param $data The result data to return
- * @param $error An error message to include in the response
- *
- * @return mixed A json formatted result response.
- */
- private function json_results($type, $count, $data, $error) {
- $json_array = array(
- 'version' => $this->version,
- 'type' => $type,
- 'resultcount' => $count,
- 'results' => $data
- );
-
- if ($this->version != 5) {
- $json_array['warning'] = 'The use of versions lower than 5 is '
- . 'now deprecated and will soon be unsupported. To ensure '
- . 'your API client supports the change without issue, it '
- . 'should use version 5 and adjust for any changes in the '
- . 'API interface. See https://aur.archlinux.org/rpc for '
- . 'documentation related to v5.';
- }
-
- if ($error) {
- $json_array['error'] = $error;
- }
-
- return json_encode($json_array);
- }
-
- /*
- * Get extended package details (for info and multiinfo queries).
- *
- * @param $pkgid The ID of the package to retrieve details for.
- * @param $base_id The ID of the package base to retrieve details for.
- *
- * @return array An array containing package details.
- */
- private function get_extended_fields($pkgid, $base_id) {
- $query = "SELECT DependencyTypes.Name AS Type, " .
- "PackageDepends.DepName AS Name, " .
- "PackageDepends.DepCondition AS Cond " .
- "FROM PackageDepends " .
- "LEFT JOIN DependencyTypes " .
- "ON DependencyTypes.ID = PackageDepends.DepTypeID " .
- "WHERE PackageDepends.PackageID = " . $pkgid . " " .
- "UNION SELECT RelationTypes.Name AS Type, " .
- "PackageRelations.RelName AS Name, " .
- "PackageRelations.RelCondition AS Cond " .
- "FROM PackageRelations " .
- "LEFT JOIN RelationTypes " .
- "ON RelationTypes.ID = PackageRelations.RelTypeID " .
- "WHERE PackageRelations.PackageID = " . $pkgid . " " .
- "UNION SELECT 'groups' AS Type, `Groups`.`Name`, '' AS Cond " .
- "FROM `Groups` INNER JOIN PackageGroups " .
- "ON PackageGroups.PackageID = " . $pkgid . " " .
- "AND PackageGroups.GroupID = `Groups`.ID " .
- "UNION SELECT 'license' AS Type, Licenses.Name, '' AS Cond " .
- "FROM Licenses INNER JOIN PackageLicenses " .
- "ON PackageLicenses.PackageID = " . $pkgid . " " .
- "AND PackageLicenses.LicenseID = Licenses.ID";
- $ttl = config_get_int('options', 'cache_pkginfo_ttl');
- $rows = db_cache_result($query, 'extended-fields:' . $pkgid, PDO::FETCH_ASSOC, $ttl);
-
- $type_map = array(
- 'depends' => 'Depends',
- 'makedepends' => 'MakeDepends',
- 'checkdepends' => 'CheckDepends',
- 'optdepends' => 'OptDepends',
- 'conflicts' => 'Conflicts',
- 'provides' => 'Provides',
- 'replaces' => 'Replaces',
- 'groups' => 'Groups',
- 'license' => 'License',
- );
- $data = array();
- foreach ($rows as $row) {
- $type = $type_map[$row['Type']];
- $data[$type][] = $row['Name'] . $row['Cond'];
- }
-
- if ($this->version >= 5) {
- $query = "SELECT Keyword FROM PackageKeywords " .
- "WHERE PackageBaseID = " . intval($base_id) . " " .
- "ORDER BY Keyword ASC";
- $ttl = config_get_int('options', 'cache_pkginfo_ttl');
- $rows = db_cache_result($query, 'keywords:' . intval($base_id), PDO::FETCH_NUM, $ttl);
- $data['Keywords'] = array_map(function ($x) { return $x[0]; }, $rows);
- }
-
- return $data;
- }
-
- /*
- * Retrieve package information (used in info, multiinfo, search and
- * depends requests).
- *
- * @param $type The request type.
- * @param $where_condition An SQL WHERE-condition to filter packages.
- *
- * @return mixed Returns an array of package matches.
- */
- private function process_query($type, $where_condition) {
- $max_results = config_get_int('options', 'max_rpc_results');
-
- if ($this->version == 1) {
- $fields = implode(',', self::$fields_v1);
- $query = "SELECT {$fields} " .
- "FROM Packages LEFT JOIN PackageBases " .
- "ON PackageBases.ID = Packages.PackageBaseID " .
- "LEFT JOIN Users " .
- "ON PackageBases.MaintainerUID = Users.ID " .
- "LEFT JOIN PackageLicenses " .
- "ON PackageLicenses.PackageID = Packages.ID " .
- "LEFT JOIN Licenses " .
- "ON Licenses.ID = PackageLicenses.LicenseID " .
- "WHERE ${where_condition} " .
- "AND PackageBases.PackagerUID IS NOT NULL " .
- "LIMIT $max_results";
- } elseif ($this->version >= 2) {
- if ($this->version == 2 || $this->version == 3) {
- $fields = implode(',', self::$fields_v2);
- } else if ($this->version >= 4 && $this->version <= 6) {
- $fields = implode(',', self::$fields_v4);
- }
- $query = "SELECT {$fields} " .
- "FROM Packages LEFT JOIN PackageBases " .
- "ON PackageBases.ID = Packages.PackageBaseID " .
- "LEFT JOIN Users " .
- "ON PackageBases.MaintainerUID = Users.ID " .
- "WHERE ${where_condition} " .
- "AND PackageBases.PackagerUID IS NOT NULL " .
- "LIMIT $max_results";
- }
- $result = $this->dbh->query($query);
-
- if ($result) {
- $resultcount = 0;
- $search_data = array();
- while ($row = $result->fetch(PDO::FETCH_ASSOC)) {
- $resultcount++;
- $row['URLPath'] = sprintf(config_get('options', 'snapshot_uri'), urlencode($row['PackageBase']));
- if ($this->version < 4) {
- $row['CategoryID'] = 1;
- }
-
- /*
- * Unfortunately, mysql_fetch_assoc() returns
- * all fields as strings. We need to coerce
- * numeric values into integers to provide
- * proper data types in the JSON response.
- */
- foreach (self::$numeric_fields as $field) {
- if (isset($row[$field])) {
- $row[$field] = intval($row[$field]);
- }
- }
-
- foreach (self::$decimal_fields as $field) {
- if (isset($row[$field])) {
- $row[$field] = floatval($row[$field]);
- }
- }
-
- if ($this->version >= 2 && ($type == 'info' || $type == 'multiinfo')) {
- $extfields = $this->get_extended_fields($row['ID'], $row['PackageBaseID']);
- if ($extfields) {
- $row = array_merge($row, $extfields);
- }
- }
-
- if ($this->version < 3) {
- if ($type == 'info') {
- $search_data = $row;
- break;
- } else {
- array_push($search_data, $row);
- }
- } elseif ($this->version >= 3) {
- array_push($search_data, $row);
- }
- }
-
- if ($resultcount === $max_results) {
- return $this->json_error('Too many package results.');
- }
-
- return $this->json_results($type, $resultcount, $search_data, NULL);
- } else {
- return $this->json_results($type, 0, array(), NULL);
- }
- }
-
- /*
- * Parse the args to the multiinfo function. We may have a string or an
- * array, so do the appropriate thing. Within the elements, both * package
- * IDs and package names are valid; sort them into the relevant arrays and
- * escape/quote the names.
- *
- * @param array $args Query parameters.
- *
- * @return mixed An array containing 'ids' and 'names'.
- */
- private function parse_multiinfo_args($args) {
- if (!is_array($args)) {
- $args = array($args);
- }
-
- $id_args = array();
- $name_args = array();
- foreach ($args as $arg) {
- if (!$arg) {
- continue;
- }
- if ($this->version < 5 && is_numeric($arg)) {
- $id_args[] = intval($arg);
- } else {
- $name_args[] = $this->dbh->quote($arg);
- }
- }
-
- return array('ids' => $id_args, 'names' => $name_args);
- }
-
- /*
- * Performs a fulltext mysql search of the package database.
- *
- * @param array $http_data Query parameters.
- *
- * @return mixed Returns an array of package matches.
- */
- private function search($http_data) {
- $keyword_string = $http_data['arg'];
-
- if (isset($http_data['by'])) {
- $search_by = $http_data['by'];
- } else {
- $search_by = 'name-desc';
- }
-
- if ($search_by === 'name' || $search_by === 'name-desc') {
- if (strlen($keyword_string) < 2) {
- return $this->json_error('Query arg too small.');
- }
-
- if ($this->version >= 6 && $search_by === 'name-desc') {
- $where_condition = construct_keyword_search($this->dbh,
- $keyword_string, true, false);
- } else {
- $keyword_string = $this->dbh->quote(
- "%" . addcslashes($keyword_string, '%_') . "%");
-
- if ($search_by === 'name') {
- $where_condition = "(Packages.Name LIKE $keyword_string)";
- } else if ($search_by === 'name-desc') {
- $where_condition = "(Packages.Name LIKE $keyword_string ";
- $where_condition .= "OR Description LIKE $keyword_string)";
- }
-
- }
- } else if ($search_by === 'maintainer') {
- if (empty($keyword_string)) {
- $where_condition = "Users.ID is NULL";
- } else {
- $keyword_string = $this->dbh->quote($keyword_string);
- $where_condition = "Users.Username = $keyword_string ";
- }
- } else if (in_array($search_by, self::$exposed_depfields)) {
- if (empty($keyword_string)) {
- return $this->json_error('Query arg is empty.');
- } else {
- $keyword_string = $this->dbh->quote($keyword_string);
- $search_by = $this->dbh->quote($search_by);
- $subquery = "SELECT PackageDepends.DepName FROM PackageDepends ";
- $subquery .= "LEFT JOIN DependencyTypes ";
- $subquery .= "ON PackageDepends.DepTypeID = DependencyTypes.ID ";
- $subquery .= "WHERE PackageDepends.PackageID = Packages.ID ";
- $subquery .= "AND DependencyTypes.Name = $search_by";
- $where_condition = "$keyword_string IN ($subquery)";
- }
- }
-
- return $this->process_query('search', $where_condition);
- }
-
- /*
- * Returns the info on a specific package.
- *
- * @param array $http_data Query parameters.
- *
- * @return mixed Returns an array of value data containing the package data
- */
- private function info($http_data) {
- $pqdata = $http_data['arg'];
- if ($this->version < 5 && is_numeric($pqdata)) {
- $where_condition = "Packages.ID = $pqdata";
- } else {
- $where_condition = "Packages.Name = " . $this->dbh->quote($pqdata);
- }
-
- return $this->process_query('info', $where_condition);
- }
-
- /*
- * Returns the info on multiple packages.
- *
- * @param array $http_data Query parameters.
- *
- * @return mixed Returns an array of results containing the package data
- */
- private function multiinfo($http_data) {
- $pqdata = $http_data['arg'];
- $args = $this->parse_multiinfo_args($pqdata);
- $ids = $args['ids'];
- $names = $args['names'];
-
- if (!$ids && !$names) {
- return $this->json_error('Invalid query arguments.');
- }
-
- $where_condition = "";
- if ($ids) {
- $ids_value = implode(',', $args['ids']);
- $where_condition .= "Packages.ID IN ($ids_value) ";
- }
- if ($ids && $names) {
- $where_condition .= "OR ";
- }
- if ($names) {
- /*
- * Individual names were quoted in
- * parse_multiinfo_args().
- */
- $names_value = implode(',', $args['names']);
- $where_condition .= "Packages.Name IN ($names_value) ";
- }
-
- return $this->process_query('multiinfo', $where_condition);
- }
-
- /*
- * Returns all the packages for a specific maintainer.
- *
- * @param array $http_data Query parameters.
- *
- * @return mixed Returns an array of value data containing the package data
- */
- private function msearch($http_data) {
- $http_data['by'] = 'maintainer';
- return $this->search($http_data);
- }
-
- /*
- * Get all package names that start with $search.
- *
- * @param array $http_data Query parameters.
- *
- * @return string The JSON formatted response data.
- */
- private function suggest($http_data) {
- $search = $http_data['arg'];
- $query = "SELECT Packages.Name FROM Packages ";
- $query.= "LEFT JOIN PackageBases ";
- $query.= "ON PackageBases.ID = Packages.PackageBaseID ";
- $query.= "WHERE Packages.Name LIKE ";
- $query.= $this->dbh->quote(addcslashes($search, '%_') . '%');
- $query.= " AND PackageBases.PackagerUID IS NOT NULL ";
- $query.= "ORDER BY Name ASC LIMIT 20";
-
- $result = $this->dbh->query($query);
- $result_array = array();
-
- if ($result) {
- $result_array = $result->fetchAll(PDO::FETCH_COLUMN, 0);
- }
-
- return json_encode($result_array);
- }
-
- /*
- * Get all package base names that start with $search.
- *
- * @param array $http_data Query parameters.
- *
- * @return string The JSON formatted response data.
- */
- private function suggest_pkgbase($http_data) {
- $search = $http_data['arg'];
- $query = "SELECT Name FROM PackageBases WHERE Name LIKE ";
- $query.= $this->dbh->quote(addcslashes($search, '%_') . '%');
- $query.= " AND PackageBases.PackagerUID IS NOT NULL ";
- $query.= "ORDER BY Name ASC LIMIT 20";
-
- $result = $this->dbh->query($query);
- $result_array = array();
-
- if ($result) {
- $result_array = $result->fetchAll(PDO::FETCH_COLUMN, 0);
- }
-
- return json_encode($result_array);
- }
-
- /**
- * Get the HTML markup of the comment form.
- *
- * @param array $http_data Query parameters.
- *
- * @return string The JSON formatted response data.
- */
- private function get_comment_form($http_data) {
- if (!isset($http_data['base_id']) || !isset($http_data['pkgbase_name'])) {
- $output = array(
- 'success' => 0,
- 'error' => __('Package base ID or package base name missing.')
- );
- return json_encode($output);
- }
-
- $comment_id = intval($http_data['arg']);
- $base_id = intval($http_data['base_id']);
- $pkgbase_name = $http_data['pkgbase_name'];
-
- list($user_id, $comment) = comment_by_id($comment_id);
-
- if (!has_credential(CRED_COMMENT_EDIT, array($user_id))) {
- $output = array(
- 'success' => 0,
- 'error' => __('You are not allowed to edit this comment.')
- );
- return json_encode($output);
- } elseif (is_null($comment)) {
- $output = array(
- 'success' => 0,
- 'error' => __('Comment does not exist.')
- );
- return json_encode($output);
- }
-
- ob_start();
- include('pkg_comment_form.php');
- $html = ob_get_clean();
- $output = array(
- 'success' => 1,
- 'form' => $html
- );
-
- return json_encode($output);
- }
-}
diff --git a/web/lib/cachefuncs.inc.php b/web/lib/cachefuncs.inc.php
deleted file mode 100644
index b2b96c24..00000000
--- a/web/lib/cachefuncs.inc.php
+++ /dev/null
@@ -1,99 +0,0 @@
-addServer($mcserver[0], intval($mcserver[1]));
- }
-}
-
-# Set a value in the cache (currently APC) if cache is available for use. If
-# not available, this becomes effectively a no-op (return value is
-# false). Accepts an optional TTL (defaults to 600 seconds).
-function set_cache_value($key, $value, $ttl=600) {
- $status = false;
- if (defined('EXTENSION_LOADED_APC')) {
- $status = apc_store(CACHE_PREFIX.$key, $value, $ttl);
- }
- if (defined('EXTENSION_LOADED_MEMCACHE')) {
- global $memcache;
- $status = $memcache->set(CACHE_PREFIX.$key, $value, $ttl);
- }
- return $status;
-}
-
-# Get a value from the cache (currently APC) if cache is available for use. If
-# not available, this returns false (optionally sets passed in variable $status
-# to false, much like apc_fetch() behaves). This allows for testing the fetch
-# result appropriately even in the event that a 'false' value was the value in
-# the cache.
-function get_cache_value($key, &$status=false) {
- if(defined('EXTENSION_LOADED_APC')) {
- $ret = apc_fetch(CACHE_PREFIX.$key, $status);
- if ($status) {
- return $ret;
- }
- }
- if (defined('EXTENSION_LOADED_MEMCACHE')) {
- global $memcache;
- $ret = $memcache->get(CACHE_PREFIX.$key);
- if (!$ret) {
- $status = false;
- }
- else {
- $status = true;
- }
- return $ret;
- }
- return $status;
-}
-
-# Run a simple db query, retrieving and/or caching the value if APC is
-# available for use. Accepts an optional TTL value (defaults to 600 seconds).
-function db_cache_value($dbq, $key, $ttl=600) {
- $dbh = DB::connect();
- $status = false;
- $value = get_cache_value($key, $status);
- if (!$status) {
- $result = $dbh->query($dbq);
- if (!$result) {
- return false;
- }
- $row = $result->fetch(PDO::FETCH_NUM);
- $value = $row[0];
- set_cache_value($key, $value, $ttl);
- }
- return $value;
-}
-
-# Run a simple db query, retrieving and/or caching the result set if APC is
-# available for use. Accepts an optional TTL value (defaults to 600 seconds).
-function db_cache_result($dbq, $key, $fetch_style=PDO::FETCH_NUM, $ttl=600) {
- $dbh = DB::connect();
- $status = false;
- $value = get_cache_value($key, $status);
- if (!$status) {
- $result = $dbh->query($dbq);
- if (!$result) {
- return false;
- }
- $value = $result->fetchAll($fetch_style);
- set_cache_value($key, $value, $ttl);
- }
- return $value;
-}
-
-?>
diff --git a/web/lib/confparser.inc.php b/web/lib/confparser.inc.php
deleted file mode 100644
index fdd2b78e..00000000
--- a/web/lib/confparser.inc.php
+++ /dev/null
@@ -1,59 +0,0 @@
-useCached(); // use cached version if age<1 hour
-$rss->title = "PHP news";
-$rss->description = "daily news from the PHP scripting world";
-
-//optional
-$rss->descriptionTruncSize = 500;
-$rss->descriptionHtmlSyndicated = true;
-
-$rss->link = "http://www.dailyphp.net/news";
-$rss->syndicationURL = "http://www.dailyphp.net/".$_SERVER["PHP_SELF"];
-
-$image = new FeedImage();
-$image->title = "dailyphp.net logo";
-$image->url = "http://www.dailyphp.net/images/logo.gif";
-$image->link = "http://www.dailyphp.net";
-$image->description = "Feed provided by dailyphp.net. Click to visit.";
-
-//optional
-$image->descriptionTruncSize = 500;
-$image->descriptionHtmlSyndicated = true;
-
-$rss->image = $image;
-
-// get your news items from somewhere, e.g. your database:
-mysql_select_db($dbHost, $dbUser, $dbPass);
-$res = mysql_query("SELECT * FROM news ORDER BY newsdate DESC");
-while ($data = mysql_fetch_object($res)) {
- $item = new FeedItem();
- $item->title = $data->title;
- $item->link = $data->url;
- $item->description = $data->short;
-
- //optional
- item->descriptionTruncSize = 500;
- item->descriptionHtmlSyndicated = true;
-
- $item->date = $data->newsdate;
- $item->source = "http://www.dailyphp.net";
- $item->author = "John Doe";
-
- $rss->addItem($item);
-}
-
-// valid format strings are: RSS0.91, RSS1.0, RSS2.0, PIE0.1 (deprecated),
-// MBOX, OPML, ATOM, ATOM0.3, HTML, JS
-echo $rss->saveFeed("RSS1.0", "news/feed.xml");
-
-
-***************************************************************************
-* A little setup *
-**************************************************************************/
-
-// your local timezone, set to "" to disable or for GMT
-define("TIME_ZONE","+01:00");
-
-
-
-
-/**
- * Version string.
- **/
-define("FEEDCREATOR_VERSION", "FeedCreator 1.7.2");
-
-
-
-/**
- * A FeedItem is a part of a FeedCreator feed.
- *
- * @author Kai Blankenhorn
- * @since 1.3
- */
-class FeedItem extends HtmlDescribable {
- /**
- * Mandatory attributes of an item.
- */
- var $title, $description, $link;
-
- /**
- * Optional attributes of an item.
- */
- var $author, $authorEmail, $image, $category, $comments, $guid, $guidIsPermaLink, $source, $creator;
-
- /**
- * Publishing date of an item. May be in one of the following formats:
- *
- * RFC 822:
- * "Mon, 20 Jan 03 18:05:41 +0400"
- * "20 Jan 03 18:05:41 +0000"
- *
- * ISO 8601:
- * "2003-01-20T18:05:41+04:00"
- *
- * Unix:
- * 1043082341
- */
- var $date;
-
- /**
- * Any additional elements to include as an assiciated array. All $key => $value pairs
- * will be included unencoded in the feed item in the form
- * <$key>$value$key>
- * Again: No encoding will be used! This means you can invalidate or enhance the feed
- * if $value contains markup. This may be abused to embed tags not implemented by
- * the FeedCreator class used.
- */
- var $additionalElements = Array();
-
- // on hold
- // var $source;
-}
-
-
-
-/**
- * An FeedImage may be added to a FeedCreator feed.
- * @author Kai Blankenhorn
- * @since 1.3
- */
-class FeedImage extends HtmlDescribable {
- /**
- * Mandatory attributes of an image.
- */
- var $title, $url, $link;
-
- /**
- * Optional attributes of an image.
- */
- var $width, $height, $description;
-}
-
-
-
-/**
- * An HtmlDescribable is an item within a feed that can have a description that may
- * include HTML markup.
- */
-class HtmlDescribable {
- /**
- * Indicates whether the description field should be rendered in HTML.
- */
- var $descriptionHtmlSyndicated;
-
- /**
- * Indicates whether and to how many characters a description should be truncated.
- */
- var $descriptionTruncSize;
-
- /**
- * Returns a formatted description field, depending on descriptionHtmlSyndicated and
- * $descriptionTruncSize properties
- * @return string the formatted description
- */
- function getDescription() {
- $descriptionField = new FeedHtmlField($this->description);
- $descriptionField->syndicateHtml = $this->descriptionHtmlSyndicated;
- $descriptionField->truncSize = $this->descriptionTruncSize;
- return $descriptionField->output();
- }
-
-}
-
-
-/**
- * An FeedHtmlField describes and generates
- * a feed, item or image html field (probably a description). Output is
- * generated based on $truncSize, $syndicateHtml properties.
- * @author Pascal Van Hecke
- * @version 1.6
- */
-class FeedHtmlField {
- /**
- * Mandatory attributes of a FeedHtmlField.
- */
- var $rawFieldContent;
-
- /**
- * Optional attributes of a FeedHtmlField.
- *
- */
- var $truncSize, $syndicateHtml;
-
- /**
- * Creates a new instance of FeedHtmlField.
- * @param $string: if given, sets the rawFieldContent property
- */
- function FeedHtmlField($parFieldContent) {
- if ($parFieldContent) {
- $this->rawFieldContent = $parFieldContent;
- }
- }
-
-
- /**
- * Creates the right output, depending on $truncSize, $syndicateHtml properties.
- * @return string the formatted field
- */
- function output() {
- // when field available and syndicated in html we assume
- // - valid html in $rawFieldContent and we enclose in CDATA tags
- // - no truncation (truncating risks producing invalid html)
- if (!$this->rawFieldContent) {
- $result = "";
- } elseif ($this->syndicateHtml) {
- $result = "rawFieldContent."]]>";
- } else {
- if ($this->truncSize and is_int($this->truncSize)) {
- $result = FeedCreator::iTrunc(htmlspecialchars($this->rawFieldContent),$this->truncSize);
- } else {
- $result = htmlspecialchars($this->rawFieldContent);
- }
- }
- return $result;
- }
-
-}
-
-
-
-/**
- * UniversalFeedCreator lets you choose during runtime which
- * format to build.
- * For general usage of a feed class, see the FeedCreator class
- * below or the example above.
- *
- * @since 1.3
- * @author Kai Blankenhorn
- */
-class UniversalFeedCreator extends FeedCreator {
- var $_feed;
-
- function _setFormat($format) {
- switch (strtoupper($format)) {
-
- case "2.0":
- // fall through
- case "RSS2.0":
- $this->_feed = new RSSCreator20();
- break;
-
- case "1.0":
- // fall through
- case "RSS1.0":
- $this->_feed = new RSSCreator10();
- break;
-
- case "0.91":
- // fall through
- case "RSS0.91":
- $this->_feed = new RSSCreator091();
- break;
-
- case "PIE0.1":
- $this->_feed = new PIECreator01();
- break;
-
- case "MBOX":
- $this->_feed = new MBOXCreator();
- break;
-
- case "OPML":
- $this->_feed = new OPMLCreator();
- break;
-
- case "ATOM":
- // fall through: always the latest ATOM version
-
- case "ATOM0.3":
- $this->_feed = new AtomCreator03();
- break;
-
- case "HTML":
- $this->_feed = new HTMLCreator();
- break;
-
- case "JS":
- // fall through
- case "JAVASCRIPT":
- $this->_feed = new JSCreator();
- break;
-
- default:
- $this->_feed = new RSSCreator091();
- break;
- }
-
- $vars = get_object_vars($this);
- foreach ($vars as $key => $value) {
- // prevent overwriting of properties "contentType", "encoding"; do not copy "_feed" itself
- if (!in_array($key, array("_feed", "contentType", "encoding"))) {
- $this->_feed->{$key} = $this->{$key};
- }
- }
- }
-
- /**
- * Creates a syndication feed based on the items previously added.
- *
- * @see FeedCreator::addItem()
- * @param string format format the feed should comply to. Valid values are:
- * "PIE0.1", "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3", "HTML", "JS"
- * @return string the contents of the feed.
- */
- function createFeed($format = "RSS0.91") {
- $this->_setFormat($format);
- return $this->_feed->createFeed();
- }
-
-
-
- /**
- * Saves this feed as a file on the local disk. After the file is saved, an HTTP redirect
- * header may be sent to redirect the use to the newly created file.
- * @since 1.4
- *
- * @param string format format the feed should comply to. Valid values are:
- * "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM", "ATOM0.3", "HTML", "JS"
- * @param string filename optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
- * @param boolean displayContents optional send the content of the file or not. If true, the file will be sent in the body of the response.
- */
- function saveFeed($format="RSS0.91", $filename="", $displayContents=true) {
- $this->_setFormat($format);
- $this->_feed->saveFeed($filename, $displayContents);
- }
-
-
- /**
- * Turns on caching and checks if there is a recent version of this feed in the cache.
- * If there is, an HTTP redirect header is sent.
- * To effectively use caching, you should create the FeedCreator object and call this method
- * before anything else, especially before you do the time consuming task to build the feed
- * (web fetching, for example).
- *
- * @param string format format the feed should comply to. Valid values are:
- * "PIE0.1" (deprecated), "mbox", "RSS0.91", "RSS1.0", "RSS2.0", "OPML", "ATOM0.3".
- * @param filename string optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
- * @param timeout int optional the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour)
- */
- function useCached($format="RSS0.91", $filename="", $timeout=3600) {
- $this->_setFormat($format);
- $this->_feed->useCached($filename, $timeout);
- }
-
-}
-
-
-/**
- * FeedCreator is the abstract base implementation for concrete
- * implementations that implement a specific format of syndication.
- *
- * @abstract
- * @author Kai Blankenhorn
- * @since 1.4
- */
-class FeedCreator extends HtmlDescribable {
-
- /**
- * Mandatory attributes of a feed.
- */
- var $title, $description, $link;
-
-
- /**
- * Optional attributes of a feed.
- */
- var $syndicationURL, $image, $language, $copyright, $pubDate, $lastBuildDate, $editor, $editorEmail, $webmaster, $category, $docs, $ttl, $rating, $skipHours, $skipDays;
-
- /**
- * The url of the external xsl stylesheet used to format the naked rss feed.
- * Ignored in the output when empty.
- */
- var $xslStyleSheet = "";
-
-
- /**
- * @access private
- */
- var $items = Array();
-
-
- /**
- * This feed's MIME content type.
- * @since 1.4
- * @access private
- */
- var $contentType = "application/xml";
-
-
- /**
- * This feed's character encoding.
- * @since 1.6.1
- **/
- var $encoding = "ISO-8859-1";
-
-
- /**
- * Any additional elements to include as an assiciated array. All $key => $value pairs
- * will be included unencoded in the feed in the form
- * <$key>$value$key>
- * Again: No encoding will be used! This means you can invalidate or enhance the feed
- * if $value contains markup. This may be abused to embed tags not implemented by
- * the FeedCreator class used.
- */
- var $additionalElements = Array();
-
-
- /**
- * Adds an FeedItem to the feed.
- *
- * @param object FeedItem $item The FeedItem to add to the feed.
- * @access public
- */
- function addItem($item) {
- $this->items[] = $item;
- }
-
-
- /**
- * Truncates a string to a certain length at the most sensible point.
- * First, if there's a '.' character near the end of the string, the string is truncated after this character.
- * If there is no '.', the string is truncated after the last ' ' character.
- * If the string is truncated, " ..." is appended.
- * If the string is already shorter than $length, it is returned unchanged.
- *
- * @static
- * @param string string A string to be truncated.
- * @param int length the maximum length the string should be truncated to
- * @return string the truncated string
- */
- function iTrunc($string, $length) {
- if (strlen($string)<=$length) {
- return $string;
- }
-
- $pos = strrpos($string,".");
- if ($pos>=$length-4) {
- $string = substr($string,0,$length-4);
- $pos = strrpos($string,".");
- }
- if ($pos>=$length*0.4) {
- return substr($string,0,$pos+1)." ...";
- }
-
- $pos = strrpos($string," ");
- if ($pos>=$length-4) {
- $string = substr($string,0,$length-4);
- $pos = strrpos($string," ");
- }
- if ($pos>=$length*0.4) {
- return substr($string,0,$pos)." ...";
- }
-
- return substr($string,0,$length-4)." ...";
-
- }
-
-
- /**
- * Creates a comment indicating the generator of this feed.
- * The format of this comment seems to be recognized by
- * Syndic8.com.
- */
- function _createGeneratorComment() {
- return "\n";
- }
-
-
- /**
- * Creates a string containing all additional elements specified in
- * $additionalElements.
- * @param elements array an associative array containing key => value pairs
- * @param indentString string a string that will be inserted before every generated line
- * @return string the XML tags corresponding to $additionalElements
- */
- function _createAdditionalElements($elements, $indentString="") {
- $ae = "";
- if (is_array($elements)) {
- foreach($elements AS $key => $value) {
- $ae.= $indentString."<$key>$value$key>\n";
- }
- }
- return $ae;
- }
-
- function _createStylesheetReferences() {
- $xml = "";
- if ($this->cssStyleSheet) $xml .= "cssStyleSheet."\" type=\"text/css\"?>\n";
- if ($this->xslStyleSheet) $xml .= "xslStyleSheet."\" type=\"text/xsl\"?>\n";
- return $xml;
- }
-
-
- /**
- * Builds the feed's text.
- * @abstract
- * @return string the feed's complete text
- */
- function createFeed() {
- }
-
- /**
- * Generate a filename for the feed cache file. The result will be $_SERVER["PHP_SELF"] with the extension changed to .xml.
- * For example:
- *
- * echo $_SERVER["PHP_SELF"]."\n";
- * echo FeedCreator::_generateFilename();
- *
- * would produce:
- *
- * /rss/latestnews.php
- * latestnews.xml
- *
- * @return string the feed cache filename
- * @since 1.4
- * @access private
- */
- function _generateFilename() {
- $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
- return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".xml";
- }
-
-
- /**
- * @since 1.4
- * @access private
- */
- function _redirect($filename) {
- // attention, heavily-commented-out-area
-
- // maybe use this in addition to file time checking
- //Header("Expires: ".date("r",time()+$this->_timeout));
-
- /* no caching at all, doesn't seem to work as good:
- Header("Cache-Control: no-cache");
- Header("Pragma: no-cache");
- */
-
- // HTTP redirect, some feed readers' simple HTTP implementations don't follow it
- //Header("Location: ".$filename);
-
- Header("Content-Type: ".$this->contentType."; charset=".$this->encoding."; filename=".basename($filename));
- Header("Content-Disposition: inline; filename=".basename($filename));
- readfile($filename, "r");
- die();
- }
-
- /**
- * Turns on caching and checks if there is a recent version of this feed in the cache.
- * If there is, an HTTP redirect header is sent.
- * To effectively use caching, you should create the FeedCreator object and call this method
- * before anything else, especially before you do the time consuming task to build the feed
- * (web fetching, for example).
- * @since 1.4
- * @param filename string optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
- * @param timeout int optional the timeout in seconds before a cached version is refreshed (defaults to 3600 = 1 hour)
- */
- function useCached($filename="", $timeout=3600) {
- $this->_timeout = $timeout;
- if ($filename=="") {
- $filename = $this->_generateFilename();
- }
- if (file_exists($filename) AND (time()-filemtime($filename) < $timeout)) {
- $this->_redirect($filename);
- }
- }
-
-
- /**
- * Saves this feed as a file on the local disk. After the file is saved, a redirect
- * header may be sent to redirect the user to the newly created file.
- * @since 1.4
- *
- * @param filename string optional the filename where a recent version of the feed is saved. If not specified, the filename is $_SERVER["PHP_SELF"] with the extension changed to .xml (see _generateFilename()).
- * @param redirect boolean optional send an HTTP redirect header or not. If true, the user will be automatically redirected to the created file.
- */
- function saveFeed($filename="", $displayContents=true) {
- if ($filename=="") {
- $filename = $this->_generateFilename();
- }
- $feedFile = fopen($filename, "w+");
- if ($feedFile) {
- fputs($feedFile,$this->createFeed());
- fclose($feedFile);
- if ($displayContents) {
- $this->_redirect($filename);
- }
- } else {
- echo " Error creating feed file, please check write permissions. ";
- }
- }
-
-}
-
-
-/**
- * FeedDate is an internal class that stores a date for a feed or feed item.
- * Usually, you won't need to use this.
- */
-class FeedDate {
- var $unix;
-
- /**
- * Creates a new instance of FeedDate representing a given date.
- * Accepts RFC 822, ISO 8601 date formats as well as unix time stamps.
- * @param mixed $dateString optional the date this FeedDate will represent. If not specified, the current date and time is used.
- */
- function FeedDate($dateString="") {
- if ($dateString=="") $dateString = date("r");
-
- if (is_integer($dateString)) {
- $this->unix = $dateString;
- return;
- }
- if (preg_match("~(?:(?:Mon|Tue|Wed|Thu|Fri|Sat|Sun),\\s+)?(\\d{1,2})\\s+([a-zA-Z]{3})\\s+(\\d{4})\\s+(\\d{2}):(\\d{2}):(\\d{2})\\s+(.*)~",$dateString,$matches)) {
- $months = Array("Jan"=>1,"Feb"=>2,"Mar"=>3,"Apr"=>4,"May"=>5,"Jun"=>6,"Jul"=>7,"Aug"=>8,"Sep"=>9,"Oct"=>10,"Nov"=>11,"Dec"=>12);
- $this->unix = mktime($matches[4],$matches[5],$matches[6],$months[$matches[2]],$matches[1],$matches[3]);
- if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') {
- $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60;
- } else {
- if (strlen($matches[7])==1) {
- $oneHour = 3600;
- $ord = ord($matches[7]);
- if ($ord < ord("M")) {
- $tzOffset = (ord("A") - $ord - 1) * $oneHour;
- } elseif ($ord >= ord("M") AND $matches[7]!="Z") {
- $tzOffset = ($ord - ord("M")) * $oneHour;
- } elseif ($matches[7]=="Z") {
- $tzOffset = 0;
- }
- }
- switch ($matches[7]) {
- case "UT":
- case "GMT": $tzOffset = 0;
- }
- }
- $this->unix += $tzOffset;
- return;
- }
- if (preg_match("~(\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})(.*)~",$dateString,$matches)) {
- $this->unix = mktime($matches[4],$matches[5],$matches[6],$matches[2],$matches[3],$matches[1]);
- if (substr($matches[7],0,1)=='+' OR substr($matches[7],0,1)=='-') {
- $tzOffset = (substr($matches[7],0,3) * 60 + substr($matches[7],-2)) * 60;
- } else {
- if ($matches[7]=="Z") {
- $tzOffset = 0;
- }
- }
- $this->unix += $tzOffset;
- return;
- }
- $this->unix = 0;
- }
-
- /**
- * Gets the date stored in this FeedDate as an RFC 822 date.
- *
- * @return a date in RFC 822 format
- */
- function rfc822() {
- //return gmdate("r",$this->unix);
- $date = gmdate("D, d M Y H:i:s", $this->unix);
- if (TIME_ZONE!="") $date .= " ".str_replace(":","",TIME_ZONE);
- return $date;
- }
-
- /**
- * Gets the date stored in this FeedDate as an ISO 8601 date.
- *
- * @return a date in ISO 8601 format
- */
- function iso8601() {
- $date = gmdate("Y-m-d\TH:i:sO",$this->unix);
- $date = substr($date,0,22) . ':' . substr($date,-2);
- if (TIME_ZONE!="") $date = str_replace("+00:00",TIME_ZONE,$date);
- return $date;
- }
-
- /**
- * Gets the date stored in this FeedDate as unix time stamp.
- *
- * @return a date as a unix time stamp
- */
- function unix() {
- return $this->unix;
- }
-}
-
-
-/**
- * RSSCreator10 is a FeedCreator that implements RDF Site Summary (RSS) 1.0.
- *
- * @see http://www.purl.org/rss/1.0/
- * @since 1.3
- * @author Kai Blankenhorn
- */
-class RSSCreator10 extends FeedCreator {
-
- /**
- * Builds the RSS feed's text. The feed will be compliant to RDF Site Summary (RSS) 1.0.
- * The feed will contain all items previously added in the same order.
- * @return string the feed's complete text
- */
- function createFeed() {
- $feed = "encoding."\"?>\n";
- $feed.= $this->_createGeneratorComment();
- if ($this->cssStyleSheet=="") {
- $cssStyleSheet = "http://www.w3.org/2000/08/w3c-synd/style.css";
- }
- $feed.= $this->_createStylesheetReferences();
- $feed.= "\n";
- $feed.= " syndicationURL."\">\n";
- $feed.= " ".htmlspecialchars($this->title)."\n";
- $feed.= " ".htmlspecialchars($this->description)."\n";
- $feed.= " ".$this->link."\n";
- if ($this->image!=null) {
- $feed.= " image->url."\" />\n";
- }
- $now = new FeedDate();
- $feed.= " ".htmlspecialchars($now->iso8601())."\n";
- $feed.= " \n";
- $feed.= " \n";
- for ($i=0;$iitems);$i++) {
- $feed.= " items[$i]->link)."\"/>\n";
- }
- $feed.= " \n";
- $feed.= " \n";
- $feed.= " \n";
- if ($this->image!=null) {
- $feed.= " image->url."\">\n";
- $feed.= " ".$this->image->title."\n";
- $feed.= " ".$this->image->link."\n";
- $feed.= " ".$this->image->url."\n";
- $feed.= " \n";
- }
- $feed.= $this->_createAdditionalElements($this->additionalElements, " ");
-
- for ($i=0;$iitems);$i++) {
- $feed.= " items[$i]->link)."\">\n";
- //$feed.= " Posting\n";
- $feed.= " text/html\n";
- if ($this->items[$i]->date!=null) {
- $itemDate = new FeedDate($this->items[$i]->date);
- $feed.= " ".htmlspecialchars($itemDate->iso8601())."\n";
- }
- if ($this->items[$i]->source!="") {
- $feed.= " ".htmlspecialchars($this->items[$i]->source)."\n";
- }
- if ($this->items[$i]->author!="") {
- $feed.= " ".htmlspecialchars($this->items[$i]->author)."\n";
- }
- $feed.= " ".htmlspecialchars(strip_tags(strtr($this->items[$i]->title,"\n\r"," ")))."\n";
- $feed.= " ".htmlspecialchars($this->items[$i]->link)."\n";
- $feed.= " ".htmlspecialchars($this->items[$i]->description)."\n";
- $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, " ");
- $feed.= " \n";
- }
- $feed.= "\n";
- return $feed;
- }
-}
-
-
-
-/**
- * RSSCreator091 is a FeedCreator that implements RSS 0.91 Spec, revision 3.
- *
- * @see http://my.netscape.com/publish/formats/rss-spec-0.91.html
- * @since 1.3
- * @author Kai Blankenhorn
- */
-class RSSCreator091 extends FeedCreator {
-
- /**
- * Stores this RSS feed's version number.
- * @access private
- */
- var $RSSVersion;
-
- function RSSCreator091() {
- $this->_setRSSVersion("0.91");
- $this->contentType = "application/rss+xml";
- }
-
- /**
- * Sets this RSS feed's version number.
- * @access private
- */
- function _setRSSVersion($version) {
- $this->RSSVersion = $version;
- }
-
- /**
- * Builds the RSS feed's text. The feed will be compliant to RDF Site Summary (RSS) 1.0.
- * The feed will contain all items previously added in the same order.
- * @return string the feed's complete text
- */
- function createFeed() {
- $feed = "encoding."\"?>\n";
- $feed.= $this->_createGeneratorComment();
- $feed.= $this->_createStylesheetReferences();
- $feed.= "RSSVersion."\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n";
- $feed.= " \n";
- $feed.= " ".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."\n";
- $this->descriptionTruncSize = 500;
- $feed.= " ".$this->getDescription()."\n";
- $feed.= " ".$this->link."\n";
- $feed.= " syndicationURL."\" rel=\"self\" type=\"application/rss+xml\" />\n";
- $now = new FeedDate();
- $feed.= " ".htmlspecialchars($now->rfc822())."\n";
- $feed.= " ".FEEDCREATOR_VERSION."\n";
-
- if ($this->image!=null) {
- $feed.= " \n";
- $feed.= " ".$this->image->url."\n";
- $feed.= " ".FeedCreator::iTrunc(htmlspecialchars($this->image->title),100)."\n";
- $feed.= " ".$this->image->link."\n";
- if ($this->image->width!="") {
- $feed.= " ".$this->image->width."\n";
- }
- if ($this->image->height!="") {
- $feed.= " ".$this->image->height."\n";
- }
- if ($this->image->description!="") {
- $feed.= " ".$this->image->getDescription()."\n";
- }
- $feed.= " \n";
- }
- if ($this->language!="") {
- $feed.= " ".$this->language."\n";
- }
- if ($this->copyright!="") {
- $feed.= " ".FeedCreator::iTrunc(htmlspecialchars($this->copyright),100)."\n";
- }
- if ($this->editor!="") {
- $feed.= " ".FeedCreator::iTrunc(htmlspecialchars($this->editor),100)."\n";
- }
- if ($this->webmaster!="") {
- $feed.= " ".FeedCreator::iTrunc(htmlspecialchars($this->webmaster),100)."\n";
- }
- if ($this->pubDate!="") {
- $pubDate = new FeedDate($this->pubDate);
- $feed.= " ".htmlspecialchars($pubDate->rfc822())."\n";
- }
- if ($this->category!="") {
- $feed.= " ".htmlspecialchars($this->category)."\n";
- }
- if ($this->docs!="") {
- $feed.= " ".FeedCreator::iTrunc(htmlspecialchars($this->docs),500)."\n";
- }
- if ($this->ttl!="") {
- $feed.= " ".htmlspecialchars($this->ttl)."\n";
- }
- if ($this->rating!="") {
- $feed.= " ".FeedCreator::iTrunc(htmlspecialchars($this->rating),500)."\n";
- }
- if ($this->skipHours!="") {
- $feed.= " ".htmlspecialchars($this->skipHours)."\n";
- }
- if ($this->skipDays!="") {
- $feed.= " ".htmlspecialchars($this->skipDays)."\n";
- }
- $feed.= $this->_createAdditionalElements($this->additionalElements, " ");
-
- for ($i=0;$iitems);$i++) {
- $feed.= " \n";
- $feed.= " ".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."\n";
- $feed.= " ".htmlspecialchars($this->items[$i]->link)."\n";
- $feed.= " ".$this->items[$i]->getDescription()."\n";
-
- if ($this->items[$i]->author!="") {
- $feed.= " ".htmlspecialchars($this->items[$i]->author)."\n";
- }
- /*
- // on hold
- if ($this->items[$i]->source!="") {
- $feed.= " ".htmlspecialchars($this->items[$i]->source)."\n";
- }
- */
- if ($this->items[$i]->category!="") {
- $feed.= " ".htmlspecialchars($this->items[$i]->category)."\n";
- }
- if ($this->items[$i]->comments!="") {
- $feed.= " ".htmlspecialchars($this->items[$i]->comments)."\n";
- }
- if ($this->items[$i]->date!="") {
- $itemDate = new FeedDate($this->items[$i]->date);
- $feed.= " ".htmlspecialchars($itemDate->rfc822())."\n";
- }
- if ($this->items[$i]->guid!="") {
- $feed.= " items[$i]->guidIsPermaLink == false) {
- $feed.= " isPermaLink=\"false\"";
- }
- $feed.= ">".htmlspecialchars($this->items[$i]->guid)."\n";
- }
- $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, " ");
- $feed.= " \n";
- }
- $feed.= " \n";
- $feed.= "\n";
- return $feed;
- }
-}
-
-
-
-/**
- * RSSCreator20 is a FeedCreator that implements RDF Site Summary (RSS) 2.0.
- *
- * @see http://backend.userland.com/rss
- * @since 1.3
- * @author Kai Blankenhorn
- */
-class RSSCreator20 extends RSSCreator091 {
-
- function RSSCreator20() {
- parent::_setRSSVersion("2.0");
- }
-
-}
-
-
-/**
- * PIECreator01 is a FeedCreator that implements the emerging PIE specification,
- * as in http://intertwingly.net/wiki/pie/Syntax.
- *
- * @deprecated
- * @since 1.3
- * @author Scott Reynen and Kai Blankenhorn
- */
-class PIECreator01 extends FeedCreator {
-
- function PIECreator01() {
- $this->encoding = "utf-8";
- }
-
- function createFeed() {
- $feed = "encoding."\"?>\n";
- $feed.= $this->_createStylesheetReferences();
- $feed.= "\n";
- $feed.= " ".FeedCreator::iTrunc(htmlspecialchars($this->title),100)."\n";
- $this->truncSize = 500;
- $feed.= " ".$this->getDescription()."\n";
- $feed.= " ".$this->link."\n";
- for ($i=0;$iitems);$i++) {
- $feed.= " \n";
- $feed.= " ".FeedCreator::iTrunc(htmlspecialchars(strip_tags($this->items[$i]->title)),100)."\n";
- $feed.= " ".htmlspecialchars($this->items[$i]->link)."\n";
- $itemDate = new FeedDate($this->items[$i]->date);
- $feed.= " ".htmlspecialchars($itemDate->iso8601())."\n";
- $feed.= " ".htmlspecialchars($itemDate->iso8601())."\n";
- $feed.= " ".htmlspecialchars($itemDate->iso8601())."\n";
- $feed.= " ".htmlspecialchars($this->items[$i]->guid)."\n";
- if ($this->items[$i]->author!="") {
- $feed.= " \n";
- $feed.= " ".htmlspecialchars($this->items[$i]->author)."\n";
- if ($this->items[$i]->authorEmail!="") {
- $feed.= " ".$this->items[$i]->authorEmail."\n";
- }
- $feed.=" \n";
- }
- $feed.= " \n";
- $feed.= "
".$this->items[$i]->getDescription()."
\n";
- $feed.= " \n";
- $feed.= " \n";
- }
- $feed.= "\n";
- return $feed;
- }
-}
-
-
-/**
- * AtomCreator03 is a FeedCreator that implements the atom specification,
- * as in http://www.intertwingly.net/wiki/pie/FrontPage.
- * Please note that just by using AtomCreator03 you won't automatically
- * produce valid atom files. For example, you have to specify either an editor
- * for the feed or an author for every single feed item.
- *
- * Some elements have not been implemented yet. These are (incomplete list):
- * author URL, item author's email and URL, item contents, alternate links,
- * other link content types than text/html. Some of them may be created with
- * AtomCreator03::additionalElements.
- *
- * @see FeedCreator#additionalElements
- * @since 1.6
- * @author Kai Blankenhorn , Scott Reynen
- */
-class AtomCreator03 extends FeedCreator {
-
- function AtomCreator03() {
- $this->contentType = "application/atom+xml";
- $this->encoding = "utf-8";
- }
-
- function createFeed() {
- $feed = "encoding."\"?>\n";
- $feed.= $this->_createGeneratorComment();
- $feed.= $this->_createStylesheetReferences();
- $feed.= "language!="") {
- $feed.= " xml:lang=\"".$this->language."\"";
- }
- $feed.= ">\n";
- $feed.= " ".htmlspecialchars($this->title)."\n";
- $feed.= " ".htmlspecialchars($this->description)."\n";
- $feed.= " link)."\"/>\n";
- $feed.= " ".htmlspecialchars($this->link)."\n";
- $now = new FeedDate();
- $feed.= " ".htmlspecialchars($now->iso8601())."\n";
- if ($this->editor!="") {
- $feed.= " \n";
- $feed.= " ".$this->editor."\n";
- if ($this->editorEmail!="") {
- $feed.= " ".$this->editorEmail."\n";
- }
- $feed.= " \n";
- }
- $feed.= " ".FEEDCREATOR_VERSION."\n";
- $feed.= $this->_createAdditionalElements($this->additionalElements, " ");
- for ($i=0;$iitems);$i++) {
- $feed.= " \n";
- $feed.= " ".htmlspecialchars(strip_tags($this->items[$i]->title))."\n";
- $feed.= " items[$i]->link)."\"/>\n";
- if ($this->items[$i]->date=="") {
- $this->items[$i]->date = time();
- }
- $itemDate = new FeedDate($this->items[$i]->date);
- $feed.= " ".htmlspecialchars($itemDate->iso8601())."\n";
- $feed.= " ".htmlspecialchars($itemDate->iso8601())."\n";
- $feed.= " ".htmlspecialchars($itemDate->iso8601())."\n";
- $feed.= " ".htmlspecialchars($this->items[$i]->link)."\n";
- $feed.= $this->_createAdditionalElements($this->items[$i]->additionalElements, " ");
- if ($this->items[$i]->author!="") {
- $feed.= " \n";
- $feed.= " ".htmlspecialchars($this->items[$i]->author)."\n";
- $feed.= " \n";
- }
- if ($this->items[$i]->description!="") {
- $feed.= " ".htmlspecialchars($this->items[$i]->description)."\n";
- }
- $feed.= " \n";
- }
- $feed.= "\n";
- return $feed;
- }
-}
-
-
-/**
- * MBOXCreator is a FeedCreator that implements the mbox format
- * as described in http://www.qmail.org/man/man5/mbox.html
- *
- * @since 1.3
- * @author Kai Blankenhorn
- */
-class MBOXCreator extends FeedCreator {
-
- function MBOXCreator() {
- $this->contentType = "text/plain";
- $this->encoding = "ISO-8859-15";
- }
-
- function qp_enc($input = "", $line_max = 76) {
- $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
- $lines = preg_split("/(?:\r\n|\r|\n)/", $input);
- $eol = "\r\n";
- $escape = "=";
- $output = "";
- while( list(, $line) = each($lines) ) {
- //$line = rtrim($line); // remove trailing white space -> no =20\r\n necessary
- $linlen = strlen($line);
- $newline = "";
- for($i = 0; $i < $linlen; $i++) {
- $c = substr($line, $i, 1);
- $dec = ord($c);
- if ( ($dec == 32) && ($i == ($linlen - 1)) ) { // convert space at eol only
- $c = "=20";
- } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
- $h2 = floor($dec/16); $h1 = floor($dec%16);
- $c = $escape.$hex["$h2"].$hex["$h1"];
- }
- if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
- $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
- $newline = "";
- }
- $newline .= $c;
- } // end of for
- $output .= $newline.$eol;
- }
- return trim($output);
- }
-
-
- /**
- * Builds the MBOX contents.
- * @return string the feed's complete text
- */
- function createFeed() {
- for ($i=0;$iitems);$i++) {
- if ($this->items[$i]->author!="") {
- $from = $this->items[$i]->author;
- } else {
- $from = $this->title;
- }
- $itemDate = new FeedDate($this->items[$i]->date);
- $feed.= "From ".strtr(MBOXCreator::qp_enc($from)," ","_")." ".date("D M d H:i:s Y",$itemDate->unix())."\n";
- $feed.= "Content-Type: text/plain;\n";
- $feed.= " charset=\"".$this->encoding."\"\n";
- $feed.= "Content-Transfer-Encoding: quoted-printable\n";
- $feed.= "Content-Type: text/plain\n";
- $feed.= "From: \"".MBOXCreator::qp_enc($from)."\"\n";
- $feed.= "Date: ".$itemDate->rfc822()."\n";
- $feed.= "Subject: ".MBOXCreator::qp_enc(FeedCreator::iTrunc($this->items[$i]->title,100))."\n";
- $feed.= "\n";
- $body = chunk_split(MBOXCreator::qp_enc($this->items[$i]->description));
- $feed.= preg_replace("~\nFrom ([^\n]*)(\n?)~","\n>From $1$2\n",$body);
- $feed.= "\n";
- $feed.= "\n";
- }
- return $feed;
- }
-
- /**
- * Generate a filename for the feed cache file. Overridden from FeedCreator to prevent XML data types.
- * @return string the feed cache filename
- * @since 1.4
- * @access private
- */
- function _generateFilename() {
- $fileInfo = pathinfo($_SERVER["PHP_SELF"]);
- return substr($fileInfo["basename"],0,-(strlen($fileInfo["extension"])+1)).".mbox";
- }
-}
-
-
-/**
- * OPMLCreator is a FeedCreator that implements OPML 1.0.
- *
- * @see http://opml.scripting.com/spec
- * @author Dirk Clemens, Kai Blankenhorn
- * @since 1.5
- */
-class OPMLCreator extends FeedCreator {
-
- function OPMLCreator() {
- $this->encoding = "utf-8";
- }
-
- function createFeed() {
- $feed = "encoding."\"?>\n";
- $feed.= $this->_createGeneratorComment();
- $feed.= $this->_createStylesheetReferences();
- $feed.= "\n";
- $feed.= " \n";
- $feed.= " ".htmlspecialchars($this->title)."\n";
- if ($this->pubDate!="") {
- $date = new FeedDate($this->pubDate);
- $feed.= " ".$date->rfc822()."\n";
- }
- if ($this->lastBuildDate!="") {
- $date = new FeedDate($this->lastBuildDate);
- $feed.= " ".$date->rfc822()."\n";
- }
- if ($this->editor!="") {
- $feed.= " ".$this->editor."\n";
- }
- if ($this->editorEmail!="") {
- $feed.= " ".$this->editorEmail."\n";
- }
- $feed.= " \n";
- $feed.= " \n";
- for ($i=0;$iitems);$i++) {
- $feed.= " items[$i]->title,"\n\r"," ")));
- $feed.= " title=\"".$title."\"";
- $feed.= " text=\"".$title."\"";
- //$feed.= " description=\"".htmlspecialchars($this->items[$i]->description)."\"";
- $feed.= " url=\"".htmlspecialchars($this->items[$i]->link)."\"";
- $feed.= "/>\n";
- }
- $feed.= " \n";
- $feed.= "\n";
- return $feed;
- }
-}
-
-
-
-/**
- * HTMLCreator is a FeedCreator that writes an HTML feed file to a specific
- * location, overriding the createFeed method of the parent FeedCreator.
- * The HTML produced can be included over http by scripting languages, or serve
- * as the source for an IFrame.
- * All output by this class is embedded in tags to enable formatting
- * using CSS.
- *
- * @author Pascal Van Hecke
- * @since 1.7
- */
-class HTMLCreator extends FeedCreator {
-
- var $contentType = "text/html";
-
- /**
- * Contains HTML to be output at the start of the feed's html representation.
- */
- var $header;
-
- /**
- * Contains HTML to be output at the end of the feed's html representation.
- */
- var $footer ;
-
- /**
- * Contains HTML to be output between entries. A separator is only used in
- * case of multiple entries.
- */
- var $separator;
-
- /**
- * Used to prefix the stylenames to make sure they are unique
- * and do not clash with stylenames on the users' page.
- */
- var $stylePrefix;
-
- /**
- * Determines whether the links open in a new window or not.
- */
- var $openInNewWindow = true;
-
- var $imageAlign ="right";
-
- /**
- * In case of very simple output you may want to get rid of the style tags,
- * hence this variable. There's no equivalent on item level, but of course you can
- * add strings to it while iterating over the items ($this->stylelessOutput .= ...)
- * and when it is non-empty, ONLY the styleless output is printed, the rest is ignored
- * in the function createFeed().
- */
- var $stylelessOutput ="";
-
- /**
- * Writes the HTML.
- * @return string the scripts's complete text
- */
- function createFeed() {
- // if there is styleless output, use the content of this variable and ignore the rest
- if ($this->stylelessOutput!="") {
- return $this->stylelessOutput;
- }
-
- //if no stylePrefix is set, generate it yourself depending on the script name
- if ($this->stylePrefix=="") {
- $this->stylePrefix = str_replace(".", "_", $this->_generateFilename())."_";
- }
-
- //set an openInNewWindow_token_to be inserted or not
- if ($this->openInNewWindow) {
- $targetInsert = " target='_blank'";
- }
-
- // use this array to put the lines in and implode later with "document.write" javascript
- $feedArray = array();
- if ($this->image!=null) {
- $imageStr = "".
- "image->width) {
- $imageStr .=" width='".$this->image->width. "' ";
- }
- if ($this->image->height) {
- $imageStr .=" height='".$this->image->height."' ";
- }
- $imageStr .="/>";
- $feedArray[] = $imageStr;
- }
-
- if ($this->title) {
- $feedArray[] = "
- = __('Click %shere%s if you want to permanently delete this account.', '', '') ?>
- = __('Click %shere%s for user details.', '', '') ?>
- = __('Click %shere%s to list the comments made by this account.', '', '') ?>
-