/********************************************************************** * * historydb.cpp -- * Copyright (C) 1999 The New Zealand Digital Library Project * * A component of the Greenstone digital library software * from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *********************************************************************/ #include "historydb.h" #include "fileutil.h" #include "cgiutils.h" #include "recptproto.h" #include "recptprototools.h" #include "dbclass.h" #if defined(USE_GDBM) #include "gdbmclass.h" #define DBCLASS gdbmclass //#define DBFNAME "history.gdb" #elif defined(USE_JDBM) #include "jdbmnaiveclass.h" #define DBCLASS jdbmnaiveclass //#define DBFNAME "history.jdb" #elif defined(USE_SQLITE) #include "sqlitedbclass.h" #define DBCLASS sqlitedbclass //#define DBFNAME "history.litedb" #elif defined(USE_MSSQL) #include "mssqldbclass.h" #define DBCLASS mssqldbclass //#define DBFNAME "history.msdb" #else #error "Unable to compile Greenstone. Need at least one database backend enabled." #endif #define MAX_RECORDS 20 #define HIST_SEP ';' dbclass* get_history_db_ptr (const text_t& gsdlhome) { // Create a dbclass of the correct type dbclass *historydb = NULL; historydb = new DBCLASS(gsdlhome); return historydb; } // returns true on success (in which case historyinfo will contain // the information for this history) bool get_history_info (const text_t &userid, text_tarray &historyinfo, const text_t &gsdlhome, ostream &logout) { bool result = false; // Create a dbclass of the correct type dbclass *historydb = get_history_db_ptr(gsdlhome); if (historydb == NULL) return false; text_t historyfile = filename_cat(gsdlhome, "etc", "history") + historydb->getfileextension(); // open the history database if (historydb->opendatabase(historyfile, DB_READER, 1000, true)) { // get history list text_t historyresult; historydb->getkeydata(userid, historyresult); if (historyresult != "") { // there are entries, process them splitchar(historyresult.begin(), historyresult.end(), '\n', historyinfo); result = true; } historydb->closedatabase(); } else { outconvertclass text_t2ascii; logout << text_t2ascii << "couldn't open history database " << historyfile << "\n"; } delete historydb; return result; } // returns true on success // changed to only save 20 records per user, numbers not included // only save if there are already entries there, or if display=true bool set_history_info (const text_t &userid, const text_t &history, const text_t &gsdlhome, bool display) { bool result = false; // Create a dbclass of the correct type dbclass *historydb = get_history_db_ptr(gsdlhome); if (historydb == NULL) return false; text_t historyfile = filename_cat(gsdlhome, "etc", "history") + historydb->getfileextension(); text_t oldhistoryresult; text_t newhistoryresult; int numentries=0; // open the history database if (!historydb->opendatabase(historyfile, DB_READER, 1000, true)) { // not created yet oldhistoryresult=""; if (!display) return true; // dont need to save } else { // get history list if (! historydb->getkeydata(userid, oldhistoryresult)) { oldhistoryresult=""; if (!display) return true; // dont need to save } historydb->closedatabase(); } text_tarray entries; if (oldhistoryresult!="") { splitchar(oldhistoryresult.begin(), oldhistoryresult.end(), '\n', entries); numentries = entries.size(); if (numentries >= MAX_RECORDS) numentries = MAX_RECORDS-1; } // open for writing if (!historydb->opendatabase(historyfile, DB_WRITER_CREATE, 1000, true)) return false; // add on new linethe new record to the front of the list, then add the // appropriate entries from the old stuff newhistoryresult += history; newhistoryresult += "\n"; for (int i=0; isetkeydata(userid, newhistoryresult)) result=true; historydb->closedatabase(); delete historydb; return result; } // deletes all a users history bool delete_all_history_info (const text_t &userid, const text_t &gsdlhome) { // Create a dbclass of the correct type dbclass *historydb = get_history_db_ptr(gsdlhome); if (historydb == NULL) return false; text_t historyfile = filename_cat(gsdlhome, "etc", "history") + historydb->getfileextension(); // open the history database if (!historydb->opendatabase(historyfile, DB_WRITER, 1000, true)) return false; historydb->deletekey(userid); historydb->closedatabase(); delete historydb; return true; } // retrieves the value of one of the arguments void parse_saved_args(text_t &args, text_t key, text_t &value) { text_t::iterator here = args.begin(); text_t::iterator end = args.end(); text_t::iterator it; while (here != end) { if(*here==key[0]) { it=findchar(here, end, '='); if (it==end) { value=""; return; } text_t entry = substr(here, it); if (entry==key) { here=it+1; it=findchar(here, end, HIST_SEP); value = substr(here, it); return; } } ++here; }// while } // retrieves the value of all of the arguments void parse_saved_args(text_t &args, infodbclass &info) { text_t::iterator here = args.begin(); text_t::iterator end = args.end(); text_t::iterator it; text_tarray values; splitchar(here, end, HIST_SEP, values); text_tarray::iterator start = values.begin(); text_tarray::iterator stop = values.end(); text_t key; text_t value; while(start!=stop) { here=(*start).begin(); end=(*start).end(); it=findchar(here, end, '='); if (it!=end) { key = substr(here, it); value = substr(it+1, end); info[key]=value; } ++start; } } void split_saved_query(text_t &query, text_t &numdocs, text_t &cgiargs) { text_t::iterator begin = query.begin(); text_t::iterator end = query.end(); while (*begin >='0'&& *begin <='9') { // get the digits for numdocs numdocs.push_back(*begin); ++begin; } if (*begin == '+') { // get the + if there numdocs.push_back(*begin); ++begin; } if (*begin == ':') { // have the old format - previous bit was record number numdocs.clear(); ++begin; while(*begin >='0' && *begin <='9') { // get the digits numdocs.push_back(*begin); ++begin; } if (*begin == '+') { // get the + if there numdocs.push_back(*begin); ++begin; } } cgiargs += (substr(begin, end)); // put rest of query into cgiargs } void format_user_info (text_t &historyargs, text_t &userinfo, cgiargsclass &args, recptprotolistclass *protos, ostream &logout) { text_tset metadata; userinfo.clear(); infodbclass argsinfo; parse_saved_args(historyargs, argsinfo); text_t collect = argsinfo["c"]; if (collect=="") { userinfo=""; return; } if (collect != args["c"]) { userinfo += collect+", "; } if (argsinfo["h"] != args["h"]) { recptproto *collectproto = protos->getrecptproto(collect,logout); if (collectproto == NULL) { userinfo=""; return; } metadata.insert(argsinfo["h"]); FilterResponse_t response; get_info("collection", collect, args["l"], metadata, false, collectproto, response, logout); text_t index = response.docInfo[0].metadata[argsinfo["h"]].values[0]; if (!index.empty()) { userinfo += index+", "; } } if (argsinfo["b"] != args["b"] || argsinfo["t"] != args["t"]) { if (argsinfo["b"]=="0") { // simple mode if (argsinfo["t"]=="0") { userinfo += " _texthallwords_, "; } else if (argsinfo["t"]=="1"){ userinfo += " _texthsomewords_, "; } } else if (argsinfo["b"] == "1") { // advanced mode if (argsinfo["t"]=="0") { userinfo += " _texthboolean_, "; } else if (argsinfo["t"]=="1") { userinfo += " _texthranked_, "; } } } if (argsinfo["k"] != "" && argsinfo["k"] != args["k"]) { text_t options; // the text translations are the wrong way round if (argsinfo["k"]=="1") { userinfo += " _texthcaseoff_, "; } else if (argsinfo["k"]=="0") { userinfo += " _texthcaseon_, "; } } if (argsinfo["s"] != "" && argsinfo["s"] != args["s"]) { if (argsinfo["s"]=="0") { userinfo += " _texthstemoff_, "; } else if (argsinfo["s"]=="1") { userinfo += " _texthstemon_, "; } } }