source: main/trunk/greenstone2/runtime-src/src/recpt/historydb.cpp@ 22067

Last change on this file since 22067 was 22067, checked in by ak19, 14 years ago
  1. More changes to makefiles: rm JDBMWrapper.jar and jdbm.jar on clean. 2. DB files (argdb, users, key, history) now not only for gdbm but to work with other db types like jdbm, sqlite and mssql.
  • Property svn:keywords set to Author Date Id Revision
File size: 9.1 KB
Line 
1/**********************************************************************
2 *
3 * historydb.cpp --
4 * Copyright (C) 1999 The New Zealand Digital Library Project
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26#include "historydb.h"
27#include "fileutil.h"
28#include "cgiutils.h"
29#include "recptproto.h"
30#include "recptprototools.h"
31#include "dbclass.h"
32
33#if defined(USE_GDBM)
34#include "gdbmclass.h"
35#define DBCLASS gdbmclass
36//#define DBFNAME "history.gdb"
37
38#elif defined(USE_JDBM)
39#include "jdbmnaiveclass.h"
40#define DBCLASS jdbmnaiveclass
41//#define DBFNAME "history.jdb"
42
43#elif defined(USE_SQLITE)
44#include "sqlitedbclass.h"
45#define DBCLASS sqlitedbclass
46//#define DBFNAME "history.litedb"
47
48#elif defined(USE_MSSQL)
49#include "mssqldbclass.h"
50#define DBCLASS mssqldbclass
51//#define DBFNAME "history.msdb"
52
53#else
54#error "Unable to compile Greenstone. Need at least one database backend enabled."
55#endif
56
57
58#define MAX_RECORDS 20
59#define HIST_SEP ';'
60
61
62dbclass* get_history_db_ptr (const text_t& gsdlhome)
63{
64 // Create a dbclass of the correct type
65 dbclass *historydb = NULL;
66
67 historydb = new DBCLASS(gsdlhome);
68
69 return historydb;
70}
71
72
73// returns true on success (in which case historyinfo will contain
74// the information for this history)
75bool get_history_info (const text_t &userid, text_tarray &historyinfo,
76 const text_t &gsdlhome, ostream &logout) {
77
78 bool result = false;
79
80 // Create a dbclass of the correct type
81 dbclass *historydb = get_history_db_ptr(gsdlhome);
82 if (historydb == NULL) return false;
83 text_t historyfile = filename_cat(gsdlhome, "etc", "history") + historydb->getfileextension();
84
85 // open the history database
86 if (historydb->opendatabase(historyfile, DB_READER, 1000, true)) {
87 // get history list
88 text_t historyresult;
89
90 historydb->getkeydata(userid, historyresult);
91
92 if (historyresult != "") { // there are entries, process them
93
94 splitchar(historyresult.begin(), historyresult.end(), '\n', historyinfo);
95 result = true;
96 }
97 historydb->closedatabase();
98
99 } else {
100 outconvertclass text_t2ascii;
101 logout << text_t2ascii << "couldn't open history database " << historyfile << "\n";
102 }
103
104 delete historydb;
105 return result;
106}
107
108
109// returns true on success
110// changed to only save 20 records per user, numbers not included
111// only save if there are already entries there, or if display=true
112bool set_history_info (const text_t &userid, const text_t &history, const text_t &gsdlhome, bool display) {
113
114 bool result = false;
115
116 // Create a dbclass of the correct type
117 dbclass *historydb = get_history_db_ptr(gsdlhome);
118 if (historydb == NULL) return false;
119 text_t historyfile = filename_cat(gsdlhome, "etc", "history") + historydb->getfileextension();
120
121 text_t oldhistoryresult;
122 text_t newhistoryresult;
123 int numentries=0;
124
125 // open the history database
126 if (!historydb->opendatabase(historyfile, DB_READER, 1000, true)) {
127 // not created yet
128 oldhistoryresult="";
129 if (!display) return true; // dont need to save
130 }
131 else {
132
133 // get history list
134 if (! historydb->getkeydata(userid, oldhistoryresult)) {
135 oldhistoryresult="";
136 if (!display) return true; // dont need to save
137 }
138 historydb->closedatabase();
139 }
140
141 text_tarray entries;
142
143 if (oldhistoryresult!="") {
144 splitchar(oldhistoryresult.begin(), oldhistoryresult.end(), '\n', entries);
145 numentries = entries.size();
146 if (numentries >= MAX_RECORDS) numentries = MAX_RECORDS-1;
147 }
148
149 // open for writing
150 if (!historydb->opendatabase(historyfile, DB_WRITER_CREATE, 1000, true)) return false;
151
152 // add on new linethe new record to the front of the list, then add the
153 // appropriate entries from the old stuff
154 newhistoryresult += history;
155 newhistoryresult += "\n";
156 for (int i=0; i<numentries;++i) {
157 newhistoryresult += entries[i]+"\n";
158 }
159
160 if (historydb->setkeydata(userid, newhistoryresult))
161 result=true;
162
163 historydb->closedatabase();
164 delete historydb;
165 return result;
166}
167
168// deletes all a users history
169bool delete_all_history_info (const text_t &userid, const text_t &gsdlhome) {
170
171 // Create a dbclass of the correct type
172 dbclass *historydb = get_history_db_ptr(gsdlhome);
173 if (historydb == NULL) return false;
174 text_t historyfile = filename_cat(gsdlhome, "etc", "history") + historydb->getfileextension();
175
176 // open the history database
177 if (!historydb->opendatabase(historyfile, DB_WRITER, 1000, true)) return false;
178
179 historydb->deletekey(userid);
180 historydb->closedatabase();
181 delete historydb;
182 return true;
183
184}
185
186// retrieves the value of one of the arguments
187void parse_saved_args(text_t &args, text_t key, text_t &value)
188{
189 text_t::iterator here = args.begin();
190 text_t::iterator end = args.end();
191 text_t::iterator it;
192 while (here != end) {
193 if(*here==key[0]) {
194 it=findchar(here, end, '=');
195 if (it==end) {
196 value=""; return;
197 }
198 text_t entry = substr(here, it);
199 if (entry==key) {
200 here=it+1;
201 it=findchar(here, end, HIST_SEP);
202 value = substr(here, it);
203 return;
204 }
205 }
206 ++here;
207 }// while
208}
209
210// retrieves the value of all of the arguments
211void parse_saved_args(text_t &args, infodbclass &info)
212{
213 text_t::iterator here = args.begin();
214 text_t::iterator end = args.end();
215 text_t::iterator it;
216 text_tarray values;
217
218 splitchar(here, end, HIST_SEP, values);
219
220 text_tarray::iterator start = values.begin();
221 text_tarray::iterator stop = values.end();
222
223 text_t key;
224 text_t value;
225 while(start!=stop) {
226
227 here=(*start).begin();
228 end=(*start).end();
229 it=findchar(here, end, '=');
230 if (it!=end) {
231 key = substr(here, it);
232 value = substr(it+1, end);
233
234 info[key]=value;
235 }
236 ++start;
237 }
238}
239
240
241void split_saved_query(text_t &query, text_t &numdocs, text_t &cgiargs)
242{
243 text_t::iterator begin = query.begin();
244 text_t::iterator end = query.end();
245
246 while (*begin >='0'&& *begin <='9') { // get the digits for numdocs
247 numdocs.push_back(*begin);
248 ++begin;
249 }
250
251 if (*begin == '+') { // get the + if there
252 numdocs.push_back(*begin);
253 ++begin;
254 }
255 if (*begin == ':') { // have the old format - previous bit was record number
256 numdocs.clear();
257 ++begin;
258
259 while(*begin >='0' && *begin <='9') { // get the digits
260 numdocs.push_back(*begin);
261 ++begin;
262 }
263 if (*begin == '+') { // get the + if there
264 numdocs.push_back(*begin);
265 ++begin;
266 }
267 }
268 cgiargs += (substr(begin, end)); // put rest of query into cgiargs
269
270}
271
272void format_user_info (text_t &historyargs, text_t &userinfo,
273 cgiargsclass &args,
274 recptprotolistclass *protos, ostream &logout)
275{
276 text_tset metadata;
277 userinfo.clear();
278
279 infodbclass argsinfo;
280 parse_saved_args(historyargs, argsinfo);
281 text_t collect = argsinfo["c"];
282 if (collect=="") {
283 userinfo="";
284 return;
285 }
286
287 if (collect != args["c"]) {
288 userinfo += collect+", ";
289 }
290
291 if (argsinfo["h"] != args["h"]) {
292
293 recptproto *collectproto = protos->getrecptproto(collect,logout);
294 if (collectproto == NULL) {
295 userinfo="";
296 return;
297 }
298 metadata.insert(argsinfo["h"]);
299 FilterResponse_t response;
300
301 get_info("collection", collect, args["l"], metadata, false, collectproto, response, logout);
302 text_t index = response.docInfo[0].metadata[argsinfo["h"]].values[0];
303 if (!index.empty()) {
304 userinfo += index+", ";
305 }
306 }
307
308 if (argsinfo["b"] != args["b"] || argsinfo["t"] != args["t"]) {
309 if (argsinfo["b"]=="0") { // simple mode
310 if (argsinfo["t"]=="0") {
311 userinfo += " _texthallwords_, ";
312 }
313 else if (argsinfo["t"]=="1"){
314 userinfo += " _texthsomewords_, ";
315 }
316
317 }
318 else if (argsinfo["b"] == "1") { // advanced mode
319 if (argsinfo["t"]=="0") {
320 userinfo += " _texthboolean_, ";
321 }
322 else if (argsinfo["t"]=="1") {
323 userinfo += " _texthranked_, ";
324 }
325 }
326 }
327
328 if (argsinfo["k"] != "" && argsinfo["k"] != args["k"]) {
329 text_t options;
330 // the text translations are the wrong way round
331 if (argsinfo["k"]=="1") {
332 userinfo += " _texthcaseoff_, ";
333 }
334 else if (argsinfo["k"]=="0") {
335 userinfo += " _texthcaseon_, ";
336 }
337 }
338
339 if (argsinfo["s"] != "" && argsinfo["s"] != args["s"]) {
340 if (argsinfo["s"]=="0") {
341 userinfo += " _texthstemoff_, ";
342 }
343 else if (argsinfo["s"]=="1") {
344 userinfo += " _texthstemon_, ";
345 }
346 }
347
348}
Note: See TracBrowser for help on using the repository browser.