xref: /web-bugs/www/search.php (revision 4efb5c34)
1<?php
2
3use App\Repository\PackageRepository;
4
5// Start session
6session_start();
7
8// Obtain common includes
9require_once '../include/prepend.php';
10
11// Redirect early if a bug id is passed as search string
12if (isset($_GET['search_for']) && preg_match('/^\d+$/', trim($_GET['search_for']), $search_for_id_array)) {
13    redirect("bug.php?id=${search_for_id_array[0]}");
14}
15
16// For bug count only, used in places like doc.php.net
17$count_only = isset($_REQUEST['count_only']) && $_REQUEST['count_only'];
18
19bugs_authenticate($user, $pw, $logged_in, $user_flags);
20
21$is_security_developer = ($user_flags & (BUGS_TRUSTED_DEV | BUGS_SECURITY_DEV));
22
23$newrequest = http_build_query(array_merge($_GET, $_POST));
24
25if (!$count_only) {
26    response_header(
27        'Bugs :: Search', "
28            <link rel='alternate' type='application/rss+xml' title='Search bugs - RDF' href='rss/search.php?{$newrequest}'>
29            <link rel='alternate' type='application/rss+xml' title='Search bugs - RSS 2.0' href='rss/search.php?format=rss2&{$newrequest}'>
30    ");
31}
32
33// Include common query handler (used also by rss/search.php)
34require "{$ROOT_DIR}/include/query.php";
35
36if (isset($_GET['cmd']) && $_GET['cmd'] == 'display')
37{
38    // FIXME: this if doesn't make sense, check is already performed in
39    // query.php - whole condition can be removed, reducing level of
40    // nesting by one.
41    if (!isset($result)) {
42        $errors[] = 'Invalid query';
43    } else {
44        // For count only, simply print the count and exit
45        if ($count_only) {
46            echo (int) $total_rows;
47            exit;
48        }
49
50        // Selected packages to search in
51        $package_name_string = '';
52        if (count($package_name) > 0) {
53            foreach ($package_name as $type_str) {
54                $package_name_string.= '&amp;package_name[]=' . urlencode($type_str);
55            }
56        }
57
58        // Selected packages NOT to search in
59        $package_nname_string = '';
60        if (count($package_nname) > 0) {
61            foreach ($package_nname as $type_str) {
62                $package_nname_string.= '&amp;package_nname[]=' . urlencode($type_str);
63            }
64        }
65
66        $link_params = [
67            'search_for'  => urlencode($search_for),
68            'project'     => urlencode($project),
69            'php_os'      => urlencode($php_os),
70            'php_os_not'  => $php_os_not,
71            'author_email' => urlencode($author_email),
72            'bug_type'    => urlencode($bug_type),
73            'boolean'     => $boolean_search,
74            'bug_age'     => $bug_age,
75            'bug_updated' => $bug_updated,
76            'order_by'    => $order_by,
77            'direction'   => $direction,
78            'limit'       => $limit,
79            'phpver'      => urlencode($phpver),
80            'cve_id'      => urlencode($cve_id),
81            'cve_id_not'  => $cve_id_not,
82            'patch'       => urlencode($patch),
83            'pull'        => urlencode($pull),
84            'assign'      => urlencode($assign),
85            'commented_by' => urlencode($commented_by),
86        ];
87
88        if ($is_security_developer) {
89            $link_params['private'] = $private;
90        }
91
92        // Remove empty URL parameters
93        foreach ($link_params as $index => $param) {
94            if (empty($param))
95                unset($link_params[$index]);
96        }
97
98        // Create link params string
99        $link_params_string = '';
100        foreach ($link_params as $index => $param) {
101            $link_params_string .= "&amp;$index=$param";
102        }
103
104        $link = "search.php?cmd=display{$package_name_string}{$package_nname_string}{$link_params_string}";
105        $clean_link = "search.php?cmd=display{$link_params_string}";
106
107        if (isset($_GET['showmenu'])) {
108            $link .= '&amp;showmenu=1';
109        }
110
111        if (!$rows) {
112            $errors[] = 'No bugs were found.';
113            display_bug_error($errors, 'warnings', '');
114        } else {
115            display_bug_error($warnings, 'warnings', 'WARNING:');
116            $link .= '&amp;status=' . urlencode($status);
117            $package_count = count($package_name);
118?>
119
120<table border="0" cellspacing="2" width="100%">
121
122<?php show_prev_next($begin, $rows, $total_rows, $link, $limit);?>
123
124<?php if ($package_count === 1) { ?>
125 <tr>
126  <td class="search-prev_next" style="text-align: center;" colspan="10">
127<?php
128    $pck = htmlspecialchars($package_name[0]);
129    $pck_url = urlencode($pck);
130    echo "Bugs for {$pck}\n";
131?>
132  </td>
133 </tr>
134<?php } ?>
135
136 <tr>
137  <th class="results"><a href="<?php echo $link;?>&amp;reorder_by=id">ID#</a></th>
138  <th class="results"><a href="<?php echo $link;?>&amp;reorder_by=ts1">Date</a></th>
139  <th class="results"><a href="<?php echo $link;?>&amp;reorder_by=ts2">Last Modified</a></th>
140<?php if ($package_count !== 1) { ?>
141  <th class="results"><a href="<?php echo $link;?>&amp;reorder_by=package_name">Package</a></th>
142<?php } ?>
143  <th class="results"><a href="<?php echo $link;?>&amp;reorder_by=bug_type">Type</a></th>
144  <th class="results"><a href="<?php echo $link;?>&amp;reorder_by=status">Status</a></th>
145  <th class="results"><a href="<?php echo $link;?>&amp;reorder_by=php_version">PHP Version</a></th>
146  <th class="results"><a href="<?php echo $link;?>&amp;reorder_by=php_os">OS</a></th>
147  <th class="results"><a href="<?php echo $link;?>&amp;reorder_by=sdesc">Summary</a></th>
148  <th class="results"><a href="<?php echo $link;?>&amp;reorder_by=assign">Assigned</a></th>
149 </tr>
150<?php
151
152            foreach ($result as $row) {
153                $status_class = $row['private'] == 'Y' ? 'Sec' : ($tla[$row['status']] ?? '');
154
155                echo ' <tr valign="top" class="' , $status_class, '">' , "\n";
156
157                // Bug ID
158                echo '  <td align="center"><a href="bug.php?id=', $row['id'], '">', $row['id'], '</a>';
159                echo '<br><a href="bug.php?id=', $row['id'], '&amp;edit=1">(edit)</a></td>', "\n";
160
161                // Date
162                echo '  <td align="center">', format_date(strtotime($row['ts1'])), "</td>\n";
163
164                // Last Modified
165                $ts2 = strtotime($row['ts2']);
166                echo '  <td align="center">' , ($ts2 ? format_date($ts2) : 'Not modified') , "</td>\n";
167
168                // Package
169                if ($package_count !== 1) {
170                    $pck = htmlspecialchars($row['package_name']);
171                    $pck_url = urlencode($pck);
172                    echo "<td><a href='{$clean_link}&amp;package_name[]={$pck_url}'>{$pck}</a></td>\n";
173                }
174
175                /// Bug type
176                $type_idx = !empty($row['bug_type']) ? $row['bug_type'] : 'Bug';
177                echo '  <td>', htmlspecialchars($bug_types[$type_idx]), '</td>', "\n";
178
179                // Status
180                echo '  <td>', htmlspecialchars($row['status']);
181                if ($row['status'] == 'Feedback' && $row['unchanged'] > 0) {
182                    printf ("<br>%d day%s", $row['unchanged'], $row['unchanged'] > 1 ? 's' : '');
183                }
184                echo '</td>', "\n";
185
186                /// PHP version
187                echo '  <td>', htmlspecialchars($row['php_version']), '</td>';
188
189                // OS
190                echo '  <td>', $row['php_os'] ? htmlspecialchars($row['php_os']) : '&nbsp;', '</td>', "\n";
191
192                // Short description
193                echo '  <td><a href="bug.php?id=', $row['id'], '">', $row['sdesc']  ? htmlspecialchars($row['sdesc']) : '&nbsp;', '</a></td>', "\n";
194
195                // Assigned to
196                echo '  <td>',  ($row['assign'] ? ("<a href=\"{$clean_link}&amp;assign=" . urlencode($row['assign']) . '">' . htmlspecialchars($row['assign']) . '</a>') : '&nbsp;'), '</td>';
197                echo " </tr>\n";
198            }
199
200            show_prev_next($begin, $rows, $total_rows, $link, $limit);
201
202            echo "</table>\n\n";
203        }
204
205        response_footer();
206        exit;
207    }
208}
209
210display_bug_error($errors);
211display_bug_error($warnings, 'warnings', 'WARNING:');
212
213?>
214<form id="asearch" method="get" action="search.php">
215<table id="primary" width="100%">
216<tr valign="top">
217  <th>Find bugs</th>
218  <td style="white-space: nowrap">with all or any of the w<span class="accesskey">o</span>rds</td>
219  <td style="white-space: nowrap"><input type="text" name="search_for" value="<?php echo htmlspecialchars($search_for, ENT_COMPAT, 'UTF-8'); ?>" size="20" maxlength="255" accesskey="o"><br>
220   <small>
221<?php show_boolean_options($boolean_search) ?>
222(<a href="search-howto.php" target="_new">?</a>)
223   </small>
224  </td>
225  <td rowspan="4">
226   <select name="limit"><?php show_limit_options($limit);?></select>
227   &nbsp;
228   <select name="order_by"><?php show_order_options($limit);?></select>
229   <br>
230   <small>
231    <input type="radio" name="direction" id="directionasc" value="ASC" <?= $direction != 'DESC' ? 'checked="checked"':'' ?>><label for="directionasc">Ascending</label>
232    <input type="radio" name="direction" id="directiondesc" value="DESC" <?= $direction == 'DESC' ? 'checked="checked"':'' ?>><label for="directiondesc">Descending</label>
233   </small>
234   <br><br>
235   <input type="hidden" name="cmd" value="display">
236   <label for="submit" accesskey="r">Sea<span class="accesskey">r</span>ch:</label>
237   <input id="submit" type="submit" value="Search">
238  </td>
239</tr>
240<tr valign="top">
241  <th>Status</th>
242  <td style="white-space: nowrap">
243   <label for="status" accesskey="n">Retur<span class="accesskey">n</span> bugs
244   with <b>status</b></label>
245  </td>
246  <td><select id="status" name="status"><?php show_state_options($status);?></select></td>
247</tr>
248<tr valign="top">
249  <th>Type</th>
250  <td style="white-space: nowrap">
251   <label for="bug_type">Return bugs with <b>type</b></label>
252  </td>
253  <td><select id="bug_type" name="bug_type"><?php show_type_options($bug_type, /* deprecated */ true, /* all */ true);?></select></td>
254</tr>
255<tr valign="top">
256  <th>Project</th>
257  <td style="white-space: nowrap">
258   <label for="bug_type">Return bugs with <b>project</b></label>
259  </td>
260  <td><select id="project" name="project">
261      <option value="All"<?php if ($project === ''): ?> selected="selected"<?php endif;?>>All</option>
262
263      <?php foreach (PackageRepository::PROJECTS as $key => $value): ?>
264        <option value="<?= htmlspecialchars($key, ENT_QUOTES); ?>" <?php if ($project === strtolower($key)): ?> selected="selected"<?php endif; ?>><?= htmlspecialchars($key, ENT_QUOTES); ?></option>
265      <?php endforeach; ?>
266    </select>
267  </td>
268</tr>
269</table>
270
271<table style="font-size: 100%;">
272<tr valign="top">
273  <th><label for="category" accesskey="c">Pa<span class="accesskey">c</span>kage</label></th>
274  <td style="white-space: nowrap">Return bugs for these <b>packages</b></td>
275  <td><select id="category" name="package_name[]" multiple="multiple" size="6"><?php show_package_options($package_name, 2);?></select></td>
276</tr>
277<tr valign="top">
278  <th>&nbsp;</th>
279  <td style="white-space: nowrap">Return bugs <b>NOT</b> for these <b>packages</b></td>
280  <td><select name="package_nname[]" multiple="multiple" size="6"><?php show_package_options($package_nname, 2);?></select></td>
281</tr>
282<tr valign="top">
283  <th>OS</th>
284  <td style="white-space: nowrap">Return bugs with <b>operating system</b></td>
285  <td>
286    <input type="text" name="php_os" value="<?php echo htmlspecialchars($php_os, ENT_COMPAT, 'UTF-8'); ?>">
287    <input type="checkbox" name="php_os_not" id="php_os_not" value="1" <?php echo ($php_os_not == 'not') ? 'checked="checked"' : ''; ?>><label for="php_os_not">NOT</label>
288  </td>
289</tr>
290<tr valign="top">
291  <th>PHP Version</th>
292  <td style="white-space: nowrap">Return bugs reported with <b>PHP version</b></td>
293  <td><input type="text" name="phpver" value="<?php echo htmlspecialchars($phpver, ENT_COMPAT, 'UTF-8'); ?>"></td>
294</tr>
295<tr valign="top">
296  <th>CVE-ID</th>
297  <td style="white-space: nowrap">Return bugs reported with <b>CVE-ID</b></td>
298  <td>
299    <input type="text" name="cve_id" value="<?php echo htmlspecialchars($cve_id, ENT_COMPAT, 'UTF-8'); ?>">
300    <input type="checkbox" name="cve_id_not" id="cve_id_not" value="1" <?php echo ($cve_id_not == 'not') ? 'checked="checked"' : ''; ?>><label for="cve_id_not">NOT</label>
301  </td>
302</tr>
303
304<tr valign="top">
305  <th>Assigned</th>
306  <td style="white-space: nowrap">Return bugs <b>assigned</b> to</td>
307  <td><input type="text" name="assign" value="<?php echo htmlspecialchars($assign, ENT_COMPAT, 'UTF-8'); ?>">
308<?php
309    if (!empty($auth_user->handle)) {
310        $u = htmlspecialchars($auth_user->handle);
311        echo "<input type=\"button\" value=\"set to $u\" onclick=\"form.assign.value='$u'\">";
312    }
313?>
314  </td>
315</tr>
316
317<tr valign="top">
318  <th>Author e<span class="accesskey">m</span>ail</th>
319  <td style="white-space: nowrap">Return bugs with author email</td>
320  <td><input accesskey="m" type="text" name="author_email" value="<?php echo htmlspecialchars($author_email, ENT_COMPAT, 'UTF-8'); ?>">
321<?php
322    if (!empty($auth_user->handle)) {
323        $u = htmlspecialchars($auth_user->handle);
324        echo "<input type=\"button\" value=\"set to $u\" onclick=\"form.author_email.value='$u@php.net'\">";
325    }
326?>
327  </td>
328</tr>
329<tr valign="top">
330  <th>Date</th>
331  <td style="white-space: nowrap">Return bugs submitted</td>
332  <td><select name="bug_age"><?php show_byage_options($bug_age);?></select></td>
333 </tr>
334 <tr>
335  <td>&nbsp;</td><td style="white-space: nowrap">Return bugs updated</td>
336  <td><select name="bug_updated"><?php show_byage_options($bug_updated);?></select></td>
337</tr>
338<tr valign="top">
339  <th>Patch</th>
340  <td style="white-space: nowrap">Return only bugs reported with <b>patch attached</b></td>
341  <td><input type="checkbox" name="patch" value="Y" <?php echo $patch == 'Y' ? " checked" : "" ?>></td>
342</tr>
343<tr valign="top">
344  <th>Pull Request</th>
345  <td style="white-space: nowrap">Return only bugs with a <b>pull request</b></td>
346  <td><input type="checkbox" name="pull" value="Y" <?php echo $pull == 'Y' ? " checked" : "" ?>></td>
347</tr>
348<tr>
349    <th>Commented by</th>
350    <td style="white-space: nowrap">Return bugs that have been <strong>commented by</strong></td>
351    <td><input type="email" name="commented_by" placeholder="me@example.com" value="<?php echo htmlspecialchars($commented_by, ENT_COMPAT, 'UTF-8'); ?>"></td>
352</tr>
353<?php
354    if ($is_security_developer) {
355?>
356<tr valign="top">
357  <th>Private</th>
358  <td style="white-space: nowrap">Return only bugs marked as <b>private</b></td>
359  <td><input type="checkbox" name="private" value="Y" <?php echo $private == 'Y' ? " checked" : "" ?>></td>
360</tr>
361<?php } ?>
362</table>
363</form>
364
365<?php
366response_footer();
367
368function show_prev_next($begin, $rows, $total_rows, $link, $limit)
369{
370    echo "<!-- BEGIN PREV/NEXT -->\n";
371    echo " <tr>\n";
372    echo '  <td class="search-prev_next" colspan="11">' . "\n";
373
374    if ($limit=='All') {
375        echo "$total_rows Bugs</td></tr>\n";
376        return;
377    }
378
379    echo '   <table border="0" cellspacing="0" cellpadding="0" width="100%">' . "\n";
380    echo "    <tr>\n";
381    echo '    <td class="search-prev">';
382    if ($begin > 0) {
383        echo '<a href="' . $link . '&amp;begin=';
384        echo max(0, $begin - $limit);
385        echo '">&laquo; Show Previous ' . $limit . ' Entries</a>';
386    } else {
387        echo '&nbsp;';
388    }
389    echo "</td>\n";
390
391    echo '   <td class="search-showing">Showing ' . ($begin+1);
392    echo '-' . ($begin+$rows) . ' of ' . $total_rows . "</td>\n";
393
394    echo '   <td class="search-next">';
395    if ($begin+$rows < $total_rows) {
396        echo '<a href="' . $link . '&amp;begin=' . ($begin+$limit);
397        echo '">Show Next ' . $limit . ' Entries &raquo;</a>';
398    } else {
399        echo '&nbsp;';
400    }
401    echo "</td>\n    </tr>\n   </table>\n  </td>\n </tr>\n";
402    echo "<!-- END PREV/NEXT -->\n";
403}
404
405function show_order_options($current)
406{
407    global $order_options;
408
409    foreach ($order_options as $k => $v) {
410        echo '<option value="', $k, '"', ($v == $current ? ' selected="selected"' : ''), '>Sort by ', $v, "</option>\n";
411    }
412}
413