source: trunk/gsdl/src/recpt/historydb.cpp@ 928

Last change on this file since 928 was 928, checked in by kjm18, 24 years ago

search history stuff added.

  • Property svn:keywords set to Author Date Id Revision
File size: 14.5 KB
Line 
1
2#include "historydb.h"
3#include "gsdlhome.h"
4#include "fileutil.h"
5#include "cgiutils.h"
6#include "recptproto.h"
7#include "OIDtools.h"
8
9
10// returns true on success (in which case historyinfo will contain
11// the information for this history)
12bool get_history_info (const text_t &userid, text_tarray &historyinfo)
13{
14 text_t historyfile = filename_cat(GSDL_GSDLHOME, "etc", "history.db");
15
16 bool result = false;
17 // open the history database
18 gdbmclass historydb;
19
20 if (historydb.opendatabase(historyfile, GDBM_READER, 1000, true)) {
21 // get history list
22 text_t historyresult;
23
24 historydb.getkeydata(userid, historyresult);
25
26 if (historyresult != "") { // there are entries, process them
27
28 splitchar(historyresult.begin(), historyresult.end(), '\n', historyinfo);
29 result = true;
30 }
31 historydb.closedatabase();
32
33 } // opendatabase
34 else {
35 cerr << "couldn't open db\n";
36
37 }
38 return result;
39} // get history info
40
41
42// returns true on success
43bool set_history_info (const text_t &userid, const text_t &history)
44{
45
46 text_t historyfile = filename_cat(GSDL_GSDLHOME, "etc", "history.db");
47
48 bool result = false;
49 // open the history database
50 gdbmclass historydb;
51
52 text_t querynum;
53 text_t historyresult;
54
55
56 if ( !historydb.opendatabase(historyfile, GDBM_READER, 1000, true)) {
57 // not created yet
58 historyresult="";
59 querynum="1";
60 }
61 else {
62
63 // get history list
64 if (! historydb.getkeydata(userid, historyresult)) {
65 historyresult="";
66 querynum="1";
67 }
68 historydb.closedatabase();
69 }
70
71 // get next query num
72 if (historyresult!="") {
73 text_tarray entries;
74 splitchar(historyresult.begin(), historyresult.end(), '\n', entries);
75 get_query_num(entries.back(), querynum);
76 querynum.setint(querynum.getint()+1);
77 }
78
79 // open for writing
80 if (!historydb.opendatabase(historyfile, GDBM_WRCREAT, 1000, true)) return false;
81
82 // add on new line
83 historyresult += querynum;
84 historyresult += ":";
85 historyresult += history;
86 historyresult += "\n";
87
88 if (historydb.setinfo(userid, historyresult))
89 result=true;
90
91 historydb.closedatabase();
92 return result;
93}
94
95// deletes all a users history
96bool delete_all_history_info (const text_t &userid)
97{
98 text_t historyfile = filename_cat(GSDL_GSDLHOME, "etc", "history.db");
99
100 // open the history database
101 gdbmclass historydb;
102
103 if ( !historydb.opendatabase(historyfile, GDBM_WRITER, 1000, true)) return false;
104
105 historydb.deletekey(userid);
106 return true;
107
108}
109
110//deletes only the selected records
111bool delete_history_info(const text_t &userid, const text_t &deletemode, const text_t &selection)
112{
113 text_t historyfile = filename_cat(GSDL_GSDLHOME, "etc", "history.db");
114 bool result;
115 // open the history database
116 gdbmclass historydb;
117
118 if ( !historydb.opendatabase(historyfile, GDBM_READER, 1000, true)) return false;
119
120 // get history list
121 text_t historyresult;
122
123 if (! historydb.getkeydata(userid, historyresult)) return false;
124
125 historydb.closedatabase();
126
127 text_t newhistory; // for the new list of search history
128 // get list of queries
129 text_tarray queries;
130 splitchar(historyresult.begin(), historyresult.end(), '\n', queries);
131 text_tarray::iterator begin=queries.begin();
132 text_tarray::iterator end=queries.end();
133
134 // get list of numbers to delete
135 text_tarray numbers;
136 splitchar(selection.begin(), selection.end(), ',', numbers);
137 text_tarray::iterator numbegin=numbers.begin();
138 text_tarray::iterator numend=numbers.end();
139
140 bool tdefault, tset;
141 if (deletemode=="delete") {
142 tdefault=true;
143 tset=false;
144 }
145 else {// deletemode == save
146 tdefault=false;
147 tset=true;
148 }
149
150 // create a HistRecord map of all the entries
151 HistRecordmap records;
152 while (begin != end) {
153 HistRecord rec;
154 rec.entry=*begin;
155 rec.save=tdefault;
156 text_t num;
157 get_query_num(*begin, num);
158 records[num] = rec;
159 begin++;
160 }
161
162
163 // now set the save field for all records that are selected
164 while(numbegin != numend) {
165
166 if (is_number(*numbegin)) {
167 if (records.count(*numbegin)==1) {
168 records[*numbegin].save=tset;
169 } // else invalid number
170 }
171 else{
172 int start, stop;
173 if (get_selection_params(*numbegin, start, stop)) {
174 for (int i=start; i<=stop; i++) {
175 text_t num = i;
176 if (records.count(num)==1) {
177 records[num].save=tset;
178 }
179 }}
180 else { // dodgy format
181 // error message
182 }
183
184 }
185 numbegin++;
186 } // while
187
188 HistRecordmap::iterator recbegin = records.begin();
189 HistRecordmap::iterator recend = records.end();
190
191 //create new history record - go through all Records
192 // and add to new history those with save set to true
193 while (recbegin != recend) {
194 if ((*recbegin).second.save) {
195 expand_query((*recbegin).second, records);
196 newhistory += (*recbegin).second.entry + "\n";
197 }
198 recbegin++;
199 }
200
201 // open for writing
202 if (!historydb.opendatabase(historyfile, GDBM_WRITER, 1000, true)) return false;
203
204 if (historydb.setinfo(userid, newhistory))
205 result=true;
206
207 historydb.closedatabase();
208 return result;
209
210
211}
212
213bool get_selection_params (text_t &data, int &start, int &stop)
214{
215 text_tarray results;
216
217 splitchar(data.begin(), data.end(), '-', results);
218 if (results.size()==2 && is_number(results[0]) && is_number(results[1])) {
219 start=results[0].getint();
220 stop=results[1].getint();
221
222 return true;
223 }
224 else {
225 // error message
226 return false;
227 }
228
229}
230
231// expand query takes a HistRecord, and expands out any hashes in
232// the query string for queries that aren't to be saved
233bool expand_query(HistRecord &record, HistRecordmap &records)
234{
235 text_tarray args;
236 splitchar(record.entry.begin(), record.entry.end(), '&', args);
237
238 text_tarray::iterator begin=args.begin();
239 text_tarray::iterator end=args.end();
240
241 text_t query;
242 // find the q argument
243 while(begin != end) {
244 if ((*begin)[0] == 'q'&& (*begin)[1] == '=') {
245 query=*begin;
246 args.erase(begin);
247 break;
248 }
249 else {
250 begin++;
251 }
252 }
253 if (query !="") {
254
255 //remove the q=
256 text_t::iterator front = query.begin();
257 query.erase(front);
258 front=query.begin();
259
260 query.erase(front);
261 decode_cgi_arg(query);
262 // now have just the query string
263 // check any refs in it to see if they are still valid
264 combine_query(query, records);
265 text_t formattedquery = cgi_safe(query);
266 text_t newquery = "q=";
267 newquery += formattedquery;
268
269 args.push_back(newquery);
270 joinchar(args, '&', record.entry);
271
272 return true;
273 }else return false;
274}// expand query
275
276// replaces a reference to a previous query with the search
277// string from that query
278bool combine_query(text_t &userid, text_t &query)
279{
280 text_t::iterator begin = query.begin();
281 text_t::iterator end = query.end();
282 text_t::iterator it = findchar(begin, end, '#');
283 if (it==end) return true; // no need to swap anything
284
285
286 text_t queryresult = "";
287 text_t historyfile = filename_cat(GSDL_GSDLHOME, "etc", "history.db");
288 text_t historyresult;
289 // open the history database
290 gdbmclass historydb;
291 bool exists = false;
292 if (historydb.opendatabase(historyfile, GDBM_READER, 1000, true)) {
293 // get history list
294 if (historydb.getkeydata(userid, historyresult)) {
295 exists=true;
296
297 historydb.closedatabase();
298 }
299 }
300 if (!exists) {// cant open history file, or user entry doesn't exist. replace #x with blanks
301 while(it !=end) {
302 queryresult += substr(begin, it);
303 it++;
304 while(*it>='0'&&*it<='9') it++;
305 begin=it;
306 it=findchar(begin, end, '#');
307 }
308 queryresult += substr(begin, end);
309 query = queryresult;
310 return false;
311 }
312 bool result=true;
313
314 // if have got to here, have a previous history in historyresult
315 text_tarray historyinfo;
316 splitchar(historyresult.begin(), historyresult.end(), '\n', historyinfo);
317 text_tarray::iterator histbegin = historyinfo.begin();
318 text_tarray::iterator histend = historyinfo.end();
319
320 text_tmap historymap;
321 // put all entries into a map, so can pull out the appropriate one easily
322 while (histbegin != histend) {
323 text_t num;
324 get_query_num(*histbegin, num);
325 historymap[num]=*histbegin;
326 histbegin++;
327 }
328 while(it!=end) { // while there still is a hash present
329 text_t querynum;
330 text_t newquery;
331
332 while (begin!=end) {
333 if (*begin==text_t('#')) {
334 begin++;
335 while(begin !=end && *begin>='0'&&*begin<='9') {
336 querynum.push_back(*begin);
337 begin++;
338 }
339 text_t oldquery = historymap[querynum];
340 if (oldquery !="") { // valid entry
341 parse_saved_args(oldquery, text_t("q"), newquery);
342 decode_cgi_arg(newquery);
343 queryresult += newquery;
344 }
345 else {
346 result=false;
347 }
348 querynum.clear();
349 // else do nothing (replace #x with nothing)
350 } // if
351 else {
352 queryresult.push_back(*begin);
353 begin++;
354 }
355 } // while begin!=end
356
357 // have got to end of query string,
358 // now go back and check for internal #
359 query = queryresult;
360 begin = query.begin();
361 end = query.end();
362 it = findchar(begin, end, '#');
363 queryresult.clear();
364
365 } // while it !=end
366
367
368 return result;
369
370} // combine query
371
372
373// replaces a reference to a previous query with the search
374// string from that query, uses the Histrecordmap rather than the GDBM file
375bool combine_query( text_t &query, HistRecordmap &records)
376{
377 text_t::iterator begin = query.begin();
378 text_t::iterator end = query.end();
379 text_t::iterator it = findchar(begin, end, '#');
380 if (it==end) return true; // no need to swap anything
381
382 text_t queryresult = "";
383 bool changed=true;
384 while(it!=end && changed) { // while there still is a hash present
385 // and query has changed since last time round
386 // we are leaving some #X in
387 text_t querynum;
388 text_t newquery;
389 changed=false;
390 while (begin!=end) { // go through the query looking for hash
391 if (*begin==text_t('#')) {
392 begin++;
393 while(begin !=end && *begin>='0'&&*begin<='9') {
394 querynum.push_back(*begin);
395 begin++;
396 }
397 if(records.count(querynum)>0) { // valid entry
398 if (!records[querynum].save){ // referenced record to be deleted
399 // get the q arg out of referenced query
400 parse_saved_args(records[querynum].entry, text_t("q"), newquery);
401 decode_cgi_arg(newquery);
402 queryresult += newquery;
403 changed=true;
404 }
405 else { // leave the #x in
406 queryresult.push_back('#');
407 queryresult += querynum;
408 }
409 }
410 querynum.clear();
411 newquery.clear();
412 // else do nothing (replace #x with nothing)
413 } // if its a hash
414 else {
415 queryresult.push_back(*begin);
416 begin++;
417 }
418 } // while begin!=end
419
420 // have got to end of query string,
421 // now go back and check for internal #
422 query = queryresult;
423 begin = query.begin();
424 end = query.end();
425 it = findchar(begin, end, '#');
426 queryresult.clear();
427
428 } // while it !=end
429
430
431 return true;
432
433} // combine query
434
435// retrieves the value of one of the arguments
436void parse_saved_args(text_t &args, text_t &key, text_t &value)
437{
438 text_t::iterator here = args.begin();
439 text_t::iterator end = args.end();
440 text_t::iterator it;
441 while (here != end) {
442 if(*here==key[0]) {
443 it=findchar(here, end, '=');
444 if (it==end) {
445 value=""; return;
446 }
447 text_t entry = substr(here, it);
448 if (entry==key) {
449 here=it+1;
450 it=findchar(here, end, '&');
451 value = substr(here, it);
452 return;
453 }
454 }
455 here++;
456 }// while
457}
458
459// retrieves the value of all of the arguments
460void parse_saved_args(text_t &args, infodbclass &info)
461{
462 text_t::iterator here = args.begin();
463 text_t::iterator end = args.end();
464 text_t::iterator it;
465 text_tarray values;
466
467 splitchar(here, end, '&', values);
468
469 text_tarray::iterator start = values.begin();
470 text_tarray::iterator stop = values.end();
471
472 text_t key;
473 text_t value;
474 while(start!=stop) {
475
476 here=(*start).begin();
477 end=(*start).end();
478 it=findchar(here, end, '=');
479 if (it!=end) {
480 key = substr(here, it);
481 value = substr(it+1, end);
482
483 info[key]=value;
484 }
485 start++;
486 }
487}
488
489void get_query_num(text_t &query, text_t &querynum)
490{
491 text_t::iterator begin = query.begin();
492
493 while (*begin >='0'&& *begin <='9') { // get the digits
494 querynum.push_back(*begin);
495 begin++;
496 }
497 if (*begin != ':') {
498 // something has gone wrong
499 }
500}
501void split_saved_query(text_t &query, text_t &querynum, text_t &numdocs, text_t &cgiargs)
502{
503 text_t::iterator begin = query.begin();
504 text_t::iterator end = query.end();
505
506 while (*begin >='0'&& *begin <='9') { // get the digits
507 querynum.push_back(*begin);
508 begin++;
509 }
510 if (*begin != ':') {
511 // something has gone wrong
512 }
513 else begin++;
514 while (*begin >='0'&& *begin <='9') { // get the digits
515 numdocs.push_back(*begin);
516 begin++;
517 }
518 if (*begin == '+') { // get the + if there
519 numdocs.push_back(*begin);
520 begin++;
521 }
522
523 cgiargs += (substr(begin, end)); // put rest of query into cgiargs
524
525}
526
527void format_user_info (text_t &cgiargs, text_t &userinfo, recptprotolistclass *protos, ostream &logout)
528{
529 logout << "in format user info";
530 text_tset metadata;
531
532 infodbclass argsinfo;
533 parse_saved_args(cgiargs, argsinfo);
534
535 text_t collect = argsinfo["c"];
536 if (collect=="") {
537 userinfo="";
538 return;
539 }
540 recptproto *collectproto = protos->getrecptproto(collect,logout);
541 if (collectproto == NULL) {
542 userinfo="";
543 return;
544 }
545 metadata.insert(argsinfo["h"]);
546 FilterResponse_t response;
547
548 get_info("collection", collect, metadata, false, collectproto, response, logout);
549
550 text_t index = response.docInfo[0].metadata[argsinfo["h"]].values[0];
551
552 text_t mode;
553 if (argsinfo["b"]=="0") { // simple mode
554 if (argsinfo["t"]=="0") {
555 mode = "all words";
556 }
557 else { // t=1
558 mode = "some words";
559 }
560
561 }
562 else { // advanced mode
563 if (argsinfo["t"]=="0") {
564 mode = "boolean";
565 }
566 else {
567 mode = "ranked";
568 }
569 }
570
571 text_t options;
572 if (argsinfo["k"]=="0") {
573 options = "case must match";
574 }
575 else {
576 options = "ignore case";
577 }
578 if (argsinfo["s"]=="0") {
579 options += ", whole word must match";
580 }
581 else {
582 options += ", ignore word endings";
583 }
584
585 userinfo.clear();
586 userinfo = "collection ("+argsinfo["c"] + ") ";
587 userinfo += "search (" + index + ") ";
588 userinfo += "mode (" + mode +") ";
589 userinfo += "options (" + options + ")";
590
591 logout << "in format user info - end";
592}
593
594
595
596
597
598
599
600
601
Note: See TracBrowser for help on using the repository browser.