From ee1048b268e3cc61267007c0bcf60b8c58d3f029 Mon Sep 17 00:00:00 2001 From: Lukas Fleischer Date: Sat, 5 Apr 2014 15:58:44 +0200 Subject: Split out package base functions Move functions operating on package bases to a separate file. Signed-off-by: Lukas Fleischer --- web/lib/pkgbasefuncs.inc.php | 968 +++++++++++++++++++++++++++++++++++++++++++ web/lib/pkgfuncs.inc.php | 968 +------------------------------------------ 2 files changed, 969 insertions(+), 967 deletions(-) create mode 100644 web/lib/pkgbasefuncs.inc.php diff --git a/web/lib/pkgbasefuncs.inc.php b/web/lib/pkgbasefuncs.inc.php new file mode 100644 index 00000000..4aadacaf --- /dev/null +++ b/web/lib/pkgbasefuncs.inc.php @@ -0,0 +1,968 @@ +query($q); + if ($result) { + while ($row = $result->fetch(PDO::FETCH_NUM)) { + $cats[$row[0]] = $row[1]; + } + } + return $cats; +} + +/** + * Get the number of non-deleted comments for a specific package base + * + * @param string $pkgid The package base ID to get comment count for + * + * @return string The number of comments left for a specific package + */ +function pkgbase_comments_count($base_id) { + $dbh = DB::connect(); + + $base_id = intval($base_id); + if ($base_id > 0) { + $dbh = DB::connect(); + $q = "SELECT COUNT(*) FROM PackageComments "; + $q.= "WHERE PackageBaseID = " . $base_id; + $q.= " AND DelUsersID IS NULL"; + } + $result = $dbh->query($q); + + if (!$result) { + return; + } + + $row = $result->fetch(PDO::FETCH_NUM); + return $row[0]; +} + +/** + * Get all package comment information for a specific package base + * + * @param int $pkgid The package base ID to get comments for + * + * @return array All package comment information for a specific package base + */ +function pkgbase_comments($base_id) { + $base_id = intval($base_id); + $comments = array(); + if ($base_id > 0) { + $dbh = DB::connect(); + $q = "SELECT PackageComments.ID, UserName, UsersID, Comments, CommentTS "; + $q.= "FROM PackageComments LEFT JOIN Users "; + $q.= "ON PackageComments.UsersID = Users.ID "; + $q.= "WHERE PackageBaseID = " . $base_id . " "; + $q.= "AND DelUsersID IS NULL "; + $q.= "ORDER BY CommentTS DESC"; + + if (!isset($_GET['comments'])) { + $q.= " LIMIT 10"; + } + + $result = $dbh->query($q); + + if (!$result) { + return; + } + + while ($row = $result->fetch(PDO::FETCH_ASSOC)) { + $comments[] = $row; + } + } + return $comments; +} + +/** + * Add a comment to a package page and send out appropriate notifications + * + * @global string $AUR_LOCATION The AUR's URL used for notification e-mails + * @param string $base_id The package base ID to add the comment on + * @param string $uid The user ID of the individual who left the comment + * @param string $comment The comment left on a package page + * + * @return void + */ +function pkgbase_add_comment($base_id, $uid, $comment) { + global $AUR_LOCATION; + + $dbh = DB::connect(); + + $q = "INSERT INTO PackageComments "; + $q.= "(PackageBaseID, UsersID, Comments, CommentTS) VALUES ("; + $q.= intval($base_id) . ", " . $uid . ", "; + $q.= $dbh->quote($comment) . ", UNIX_TIMESTAMP())"; + $dbh->exec($q); + + /* + * Send e-mail notifications. + * TODO: Move notification logic to separate function where it belongs. + */ + $q = "SELECT CommentNotify.*, Users.Email "; + $q.= "FROM CommentNotify, Users "; + $q.= "WHERE Users.ID = CommentNotify.UserID "; + $q.= "AND CommentNotify.UserID != " . $uid . " "; + $q.= "AND CommentNotify.PackageBaseID = " . intval($base_id); + $result = $dbh->query($q); + $bcc = array(); + + if ($result) { + while ($row = $result->fetch(PDO::FETCH_ASSOC)) { + array_push($bcc, $row['Email']); + } + + $q = "SELECT Name FROM PackageBases WHERE ID = "; + $q.= intval($base_id); + $result = $dbh->query($q); + $row = $result->fetch(PDO::FETCH_ASSOC); + + /* + * TODO: Add native language emails for users, based on their + * preferences. Simply making these strings translatable won't + * work, users would be getting emails in the language that the + * user who posted the comment was in. + */ + $body = + 'from ' . $AUR_LOCATION . get_pkg_uri($row['Name']) . "\n" + . username_from_sid($_COOKIE['AURSID']) . " wrote:\n\n" + . $comment + . "\n\n---\nIf you no longer wish to receive notifications about this package, please go the the above package page and click the UnNotify button."; + $body = wordwrap($body, 70); + $bcc = implode(', ', $bcc); + $headers = "MIME-Version: 1.0\r\n" . + "Content-type: text/plain; charset=UTF-8\r\n" . + "Bcc: $bcc\r\n" . + "Reply-to: nobody@archlinux.org\r\n" . + "From: aur-notify@archlinux.org\r\n" . + "X-Mailer: AUR"; + @mail('undisclosed-recipients: ;', "AUR Comment for " . $row['Name'], $body, $headers); + } +} + +/** + * Get a list of all packages a logged-in user has voted for + * + * @param string $sid The session ID of the visitor + * + * @return array All packages the visitor has voted for + */ +function pkgbase_votes_from_sid($sid="") { + $pkgs = array(); + if (!$sid) {return $pkgs;} + $dbh = DB::connect(); + $q = "SELECT PackageBaseID "; + $q.= "FROM PackageVotes, Users, Sessions "; + $q.= "WHERE Users.ID = Sessions.UsersID "; + $q.= "AND Users.ID = PackageVotes.UsersID "; + $q.= "AND Sessions.SessionID = " . $dbh->quote($sid); + $result = $dbh->query($q); + if ($result) { + while ($row = $result->fetch(PDO::FETCH_NUM)) { + $pkgs[$row[0]] = 1; + } + } + return $pkgs; +} + +/** + * Get the package base details + * + * @param string $id The package base ID to get description for + * + * @return array The package base's details OR error message + **/ +function pkgbase_get_details($base_id) { + $dbh = DB::connect(); + + $q = "SELECT PackageBases.ID, PackageBases.Name, "; + $q.= "PackageBases.CategoryID, PackageBases.NumVotes, "; + $q.= "PackageBases.OutOfDateTS, PackageBases.SubmittedTS, "; + $q.= "PackageBases.ModifiedTS, PackageBases.SubmitterUID, "; + $q.= "PackageBases.MaintainerUID, PackageCategories.Category "; + $q.= "FROM PackageBases, PackageCategories "; + $q.= "WHERE PackageBases.CategoryID = PackageCategories.ID "; + $q.= "AND PackageBases.ID = " . intval($base_id); + $result = $dbh->query($q); + + $row = array(); + + if (!$result) { + $row['error'] = __("Error retrieving package details."); + } + else { + $row = $result->fetch(PDO::FETCH_ASSOC); + if (empty($row)) { + $row['error'] = __("Package details could not be found."); + } + } + + return $row; +} + +/** + * Display the package base details page + * + * @global string $AUR_LOCATION The AUR's URL used for notification e-mails + * @global bool $USE_VIRTUAL_URLS True if using URL rewriting, otherwise false + * @param string $id The package base ID to get details page for + * @param array $row Package base details retrieved by pkgbase_get_details() + * @param string $SID The session ID of the visitor + * + * @return void + */ +function pkgbase_display_details($base_id, $row, $SID="") { + global $AUR_LOCATION; + global $USE_VIRTUAL_URLS; + + $dbh = DB::connect(); + + if (isset($row['error'])) { + print "

" . $row['error'] . "

\n"; + } + else { + $pkgbase_name = pkgbase_name_from_id($base_id); + + include('pkgbase_details.php'); + + if ($SID) { + include('actions_form.php'); + include('pkg_comment_form.php'); + } + + $comments = pkgbase_comments($base_id); + if (!empty($comments)) { + include('pkg_comments.php'); + } + } +} + +/** + * Convert a list of package IDs into a list of corresponding package bases. + * + * @param array|int $ids Array of package IDs to convert + * + * @return array|int List of package base IDs + */ +function pkgbase_from_pkgid($ids) { + $dbh = DB::connect(); + + if (is_array($ids)) { + $q = "SELECT PackageBaseID FROM Packages "; + $q.= "WHERE ID IN (" . implode(",", $ids) . ")"; + $result = $dbh->query($q); + return $result->fetchAll(PDO::FETCH_COLUMN, 0); + } else { + $q = "SELECT PackageBaseID FROM Packages "; + $q.= "WHERE ID = " . $ids; + $result = $dbh->query($q); + return $result->fetch(PDO::FETCH_COLUMN, 0); + } +} + +/** + * Retrieve ID of a package base by name + * + * @param string $name The package base name to retrieve the ID for + * + * @return int The ID of the package base + */ +function pkgbase_from_name($name) { + $dbh = DB::connect(); + $q = "SELECT ID FROM PackageBases WHERE Name = " . $dbh->quote($name); + $result = $dbh->query($q); + return $result->fetch(PDO::FETCH_COLUMN, 0); +} + +/** + * Retrieve the name of a package base given its ID + * + * @param int $base_id The ID of the package base to query + * + * @return string The name of the package base + */ +function pkgbase_name_from_id($base_id) { + $dbh = DB::connect(); + $q = "SELECT Name FROM PackageBases WHERE ID = " . intval($base_id); + $result = $dbh->query($q); + return $result->fetch(PDO::FETCH_COLUMN, 0); +} + +/** + * Get the names of all packages belonging to a package base + * + * @param int $base_id The ID of the package base + * + * @return array The names of all packages belonging to the package base + */ +function pkgbase_get_pkgnames($base_id) { + $dbh = DB::connect(); + $q = "SELECT Name FROM Packages WHERE PackageBaseID = " . intval($base_id); + $result = $dbh->query($q); + return $result->fetchAll(PDO::FETCH_COLUMN, 0); +} + +/** + * Delete all packages belonging to a package base + * + * @param int $base_id The ID of the package base + * + * @return void + */ +function pkgbase_delete_packages($base_id) { + $dbh = DB::connect(); + $q = "DELETE FROM Packages WHERE PackageBaseID = " . intval($base_id); + $dbh->exec($q); +} + +/** + * Retrieve the maintainer of a package base given its ID + * + * @param int $base_id The ID of the package base to query + * + * @return int The user ID of the current package maintainer + */ +function pkgbase_maintainer_uid($base_id) { + $dbh = DB::connect(); + $q = "SELECT MaintainerUID FROM PackageBases WHERE ID = " . intval($base_id); + $result = $dbh->query($q); + return $result->fetch(PDO::FETCH_COLUMN, 0); +} + + +/** + * Flag package(s) as out-of-date + * + * @global string $AUR_LOCATION The AUR's URL used for notification e-mails + * @param string $atype Account type, output of account_from_sid + * @param array $base_ids Array of package base IDs to flag/unflag + * + * @return array Tuple of success/failure indicator and error message + */ +function pkgbase_flag($atype, $base_ids) { + global $AUR_LOCATION; + + if (!$atype) { + return array(false, __("You must be logged in before you can flag packages.")); + } + + $base_ids = pkgbase_from_pkgid($base_ids); + if (empty($base_ids)) { + return array(false, __("You did not select any packages to flag.")); + } + + $dbh = DB::connect(); + + $q = "UPDATE PackageBases SET"; + $q.= " OutOfDateTS = UNIX_TIMESTAMP()"; + $q.= " WHERE ID IN (" . implode(",", $base_ids) . ")"; + $q.= " AND OutOfDateTS IS NULL"; + + $affected_pkgs = $dbh->exec($q); + + if ($affected_pkgs > 0) { + /* Notify of flagging by e-mail. */ + $f_name = username_from_sid($_COOKIE['AURSID']); + $f_email = email_from_sid($_COOKIE['AURSID']); + $f_uid = uid_from_sid($_COOKIE['AURSID']); + $q = "SELECT PackageBases.Name, Users.Email "; + $q.= "FROM PackageBases, Users "; + $q.= "WHERE PackageBases.ID IN (" . implode(",", $base_ids) .") "; + $q.= "AND Users.ID = PackageBases.MaintainerUID "; + $q.= "AND Users.ID != " . $f_uid; + $result = $dbh->query($q); + if ($result) { + while ($row = $result->fetch(PDO::FETCH_ASSOC)) { + $body = "Your package " . $row['Name'] . " has been flagged out of date by " . $f_name . " [1]. You may view your package at:\n" . $AUR_LOCATION . get_pkg_uri($row['Name']) . "\n\n[1] - " . $AUR_LOCATION . get_user_uri($f_name); + $body = wordwrap($body, 70); + $headers = "MIME-Version: 1.0\r\n" . + "Content-type: text/plain; charset=UTF-8\r\n" . + "Reply-to: nobody@archlinux.org\r\n" . + "From: aur-notify@archlinux.org\r\n" . + "X-Mailer: PHP\r\n" . + "X-MimeOLE: Produced By AUR"; + @mail($row['Email'], "AUR Out-of-date Notification for ".$row['Name'], $body, $headers); + } + } + } + + return array(true, __("The selected packages have been flagged out-of-date.")); +} + +/** + * Unflag package(s) as out-of-date + * + * @param string $atype Account type, output of account_from_sid + * @param array $base_ids Array of package base IDs to flag/unflag + * + * @return array Tuple of success/failure indicator and error message + */ +function pkgbase_unflag($atype, $base_ids) { + if (!$atype) { + return array(false, __("You must be logged in before you can unflag packages.")); + } + + $base_ids = pkgbase_from_pkgid($base_ids); + if (empty($base_ids)) { + return array(false, __("You did not select any packages to unflag.")); + } + + $dbh = DB::connect(); + + $q = "UPDATE PackageBases SET "; + $q.= "OutOfDateTS = NULL "; + $q.= "WHERE ID IN (" . implode(",", $base_ids) . ") "; + + if ($atype != "Trusted User" && $atype != "Developer") { + $q.= "AND MaintainerUID = " . uid_from_sid($_COOKIE["AURSID"]); + } + + $result = $dbh->exec($q); + + if ($result) { + return array(true, __("The selected packages have been unflagged.")); + } +} + +/** + * Delete package bases + * + * @param string $atype Account type, output of account_from_sid + * @param array $base_ids Array of package base IDs to delete + * @param int $merge_base_id Package base to merge the deleted ones into + * + * @return array Tuple of success/failure indicator and error message + */ +function pkgbase_delete ($atype, $base_ids, $merge_base_id) { + if (!$atype) { + return array(false, __("You must be logged in before you can delete packages.")); + } + + if ($atype != "Trusted User" && $atype != "Developer") { + return array(false, __("You do not have permission to delete packages.")); + } + + $base_ids = sanitize_ids($base_ids); + if (empty($base_ids)) { + return array(false, __("You did not select any packages to delete.")); + } + + $dbh = DB::connect(); + + if ($merge_base_id) { + $merge_base_name = pkgbase_name_from_id($merge_base_id); + } + + /* Send e-mail notifications. */ + foreach ($base_ids as $base_id) { + $q = "SELECT CommentNotify.*, Users.Email "; + $q.= "FROM CommentNotify, Users "; + $q.= "WHERE Users.ID = CommentNotify.UserID "; + $q.= "AND CommentNotify.UserID != " . uid_from_sid($_COOKIE['AURSID']) . " "; + $q.= "AND CommentNotify.PackageBaseID = " . $base_id; + $result = $dbh->query($q); + $bcc = array(); + + while ($row = $result->fetch(PDO::FETCH_ASSOC)) { + array_push($bcc, $row['Email']); + } + if (!empty($bcc)) { + $pkgbase_name = pkgbase_name_from_id($base_id); + + /* + * TODO: Add native language emails for users, based on + * their preferences. Simply making these strings + * translatable won't work, users would be getting + * emails in the language that the user who posted the + * comment was in. + */ + $body = ""; + if ($merge_base_id) { + $body .= username_from_sid($_COOKIE['AURSID']) . " merged \"".$pkgbase_name."\" into \"$merge_base_name\".\n\n"; + $body .= "You will no longer receive notifications about this package, please go to https://aur.archlinux.org" . get_pkgbase_uri($merge_base_name) . " and click the Notify button if you wish to recieve them again."; + } else { + $body .= username_from_sid($_COOKIE['AURSID']) . " deleted \"".$pkgbase_name."\".\n\n"; + $body .= "You will no longer receive notifications about this package."; + } + $body = wordwrap($body, 70); + $bcc = implode(', ', $bcc); + $headers = "MIME-Version: 1.0\r\n" . + "Content-type: text/plain; charset=UTF-8\r\n" . + "Bcc: $bcc\r\n" . + "Reply-to: nobody@archlinux.org\r\n" . + "From: aur-notify@archlinux.org\r\n" . + "X-Mailer: AUR"; + @mail('undisclosed-recipients: ;', "AUR Package deleted: " . $pkgbase_name, $body, $headers); + } + } + + if ($merge_base_id) { + /* Merge comments */ + $q = "UPDATE PackageComments "; + $q.= "SET PackageBaseID = " . intval($merge_base_id) . " "; + $q.= "WHERE PackageBaseID IN (" . implode(",", $base_ids) . ")"; + $dbh->exec($q); + + /* Merge votes */ + foreach ($base_ids as $base_id) { + $q = "UPDATE PackageVotes "; + $q.= "SET PackageBaseID = " . intval($merge_base_id) . " "; + $q.= "WHERE PackageBaseID = " . $base_id . " "; + $q.= "AND UsersID NOT IN ("; + $q.= "SELECT * FROM (SELECT UsersID "; + $q.= "FROM PackageVotes "; + $q.= "WHERE PackageBaseID = " . intval($merge_base_id); + $q.= ") temp)"; + $dbh->exec($q); + } + + $q = "UPDATE PackageBases "; + $q.= "SET NumVotes = (SELECT COUNT(*) FROM PackageVotes "; + $q.= "WHERE PackageBaseID = " . intval($merge_base_id) . ") "; + $q.= "WHERE ID = " . intval($merge_base_id); + $dbh->exec($q); + } + + $q = "DELETE FROM Packages WHERE PackageBaseID IN (" . implode(",", $base_ids) . ")"; + $dbh->exec($q); + + $q = "DELETE FROM PackageBases WHERE ID IN (" . implode(",", $base_ids) . ")"; + $dbh->exec($q); + + return array(true, __("The selected packages have been deleted.")); +} + +/** + * Adopt or disown packages + * + * @param string $atype Account type, output of account_from_sid + * @param array $base_ids Array of package base IDs to adopt/disown + * @param bool $action Adopts if true, disowns if false. Adopts by default + * + * @return array Tuple of success/failure indicator and error message + */ +function pkgbase_adopt ($atype, $base_ids, $action=true) { + if (!$atype) { + if ($action) { + return array(false, __("You must be logged in before you can adopt packages.")); + } else { + return array(false, __("You must be logged in before you can disown packages.")); + } + } + + $base_ids = sanitize_ids($base_ids); + if (empty($base_ids)) { + if ($action) { + return array(false, __("You did not select any packages to adopt.")); + } else { + return array(false, __("You did not select any packages to disown.")); + } + } + + $dbh = DB::connect(); + + $field = "MaintainerUID"; + $q = "UPDATE PackageBases "; + + if ($action) { + $user = uid_from_sid($_COOKIE["AURSID"]); + } else { + $user = 'NULL'; + } + + $q.= "SET $field = $user "; + $q.= "WHERE ID IN (" . implode(",", $base_ids) . ") "; + + if ($action && $atype == "User") { + /* Regular users may only adopt orphan packages. */ + $q.= "AND $field IS NULL "; + } else if ($atype == "User") { + $q.= "AND $field = " . uid_from_sid($_COOKIE["AURSID"]); + } + + $dbh->exec($q); + + if ($action) { + pkgbase_notify(account_from_sid($_COOKIE["AURSID"]), $pkg_ids); + return array(true, __("The selected packages have been adopted.")); + } else { + return array(true, __("The selected packages have been disowned.")); + } +} + +/** + * Vote and un-vote for packages + * + * @param string $atype Account type, output of account_from_sid + * @param array $base_ids Array of package base IDs to vote/un-vote + * @param bool $action Votes if true, un-votes if false. Votes by default + * + * @return array Tuple of success/failure indicator and error message + */ +function pkgbase_vote ($atype, $base_ids, $action=true) { + if (!$atype) { + if ($action) { + return array(false, __("You must be logged in before you can vote for packages.")); + } else { + return array(false, __("You must be logged in before you can un-vote for packages.")); + } + } + + $base_ids = sanitize_ids($base_ids); + if (empty($base_ids)) { + if ($action) { + return array(false, __("You did not select any packages to vote for.")); + } else { + return array(false, __("Your votes have been removed from the selected packages.")); + } + } + + $dbh = DB::connect(); + $my_votes = pkgbase_votes_from_sid($_COOKIE["AURSID"]); + $uid = uid_from_sid($_COOKIE["AURSID"]); + + $first = 1; + foreach ($base_ids as $pid) { + if ($action) { + $check = !isset($my_votes[$pid]); + } else { + $check = isset($my_votes[$pid]); + } + + if ($check) { + if ($first) { + $first = 0; + $vote_ids = $pid; + if ($action) { + $vote_clauses = "($uid, $pid)"; + } + } else { + $vote_ids .= ", $pid"; + if ($action) { + $vote_clauses .= ", ($uid, $pid)"; + } + } + } + } + + /* Only add votes for packages the user hasn't already voted for. */ + $op = $action ? "+" : "-"; + $q = "UPDATE PackageBases SET NumVotes = NumVotes $op 1 "; + $q.= "WHERE ID IN ($vote_ids)"; + + $dbh->exec($q); + + if ($action) { + $q = "INSERT INTO PackageVotes (UsersID, PackageBaseID) VALUES "; + $q.= $vote_clauses; + } else { + $q = "DELETE FROM PackageVotes WHERE UsersID = $uid "; + $q.= "AND PackageBaseID IN ($vote_ids)"; + } + + $dbh->exec($q); + + if ($action) { + return array(true, __("Your votes have been cast for the selected packages.")); + } else { + return array(true, __("Your votes have been removed from the selected packages.")); + } +} + +/** + * Get all usernames and IDs that voted for a specific package + * + * @param string $pkgname The name of the package to retrieve votes for + * + * @return array User IDs and usernames that voted for a specific package + */ +function pkgbase_votes_from_name($pkgname) { + $dbh = DB::connect(); + + $q = "SELECT UsersID,Username,Name FROM PackageVotes "; + $q.= "LEFT JOIN Users on (UsersID = Users.ID) "; + $q.= "LEFT JOIN Packages on (PackageVotes.PackageBaseID = Packages.PackageBaseID) "; + $q.= "WHERE Name = ". $dbh->quote($pkgname) . " "; + $q.= "ORDER BY Username"; + $result = $dbh->query($q); + + if (!$result) { + return; + } + + $votes = array(); + while ($row = $result->fetch(PDO::FETCH_ASSOC)) { + $votes[] = $row; + } + + return $votes; +} + +/** + * Determine if a user has already voted for a specific package + * + * @param string $uid The user ID to check for an existing vote + * @param string $pkgid The package ID to check for an existing vote + * + * @return bool True if the user has already voted, otherwise false + */ +function pkgbase_user_voted($uid, $pkgid) { + $dbh = DB::connect(); + + $q = "SELECT * FROM PackageVotes, Packages WHERE "; + $q.= "PackageVotes.UsersID = ". $dbh->quote($uid) . " AND "; + $q.= "PackageVotes.PackageBaseID = Packages.PackageBaseID AND "; + $q.= "Packages.ID = " . $dbh->quote($pkgid); + $result = $dbh->query($q); + + if ($result->fetch(PDO::FETCH_NUM)) { + return true; + } + else { + return false; + } +} + +/** + * Determine if a user wants notifications for a specific package base + * + * @param string $uid User ID to check in the database + * @param string $base_id Package base ID to check notifications for + * + * @return bool True if the user wants notifications, otherwise false + */ +function pkgbase_user_notify($uid, $base_id) { + $dbh = DB::connect(); + + $q = "SELECT * FROM CommentNotify WHERE UserID = " . $dbh->quote($uid); + $q.= " AND PackageBaseID = " . $dbh->quote($base_id); + $result = $dbh->query($q); + + if ($result->fetch(PDO::FETCH_NUM)) { + return true; + } + else { + return false; + } +} + +/** + * Toggle notification of packages + * + * @param string $atype Account type, output of account_from_sid + * @param array $base_ids Array of package base IDs to toggle + * + * @return array Tuple of success/failure indicator and error message + */ +function pkgbase_notify ($atype, $base_ids, $action=true) { + if (!$atype) { + return; + } + + $base_ids = sanitize_ids($base_ids); + if (empty($base_ids)) { + return array(false, __("Couldn't add to notification list.")); + } + + $dbh = DB::connect(); + $uid = uid_from_sid($_COOKIE["AURSID"]); + + $output = ""; + + $first = true; + + /* + * There currently shouldn't be multiple requests here, but the format + * in which it's sent requires this. + */ + foreach ($base_ids as $bid) { + $q = "SELECT Name FROM PackageBases WHERE ID = $bid"; + $result = $dbh->query($q); + if ($result) { + $row = $result->fetch(PDO::FETCH_NUM); + $basename = $row[0]; + } + else { + $basename = ''; + } + + if ($first) + $first = false; + else + $output .= ", "; + + + if ($action) { + $q = "SELECT COUNT(*) FROM CommentNotify WHERE "; + $q .= "UserID = $uid AND PackageBaseID = $bid"; + + /* Notification already added. Don't add again. */ + $result = $dbh->query($q); + if ($result->fetchColumn() == 0) { + $q = "INSERT INTO CommentNotify (PackageBaseID, UserID) VALUES ($bid, $uid)"; + $dbh->exec($q); + } + + $output .= $basename; + } + else { + $q = "DELETE FROM CommentNotify WHERE PackageBaseID = $bid "; + $q .= "AND UserID = $uid"; + $dbh->exec($q); + + $output .= $basename; + } + } + + if ($action) { + $output = __("You have been added to the comment notification list for %s.", $output); + } + else { + $output = __("You have been removed from the comment notification list for %s.", $output); + } + + return array(true, $output); +} + +/** + * Delete a package comment + * + * @param string $atype Account type, output of account_from_sid + * + * @return array Tuple of success/failure indicator and error message + */ +function pkgbase_delete_comment($atype) { + if (!$atype) { + return array(false, __("You must be logged in before you can edit package information.")); + } + + if (isset($_POST["comment_id"])) { + $comment_id = $_POST["comment_id"]; + } else { + return array(false, __("Missing comment ID.")); + } + + $dbh = DB::connect(); + $uid = uid_from_sid($_COOKIE["AURSID"]); + if (can_delete_comment($comment_id, $atype, $uid)) { + $q = "UPDATE PackageComments "; + $q.= "SET DelUsersID = ".$uid." "; + $q.= "WHERE ID = ".intval($comment_id); + $dbh->exec($q); + return array(true, __("Comment has been deleted.")); + } else { + return array(false, __("You are not allowed to delete this comment.")); + } +} + +/** + * Change package category + * + * @param string $atype Account type, output of account_from_sid + * + * @return array Tuple of success/failure indicator and error message + */ +function pkgbase_change_category($pid, $atype) { + if (!$atype) { + return array(false, __("You must be logged in before you can edit package information.")); + } + + if (isset($_POST["category_id"])) { + $category_id = $_POST["category_id"]; + } else { + return array(false, __("Missing category ID.")); + } + + $dbh = DB::connect(); + $catArray = pkgbase_categories($dbh); + if (!array_key_exists($category_id, $catArray)) { + return array(false, __("Invalid category ID.")); + } + + $base_id = pkgbase_from_pkgid($pid); + + /* Verify package ownership. */ + $q = "SELECT MaintainerUID FROM PackageBases WHERE ID = " . $base_id; + $result = $dbh->query($q); + if ($result) { + $row = $result->fetch(PDO::FETCH_ASSOC); + } + else { + return array(false, __("You are not allowed to change this package category.")); + } + + $uid = uid_from_sid($_COOKIE["AURSID"]); + if ($uid == $row["MaintainerUID"] || + ($atype == "Developer" || $atype == "Trusted User")) { + $q = "UPDATE PackageBases "; + $q.= "SET CategoryID = ".intval($category_id)." "; + $q.= "WHERE ID = ".intval($base_id); + $dbh->exec($q); + return array(true, __("Package category changed.")); + } else { + return array(false, __("You are not allowed to change this package category.")); + } +} + +/** + * Add package base information to the database + * + * @param string $name Name of the new package base + * @param int $category_id Category for the new package base + * @param int $uid User ID of the package uploader + * + * @return int ID of the new package base + */ +function pkgbase_create($name, $category_id, $uid) { + $dbh = DB::connect(); + $q = sprintf("INSERT INTO PackageBases (Name, CategoryID, " . + "SubmittedTS, ModifiedTS, SubmitterUID, MaintainerUID) " . + "VALUES (%s, %d, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), %d, %d)", + $dbh->quote($name), $category_id, $uid, $uid); + $dbh->exec($q); + return $dbh->lastInsertId(); +} + +/** + * Update package base information for a specific package base + * + * @param string $name Name of the updated package base + * @param int $base_id The package base ID of the affected package + * @param int $uid User ID of the package uploader + * + * @return void + */ +function pkgbase_update($base_id, $name, $uid) { + $dbh = DB::connect(); + $q = sprintf("UPDATE PackageBases SET " . + "Name = %s, ModifiedTS = UNIX_TIMESTAMP(), " . + "MaintainerUID = %d, OutOfDateTS = NULL WHERE ID = %d", + $dbh->quote($name), $uid, $base_id); + $dbh->exec($q); +} + +/** + * Change the category a package base belongs to + * + * @param int $base_id The package base ID to change the category for + * @param int $category_id The new category ID for the package + * + * @return void + */ +function pkgbase_update_category($base_id, $category_id) { + $dbh = DB::connect(); + $q = sprintf("UPDATE PackageBases SET CategoryID = %d WHERE ID = %d", + $category_id, $base_id); + $dbh->exec($q); +} diff --git a/web/lib/pkgfuncs.inc.php b/web/lib/pkgfuncs.inc.php index 45c786bd..17402048 100644 --- a/web/lib/pkgfuncs.inc.php +++ b/web/lib/pkgfuncs.inc.php @@ -1,5 +1,6 @@ query($q); - if ($result) { - while ($row = $result->fetch(PDO::FETCH_NUM)) { - $cats[$row[0]] = $row[1]; - } - } - return $cats; -} - /** * Check to see if the package name already exists in the database * @@ -175,135 +155,6 @@ function pkg_required($name="") { return $deps; } -/** - * Get the number of non-deleted comments for a specific package base - * - * @param string $pkgid The package base ID to get comment count for - * - * @return string The number of comments left for a specific package - */ -function pkgbase_comments_count($base_id) { - $dbh = DB::connect(); - - $base_id = intval($base_id); - if ($base_id > 0) { - $dbh = DB::connect(); - $q = "SELECT COUNT(*) FROM PackageComments "; - $q.= "WHERE PackageBaseID = " . $base_id; - $q.= " AND DelUsersID IS NULL"; - } - $result = $dbh->query($q); - - if (!$result) { - return; - } - - $row = $result->fetch(PDO::FETCH_NUM); - return $row[0]; -} - -/** - * Get all package comment information for a specific package base - * - * @param int $pkgid The package base ID to get comments for - * - * @return array All package comment information for a specific package base - */ -function pkgbase_comments($base_id) { - $base_id = intval($base_id); - $comments = array(); - if ($base_id > 0) { - $dbh = DB::connect(); - $q = "SELECT PackageComments.ID, UserName, UsersID, Comments, CommentTS "; - $q.= "FROM PackageComments LEFT JOIN Users "; - $q.= "ON PackageComments.UsersID = Users.ID "; - $q.= "WHERE PackageBaseID = " . $base_id . " "; - $q.= "AND DelUsersID IS NULL "; - $q.= "ORDER BY CommentTS DESC"; - - if (!isset($_GET['comments'])) { - $q.= " LIMIT 10"; - } - - $result = $dbh->query($q); - - if (!$result) { - return; - } - - while ($row = $result->fetch(PDO::FETCH_ASSOC)) { - $comments[] = $row; - } - } - return $comments; -} - -/** - * Add a comment to a package page and send out appropriate notifications - * - * @global string $AUR_LOCATION The AUR's URL used for notification e-mails - * @param string $base_id The package base ID to add the comment on - * @param string $uid The user ID of the individual who left the comment - * @param string $comment The comment left on a package page - * - * @return void - */ -function pkgbase_add_comment($base_id, $uid, $comment) { - global $AUR_LOCATION; - - $dbh = DB::connect(); - - $q = "INSERT INTO PackageComments "; - $q.= "(PackageBaseID, UsersID, Comments, CommentTS) VALUES ("; - $q.= intval($base_id) . ", " . $uid . ", "; - $q.= $dbh->quote($comment) . ", UNIX_TIMESTAMP())"; - $dbh->exec($q); - - /* - * Send e-mail notifications. - * TODO: Move notification logic to separate function where it belongs. - */ - $q = "SELECT CommentNotify.*, Users.Email "; - $q.= "FROM CommentNotify, Users "; - $q.= "WHERE Users.ID = CommentNotify.UserID "; - $q.= "AND CommentNotify.UserID != " . $uid . " "; - $q.= "AND CommentNotify.PackageBaseID = " . intval($base_id); - $result = $dbh->query($q); - $bcc = array(); - - if ($result) { - while ($row = $result->fetch(PDO::FETCH_ASSOC)) { - array_push($bcc, $row['Email']); - } - - $q = "SELECT Name FROM PackageBases WHERE ID = "; - $q.= intval($base_id); - $result = $dbh->query($q); - $row = $result->fetch(PDO::FETCH_ASSOC); - - /* - * TODO: Add native language emails for users, based on their - * preferences. Simply making these strings translatable won't - * work, users would be getting emails in the language that the - * user who posted the comment was in. - */ - $body = - 'from ' . $AUR_LOCATION . get_pkg_uri($row['Name']) . "\n" - . username_from_sid($_COOKIE['AURSID']) . " wrote:\n\n" - . $comment - . "\n\n---\nIf you no longer wish to receive notifications about this package, please go the the above package page and click the UnNotify button."; - $body = wordwrap($body, 70); - $bcc = implode(', ', $bcc); - $headers = "MIME-Version: 1.0\r\n" . - "Content-type: text/plain; charset=UTF-8\r\n" . - "Bcc: $bcc\r\n" . - "Reply-to: nobody@archlinux.org\r\n" . - "From: aur-notify@archlinux.org\r\n" . - "X-Mailer: AUR"; - @mail('undisclosed-recipients: ;', "AUR Comment for " . $row['Name'], $body, $headers); - } -} - /** * Get all package sources for a specific package * @@ -330,31 +181,6 @@ function pkg_sources($pkgid) { return $sources; } -/** - * Get a list of all packages a logged-in user has voted for - * - * @param string $sid The session ID of the visitor - * - * @return array All packages the visitor has voted for - */ -function pkgbase_votes_from_sid($sid="") { - $pkgs = array(); - if (!$sid) {return $pkgs;} - $dbh = DB::connect(); - $q = "SELECT PackageBaseID "; - $q.= "FROM PackageVotes, Users, Sessions "; - $q.= "WHERE Users.ID = Sessions.UsersID "; - $q.= "AND Users.ID = PackageVotes.UsersID "; - $q.= "AND Sessions.SessionID = " . $dbh->quote($sid); - $result = $dbh->query($q); - if ($result) { - while ($row = $result->fetch(PDO::FETCH_NUM)) { - $pkgs[$row[0]] = 1; - } - } - return $pkgs; -} - /** * Determine package names from package IDs * @@ -444,41 +270,6 @@ function pkg_get_details($id=0) { return $row; } -/** - * Get the package base details - * - * @param string $id The package base ID to get description for - * - * @return array The package base's details OR error message - **/ -function pkgbase_get_details($base_id) { - $dbh = DB::connect(); - - $q = "SELECT PackageBases.ID, PackageBases.Name, "; - $q.= "PackageBases.CategoryID, PackageBases.NumVotes, "; - $q.= "PackageBases.OutOfDateTS, PackageBases.SubmittedTS, "; - $q.= "PackageBases.ModifiedTS, PackageBases.SubmitterUID, "; - $q.= "PackageBases.MaintainerUID, PackageCategories.Category "; - $q.= "FROM PackageBases, PackageCategories "; - $q.= "WHERE PackageBases.CategoryID = PackageCategories.ID "; - $q.= "AND PackageBases.ID = " . intval($base_id); - $result = $dbh->query($q); - - $row = array(); - - if (!$result) { - $row['error'] = __("Error retrieving package details."); - } - else { - $row = $result->fetch(PDO::FETCH_ASSOC); - if (empty($row)) { - $row['error'] = __("Package details could not be found."); - } - } - - return $row; -} - /** * Display the package details page * @@ -517,44 +308,6 @@ function pkg_display_details($id=0, $row, $SID="") { } } -/** - * Display the package base details page - * - * @global string $AUR_LOCATION The AUR's URL used for notification e-mails - * @global bool $USE_VIRTUAL_URLS True if using URL rewriting, otherwise false - * @param string $id The package base ID to get details page for - * @param array $row Package base details retrieved by pkgbase_get_details() - * @param string $SID The session ID of the visitor - * - * @return void - */ -function pkgbase_display_details($base_id, $row, $SID="") { - global $AUR_LOCATION; - global $USE_VIRTUAL_URLS; - - $dbh = DB::connect(); - - if (isset($row['error'])) { - print "

" . $row['error'] . "

\n"; - } - else { - $pkgbase_name = pkgbase_name_from_id($base_id); - - include('pkgbase_details.php'); - - if ($SID) { - include('actions_form.php'); - include('pkg_comment_form.php'); - } - - $comments = pkgbase_comments($base_id); - if (!empty($comments)) { - include('pkg_comments.php'); - } - } -} - - /* pkg_search_page(SID) * outputs the body of search/search results page * @@ -848,673 +601,6 @@ function sanitize_ids($ids) { return $new_ids; } -/** - * Convert a list of package IDs into a list of corresponding package bases. - * - * @param array|int $ids Array of package IDs to convert - * - * @return array|int List of package base IDs - */ -function pkgbase_from_pkgid($ids) { - $dbh = DB::connect(); - - if (is_array($ids)) { - $q = "SELECT PackageBaseID FROM Packages "; - $q.= "WHERE ID IN (" . implode(",", $ids) . ")"; - $result = $dbh->query($q); - return $result->fetchAll(PDO::FETCH_COLUMN, 0); - } else { - $q = "SELECT PackageBaseID FROM Packages "; - $q.= "WHERE ID = " . $ids; - $result = $dbh->query($q); - return $result->fetch(PDO::FETCH_COLUMN, 0); - } -} - -/** - * Retrieve ID of a package base by name - * - * @param string $name The package base name to retrieve the ID for - * - * @return int The ID of the package base - */ -function pkgbase_from_name($name) { - $dbh = DB::connect(); - $q = "SELECT ID FROM PackageBases WHERE Name = " . $dbh->quote($name); - $result = $dbh->query($q); - return $result->fetch(PDO::FETCH_COLUMN, 0); -} - -/** - * Retrieve the name of a package base given its ID - * - * @param int $base_id The ID of the package base to query - * - * @return string The name of the package base - */ -function pkgbase_name_from_id($base_id) { - $dbh = DB::connect(); - $q = "SELECT Name FROM PackageBases WHERE ID = " . intval($base_id); - $result = $dbh->query($q); - return $result->fetch(PDO::FETCH_COLUMN, 0); -} - -/** - * Get the names of all packages belonging to a package base - * - * @param int $base_id The ID of the package base - * - * @return array The names of all packages belonging to the package base - */ -function pkgbase_get_pkgnames($base_id) { - $dbh = DB::connect(); - $q = "SELECT Name FROM Packages WHERE PackageBaseID = " . intval($base_id); - $result = $dbh->query($q); - return $result->fetchAll(PDO::FETCH_COLUMN, 0); -} - -/** - * Delete all packages belonging to a package base - * - * @param int $base_id The ID of the package base - * - * @return void - */ -function pkgbase_delete_packages($base_id) { - $dbh = DB::connect(); - $q = "DELETE FROM Packages WHERE PackageBaseID = " . intval($base_id); - $dbh->exec($q); -} - -/** - * Retrieve the maintainer of a package base given its ID - * - * @param int $base_id The ID of the package base to query - * - * @return int The user ID of the current package maintainer - */ -function pkgbase_maintainer_uid($base_id) { - $dbh = DB::connect(); - $q = "SELECT MaintainerUID FROM PackageBases WHERE ID = " . intval($base_id); - $result = $dbh->query($q); - return $result->fetch(PDO::FETCH_COLUMN, 0); -} - - -/** - * Flag package(s) as out-of-date - * - * @global string $AUR_LOCATION The AUR's URL used for notification e-mails - * @param string $atype Account type, output of account_from_sid - * @param array $base_ids Array of package base IDs to flag/unflag - * - * @return array Tuple of success/failure indicator and error message - */ -function pkgbase_flag($atype, $base_ids) { - global $AUR_LOCATION; - - if (!$atype) { - return array(false, __("You must be logged in before you can flag packages.")); - } - - $base_ids = pkgbase_from_pkgid($base_ids); - if (empty($base_ids)) { - return array(false, __("You did not select any packages to flag.")); - } - - $dbh = DB::connect(); - - $q = "UPDATE PackageBases SET"; - $q.= " OutOfDateTS = UNIX_TIMESTAMP()"; - $q.= " WHERE ID IN (" . implode(",", $base_ids) . ")"; - $q.= " AND OutOfDateTS IS NULL"; - - $affected_pkgs = $dbh->exec($q); - - if ($affected_pkgs > 0) { - /* Notify of flagging by e-mail. */ - $f_name = username_from_sid($_COOKIE['AURSID']); - $f_email = email_from_sid($_COOKIE['AURSID']); - $f_uid = uid_from_sid($_COOKIE['AURSID']); - $q = "SELECT PackageBases.Name, Users.Email "; - $q.= "FROM PackageBases, Users "; - $q.= "WHERE PackageBases.ID IN (" . implode(",", $base_ids) .") "; - $q.= "AND Users.ID = PackageBases.MaintainerUID "; - $q.= "AND Users.ID != " . $f_uid; - $result = $dbh->query($q); - if ($result) { - while ($row = $result->fetch(PDO::FETCH_ASSOC)) { - $body = "Your package " . $row['Name'] . " has been flagged out of date by " . $f_name . " [1]. You may view your package at:\n" . $AUR_LOCATION . get_pkg_uri($row['Name']) . "\n\n[1] - " . $AUR_LOCATION . get_user_uri($f_name); - $body = wordwrap($body, 70); - $headers = "MIME-Version: 1.0\r\n" . - "Content-type: text/plain; charset=UTF-8\r\n" . - "Reply-to: nobody@archlinux.org\r\n" . - "From: aur-notify@archlinux.org\r\n" . - "X-Mailer: PHP\r\n" . - "X-MimeOLE: Produced By AUR"; - @mail($row['Email'], "AUR Out-of-date Notification for ".$row['Name'], $body, $headers); - } - } - } - - return array(true, __("The selected packages have been flagged out-of-date.")); -} - -/** - * Unflag package(s) as out-of-date - * - * @param string $atype Account type, output of account_from_sid - * @param array $base_ids Array of package base IDs to flag/unflag - * - * @return array Tuple of success/failure indicator and error message - */ -function pkgbase_unflag($atype, $base_ids) { - if (!$atype) { - return array(false, __("You must be logged in before you can unflag packages.")); - } - - $base_ids = pkgbase_from_pkgid($base_ids); - if (empty($base_ids)) { - return array(false, __("You did not select any packages to unflag.")); - } - - $dbh = DB::connect(); - - $q = "UPDATE PackageBases SET "; - $q.= "OutOfDateTS = NULL "; - $q.= "WHERE ID IN (" . implode(",", $base_ids) . ") "; - - if ($atype != "Trusted User" && $atype != "Developer") { - $q.= "AND MaintainerUID = " . uid_from_sid($_COOKIE["AURSID"]); - } - - $result = $dbh->exec($q); - - if ($result) { - return array(true, __("The selected packages have been unflagged.")); - } -} - -/** - * Delete package bases - * - * @param string $atype Account type, output of account_from_sid - * @param array $base_ids Array of package base IDs to delete - * @param int $merge_base_id Package base to merge the deleted ones into - * - * @return array Tuple of success/failure indicator and error message - */ -function pkgbase_delete ($atype, $base_ids, $merge_base_id) { - if (!$atype) { - return array(false, __("You must be logged in before you can delete packages.")); - } - - if ($atype != "Trusted User" && $atype != "Developer") { - return array(false, __("You do not have permission to delete packages.")); - } - - $base_ids = sanitize_ids($base_ids); - if (empty($base_ids)) { - return array(false, __("You did not select any packages to delete.")); - } - - $dbh = DB::connect(); - - if ($merge_base_id) { - $merge_base_name = pkgbase_name_from_id($merge_base_id); - } - - /* Send e-mail notifications. */ - foreach ($base_ids as $base_id) { - $q = "SELECT CommentNotify.*, Users.Email "; - $q.= "FROM CommentNotify, Users "; - $q.= "WHERE Users.ID = CommentNotify.UserID "; - $q.= "AND CommentNotify.UserID != " . uid_from_sid($_COOKIE['AURSID']) . " "; - $q.= "AND CommentNotify.PackageBaseID = " . $base_id; - $result = $dbh->query($q); - $bcc = array(); - - while ($row = $result->fetch(PDO::FETCH_ASSOC)) { - array_push($bcc, $row['Email']); - } - if (!empty($bcc)) { - $pkgbase_name = pkgbase_name_from_id($base_id); - - /* - * TODO: Add native language emails for users, based on - * their preferences. Simply making these strings - * translatable won't work, users would be getting - * emails in the language that the user who posted the - * comment was in. - */ - $body = ""; - if ($merge_base_id) { - $body .= username_from_sid($_COOKIE['AURSID']) . " merged \"".$pkgbase_name."\" into \"$merge_base_name\".\n\n"; - $body .= "You will no longer receive notifications about this package, please go to https://aur.archlinux.org" . get_pkgbase_uri($merge_base_name) . " and click the Notify button if you wish to recieve them again."; - } else { - $body .= username_from_sid($_COOKIE['AURSID']) . " deleted \"".$pkgbase_name."\".\n\n"; - $body .= "You will no longer receive notifications about this package."; - } - $body = wordwrap($body, 70); - $bcc = implode(', ', $bcc); - $headers = "MIME-Version: 1.0\r\n" . - "Content-type: text/plain; charset=UTF-8\r\n" . - "Bcc: $bcc\r\n" . - "Reply-to: nobody@archlinux.org\r\n" . - "From: aur-notify@archlinux.org\r\n" . - "X-Mailer: AUR"; - @mail('undisclosed-recipients: ;', "AUR Package deleted: " . $pkgbase_name, $body, $headers); - } - } - - if ($merge_base_id) { - /* Merge comments */ - $q = "UPDATE PackageComments "; - $q.= "SET PackageBaseID = " . intval($merge_base_id) . " "; - $q.= "WHERE PackageBaseID IN (" . implode(",", $base_ids) . ")"; - $dbh->exec($q); - - /* Merge votes */ - foreach ($base_ids as $base_id) { - $q = "UPDATE PackageVotes "; - $q.= "SET PackageBaseID = " . intval($merge_base_id) . " "; - $q.= "WHERE PackageBaseID = " . $base_id . " "; - $q.= "AND UsersID NOT IN ("; - $q.= "SELECT * FROM (SELECT UsersID "; - $q.= "FROM PackageVotes "; - $q.= "WHERE PackageBaseID = " . intval($merge_base_id); - $q.= ") temp)"; - $dbh->exec($q); - } - - $q = "UPDATE PackageBases "; - $q.= "SET NumVotes = (SELECT COUNT(*) FROM PackageVotes "; - $q.= "WHERE PackageBaseID = " . intval($merge_base_id) . ") "; - $q.= "WHERE ID = " . intval($merge_base_id); - $dbh->exec($q); - } - - $q = "DELETE FROM Packages WHERE PackageBaseID IN (" . implode(",", $base_ids) . ")"; - $dbh->exec($q); - - $q = "DELETE FROM PackageBases WHERE ID IN (" . implode(",", $base_ids) . ")"; - $dbh->exec($q); - - return array(true, __("The selected packages have been deleted.")); -} - -/** - * Adopt or disown packages - * - * @param string $atype Account type, output of account_from_sid - * @param array $base_ids Array of package base IDs to adopt/disown - * @param bool $action Adopts if true, disowns if false. Adopts by default - * - * @return array Tuple of success/failure indicator and error message - */ -function pkgbase_adopt ($atype, $base_ids, $action=true) { - if (!$atype) { - if ($action) { - return array(false, __("You must be logged in before you can adopt packages.")); - } else { - return array(false, __("You must be logged in before you can disown packages.")); - } - } - - $base_ids = sanitize_ids($base_ids); - if (empty($base_ids)) { - if ($action) { - return array(false, __("You did not select any packages to adopt.")); - } else { - return array(false, __("You did not select any packages to disown.")); - } - } - - $dbh = DB::connect(); - - $field = "MaintainerUID"; - $q = "UPDATE PackageBases "; - - if ($action) { - $user = uid_from_sid($_COOKIE["AURSID"]); - } else { - $user = 'NULL'; - } - - $q.= "SET $field = $user "; - $q.= "WHERE ID IN (" . implode(",", $base_ids) . ") "; - - if ($action && $atype == "User") { - /* Regular users may only adopt orphan packages. */ - $q.= "AND $field IS NULL "; - } else if ($atype == "User") { - $q.= "AND $field = " . uid_from_sid($_COOKIE["AURSID"]); - } - - $dbh->exec($q); - - if ($action) { - pkgbase_notify(account_from_sid($_COOKIE["AURSID"]), $pkg_ids); - return array(true, __("The selected packages have been adopted.")); - } else { - return array(true, __("The selected packages have been disowned.")); - } -} - -/** - * Vote and un-vote for packages - * - * @param string $atype Account type, output of account_from_sid - * @param array $base_ids Array of package base IDs to vote/un-vote - * @param bool $action Votes if true, un-votes if false. Votes by default - * - * @return array Tuple of success/failure indicator and error message - */ -function pkgbase_vote ($atype, $base_ids, $action=true) { - if (!$atype) { - if ($action) { - return array(false, __("You must be logged in before you can vote for packages.")); - } else { - return array(false, __("You must be logged in before you can un-vote for packages.")); - } - } - - $base_ids = sanitize_ids($base_ids); - if (empty($base_ids)) { - if ($action) { - return array(false, __("You did not select any packages to vote for.")); - } else { - return array(false, __("Your votes have been removed from the selected packages.")); - } - } - - $dbh = DB::connect(); - $my_votes = pkgbase_votes_from_sid($_COOKIE["AURSID"]); - $uid = uid_from_sid($_COOKIE["AURSID"]); - - $first = 1; - foreach ($base_ids as $pid) { - if ($action) { - $check = !isset($my_votes[$pid]); - } else { - $check = isset($my_votes[$pid]); - } - - if ($check) { - if ($first) { - $first = 0; - $vote_ids = $pid; - if ($action) { - $vote_clauses = "($uid, $pid)"; - } - } else { - $vote_ids .= ", $pid"; - if ($action) { - $vote_clauses .= ", ($uid, $pid)"; - } - } - } - } - - /* Only add votes for packages the user hasn't already voted for. */ - $op = $action ? "+" : "-"; - $q = "UPDATE PackageBases SET NumVotes = NumVotes $op 1 "; - $q.= "WHERE ID IN ($vote_ids)"; - - $dbh->exec($q); - - if ($action) { - $q = "INSERT INTO PackageVotes (UsersID, PackageBaseID) VALUES "; - $q.= $vote_clauses; - } else { - $q = "DELETE FROM PackageVotes WHERE UsersID = $uid "; - $q.= "AND PackageBaseID IN ($vote_ids)"; - } - - $dbh->exec($q); - - if ($action) { - return array(true, __("Your votes have been cast for the selected packages.")); - } else { - return array(true, __("Your votes have been removed from the selected packages.")); - } -} - -/** - * Get all usernames and IDs that voted for a specific package - * - * @param string $pkgname The name of the package to retrieve votes for - * - * @return array User IDs and usernames that voted for a specific package - */ -function pkgbase_votes_from_name($pkgname) { - $dbh = DB::connect(); - - $q = "SELECT UsersID,Username,Name FROM PackageVotes "; - $q.= "LEFT JOIN Users on (UsersID = Users.ID) "; - $q.= "LEFT JOIN Packages on (PackageVotes.PackageBaseID = Packages.PackageBaseID) "; - $q.= "WHERE Name = ". $dbh->quote($pkgname) . " "; - $q.= "ORDER BY Username"; - $result = $dbh->query($q); - - if (!$result) { - return; - } - - $votes = array(); - while ($row = $result->fetch(PDO::FETCH_ASSOC)) { - $votes[] = $row; - } - - return $votes; -} - -/** - * Determine if a user has already voted for a specific package - * - * @param string $uid The user ID to check for an existing vote - * @param string $pkgid The package ID to check for an existing vote - * - * @return bool True if the user has already voted, otherwise false - */ -function pkgbase_user_voted($uid, $pkgid) { - $dbh = DB::connect(); - - $q = "SELECT * FROM PackageVotes, Packages WHERE "; - $q.= "PackageVotes.UsersID = ". $dbh->quote($uid) . " AND "; - $q.= "PackageVotes.PackageBaseID = Packages.PackageBaseID AND "; - $q.= "Packages.ID = " . $dbh->quote($pkgid); - $result = $dbh->query($q); - - if ($result->fetch(PDO::FETCH_NUM)) { - return true; - } - else { - return false; - } -} - -/** - * Determine if a user wants notifications for a specific package base - * - * @param string $uid User ID to check in the database - * @param string $base_id Package base ID to check notifications for - * - * @return bool True if the user wants notifications, otherwise false - */ -function pkgbase_user_notify($uid, $base_id) { - $dbh = DB::connect(); - - $q = "SELECT * FROM CommentNotify WHERE UserID = " . $dbh->quote($uid); - $q.= " AND PackageBaseID = " . $dbh->quote($base_id); - $result = $dbh->query($q); - - if ($result->fetch(PDO::FETCH_NUM)) { - return true; - } - else { - return false; - } -} - -/** - * Toggle notification of packages - * - * @param string $atype Account type, output of account_from_sid - * @param array $base_ids Array of package base IDs to toggle - * - * @return array Tuple of success/failure indicator and error message - */ -function pkgbase_notify ($atype, $base_ids, $action=true) { - if (!$atype) { - return; - } - - $base_ids = sanitize_ids($base_ids); - if (empty($base_ids)) { - return array(false, __("Couldn't add to notification list.")); - } - - $dbh = DB::connect(); - $uid = uid_from_sid($_COOKIE["AURSID"]); - - $output = ""; - - $first = true; - - /* - * There currently shouldn't be multiple requests here, but the format - * in which it's sent requires this. - */ - foreach ($base_ids as $bid) { - $q = "SELECT Name FROM PackageBases WHERE ID = $bid"; - $result = $dbh->query($q); - if ($result) { - $row = $result->fetch(PDO::FETCH_NUM); - $basename = $row[0]; - } - else { - $basename = ''; - } - - if ($first) - $first = false; - else - $output .= ", "; - - - if ($action) { - $q = "SELECT COUNT(*) FROM CommentNotify WHERE "; - $q .= "UserID = $uid AND PackageBaseID = $bid"; - - /* Notification already added. Don't add again. */ - $result = $dbh->query($q); - if ($result->fetchColumn() == 0) { - $q = "INSERT INTO CommentNotify (PackageBaseID, UserID) VALUES ($bid, $uid)"; - $dbh->exec($q); - } - - $output .= $basename; - } - else { - $q = "DELETE FROM CommentNotify WHERE PackageBaseID = $bid "; - $q .= "AND UserID = $uid"; - $dbh->exec($q); - - $output .= $basename; - } - } - - if ($action) { - $output = __("You have been added to the comment notification list for %s.", $output); - } - else { - $output = __("You have been removed from the comment notification list for %s.", $output); - } - - return array(true, $output); -} - -/** - * Delete a package comment - * - * @param string $atype Account type, output of account_from_sid - * - * @return array Tuple of success/failure indicator and error message - */ -function pkgbase_delete_comment($atype) { - if (!$atype) { - return array(false, __("You must be logged in before you can edit package information.")); - } - - if (isset($_POST["comment_id"])) { - $comment_id = $_POST["comment_id"]; - } else { - return array(false, __("Missing comment ID.")); - } - - $dbh = DB::connect(); - $uid = uid_from_sid($_COOKIE["AURSID"]); - if (can_delete_comment($comment_id, $atype, $uid)) { - $q = "UPDATE PackageComments "; - $q.= "SET DelUsersID = ".$uid." "; - $q.= "WHERE ID = ".intval($comment_id); - $dbh->exec($q); - return array(true, __("Comment has been deleted.")); - } else { - return array(false, __("You are not allowed to delete this comment.")); - } -} - -/** - * Change package category - * - * @param string $atype Account type, output of account_from_sid - * - * @return array Tuple of success/failure indicator and error message - */ -function pkgbase_change_category($pid, $atype) { - if (!$atype) { - return array(false, __("You must be logged in before you can edit package information.")); - } - - if (isset($_POST["category_id"])) { - $category_id = $_POST["category_id"]; - } else { - return array(false, __("Missing category ID.")); - } - - $dbh = DB::connect(); - $catArray = pkgbase_categories($dbh); - if (!array_key_exists($category_id, $catArray)) { - return array(false, __("Invalid category ID.")); - } - - $base_id = pkgbase_from_pkgid($pid); - - /* Verify package ownership. */ - $q = "SELECT MaintainerUID FROM PackageBases WHERE ID = " . $base_id; - $result = $dbh->query($q); - if ($result) { - $row = $result->fetch(PDO::FETCH_ASSOC); - } - else { - return array(false, __("You are not allowed to change this package category.")); - } - - $uid = uid_from_sid($_COOKIE["AURSID"]); - if ($uid == $row["MaintainerUID"] || - ($atype == "Developer" || $atype == "Trusted User")) { - $q = "UPDATE PackageBases "; - $q.= "SET CategoryID = ".intval($category_id)." "; - $q.= "WHERE ID = ".intval($base_id); - $dbh->exec($q); - return array(true, __("Package category changed.")); - } else { - return array(false, __("You are not allowed to change this package category.")); - } -} - /** * Get all package information in the database for a specific package * @@ -1539,25 +625,6 @@ function pkg_details_by_name($pkgname) { return $row; } -/** - * Add package base information to the database - * - * @param string $name Name of the new package base - * @param int $category_id Category for the new package base - * @param int $uid User ID of the package uploader - * - * @return int ID of the new package base - */ -function pkgbase_create($name, $category_id, $uid) { - $dbh = DB::connect(); - $q = sprintf("INSERT INTO PackageBases (Name, CategoryID, " . - "SubmittedTS, ModifiedTS, SubmitterUID, MaintainerUID) " . - "VALUES (%s, %d, UNIX_TIMESTAMP(), UNIX_TIMESTAMP(), %d, %d)", - $dbh->quote($name), $category_id, $uid, $uid); - $dbh->exec($q); - return $dbh->lastInsertId(); -} - /** * Add package information to the database for a specific package * @@ -1581,24 +648,6 @@ function pkg_create($base_id, $pkgname, $license, $pkgver, $pkgdesc, $pkgurl) { return $dbh->lastInsertId(); } -/** - * Update package base information for a specific package base - * - * @param string $name Name of the updated package base - * @param int $base_id The package base ID of the affected package - * @param int $uid User ID of the package uploader - * - * @return void - */ -function pkgbase_update($base_id, $name, $uid) { - $dbh = DB::connect(); - $q = sprintf("UPDATE PackageBases SET " . - "Name = %s, ModifiedTS = UNIX_TIMESTAMP(), " . - "MaintainerUID = %d, OutOfDateTS = NULL WHERE ID = %d", - $dbh->quote($name), $uid, $base_id); - $dbh->exec($q); -} - /** * Update all database information for a specific package * @@ -1660,21 +709,6 @@ function pkg_add_src($pkgid, $pkgsrc) { $dbh->exec($q); } -/** - * Change the category a package base belongs to - * - * @param int $base_id The package base ID to change the category for - * @param int $category_id The new category ID for the package - * - * @return void - */ -function pkgbase_update_category($base_id, $category_id) { - $dbh = DB::connect(); - $q = sprintf("UPDATE PackageBases SET CategoryID = %d WHERE ID = %d", - $category_id, $base_id); - $dbh->exec($q); -} - /** * Remove package dependencies from a specific package * -- cgit v1.2.3-24-g4f1b