PageRenderTime 54ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/public_html/bugs/rss/search.php

https://github.com/pear/pearweb
PHP | 424 lines | 360 code | 40 blank | 24 comment | 86 complexity | 4e51af7140fac1a3f054e8e9f0684cb7 MD5 | raw file
  1. <?php /* vim: set noet ts=4 sw=4: : */
  2. /* Generates an RSS/RDF feed for a set of bugs
  3. * based on search criteria as provided.
  4. *
  5. * Search code borrowed from /search.php (As of Revision: 1.82)
  6. * and accepts the same parameters.
  7. *
  8. * When changes are made to that API,
  9. * they should be reflected here for consistency
  10. *
  11. * borrowed from php-bugs-web, implementation by Sara Golemon <pollita@php.net>
  12. * ported by Gregory Beaver <cellog@php.net>
  13. */
  14. /* Maximum number of bugs to return */
  15. define ('MAX_BUGS_RETURN', 150);
  16. /**
  17. * Obtain common includes
  18. */
  19. require_once '../include/functions.inc';
  20. $errors = array();
  21. $warnings = array();
  22. $order_options = array(
  23. '' => 'relevance',
  24. 'id' => 'ID',
  25. 'ts1' => 'date',
  26. 'package_name' => 'package',
  27. 'bug_type' => 'bug_type',
  28. 'status' => 'status',
  29. 'package_version' => 'package_version',
  30. 'php_version' => 'php_version',
  31. 'php_os' => 'os',
  32. 'sdesc' => 'summary',
  33. 'assign' => 'assignment',
  34. );
  35. define('BOOLEAN_SEARCH', @intval($_GET['boolean']));
  36. $query = 'SELECT SQL_CALC_FOUND_ROWS';
  37. $query .= ' bugdb.*, UNIX_TIMESTAMP(ts1) as ts1a, UNIX_TIMESTAMP(ts2) as ts2a,
  38. TO_DAYS(NOW())-TO_DAYS(bugdb.ts2) AS unchanged'
  39. . ' FROM bugdb' .
  40. ' LEFT JOIN packages ON packages.name = bugdb.package_name';
  41. if (!empty($_GET['maintain']) || !empty($_GET['handle'])) {
  42. $query .= ' LEFT JOIN maintains ON packages.id = maintains.package';
  43. $query .= ' AND maintains.handle = ';
  44. if (!empty($_GET['maintain'])) {
  45. $query .= $dbh->quoteSmart($_GET['maintain']);
  46. } else {
  47. $query .= $dbh->quoteSmart($_GET['handle']);
  48. }
  49. }
  50. if (empty($_GET['package_name']) || !is_array($_GET['package_name'])) {
  51. $_GET['package_name'] = array();
  52. $where_clause = ' WHERE bugdb.registered=1';
  53. } else {
  54. $where_clause = ' WHERE bugdb.registered=1 AND bugdb.package_name';
  55. if (count($_GET['package_name']) > 1) {
  56. $where_clause .= " IN ('"
  57. . join("', '", escapeSQL($_GET['package_name']))
  58. . "')";
  59. } else {
  60. $where_clause .= ' = '
  61. . $dbh->quoteSmart($_GET['package_name'][0]);
  62. }
  63. }
  64. if (empty($_GET['package_nname']) || !is_array($_GET['package_nname'])) {
  65. $_GET['package_nname'] = array();
  66. } else {
  67. $where_clause .= ' AND bugdb.package_name';
  68. if (count($_GET['package_nname']) > 1) {
  69. $where_clause .= " NOT IN ('"
  70. . join("', '", escapeSQL($_GET['package_nname']))
  71. . "')";
  72. } else {
  73. $where_clause .= ' <> '
  74. . $dbh->quoteSmart($_GET['package_nname'][0]);
  75. }
  76. }
  77. /*
  78. * Ensure status is valid and tweak search clause
  79. * to treat assigned, analyzed, critical and verified bugs as open
  80. */
  81. if (empty($_GET['status'])) {
  82. $status = 'Open';
  83. } else {
  84. $status = $_GET['status'];
  85. }
  86. switch ($status) {
  87. case 'All':
  88. break;
  89. case 'Closed':
  90. case 'Duplicate':
  91. case 'Critical':
  92. case 'Assigned':
  93. case 'Analyzed':
  94. case 'Verified':
  95. case 'Suspended':
  96. case 'Wont fix':
  97. case 'No Feedback':
  98. case 'Feedback':
  99. case 'Bogus':
  100. $where_clause .= " AND bugdb.status='$status'";
  101. break;
  102. case 'Old Feedback':
  103. $where_clause .= " AND bugdb.status='Feedback'" .
  104. ' AND TO_DAYS(NOW())-TO_DAYS(bugdb.ts2) > 60';
  105. break;
  106. case 'Fresh':
  107. $where_clause .= ' AND bugdb.status NOT IN' .
  108. " ('Closed', 'Duplicate', 'Bogus')" .
  109. ' AND TO_DAYS(NOW())-TO_DAYS(bugdb.ts2) < 30';
  110. break;
  111. case 'Stale':
  112. $where_clause .= ' AND bugdb.status NOT IN' .
  113. " ('Closed', 'Duplicate', 'Bogus')" .
  114. ' AND TO_DAYS(NOW())-TO_DAYS(bugdb.ts2) > 30';
  115. break;
  116. case 'Not Assigned':
  117. $where_clause .= ' AND bugdb.status NOT IN' .
  118. " ('Closed', 'Duplicate', 'Bogus', 'Assigned'," .
  119. " 'Wont Fix', 'Suspended')";
  120. break;
  121. // Closed Reports Since Last Release
  122. case 'CRSLR':
  123. if (!isset($_GET['package_name']) || count($_GET['package_name']) > 1) {
  124. // Act as ALL
  125. break;
  126. }
  127. // Fetch the last release date
  128. include_once 'pear-database-package.php';
  129. $releaseDate = package::getRecent(1, $_GET['package_name'][0]);
  130. if (PEAR::isError($releaseDate)) {
  131. break;
  132. }
  133. $where_clause .= ' AND bugdb.status IN' .
  134. " ('Closed', 'Duplicate', 'Bogus', 'Wont Fix', 'Suspended')
  135. AND (UNIX_TIMESTAMP('" . $releaseDate[0]['releasedate'] . "') < UNIX_TIMESTAMP(bugdb.ts2))
  136. ";
  137. break;
  138. case 'Open':
  139. $where_clause .= " AND bugdb.status IN ('Open', 'Assigned'," .
  140. " 'Analyzed', 'Critical', 'Verified')";
  141. break;
  142. case 'OpenFeedback':
  143. default:
  144. $where_clause .= " AND bugdb.status IN ('Open', 'Assigned'," .
  145. " 'Analyzed', 'Critical', 'Verified', 'Feedback')";
  146. }
  147. if (empty($_GET['search_for'])) {
  148. $search_for = '';
  149. } else {
  150. $search_for = htmlspecialchars($_GET['search_for']);
  151. list($sql_search, $ignored) = format_search_string($search_for);
  152. $where_clause .= $sql_search;
  153. if (count($ignored) > 0 ) {
  154. $warnings[] = 'The following words were ignored: ' .
  155. implode(', ', array_unique($ignored));
  156. }
  157. }
  158. if (empty($_GET['bug_type']) || $_GET['bug_type'] == 'All') {
  159. $bug_type = '';
  160. } else {
  161. $bug_type = $_GET['bug_type'];
  162. if ($bug_type == 'Bugs') {
  163. $where_clause .= ' AND (bugdb.bug_type = "Bug" OR bugdb.bug_type="Documentation Problem")';
  164. } else {
  165. $where_clause .= ' AND bugdb.bug_type = ' . $dbh->quoteSmart($bug_type);
  166. }
  167. }
  168. if (empty($_GET['bug_age']) || !(int)$_GET['bug_age']) {
  169. $bug_age = 0;
  170. } else {
  171. $bug_age = (int)$_GET['bug_age'];
  172. $where_clause .= ' AND bugdb.ts1 >= '
  173. . " DATE_SUB(NOW(), INTERVAL $bug_age DAY)";
  174. }
  175. if (empty($_GET['bug_updated']) || !(int)$_GET['bug_updated']) {
  176. $bug_updated = 0;
  177. } else {
  178. $bug_updated = (int)$_GET['bug_updated'];
  179. $where_clause .= ' AND bugdb.ts2 >= '
  180. . " DATE_SUB(NOW(), INTERVAL $bug_updated DAY)";
  181. }
  182. if (empty($_GET['php_os'])) {
  183. $php_os = '';
  184. } else {
  185. $php_os = $_GET['php_os'];
  186. $where_clause .= " AND bugdb.php_os LIKE '%"
  187. . $dbh->escapeSimple($php_os) . "%'";
  188. }
  189. if (empty($_GET['phpver'])) {
  190. $phpver = '';
  191. } else {
  192. $phpver = $_GET['phpver'];
  193. $where_clause .= " AND bugdb.php_version LIKE '"
  194. . $dbh->escapeSimple($phpver) . "%'";
  195. }
  196. if (empty($_GET['packagever'])) {
  197. $packagever = '';
  198. } else {
  199. $packagever = $_GET['packagever'];
  200. $where_clause .= " AND bugdb.package_version LIKE '"
  201. . $dbh->escapeSimple($packagever) . "%'";
  202. }
  203. if (empty($_GET['handle'])) {
  204. $handle = '';
  205. if (empty($_GET['assign'])) {
  206. $assign = '';
  207. } else {
  208. $assign = $_GET['assign'];
  209. $where_clause .= ' AND bugdb.assign = '
  210. . $dbh->quoteSmart($assign);
  211. }
  212. if (empty($_GET['maintain'])) {
  213. $maintain = '';
  214. } else {
  215. $maintain = $_GET['maintain'];
  216. $where_clause .= ' AND maintains.handle = '
  217. . $dbh->quoteSmart($maintain);
  218. }
  219. } else {
  220. $handle = $_GET['handle'];
  221. $where_clause .= ' AND (maintains.handle = '
  222. . $dbh->quoteSmart($handle)
  223. . ' OR bugdb.assign = '
  224. . $dbh->quoteSmart($handle). ')';
  225. }
  226. if (empty($_GET['author_email'])) {
  227. $author_email = '';
  228. } else {
  229. $author_email = $_GET['author_email'];
  230. $qae = $dbh->quoteSmart($author_email);
  231. $where_clause .= ' AND (bugdb.email = '
  232. . $qae . ' OR bugdb.handle=' . $qae . ')';
  233. }
  234. $where_clause .= ' AND (packages.package_type = '
  235. . $dbh->quoteSmart(SITE);
  236. if ($pseudo = array_intersect($pseudo_pkgs, $_GET['package_name'])) {
  237. $where_clause .= " OR bugdb.package_name";
  238. if (count($pseudo) > 1) {
  239. $where_clause .= " IN ('"
  240. . join("', '", escapeSQL($pseudo)) . "')";
  241. } else {
  242. $where_clause .= " = '" . implode('', escapeSQL($pseudo)) . "'";
  243. }
  244. } else {
  245. $where_clause .= " OR bugdb.package_name IN ('"
  246. . join("', '", escapeSQL($pseudo_pkgs)) . "')";
  247. }
  248. $where_clause .= ')';
  249. $query .= $where_clause;
  250. if (isset($_GET['direction']) && $_GET['direction'] != 'DESC') {
  251. $direction = 'ASC';
  252. } else {
  253. $direction = 'DESC';
  254. }
  255. if (empty($_GET['order_by']) ||
  256. !array_key_exists($_GET['order_by'], $order_options))
  257. {
  258. $order_by = 'id';
  259. } else {
  260. $order_by = $_GET['order_by'];
  261. }
  262. if (empty($_GET['reorder_by']) ||
  263. !array_key_exists($_GET['reorder_by'], $order_options))
  264. {
  265. $reorder_by = '';
  266. } else {
  267. $reorder_by = $_GET['reorder_by'];
  268. if ($order_by == $reorder_by) {
  269. $direction = $direction == 'ASC' ? 'DESC' : 'ASC';
  270. } else {
  271. $direction = 'ASC';
  272. $order_by = $reorder_by;
  273. }
  274. }
  275. $query .= ' ORDER BY ' . $order_by . ' ' . $direction;
  276. // if status Feedback then sort also after last updated time.
  277. if ($status == 'Feedback') {
  278. $query .= ', bugdb.ts2 ' . $direction;
  279. }
  280. if (empty($_GET['limit']) || !(int)$_GET['limit']) {
  281. if (!empty($_GET['limit']) && $_GET['limit'] == 'All') {
  282. $limit = 'All';
  283. } else {
  284. $limit = MAX_BUGS_RETURN;
  285. $query .= " LIMIT 0, $limit";
  286. }
  287. } else {
  288. $limit = (int)$_GET['limit'];
  289. $query .= " LIMIT 0, $limit";
  290. }
  291. if (stristr($query, ';')) {
  292. die('BAD HACKER!! No database cracking for you today!');
  293. } else {
  294. $res = $dbh->query($query);
  295. $rows = $res->numRows();
  296. $total_rows = $dbh->getOne('SELECT FOUND_ROWS()');
  297. if ($total_rows > $rows) {
  298. $warnings[] = 'The search was too general, only ' . MAX_BUGS_RETURN .
  299. ' bugs will be returned';
  300. }
  301. }
  302. header('Content-type: text/xml');
  303. echo '<?xml version="1.0"?>
  304. <?xml-stylesheet
  305. href="http://www.w3.org/2000/08/w3c-synd/style.css" type="text/css"
  306. ?>
  307. <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://purl.org/rss/1.0/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:content="http://purl.org/rss/1.0/modules/content/">';
  308. echo "\n <channel rdf:about=\"http://" . PEAR_CHANNELNAME . "/bugs/search.php\">\n";
  309. echo " <title>" . SITE_BIG . " Bug Search Results</title>\n";
  310. echo ' <link>http://' . htmlspecialchars(PEAR_CHANNELNAME . '/bugs/search.php?' .
  311. http_build_query($_GET)) . "</link>\n";
  312. echo " <description>Search Results</description>\n";
  313. echo " <dc:language>en-us</dc:language>\n";
  314. echo " <dc:creator>" . PEAR_WEBMASTER_EMAIL . "</dc:creator>\n";
  315. echo " <dc:publisher>" . PEAR_WEBMASTER_EMAIL . "</dc:publisher>\n";
  316. echo " <admin:generatorAgent rdf:resource=\"http://" . PEAR_CHANNELNAME . "/bugs\"/>\n";
  317. echo " <sy:updatePeriod>hourly</sy:updatePeriod>\n";
  318. echo " <sy:updateFrequency>1</sy:updateFrequency>\n";
  319. echo " <sy:updateBase>2000-01-01T12:00+00:00</sy:updateBase>\n";
  320. echo ' <items>
  321. <rdf:Seq>
  322. ';
  323. if ($total_rows > 0) {
  324. require_once 'bugs/pear-bugs-utils.php';
  325. $pbu = new PEAR_Bugs_Utils;
  326. $i = 0;
  327. $items = array();
  328. while ($row = $res->fetchRow(DB_FETCHMODE_ASSOC)) {
  329. $i++;
  330. $bug = $row;
  331. $desc = "{$row['package_name']} {$row['bug_type']}\nReported by ";
  332. if ($bug['handle']) {
  333. $desc .= "{$row['handle']}\n";
  334. } else {
  335. $desc .= substr($row['email'], 0, strpos($row['email'], '@')) . "@...\n";
  336. }
  337. $desc .= date(DATE_ATOM, $row['ts1a']) . "\n";
  338. $desc .= "PHP: {$row['php_version']} OS: {$row['php_os']} Package Version: {$row['package_version']}\n\n";
  339. $desc .= $row['ldesc'];
  340. $desc = '<pre>' . utf8_encode(htmlspecialchars($desc)) . '</pre>';
  341. echo " <rdf:li rdf:resource=\"http://" . PEAR_CHANNELNAME . "/bug/{$row['id']}\" />\n";
  342. $items[$i] = " <item rdf:about=\"http://" . PEAR_CHANNELNAME . "/bug/{$row['id']}\">\n";
  343. $items[$i] .= ' <title>' . utf8_encode(htmlspecialchars($row['package_name'] . ': ' . $row['bug_type'] . ' ' . $row['id'] . ' [' . $row['status'] . '] ' . $row['sdesc'])) . "</title>\n";
  344. $items[$i] .= " <link>http://" . PEAR_CHANNELNAME . "/bugs/{$row['id']}</link>\n";
  345. $items[$i] .= ' <content:encoded><![CDATA[' . $desc . "]]></content:encoded>\n";
  346. $items[$i] .= ' <description><![CDATA[' . $desc . "]]></description>\n";
  347. if (!$row['unchanged']) {
  348. $items[$i] .= ' <dc:date>' . date(DATE_ATOM, $row['ts1a']) . "</dc:date>\n";
  349. } else {
  350. $items[$i] .= ' <dc:date>' . date(DATE_ATOM, $row['ts2a']) . "</dc:date>\n";
  351. }
  352. $items[$i] .= ' <dc:creator>' . utf8_encode(htmlspecialchars($pbu->spamProtect($row['email']))) . "</dc:creator>\n";
  353. $items[$i] .= ' <dc:subject>' .
  354. utf8_encode(htmlspecialchars($row['package_name'])) . ' ' .
  355. utf8_encode(htmlspecialchars($row['bug_type'])) . "</dc:subject>\n";
  356. $items[$i] .= " </item>\n";
  357. }
  358. $items = implode('', $items);
  359. } else {
  360. $warnings[] = "No bugs matched your criteria";
  361. }
  362. echo '
  363. </rdf:Seq>
  364. </items>
  365. </channel>
  366. <image rdf:about="http://' . PEAR_CHANNELNAME . '/gifs/pearsmall.gif">
  367. <title>' . SITE_BIG . ' Bugs</title>
  368. <url>http://' . PEAR_CHANNELNAME . '/gifs/pearsmall.gif</url>
  369. <link>http://' . PEAR_CHANNELNAME . '/bugs</link>
  370. </image>
  371. ', $items;
  372. ?>
  373. </rdf:RDF>
  374. <?php
  375. if (count($warnings) > 0) {
  376. echo "<!--\n\n";
  377. echo "The following warnings occured during your request:\n\n";
  378. foreach($warnings as $warning) {
  379. echo utf8_encode(htmlspecialchars('* ' . $warning)) . "\n";
  380. }
  381. echo "-->\n";
  382. }