From 6ed78f274206b33ba34bd32af54003c7414b9067 Mon Sep 17 00:00:00 2001 From: Darko Date: Tue, 8 Jul 2014 12:58:52 +0200 Subject: [PATCH 01/20] Added PC games postprocessing. --- bin/monitor.php | 7 +- bin/postprocess_new.php | 2 + lib/DB/db.sql | 42 +- lib/DB/patches/0052~gamesinfo.sql | 24 + lib/DB/patches/0053~site.sql | 4 + lib/DB/patches/0054~releases.sql | 3 + lib/DB/patches/0055~users.sql | 2 + lib/Pprocess.php | 21 +- lib/copy_this/www/admin/user-edit.php | 121 +++ lib/copy_this/www/lib/Games.php | 889 ++++++++++++++++++ lib/copy_this/www/lib/GiantBombAPI.php | 435 +++++++++ lib/copy_this/www/lib/nntp.php | 1 - lib/copy_this/www/lib/users.php | 3 +- lib/copy_this/www/pages/browse.php | 82 ++ lib/copy_this/www/pages/games.php | 97 ++ lib/copy_this/www/pages/profileedit.php | 1 + .../nntmux/images/icons/giantbomb.png | Bin 0 -> 815 bytes .../nntmux/views/admin/site-edit.tpl | 11 +- .../nntmux/views/admin/user-edit.tpl | 23 +- .../templates/nntmux/views/frontend/games.tpl | 231 +++++ .../nntmux/views/frontend/profile.tpl | 21 +- .../nntmux/views/frontend/profileedit.tpl | 7 + lib/getGames.php | 36 + lib/updateGamesImages.php | 45 + start.php | 2 +- 25 files changed, 2073 insertions(+), 37 deletions(-) create mode 100644 lib/DB/patches/0052~gamesinfo.sql create mode 100644 lib/DB/patches/0053~site.sql create mode 100644 lib/DB/patches/0054~releases.sql create mode 100644 lib/DB/patches/0055~users.sql create mode 100644 lib/copy_this/www/admin/user-edit.php create mode 100644 lib/copy_this/www/lib/Games.php create mode 100644 lib/copy_this/www/lib/GiantBombAPI.php create mode 100644 lib/copy_this/www/pages/browse.php create mode 100644 lib/copy_this/www/pages/games.php create mode 100644 lib/copy_this/www/templates/nntmux/images/icons/giantbomb.png create mode 100644 lib/copy_this/www/templates/nntmux/views/frontend/games.tpl create mode 100644 lib/getGames.php create mode 100644 lib/updateGamesImages.php diff --git a/bin/monitor.php b/bin/monitor.php index 4133d24a0..543aaf0c0 100644 --- a/bin/monitor.php +++ b/bin/monitor.php @@ -8,7 +8,7 @@ require_once(dirname(__FILE__) . "/../lib/showsleep.php"); require_once(dirname(__FILE__) . "/../lib/functions.php"); -$version = "0.4r2004"; +$version = "0.4r2010"; $db = new DB(); $functions = new Functions(); @@ -1657,11 +1657,12 @@ while ($i > 0) { shell_exec("tmux respawnp -t${tmux_session}:2.4 'echo \"\033[38;5;${color}m\n${panes2[4]} has been disabled/terminated by Postprocess Anime\"'"); } - //Process Console releases in pane 2.5 once if needed then exits + //Process Games in pane 2.5 once if needed then exits if (($maxload >= get_load()) && ($post_amazon == 1) && ($console_releases_proc > 0)) { $color = get_color($colors_start, $colors_end, $colors_exc); $log = writelog($panes2[5]); - shell_exec("tmux respawnp -t${tmux_session}:2.5 'echo \"\033[38;5;\"$color\"m\" && cd $_bin && $_php postprocess_new.php games 2>&1 $log && $_sleep $post_timer_amazon && echo \" \033[1;0;33m\"' 2>&1 1> /dev/null"); + shell_exec("tmux respawnp -t${tmux_session}:2.5 'echo \"\033[38;5;\"$color\"m\" && cd $_bin && $_php postprocess_new.php console 2>&1 $log; \ + $_php postprocess_new.php games 2>&1 $log; $_sleep $post_timer_amazon && echo \" \033[1;0;33m\"' 2>&1 1> /dev/null"); } else if (($maxload >= get_load()) && ($post_amazon == 1) && ($console_releases_proc == 0)) { $color = get_color($colors_start, $colors_end, $colors_exc); shell_exec("tmux respawnp -t${tmux_session}:2.5 'echo \"\033[38;5;\"$color\"m\n$panes2[5] has been disabled/terminated by No Games to process\"'"); diff --git a/bin/postprocess_new.php b/bin/postprocess_new.php index 7f1c371d2..eb5be7611 100644 --- a/bin/postprocess_new.php +++ b/bin/postprocess_new.php @@ -51,6 +51,8 @@ if (isset($argv[1]) && $argv[1] === "additional") { $thetvdb->processReleases(); } else if (isset($argv[1]) && $argv[1] === "games") { $pprocess->processGames(); +} else if (isset($argv[1]) && $argv[1] === "console") { + $pprocess->processConsoleGames(); } else if (isset($argv[1]) && $argv[1] === "ebook") { $postprocess->processBooks(); } else if (isset($argv[1]) && $argv[1] === "music") { diff --git a/lib/DB/db.sql b/lib/DB/db.sql index d0c794fe3..ab8608169 100644 --- a/lib/DB/db.sql +++ b/lib/DB/db.sql @@ -17,6 +17,7 @@ ADD `proc_pp` TINYINT(1) NOT NULL DEFAULT 0, ADD `proc_par2` BIT NOT NULL DEFAULT 0, ADD `proc_nfo` BIT NOT NULL DEFAULT 0, ADD `proc_files` BIT NOT NULL DEFAULT 0, +ADD `gamesinfo_id` INT AFTER consoleinfoID, ADD `nzbstatus` TINYINT(1) NOT NULL DEFAULT 1; CREATE INDEX `ix_releases_nfostatus` ON `releases` (`nfostatus` ASC) USING HASH; CREATE INDEX `ix_releases_reqidstatus` ON `releases` (`reqidstatus` ASC) USING HASH; @@ -26,8 +27,11 @@ CREATE INDEX `ix_releases_dehashstatus` ON `releases` (`dehashstatus`); CREATE INDEX `ix_releases_haspreview` ON `releases` (`haspreview` ASC) USING HASH; CREATE INDEX `ix_releases_postdate_name` ON `releases` (`postdate`, `name`); CREATE INDEX `ix_releases_prehashid_searchname` ON `releases` (`prehashID`, `searchname`); +CREATE INDEX `ix_releases_gamesinfo_id` ON `releases` (`gamesinfo_id`); CREATE INDEX `ix_releases_status` ON `releases` (`nzbstatus`, `iscategorized`, `isrenamed`, `nfostatus`, `ishashed`, `passwordstatus`, `dehashstatus`, `releasenfoID`, `musicinfoID`, `consoleinfoID`, `bookinfoID`, `haspreview`, `categoryID`, `imdbID`, `rageID`); +ALTER TABLE users ADD COLUMN gameview INT AFTER consoleview; + DROP TABLE IF EXISTS prehash; CREATE TABLE prehash ( ID INT(11) UNSIGNED NOT NULL AUTO_INCREMENT, @@ -203,7 +207,7 @@ INSERT INTO tmux (setting, value) VALUES ('defrag_cache', '900'), ('ffmpeg_duration', '5'), ('ffmpeg_image_time', '5'), ('processvideos', '0'), - ('sqlpatch', '50'); + ('sqlpatch', '55'); DROP TABLE IF EXISTS releasesearch; CREATE TABLE releasesearch ( @@ -476,6 +480,29 @@ INSERT INTO country (code, name) VALUES ('AF', 'Afghanistan'), ('ZM', 'Zambia'), ('ZW', 'Zimbabwe'); +DROP TABLE IF EXISTS gamesinfo; +CREATE TABLE gamesinfo ( + id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + title VARCHAR(255) NOT NULL, + asin VARCHAR(128) DEFAULT NULL, + url VARCHAR(1000) DEFAULT NULL, + platform VARCHAR(255) DEFAULT NULL, + publisher VARCHAR(255) DEFAULT NULL, + genreid INT(10) NULL DEFAULT NULL, + esrb VARCHAR(255) NULL DEFAULT NULL, + releasedate DATETIME DEFAULT NULL, + review VARCHAR(3000) DEFAULT NULL, + cover TINYINT(1) UNSIGNED NOT NULL DEFAULT '0', + createddate DATETIME NOT NULL, + updateddate DATETIME NOT NULL, + PRIMARY KEY (id), + UNIQUE INDEX ix_gamesinfo_asin (asin) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8 + COLLATE = utf8_unicode_ci + AUTO_INCREMENT = 1; + DROP TABLE IF EXISTS shortgroups; CREATE TABLE shortgroups ( ID INT(11) NOT NULL AUTO_INCREMENT, @@ -701,6 +728,11 @@ INSERT INTO menu (href, title, tooltip, role, ordinal) VALUES ('prehash', 'Prehash', 'Prehash', 1, 68); +INSERT INTO `site` (`setting`, `value`) VALUES + ('categorizeforeign', '1'), + ('catwebdl', '0'), + ('giantbombkey', ''); + DROP TRIGGER IF EXISTS check_insert; DROP TRIGGER IF EXISTS check_update; @@ -745,10 +777,4 @@ CREATE TRIGGER delete_search AFTER DELETE ON releases FOR EACH ROW BEGIN DELETE WHERE releaseID = OLD.ID; END; $$ -DELIMITER ; - - - - - - +DELIMITER ; \ No newline at end of file diff --git a/lib/DB/patches/0052~gamesinfo.sql b/lib/DB/patches/0052~gamesinfo.sql new file mode 100644 index 000000000..1c51df787 --- /dev/null +++ b/lib/DB/patches/0052~gamesinfo.sql @@ -0,0 +1,24 @@ +DROP TABLE IF EXISTS gamesinfo; +CREATE TABLE gamesinfo ( + id INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + title VARCHAR(255) NOT NULL, + asin VARCHAR(128) DEFAULT NULL, + url VARCHAR(1000) DEFAULT NULL, + platform VARCHAR(255) DEFAULT NULL, + publisher VARCHAR(255) DEFAULT NULL, + genreid INT(10) NULL DEFAULT NULL, + esrb VARCHAR(255) NULL DEFAULT NULL, + releasedate DATETIME DEFAULT NULL, + review VARCHAR(3000) DEFAULT NULL, + cover TINYINT(1) UNSIGNED NOT NULL DEFAULT '0', + createddate DATETIME NOT NULL, + updateddate DATETIME NOT NULL, + PRIMARY KEY (id), + UNIQUE INDEX ix_gamesinfo_asin (asin) +) + ENGINE = InnoDB + DEFAULT CHARSET = utf8 + COLLATE = utf8_unicode_ci + AUTO_INCREMENT = 1; + + UPDATE `tmux` SET `value` = '52' WHERE `setting` = 'sqlpatch'; \ No newline at end of file diff --git a/lib/DB/patches/0053~site.sql b/lib/DB/patches/0053~site.sql new file mode 100644 index 000000000..eb03054de --- /dev/null +++ b/lib/DB/patches/0053~site.sql @@ -0,0 +1,4 @@ +INSERT INTO `site` + (`setting`, `value`) + VALUES ('giantbombkey', ''); +UPDATE `tmux` SET `value` = '53' WHERE `setting` = 'sqlpatch'; \ No newline at end of file diff --git a/lib/DB/patches/0054~releases.sql b/lib/DB/patches/0054~releases.sql new file mode 100644 index 000000000..3e59e2db5 --- /dev/null +++ b/lib/DB/patches/0054~releases.sql @@ -0,0 +1,3 @@ +ALTER TABLE releases ADD COLUMN gamesinfo_id INT AFTER consoleinfoID; +CREATE INDEX ix_releases_gamesinfo_id ON releases (gamesinfo_id); +UPDATE `tmux` SET `value` = '54' WHERE `setting` = 'sqlpatch'; \ No newline at end of file diff --git a/lib/DB/patches/0055~users.sql b/lib/DB/patches/0055~users.sql new file mode 100644 index 000000000..3856ff3b1 --- /dev/null +++ b/lib/DB/patches/0055~users.sql @@ -0,0 +1,2 @@ +ALTER TABLE users ADD COLUMN gameview INT AFTER consoleview; +UPDATE `tmux` SET `value` = '55' WHERE `setting` = 'sqlpatch'; \ No newline at end of file diff --git a/lib/Pprocess.php b/lib/Pprocess.php index 5a08d5426..8e98b44e6 100644 --- a/lib/Pprocess.php +++ b/lib/Pprocess.php @@ -16,6 +16,7 @@ require_once(WWW_DIR . "/lib/amazon.php"); require_once(WWW_DIR . "/lib/genres.php"); require_once(WWW_DIR . "/lib/anidb.php"); require_once(WWW_DIR . "/lib/book.php"); +require_once(WWW_DIR . "/lib/Games.php"); require_once("consoletools.php"); require_once("ColorCLI.php"); require_once("nzbcontents.php"); @@ -131,6 +132,7 @@ class PProcess $this->processSharing($nntp); $this->processMovies(); $this->processMusic(); + $this->processConsoleGames(); $this->processGames(); $this->processAnime(); $this->processTv(); @@ -164,6 +166,19 @@ class PProcess } } + /** + * Lookup console games if enabled. + * + * @return void + */ + public function processConsoleGames() + { + if ($this->site->lookupgames !== '0') { + $console = new Konsole($this->echooutput); + $console->processConsoleReleases(); + } + } + /** * Lookup games if enabled. * @@ -171,9 +186,9 @@ class PProcess */ public function processGames() { - if ($this->site->lookupgames !== '0') { - $console = new Konsole($this->echooutput); - $console->processConsoleReleases(); + if ($this->site->lookupgames !== 0) { + $games = new Games($this->echooutput); + $games->processGamesReleases(); } } diff --git a/lib/copy_this/www/admin/user-edit.php b/lib/copy_this/www/admin/user-edit.php new file mode 100644 index 000000000..bff4d5e6c --- /dev/null +++ b/lib/copy_this/www/admin/user-edit.php @@ -0,0 +1,121 @@ +getRoles(); +$roles = array(); +$defaultrole = Users::ROLE_USER; +$defaultinvites = Users::DEFAULT_INVITES; +foreach ($userroles as $r) { + $roles[$r['ID']] = $r['name']; + if ($r['isdefault'] == 1) + { + $defaultrole = $r['ID']; + $defaultinvites = $r['defaultinvites']; + } +} + +switch($action) +{ + case 'add': + $user = array(); + $user["role"] = $defaultrole; + $user["notes"] = ""; + $user["invites"] = $defaultinvites; + $user["movieview"] = "1"; + $user["musicview"] = "1"; + $user["gameview"] = "1"; + $user["consoleview"] = "1"; + $user["bookview"] = "1"; + $page->smarty->assign('user', $user); + break; + case 'submit': + + if ($_POST["id"] == "") + { + $invites = $defaultinvites; + foreach($userroles as $role) { + if ($role['ID'] == $_POST['role']) + $invites = $role['defaultinvites']; + } + $ret = $users->signup($_POST["username"], $_POST["password"], $_POST["email"], '', $_POST["role"], $_POST["notes"], $invites, "", true, false, false, true); + } + else + { + $ret = $users->update($_POST["id"], $_POST["username"], $_POST["email"], $_POST["grabs"], $_POST["role"], $_POST["notes"], $_POST["invites"], (isset($_POST['movieview']) ? "1" : "0"), (isset($_POST['musicview']) ? "1" : "0"), (isset($_POST['gameview']) ? "1" : "0"), (isset($_POST['consoleview']) ? "1" : "0"), (isset($_POST['bookview']) ? "1" : "0")); + if ($_POST['password'] != "") + $users->updatePassword($_POST["id"], $_POST['password']); + } + + if ($ret >= 0) + header("Location:".WWW_TOP."/user-list.php"); + else + { + switch ($ret) + { + case Users::ERR_SIGNUP_BADUNAME: + $page->smarty->assign('error', "Bad username. Try a better one."); + break; + case Users::ERR_SIGNUP_BADPASS: + $page->smarty->assign('error', "Bad password. Try a longer one."); + break; + case Users::ERR_SIGNUP_BADEMAIL: + $page->smarty->assign('error', "Bad email."); + break; + case Users::ERR_SIGNUP_UNAMEINUSE: + $page->smarty->assign('error', "Username in use."); + break; + case Users::ERR_SIGNUP_EMAILINUSE: + $page->smarty->assign('error', "Email in use."); + break; + default: + $page->smarty->assign('error', "Unknown save error."); + break; + } + $user = array(); + $user["ID"] = $_POST["id"]; + $user["username"] = $_POST["username"]; + $user["email"] = $_POST["email"]; + $user["grabs"] = (isset($_POST["grabs"]) ? $_POST["grabs"] : "0"); + $user["role"] = $_POST["role"]; + $user["notes"] = $_POST["notes"]; + $user["invites"] = (isset($_POST["invites"]) ? $_POST["invites"] : "0"); + $user["movieview"] = $_POST["movieview"]; + $user["bookview"] = $_POST["bookview"]; + $page->smarty->assign('user', $user); + } + break; + case 'view': + default: + + if (isset($_GET["id"])) + { + $page->title = "User Edit"; + $id = $_GET["id"]; + $user = $users->getByID($id); + + $page->smarty->assign('user', $user); + } + + break; +} + +$page->smarty->assign('yesno_ids', array(1,0)); +$page->smarty->assign('yesno_names', array( 'Yes', 'No')); + +$page->smarty->assign('role_ids', array_keys($roles)); +$page->smarty->assign('role_names', $roles); + +$page->content = $page->smarty->fetch('user-edit.tpl'); +$page->render(); + diff --git a/lib/copy_this/www/lib/Games.php b/lib/copy_this/www/lib/Games.php new file mode 100644 index 000000000..f727a826f --- /dev/null +++ b/lib/copy_this/www/lib/Games.php @@ -0,0 +1,889 @@ +echooutput = $echooutput; + + $this->pdo = new DB(); + $s = new Sites(); + $this->site = $s->get(); + $t = new Tmux(); + $this->tmux = $t->get(); + $this->pubkey = $this->site->giantbombkey; + $this->gameqty = ($this->tmux->maxgamesprocessed != '') ? $this->tmux->maxgamesprocessed : 150; + $this->sleeptime = ($this->tmux->amazonsleep != '') ? $this->tmux->amazonsleep : 1000; + $this->imgSavePath = WWW_DIR . 'covers/games' . '/'; + $this->renamed = ''; + if ($this->site->lookupgames == 2) { + $this->renamed = 'AND isrenamed = 1'; + } + //$this->cleangames = ($this->pdo->getSetting('lookupgames') == 2) ? 'AND isrenamed = 1' : ''; + $this->c = new ColorCLI(); + } + + /** + * @param $id + * + * @return array|bool + */ + public function getgamesinfo($id) + { + return $this->pdo->queryOneRow( + sprintf(" + SELECT gamesinfo.*, genres.title AS genres + FROM gamesinfo + LEFT OUTER JOIN genres ON genres.ID = gamesinfo.genreid + WHERE gamesinfo.id = %d", + $id + ) + ); + } + + /** + * @param $title + * @param $platform + * + * @return array|bool + */ + public function getgamesinfoByName($title, $platform) + { + return $this->pdo->queryOneRow( + sprintf(" + SELECT * + FROM gamesinfo + WHERE title LIKE %s + AND platform LIKE %s", + $this->pdo->escapeString("%" . $title . "%"), + $this->pdo->escapeString("%" . $platform . "%") + ) + ); + } + + /** + * @param $start + * @param $num + * + * @return array + */ + public function getRange($start, $num) + { + return $this->pdo->query( + sprintf( + "SELECT * FROM gamesinfo ORDER BY createddate DESC %s", + ($start === false ? '' : 'LIMIT ' . $num . ' OFFSET ' . $start) + ) + ); + } + + /** + * @return int + */ + public function getCount() + { + $res = $this->pdo->queryOneRow("SELECT COUNT(id) AS num FROM gamesinfo"); + return ($res === false ? 0 : $res["num"]); + } + + /** + * @param $cat + * @param $maxage + * @param array $excludedcats + * + * @return int + */ + public function getgamesCount($cat, $maxage = -1, $excludedcats = array()) + { + $catsrch = ""; + if (count($cat) > 0 && $cat[0] != -1) { + $catsrch = " ("; + $categ = new Category(); + foreach ($cat as $category) { + if ($category != -1) { + if ($categ->isParent($category)) { + $children = $categ->getChildren($category); + $chlist = "-99"; + foreach ($children as $child) { + $chlist .= ", " . $child["ID"]; + } + + if ($chlist != "-99") { + $catsrch .= " r.categoryID IN (" . $chlist . ") OR "; + } + } else { + $catsrch .= sprintf(" r.categoryID = %d OR ", $category); + } + } + } + $catsrch .= "1=2 )"; + } + + $res = $this->pdo->queryOneRow( + sprintf(" + SELECT COUNT(DISTINCT r.gamesinfo_id) AS num + FROM releases r + INNER JOIN gamesinfo gam ON gam.id = r.gamesinfo_id + WHERE r.nzbstatus = 1 + AND gam.title != '' + AND gam.cover = 1 + AND r.passwordstatus <= (SELECT value FROM site WHERE setting='showpasswordedrelease') + AND %s %s %s %s", + $this->getBrowseBy(), + $catsrch, + ($maxage > 0 ? sprintf(' AND r.postdate > NOW() - INTERVAL %d DAY ', $maxage) : ''), + (count($excludedcats) > 0 ? " AND r.categoryID NOT IN (" . implode(",", $excludedcats) . ")" : '') + ) + ); + + return ($res === false ? 0 : $res["num"]); + } + + /** + * @param $cat + * @param $start + * @param $num + * @param $orderby + * @param $maxage + * @param array $excludedcats + * + * @return array + */ + public function getgamesRange($cat, $start, $num, $orderby, $maxage = -1, $excludedcats = array()) + { + $browseby = $this->getBrowseBy(); + + if ($start === false) { + $limit = ""; + } else { + $limit = " LIMIT " . $num . " OFFSET " . $start; + } + $catsrch = ""; + if (count($cat) > 0 && $cat[0] != -1) { + $catsrch = " ("; + $categ = new Category(); + foreach ($cat as $category) { + if ($category != -1) { + if ($categ->isParent($category)) { + $children = $categ->getChildren($category); + $chlist = "-99"; + foreach ($children as $child) { + $chlist .= ", " . $child["id"]; + } + + if ($chlist != "-99") { + $catsrch .= " r.categoryID IN (" . $chlist . ") OR "; + } + } else { + $catsrch .= sprintf(" r.categoryID = %d OR ", $category); + } + } + } + $catsrch .= "1=2 )"; + } + + if ($maxage > 0) { + $maxage = sprintf(' AND r.postdate > NOW() - INTERVAL %d DAY ', $maxage); + } else { + $maxage = ''; + } + + $exccatlist = ""; + if (count($excludedcats) > 0) { + $exccatlist = " AND r.categoryID NOT IN (" . implode(",", $excludedcats) . ")"; + } + + $order = $this->getgamesOrder($orderby); + + return $this->pdo->query( + sprintf( + "SELECT GROUP_CONCAT(r.ID ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_id, " + . "GROUP_CONCAT(r.rarinnerfilecount ORDER BY r.postdate DESC SEPARATOR ',') as grp_rarinnerfilecount, " + . "GROUP_CONCAT(r.haspreview ORDER BY r.postdate DESC SEPARATOR ',') AS grp_haspreview, " + . "GROUP_CONCAT(r.passwordstatus ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_password, " + . "GROUP_CONCAT(r.guid ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_guid, " + . "GROUP_CONCAT(rn.ID ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_nfoid, " + . "GROUP_CONCAT(groups.name ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_grpname, " + . "GROUP_CONCAT(r.searchname ORDER BY r.postdate DESC SEPARATOR '#') AS grp_release_name, " + . "GROUP_CONCAT(r.postdate ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_postdate, " + . "GROUP_CONCAT(r.size ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_size, " + . "GROUP_CONCAT(r.totalpart ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_totalparts, " + . "GROUP_CONCAT(r.comments ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_comments, " + . "GROUP_CONCAT(r.grabs ORDER BY r.postdate DESC SEPARATOR ',') AS grp_release_grabs, " + . "gam.*, r.gamesinfo_id, groups.name AS group_name, rn.ID as nfoid FROM releases r " + . "LEFT OUTER JOIN groups ON groups.ID = r.groupID " + . "LEFT OUTER JOIN releasenfo rn ON rn.releaseID = r.ID " + . "INNER JOIN gamesinfo gam ON gam.id = r.gamesinfo_id " + . "WHERE r.nzbstatus = 1 AND gam.cover = 1 AND gam.title != '' AND " + . "r.passwordstatus <= (SELECT value FROM site WHERE setting='showpasswordedrelease') AND %s %s %s %s " + . "GROUP BY gam.id ORDER BY %s %s" . $limit, + $browseby, + $catsrch, + $maxage, + $exccatlist, + $order[0], + $order[1] + ) + ); + } + + /** + * @param $orderby + * + * @return array + */ + public function getgamesOrder($orderby) + { + $order = ($orderby == '') ? 'r.postdate' : $orderby; + $orderArr = explode("_", $order); + switch ($orderArr[0]) { + case 'title': + $orderfield = 'gam.title'; + break; + case 'platform': + $orderfield = 'gam.platform'; + break; + case 'releasedate': + $orderfield = 'gam.releasedate'; + break; + case 'genre': + $orderfield = 'gam.genreID'; + break; + case 'size': + $orderfield = 'r.size'; + break; + case 'files': + $orderfield = 'r.totalpart'; + break; + case 'stats': + $orderfield = 'r.grabs'; + break; + case 'posted': + default: + $orderfield = 'r.postdate'; + break; + } + $ordersort = (isset($orderArr[1]) && preg_match('/^asc|desc$/i', $orderArr[1])) ? $orderArr[1] : 'desc'; + + return array($orderfield, $ordersort); + } + + /** + * @return array + */ + public function getgamesOrdering() + { + return array( + 'title_asc', 'title_desc', 'posted_asc', 'posted_desc', 'size_asc', 'size_desc', + 'files_asc', 'files_desc', 'stats_asc', 'stats_desc', 'platform_asc', 'platform_desc', + 'releasedate_asc', 'releasedate_desc', 'genre_asc', 'genre_desc' + ); + } + + /** + * @return array + */ + public function getBrowseByOptions() + { + return array('platform' => 'platform', 'title' => 'title', 'genre' => 'genreID'); + } + + /** + * @return string + */ + public function getBrowseBy() + { + $browseby = ' '; + $browsebyArr = $this->getBrowseByOptions(); + $like = 'LIKE'; + + foreach ($browsebyArr as $bbk => $bbv) { + if (isset($_REQUEST[$bbk]) && !empty($_REQUEST[$bbk])) { + $bbs = stripslashes($_REQUEST[$bbk]); + $browseby .= 'gam.' . $bbv . ' ' . $like . ' (' . $this->pdo->escapeString('%' . $bbs . '%') . ') AND '; + } + } + + return $browseby; + } + + /** + * @param $data + * @param $field + * + * @return string + */ + public function makeFieldLinks($data, $field) + { + $tmpArr = explode(', ', $data[$field]); + $newArr = array(); + $i = 0; + foreach ($tmpArr as $ta) { + // Only use first 6. + if ($i > 5) { + break; + } + $newArr[] = + '' . $ta . ''; + $i++; + } + + return implode(', ', $newArr); + } + + /** + * @param $id + * @param $title + * @param $asin + * @param $url + * @param $salesrank + * @param $platform + * @param $publisher + * @param $releasedate + * @param $esrb + * @param $cover + * @param $genreID + */ + public function update($id, $title, $asin, $url, $salesrank, $platform, $publisher, $releasedate, $esrb, $cover, $genreID) + { + + $this->pdo->exec( + sprintf(" + UPDATE gamesinfo + SET + title = %s, asin = %s, url = %s, salesrank = %s, platform = %s, publisher = %s, + releasedate= %s,esrb = %s, cover = %d, genreid = %d, updateddate = NOW() + WHERE id = %d", + $this->pdo->escapeString($title), + $this->pdo->escapeString($asin), + $this->pdo->escapeString($url), + $salesrank, + $this->pdo->escapeString($platform), + $this->pdo->escapeString($publisher), + $this->pdo->escapeString($releasedate), + $this->pdo->escapeString($esrb), + $cover, + $genreID, + $id + ) + ); + } + + /** + * Process each game, updating game information from Giantbomb + * + * @param $gameInfo + * + * @return bool + */ + public function updategamesinfo($gameInfo) + { + $gen = new Genres(); + $ri = new ReleaseImage(); + + $con = array(); + $ggameid = $this->fetchgiantbombgameid($gameInfo['title']); + $gb = $this->fetchGiantBombArray($ggameid); + $gb = $gb['results']; + if (!is_array($gb)) { + return false; + } + + // Load genres. + $defaultGenres = $gen->getGenres(Genres::GAME_TYPE); + $genreassoc = array(); + foreach ($defaultGenres as $dg) { + $genreassoc[$dg['ID']] = strtolower($dg['title']); + } + + // Get game properties. + $con['coverurl'] = (string)$gb['image']['super_url']; + if ($con['coverurl'] != "") { + $con['cover'] = 1; + } else { + $con['cover'] = 0; + } + + $con['title'] = (string)$gb['name']; + if (empty($con['title'])) { + $con['title'] = $gameInfo['title']; + } + if (is_array($gb['platforms'])) { + while (list($key) = each($gb['platforms'])) { + if ($gb['platforms'][$key]['id'] == $gameInfo['node']) { + $con['platform'] = (string)$gb['platforms'][$key]['name']; + } + } + } + + if (empty($con['platform'])) { + $con['platform'] = $gameInfo['platform']; + } + + // Beginning of Recheck Code. + // This is to verify the result back from amazon was at least somewhat related to what was intended. + // Some of the platforms don't match Amazon's exactly. This code is needed to facilitate rechecking. + if (preg_match('/^Pc$/i', $gameInfo['platform'])) { + $gameInfo['platform'] = str_replace('Pc', 'PC', $gameInfo['platform']); + } // baseline single quote + if (preg_match('/^Mac$/i', $gameInfo['platform'])) { + $gameInfo['platform'] = str_replace('Mac', 'MAC', $gameInfo['platform']); + } // baseline single quote + + // Remove Online Game Code So Titles Match Properly. + if (preg_match('/\[Online Game Code\]/i', $con['title'])) { + $con['title'] = str_replace(' [Online Game Code]', '', $con['title']); + } // baseline single quote + // Basically the XBLA names contain crap, this is to reduce the title down far enough to be usable. + + // This actual compares the two strings and outputs a percentage value. + $titlepercent = $platformpercent = ''; + similar_text(strtolower($gameInfo['title']), strtolower($con['title']), $titlepercent); + similar_text(strtolower($gameInfo['platform']), + strtolower($con['platform']), + $platformpercent); + + // If the release is DLC matching sucks, so assume anything over 50% is legit. + if (isset($gameInfo['dlc']) && $gameInfo['dlc'] == 1) { + if ($titlepercent >= 50) { + $titlepercent = 100; + $platformpercent = 100; + } + } + + /* + echo("Matched: Title Percentage: $titlepercent% between " . strtolower($gameInfo['title']) . " and " . strtolower($con['title']) . ".\n"); + echo("Matched: Platform Percentage: $platformpercent% \n"); + */ + + // If the Title is less than 80% Platform must be 100% unless it is XBLA. + if ($titlepercent < 60) { + if ($platformpercent != 100) { + return false; + } + } + + // If title is less than 80% then its most likely not a match. + if ($titlepercent < 60) { + similar_text(strtolower($gameInfo['title'] . ' - ' . $gameInfo['platform']), + strtolower($con['title']), + $titlewithplatpercent); + if ($titlewithplatpercent < 70) { + return false; + } + } + + // Platform must equal 100%. + if ($platformpercent != 100) { + return false; + } + + $con['asin'] = $ggameid; + + $con['url'] = (string)$gb['site_detail_url']; + $con['url'] = str_replace("%26tag%3Dws", "%26tag%3Dopensourceins%2D21", $con['url']); + + /*$con['salesrank'] = (string)$amaz->Items->Item->SalesRank; + if ($con['salesrank'] == "") { + $con['salesrank'] = 'null'; + } + */ + if (is_array($gb['publishers'])) { + while (list($key) = each($gb['publishers'])) { + if ($key == 0) { + $con['publisher'] = (string)$gb['publishers'][$key]['name']; + } + } + } else { + $con['publisher'] = "Unknown"; + } + + if (is_array($gb['original_game_rating'])) { + $con['esrb'] = (string)$gb['original_game_rating'][0]['name']; + } else { + $con['esrb'] = (string)$gb['original_game_rating']['name']; + } + $con['releasedate'] = $this->pdo->escapeString((string)$gb['original_release_date']); + if ($con['releasedate'] == "''") { + $con['releasedate'] = 'null'; + } + + $con['review'] = ""; + if (isset($gb['decription'])) { + $con['review'] = trim(strip_tags((string)$gb['description'])); + } + + $genreKey = -1; + $genreName = ''; + + if (empty($genreName) && isset($gb['genres'][0]['name'])) { + $a = (string)$gb['genres'][0]['name']; + $b = str_replace('-', ' ', $a); + $tmpGenre = explode(',', $b); + foreach ($tmpGenre as $tg) { + $genreMatch = $this->matchBrowseNode(ucwords($tg)); + if ($genreMatch !== false) { + $genreName = $genreMatch; + break; + } + } + } + + if (empty($genreName)) { + $genreName = 'Unknown'; + } + if (in_array(strtolower($genreName), $genreassoc)) { + $genreKey = array_search(strtolower($genreName), $genreassoc); + } else { + $genreKey = $this->pdo->queryInsert( + sprintf(" + INSERT INTO genres (title, type) + VALUES (%s, %d)", + $this->pdo->escapeString($genreName), + Genres::GAME_TYPE + ) + ); + } + + $con['gamesgenre'] = $genreName; + $con['gamesgenreID'] = $genreKey; + + $check = $this->pdo->queryOneRow( + sprintf(' + SELECT id + FROM gamesinfo + WHERE title = %s + AND asin = %s', + $this->pdo->escapeString($con['title']), + $this->pdo->escapeString($con['asin']) + ) + ); + if ($check === false) { + $gamesId = $this->pdo->queryInsert( + sprintf(" + INSERT INTO gamesinfo + (title, asin, url, platform, publisher, genreid, esrb, releasedate, review, cover, createddate, updateddate) + VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %d, NOW(), NOW())", + $this->pdo->escapeString($con['title']), + $this->pdo->escapeString($con['asin']), + $this->pdo->escapeString($con['url']), + $this->pdo->escapeString($con['platform']), + $this->pdo->escapeString($con['publisher']), + ($con['gamesgenreID'] == -1 ? "null" : $con['gamesgenreID']), + $this->pdo->escapeString($con['esrb']), + $con['releasedate'], + $this->pdo->escapeString(substr($con['review'], 0, 3000)), + $con['cover'] + ) + ); + } else { + $gamesId = $check['id']; + $this->pdo->exec( + sprintf(' + UPDATE gamesinfo + SET + title = %s, asin = %s, url = %s, platform = %s, publisher = %s, genreid = %s, + esrb = %s, releasedate = %s, review = %s, cover = %s, updateddate = NOW() + WHERE id = %d', + $this->pdo->escapeString($con['title']), + $this->pdo->escapeString($con['asin']), + $this->pdo->escapeString($con['url']), + $this->pdo->escapeString($con['platform']), + $this->pdo->escapeString($con['publisher']), + ($con['gamesgenreID'] == -1 ? "null" : $con['gamesgenreID']), + $this->pdo->escapeString($con['esrb']), + $con['releasedate'], + $this->pdo->escapeString(substr($con['review'], 0, 3000)), + $con['cover'], + $gamesId + ) + ); + } + + if ($gamesId) { + if ($this->echooutput) { + $this->c->doEcho( + $this->c->header("Added/updated game: ") . + $this->c->alternateOver(" Title: ") . + $this->c->primary($con['title']) . + $this->c->alternateOver(" Platform: ") . + $this->c->primary($con['platform']) + ); + } + $con['cover'] = $ri->saveImage($gamesId, $con['coverurl'], $this->imgSavePath, 250, 250); + } else { + if ($this->echooutput) { + $this->c->doEcho( + $this->c->headerOver("Nothing to update: ") . + $this->c->primary($con['title'] . " (" . $con['platform'] . ')' ) + ); + } + } + + return $gamesId; + } + + /** + * Get Giantbomb search results + * + * @param $gameid + * + * @return bool|mixed Json Array if no result False + */ + + public function fetchGiantBombArray($gameid) + { + $obj = new GiantBomb($this->pubkey); + try { + $fields = array( + "deck", "description", "original_game_rating", "api_detail_url", "image", "genres", + "name", "platforms", "publishers", "original_release_date", "reviews", + "site_detail_url" + ); + $result = json_decode(json_encode($obj->game($gameid, $fields)), true); + } catch (Exception $e) { + $result = false; + } + + return $result; + } + + /** + * Retrieve Giantbomb game ID for api requests + * + * @param $title + * + * @return bool|mixed - Json Array if game was found false if nothing + */ + public function fetchgiantbombgameid($title) + { + $obj = new GiantBomb($this->pubkey); + try { + $result = json_decode(json_encode($obj->search($title, '', 1)), true); + if (!is_array($result['results']) || (int) $result['number_of_total_results'] === 0) { + $result = false; + } else { + $result = $result['results'][0]['id']; + } + } catch (Exception $e) { + $result = false; + } + + return $result; + } + + /** + * + */ + public function processGamesReleases() + { + $res = $this->pdo->queryDirect( + sprintf(' + SELECT searchname, ID + FROM releases + WHERE nzbstatus = 1 %s + AND gamesinfo_id IS NULL + AND categoryID = 4050 + ORDER BY postdate DESC + LIMIT %d', + $this->renamed, + $this->gameqty + ) + ); + + if ($res !== false && $res->rowCount() > 0) { + if ($this->echooutput) { + $this->c->doEcho($this->c->header("Processing " . $res->rowCount() . ' games release(s).')); + } + + foreach ($res as $arr) { + $startTime = microtime(true); + $usedgb = false; + $gameInfo = $this->parseTitle($arr['searchname']); + if ($gameInfo !== false) { + + if ($this->echooutput) { + $this->c->doEcho( + $this->c->headerOver('Looking up: ') . + $this->c->primary($gameInfo['title'] . ' (' . $gameInfo['platform'] . ')' ) + ); + } + + // Check for existing games entry. + $gameCheck = $this->getgamesinfoByName($gameInfo['title'], $gameInfo['platform']); + + if ($gameCheck === false) { + $gameId = $this->updategamesinfo($gameInfo); + $usedgb = true; + if ($gameId === false) { + $gameId = -2; + } + } else { + $gameId = $gameCheck['id']; + } + //$gameId = null; + // Update release. + $this->pdo->exec(sprintf('UPDATE releases SET gamesinfo_id = %d WHERE ID = %d', $gameId, $arr['ID'])); + } else { + // Could not parse release title. + $this->pdo->exec(sprintf('UPDATE releases SET gamesinfo_id = %d WHERE ID = %d', -2, $arr['ID'])); + + if ($this->echooutput) { + echo '.'; + } + } + + // Sleep to not flood amazon. + $diff = floor((microtime(true) - $startTime) * 1000000); + if ($this->sleeptime * 1000 - $diff > 0 && $usedgb === true) { + usleep($this->sleeptime * 1000 - $diff); + } + } + } else { + if ($this->echooutput) { + $this->c->doEcho($this->c->header('No games releases to process.')); + } + } + } + + /** + * Parse the game release title + * + * @param string $releasename + * + * @return array|bool + */ + public function parseTitle($releasename) + { + // Get name of the game from name of release. + if (preg_match( + '/^(.+((EFNet|EFNet\sFULL|FULL\sabgxEFNet|abgx\sFULL|abgxbox360EFNet)\s|illuminatenboard\sorg|' . + 'Place2(hom|us)e.net|united-forums? co uk|\(\d+\)))?(?P.*?)[\.\-_ \:](v\.?\d\.\d|RIP|ADDON|' . + 'EUR|USA|JP|ASIA|JAP|JPN|AUS|MULTI(\.?\d{1,2})?|PATCHED|FULLDVD|DVD5|DVD9|DVDRIP|\(GAMES\)\s*\(C\)|PROPER|REPACK|RETAIL|' . + 'DEMO|DISTRIBUTION|BETA|REGIONFREE|READ\.?NFO|NFOFIX|Update|' . + // Group names, like Reloaded, CPY, Razor1911, etc + '[a-z0-9]{2,}$)/i', + preg_replace('/\sMulti\d?\s/i', '', $releasename), + $matches) + ) { + // Replace dots, underscores, or brackets with spaces. + $result['title'] = str_replace(' RF ', ' ', preg_replace('/(\.|_|\%20|\[|\])/', ' ', $matches['title'])); + // Needed to add code to handle DLC Properly. + if (stripos($result['title'], 'dlc') !== false) { + $result['dlc'] = '1'; + if (stripos($result['title'], 'Rock Band Network') !== false) { + $result['title'] = 'Rock Band'; + } else if (stripos($result['title'], '-') !== false) { + $dlc = explode("-", $result['title']); + $result['title'] = $dlc[0]; + } else if (preg_match('/(.*? .*?) /i', $result['title'], $dlc)) { + $result['title'] = $dlc[0]; + } + } + + //get the platform of the release + if (preg_match('/[\.\-_ ](?P<platform>MAC|MACOSX)/i', $releasename, $matches)) { + $platform = $matches['platform']; + if (preg_match('/^MAC$/i', $platform)) { + $platform = 'MAC'; + } else { + $platform = 'MACOSX'; + } + } else { + $platform = "PC"; + } + + $browseNode = $this->getBrowseNode($platform); + $result['platform'] = $platform; + $result['node'] = $browseNode; + $result['release'] = $releasename; + + // Other option is to pass the $release->categoryID here if we don't find a platform but that would require an + // extra lookup to determine the name. In either case we should have a title at the minimum. + return array_map("trim", $result); + } + + return false; + } + + /** + * Set the Giantbomb Category ID # + * + * @param $platform + * + * @return string + */ + protected function getBrowseNode($platform) + { + switch ($platform) { + case 'PC': + $nodeId = '94'; + break; + case 'MAC': + $nodeId = '17'; + break; + default: + $nodeId = '94'; + break; + } + + return $nodeId; + } + + /** + * Not in use for future additions. + * + * @param $nodeName + * + * @return bool|string + */ + public function matchBrowseNode($nodeName) + { + $str = ''; + + //music nodes above mp3 download nodes + switch ($nodeName) { + case 'Action': + case 'Adventure': + case 'Arcade': + case 'Board Games': + case 'Cards': + case 'Casino': + case 'Flying': + case 'Puzzle': + case 'Racing': + case 'Rhythm': + case 'Role-Playing': + case 'Simulation': + case 'Sports': + case 'Strategy': + case 'Trivia': + $str = $nodeName; + break; + } + + return ($str !== '') ? $str : false; + } +} \ No newline at end of file diff --git a/lib/copy_this/www/lib/GiantBombAPI.php b/lib/copy_this/www/lib/GiantBombAPI.php new file mode 100644 index 000000000..96ba3d650 --- /dev/null +++ b/lib/copy_this/www/lib/GiantBombAPI.php @@ -0,0 +1,435 @@ +<?php + +/** + * GiantBomb PHP wrapper is a simple class written in PHP to + * make interactions with GiantBomb api easier. + * + * @package GiantBomb api PHP wrapper + * @version 0.4 + * @author Amal Francis + * @author Koroban + * @license MIT License + */ +class GiantBomb +{ + + /** + * The api key + * + * @access private + * @type string + */ + private $api_key = ""; + + /** + * The api response type : json/xml + * + * @access private + * @type string + */ + private $resp_type = "json"; + + /** + * A variable to hold the formatted result of + * last api request + * + * @access public + * @type array + */ + public $result = array(); + + /** + * api endpoint + * prefix for all API cals + * + * @access protected + * @type string + */ + protected $endpoint = 'http://www.giantbomb.com/api/'; + + /** + * curl instance + * + * @access protected + * @type handle + */ + protected $ch = null; + + /** + * Constructor of class + * + * @param string $key string API key to use + * @param string $resp type Type of respone to request + * + * @void + */ + public function __construct($key, $resp = "json") + { + // Set the api key + $this->api_key = $key; + + // Now set the api response type, Default to json + $this->resp_type = $resp; + + // Init new instance of curl + $this->ch = curl_init(); + + // set default options for curl + curl_setopt_array( + $this->ch, + array( + CURLOPT_HEADER => false, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_NOPROGRESS => true, + CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31' + ) + ); + } + + /** + * Destructor + * deletes curl instance + * + * @void + */ + public function __destruct() + { + // Close request to clear up some resources + if (!is_null($this->ch)) { + curl_close($this->ch); + } + } + + /** + * Send call to API + * + * @param string $module string name of url suffix + * @param array $params array get parameters to send to API + * + * @return mixed|array response of API + * @throws GiantBombException + */ + private function call($module, $params = array()) + { + // set api data + $params['api_key'] = $this->api_key; + $params['format'] = $this->resp_type; + + // build URL + $url = $this->endpoint . $module . '?' . http_build_query($params); + + // Set URL + curl_setopt($this->ch, CURLOPT_URL, $url); + + // Send the request & save response to $resp + $resp["data"] = curl_exec($this->ch); + if (curl_errno($this->ch)) { + throw new GiantBombException('API call failed: ' . curl_error($this->ch)); + } + + // save http response code + $resp["httpCode"] = curl_getinfo($this->ch, CURLINFO_HTTP_CODE); + + if (!$resp || !$resp["data"]) { + throw new GiantBombException("Couldn't get information from API"); + } + + return $resp; + } + + /** + * Format filter array to string + * + * @param $filters array list of filters + * + * @return string combined filter string + */ + private function format_filter($filters = array()) + { + $filters_merged = array(); + foreach ($filters as $ky => $vl) { + $filters_merged[] = $ky . ':' . $vl; + } + + return implode(',', $filters_merged); + } + + /** + * Get information about given object type + * + * @param string $type + * @param string $id string ID to request + * @param array $field_list array list of fields to response + * + * @return array response + * @throws GiantBombException + */ + public function get_object($type, $id, $field_list = array()) + { + $resp = $this->call($type . '/' . $id . '/', + array('field_list' => implode(',', $field_list))); + + // No game with given game id found + if ($resp["httpCode"] == 404) { + throw new GiantBombException('Couldn\'t find ' . $type . ' with game id "' . $id . '"'); + } + + return $this->parse_result($resp["data"]); + } + + /** + * Get list of objects by given filters + * + * @param $type + * @param $filter array filter by given values - no "," accepted + * @param $limit integer limit result count by given limit + * @param $offset integer offset of results + * @param $platform integer ID of platform to limit + * @param $sort array list of keys to sort, format key => asc/desc, + * @param $field_list array list of field to result + * + * @return mixed|array response + */ + public function get_objects($type, $filter = array(), $limit = 100, $offset = 0, + $platform = null, $sort = array(), $field_list = array()) + { + $resp = $this->call($type . '/', + array( + 'field_list' => implode(',', $field_list), + 'limit' => $limit, + 'offset' => $offset, + 'platforms' => $platform, + 'sort' => $this->format_filter($sort), + 'filter' => $this->format_filter($filter) + )); + + return $this->parse_result($resp["data"]); + } + + /** + * Get information about a game + * + * @param $id string ID to request + * @param $field_list array list of fields to response + * + * @return array response + */ + public function game($id, $field_list = array()) + { + return $this->get_object('game', $id, $field_list); + } + + /** + * List games by filters + * + * @param $filter array filter by given values - no "," accepted + * @param $limit integer limit result count by given limit + * @param $offset integer offset of results + * @param $platform integer ID of platform to limit + * @param $sort array list of keys to sort, format key => asc/desc, + * @param $field_list array list of field to result + * + * @return array list of games + */ + public function games($filter = array(), $limit = 100, $offset = 0, $platform = null, + $sort = array(), $field_list = array()) + { + return $this->get_objects('games', $filter, $limit, $offset, $platform, $sort, $field_list); + } + + /** + * Get review by id + * + * @param $review_id string ID to request + * @param $field_list array list of fields to response + * + * @return array response + */ + public function review($review_id, $field_list = array()) + { + return $this->get_object('review', $review_id, $field_list); + } + + /** + * Get game_rating by id + * + * @param $rating_id string ID to request + * @param $field_list array list of fields to response + * + * @return array response + */ + public function game_rating($rating_id, $field_list = array()) + { + return $this->get_object('game_rating', $rating_id, $field_list); + } + + /** + * Get company by id + * + * @param $company_id string ID to request + * @param $field_list array list of fields to response + * + * @return array response + */ + public function company($company_id, $field_list = array()) + { + return $this->get_object('company', $company_id, $field_list); + } + + /** + * Get character by id + * + * @param $character_id string ID to request + * @param $field_list array list of fields to response + * + * @return array response + */ + public function character($character_id, $field_list = array()) + { + return $this->get_object('character', $character_id, $field_list); + } + + /** + * Perform a search with given keyword + * + * @param $query string keyword to search + * @param $field_list array list of fields to response + * @param $limit integer limit result count by given limit + * @param $page + * @param $resources + * + * @return array response + */ + public function search($query, $field_list = array(), $limit = 100, $page = 0, $resources = array()) + { + if (!is_array($field_list)) { + $field_list = (array)$field_list; + } + if (!is_array($resources)) { + $resources = (array)$resources; + } + + $resp = $this->call( + 'search/', + array( + 'field_list' => implode(',', $field_list), + 'limit' => $limit, + 'page' => $page, + 'query' => $query, + 'resources' => implode(',', $resources) + ) + ); + + return $this->parse_result($resp['data']); + } + + /** + * List genres + * + * @param $field_list array list of field to result + * @param $limit integer limit result count by given limit + * @param $offset integer offset of results + * + * @return array list of games + */ + public function genres($field_list = array(), $limit = 100, $offset = 0) + { + $resp = $this->call( + 'genres/', + array( + 'field_list' => implode(',', $field_list), + 'limit' => $limit, + 'offset' => $offset + ) + ); + + return $this->parse_result($resp['data']); + } + + /** + * List platforms by filter + * + * @param $field_list array list of field to result + * @param $limit integer limit result count by given limit + * @param $offset integer offset of results + * @param $filter array filter by given values - no "," accepted + * @param $sort array list of keys to sort, format key => asc/desc, + * + * @return array list of games + */ + public function platforms($field_list = array(), $limit = 100, $offset = 0, $filter = array(), + $sort = array()) + { + $resp = $this->call( + 'platforms/', + array( + 'field_list' => implode(',', $field_list), + 'limit' => $limit, + 'offset' => $offset, + 'sort' => $this->format_filter($sort), + 'filter' => $this->format_filter($filter) + ) + ); + + return $this->parse_result($resp["data"]); + } + + /** + * Return parsed result of api response + * + * @param $data string result of API + * + * @return mixed|SimpleXMLElement parsed version of input string(object) + * @throws GiantBombException + */ + private function parse_result($data) + { + try { + if ($this->resp_type == "json") { + $result = @json_decode($data); + } else { + $result = @simplexml_load_string($data); + } + } catch (Exception $e) { + throw new GiantBombException("Parse error occoured", null, $e); + } + + if (empty($result) || !empty($result->error) && strtoupper($result->error) != "OK") { + throw new GiantBombException("Following error encountered: " . $result->error); + } + + return $result; + } +} + +/** + * Define a custom exception class for api wrapper + */ +class GiantBombException extends Exception +{ + + /** + * Redefine the exception so message isn't optional + * + * @param $message string message to set in exception + * @param $code integer error code + * @param $previous Exception previous Exception to save + * + * @void + */ + public function __construct($message, $code = 0, Exception $previous = null) + { + // make sure everything is assigned properly + parent::__construct($message, $code, $previous); + } + + /** + * convert exception to string + * + * @return string + */ + public function __toString() + { + return __CLASS__ . ": [{$this->code}]: {$this->message}\n"; + } +} \ No newline at end of file diff --git a/lib/copy_this/www/lib/nntp.php b/lib/copy_this/www/lib/nntp.php index 277bf1efc..0d75d59f5 100644 --- a/lib/copy_this/www/lib/nntp.php +++ b/lib/copy_this/www/lib/nntp.php @@ -1,5 +1,4 @@ <?php - /** * Attempt to include PEAR's nntp class if it has not already been included. */ diff --git a/lib/copy_this/www/lib/users.php b/lib/copy_this/www/lib/users.php index 21d36a9e7..83414e647 100644 --- a/lib/copy_this/www/lib/users.php +++ b/lib/copy_this/www/lib/users.php @@ -157,7 +157,7 @@ class Users return $db->queryInsert($sql); } - public function update($id, $uname, $email, $grabs, $role, $notes, $invites, $movieview, $musicview, $consoleview, $bookview, $queueType = '', $nzbgetURL = '', $nzbgetUsername = '', $nzbgetPassword = '', $saburl = '', $sabapikey = '', $sabpriority = '', $sabapikeytype = '', $nzbvortexServerUrl = false, $nzbvortexApiKey = false) + public function update($id, $uname, $email, $grabs, $role, $notes, $invites, $movieview, $musicview, $gameview, $consoleview, $bookview, $queueType = '', $nzbgetURL = '', $nzbgetUsername = '', $nzbgetPassword = '', $saburl = '', $sabapikey = '', $sabpriority = '', $sabapikeytype = '', $nzbvortexServerUrl = false, $nzbvortexApiKey = false) { $db = new DB(); @@ -190,6 +190,7 @@ class Users $sql[] = sprintf('invites = %d', $invites); $sql[] = sprintf('movieview = %d', $movieview); $sql[] = sprintf('musicview = %d', $musicview); + $sql[] = sprintf('gameview = %d', $gameview); $sql[] = sprintf('consoleview = %d', $consoleview); $sql[] = sprintf('bookview = %d', $bookview); diff --git a/lib/copy_this/www/pages/browse.php b/lib/copy_this/www/pages/browse.php new file mode 100644 index 000000000..3148c4fa2 --- /dev/null +++ b/lib/copy_this/www/pages/browse.php @@ -0,0 +1,82 @@ +<?php +require_once(WWW_DIR."/lib/releases.php"); +require_once(WWW_DIR."/lib/category.php"); + +$releases = new Releases; + +if (!$users->isLoggedIn()) + $page->show403(); + +$category = -1; +if (isset($_REQUEST["t"]) && ctype_digit($_REQUEST["t"])) + $category = $_REQUEST["t"]; + +$grp = array(); +if (isset($_REQUEST["g"])) + $grp = explode(",", $_REQUEST["g"]); + +$catarray = array(); +$catarray[] = $category; + +$page->smarty->assign('category', $category); +$browsecount = $releases->getBrowseCount($catarray, -1, $page->userdata["categoryexclusions"], $grp); + +$offset = (isset($_REQUEST["offset"]) && ctype_digit($_REQUEST['offset'])) ? $_REQUEST["offset"] : 0; +$ordering = $releases->getBrowseOrdering(); +$orderby = isset($_REQUEST["ob"]) && in_array($_REQUEST['ob'], $ordering) ? $_REQUEST["ob"] : ''; + +$results = array(); +$results = $releases->getBrowseRange($catarray, $offset, ITEMS_PER_PAGE, $orderby, -1, $page->userdata["categoryexclusions"], $grp); + +$page->smarty->assign('pagertotalitems',$browsecount); +$page->smarty->assign('pageroffset',$offset); +$page->smarty->assign('pageritemsperpage',ITEMS_PER_PAGE); +$page->smarty->assign('pagerquerybase', WWW_TOP."/browse?t=".$category.(count($grp) > 0 ? "&g=".$grp[0] : "")."&ob=".$orderby."&offset="); +$page->smarty->assign('pagerquerysuffix', "#results"); + +$pager = $page->smarty->fetch("pager.tpl"); +$page->smarty->assign('pager', $pager); + +$section = ''; +if ($category == -1 && count($grp) == 0) + $page->smarty->assign("catname","All"); +elseif ($category != -1 && count($grp) == 0) +{ + $cat = new Category(); + $cdata = $cat->getById($category); + + if ($cdata) { + $page->smarty->assign('catname',$cdata["title"]); + if ($cdata['parentID'] == Category::CAT_PARENT_GAME || $cdata['ID'] == Category::CAT_PARENT_GAME) + $section = 'console'; + elseif ($cdata['ID'] == Category::CAT_BOOK_EBOOK) + $section = 'books'; + elseif ($cdata['parentID'] == Category::CAT_PARENT_MOVIE || $cdata['ID'] == Category::CAT_PARENT_MOVIE) + $section = 'movies'; + elseif ($cdata['parentid'] == Category::CAT_PARENT_PC || $cdata['ID'] == Category::CAT_PC_GAMES) + $section = 'games'; + elseif ($cdata['parentID'] == Category::CAT_PARENT_MUSIC || $cdata['ID'] == Category::CAT_PARENT_MUSIC) + $section = 'music'; + } else { + $page->show404(); + } +} +elseif (count($grp) > 0) +{ + $page->smarty->assign('catname',$grp[0]); +} +$page->smarty->assign('section',$section); + +foreach($ordering as $ordertype) + $page->smarty->assign('orderby'.$ordertype, WWW_TOP."/browse?t=".$category."&ob=".$ordertype."&offset=0".(count($grp) > 0 ? "&g=".$grp[0] : "")); + +$page->smarty->assign('lastvisit',$page->userdata['lastlogin']); + +$page->smarty->assign('results',$results); + +$page->meta_title = "Browse Nzbs"; +$page->meta_keywords = "browse,nzb,description,details"; +$page->meta_description = "Browse for Nzbs"; + +$page->content = $page->smarty->fetch('browse.tpl'); +$page->render(); \ No newline at end of file diff --git a/lib/copy_this/www/pages/games.php b/lib/copy_this/www/pages/games.php new file mode 100644 index 000000000..32f8954dd --- /dev/null +++ b/lib/copy_this/www/pages/games.php @@ -0,0 +1,97 @@ +<?php +require_once(WWW_DIR . "/lib/category.php"); +require_once(WWW_DIR . "/lib/Games.php"); +require_once(WWW_DIR . "/lib/genres.php"); +if (!$users->isLoggedIn()) { + $page->show403(); +} + +$games = new Games(); +$cat = new Category(); +$gen = new Genres(); + +$concats = $cat->getChildren(Category::CAT_PARENT_PC); +$ctmp = array(); +foreach ($concats as $ccat) { + $ctmp[$ccat['ID']] = $ccat; +} +$category = Category::CAT_PC_GAMES; +if (isset($_REQUEST["t"]) && array_key_exists($_REQUEST['t'], $ctmp)) { + $category = $_REQUEST["t"] + 0; +} + +$catarray = array(); +$catarray[] = $category; + +$page->smarty->assign('catlist', $ctmp); +$page->smarty->assign('category', $category); + +$browsecount = $games->getgamesCount($catarray, -1, $page->userdata["categoryexclusions"]); + +$offset = (isset($_REQUEST["offset"]) && ctype_digit($_REQUEST['offset'])) ? $_REQUEST["offset"] : 0; +$ordering = $games->getgamesOrdering(); + +$orderby = isset($_REQUEST["ob"]) && in_array($_REQUEST['ob'], $ordering) ? $_REQUEST["ob"] : ''; + +$results = $games2 = array(); +$results = $games->getgamesRange($catarray, $offset, ITEMS_PER_COVER_PAGE, $orderby, -1, $page->userdata["categoryexclusions"]); +$maxwords = 50; +foreach ($results as $result) { + if (!empty($result['review'])) { + $words = explode(' ', $result['review']); + if (sizeof($words) > $maxwords) { + $newwords = array_slice($words, 0, $maxwords); + $result['review'] = implode(' ', $newwords) . '...'; + } + } + $games2[] = $result; +} +$platform = (isset($_REQUEST['platform']) && !empty($_REQUEST['platform'])) ? stripslashes($_REQUEST['platform']) : ''; +$page->smarty->assign('platform', $platform); + +$title = (isset($_REQUEST['title']) && !empty($_REQUEST['title'])) ? stripslashes($_REQUEST['title']) : ''; +$page->smarty->assign('title', $title); + +$genres = $gen->getGenres(Genres::GAME_TYPE, true); +$tmpgnr = array(); +foreach ($genres as $gn) { + $tmpgnr[$gn['id']] = $gn['title']; +} +$genre = (isset($_REQUEST['genre']) && array_key_exists($_REQUEST['genre'], $tmpgnr)) ? $_REQUEST['genre'] : ''; +$page->smarty->assign('genres', $genres); +$page->smarty->assign('genre', $genre); + +$browseby_link = '&title=' . $title . '&platform=' . $platform; + +$page->smarty->assign('pagertotalitems', $browsecount); +$page->smarty->assign('pageroffset', $offset); +$page->smarty->assign('pageritemsperpage', ITEMS_PER_COVER_PAGE); +$page->smarty->assign('pagerquerybase', WWW_TOP . "/games?t=" . $category . $browseby_link . "&ob=" . $orderby . "&offset="); +$page->smarty->assign('pagerquerysuffix', "#results"); + +$pager = $page->smarty->fetch("pager.tpl"); +$page->smarty->assign('pager', $pager); + +if ($category == -1) { + $page->smarty->assign("catname", "All"); +} else { + $cdata = $cat->getById($category); + if ($cdata) { + $page->smarty->assign('catname', $cdata["title"]); + } else { + $page->show404(); + } +} + +foreach ($ordering as $ordertype) { + $page->smarty->assign('orderby' . $ordertype, WWW_TOP . "/games?t=" . $category . $browseby_link . "&ob=" . $ordertype . "&offset=0"); +} + +$page->smarty->assign('results', $games2); + +$page->meta_title = "Browse Games"; +$page->meta_keywords = "browse,nzb,games,description,details"; +$page->meta_description = "Browse for Games"; + +$page->content = $page->smarty->fetch('games.tpl'); +$page->render(); \ No newline at end of file diff --git a/lib/copy_this/www/pages/profileedit.php b/lib/copy_this/www/pages/profileedit.php index f98f7fd46..eedcf5e7e 100644 --- a/lib/copy_this/www/pages/profileedit.php +++ b/lib/copy_this/www/pages/profileedit.php @@ -67,6 +67,7 @@ switch ($action) { $data["invites"], (isset($_POST['movieview']) ? "1" : "0"), (isset($_POST['musicview']) ? "1" : "0"), + (isset($_POST['gameview']) ? "1" : "0"), (isset($_POST['consoleview']) ? "1" : "0"), (isset($_POST['bookview']) ? "1" : "0"), $_POST['queuetypeids'], diff --git a/lib/copy_this/www/templates/nntmux/images/icons/giantbomb.png b/lib/copy_this/www/templates/nntmux/images/icons/giantbomb.png new file mode 100644 index 0000000000000000000000000000000000000000..e1f450c5f51a00e60c28befc4a53a4fde39b7391 GIT binary patch literal 815 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GXl47y|-)LR^8|l$4aDq@?)x`2U+3 z{%>Ij4Gjf~q#}W|w6upU4F5NP5ReT75J@<rx*#k!GyZlJ$S9x`(6s32=$eAigA>#b zg)sm{JUl#r7D2#vcZOY_48NB$C@CocMb4!$JZWUu>B_Lng8?YD(~|+@jE!LH)-!xs z$@zaB!~eA)t#@k}{;y&9znbCyDh7FZc|AQnPfyQ?hzMR@-p!jg-z;G`lf=Ny&0Sep z33S;1|No1Mif$G&<mKhr+uNTzcdoy`|NHmv4Gj&;mMxQ%l)NJ(^#1+(4I4IyiHV&* zf4;M`^WedQ78VxqF)=}YeqCK%=H})%u3Wu;;qv7R7X$<ZbaZr*laqUx#Ge}ZzD_Fp zyl`!-p?NI3@cV+ymvJ!<_;sE+cs-If?wrm17U)*Pk|4ie1{q5ZhXtIC=k`B+>{zg2 z0qfaMIkSIE+5Gp&?k`e&wI8!y+`DwaLE*u&V+}Jd7!)`(yt{wvI8ZZVlDE5y#|Ne> zuYerR0*}aIAPovY4+giB*>*t2O-~oc5Q)pl2@H&GYH1254{<#+*s!s<ps4V(fx!o< zPai)U8*p%NaT*(RbaZukOGwW4Ff#D)Jl$~R<f)UhXU&|gZD63Gr5PO&v0}xlmC;d= zw=)b3GH%_vX>DN@nPHf5+hX?%gB81W?X0e-U=m&Vs_NxSX@eCNzkgI!RQ&kKzQW)| zBhO|Io=+b*zH#t<+|aP&kkXYy%xjqR1SHY~-w6u76l4$$_}KTUqi-X_O&-Aj-tOM+ z?;kuoe1cjz3^G)gFIl!UJtfQVKtonUSXo&gE3?ps6K7Aib22alDXJURy%PQd^rUKu zYeY#(Vo9o1a#1RfVlXl=G|@FM(>1gRF)+6>G_W!<(l)TLGB9}TRPq@`LvDUbW?Cg~ V4U^>0_yaXCc)I$ztaD0e0suFiJv{&b literal 0 HcmV?d00001 diff --git a/lib/copy_this/www/templates/nntmux/views/admin/site-edit.tpl b/lib/copy_this/www/templates/nntmux/views/admin/site-edit.tpl index 6bac44d41..0b3f0fc19 100644 --- a/lib/copy_this/www/templates/nntmux/views/admin/site-edit.tpl +++ b/lib/copy_this/www/templates/nntmux/views/admin/site-edit.tpl @@ -232,6 +232,14 @@ <div class="hint">The amazon associate tag. Used for cover lookups.</div> </td> </tr> +<tr> + <td style="width:180px;"><label for="giantbombkey">Giant Bomb API Key:</label></td> + <td> + <input id="giantbombkey" class="long" name="giantbombkey" type="text" value="{$fsite->giantbombkey}"/> + + <div class="hint">The giantbomb key. Used for game lookups.</div> + </td> +</tr> </table> </fieldset> @@ -981,5 +989,4 @@ <input type="submit" value="Save Site Settings" /> -</form> - +</form> \ No newline at end of file diff --git a/lib/copy_this/www/templates/nntmux/views/admin/user-edit.tpl b/lib/copy_this/www/templates/nntmux/views/admin/user-edit.tpl index a6b5d445e..47fece2d0 100644 --- a/lib/copy_this/www/templates/nntmux/views/admin/user-edit.tpl +++ b/lib/copy_this/www/templates/nntmux/views/admin/user-edit.tpl @@ -1,4 +1,4 @@ - + <h1>{$page->title}</h1> {if $error != ''} @@ -31,7 +31,7 @@ {if $user.ID} <div class="hint">Only enter a password if you want to change it.</div> {/if} - </td> + </td> </tr> {if $user.ID} <tr> @@ -63,6 +63,13 @@ </td> </tr> +<tr> + <td>Game View:</td> + <td> + <input name="gameview" type="checkbox" value="1" {if $user.gameview=="1"}checked="checked"{/if}" /> + </td> +</tr> + <tr> <td>Console View:</td> <td> @@ -95,16 +102,16 @@ <td></td> <td> <input type="submit" value="Save" /> - + {if $user.ID != ""} - <input onclick="return doDelete();" type="button" value="Delete" /> - + <input onclick="return doDelete();" type="button" value="Delete" /> + <script type="text/javascript"> function doDelete() { - if (confirm('Are you sure?')) - window.location='user-delete.php?id={$user.ID}&redir=user-list.php'; - else + if (confirm('Are you sure?')) + window.location='user-delete.php?id={$user.ID}&redir=user-list.php'; + else return false; } </script> diff --git a/lib/copy_this/www/templates/nntmux/views/frontend/games.tpl b/lib/copy_this/www/templates/nntmux/views/frontend/games.tpl new file mode 100644 index 000000000..1b53d0424 --- /dev/null +++ b/lib/copy_this/www/templates/nntmux/views/frontend/games.tpl @@ -0,0 +1,231 @@ +{if $site->adbrowse} + {$site->adbrowse} +{/if} +<h1>Browse Games</h1> + +<form name="browseby" action="games"> + <table class="rndbtn" border="0" cellpadding="2" cellspacing="0"> + <tr> + <th class="left"><label for="title">Title</label></th> + <th class="left"><label for="platform">Platform</label></th> + <th class="left"><label for="genre">Genre</label></th> + <th class="left"><label for="category">Category</label></th> + <th></th> + </tr> + <tr> + <td><input id="title" type="text" name="title" value="{$title}" size="15"/></td> + <td><input id="platform" type="text" name="platform" value="{$platform}" size="15"/></td> + <td> + <select id="genre" name="genre"> + <option class="grouping" value=""></option> + {foreach from=$genres item=gen} + <option {if $gen.id == $genre}selected="selected"{/if} value="{$gen.id}">{$gen.title}</option> + {/foreach} + </select> + </td> + <td> + <select id="category" name="t"> + <option class="grouping" value="1000"></option> + {foreach from=$catlist item=ct} + <option {if $ct.id==$category}selected="selected"{/if} value="{$ct.id}">{$ct.title}</option> + {/foreach} + </select> + </td> + <td><input class='rndbtn' type="submit" value="Go"/></td> + </tr> + </table> +</form> +<p></p> + +{if $results|@count > 0} + <form id="nzb_multi_operations_form" action="get"> + + <div class="nzb_multi_operations"> + View: <b>Covers</b> | <a href="{$smarty.const.WWW_TOP}/browse?t={$category}">List</a><br/> + <small>With Selected:</small> + <input type="button" class="nzb_multi_operations_download" value="Download NZBs"/> + <input type="button" class="nzb_multi_operations_cart" value="Add to Cart"/> + {if $sabintegrated}<input type="button" class="nzb_multi_operations_sab" value="Send to my Queue"/>{/if} + </div> + <br/> + + {$pager} + + <table style="width:100%;" class="data highlight icons" id="coverstable"> + <tr> + <th width="130"><input type="checkbox" class="nzb_check_all"/></th> + <th>title<br/><a title="Sort Descending" href="{$orderbytitle_desc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_down.gif" + alt=""/></a><a title="Sort Ascending" href="{$orderbytitle_asc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_up.gif" alt=""/></a> + </th> + <th>platform<br/><a title="Sort Descending" href="{$orderbyplatform_desc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_down.gif" + alt=""/></a><a title="Sort Ascending" href="{$orderbyplatform_asc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_up.gif" alt=""/></a> + </th> + <th>genre<br/><a title="Sort Descending" href="{$orderbygenre_desc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_down.gif" + alt=""/></a><a title="Sort Ascending" href="{$orderbygenre_asc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_up.gif" alt=""/></a> + </th> + <th>release date<br/><a title="Sort Descending" href="{$orderbyreleasedate_desc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_down.gif" + alt=""/></a><a title="Sort Ascending" href="{$orderbyreleasedate_asc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_up.gif" alt=""/></a> + </th> + <th>posted<br/><a title="Sort Descending" href="{$orderbyposted_desc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_down.gif" + alt=""/></a><a title="Sort Ascending" href="{$orderbyposted_asc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_up.gif" alt=""/></a> + </th> + <th>size<br/><a title="Sort Descending" href="{$orderbysize_desc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_down.gif" + alt=""/></a><a title="Sort Ascending" href="{$orderbysize_asc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_up.gif" alt=""/></a> + </th> + <th>files<br/><a title="Sort Descending" href="{$orderbyfiles_desc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_down.gif" + alt=""/></a><a title="Sort Ascending" href="{$orderbyfiles_asc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_up.gif" alt=""/></a> + </th> + <th>stats<br/><a title="Sort Descending" href="{$orderbystats_desc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_down.gif" + alt=""/></a><a title="Sort Ascending" href="{$orderbystats_asc}"><img + src="{$smarty.const.WWW_TOP}/templates/nntmux/images/sorting/arrow_up.gif" alt=""/></a> + </th> + </tr> + + {foreach from=$results item=result} + <tr class="{cycle values=",alt"}"> + <td class="mid"> + <div class="movcover"> + <a class="title" title="View details" + href="{$smarty.const.WWW_TOP}/details/{$result.guid}/{$result.searchname|escape:"htmlall"}"> + <img class="shadow" + src="{$smarty.const.WWW_TOP}/covers/games/{if $result.cover == 1}{$result.gamesinfo_id}.jpg{else}no-cover.jpg{/if}" + width="120" border="0" alt="{$result.title|escape:"htmlall"}"/> + </a> + + <div class="movextra"> + {if $result.nfoid > 0}<a href="{$smarty.const.WWW_TOP}/nfo/{$result.guid}" + title="View Nfo" class="rndbtn modal_nfo" rel="nfo"> + Nfo</a>{/if} + <a class="rndbtn" target="_blank" href="{$site->dereferrer_link}{$result.url}" + name="amazon{$result.gamesinfo_id}" title="View amazon page">Amazon</a> + <a class="rndbtn" target="_blank" + href="{$site->dereferrer_link}http://ign.com/search?q={$result.title|escape:"htmlall"}&page=0&count=10&type=object&objectType=game&filter=games&" + name="ign{$result.gamesinfo_id}" title="View ign page">IGN</a> + <a class="rndbtn" target="_blank" + href="{$site->dereferrer_link}http://www.gamespot.com/search/?qs={$result.title|escape:"htmlall"}/" + name="gamespot{$result.gamesinfo_id}" title="View gamespot page">Gamespot</a> + <a class="rndbtn" target="_blank" + href="{$site->dereferrer_link}http://www.metacritic.com/search/game/{$result.title|escape:"htmlall"}/results" + name="metacritic{$result.gamesinfo_id}" title="View metacritic page">Metacritic</a> + </div> + </div> + </td> + <td colspan="8" class="left" id="guid{$result.guid}"> + <h2><a class="title" title="View details" + href="{$smarty.const.WWW_TOP}/details/{$result.guid}/{$result.searchname|escape:"htmlall"}">{$result.title|stripslashes|escape:"htmlall"} + - {$result.platform|escape:"htmlall"}</a></h2> + {if $result.genre != ""}<b>Genre:</b>{$result.genre}<br/>{/if} + {if $result.esrb != ""}<b>Rating:</b>{$result.esrb}<br/>{/if} + {if $result.publisher != ""}<b>Publisher:</b>{$result.publisher}<br/>{/if} + {if $result.releasedate != ""}<b>Released:</b>{$result.releasedate|date_format}<br/>{/if} + {if $result.review != ""}<b>Review:</b>{$result.review|stripslashes|escape:'htmlall'}<br/>{/if} + <br/> + + <div class="movextra"> + <table> + {assign var="msplits" value=","|explode:$result.grp_release_id} + {assign var="mguid" value=","|explode:$result.grp_release_guid} + {assign var="mnfo" value=","|explode:$result.grp_release_nfoid} + {assign var="mgrp" value=","|explode:$result.grp_release_grpname} + {assign var="mname" value="#"|explode:$result.grp_release_name} + {assign var="mpostdate" value=","|explode:$result.grp_release_postdate} + {assign var="msize" value=","|explode:$result.grp_release_size} + {assign var="mtotalparts" value=","|explode:$result.grp_release_totalparts} + {assign var="mcomments" value=","|explode:$result.grp_release_comments} + {assign var="mgrabs" value=","|explode:$result.grp_release_grabs} + {assign var="mpass" value=","|explode:$result.grp_release_password} + {assign var="minnerfiles" value=","|explode:$result.grp_rarinnerfilecount} + {assign var="mhaspreview" value=","|explode:$result.grp_haspreview} + {foreach from=$msplits item=m} + <tr id="guid{$mguid[$m@index]}" {if $m@index > 1}class="mlextra"{/if}> + <td> + <div class="icon"><input type="checkbox" class="nzb_check" + value="{$mguid[$m@index]}"/></div> + </td> + <td> + <a href="{$smarty.const.WWW_TOP}/details/{$mguid[$m@index]}/{$mname[$m@index]|escape:"htmlall"}">{$mname[$m@index]|escape:"htmlall"}</a> + + <div> + <i class="icon-calendar"></i> Posted {$mpostdate[$m@index]|timeago} | <i + class="icon-hdd"></i> {$msize[$m@index]|fsize_format:"MB"} | <i + class="icon-file"></i> <a title="View file list" + href="{$smarty.const.WWW_TOP}/filelist/{$mguid[$m@index]}">{$mtotalparts[$m@index]} + files</a> | <i class="icon-comments"></i> <a + title="View comments for {$mname[$m@index]|escape:"htmlall"}" + href="{$smarty.const.WWW_TOP}/details/{$mguid[$m@index]}/{$mname[$m@index]|escape:"htmlall"}#comments">{$mcomments[$m@index]} + cmt{if $mcomments[$m@index] != 1}s{/if}</a> | <i + class="icon-download"></i> {$mgrabs[$m@index]} + grab{if $mgrabs[$m@index] != 1}s{/if} | + {if $mnfo[$m@index] > 0}<a + href="{$smarty.const.WWW_TOP}/nfo/{$mguid[$m@index]}" + title="View Nfo" class="modal_nfo" rel="nfo">Nfo</a> | {/if} + {if $mpass[$m@index] == 1}Passworded | {elseif $mpass[$m@index] == 2}Potential Password | {/if} + <a href="{$smarty.const.WWW_TOP}/browse?g={$mgrp[$m@index]}" + title="Browse releases in {$mgrp[$m@index]|replace:"alt.binaries":"a.b"}">Grp</a> + {if $mhaspreview[$m@index] == 1 && $userdata.canpreview == 1} | <a + href="{$smarty.const.WWW_TOP}/covers/preview/{$mguid[$m@index]}_thumb.jpg" + name="name{$mguid[$m@index]}" + title="Screenshot of {$mname[$m@index]|escape:"htmlall"}" + class="modal_prev" rel="preview">Preview</a>{/if} + {if $minnerfiles[$m@index] > 0} | <a href="#" onclick="return false;" + class="mediainfo" + title="{$mguid[$m@index]}"> + Media</a>{/if} + </div> + </td> + <td class="icons"> + <div class="icon icon_nzb"><a title="Download Nzb" + href="{$smarty.const.WWW_TOP}/getnzb/{$mguid[$m@index]}/{$mname[$m@index]|escape:"htmlall"}"> +  </a></div> + <div class="icon icon_cart" title="Add to Cart"></div> + {if $sabintegrated} + <div class="icon icon_sab" title="Send to my Queue"></div> + {/if} + </td> + </tr> + {if $m@index == 1 && $m@total > 2} + <tr> + <td colspan="5"><a class="mlmore" href="#">{$m@total-2} more...</a></td> + </tr> + {/if} + {/foreach} + </table> + </div> + </td> + </tr> + {/foreach} + + </table> + <br/> + + {$pager} + + <div class="nzb_multi_operations"> + <small>With Selected:</small> + <input type="button" class="nzb_multi_operations_download" value="Download NZBs"/> + <input type="button" class="nzb_multi_operations_cart" value="Add to Cart"/> + {if $sabintegrated}<input type="button" class="nzb_multi_operations_sab" value="Send to my Queue"/>{/if} + </div> + + </form> +{else} + <h4>There doesn't seem to be any releases here. Please try the <a + href="{$smarty.const.WWW_TOP}/browse?t={$category}">list</a> view.</h4> +{/if} + +<br/><br/><br/> \ No newline at end of file diff --git a/lib/copy_this/www/templates/nntmux/views/frontend/profile.tpl b/lib/copy_this/www/templates/nntmux/views/frontend/profile.tpl index d3d2ce487..aec7136be 100644 --- a/lib/copy_this/www/templates/nntmux/views/frontend/profile.tpl +++ b/lib/copy_this/www/templates/nntmux/views/frontend/profile.tpl @@ -1,4 +1,4 @@ - + <h1>Profile for {$user.username|escape:"htmlall"}</h1> <table class="data"> @@ -14,11 +14,11 @@ <tr><th>Grabs Today:</th><td><span id="ugrtd">{$grabstoday.num}</span> {if $grabstoday.num >= $user.downloadrequests}  <small>(Next DL in {($grabstoday.nextdl/3600)|intval}h {($grabstoday.nextdl/60) % 60}m)</small>{/if}{if $userdata.role==2 && $grabstoday.num > 0}<a onclick="resetapireq({$user.ID}, 'grabs'); document.getElementById('ugrtd').innerHTML='0'; return false;" href="#">Reset</a>{/if}</td></tr> {/if} <tr><th>Grabs Total:</th><td>{$user.grabs}</td></tr> - + {if ($user.ID==$userdata.ID || $userdata.role==2) && $site->registerstatus==1} <tr> <th title="Not public">Invites:</th> - <td>{$user.invites} + <td>{$user.invites} {if $user.invites > 0} [<a id="lnkSendInvite" onclick="return false;" href="#">Send Invite</a>] <span title="Your invites will be reduced when the invitation is claimed." class="invitesuccess" id="divInviteSuccess">Invite Sent</span> @@ -34,15 +34,16 @@ </td> </tr> {/if} - + {if $userinvitedby && $userinvitedby.username != ""} <tr><th>Invited By:</th><td><a title="View {$userinvitedby.username}'s profile" href="{$smarty.const.WWW_TOP}/profile?name={$userinvitedby.username}">{$userinvitedby.username}</a></td> {/if} - + <tr><th>UI Preferences:</th> <td> {if $user.movieview == "1"}View movie covers{else}View standard movie category{/if}<br/> {if $user.musicview == "1"}View music covers{else}View standard music category{/if}<br/> + {if $user.gameview == "1"}View game covers{else}View standard game category{/if}<br/> {if $user.consoleview == "1"}View console covers{else}View standard console category{/if}<br/> {if $user.bookview == "1"}View book covers{else}View standard book category{/if} </td> @@ -58,7 +59,7 @@ Storage: {if $sabsetting == ''}N/A{else}{$sabsetting}{/if} </td> {/if} - + {if ($user.ID==$userdata.ID)} <tr> <th>NZBVortex</th> @@ -74,8 +75,8 @@ <tr><th>My TV Shows:</th><td><a href="{$smarty.const.WWW_TOP}/myshows">Manage my shows</a></td></tr> <tr><th>My Movies:</th><td><a href="{$smarty.const.WWW_TOP}/mymovies">Manage my movies</a></td></tr> {/if} - - + + {if $user.ID==$userdata.ID}<tr><th></th><td><a href="{$smarty.const.WWW_TOP}/profileedit">Edit</a></td></tr>{/if} </table> @@ -91,7 +92,7 @@ <th>hosthash</th> <th>release</th> </tr> - + {foreach from=$downloadlist item=download} {if $download@iteration == 10} <tr class="more"><td colspan="3"><a onclick="$('tr.extra').toggle();$('tr.more').toggle();return false;" href="#">show all...</a></td></tr> @@ -121,7 +122,7 @@ <th>comment</th> </tr> - + {foreach from=$commentslist item=comment} <tr> <td width="80" title="{$comment.createddate}">{$comment.createddate|date_format}</td> diff --git a/lib/copy_this/www/templates/nntmux/views/frontend/profileedit.tpl b/lib/copy_this/www/templates/nntmux/views/frontend/profileedit.tpl index 6ea33ee5b..e2f836a3a 100644 --- a/lib/copy_this/www/templates/nntmux/views/frontend/profileedit.tpl +++ b/lib/copy_this/www/templates/nntmux/views/frontend/profileedit.tpl @@ -60,6 +60,13 @@ <div class="hint">Browse music covers. Only shows music with known lookup info.</div> </td> </tr> + <tr> + <th>View Game Page:</th> + <td> + <input id="gameview" name="gameview" value="1" type="checkbox" {if $user.gameview=="1"}checked="checked"{/if}> + <span class="help-block">Browse game covers. Only shows games with known lookup info.</span> + </td> + </tr> <tr> <th>View Console Page:</th> <td> diff --git a/lib/getGames.php b/lib/getGames.php new file mode 100644 index 000000000..39fa714ba --- /dev/null +++ b/lib/getGames.php @@ -0,0 +1,36 @@ +<?php +//This script will update all records in the gamesinfo table +require_once(dirname(__FILE__) . "/../bin/config.php"); +require_once(WWW_DIR . "/lib/Games.php"); +require_once("ColorCLI.php"); + + +$game = new Games(true); +$pdo = new DB(); +$c = new ColorCLI(); + +$res = $pdo->query( + sprintf("SELECT searchname FROM releases WHERE gamesinfo_id IS NULL AND categoryID = 4050 ORDER BY id DESC LIMIT 100") +); +$total = count($res); +if ($total > 0) { + echo $c->header("Updating game info for " . number_format($total) . " releases."); + + foreach ($res as $arr) { + $starttime = microtime(true); + $gameInfo = $game->parseTitle($arr['searchname']); + if ($gameInfo !== false) { + $gameData = $game->updateGamesInfo($gameInfo); + if ($gameData === false) { + echo $c->primary($gameInfo['release'] . ' not found'); + } + } + + // amazon limits are 1 per 1 sec + $diff = floor((microtime(true) - $starttime) * 1000000); + if (1000000 - $diff > 0) { + echo $c->alternate("Sleeping"); + usleep(1000000 - $diff); + } + } +} \ No newline at end of file diff --git a/lib/updateGamesImages.php b/lib/updateGamesImages.php new file mode 100644 index 000000000..c9d221da6 --- /dev/null +++ b/lib/updateGamesImages.php @@ -0,0 +1,45 @@ +<?php +require_once(dirname(__FILE__) . "/../bin/config.php"); +require_once(WWW_DIR . "/lib/framework/db.php"); +require_once("ColorCLI.php"); + +$pdo = new DB(); +$covers = $updated = $deleted = 0; +$c = new ColorCLI(); + +if ($argc == 1 || $argv[1] != 'true') { + exit($c->error("\nThis script will check all images in covers/games and compare to db->gamesinfo.\nTo run:\nphp $argv[0] true\n")); +} +$path2covers = WWW_DIR . 'covers/games' . '/'; + +$dirItr = new RecursiveDirectoryIterator($path2covers); +$itr = new RecursiveIteratorIterator($dirItr, RecursiveIteratorIterator::LEAVES_ONLY); +foreach ($itr as $filePath) { + if (is_file($filePath) && preg_match('/\d+\.jpg/', $filePath)) { + preg_match('/(\d+)\.jpg/', basename($filePath), $match); + if (isset($match[1])) { + $run = $pdo->queryDirect("UPDATE gamesinfo SET cover = 1 WHERE cover = 0 AND id = " . $match[1]); + if ($run !== false) { + if ($run->rowCount() >= 1) { + $covers++; + } else { + $run = $pdo->queryDirect("SELECT id FROM gamesinfo WHERE id = " . $match[1]); + if ($run !== false && $run->rowCount() == 0) { + echo $c->info($filePath . " not found in db."); + } + } + } + } + } +} + +$qry = $pdo->queryDirect("SELECT id FROM gamesinfo WHERE cover = 1"); +foreach ($qry as $rows) { + if (!is_file($path2covers . $rows['id'] . '.jpg')) { + $pdo->queryDirect("UPDATE gamesinfo SET cover = 0 WHERE cover = 1 AND id = " . $rows['id']); + echo $c->info($path2covers . $rows['id'] . ".jpg does not exist."); + $deleted++; + } +} +echo $c->header($covers . " covers set."); +echo $c->header($deleted . " games unset."); \ No newline at end of file diff --git a/start.php b/start.php index d06b4fe37..fd90fed7e 100644 --- a/start.php +++ b/start.php @@ -15,7 +15,7 @@ $tmux = $t->get(); $patch = (isset($tmux->sqlpatch)) ? $tmux->sqlpatch : 0; // Check database patch version -if ($patch < 51) { +if ($patch < 55) { exit($c->error("\nYour database is not up to date. Please update.\nphp ${DIR}/lib/DB/patchDB.php\n")); } $tmux_session = (isset($tmux->tmux_session)) ? $tmux->tmux_session : 0; From 168f111190c81fb5bc007035c198123f9246b6e1 Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 13:17:00 +0200 Subject: [PATCH 02/20] Fixed the _handleErrorResponse. --- .../www/lib/Net_NNTP/NNTP/Protocol/Client.php | 1697 +++++------------ 1 file changed, 527 insertions(+), 1170 deletions(-) diff --git a/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php b/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php index 992227b61..a899370a9 100644 --- a/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php +++ b/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php @@ -69,16 +69,10 @@ // Warn about PHP bugs if (version_compare(PHP_VERSION, '5.2.11') === 0) { - trigger_error('PHP bug #16657 breaks feof() on socket streams! ' - . 'Connection consistency might be compromised!', E_USER_WARNING - ); + trigger_error('PHP bug #16657 breaks feof() on socket streams! Connection consistency might be compromised!', E_USER_WARNING); } -/** - * - */ require_once 'PEAR.php'; -//require_once 'Net/NNTP/Error.php'; require_once 'Responsecode.php'; // {{{ constants @@ -105,7 +99,7 @@ define('NET_NNTP_PROTOCOL_CLIENT_DEFAULT_PORT', '119'); /** * Low level NNTP Client * - * Implements the client part of the NNTP standard acording to: + * Implements the client part of the NNTP standard according to: * - RFC 977, * - RFC 2980, * - RFC 850/1036, and @@ -117,11 +111,11 @@ define('NET_NNTP_PROTOCOL_CLIENT_DEFAULT_PORT', '119'); * class (and should therefore currently not be extended * directly outside of the Net_NNTP package). Therefore its * API is NOT required to be fully stable, for as long as such - * changes doesn't affect the public API of + * changes do not affect the public API of * the Net_NNTP_Client class, which is considered stable. * - * TODO: cmdListActiveTimes() - * cmdDistribPats() + * TODO: cmdListActiveTimes() + * cmdDistribPats() * * @category Net * @package Net_NNTP @@ -139,119 +133,105 @@ class Net_NNTP_Protocol_Client extends PEAR * The socket resource being used to connect to the NNTP server. * * @var resource - * @access private + * @access protected */ - var $_socket = null; + protected $_socket = null; /** - * Contains the last recieved status response code and text + * Contains the last received status response code and text. * * @var array - * @access private + * @access protected */ - var $_currentStatusResponse = null; + protected $_currentStatusResponse = null; /** - * + * Optional logger class to use for debugging. * * @var object * @access private */ - var $_logger = null; + private $_logger = null; - // }}} - // {{{ constructor + /** + * Seconds to wait for the blocking socket to timeout. + * + * @var int + */ + protected $_socketTimeout = 120; /** * Constructor * * @access public */ - function Net_NNTP_Protocol_Client() + public function Net_NNTP_Protocol_Client() { - // -// parent::PEAR('Net_NNTP_Error'); + // Init PEAR. parent::PEAR(); } - // }}} - // {{{ getPackageVersion() - /** - * + * Get current package version. * * @access public */ - function getPackageVersion() + public function getPackageVersion() { return '1.5.0'; } - // }}} - // {{{ getApiVersion() - /** - * + * Get current API version. * * @access public */ - function getApiVersion() + public function getApiVersion() { return '0.9.0'; } - // }}} - // {{{ setLogger() - /** - * + * Set the debug logger instance object. * * @param object $logger * * @access protected */ - function setLogger($logger) + protected function setLogger($logger) { $this->_logger = $logger; } - // }}} - // {{{ setDebug() - /** * @deprecated */ - function setDebug($debug = true) + public function setDebug($debug = true) { - trigger_error('You are using deprecated API v1.0 in ' - . 'Net_NNTP_Protocol_Client: setDebug() ! Debugging in now ' - . 'automatically handled when a logger is given.', E_USER_NOTICE + trigger_error( + 'You are using deprecated API v1.0 in Net_NNTP_Protocol_Client: setDebug() ! Debugging in now automatically handled when a logger is given.', + E_USER_NOTICE ); } - // }}} - // {{{ _sendCommand() - /** - * Send command + * Send a command to usenet. * * Send a command to the server. A carriage return / linefeed - * (CRLF) sequence will be appended to each command string before - * it is sent to the IMAP server. + * (CRLF) sequence will be appended to each command string before it is sent to the IMAP server. * * @param string $cmd The command to launch, ie: "ARTICLE 1004853" * - * @return mixed (int) response code on success or (object) - * pear_error on failure - * @access private + * @return mixed (int) response code on success + * (object) pear_error on failure + * @access protected */ - function _sendCommand($cmd) + protected function _sendCommand($cmd) { // NNTP/RFC977 only allows command up to 512 (-2) chars. - if (!strlen($cmd) > 510) - return $this->throwError( - 'Failed writing to socket! (Command to long - max 510 chars)' - ); + if (strlen($cmd) > 510) { + return$this->throwError('Failed writing to socket! (Command to long - max 510 chars)'); + } /*************************************************************** * Credit: * @@ -262,192 +242,152 @@ class Net_NNTP_Protocol_Client extends PEAR * function with user input, by appending a new line * * character followed by the injection. * *************************************************************** + * Prevent new line (and possible future) characters in the NNTP * commands Net_NNTP does not support pipelined commands. - * Inserting a new line charecter allows sending multiple + * Inserting a new line character allows sending multiple * commands and thereby making the communication between * NET_NNTP and the server out of sync... */ if (preg_match_all('/\r?\n/', $cmd, $matches, PREG_PATTERN_ORDER)) { - foreach ($matches[0] as $key => $match) { - $this->_logger->debug("Illegal character in command: " . - htmlentities(str_replace(array("\r", "\n"), - array("'Carriage Return'", "'New Line'"), $match - ) - ) - ); + if ($this->_logger) { + foreach ($matches[0] as $match) { + $this->_logger->debug( + "Illegal character in command: " . htmlentities(str_replace(array("\r","\n"), + array("'Carriage Return'", "'New Line'"), $match)) + ); + } } return $this->throwError("Illegal character(s) in NNTP command!"); } - // Check if connected + // Check if connected. if (!$this->_isConnected()) { return $this->throwError('Failed to write to socket! (connection lost!)'); } - // Send the command - $R = @fwrite($this->_socket, $cmd . "\r\n"); - if ($R === false) { + // Send the command. + if (@fwrite($this->_socket, $cmd . "\r\n") === false) { return $this->throwError('Failed to write to socket!'); } - // + // Log sent message. if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { $this->_logger->debug('C: ' . $cmd); } - // return $this->_getStatusResponse(); } - // }}} - // {{{ _getStatusResponse() - /** * Get servers status response after a command. * - * @return mixed (int) statuscode on success or - * (object) pear_error on failure + * @return mixed (int) response code on success + * (object) pear_error on failure * @access private */ - function _getStatusResponse() + private function _getStatusResponse() { - // Retrieve a line (terminated by "\r\n") from the server. - // RFC says max is 510, but IETF says "be liberal in what you accept"... + // Retrieve a line (terminated by "\r\n") from the server. RFC says max is 510, but IETF says "be liberal in what you accept"... $response = @fgets($this->_socket, 4096); if ($response === false) { return $this->throwError('Failed to read from socket...!'); } - // + // Log incoming message. if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { $this->_logger->debug('S: ' . rtrim($response, "\r\n")); } - /* Trim the start of the response in case of - * misplased whitespace (should not be needen!!!) - */ + // Trim the start of the response in case of misplaced whitespace (should not be needed). $response = ltrim($response); - $this->_currentStatusResponse = - array((int)substr($response, 0, 3), - (string)rtrim(substr($response, 4)) - ); + // Store the response in an array, 0 => response code, 1 => response message. + $this->_currentStatusResponse = array((int) substr($response, 0, 3), (string) rtrim(substr($response, 4))); - // return $this->_currentStatusResponse[0]; } - // }}} - // {{{ _getTextResponse() - /** * Retrieve textural data * * Get data until a line with only a '.' in it is read and return data. * - * @return mixed (array) text response on success or - * (object) pear_error on failure - * @access private + * @return mixed (array) text response on success + * (object) pear_error on failure + * @access protected */ - function _getTextResponse() + protected function _getTextResponse() { + // Buffer to hold the received lines. $data = array(); - $line = ''; - // - $debug = $this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG); + $debug = ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)); - // Continue until connection is lost + // Continue until connection is lost. while (!feof($this->_socket)) { // Retrieve and append up to 1024 characters from the server. - $recieved = @fgets($this->_socket, 1024); + $line = @fgets($this->_socket, 1024); - if ($recieved === false) { + if ($line === false) { return $this->throwError('Failed to read line from socket.', null); } - $line .= $recieved; - - // Continue if the line is not terminated by CRLF - if (substr($line, -2) != "\r\n" || strlen($line) < 2) { + // Continue if the line is not terminated by CR LF. + if (substr($line, -2) !== "\r\n" || strlen($line) < 2) { continue; } - // Validate recieved line - if (false) { - // Lines should/may not be longer than 998+2 chars (RFC2822 2.3) - if (strlen($line) > 1000) { - if ($this->_logger) { - $this->_logger->notice('Max line length...'); - } - - return $this->throwError('Invalid line recieved!', null); - } - } - - // Remove CRLF from the end of the line + // Remove CR LF from the end of the line. $line = substr($line, 0, -2); - // Check if the line terminates the textresponse - if ($line == '.') { + // Check if the line terminates the text response. + if ($line === '.') { if ($this->_logger) { $this->_logger->debug('T: ' . $line); } - // return all previous lines + // Return all previous lines. return $data; } - // If 1st char is '.' it's doubled (NNTP/RFC977 2.4.1) - if (substr($line, 0, 2) == '..') { + // If 1st char is '.' it's doubled (NNTP/RFC977 2.4.1). + if (substr($line, 0, 2) === '..') { $line = substr($line, 1); } - // if ($debug) { $this->_logger->debug('T: ' . $line); } - // Add the line to the array of lines + // Add the line to the array of lines. $data[] = $line; - - // Reset/empty $line - $line = ''; } if ($this->_logger) { - $this->_logger->warning('Broke out of reception loop! ' - . 'This souldn\'t happen unless connection has been lost?' - ); + $this->_logger->warning('Broke out of reception loop! This souldn\'t happen unless connection has been lost?'); } - // return $this->throwError('End of stream! Connection lost?', null); } - // }}} - // {{{ _sendText() - /** + * Send an article to usenet. * + * @note Data should be in the format specified by RFC850. * * @access private */ - function _sendArticle($article) + private function _sendArticle($article) { - /* data should be in the format specified by RFC850 */ - switch (true) { case is_string($article): - // @fwrite($this->_socket, $article); @fwrite($this->_socket, "\r\n.\r\n"); - // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { foreach (explode("\r\n", $article) as $line) { $this->_logger->debug('D: ' . $line); @@ -472,7 +412,6 @@ class Net_NNTP_Protocol_Client extends PEAR @fwrite($this->_socket, $header); @fwrite($this->_socket, "\r\n"); - // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { foreach (explode("\r\n", $header) as $line) { $this->_logger->debug('D: ' . $line); @@ -491,7 +430,6 @@ class Net_NNTP_Protocol_Client extends PEAR @fwrite($this->_socket, $body); @fwrite($this->_socket, "\r\n.\r\n"); - // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { foreach (explode("\r\n", $body) as $line) { $this->_logger->debug('D: ' . $line); @@ -507,116 +445,63 @@ class Net_NNTP_Protocol_Client extends PEAR return true; } - // }}} - // {{{ _currentStatusResponse() - /** + * Return the last received response message. * - * - * @return string status text + * @return string The response message. * @access private */ - function _currentStatusResponse() + private function _currentStatusResponse() { return $this->_currentStatusResponse[1]; } - // }}} - // {{{ _handleUnexpectedResponse() - - /** - * - * - * @param int $code Status code number - * @param string $text Status text - * - * @return mixed - * @access private - */ - function _handleUnexpectedResponse($code = null, $text = null) - { - if ($code === null) { - $code = $this->_currentStatusResponse[0]; - } - - if ($text === null) { - $text = $this->_currentStatusResponse(); - } - - switch ($code) { - /* 502, 'access restriction or permission denied' - * / service permanently unavailable - */ - case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: - return $this->throwError('Command not permitted / Access' - . ' restriction / Permission denied', $code, $text - ); - break; - default: - return $this->throwError("Unexpected response: '$text'", - $code, $text - ); - } - } - - // }}} - /* Session administration commands */ - // {{{ Connect() - /** * Connect to a NNTP server * - * @param string $host (optional) The address of the - * NNTP-server to connect to, defaults to 'localhost'. - * @param mixed $encryption (optional) - * @param int $port (optional) The port number to connect to, - * defaults to 119. - * @param int $timeout (optional) + * @param string $host (optional) The address of the NNTP-server to connect to, defaults to 'localhost'. + * @param mixed $encryption (optional) Use TLS/SSL on the connection? + * (string) 'tcp' => Use no encryption. + * 'ssl', 'sslv3', 'tls' => Use encryption. + * (null)|(false) Use no encryption. + * @param int $port (optional) The port number to connect to, defaults to 119. + * @param int $timeout (optional) How many seconds to wait before giving up when connecting. + * @param int $socketTimeout (optional) How many seconds to wait before timing out the (blocked) socket. * - * @return mixed (bool) on success (true when posting allowed, - * otherwise false) or (object) pear_error on failure + * @return mixed (bool) On success: True when posting allowed, otherwise false. + * (object) On failure: pear_error * @access protected */ - function connect($host = null, $encryption = null, $port = null, $timeout = 15) + protected function connect($host = null, $encryption = null, $port = null, $timeout = 15, $socketTimeout = 120) { - // - if ($this->_isConnected()) { + if ($this->_isConnected() ) { return $this->throwError('Already connected, disconnect first!', null); } // v1.0.x API if (is_int($encryption)) { - trigger_error('You are using deprecated API v1.0 in ' - . 'Net_NNTP_Protocol_Client: connect() !', E_USER_NOTICE - ); + trigger_error('You are using deprecated API v1.0 in Net_NNTP_Protocol_Client: connect() !', E_USER_NOTICE); $port = $encryption; $encryption = false; } - // if (is_null($host)) { $host = 'localhost'; } - /* Choose transport based on encryption, and if no port is - * given, use default for that encryption - */ + // Choose transport based on encryption, and if no port is given, use default for that encryption. switch ($encryption) { case null: - case 'tcp': - case false: $transport = 'tcp'; $port = is_null($port) ? 119 : $port; break; case 'sslv3': - case 'ssl': - case 'tls': $transport = $encryption; $port = is_null($port) ? 563 : $port; @@ -628,29 +513,40 @@ class Net_NNTP_Protocol_Client extends PEAR return $this->throwError($message); } - // Open Connection - $R = @stream_socket_client($transport . '://' . $host . ':' . $port, $errno, $errstr, $timeout); - if ($R === false) { + // Attempt to connect to usenet. + $socket = @stream_socket_client( + $transport . '://' . $host . ':' . $port, $errorNumber, $errorString, $timeout + ); + + if ($socket === false) { + $message = "Connection to $transport://$host:$port failed."; + if (preg_match('/tls|ssl/', $transport)) { $message .= ' Try disabling SSL/TLS, and/or try a different port.'; } - $message .= ' [ERROR ' . $errno . ': ' . $errstr . ']'; + + $message .= ' [ERROR ' . $errorNumber . ': ' . $errorString . ']'; + if ($this->_logger) { $this->_logger->notice($message); } return $this->throwError($message); } - $this->_socket = $R; - stream_set_timeout($this->_socket, 120); + // Store the socket resource as property. + $this->_socket = $socket; + + $this->_socketTimeout = (is_numeric($socketTimeout) ? $socketTimeout : $this->_socketTimeout); + + // Set the socket timeout. + stream_set_timeout($this->_socket, $this->_socketTimeout); - // if ($this->_logger) { $this->_logger->info("Connection to $transport://$host:$port has been established."); } - // Retrive the server's initial response. + // Retrieve the server's initial response. $response = $this->_getStatusResponse(); if ($this->isError($response)) { return $response; @@ -661,65 +557,30 @@ class Net_NNTP_Protocol_Client extends PEAR case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_ALLOWED: // TODO: Set some variable before return return true; - break; // 201, Posting NOT allowed case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED: - // if ($this->_logger) { $this->_logger->info('Posting not allowed!'); } // TODO: Set some variable before return return false; - break; - - case 400: - return $this->throwError('Server refused connection', - $response, $this->_currentStatusResponse() - ); - break; - - /* 502, 'access restriction or permission denied' - * / service permanently unavailable - */ - case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: - return $this->throwError('Server refused connection', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ disconnect() - - /** - * alias for cmdQuit() - * - * @access protected - */ - function disconnect() - { - return $this->cmdQuit(); - } - - // }}} - // {{{ cmdCapabilities() - /** * Returns servers capabilities * - * @return mixed (array) list of capabilities on success or - * (object) pear_error on failure + * @return mixed (array) list of capabilities on success or + * (object) pear_error on failure * @access protected */ - function cmdCapabilities() + protected function cmdCapabilities() { - // tell the newsserver we want an article $response = $this->_sendCommand('CAPABILITIES'); if ($this->isError($response)) { return $response; @@ -733,26 +594,21 @@ class Net_NNTP_Protocol_Client extends PEAR return $data; } return $data; - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdModeReader() - /** * * - * @return mixed (bool) true when posting allowed, false when - * postind disallowed or (object) pear_error on failure + * @return mixed (bool) true when posting allowed, false when posting disallowed + * (object) pear_error on failure * @access protected */ - function cmdModeReader() + protected function cmdModeReader() { - // tell the newsserver we want an article $response = $this->_sendCommand('MODE READER'); if ($this->isError($response)) { return $response; @@ -763,7 +619,6 @@ class Net_NNTP_Protocol_Client extends PEAR case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_ALLOWED: // TODO: Set some variable before return return true; - break; // 201, RFC2980: 'Hello, you can't post' case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED: @@ -772,46 +627,43 @@ class Net_NNTP_Protocol_Client extends PEAR } // TODO: Set some variable before return return false; - break; - - /* 502, 'access restriction or permission denied' - * / service permanently unavailable - */ - case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: - return $this->throwError('Connection being closed, ' - . 'since service so permanently unavailable', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdQuit() + /** + * Alias for cmdQuit() + * + * @access protected + */ + protected function disconnect() + { + return $this->cmdQuit(); + } /** * Disconnect from the NNTP server * - * @return mixed (bool) true on success or - * (object) pear_error on failure + * @return mixed (bool) true on success + * (object) pear_error on failure * @access protected */ - function cmdQuit() + protected function cmdQuit() { - // Tell the server to close the connection $response = $this->_sendCommand('QUIT'); if ($this->isError($response)) { return $response; } switch ($response) { - case 205: // RFC977: 'closing connection - goodbye!' + // RFC977: 'closing connection - goodbye!' + case NET_NNTP_PROTOCOL_RESPONSECODE_DISCONNECTING_REQUESTED: // If socket is still open, close it. - if ($this->_isConnected()) { - fclose($this->_socket); + $disconnected = true; + if ($this->_isConnected(false)) { + $disconnected = (bool)stream_socket_shutdown($this->_socket, STREAM_SHUT_RDWR); } if ($this->_logger) { @@ -819,28 +671,20 @@ class Net_NNTP_Protocol_Client extends PEAR } $this->_currentStatusResponse = null; $this->_socket = null; - - return true; - break; + return $disconnected; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - - // }}} - - /* */ - - // {{{ cmdStartTLS() - /** + * Request TLS encryption to the news server. * - * - * @return mixed (bool) on success or (object) pear_error on failure + * @return mixed (bool) on success + * (object) pear_error on failure * @access protected */ - function cmdStartTLS() + protected function cmdStartTLS() { $response = $this->_sendCommand('STARTTLS'); if ($this->isError($response)) { @@ -848,75 +692,52 @@ class Net_NNTP_Protocol_Client extends PEAR } switch ($response) { - case 382: // RFC4642: 'continue with TLS negotiation' - $encrypted = stream_socket_enable_crypto($this->_socket, - true, STREAM_CRYPTO_METHOD_TLS_CLIENT - ); + // RFC4642: 'continue with TLS negotiation' + case NET_NNTP_PROTOCOL_RESPONSECODE_TLS_AUTHENTICATION_CONTINUE: + $encrypted = stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); switch (true) { case $encrypted === true: if ($this->_logger) { $this->_logger->info('TLS encryption started.'); } return true; - break; - case $encrypted === true: + case $encrypted === false: if ($this->_logger) { $this->_logger->info('TLS encryption failed.'); } - - return $this->throwError('Could not initiate ' - . 'TLS negotiation', $response, - $this->_currentStatusResponse() - ); - break; + return $this->throwError('Could not initiate TLS negotiation', $response, $this->_currentStatusResponse()); case is_int($encrypted): - return $this->throwError('', $response, - $this->_currentStatusResponse() - ); - break; + return $this->throwError('TLS encryption failed.', $response, $this->_currentStatusResponse()); default: - return $this->throwError('Internal error - ' - . 'unknown response from' - . 'stream_socket_enable_crypto()', - $response, $this->_currentStatusResponse() + return $this->throwError( + 'Internal error - unknown response from stream_socket_enable_crypto()', + $response, + $this->_currentStatusResponse() ); } - break; - - case 580: // RFC4642: 'can not initiate TLS negotiation' - return $this->throwError('', $response, - $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - - /* Article posting and retrieval */ - /* Group and article selection */ - // {{{ cmdGroup() - /** * Selects a news group (issue a GROUP command to the server) * * @param string $newsgroup The newsgroup name * - * @return mixed (array) groupinfo on success or - * (object) pear_error on failure + * @return mixed (array) group info on success + * (object) pear_error on failure * @access protected */ - function cmdGroup($newsgroup) + protected function cmdGroup($newsgroup) { - $response = $this->_sendCommand('GROUP ' . $newsgroup); + $response = $this->_sendCommand('GROUP '.$newsgroup); if ($this->isError($response)) { return $response; } @@ -924,49 +745,35 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 211, RFC977: 'n f l s group selected' case NET_NNTP_PROTOCOL_RESPONSECODE_GROUP_SELECTED: - $response_arr = explode(' ', - trim($this->_currentStatusResponse()) - ); + $response_arr = explode(' ', trim($this->_currentStatusResponse())); if ($this->_logger) { - $this->_logger->info('Group selected: ' - . $response_arr[3] - ); + $this->_logger->info('Group selected: ' . $response_arr[3]); } - return array('group' => $response_arr[3], - 'first' => $response_arr[1], - 'last' => $response_arr[2], - 'count' => $response_arr[0] + return array( + 'group' => $response_arr[3], + 'first' => $response_arr[1], + 'last' => $response_arr[2], + 'count' => $response_arr[0] ); - break; - - // 411, RFC977: 'no such news group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_GROUP: - return $this->throwError('No such news group on server', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdListgroup() - /** + * Gets a group overview. * + * @param string $newsgroup (optional) + * @param mixed $range (optional) * - * @param optional string $newsgroup - * @param optional mixed $range - * - * @return optional mixed (array) on success or - * (object) pear_error on failure + * @return mixed (array) On success + * (object) pear_error On failure * @access protected */ - function cmdListgroup($newsgroup = null, $range = null) + protected function cmdListgroup($newsgroup = null, $range = null) { if (is_null($newsgroup)) { $command = 'LISTGROUP'; @@ -979,7 +786,7 @@ class Net_NNTP_Protocol_Client extends PEAR } $response = $this->_sendCommand($command); - if ($this->isError($response)) { + if ($this->isError($response)){ return $response; } @@ -992,194 +799,110 @@ class Net_NNTP_Protocol_Client extends PEAR return $articles; } - $response_arr = explode(' ', - trim($this->_currentStatusResponse()), 4 - ); + $response_arr = explode(' ', trim($this->_currentStatusResponse()), 4); - /* If server does not return group summary in - * status response, return null'ed array - */ + // If server does not return group summary in status response, return null array. if (!is_numeric($response_arr[0]) || !is_numeric($response_arr[1]) || !is_numeric($response_arr[2]) || empty($response_arr[3]) ) { - return array('group' => null, - 'first' => null, - 'last' => null, - 'count' => null, - 'articles' => $articles + return array( + 'group' => null, + 'first' => null, + 'last' => null, + 'count' => null, + 'articles' => $articles ); } - return array('group' => $response_arr[3], - 'first' => $response_arr[1], - 'last' => $response_arr[2], - 'count' => $response_arr[0], - 'articles' => $articles + return array( + 'group' => $response_arr[3], + 'first' => $response_arr[1], + 'last' => $response_arr[2], + 'count' => $response_arr[0], + 'articles' => $articles ); - break; - - // 412, RFC2980: 'Not currently in newsgroup' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('Not currently in newsgroup', - $response, $this->_currentStatusResponse() - ); - break; - - // RFC2980: 'no permission' - case 502: - return $this->throwError('No permission', $response, - $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdLast() - /** + * Select the previous article in current group. * - * - * @return mixed (array) or (string) or (int) or - * (object) pear_error on failure + * @return mixed (array) or (string) or (int) On success + * (object) pear_error On failure * @access protected */ - function cmdLast() + protected function cmdLast() { - // $response = $this->_sendCommand('LAST'); if ($this->isError($response)) { return $response; } switch ($response) { - /* 223, RFC977: 'n a article retrieved - request text - * separately (n = article number, a = unique article id)' - */ + // 223, RFC977: 'n a article retrieved - request text separately (n = article number, a = unique article id)' case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED: - $response_arr = explode(' ', - trim($this->_currentStatusResponse()) - ); + $response_arr = explode(' ', trim($this->_currentStatusResponse())); if ($this->_logger) { - $this->_logger->info('Selected previous article: ' . - $response_arr[0] . ' - ' . $response_arr[1] - ); + $this->_logger->info('Selected previous article: ' . $response_arr[0] .' - '. $response_arr[1]); } - return array($response_arr[0], (string)$response_arr[1]); - break; - - // 412, RFC977: 'no newsgroup selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No newsgroup has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC977: 'no current article has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No current article has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 422, RFC977: 'no previous article in this group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_PREVIOUS_ARTICLE: - return $this->throwError('No previous article in this group', - $response, $this->_currentStatusResponse() - ); - break; + return array($response_arr[0], (string) $response_arr[1]); default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdNext() - /** + * Select the next article in current group. * - * - * @return mixed (array) or (string) or (int) or - * (object) pear_error on failure + * @return mixed (array) or (string) or (int) On success + * (object) pear_error On failure * @access protected */ - function cmdNext() + protected function cmdNext() { - // $response = $this->_sendCommand('NEXT'); if ($this->isError($response)) { return $response; } switch ($response) { - /* 223, RFC977: 'n a article retrieved - request text - * separately (n = article number, a = unique article id)' - */ + // 223, RFC977: 'n a article retrieved - request text separately (n = article number, a = unique article id)' case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED: $response_arr = explode(' ', - trim($this->_currentStatusResponse()) - ); + trim($this->_currentStatusResponse())); if ($this->_logger) { - $this->_logger->info('Selected previous article: ' . - $response_arr[0] . ' - ' . $response_arr[1] - ); + $this->_logger->info('Selected previous article: ' . $response_arr[0] .' - '. $response_arr[1]); } - return array($response_arr[0], (string)$response_arr[1]); - break; - - // 412, RFC977: 'no newsgroup selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No newsgroup has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC977: 'no current article has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No current article has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 421, RFC977: 'no next article in this group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_NEXT_ARTICLE: - return $this->throwError('No next article in this group', - $response, $this->_currentStatusResponse() - ); - break; + return array($response_arr[0], (string) $response_arr[1]); default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - /* Retrieval of articles and article sections */ - // {{{ cmdArticle() - /** * Get an article from the currently open connection. * - * @param mixed $article Either a message-id or a message-number - * of the article to fetch. If null or '', then use current article. + * @param mixed $article Either a message-id or a message-number of the article to fetch. + * If null or '', then use current article. * - * @return mixed (array) article on success or - * (object) pear_error on failure + * @return mixed (array) article on success + * (object) pear_error on failure * @access protected */ - function cmdArticle($article = null) + protected function cmdArticle($article = null) { if (is_null($article)) { $command = 'ARTICLE'; @@ -1187,16 +910,13 @@ class Net_NNTP_Protocol_Client extends PEAR $command = 'ARTICLE ' . $article; } - // tell the newsserver we want an article $response = $this->_sendCommand($command); if ($this->isError($response)) { return $response; } switch ($response) { - /* 220, RFC977: 'n <a> article retrieved - head and - * body follow (n = article number, <a> = message-id)' - */ + // 220, RFC977: 'n <a> article retrieved - head and body follow (n = article number, <a> = message-id)' case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_FOLLOWS: $data = $this->_getTextResponse(); if ($this->isError($data)) { @@ -1204,62 +924,26 @@ class Net_NNTP_Protocol_Client extends PEAR } if ($this->_logger) { - $this->_logger->info(($article == null ? - 'Fetched current article' : 'Fetched article: ' . - $article) - ); + $this->_logger->info(($article == null ? 'Fetched current article' : 'Fetched article: '. $article)); } return $data; - break; - - // 412, RFC977: 'no newsgroup has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No newsgroup has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC977: 'no current article has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No current article has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 423, RFC977: 'no such article number in this group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: - return $this->throwError('No such article number in this group', - $response, $this->_currentStatusResponse() - ); - break; - - // 430, RFC977: 'no such article found' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: - return $this->throwError('No such article found', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdHead() - /** * Get the headers of an article from the currently open connection. * - * @param mixed $article Either a message-id or a message-number - * of the article to fetch the headers from. If null or '', - * then use current article. + * @param mixed $article Either a message-id or a message-number of the article to fetch the headers from. + * If null or '', then use current article. * - * @return mixed (array) headers on success or - * (object) pear_error on failure + * @return mixed (array) headers on success or + * (object) pear_error on failure * @access protected */ - function cmdHead($article = null) + protected function cmdHead($article = null) { if (is_null($article)) { $command = 'HEAD'; @@ -1267,7 +951,6 @@ class Net_NNTP_Protocol_Client extends PEAR $command = 'HEAD ' . $article; } - // tell the newsserver we want the header of an article $response = $this->_sendCommand($command); if ($this->isError($response)) { return $response; @@ -1282,63 +965,27 @@ class Net_NNTP_Protocol_Client extends PEAR } if ($this->_logger) { - $this->_logger->info(($article == null ? - 'Fetched current article header' : 'Fetched ' - . 'article header for article: ' . $article) - ); + $this->_logger->info(($article == null ? 'Fetched current article header' : 'Fetched article header for article: '.$article)); } return $data; - break; - - // 412, RFC977: 'no newsgroup has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No newsgroup has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC977: 'no current article has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No current article has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 423, RFC977: 'no such article number in this group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: - return $this->throwError('No such article number in this group', - $response, $this->_currentStatusResponse() - ); - break; - - // 430, RFC977: 'no such article found' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: - return $this->throwError('No such article found', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdBody() - /** * Get the body of an article from the currently open connection. * - * @param mixed $article Either a message-id or a message-number of - * the article to fetch the body from. If null or '', - * then use current article. + * @param mixed $article Either a message-id or a message-number of the article to fetch the body from. + * If null or '', then use current article. * - * @return mixed (array) body on success or - * (object) pear_error on failure + * @return mixed (array) body on success + * (object) pear_error on failure * @access protected */ - function cmdBody($article = null) + protected function cmdBody($article = null) { if (is_null($article)) { $command = 'BODY'; @@ -1346,7 +993,6 @@ class Net_NNTP_Protocol_Client extends PEAR $command = 'BODY ' . $article; } - // tell the newsserver we want the body of an article $response = $this->_sendCommand($command); if ($this->isError($response)) { return $response; @@ -1361,61 +1007,26 @@ class Net_NNTP_Protocol_Client extends PEAR } if ($this->_logger) { - $this->_logger->info(($article == null ? - 'Fetched current article body' : 'Fetched ' - . 'article body for article: ' . $article) - ); + $this->_logger->info(($article == null ? 'Fetched current article body' : 'Fetched article body for article: '.$article)); } return $data; - break; - - // 412, RFC977: 'no newsgroup has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No newsgroup has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC977: 'no current article has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No current article has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 423, RFC977: 'no such article number in this group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: - return $this->throwError('No such article number in this group', - $response, $this->_currentStatusResponse() - ); - break; - - // 430, RFC977: 'no such article found' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: - return $this->throwError('No such article found', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdStat - /** - * + * Selects an article by article message-number. * * @param mixed $article * - * @return mixed (array) or (string) or (int) or - * (object) pear_error on failure + * @return mixed (array) or (string) or (int) on success + * (object) pear_error on failure * @access protected */ - function cmdStat($article = null) + protected function cmdStat($article = null) { if (is_null($article)) { $command = 'STAT'; @@ -1423,7 +1034,6 @@ class Net_NNTP_Protocol_Client extends PEAR $command = 'STAT ' . $article; } - // tell the newsserver we want an article $response = $this->_sendCommand($command); if ($this->isError($response)) { return $response; @@ -1436,67 +1046,30 @@ class Net_NNTP_Protocol_Client extends PEAR */ case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED: $response_arr = explode(' ', - trim($this->_currentStatusResponse()) - ); + trim($this->_currentStatusResponse())); if ($this->_logger) { - $this->_logger->info('Selected article: ' . - $response_arr[0] . ' - ' . $response_arr[1] - ); + $this->_logger->info('Selected article: ' . $response_arr[0].' - '.$response_arr[1]); } - return array($response_arr[0], (string)$response_arr[1]); - break; - - /* 412, RFC977: 'no newsgroup has been selected' - * (actually not documented, but copied from the - * ARTICLE command) - */ - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No newsgroup has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - /* 423, RFC977: 'no such article number in this group' - * (actually not documented, but copied from the - * ARTICLE command) - */ - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: - return $this->throwError('No such article number in this group', - $response, $this->_currentStatusResponse() - ); - break; - - /* 430, RFC977: 'no such article found' (actually not - * documented, but copied from the ARTICLE command) - */ - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: - return $this->throwError('No such article found', - $response, $this->_currentStatusResponse() - ); - break; + return array($response_arr[0], (string) $response_arr[1]); default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - /* Article posting */ - // {{{ cmdPost() - /** * Post an article to a newsgroup. * - * @return mixed (bool) true on success or (object) pear_error on failure + * @return mixed (bool) true on success + * (object) pear_error on failure * @access protected */ - function cmdPost() + protected function cmdPost() { - // tell the newsserver we want to post an article $response = $this->_sendCommand('POST'); if ($this->isError($response)) { return $response; @@ -1506,40 +1079,29 @@ class Net_NNTP_Protocol_Client extends PEAR // 340, RFC977: 'send article to be posted. End with <CR-LF>.<CR-LF>' case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_SEND: return true; - break; - // 440, RFC977: 'posting not allowed' - case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_PROHIBITED: - return $this->throwError('Posting not allowed', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdPost2() - /** * Post an article to a newsgroup. * + * @note Should be presented in the format specified by RFC850. + * * @param mixed $article (string/array) * - * @return mixed (bool) true on success or - * (object) pear_error on failure + * @return mixed (bool) true on success + * (object) pear_error on failure * @access protected */ - function cmdPost2($article) + protected function cmdPost2($article) { - /* should be presented in the format specified by RFC850 */ - - // $this->_sendArticle($article); - // Retrive server's response. + // Retrieve server's response. $response = $this->_getStatusResponse(); if ($this->isError($response)) { return $response; @@ -1549,199 +1111,145 @@ class Net_NNTP_Protocol_Client extends PEAR // 240, RFC977: 'article posted ok' case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_SUCCESS: return true; - break; - - // 441, RFC977: 'posting failed' - case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_FAILURE: - return $this->throwError('Posting failed', $response, - $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdIhave() - /** + * Tell the news server we want to upload an article, the server will check if it has the message-id first. * + * @param string $id Message-ID. * - * @param string $id - * - * @return mixed (bool) true on success or - * (object) pear_error on failure + * @return mixed (bool) true on success + * (object) pear_error on failure * @access protected */ - function cmdIhave($id) + protected function cmdIhave($id) { - // tell the newsserver we want to post an article $response = $this->_sendCommand('IHAVE ' . $id); if ($this->isError($response)) { return $response; } switch ($response) { - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SEND: // 335 + // 335, RFC997: 'Send article to be transferred' + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SEND: return true; - break; - - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_UNWANTED: // 435 - return $this->throwError('Article not wanted', - $response, $this->_currentStatusResponse() - ); - break; - - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_FAILURE: // 436 - return $this->throwError - ('Transfer not possible; try again later', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdIhave2() - /** + * Tell the news server we have an article to upload, the server will check if it has it first. * + * @note Should be presented in the format specified by RFC850. * * @param mixed $article (string/array) * - * @return mixed (bool) true on success or (object) pear_error on failure + * @return mixed (bool) true on success + * (object) pear_error on failure * @access protected */ - function cmdIhave2($article) + protected function cmdIhave2($article) { - /* should be presented in the format specified by RFC850 */ - - // $this->_sendArticle($article); - // Retrive server's response. + // Retrieve server's response. $response = $this->_getStatusResponse(); if ($this->isError($response)) { return $response; } switch ($response) { - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SUCCESS: // 235 + // 235, RFC977: 'Article transferred OK' + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SUCCESS: return true; - break; - - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_FAILURE: // 436 - return $this->throwError - ('Transfer not possible; try again later', - $response, $this->_currentStatusResponse() - ); - break; - - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_REJECTED: // 437 - return $this->throwError - ('Transfer rejected; do not retry', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - /* Information commands */ - // {{{ cmdDate() - /** - * Get the date from the newsserver format of returned date + * Get the date from the news server. * - * @return mixed (string) 'YYYYMMDDhhmmss' / (int) timestamp on - * success or (object) pear_error on failure + * @return mixed (string) or (int) 'YYYYMMDDhhmmss', timestamp on success + * (object) pear_error on failure * @access protected */ - function cmdDate() + protected function cmdDate() { $response = $this->_sendCommand('DATE'); - if ($this->isError($response)) { + if ($this->isError($response)){ return $response; } switch ($response) { - // 111, RFC2980: 'YYYYMMDDhhmmss' + // 111, RFC2980: '(string of numbers representing the date and time)' case NET_NNTP_PROTOCOL_RESPONSECODE_SERVER_DATE: return $this->_currentStatusResponse(); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdHelp() /** - * Returns the server's help text + * Returns the server's help text. * * @return mixed (array) help text on success or - * (object) pear_error on failure + * (object) pear_error on failure * @access protected */ - function cmdHelp() + protected function cmdHelp() { - // tell the newsserver we want an article $response = $this->_sendCommand('HELP'); if ($this->isError($response)) { return $response; } switch ($response) { - case NET_NNTP_PROTOCOL_RESPONSECODE_HELP_FOLLOWS: // 100 + // 100, RFC977: 'Help text follows' + case NET_NNTP_PROTOCOL_RESPONSECODE_HELP_FOLLOWS: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; } return $data; - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdNewgroups() - /** * Fetches a list of all newsgroups created since a specified date. * - * @param int $time Last time you checked for groups (timestamp). - * @param optional string $distributions (deprecaded in rfc draft) + * @param int $time Last time you checked for groups (timestamp). + * @param string $distributions (optional) (deprecaded in rfc draft) * - * @return mixed (array) nested array with informations about - * existing newsgroups on success or (object) pear_error on failure + * @return mixed (array) nested array with informations about existing newsgroups on success + * (object) pear_error on failure * @access protected */ - function cmdNewgroups($time, $distributions = null) + protected function cmdNewgroups($time, $distributions = null) { $date = gmdate('ymd His', $time); if (is_null($distributions)) { $command = 'NEWGROUPS ' . $date . ' GMT'; } else { - $command = 'NEWGROUPS ' . $date . ' GMT <' . - $distributions . '>'; + $command = 'NEWGROUPS ' . $date . ' GMT <' . $distributions . '>'; } $response = $this->_sendCommand($command); - if ($this->isError($response)) { + if ($this->isError($response)){ return $response; } @@ -1754,13 +1262,14 @@ class Net_NNTP_Protocol_Client extends PEAR } $groups = array(); - foreach ($data as $line) { + foreach($data as $line) { $arr = explode(' ', trim($line)); - $group = array('group' => $arr[0], - 'last' => $arr[1], - 'first' => $arr[2], - 'posting' => $arr[3] + $group = array( + 'group' => $arr[0], + 'last' => $arr[1], + 'first' => $arr[2], + 'posting' => $arr[3] ); $groups[$group['group']] = $group; @@ -1768,24 +1277,21 @@ class Net_NNTP_Protocol_Client extends PEAR return $groups; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdNewnews() - /** * * - * @param timestamp $time - * @param mixed $newsgroups (string or array of strings) + * @param int $time Unix timestamp. + * @param mixed $newsgroups (string or array of strings) * @param mixed $distribution (string or array of strings) * * @return mixed * @access protected */ - function cmdNewnews($time, $newsgroups, $distribution = null) + protected function cmdNewnews($time, $newsgroups, $distribution = null) { $date = gmdate('ymd His', $time); @@ -1796,18 +1302,18 @@ class Net_NNTP_Protocol_Client extends PEAR if (is_null($distribution)) { $command = 'NEWNEWS ' . $newsgroups . ' ' . $date . ' GMT'; } else { + if (is_array($distribution)) { $distribution = implode(',', $distribution); } - $command = 'NEWNEWS ' . $newsgroups . ' ' . $date . ' GMT <' - . $distribution . '>'; + $command = 'NEWNEWS ' . $newsgroups . ' ' . $date . ' GMT <' . $distribution . '>'; } - // TODO: the lenght of the request string may not exceed 510 chars + // TODO: the length of the request string may not exceed 510 chars. $response = $this->_sendCommand($command); - if ($this->isError($response)) { + if ($this->isError($response)){ return $response; } @@ -1815,34 +1321,29 @@ class Net_NNTP_Protocol_Client extends PEAR // 230, RFC977: 'list of new articles by message-id follows' case NET_NNTP_PROTOCOL_RESPONSECODE_NEW_ARTICLES_FOLLOW: $messages = array(); - foreach ($this->_getTextResponse() as $line) { + foreach($this->_getTextResponse() as $line) { $messages[] = $line; } return $messages; - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - /* The LIST commands */ - // {{{ cmdList() - /** - * Fetches a list of all avaible newsgroups + * Fetches a list of all available newsgroups. * - * @return mixed (array) nested array with informations about - * existing newsgroups on success or (object) pear_error on failure + * @return mixed (array) nested array with informations about existing newsgroups on success + * (object) pear_error on failure * @access protected */ - function cmdList() + protected function cmdList() { $response = $this->_sendCommand('LIST'); - if ($this->isError($response)) { + if ($this->isError($response)){ return $response; } @@ -1855,47 +1356,44 @@ class Net_NNTP_Protocol_Client extends PEAR } $groups = array(); - foreach ($data as $line) { + foreach($data as $line) { $arr = explode(' ', trim($line)); - $group = array('group' => $arr[0], - 'last' => $arr[1], - 'first' => $arr[2], - 'posting' => $arr[3] + $group = array( + 'group' => $arr[0], + 'last' => $arr[1], + 'first' => $arr[2], + 'posting' => $arr[3] ); $groups[$group['group']] = $group; } return $groups; - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdListActive() - /** - * Fetches a list of all avaible newsgroups + * Fetches a list of all available newsgroups. * - * @param string $wildmat + * @param string $wildMat * - * @return mixed (array) nested array with informations about - * existing newsgroups on success or (object) pear_error on failure + * @return mixed (array) nested array with informations about existing newsgroups on success + * (object) pear_error on failure * @access protected */ - function cmdListActive($wildmat = null) + protected function cmdListActive($wildMat = null) { - if (is_null($wildmat)) { + if (is_null($wildMat)) { $command = 'LIST ACTIVE'; } else { - $command = 'LIST ACTIVE ' . $wildmat; + $command = 'LIST ACTIVE ' . $wildMat; } $response = $this->_sendCommand($command); - if ($this->isError($response)) { + if ($this->isError($response)){ return $response; } @@ -1908,13 +1406,14 @@ class Net_NNTP_Protocol_Client extends PEAR } $groups = array(); - foreach ($data as $line) { + foreach($data as $line) { $arr = explode(' ', trim($line)); - $group = array('group' => $arr[0], - 'last' => $arr[1], - 'first' => $arr[2], - 'posting' => $arr[3] + $group = array( + 'group' => $arr[0], + 'last' => $arr[1], + 'first' => $arr[2], + 'posting' => $arr[3] ); $groups[$group['group']] = $group; @@ -1925,36 +1424,31 @@ class Net_NNTP_Protocol_Client extends PEAR } return $groups; - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdListNewsgroups() - /** * Fetches a list of (all) avaible newsgroup descriptions. * - * @param string $wildmat Wildmat of the groups, that is to be - * listed, defaults to null; + * @param string $wildMat Wildmat of the groups, that is to be listed, defaults to null; * - * @return mixed (array) nested array with description of existing - * newsgroups on success or (object) pear_error on failure + * @return mixed (array) nested array with description of existing newsgroups on success + * (object) pear_error on failure * @access protected */ - function cmdListNewsgroups($wildmat = null) + protected function cmdListNewsgroups($wildMat = null) { - if (is_null($wildmat)) { + if (is_null($wildMat)) { $command = 'LIST NEWSGROUPS'; } else { - $command = 'LIST NEWSGROUPS ' . $wildmat; + $command = 'LIST NEWSGROUPS ' . $wildMat; } $response = $this->_sendCommand($command); - if ($this->isError($response)) { + if ($this->isError($response)){ return $response; } @@ -1968,18 +1462,11 @@ class Net_NNTP_Protocol_Client extends PEAR $groups = array(); - foreach ($data as $line) { - if (preg_match("/^(\S+)\s+(.*)$/", ltrim($line), - $matches - ) - ) { - $groups[$matches[1]] = (string)$matches[2]; - } else { - if ($this->_logger) { - $this->_logger->warning - ("Recieved non-standard line: '$line'" - ); - } + foreach($data as $line) { + if (preg_match('/^(\S+)\s+(.*)$/', ltrim($line), $matches)) { + $groups[$matches[1]] = (string) $matches[2]; + } else if ($this->_logger) { + $this->_logger->warning("Recieved non-standard line: '$line'"); } } @@ -1988,40 +1475,26 @@ class Net_NNTP_Protocol_Client extends PEAR } return $groups; - break; - - // RFC2980: 'program error, function not performed' - case 503: - return $this->throwError - ('Internal server error, function not performed', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - /* Article field access commands */ - // {{{ cmdOver() - /** * Fetch message header from message number $first until $last * - * The format of the returned array is: - * $messages[][header_name] + * @info The format of the returned array is: $messages[][header_name] * - * @param optional string $range articles to fetch + * @param string $range (optional) articles to fetch * - * @return mixed (array) nested array of message and there headers - * on success or (object) pear_error on failure + * @return mixed (array) nested array of message and there headers on success + * (object) pear_error on failure * @access protected */ - function cmdOver($range = null) + protected function cmdOver($range = null) { if (is_null($range)) { $command = 'OVER'; @@ -2030,7 +1503,7 @@ class Net_NNTP_Protocol_Client extends PEAR } $response = $this->_sendCommand($command); - if ($this->isError($response)) { + if ($this->isError($response)){ return $response; } @@ -2047,69 +1520,32 @@ class Net_NNTP_Protocol_Client extends PEAR } if ($this->_logger) { - $this->_logger->info('Fetched overview ' . - ($range == null ? - 'for current article' : 'for range: ' . $range) - ); + $this->_logger->info('Fetched overview ' . ($range == null ? 'for current article' : 'for range: ' . $range)); } return $data; - break; - - // 412, RFC2980: 'No news group current selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No news group current selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC2980: 'No article(s) selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No article(s) selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 423:, Draft27: 'No articles in that range' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: - return $this->throwError('No articles in that range', - $response, $this->_currentStatusResponse() - ); - break; - - // RFC2980: 'no permission' - case 502: - return $this->throwError('No permission', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdXOver() - /** * Fetch message header from message number $first until $last * - * The format of the returned array is: - * $messages[message_id][header_name] + * @info The format of the returned array is: $messages[message_id][header_name] * - * @param optional string $range articles to fetch + * @param string $range (optional) articles to fetch * - * @return mixed (array) nested array of message and there headers - * on success or (object) pear_error on failure + * @return mixed (array) nested array of message and there headers on success + * (object) pear_error on failure * @access protected */ - function cmdXOver($range = null) + protected function cmdXOver($range = null) { - // deprecated API (the code _is_ still in alpha state) + // Deprecated API (the code _is_ still in alpha state). if (func_num_args() > 1) { - die('The second parameter in cmdXOver() has been ' - . 'deprecated! Use x-y instead...'); + exit('The second parameter in cmdXOver() has been deprecated! Use x-y instead...'); } if (is_null($range)) { @@ -2119,7 +1555,7 @@ class Net_NNTP_Protocol_Client extends PEAR } $response = $this->_sendCommand($command); - if ($this->isError($response)) { + if ($this->isError($response)){ return $response; } @@ -2136,56 +1572,27 @@ class Net_NNTP_Protocol_Client extends PEAR } if ($this->_logger) { - $this->_logger->info('Fetched overview ' . - ($range == null ? - 'for current article' : 'for range: ' . $range) - ); + $this->_logger->info('Fetched overview ' . ($range == null ? 'for current article' : 'for range: ' . $range)); } return $data; - break; - - // 412, RFC2980: 'No news group current selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No news group current selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC2980: 'No article(s) selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No article(s) selected', - $response, $this->_currentStatusResponse() - ); - break; - - // RFC2980: 'no permission' - case 502: - return $this->throwError('No permission', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdListOverviewFmt() - /** - * Returns a list of avaible headers which are send from newsserver - * to client for every news message + * Returns a list of available headers which are sent from tge news server to the client for every news message. * * @return mixed (array) of header names on success or - * (object) pear_error on failure + * (object) pear_error on failure * @access protected */ - function cmdListOverviewFmt() + protected function cmdListOverviewFmt() { $response = $this->_sendCommand('LIST OVERVIEW.FMT'); - if ($this->isError($response)) { + if ($this->isError($response)){ return $response; } @@ -2201,7 +1608,7 @@ class Net_NNTP_Protocol_Client extends PEAR foreach ($data as $line) { - // Check if postfixed by ':full' (case-insensitive) + // Check if post fixed by ':full' (case-insensitive) if (0 == strcasecmp(substr($line, -5, 5), ':full')) { // ':full' is _not_ included in tag, but value set to true $format[substr($line, 0, -5)] = true; @@ -2215,38 +1622,26 @@ class Net_NNTP_Protocol_Client extends PEAR $this->_logger->info('Fetched overview format'); } return $format; - break; - - // RFC2980: 'program error, function not performed' - case 503: - return $this->throwError - ('Internal server error, function not performed', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdXHdr() - /** * * * The format of the returned array is: * $messages[message_id] * - * @param optional string $field - * @param optional string $range articles to fetch + * @param string $field (optional) + * @param string $range (optional) articles to fetch * - * @return mixed (array) nested array of message and there header - * on success or (object) pear_error on failure + * @return mixed (array) nested array of message and there header on success + * (object) pear_error on failure * @access protected */ - function cmdXHdr($field, $range = null) + protected function cmdXHdr($field, $range = null) { if (is_null($range)) { $command = 'XHDR ' . $field; @@ -2255,84 +1650,51 @@ class Net_NNTP_Protocol_Client extends PEAR } $response = $this->_sendCommand($command); - if ($this->isError($response)) { + if ($this->isError($response)){ return $response; } switch ($response) { // 221, RFC2980: 'Header follows' - case 221: + case NET_NNTP_PROTOCOL_RESPONSECODE_HEAD_FOLLOWS: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; } $return = array(); - foreach ($data as $line) { + foreach($data as $line) { $line = explode(' ', trim($line), 2); $return[$line[0]] = $line[1]; } return $return; - break; - - // 412, RFC2980: 'No news group current selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No news group current selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC2980: 'No current article selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No current article selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 430, RFC2980: 'No such article' - case 430: - return $this->throwError('No such article', - $response, $this->_currentStatusResponse() - ); - break; - - // RFC2980: 'no permission' - case 502: - return $this->throwError('No permission', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdXGTitle() - /** - * Fetches a list of (all) avaible newsgroup descriptions. - * Depresated as of RFC2980. + * Fetches a list of (all) available newsgroup descriptions. + * Deprecated as of RFC2980. * - * @param string $wildmat Wildmat of the groups, that is - * to be listed, defaults to '*'; + * @param string $wildMat Wildmat of the groups, that is to be listed, defaults to '*'; * - * @return mixed (array) nested array with description of - * existing newsgroups on success or (object) pear_error on failure + * @return mixed (array) nested array with description of existing newsgroups on success + * (object) pear_error on failure * @access protected */ - function cmdXGTitle($wildmat = '*') + protected function cmdXGTitle($wildMat = '*') { - $response = $this->_sendCommand('XGTITLE ' . $wildmat); - if ($this->isError($response)) { + $response = $this->_sendCommand('XGTITLE '.$wildMat); + if ($this->isError($response)){ return $response; } switch ($response) { // RFC2980: 'list of groups and descriptions follows' - case 282: + case NET_NNTP_PROTOCOL_RESPONSECODE_XGTITLE_GROUPS_FOLLOW: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -2340,44 +1702,32 @@ class Net_NNTP_Protocol_Client extends PEAR $groups = array(); - foreach ($data as $line) { - preg_match("/^(.*?)\s(.*?$)/", trim($line), $matches); - $groups[$matches[1]] = (string)$matches[2]; + foreach($data as $line) { + preg_match('/^(.*?)\s(.*?$)/', trim($line), $matches); + $groups[$matches[1]] = (string) $matches[2]; } return $groups; - break; - - case 481: // RFC2980: 'Groups and descriptions unavailable' - return $this->throwError - ('Groups and descriptions unavailable', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdXROver() - /** * Fetch message references from message number $first to $last * - * @param optional string $range articles to fetch + * @param string $range (optional) articles to fetch * - * @return mixed (array) assoc. array of message references on - * success or (object) pear_error on failure + * @return mixed (array) assoc. array of message references on success + * (object) pear_error on failure * @access protected */ - function cmdXROver($range = null) + protected function cmdXROver($range = null) { // Warn about deprecated API (the code _is_ still in alpha state) - if (func_num_args() > 1) { - die('The second parameter in cmdXROver() has been ' - . 'deprecated! Use x-y instead...'); + if (func_num_args() > 1 ) { + exit('The second parameter in cmdXROver() has been deprecated! Use x-y instead...'); } if (is_null($range)) { @@ -2387,7 +1737,7 @@ class Net_NNTP_Protocol_Client extends PEAR } $response = $this->_sendCommand($command); - if ($this->isError($response)) { + if ($this->isError($response)){ return $response; } @@ -2400,63 +1750,36 @@ class Net_NNTP_Protocol_Client extends PEAR } $return = array(); - foreach ($data as $line) { + foreach($data as $line) { $line = explode(' ', trim($line), 2); $return[$line[0]] = $line[1]; } return $return; - break; - - // 412, RFC2980: 'No news group current selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No news group current selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC2980: 'No article(s) selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No article(s) selected', - $response, $this->_currentStatusResponse() - ); - break; - - // RFC2980: 'no permission' - case 502: - return $this->throwError('No permission', $response, - $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdXPat() - /** * * * @param string $field * @param string $range - * @param mixed $wildmat + * @param mixed $wildMat * - * @return mixed (array) nested array of message and there - * headers on success or (object) pear_error on failure + * @return mixed (array) nested array of message and there headers on success + * (object) pear_error on failure * @access protected */ - function cmdXPat($field, $range, $wildmat) + protected function cmdXPat($field, $range, $wildMat) { - if (is_array($wildmat)) { - $wildmat = implode(' ', $wildmat); + if (is_array($wildMat)) { + $wildMat = implode(' ', $wildMat); } - $response = $this->_sendCommand('XPAT ' . $field . ' ' . - $range . ' ' . $wildmat - ); - if ($this->isError($response)) { + $response = $this->_sendCommand('XPAT ' . $field . ' ' . $range . ' ' . $wildMat); + if ($this->isError($response)){ return $response; } @@ -2468,34 +1791,18 @@ class Net_NNTP_Protocol_Client extends PEAR } $return = array(); - foreach ($data as $line) { + foreach($data as $line) { $line = explode(' ', trim($line), 2); $return[$line[0]] = $line[1]; } return $return; - break; - - case 430: // 430, RFC2980: 'No such article' - return $this->throwError('No current article selected', - $response, $this->_currentStatusResponse() - ); - break; - - case 502: // RFC2980: 'no permission' - return $this->throwError('No permission', $response, - $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdAuthinfo() - /** * Authenticate using 'original' method * @@ -2503,13 +1810,13 @@ class Net_NNTP_Protocol_Client extends PEAR * @param string $pass The password to authenticate with. * * @return mixed (bool) true on success or - * (object) pear_error on failure + * (object) pear_error on failure + * * @access protected */ - function cmdAuthinfo($user, $pass) - { + protected function cmdAuthinfo($user, $pass) { // Send the username - $response = $this->_sendCommand('AUTHINFO user ' . $user); + $response = $this->_sendCommand('AUTHINFO user '.$user); if ($this->isError($response)) { return $response; } @@ -2517,7 +1824,7 @@ class Net_NNTP_Protocol_Client extends PEAR // Send the password, if the server asks if (($response == 381) && ($pass !== null)) { // Send the password - $response = $this->_sendCommand('AUTHINFO pass ' . $pass); + $response = $this->_sendCommand('AUTHINFO pass '.$pass); if ($this->isError($response)) { return $response; } @@ -2532,39 +1839,12 @@ class Net_NNTP_Protocol_Client extends PEAR // TODO: Set some variable before return return true; - break; - - case 381: // RFC2980: 'More authentication information required' - return $this->throwError('Authentication uncompleted', - $response, $this->_currentStatusResponse() - ); - break; - - case 482: // RFC2980: 'Authentication rejected' - return $this->throwError('Authentication rejected', - $response, $this->_currentStatusResponse() - ); - break; - - case 502: // RFC2980: 'No permission' - return $this->throwError('Authentication rejected', - $response, $this->_currentStatusResponse() - ); - break; - - /*case 500: - case 501: - return $this->throwError('Authentication failed', $response, $this->_currentStatusResponse()); - break;*/ default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdAuthinfoSimple() - /** * Authenticate using 'simple' method * @@ -2574,60 +1854,137 @@ class Net_NNTP_Protocol_Client extends PEAR * @return mixed (bool) true on success or (object) pear_error on failure * @access protected */ - function cmdAuthinfoSimple($user, $pass) - { - return $this->throwError - ("The auth mode: 'simple' is has not been implemented yet", - null - ); + protected function cmdAuthinfoSimple($user, $pass) { + return $this->throwError("The auth mode: 'simple' is has not been implemented yet", null); } - // }}} - // {{{ cmdAuthinfoGeneric() - /** * Authenticate using 'generic' method * * @param string $user The username to authenticate as. * @param string $pass The password to authenticate with. * - * @return mixed (bool) true on success or (object) pear_error on failure + * @return mixed (bool) true on success + * (object) pear_error on failure * @access protected */ - function cmdAuthinfoGeneric($user, $pass) - { - return $this->throwError - ("The auth mode: 'generic' is has not been implemented yet", - null - ); + protected function cmdAuthinfoGeneric($user, $pass) { + return $this->throwError("The auth mode: 'generic' is has not been implemented yet", null); } - // }}} - // {{{ _isConnected() - /** * Test whether we are connected or not. * + * @param bool $feof Check for the end of file pointer. + * * @return bool true or false * @access protected */ - function _isConnected() + protected function _isConnected($feof = true) { - return (is_resource($this->_socket) && (!feof($this->_socket))); + return (is_resource($this->_socket) && ($feof ? !feof($this->_socket) : true)); } - // }}} + /** + * Verify NNTP error code and return PEAR error. + * + * @param int $response NET_NNTP Response code + * + * @return object PEAR error + * @access protected + */ + protected function _handleErrorResponse(&$response) + { + switch ($response) { -} + // 381, RFC2980: 'More authentication information required' + case NET_NNTP_PROTOCOL_RESPONSECODE_AUTHENTICATION_CONTINUE: + return $this->throwError('More authentication information required', $response, $this->_currentStatusResponse()); -// }}} + // 400, RFC977: 'Service discontinued' + case NET_NNTP_PROTOCOL_RESPONSECODE_DISCONNECTING_FORCED: + return $this->throwError('Server refused connection', $response, $this->_currentStatusResponse()); -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * c-hanging-comment-ender-p: nil - * End: - */ + // 411, RFC977: 'no such news group' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_GROUP: + return $this->throwError('No such news group on server', $response, $this->_currentStatusResponse()); -?> \ No newline at end of file + // 412, RFC2980: 'No news group current selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: + return $this->throwError('No news group current selected', $response, $this->_currentStatusResponse()); + + // 420, RFC2980: 'Current article number is invalid' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: + return $this->throwError('Current article number is invalid', $response, $this->_currentStatusResponse()); + + // 421, RFC977: 'no next article in this group' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_NEXT_ARTICLE: + return $this->throwError('No next article in this group', $response, $this->_currentStatusResponse()); + + // 422, RFC977: 'no previous article in this group' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_PREVIOUS_ARTICLE: + return $this->throwError('No previous article in this group', $response, $this->_currentStatusResponse()); + + // 423, RFC977: 'No such article number in this group' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: + return $this->throwError('No such article number in this group', $response, $this->_currentStatusResponse()); + + // 430, RFC977: 'No such article found' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: + return $this->throwError('No such article found', $response, $this->_currentStatusResponse()); + + // 435, RFC977: 'Article not wanted' + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_UNWANTED: + return $this->throwError('Article not wanted', $response, $this->_currentStatusResponse()); + + // 436, RFC977: 'Transfer failed - try again later' + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_FAILURE: + return $this->throwError('Transfer failed - try again later', $response, $this->_currentStatusResponse()); + + // 437, RFC977: 'Article rejected - do not try again' + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_REJECTED: + return $this->throwError('Article rejected - do not try again', $response, $this->_currentStatusResponse()); + + // 440, RFC977: 'posting not allowed' + case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_PROHIBITED: + return $this->throwError('Posting not allowed', $response, $this->_currentStatusResponse()); + + // 441, RFC977: 'posting failed' + case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_FAILURE: + return $this->throwError('Posting failed', $response, $this->_currentStatusResponse()); + + // 481, RFC2980: 'Groups and descriptions unavailable' + case NET_NNTP_PROTOCOL_RESPONSECODE_XGTITLE_GROUPS_UNAVAILABLE: + return $this->throwError('Groups and descriptions unavailable', $response, $this->_currentStatusResponse()); + + // 482, RFC2980: 'Authentication rejected' + case NET_NNTP_PROTOCOL_RESPONSECODE_AUTHENTICATION_REJECTED: + return $this->throwError('Authentication rejected', $response, $this->_currentStatusResponse()); + + // 500, RFC977: 'Command not recognized' + case NET_NNTP_PROTOCOL_RESPONSECODE_UNKNOWN_COMMAND: + return $this->throwError('Command not recognized', $response, $this->_currentStatusResponse()); + + // 501, RFC977: 'Command syntax error' + case NET_NNTP_PROTOCOL_RESPONSECODE_SYNTAX_ERROR: + return $this->throwError('Command syntax error', $response, $this->_currentStatusResponse()); + + // 502, RFC2980: 'No permission' + case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: + return $this->throwError('No permission', $response, $this->_currentStatusResponse()); + + // 503, RFC2980: 'Program fault - command not performed' + case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_SUPPORTED: + return $this->throwError('Internal server error, function not performed', $response, $this->_currentStatusResponse()); + + // RFC4642: 'Can not initiate TLS negotiation' + case NET_NNTP_PROTOCOL_RESPONSECODE_TLS_FAILED_NEGOTIATION: + return $this->throwError('Can not initiate TLS negotiation', $response, $this->_currentStatusResponse()); + + default: + $text = $this->_currentStatusResponse(); + return $this->throwError("Unexpected response: '$text'", $response, $text); + } + } + +} \ No newline at end of file From d03b21c9b63ad7edf72c508db83b193c7f3ec491 Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 13:20:31 +0200 Subject: [PATCH 03/20] Small cosmetic change. --- .../www/templates/nntmux/views/frontend/profileedit.tpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/copy_this/www/templates/nntmux/views/frontend/profileedit.tpl b/lib/copy_this/www/templates/nntmux/views/frontend/profileedit.tpl index e2f836a3a..a2361234b 100644 --- a/lib/copy_this/www/templates/nntmux/views/frontend/profileedit.tpl +++ b/lib/copy_this/www/templates/nntmux/views/frontend/profileedit.tpl @@ -64,7 +64,7 @@ <th>View Game Page:</th> <td> <input id="gameview" name="gameview" value="1" type="checkbox" {if $user.gameview=="1"}checked="checked"{/if}> - <span class="help-block">Browse game covers. Only shows games with known lookup info.</span> + <div class="hint">Browse game covers. Only shows games with known lookup info.</div> </td> </tr> <tr> From 2b144c60f3fa5ab2c7f7b1fb853a27d1b3dbaae7 Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 13:23:10 +0200 Subject: [PATCH 04/20] Fix for notices. --- .../www/lib/Net_NNTP/NNTP/Protocol/Client.php | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php b/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php index a899370a9..da4ec9ca4 100644 --- a/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php +++ b/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php @@ -1898,87 +1898,87 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 381, RFC2980: 'More authentication information required' - case NET_NNTP_PROTOCOL_RESPONSECODE_AUTHENTICATION_CONTINUE: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_AUTHENTICATION_CONTINUE': return $this->throwError('More authentication information required', $response, $this->_currentStatusResponse()); // 400, RFC977: 'Service discontinued' - case NET_NNTP_PROTOCOL_RESPONSECODE_DISCONNECTING_FORCED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_DISCONNECTING_FORCED': return $this->throwError('Server refused connection', $response, $this->_currentStatusResponse()); // 411, RFC977: 'no such news group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_GROUP: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_GROUP': return $this->throwError('No such news group on server', $response, $this->_currentStatusResponse()); // 412, RFC2980: 'No news group current selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED': return $this->throwError('No news group current selected', $response, $this->_currentStatusResponse()); // 420, RFC2980: 'Current article number is invalid' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED': return $this->throwError('Current article number is invalid', $response, $this->_currentStatusResponse()); // 421, RFC977: 'no next article in this group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_NEXT_ARTICLE: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_NO_NEXT_ARTICLE': return $this->throwError('No next article in this group', $response, $this->_currentStatusResponse()); // 422, RFC977: 'no previous article in this group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_PREVIOUS_ARTICLE: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_NO_PREVIOUS_ARTICLE': return $this->throwError('No previous article in this group', $response, $this->_currentStatusResponse()); // 423, RFC977: 'No such article number in this group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER': return $this->throwError('No such article number in this group', $response, $this->_currentStatusResponse()); // 430, RFC977: 'No such article found' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID': return $this->throwError('No such article found', $response, $this->_currentStatusResponse()); // 435, RFC977: 'Article not wanted' - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_UNWANTED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_UNWANTED': return $this->throwError('Article not wanted', $response, $this->_currentStatusResponse()); // 436, RFC977: 'Transfer failed - try again later' - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_FAILURE: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_FAILURE': return $this->throwError('Transfer failed - try again later', $response, $this->_currentStatusResponse()); // 437, RFC977: 'Article rejected - do not try again' - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_REJECTED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_REJECTED': return $this->throwError('Article rejected - do not try again', $response, $this->_currentStatusResponse()); // 440, RFC977: 'posting not allowed' - case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_PROHIBITED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_PROHIBITED': return $this->throwError('Posting not allowed', $response, $this->_currentStatusResponse()); // 441, RFC977: 'posting failed' - case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_FAILURE: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_FAILURE': return $this->throwError('Posting failed', $response, $this->_currentStatusResponse()); // 481, RFC2980: 'Groups and descriptions unavailable' - case NET_NNTP_PROTOCOL_RESPONSECODE_XGTITLE_GROUPS_UNAVAILABLE: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_XGTITLE_GROUPS_UNAVAILABLE': return $this->throwError('Groups and descriptions unavailable', $response, $this->_currentStatusResponse()); // 482, RFC2980: 'Authentication rejected' - case NET_NNTP_PROTOCOL_RESPONSECODE_AUTHENTICATION_REJECTED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_AUTHENTICATION_REJECTED': return $this->throwError('Authentication rejected', $response, $this->_currentStatusResponse()); // 500, RFC977: 'Command not recognized' - case NET_NNTP_PROTOCOL_RESPONSECODE_UNKNOWN_COMMAND: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_UNKNOWN_COMMAND': return $this->throwError('Command not recognized', $response, $this->_currentStatusResponse()); // 501, RFC977: 'Command syntax error' - case NET_NNTP_PROTOCOL_RESPONSECODE_SYNTAX_ERROR: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_SYNTAX_ERROR': return $this->throwError('Command syntax error', $response, $this->_currentStatusResponse()); // 502, RFC2980: 'No permission' - case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED': return $this->throwError('No permission', $response, $this->_currentStatusResponse()); // 503, RFC2980: 'Program fault - command not performed' - case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_SUPPORTED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_NOT_SUPPORTED': return $this->throwError('Internal server error, function not performed', $response, $this->_currentStatusResponse()); // RFC4642: 'Can not initiate TLS negotiation' - case NET_NNTP_PROTOCOL_RESPONSECODE_TLS_FAILED_NEGOTIATION: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_TLS_FAILED_NEGOTIATION': return $this->throwError('Can not initiate TLS negotiation', $response, $this->_currentStatusResponse()); default: From fef7eb8652b976323efae32f9e2fd8a359c12033 Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 13:30:18 +0200 Subject: [PATCH 05/20] Another fix --- lib/copy_this/www/pages/games.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/copy_this/www/pages/games.php b/lib/copy_this/www/pages/games.php index 32f8954dd..2e7b68739 100644 --- a/lib/copy_this/www/pages/games.php +++ b/lib/copy_this/www/pages/games.php @@ -34,7 +34,7 @@ $ordering = $games->getgamesOrdering(); $orderby = isset($_REQUEST["ob"]) && in_array($_REQUEST['ob'], $ordering) ? $_REQUEST["ob"] : ''; $results = $games2 = array(); -$results = $games->getgamesRange($catarray, $offset, ITEMS_PER_COVER_PAGE, $orderby, -1, $page->userdata["categoryexclusions"]); +$results = $games->getgamesRange($catarray, $offset, 'ITEMS_PER_PAGE_SMALL', $orderby, -1, $page->userdata["categoryexclusions"]); $maxwords = 50; foreach ($results as $result) { if (!empty($result['review'])) { From 8ecf41655deb81fbe4dd15ddaf38b98fbe99cfb3 Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 13:34:09 +0200 Subject: [PATCH 06/20] Another fix --- lib/copy_this/www/pages/games.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/copy_this/www/pages/games.php b/lib/copy_this/www/pages/games.php index 2e7b68739..6ad903650 100644 --- a/lib/copy_this/www/pages/games.php +++ b/lib/copy_this/www/pages/games.php @@ -55,7 +55,7 @@ $page->smarty->assign('title', $title); $genres = $gen->getGenres(Genres::GAME_TYPE, true); $tmpgnr = array(); foreach ($genres as $gn) { - $tmpgnr[$gn['id']] = $gn['title']; + $tmpgnr[$gn['ID']] = $gn['title']; } $genre = (isset($_REQUEST['genre']) && array_key_exists($_REQUEST['genre'], $tmpgnr)) ? $_REQUEST['genre'] : ''; $page->smarty->assign('genres', $genres); @@ -65,7 +65,7 @@ $browseby_link = '&title=' . $title . '&platform=' . $platform; $page->smarty->assign('pagertotalitems', $browsecount); $page->smarty->assign('pageroffset', $offset); -$page->smarty->assign('pageritemsperpage', ITEMS_PER_COVER_PAGE); +$page->smarty->assign('pageritemsperpage', 'ITEMS_PER_PAGE_SMALL'); $page->smarty->assign('pagerquerybase', WWW_TOP . "/games?t=" . $category . $browseby_link . "&ob=" . $orderby . "&offset="); $page->smarty->assign('pagerquerysuffix', "#results"); From 93a191d2532162c5859422b0a9722502f6c1427d Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 13:45:15 +0200 Subject: [PATCH 07/20] Another fix --- .../www/lib/Net_NNTP/NNTP/Protocol/Client.php | 64 +++++++++---------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php b/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php index da4ec9ca4..8435f48f1 100644 --- a/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php +++ b/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php @@ -554,12 +554,12 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 200, Posting allowed - case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_ALLOWED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_ALLOWED': // TODO: Set some variable before return return true; // 201, Posting NOT allowed - case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED': if ($this->_logger) { $this->_logger->info('Posting not allowed!'); } @@ -588,7 +588,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 101, Draft: 'Capability list follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_CAPABILITIES_FOLLOW: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_CAPABILITIES_FOLLOW': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -616,12 +616,12 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 200, RFC2980: 'Hello, you can post' - case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_ALLOWED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_ALLOWED': // TODO: Set some variable before return return true; // 201, RFC2980: 'Hello, you can't post' - case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED': if ($this->_logger) { $this->_logger->info('Posting not allowed!'); } @@ -659,7 +659,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // RFC977: 'closing connection - goodbye!' - case NET_NNTP_PROTOCOL_RESPONSECODE_DISCONNECTING_REQUESTED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_DISCONNECTING_REQUESTED': // If socket is still open, close it. $disconnected = true; if ($this->_isConnected(false)) { @@ -693,7 +693,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // RFC4642: 'continue with TLS negotiation' - case NET_NNTP_PROTOCOL_RESPONSECODE_TLS_AUTHENTICATION_CONTINUE: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_TLS_AUTHENTICATION_CONTINUE': $encrypted = stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); switch (true) { case $encrypted === true: @@ -744,7 +744,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 211, RFC977: 'n f l s group selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_GROUP_SELECTED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_GROUP_SELECTED': $response_arr = explode(' ', trim($this->_currentStatusResponse())); if ($this->_logger) { @@ -792,7 +792,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 211, RFC2980: 'list of article numbers follow' - case NET_NNTP_PROTOCOL_RESPONSECODE_GROUP_SELECTED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_GROUP_SELECTED': $articles = $this->_getTextResponse(); if ($this->isError($articles)) { @@ -845,7 +845,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 223, RFC977: 'n a article retrieved - request text separately (n = article number, a = unique article id)' - case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED': $response_arr = explode(' ', trim($this->_currentStatusResponse())); if ($this->_logger) { @@ -875,7 +875,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 223, RFC977: 'n a article retrieved - request text separately (n = article number, a = unique article id)' - case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED': $response_arr = explode(' ', trim($this->_currentStatusResponse())); @@ -917,7 +917,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 220, RFC977: 'n <a> article retrieved - head and body follow (n = article number, <a> = message-id)' - case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_FOLLOWS: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_FOLLOWS': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -958,7 +958,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 221, RFC977: 'n <a> article retrieved - head follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_HEAD_FOLLOWS: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_HEAD_FOLLOWS': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1000,7 +1000,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 222, RFC977: 'n <a> article retrieved - body follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_BODY_FOLLOWS: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_BODY_FOLLOWS': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1044,7 +1044,7 @@ class Net_NNTP_Protocol_Client extends PEAR * separately' (actually not documented, but copied * from the ARTICLE command) */ - case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED': $response_arr = explode(' ', trim($this->_currentStatusResponse())); @@ -1077,7 +1077,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 340, RFC977: 'send article to be posted. End with <CR-LF>.<CR-LF>' - case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_SEND: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_SEND': return true; default: @@ -1109,7 +1109,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 240, RFC977: 'article posted ok' - case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_SUCCESS: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_SUCCESS': return true; default: @@ -1135,7 +1135,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 335, RFC997: 'Send article to be transferred' - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SEND: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SEND': return true; default: @@ -1166,7 +1166,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 235, RFC977: 'Article transferred OK' - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SUCCESS: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SUCCESS': return true; default: @@ -1192,7 +1192,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 111, RFC2980: '(string of numbers representing the date and time)' - case NET_NNTP_PROTOCOL_RESPONSECODE_SERVER_DATE: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_SERVER_DATE': return $this->_currentStatusResponse(); default: @@ -1216,7 +1216,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 100, RFC977: 'Help text follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_HELP_FOLLOWS: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_HELP_FOLLOWS': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1255,7 +1255,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 231, REF977: 'list of new newsgroups follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_NEW_GROUPS_FOLLOW: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_NEW_GROUPS_FOLLOW': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1319,7 +1319,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 230, RFC977: 'list of new articles by message-id follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_NEW_ARTICLES_FOLLOW: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_NEW_ARTICLES_FOLLOW': $messages = array(); foreach($this->_getTextResponse() as $line) { $messages[] = $line; @@ -1349,7 +1349,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 215, RFC977: 'list of newsgroups follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1399,7 +1399,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 215, RFC977: 'list of newsgroups follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1454,7 +1454,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 215, RFC2980: 'information follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1509,7 +1509,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 224, RFC2980: 'Overview information follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1561,7 +1561,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 224, RFC2980: 'Overview information follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1598,7 +1598,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 215, RFC2980: 'information follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1656,7 +1656,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 221, RFC2980: 'Header follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_HEAD_FOLLOWS: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_HEAD_FOLLOWS': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1694,7 +1694,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // RFC2980: 'list of groups and descriptions follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_XGTITLE_GROUPS_FOLLOW: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_XGTITLE_GROUPS_FOLLOW': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1743,7 +1743,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 224, RFC2980: 'Overview information follows' - case NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS: + case 'NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS': $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; From a9033fcdb4fb00dd99e7f565ae887b52bc665415 Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 13:49:46 +0200 Subject: [PATCH 08/20] Edited genres.php --- lib/copy_this/www/lib/genres.php | 58 ++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 lib/copy_this/www/lib/genres.php diff --git a/lib/copy_this/www/lib/genres.php b/lib/copy_this/www/lib/genres.php new file mode 100644 index 000000000..6c6b89b96 --- /dev/null +++ b/lib/copy_this/www/lib/genres.php @@ -0,0 +1,58 @@ +<?php +require_once(WWW_DIR."/lib/framework/db.php"); +require_once(WWW_DIR."/lib/category.php"); + +/** + * This class handles data access for genre data. + */ +class Genres +{ + const CONSOLE_TYPE = Category::CAT_PARENT_GAME; + const MUSIC_TYPE = Category::CAT_PARENT_MUSIC; + const BOOK_TYPE = Category::CAT_BOOK_EBOOK; + const GAME_TYPE = Category::CAT_PARENT_PC; + + /** + * Get genre rows, filter by type/active. + */ + public function getGenres($type='', $activeonly=false, $usecache=false) + { + $db = new DB(); + + if (!empty($type)) + $typesql = sprintf(" and genres.type = %d", $type); + else + $typesql = ''; + + if ($activeonly) + { + $sql = sprintf("SELECT genres.* FROM genres INNER JOIN (SELECT DISTINCT genreID FROM musicinfo) X ON X.genreID = genres.ID %s + UNION + SELECT genres.* FROM genres INNER JOIN (SELECT DISTINCT genreID FROM consoleinfo) X ON X.genreID = genres.ID %s + ORDER BY title", $typesql, $typesql); + } + else + $sql = sprintf("select genres.* from genres where 1 %s order by title", $typesql); + + return $db->query($sql, $usecache); + } + + /** + * Add new genre. + */ + public function getOrAddGenreKey($genreName, &$genreassoc) + { + if (in_array(strtolower($genreName), $genreassoc)) + { + $genreKey = array_search(strtolower($genreName), $genreassoc); + } + else + { + $db = new DB(); + $genreKey = $db->queryInsert(sprintf("INSERT INTO genres (`title`, `type`) VALUES (%s, %d)", $db->escapeString($genreName), Genres::MUSIC_TYPE)); + $genreassoc[$genreKey] = strtolower($genreName); + } + + return $genreKey; + } +} \ No newline at end of file From 22fa938484ed0ac8cde9d41bcd3cd593de23dfc9 Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 14:06:45 +0200 Subject: [PATCH 09/20] Small fix --- lib/copy_this/www/pages/games.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/copy_this/www/pages/games.php b/lib/copy_this/www/pages/games.php index 6ad903650..6394026dc 100644 --- a/lib/copy_this/www/pages/games.php +++ b/lib/copy_this/www/pages/games.php @@ -34,7 +34,7 @@ $ordering = $games->getgamesOrdering(); $orderby = isset($_REQUEST["ob"]) && in_array($_REQUEST['ob'], $ordering) ? $_REQUEST["ob"] : ''; $results = $games2 = array(); -$results = $games->getgamesRange($catarray, $offset, 'ITEMS_PER_PAGE_SMALL', $orderby, -1, $page->userdata["categoryexclusions"]); +$results = $games->getgamesRange($catarray, $offset, ITEMS_PER_PAGE_SMALL, $orderby, -1, $page->userdata["categoryexclusions"]); $maxwords = 50; foreach ($results as $result) { if (!empty($result['review'])) { From 284a08386a53af072236a907be08ee33b117e4e8 Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 14:08:06 +0200 Subject: [PATCH 10/20] Another small fix --- lib/copy_this/www/pages/games.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/copy_this/www/pages/games.php b/lib/copy_this/www/pages/games.php index 6394026dc..81149c7b6 100644 --- a/lib/copy_this/www/pages/games.php +++ b/lib/copy_this/www/pages/games.php @@ -65,7 +65,7 @@ $browseby_link = '&title=' . $title . '&platform=' . $platform; $page->smarty->assign('pagertotalitems', $browsecount); $page->smarty->assign('pageroffset', $offset); -$page->smarty->assign('pageritemsperpage', 'ITEMS_PER_PAGE_SMALL'); +$page->smarty->assign('pageritemsperpage', ITEMS_PER_PAGE_SMALL); $page->smarty->assign('pagerquerybase', WWW_TOP . "/games?t=" . $category . $browseby_link . "&ob=" . $orderby . "&offset="); $page->smarty->assign('pagerquerysuffix', "#results"); From 11597f9620ec5cb55364c4d976cdbee62afd648a Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 14:13:44 +0200 Subject: [PATCH 11/20] Another small fix --- lib/getGames.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/getGames.php b/lib/getGames.php index 39fa714ba..08d617eed 100644 --- a/lib/getGames.php +++ b/lib/getGames.php @@ -10,7 +10,7 @@ $pdo = new DB(); $c = new ColorCLI(); $res = $pdo->query( - sprintf("SELECT searchname FROM releases WHERE gamesinfo_id IS NULL AND categoryID = 4050 ORDER BY id DESC LIMIT 100") + sprintf("SELECT searchname FROM releases WHERE gamesinfo_id IS NULL AND categoryID = 4050 ORDER BY ID DESC LIMIT 100") ); $total = count($res); if ($total > 0) { From 879e06dc140cb5da39e452df5e350640bdfe3567 Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 14:43:58 +0200 Subject: [PATCH 12/20] Add new game processing to work and pc count. --- bin/monitor.php | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bin/monitor.php b/bin/monitor.php index 543aaf0c0..d4d7c6f27 100644 --- a/bin/monitor.php +++ b/bin/monitor.php @@ -8,7 +8,7 @@ require_once(dirname(__FILE__) . "/../lib/showsleep.php"); require_once(dirname(__FILE__) . "/../lib/functions.php"); -$version = "0.4r2010"; +$version = "0.4r2011"; $db = new DB(); $functions = new Functions(); @@ -49,10 +49,10 @@ $proc = "SELECT ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID BETWEEN 2000 AND 2999 AND imdbID IS NULL ) AS movies, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID BETWEEN 3000 AND 3999 AND musicinfoID IS NULL) AS audio, ( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status), category c WHERE c.ID = r.categoryID AND c.parentID = 6000 AND r.passwordstatus = -1 AND r.haspreview = -1 AND c.disablepreview = 0) AS xxx, -( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status) INNER JOIN category c on c.ID = r.categoryID WHERE (r.passwordstatus = -1) OR (r.haspreview = -1 and c.disablepreview = 0)) AS pc, +( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status) INNER JOIN category c on c.ID = r.categoryID WHERE (r.passwordstatus = -1) OR (r.haspreview = -1 and c.disablepreview = 0) OR (r.categoryID = 4050 AND r.gamesinfo_id IS NULL))) AS pc, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID BETWEEN 5000 AND 5999 AND rageID = -1) AS tv, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID = 7020 AND bookinfoID IS NULL ) AS book, -( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status), category c WHERE c.ID = r.categoryID AND r.passwordstatus = -1 AND r.haspreview = -1 AND c.disablepreview = 0) AS work, +( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status), category c WHERE c.ID = r.categoryID AND r.passwordstatus = -1 AND r.haspreview = -1 AND c.disablepreview = 0) OR (r.categoryID = 4050 AND r.gamesinfo_id IS NULL))) AS work, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status)) AS releases, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE releasenfoID = 0 AND nfostatus BETWEEN -6 AND -1) AS nforemains, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE nfostatus = 1 AND releasenfoID = 1) AS nfo, @@ -1661,8 +1661,7 @@ while ($i > 0) { if (($maxload >= get_load()) && ($post_amazon == 1) && ($console_releases_proc > 0)) { $color = get_color($colors_start, $colors_end, $colors_exc); $log = writelog($panes2[5]); - shell_exec("tmux respawnp -t${tmux_session}:2.5 'echo \"\033[38;5;\"$color\"m\" && cd $_bin && $_php postprocess_new.php console 2>&1 $log; \ - $_php postprocess_new.php games 2>&1 $log; $_sleep $post_timer_amazon && echo \" \033[1;0;33m\"' 2>&1 1> /dev/null"); + shell_exec("tmux respawnp -t${tmux_session}:2.5 'echo \"\033[38;5;\"$color\"m\" && cd $_bin && $_php postprocess_new.php console 2>&1 $log && $_php postprocess_new.php games 2>&1 $log && $_sleep $post_timer_amazon && echo \" \033[1;0;33m\"' 2>&1 1> /dev/null"); } else if (($maxload >= get_load()) && ($post_amazon == 1) && ($console_releases_proc == 0)) { $color = get_color($colors_start, $colors_end, $colors_exc); shell_exec("tmux respawnp -t${tmux_session}:2.5 'echo \"\033[38;5;\"$color\"m\n$panes2[5] has been disabled/terminated by No Games to process\"'"); From f0220adb892c3cde944d6d7714f9fbded594973b Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 14:49:32 +0200 Subject: [PATCH 13/20] Add gameview to headermenu --- .../nntmux/views/frontend/headermenu.tpl | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/copy_this/www/templates/nntmux/views/frontend/headermenu.tpl b/lib/copy_this/www/templates/nntmux/views/frontend/headermenu.tpl index 7ae0eb403..f8f3281c3 100644 --- a/lib/copy_this/www/templates/nntmux/views/frontend/headermenu.tpl +++ b/lib/copy_this/www/templates/nntmux/views/frontend/headermenu.tpl @@ -1,4 +1,4 @@ -<div id="menucontainer"> +<div id="menucontainer"> <div id="menulink"> <ul> {foreach from=$parentcatlist item=parentcat} @@ -30,6 +30,20 @@ {/foreach} </ul> </li> + {elseif ($parentcat.ID == 4000 && $userdata.gameview=="1")} + <li><a title="Browse {$parentcat.title}" href="{$smarty.const.WWW_TOP}/games">{$parentcat.title}</a> + <ul> + {foreach from=$parentcat.subcatlist item=subcat} + {if $subcat.ID == 4050} + <li><a title="Browse {$subcat.title}" + href="{$smarty.const.WWW_TOP}/games">{$subcat.title}</a></li> + {else} + <li><a title="Browse {$subcat.title}" + href="{$smarty.const.WWW_TOP}/browse?t={$subcat.ID}">{$subcat.title}</a></li> + {/if} + {/foreach} + </ul> + </li> {else} <li><a title="Browse {$parentcat.title}" href="{$smarty.const.WWW_TOP}/browse?t={$parentcat.ID}">{$parentcat.title}</a> <ul> @@ -51,7 +65,7 @@ </li> </ul> </div> - + <div id="menusearchlink"> <form id="headsearch_form" action="{$smarty.const.WWW_TOP}/search/" method="get"> @@ -69,7 +83,9 @@ </select> <label style="display:none;" for="headsearch">Search Text</label> - <input id="headsearch" name="search" value="{if $header_menu_search == ""}Enter keywords{else}{$header_menu_search|escape:"htmlall"}{/if}" style="width:85px;" type="text" tabindex="1" /> + <input id="headsearch" name="search" + value="{if $header_menu_search == ""}Enter keywords{else}{$header_menu_search|escape:"htmlall"}{/if}" + style="width:85px;" type="text" tabindex="1"/> </form> </div> From 37efca807d68e19adc13fc7c1671950dec79917f Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 14:51:52 +0200 Subject: [PATCH 14/20] Fix for monitor. --- bin/monitor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/monitor.php b/bin/monitor.php index d4d7c6f27..e53e0d428 100644 --- a/bin/monitor.php +++ b/bin/monitor.php @@ -49,10 +49,10 @@ $proc = "SELECT ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID BETWEEN 2000 AND 2999 AND imdbID IS NULL ) AS movies, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID BETWEEN 3000 AND 3999 AND musicinfoID IS NULL) AS audio, ( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status), category c WHERE c.ID = r.categoryID AND c.parentID = 6000 AND r.passwordstatus = -1 AND r.haspreview = -1 AND c.disablepreview = 0) AS xxx, -( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status) INNER JOIN category c on c.ID = r.categoryID WHERE (r.passwordstatus = -1) OR (r.haspreview = -1 and c.disablepreview = 0) OR (r.categoryID = 4050 AND r.gamesinfo_id IS NULL))) AS pc, +( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status) INNER JOIN category c on c.ID = r.categoryID WHERE (r.passwordstatus = -1) OR (r.haspreview = -1 and c.disablepreview = 0) OR (r.categoryID = 4050 AND r.gamesinfo_id IS NULL)) AS pc, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID BETWEEN 5000 AND 5999 AND rageID = -1) AS tv, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID = 7020 AND bookinfoID IS NULL ) AS book, -( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status), category c WHERE c.ID = r.categoryID AND r.passwordstatus = -1 AND r.haspreview = -1 AND c.disablepreview = 0) OR (r.categoryID = 4050 AND r.gamesinfo_id IS NULL))) AS work, +( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status), category c WHERE c.ID = r.categoryID AND r.passwordstatus = -1 AND r.haspreview = -1 AND c.disablepreview = 0) OR (r.categoryID = 4050 AND r.gamesinfo_id IS NULL)) AS work, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status)) AS releases, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE releasenfoID = 0 AND nfostatus BETWEEN -6 AND -1) AS nforemains, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE nfostatus = 1 AND releasenfoID = 1) AS nfo, From 3775b66d8721299bcf0c29cacde9ccef9b6b6c61 Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 14:55:03 +0200 Subject: [PATCH 15/20] Another try --- bin/monitor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/monitor.php b/bin/monitor.php index e53e0d428..52ee16387 100644 --- a/bin/monitor.php +++ b/bin/monitor.php @@ -49,10 +49,10 @@ $proc = "SELECT ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID BETWEEN 2000 AND 2999 AND imdbID IS NULL ) AS movies, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID BETWEEN 3000 AND 3999 AND musicinfoID IS NULL) AS audio, ( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status), category c WHERE c.ID = r.categoryID AND c.parentID = 6000 AND r.passwordstatus = -1 AND r.haspreview = -1 AND c.disablepreview = 0) AS xxx, -( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status) INNER JOIN category c on c.ID = r.categoryID WHERE (r.passwordstatus = -1) OR (r.haspreview = -1 and c.disablepreview = 0) OR (r.categoryID = 4050 AND r.gamesinfo_id IS NULL)) AS pc, +( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status) INNER JOIN category c on c.ID = r.categoryID WHERE (r.passwordstatus = -1) OR (r.haspreview = -1 and c.disablepreview = 0) OR (r.categoryID = 4050 AND r.gamesinfo_id IS NULL) AS pc, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID BETWEEN 5000 AND 5999 AND rageID = -1) AS tv, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID = 7020 AND bookinfoID IS NULL ) AS book, -( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status), category c WHERE c.ID = r.categoryID AND r.passwordstatus = -1 AND r.haspreview = -1 AND c.disablepreview = 0) OR (r.categoryID = 4050 AND r.gamesinfo_id IS NULL)) AS work, +( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status), category c WHERE c.ID = r.categoryID AND r.passwordstatus = -1 AND r.haspreview = -1 AND c.disablepreview = 0) OR (r.categoryID = 4050 AND r.gamesinfo_id IS NULL) AS work, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status)) AS releases, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE releasenfoID = 0 AND nfostatus BETWEEN -6 AND -1) AS nforemains, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE nfostatus = 1 AND releasenfoID = 1) AS nfo, From bd10e27e7033385f9c020c53939a70ac73449631 Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 15:02:03 +0200 Subject: [PATCH 16/20] Definite fix, i hope --- bin/monitor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/monitor.php b/bin/monitor.php index 52ee16387..9010c3888 100644 --- a/bin/monitor.php +++ b/bin/monitor.php @@ -49,10 +49,10 @@ $proc = "SELECT ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID BETWEEN 2000 AND 2999 AND imdbID IS NULL ) AS movies, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID BETWEEN 3000 AND 3999 AND musicinfoID IS NULL) AS audio, ( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status), category c WHERE c.ID = r.categoryID AND c.parentID = 6000 AND r.passwordstatus = -1 AND r.haspreview = -1 AND c.disablepreview = 0) AS xxx, -( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status) INNER JOIN category c on c.ID = r.categoryID WHERE (r.passwordstatus = -1) OR (r.haspreview = -1 and c.disablepreview = 0) OR (r.categoryID = 4050 AND r.gamesinfo_id IS NULL) AS pc, +( SELECT COUNT(*) FROM releases r INNER JOIN category c ON c.ID = r.categoryID WHERE r.nzbstatus = 1 AND ((r.categoryID BETWEEN 4000 AND 4999 AND r.passwordstatus BETWEEN -6 AND -1 AND r.haspreview = -1 AND c.disablepreview = 0) OR (r.categoryID = 4050 AND r.gamesinfo_id IS NULL))) AS pc, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID BETWEEN 5000 AND 5999 AND rageID = -1) AS tv, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE categoryID = 7020 AND bookinfoID IS NULL ) AS book, -( SELECT COUNT(*) FROM releases r USE INDEX(ix_releases_status), category c WHERE c.ID = r.categoryID AND r.passwordstatus = -1 AND r.haspreview = -1 AND c.disablepreview = 0) OR (r.categoryID = 4050 AND r.gamesinfo_id IS NULL) AS work, +( SELECT COUNT(*) FROM releases r INNER JOIN category c ON c.ID = r.categoryID WHERE r.nzbstatus = 1 AND ((r.passwordstatus BETWEEN -6 AND -1 AND r.haspreview = -1 AND c.disablepreview = 0) OR (r.categoryID = 4050 AND r.gamesinfo_id IS NULL))) AS work, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status)) AS releases, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE releasenfoID = 0 AND nfostatus BETWEEN -6 AND -1) AS nforemains, ( SELECT COUNT(*) FROM releases USE INDEX(ix_releases_status) WHERE nfostatus = 1 AND releasenfoID = 1) AS nfo, From 65f6550b7770b0b61282ab660da2963c2804f37d Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 15:18:38 +0200 Subject: [PATCH 17/20] revert the change to client.php for testing --- .../www/lib/Net_NNTP/NNTP/Protocol/Client.php | 1686 ++++++++++++----- 1 file changed, 1164 insertions(+), 522 deletions(-) diff --git a/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php b/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php index 8435f48f1..0a8fe8cb8 100644 --- a/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php +++ b/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php @@ -69,10 +69,16 @@ // Warn about PHP bugs if (version_compare(PHP_VERSION, '5.2.11') === 0) { - trigger_error('PHP bug #16657 breaks feof() on socket streams! Connection consistency might be compromised!', E_USER_WARNING); + trigger_error('PHP bug #16657 breaks feof() on socket streams! ' + . 'Connection consistency might be compromised!', E_USER_WARNING + ); } +/** + * + */ require_once 'PEAR.php'; +//require_once 'Net/NNTP/Error.php'; require_once 'Responsecode.php'; // {{{ constants @@ -99,7 +105,7 @@ define('NET_NNTP_PROTOCOL_CLIENT_DEFAULT_PORT', '119'); /** * Low level NNTP Client * - * Implements the client part of the NNTP standard according to: + * Implements the client part of the NNTP standard acording to: * - RFC 977, * - RFC 2980, * - RFC 850/1036, and @@ -111,11 +117,11 @@ define('NET_NNTP_PROTOCOL_CLIENT_DEFAULT_PORT', '119'); * class (and should therefore currently not be extended * directly outside of the Net_NNTP package). Therefore its * API is NOT required to be fully stable, for as long as such - * changes do not affect the public API of + * changes doesn't affect the public API of * the Net_NNTP_Client class, which is considered stable. * - * TODO: cmdListActiveTimes() - * cmdDistribPats() + * TODO: cmdListActiveTimes() + * cmdDistribPats() * * @category Net * @package Net_NNTP @@ -133,105 +139,119 @@ class Net_NNTP_Protocol_Client extends PEAR * The socket resource being used to connect to the NNTP server. * * @var resource - * @access protected + * @access private */ - protected $_socket = null; + var $_socket = null; /** - * Contains the last received status response code and text. + * Contains the last recieved status response code and text * * @var array - * @access protected + * @access private */ - protected $_currentStatusResponse = null; + var $_currentStatusResponse = null; /** - * Optional logger class to use for debugging. + * * * @var object * @access private */ - private $_logger = null; + var $_logger = null; - /** - * Seconds to wait for the blocking socket to timeout. - * - * @var int - */ - protected $_socketTimeout = 120; + // }}} + // {{{ constructor /** * Constructor * * @access public */ - public function Net_NNTP_Protocol_Client() + function Net_NNTP_Protocol_Client() { - // Init PEAR. + // +// parent::PEAR('Net_NNTP_Error'); parent::PEAR(); } + // }}} + // {{{ getPackageVersion() + /** - * Get current package version. + * * * @access public */ - public function getPackageVersion() + function getPackageVersion() { return '1.5.0'; } + // }}} + // {{{ getApiVersion() + /** - * Get current API version. + * * * @access public */ - public function getApiVersion() + function getApiVersion() { return '0.9.0'; } + // }}} + // {{{ setLogger() + /** - * Set the debug logger instance object. + * * * @param object $logger * * @access protected */ - protected function setLogger($logger) + function setLogger($logger) { $this->_logger = $logger; } + // }}} + // {{{ setDebug() + /** * @deprecated */ - public function setDebug($debug = true) + function setDebug($debug = true) { - trigger_error( - 'You are using deprecated API v1.0 in Net_NNTP_Protocol_Client: setDebug() ! Debugging in now automatically handled when a logger is given.', - E_USER_NOTICE + trigger_error('You are using deprecated API v1.0 in ' + . 'Net_NNTP_Protocol_Client: setDebug() ! Debugging in now ' + . 'automatically handled when a logger is given.', E_USER_NOTICE ); } + // }}} + // {{{ _sendCommand() + /** - * Send a command to usenet. + * Send command * * Send a command to the server. A carriage return / linefeed - * (CRLF) sequence will be appended to each command string before it is sent to the IMAP server. + * (CRLF) sequence will be appended to each command string before + * it is sent to the IMAP server. * * @param string $cmd The command to launch, ie: "ARTICLE 1004853" * - * @return mixed (int) response code on success - * (object) pear_error on failure - * @access protected + * @return mixed (int) response code on success or (object) + * pear_error on failure + * @access private */ - protected function _sendCommand($cmd) + function _sendCommand($cmd) { // NNTP/RFC977 only allows command up to 512 (-2) chars. - if (strlen($cmd) > 510) { - return$this->throwError('Failed writing to socket! (Command to long - max 510 chars)'); - } + if (!strlen($cmd) > 510) + return $this->throwError( + 'Failed writing to socket! (Command to long - max 510 chars)' + ); /*************************************************************** * Credit: * @@ -245,149 +265,190 @@ class Net_NNTP_Protocol_Client extends PEAR * Prevent new line (and possible future) characters in the NNTP * commands Net_NNTP does not support pipelined commands. - * Inserting a new line character allows sending multiple + * Inserting a new line charecter allows sending multiple * commands and thereby making the communication between * NET_NNTP and the server out of sync... */ if (preg_match_all('/\r?\n/', $cmd, $matches, PREG_PATTERN_ORDER)) { - if ($this->_logger) { - foreach ($matches[0] as $match) { - $this->_logger->debug( - "Illegal character in command: " . htmlentities(str_replace(array("\r","\n"), - array("'Carriage Return'", "'New Line'"), $match)) - ); - } + foreach ($matches[0] as $key => $match) { + $this->_logger->debug("Illegal character in command: " . + htmlentities(str_replace(array("\r", "\n"), + array("'Carriage Return'", "'New Line'"), $match + ) + ) + ); } return $this->throwError("Illegal character(s) in NNTP command!"); } - // Check if connected. + // Check if connected if (!$this->_isConnected()) { return $this->throwError('Failed to write to socket! (connection lost!)'); } - // Send the command. - if (@fwrite($this->_socket, $cmd . "\r\n") === false) { + // Send the command + $R = @fwrite($this->_socket, $cmd . "\r\n"); + if ($R === false) { return $this->throwError('Failed to write to socket!'); } - // Log sent message. + // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { $this->_logger->debug('C: ' . $cmd); } + // return $this->_getStatusResponse(); } + // }}} + // {{{ _getStatusResponse() + /** * Get servers status response after a command. * - * @return mixed (int) response code on success - * (object) pear_error on failure + * @return mixed (int) statuscode on success or + * (object) pear_error on failure * @access private */ - private function _getStatusResponse() + function _getStatusResponse() { - // Retrieve a line (terminated by "\r\n") from the server. RFC says max is 510, but IETF says "be liberal in what you accept"... + // Retrieve a line (terminated by "\r\n") from the server. + // RFC says max is 510, but IETF says "be liberal in what you accept"... $response = @fgets($this->_socket, 4096); if ($response === false) { return $this->throwError('Failed to read from socket...!'); } - // Log incoming message. + // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { $this->_logger->debug('S: ' . rtrim($response, "\r\n")); } - // Trim the start of the response in case of misplaced whitespace (should not be needed). + /* Trim the start of the response in case of + * misplased whitespace (should not be needen!!!) + */ $response = ltrim($response); - // Store the response in an array, 0 => response code, 1 => response message. - $this->_currentStatusResponse = array((int) substr($response, 0, 3), (string) rtrim(substr($response, 4))); + $this->_currentStatusResponse = + array((int)substr($response, 0, 3), + (string)rtrim(substr($response, 4)) + ); + // return $this->_currentStatusResponse[0]; } + // }}} + // {{{ _getTextResponse() + /** * Retrieve textural data * * Get data until a line with only a '.' in it is read and return data. * - * @return mixed (array) text response on success - * (object) pear_error on failure - * @access protected + * @return mixed (array) text response on success or + * (object) pear_error on failure + * @access private */ - protected function _getTextResponse() + function _getTextResponse() { - // Buffer to hold the received lines. $data = array(); + $line = ''; - $debug = ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)); + // + $debug = $this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG); - // Continue until connection is lost. + // Continue until connection is lost while (!feof($this->_socket)) { // Retrieve and append up to 1024 characters from the server. - $line = @fgets($this->_socket, 1024); + $recieved = @fgets($this->_socket, 1024); - if ($line === false) { + if ($recieved === false) { return $this->throwError('Failed to read line from socket.', null); } - // Continue if the line is not terminated by CR LF. - if (substr($line, -2) !== "\r\n" || strlen($line) < 2) { + $line .= $recieved; + + // Continue if the line is not terminated by CRLF + if (substr($line, -2) != "\r\n" || strlen($line) < 2) { continue; } - // Remove CR LF from the end of the line. + // Validate recieved line + if (false) { + // Lines should/may not be longer than 998+2 chars (RFC2822 2.3) + if (strlen($line) > 1000) { + if ($this->_logger) { + $this->_logger->notice('Max line length...'); + } + + return $this->throwError('Invalid line recieved!', null); + } + } + + // Remove CRLF from the end of the line $line = substr($line, 0, -2); - // Check if the line terminates the text response. - if ($line === '.') { + // Check if the line terminates the textresponse + if ($line == '.') { if ($this->_logger) { $this->_logger->debug('T: ' . $line); } - // Return all previous lines. + // return all previous lines return $data; } - // If 1st char is '.' it's doubled (NNTP/RFC977 2.4.1). - if (substr($line, 0, 2) === '..') { + // If 1st char is '.' it's doubled (NNTP/RFC977 2.4.1) + if (substr($line, 0, 2) == '..') { $line = substr($line, 1); } + // if ($debug) { $this->_logger->debug('T: ' . $line); } - // Add the line to the array of lines. + // Add the line to the array of lines $data[] = $line; + + // Reset/empty $line + $line = ''; } if ($this->_logger) { - $this->_logger->warning('Broke out of reception loop! This souldn\'t happen unless connection has been lost?'); + $this->_logger->warning('Broke out of reception loop! ' + . 'This souldn\'t happen unless connection has been lost?' + ); } + // return $this->throwError('End of stream! Connection lost?', null); } + // }}} + // {{{ _sendText() + /** - * Send an article to usenet. * - * @note Data should be in the format specified by RFC850. * * @access private */ - private function _sendArticle($article) + function _sendArticle($article) { + /* data should be in the format specified by RFC850 */ + switch (true) { case is_string($article): + // @fwrite($this->_socket, $article); @fwrite($this->_socket, "\r\n.\r\n"); + // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { foreach (explode("\r\n", $article) as $line) { $this->_logger->debug('D: ' . $line); @@ -412,6 +473,7 @@ class Net_NNTP_Protocol_Client extends PEAR @fwrite($this->_socket, $header); @fwrite($this->_socket, "\r\n"); + // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { foreach (explode("\r\n", $header) as $line) { $this->_logger->debug('D: ' . $line); @@ -430,6 +492,7 @@ class Net_NNTP_Protocol_Client extends PEAR @fwrite($this->_socket, $body); @fwrite($this->_socket, "\r\n.\r\n"); + // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { foreach (explode("\r\n", $body) as $line) { $this->_logger->debug('D: ' . $line); @@ -445,63 +508,116 @@ class Net_NNTP_Protocol_Client extends PEAR return true; } + // }}} + // {{{ _currentStatusResponse() + /** - * Return the last received response message. * - * @return string The response message. + * + * @return string status text * @access private */ - private function _currentStatusResponse() + function _currentStatusResponse() { return $this->_currentStatusResponse[1]; } + // }}} + // {{{ _handleUnexpectedResponse() + + /** + * + * + * @param int $code Status code number + * @param string $text Status text + * + * @return mixed + * @access private + */ + function _handleUnexpectedResponse($code = null, $text = null) + { + if ($code === null) { + $code = $this->_currentStatusResponse[0]; + } + + if ($text === null) { + $text = $this->_currentStatusResponse(); + } + + switch ($code) { + /* 502, 'access restriction or permission denied' + * / service permanently unavailable + */ + case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: + return $this->throwError('Command not permitted / Access' + . ' restriction / Permission denied', $code, $text + ); + break; + default: + return $this->throwError("Unexpected response: '$text'", + $code, $text + ); + } + } + + // }}} + /* Session administration commands */ + // {{{ Connect() + /** * Connect to a NNTP server * - * @param string $host (optional) The address of the NNTP-server to connect to, defaults to 'localhost'. - * @param mixed $encryption (optional) Use TLS/SSL on the connection? - * (string) 'tcp' => Use no encryption. - * 'ssl', 'sslv3', 'tls' => Use encryption. - * (null)|(false) Use no encryption. - * @param int $port (optional) The port number to connect to, defaults to 119. - * @param int $timeout (optional) How many seconds to wait before giving up when connecting. - * @param int $socketTimeout (optional) How many seconds to wait before timing out the (blocked) socket. + * @param string $host (optional) The address of the + * NNTP-server to connect to, defaults to 'localhost'. + * @param mixed $encryption (optional) + * @param int $port (optional) The port number to connect to, + * defaults to 119. + * @param int $timeout (optional) * - * @return mixed (bool) On success: True when posting allowed, otherwise false. - * (object) On failure: pear_error + * @return mixed (bool) on success (true when posting allowed, + * otherwise false) or (object) pear_error on failure * @access protected */ - protected function connect($host = null, $encryption = null, $port = null, $timeout = 15, $socketTimeout = 120) + function connect($host = null, $encryption = null, $port = null, $timeout = 15) { + // if ($this->_isConnected() ) { return $this->throwError('Already connected, disconnect first!', null); } // v1.0.x API if (is_int($encryption)) { - trigger_error('You are using deprecated API v1.0 in Net_NNTP_Protocol_Client: connect() !', E_USER_NOTICE); + trigger_error('You are using deprecated API v1.0 in ' + . 'Net_NNTP_Protocol_Client: connect() !', E_USER_NOTICE + ); $port = $encryption; $encryption = false; } + // if (is_null($host)) { $host = 'localhost'; } - // Choose transport based on encryption, and if no port is given, use default for that encryption. + /* Choose transport based on encryption, and if no port is + * given, use default for that encryption + */ switch ($encryption) { case null: + case 'tcp': + case false: $transport = 'tcp'; $port = is_null($port) ? 119 : $port; break; case 'sslv3': + case 'ssl': + case 'tls': $transport = $encryption; $port = is_null($port) ? 563 : $port; @@ -513,40 +629,29 @@ class Net_NNTP_Protocol_Client extends PEAR return $this->throwError($message); } - // Attempt to connect to usenet. - $socket = @stream_socket_client( - $transport . '://' . $host . ':' . $port, $errorNumber, $errorString, $timeout - ); - - if ($socket === false) { - + // Open Connection + $R = @stream_socket_client($transport . '://' . $host . ':' . $port, $errno, $errstr, $timeout); + if ($R === false) { $message = "Connection to $transport://$host:$port failed."; - if (preg_match('/tls|ssl/', $transport)) { $message .= ' Try disabling SSL/TLS, and/or try a different port.'; } - - $message .= ' [ERROR ' . $errorNumber . ': ' . $errorString . ']'; - + $message .= ' [ERROR ' . $errno . ': ' . $errstr . ']'; if ($this->_logger) { $this->_logger->notice($message); } return $this->throwError($message); } - // Store the socket resource as property. - $this->_socket = $socket; - - $this->_socketTimeout = (is_numeric($socketTimeout) ? $socketTimeout : $this->_socketTimeout); - - // Set the socket timeout. - stream_set_timeout($this->_socket, $this->_socketTimeout); + $this->_socket = $R; + stream_set_timeout($this->_socket, 120); + // if ($this->_logger) { $this->_logger->info("Connection to $transport://$host:$port has been established."); } - // Retrieve the server's initial response. + // Retrive the server's initial response. $response = $this->_getStatusResponse(); if ($this->isError($response)) { return $response; @@ -554,33 +659,68 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 200, Posting allowed - case 'NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_ALLOWED': + case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_ALLOWED: // TODO: Set some variable before return return true; + break; // 201, Posting NOT allowed - case 'NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED': + case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED: + // if ($this->_logger) { $this->_logger->info('Posting not allowed!'); } // TODO: Set some variable before return return false; + break; + + case 400: + return $this->throwError('Server refused connection', + $response, $this->_currentStatusResponse() + ); + break; + + /* 502, 'access restriction or permission denied' + * / service permanently unavailable + */ + case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: + return $this->throwError('Server refused connection', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ disconnect() + + /** + * alias for cmdQuit() + * + * @access protected + */ + function disconnect() + { + return $this->cmdQuit(); + } + + // }}} + // {{{ cmdCapabilities() + /** * Returns servers capabilities * - * @return mixed (array) list of capabilities on success or - * (object) pear_error on failure + * @return mixed (array) list of capabilities on success or + * (object) pear_error on failure * @access protected */ - protected function cmdCapabilities() + function cmdCapabilities() { + // tell the newsserver we want an article $response = $this->_sendCommand('CAPABILITIES'); if ($this->isError($response)) { return $response; @@ -588,27 +728,32 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 101, Draft: 'Capability list follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_CAPABILITIES_FOLLOW': + case NET_NNTP_PROTOCOL_RESPONSECODE_CAPABILITIES_FOLLOW: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; } return $data; + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdModeReader() + /** * * - * @return mixed (bool) true when posting allowed, false when posting disallowed - * (object) pear_error on failure + * @return mixed (bool) true when posting allowed, false when + * postind disallowed or (object) pear_error on failure * @access protected */ - protected function cmdModeReader() + function cmdModeReader() { + // tell the newsserver we want an article $response = $this->_sendCommand('MODE READER'); if ($this->isError($response)) { return $response; @@ -616,54 +761,58 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 200, RFC2980: 'Hello, you can post' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_ALLOWED': + case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_ALLOWED: // TODO: Set some variable before return return true; + break; // 201, RFC2980: 'Hello, you can't post' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED': + case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED: if ($this->_logger) { $this->_logger->info('Posting not allowed!'); } // TODO: Set some variable before return return false; + break; + + /* 502, 'access restriction or permission denied' + * / service permanently unavailable + */ + case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: + return $this->throwError('Connection being closed, ' + . 'since service so permanently unavailable', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } - /** - * Alias for cmdQuit() - * - * @access protected - */ - protected function disconnect() - { - return $this->cmdQuit(); - } + // }}} + // {{{ cmdQuit() /** * Disconnect from the NNTP server * - * @return mixed (bool) true on success - * (object) pear_error on failure + * @return mixed (bool) true on success or + * (object) pear_error on failure * @access protected */ - protected function cmdQuit() + function cmdQuit() { + // Tell the server to close the connection $response = $this->_sendCommand('QUIT'); if ($this->isError($response)) { return $response; } switch ($response) { - // RFC977: 'closing connection - goodbye!' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_DISCONNECTING_REQUESTED': + case 205: // RFC977: 'closing connection - goodbye!' // If socket is still open, close it. - $disconnected = true; - if ($this->_isConnected(false)) { - $disconnected = (bool)stream_socket_shutdown($this->_socket, STREAM_SHUT_RDWR); + if ($this->_isConnected()) { + fclose($this->_socket); } if ($this->_logger) { @@ -671,20 +820,28 @@ class Net_NNTP_Protocol_Client extends PEAR } $this->_currentStatusResponse = null; $this->_socket = null; - return $disconnected; + + return true; + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + + // }}} + + /* */ + + // {{{ cmdStartTLS() + /** - * Request TLS encryption to the news server. * - * @return mixed (bool) on success - * (object) pear_error on failure + * + * @return mixed (bool) on success or (object) pear_error on failure * @access protected */ - protected function cmdStartTLS() + function cmdStartTLS() { $response = $this->_sendCommand('STARTTLS'); if ($this->isError($response)) { @@ -692,50 +849,73 @@ class Net_NNTP_Protocol_Client extends PEAR } switch ($response) { - // RFC4642: 'continue with TLS negotiation' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_TLS_AUTHENTICATION_CONTINUE': - $encrypted = stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); + case 382: // RFC4642: 'continue with TLS negotiation' + $encrypted = stream_socket_enable_crypto($this->_socket, + true, STREAM_CRYPTO_METHOD_TLS_CLIENT + ); switch (true) { case $encrypted === true: if ($this->_logger) { $this->_logger->info('TLS encryption started.'); } return true; + break; - case $encrypted === false: + case $encrypted === true: if ($this->_logger) { $this->_logger->info('TLS encryption failed.'); } - return $this->throwError('Could not initiate TLS negotiation', $response, $this->_currentStatusResponse()); - case is_int($encrypted): - return $this->throwError('TLS encryption failed.', $response, $this->_currentStatusResponse()); - - default: - return $this->throwError( - 'Internal error - unknown response from stream_socket_enable_crypto()', - $response, + return $this->throwError('Could not initiate ' + . 'TLS negotiation', $response, $this->_currentStatusResponse() ); + break; + + case is_int($encrypted): + return $this->throwError('', $response, + $this->_currentStatusResponse() + ); + break; + + default: + return $this->throwError('Internal error - ' + . 'unknown response from' + . 'stream_socket_enable_crypto()', + $response, $this->_currentStatusResponse() + ); } + break; + + case 580: // RFC4642: 'can not initiate TLS negotiation' + return $this->throwError('', $response, + $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + + /* Article posting and retrieval */ + /* Group and article selection */ + // {{{ cmdGroup() + /** * Selects a news group (issue a GROUP command to the server) * * @param string $newsgroup The newsgroup name * - * @return mixed (array) group info on success - * (object) pear_error on failure + * @return mixed (array) groupinfo on success or + * (object) pear_error on failure * @access protected */ - protected function cmdGroup($newsgroup) + function cmdGroup($newsgroup) { $response = $this->_sendCommand('GROUP '.$newsgroup); if ($this->isError($response)) { @@ -744,36 +924,50 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 211, RFC977: 'n f l s group selected' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_GROUP_SELECTED': - $response_arr = explode(' ', trim($this->_currentStatusResponse())); - - if ($this->_logger) { - $this->_logger->info('Group selected: ' . $response_arr[3]); - } - - return array( - 'group' => $response_arr[3], - 'first' => $response_arr[1], - 'last' => $response_arr[2], - 'count' => $response_arr[0] + case NET_NNTP_PROTOCOL_RESPONSECODE_GROUP_SELECTED: + $response_arr = explode(' ', + trim($this->_currentStatusResponse()) ); + if ($this->_logger) { + $this->_logger->info('Group selected: ' + . $response_arr[3] + ); + } + + return array('group' => $response_arr[3], + 'first' => $response_arr[1], + 'last' => $response_arr[2], + 'count' => $response_arr[0] + ); + break; + + // 411, RFC977: 'no such news group' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_GROUP: + return $this->throwError('No such news group on server', + $response, $this->_currentStatusResponse() + ); + break; + default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdListgroup() + /** - * Gets a group overview. * - * @param string $newsgroup (optional) - * @param mixed $range (optional) * - * @return mixed (array) On success - * (object) pear_error On failure + * @param optional string $newsgroup + * @param optional mixed $range + * + * @return optional mixed (array) on success or + * (object) pear_error on failure * @access protected */ - protected function cmdListgroup($newsgroup = null, $range = null) + function cmdListgroup($newsgroup = null, $range = null) { if (is_null($newsgroup)) { $command = 'LISTGROUP'; @@ -792,117 +986,200 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 211, RFC2980: 'list of article numbers follow' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_GROUP_SELECTED': + case NET_NNTP_PROTOCOL_RESPONSECODE_GROUP_SELECTED: $articles = $this->_getTextResponse(); if ($this->isError($articles)) { return $articles; } - $response_arr = explode(' ', trim($this->_currentStatusResponse()), 4); + $response_arr = explode(' ', + trim($this->_currentStatusResponse()), 4 + ); - // If server does not return group summary in status response, return null array. + /* If server does not return group summary in + * status response, return null'ed array + */ if (!is_numeric($response_arr[0]) || !is_numeric($response_arr[1]) || !is_numeric($response_arr[2]) || empty($response_arr[3]) ) { - return array( - 'group' => null, - 'first' => null, - 'last' => null, - 'count' => null, - 'articles' => $articles + return array('group' => null, + 'first' => null, + 'last' => null, + 'count' => null, + 'articles' => $articles ); } - return array( - 'group' => $response_arr[3], - 'first' => $response_arr[1], - 'last' => $response_arr[2], - 'count' => $response_arr[0], - 'articles' => $articles + return array('group' => $response_arr[3], + 'first' => $response_arr[1], + 'last' => $response_arr[2], + 'count' => $response_arr[0], + 'articles' => $articles ); + break; + + // 412, RFC2980: 'Not currently in newsgroup' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: + return $this->throwError('Not currently in newsgroup', + $response, $this->_currentStatusResponse() + ); + break; + + // RFC2980: 'no permission' + case 502: + return $this->throwError('No permission', $response, + $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdLast() + /** - * Select the previous article in current group. * - * @return mixed (array) or (string) or (int) On success - * (object) pear_error On failure + * + * @return mixed (array) or (string) or (int) or + * (object) pear_error on failure * @access protected */ - protected function cmdLast() + function cmdLast() { + // $response = $this->_sendCommand('LAST'); if ($this->isError($response)) { return $response; } switch ($response) { - // 223, RFC977: 'n a article retrieved - request text separately (n = article number, a = unique article id)' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED': - $response_arr = explode(' ', trim($this->_currentStatusResponse())); + /* 223, RFC977: 'n a article retrieved - request text + * separately (n = article number, a = unique article id)' + */ + case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED: + $response_arr = explode(' ', + trim($this->_currentStatusResponse()) + ); if ($this->_logger) { - $this->_logger->info('Selected previous article: ' . $response_arr[0] .' - '. $response_arr[1]); + $this->_logger->info('Selected previous article: ' . + $response_arr[0] . ' - ' . $response_arr[1] + ); } return array($response_arr[0], (string) $response_arr[1]); + break; + + // 412, RFC977: 'no newsgroup selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: + return $this->throwError('No newsgroup has been selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 420, RFC977: 'no current article has been selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: + return $this->throwError('No current article has been selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 422, RFC977: 'no previous article in this group' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_PREVIOUS_ARTICLE: + return $this->throwError('No previous article in this group', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdNext() + /** - * Select the next article in current group. * - * @return mixed (array) or (string) or (int) On success - * (object) pear_error On failure + * + * @return mixed (array) or (string) or (int) or + * (object) pear_error on failure * @access protected */ - protected function cmdNext() + function cmdNext() { + // $response = $this->_sendCommand('NEXT'); if ($this->isError($response)) { return $response; } switch ($response) { - // 223, RFC977: 'n a article retrieved - request text separately (n = article number, a = unique article id)' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED': + /* 223, RFC977: 'n a article retrieved - request text + * separately (n = article number, a = unique article id)' + */ + case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED: $response_arr = explode(' ', trim($this->_currentStatusResponse())); if ($this->_logger) { - $this->_logger->info('Selected previous article: ' . $response_arr[0] .' - '. $response_arr[1]); + $this->_logger->info('Selected previous article: ' . + $response_arr[0] . ' - ' . $response_arr[1] + ); } return array($response_arr[0], (string) $response_arr[1]); + break; + + // 412, RFC977: 'no newsgroup selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: + return $this->throwError('No newsgroup has been selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 420, RFC977: 'no current article has been selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: + return $this->throwError('No current article has been selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 421, RFC977: 'no next article in this group' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_NEXT_ARTICLE: + return $this->throwError('No next article in this group', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + /* Retrieval of articles and article sections */ + // {{{ cmdArticle() + /** * Get an article from the currently open connection. * - * @param mixed $article Either a message-id or a message-number of the article to fetch. - * If null or '', then use current article. + * @param mixed $article Either a message-id or a message-number + * of the article to fetch. If null or '', then use current article. * - * @return mixed (array) article on success - * (object) pear_error on failure + * @return mixed (array) article on success or + * (object) pear_error on failure * @access protected */ - protected function cmdArticle($article = null) + function cmdArticle($article = null) { if (is_null($article)) { $command = 'ARTICLE'; @@ -910,40 +1187,79 @@ class Net_NNTP_Protocol_Client extends PEAR $command = 'ARTICLE ' . $article; } + // tell the newsserver we want an article $response = $this->_sendCommand($command); if ($this->isError($response)) { return $response; } switch ($response) { - // 220, RFC977: 'n <a> article retrieved - head and body follow (n = article number, <a> = message-id)' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_FOLLOWS': + /* 220, RFC977: 'n <a> article retrieved - head and + * body follow (n = article number, <a> = message-id)' + */ + case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_FOLLOWS: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; } if ($this->_logger) { - $this->_logger->info(($article == null ? 'Fetched current article' : 'Fetched article: '. $article)); + $this->_logger->info(($article == null ? + 'Fetched current article' : 'Fetched article: ' . + $article) + ); } return $data; + break; + + // 412, RFC977: 'no newsgroup has been selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: + return $this->throwError('No newsgroup has been selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 420, RFC977: 'no current article has been selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: + return $this->throwError('No current article has been selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 423, RFC977: 'no such article number in this group' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: + return $this->throwError('No such article number in this group', + $response, $this->_currentStatusResponse() + ); + break; + + // 430, RFC977: 'no such article found' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: + return $this->throwError('No such article found', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdHead() + /** * Get the headers of an article from the currently open connection. * - * @param mixed $article Either a message-id or a message-number of the article to fetch the headers from. - * If null or '', then use current article. + * @param mixed $article Either a message-id or a message-number + * of the article to fetch the headers from. If null or '', + * then use current article. * - * @return mixed (array) headers on success or - * (object) pear_error on failure + * @return mixed (array) headers on success or + * (object) pear_error on failure * @access protected */ - protected function cmdHead($article = null) + function cmdHead($article = null) { if (is_null($article)) { $command = 'HEAD'; @@ -951,6 +1267,7 @@ class Net_NNTP_Protocol_Client extends PEAR $command = 'HEAD ' . $article; } + // tell the newsserver we want the header of an article $response = $this->_sendCommand($command); if ($this->isError($response)) { return $response; @@ -958,34 +1275,70 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 221, RFC977: 'n <a> article retrieved - head follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_HEAD_FOLLOWS': + case NET_NNTP_PROTOCOL_RESPONSECODE_HEAD_FOLLOWS: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; } if ($this->_logger) { - $this->_logger->info(($article == null ? 'Fetched current article header' : 'Fetched article header for article: '.$article)); + $this->_logger->info(($article == null ? + 'Fetched current article header' : 'Fetched ' + . 'article header for article: ' . $article) + ); } return $data; + break; + + // 412, RFC977: 'no newsgroup has been selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: + return $this->throwError('No newsgroup has been selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 420, RFC977: 'no current article has been selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: + return $this->throwError('No current article has been selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 423, RFC977: 'no such article number in this group' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: + return $this->throwError('No such article number in this group', + $response, $this->_currentStatusResponse() + ); + break; + + // 430, RFC977: 'no such article found' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: + return $this->throwError('No such article found', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdBody() + /** * Get the body of an article from the currently open connection. * - * @param mixed $article Either a message-id or a message-number of the article to fetch the body from. - * If null or '', then use current article. + * @param mixed $article Either a message-id or a message-number of + * the article to fetch the body from. If null or '', + * then use current article. * - * @return mixed (array) body on success - * (object) pear_error on failure + * @return mixed (array) body on success or + * (object) pear_error on failure * @access protected */ - protected function cmdBody($article = null) + function cmdBody($article = null) { if (is_null($article)) { $command = 'BODY'; @@ -993,6 +1346,7 @@ class Net_NNTP_Protocol_Client extends PEAR $command = 'BODY ' . $article; } + // tell the newsserver we want the body of an article $response = $this->_sendCommand($command); if ($this->isError($response)) { return $response; @@ -1000,33 +1354,68 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 222, RFC977: 'n <a> article retrieved - body follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_BODY_FOLLOWS': + case NET_NNTP_PROTOCOL_RESPONSECODE_BODY_FOLLOWS: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; } if ($this->_logger) { - $this->_logger->info(($article == null ? 'Fetched current article body' : 'Fetched article body for article: '.$article)); + $this->_logger->info(($article == null ? + 'Fetched current article body' : 'Fetched ' + . 'article body for article: ' . $article) + ); } return $data; + break; + + // 412, RFC977: 'no newsgroup has been selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: + return $this->throwError('No newsgroup has been selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 420, RFC977: 'no current article has been selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: + return $this->throwError('No current article has been selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 423, RFC977: 'no such article number in this group' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: + return $this->throwError('No such article number in this group', + $response, $this->_currentStatusResponse() + ); + break; + + // 430, RFC977: 'no such article found' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: + return $this->throwError('No such article found', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdStat + /** - * Selects an article by article message-number. + * * * @param mixed $article * - * @return mixed (array) or (string) or (int) on success - * (object) pear_error on failure + * @return mixed (array) or (string) or (int) or + * (object) pear_error on failure * @access protected */ - protected function cmdStat($article = null) + function cmdStat($article = null) { if (is_null($article)) { $command = 'STAT'; @@ -1034,6 +1423,7 @@ class Net_NNTP_Protocol_Client extends PEAR $command = 'STAT ' . $article; } + // tell the newsserver we want an article $response = $this->_sendCommand($command); if ($this->isError($response)) { return $response; @@ -1044,32 +1434,68 @@ class Net_NNTP_Protocol_Client extends PEAR * separately' (actually not documented, but copied * from the ARTICLE command) */ - case 'NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED': + case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED: $response_arr = explode(' ', trim($this->_currentStatusResponse())); if ($this->_logger) { - $this->_logger->info('Selected article: ' . $response_arr[0].' - '.$response_arr[1]); + $this->_logger->info('Selected article: ' . + $response_arr[0] . ' - ' . $response_arr[1] + ); } return array($response_arr[0], (string) $response_arr[1]); + break; + + /* 412, RFC977: 'no newsgroup has been selected' + * (actually not documented, but copied from the + * ARTICLE command) + */ + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: + return $this->throwError('No newsgroup has been selected', + $response, $this->_currentStatusResponse() + ); + break; + + /* 423, RFC977: 'no such article number in this group' + * (actually not documented, but copied from the + * ARTICLE command) + */ + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: + return $this->throwError('No such article number in this group', + $response, $this->_currentStatusResponse() + ); + break; + + /* 430, RFC977: 'no such article found' (actually not + * documented, but copied from the ARTICLE command) + */ + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: + return $this->throwError('No such article found', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + /* Article posting */ + // {{{ cmdPost() + /** * Post an article to a newsgroup. * - * @return mixed (bool) true on success - * (object) pear_error on failure + * @return mixed (bool) true on success or (object) pear_error on failure * @access protected */ - protected function cmdPost() + function cmdPost() { + // tell the newsserver we want to post an article $response = $this->_sendCommand('POST'); if ($this->isError($response)) { return $response; @@ -1077,31 +1503,42 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 340, RFC977: 'send article to be posted. End with <CR-LF>.<CR-LF>' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_SEND': + case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_SEND: return true; + break; + // 440, RFC977: 'posting not allowed' + case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_PROHIBITED: + return $this->throwError('Posting not allowed', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdPost2() + /** * Post an article to a newsgroup. * - * @note Should be presented in the format specified by RFC850. - * * @param mixed $article (string/array) * - * @return mixed (bool) true on success - * (object) pear_error on failure + * @return mixed (bool) true on success or + * (object) pear_error on failure * @access protected */ - protected function cmdPost2($article) + function cmdPost2($article) { + /* should be presented in the format specified by RFC850 */ + + // $this->_sendArticle($article); - // Retrieve server's response. + // Retrive server's response. $response = $this->_getStatusResponse(); if ($this->isError($response)) { return $response; @@ -1109,81 +1546,127 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 240, RFC977: 'article posted ok' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_SUCCESS': + case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_SUCCESS: return true; + break; + + // 441, RFC977: 'posting failed' + case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_FAILURE: + return $this->throwError('Posting failed', $response, + $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdIhave() + /** - * Tell the news server we want to upload an article, the server will check if it has the message-id first. * - * @param string $id Message-ID. * - * @return mixed (bool) true on success - * (object) pear_error on failure + * @param string $id + * + * @return mixed (bool) true on success or + * (object) pear_error on failure * @access protected */ - protected function cmdIhave($id) + function cmdIhave($id) { + // tell the newsserver we want to post an article $response = $this->_sendCommand('IHAVE ' . $id); if ($this->isError($response)) { return $response; } switch ($response) { - // 335, RFC997: 'Send article to be transferred' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SEND': + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SEND: // 335 return true; + break; + + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_UNWANTED: // 435 + return $this->throwError('Article not wanted', + $response, $this->_currentStatusResponse() + ); + break; + + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_FAILURE: // 436 + return $this->throwError + ('Transfer not possible; try again later', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdIhave2() + /** - * Tell the news server we have an article to upload, the server will check if it has it first. * - * @note Should be presented in the format specified by RFC850. * * @param mixed $article (string/array) * - * @return mixed (bool) true on success - * (object) pear_error on failure + * @return mixed (bool) true on success or (object) pear_error on failure * @access protected */ - protected function cmdIhave2($article) + function cmdIhave2($article) { + /* should be presented in the format specified by RFC850 */ + + // $this->_sendArticle($article); - // Retrieve server's response. + // Retrive server's response. $response = $this->_getStatusResponse(); if ($this->isError($response)) { return $response; } switch ($response) { - // 235, RFC977: 'Article transferred OK' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SUCCESS': + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SUCCESS: // 235 return true; + break; + + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_FAILURE: // 436 + return $this->throwError + ('Transfer not possible; try again later', + $response, $this->_currentStatusResponse() + ); + break; + + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_REJECTED: // 437 + return $this->throwError + ('Transfer rejected; do not retry', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + /* Information commands */ + // {{{ cmdDate() + /** - * Get the date from the news server. + * Get the date from the newsserver format of returned date * - * @return mixed (string) or (int) 'YYYYMMDDhhmmss', timestamp on success - * (object) pear_error on failure + * @return mixed (string) 'YYYYMMDDhhmmss' / (int) timestamp on + * success or (object) pear_error on failure * @access protected */ - protected function cmdDate() + function cmdDate() { $response = $this->_sendCommand('DATE'); if ($this->isError($response)){ @@ -1191,61 +1674,69 @@ class Net_NNTP_Protocol_Client extends PEAR } switch ($response) { - // 111, RFC2980: '(string of numbers representing the date and time)' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_SERVER_DATE': + // 111, RFC2980: 'YYYYMMDDhhmmss' + case NET_NNTP_PROTOCOL_RESPONSECODE_SERVER_DATE: return $this->_currentStatusResponse(); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdHelp() /** - * Returns the server's help text. + * Returns the server's help text * * @return mixed (array) help text on success or - * (object) pear_error on failure + * (object) pear_error on failure * @access protected */ - protected function cmdHelp() + function cmdHelp() { + // tell the newsserver we want an article $response = $this->_sendCommand('HELP'); if ($this->isError($response)) { return $response; } switch ($response) { - // 100, RFC977: 'Help text follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_HELP_FOLLOWS': + case NET_NNTP_PROTOCOL_RESPONSECODE_HELP_FOLLOWS: // 100 $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; } return $data; + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdNewgroups() + /** * Fetches a list of all newsgroups created since a specified date. * - * @param int $time Last time you checked for groups (timestamp). - * @param string $distributions (optional) (deprecaded in rfc draft) + * @param int $time Last time you checked for groups (timestamp). + * @param optional string $distributions (deprecaded in rfc draft) * - * @return mixed (array) nested array with informations about existing newsgroups on success - * (object) pear_error on failure + * @return mixed (array) nested array with informations about + * existing newsgroups on success or (object) pear_error on failure * @access protected */ - protected function cmdNewgroups($time, $distributions = null) + function cmdNewgroups($time, $distributions = null) { $date = gmdate('ymd His', $time); if (is_null($distributions)) { $command = 'NEWGROUPS ' . $date . ' GMT'; } else { - $command = 'NEWGROUPS ' . $date . ' GMT <' . $distributions . '>'; + $command = 'NEWGROUPS ' . $date . ' GMT <' . + $distributions . '>'; } $response = $this->_sendCommand($command); @@ -1255,7 +1746,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 231, REF977: 'list of new newsgroups follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_NEW_GROUPS_FOLLOW': + case NET_NNTP_PROTOCOL_RESPONSECODE_NEW_GROUPS_FOLLOW: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1265,11 +1756,10 @@ class Net_NNTP_Protocol_Client extends PEAR foreach($data as $line) { $arr = explode(' ', trim($line)); - $group = array( - 'group' => $arr[0], - 'last' => $arr[1], - 'first' => $arr[2], - 'posting' => $arr[3] + $group = array('group' => $arr[0], + 'last' => $arr[1], + 'first' => $arr[2], + 'posting' => $arr[3] ); $groups[$group['group']] = $group; @@ -1277,21 +1767,24 @@ class Net_NNTP_Protocol_Client extends PEAR return $groups; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdNewnews() + /** * * - * @param int $time Unix timestamp. - * @param mixed $newsgroups (string or array of strings) + * @param timestamp $time + * @param mixed $newsgroups (string or array of strings) * @param mixed $distribution (string or array of strings) * * @return mixed * @access protected */ - protected function cmdNewnews($time, $newsgroups, $distribution = null) + function cmdNewnews($time, $newsgroups, $distribution = null) { $date = gmdate('ymd His', $time); @@ -1302,15 +1795,15 @@ class Net_NNTP_Protocol_Client extends PEAR if (is_null($distribution)) { $command = 'NEWNEWS ' . $newsgroups . ' ' . $date . ' GMT'; } else { - if (is_array($distribution)) { $distribution = implode(',', $distribution); } - $command = 'NEWNEWS ' . $newsgroups . ' ' . $date . ' GMT <' . $distribution . '>'; + $command = 'NEWNEWS ' . $newsgroups . ' ' . $date . ' GMT <' + . $distribution . '>'; } - // TODO: the length of the request string may not exceed 510 chars. + // TODO: the lenght of the request string may not exceed 510 chars $response = $this->_sendCommand($command); if ($this->isError($response)){ @@ -1319,28 +1812,33 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 230, RFC977: 'list of new articles by message-id follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_NEW_ARTICLES_FOLLOW': + case NET_NNTP_PROTOCOL_RESPONSECODE_NEW_ARTICLES_FOLLOW: $messages = array(); foreach($this->_getTextResponse() as $line) { $messages[] = $line; } return $messages; + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + /* The LIST commands */ + // {{{ cmdList() + /** - * Fetches a list of all available newsgroups. + * Fetches a list of all avaible newsgroups * - * @return mixed (array) nested array with informations about existing newsgroups on success - * (object) pear_error on failure + * @return mixed (array) nested array with informations about + * existing newsgroups on success or (object) pear_error on failure * @access protected */ - protected function cmdList() + function cmdList() { $response = $this->_sendCommand('LIST'); if ($this->isError($response)){ @@ -1349,7 +1847,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 215, RFC977: 'list of newsgroups follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW': + case NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1359,37 +1857,40 @@ class Net_NNTP_Protocol_Client extends PEAR foreach($data as $line) { $arr = explode(' ', trim($line)); - $group = array( - 'group' => $arr[0], - 'last' => $arr[1], - 'first' => $arr[2], - 'posting' => $arr[3] + $group = array('group' => $arr[0], + 'last' => $arr[1], + 'first' => $arr[2], + 'posting' => $arr[3] ); $groups[$group['group']] = $group; } return $groups; + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdListActive() + /** - * Fetches a list of all available newsgroups. + * Fetches a list of all avaible newsgroups * - * @param string $wildMat + * @param string $wildmat * - * @return mixed (array) nested array with informations about existing newsgroups on success - * (object) pear_error on failure + * @return mixed (array) nested array with informations about + * existing newsgroups on success or (object) pear_error on failure * @access protected */ - protected function cmdListActive($wildMat = null) + function cmdListActive($wildmat = null) { - if (is_null($wildMat)) { + if (is_null($wildmat)) { $command = 'LIST ACTIVE'; } else { - $command = 'LIST ACTIVE ' . $wildMat; + $command = 'LIST ACTIVE ' . $wildmat; } $response = $this->_sendCommand($command); @@ -1399,7 +1900,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 215, RFC977: 'list of newsgroups follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW': + case NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1409,11 +1910,10 @@ class Net_NNTP_Protocol_Client extends PEAR foreach($data as $line) { $arr = explode(' ', trim($line)); - $group = array( - 'group' => $arr[0], - 'last' => $arr[1], - 'first' => $arr[2], - 'posting' => $arr[3] + $group = array('group' => $arr[0], + 'last' => $arr[1], + 'first' => $arr[2], + 'posting' => $arr[3] ); $groups[$group['group']] = $group; @@ -1424,27 +1924,32 @@ class Net_NNTP_Protocol_Client extends PEAR } return $groups; + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdListNewsgroups() + /** * Fetches a list of (all) avaible newsgroup descriptions. * - * @param string $wildMat Wildmat of the groups, that is to be listed, defaults to null; + * @param string $wildmat Wildmat of the groups, that is to be + * listed, defaults to null; * - * @return mixed (array) nested array with description of existing newsgroups on success - * (object) pear_error on failure + * @return mixed (array) nested array with description of existing + * newsgroups on success or (object) pear_error on failure * @access protected */ - protected function cmdListNewsgroups($wildMat = null) + function cmdListNewsgroups($wildmat = null) { - if (is_null($wildMat)) { + if (is_null($wildmat)) { $command = 'LIST NEWSGROUPS'; } else { - $command = 'LIST NEWSGROUPS ' . $wildMat; + $command = 'LIST NEWSGROUPS ' . $wildmat; } $response = $this->_sendCommand($command); @@ -1454,7 +1959,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 215, RFC2980: 'information follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW': + case NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1463,10 +1968,17 @@ class Net_NNTP_Protocol_Client extends PEAR $groups = array(); foreach($data as $line) { - if (preg_match('/^(\S+)\s+(.*)$/', ltrim($line), $matches)) { + if (preg_match("/^(\S+)\s+(.*)$/", ltrim($line), + $matches + ) + ) { $groups[$matches[1]] = (string) $matches[2]; - } else if ($this->_logger) { - $this->_logger->warning("Recieved non-standard line: '$line'"); + } else { + if ($this->_logger) { + $this->_logger->warning + ("Recieved non-standard line: '$line'" + ); + } } } @@ -1475,26 +1987,40 @@ class Net_NNTP_Protocol_Client extends PEAR } return $groups; + break; + + // RFC2980: 'program error, function not performed' + case 503: + return $this->throwError + ('Internal server error, function not performed', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + /* Article field access commands */ + // {{{ cmdOver() + /** * Fetch message header from message number $first until $last * - * @info The format of the returned array is: $messages[][header_name] + * The format of the returned array is: + * $messages[][header_name] * - * @param string $range (optional) articles to fetch + * @param optional string $range articles to fetch * - * @return mixed (array) nested array of message and there headers on success - * (object) pear_error on failure + * @return mixed (array) nested array of message and there headers + * on success or (object) pear_error on failure * @access protected */ - protected function cmdOver($range = null) + function cmdOver($range = null) { if (is_null($range)) { $command = 'OVER'; @@ -1509,7 +2035,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 224, RFC2980: 'Overview information follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS': + case NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1520,32 +2046,69 @@ class Net_NNTP_Protocol_Client extends PEAR } if ($this->_logger) { - $this->_logger->info('Fetched overview ' . ($range == null ? 'for current article' : 'for range: ' . $range)); + $this->_logger->info('Fetched overview ' . + ($range == null ? + 'for current article' : 'for range: ' . $range) + ); } return $data; + break; + + // 412, RFC2980: 'No news group current selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: + return $this->throwError('No news group current selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 420, RFC2980: 'No article(s) selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: + return $this->throwError('No article(s) selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 423:, Draft27: 'No articles in that range' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: + return $this->throwError('No articles in that range', + $response, $this->_currentStatusResponse() + ); + break; + + // RFC2980: 'no permission' + case 502: + return $this->throwError('No permission', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdXOver() + /** * Fetch message header from message number $first until $last * - * @info The format of the returned array is: $messages[message_id][header_name] + * The format of the returned array is: + * $messages[message_id][header_name] * - * @param string $range (optional) articles to fetch + * @param optional string $range articles to fetch * - * @return mixed (array) nested array of message and there headers on success - * (object) pear_error on failure + * @return mixed (array) nested array of message and there headers + * on success or (object) pear_error on failure * @access protected */ - protected function cmdXOver($range = null) + function cmdXOver($range = null) { - // Deprecated API (the code _is_ still in alpha state). + // deprecated API (the code _is_ still in alpha state) if (func_num_args() > 1) { - exit('The second parameter in cmdXOver() has been deprecated! Use x-y instead...'); + die('The second parameter in cmdXOver() has been ' + . 'deprecated! Use x-y instead...'); } if (is_null($range)) { @@ -1561,7 +2124,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 224, RFC2980: 'Overview information follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS': + case NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1572,24 +2135,53 @@ class Net_NNTP_Protocol_Client extends PEAR } if ($this->_logger) { - $this->_logger->info('Fetched overview ' . ($range == null ? 'for current article' : 'for range: ' . $range)); + $this->_logger->info('Fetched overview ' . + ($range == null ? + 'for current article' : 'for range: ' . $range) + ); } return $data; + break; + + // 412, RFC2980: 'No news group current selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: + return $this->throwError('No news group current selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 420, RFC2980: 'No article(s) selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: + return $this->throwError('No article(s) selected', + $response, $this->_currentStatusResponse() + ); + break; + + // RFC2980: 'no permission' + case 502: + return $this->throwError('No permission', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdListOverviewFmt() + /** - * Returns a list of available headers which are sent from tge news server to the client for every news message. + * Returns a list of avaible headers which are send from newsserver + * to client for every news message * * @return mixed (array) of header names on success or - * (object) pear_error on failure + * (object) pear_error on failure * @access protected */ - protected function cmdListOverviewFmt() + function cmdListOverviewFmt() { $response = $this->_sendCommand('LIST OVERVIEW.FMT'); if ($this->isError($response)){ @@ -1598,7 +2190,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 215, RFC2980: 'information follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW': + case NET_NNTP_PROTOCOL_RESPONSECODE_GROUPS_FOLLOW: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1608,7 +2200,7 @@ class Net_NNTP_Protocol_Client extends PEAR foreach ($data as $line) { - // Check if post fixed by ':full' (case-insensitive) + // Check if postfixed by ':full' (case-insensitive) if (0 == strcasecmp(substr($line, -5, 5), ':full')) { // ':full' is _not_ included in tag, but value set to true $format[substr($line, 0, -5)] = true; @@ -1622,26 +2214,38 @@ class Net_NNTP_Protocol_Client extends PEAR $this->_logger->info('Fetched overview format'); } return $format; + break; + + // RFC2980: 'program error, function not performed' + case 503: + return $this->throwError + ('Internal server error, function not performed', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdXHdr() + /** * * * The format of the returned array is: * $messages[message_id] * - * @param string $field (optional) - * @param string $range (optional) articles to fetch + * @param optional string $field + * @param optional string $range articles to fetch * - * @return mixed (array) nested array of message and there header on success - * (object) pear_error on failure + * @return mixed (array) nested array of message and there header + * on success or (object) pear_error on failure * @access protected */ - protected function cmdXHdr($field, $range = null) + function cmdXHdr($field, $range = null) { if (is_null($range)) { $command = 'XHDR ' . $field; @@ -1656,7 +2260,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 221, RFC2980: 'Header follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_HEAD_FOLLOWS': + case 221: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1669,32 +2273,65 @@ class Net_NNTP_Protocol_Client extends PEAR } return $return; + break; + + // 412, RFC2980: 'No news group current selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: + return $this->throwError('No news group current selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 420, RFC2980: 'No current article selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: + return $this->throwError('No current article selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 430, RFC2980: 'No such article' + case 430: + return $this->throwError('No such article', + $response, $this->_currentStatusResponse() + ); + break; + + // RFC2980: 'no permission' + case 502: + return $this->throwError('No permission', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdXGTitle() + /** - * Fetches a list of (all) available newsgroup descriptions. - * Deprecated as of RFC2980. + * Fetches a list of (all) avaible newsgroup descriptions. + * Depresated as of RFC2980. * - * @param string $wildMat Wildmat of the groups, that is to be listed, defaults to '*'; + * @param string $wildmat Wildmat of the groups, that is + * to be listed, defaults to '*'; * - * @return mixed (array) nested array with description of existing newsgroups on success - * (object) pear_error on failure + * @return mixed (array) nested array with description of + * existing newsgroups on success or (object) pear_error on failure * @access protected */ - protected function cmdXGTitle($wildMat = '*') + function cmdXGTitle($wildmat = '*') { - $response = $this->_sendCommand('XGTITLE '.$wildMat); + $response = $this->_sendCommand('XGTITLE ' . $wildmat); if ($this->isError($response)){ return $response; } switch ($response) { // RFC2980: 'list of groups and descriptions follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_XGTITLE_GROUPS_FOLLOW': + case 282: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1703,31 +2340,43 @@ class Net_NNTP_Protocol_Client extends PEAR $groups = array(); foreach($data as $line) { - preg_match('/^(.*?)\s(.*?$)/', trim($line), $matches); + preg_match("/^(.*?)\s(.*?$)/", trim($line), $matches); $groups[$matches[1]] = (string) $matches[2]; } return $groups; + break; + + case 481: // RFC2980: 'Groups and descriptions unavailable' + return $this->throwError + ('Groups and descriptions unavailable', + $response, $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdXROver() + /** * Fetch message references from message number $first to $last * - * @param string $range (optional) articles to fetch + * @param optional string $range articles to fetch * - * @return mixed (array) assoc. array of message references on success - * (object) pear_error on failure + * @return mixed (array) assoc. array of message references on + * success or (object) pear_error on failure * @access protected */ - protected function cmdXROver($range = null) + function cmdXROver($range = null) { // Warn about deprecated API (the code _is_ still in alpha state) if (func_num_args() > 1 ) { - exit('The second parameter in cmdXROver() has been deprecated! Use x-y instead...'); + die('The second parameter in cmdXROver() has been ' + . 'deprecated! Use x-y instead...'); } if (is_null($range)) { @@ -1743,7 +2392,7 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 224, RFC2980: 'Overview information follows' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS': + case NET_NNTP_PROTOCOL_RESPONSECODE_OVERVIEW_FOLLOWS: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -1755,30 +2404,57 @@ class Net_NNTP_Protocol_Client extends PEAR $return[$line[0]] = $line[1]; } return $return; + break; + + // 412, RFC2980: 'No news group current selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: + return $this->throwError('No news group current selected', + $response, $this->_currentStatusResponse() + ); + break; + + // 420, RFC2980: 'No article(s) selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: + return $this->throwError('No article(s) selected', + $response, $this->_currentStatusResponse() + ); + break; + + // RFC2980: 'no permission' + case 502: + return $this->throwError('No permission', $response, + $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdXPat() + /** * * * @param string $field * @param string $range - * @param mixed $wildMat + * @param mixed $wildmat * - * @return mixed (array) nested array of message and there headers on success - * (object) pear_error on failure + * @return mixed (array) nested array of message and there + * headers on success or (object) pear_error on failure * @access protected */ - protected function cmdXPat($field, $range, $wildMat) + function cmdXPat($field, $range, $wildmat) { - if (is_array($wildMat)) { - $wildMat = implode(' ', $wildMat); + if (is_array($wildmat)) { + $wildmat = implode(' ', $wildmat); } - $response = $this->_sendCommand('XPAT ' . $field . ' ' . $range . ' ' . $wildMat); + $response = $this->_sendCommand('XPAT ' . $field . ' ' . + $range . ' ' . $wildmat + ); if ($this->isError($response)){ return $response; } @@ -1797,12 +2473,28 @@ class Net_NNTP_Protocol_Client extends PEAR } return $return; + break; + + case 430: // 430, RFC2980: 'No such article' + return $this->throwError('No current article selected', + $response, $this->_currentStatusResponse() + ); + break; + + case 502: // RFC2980: 'no permission' + return $this->throwError('No permission', $response, + $this->_currentStatusResponse() + ); + break; default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdAuthinfo() + /** * Authenticate using 'original' method * @@ -1810,11 +2502,11 @@ class Net_NNTP_Protocol_Client extends PEAR * @param string $pass The password to authenticate with. * * @return mixed (bool) true on success or - * (object) pear_error on failure - * + * (object) pear_error on failure * @access protected */ - protected function cmdAuthinfo($user, $pass) { + function cmdAuthinfo($user, $pass) + { // Send the username $response = $this->_sendCommand('AUTHINFO user '.$user); if ($this->isError($response)) { @@ -1839,12 +2531,39 @@ class Net_NNTP_Protocol_Client extends PEAR // TODO: Set some variable before return return true; + break; + + case 381: // RFC2980: 'More authentication information required' + return $this->throwError('Authentication uncompleted', + $response, $this->_currentStatusResponse() + ); + break; + + case 482: // RFC2980: 'Authentication rejected' + return $this->throwError('Authentication rejected', + $response, $this->_currentStatusResponse() + ); + break; + + case 502: // RFC2980: 'No permission' + return $this->throwError('Authentication rejected', + $response, $this->_currentStatusResponse() + ); + break; + + /*case 500: + case 501: + return $this->throwError('Authentication failed', $response, $this->_currentStatusResponse()); + break;*/ default: - return $this->_handleErrorResponse($response); + return $this->_handleUnexpectedResponse($response); } } + // }}} + // {{{ cmdAuthinfoSimple() + /** * Authenticate using 'simple' method * @@ -1854,137 +2573,60 @@ class Net_NNTP_Protocol_Client extends PEAR * @return mixed (bool) true on success or (object) pear_error on failure * @access protected */ - protected function cmdAuthinfoSimple($user, $pass) { - return $this->throwError("The auth mode: 'simple' is has not been implemented yet", null); + function cmdAuthinfoSimple($user, $pass) + { + return $this->throwError + ("The auth mode: 'simple' is has not been implemented yet", + null + ); } + // }}} + // {{{ cmdAuthinfoGeneric() + /** * Authenticate using 'generic' method * * @param string $user The username to authenticate as. * @param string $pass The password to authenticate with. * - * @return mixed (bool) true on success - * (object) pear_error on failure + * @return mixed (bool) true on success or (object) pear_error on failure * @access protected */ - protected function cmdAuthinfoGeneric($user, $pass) { - return $this->throwError("The auth mode: 'generic' is has not been implemented yet", null); + function cmdAuthinfoGeneric($user, $pass) + { + return $this->throwError + ("The auth mode: 'generic' is has not been implemented yet", + null + ); } + // }}} + // {{{ _isConnected() + /** * Test whether we are connected or not. * - * @param bool $feof Check for the end of file pointer. - * * @return bool true or false * @access protected */ - protected function _isConnected($feof = true) + function _isConnected() { - return (is_resource($this->_socket) && ($feof ? !feof($this->_socket) : true)); + return (is_resource($this->_socket) && (!feof($this->_socket))); } - /** - * Verify NNTP error code and return PEAR error. - * - * @param int $response NET_NNTP Response code - * - * @return object PEAR error - * @access protected - */ - protected function _handleErrorResponse(&$response) - { - switch ($response) { + // }}} - // 381, RFC2980: 'More authentication information required' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_AUTHENTICATION_CONTINUE': - return $this->throwError('More authentication information required', $response, $this->_currentStatusResponse()); +} - // 400, RFC977: 'Service discontinued' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_DISCONNECTING_FORCED': - return $this->throwError('Server refused connection', $response, $this->_currentStatusResponse()); +// }}} - // 411, RFC977: 'no such news group' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_GROUP': - return $this->throwError('No such news group on server', $response, $this->_currentStatusResponse()); +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * c-hanging-comment-ender-p: nil + * End: + */ - // 412, RFC2980: 'No news group current selected' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED': - return $this->throwError('No news group current selected', $response, $this->_currentStatusResponse()); - - // 420, RFC2980: 'Current article number is invalid' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED': - return $this->throwError('Current article number is invalid', $response, $this->_currentStatusResponse()); - - // 421, RFC977: 'no next article in this group' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_NO_NEXT_ARTICLE': - return $this->throwError('No next article in this group', $response, $this->_currentStatusResponse()); - - // 422, RFC977: 'no previous article in this group' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_NO_PREVIOUS_ARTICLE': - return $this->throwError('No previous article in this group', $response, $this->_currentStatusResponse()); - - // 423, RFC977: 'No such article number in this group' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER': - return $this->throwError('No such article number in this group', $response, $this->_currentStatusResponse()); - - // 430, RFC977: 'No such article found' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID': - return $this->throwError('No such article found', $response, $this->_currentStatusResponse()); - - // 435, RFC977: 'Article not wanted' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_UNWANTED': - return $this->throwError('Article not wanted', $response, $this->_currentStatusResponse()); - - // 436, RFC977: 'Transfer failed - try again later' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_FAILURE': - return $this->throwError('Transfer failed - try again later', $response, $this->_currentStatusResponse()); - - // 437, RFC977: 'Article rejected - do not try again' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_REJECTED': - return $this->throwError('Article rejected - do not try again', $response, $this->_currentStatusResponse()); - - // 440, RFC977: 'posting not allowed' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_PROHIBITED': - return $this->throwError('Posting not allowed', $response, $this->_currentStatusResponse()); - - // 441, RFC977: 'posting failed' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_FAILURE': - return $this->throwError('Posting failed', $response, $this->_currentStatusResponse()); - - // 481, RFC2980: 'Groups and descriptions unavailable' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_XGTITLE_GROUPS_UNAVAILABLE': - return $this->throwError('Groups and descriptions unavailable', $response, $this->_currentStatusResponse()); - - // 482, RFC2980: 'Authentication rejected' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_AUTHENTICATION_REJECTED': - return $this->throwError('Authentication rejected', $response, $this->_currentStatusResponse()); - - // 500, RFC977: 'Command not recognized' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_UNKNOWN_COMMAND': - return $this->throwError('Command not recognized', $response, $this->_currentStatusResponse()); - - // 501, RFC977: 'Command syntax error' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_SYNTAX_ERROR': - return $this->throwError('Command syntax error', $response, $this->_currentStatusResponse()); - - // 502, RFC2980: 'No permission' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED': - return $this->throwError('No permission', $response, $this->_currentStatusResponse()); - - // 503, RFC2980: 'Program fault - command not performed' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_NOT_SUPPORTED': - return $this->throwError('Internal server error, function not performed', $response, $this->_currentStatusResponse()); - - // RFC4642: 'Can not initiate TLS negotiation' - case 'NET_NNTP_PROTOCOL_RESPONSECODE_TLS_FAILED_NEGOTIATION': - return $this->throwError('Can not initiate TLS negotiation', $response, $this->_currentStatusResponse()); - - default: - $text = $this->_currentStatusResponse(); - return $this->throwError("Unexpected response: '$text'", $response, $text); - } - } - -} \ No newline at end of file +?> \ No newline at end of file From 68505bf6cf89692dd0911295621c8d08e5aeef6e Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 15:29:12 +0200 Subject: [PATCH 18/20] Change in handling games processing in monitor --- bin/monitor.php | 4 +- .../www/lib/Net_NNTP/NNTP/Protocol/Client.php | 103 ++++++++++++++++++ 2 files changed, 105 insertions(+), 2 deletions(-) diff --git a/bin/monitor.php b/bin/monitor.php index 9010c3888..5a8c60782 100644 --- a/bin/monitor.php +++ b/bin/monitor.php @@ -1658,11 +1658,11 @@ while ($i > 0) { } //Process Games in pane 2.5 once if needed then exits - if (($maxload >= get_load()) && ($post_amazon == 1) && ($console_releases_proc > 0)) { + if (($maxload >= get_load()) && ($post_amazon == 1) && ($console_releases_proc > 0) && ($pc_releases_proc > 0)) { $color = get_color($colors_start, $colors_end, $colors_exc); $log = writelog($panes2[5]); shell_exec("tmux respawnp -t${tmux_session}:2.5 'echo \"\033[38;5;\"$color\"m\" && cd $_bin && $_php postprocess_new.php console 2>&1 $log && $_php postprocess_new.php games 2>&1 $log && $_sleep $post_timer_amazon && echo \" \033[1;0;33m\"' 2>&1 1> /dev/null"); - } else if (($maxload >= get_load()) && ($post_amazon == 1) && ($console_releases_proc == 0)) { + } else if (($maxload >= get_load()) && ($post_amazon == 1) && ($console_releases_proc == 0) && ($pc_releases_proc > 0)) { $color = get_color($colors_start, $colors_end, $colors_exc); shell_exec("tmux respawnp -t${tmux_session}:2.5 'echo \"\033[38;5;\"$color\"m\n$panes2[5] has been disabled/terminated by No Games to process\"'"); } else if ($maxload <= get_load()) { diff --git a/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php b/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php index 0a8fe8cb8..0462eaa32 100644 --- a/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php +++ b/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php @@ -2617,6 +2617,109 @@ class Net_NNTP_Protocol_Client extends PEAR // }}} + /** + * Verify NNTP error code and return PEAR error. + * + * @param int $response NET_NNTP Response code + * + * @return object PEAR error + * @access protected + */ + protected function _handleErrorResponse(&$response) + { + switch ($response) { + + // 381, RFC2980: 'More authentication information required' + case NET_NNTP_PROTOCOL_RESPONSECODE_AUTHENTICATION_CONTINUE: + return $this->throwError('More authentication information required', $response, $this->_currentStatusResponse()); + + // 400, RFC977: 'Service discontinued' + case NET_NNTP_PROTOCOL_RESPONSECODE_DISCONNECTING_FORCED: + return $this->throwError('Server refused connection', $response, $this->_currentStatusResponse()); + + // 411, RFC977: 'no such news group' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_GROUP: + return $this->throwError('No such news group on server', $response, $this->_currentStatusResponse()); + + // 412, RFC2980: 'No news group current selected' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: + return $this->throwError('No news group current selected', $response, $this->_currentStatusResponse()); + + // 420, RFC2980: 'Current article number is invalid' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: + return $this->throwError('Current article number is invalid', $response, $this->_currentStatusResponse()); + + // 421, RFC977: 'no next article in this group' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_NEXT_ARTICLE: + return $this->throwError('No next article in this group', $response, $this->_currentStatusResponse()); + + // 422, RFC977: 'no previous article in this group' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_PREVIOUS_ARTICLE: + return $this->throwError('No previous article in this group', $response, $this->_currentStatusResponse()); + + // 423, RFC977: 'No such article number in this group' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: + return $this->throwError('No such article number in this group', $response, $this->_currentStatusResponse()); + + // 430, RFC977: 'No such article found' + case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: + return $this->throwError('No such article found', $response, $this->_currentStatusResponse()); + + // 435, RFC977: 'Article not wanted' + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_UNWANTED: + return $this->throwError('Article not wanted', $response, $this->_currentStatusResponse()); + + // 436, RFC977: 'Transfer failed - try again later' + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_FAILURE: + return $this->throwError('Transfer failed - try again later', $response, $this->_currentStatusResponse()); + + // 437, RFC977: 'Article rejected - do not try again' + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_REJECTED: + return $this->throwError('Article rejected - do not try again', $response, $this->_currentStatusResponse()); + + // 440, RFC977: 'posting not allowed' + case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_PROHIBITED: + return $this->throwError('Posting not allowed', $response, $this->_currentStatusResponse()); + + // 441, RFC977: 'posting failed' + case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_FAILURE: + return $this->throwError('Posting failed', $response, $this->_currentStatusResponse()); + + // 481, RFC2980: 'Groups and descriptions unavailable' + case NET_NNTP_PROTOCOL_RESPONSECODE_XGTITLE_GROUPS_UNAVAILABLE: + return $this->throwError('Groups and descriptions unavailable', $response, $this->_currentStatusResponse()); + + // 482, RFC2980: 'Authentication rejected' + case NET_NNTP_PROTOCOL_RESPONSECODE_AUTHENTICATION_REJECTED: + return $this->throwError('Authentication rejected', $response, $this->_currentStatusResponse()); + + // 500, RFC977: 'Command not recognized' + case NET_NNTP_PROTOCOL_RESPONSECODE_UNKNOWN_COMMAND: + return $this->throwError('Command not recognized', $response, $this->_currentStatusResponse()); + + // 501, RFC977: 'Command syntax error' + case NET_NNTP_PROTOCOL_RESPONSECODE_SYNTAX_ERROR: + return $this->throwError('Command syntax error', $response, $this->_currentStatusResponse()); + + // 502, RFC2980: 'No permission' + case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: + return $this->throwError('No permission', $response, $this->_currentStatusResponse()); + + // 503, RFC2980: 'Program fault - command not performed' + case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_SUPPORTED: + return $this->throwError('Internal server error, function not performed', $response, $this->_currentStatusResponse()); + + // RFC4642: 'Can not initiate TLS negotiation' + case NET_NNTP_PROTOCOL_RESPONSECODE_TLS_FAILED_NEGOTIATION: + return $this->throwError('Can not initiate TLS negotiation', $response, $this->_currentStatusResponse()); + + default: + $text = $this->_currentStatusResponse(); + + return $this->throwError("Unexpected response: '$text'", $response, $text); + } + } + } // }}} From 5c53d7fbaa3f6ad990a32612f9a9255f4b9bad75 Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 15:36:39 +0200 Subject: [PATCH 19/20] More changes to nntp. --- .../www/lib/Net_NNTP/NNTP/Protocol/Client.php | 1534 +++++------------ .../Net_NNTP/NNTP/Protocol/Responsecode.php | 34 +- 2 files changed, 428 insertions(+), 1140 deletions(-) diff --git a/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php b/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php index 0462eaa32..1d0f24c77 100644 --- a/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php +++ b/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Client.php @@ -69,16 +69,10 @@ // Warn about PHP bugs if (version_compare(PHP_VERSION, '5.2.11') === 0) { - trigger_error('PHP bug #16657 breaks feof() on socket streams! ' - . 'Connection consistency might be compromised!', E_USER_WARNING - ); + trigger_error('PHP bug #16657 breaks feof() on socket streams! Connection consistency might be compromised!', E_USER_WARNING); } -/** - * - */ require_once 'PEAR.php'; -//require_once 'Net/NNTP/Error.php'; require_once 'Responsecode.php'; // {{{ constants @@ -105,7 +99,7 @@ define('NET_NNTP_PROTOCOL_CLIENT_DEFAULT_PORT', '119'); /** * Low level NNTP Client * - * Implements the client part of the NNTP standard acording to: + * Implements the client part of the NNTP standard according to: * - RFC 977, * - RFC 2980, * - RFC 850/1036, and @@ -117,11 +111,11 @@ define('NET_NNTP_PROTOCOL_CLIENT_DEFAULT_PORT', '119'); * class (and should therefore currently not be extended * directly outside of the Net_NNTP package). Therefore its * API is NOT required to be fully stable, for as long as such - * changes doesn't affect the public API of + * changes do not affect the public API of * the Net_NNTP_Client class, which is considered stable. * - * TODO: cmdListActiveTimes() - * cmdDistribPats() + * TODO: cmdListActiveTimes() + * cmdDistribPats() * * @category Net * @package Net_NNTP @@ -139,119 +133,105 @@ class Net_NNTP_Protocol_Client extends PEAR * The socket resource being used to connect to the NNTP server. * * @var resource - * @access private + * @access protected */ - var $_socket = null; + protected $_socket = null; /** - * Contains the last recieved status response code and text + * Contains the last received status response code and text. * * @var array - * @access private + * @access protected */ - var $_currentStatusResponse = null; + protected $_currentStatusResponse = null; /** - * + * Optional logger class to use for debugging. * * @var object * @access private */ - var $_logger = null; + private $_logger = null; - // }}} - // {{{ constructor + /** + * Seconds to wait for the blocking socket to timeout. + * + * @var int + */ + protected $_socketTimeout = 120; /** * Constructor * * @access public */ - function Net_NNTP_Protocol_Client() + public function Net_NNTP_Protocol_Client() { - // -// parent::PEAR('Net_NNTP_Error'); + // Init PEAR. parent::PEAR(); } - // }}} - // {{{ getPackageVersion() - /** - * + * Get current package version. * * @access public */ - function getPackageVersion() + public function getPackageVersion() { return '1.5.0'; } - // }}} - // {{{ getApiVersion() - /** - * + * Get current API version. * * @access public */ - function getApiVersion() + public function getApiVersion() { return '0.9.0'; } - // }}} - // {{{ setLogger() - /** - * + * Set the debug logger instance object. * * @param object $logger * * @access protected */ - function setLogger($logger) + protected function setLogger($logger) { $this->_logger = $logger; } - // }}} - // {{{ setDebug() - /** * @deprecated */ - function setDebug($debug = true) + public function setDebug($debug = true) { - trigger_error('You are using deprecated API v1.0 in ' - . 'Net_NNTP_Protocol_Client: setDebug() ! Debugging in now ' - . 'automatically handled when a logger is given.', E_USER_NOTICE + trigger_error( + 'You are using deprecated API v1.0 in Net_NNTP_Protocol_Client: setDebug() ! Debugging in now automatically handled when a logger is given.', + E_USER_NOTICE ); } - // }}} - // {{{ _sendCommand() - /** - * Send command + * Send a command to usenet. * * Send a command to the server. A carriage return / linefeed - * (CRLF) sequence will be appended to each command string before - * it is sent to the IMAP server. + * (CRLF) sequence will be appended to each command string before it is sent to the IMAP server. * * @param string $cmd The command to launch, ie: "ARTICLE 1004853" * - * @return mixed (int) response code on success or (object) - * pear_error on failure - * @access private + * @return mixed (int) response code on success + * (object) pear_error on failure + * @access protected */ - function _sendCommand($cmd) + protected function _sendCommand($cmd) { // NNTP/RFC977 only allows command up to 512 (-2) chars. - if (!strlen($cmd) > 510) - return $this->throwError( - 'Failed writing to socket! (Command to long - max 510 chars)' - ); + if (strlen($cmd) > 510) { + return $this->throwError('Failed writing to socket! (Command to long - max 510 chars)'); + } /*************************************************************** * Credit: * @@ -265,190 +245,151 @@ class Net_NNTP_Protocol_Client extends PEAR * Prevent new line (and possible future) characters in the NNTP * commands Net_NNTP does not support pipelined commands. - * Inserting a new line charecter allows sending multiple + * Inserting a new line character allows sending multiple * commands and thereby making the communication between * NET_NNTP and the server out of sync... */ if (preg_match_all('/\r?\n/', $cmd, $matches, PREG_PATTERN_ORDER)) { - foreach ($matches[0] as $key => $match) { - $this->_logger->debug("Illegal character in command: " . - htmlentities(str_replace(array("\r", "\n"), - array("'Carriage Return'", "'New Line'"), $match + if ($this->_logger) { + foreach ($matches[0] as $match) { + $this->_logger->debug( + "Illegal character in command: " . htmlentities(str_replace(array("\r", "\n"), + array("'Carriage Return'", "'New Line'"), $match + ) ) - ) - ); + ); + } } return $this->throwError("Illegal character(s) in NNTP command!"); } - // Check if connected + // Check if connected. if (!$this->_isConnected()) { return $this->throwError('Failed to write to socket! (connection lost!)'); } - // Send the command - $R = @fwrite($this->_socket, $cmd . "\r\n"); - if ($R === false) { + // Send the command. + if (@fwrite($this->_socket, $cmd . "\r\n") === false) { return $this->throwError('Failed to write to socket!'); } - // + // Log sent message. if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { $this->_logger->debug('C: ' . $cmd); } - // return $this->_getStatusResponse(); } - // }}} - // {{{ _getStatusResponse() - /** * Get servers status response after a command. * - * @return mixed (int) statuscode on success or - * (object) pear_error on failure + * @return mixed (int) response code on success + * (object) pear_error on failure * @access private */ - function _getStatusResponse() + private function _getStatusResponse() { - // Retrieve a line (terminated by "\r\n") from the server. - // RFC says max is 510, but IETF says "be liberal in what you accept"... + // Retrieve a line (terminated by "\r\n") from the server. RFC says max is 510, but IETF says "be liberal in what you accept"... $response = @fgets($this->_socket, 4096); if ($response === false) { return $this->throwError('Failed to read from socket...!'); } - // + // Log incoming message. if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { $this->_logger->debug('S: ' . rtrim($response, "\r\n")); } - /* Trim the start of the response in case of - * misplased whitespace (should not be needen!!!) - */ + // Trim the start of the response in case of misplaced whitespace (should not be needed). $response = ltrim($response); - $this->_currentStatusResponse = - array((int)substr($response, 0, 3), - (string)rtrim(substr($response, 4)) - ); + // Store the response in an array, 0 => response code, 1 => response message. + $this->_currentStatusResponse = array((int)substr($response, 0, 3), (string)rtrim(substr($response, 4))); - // return $this->_currentStatusResponse[0]; } - // }}} - // {{{ _getTextResponse() - /** * Retrieve textural data * * Get data until a line with only a '.' in it is read and return data. * - * @return mixed (array) text response on success or - * (object) pear_error on failure - * @access private + * @return mixed (array) text response on success + * (object) pear_error on failure + * @access protected */ - function _getTextResponse() + protected function _getTextResponse() { + // Buffer to hold the received lines. $data = array(); - $line = ''; - // - $debug = $this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG); + $debug = ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)); - // Continue until connection is lost + // Continue until connection is lost. while (!feof($this->_socket)) { // Retrieve and append up to 1024 characters from the server. - $recieved = @fgets($this->_socket, 1024); + $line = @fgets($this->_socket, 1024); - if ($recieved === false) { + if ($line === false) { return $this->throwError('Failed to read line from socket.', null); } - $line .= $recieved; - - // Continue if the line is not terminated by CRLF - if (substr($line, -2) != "\r\n" || strlen($line) < 2) { + // Continue if the line is not terminated by CR LF. + if (substr($line, -2) !== "\r\n" || strlen($line) < 2) { continue; } - // Validate recieved line - if (false) { - // Lines should/may not be longer than 998+2 chars (RFC2822 2.3) - if (strlen($line) > 1000) { - if ($this->_logger) { - $this->_logger->notice('Max line length...'); - } - - return $this->throwError('Invalid line recieved!', null); - } - } - - // Remove CRLF from the end of the line + // Remove CR LF from the end of the line. $line = substr($line, 0, -2); - // Check if the line terminates the textresponse - if ($line == '.') { + // Check if the line terminates the text response. + if ($line === '.') { if ($this->_logger) { $this->_logger->debug('T: ' . $line); } - // return all previous lines + // Return all previous lines. return $data; } - // If 1st char is '.' it's doubled (NNTP/RFC977 2.4.1) - if (substr($line, 0, 2) == '..') { + // If 1st char is '.' it's doubled (NNTP/RFC977 2.4.1). + if (substr($line, 0, 2) === '..') { $line = substr($line, 1); } - // if ($debug) { $this->_logger->debug('T: ' . $line); } - // Add the line to the array of lines + // Add the line to the array of lines. $data[] = $line; - - // Reset/empty $line - $line = ''; } if ($this->_logger) { - $this->_logger->warning('Broke out of reception loop! ' - . 'This souldn\'t happen unless connection has been lost?' - ); + $this->_logger->warning('Broke out of reception loop! This souldn\'t happen unless connection has been lost?'); } - // return $this->throwError('End of stream! Connection lost?', null); } - // }}} - // {{{ _sendText() - /** + * Send an article to usenet. * + * @note Data should be in the format specified by RFC850. * * @access private */ - function _sendArticle($article) + private function _sendArticle($article) { - /* data should be in the format specified by RFC850 */ - switch (true) { case is_string($article): - // @fwrite($this->_socket, $article); @fwrite($this->_socket, "\r\n.\r\n"); - // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { foreach (explode("\r\n", $article) as $line) { $this->_logger->debug('D: ' . $line); @@ -473,7 +414,6 @@ class Net_NNTP_Protocol_Client extends PEAR @fwrite($this->_socket, $header); @fwrite($this->_socket, "\r\n"); - // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { foreach (explode("\r\n", $header) as $line) { $this->_logger->debug('D: ' . $line); @@ -492,7 +432,6 @@ class Net_NNTP_Protocol_Client extends PEAR @fwrite($this->_socket, $body); @fwrite($this->_socket, "\r\n.\r\n"); - // if ($this->_logger && $this->_logger->_isMasked(PEAR_LOG_DEBUG)) { foreach (explode("\r\n", $body) as $line) { $this->_logger->debug('D: ' . $line); @@ -508,116 +447,63 @@ class Net_NNTP_Protocol_Client extends PEAR return true; } - // }}} - // {{{ _currentStatusResponse() - /** + * Return the last received response message. * - * - * @return string status text + * @return string The response message. * @access private */ - function _currentStatusResponse() + private function _currentStatusResponse() { return $this->_currentStatusResponse[1]; } - // }}} - // {{{ _handleUnexpectedResponse() - - /** - * - * - * @param int $code Status code number - * @param string $text Status text - * - * @return mixed - * @access private - */ - function _handleUnexpectedResponse($code = null, $text = null) - { - if ($code === null) { - $code = $this->_currentStatusResponse[0]; - } - - if ($text === null) { - $text = $this->_currentStatusResponse(); - } - - switch ($code) { - /* 502, 'access restriction or permission denied' - * / service permanently unavailable - */ - case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: - return $this->throwError('Command not permitted / Access' - . ' restriction / Permission denied', $code, $text - ); - break; - default: - return $this->throwError("Unexpected response: '$text'", - $code, $text - ); - } - } - - // }}} - /* Session administration commands */ - // {{{ Connect() - /** * Connect to a NNTP server * - * @param string $host (optional) The address of the - * NNTP-server to connect to, defaults to 'localhost'. - * @param mixed $encryption (optional) - * @param int $port (optional) The port number to connect to, - * defaults to 119. - * @param int $timeout (optional) + * @param string $host (optional) The address of the NNTP-server to connect to, defaults to 'localhost'. + * @param mixed $encryption (optional) Use TLS/SSL on the connection? + * (string) 'tcp' => Use no encryption. + * 'ssl', 'sslv3', 'tls' => Use encryption. + * (null)|(false) Use no encryption. + * @param int $port (optional) The port number to connect to, defaults to 119. + * @param int $timeout (optional) How many seconds to wait before giving up when connecting. + * @param int $socketTimeout (optional) How many seconds to wait before timing out the (blocked) socket. * - * @return mixed (bool) on success (true when posting allowed, - * otherwise false) or (object) pear_error on failure + * @return mixed (bool) On success: True when posting allowed, otherwise false. + * (object) On failure: pear_error * @access protected */ - function connect($host = null, $encryption = null, $port = null, $timeout = 15) + protected function connect($host = null, $encryption = null, $port = null, $timeout = 15, $socketTimeout = 120) { - // if ($this->_isConnected() ) { return $this->throwError('Already connected, disconnect first!', null); } // v1.0.x API if (is_int($encryption)) { - trigger_error('You are using deprecated API v1.0 in ' - . 'Net_NNTP_Protocol_Client: connect() !', E_USER_NOTICE - ); + trigger_error('You are using deprecated API v1.0 in Net_NNTP_Protocol_Client: connect() !', E_USER_NOTICE); $port = $encryption; $encryption = false; } - // if (is_null($host)) { $host = 'localhost'; } - /* Choose transport based on encryption, and if no port is - * given, use default for that encryption - */ + // Choose transport based on encryption, and if no port is given, use default for that encryption. switch ($encryption) { case null: - case 'tcp': - case false: $transport = 'tcp'; $port = is_null($port) ? 119 : $port; break; case 'sslv3': - case 'ssl': - case 'tls': $transport = $encryption; $port = is_null($port) ? 563 : $port; @@ -629,29 +515,40 @@ class Net_NNTP_Protocol_Client extends PEAR return $this->throwError($message); } - // Open Connection - $R = @stream_socket_client($transport . '://' . $host . ':' . $port, $errno, $errstr, $timeout); - if ($R === false) { + // Attempt to connect to usenet. + $socket = @stream_socket_client( + $transport . '://' . $host . ':' . $port, $errorNumber, $errorString, $timeout + ); + + if ($socket === false) { + $message = "Connection to $transport://$host:$port failed."; + if (preg_match('/tls|ssl/', $transport)) { $message .= ' Try disabling SSL/TLS, and/or try a different port.'; } - $message .= ' [ERROR ' . $errno . ': ' . $errstr . ']'; + + $message .= ' [ERROR ' . $errorNumber . ': ' . $errorString . ']'; + if ($this->_logger) { $this->_logger->notice($message); } return $this->throwError($message); } - $this->_socket = $R; - stream_set_timeout($this->_socket, 120); + // Store the socket resource as property. + $this->_socket = $socket; + + $this->_socketTimeout = (is_numeric($socketTimeout) ? $socketTimeout : $this->_socketTimeout); + + // Set the socket timeout. + stream_set_timeout($this->_socket, $this->_socketTimeout); - // if ($this->_logger) { $this->_logger->info("Connection to $transport://$host:$port has been established."); } - // Retrive the server's initial response. + // Retrieve the server's initial response. $response = $this->_getStatusResponse(); if ($this->isError($response)) { return $response; @@ -662,65 +559,30 @@ class Net_NNTP_Protocol_Client extends PEAR case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_ALLOWED: // TODO: Set some variable before return return true; - break; // 201, Posting NOT allowed case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED: - // if ($this->_logger) { $this->_logger->info('Posting not allowed!'); } // TODO: Set some variable before return return false; - break; - - case 400: - return $this->throwError('Server refused connection', - $response, $this->_currentStatusResponse() - ); - break; - - /* 502, 'access restriction or permission denied' - * / service permanently unavailable - */ - case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: - return $this->throwError('Server refused connection', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ disconnect() - - /** - * alias for cmdQuit() - * - * @access protected - */ - function disconnect() - { - return $this->cmdQuit(); - } - - // }}} - // {{{ cmdCapabilities() - /** * Returns servers capabilities * - * @return mixed (array) list of capabilities on success or - * (object) pear_error on failure + * @return mixed (array) list of capabilities on success or + * (object) pear_error on failure * @access protected */ - function cmdCapabilities() + protected function cmdCapabilities() { - // tell the newsserver we want an article $response = $this->_sendCommand('CAPABILITIES'); if ($this->isError($response)) { return $response; @@ -734,26 +596,21 @@ class Net_NNTP_Protocol_Client extends PEAR return $data; } return $data; - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdModeReader() - /** * * - * @return mixed (bool) true when posting allowed, false when - * postind disallowed or (object) pear_error on failure + * @return mixed (bool) true when posting allowed, false when posting disallowed + * (object) pear_error on failure * @access protected */ - function cmdModeReader() + protected function cmdModeReader() { - // tell the newsserver we want an article $response = $this->_sendCommand('MODE READER'); if ($this->isError($response)) { return $response; @@ -764,7 +621,6 @@ class Net_NNTP_Protocol_Client extends PEAR case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_ALLOWED: // TODO: Set some variable before return return true; - break; // 201, RFC2980: 'Hello, you can't post' case NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED: @@ -773,46 +629,43 @@ class Net_NNTP_Protocol_Client extends PEAR } // TODO: Set some variable before return return false; - break; - - /* 502, 'access restriction or permission denied' - * / service permanently unavailable - */ - case NET_NNTP_PROTOCOL_RESPONSECODE_NOT_PERMITTED: - return $this->throwError('Connection being closed, ' - . 'since service so permanently unavailable', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdQuit() + /** + * Alias for cmdQuit() + * + * @access protected + */ + protected function disconnect() + { + return $this->cmdQuit(); + } /** * Disconnect from the NNTP server * - * @return mixed (bool) true on success or - * (object) pear_error on failure + * @return mixed (bool) true on success + * (object) pear_error on failure * @access protected */ - function cmdQuit() + protected function cmdQuit() { - // Tell the server to close the connection $response = $this->_sendCommand('QUIT'); if ($this->isError($response)) { return $response; } switch ($response) { - case 205: // RFC977: 'closing connection - goodbye!' + // RFC977: 'closing connection - goodbye!' + case NET_NNTP_PROTOCOL_RESPONSECODE_DISCONNECTING_REQUESTED: // If socket is still open, close it. - if ($this->_isConnected()) { - fclose($this->_socket); + $disconnected = true; + if ($this->_isConnected(false)) { + $disconnected = (bool)stream_socket_shutdown($this->_socket, STREAM_SHUT_RDWR); } if ($this->_logger) { @@ -821,27 +674,20 @@ class Net_NNTP_Protocol_Client extends PEAR $this->_currentStatusResponse = null; $this->_socket = null; - return true; - break; + return $disconnected; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - - // }}} - - /* */ - - // {{{ cmdStartTLS() - /** + * Request TLS encryption to the news server. * - * - * @return mixed (bool) on success or (object) pear_error on failure + * @return mixed (bool) on success + * (object) pear_error on failure * @access protected */ - function cmdStartTLS() + protected function cmdStartTLS() { $response = $this->_sendCommand('STARTTLS'); if ($this->isError($response)) { @@ -849,73 +695,51 @@ class Net_NNTP_Protocol_Client extends PEAR } switch ($response) { - case 382: // RFC4642: 'continue with TLS negotiation' - $encrypted = stream_socket_enable_crypto($this->_socket, - true, STREAM_CRYPTO_METHOD_TLS_CLIENT - ); + // RFC4642: 'continue with TLS negotiation' + case NET_NNTP_PROTOCOL_RESPONSECODE_TLS_AUTHENTICATION_CONTINUE: + $encrypted = stream_socket_enable_crypto($this->_socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); switch (true) { case $encrypted === true: if ($this->_logger) { $this->_logger->info('TLS encryption started.'); } return true; - break; - case $encrypted === true: + case $encrypted === false: if ($this->_logger) { $this->_logger->info('TLS encryption failed.'); } - return $this->throwError('Could not initiate ' - . 'TLS negotiation', $response, - $this->_currentStatusResponse() - ); - break; + return $this->throwError('Could not initiate TLS negotiation', $response, $this->_currentStatusResponse()); case is_int($encrypted): - return $this->throwError('', $response, - $this->_currentStatusResponse() - ); - break; + return $this->throwError('TLS encryption failed.', $response, $this->_currentStatusResponse()); default: - return $this->throwError('Internal error - ' - . 'unknown response from' - . 'stream_socket_enable_crypto()', - $response, $this->_currentStatusResponse() + return $this->throwError( + 'Internal error - unknown response from stream_socket_enable_crypto()', + $response, + $this->_currentStatusResponse() ); } - break; - - case 580: // RFC4642: 'can not initiate TLS negotiation' - return $this->throwError('', $response, - $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - - /* Article posting and retrieval */ - /* Group and article selection */ - // {{{ cmdGroup() - /** * Selects a news group (issue a GROUP command to the server) * * @param string $newsgroup The newsgroup name * - * @return mixed (array) groupinfo on success or - * (object) pear_error on failure + * @return mixed (array) group info on success + * (object) pear_error on failure * @access protected */ - function cmdGroup($newsgroup) + protected function cmdGroup($newsgroup) { $response = $this->_sendCommand('GROUP '.$newsgroup); if ($this->isError($response)) { @@ -925,49 +749,35 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 211, RFC977: 'n f l s group selected' case NET_NNTP_PROTOCOL_RESPONSECODE_GROUP_SELECTED: - $response_arr = explode(' ', - trim($this->_currentStatusResponse()) - ); + $response_arr = explode(' ', trim($this->_currentStatusResponse())); if ($this->_logger) { - $this->_logger->info('Group selected: ' - . $response_arr[3] - ); + $this->_logger->info('Group selected: ' . $response_arr[3]); } - return array('group' => $response_arr[3], - 'first' => $response_arr[1], - 'last' => $response_arr[2], - 'count' => $response_arr[0] + return array( + 'group' => $response_arr[3], + 'first' => $response_arr[1], + 'last' => $response_arr[2], + 'count' => $response_arr[0] ); - break; - - // 411, RFC977: 'no such news group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_GROUP: - return $this->throwError('No such news group on server', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdListgroup() - /** + * Gets a group overview. * + * @param string $newsgroup (optional) + * @param mixed $range (optional) * - * @param optional string $newsgroup - * @param optional mixed $range - * - * @return optional mixed (array) on success or - * (object) pear_error on failure + * @return mixed (array) On success + * (object) pear_error On failure * @access protected */ - function cmdListgroup($newsgroup = null, $range = null) + protected function cmdListgroup($newsgroup = null, $range = null) { if (is_null($newsgroup)) { $command = 'LISTGROUP'; @@ -993,193 +803,110 @@ class Net_NNTP_Protocol_Client extends PEAR return $articles; } - $response_arr = explode(' ', - trim($this->_currentStatusResponse()), 4 - ); + $response_arr = explode(' ', trim($this->_currentStatusResponse()), 4); - /* If server does not return group summary in - * status response, return null'ed array - */ + // If server does not return group summary in status response, return null array. if (!is_numeric($response_arr[0]) || !is_numeric($response_arr[1]) || !is_numeric($response_arr[2]) || empty($response_arr[3]) ) { - return array('group' => null, - 'first' => null, - 'last' => null, - 'count' => null, - 'articles' => $articles + return array( + 'group' => null, + 'first' => null, + 'last' => null, + 'count' => null, + 'articles' => $articles ); } - return array('group' => $response_arr[3], - 'first' => $response_arr[1], - 'last' => $response_arr[2], - 'count' => $response_arr[0], - 'articles' => $articles + return array( + 'group' => $response_arr[3], + 'first' => $response_arr[1], + 'last' => $response_arr[2], + 'count' => $response_arr[0], + 'articles' => $articles ); - break; - - // 412, RFC2980: 'Not currently in newsgroup' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('Not currently in newsgroup', - $response, $this->_currentStatusResponse() - ); - break; - - // RFC2980: 'no permission' - case 502: - return $this->throwError('No permission', $response, - $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdLast() - /** + * Select the previous article in current group. * - * - * @return mixed (array) or (string) or (int) or - * (object) pear_error on failure + * @return mixed (array) or (string) or (int) On success + * (object) pear_error On failure * @access protected */ - function cmdLast() + protected function cmdLast() { - // $response = $this->_sendCommand('LAST'); if ($this->isError($response)) { return $response; } switch ($response) { - /* 223, RFC977: 'n a article retrieved - request text - * separately (n = article number, a = unique article id)' - */ + // 223, RFC977: 'n a article retrieved - request text separately (n = article number, a = unique article id)' case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED: - $response_arr = explode(' ', - trim($this->_currentStatusResponse()) - ); + $response_arr = explode(' ', trim($this->_currentStatusResponse())); if ($this->_logger) { - $this->_logger->info('Selected previous article: ' . - $response_arr[0] . ' - ' . $response_arr[1] - ); + $this->_logger->info('Selected previous article: ' . $response_arr[0] . ' - ' . $response_arr[1]); } return array($response_arr[0], (string) $response_arr[1]); - break; - - // 412, RFC977: 'no newsgroup selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No newsgroup has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC977: 'no current article has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No current article has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 422, RFC977: 'no previous article in this group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_PREVIOUS_ARTICLE: - return $this->throwError('No previous article in this group', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdNext() - /** + * Select the next article in current group. * - * - * @return mixed (array) or (string) or (int) or - * (object) pear_error on failure + * @return mixed (array) or (string) or (int) On success + * (object) pear_error On failure * @access protected */ - function cmdNext() + protected function cmdNext() { - // $response = $this->_sendCommand('NEXT'); if ($this->isError($response)) { return $response; } switch ($response) { - /* 223, RFC977: 'n a article retrieved - request text - * separately (n = article number, a = unique article id)' - */ + // 223, RFC977: 'n a article retrieved - request text separately (n = article number, a = unique article id)' case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_SELECTED: $response_arr = explode(' ', trim($this->_currentStatusResponse())); if ($this->_logger) { - $this->_logger->info('Selected previous article: ' . - $response_arr[0] . ' - ' . $response_arr[1] - ); + $this->_logger->info('Selected previous article: ' . $response_arr[0] . ' - ' . $response_arr[1]); } return array($response_arr[0], (string) $response_arr[1]); - break; - - // 412, RFC977: 'no newsgroup selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No newsgroup has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC977: 'no current article has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No current article has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 421, RFC977: 'no next article in this group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_NEXT_ARTICLE: - return $this->throwError('No next article in this group', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - /* Retrieval of articles and article sections */ - // {{{ cmdArticle() - /** * Get an article from the currently open connection. * - * @param mixed $article Either a message-id or a message-number - * of the article to fetch. If null or '', then use current article. + * @param mixed $article Either a message-id or a message-number of the article to fetch. + * If null or '', then use current article. * - * @return mixed (array) article on success or - * (object) pear_error on failure + * @return mixed (array) article on success + * (object) pear_error on failure * @access protected */ - function cmdArticle($article = null) + protected function cmdArticle($article = null) { if (is_null($article)) { $command = 'ARTICLE'; @@ -1187,16 +914,13 @@ class Net_NNTP_Protocol_Client extends PEAR $command = 'ARTICLE ' . $article; } - // tell the newsserver we want an article $response = $this->_sendCommand($command); if ($this->isError($response)) { return $response; } switch ($response) { - /* 220, RFC977: 'n <a> article retrieved - head and - * body follow (n = article number, <a> = message-id)' - */ + // 220, RFC977: 'n <a> article retrieved - head and body follow (n = article number, <a> = message-id)' case NET_NNTP_PROTOCOL_RESPONSECODE_ARTICLE_FOLLOWS: $data = $this->_getTextResponse(); if ($this->isError($data)) { @@ -1204,62 +928,26 @@ class Net_NNTP_Protocol_Client extends PEAR } if ($this->_logger) { - $this->_logger->info(($article == null ? - 'Fetched current article' : 'Fetched article: ' . - $article) - ); + $this->_logger->info(($article == null ? 'Fetched current article' : 'Fetched article: ' . $article)); } return $data; - break; - - // 412, RFC977: 'no newsgroup has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No newsgroup has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC977: 'no current article has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No current article has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 423, RFC977: 'no such article number in this group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: - return $this->throwError('No such article number in this group', - $response, $this->_currentStatusResponse() - ); - break; - - // 430, RFC977: 'no such article found' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: - return $this->throwError('No such article found', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdHead() - /** * Get the headers of an article from the currently open connection. * - * @param mixed $article Either a message-id or a message-number - * of the article to fetch the headers from. If null or '', - * then use current article. + * @param mixed $article Either a message-id or a message-number of the article to fetch the headers from. + * If null or '', then use current article. * - * @return mixed (array) headers on success or - * (object) pear_error on failure + * @return mixed (array) headers on success or + * (object) pear_error on failure * @access protected */ - function cmdHead($article = null) + protected function cmdHead($article = null) { if (is_null($article)) { $command = 'HEAD'; @@ -1267,7 +955,6 @@ class Net_NNTP_Protocol_Client extends PEAR $command = 'HEAD ' . $article; } - // tell the newsserver we want the header of an article $response = $this->_sendCommand($command); if ($this->isError($response)) { return $response; @@ -1282,63 +969,27 @@ class Net_NNTP_Protocol_Client extends PEAR } if ($this->_logger) { - $this->_logger->info(($article == null ? - 'Fetched current article header' : 'Fetched ' - . 'article header for article: ' . $article) - ); + $this->_logger->info(($article == null ? 'Fetched current article header' : 'Fetched article header for article: ' . $article)); } return $data; - break; - - // 412, RFC977: 'no newsgroup has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No newsgroup has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC977: 'no current article has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No current article has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 423, RFC977: 'no such article number in this group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: - return $this->throwError('No such article number in this group', - $response, $this->_currentStatusResponse() - ); - break; - - // 430, RFC977: 'no such article found' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: - return $this->throwError('No such article found', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdBody() - /** * Get the body of an article from the currently open connection. * - * @param mixed $article Either a message-id or a message-number of - * the article to fetch the body from. If null or '', - * then use current article. + * @param mixed $article Either a message-id or a message-number of the article to fetch the body from. + * If null or '', then use current article. * - * @return mixed (array) body on success or - * (object) pear_error on failure + * @return mixed (array) body on success + * (object) pear_error on failure * @access protected */ - function cmdBody($article = null) + protected function cmdBody($article = null) { if (is_null($article)) { $command = 'BODY'; @@ -1346,7 +997,6 @@ class Net_NNTP_Protocol_Client extends PEAR $command = 'BODY ' . $article; } - // tell the newsserver we want the body of an article $response = $this->_sendCommand($command); if ($this->isError($response)) { return $response; @@ -1361,61 +1011,26 @@ class Net_NNTP_Protocol_Client extends PEAR } if ($this->_logger) { - $this->_logger->info(($article == null ? - 'Fetched current article body' : 'Fetched ' - . 'article body for article: ' . $article) - ); + $this->_logger->info(($article == null ? 'Fetched current article body' : 'Fetched article body for article: ' . $article)); } return $data; - break; - - // 412, RFC977: 'no newsgroup has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No newsgroup has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC977: 'no current article has been selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No current article has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 423, RFC977: 'no such article number in this group' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: - return $this->throwError('No such article number in this group', - $response, $this->_currentStatusResponse() - ); - break; - - // 430, RFC977: 'no such article found' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: - return $this->throwError('No such article found', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdStat - /** - * + * Selects an article by article message-number. * * @param mixed $article * - * @return mixed (array) or (string) or (int) or - * (object) pear_error on failure + * @return mixed (array) or (string) or (int) on success + * (object) pear_error on failure * @access protected */ - function cmdStat($article = null) + protected function cmdStat($article = null) { if (is_null($article)) { $command = 'STAT'; @@ -1423,7 +1038,6 @@ class Net_NNTP_Protocol_Client extends PEAR $command = 'STAT ' . $article; } - // tell the newsserver we want an article $response = $this->_sendCommand($command); if ($this->isError($response)) { return $response; @@ -1439,63 +1053,27 @@ class Net_NNTP_Protocol_Client extends PEAR trim($this->_currentStatusResponse())); if ($this->_logger) { - $this->_logger->info('Selected article: ' . - $response_arr[0] . ' - ' . $response_arr[1] - ); + $this->_logger->info('Selected article: ' . $response_arr[0] . ' - ' . $response_arr[1]); } return array($response_arr[0], (string) $response_arr[1]); - break; - - /* 412, RFC977: 'no newsgroup has been selected' - * (actually not documented, but copied from the - * ARTICLE command) - */ - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No newsgroup has been selected', - $response, $this->_currentStatusResponse() - ); - break; - - /* 423, RFC977: 'no such article number in this group' - * (actually not documented, but copied from the - * ARTICLE command) - */ - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: - return $this->throwError('No such article number in this group', - $response, $this->_currentStatusResponse() - ); - break; - - /* 430, RFC977: 'no such article found' (actually not - * documented, but copied from the ARTICLE command) - */ - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID: - return $this->throwError('No such article found', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - /* Article posting */ - // {{{ cmdPost() - /** * Post an article to a newsgroup. * - * @return mixed (bool) true on success or (object) pear_error on failure + * @return mixed (bool) true on success + * (object) pear_error on failure * @access protected */ - function cmdPost() + protected function cmdPost() { - // tell the newsserver we want to post an article $response = $this->_sendCommand('POST'); if ($this->isError($response)) { return $response; @@ -1505,40 +1083,29 @@ class Net_NNTP_Protocol_Client extends PEAR // 340, RFC977: 'send article to be posted. End with <CR-LF>.<CR-LF>' case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_SEND: return true; - break; - // 440, RFC977: 'posting not allowed' - case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_PROHIBITED: - return $this->throwError('Posting not allowed', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdPost2() - /** * Post an article to a newsgroup. * + * @note Should be presented in the format specified by RFC850. + * * @param mixed $article (string/array) * - * @return mixed (bool) true on success or - * (object) pear_error on failure + * @return mixed (bool) true on success + * (object) pear_error on failure * @access protected */ - function cmdPost2($article) + protected function cmdPost2($article) { - /* should be presented in the format specified by RFC850 */ - - // $this->_sendArticle($article); - // Retrive server's response. + // Retrieve server's response. $response = $this->_getStatusResponse(); if ($this->isError($response)) { return $response; @@ -1548,125 +1115,79 @@ class Net_NNTP_Protocol_Client extends PEAR // 240, RFC977: 'article posted ok' case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_SUCCESS: return true; - break; - - // 441, RFC977: 'posting failed' - case NET_NNTP_PROTOCOL_RESPONSECODE_POSTING_FAILURE: - return $this->throwError('Posting failed', $response, - $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdIhave() - /** + * Tell the news server we want to upload an article, the server will check if it has the message-id first. * + * @param string $id Message-ID. * - * @param string $id - * - * @return mixed (bool) true on success or - * (object) pear_error on failure + * @return mixed (bool) true on success + * (object) pear_error on failure * @access protected */ - function cmdIhave($id) + protected function cmdIhave($id) { - // tell the newsserver we want to post an article $response = $this->_sendCommand('IHAVE ' . $id); if ($this->isError($response)) { return $response; } switch ($response) { - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SEND: // 335 - return true; - break; - - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_UNWANTED: // 435 - return $this->throwError('Article not wanted', - $response, $this->_currentStatusResponse() - ); - break; - - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_FAILURE: // 436 - return $this->throwError - ('Transfer not possible; try again later', - $response, $this->_currentStatusResponse() - ); - break; + // 335, RFC997: 'Send article to be transferred' + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SEND: + return true; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdIhave2() - /** + * Tell the news server we have an article to upload, the server will check if it has it first. * + * @note Should be presented in the format specified by RFC850. * * @param mixed $article (string/array) * - * @return mixed (bool) true on success or (object) pear_error on failure + * @return mixed (bool) true on success + * (object) pear_error on failure * @access protected */ - function cmdIhave2($article) + protected function cmdIhave2($article) { - /* should be presented in the format specified by RFC850 */ - - // $this->_sendArticle($article); - // Retrive server's response. + // Retrieve server's response. $response = $this->_getStatusResponse(); if ($this->isError($response)) { return $response; } switch ($response) { - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SUCCESS: // 235 - return true; - break; - - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_FAILURE: // 436 - return $this->throwError - ('Transfer not possible; try again later', - $response, $this->_currentStatusResponse() - ); - break; - - case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_REJECTED: // 437 - return $this->throwError - ('Transfer rejected; do not retry', - $response, $this->_currentStatusResponse() - ); - break; + // 235, RFC977: 'Article transferred OK' + case NET_NNTP_PROTOCOL_RESPONSECODE_TRANSFER_SUCCESS: + return true; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - /* Information commands */ - // {{{ cmdDate() - /** - * Get the date from the newsserver format of returned date + * Get the date from the news server. * - * @return mixed (string) 'YYYYMMDDhhmmss' / (int) timestamp on - * success or (object) pear_error on failure + * @return mixed (string) or (int) 'YYYYMMDDhhmmss', timestamp on success + * (object) pear_error on failure * @access protected */ - function cmdDate() + protected function cmdDate() { $response = $this->_sendCommand('DATE'); if ($this->isError($response)){ @@ -1674,69 +1195,61 @@ class Net_NNTP_Protocol_Client extends PEAR } switch ($response) { - // 111, RFC2980: 'YYYYMMDDhhmmss' + // 111, RFC2980: '(string of numbers representing the date and time)' case NET_NNTP_PROTOCOL_RESPONSECODE_SERVER_DATE: return $this->_currentStatusResponse(); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdHelp() /** - * Returns the server's help text + * Returns the server's help text. * * @return mixed (array) help text on success or - * (object) pear_error on failure + * (object) pear_error on failure * @access protected */ - function cmdHelp() + protected function cmdHelp() { - // tell the newsserver we want an article $response = $this->_sendCommand('HELP'); if ($this->isError($response)) { return $response; } switch ($response) { - case NET_NNTP_PROTOCOL_RESPONSECODE_HELP_FOLLOWS: // 100 - $data = $this->_getTextResponse(); + // 100, RFC977: 'Help text follows' + case NET_NNTP_PROTOCOL_RESPONSECODE_HELP_FOLLOWS: + $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; } return $data; - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdNewgroups() - /** * Fetches a list of all newsgroups created since a specified date. * - * @param int $time Last time you checked for groups (timestamp). - * @param optional string $distributions (deprecaded in rfc draft) + * @param int $time Last time you checked for groups (timestamp). + * @param string $distributions (optional) (deprecaded in rfc draft) * - * @return mixed (array) nested array with informations about - * existing newsgroups on success or (object) pear_error on failure + * @return mixed (array) nested array with informations about existing newsgroups on success + * (object) pear_error on failure * @access protected */ - function cmdNewgroups($time, $distributions = null) + protected function cmdNewgroups($time, $distributions = null) { $date = gmdate('ymd His', $time); if (is_null($distributions)) { $command = 'NEWGROUPS ' . $date . ' GMT'; } else { - $command = 'NEWGROUPS ' . $date . ' GMT <' . - $distributions . '>'; + $command = 'NEWGROUPS ' . $date . ' GMT <' . $distributions . '>'; } $response = $this->_sendCommand($command); @@ -1756,10 +1269,11 @@ class Net_NNTP_Protocol_Client extends PEAR foreach($data as $line) { $arr = explode(' ', trim($line)); - $group = array('group' => $arr[0], - 'last' => $arr[1], - 'first' => $arr[2], - 'posting' => $arr[3] + $group = array( + 'group' => $arr[0], + 'last' => $arr[1], + 'first' => $arr[2], + 'posting' => $arr[3] ); $groups[$group['group']] = $group; @@ -1767,24 +1281,21 @@ class Net_NNTP_Protocol_Client extends PEAR return $groups; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdNewnews() - /** * * - * @param timestamp $time - * @param mixed $newsgroups (string or array of strings) + * @param int $time Unix timestamp. + * @param mixed $newsgroups (string or array of strings) * @param mixed $distribution (string or array of strings) * * @return mixed * @access protected */ - function cmdNewnews($time, $newsgroups, $distribution = null) + protected function cmdNewnews($time, $newsgroups, $distribution = null) { $date = gmdate('ymd His', $time); @@ -1795,15 +1306,15 @@ class Net_NNTP_Protocol_Client extends PEAR if (is_null($distribution)) { $command = 'NEWNEWS ' . $newsgroups . ' ' . $date . ' GMT'; } else { + if (is_array($distribution)) { $distribution = implode(',', $distribution); } - $command = 'NEWNEWS ' . $newsgroups . ' ' . $date . ' GMT <' - . $distribution . '>'; + $command = 'NEWNEWS ' . $newsgroups . ' ' . $date . ' GMT <' . $distribution . '>'; } - // TODO: the lenght of the request string may not exceed 510 chars + // TODO: the length of the request string may not exceed 510 chars. $response = $this->_sendCommand($command); if ($this->isError($response)){ @@ -1818,27 +1329,22 @@ class Net_NNTP_Protocol_Client extends PEAR $messages[] = $line; } return $messages; - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - /* The LIST commands */ - // {{{ cmdList() - /** - * Fetches a list of all avaible newsgroups + * Fetches a list of all available newsgroups. * - * @return mixed (array) nested array with informations about - * existing newsgroups on success or (object) pear_error on failure + * @return mixed (array) nested array with informations about existing newsgroups on success + * (object) pear_error on failure * @access protected */ - function cmdList() + protected function cmdList() { $response = $this->_sendCommand('LIST'); if ($this->isError($response)){ @@ -1857,40 +1363,37 @@ class Net_NNTP_Protocol_Client extends PEAR foreach($data as $line) { $arr = explode(' ', trim($line)); - $group = array('group' => $arr[0], - 'last' => $arr[1], - 'first' => $arr[2], - 'posting' => $arr[3] + $group = array( + 'group' => $arr[0], + 'last' => $arr[1], + 'first' => $arr[2], + 'posting' => $arr[3] ); $groups[$group['group']] = $group; } return $groups; - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdListActive() - /** - * Fetches a list of all avaible newsgroups + * Fetches a list of all available newsgroups. * - * @param string $wildmat + * @param string $wildMat * - * @return mixed (array) nested array with informations about - * existing newsgroups on success or (object) pear_error on failure + * @return mixed (array) nested array with informations about existing newsgroups on success + * (object) pear_error on failure * @access protected */ - function cmdListActive($wildmat = null) + protected function cmdListActive($wildMat = null) { - if (is_null($wildmat)) { + if (is_null($wildMat)) { $command = 'LIST ACTIVE'; } else { - $command = 'LIST ACTIVE ' . $wildmat; + $command = 'LIST ACTIVE ' . $wildMat; } $response = $this->_sendCommand($command); @@ -1910,10 +1413,11 @@ class Net_NNTP_Protocol_Client extends PEAR foreach($data as $line) { $arr = explode(' ', trim($line)); - $group = array('group' => $arr[0], - 'last' => $arr[1], - 'first' => $arr[2], - 'posting' => $arr[3] + $group = array( + 'group' => $arr[0], + 'last' => $arr[1], + 'first' => $arr[2], + 'posting' => $arr[3] ); $groups[$group['group']] = $group; @@ -1924,32 +1428,27 @@ class Net_NNTP_Protocol_Client extends PEAR } return $groups; - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdListNewsgroups() - /** * Fetches a list of (all) avaible newsgroup descriptions. * - * @param string $wildmat Wildmat of the groups, that is to be - * listed, defaults to null; + * @param string $wildMat Wildmat of the groups, that is to be listed, defaults to null; * - * @return mixed (array) nested array with description of existing - * newsgroups on success or (object) pear_error on failure + * @return mixed (array) nested array with description of existing newsgroups on success + * (object) pear_error on failure * @access protected */ - function cmdListNewsgroups($wildmat = null) + protected function cmdListNewsgroups($wildMat = null) { - if (is_null($wildmat)) { + if (is_null($wildMat)) { $command = 'LIST NEWSGROUPS'; } else { - $command = 'LIST NEWSGROUPS ' . $wildmat; + $command = 'LIST NEWSGROUPS ' . $wildMat; } $response = $this->_sendCommand($command); @@ -1968,17 +1467,10 @@ class Net_NNTP_Protocol_Client extends PEAR $groups = array(); foreach($data as $line) { - if (preg_match("/^(\S+)\s+(.*)$/", ltrim($line), - $matches - ) - ) { + if (preg_match('/^(\S+)\s+(.*)$/', ltrim($line), $matches)) { $groups[$matches[1]] = (string) $matches[2]; - } else { - if ($this->_logger) { - $this->_logger->warning - ("Recieved non-standard line: '$line'" - ); - } + } else if ($this->_logger) { + $this->_logger->warning("Recieved non-standard line: '$line'"); } } @@ -1987,40 +1479,26 @@ class Net_NNTP_Protocol_Client extends PEAR } return $groups; - break; - - // RFC2980: 'program error, function not performed' - case 503: - return $this->throwError - ('Internal server error, function not performed', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - /* Article field access commands */ - // {{{ cmdOver() - /** * Fetch message header from message number $first until $last * - * The format of the returned array is: - * $messages[][header_name] + * @info The format of the returned array is: $messages[][header_name] * - * @param optional string $range articles to fetch + * @param string $range (optional) articles to fetch * - * @return mixed (array) nested array of message and there headers - * on success or (object) pear_error on failure + * @return mixed (array) nested array of message and there headers on success + * (object) pear_error on failure * @access protected */ - function cmdOver($range = null) + protected function cmdOver($range = null) { if (is_null($range)) { $command = 'OVER'; @@ -2046,69 +1524,32 @@ class Net_NNTP_Protocol_Client extends PEAR } if ($this->_logger) { - $this->_logger->info('Fetched overview ' . - ($range == null ? - 'for current article' : 'for range: ' . $range) - ); + $this->_logger->info('Fetched overview ' . ($range == null ? 'for current article' : 'for range: ' . $range)); } return $data; - break; - - // 412, RFC2980: 'No news group current selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No news group current selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC2980: 'No article(s) selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No article(s) selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 423:, Draft27: 'No articles in that range' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER: - return $this->throwError('No articles in that range', - $response, $this->_currentStatusResponse() - ); - break; - - // RFC2980: 'no permission' - case 502: - return $this->throwError('No permission', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdXOver() - /** * Fetch message header from message number $first until $last * - * The format of the returned array is: - * $messages[message_id][header_name] + * @info The format of the returned array is: $messages[message_id][header_name] * - * @param optional string $range articles to fetch + * @param string $range (optional) articles to fetch * - * @return mixed (array) nested array of message and there headers - * on success or (object) pear_error on failure + * @return mixed (array) nested array of message and there headers on success + * (object) pear_error on failure * @access protected */ - function cmdXOver($range = null) + protected function cmdXOver($range = null) { - // deprecated API (the code _is_ still in alpha state) + // Deprecated API (the code _is_ still in alpha state). if (func_num_args() > 1) { - die('The second parameter in cmdXOver() has been ' - . 'deprecated! Use x-y instead...'); + exit('The second parameter in cmdXOver() has been deprecated! Use x-y instead...'); } if (is_null($range)) { @@ -2135,53 +1576,24 @@ class Net_NNTP_Protocol_Client extends PEAR } if ($this->_logger) { - $this->_logger->info('Fetched overview ' . - ($range == null ? - 'for current article' : 'for range: ' . $range) - ); + $this->_logger->info('Fetched overview ' . ($range == null ? 'for current article' : 'for range: ' . $range)); } return $data; - break; - - // 412, RFC2980: 'No news group current selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No news group current selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC2980: 'No article(s) selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No article(s) selected', - $response, $this->_currentStatusResponse() - ); - break; - - // RFC2980: 'no permission' - case 502: - return $this->throwError('No permission', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdListOverviewFmt() - /** - * Returns a list of avaible headers which are send from newsserver - * to client for every news message + * Returns a list of available headers which are sent from tge news server to the client for every news message. * * @return mixed (array) of header names on success or - * (object) pear_error on failure + * (object) pear_error on failure * @access protected */ - function cmdListOverviewFmt() + protected function cmdListOverviewFmt() { $response = $this->_sendCommand('LIST OVERVIEW.FMT'); if ($this->isError($response)){ @@ -2200,7 +1612,7 @@ class Net_NNTP_Protocol_Client extends PEAR foreach ($data as $line) { - // Check if postfixed by ':full' (case-insensitive) + // Check if post fixed by ':full' (case-insensitive) if (0 == strcasecmp(substr($line, -5, 5), ':full')) { // ':full' is _not_ included in tag, but value set to true $format[substr($line, 0, -5)] = true; @@ -2214,38 +1626,26 @@ class Net_NNTP_Protocol_Client extends PEAR $this->_logger->info('Fetched overview format'); } return $format; - break; - - // RFC2980: 'program error, function not performed' - case 503: - return $this->throwError - ('Internal server error, function not performed', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdXHdr() - /** * * * The format of the returned array is: * $messages[message_id] * - * @param optional string $field - * @param optional string $range articles to fetch + * @param string $field (optional) + * @param string $range (optional) articles to fetch * - * @return mixed (array) nested array of message and there header - * on success or (object) pear_error on failure + * @return mixed (array) nested array of message and there header on success + * (object) pear_error on failure * @access protected */ - function cmdXHdr($field, $range = null) + protected function cmdXHdr($field, $range = null) { if (is_null($range)) { $command = 'XHDR ' . $field; @@ -2260,8 +1660,8 @@ class Net_NNTP_Protocol_Client extends PEAR switch ($response) { // 221, RFC2980: 'Header follows' - case 221: - $data = $this->_getTextResponse(); + case NET_NNTP_PROTOCOL_RESPONSECODE_HEAD_FOLLOWS: + $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; } @@ -2273,65 +1673,32 @@ class Net_NNTP_Protocol_Client extends PEAR } return $return; - break; - - // 412, RFC2980: 'No news group current selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No news group current selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC2980: 'No current article selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No current article selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 430, RFC2980: 'No such article' - case 430: - return $this->throwError('No such article', - $response, $this->_currentStatusResponse() - ); - break; - - // RFC2980: 'no permission' - case 502: - return $this->throwError('No permission', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdXGTitle() - /** - * Fetches a list of (all) avaible newsgroup descriptions. - * Depresated as of RFC2980. + * Fetches a list of (all) available newsgroup descriptions. + * Deprecated as of RFC2980. * - * @param string $wildmat Wildmat of the groups, that is - * to be listed, defaults to '*'; + * @param string $wildMat Wildmat of the groups, that is to be listed, defaults to '*'; * - * @return mixed (array) nested array with description of - * existing newsgroups on success or (object) pear_error on failure + * @return mixed (array) nested array with description of existing newsgroups on success + * (object) pear_error on failure * @access protected */ - function cmdXGTitle($wildmat = '*') + protected function cmdXGTitle($wildMat = '*') { - $response = $this->_sendCommand('XGTITLE ' . $wildmat); + $response = $this->_sendCommand('XGTITLE ' . $wildMat); if ($this->isError($response)){ return $response; } switch ($response) { // RFC2980: 'list of groups and descriptions follows' - case 282: + case NET_NNTP_PROTOCOL_RESPONSECODE_XGTITLE_GROUPS_FOLLOW: $data = $this->_getTextResponse(); if ($this->isError($data)) { return $data; @@ -2340,43 +1707,31 @@ class Net_NNTP_Protocol_Client extends PEAR $groups = array(); foreach($data as $line) { - preg_match("/^(.*?)\s(.*?$)/", trim($line), $matches); + preg_match('/^(.*?)\s(.*?$)/', trim($line), $matches); $groups[$matches[1]] = (string) $matches[2]; } return $groups; - break; - - case 481: // RFC2980: 'Groups and descriptions unavailable' - return $this->throwError - ('Groups and descriptions unavailable', - $response, $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdXROver() - /** * Fetch message references from message number $first to $last * - * @param optional string $range articles to fetch + * @param string $range (optional) articles to fetch * - * @return mixed (array) assoc. array of message references on - * success or (object) pear_error on failure + * @return mixed (array) assoc. array of message references on success + * (object) pear_error on failure * @access protected */ - function cmdXROver($range = null) + protected function cmdXROver($range = null) { // Warn about deprecated API (the code _is_ still in alpha state) if (func_num_args() > 1 ) { - die('The second parameter in cmdXROver() has been ' - . 'deprecated! Use x-y instead...'); + exit('The second parameter in cmdXROver() has been deprecated! Use x-y instead...'); } if (is_null($range)) { @@ -2404,57 +1759,30 @@ class Net_NNTP_Protocol_Client extends PEAR $return[$line[0]] = $line[1]; } return $return; - break; - - // 412, RFC2980: 'No news group current selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_GROUP_SELECTED: - return $this->throwError('No news group current selected', - $response, $this->_currentStatusResponse() - ); - break; - - // 420, RFC2980: 'No article(s) selected' - case NET_NNTP_PROTOCOL_RESPONSECODE_NO_ARTICLE_SELECTED: - return $this->throwError('No article(s) selected', - $response, $this->_currentStatusResponse() - ); - break; - - // RFC2980: 'no permission' - case 502: - return $this->throwError('No permission', $response, - $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdXPat() - /** * * * @param string $field * @param string $range - * @param mixed $wildmat + * @param mixed $wildMat * - * @return mixed (array) nested array of message and there - * headers on success or (object) pear_error on failure + * @return mixed (array) nested array of message and there headers on success + * (object) pear_error on failure * @access protected */ - function cmdXPat($field, $range, $wildmat) + protected function cmdXPat($field, $range, $wildMat) { - if (is_array($wildmat)) { - $wildmat = implode(' ', $wildmat); + if (is_array($wildMat)) { + $wildMat = implode(' ', $wildMat); } - $response = $this->_sendCommand('XPAT ' . $field . ' ' . - $range . ' ' . $wildmat - ); + $response = $this->_sendCommand('XPAT ' . $field . ' ' . $range . ' ' . $wildMat); if ($this->isError($response)){ return $response; } @@ -2473,28 +1801,12 @@ class Net_NNTP_Protocol_Client extends PEAR } return $return; - break; - - case 430: // 430, RFC2980: 'No such article' - return $this->throwError('No current article selected', - $response, $this->_currentStatusResponse() - ); - break; - - case 502: // RFC2980: 'no permission' - return $this->throwError('No permission', $response, - $this->_currentStatusResponse() - ); - break; default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdAuthinfo() - /** * Authenticate using 'original' method * @@ -2502,10 +1814,11 @@ class Net_NNTP_Protocol_Client extends PEAR * @param string $pass The password to authenticate with. * * @return mixed (bool) true on success or - * (object) pear_error on failure + * (object) pear_error on failure + * * @access protected */ - function cmdAuthinfo($user, $pass) + protected function cmdAuthinfo($user, $pass) { // Send the username $response = $this->_sendCommand('AUTHINFO user '.$user); @@ -2531,39 +1844,12 @@ class Net_NNTP_Protocol_Client extends PEAR // TODO: Set some variable before return return true; - break; - - case 381: // RFC2980: 'More authentication information required' - return $this->throwError('Authentication uncompleted', - $response, $this->_currentStatusResponse() - ); - break; - - case 482: // RFC2980: 'Authentication rejected' - return $this->throwError('Authentication rejected', - $response, $this->_currentStatusResponse() - ); - break; - - case 502: // RFC2980: 'No permission' - return $this->throwError('Authentication rejected', - $response, $this->_currentStatusResponse() - ); - break; - - /*case 500: - case 501: - return $this->throwError('Authentication failed', $response, $this->_currentStatusResponse()); - break;*/ default: - return $this->_handleUnexpectedResponse($response); + return $this->_handleErrorResponse($response); } } - // }}} - // {{{ cmdAuthinfoSimple() - /** * Authenticate using 'simple' method * @@ -2573,50 +1859,39 @@ class Net_NNTP_Protocol_Client extends PEAR * @return mixed (bool) true on success or (object) pear_error on failure * @access protected */ - function cmdAuthinfoSimple($user, $pass) + protected function cmdAuthinfoSimple($user, $pass) { - return $this->throwError - ("The auth mode: 'simple' is has not been implemented yet", - null - ); + return $this->throwError("The auth mode: 'simple' is has not been implemented yet", null); } - // }}} - // {{{ cmdAuthinfoGeneric() - /** * Authenticate using 'generic' method * * @param string $user The username to authenticate as. * @param string $pass The password to authenticate with. * - * @return mixed (bool) true on success or (object) pear_error on failure + * @return mixed (bool) true on success + * (object) pear_error on failure * @access protected */ - function cmdAuthinfoGeneric($user, $pass) + protected function cmdAuthinfoGeneric($user, $pass) { - return $this->throwError - ("The auth mode: 'generic' is has not been implemented yet", - null - ); + return $this->throwError("The auth mode: 'generic' is has not been implemented yet", null); } - // }}} - // {{{ _isConnected() - /** * Test whether we are connected or not. * + * @param bool $feof Check for the end of file pointer. + * * @return bool true or false * @access protected */ - function _isConnected() + protected function _isConnected($feof = true) { - return (is_resource($this->_socket) && (!feof($this->_socket))); + return (is_resource($this->_socket) && ($feof ? !feof($this->_socket) : true)); } - // }}} - /** * Verify NNTP error code and return PEAR error. * @@ -2715,21 +1990,8 @@ class Net_NNTP_Protocol_Client extends PEAR default: $text = $this->_currentStatusResponse(); - return $this->throwError("Unexpected response: '$text'", $response, $text); } } -} - -// }}} - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * c-hanging-comment-ender-p: nil - * End: - */ - -?> \ No newline at end of file +} \ No newline at end of file diff --git a/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Responsecode.php b/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Responsecode.php index dc1a054b7..54dcee6ad 100644 --- a/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Responsecode.php +++ b/lib/copy_this/www/lib/Net_NNTP/NNTP/Protocol/Responsecode.php @@ -91,17 +91,15 @@ define('NET_NNTP_PROTOCOL_RESPONSECODE_READY_POSTING_PROHIBITED', 201); * 'Closing connection - goodbye!' (RFC977) * * @access public - * @since ? */ -//define('NET_NNTP_PROTOCOL_RESPONSECODE_DISCONNECTING_REQUESTED', 205); ///// goodbye +define('NET_NNTP_PROTOCOL_RESPONSECODE_DISCONNECTING_REQUESTED', 205); /** * 'Service discontinued' (RFC977) * * @access public - * @since ? */ -//define('NET_NNTP_PROTOCOL_RESPONSECODE_DISCONNECTING_FORCED', 400); ///// unavailable / discontinued +define('NET_NNTP_PROTOCOL_RESPONSECODE_DISCONNECTING_FORCED', 400); /** @@ -168,6 +166,12 @@ define('NET_NNTP_PROTOCOL_RESPONSECODE_GROUP_SELECTED', 211); */ define('NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_GROUP', 411); +/** + * 'Groups and descriptions unavailable' + * + * @access public + */ +define('NET_NNTP_PROTOCOL_RESPONSECODE_XGTITLE_GROUPS_UNAVAILABLE', 481); // }}} // {{{ Constants: Article retrieval @@ -249,6 +253,13 @@ define('NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_NUMBER', 423); */ define('NET_NNTP_PROTOCOL_RESPONSECODE_NO_SUCH_ARTICLE_ID', 430); +/** + * 'List of groups and descriptions follows' (RFC2980) + * + * @access public + */ +define('NET_NNTP_PROTOCOL_RESPONSECODE_XGTITLE_GROUPS_FOLLOW', 482); + // }}} // {{{ Constants: Transferring @@ -383,6 +394,13 @@ define('NET_NNTP_PROTOCOL_RESPONSECODE_AUTHENTICATION_REQUIRED', 480); */ define('NET_NNTP_PROTOCOL_RESPONSECODE_AUTHENTICATION_CONTINUE', 381); +/** + * 'Continue with TLS negotiation' (RFC4642) + * + * @access public + */ +define('NET_NNTP_PROTOCOL_RESPONSECODE_TLS_AUTHENTICATION_CONTINUE', 382); + /** * 'Authentication accepted' (RFC2980) * @@ -491,6 +509,14 @@ define('NET_NNTP_PROTOCOL_RESPONSECODE_INTERNAL_FAULT', 403); */ define('NET_NNTP_PROTOCOL_RESPONSECODE_BASE64_ENCODING_ERROR', 504); +/** + * 'Can not initiate TLS negotiation' (RFC4642) + * + * @access public + */ +define('NET_NNTP_PROTOCOL_RESPONSECODE_TLS_FAILED_NEGOTIATION', 580); + + // }}} /* From f79ce3063cc326917fdcc0483f1c0e95551d2cab Mon Sep 17 00:00:00 2001 From: Darko <dkrisan@gmail.com> Date: Tue, 8 Jul 2014 15:39:21 +0200 Subject: [PATCH 20/20] Another change in montor. --- bin/monitor.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bin/monitor.php b/bin/monitor.php index 5a8c60782..6a1c45582 100644 --- a/bin/monitor.php +++ b/bin/monitor.php @@ -1658,11 +1658,11 @@ while ($i > 0) { } //Process Games in pane 2.5 once if needed then exits - if (($maxload >= get_load()) && ($post_amazon == 1) && ($console_releases_proc > 0) && ($pc_releases_proc > 0)) { + if (($maxload >= get_load()) && ($post_amazon == 1) && (($console_releases_proc > 0) || ($pc_releases_proc > 0))) { $color = get_color($colors_start, $colors_end, $colors_exc); $log = writelog($panes2[5]); shell_exec("tmux respawnp -t${tmux_session}:2.5 'echo \"\033[38;5;\"$color\"m\" && cd $_bin && $_php postprocess_new.php console 2>&1 $log && $_php postprocess_new.php games 2>&1 $log && $_sleep $post_timer_amazon && echo \" \033[1;0;33m\"' 2>&1 1> /dev/null"); - } else if (($maxload >= get_load()) && ($post_amazon == 1) && ($console_releases_proc == 0) && ($pc_releases_proc > 0)) { + } else if (($maxload >= get_load()) && ($post_amazon == 1) && (($console_releases_proc == 0) || ($pc_releases_proc > 0))) { $color = get_color($colors_start, $colors_end, $colors_exc); shell_exec("tmux respawnp -t${tmux_session}:2.5 'echo \"\033[38;5;\"$color\"m\n$panes2[5] has been disabled/terminated by No Games to process\"'"); } else if ($maxload <= get_load()) {