brute-force changed access to $_GET['key'] to use get_array instead
[plewww.git] / planetlab / common / adminsearch.php
1 <?php
2
3   // $Id$
4
5 // Require login
6 require_once 'plc_login.php';
7
8 // Get session and API handles
9 require_once 'plc_session.php';
10 global $plc, $api;
11
12 // Print header
13 require_once 'plc_drupal.php';
14 // set default
15 drupal_set_title('DB Search');
16 include 'plc_header.php';
17
18 // Common functions
19 require_once 'plc_functions.php';
20 require_once 'plc_objects.php';
21 require_once 'plc_peers.php';
22 require_once 'table.php';
23 require_once 'form.php';
24 require_once 'toggle.php';
25
26 ini_set("memory_limit","256M");
27
28 if ( ! plc_is_admin()) {
29   plc_warning ("DB Search is available to admins only");
30   return;
31  }
32
33 $pattern="";
34 if (get_array($_GET,  'pattern')) { $pattern=$_GET['pattern']; }
35 if (get_array($_POST, 'pattern')) { $pattern=$_POST['pattern']; }
36
37 $tokens=explode(" ",$pattern);
38 function token_filter ($t) { $t = trim($t); if (empty($t)) return false; return true; }
39 $tokens=array_filter($tokens, "token_filter");
40
41
42 ////////////////////
43 // from a single search form, extract all tokens entered
44 // and then show all entities that match one of that tokens among
45 // persons - sites - slices - nodes
46 ////////////////////
47 function display_form ($pattern) {
48   if ($pattern) {
49     $title="Searching for $pattern";
50     $visible=false;
51   } else {
52     $title="Search for what";
53     $visible=true;
54   }
55   $toggle=new PlekitToggle("admin-search",$title,array('visible'=>$visible));
56   $toggle->start();
57   print <<< EOF
58 <p id='admin-search-message'>
59 This form searches for <span class="bold">any entry</span> in the database
60 (among <span class="bold">persons</span>, <span class="bold">slices</span>,
61 <span class="bold">sites</span> and <span class="bold">nodes</span>)
62 matching a name fragment, or token. <br/>
63 You can specify a space-separated list of tokens, all entries matching
64 <span class="bold">any token</span> would then get listed.
65 </p>
66 EOF;
67   print "<div id='admin-search-form'>";
68   $form=new PlekitForm ('/db/common/adminsearch.php',array());
69   $form->start();
70   print $form->label_html('pattern',"Enter space-separated tokens");
71   print $form->text_html('pattern',$pattern);
72   print $form->submit_html('submit','Submit');
73   $form->end();
74   print "</div>\n";
75   $toggle->end();
76 }
77
78 // just look for *token*
79 function token_pattern ($token) {
80   return "*" . $token . "*";
81 }
82
83 // $type is e.g. 'Persons' -- $field is e.g. 'email'
84 function generic_search ($type,$field,$tokens) {
85   global $api;
86   $results=array();
87   $methodname='Get'.$type;
88   /*
89     This was broken after 598e1e840b55262fd40c6d1700148e4f0b508065 change in plcapi.
90     We no longer generate a list of methods but let the api (php) object pass them through.
91
92   if ( ! method_exists($api,$methodname)) {
93     plc_error("generic_search failed with methodname=$methodname");
94     return $results;
95   }
96   */
97   foreach ($tokens as $token) {
98     $filter=array($field=>token_pattern($token));
99     $new_results = $api->$methodname($filter);
100     if (is_array($new_results)) {
101         $results = array_merge ($results, $new_results);
102     }
103   }
104   return $results;
105 }
106
107 // $objects is e.g. a collection of persons
108 // then, e.g. on slice,  $key='site_id'  & $plural=false
109 // or,   e.g. on person, $key='site_ids'  & $plural=true
110 function generic_gather_related ($objects, $key, $plural) {
111   if ( empty ($objects))
112     return array();
113   // else, look for either 'site_id' or 'site_ids' in the first object
114   $sample=$objects[0];
115   if ( array_key_exists($key,$sample)) {
116     $result=array();
117     foreach ($objects as $object) {
118       if ($plural) {
119         $result = array_merge ($result, $object[$key]);
120       } else {
121         $result []= $object[$key];
122       }
123     }
124     return $result;
125   } else {
126     plc_debug("gather_related failed with $key",$sample);
127     return array();
128   }
129 }
130
131 //////////
132 // create link from an id, using the various global hashes
133 function plc_person_link ($person_id) {global $persons_hash; return l_person_obj($persons_hash[$person_id]);}
134 function plc_slice_link ($slice_id) {global $slices_hash; return l_slice_obj($slices_hash[$slice_id]);}
135 function plc_site_link ($site_id) {global $sites_hash; return l_site_obj($sites_hash[$site_id]);}
136 function plc_node_link ($node_id) {global $nodes_hash; return l_node_obj($nodes_hash[$node_id]);}
137
138 global $table_options;
139 $table_options = array('notes_area'=>false);
140
141 global $peers;
142 $peers = new Peers ($api);
143
144 function display_persons ($persons,$visible) {
145   if ( ! $persons) return;
146
147   $toggle=new PlekitToggle('persons-area',"Persons",array('visible'=>$visible));
148   $toggle->start();
149
150   $headers=array('id'=>'int',
151                  'P'=>'string',
152                  'email'=>'string',
153                  'sites'=>'string',
154                  'slices'=>'string',
155                  'roles'=>'string');
156   global $table_options;
157   global $peers;
158   $table=new PlekitTable('persons',$headers,1,$table_options);
159   $table->start();
160   foreach ($persons as $person) {
161     $table->row_start();
162     $table->cell($person['person_id']);
163     $peers->cell($table,$person['peer_id']);
164     $table->cell(l_person_obj($person));
165     $table->cell(plc_vertical_table(array_map("plc_site_link",$person['site_ids'])));
166     $table->cell(plc_vertical_table(array_map("plc_slice_link",$person['slice_ids'])));
167     $table->cell(plc_vertical_table($person['roles']));
168     $table->row_end();
169   }
170   $table->end();
171   $toggle->end();
172 }
173
174 function display_slices ($slices,$visible) {
175   if ( ! $slices) return;
176
177   $toggle=new PlekitToggle('slices-area',"Slices",array('visible'=>$visible));
178   $toggle->start();
179
180   $headers=array('id'=>'int',
181                  'P'=>'string',
182                  'name'=>'string',
183                  'site'=>'string',
184                  'persons'=>'string',
185                  'N'=>'string');
186   global $table_options;
187   global $peers;
188   $table=new PlekitTable('slices',$headers,1,$table_options);
189   $table->start();
190   foreach ($slices as $slice) {
191     $table->row_start();
192     $table->cell($slice['slice_id']);
193     $peers->cell($table,$slice['peer_id']);
194     $table->cell(l_slice_obj($slice));
195     global $sites_hash;
196     $site=$sites_hash[$slice['site_id']];
197     $table->cell(l_site_obj($site));
198     $table->cell(plc_vertical_table(array_map("plc_person_link",$slice['person_ids'])));
199     // this makes really long tables, use the slice link to see details
200     //$table->cell(plc_vertical_table(array_map("plc_node_link",$slice['node_ids'])));
201     $table->cell(count($slice['node_ids']));
202     $table->row_end();
203   }
204   $table->end();
205   $toggle->end();
206 }
207
208 function display_sites ($sites,$visible) {
209   if ( ! $sites) return;
210
211   $toggle=new PlekitToggle('sites-area',"Sites",array('visible'=>$visible));
212   $toggle->start();
213
214   $headers=array('id'=>'int',
215                  'P'=>'string',
216                  'name'=>'string',
217                  'url'=>'string',
218                  'persons'=>'string',
219                  'slices'=>'string',
220                  'nodes'=>'string');
221   global $table_options;
222   global $peers;
223   $table=new PlekitTable('sites',$headers,1,$table_options);
224   $table->start();
225   foreach ($sites as $site) {
226     $table->row_start();
227     $table->cell($site['site_id']);
228     $peers->cell($table,$site['peer_id']);
229     $table->cell(l_site_obj($site));
230     $table->cell(href($site['url'],$site['url']));
231     $table->cell(plc_vertical_table(array_map("plc_person_link",$site['person_ids'])));
232     $table->cell(plc_vertical_table(array_map("plc_slice_link",$site['slice_ids'])));
233     $table->cell(plc_vertical_table(array_map("plc_node_link",$site['node_ids'])));
234     $table->row_end();
235   }
236   $table->end();
237   $toggle->end();
238 }
239
240 function display_nodes ($nodes,$visible) {
241   if ( ! $nodes) return;
242
243   $toggle=new PlekitToggle('nodes-area',"Nodes",array('visible'=>$visible));
244   $toggle->start();
245
246   $headers=array('id'=>'int',
247                  'P'=>'string',
248                  'hostname'=>'string',
249                  'site'=>'string',
250                  'slices'=>'string');
251   global $table_options;
252   global $peers;
253   $table=new PlekitTable('nodes',$headers,1,$table_options);
254   $table->start();
255   foreach ($nodes as $node) {
256     $table->row_start();
257     $table->cell($node['node_id']);
258     $peers->cell($table,$node['peer_id']);
259     $table->cell(l_node_obj($node));
260     global $sites_hash;
261     $site=$sites_hash[$node['site_id']];
262     $table->cell(l_site_obj($site));
263     // same as above, too many entries, just list how many there are
264     //$table->cell(plc_vertical_table(array_map("plc_slice_link",$node['slice_ids'])));
265     $table->cell(count($node['slice_ids']));
266     $table->row_end();
267   }
268   $table->end();
269   $toggle->end();
270 }
271
272
273 ////////////////////////////////////////////////////////////
274 display_form($pattern);
275
276 if ($pattern) {
277
278   ////////// search database
279   // search persons on email
280   $persons = array();
281   $persons = array_merge ($persons, generic_search ('Persons','email',$tokens));
282
283   // search slices on name
284   $slices=array();
285   $slices = array_merge ($slices, generic_search ('Slices','name',$tokens));
286
287   // search sites on name and login_base
288   $sites=array();
289   $sites = array_merge ($sites, generic_search('Sites','name',$tokens));
290   $sites = array_merge ($sites, generic_search('Sites','login_base',$tokens));
291
292   // nodes on hostname
293   $nodes=array();
294   $nodes = array_merge ($nodes, generic_search('Nodes','hostname',$tokens));
295
296   print "Search results for <span class='tokens'> $pattern </span>\n";
297
298   // what kind of result have we gotten:
299   // if none : display message and exit
300   // if only one kind of objects : start toggle with visible=true
301   // otherwise start all toggles with visible=false
302   $areas=0;
303   if ($persons) $areas += 1;
304   if ($slices) $areas += 1;
305   if ($sites) $areas += 1;
306   if ($nodes) $areas += 1;
307
308   if ( $areas == 0) {
309     plc_warning ("No result found");
310     return;
311   } else if ($areas == 1) {
312     $visible=true;
313   } else {
314     $visible=false;
315   }
316
317
318   ////////// collect all related objects
319   $rel_person_ids = array();
320   $rel_person_ids = array_merge($rel_person_ids, generic_gather_related ($sites,'person_ids',true));
321   $rel_person_ids = array_merge($rel_person_ids, generic_gather_related ($slices,'person_ids',true));
322
323   $rel_slice_ids = array();
324   $rel_slice_ids = array_merge($rel_slice_ids, generic_gather_related ($persons,'slice_ids',true));
325   $rel_slice_ids = array_merge($rel_slice_ids, generic_gather_related ($sites,'slice_ids',true));
326   $rel_slice_ids = array_merge($rel_slice_ids, generic_gather_related ($nodes,'slice_ids',true));
327
328   $rel_site_ids = array();
329   $rel_site_ids = array_merge ( $rel_site_ids, generic_gather_related ($persons,'site_ids',true));
330   $rel_site_ids = array_merge ( $rel_site_ids, generic_gather_related ($slices,'site_id',false));
331   $rel_site_ids = array_merge ( $rel_site_ids, generic_gather_related ($nodes,'site_id',false));
332
333   $rel_node_ids = array();
334   $rel_node_ids = array_merge($rel_node_ids, generic_gather_related ($sites,'node_ids',true));
335   $rel_node_ids = array_merge($rel_node_ids, generic_gather_related ($slices,'node_ids',true));
336
337
338   ////////// fetch related and store in a global hash
339   $rel_persons = $api->GetPersons ($rel_person_ids);
340   global $persons_hash; $persons_hash=array();
341   foreach ($rel_persons as $person) $persons_hash[$person['person_id']]=$person;
342
343   $rel_slices = $api->GetSlices ($rel_slice_ids);
344   global $slices_hash; $slices_hash=array();
345   foreach ($rel_slices as $slice) $slices_hash[$slice['slice_id']]=$slice;
346
347   $rel_sites = $api->GetSites ($rel_site_ids);
348   global $sites_hash; $sites_hash=array();
349   foreach ($rel_sites as $site) $sites_hash[$site['site_id']]=$site;
350
351   $rel_nodes = $api->GetNodes ($rel_node_ids);
352   global $nodes_hash; $nodes_hash=array();
353   foreach ($rel_nodes as $node) $nodes_hash[$node['node_id']]=$node;
354
355   ////////// show results
356   display_persons ($persons,$visible);
357   display_slices ($slices,$visible);
358   display_sites($sites,$visible);
359   display_nodes($nodes,$visible);
360
361  }
362
363 // Print footer
364 include 'plc_footer.php';
365
366 ?>