separate file and document dates (mainly for email folders). Better check configuration at startup

This commit is contained in:
dockes 2005-11-05 14:40:50 +00:00
parent d26cedf7ef
commit 5ebcb0c104
14 changed files with 132 additions and 55 deletions

View File

@ -1,5 +1,5 @@
#ifndef lint #ifndef lint
static char rcsid[] = "@(#$Id: rclconfig.cpp,v 1.9 2005-10-19 14:14:17 dockes Exp $ (C) 2004 J.F.Dockes"; static char rcsid[] = "@(#$Id: rclconfig.cpp,v 1.10 2005-11-05 14:40:50 dockes Exp $ (C) 2004 J.F.Dockes";
#endif #endif
#include <unistd.h> #include <unistd.h>
@ -32,11 +32,13 @@ RclConfig::RclConfig()
string cfilename = confdir; string cfilename = confdir;
path_cat(cfilename, "recoll.conf"); path_cat(cfilename, "recoll.conf");
// Maybe we should try to open readonly here as, else, this will // Open readonly here so as not to casually create a config file
// casually create a configuration file conf = new ConfTree(cfilename.c_str(), true);
conf = new ConfTree(cfilename.c_str(), 0); if (conf == 0 ||
if (conf == 0) { (conf->getStatus() != ConfSimple::STATUS_RO &&
cerr << "No configuration" << endl; conf->getStatus() != ConfSimple::STATUS_RW)) {
reason = string("No main configuration file: ") + cfilename +
" does not exist or cannot be parsed";
return; return;
} }
@ -46,9 +48,12 @@ RclConfig::RclConfig()
} }
string mpath = confdir; string mpath = confdir;
path_cat(mpath, mimemapfile); path_cat(mpath, mimemapfile);
mimemap = new ConfTree(mpath.c_str()); mimemap = new ConfTree(mpath.c_str(), true);
if (mimemap == 0) { if (mimemap == 0 ||
cerr << "No mime map file" << endl; (mimemap->getStatus() != ConfSimple::STATUS_RO &&
mimemap->getStatus() != ConfSimple::STATUS_RW)) {
reason = string("No mime map configuration file: ") + mpath +
" does not exist or cannot be parsed";
return; return;
} }
// mimemap->list(); // mimemap->list();
@ -59,9 +64,12 @@ RclConfig::RclConfig()
} }
mpath = confdir; mpath = confdir;
path_cat(mpath, mimeconffile); path_cat(mpath, mimeconffile);
mimeconf = new ConfTree(mpath.c_str()); mimeconf = new ConfTree(mpath.c_str(), true);
if (mimeconf == 0) { if (mimeconf == 0 ||
cerr << "No mime conf file" << endl; (mimeconf->getStatus() != ConfSimple::STATUS_RO &&
mimeconf->getStatus() != ConfSimple::STATUS_RW)) {
reason = string("No mime configuration file: ") + mpath +
" does not exist or cannot be parsed";
return; return;
} }
// mimeconf->list(); // mimeconf->list();

View File

@ -1,6 +1,6 @@
#ifndef _RCLCONFIG_H_INCLUDED_ #ifndef _RCLCONFIG_H_INCLUDED_
#define _RCLCONFIG_H_INCLUDED_ #define _RCLCONFIG_H_INCLUDED_
/* @(#$Id: rclconfig.h,v 1.5 2005-10-17 13:36:53 dockes Exp $ (C) 2004 J.F.Dockes */ /* @(#$Id: rclconfig.h,v 1.6 2005-11-05 14:40:50 dockes Exp $ (C) 2004 J.F.Dockes */
#include <list> #include <list>
@ -8,6 +8,7 @@
class RclConfig { class RclConfig {
int m_ok; int m_ok;
string reason; // Explanation for bad state
string confdir; // Directory where the files are stored string confdir; // Directory where the files are stored
ConfTree *conf; // Parsed main configuration ConfTree *conf; // Parsed main configuration
string keydir; // Current directory used for parameter fetches. string keydir; // Current directory used for parameter fetches.
@ -26,7 +27,7 @@ class RclConfig {
~RclConfig() {delete conf;delete mimemap;delete mimeconf;} ~RclConfig() {delete conf;delete mimemap;delete mimeconf;}
bool ok() {return m_ok;} bool ok() {return m_ok;}
const string &getReason() {return reason;}
string getConfDir() {return confdir;} string getConfDir() {return confdir;}
ConfTree *getConfig() {return m_ok ? conf : 0;} ConfTree *getConfig() {return m_ok ? conf : 0;}

View File

@ -1,5 +1,5 @@
#ifndef lint #ifndef lint
static char rcsid[] = "@(#$Id: rclinit.cpp,v 1.1 2005-04-05 09:35:35 dockes Exp $ (C) 2004 J.F.Dockes"; static char rcsid[] = "@(#$Id: rclinit.cpp,v 1.2 2005-11-05 14:40:50 dockes Exp $ (C) 2004 J.F.Dockes";
#endif #endif
#include <stdio.h> #include <stdio.h>
@ -7,8 +7,10 @@ static char rcsid[] = "@(#$Id: rclinit.cpp,v 1.1 2005-04-05 09:35:35 dockes Exp
#include "debuglog.h" #include "debuglog.h"
#include "rclconfig.h" #include "rclconfig.h"
#include "rclinit.h"
RclConfig *recollinit(void (*cleanup)(void), void (*sigcleanup)(int)) RclConfig *recollinit(void (*cleanup)(void), void (*sigcleanup)(int),
string &reason)
{ {
atexit(cleanup); atexit(cleanup);
if (signal(SIGHUP, SIG_IGN) != SIG_IGN) if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
@ -24,8 +26,12 @@ RclConfig *recollinit(void (*cleanup)(void), void (*sigcleanup)(int))
DebugLog::setfilename("stderr"); DebugLog::setfilename("stderr");
RclConfig *config = new RclConfig; RclConfig *config = new RclConfig;
if (!config || !config->ok()) { if (!config || !config->ok()) {
fprintf(stderr, "Config could not be built\n"); reason = "Configuration could not be built:\n";
exit(1); if (config)
reason += config->getReason();
else
reason += "Out of memory ?";
return 0;
} }
string logfilename, loglevel; string logfilename, loglevel;

View File

@ -1,9 +1,12 @@
#ifndef _RCLINIT_H_INCLUDED_ #ifndef _RCLINIT_H_INCLUDED_
#define _RCLINIT_H_INCLUDED_ #define _RCLINIT_H_INCLUDED_
/* @(#$Id: rclinit.h,v 1.1 2005-04-05 09:35:35 dockes Exp $ (C) 2004 J.F.Dockes */ /* @(#$Id: rclinit.h,v 1.2 2005-11-05 14:40:50 dockes Exp $ (C) 2004 J.F.Dockes */
#include <string>
class RclConfig; class RclConfig;
extern RclConfig *recollinit(void (*cleanup)(void), void (*sigcleanup)(int)); extern RclConfig *recollinit(void (*cleanup)(void), void (*sigcleanup)(int),
std::string &reason);
#endif /* _RCLINIT_H_INCLUDED_ */ #endif /* _RCLINIT_H_INCLUDED_ */

View File

@ -1,5 +1,5 @@
#ifndef lint #ifndef lint
static char rcsid[] = "@(#$Id: indexer.cpp,v 1.12 2005-10-15 12:18:04 dockes Exp $ (C) 2004 J.F.Dockes"; static char rcsid[] = "@(#$Id: indexer.cpp,v 1.13 2005-11-05 14:40:50 dockes Exp $ (C) 2004 J.F.Dockes";
#endif #endif
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -173,11 +173,10 @@ DbIndexer::processone(const std::string &fn, const struct stat *stp,
break; break;
// Set the date if this was not done in the document handler // Set the date if this was not done in the document handler
// (ie: date from Date: mail header). if (doc.fmtime.empty()) {
if (doc.mtime.empty()) {
char ascdate[20]; char ascdate[20];
sprintf(ascdate, "%ld", long(stp->st_ctime)); sprintf(ascdate, "%ld", long(stp->st_ctime));
doc.mtime = ascdate; doc.fmtime = ascdate;
} }
// Internal access path for multi-document files // Internal access path for multi-document files
doc.ipath = ipath; doc.ipath = ipath;

View File

@ -1,5 +1,5 @@
#ifndef lint #ifndef lint
static char rcsid[] = "@(#$Id: recollindex.cpp,v 1.10 2005-04-05 09:35:35 dockes Exp $ (C) 2004 J.F.Dockes"; static char rcsid[] = "@(#$Id: recollindex.cpp,v 1.11 2005-11-05 14:40:50 dockes Exp $ (C) 2004 J.F.Dockes";
#endif #endif
#include <stdio.h> #include <stdio.h>
@ -26,8 +26,15 @@ static void sigcleanup(int sig)
int main(int argc, const char **argv) int main(int argc, const char **argv)
{ {
RclConfig *config = recollinit(cleanup, sigcleanup); string reason;
RclConfig *config = recollinit(cleanup, sigcleanup, reason);
if (config == 0 || !config->ok()) {
string str = "Configuration problem: ";
str += reason;
fprintf(stderr, "%s\n", str.c_str());
exit(1);
}
indexer = new ConfIndexer(config); indexer = new ConfIndexer(config);
exit(!indexer->index()); exit(!indexer->index());

View File

@ -1,5 +1,5 @@
#ifndef lint #ifndef lint
static char rcsid[] = "@(#$Id: mh_mail.cpp,v 1.7 2005-10-31 08:59:05 dockes Exp $ (C) 2005 J.F.Dockes"; static char rcsid[] = "@(#$Id: mh_mail.cpp,v 1.8 2005-11-05 14:40:50 dockes Exp $ (C) 2005 J.F.Dockes";
#endif #endif
#include <stdio.h> #include <stdio.h>
@ -199,7 +199,7 @@ MimeHandlerMail::processone(const string &fn, Binc::MimeDocument& doc,
if (strptime(date.c_str(), " %d %b %Y %H:%M:%S %z ", &tm)) { if (strptime(date.c_str(), " %d %b %Y %H:%M:%S %z ", &tm)) {
char ascuxtime[100]; char ascuxtime[100];
sprintf(ascuxtime, "%ld", (long)mktime(&tm)); sprintf(ascuxtime, "%ld", (long)mktime(&tm));
docout.mtime = ascuxtime; docout.dmtime = ascuxtime;
} else { } else {
LOGDEB(("strptime failed for [%s]\n", date.c_str())); LOGDEB(("strptime failed for [%s]\n", date.c_str()));
} }

View File

@ -5,6 +5,9 @@ CXXFLAGS = $(COMMONCXXFLAGS)
CC=gcc CC=gcc
CXX=g++ CXX=g++
LIBICONV = -L/usr/local/lib -liconv # Note that we use a static libiconv only to ease installation of binary
# packages
#LIBICONV = -L/usr/local/lib -liconv
LIBICONV = /usr/local/lib/libiconv.a
LIBSYS = -lpthread -lnsl -lsocket LIBSYS = -lpthread -lnsl -lsocket

View File

@ -1,5 +1,5 @@
#ifndef lint #ifndef lint
static char rcsid[] = "@(#$Id: main.cpp,v 1.11 2005-10-22 05:35:16 dockes Exp $ (C) 2005 J.F.Dockes"; static char rcsid[] = "@(#$Id: main.cpp,v 1.12 2005-11-05 14:40:50 dockes Exp $ (C) 2005 J.F.Dockes";
#endif #endif
#include <unistd.h> #include <unistd.h>
@ -101,11 +101,14 @@ int main( int argc, char ** argv )
w.connect(timer, SIGNAL(timeout()), &w, SLOT(checkExit())); w.connect(timer, SIGNAL(timeout()), &w, SLOT(checkExit()));
timer->start(100); timer->start(100);
rclconfig = recollinit(recollCleanup, sigcleanup); string reason;
rclconfig = recollinit(recollCleanup, sigcleanup, reason);
if (!rclconfig || !rclconfig->ok()) { if (!rclconfig || !rclconfig->ok()) {
string msg = "Configuration problem: ";
msg += reason;
QMessageBox::critical(0, "Recoll", QMessageBox::critical(0, "Recoll",
QString("Could not find configuration")); QString(msg.c_str()));
exit(1); exit(1);
} }

View File

@ -35,7 +35,7 @@
</property> </property>
<widget class="QLayoutWidget"> <widget class="QLayoutWidget">
<property name="name"> <property name="name">
<cstring>layout9</cstring> <cstring>layout4</cstring>
</property> </property>
<vbox> <vbox>
<property name="name"> <property name="name">
@ -75,7 +75,7 @@
</widget> </widget>
<widget class="QLayoutWidget"> <widget class="QLayoutWidget">
<property name="name"> <property name="name">
<cstring>layout7</cstring> <cstring>layout3</cstring>
</property> </property>
<hbox> <hbox>
<property name="name"> <property name="name">
@ -107,6 +107,9 @@
<property name="name"> <property name="name">
<cstring>nextButton</cstring> <cstring>nextButton</cstring>
</property> </property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text"> <property name="text">
<string>&amp;Next</string> <string>&amp;Next</string>
</property> </property>
@ -118,6 +121,9 @@
<property name="name"> <property name="name">
<cstring>prevButton</cstring> <cstring>prevButton</cstring>
</property> </property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text"> <property name="text">
<string>&amp;Previous</string> <string>&amp;Previous</string>
</property> </property>
@ -125,6 +131,17 @@
<string>Alt+P</string> <string>Alt+P</string>
</property> </property>
</widget> </widget>
<widget class="QPushButton">
<property name="name">
<cstring>clearPB</cstring>
</property>
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Clear</string>
</property>
</widget>
<widget class="QCheckBox"> <widget class="QCheckBox">
<property name="name"> <property name="name">
<cstring>matchCheck</cstring> <cstring>matchCheck</cstring>
@ -161,6 +178,12 @@
<receiver>Preview</receiver> <receiver>Preview</receiver>
<slot>prevPressed()</slot> <slot>prevPressed()</slot>
</connection> </connection>
<connection>
<sender>clearPB</sender>
<signal>clicked()</signal>
<receiver>searchTextLine</receiver>
<slot>clear()</slot>
</connection>
</connections> </connections>
<includes> <includes>
<include location="local" impldecl="in implementation">qapplication.h</include> <include location="local" impldecl="in implementation">qapplication.h</include>

View File

@ -57,6 +57,7 @@ bool Preview::eventFilter(QObject *target, QEvent *event)
e = (QTextEdit *)tw->child("pvEdit"); e = (QTextEdit *)tw->child("pvEdit");
LOGDEB1(("Widget: %p, edit %p, target %p\n", tw, e, target)); LOGDEB1(("Widget: %p, edit %p, target %p\n", tw, e, target));
if (e && target == tw && keyEvent->key() == Key_Slash) { if (e && target == tw && keyEvent->key() == Key_Slash) {
searchTextLine->setFocus();
dynSearchActive = true; dynSearchActive = true;
return true; return true;
} }
@ -70,8 +71,14 @@ void Preview::searchTextLine_textChanged(const QString & text)
LOGDEB1(("search line text changed. text: '%s'\n", text.ascii())); LOGDEB1(("search line text changed. text: '%s'\n", text.ascii()));
if (text.isEmpty()) { if (text.isEmpty()) {
dynSearchActive = false; dynSearchActive = false;
nextButton->setEnabled(false);
prevButton->setEnabled(false);
clearPB->setEnabled(false);
} else { } else {
dynSearchActive = true; dynSearchActive = true;
nextButton->setEnabled(true);
prevButton->setEnabled(true);
clearPB->setEnabled(true);
doSearch(false, false); doSearch(false, false);
} }
} }

View File

@ -407,8 +407,9 @@ void RecollMain::listNextPB_clicked()
doc.title = path_getsimple(doc.url); doc.title = path_getsimple(doc.url);
char datebuf[100]; char datebuf[100];
datebuf[0] = 0; datebuf[0] = 0;
if (!doc.mtime.empty()) { if (!doc.dmtime.empty() || !doc.fmtime.empty()) {
time_t mtime = atol(doc.mtime.c_str()); time_t mtime = doc.dmtime.empty() ?
atol(doc.fmtime.c_str()) : atol(doc.dmtime.c_str());
struct tm *tm = localtime(&mtime); struct tm *tm = localtime(&mtime);
strftime(datebuf, 99, "<i>Modified:</i>&nbsp;%F&nbsp;%T", tm); strftime(datebuf, 99, "<i>Modified:</i>&nbsp;%F&nbsp;%T", tm);
} }
@ -417,7 +418,7 @@ void RecollMain::listNextPB_clicked()
string result = "<p>" + string result = "<p>" +
string(perbuf) + " <b>" + doc.title + "</b><br>" + string(perbuf) + " <b>" + doc.title + "</b><br>" +
doc.mimetype + "&nbsp;" + doc.mimetype + "&nbsp;" +
(!doc.mtime.empty() ? string(datebuf) + "<br>" : string("<br>")) + (datebuf[0] ? string(datebuf) + "<br>" : string("<br>")) +
(!abst.empty() ? abst + "<br>" : string("")) + (!abst.empty() ? abst + "<br>" : string("")) +
(!doc.keywords.empty() ? doc.keywords + "<br>" : string("")) + (!doc.keywords.empty() ? doc.keywords + "<br>" : string("")) +
"<i>" + doc.url + +"</i><br>" + "<i>" + doc.url + +"</i><br>" +
@ -620,14 +621,14 @@ void RecollMain::startPreview(int docnum)
doc.title = path_getsimple(doc.url); doc.title = path_getsimple(doc.url);
char datebuf[100]; char datebuf[100];
datebuf[0] = 0; datebuf[0] = 0;
if (!doc.mtime.empty()) { if (!doc.fmtime.empty() || !doc.dmtime.empty()) {
time_t mtime = atol(doc.mtime.c_str()); time_t mtime = doc.dmtime.empty() ?
atol(doc.fmtime.c_str()) : atol(doc.dmtime.c_str());
struct tm *tm = localtime(&mtime); struct tm *tm = localtime(&mtime);
strftime(datebuf, 99, "%F %T", tm); strftime(datebuf, 99, "%F %T", tm);
} }
string tiptxt = doc.url + string("\n"); string tiptxt = doc.url + string("\n");
tiptxt += doc.mimetype + " " tiptxt += doc.mimetype + " " + string(datebuf) + "\n";
+ (doc.mtime.empty() ? "\n" : string(datebuf) + "\n");
if (!doc.title.empty()) if (!doc.title.empty())
tiptxt += doc.title + "\n"; tiptxt += doc.title + "\n";
curPreview->pvTab->setTabToolTip(curPreview->pvTab->currentPage(), curPreview->pvTab->setTabToolTip(curPreview->pvTab->currentPage(),

View File

@ -1,5 +1,5 @@
#ifndef lint #ifndef lint
static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.31 2005-10-20 11:33:49 dockes Exp $ (C) 2004 J.F.Dockes"; static char rcsid[] = "@(#$Id: rcldb.cpp,v 1.32 2005-11-05 14:40:50 dockes Exp $ (C) 2004 J.F.Dockes";
#endif #endif
#include <stdio.h> #include <stdio.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -338,7 +338,9 @@ bool Rcl::Db::add(const string &fn, const Rcl::Doc &idoc)
// - mime type // - mime type
string record = "url=file://" + fn; string record = "url=file://" + fn;
record += "\nmtype=" + doc.mimetype; record += "\nmtype=" + doc.mimetype;
record += "\nmtime=" + doc.mtime; record += "\nfmtime=" + doc.fmtime;
if (!doc.dmtime.empty())
record += "\ndmtime=" + doc.dmtime;
record += "\norigcharset=" + doc.origcharset; record += "\norigcharset=" + doc.origcharset;
record += "\ncaption=" + doc.title; record += "\ncaption=" + doc.title;
record += "\nkeywords=" + doc.keywords; record += "\nkeywords=" + doc.keywords;
@ -351,7 +353,8 @@ bool Rcl::Db::add(const string &fn, const Rcl::Doc &idoc)
LOGDEB1(("Newdocument data: %s\n", record.c_str())); LOGDEB1(("Newdocument data: %s\n", record.c_str()));
newdocument.set_data(record); newdocument.set_data(record);
time_t mtime = atol(doc.mtime.c_str()); time_t mtime = atol(doc.dmtime.empty() ? doc.fmtime.c_str() :
doc.dmtime.c_str());
struct tm *tm = localtime(&mtime); struct tm *tm = localtime(&mtime);
char buf[9]; char buf[9];
sprintf(buf, "%04d%02d%02d",tm->tm_year+1900, tm->tm_mon + 1, tm->tm_mday); sprintf(buf, "%04d%02d%02d",tm->tm_year+1900, tm->tm_mon + 1, tm->tm_mday);
@ -399,8 +402,9 @@ bool Rcl::Db::needUpdate(const string &filename, const struct stat *stp)
return true; return true;
} }
// Look for all documents with this path. Check the update time (once). // Look for all documents with this path. We need to look at all
// If the db is up to date, set the update flags for all documents // to set their existence flag.
// We check the update time on the spe
Xapian::PostingIterator doc; Xapian::PostingIterator doc;
try { try {
Xapian::PostingIterator docid0 = ndb->wdb.postlist_begin(pathterm); Xapian::PostingIterator docid0 = ndb->wdb.postlist_begin(pathterm);
@ -409,14 +413,23 @@ bool Rcl::Db::needUpdate(const string &filename, const struct stat *stp)
Xapian::Document doc = ndb->wdb.get_document(*docid); Xapian::Document doc = ndb->wdb.get_document(*docid);
// Check the date once. no need to look at the others if the // Check the date once. no need to look at the others if
// db needs updating. // the db needs updating. Note that the fmtime used to be
// called mtime, and we're keeping compat
if (docid == docid0) { if (docid == docid0) {
string data = doc.get_data(); string data = doc.get_data();
const char *cp = strstr(data.c_str(), "mtime="); const char *cp = strstr(data.c_str(), "fmtime=");
cp += 6; if (cp) {
long mtime = atol(cp); cp += 7;
} else {
cp = strstr(data.c_str(), "mtime=");
if (cp)
cp+= 6;
}
long mtime = cp ? atol(cp) : 0;
if (mtime < stp->st_mtime) { if (mtime < stp->st_mtime) {
LOGDEB2(("Need update: Db Doc mtime %ld file mtime %ld\n",
(long)mtime, (long)stp->st_mtime));
// Db is not up to date. Let's index the file // Db is not up to date. Let's index the file
return true; return true;
} }
@ -1027,7 +1040,8 @@ bool Rcl::Db::getDoc(int exti, Doc &doc, int *percent)
ConfSimple parms(&data); ConfSimple parms(&data);
parms.get(string("url"), doc.url); parms.get(string("url"), doc.url);
parms.get(string("mtype"), doc.mimetype); parms.get(string("mtype"), doc.mimetype);
parms.get(string("mtime"), doc.mtime); parms.get(string("fmtime"), doc.fmtime);
parms.get(string("dmtime"), doc.dmtime);
parms.get(string("origcharset"), doc.origcharset); parms.get(string("origcharset"), doc.origcharset);
parms.get(string("caption"), doc.title); parms.get(string("caption"), doc.title);
parms.get(string("keywords"), doc.keywords); parms.get(string("keywords"), doc.keywords);

View File

@ -1,6 +1,6 @@
#ifndef _DB_H_INCLUDED_ #ifndef _DB_H_INCLUDED_
#define _DB_H_INCLUDED_ #define _DB_H_INCLUDED_
/* @(#$Id: rcldb.h,v 1.15 2005-10-19 14:14:17 dockes Exp $ (C) 2004 J.F.Dockes */ /* @(#$Id: rcldb.h,v 1.16 2005-11-05 14:40:50 dockes Exp $ (C) 2004 J.F.Dockes */
#include <string> #include <string>
#include <list> #include <list>
@ -39,7 +39,8 @@ class Doc {
string url; string url;
string ipath; string ipath;
string mimetype; string mimetype;
string mtime; // Modification time as decimal ascii string fmtime; // File modification time as decimal ascii unix time
string dmtime; // Data reference date (same format). Ie: mail date
string origcharset; string origcharset;
string title; string title;
string keywords; string keywords;
@ -51,7 +52,8 @@ class Doc {
url.erase(); url.erase();
ipath.erase(); ipath.erase();
mimetype.erase(); mimetype.erase();
mtime.erase(); fmtime.erase();
dmtime.erase();
origcharset.erase(); origcharset.erase();
title.erase(); title.erase();
keywords.erase(); keywords.erase();