summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/borrower.h2
-rw-r--r--src/borroweritem.cpp2
-rw-r--r--src/borroweritem.h2
-rw-r--r--src/collection.cpp4
-rw-r--r--src/collectionfieldsdialog.cpp6
-rw-r--r--src/collections/filecatalog.cpp17
-rw-r--r--src/collections/filecatalog.h3
-rw-r--r--src/controller.cpp2
-rw-r--r--src/core/Makefile.am2
-rw-r--r--src/core/dcopinterface_skel.cpp48
-rw-r--r--src/core/drophandler.cpp37
-rw-r--r--src/document.cpp8
-rw-r--r--src/document.h5
-rw-r--r--src/entry.cpp17
-rw-r--r--src/entry.h11
-rw-r--r--src/entrygroupitem.cpp2
-rw-r--r--src/entrygroupitem.h2
-rw-r--r--src/entryview.cpp15
-rw-r--r--src/entryview.h11
-rw-r--r--src/fetch/Makefile.am4
-rw-r--r--src/fetch/amazonfetcher.cpp117
-rw-r--r--src/fetch/amazonfetcher.h3
-rw-r--r--src/fetch/amazonrequest.cpp72
-rw-r--r--src/fetch/amazonrequest.h52
-rw-r--r--src/fetch/arxivfetcher.cpp7
-rw-r--r--src/fetch/citebasefetcher.cpp10
-rw-r--r--src/fetch/entrezfetcher.cpp2
-rw-r--r--src/fetch/entrezfetcher.h4
-rw-r--r--src/fetch/googlescholarfetcher.cpp4
-rw-r--r--src/fetch/googlescholarfetcher.h6
-rw-r--r--src/fetch/hmac_sha2.c544
-rw-r--r--src/fetch/hmac_sha2.h140
-rw-r--r--src/fetch/ibsfetcher.cpp3
-rw-r--r--src/fetch/imdbfetcher.cpp4
-rw-r--r--src/fetch/sha2.c950
-rw-r--r--src/fetch/sha2.h108
-rw-r--r--src/fetch/z3950-servers.cfg4
-rw-r--r--src/fetch/z3950fetcher.cpp6
-rw-r--r--src/fetchdialog.cpp4
-rw-r--r--src/field.cpp24
-rw-r--r--src/field.h1
-rw-r--r--src/gui/counteditem.h4
-rw-r--r--src/gui/listview.h2
-rw-r--r--src/gui/tabcontrol.cpp3
-rw-r--r--src/image.cpp3
-rw-r--r--src/imagefactory.cpp80
-rw-r--r--src/isbnvalidator.cpp8
-rw-r--r--src/lccnvalidator.cpp2
-rw-r--r--src/listviewcomparison.cpp10
-rw-r--r--src/listviewcomparison.h11
-rw-r--r--src/mainwindow.cpp32
-rw-r--r--src/mainwindow.h2
-rw-r--r--src/reportdialog.cpp2
-rw-r--r--src/tellico_debug.h2
-rw-r--r--src/tests/Makefile.am2
-rw-r--r--src/translators/Makefile.am12
-rw-r--r--src/translators/alexandriaexporter.cpp2
-rw-r--r--src/translators/bibteximporter.cpp42
-rw-r--r--src/translators/bibteximporter.h2
-rw-r--r--src/translators/csvimporter.cpp28
-rw-r--r--src/translators/deliciousimporter.cpp17
-rw-r--r--src/translators/freedb_util.cpp2
-rw-r--r--src/translators/htmlexporter.cpp4
-rw-r--r--src/translators/risimporter.cpp23
-rw-r--r--src/translators/risimporter.h2
-rw-r--r--src/translators/tellico_xml.cpp6
-rw-r--r--src/translators/tellico_xml.h2
-rw-r--r--src/translators/tellicoimporter.cpp14
-rw-r--r--src/translators/tellicoimporter.h2
-rw-r--r--src/translators/tellicosaximporter.cpp293
-rw-r--r--src/translators/tellicosaximporter.h87
-rw-r--r--src/translators/tellicoxmlhandler.cpp74
-rw-r--r--src/translators/tellicoxmlhandler.h49
-rw-r--r--src/translators/xmlstatehandler.cpp772
-rw-r--r--src/translators/xmlstatehandler.h345
-rw-r--r--src/translators/xsltexporter.cpp24
-rw-r--r--src/translators/xsltexporter.h4
-rw-r--r--src/upcvalidator.cpp15
-rw-r--r--src/upcvalidator.h7
79 files changed, 4059 insertions, 197 deletions
diff --git a/src/borrower.h b/src/borrower.h
index 81a5dc2..261ab4d 100644
--- a/src/borrower.h
+++ b/src/borrower.h
@@ -78,7 +78,7 @@ public:
const TQString& name() const { return m_name; }
const LoanVec& loans() const { return m_loans; }
bool isEmpty() const { return m_loans.isEmpty(); }
- int count() const { return m_loans.count(); }
+ size_t count() const { return m_loans.count(); }
Data::LoanPtr loan(Data::ConstEntryPtr entry);
void addLoan(Data::LoanPtr loan);
diff --git a/src/borroweritem.cpp b/src/borroweritem.cpp
index f43e502..80a305f 100644
--- a/src/borroweritem.cpp
+++ b/src/borroweritem.cpp
@@ -25,7 +25,7 @@ BorrowerItem::BorrowerItem(GUI::ListView* parent_, Data::BorrowerPtr borrower_)
setPixmap(0, SmallIcon(TQString::fromLatin1("kaddressbook")));
}
-int BorrowerItem::count() const {
+size_t BorrowerItem::count() const {
return m_borrower ? m_borrower->count() : GUI::CountedItem::count();
}
diff --git a/src/borroweritem.h b/src/borroweritem.h
index ad0b7d6..9d15f3f 100644
--- a/src/borroweritem.h
+++ b/src/borroweritem.h
@@ -29,7 +29,7 @@ public:
virtual bool isBorrowerItem() const { return true; }
Data::BorrowerPtr borrower() { return m_borrower; }
- virtual int count() const;
+ virtual size_t count() const;
virtual Data::EntryVec entries() const;
private:
diff --git a/src/collection.cpp b/src/collection.cpp
index 7d121e0..59cbef6 100644
--- a/src/collection.cpp
+++ b/src/collection.cpp
@@ -878,6 +878,9 @@ bool Collection::mergeEntry(EntryPtr e1, EntryPtr e2, bool overwrite_, bool askU
if(ret) {
e1->setField(field, vals1.join(TQString::fromLatin1("; ")));
}
+// remove the merging due to use comments
+// maybe in the future have a more intelligent way
+#if 0
} else if(field->flags() & Data::Field::AllowMultiple) {
// if field F allows multiple values and not a Table (see above case),
// e1's F values = (e1's F values) U (e2's F values) (union)
@@ -894,6 +897,7 @@ bool Collection::mergeEntry(EntryPtr e1, EntryPtr e2, bool overwrite_, bool askU
// items1.sort();
e1->setField(field, items1.join(TQString::fromLatin1("; ")));
ret = true;
+#endif
} else if(askUser_ && e1->field(field) != e2->field(field)) {
int ret = Kernel::self()->askAndMerge(e1, e2, field);
if(ret == 0) {
diff --git a/src/collectionfieldsdialog.cpp b/src/collectionfieldsdialog.cpp
index ef3583f..7d1fc46 100644
--- a/src/collectionfieldsdialog.cpp
+++ b/src/collectionfieldsdialog.cpp
@@ -254,7 +254,6 @@ CollectionFieldsDialog::CollectionFieldsDialog(Data::CollPtr coll_, TQWidget* pa
// need to stretch at bottom
vbox->setStretchFactor(new TQWidget(vbox), 1);
- TDEAcceleratorManager::manage(vbox);
// keep a default collection
m_defaultCollection = CollectionFactory::collection(m_coll->type(), true);
@@ -279,6 +278,9 @@ CollectionFieldsDialog::~CollectionFieldsDialog() {
}
void CollectionFieldsDialog::slotSelectInitial() {
+ // the accel management is here so that it doesn't cause conflicts with the
+ // ones explicitly set in the constructor
+ TDEAcceleratorManager::manage(mainWidget());
m_fieldsBox->setSelected(0, true);
}
@@ -405,7 +407,7 @@ void CollectionFieldsDialog::slotNew() {
}
TQString name = TQString::fromLatin1("custom") + TQString::number(m_newFields.count()+1);
- int count = m_newFields.count() + 1;
+ size_t count = m_newFields.count() + 1;
TQString title = i18n("New Field") + TQString::fromLatin1(" %1").arg(count);
while(m_fieldsBox->findItem(title)) {
++count;
diff --git a/src/collections/filecatalog.cpp b/src/collections/filecatalog.cpp
index 92d088f..afba7fc 100644
--- a/src/collections/filecatalog.cpp
+++ b/src/collections/filecatalog.cpp
@@ -102,4 +102,21 @@ Tellico::Data::FieldVec FileCatalog::defaultFields() {
return list;
}
+int FileCatalog::sameEntry(Data::EntryPtr entry1_, Data::EntryPtr entry2_) const {
+ // equal urls are always equal, even if modification time or something is different
+ if(Entry::compareValues(entry1_, entry2_, TQString::fromLatin1("url"), this) > 0) {
+ return 100; // good match
+ }
+ // if volume or created time is different, it can't be same entry
+ if(Entry::compareValues(entry1_, entry2_, TQString::fromLatin1("volume"), this) == 0 ||
+ Entry::compareValues(entry1_, entry2_, TQString::fromLatin1("created"), this) == 0 ||
+ Entry::compareValues(entry1_, entry2_, TQString::fromLatin1("size"), this) == 0) {
+ return 0;
+ }
+ int res = Entry::compareValues(entry1_, entry2_, TQString::fromLatin1("title"), this);
+ res += Entry::compareValues(entry1_, entry2_, TQString::fromLatin1("description"), this);
+ res += Entry::compareValues(entry1_, entry2_, TQString::fromLatin1("mimetype"), this);
+ return res;
+}
+
#include "filecatalog.moc"
diff --git a/src/collections/filecatalog.h b/src/collections/filecatalog.h
index f2ede29..6a08dc9 100644
--- a/src/collections/filecatalog.h
+++ b/src/collections/filecatalog.h
@@ -1,5 +1,5 @@
/***************************************************************************
- copyright : (C) 2005-2006 by Robby Stephenson
+ copyright : (C) 2005-2008 by Robby Stephenson
email : robby@periapsis.org
***************************************************************************/
@@ -30,6 +30,7 @@ public:
FileCatalog(bool addFields, const TQString& title = TQString());
virtual Type type() const { return File; }
+ virtual int sameEntry(Data::EntryPtr entry1, Data::EntryPtr entry2) const;
static FieldVec defaultFields();
};
diff --git a/src/controller.cpp b/src/controller.cpp
index f3afb2a..d4a1599 100644
--- a/src/controller.cpp
+++ b/src/controller.cpp
@@ -434,6 +434,7 @@ void Controller::slotDeleteSelectedEntries() {
int ret = KMessageBox::warningContinueCancel(Kernel::self()->widget(), str, i18n("Delete Entry"),
KGuiItem(i18n("&Delete"), TQString::fromLatin1("editdelete")), dontAsk);
if(ret != KMessageBox::Continue) {
+ m_working = false;
return;
}
} else {
@@ -448,6 +449,7 @@ void Controller::slotDeleteSelectedEntries() {
i18n("Delete Multiple Entries"),
KGuiItem(i18n("&Delete"), TQString::fromLatin1("editdelete")), dontAsk);
if(ret != KMessageBox::Continue) {
+ m_working = false;
return;
}
}
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 15fc0df..01bf5a8 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -17,6 +17,8 @@ drophandler.h drophandler.cpp \
tellico-rename.upd tellico.upd \
tellico-1-3-update.pl
+dcopinterface_DCOPIDLNG = ALL
+
kde_kcfg_DATA = tellico_config.kcfg
updatedir = $(kde_datadir)/tdeconf_update
diff --git a/src/core/dcopinterface_skel.cpp b/src/core/dcopinterface_skel.cpp
index 8de56bf..4e819ed 100644
--- a/src/core/dcopinterface_skel.cpp
+++ b/src/core/dcopinterface_skel.cpp
@@ -25,11 +25,11 @@ static const char* const ApplicationInterface_ftable[16][3] = {
{ "bool", "exportHTML(TQString)", "exportHTML(TQString file)" },
{ "bool", "exportCSV(TQString)", "exportCSV(TQString file)" },
{ "bool", "exportPilotDB(TQString)", "exportPilotDB(TQString file)" },
- { "TQValueList<long int>", "selectedEntries()", "selectedEntries()" },
- { "TQValueList<long int>", "filteredEntries()", "filteredEntries()" },
+ { "TQValueList<long>", "selectedEntries()", "selectedEntries()" },
+ { "TQValueList<long>", "filteredEntries()", "filteredEntries()" },
{ "void", "openFile(TQString)", "openFile(TQString file)" },
{ "void", "setFilter(TQString)", "setFilter(TQString text)" },
- { "bool", "showEntry(long int)", "showEntry(long int id)" },
+ { "bool", "showEntry(long)", "showEntry(long id)" },
{ 0, 0, 0 }
};
static const int ApplicationInterface_ftable_hiddens[15] = {
@@ -162,12 +162,12 @@ bool ApplicationInterface::process(const TQCString &fun, const TQByteArray &data
TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << exportPilotDB(arg0 );
} break;
- case 10: { // TQValueList<long int> selectedEntries()
+ case 10: { // TQValueList<long> selectedEntries()
replyType = ApplicationInterface_ftable[10][0];
TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << selectedEntries( );
} break;
- case 11: { // TQValueList<long int> filteredEntries()
+ case 11: { // TQValueList<long> filteredEntries()
replyType = ApplicationInterface_ftable[11][0];
TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << filteredEntries( );
@@ -188,8 +188,8 @@ bool ApplicationInterface::process(const TQCString &fun, const TQByteArray &data
replyType = ApplicationInterface_ftable[13][0];
setFilter(arg0 );
} break;
- case 14: { // bool showEntry(long int)
- long int arg0;
+ case 14: { // bool showEntry(long)
+ long arg0;
TQDataStream arg( data, IO_ReadOnly );
if (arg.atEnd()) return false;
arg >> arg0;
@@ -233,14 +233,14 @@ namespace Tellico {
static const int CollectionInterface_fhash = 11;
static const char* const CollectionInterface_ftable[9][3] = {
- { "long int", "addEntry()", "addEntry()" },
- { "bool", "removeEntry(long int)", "removeEntry(long int entryID)" },
+ { "long", "addEntry()", "addEntry()" },
+ { "bool", "removeEntry(long)", "removeEntry(long entryID)" },
{ TQSTRINGLIST_OBJECT_NAME_STRING, "values(TQString)", "values(TQString fieldName)" },
- { TQSTRINGLIST_OBJECT_NAME_STRING, "values(long int,TQString)", "values(long int entryID,TQString fieldName)" },
+ { TQSTRINGLIST_OBJECT_NAME_STRING, "values(long,TQString)", "values(long entryID,TQString fieldName)" },
{ TQSTRINGLIST_OBJECT_NAME_STRING, "bibtexKeys()", "bibtexKeys()" },
- { TQSTRING_OBJECT_NAME_STRING, "bibtexKey(long int)", "bibtexKey(long int entryID)" },
- { "bool", "setFieldValue(long int,TQString,TQString)", "setFieldValue(long int entryID,TQString fieldName,TQString value)" },
- { "bool", "addFieldValue(long int,TQString,TQString)", "addFieldValue(long int entryID,TQString fieldName,TQString value)" },
+ { TQSTRING_OBJECT_NAME_STRING, "bibtexKey(long)", "bibtexKey(long entryID)" },
+ { "bool", "setFieldValue(long,TQString,TQString)", "setFieldValue(long entryID,TQString fieldName,TQString value)" },
+ { "bool", "addFieldValue(long,TQString,TQString)", "addFieldValue(long entryID,TQString fieldName,TQString value)" },
{ 0, 0, 0 }
};
static const int CollectionInterface_ftable_hiddens[8] = {
@@ -264,13 +264,13 @@ bool CollectionInterface::process(const TQCString &fun, const TQByteArray &data,
}
int* fp = fdict->find( fun );
switch ( fp?*fp:-1) {
- case 0: { // long int addEntry()
+ case 0: { // long addEntry()
replyType = CollectionInterface_ftable[0][0];
TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << addEntry( );
} break;
- case 1: { // bool removeEntry(long int)
- long int arg0;
+ case 1: { // bool removeEntry(long)
+ long arg0;
TQDataStream arg( data, IO_ReadOnly );
if (arg.atEnd()) return false;
arg >> arg0;
@@ -287,8 +287,8 @@ bool CollectionInterface::process(const TQCString &fun, const TQByteArray &data,
TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << values(arg0 );
} break;
- case 3: { // TQStringList values(long int,TQString)
- long int arg0;
+ case 3: { // TQStringList values(long,TQString)
+ long arg0;
TQString arg1;
TQDataStream arg( data, IO_ReadOnly );
if (arg.atEnd()) return false;
@@ -304,8 +304,8 @@ bool CollectionInterface::process(const TQCString &fun, const TQByteArray &data,
TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << bibtexKeys( );
} break;
- case 5: { // TQString bibtexKey(long int)
- long int arg0;
+ case 5: { // TQString bibtexKey(long)
+ long arg0;
TQDataStream arg( data, IO_ReadOnly );
if (arg.atEnd()) return false;
arg >> arg0;
@@ -313,8 +313,8 @@ bool CollectionInterface::process(const TQCString &fun, const TQByteArray &data,
TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << bibtexKey(arg0 );
} break;
- case 6: { // bool setFieldValue(long int,TQString,TQString)
- long int arg0;
+ case 6: { // bool setFieldValue(long,TQString,TQString)
+ long arg0;
TQString arg1;
TQString arg2;
TQDataStream arg( data, IO_ReadOnly );
@@ -328,8 +328,8 @@ bool CollectionInterface::process(const TQCString &fun, const TQByteArray &data,
TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << setFieldValue(arg0, arg1, arg2 );
} break;
- case 7: { // bool addFieldValue(long int,TQString,TQString)
- long int arg0;
+ case 7: { // bool addFieldValue(long,TQString,TQString)
+ long arg0;
TQString arg1;
TQString arg2;
TQDataStream arg( data, IO_ReadOnly );
diff --git a/src/core/drophandler.cpp b/src/core/drophandler.cpp
index e609e7b..8d4875d 100644
--- a/src/core/drophandler.cpp
+++ b/src/core/drophandler.cpp
@@ -15,9 +15,13 @@
#include "../mainwindow.h"
#include "../tellico_kernel.h"
#include "../tellico_debug.h"
+#include "../translators/bibteximporter.h"
+#include "../translators/risimporter.h"
#include <kurldrag.h>
#include <kmimetype.h>
+#include <tdeio/netaccess.h>
+#include <tdeio/job.h>
using Tellico::DropHandler;
@@ -62,18 +66,37 @@ bool DropHandler::handleURL(const KURL::List& urls_) {
bool hasUnknown = false;
KURL::List tc, pdf, bib, ris;
for(KURL::List::ConstIterator it = urls_.begin(); it != urls_.end(); ++it) {
- KMimeType::Ptr ptr = KMimeType::findByURL(*it);
+ const KURL& url = *it;
+ KMimeType::Ptr ptr;
+ // findByURL doesn't work for http, so actually query
+ // the url itself
+ if(url.protocol() != TQString::fromLatin1("http")) {
+ ptr = KMimeType::findByURL(url);
+ } else {
+ TDEIO::MimetypeJob* job = TDEIO::mimetype(url, false /*progress*/);
+ TDEIO::NetAccess::synchronousRun(job, Kernel::self()->widget());
+ ptr = KMimeType::mimeType(job->mimetype());
+ }
if(ptr->is(TQString::fromLatin1("application/x-tellico"))) {
- tc << *it;
+ tc << url;
} else if(ptr->is(TQString::fromLatin1("application/pdf"))) {
- pdf << *it;
+ pdf << url;
} else if(ptr->is(TQString::fromLatin1("text/x-bibtex")) ||
- ptr->is(TQString::fromLatin1("application/x-bibtex"))) {
- bib << *it;
+ ptr->is(TQString::fromLatin1("application/x-bibtex")) ||
+ ptr->is(TQString::fromLatin1("application/bibtex"))) {
+ bib << url;
} else if(ptr->is(TQString::fromLatin1("application/x-research-info-systems"))) {
- ris << *it;
+ ris << url;
+ } else if(url.fileName().endsWith(TQString::fromLatin1(".bib"))) {
+ bib << url;
+ } else if(url.fileName().endsWith(TQString::fromLatin1(".ris"))) {
+ ris << url;
+ } else if(ptr->is(TQString::fromLatin1("text/plain")) && Import::BibtexImporter::maybeBibtex(url)) {
+ bib << url;
+ } else if(ptr->is(TQString::fromLatin1("text/plain")) && Import::RISImporter::maybeRIS(url)) {
+ ris << url;
} else {
- myDebug() << "DropHandler::handleURL() - unrecognized type: " << ptr->name() << " (" << *it << ")" << endl;
+ myDebug() << "DropHandler::handleURL() - unrecognized type: " << ptr->name() << " (" << url << ")" << endl;
hasUnknown = true;
}
}
diff --git a/src/document.cpp b/src/document.cpp
index 40a38dd..97a5c5a 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -15,6 +15,7 @@
#include "mainwindow.h" // needed for calling fileSave()
#include "collectionfactory.h"
#include "translators/tellicoimporter.h"
+#include "translators/tellicosaximporter.h"
#include "translators/tellicozipexporter.h"
#include "translators/tellicoxmlexporter.h"
#include "collection.h"
@@ -109,7 +110,12 @@ bool Document::openDocument(const KURL& url_) {
}
delete m_importer;
+#ifdef SAX_SUPPORT
+ myLog() << "Document::openDocument() - using SAX loader" << endl;
+ m_importer = new Import::TellicoSaxImporter(url_, m_loadAllImages);
+#else
m_importer = new Import::TellicoImporter(url_, m_loadAllImages);
+#endif
CollPtr coll = m_importer->collection();
// delayed image loading only works for zip files
@@ -146,6 +152,8 @@ bool Document::openDocument(const KURL& url_) {
TQTimer::singleShot(500, this, TQT_SLOT(slotLoadAllImages()));
} else {
emit signalCollectionImagesLoaded(m_coll);
+ m_importer->deleteLater();
+ m_importer = 0;
}
return true;
}
diff --git a/src/document.h b/src/document.h
index b270be6..6d3e99e 100644
--- a/src/document.h
+++ b/src/document.h
@@ -27,6 +27,7 @@
namespace Tellico {
namespace Import {
class TellicoImporter;
+ class TellicoSaxImporter;
}
namespace Data {
@@ -227,7 +228,11 @@ private:
bool m_loadAllImages : 1;
KURL m_url;
bool m_validFile : 1;
+#ifdef SAX_SUPPORT
+ TQGuardedPtr<Import::TellicoSaxImporter> m_importer;
+#else
TQGuardedPtr<Import::TellicoImporter> m_importer;
+#endif
bool m_cancelImageWriting : 1;
int m_fileFormat;
bool m_allImagesOnDisk : 1;
diff --git a/src/entry.cpp b/src/entry.cpp
index fc97354..a1274db 100644
--- a/src/entry.cpp
+++ b/src/entry.cpp
@@ -252,8 +252,13 @@ bool Entry::setField(const TQString& name_, const TQString& value_) {
}
// the string store is probable only useful for fields with auto-completion or choice/number/bool
+ bool shareType = f->type() == Field::Choice ||
+ f->type() == Field::Bool ||
+ f->type() == Field::Image ||
+ f->type() == Field::Rating ||
+ f->type() == Field::Number;
if(!(f->flags() & Field::AllowMultiple) &&
- ((f->type() == Field::Choice || f->type() == Field::Bool || f->type() == Field::Number) ||
+ (shareType ||
(f->type() == Field::Line && (f->flags() & Field::AllowCompletion)))) {
m_fields.insert(Tellico::shareString(name_), Tellico::shareString(value_));
} else {
@@ -415,6 +420,16 @@ int Entry::compareValues(EntryPtr e1, EntryPtr e2, FieldPtr f) {
if(f->name() == Latin1Literal("lccn") && LCCNValidator::formalize(s1) == LCCNValidator::formalize(s2)) {
return 5;
}
+ if(f->name() == Latin1Literal("arxiv")) {
+ // normalize and unVersion arxiv ID
+ s1.remove(TQRegExp(TQString::fromLatin1("^arxiv:"), false));
+ s1.remove(TQRegExp(TQString::fromLatin1("v\\d+$")));
+ s2.remove(TQRegExp(TQString::fromLatin1("^arxiv:"), false));
+ s2.remove(TQRegExp(TQString::fromLatin1("v\\d+$")));
+ if(s1 == s2) {
+ return 5;
+ }
+ }
if(f->formatFlag() == Field::FormatName) {
s1 = e1->field(f, true).lower();
s2 = e2->field(f, true).lower();
diff --git a/src/entry.h b/src/entry.h
index 92bda7c..de1ba66 100644
--- a/src/entry.h
+++ b/src/entry.h
@@ -84,11 +84,6 @@ public:
* The assignment operator is overloaded, since the id must be different.
*/
Entry& operator=(const Entry& other);
- /**
- * two entries are equal if all their field values are equal, except for
- * file catalogs which match on the url only
- */
- bool operator==(const Entry& other);
~Entry();
@@ -231,6 +226,12 @@ public:
static TQString dependentValue(ConstEntryPtr e, const TQString& formatString, bool formatted);
private:
+ /**
+ * two entries are equal if all their field values are equal, except for
+ * file catalogs which match on the url only
+ */
+ bool operator==(const Entry& other);
+
CollPtr m_coll;
long m_id;
StringMap m_fields;
diff --git a/src/entrygroupitem.cpp b/src/entrygroupitem.cpp
index 3d08169..3ddf6c1 100644
--- a/src/entrygroupitem.cpp
+++ b/src/entrygroupitem.cpp
@@ -131,7 +131,7 @@ TQString EntryGroupItem::key(int col_, bool) const {
return m_key;
}
-int EntryGroupItem::count() const {
+size_t EntryGroupItem::count() const {
return m_group ? m_group->count() : GUI::CountedItem::count();
}
diff --git a/src/entrygroupitem.h b/src/entrygroupitem.h
index 68e9fd5..4531e95 100644
--- a/src/entrygroupitem.h
+++ b/src/entrygroupitem.h
@@ -51,7 +51,7 @@ public:
*/
virtual TQString key(int col, bool) const;
- virtual int count() const;
+ virtual size_t count() const;
virtual Data::EntryVec entries() const;
private:
diff --git a/src/entryview.cpp b/src/entryview.cpp
index ab61616..66ad116 100644
--- a/src/entryview.cpp
+++ b/src/entryview.cpp
@@ -26,6 +26,7 @@
#include "document.h"
#include "latin1literal.h"
#include "../core/drophandler.h"
+#include "../tellico_debug.h"
#include <kstandarddirs.h>
#include <krun.h>
@@ -37,10 +38,22 @@
#include <tdelocale.h>
#include <tqfile.h>
+#include <tqclipboard.h>
using Tellico::EntryView;
+using Tellico::EntryViewWidget;
-EntryView::EntryView(TQWidget* parent_, const char* name_) : TDEHTMLPart(parent_, name_),
+EntryViewWidget::EntryViewWidget(TDEHTMLPart* part, TQWidget* parent)
+ : TDEHTMLView(part, parent) {}
+
+// for the life of me, I could not figure out how to call the actual
+// TDEHTMLPartBrowserExtension::copy() slot, so this will have to do
+void EntryViewWidget::copy() {
+ TQString text = part()->selectedText();
+ TQApplication::clipboard()->setText(text, TQClipboard::Clipboard);
+}
+
+EntryView::EntryView(TQWidget* parent_, const char* name_) : TDEHTMLPart(new EntryViewWidget(this, parent_), parent_, name_),
m_entry(0), m_handler(0), m_run(0), m_tempFile(0), m_useGradientImages(true), m_checkCommonFile(true) {
setJScriptEnabled(false);
setJavaEnabled(false);
diff --git a/src/entryview.h b/src/entryview.h
index 2ddc7e7..b5dc3a3 100644
--- a/src/entryview.h
+++ b/src/entryview.h
@@ -20,6 +20,7 @@ class KTempFile;
#include "datavectors.h"
#include <tdehtml_part.h>
+#include <tdehtmlview.h>
#include <tqguardedptr.h>
@@ -103,5 +104,15 @@ private:
bool m_checkCommonFile : 1;
};
+// stupid naming on my part, I need to subclass the view to
+// add a slot. EntryView is really a part though
+class EntryViewWidget : public TDEHTMLView {
+Q_OBJECT
+public:
+ EntryViewWidget(TDEHTMLPart* part, TQWidget* parent);
+public slots:
+ void copy();
+};
+
} //end namespace
#endif
diff --git a/src/fetch/Makefile.am b/src/fetch/Makefile.am
index 017ef60..2f56fa5 100644
--- a/src/fetch/Makefile.am
+++ b/src/fetch/Makefile.am
@@ -10,7 +10,7 @@ libfetch_a_SOURCES = amazonfetcher.cpp animenfofetcher.cpp arxivfetcher.cpp \
discogsfetcher.cpp entrezfetcher.cpp execexternalfetcher.cpp fetcher.cpp fetchmanager.cpp \
gcstarpluginfetcher.cpp googlescholarfetcher.cpp ibsfetcher.cpp imdbfetcher.cpp \
isbndbfetcher.cpp messagehandler.cpp srufetcher.cpp yahoofetcher.cpp z3950connection.cpp \
- z3950fetcher.cpp
+ z3950fetcher.cpp amazonrequest.cpp hmac_sha2.c sha2.c
####### tdevelop will overwrite this part!!! (end)############
@@ -40,6 +40,8 @@ citebasefetcher.h citebasefetcher.cpp \
bibsonomyfetcher.h bibsonomyfetcher.cpp \
googlescholarfetcher.h googlescholarfetcher.cpp \
discogsfetcher.h discogsfetcher.cpp \
+amazonrequest.h amazonrequest.cpp \
+hmac_sha2.h hmac_sha2.c sha2.h sha2.c \
z3950-servers.cfg
appdir = $(kde_datadir)/tellico
diff --git a/src/fetch/amazonfetcher.cpp b/src/fetch/amazonfetcher.cpp
index 9088643..1cb6b0c 100644
--- a/src/fetch/amazonfetcher.cpp
+++ b/src/fetch/amazonfetcher.cpp
@@ -12,6 +12,7 @@
***************************************************************************/
#include "amazonfetcher.h"
+#include "amazonrequest.h"
#include "messagehandler.h"
#include "../translators/xslthandler.h"
#include "../translators/tellicoimporter.h"
@@ -47,7 +48,6 @@
namespace {
static const int AMAZON_RETURNS_PER_REQUEST = 10;
static const int AMAZON_MAX_RETURNS_TOTAL = 20;
- static const char* AMAZON_ACCESS_KEY = "0834VQ4S71KYPVSYQD02";
static const char* AMAZON_ASSOC_TOKEN = "tellico-20";
// need to have these in the translation file
static const char* linkText = I18N_NOOP("Amazon Link");
@@ -84,7 +84,6 @@ const AmazonFetcher::SiteData& AmazonFetcher::siteData(int site_) {
AmazonFetcher::AmazonFetcher(Site site_, TQObject* parent_, const char* name_)
: Fetcher(parent_, name_), m_xsltHandler(0), m_site(site_), m_imageSize(MediumImage),
- m_access(TQString::fromLatin1(AMAZON_ACCESS_KEY)),
m_assoc(TQString::fromLatin1(AMAZON_ASSOC_TOKEN)), m_addLinkField(true), m_limit(AMAZON_MAX_RETURNS_TOTAL),
m_countOffset(0), m_page(1), m_total(-1), m_numResults(0), m_job(0), m_started(false) {
m_name = siteData(site_).title;
@@ -109,7 +108,8 @@ bool AmazonFetcher::canFetch(int type) const {
|| type == Data::Collection::Bibtex
|| type == Data::Collection::Album
|| type == Data::Collection::Video
- || type == Data::Collection::Game;
+ || type == Data::Collection::Game
+ || type == Data::Collection::BoardGame;
}
void AmazonFetcher::readConfigHook(const TDEConfigGroup& config_) {
@@ -117,6 +117,10 @@ void AmazonFetcher::readConfigHook(const TDEConfigGroup& config_) {
if(!s.isEmpty()) {
m_access = s;
}
+ s = config_.readEntry("SecretKey");
+ if(!s.isEmpty()) {
+ m_amazonKey = s;
+ }
s = config_.readEntry("AssocToken");
if(!s.isEmpty()) {
m_assoc = s;
@@ -152,35 +156,41 @@ void AmazonFetcher::doSearch() {
// myDebug() << "AmazonFetcher::doSearch() - getting page " << m_page << endl;
const SiteData& data = siteData(m_site);
- KURL u = data.url;
- u.addQueryItem(TQString::fromLatin1("Service"), TQString::fromLatin1("AWSECommerceService"));
- u.addQueryItem(TQString::fromLatin1("AssociateTag"), m_assoc);
- u.addQueryItem(TQString::fromLatin1("AWSAccessKeyId"), m_access);
- u.addQueryItem(TQString::fromLatin1("Operation"), TQString::fromLatin1("ItemSearch"));
- u.addQueryItem(TQString::fromLatin1("ResponseGroup"), TQString::fromLatin1("Large"));
- u.addQueryItem(TQString::fromLatin1("ItemPage"), TQString::number(m_page));
- u.addQueryItem(TQString::fromLatin1("Version"), TQString::fromLatin1("2007-10-29"));
+
+ TQMap<TQString, TQString> params;
+ params.insert(TQString::fromLatin1("Service"), TQString::fromLatin1("AWSECommerceService"));
+ params.insert(TQString::fromLatin1("AssociateTag"), m_assoc);
+ params.insert(TQString::fromLatin1("AWSAccessKeyId"), m_access);
+ params.insert(TQString::fromLatin1("Operation"), TQString::fromLatin1("ItemSearch"));
+ params.insert(TQString::fromLatin1("ResponseGroup"), TQString::fromLatin1("Large"));
+ params.insert(TQString::fromLatin1("ItemPage"), TQString::number(m_page));
+ params.insert(TQString::fromLatin1("Version"), TQString::fromLatin1("2007-10-29"));
const int type = Kernel::self()->collectionType();
switch(type) {
case Data::Collection::Book:
case Data::Collection::ComicBook:
case Data::Collection::Bibtex:
- u.addQueryItem(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("Books"));
- u.addQueryItem(TQString::fromLatin1("SortIndex"), TQString::fromLatin1("relevancerank"));
+ params.insert(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("Books"));
+ params.insert(TQString::fromLatin1("SortIndex"), TQString::fromLatin1("relevancerank"));
break;
case Data::Collection::Album:
- u.addQueryItem(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("Music"));
+ params.insert(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("Music"));
break;
case Data::Collection::Video:
- u.addQueryItem(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("Video"));
- u.addQueryItem(TQString::fromLatin1("SortIndex"), TQString::fromLatin1("relevancerank"));
+ params.insert(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("Video"));
+ params.insert(TQString::fromLatin1("SortIndex"), TQString::fromLatin1("relevancerank"));
break;
case Data::Collection::Game:
- u.addQueryItem(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("VideoGames"));
+ params.insert(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("VideoGames"));
+ break;
+
+ case Data::Collection::BoardGame:
+ params.insert(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("Toys"));
+ params.insert(TQString::fromLatin1("SortIndex"), TQString::fromLatin1("relevancerank"));
break;
case Data::Collection::Coin:
@@ -188,7 +198,6 @@ void AmazonFetcher::doSearch() {
case Data::Collection::Wine:
case Data::Collection::Base:
case Data::Collection::Card:
- default:
message(i18n("%1 does not allow searching for this collection type.").arg(source()), MessageHandler::Warning);
stop();
return;
@@ -207,29 +216,28 @@ void AmazonFetcher::doSearch() {
switch(m_key) {
case Title:
- u.addQueryItem(TQString::fromLatin1("Title"), value, mib);
+ params.insert(TQString::fromLatin1("Title"), value);
break;
case Person:
if(type == Data::Collection::Video) {
- u.addQueryItem(TQString::fromLatin1("Actor"), value, mib);
- u.addQueryItem(TQString::fromLatin1("Director"), value, mib);
+ params.insert(TQString::fromLatin1("Actor"), value);
+ params.insert(TQString::fromLatin1("Director"), value);
} else if(type == Data::Collection::Album) {
- u.addQueryItem(TQString::fromLatin1("Artist"), value, mib);
+ params.insert(TQString::fromLatin1("Artist"), value);
} else if(type == Data::Collection::Game) {
- u.addQueryItem(TQString::fromLatin1("Manufacturer"), value, mib);
+ params.insert(TQString::fromLatin1("Manufacturer"), value);
} else { // books and bibtex
TQString s = TQString::fromLatin1("author:%1 or publisher:%2").arg(value, value);
-// u.addQueryItem(TQString::fromLatin1("Author"), value, mib);
-// u.addQueryItem(TQString::fromLatin1("Publisher"), value, mib);
- u.addQueryItem(TQString::fromLatin1("Power"), s, mib);
+// params.insert(TQString::fromLatin1("Author"), value, mib);
+// params.insert(TQString::fromLatin1("Publisher"), value, mib);
+ params.insert(TQString::fromLatin1("Power"), s);
}
break;
case ISBN:
{
- u.removeQueryItem(TQString::fromLatin1("Operation"));
- u.addQueryItem(TQString::fromLatin1("Operation"), TQString::fromLatin1("ItemLookup"));
+ params.insert(TQString::fromLatin1("Operation"), TQString::fromLatin1("ItemLookup"));
TQString s = m_value; // not encValue!!!
s.remove('-');
@@ -260,47 +268,46 @@ void AmazonFetcher::doSearch() {
}
}
// the default search is by ASIN, which prohibits SearchIndex
- u.removeQueryItem(TQString::fromLatin1("SearchIndex"));
+ params.remove(TQString::fromLatin1("SearchIndex"));
}
// limit to first 10
while(isbns.size() > 10) {
isbns.pop_back();
}
- u.addQueryItem(TQString::fromLatin1("ItemId"), isbns.join(TQString::fromLatin1(",")));
+ params.insert(TQString::fromLatin1("ItemId"), isbns.join(TQString::fromLatin1(",")));
if(isbn13) {
- u.addQueryItem(TQString::fromLatin1("IdType"), TQString::fromLatin1("EAN"));
+ params.insert(TQString::fromLatin1("IdType"), TQString::fromLatin1("EAN"));
}
}
break;
case UPC:
{
- u.removeQueryItem(TQString::fromLatin1("Operation"));
- u.addQueryItem(TQString::fromLatin1("Operation"), TQString::fromLatin1("ItemLookup"));
+ params.insert(TQString::fromLatin1("Operation"), TQString::fromLatin1("ItemLookup"));
// US allows UPC, all others are EAN
if(m_site == US) {
- u.addQueryItem(TQString::fromLatin1("IdType"), TQString::fromLatin1("UPC"));
+ params.insert(TQString::fromLatin1("IdType"), TQString::fromLatin1("UPC"));
} else {
- u.addQueryItem(TQString::fromLatin1("IdType"), TQString::fromLatin1("EAN"));
+ params.insert(TQString::fromLatin1("IdType"), TQString::fromLatin1("EAN"));
}
TQString s = m_value; // not encValue!!!
s.remove('-');
// limit to first 10
s.replace(TQString::fromLatin1("; "), TQString::fromLatin1(","));
s = s.section(',', 0, 9);
- u.addQueryItem(TQString::fromLatin1("ItemId"), s);
+ params.insert(TQString::fromLatin1("ItemId"), s);
}
break;
case Keyword:
- u.addQueryItem(TQString::fromLatin1("Keywords"), m_value, mib);
+ params.insert(TQString::fromLatin1("Keywords"), value);
break;
case Raw:
{
TQString key = value.section('=', 0, 0).stripWhiteSpace();
TQString str = value.section('=', 1).stripWhiteSpace();
- u.addQueryItem(key, str, mib);
+ params.insert(key, str);
}
break;
@@ -309,9 +316,11 @@ void AmazonFetcher::doSearch() {
stop();
return;
}
-// myDebug() << "AmazonFetcher::search() - url: " << u.url() << endl;
+ AmazonRequest request(siteData(m_site).url, m_amazonKey);
+ KURL newUrl = request.signedRequest(params);
+// myDebug() << "AmazonFetcher::search() - url: " << newUrl.url() << endl;
- m_job = TDEIO::get(u, false, false);
+ m_job = TDEIO::get(newUrl, false, false);
connect(m_job, TQT_SIGNAL(data(TDEIO::Job*, const TQByteArray&)),
TQT_SLOT(slotData(TDEIO::Job*, const TQByteArray&)));
connect(m_job, TQT_SIGNAL(result(TDEIO::Job*)),
@@ -520,6 +529,12 @@ void AmazonFetcher::slotComplete(TDEIO::Job* job_) {
+ entry->field(TQString::fromLatin1("year"));
break;
+ case Data::Collection::BoardGame:
+ desc = entry->field(TQString::fromLatin1("publisher"))
+ + TQChar('/')
+ + entry->field(TQString::fromLatin1("year"));
+ break;
+
default:
break;
}
@@ -889,11 +904,25 @@ AmazonFetcher::ConfigWidget::ConfigWidget(TQWidget* parent_, const AmazonFetcher
TQWhatsThis::add(m_assocEdit, w);
label->setBuddy(m_assocEdit);
+ label = new TQLabel(i18n("Access key: "), optionsWidget());
+ l->addWidget(label, ++row, 0);
+ m_accessEdit = new KLineEdit(optionsWidget());
+ connect(m_accessEdit, SIGNAL(textChanged(const TQString&)), SLOT(slotSetModified()));
+ l->addWidget(m_accessEdit, row, 1);
+
+ label = new TQLabel(i18n("Secret Key: "), optionsWidget());
+ l->addWidget(label, ++row, 0);
+ m_secretKeyEdit = new KLineEdit(optionsWidget());
+ connect(m_secretKeyEdit, SIGNAL(textChanged(const TQString&)), SLOT(slotSetModified()));
+ l->addWidget(m_secretKeyEdit, row, 1);
+
l->setRowStretch(++row, 10);
if(fetcher_) {
m_siteCombo->setCurrentData(fetcher_->m_site);
m_assocEdit->setText(fetcher_->m_assoc);
+ m_accessEdit->setText(fetcher_->m_access);
+ m_secretKeyEdit->setText(fetcher_->m_amazonKey);
m_imageCombo->setCurrentData(fetcher_->m_imageSize);
} else { // defaults
m_assocEdit->setText(TQString::fromLatin1(AMAZON_ASSOC_TOKEN));
@@ -912,6 +941,14 @@ void AmazonFetcher::ConfigWidget::saveConfig(TDEConfigGroup& config_) {
if(!s.isEmpty()) {
config_.writeEntry("AssocToken", s);
}
+ s = m_accessEdit->text().stripWhiteSpace();
+ if(!s.isEmpty()) {
+ config_.writeEntry("AccessKey", s);
+ }
+ s = m_secretKeyEdit->text().stripWhiteSpace();
+ if(!s.isEmpty()) {
+ config_.writeEntry("SecretKey", s);
+ }
n = m_imageCombo->currentData().toInt();
config_.writeEntry("Image Size", n);
diff --git a/src/fetch/amazonfetcher.h b/src/fetch/amazonfetcher.h
index 03aed7d..8628b2c 100644
--- a/src/fetch/amazonfetcher.h
+++ b/src/fetch/amazonfetcher.h
@@ -118,6 +118,7 @@ private:
ImageSize m_imageSize;
TQString m_access;
+ TQString m_amazonKey;
TQString m_assoc;
bool m_addLinkField;
int m_limit;
@@ -151,6 +152,8 @@ private slots:
private:
KLineEdit* m_assocEdit;
+ KLineEdit* m_accessEdit;
+ KLineEdit* m_secretKeyEdit;
GUI::ComboBox* m_siteCombo;
GUI::ComboBox* m_imageCombo;
};
diff --git a/src/fetch/amazonrequest.cpp b/src/fetch/amazonrequest.cpp
new file mode 100644
index 0000000..bb8d729
--- /dev/null
+++ b/src/fetch/amazonrequest.cpp
@@ -0,0 +1,72 @@
+/***************************************************************************
+ Copyright (C) 2007-2009 Robby Stephenson <robby@periapsis.org>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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) version 3 or any later version *
+ * accepted by the membership of KDE e.V. (or its successor approved *
+ * by the membership of KDE e.V.), which shall act as a proxy *
+ * defined in Section 14 of version 3 of the license. *
+ * *
+ * 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, see <http://www.gnu.org/licenses/>. *
+ * *
+ ***************************************************************************/
+
+#include "amazonrequest.h"
+#include "hmac_sha2.h"
+#include "../tellico_debug.h"
+
+#include <kmdcodec.h>
+
+#include <tqdatetime.h>
+
+using Tellico::Fetch::AmazonRequest;
+
+AmazonRequest::AmazonRequest(const KURL& site_, const TQString& key_) : m_siteUrl(site_), m_key(key_) {
+}
+
+KURL AmazonRequest::signedRequest(const TQMap<TQString, TQString>& params_) const {
+ TQMap<TQString, TQString> allParams = params_;
+ allParams.insert(TQString::fromLatin1("Timestamp"),
+ TQDateTime::currentDateTime(TQt::UTC).toString(TQt::ISODate));
+
+ TQString query;
+ // has to be a map so that the query elements are sorted
+ TQMap<TQString, TQString>::Iterator it;
+ for ( it = allParams.begin(); it != allParams.end(); ++it ) {
+ query += KURL::encode_string(it.key());
+ query += '=';
+ query += KURL::encode_string(it.data());
+ query += '&';
+ }
+ // remove last '&'
+ query.truncate(query.length()-1);
+
+ const TQCString toSign = "GET\n"
+ + m_siteUrl.host().utf8() + '\n'
+ + m_siteUrl.path().utf8() + '\n'
+ + query.latin1();
+
+ TQByteArray hmac_buffer;
+ hmac_buffer.fill('\0', SHA256_DIGEST_SIZE);
+ // subtract one from string size for toSign, not exactly sure why
+ hmac_sha256(reinterpret_cast<unsigned char*>(const_cast<char*>(m_key.latin1())), m_key.length(),
+ reinterpret_cast<unsigned char*>(toSign.data()), toSign.size()-1,
+ reinterpret_cast<unsigned char*>(hmac_buffer.data()), hmac_buffer.size());
+ const TQString sig = KURL::encode_string(KCodecs::base64Encode(hmac_buffer));
+// myDebug() << sig << endl;
+
+ KURL url = m_siteUrl;
+ url.setQuery(query + "&Signature=" + sig);
+ return url;
+}
diff --git a/src/fetch/amazonrequest.h b/src/fetch/amazonrequest.h
new file mode 100644
index 0000000..d1d9017
--- /dev/null
+++ b/src/fetch/amazonrequest.h
@@ -0,0 +1,52 @@
+/***************************************************************************
+ Copyright (C) 2007-2009 Robby Stephenson <robby@periapsis.org>
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * 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) version 3 or any later version *
+ * accepted by the membership of KDE e.V. (or its successor approved *
+ * by the membership of KDE e.V.), which shall act as a proxy *
+ * defined in Section 14 of version 3 of the license. *
+ * *
+ * 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, see <http://www.gnu.org/licenses/>. *
+ * *
+ ***************************************************************************/
+
+#ifndef TELLICO_FETCH_AMAZONREQUEST_H
+#define TELLICO_FETCH_AMAZONREQUEST_H
+
+#include <kurl.h>
+
+#include <tqmap.h>
+
+namespace Tellico {
+ namespace Fetch {
+
+/**
+ * @author Robby Stephenson
+ */
+class AmazonRequest {
+public:
+ AmazonRequest(const KURL& site, const TQString& key);
+
+ KURL signedRequest(const TQMap<TQString, TQString>& params) const;
+
+private:
+ KURL m_siteUrl;
+ TQString m_key;
+};
+
+ } // end Fetch namespace
+} // end Tellico namespace
+
+#endif
diff --git a/src/fetch/arxivfetcher.cpp b/src/fetch/arxivfetcher.cpp
index f59d246..ec3f8fb 100644
--- a/src/fetch/arxivfetcher.cpp
+++ b/src/fetch/arxivfetcher.cpp
@@ -226,6 +226,13 @@ Tellico::Data::EntryPtr ArxivFetcher::fetchEntry(uint uid_) {
}
}
}
+ TQRegExp versionRx(TQString::fromLatin1("v\\d+$"));
+ // if the original search was not for a versioned ID, remove it
+ if(m_key != ArxivID || !m_value.contains(versionRx)) {
+ TQString arxiv = entry->field(TQString::fromLatin1("arxiv"));
+ arxiv.remove(versionRx);
+ entry->setField(TQString::fromLatin1("arxiv"), arxiv);
+ }
return entry;
}
diff --git a/src/fetch/citebasefetcher.cpp b/src/fetch/citebasefetcher.cpp
index f5e8cd6..2b5a8db 100644
--- a/src/fetch/citebasefetcher.cpp
+++ b/src/fetch/citebasefetcher.cpp
@@ -163,7 +163,15 @@ void CitebaseFetcher::slotComplete(TDEIO::Job* job_) {
}
Tellico::Data::EntryPtr CitebaseFetcher::fetchEntry(uint uid_) {
- return m_entries[uid_];
+ Data::EntryPtr entry = m_entries[uid_];
+ TQRegExp versionRx(TQString::fromLatin1("v\\d+$"));
+ // if the original search was not for a versioned ID, remove it
+ if(m_key != ArxivID || !m_value.contains(versionRx)) {
+ TQString arxiv = entry->field(TQString::fromLatin1("arxiv"));
+ arxiv.remove(versionRx);
+ entry->setField(TQString::fromLatin1("arxiv"), arxiv);
+ }
+ return entry;
}
KURL CitebaseFetcher::searchURL(FetchKey key_, const TQString& value_) const {
diff --git a/src/fetch/entrezfetcher.cpp b/src/fetch/entrezfetcher.cpp
index 07066b8..b1d2789 100644
--- a/src/fetch/entrezfetcher.cpp
+++ b/src/fetch/entrezfetcher.cpp
@@ -34,7 +34,7 @@
//#define ENTREZ_TEST
namespace {
- static const int ENTREZ_MAX_RETURNS_TOTAL = 25;
+ static const size_t ENTREZ_MAX_RETURNS_TOTAL = 25;
static const char* ENTREZ_BASE_URL = "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/";
static const char* ENTREZ_SEARCH_CGI = "esearch.fcgi";
static const char* ENTREZ_SUMMARY_CGI = "esummary.fcgi";
diff --git a/src/fetch/entrezfetcher.h b/src/fetch/entrezfetcher.h
index 87e13ae..7a9a0a1 100644
--- a/src/fetch/entrezfetcher.h
+++ b/src/fetch/entrezfetcher.h
@@ -92,8 +92,8 @@ private:
XSLTHandler* m_xsltHandler;
TQString m_dbname;
- int m_start;
- int m_total;
+ size_t m_start;
+ size_t m_total;
TQByteArray m_data;
TQMap<int, Data::EntryPtr> m_entries; // map from search result id to entry
diff --git a/src/fetch/googlescholarfetcher.cpp b/src/fetch/googlescholarfetcher.cpp
index 19e69c6..8ac7d4d 100644
--- a/src/fetch/googlescholarfetcher.cpp
+++ b/src/fetch/googlescholarfetcher.cpp
@@ -28,7 +28,7 @@
#include <tqlayout.h>
namespace {
- static const int GOOGLE_MAX_RETURNS_TOTAL = 20;
+ static const size_t GOOGLE_MAX_RETURNS_TOTAL = 20;
static const char* SCHOLAR_BASE_URL = "http://scholar.google.com/scholar";
}
@@ -157,7 +157,7 @@ void GoogleScholarFetcher::slotComplete(TDEIO::Job* job_) {
TQString text = TQString::fromUtf8(m_data, m_data.size());
TQString bibtex;
- int count = 0;
+ size_t count = 0;
for(int pos = text.find(m_bibtexRx); count < m_limit && pos > -1; pos = text.find(m_bibtexRx, pos+m_bibtexRx.matchedLength()), ++count) {
KURL bibtexUrl(TQString::fromLatin1(SCHOLAR_BASE_URL), m_bibtexRx.cap(1));
// myDebug() << bibtexUrl << endl;
diff --git a/src/fetch/googlescholarfetcher.h b/src/fetch/googlescholarfetcher.h
index 8ef91da..5c0b8a1 100644
--- a/src/fetch/googlescholarfetcher.h
+++ b/src/fetch/googlescholarfetcher.h
@@ -83,9 +83,9 @@ private slots:
private:
void doSearch();
- int m_limit;
- int m_start;
- int m_total;
+ size_t m_limit;
+ size_t m_start;
+ size_t m_total;
TQByteArray m_data;
TQMap<int, Data::EntryPtr> m_entries;
diff --git a/src/fetch/hmac_sha2.c b/src/fetch/hmac_sha2.c
new file mode 100644
index 0000000..dd7c24a
--- /dev/null
+++ b/src/fetch/hmac_sha2.c
@@ -0,0 +1,544 @@
+/*-
+ * HMAC-SHA-224/256/384/512 implementation
+ * Last update: 06/15/2005
+ * Issue date: 06/15/2005
+ *
+ * Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <string.h>
+
+#include "hmac_sha2.h"
+
+/* HMAC-SHA-224 functions */
+
+void hmac_sha224_init(hmac_sha224_ctx *ctx, unsigned char *key,
+ unsigned int key_size)
+{
+ unsigned int fill;
+ unsigned int num;
+
+ unsigned char *key_used;
+ unsigned char key_temp[SHA224_DIGEST_SIZE];
+ int i;
+
+ if (key_size == SHA224_BLOCK_SIZE) {
+ key_used = key;
+ num = SHA224_BLOCK_SIZE;
+ } else {
+ if (key_size > SHA224_BLOCK_SIZE){
+ key_used = key_temp;
+ num = SHA224_DIGEST_SIZE;
+ sha224(key, key_size, key_used);
+ } else { /* key_size > SHA224_BLOCK_SIZE */
+ key_used = key;
+ num = key_size;
+ }
+ fill = SHA224_BLOCK_SIZE - num;
+
+ memset(ctx->block_ipad + num, 0x36, fill);
+ memset(ctx->block_opad + num, 0x5c, fill);
+ }
+
+ for (i = 0; i < num; i++) {
+ ctx->block_ipad[i] = key_used[i] ^ 0x36;
+ ctx->block_opad[i] = key_used[i] ^ 0x5c;
+ }
+
+ sha224_init(&ctx->ctx_inside);
+ sha224_update(&ctx->ctx_inside, ctx->block_ipad, SHA224_BLOCK_SIZE);
+
+ sha224_init(&ctx->ctx_outside);
+ sha224_update(&ctx->ctx_outside, ctx->block_opad,
+ SHA224_BLOCK_SIZE);
+
+ /* for hmac_reinit */
+ memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
+ sizeof(sha224_ctx));
+ memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
+ sizeof(sha224_ctx));
+}
+
+void hmac_sha224_reinit(hmac_sha224_ctx *ctx)
+{
+ memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
+ sizeof(sha224_ctx));
+ memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
+ sizeof(sha224_ctx));
+}
+
+void hmac_sha224_update(hmac_sha224_ctx *ctx, unsigned char *message,
+ unsigned int message_len)
+{
+ sha224_update(&ctx->ctx_inside, message, message_len);
+}
+
+void hmac_sha224_final(hmac_sha224_ctx *ctx, unsigned char *mac,
+ unsigned int mac_size)
+{
+ unsigned char digest_inside[SHA224_DIGEST_SIZE];
+ unsigned char mac_temp[SHA224_DIGEST_SIZE];
+
+ sha224_final(&ctx->ctx_inside, digest_inside);
+ sha224_update(&ctx->ctx_outside, digest_inside, SHA224_DIGEST_SIZE);
+ sha224_final(&ctx->ctx_outside, mac_temp);
+ memcpy(mac, mac_temp, mac_size);
+}
+
+void hmac_sha224(unsigned char *key, unsigned int key_size,
+ unsigned char *message, unsigned int message_len,
+ unsigned char *mac, unsigned mac_size)
+{
+ hmac_sha224_ctx ctx;
+
+ hmac_sha224_init(&ctx, key, key_size);
+ hmac_sha224_update(&ctx, message, message_len);
+ hmac_sha224_final(&ctx, mac, mac_size);
+}
+
+/* HMAC-SHA-256 functions */
+
+void hmac_sha256_init(hmac_sha256_ctx *ctx, unsigned char *key,
+ unsigned int key_size)
+{
+ unsigned int fill;
+ unsigned int num;
+
+ unsigned char *key_used;
+ unsigned char key_temp[SHA256_DIGEST_SIZE];
+ int i;
+
+ if (key_size == SHA256_BLOCK_SIZE) {
+ key_used = key;
+ num = SHA256_BLOCK_SIZE;
+ } else {
+ if (key_size > SHA256_BLOCK_SIZE){
+ key_used = key_temp;
+ num = SHA256_DIGEST_SIZE;
+ sha256(key, key_size, key_used);
+ } else { /* key_size > SHA256_BLOCK_SIZE */
+ key_used = key;
+ num = key_size;
+ }
+ fill = SHA256_BLOCK_SIZE - num;
+
+ memset(ctx->block_ipad + num, 0x36, fill);
+ memset(ctx->block_opad + num, 0x5c, fill);
+ }
+
+ for (i = 0; i < num; i++) {
+ ctx->block_ipad[i] = key_used[i] ^ 0x36;
+ ctx->block_opad[i] = key_used[i] ^ 0x5c;
+ }
+
+ sha256_init(&ctx->ctx_inside);
+ sha256_update(&ctx->ctx_inside, ctx->block_ipad, SHA256_BLOCK_SIZE);
+
+ sha256_init(&ctx->ctx_outside);
+ sha256_update(&ctx->ctx_outside, ctx->block_opad,
+ SHA256_BLOCK_SIZE);
+
+ /* for hmac_reinit */
+ memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
+ sizeof(sha256_ctx));
+ memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
+ sizeof(sha256_ctx));
+}
+
+void hmac_sha256_reinit(hmac_sha256_ctx *ctx)
+{
+ memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
+ sizeof(sha256_ctx));
+ memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
+ sizeof(sha256_ctx));
+}
+
+void hmac_sha256_update(hmac_sha256_ctx *ctx, unsigned char *message,
+ unsigned int message_len)
+{
+ sha256_update(&ctx->ctx_inside, message, message_len);
+}
+
+void hmac_sha256_final(hmac_sha256_ctx *ctx, unsigned char *mac,
+ unsigned int mac_size)
+{
+ unsigned char digest_inside[SHA256_DIGEST_SIZE];
+ unsigned char mac_temp[SHA256_DIGEST_SIZE];
+
+ sha256_final(&ctx->ctx_inside, digest_inside);
+ sha256_update(&ctx->ctx_outside, digest_inside, SHA256_DIGEST_SIZE);
+ sha256_final(&ctx->ctx_outside, mac_temp);
+ memcpy(mac, mac_temp, mac_size);
+}
+
+void hmac_sha256(unsigned char *key, unsigned int key_size,
+ unsigned char *message, unsigned int message_len,
+ unsigned char *mac, unsigned mac_size)
+{
+ hmac_sha256_ctx ctx;
+
+ hmac_sha256_init(&ctx, key, key_size);
+ hmac_sha256_update(&ctx, message, message_len);
+ hmac_sha256_final(&ctx, mac, mac_size);
+}
+
+/* HMAC-SHA-384 functions */
+
+void hmac_sha384_init(hmac_sha384_ctx *ctx, unsigned char *key,
+ unsigned int key_size)
+{
+ unsigned int fill;
+ unsigned int num;
+
+ unsigned char *key_used;
+ unsigned char key_temp[SHA384_DIGEST_SIZE];
+ int i;
+
+ if (key_size == SHA384_BLOCK_SIZE) {
+ key_used = key;
+ num = SHA384_BLOCK_SIZE;
+ } else {
+ if (key_size > SHA384_BLOCK_SIZE){
+ key_used = key_temp;
+ num = SHA384_DIGEST_SIZE;
+ sha384(key, key_size, key_used);
+ } else { /* key_size > SHA384_BLOCK_SIZE */
+ key_used = key;
+ num = key_size;
+ }
+ fill = SHA384_BLOCK_SIZE - num;
+
+ memset(ctx->block_ipad + num, 0x36, fill);
+ memset(ctx->block_opad + num, 0x5c, fill);
+ }
+
+ for (i = 0; i < num; i++) {
+ ctx->block_ipad[i] = key_used[i] ^ 0x36;
+ ctx->block_opad[i] = key_used[i] ^ 0x5c;
+ }
+
+ sha384_init(&ctx->ctx_inside);
+ sha384_update(&ctx->ctx_inside, ctx->block_ipad, SHA384_BLOCK_SIZE);
+
+ sha384_init(&ctx->ctx_outside);
+ sha384_update(&ctx->ctx_outside, ctx->block_opad,
+ SHA384_BLOCK_SIZE);
+
+ /* for hmac_reinit */
+ memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
+ sizeof(sha384_ctx));
+ memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
+ sizeof(sha384_ctx));
+}
+
+void hmac_sha384_reinit(hmac_sha384_ctx *ctx)
+{
+ memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
+ sizeof(sha384_ctx));
+ memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
+ sizeof(sha384_ctx));
+}
+
+void hmac_sha384_update(hmac_sha384_ctx *ctx, unsigned char *message,
+ unsigned int message_len)
+{
+ sha384_update(&ctx->ctx_inside, message, message_len);
+}
+
+void hmac_sha384_final(hmac_sha384_ctx *ctx, unsigned char *mac,
+ unsigned int mac_size)
+{
+ unsigned char digest_inside[SHA384_DIGEST_SIZE];
+ unsigned char mac_temp[SHA384_DIGEST_SIZE];
+
+ sha384_final(&ctx->ctx_inside, digest_inside);
+ sha384_update(&ctx->ctx_outside, digest_inside, SHA384_DIGEST_SIZE);
+ sha384_final(&ctx->ctx_outside, mac_temp);
+ memcpy(mac, mac_temp, mac_size);
+}
+
+void hmac_sha384(unsigned char *key, unsigned int key_size,
+ unsigned char *message, unsigned int message_len,
+ unsigned char *mac, unsigned mac_size)
+{
+ hmac_sha384_ctx ctx;
+
+ hmac_sha384_init(&ctx, key, key_size);
+ hmac_sha384_update(&ctx, message, message_len);
+ hmac_sha384_final(&ctx, mac, mac_size);
+}
+
+/* HMAC-SHA-512 functions */
+
+void hmac_sha512_init(hmac_sha512_ctx *ctx, unsigned char *key,
+ unsigned int key_size)
+{
+ unsigned int fill;
+ unsigned int num;
+
+ unsigned char *key_used;
+ unsigned char key_temp[SHA512_DIGEST_SIZE];
+ int i;
+
+ if (key_size == SHA512_BLOCK_SIZE) {
+ key_used = key;
+ num = SHA512_BLOCK_SIZE;
+ } else {
+ if (key_size > SHA512_BLOCK_SIZE){
+ key_used = key_temp;
+ num = SHA512_DIGEST_SIZE;
+ sha512(key, key_size, key_used);
+ } else { /* key_size > SHA512_BLOCK_SIZE */
+ key_used = key;
+ num = key_size;
+ }
+ fill = SHA512_BLOCK_SIZE - num;
+
+ memset(ctx->block_ipad + num, 0x36, fill);
+ memset(ctx->block_opad + num, 0x5c, fill);
+ }
+
+ for (i = 0; i < num; i++) {
+ ctx->block_ipad[i] = key_used[i] ^ 0x36;
+ ctx->block_opad[i] = key_used[i] ^ 0x5c;
+ }
+
+ sha512_init(&ctx->ctx_inside);
+ sha512_update(&ctx->ctx_inside, ctx->block_ipad, SHA512_BLOCK_SIZE);
+
+ sha512_init(&ctx->ctx_outside);
+ sha512_update(&ctx->ctx_outside, ctx->block_opad,
+ SHA512_BLOCK_SIZE);
+
+ /* for hmac_reinit */
+ memcpy(&ctx->ctx_inside_reinit, &ctx->ctx_inside,
+ sizeof(sha512_ctx));
+ memcpy(&ctx->ctx_outside_reinit, &ctx->ctx_outside,
+ sizeof(sha512_ctx));
+}
+
+void hmac_sha512_reinit(hmac_sha512_ctx *ctx)
+{
+ memcpy(&ctx->ctx_inside, &ctx->ctx_inside_reinit,
+ sizeof(sha512_ctx));
+ memcpy(&ctx->ctx_outside, &ctx->ctx_outside_reinit,
+ sizeof(sha512_ctx));
+}
+
+void hmac_sha512_update(hmac_sha512_ctx *ctx, unsigned char *message,
+ unsigned int message_len)
+{
+ sha512_update(&ctx->ctx_inside, message, message_len);
+}
+
+void hmac_sha512_final(hmac_sha512_ctx *ctx, unsigned char *mac,
+ unsigned int mac_size)
+{
+ unsigned char digest_inside[SHA512_DIGEST_SIZE];
+ unsigned char mac_temp[SHA512_DIGEST_SIZE];
+
+ sha512_final(&ctx->ctx_inside, digest_inside);
+ sha512_update(&ctx->ctx_outside, digest_inside, SHA512_DIGEST_SIZE);
+ sha512_final(&ctx->ctx_outside, mac_temp);
+ memcpy(mac, mac_temp, mac_size);
+}
+
+void hmac_sha512(unsigned char *key, unsigned int key_size,
+ unsigned char *message, unsigned int message_len,
+ unsigned char *mac, unsigned mac_size)
+{
+ hmac_sha512_ctx ctx;
+
+ hmac_sha512_init(&ctx, key, key_size);
+ hmac_sha512_update(&ctx, message, message_len);
+ hmac_sha512_final(&ctx, mac, mac_size);
+}
+
+#ifdef TEST_VECTORS
+
+/* IETF Validation tests */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void test(unsigned char *vector, unsigned char *digest,
+ unsigned int digest_size)
+{
+ unsigned char output[2 * SHA512_DIGEST_SIZE + 1];
+ int i;
+
+ output[2 * digest_size] = '\0';
+
+ for (i = 0; i < digest_size ; i++) {
+ sprintf((char *) output + 2*i, "%02x", digest[i]);
+ }
+
+ printf("H: %s\n", output);
+ if (strcmp((char *) vector, (char *) output)) {
+ fprintf(stderr, "Test failed.\n");
+ exit(1);
+ }
+}
+
+int main()
+{
+ static unsigned char *vectors[] =
+ {
+ /* HMAC-SHA-224 */
+ "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22",
+ "a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44",
+ "7fb3cb3588c6c1f6ffa9694d7d6ad2649365b0c1f65d69d1ec8333ea",
+ "6c11506874013cac6a2abc1bb382627cec6a90d86efc012de7afec5a",
+ "0e2aea68a90c8d37c988bcdb9fca6fa8",
+ "95e9a0db962095adaebe9b2d6f0dbce2d499f112f2d2b7273fa6870e",
+ "3a854166ac5d9f023f54d517d0b39dbd946770db9c2b95c9f6f565d1",
+ /* HMAC-SHA-256 */
+ "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
+ "5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843",
+ "773ea91e36800e46854db8ebd09181a72959098b3ef8c122d9635514ced565fe",
+ "82558a389a443c0ea4cc819899f2083a85f0faa3e578f8077a2e3ff46729665b",
+ "a3b6167473100ee06e0c796c2955552b",
+ "60e431591ee0b67f0d8a26aacbf5b77f8e0bc6213728c5140546040f0ee37f54",
+ "9b09ffa71b942fcb27635fbcd5b0e944bfdc63644f0713938a7f51535c3a35e2",
+ /* HMAC-SHA-384 */
+ "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59c"
+ "faea9ea9076ede7f4af152e8b2fa9cb6",
+ "af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e"
+ "8e2240ca5e69e2c78b3239ecfab21649",
+ "88062608d3e6ad8a0aa2ace014c8a86f0aa635d947ac9febe83ef4e55966144b"
+ "2a5ab39dc13814b94e3ab6e101a34f27",
+ "3e8a69b7783c25851933ab6290af6ca77a9981480850009cc5577c6e1f573b4e"
+ "6801dd23c4a7d679ccf8a386c674cffb",
+ "3abf34c3503b2a23a46efc619baef897",
+ "4ece084485813e9088d2c63a041bc5b44f9ef1012a2b588f3cd11f05033ac4c6"
+ "0c2ef6ab4030fe8296248df163f44952",
+ "6617178e941f020d351e2f254e8fd32c602420feb0b8fb9adccebb82461e99c5"
+ "a678cc31e799176d3860e6110c46523e",
+ /* HMAC-SHA-512 */
+ "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cde"
+ "daa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854",
+ "164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea250554"
+ "9758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737",
+ "fa73b0089d56a284efb0f0756c890be9b1b5dbdd8ee81a3655f83e33b2279d39"
+ "bf3e848279a722c806b485a47e67c807b946a337bee8942674278859e13292fb",
+ "b0ba465637458c6990e5a8c5f61d4af7e576d97ff94b872de76f8050361ee3db"
+ "a91ca5c11aa25eb4d679275cc5788063a5f19741120c4f2de2adebeb10a298dd",
+ "415fad6271580a531d4179bc891d87a6",
+ "80b24263c7c1a3ebb71493c1dd7be8b49b46d1f41b4aeec1121b013783f8f352"
+ "6b56d037e05f2598bd0fd2215d6a1e5295e64f73f63f0aec8b915a985d786598",
+ "e37b6a775dc87dbaa4dfa9f96e5e3ffddebd71f8867289865df5a32d20cdc944"
+ "b6022cac3c4982b10d5eeb55c3e4de15134676fb6de0446065c97440fa8c6a58"
+ };
+
+ static unsigned char *messages[] =
+ {
+ "Hi There",
+ "what do ya want for nothing?",
+ NULL,
+ NULL,
+ "Test With Truncation",
+ "Test Using Larger Than Block-Size Key - Hash Key First",
+ "This is a test using a larger than block-size key "
+ "and a larger than block-size data. The key needs"
+ " to be hashed before being used by the HMAC algorithm."
+ };
+
+ unsigned char mac[SHA512_DIGEST_SIZE];
+ unsigned char *keys[7];
+ unsigned int keys_len[7] = {20, 4, 20, 25, 20, 131, 131};
+ unsigned int messages2and3_len = 50;
+ unsigned int mac_224_size, mac_256_size, mac_384_size, mac_512_size;
+ int i;
+
+ for (i = 0; i < 7; i++) {
+ keys[i] = malloc(keys_len[i]);
+ if (keys[i] == NULL) {
+ fprintf(stderr, "Can't allocate memory\n");
+ return 1;
+ }
+ }
+
+ memset(keys[0], 0x0b, keys_len[0]);
+ strcpy(keys[1], "Jefe");
+ memset(keys[2], 0xaa, keys_len[2]);
+ for (i = 0; i < keys_len[3]; i++)
+ keys[3][i] = (unsigned char) i + 1;
+ memset(keys[4], 0x0c, keys_len[4]);
+ memset(keys[5], 0xaa, keys_len[5]);
+ memset(keys[6], 0xaa, keys_len[6]);
+
+ messages[2] = malloc(messages2and3_len + 1);
+ messages[3] = malloc(messages2and3_len + 1);
+
+ if (messages[2] == NULL || messages[3] == NULL) {
+ fprintf(stderr, "Can't allocate memory\n");
+ return 1;
+ }
+
+ messages[2][messages2and3_len] = '\0';
+ messages[3][messages2and3_len] = '\0';
+
+ memset(messages[2], 0xdd, messages2and3_len);
+ memset(messages[3], 0xcd, messages2and3_len);
+
+ printf("HMAC-SHA-2 IETF Validation tests\n\n");
+
+ for (i = 0; i < 7; i++) {
+ if (i != 4) {
+ mac_224_size = SHA224_DIGEST_SIZE;
+ mac_256_size = SHA256_DIGEST_SIZE;
+ mac_384_size = SHA384_DIGEST_SIZE;
+ mac_512_size = SHA512_DIGEST_SIZE;
+ } else {
+ mac_224_size = 128 / 8; mac_256_size = 128 / 8;
+ mac_384_size = 128 / 8; mac_512_size = 128 / 8;
+ }
+
+ printf("Test %d:\n", i + 1);
+
+ hmac_sha224(keys[i], keys_len[i], messages[i], strlen(messages[i]),
+ mac, mac_224_size);
+ test(vectors[i], mac, mac_224_size );
+ hmac_sha256(keys[i], keys_len[i], messages[i], strlen(messages[i]),
+ mac, mac_256_size);
+ test(vectors[7 + i], mac, mac_256_size);
+ hmac_sha384(keys[i], keys_len[i], messages[i], strlen(messages[i]),
+ mac, mac_384_size);
+ test(vectors[14 + i], mac, mac_384_size);
+ hmac_sha512(keys[i], keys_len[i], messages[i], strlen(messages[i]),
+ mac, mac_512_size);
+ test(vectors[21 + i], mac, mac_512_size);
+ }
+
+ printf("All tests passed.\n");
+
+ return 0;
+}
+
+#endif /* TEST_VECTORS */
+
diff --git a/src/fetch/hmac_sha2.h b/src/fetch/hmac_sha2.h
new file mode 100644
index 0000000..f10fb49
--- /dev/null
+++ b/src/fetch/hmac_sha2.h
@@ -0,0 +1,140 @@
+/*-
+ * HMAC-SHA-224/256/384/512 implementation
+ * Last update: 06/15/2005
+ * Issue date: 06/15/2005
+ *
+ * Copyright (C) 2005 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _HMAC_SHA2_H
+#define _HMAC_SHA2_H
+
+#include "sha2.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ sha224_ctx ctx_inside;
+ sha224_ctx ctx_outside;
+
+ /* for hmac_reinit */
+ sha224_ctx ctx_inside_reinit;
+ sha224_ctx ctx_outside_reinit;
+
+ unsigned char block_ipad[SHA224_BLOCK_SIZE];
+ unsigned char block_opad[SHA224_BLOCK_SIZE];
+} hmac_sha224_ctx;
+
+typedef struct {
+ sha256_ctx ctx_inside;
+ sha256_ctx ctx_outside;
+
+ /* for hmac_reinit */
+ sha256_ctx ctx_inside_reinit;
+ sha256_ctx ctx_outside_reinit;
+
+ unsigned char block_ipad[SHA256_BLOCK_SIZE];
+ unsigned char block_opad[SHA256_BLOCK_SIZE];
+} hmac_sha256_ctx;
+
+typedef struct {
+ sha384_ctx ctx_inside;
+ sha384_ctx ctx_outside;
+
+ /* for hmac_reinit */
+ sha384_ctx ctx_inside_reinit;
+ sha384_ctx ctx_outside_reinit;
+
+ unsigned char block_ipad[SHA384_BLOCK_SIZE];
+ unsigned char block_opad[SHA384_BLOCK_SIZE];
+} hmac_sha384_ctx;
+
+typedef struct {
+ sha512_ctx ctx_inside;
+ sha512_ctx ctx_outside;
+
+ /* for hmac_reinit */
+ sha512_ctx ctx_inside_reinit;
+ sha512_ctx ctx_outside_reinit;
+
+ unsigned char block_ipad[SHA512_BLOCK_SIZE];
+ unsigned char block_opad[SHA512_BLOCK_SIZE];
+} hmac_sha512_ctx;
+
+void hmac_sha224_init(hmac_sha224_ctx *ctx, unsigned char *key,
+ unsigned int key_size);
+void hmac_sha224_reinit(hmac_sha224_ctx *ctx);
+void hmac_sha224_update(hmac_sha224_ctx *ctx, unsigned char *message,
+ unsigned int message_len);
+void hmac_sha224_final(hmac_sha224_ctx *ctx, unsigned char *mac,
+ unsigned int mac_size);
+void hmac_sha224(unsigned char *key, unsigned int key_size,
+ unsigned char *message, unsigned int message_len,
+ unsigned char *mac, unsigned mac_size);
+
+void hmac_sha256_init(hmac_sha256_ctx *ctx, unsigned char *key,
+ unsigned int key_size);
+void hmac_sha256_reinit(hmac_sha256_ctx *ctx);
+void hmac_sha256_update(hmac_sha256_ctx *ctx, unsigned char *message,
+ unsigned int message_len);
+void hmac_sha256_final(hmac_sha256_ctx *ctx, unsigned char *mac,
+ unsigned int mac_size);
+void hmac_sha256(unsigned char *key, unsigned int key_size,
+ unsigned char *message, unsigned int message_len,
+ unsigned char *mac, unsigned mac_size);
+
+void hmac_sha384_init(hmac_sha384_ctx *ctx, unsigned char *key,
+ unsigned int key_size);
+void hmac_sha384_reinit(hmac_sha384_ctx *ctx);
+void hmac_sha384_update(hmac_sha384_ctx *ctx, unsigned char *message,
+ unsigned int message_len);
+void hmac_sha384_final(hmac_sha384_ctx *ctx, unsigned char *mac,
+ unsigned int mac_size);
+void hmac_sha384(unsigned char *key, unsigned int key_size,
+ unsigned char *message, unsigned int message_len,
+ unsigned char *mac, unsigned mac_size);
+
+void hmac_sha512_init(hmac_sha512_ctx *ctx, unsigned char *key,
+ unsigned int key_size);
+void hmac_sha512_reinit(hmac_sha512_ctx *ctx);
+void hmac_sha512_update(hmac_sha512_ctx *ctx, unsigned char *message,
+ unsigned int message_len);
+void hmac_sha512_final(hmac_sha512_ctx *ctx, unsigned char *mac,
+ unsigned int mac_size);
+void hmac_sha512(unsigned char *key, unsigned int key_size,
+ unsigned char *message, unsigned int message_len,
+ unsigned char *mac, unsigned mac_size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ! _HMAC_SHA2_H */
+
diff --git a/src/fetch/ibsfetcher.cpp b/src/fetch/ibsfetcher.cpp
index e715e5b..404bc1c 100644
--- a/src/fetch/ibsfetcher.cpp
+++ b/src/fetch/ibsfetcher.cpp
@@ -156,7 +156,8 @@ void IBSFetcher::slotComplete(TDEIO::Job* job_) {
TQString s = Tellico::decodeHTML(TQString(m_data));
// really specific regexp
- TQString pat = TQString::fromLatin1("http://www.internetbookshop.it/code/");
+ //TQString pat = TQString::fromLatin1("http://www.internetbookshop.it/code/");
+ TQString pat = TQString::fromLatin1("http://www.ibs.it/code/");
TQRegExp anchorRx(TQString::fromLatin1("<a\\s+[^>]*href\\s*=\\s*[\"'](") +
TQRegExp::escape(pat) +
TQString::fromLatin1("[^\"]*)\"[^>]*><b>([^<]+)<"), false);
diff --git a/src/fetch/imdbfetcher.cpp b/src/fetch/imdbfetcher.cpp
index a9c0dd0..36b19a1 100644
--- a/src/fetch/imdbfetcher.cpp
+++ b/src/fetch/imdbfetcher.cpp
@@ -799,7 +799,7 @@ void IMDBFetcher::doPlot(const TQString& str_, Data::EntryPtr entry_, const KURL
TQString thisPlot;
// match until next opening tag
- TQRegExp plotRx(TQString::fromLatin1("plot (?:outline|summary):(.*)<[^/].*</"), false);
+ TQRegExp plotRx(TQString::fromLatin1("plot\\s*(?:outline|summary)?:(.*)<[^/].*</"), false);
plotRx.setMinimal(true);
TQRegExp plotURLRx(TQString::fromLatin1("<a\\s+.*href\\s*=\\s*\".*/title/.*/plotsummary\""), false);
plotURLRx.setMinimal(true);
@@ -828,6 +828,8 @@ void IMDBFetcher::doPlot(const TQString& str_, Data::EntryPtr entry_, const KURL
if(plotRx.search(plotPage) > -1) {
TQString userPlot = plotRx.cap(1);
userPlot.remove(*s_tagRx); // remove HTML tags
+ // remove last little "written by", if there
+ userPlot.remove(TQRegExp(TQString::fromLatin1("\\s*written by.*$"), false));
entry_->setField(TQString::fromLatin1("plot"), Tellico::decodeHTML(userPlot));
}
}
diff --git a/src/fetch/sha2.c b/src/fetch/sha2.c
new file mode 100644
index 0000000..a32427e
--- /dev/null
+++ b/src/fetch/sha2.c
@@ -0,0 +1,950 @@
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date: 04/30/2005
+ *
+ * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#define UNROLL_LOOPS /* Enable loops unrolling */
+#endif
+
+#include <string.h>
+
+#include "sha2.h"
+
+#define SHFR(x, n) (x >> n)
+#define ROTR(x, n) ((x >> n) | (x << ((sizeof(x) << 3) - n)))
+#define ROTL(x, n) ((x << n) | (x >> ((sizeof(x) << 3) - n)))
+#define CH(x, y, z) ((x & y) ^ (~x & z))
+#define MAJ(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
+
+#define SHA256_F1(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
+#define SHA256_F2(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
+#define SHA256_F3(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHFR(x, 3))
+#define SHA256_F4(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHFR(x, 10))
+
+#define SHA512_F1(x) (ROTR(x, 28) ^ ROTR(x, 34) ^ ROTR(x, 39))
+#define SHA512_F2(x) (ROTR(x, 14) ^ ROTR(x, 18) ^ ROTR(x, 41))
+#define SHA512_F3(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHFR(x, 7))
+#define SHA512_F4(x) (ROTR(x, 19) ^ ROTR(x, 61) ^ SHFR(x, 6))
+
+#define UNPACK32(x, str) \
+{ \
+ *((str) + 3) = (uint8) ((x) ); \
+ *((str) + 2) = (uint8) ((x) >> 8); \
+ *((str) + 1) = (uint8) ((x) >> 16); \
+ *((str) + 0) = (uint8) ((x) >> 24); \
+}
+
+#define PACK32(str, x) \
+{ \
+ *(x) = ((uint32) *((str) + 3) ) \
+ | ((uint32) *((str) + 2) << 8) \
+ | ((uint32) *((str) + 1) << 16) \
+ | ((uint32) *((str) + 0) << 24); \
+}
+
+#define UNPACK64(x, str) \
+{ \
+ *((str) + 7) = (uint8) ((x) ); \
+ *((str) + 6) = (uint8) ((x) >> 8); \
+ *((str) + 5) = (uint8) ((x) >> 16); \
+ *((str) + 4) = (uint8) ((x) >> 24); \
+ *((str) + 3) = (uint8) ((x) >> 32); \
+ *((str) + 2) = (uint8) ((x) >> 40); \
+ *((str) + 1) = (uint8) ((x) >> 48); \
+ *((str) + 0) = (uint8) ((x) >> 56); \
+}
+
+#define PACK64(str, x) \
+{ \
+ *(x) = ((uint64) *((str) + 7) ) \
+ | ((uint64) *((str) + 6) << 8) \
+ | ((uint64) *((str) + 5) << 16) \
+ | ((uint64) *((str) + 4) << 24) \
+ | ((uint64) *((str) + 3) << 32) \
+ | ((uint64) *((str) + 2) << 40) \
+ | ((uint64) *((str) + 1) << 48) \
+ | ((uint64) *((str) + 0) << 56); \
+}
+
+/* Macros used for loops unrolling */
+
+#define SHA256_SCR(i) \
+{ \
+ w[i] = SHA256_F4(w[i - 2]) + w[i - 7] \
+ + SHA256_F3(w[i - 15]) + w[i - 16]; \
+}
+
+#define SHA512_SCR(i) \
+{ \
+ w[i] = SHA512_F4(w[i - 2]) + w[i - 7] \
+ + SHA512_F3(w[i - 15]) + w[i - 16]; \
+}
+
+#define SHA256_EXP(a, b, c, d, e, f, g, h, j) \
+{ \
+ t1 = wv[h] + SHA256_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
+ + sha256_k[j] + w[j]; \
+ t2 = SHA256_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
+ wv[d] += t1; \
+ wv[h] = t1 + t2; \
+}
+
+#define SHA512_EXP(a, b, c, d, e, f, g ,h, j) \
+{ \
+ t1 = wv[h] + SHA512_F2(wv[e]) + CH(wv[e], wv[f], wv[g]) \
+ + sha512_k[j] + w[j]; \
+ t2 = SHA512_F1(wv[a]) + MAJ(wv[a], wv[b], wv[c]); \
+ wv[d] += t1; \
+ wv[h] = t1 + t2; \
+}
+
+uint32 sha224_h0[8] =
+ {0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939,
+ 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4};
+
+uint32 sha256_h0[8] =
+ {0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
+ 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19};
+
+uint64 sha384_h0[8] =
+ {0xcbbb9d5dc1059ed8ULL, 0x629a292a367cd507ULL,
+ 0x9159015a3070dd17ULL, 0x152fecd8f70e5939ULL,
+ 0x67332667ffc00b31ULL, 0x8eb44a8768581511ULL,
+ 0xdb0c2e0d64f98fa7ULL, 0x47b5481dbefa4fa4ULL};
+
+uint64 sha512_h0[8] =
+ {0x6a09e667f3bcc908ULL, 0xbb67ae8584caa73bULL,
+ 0x3c6ef372fe94f82bULL, 0xa54ff53a5f1d36f1ULL,
+ 0x510e527fade682d1ULL, 0x9b05688c2b3e6c1fULL,
+ 0x1f83d9abfb41bd6bULL, 0x5be0cd19137e2179ULL};
+
+uint32 sha256_k[64] =
+ {0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5,
+ 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
+ 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
+ 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
+ 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc,
+ 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
+ 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7,
+ 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
+ 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
+ 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
+ 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3,
+ 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
+ 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5,
+ 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
+ 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
+ 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2};
+
+uint64 sha512_k[80] =
+ {0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL,
+ 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
+ 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL,
+ 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
+ 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL,
+ 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
+ 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL,
+ 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
+ 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL,
+ 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
+ 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL,
+ 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
+ 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL,
+ 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
+ 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL,
+ 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
+ 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL,
+ 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
+ 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL,
+ 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
+ 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL,
+ 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
+ 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL,
+ 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
+ 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL,
+ 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
+ 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL,
+ 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
+ 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL,
+ 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
+ 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL,
+ 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
+ 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL,
+ 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
+ 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL,
+ 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
+ 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL,
+ 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
+ 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL,
+ 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL};
+
+/* SHA-256 functions */
+
+void sha256_transf(sha256_ctx *ctx, const unsigned char *message,
+ unsigned int block_nb)
+{
+ uint32 w[64];
+ uint32 wv[8];
+ uint32 t1, t2;
+ const unsigned char *sub_block;
+ int i;
+
+#ifndef UNROLL_LOOPS
+ int j;
+#endif
+
+ for (i = 0; i < (int) block_nb; i++) {
+ sub_block = message + (i << 6);
+
+#ifndef UNROLL_LOOPS
+ for (j = 0; j < 16; j++) {
+ PACK32(&sub_block[j << 2], &w[j]);
+ }
+
+ for (j = 16; j < 64; j++) {
+ SHA256_SCR(j);
+ }
+
+ for (j = 0; j < 8; j++) {
+ wv[j] = ctx->h[j];
+ }
+
+ for (j = 0; j < 64; j++) {
+ t1 = wv[7] + SHA256_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
+ + sha256_k[j] + w[j];
+ t2 = SHA256_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+ wv[7] = wv[6];
+ wv[6] = wv[5];
+ wv[5] = wv[4];
+ wv[4] = wv[3] + t1;
+ wv[3] = wv[2];
+ wv[2] = wv[1];
+ wv[1] = wv[0];
+ wv[0] = t1 + t2;
+ }
+
+ for (j = 0; j < 8; j++) {
+ ctx->h[j] += wv[j];
+ }
+#else
+ PACK32(&sub_block[ 0], &w[ 0]); PACK32(&sub_block[ 4], &w[ 1]);
+ PACK32(&sub_block[ 8], &w[ 2]); PACK32(&sub_block[12], &w[ 3]);
+ PACK32(&sub_block[16], &w[ 4]); PACK32(&sub_block[20], &w[ 5]);
+ PACK32(&sub_block[24], &w[ 6]); PACK32(&sub_block[28], &w[ 7]);
+ PACK32(&sub_block[32], &w[ 8]); PACK32(&sub_block[36], &w[ 9]);
+ PACK32(&sub_block[40], &w[10]); PACK32(&sub_block[44], &w[11]);
+ PACK32(&sub_block[48], &w[12]); PACK32(&sub_block[52], &w[13]);
+ PACK32(&sub_block[56], &w[14]); PACK32(&sub_block[60], &w[15]);
+
+ SHA256_SCR(16); SHA256_SCR(17); SHA256_SCR(18); SHA256_SCR(19);
+ SHA256_SCR(20); SHA256_SCR(21); SHA256_SCR(22); SHA256_SCR(23);
+ SHA256_SCR(24); SHA256_SCR(25); SHA256_SCR(26); SHA256_SCR(27);
+ SHA256_SCR(28); SHA256_SCR(29); SHA256_SCR(30); SHA256_SCR(31);
+ SHA256_SCR(32); SHA256_SCR(33); SHA256_SCR(34); SHA256_SCR(35);
+ SHA256_SCR(36); SHA256_SCR(37); SHA256_SCR(38); SHA256_SCR(39);
+ SHA256_SCR(40); SHA256_SCR(41); SHA256_SCR(42); SHA256_SCR(43);
+ SHA256_SCR(44); SHA256_SCR(45); SHA256_SCR(46); SHA256_SCR(47);
+ SHA256_SCR(48); SHA256_SCR(49); SHA256_SCR(50); SHA256_SCR(51);
+ SHA256_SCR(52); SHA256_SCR(53); SHA256_SCR(54); SHA256_SCR(55);
+ SHA256_SCR(56); SHA256_SCR(57); SHA256_SCR(58); SHA256_SCR(59);
+ SHA256_SCR(60); SHA256_SCR(61); SHA256_SCR(62); SHA256_SCR(63);
+
+ wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
+ wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
+ wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
+ wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
+
+ SHA256_EXP(0,1,2,3,4,5,6,7, 0); SHA256_EXP(7,0,1,2,3,4,5,6, 1);
+ SHA256_EXP(6,7,0,1,2,3,4,5, 2); SHA256_EXP(5,6,7,0,1,2,3,4, 3);
+ SHA256_EXP(4,5,6,7,0,1,2,3, 4); SHA256_EXP(3,4,5,6,7,0,1,2, 5);
+ SHA256_EXP(2,3,4,5,6,7,0,1, 6); SHA256_EXP(1,2,3,4,5,6,7,0, 7);
+ SHA256_EXP(0,1,2,3,4,5,6,7, 8); SHA256_EXP(7,0,1,2,3,4,5,6, 9);
+ SHA256_EXP(6,7,0,1,2,3,4,5,10); SHA256_EXP(5,6,7,0,1,2,3,4,11);
+ SHA256_EXP(4,5,6,7,0,1,2,3,12); SHA256_EXP(3,4,5,6,7,0,1,2,13);
+ SHA256_EXP(2,3,4,5,6,7,0,1,14); SHA256_EXP(1,2,3,4,5,6,7,0,15);
+ SHA256_EXP(0,1,2,3,4,5,6,7,16); SHA256_EXP(7,0,1,2,3,4,5,6,17);
+ SHA256_EXP(6,7,0,1,2,3,4,5,18); SHA256_EXP(5,6,7,0,1,2,3,4,19);
+ SHA256_EXP(4,5,6,7,0,1,2,3,20); SHA256_EXP(3,4,5,6,7,0,1,2,21);
+ SHA256_EXP(2,3,4,5,6,7,0,1,22); SHA256_EXP(1,2,3,4,5,6,7,0,23);
+ SHA256_EXP(0,1,2,3,4,5,6,7,24); SHA256_EXP(7,0,1,2,3,4,5,6,25);
+ SHA256_EXP(6,7,0,1,2,3,4,5,26); SHA256_EXP(5,6,7,0,1,2,3,4,27);
+ SHA256_EXP(4,5,6,7,0,1,2,3,28); SHA256_EXP(3,4,5,6,7,0,1,2,29);
+ SHA256_EXP(2,3,4,5,6,7,0,1,30); SHA256_EXP(1,2,3,4,5,6,7,0,31);
+ SHA256_EXP(0,1,2,3,4,5,6,7,32); SHA256_EXP(7,0,1,2,3,4,5,6,33);
+ SHA256_EXP(6,7,0,1,2,3,4,5,34); SHA256_EXP(5,6,7,0,1,2,3,4,35);
+ SHA256_EXP(4,5,6,7,0,1,2,3,36); SHA256_EXP(3,4,5,6,7,0,1,2,37);
+ SHA256_EXP(2,3,4,5,6,7,0,1,38); SHA256_EXP(1,2,3,4,5,6,7,0,39);
+ SHA256_EXP(0,1,2,3,4,5,6,7,40); SHA256_EXP(7,0,1,2,3,4,5,6,41);
+ SHA256_EXP(6,7,0,1,2,3,4,5,42); SHA256_EXP(5,6,7,0,1,2,3,4,43);
+ SHA256_EXP(4,5,6,7,0,1,2,3,44); SHA256_EXP(3,4,5,6,7,0,1,2,45);
+ SHA256_EXP(2,3,4,5,6,7,0,1,46); SHA256_EXP(1,2,3,4,5,6,7,0,47);
+ SHA256_EXP(0,1,2,3,4,5,6,7,48); SHA256_EXP(7,0,1,2,3,4,5,6,49);
+ SHA256_EXP(6,7,0,1,2,3,4,5,50); SHA256_EXP(5,6,7,0,1,2,3,4,51);
+ SHA256_EXP(4,5,6,7,0,1,2,3,52); SHA256_EXP(3,4,5,6,7,0,1,2,53);
+ SHA256_EXP(2,3,4,5,6,7,0,1,54); SHA256_EXP(1,2,3,4,5,6,7,0,55);
+ SHA256_EXP(0,1,2,3,4,5,6,7,56); SHA256_EXP(7,0,1,2,3,4,5,6,57);
+ SHA256_EXP(6,7,0,1,2,3,4,5,58); SHA256_EXP(5,6,7,0,1,2,3,4,59);
+ SHA256_EXP(4,5,6,7,0,1,2,3,60); SHA256_EXP(3,4,5,6,7,0,1,2,61);
+ SHA256_EXP(2,3,4,5,6,7,0,1,62); SHA256_EXP(1,2,3,4,5,6,7,0,63);
+
+ ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
+ ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
+ ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
+ ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
+#endif /* !UNROLL_LOOPS */
+ }
+}
+
+void sha256(const unsigned char *message, unsigned int len, unsigned char *digest)
+{
+ sha256_ctx ctx;
+
+ sha256_init(&ctx);
+ sha256_update(&ctx, message, len);
+ sha256_final(&ctx, digest);
+}
+
+void sha256_init(sha256_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = sha256_h0[i];
+ }
+#else
+ ctx->h[0] = sha256_h0[0]; ctx->h[1] = sha256_h0[1];
+ ctx->h[2] = sha256_h0[2]; ctx->h[3] = sha256_h0[3];
+ ctx->h[4] = sha256_h0[4]; ctx->h[5] = sha256_h0[5];
+ ctx->h[6] = sha256_h0[6]; ctx->h[7] = sha256_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void sha256_update(sha256_ctx *ctx, const unsigned char *message,
+ unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SHA256_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SHA256_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SHA256_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ sha256_transf(ctx, ctx->block, 1);
+ sha256_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SHA256_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 6],
+ rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 6;
+}
+
+void sha256_final(sha256_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = (1 + ((SHA256_BLOCK_SIZE - 9)
+ < (ctx->len % SHA256_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 6;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ sha256_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0 ; i < 8; i++) {
+ UNPACK32(ctx->h[i], &digest[i << 2]);
+ }
+#else
+ UNPACK32(ctx->h[0], &digest[ 0]);
+ UNPACK32(ctx->h[1], &digest[ 4]);
+ UNPACK32(ctx->h[2], &digest[ 8]);
+ UNPACK32(ctx->h[3], &digest[12]);
+ UNPACK32(ctx->h[4], &digest[16]);
+ UNPACK32(ctx->h[5], &digest[20]);
+ UNPACK32(ctx->h[6], &digest[24]);
+ UNPACK32(ctx->h[7], &digest[28]);
+#endif /* !UNROLL_LOOPS */
+}
+
+/* SHA-512 functions */
+
+void sha512_transf(sha512_ctx *ctx, const unsigned char *message,
+ unsigned int block_nb)
+{
+ uint64 w[80];
+ uint64 wv[8];
+ uint64 t1, t2;
+ const unsigned char *sub_block;
+ int i, j;
+
+ for (i = 0; i < (int) block_nb; i++) {
+ sub_block = message + (i << 7);
+
+#ifndef UNROLL_LOOPS
+ for (j = 0; j < 16; j++) {
+ PACK64(&sub_block[j << 3], &w[j]);
+ }
+
+ for (j = 16; j < 80; j++) {
+ SHA512_SCR(j);
+ }
+
+ for (j = 0; j < 8; j++) {
+ wv[j] = ctx->h[j];
+ }
+
+ for (j = 0; j < 80; j++) {
+ t1 = wv[7] + SHA512_F2(wv[4]) + CH(wv[4], wv[5], wv[6])
+ + sha512_k[j] + w[j];
+ t2 = SHA512_F1(wv[0]) + MAJ(wv[0], wv[1], wv[2]);
+ wv[7] = wv[6];
+ wv[6] = wv[5];
+ wv[5] = wv[4];
+ wv[4] = wv[3] + t1;
+ wv[3] = wv[2];
+ wv[2] = wv[1];
+ wv[1] = wv[0];
+ wv[0] = t1 + t2;
+ }
+
+ for (j = 0; j < 8; j++) {
+ ctx->h[j] += wv[j];
+ }
+#else
+ PACK64(&sub_block[ 0], &w[ 0]); PACK64(&sub_block[ 8], &w[ 1]);
+ PACK64(&sub_block[ 16], &w[ 2]); PACK64(&sub_block[ 24], &w[ 3]);
+ PACK64(&sub_block[ 32], &w[ 4]); PACK64(&sub_block[ 40], &w[ 5]);
+ PACK64(&sub_block[ 48], &w[ 6]); PACK64(&sub_block[ 56], &w[ 7]);
+ PACK64(&sub_block[ 64], &w[ 8]); PACK64(&sub_block[ 72], &w[ 9]);
+ PACK64(&sub_block[ 80], &w[10]); PACK64(&sub_block[ 88], &w[11]);
+ PACK64(&sub_block[ 96], &w[12]); PACK64(&sub_block[104], &w[13]);
+ PACK64(&sub_block[112], &w[14]); PACK64(&sub_block[120], &w[15]);
+
+ SHA512_SCR(16); SHA512_SCR(17); SHA512_SCR(18); SHA512_SCR(19);
+ SHA512_SCR(20); SHA512_SCR(21); SHA512_SCR(22); SHA512_SCR(23);
+ SHA512_SCR(24); SHA512_SCR(25); SHA512_SCR(26); SHA512_SCR(27);
+ SHA512_SCR(28); SHA512_SCR(29); SHA512_SCR(30); SHA512_SCR(31);
+ SHA512_SCR(32); SHA512_SCR(33); SHA512_SCR(34); SHA512_SCR(35);
+ SHA512_SCR(36); SHA512_SCR(37); SHA512_SCR(38); SHA512_SCR(39);
+ SHA512_SCR(40); SHA512_SCR(41); SHA512_SCR(42); SHA512_SCR(43);
+ SHA512_SCR(44); SHA512_SCR(45); SHA512_SCR(46); SHA512_SCR(47);
+ SHA512_SCR(48); SHA512_SCR(49); SHA512_SCR(50); SHA512_SCR(51);
+ SHA512_SCR(52); SHA512_SCR(53); SHA512_SCR(54); SHA512_SCR(55);
+ SHA512_SCR(56); SHA512_SCR(57); SHA512_SCR(58); SHA512_SCR(59);
+ SHA512_SCR(60); SHA512_SCR(61); SHA512_SCR(62); SHA512_SCR(63);
+ SHA512_SCR(64); SHA512_SCR(65); SHA512_SCR(66); SHA512_SCR(67);
+ SHA512_SCR(68); SHA512_SCR(69); SHA512_SCR(70); SHA512_SCR(71);
+ SHA512_SCR(72); SHA512_SCR(73); SHA512_SCR(74); SHA512_SCR(75);
+ SHA512_SCR(76); SHA512_SCR(77); SHA512_SCR(78); SHA512_SCR(79);
+
+ wv[0] = ctx->h[0]; wv[1] = ctx->h[1];
+ wv[2] = ctx->h[2]; wv[3] = ctx->h[3];
+ wv[4] = ctx->h[4]; wv[5] = ctx->h[5];
+ wv[6] = ctx->h[6]; wv[7] = ctx->h[7];
+
+ j = 0;
+
+ do {
+ SHA512_EXP(0,1,2,3,4,5,6,7,j); j++;
+ SHA512_EXP(7,0,1,2,3,4,5,6,j); j++;
+ SHA512_EXP(6,7,0,1,2,3,4,5,j); j++;
+ SHA512_EXP(5,6,7,0,1,2,3,4,j); j++;
+ SHA512_EXP(4,5,6,7,0,1,2,3,j); j++;
+ SHA512_EXP(3,4,5,6,7,0,1,2,j); j++;
+ SHA512_EXP(2,3,4,5,6,7,0,1,j); j++;
+ SHA512_EXP(1,2,3,4,5,6,7,0,j); j++;
+ } while (j < 80);
+
+ ctx->h[0] += wv[0]; ctx->h[1] += wv[1];
+ ctx->h[2] += wv[2]; ctx->h[3] += wv[3];
+ ctx->h[4] += wv[4]; ctx->h[5] += wv[5];
+ ctx->h[6] += wv[6]; ctx->h[7] += wv[7];
+#endif /* !UNROLL_LOOPS */
+ }
+}
+
+void sha512(const unsigned char *message, unsigned int len,
+ unsigned char *digest)
+{
+ sha512_ctx ctx;
+
+ sha512_init(&ctx);
+ sha512_update(&ctx, message, len);
+ sha512_final(&ctx, digest);
+}
+
+void sha512_init(sha512_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = sha512_h0[i];
+ }
+#else
+ ctx->h[0] = sha512_h0[0]; ctx->h[1] = sha512_h0[1];
+ ctx->h[2] = sha512_h0[2]; ctx->h[3] = sha512_h0[3];
+ ctx->h[4] = sha512_h0[4]; ctx->h[5] = sha512_h0[5];
+ ctx->h[6] = sha512_h0[6]; ctx->h[7] = sha512_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void sha512_update(sha512_ctx *ctx, const unsigned char *message,
+ unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SHA512_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SHA512_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SHA512_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ sha512_transf(ctx, ctx->block, 1);
+ sha512_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SHA512_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 7],
+ rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 7;
+}
+
+void sha512_final(sha512_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = 1 + ((SHA512_BLOCK_SIZE - 17)
+ < (ctx->len % SHA512_BLOCK_SIZE));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 7;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ sha512_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0 ; i < 8; i++) {
+ UNPACK64(ctx->h[i], &digest[i << 3]);
+ }
+#else
+ UNPACK64(ctx->h[0], &digest[ 0]);
+ UNPACK64(ctx->h[1], &digest[ 8]);
+ UNPACK64(ctx->h[2], &digest[16]);
+ UNPACK64(ctx->h[3], &digest[24]);
+ UNPACK64(ctx->h[4], &digest[32]);
+ UNPACK64(ctx->h[5], &digest[40]);
+ UNPACK64(ctx->h[6], &digest[48]);
+ UNPACK64(ctx->h[7], &digest[56]);
+#endif /* !UNROLL_LOOPS */
+}
+
+/* SHA-384 functions */
+
+void sha384(const unsigned char *message, unsigned int len,
+ unsigned char *digest)
+{
+ sha384_ctx ctx;
+
+ sha384_init(&ctx);
+ sha384_update(&ctx, message, len);
+ sha384_final(&ctx, digest);
+}
+
+void sha384_init(sha384_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = sha384_h0[i];
+ }
+#else
+ ctx->h[0] = sha384_h0[0]; ctx->h[1] = sha384_h0[1];
+ ctx->h[2] = sha384_h0[2]; ctx->h[3] = sha384_h0[3];
+ ctx->h[4] = sha384_h0[4]; ctx->h[5] = sha384_h0[5];
+ ctx->h[6] = sha384_h0[6]; ctx->h[7] = sha384_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void sha384_update(sha384_ctx *ctx, const unsigned char *message,
+ unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SHA384_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SHA384_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SHA384_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ sha512_transf(ctx, ctx->block, 1);
+ sha512_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SHA384_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 7],
+ rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 7;
+}
+
+void sha384_final(sha384_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = (1 + ((SHA384_BLOCK_SIZE - 17)
+ < (ctx->len % SHA384_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 7;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ sha512_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0 ; i < 6; i++) {
+ UNPACK64(ctx->h[i], &digest[i << 3]);
+ }
+#else
+ UNPACK64(ctx->h[0], &digest[ 0]);
+ UNPACK64(ctx->h[1], &digest[ 8]);
+ UNPACK64(ctx->h[2], &digest[16]);
+ UNPACK64(ctx->h[3], &digest[24]);
+ UNPACK64(ctx->h[4], &digest[32]);
+ UNPACK64(ctx->h[5], &digest[40]);
+#endif /* !UNROLL_LOOPS */
+}
+
+/* SHA-224 functions */
+
+void sha224(const unsigned char *message, unsigned int len,
+ unsigned char *digest)
+{
+ sha224_ctx ctx;
+
+ sha224_init(&ctx);
+ sha224_update(&ctx, message, len);
+ sha224_final(&ctx, digest);
+}
+
+void sha224_init(sha224_ctx *ctx)
+{
+#ifndef UNROLL_LOOPS
+ int i;
+ for (i = 0; i < 8; i++) {
+ ctx->h[i] = sha224_h0[i];
+ }
+#else
+ ctx->h[0] = sha224_h0[0]; ctx->h[1] = sha224_h0[1];
+ ctx->h[2] = sha224_h0[2]; ctx->h[3] = sha224_h0[3];
+ ctx->h[4] = sha224_h0[4]; ctx->h[5] = sha224_h0[5];
+ ctx->h[6] = sha224_h0[6]; ctx->h[7] = sha224_h0[7];
+#endif /* !UNROLL_LOOPS */
+
+ ctx->len = 0;
+ ctx->tot_len = 0;
+}
+
+void sha224_update(sha224_ctx *ctx, const unsigned char *message,
+ unsigned int len)
+{
+ unsigned int block_nb;
+ unsigned int new_len, rem_len, tmp_len;
+ const unsigned char *shifted_message;
+
+ tmp_len = SHA224_BLOCK_SIZE - ctx->len;
+ rem_len = len < tmp_len ? len : tmp_len;
+
+ memcpy(&ctx->block[ctx->len], message, rem_len);
+
+ if (ctx->len + len < SHA224_BLOCK_SIZE) {
+ ctx->len += len;
+ return;
+ }
+
+ new_len = len - rem_len;
+ block_nb = new_len / SHA224_BLOCK_SIZE;
+
+ shifted_message = message + rem_len;
+
+ sha256_transf(ctx, ctx->block, 1);
+ sha256_transf(ctx, shifted_message, block_nb);
+
+ rem_len = new_len % SHA224_BLOCK_SIZE;
+
+ memcpy(ctx->block, &shifted_message[block_nb << 6],
+ rem_len);
+
+ ctx->len = rem_len;
+ ctx->tot_len += (block_nb + 1) << 6;
+}
+
+void sha224_final(sha224_ctx *ctx, unsigned char *digest)
+{
+ unsigned int block_nb;
+ unsigned int pm_len;
+ unsigned int len_b;
+
+#ifndef UNROLL_LOOPS
+ int i;
+#endif
+
+ block_nb = (1 + ((SHA224_BLOCK_SIZE - 9)
+ < (ctx->len % SHA224_BLOCK_SIZE)));
+
+ len_b = (ctx->tot_len + ctx->len) << 3;
+ pm_len = block_nb << 6;
+
+ memset(ctx->block + ctx->len, 0, pm_len - ctx->len);
+ ctx->block[ctx->len] = 0x80;
+ UNPACK32(len_b, ctx->block + pm_len - 4);
+
+ sha256_transf(ctx, ctx->block, block_nb);
+
+#ifndef UNROLL_LOOPS
+ for (i = 0 ; i < 7; i++) {
+ UNPACK32(ctx->h[i], &digest[i << 2]);
+ }
+#else
+ UNPACK32(ctx->h[0], &digest[ 0]);
+ UNPACK32(ctx->h[1], &digest[ 4]);
+ UNPACK32(ctx->h[2], &digest[ 8]);
+ UNPACK32(ctx->h[3], &digest[12]);
+ UNPACK32(ctx->h[4], &digest[16]);
+ UNPACK32(ctx->h[5], &digest[20]);
+ UNPACK32(ctx->h[6], &digest[24]);
+#endif /* !UNROLL_LOOPS */
+}
+
+#ifdef TEST_VECTORS
+
+/* FIPS 180-2 Validation tests */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+void test(const unsigned char *vector, unsigned char *digest,
+ unsigned int digest_size)
+{
+ unsigned char output[2 * SHA512_DIGEST_SIZE + 1];
+ int i;
+
+ output[2 * digest_size] = '\0';
+
+ for (i = 0; i < (int) digest_size ; i++) {
+ sprintf((char *) output + 2 * i, "%02x", digest[i]);
+ }
+
+ printf("H: %s\n", output);
+ if (strcmp((char *) vector, (char *) output)) {
+ fprintf(stderr, "Test failed.\n");
+ exit(EXIT_FAILURE);
+ }
+}
+
+int main()
+{
+ static const unsigned char *vectors[4][3] =
+ { /* SHA-224 */
+ {
+ "23097d223405d8228642a477bda255b32aadbce4bda0b3f7e36c9da7",
+ "75388b16512776cc5dba5da1fd890150b0c6455cb4f58b1952522525",
+ "20794655980c91d8bbb4c1ea97618a4bf03f42581948b2ee4ee7ad67",
+ },
+ /* SHA-256 */
+ {
+ "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad",
+ "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1",
+ "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0",
+ },
+ /* SHA-384 */
+ {
+ "cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed"
+ "8086072ba1e7cc2358baeca134c825a7",
+ "09330c33f71147e83d192fc782cd1b4753111b173b3b05d22fa08086e3b0f712"
+ "fcc7c71a557e2db966c3e9fa91746039",
+ "9d0e1809716474cb086e834e310a4a1ced149e9c00f248527972cec5704c2a5b"
+ "07b8b3dc38ecc4ebae97ddd87f3d8985",
+ },
+ /* SHA-512 */
+ {
+ "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a"
+ "2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f",
+ "8e959b75dae313da8cf4f72814fc143f8f7779c6eb9f7fa17299aeadb6889018"
+ "501d289e4900f7e4331b99dec4b5433ac7d329eeb6dd26545e96e55b874be909",
+ "e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"
+ "de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b"
+ }
+ };
+
+ static const unsigned char message1[] = "abc";
+ static const unsigned char message2a[] = "abcdbcdecdefdefgefghfghighijhi"
+ "jkijkljklmklmnlmnomnopnopq";
+ static const unsigned char message2b[] =
+ "abcdefghbcdefghicdefghijdefghijkefghij"
+ "klfghijklmghijklmnhijklmnoijklmnopjklm"
+ "nopqklmnopqrlmnopqrsmnopqrstnopqrstu";
+ unsigned char *message3;
+ unsigned int message3_len = 1000000;
+ unsigned char digest[SHA512_DIGEST_SIZE];
+
+ message3 = malloc(message3_len);
+ if (message3 == NULL) {
+ fprintf(stderr, "Can't allocate memory\n");
+ return -1;
+ }
+ memset(message3, 'a', message3_len);
+
+ printf("SHA-2 FIPS 180-2 Validation tests\n\n");
+ printf("SHA-224 Test vectors\n");
+
+ sha224(message1, strlen((char *) message1), digest);
+ test(vectors[0][0], digest, SHA224_DIGEST_SIZE);
+ sha224(message2a, strlen((char *) message2a), digest);
+ test(vectors[0][1], digest, SHA224_DIGEST_SIZE);
+ sha224(message3, message3_len, digest);
+ test(vectors[0][2], digest, SHA224_DIGEST_SIZE);
+ printf("\n");
+
+ printf("SHA-256 Test vectors\n");
+
+ sha256(message1, strlen((char *) message1), digest);
+ test(vectors[1][0], digest, SHA256_DIGEST_SIZE);
+ sha256(message2a, strlen((char *) message2a), digest);
+ test(vectors[1][1], digest, SHA256_DIGEST_SIZE);
+ sha256(message3, message3_len, digest);
+ test(vectors[1][2], digest, SHA256_DIGEST_SIZE);
+ printf("\n");
+
+ printf("SHA-384 Test vectors\n");
+
+ sha384(message1, strlen((char *) message1), digest);
+ test(vectors[2][0], digest, SHA384_DIGEST_SIZE);
+ sha384(message2b, strlen((char *) message2b), digest);
+ test(vectors[2][1], digest, SHA384_DIGEST_SIZE);
+ sha384(message3, message3_len, digest);
+ test(vectors[2][2], digest, SHA384_DIGEST_SIZE);
+ printf("\n");
+
+ printf("SHA-512 Test vectors\n");
+
+ sha512(message1, strlen((char *) message1), digest);
+ test(vectors[3][0], digest, SHA512_DIGEST_SIZE);
+ sha512(message2b, strlen((char *) message2b), digest);
+ test(vectors[3][1], digest, SHA512_DIGEST_SIZE);
+ sha512(message3, message3_len, digest);
+ test(vectors[3][2], digest, SHA512_DIGEST_SIZE);
+ printf("\n");
+
+ printf("All tests passed.\n");
+
+ return 0;
+}
+
+#endif /* TEST_VECTORS */
+
diff --git a/src/fetch/sha2.h b/src/fetch/sha2.h
new file mode 100644
index 0000000..60f52e3
--- /dev/null
+++ b/src/fetch/sha2.h
@@ -0,0 +1,108 @@
+/*
+ * FIPS 180-2 SHA-224/256/384/512 implementation
+ * Last update: 02/02/2007
+ * Issue date: 04/30/2005
+ *
+ * Copyright (C) 2005, 2007 Olivier Gay <olivier.gay@a3.epfl.ch>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef SHA2_H
+#define SHA2_H
+
+#define SHA224_DIGEST_SIZE ( 224 / 8)
+#define SHA256_DIGEST_SIZE ( 256 / 8)
+#define SHA384_DIGEST_SIZE ( 384 / 8)
+#define SHA512_DIGEST_SIZE ( 512 / 8)
+
+#define SHA256_BLOCK_SIZE ( 512 / 8)
+#define SHA512_BLOCK_SIZE (1024 / 8)
+#define SHA384_BLOCK_SIZE SHA512_BLOCK_SIZE
+#define SHA224_BLOCK_SIZE SHA256_BLOCK_SIZE
+
+#ifndef SHA2_TYPES
+#define SHA2_TYPES
+typedef unsigned char uint8;
+typedef unsigned int uint32;
+typedef unsigned long long uint64;
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+ unsigned int tot_len;
+ unsigned int len;
+ unsigned char block[2 * SHA256_BLOCK_SIZE];
+ uint32 h[8];
+} sha256_ctx;
+
+typedef struct {
+ unsigned int tot_len;
+ unsigned int len;
+ unsigned char block[2 * SHA512_BLOCK_SIZE];
+ uint64 h[8];
+} sha512_ctx;
+
+typedef sha512_ctx sha384_ctx;
+typedef sha256_ctx sha224_ctx;
+
+void sha224_init(sha224_ctx *ctx);
+void sha224_update(sha224_ctx *ctx, const unsigned char *message,
+ unsigned int len);
+void sha224_final(sha224_ctx *ctx, unsigned char *digest);
+void sha224(const unsigned char *message, unsigned int len,
+ unsigned char *digest);
+
+void sha256_init(sha256_ctx * ctx);
+void sha256_update(sha256_ctx *ctx, const unsigned char *message,
+ unsigned int len);
+void sha256_final(sha256_ctx *ctx, unsigned char *digest);
+void sha256(const unsigned char *message, unsigned int len,
+ unsigned char *digest);
+
+void sha384_init(sha384_ctx *ctx);
+void sha384_update(sha384_ctx *ctx, const unsigned char *message,
+ unsigned int len);
+void sha384_final(sha384_ctx *ctx, unsigned char *digest);
+void sha384(const unsigned char *message, unsigned int len,
+ unsigned char *digest);
+
+void sha512_init(sha512_ctx *ctx);
+void sha512_update(sha512_ctx *ctx, const unsigned char *message,
+ unsigned int len);
+void sha512_final(sha512_ctx *ctx, unsigned char *digest);
+void sha512(const unsigned char *message, unsigned int len,
+ unsigned char *digest);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !SHA2_H */
+
diff --git a/src/fetch/z3950-servers.cfg b/src/fetch/z3950-servers.cfg
index f4f6157..b30b661 100644
--- a/src/fetch/z3950-servers.cfg
+++ b/src/fetch/z3950-servers.cfg
@@ -43,9 +43,9 @@ Locale=it
Syntax=unimarc
[porbase]
-Host=z3950.bn.pt
+Host=z3950.porbase.org
Port=210
-Database=bnd
+Database=Default
Name=Portuguese National Library
Charset=iso-8859-1
Locale=pt
diff --git a/src/fetch/z3950fetcher.cpp b/src/fetch/z3950fetcher.cpp
index 7e70aa4..bd517ae 100644
--- a/src/fetch/z3950fetcher.cpp
+++ b/src/fetch/z3950fetcher.cpp
@@ -175,13 +175,13 @@ void Z3950Fetcher::search(FetchKey key_, const TQString& value_) {
isbnList.insert(it, isbn10);
}
}
- const int count = isbnList.count();
+ const size_t count = isbnList.count();
if(count > 1) {
m_pqn = TQString::fromLatin1("@or ");
}
- for(int i = 0; i < count; ++i) {
+ for(size_t i = 0; i < count; ++i) {
m_pqn += TQString::fromLatin1(" @attr 1=7 ") + isbnList[i];
- if(i < count-2) {
+ if(count > 1 && i < count-2) {
m_pqn += TQString::fromLatin1(" @or");
}
}
diff --git a/src/fetchdialog.cpp b/src/fetchdialog.cpp
index ab9d91b..9586b13 100644
--- a/src/fetchdialog.cpp
+++ b/src/fetchdialog.cpp
@@ -591,6 +591,10 @@ void FetchDialog::slotMultipleISBN(bool toggle_) {
m_valueLineEdit->setText(val);
}
m_editISBN->setEnabled(toggle_);
+ if(toggle_) {
+ // if we're editing multiple values, it makes sense to popup the dialog now
+ slotEditMultipleISBN();
+ }
}
void FetchDialog::slotEditMultipleISBN() {
diff --git a/src/field.cpp b/src/field.cpp
index 4ad2fa7..793de90 100644
--- a/src/field.cpp
+++ b/src/field.cpp
@@ -32,6 +32,7 @@ namespace {
using Tellico::Data::Field;
//these get overwritten, but are here since they're static
+TQStringList Field::s_articles;
TQStringList Field::s_articlesApos;
TQRegExp Field::s_delimiter = TQRegExp(TQString::fromLatin1("\\s*;\\s*"));
@@ -171,7 +172,7 @@ const TQString& Field::defaultValue() const {
}
void Field::setDefaultValue(const TQString& value_) {
- if(m_type != Choice || m_allowed.findIndex(value_) > -1) {
+ if(value_.isEmpty() || m_type != Choice || m_allowed.findIndex(value_) > -1) {
setProperty(TQString::fromLatin1("default"), value_);
}
}
@@ -260,8 +261,7 @@ TQString Field::formatTitle(const TQString& title_) {
if(Config::autoFormat()) {
const TQString lower = newTitle.lower();
// TODO if the title has ",the" at the end, put it at the front
- const TQStringList& articles = Config::articleList();
- for(TQStringList::ConstIterator it = articles.begin(); it != articles.end(); ++it) {
+ for(TQStringList::ConstIterator it = s_articles.constBegin(); it != s_articles.constEnd(); ++it) {
// assume white space is already stripped
// the articles are already in lower-case
if(lower.startsWith(*it + TQChar(' '))) {
@@ -415,7 +415,7 @@ TQString Field::capitalize(TQString str_) {
TQString word = str_.mid(0, pos);
// now check to see if words starts with apostrophe list
- for(TQStringList::ConstIterator it = s_articlesApos.begin(); it != s_articlesApos.end(); ++it) {
+ for(TQStringList::ConstIterator it = s_articlesApos.constBegin(); it != s_articlesApos.constEnd(); ++it) {
if(word.lower().startsWith(*it)) {
uint l = (*it).length();
str_.replace(l, 1, str_.at(l).upper());
@@ -432,7 +432,7 @@ TQString Field::capitalize(TQString str_) {
word = str_.mid(pos+1, nextPos-pos-1);
bool aposMatch = false;
// now check to see if words starts with apostrophe list
- for(TQStringList::ConstIterator it = s_articlesApos.begin(); it != s_articlesApos.end(); ++it) {
+ for(TQStringList::ConstIterator it = s_articlesApos.constBegin(); it != s_articlesApos.constEnd(); ++it) {
if(word.lower().startsWith(*it)) {
uint l = (*it).length();
str_.replace(pos+l+1, 1, str_.at(pos+l+1).upper());
@@ -455,8 +455,7 @@ TQString Field::capitalize(TQString str_) {
TQString Field::sortKeyTitle(const TQString& title_) {
const TQString lower = title_.lower();
- const TQStringList& articles = Config::articleList();
- for(TQStringList::ConstIterator it = articles.begin(); it != articles.end(); ++it) {
+ for(TQStringList::ConstIterator it = s_articles.constBegin(); it != s_articles.constEnd(); ++it) {
// assume white space is already stripped
// the articles are already in lower-case
if(lower.startsWith(*it + TQChar(' '))) {
@@ -464,7 +463,7 @@ TQString Field::sortKeyTitle(const TQString& title_) {
}
}
// check apostrophes, too
- for(TQStringList::ConstIterator it = s_articlesApos.begin(); it != s_articlesApos.end(); ++it) {
+ for(TQStringList::ConstIterator it = s_articlesApos.constBegin(); it != s_articlesApos.constEnd(); ++it) {
if(lower.startsWith(*it)) {
return title_.mid((*it).length());
}
@@ -474,9 +473,9 @@ TQString Field::sortKeyTitle(const TQString& title_) {
// articles should all be in lower-case
void Field::articlesUpdated() {
- const TQStringList articles = Config::articleList();
+ s_articles = Config::articleList();
s_articlesApos.clear();
- for(TQStringList::ConstIterator it = articles.begin(); it != articles.end(); ++it) {
+ for(TQStringList::ConstIterator it = s_articles.constBegin(); it != s_articles.constEnd(); ++it) {
if((*it).endsWith(TQChar('\''))) {
s_articlesApos += (*it);
}
@@ -581,11 +580,10 @@ long Field::getID() {
}
void Field::stripArticles(TQString& value) {
- const TQStringList articles = Config::articleList();
- if(articles.isEmpty()) {
+ if(s_articles.isEmpty()) {
return;
}
- for(TQStringList::ConstIterator it = articles.begin(); it != articles.end(); ++it) {
+ for(TQStringList::ConstIterator it = s_articles.constBegin(); it != s_articles.constEnd(); ++it) {
TQRegExp rx(TQString::fromLatin1("\\b") + *it + TQString::fromLatin1("\\b"));
value.remove(rx);
}
diff --git a/src/field.h b/src/field.h
index f0b591a..c271705 100644
--- a/src/field.h
+++ b/src/field.h
@@ -385,6 +385,7 @@ private:
FormatFlag m_formatFlag;
StringMap m_properties;
+ static TQStringList s_articles;
// need to remember articles with apostrophes for capitalization
static TQStringList s_articlesApos;
static TQRegExp s_delimiter;
diff --git a/src/gui/counteditem.h b/src/gui/counteditem.h
index 3aff0b7..4275696 100644
--- a/src/gui/counteditem.h
+++ b/src/gui/counteditem.h
@@ -39,8 +39,8 @@ public:
int column, int width, int align);
virtual int width(const TQFontMetrics& fm, const TQListView* lv, int c) const;
- virtual int count() const { return childCount(); }
- virtual int realChildCount() const { return count(); }
+ virtual size_t count() const { return childCount(); }
+ virtual size_t realChildCount() const { return count(); }
};
} // end namespace
diff --git a/src/gui/listview.h b/src/gui/listview.h
index ccb0867..5e1137b 100644
--- a/src/gui/listview.h
+++ b/src/gui/listview.h
@@ -139,7 +139,7 @@ public:
ListViewItem(ListViewItem* parent, const TQString& text) : TDEListViewItem(parent, text), m_sortWeight(-1) {}
virtual ~ListViewItem();
- virtual int realChildCount() const { return childCount(); }
+ virtual size_t realChildCount() const { return childCount(); }
virtual void clear();
virtual bool isEntryGroupItem() const { return false; }
diff --git a/src/gui/tabcontrol.cpp b/src/gui/tabcontrol.cpp
index f3c2bf2..92afec6 100644
--- a/src/gui/tabcontrol.cpp
+++ b/src/gui/tabcontrol.cpp
@@ -29,6 +29,9 @@ TQTabBar* TabControl::tabBar() const {
void TabControl::setFocusToFirstChild() {
TQWidget* page = currentPage();
Q_ASSERT(page);
+ if(!page) {
+ return;
+ }
TQObjectList* list = page->queryList(TQWIDGET_OBJECT_NAME_STRING);
for(TQObjectListIt it(*list); it.current(); ++it) {
TQWidget* w = TQT_TQWIDGET(it.current());
diff --git a/src/image.cpp b/src/image.cpp
index 8cb6fa4..cc015ae 100644
--- a/src/image.cpp
+++ b/src/image.cpp
@@ -14,6 +14,7 @@
#include "image.h"
#include "imagefactory.h"
#include "tellico_debug.h"
+#include "tellico_utils.h"
#include <kmdcodec.h>
#include <kpixmapio.h>
@@ -105,7 +106,7 @@ TQByteArray Image::byteArray(const TQImage& img_, const TQCString& outputFormat_
TQString Image::idClean(const TQString& id_) {
static const TQRegExp rx('[' + TQRegExp::escape(TQString::fromLatin1("/@<>#\"&%?={}|^~[]'`\\:+")) + ']');
TQString clean = id_;
- return clean.remove(rx);
+ return shareString(clean.remove(rx));
}
void Image::setID(const TQString& id_) {
diff --git a/src/imagefactory.cpp b/src/imagefactory.cpp
index 574b199..0cc6acb 100644
--- a/src/imagefactory.cpp
+++ b/src/imagefactory.cpp
@@ -316,7 +316,7 @@ bool ImageFactory::writeCachedImage(const TQString& id_, CacheDir dir_, bool for
const Tellico::Data::Image& ImageFactory::imageById(const TQString& id_) {
if(id_.isEmpty()) {
- myDebug() << "ImageFactory::imageById() - empty id" << endl;
+// myDebug() << "ImageFactory::imageById() - empty id" << endl;
return s_null;
}
// myLog() << "ImageFactory::imageById() - " << id_ << endl;
@@ -348,7 +348,7 @@ const Tellico::Data::Image& ImageFactory::imageById(const TQString& id_) {
if((s_imageInfoMap.contains(id_) && s_imageInfoMap[id_].linkOnly) || !KURL::isRelativeURL(id_)) {
KURL u = id_;
if(u.isValid()) {
- return addImageImpl(u, false, KURL(), true);
+ return addImageImpl(u, true, KURL(), true);
}
}
@@ -385,43 +385,53 @@ const Tellico::Data::Image& ImageFactory::imageById(const TQString& id_) {
}
}
- // don't check Config::writeImagesInFile(), someday we might have problems
- // and the image will exist in the data dir, but the app thinks everything should
- // be in the zip file instead
- bool exists = TQFile::exists(dataDir() + id_);
- if(exists) {
- // if we're loading from the application data dir, but images are being saved in the
- // data file instead, then consider the document to be modified since it needs
- // the image saved
- if(Config::imageLocation() != Config::ImagesInAppDir) {
+ if(Config::imageLocation() == Config::ImagesInLocalDir) {
+ bool exists = TQFile::exists(localDir() + id_);
+ if(exists) {
+ const Data::Image& img2 = addCachedImageImpl(id_, LocalDir);
+ if(img2.isNull()) {
+ myDebug() << "ImageFactory::imageById() - tried to add from LocalDir, but failed: " << id_ << endl;
+ } else {
+// myLog() << "...imageById() - found in local dir" << endl;
+ return img2;
+ }
+ }
+ // not an else statement, it might be null
+ if(TQFile::exists(dataDir() + id_)) {
+ // the img is in the other location
+ // consider the document to be modified since it needs the image saved
Data::Document::self()->slotSetModified(true);
+ const Data::Image& img2 = addCachedImageImpl(id_, DataDir);
+ if(img2.isNull()) {
+ myDebug() << "ImageFactory::imageById() - tried to add from DataDir, but failed: " << id_ << endl;
+ } else {
+// myLog() << "...imageById() - found in data dir" << endl;
+ return img2;
+ }
}
- const Data::Image& img2 = addCachedImageImpl(id_, DataDir);
- if(img2.isNull()) {
- myDebug() << "ImageFactory::imageById() - tried to add from DataDir, but failed: " << id_ << endl;
- } else {
-// myLog() << "...imageById() - found in data dir" << endl;
- return img2;
+ } else if(Config::imageLocation() == Config::ImagesInAppDir) {
+ bool exists = TQFile::exists(dataDir() + id_);
+ if(exists) {
+ const Data::Image& img2 = addCachedImageImpl(id_, DataDir);
+ if(img2.isNull()) {
+ myDebug() << "ImageFactory::imageById() - tried to add from DataDir, but failed: " << id_ << endl;
+ } else {
+// myLog() << "...imageById() - found in data dir" << endl;
+ return img2;
+ }
}
- }
- // if localDir() == DataDir(), then there's nothing left to check
- if(localDir() == dataDir()) {
- return s_null;
- }
- exists = TQFile::exists(localDir() + id_);
- if(exists) {
- // if we're loading from the application data dir, but images are being saved in the
- // data file instead, then consider the document to be modified since it needs
- // the image saved
- if(Config::imageLocation() != Config::ImagesInLocalDir) {
+ // not an else statement, it might be null
+ if(TQFile::exists(localDir() + id_)) {
+ // the img is in the other location
+ // consider the document to be modified since it needs the image saved
Data::Document::self()->slotSetModified(true);
- }
- const Data::Image& img2 = addCachedImageImpl(id_, LocalDir);
- if(img2.isNull()) {
- myDebug() << "ImageFactory::imageById() - tried to add from LocalDir, but failed: " << id_ << endl;
- } else {
-// myLog() << "...imageById() - found in data dir" << endl;
- return img2;
+ const Data::Image& img2 = addCachedImageImpl(id_, LocalDir);
+ if(img2.isNull()) {
+ myDebug() << "ImageFactory::imageById() - tried to add from LocalDir, but failed: " << id_ << endl;
+ } else {
+// myLog() << "...imageById() - found in local dir" << endl;
+ return img2;
+ }
}
}
myDebug() << "***ImageFactory::imageById() - not found: " << id_ << endl;
diff --git a/src/isbnvalidator.cpp b/src/isbnvalidator.cpp
index 4832cdd..d6ae49f 100644
--- a/src/isbnvalidator.cpp
+++ b/src/isbnvalidator.cpp
@@ -12,6 +12,7 @@
***************************************************************************/
#include "isbnvalidator.h"
+#include "upcvalidator.h"
#include "tellico_debug.h"
using Tellico::ISBNValidator;
@@ -58,6 +59,13 @@ ISBNValidator::ISBNValidator(TQObject* parent_, const char* name_/*=0*/)
}
TQValidator::State ISBNValidator::validate(TQString& input_, int& pos_) const {
+ // check if it's a cuecat first
+ State catState = CueCat::decode(input_);
+ if(catState != Invalid) {
+ pos_ = input_.length();
+ return catState;
+ }
+
if(input_.startsWith(TQString::fromLatin1("978")) ||
input_.startsWith(TQString::fromLatin1("979"))) {
return validate13(input_, pos_);
diff --git a/src/lccnvalidator.cpp b/src/lccnvalidator.cpp
index cf0e850..b177d55 100644
--- a/src/lccnvalidator.cpp
+++ b/src/lccnvalidator.cpp
@@ -65,7 +65,7 @@ TQString LCCNValidator::formalize(const TQString& value_) {
// now check for non digits in the serial
pos = 0;
- for( ; pos < serial.length() && serial.at(pos).isNumber(); ++pos) { ; }
+ for( ; pos < static_cast<int>(serial.length()) && serial.at(pos).isNumber(); ++pos) { ; }
TQString suffix = serial.mid(pos);
serial = serial.left(pos);
// serial must be left-padded with zeros to 6 characters
diff --git a/src/listviewcomparison.cpp b/src/listviewcomparison.cpp
index b78de94..c03d402 100644
--- a/src/listviewcomparison.cpp
+++ b/src/listviewcomparison.cpp
@@ -48,6 +48,8 @@ Tellico::ListViewComparison* Tellico::ListViewComparison::create(Data::ConstFiel
return new DependentComparison(field_);
} else if(field_->type() == Data::Field::Date || field_->formatFlag() == Data::Field::FormatDate) {
return new ISODateComparison(field_);
+ } else if(field_->type() == Data::Field::Choice) {
+ return new ChoiceComparison(field_);
} else if(field_->formatFlag() == Data::Field::FormatTitle) {
// Dependent could be title, so put this test after
return new TitleComparison(field_);
@@ -277,3 +279,11 @@ int Tellico::ISODateComparison::compare(const TQString& str1, const TQString& st
}
return 0;
}
+
+Tellico::ChoiceComparison::ChoiceComparison(Data::ConstFieldPtr field) : ListViewComparison(field) {
+ m_values = field->allowed();
+}
+
+int Tellico::ChoiceComparison::compare(const TQString& str1, const TQString& str2) {
+ return m_values.findIndex(str1) - m_values.findIndex(str2);
+}
diff --git a/src/listviewcomparison.h b/src/listviewcomparison.h
index 28a3878..3615df4 100644
--- a/src/listviewcomparison.h
+++ b/src/listviewcomparison.h
@@ -112,5 +112,16 @@ protected:
virtual int compare(const TQString& str1, const TQString& str2);
};
+class ChoiceComparison : public ListViewComparison {
+public:
+ ChoiceComparison(Data::ConstFieldPtr field);
+
+protected:
+ virtual int compare(const TQString& str1, const TQString& str2);
+
+private:
+ TQStringList m_values;
+};
+
}
#endif
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 74451ac..54aac95 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -336,7 +336,7 @@ void MainWindow::initActions() {
action = new TDEAction(actionCollection(), "file_import_csv");
action->setText(i18n("Import CSV Data..."));
action->setToolTip(i18n("Import a CSV file"));
- action->setIcon(MIME_ICON("text/x-csv"));
+ action->setIcon(MIME_ICON("text/csv"));
importMenu->insert(action);
connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map()));
importMapper->setMapping(action, Import::CSV);
@@ -506,7 +506,7 @@ void MainWindow::initActions() {
action = new TDEAction(actionCollection(), "file_export_csv");
action->setText(i18n("Export to CSV..."));
action->setToolTip(i18n("Export to a comma-separated values file"));
- action->setIcon(MIME_ICON("text/x-csv"));
+ action->setIcon(MIME_ICON("text/csv"));
exportMenu->insert(action);
connect(action, TQT_SIGNAL(activated()), exportMapper, TQT_SLOT(map()));
exportMapper->setMapping(action, Export::CSV);
@@ -750,6 +750,7 @@ void MainWindow::initActions() {
// want to update every time the filter text changes
connect(m_quickFilter, TQT_SIGNAL(textChanged(const TQString&)),
TQT_TQOBJECT(this), TQT_SLOT(slotQueueFilter()));
+ m_quickFilter->installEventFilter(this); // intercept keyEvents
KWidgetAction* wAction = new KWidgetAction(m_quickFilter, i18n("Filter"), 0, 0, 0,
actionCollection(), "quick_filter");
@@ -907,12 +908,12 @@ void MainWindow::saveOptions() {
Config::setGroupViewSortAscending(m_groupView->ascendingSort());
if(m_loanView) {
- Config::setLoanViewSortAscending(m_loanView->sortStyle()); // ok to use SortColumn key, save semantics
+ Config::setLoanViewSortColumn(m_loanView->sortStyle()); // ok to use SortColumn key, save semantics
Config::setLoanViewSortAscending(m_loanView->ascendingSort());
}
if(m_filterView) {
- Config::setFilterViewSortAscending(m_filterView->sortStyle()); // ok to use SortColumn key, save semantics
+ Config::setFilterViewSortColumn(m_filterView->sortStyle()); // ok to use SortColumn key, save semantics
Config::setFilterViewSortAscending(m_filterView->ascendingSort());
}
@@ -991,7 +992,7 @@ void MainWindow::saveCollectionOptions(Data::CollPtr coll_) {
configIndex = i;
}
}
- uint limit = TQMIN(urls.count(), Config::maxCustomURLSettings());
+ size_t limit = TQMIN(urls.count(), Config::maxCustomURLSettings());
for(uint i = 0; i < limit; ++i) {
config.writeEntry(TQString::fromLatin1("URL_%1").arg(i), urls[i].url());
config.writeEntry(TQString::fromLatin1("Group By_%1").arg(i), groupBys[i]);
@@ -1531,11 +1532,11 @@ void MainWindow::slotEntryCount() {
return;
}
- int count = coll->entryCount();
+ size_t count = coll->entryCount();
TQString text = i18n("Total entries: %1").arg(count);
- int selectCount = Controller::self()->selectedEntries().count();
- int filterCount = m_detailedView->visibleItems();
+ size_t selectCount = Controller::self()->selectedEntries().count();
+ size_t filterCount = m_detailedView->visibleItems();
// if more than one book is selected, add the number of selected books
if(filterCount < count && selectCount > 1) {
text += TQChar(' ');
@@ -1848,6 +1849,10 @@ void MainWindow::setFilter(const TQString& text_) {
// if it isn't valid, hold off on applying the filter
TQRegExp tx(text);
if(!tx.isValid()) {
+ text = TQRegExp::escape(text);
+ tx.setPattern(text);
+ }
+ if(!tx.isValid()) {
myDebug() << "MainWindow::slotUpdateFilter() - invalid regexp: " << text << endl;
return;
}
@@ -2389,4 +2394,15 @@ void MainWindow::slotURLAction(const KURL& url_) {
}
}
+bool MainWindow::eventFilter(TQObject* obj_, TQEvent* ev_) {
+ if(ev_->type() == TQEvent::KeyPress && obj_ == m_quickFilter) {
+ switch(static_cast<TQKeyEvent*>(ev_)->key()) {
+ case TQt::Key_Escape:
+ m_quickFilter->clear();
+ return true;
+ }
+ }
+ return false;
+}
+
#include "mainwindow.moc"
diff --git a/src/mainwindow.h b/src/mainwindow.h
index 6b790e1..535085c 100644
--- a/src/mainwindow.h
+++ b/src/mainwindow.h
@@ -123,6 +123,8 @@ public:
virtual void setFilter(const TQString& text);
virtual bool showEntry(long id);
+ bool eventFilter(TQObject* watched, TQEvent* event);
+
public slots:
/**
* Initializes some stuff after the object is created.
diff --git a/src/reportdialog.cpp b/src/reportdialog.cpp
index c47766e..6f6533a 100644
--- a/src/reportdialog.cpp
+++ b/src/reportdialog.cpp
@@ -197,7 +197,7 @@ void ReportDialog::slotSaveAs() {
if(!u.isEmpty() && u.isValid()) {
TDEConfigGroup config(TDEGlobal::config(), "ExportOptions");
bool encode = config.readBoolEntry("EncodeUTF8", true);
- int oldOpt = m_exporter->options();
+ long oldOpt = m_exporter->options();
// turn utf8 off
long options = oldOpt & ~Export::ExportUTF8;
diff --git a/src/tellico_debug.h b/src/tellico_debug.h
index ea65518..08a4912 100644
--- a/src/tellico_debug.h
+++ b/src/tellico_debug.h
@@ -22,7 +22,7 @@
// std::clock_t
#include <ctime>
-// linux has __GNUC_PREREQ, NetBSD has __GNUC_PREQ__
+// linux has __GNUC_PREREQ, NetBSD has __GNUC_PREREQ__
#if defined(__GNUC_PREREQ) && !defined(__GNUC_PREREQ__)
#define __GNUC_PREREQ__ __GNUC_PREREQ
#endif
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index a0cdd59..3dc9d98 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -16,7 +16,7 @@ METASOURCES = AUTO
DISTCLEANFILES = *~ *.Po $(CLEANFILES)
isbntest_SOURCES = isbntest.cpp
-isbntest_LDADD = ../isbnvalidator.o $(LIB_QT) $(LIB_TDECORE) $(LIB_TDEUI)
+isbntest_LDADD = ../isbnvalidator.o ../upcvalidator.o $(LIB_QT) $(LIB_TDECORE) $(LIB_TDEUI)
latin1test_SOURCES = latin1test.cpp
latin1test_LDADD = $(LIB_QT) $(LIB_TDECORE)
diff --git a/src/translators/Makefile.am b/src/translators/Makefile.am
index fbbb11b..f0e8520 100644
--- a/src/translators/Makefile.am
+++ b/src/translators/Makefile.am
@@ -12,9 +12,9 @@ libtranslators_a_SOURCES = alexandriaexporter.cpp alexandriaimporter.cpp \
filelistingimporter.cpp freedb_util.cpp freedbimporter.cpp gcfilmsexporter.cpp \
gcfilmsimporter.cpp griffithimporter.cpp grs1importer.cpp htmlexporter.cpp libcsv.c \
onixexporter.cpp pdfimporter.cpp pilotdbexporter.cpp referencerimporter.cpp \
- risimporter.cpp tellico_xml.cpp tellicoimporter.cpp tellicoxmlexporter.cpp \
- tellicozipexporter.cpp textimporter.cpp xmlimporter.cpp xsltexporter.cpp xslthandler.cpp \
- xsltimporter.cpp
+ risimporter.cpp tellico_xml.cpp tellicoimporter.cpp tellicosaximporter.cpp \
+ tellicoxmlexporter.cpp tellicoxmlhandler.cpp tellicozipexporter.cpp textimporter.cpp \
+ xmlimporter.cpp xmlstatehandler.cpp xsltexporter.cpp xslthandler.cpp xsltimporter.cpp
if !USE_LIBBTPARSE
SUBDIR_LIBBTPARSE = btparse
@@ -51,7 +51,10 @@ dcimporter.h dcimporter.cpp griffithimporter.h \
griffithimporter.cpp griffith2tellico.py pdfimporter.h \
pdfimporter.cpp referencerimporter.h referencerimporter.cpp \
libcsv.h libcsv.c \
-deliciousimporter.h deliciousimporter.cpp
+deliciousimporter.h deliciousimporter.cpp \
+tellicosaximporter.h tellicosaximporter.cpp \
+tellicoxmlhandler.h tellicoxmlhandler.cpp \
+xmlstatehandler.h xmlstatehandler.cpp
####### tdevelop will overwrite this part!!! (end)############
@@ -68,3 +71,4 @@ KDE_OPTIONS = noautodist
appdir = $(kde_datadir)/tellico
app_DATA = bibtex-translation.xml
app_SCRIPTS = griffith2tellico.py
+
diff --git a/src/translators/alexandriaexporter.cpp b/src/translators/alexandriaexporter.cpp
index de64fbb..633864f 100644
--- a/src/translators/alexandriaexporter.cpp
+++ b/src/translators/alexandriaexporter.cpp
@@ -77,7 +77,7 @@ bool AlexandriaExporter::exec() {
ProgressItem& item = ProgressManager::self()->newProgressItem(this, TQString(), false);
item.setTotalSteps(entries().count());
ProgressItem::Done done(this);
- const uint stepSize = TQMIN(1, entries().count()/100);
+ const uint stepSize = TQMAX(1, entries().count()/100);
const bool showProgress = options() & ExportProgress;
GUI::CursorSaver cs;
diff --git a/src/translators/bibteximporter.cpp b/src/translators/bibteximporter.cpp
index fb52f95..d3668d4 100644
--- a/src/translators/bibteximporter.cpp
+++ b/src/translators/bibteximporter.cpp
@@ -308,5 +308,47 @@ TQWidget* BibtexImporter::widget(TQWidget* parent_, const char* name_/*=0*/) {
return m_widget;
}
+bool BibtexImporter::maybeBibtex(const KURL& url_) {
+ TQString text = FileHandler::readTextFile(url_, true /*quiet*/);
+ if(text.isEmpty()) {
+ return false;
+ }
+
+ bt_initialize();
+ TQRegExp rx(TQString::fromLatin1("[{}]"));
+
+ ushort bt_options = 0; // ushort is defined in btparse.h
+ boolean ok; // boolean is defined in btparse.h as an int
+ bool foundOne = false;
+ int brace = 0;
+ int startpos = 0;
+ int pos = text.find(rx, 0);
+ while(pos > 0) {
+ if(text[pos] == '{') {
+ ++brace;
+ } else if(text[pos] == '}' && brace > 0) {
+ --brace;
+ }
+ if(brace == 0) {
+ TQString entry = text.mid(startpos, pos-startpos+1).stripWhiteSpace();
+ // All the downstream text processing on the AST node will assume utf-8
+ AST* node = bt_parse_entry_s(const_cast<char*>(entry.utf8().data()),
+ const_cast<char*>(url_.fileName().local8Bit().data()),
+ 0, bt_options, &ok);
+ if(ok && node) {
+ foundOne = true;
+ break;
+ }
+ startpos = pos+1;
+ }
+ pos = text.find(rx, pos+1);
+ }
+ if(foundOne) {
+ // clean up some structures
+ bt_parse_entry_s(0, 0, 1, 0, 0);
+ }
+ bt_cleanup();
+ return foundOne;
+}
#include "bibteximporter.moc"
diff --git a/src/translators/bibteximporter.h b/src/translators/bibteximporter.h
index 6d1b878..09e1ec3 100644
--- a/src/translators/bibteximporter.h
+++ b/src/translators/bibteximporter.h
@@ -67,6 +67,8 @@ public:
virtual TQWidget* widget(TQWidget* parent, const char* name=0);
virtual bool canImport(int type) const;
+ static bool maybeBibtex(const KURL& url);
+
public slots:
void slotCancel();
diff --git a/src/translators/csvimporter.cpp b/src/translators/csvimporter.cpp
index 8a53ff9..d6198d0 100644
--- a/src/translators/csvimporter.cpp
+++ b/src/translators/csvimporter.cpp
@@ -50,15 +50,26 @@ extern "C" {
using Tellico::Import::CSVImporter;
+typedef int(*SpaceFunc)(char);
+
static void writeToken(char* buffer, size_t len, void* data);
static void writeRow(char buffer, void* data);
+static int isSpace(char c);
+static int isSpaceOrTab(char c);
+static int isTab(char c);
class CSVImporter::Parser {
public:
Parser(const TQString& str) : stream(new TQTextIStream(&str)) { csv_init(&parser, 0); }
~Parser() { csv_free(parser); delete stream; stream = 0; }
- void setDelimiter(const TQString& s) { Q_ASSERT(s.length() == 1); csv_set_delim(parser, s[0].latin1()); }
+ void setDelimiter(const TQString& s) {
+ Q_ASSERT(s.length() == 1);
+ csv_set_delim(parser, s[0].latin1());
+ if(s[0] == '\t') csv_set_space_func(parser, isSpace);
+ else if(s[0] == ' ') csv_set_space_func(parser, isTab);
+ else csv_set_space_func(parser, isSpaceOrTab);
+ }
void reset(const TQString& str) { delete stream; stream = new TQTextIStream(&str); };
bool hasNext() { return !stream->atEnd(); }
void skipLine() { stream->readLine(); }
@@ -95,6 +106,21 @@ static void writeRow(char c, void* data) {
p->setRowDone(true);
}
+static int isSpace(char c) {
+ if (c == CSV_SPACE) return 1;
+ return 0;
+}
+
+static int isSpaceOrTab(char c) {
+ if (c == CSV_SPACE || c == CSV_TAB) return 1;
+ return 0;
+}
+
+static int isTab(char c) {
+ if (c == CSV_TAB) return 1;
+ return 0;
+}
+
CSVImporter::CSVImporter(const KURL& url_) : Tellico::Import::TextImporter(url_),
m_coll(0),
m_existingCollection(0),
diff --git a/src/translators/deliciousimporter.cpp b/src/translators/deliciousimporter.cpp
index a82c006..be6fe3e 100644
--- a/src/translators/deliciousimporter.cpp
+++ b/src/translators/deliciousimporter.cpp
@@ -35,7 +35,9 @@ DeliciousImporter::DeliciousImporter(const KURL& url_) : XSLTImporter(url_) {
}
bool DeliciousImporter::canImport(int type) const {
- return type == Data::Collection::Book;
+ return type == Data::Collection::Book ||
+ type == Data::Collection::Video ||
+ type == Data::Collection::Game;
}
Tellico::Data::CollPtr DeliciousImporter::collection() {
@@ -51,7 +53,18 @@ Tellico::Data::CollPtr DeliciousImporter::collection() {
<< TQString::fromLatin1("Medium Covers/")
<< TQString::fromLatin1("Small Covers/")
<< TQString::fromLatin1("Plain Covers/");
- const TQString commField = TQString::fromLatin1("comments");
+ TQString commField;
+ switch(coll->type()) {
+ case Data::Collection::Book:
+ commField = TQString::fromLatin1("comments"); break;
+ case Data::Collection::Video:
+ commField = TQString::fromLatin1("plot"); break;
+ case Data::Collection::Game:
+ commField = TQString::fromLatin1("description"); break;
+ default:
+ myWarning() << "bad collection type:" << coll->type() << endl;
+ }
+
const TQString uuidField = TQString::fromLatin1("uuid");
const TQString coverField = TQString::fromLatin1("cover");
const bool isLocal = url().isLocalFile();
diff --git a/src/translators/freedb_util.cpp b/src/translators/freedb_util.cpp
index 07292af..2a2e5ed 100644
--- a/src/translators/freedb_util.cpp
+++ b/src/translators/freedb_util.cpp
@@ -365,7 +365,7 @@ FreeDBImporter::CDText FreeDBImporter::getCDText(const TQCString& drive_) {
}
}
if(cdtext.trackTitles.size() != cdtext.trackArtists.size()) {
- int size = TQMAX(cdtext.trackTitles.size(), cdtext.trackArtists.size());
+ size_t size = TQMAX(cdtext.trackTitles.size(), cdtext.trackArtists.size());
cdtext.trackTitles.resize(size);
cdtext.trackArtists.resize(size);
}
diff --git a/src/translators/htmlexporter.cpp b/src/translators/htmlexporter.cpp
index e27d6e5..e8bb95d 100644
--- a/src/translators/htmlexporter.cpp
+++ b/src/translators/htmlexporter.cpp
@@ -31,6 +31,7 @@
#include <tdeio/netaccess.h>
#include <tdeapplication.h>
#include <tdelocale.h>
+#include <kuser.h>
#include <tqdom.h>
#include <tqgroupbox.h>
@@ -192,6 +193,9 @@ bool HTMLExporter::loadXSLTFile() {
m_handler = 0;
return false;
}
+ m_handler->addStringParam("date", TQDate::currentDate().toString(TQt::ISODate).latin1());
+ m_handler->addStringParam("time", TQTime::currentTime().toString(TQt::ISODate).latin1());
+ m_handler->addStringParam("user", KUser(KUser::UseRealUserID).loginName().latin1());
if(m_exportEntryFiles) {
// export entries to same place as all the other date files
diff --git a/src/translators/risimporter.cpp b/src/translators/risimporter.cpp
index 735368c..0158708 100644
--- a/src/translators/risimporter.cpp
+++ b/src/translators/risimporter.cpp
@@ -188,7 +188,7 @@ void RISImporter::readURL(const KURL& url_, int n, const TQDict<Data::Field>& ri
// technically, the spec requires a space immediately after the hyphen
// however, at least one website (Springer) outputs RIS with no space after the final "ER -"
// so just strip the white space later
- // also be gracious and allow only any amount of space before hyphen
+ // also be gracious and allow any amount of space before hyphen
TQRegExp rx(TQString::fromLatin1("^(\\w\\w)\\s+-(.*)$"));
TQString currLine, nextLine;
for(currLine = t.readLine(); !m_cancelled && !currLine.isNull(); currLine = nextLine, j += currLine.length()) {
@@ -312,4 +312,25 @@ void RISImporter::slotCancel() {
m_cancelled = true;
}
+bool RISImporter::maybeRIS(const KURL& url_) {
+ TQString text = FileHandler::readTextFile(url_, true /*quiet*/);
+ if(text.isEmpty()) {
+ return false;
+ }
+
+ // bare bones check, strip white space at beginning
+ // and then first text line must be valid RIS
+ TQTextIStream t(&text);
+
+ TQRegExp rx(TQString::fromLatin1("^(\\w\\w)\\s+-(.*)$"));
+ TQString currLine;
+ for(currLine = t.readLine(); !currLine.isNull(); currLine = t.readLine()) {
+ if(currLine.stripWhiteSpace().isEmpty()) {
+ continue;
+ }
+ break;
+ }
+ return rx.exactMatch(currLine);
+}
+
#include "risimporter.moc"
diff --git a/src/translators/risimporter.h b/src/translators/risimporter.h
index fa581ba..a572283 100644
--- a/src/translators/risimporter.h
+++ b/src/translators/risimporter.h
@@ -50,6 +50,8 @@ public:
virtual TQWidget* widget(TQWidget*, const char*) { return 0; }
virtual bool canImport(int type) const;
+ static bool maybeRIS(const KURL& url);
+
public slots:
void slotCancel();
diff --git a/src/translators/tellico_xml.cpp b/src/translators/tellico_xml.cpp
index bcfb412..3a927d6 100644
--- a/src/translators/tellico_xml.cpp
+++ b/src/translators/tellico_xml.cpp
@@ -63,6 +63,12 @@ TQString Tellico::XML::dtdTellico(int version) {
return TQString::fromLatin1("http://periapsis.org/tellico/dtd/v%1/tellico.dtd").arg(version);
}
+// returns true if the file has to be converted
+// version 9 to 10 requires no conversion since it only added board games
+bool Tellico::XML::versionConversion(uint from, uint to) {
+ return from < to && (from != 9 || to != 10);
+}
+
bool Tellico::XML::validXMLElementName(const TQString& name_) {
return xmlValidateNameValue((xmlChar *)name_.utf8().data());
}
diff --git a/src/translators/tellico_xml.h b/src/translators/tellico_xml.h
index 6ff4c1b..6ffda10 100644
--- a/src/translators/tellico_xml.h
+++ b/src/translators/tellico_xml.h
@@ -28,6 +28,8 @@ namespace Tellico {
TQString pubTellico(int version = syntaxVersion);
TQString dtdTellico(int version = syntaxVersion);
+ bool versionConversion(uint from, uint to);
+
extern const TQString nsBookcase;
extern const TQString nsDublinCore;
extern const TQString nsZing;
diff --git a/src/translators/tellicoimporter.cpp b/src/translators/tellicoimporter.cpp
index a8dfb62..d722c0c 100644
--- a/src/translators/tellicoimporter.cpp
+++ b/src/translators/tellicoimporter.cpp
@@ -39,11 +39,6 @@
using Tellico::Import::TellicoImporter;
-bool TellicoImporter::versionConversion(uint from, uint to) {
- // version 10 only added board games to version 9
- return from < to && (from != 9 || to != 10);
-}
-
TellicoImporter::TellicoImporter(const KURL& url_, bool loadAllImages_) : DataImporter(url_),
m_coll(0), m_loadAllImages(loadAllImages_), m_format(Unknown), m_modified(false),
m_cancelled(false), m_hasImages(false), m_buffer(0), m_zip(0), m_imgDir(0) {
@@ -157,7 +152,7 @@ void TellicoImporter::loadXMLData(const TQByteArray& data_, bool loadImages_) {
}
m_format = Error;
return;
- } else if(versionConversion(syntaxVersion, XML::syntaxVersion)) {
+ } else if(XML::versionConversion(syntaxVersion, XML::syntaxVersion)) {
// going form version 9 to 10, there's no conversion needed
TQString str = i18n("Tellico is converting the file to a more recent document format. "
"Information loss may occur if an older version of Tellico is used "
@@ -374,7 +369,7 @@ void TellicoImporter::readField(uint syntaxVersion_, const TQDomElement& elem_)
Data::FieldPtr field;
if(type == Data::Field::Choice) {
- TQStringList allowed = TQStringList::split(TQString::fromLatin1(";"),
+ TQStringList allowed = TQStringList::split(TQRegExp(TQString::fromLatin1("\\s*;\\s*")),
elem_.attribute(TQString::fromLatin1("allowed")));
if(isI18n) {
for(TQStringList::Iterator it = allowed.begin(); it != allowed.end(); ++it) {
@@ -652,8 +647,9 @@ void TellicoImporter::readEntry(uint syntaxVersion_, const TQDomElement& entryEl
void TellicoImporter::readImage(const TQDomElement& elem_, bool loadImage_) {
TQString format = elem_.attribute(TQString::fromLatin1("format"));
const bool link = elem_.attribute(TQString::fromLatin1("link")) == Latin1Literal("true");
- TQString id = shareString(link ? elem_.attribute(TQString::fromLatin1("id"))
- : Data::Image::idClean(elem_.attribute(TQString::fromLatin1("id"))));
+ // idClean() already calls shareString()
+ TQString id = link ? shareString(elem_.attribute(TQString::fromLatin1("id")))
+ : Data::Image::idClean(elem_.attribute(TQString::fromLatin1("id")));
bool readInfo = true;
if(loadImage_) {
diff --git a/src/translators/tellicoimporter.h b/src/translators/tellicoimporter.h
index 93cf7da..6ea0ac5 100644
--- a/src/translators/tellicoimporter.h
+++ b/src/translators/tellicoimporter.h
@@ -70,8 +70,6 @@ public slots:
void slotCancel();
private:
- static bool versionConversion(uint from, uint to);
-
void loadXMLData(const TQByteArray& data, bool loadImages);
void loadZipData();
diff --git a/src/translators/tellicosaximporter.cpp b/src/translators/tellicosaximporter.cpp
new file mode 100644
index 0000000..de60c63
--- /dev/null
+++ b/src/translators/tellicosaximporter.cpp
@@ -0,0 +1,293 @@
+/***************************************************************************
+ copyright : (C) 2008 by Robby Stephenson
+ email : robby@periapsis.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+// before tellicosaxmporter.h because of QT_NO_CAST_ASCII issues
+#include "tellicoxmlhandler.h"
+#include "tellicosaximporter.h"
+#include "tellico_xml.h"
+#include "../collectionfactory.h"
+#include "../collections/bibtexcollection.h"
+#include "../entry.h"
+#include "../field.h"
+#include "../imagefactory.h"
+#include "../image.h"
+#include "../isbnvalidator.h"
+#include "../latin1literal.h"
+#include "../tellico_strings.h"
+#include "../tellico_kernel.h"
+#include "../tellico_utils.h"
+#include "../tellico_debug.h"
+#include "../progressmanager.h"
+
+#include <tdelocale.h>
+#include <kmdcodec.h>
+#include <kzip.h>
+#include <tdeapplication.h>
+
+#include <tqbuffer.h>
+#include <tqfile.h>
+#include <tqtimer.h>
+
+using Tellico::Import::TellicoSaxImporter;
+
+TellicoSaxImporter::TellicoSaxImporter(const KURL& url_, bool loadAllImages_) : DataImporter(url_),
+ m_coll(0), m_loadAllImages(loadAllImages_), m_format(Unknown), m_modified(false),
+ m_cancelled(false), m_hasImages(false), m_buffer(0), m_zip(0), m_imgDir(0) {
+}
+
+TellicoSaxImporter::TellicoSaxImporter(const TQString& text_) : DataImporter(text_),
+ m_coll(0), m_loadAllImages(true), m_format(Unknown), m_modified(false),
+ m_cancelled(false), m_hasImages(false), m_buffer(0), m_zip(0), m_imgDir(0) {
+}
+
+TellicoSaxImporter::~TellicoSaxImporter() {
+ if(m_zip) {
+ m_zip->close();
+ }
+ delete m_zip;
+ m_zip = 0;
+ delete m_buffer;
+ m_buffer = 0;
+}
+
+Tellico::Data::CollPtr TellicoSaxImporter::collection() {
+ if(m_coll) {
+ return m_coll;
+ }
+
+ TQCString s; // read first 5 characters
+ if(source() == URL) {
+ if(!fileRef().open()) {
+ return 0;
+ }
+ TQIODevice* f = fileRef().file();
+ for(uint i = 0; i < 5; ++i) {
+ s += static_cast<char>(f->getch());
+ }
+ f->reset();
+ } else {
+ if(data().size() < 5) {
+ m_format = Error;
+ return 0;
+ }
+ s = TQCString(data(), 6);
+ }
+
+ // need to decide if the data is xml text, or a zip file
+ // if the first 5 characters are <?xml then treat it like text
+ if(s[0] == '<' && s[1] == '?' && s[2] == 'x' && s[3] == 'm' && s[4] == 'l') {
+ m_format = XML;
+ loadXMLData(source() == URL ? fileRef().file()->readAll() : data(), true);
+ } else {
+ m_format = Zip;
+ loadZipData();
+ }
+ return m_coll;
+}
+
+void TellicoSaxImporter::loadXMLData(const TQByteArray& data_, bool loadImages_) {
+ ProgressItem& item = ProgressManager::self()->newProgressItem(this, progressLabel(), true);
+ item.setTotalSteps(data_.size());
+ connect(&item, SIGNAL(signalCancelled(ProgressItem*)), SLOT(slotCancel()));
+ ProgressItem::Done done(this);
+
+ const bool showProgress = options() & ImportProgress;
+
+ TellicoXMLHandler handler;
+ handler.setLoadImages(loadImages_);
+
+ TQXmlSimpleReader reader;
+ reader.setContentHandler(&handler);
+
+ TQXmlInputSource source;
+ bool success = reader.parse(&source, true);
+
+ const uint blockSize = data_.size()/100 + 1;
+ uint pos = 0;
+ TQByteArray block;
+
+ while(success && !m_cancelled && pos < data_.size()) {
+ uint size = TQMIN(blockSize, data_.size() - pos);
+ block.setRawData(data_.data() + pos, size);
+ source.setData(block);
+ success = reader.parseContinue();
+ block.resetRawData(data_.data() + pos, size);
+ pos += blockSize;
+ if(showProgress) {
+ ProgressManager::self()->setProgress(this, pos);
+ kapp->processEvents();
+ }
+ }
+
+ if(!success) {
+ m_format = Error;
+ TQString error;
+ if(!url().isEmpty()) {
+ error = i18n(errorLoad).arg(url().fileName()) + TQChar('\n');
+ }
+ error += handler.errorString();
+ myDebug() << error << endl;
+ setStatusMessage(error);
+ return;
+ }
+
+ if(!m_cancelled) {
+ m_hasImages = handler.hasImages();
+ m_coll = handler.collection();
+ }
+}
+
+void TellicoSaxImporter::loadZipData() {
+ delete m_buffer;
+ delete m_zip;
+ if(source() == URL) {
+ m_buffer = 0;
+ m_zip = new KZip(fileRef().fileName());
+ } else {
+ m_buffer = new TQBuffer(data());
+ m_zip = new KZip(m_buffer);
+ }
+ if(!m_zip->open(IO_ReadOnly)) {
+ setStatusMessage(i18n(errorLoad).arg(url().fileName()));
+ m_format = Error;
+ delete m_zip;
+ m_zip = 0;
+ delete m_buffer;
+ m_buffer = 0;
+ return;
+ }
+
+ const KArchiveDirectory* dir = m_zip->directory();
+ if(!dir) {
+ TQString str = i18n(errorLoad).arg(url().fileName()) + TQChar('\n');
+ str += i18n("The file is empty.");
+ setStatusMessage(str);
+ m_format = Error;
+ m_zip->close();
+ delete m_zip;
+ m_zip = 0;
+ delete m_buffer;
+ m_buffer = 0;
+ return;
+ }
+
+ // main file was changed from bookcase.xml to tellico.xml as of version 0.13
+ const KArchiveEntry* entry = dir->entry(TQString::fromLatin1("tellico.xml"));
+ if(!entry) {
+ entry = dir->entry(TQString::fromLatin1("bookcase.xml"));
+ }
+ if(!entry || !entry->isFile()) {
+ TQString str = i18n(errorLoad).arg(url().fileName()) + TQChar('\n');
+ str += i18n("The file contains no collection data.");
+ setStatusMessage(str);
+ m_format = Error;
+ m_zip->close();
+ delete m_zip;
+ m_zip = 0;
+ delete m_buffer;
+ m_buffer = 0;
+ return;
+ }
+
+ const TQByteArray xmlData = static_cast<const KArchiveFile*>(entry)->data();
+ loadXMLData(xmlData, false);
+ if(!m_coll) {
+ m_format = Error;
+ m_zip->close();
+ delete m_zip;
+ m_zip = 0;
+ delete m_buffer;
+ m_buffer = 0;
+ return;
+ }
+
+ if(m_cancelled) {
+ m_zip->close();
+ delete m_zip;
+ m_zip = 0;
+ delete m_buffer;
+ m_buffer = 0;
+ return;
+ }
+
+ const KArchiveEntry* imgDirEntry = dir->entry(TQString::fromLatin1("images"));
+ if(!imgDirEntry || !imgDirEntry->isDirectory()) {
+ m_zip->close();
+ delete m_zip;
+ m_zip = 0;
+ delete m_buffer;
+ m_buffer = 0;
+ return;
+ }
+ m_imgDir = static_cast<const KArchiveDirectory*>(imgDirEntry);
+ m_images.clear();
+ m_images.add(m_imgDir->entries());
+ m_hasImages = !m_images.isEmpty();
+
+ // if all the images are not to be loaded, then we're done
+ if(!m_loadAllImages) {
+// myLog() << "TellicoSaxImporter::loadZipData() - delayed loading for " << m_images.count() << " images" << endl;
+ return;
+ }
+
+ const TQStringList images = static_cast<const KArchiveDirectory*>(imgDirEntry)->entries();
+ const uint stepSize = TQMAX(s_stepSize, images.count()/100);
+
+ uint j = 0;
+ for(TQStringList::ConstIterator it = images.begin(); !m_cancelled && it != images.end(); ++it, ++j) {
+ const KArchiveEntry* file = m_imgDir->entry(*it);
+ if(file && file->isFile()) {
+ ImageFactory::addImage(static_cast<const KArchiveFile*>(file)->data(),
+ (*it).section('.', -1).upper(), (*it));
+ m_images.remove(*it);
+ }
+ if(j%stepSize == 0) {
+ kapp->processEvents();
+ }
+ }
+
+ if(m_images.isEmpty()) {
+ // give it some time
+ TQTimer::singleShot(3000, this, SLOT(deleteLater()));
+ }
+}
+
+bool TellicoSaxImporter::hasImages() const {
+ return m_hasImages;
+}
+
+bool TellicoSaxImporter::loadImage(const TQString& id_) {
+// myLog() << "TellicoSaxImporter::loadImage() - id = " << id_ << endl;
+ if(m_format != Zip || !m_imgDir) {
+ return false;
+ }
+ const KArchiveEntry* file = m_imgDir->entry(id_);
+ if(!file || !file->isFile()) {
+ return false;
+ }
+ TQString newID = ImageFactory::addImage(static_cast<const KArchiveFile*>(file)->data(),
+ id_.section('.', -1).upper(), id_);
+ m_images.remove(id_);
+ if(m_images.isEmpty()) {
+ // give it some time
+ TQTimer::singleShot(3000, this, SLOT(deleteLater()));
+ }
+ return !newID.isEmpty();
+}
+
+void TellicoSaxImporter::slotCancel() {
+ m_cancelled = true;
+ m_format = Cancel;
+}
+
+#include "tellicosaximporter.moc"
diff --git a/src/translators/tellicosaximporter.h b/src/translators/tellicosaximporter.h
new file mode 100644
index 0000000..056f60f
--- /dev/null
+++ b/src/translators/tellicosaximporter.h
@@ -0,0 +1,87 @@
+/***************************************************************************
+ copyright : (C) 2008 by Robby Stephenson
+ email : robby@periapsis.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#ifndef TELLICO_IMPORT_TELLICOSAXIMPORTER_H
+#define TELLICO_IMPORT_TELLICOSAXIMPORTER_H
+
+#include "dataimporter.h"
+#include "../datavectors.h"
+#include "../stringset.h"
+
+class TQBuffer;
+class KZip;
+class KArchiveDirectory;
+
+namespace Tellico {
+ namespace Import {
+
+/**
+ * @author Robby Stephenson
+ */
+class TellicoSaxImporter : public DataImporter {
+Q_OBJECT
+
+public:
+ enum Format { Unknown, Error, XML, Zip, Cancel };
+
+ /**
+ * @param url The tellico data file.
+ */
+ TellicoSaxImporter(const KURL& url, bool loadAllImages=true);
+ /**
+ * Constructor used to convert arbitrary text to a @ref Collection
+ *
+ * @param text The text
+ */
+ TellicoSaxImporter(const TQString& text);
+ virtual ~TellicoSaxImporter();
+
+ /**
+ * sometimes, a new document format might add data
+ */
+ bool modifiedOriginal() const { return m_modified; }
+
+ /**
+ */
+ virtual Data::CollPtr collection();
+ Format format() const { return m_format; }
+
+ bool hasImages() const;
+ bool loadImage(const TQString& id_);
+
+ static bool loadAllImages(const KURL& url);
+
+public slots:
+ void slotCancel();
+
+private:
+ void loadXMLData(const TQByteArray& data, bool loadImages);
+ void loadZipData();
+
+ Data::CollPtr m_coll;
+ bool m_loadAllImages;
+ TQString m_namespace;
+ Format m_format;
+ bool m_modified : 1;
+ bool m_cancelled : 1;
+ bool m_hasImages : 1;
+ StringSet m_images;
+
+ TQBuffer* m_buffer;
+ KZip* m_zip;
+ const KArchiveDirectory* m_imgDir;
+};
+
+ } // end namespace
+} // end namespace
+#endif
diff --git a/src/translators/tellicoxmlhandler.cpp b/src/translators/tellicoxmlhandler.cpp
new file mode 100644
index 0000000..5b3f063
--- /dev/null
+++ b/src/translators/tellicoxmlhandler.cpp
@@ -0,0 +1,74 @@
+/***************************************************************************
+ copyright : (C) 2008 by Robby Stephenson
+ email : robby@periapsis.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#include "tellicoxmlhandler.h"
+#include "../collection.h"
+#include "../tellico_debug.h"
+
+using Tellico::Import::TellicoXMLHandler;
+
+TellicoXMLHandler::TellicoXMLHandler() : TQXmlDefaultHandler(), m_data(new SAX::StateData) {
+ m_handlers.setAutoDelete(true);
+ m_handlers.push(new SAX::RootHandler(m_data));
+}
+
+TellicoXMLHandler::~TellicoXMLHandler() {
+ delete m_data;
+ m_data = 0;
+}
+
+bool TellicoXMLHandler::startElement(const TQString& nsURI_, const TQString& localName_,
+ const TQString& qName_, const TQXmlAttributes& atts_) {
+ SAX::StateHandler* handler = m_handlers.top()->nextHandler(nsURI_, localName_, qName_);
+ Q_ASSERT(handler);
+ m_handlers.push(handler);
+ return handler->start(nsURI_, localName_, qName_, atts_);
+}
+
+bool TellicoXMLHandler::endElement(const TQString& nsURI_, const TQString& localName_,
+ const TQString& qName_) {
+ m_data->text = m_data->text.stripWhiteSpace();
+/*
+ if(!m_data->text.isEmpty()) {
+ myDebug() << " text: " << m_text << endl;
+ }
+*/
+
+ SAX::StateHandler* handler = m_handlers.pop();
+ bool res = handler->end(nsURI_, localName_, qName_);
+ // need to reset character data, too
+ m_data->text = TQString();
+ delete handler;
+ return res;
+}
+
+bool TellicoXMLHandler::characters(const TQString& ch_) {
+ m_data->text += ch_;
+ return true;
+}
+
+TQString TellicoXMLHandler::errorString() {
+ return m_data->error;
+}
+
+Tellico::Data::CollPtr TellicoXMLHandler::collection() const {
+ return m_data->coll;
+}
+
+bool TellicoXMLHandler::hasImages() const {
+ return m_data->hasImages;
+}
+
+void TellicoXMLHandler::setLoadImages(bool loadImages_) {
+ m_data->loadImages = loadImages_;
+}
diff --git a/src/translators/tellicoxmlhandler.h b/src/translators/tellicoxmlhandler.h
new file mode 100644
index 0000000..1edeacc
--- /dev/null
+++ b/src/translators/tellicoxmlhandler.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ copyright : (C) 2008 by Robby Stephenson
+ email : robby@periapsis.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#ifndef TELLICO_IMPORT_TELLICOXMLHANDLER_H
+#define TELLICO_IMPORT_TELLICOXMLHANDLER_H
+
+#include "xmlstatehandler.h"
+
+#include <tqptrstack.h>
+
+namespace Tellico {
+ namespace Import {
+
+class TellicoXMLHandler : public TQXmlDefaultHandler {
+public:
+ TellicoXMLHandler();
+ ~TellicoXMLHandler();
+
+ virtual bool startElement(const TQString& namespaceURI, const TQString& localName,
+ const TQString& qName, const TQXmlAttributes& atts);
+ virtual bool endElement(const TQString& namespaceURI, const TQString& localName,
+ const TQString& qName);
+ virtual bool characters(const TQString& ch);
+
+ virtual TQString errorString();
+
+ Data::CollPtr collection() const;
+ bool hasImages() const;
+
+ void setLoadImages(bool loadImages);
+
+private:
+ TQPtrStack<SAX::StateHandler> m_handlers;
+ SAX::StateData* m_data;
+};
+
+ }
+}
+#endif
diff --git a/src/translators/xmlstatehandler.cpp b/src/translators/xmlstatehandler.cpp
new file mode 100644
index 0000000..48d52d6
--- /dev/null
+++ b/src/translators/xmlstatehandler.cpp
@@ -0,0 +1,772 @@
+/***************************************************************************
+ copyright : (C) 2008 by Robby Stephenson
+ email : robby@periapsis.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#include "xmlstatehandler.h"
+#include "tellico_xml.h"
+#include "../latin1literal.h"
+#include "../collection.h"
+#include "../collectionfactory.h"
+#include "../collections/bibtexcollection.h"
+#include "../image.h"
+#include "../imagefactory.h"
+#include "../isbnvalidator.h"
+#include "../tellico_utils.h"
+#include "../tellico_debug.h"
+
+#include <tdelocale.h>
+#include <kmdcodec.h>
+
+namespace {
+
+inline
+TQString attValue(const TQXmlAttributes& atts, const char* name, const TQString& defaultValue=TQString()) {
+ int idx = atts.index(TQString::fromLatin1(name));
+ return idx < 0 ? defaultValue : atts.value(idx);
+}
+
+inline
+TQString attValue(const TQXmlAttributes& atts, const char* name, const char* defaultValue) {
+ Q_ASSERT(defaultValue);
+ return attValue(atts, name, TQString::fromLatin1(defaultValue));
+}
+
+}
+
+using Tellico::Import::SAX::StateHandler;
+using Tellico::Import::SAX::NullHandler;
+using Tellico::Import::SAX::RootHandler;
+using Tellico::Import::SAX::DocumentHandler;
+using Tellico::Import::SAX::CollectionHandler;
+using Tellico::Import::SAX::FieldsHandler;
+using Tellico::Import::SAX::FieldHandler;
+using Tellico::Import::SAX::FieldPropertyHandler;
+using Tellico::Import::SAX::BibtexPreambleHandler;
+using Tellico::Import::SAX::BibtexMacrosHandler;
+using Tellico::Import::SAX::BibtexMacroHandler;
+using Tellico::Import::SAX::EntryHandler;
+using Tellico::Import::SAX::FieldValueContainerHandler;
+using Tellico::Import::SAX::FieldValueHandler;
+using Tellico::Import::SAX::DateValueHandler;
+using Tellico::Import::SAX::TableColumnHandler;
+using Tellico::Import::SAX::ImagesHandler;
+using Tellico::Import::SAX::ImageHandler;
+using Tellico::Import::SAX::FiltersHandler;
+using Tellico::Import::SAX::FilterHandler;
+using Tellico::Import::SAX::FilterRuleHandler;
+using Tellico::Import::SAX::BorrowersHandler;
+using Tellico::Import::SAX::BorrowerHandler;
+using Tellico::Import::SAX::LoanHandler;
+
+StateHandler* StateHandler::nextHandler(const TQString& ns_, const TQString& localName_, const TQString& qName_) {
+ StateHandler* handler = nextHandlerImpl(ns_, localName_, qName_);
+ if(!handler) {
+ myWarning() << "StateHandler::nextHandler() - no handler for " << localName_ << endl;
+ }
+ return handler ? handler : new NullHandler(d);
+}
+
+StateHandler* RootHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("tellico") || localName_ == Latin1Literal("bookcase")) {
+ return new DocumentHandler(d);
+ }
+ return new RootHandler(d);
+}
+
+StateHandler* DocumentHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("collection")) {
+ return new CollectionHandler(d);
+ } else if(localName_ == Latin1Literal("filters")) {
+ return new FiltersHandler(d);
+ } else if(localName_ == Latin1Literal("borrowers")) {
+ return new BorrowersHandler(d);
+ }
+ return 0;
+}
+
+bool DocumentHandler::start(const TQString&, const TQString& localName_, const TQString&, const TQXmlAttributes& atts_) {
+ // the syntax version field name changed from "version" to "syntaxVersion" in version 3
+ int idx = atts_.index(TQString::fromLatin1("syntaxVersion"));
+ if(idx < 0) {
+ idx = atts_.index(TQString::fromLatin1("version"));
+ }
+ if(idx < 0) {
+ myWarning() << "RootHandler::start() - no syntax version" << endl;
+ return false;
+ }
+ d->syntaxVersion = atts_.value(idx).toUInt();
+ if(d->syntaxVersion > Tellico::XML::syntaxVersion) {
+ d->error = i18n("It is from a future version of Tellico.");
+ return false;
+ } else if(Tellico::XML::versionConversion(d->syntaxVersion, Tellico::XML::syntaxVersion)) {
+ // going from version 9 to 10, there's no conversion needed
+ TQString str = i18n("Tellico is converting the file to a more recent document format. "
+ "Information loss may occur if an older version of Tellico is used "
+ "to read this file in the future.");
+ myDebug() << str << endl;
+ }
+ if((d->syntaxVersion > 6 && localName_ != Latin1Literal("tellico")) ||
+ (d->syntaxVersion < 7 && localName_ != Latin1Literal("bookcase"))) {
+ // no error message
+ myWarning() << "RootHandler::start() - bad root element name" << endl;
+ return false;
+ }
+ d->ns = d->syntaxVersion > 6 ? Tellico::XML::nsTellico : Tellico::XML::nsBookcase;
+ return true;
+}
+
+bool DocumentHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+StateHandler* CollectionHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if((d->syntaxVersion > 3 && localName_ == Latin1Literal("fields")) ||
+ (d->syntaxVersion < 4 && localName_ == Latin1Literal("attributes"))) {
+ return new FieldsHandler(d);
+ } else if(localName_ == Latin1Literal("bibtex-preamble")) {
+ return new BibtexPreambleHandler(d);
+ } else if(localName_ == Latin1Literal("macros")) {
+ return new BibtexMacrosHandler(d);
+ } else if(localName_ == d->entryName) {
+ return new EntryHandler(d);
+ } else if(localName_ == Latin1Literal("images")) {
+ return new ImagesHandler(d);
+ }
+ return 0;
+}
+
+bool CollectionHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ d->collTitle = attValue(atts_, "title");
+ d->collType = attValue(atts_, "type").toInt();
+ d->entryName = attValue(atts_, "unit");
+
+ Q_ASSERT(d->collType);
+ return true;
+}
+
+bool CollectionHandler::end(const TQString&, const TQString&, const TQString&) {
+ d->coll->addEntries(d->entries);
+ // a little hidden capability was to just have a local path as an image file name
+ // and on reading the xml file, Tellico would load the image file, too
+ // here, we need to scan all the image values in all the entries and check
+ // maybe this is too costly, especially since the capability wasn't advertised?
+ Data::FieldVec fields = d->coll->imageFields();
+ for(Data::EntryVecIt entry = d->entries.begin(); entry != d->entries.end(); ++entry) {
+ for(Data::FieldVecIt field = fields.begin(); field != fields.end(); ++field) {
+ TQString value = entry->field(field, false);
+ // image info should have already been loaded
+ const Data::ImageInfo& info = ImageFactory::imageInfo(value);
+ // possible that value needs to be cleaned first in which case info is null
+ if(info.isNull() || !info.linkOnly) {
+ // for local files only, allow paths here
+ KURL u = KURL::fromPathOrURL(value);
+ if(u.isValid() && u.isLocalFile()) {
+ TQString result = ImageFactory::addImage(u, false /* quiet */);
+ if(!result.isEmpty()) {
+ value = result;
+ }
+ }
+ value = Data::Image::idClean(value);
+ entry->setField(field->name(), value);
+ }
+ }
+ }
+ return true;
+}
+
+StateHandler* FieldsHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if((d->syntaxVersion > 3 && localName_ == Latin1Literal("field")) ||
+ (d->syntaxVersion < 4 && localName_ == Latin1Literal("attribute"))) {
+ return new FieldHandler(d);
+ }
+ return 0;
+}
+
+bool FieldsHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ d->defaultFields = false;
+ return true;
+}
+
+bool FieldsHandler::end(const TQString&, const TQString&, const TQString&) {
+ // add default fields if there was a default field name, or no names at all
+ const bool addFields = d->defaultFields || d->fields.isEmpty();
+ // in syntax 4, the element name was changed to "entry", always, rather than depending on
+ // on the entryName of the collection.
+ if(d->syntaxVersion > 3) {
+ d->entryName = TQString::fromLatin1("entry");
+ Data::Collection::Type type = static_cast<Data::Collection::Type>(d->collType);
+ d->coll = CollectionFactory::collection(type, addFields);
+ } else {
+ d->coll = CollectionFactory::collection(d->entryName, addFields);
+ }
+
+ if(!d->collTitle.isEmpty()) {
+ d->coll->setTitle(d->collTitle);
+ }
+
+ d->coll->addFields(d->fields);
+
+// as a special case, for old book collections with a bibtex-id field, convert to Bibtex
+ if(d->syntaxVersion < 4 && d->collType == Data::Collection::Book
+ && d->coll->hasField(TQString::fromLatin1("bibtex-id"))) {
+ d->coll = Data::BibtexCollection::convertBookCollection(d->coll);
+ }
+
+ return true;
+}
+
+StateHandler* FieldHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("prop")) {
+ return new FieldPropertyHandler(d);
+ }
+ return 0;
+}
+
+bool FieldHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ // special case: if the i18n attribute equals true, then translate the title, description, and category
+ const bool isI18n = attValue(atts_, "i18n") == Latin1Literal("true");
+
+ TQString name = attValue(atts_, "name", "unknown");
+ if(name == Latin1Literal("_default")) {
+ d->defaultFields = true;
+ return true;
+ }
+
+ TQString title = attValue(atts_, "title", i18n("Unknown"));
+ if(isI18n) {
+ title = i18n(title.utf8());
+ }
+
+ TQString typeStr = attValue(atts_, "type", TQString::number(Data::Field::Line));
+ Data::Field::Type type = static_cast<Data::Field::Type>(typeStr.toInt());
+
+ Data::FieldPtr field;
+ if(type == Data::Field::Choice) {
+ TQStringList allowed = TQStringList::split(TQRegExp(TQString::fromLatin1("\\s*;\\s*")),
+ attValue(atts_, "allowed"));
+ if(isI18n) {
+ for(TQStringList::Iterator word = allowed.begin(); word != allowed.end(); ++word) {
+ (*word) = i18n((*word).utf8());
+ }
+ }
+ field = new Data::Field(name, title, allowed);
+ } else {
+ field = new Data::Field(name, title, type);
+ }
+
+ int idx = atts_.index(TQString::fromLatin1("category"));
+ if(idx > -1) {
+ // at one point, the categories had keyboard accels
+ TQString cat = atts_.value(idx);
+ if(d->syntaxVersion < 9 && cat.find('&') > -1) {
+ cat.remove('&');
+ }
+ if(isI18n) {
+ cat = i18n(cat.utf8());
+ }
+ field->setCategory(cat);
+ }
+
+ idx = atts_.index(TQString::fromLatin1("flags"));
+ if(idx > -1) {
+ int flags = atts_.value(idx).toInt();
+ // I also changed the enum values for syntax 3, but the only custom field
+ // would have been bibtex-id
+ if(d->syntaxVersion < 3 && name == Latin1Literal("bibtex-id")) {
+ flags = 0;
+ }
+
+ // in syntax version 4, added a flag to disallow deleting attributes
+ // if it's a version before that and is the title, then add the flag
+ if(d->syntaxVersion < 4 && name == Latin1Literal("title")) {
+ flags |= Data::Field::NoDelete;
+ }
+ field->setFlags(flags);
+ }
+
+ TQString formatStr = attValue(atts_, "format", TQString::number(Data::Field::FormatNone));
+ Data::Field::FormatFlag format = static_cast<Data::Field::FormatFlag>(formatStr.toInt());
+ field->setFormatFlag(format);
+
+ idx = atts_.index(TQString::fromLatin1("description"));
+ if(idx > -1) {
+ TQString desc = atts_.value(idx);
+ if(isI18n) {
+ desc = i18n(desc.utf8());
+ }
+ field->setDescription(desc);
+ }
+
+ if(d->syntaxVersion < 5 && atts_.index(TQString::fromLatin1("bibtex-field")) > -1) {
+ field->setProperty(TQString::fromLatin1("bibtex"), attValue(atts_, "bibtex-field"));
+ }
+
+ // Table2 is deprecated
+ if(type == Data::Field::Table2) {
+ field->setType(Data::Field::Table);
+ field->setProperty(TQString::fromLatin1("columns"), TQChar('2'));
+ }
+
+ // for syntax 8, rating fields got their own type
+ if(d->syntaxVersion < 8) {
+ Data::Field::convertOldRating(field); // does all its own checking
+ }
+ d->fields.append(field);
+
+ return true;
+}
+
+bool FieldHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+bool FieldPropertyHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ // there should be at least one field already so we can add properties to it
+ Q_ASSERT(!d->fields.isEmpty());
+ Data::FieldPtr field = d->fields.back();
+
+ m_propertyName = attValue(atts_, "name");
+
+ // all track fields in music collections prior to version 9 get converted to three columns
+ if(d->syntaxVersion < 9) {
+ if(d->collType == Data::Collection::Album && field->name() == Latin1Literal("track")) {
+ field->setProperty(TQString::fromLatin1("columns"), TQChar('3'));
+ field->setProperty(TQString::fromLatin1("column1"), i18n("Title"));
+ field->setProperty(TQString::fromLatin1("column2"), i18n("Artist"));
+ field->setProperty(TQString::fromLatin1("column3"), i18n("Length"));
+ } else if(d->collType == Data::Collection::Video && field->name() == Latin1Literal("cast")) {
+ field->setProperty(TQString::fromLatin1("column1"), i18n("Actor/Actress"));
+ field->setProperty(TQString::fromLatin1("column2"), i18n("Role"));
+ }
+ }
+
+ return true;
+}
+
+bool FieldPropertyHandler::end(const TQString&, const TQString&, const TQString&) {
+ Q_ASSERT(!m_propertyName.isEmpty());
+ // add the previous property
+ Data::FieldPtr field = d->fields.back();
+ field->setProperty(m_propertyName, d->text);
+ return true;
+}
+
+bool BibtexPreambleHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ return true;
+}
+
+bool BibtexPreambleHandler::end(const TQString&, const TQString&, const TQString&) {
+ Q_ASSERT(d->coll);
+ if(d->coll && d->collType == Data::Collection::Bibtex && !d->text.isEmpty()) {
+ Data::BibtexCollection* c = static_cast<Data::BibtexCollection*>(d->coll.data());
+ c->setPreamble(d->text);
+ }
+ return true;
+}
+
+StateHandler* BibtexMacrosHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("macro")) {
+ return new BibtexMacroHandler(d);
+ }
+ return 0;
+}
+
+bool BibtexMacrosHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ return true;
+}
+
+bool BibtexMacrosHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+bool BibtexMacroHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ m_macroName = attValue(atts_, "name");
+ return true;
+}
+
+bool BibtexMacroHandler::end(const TQString&, const TQString&, const TQString&) {
+ if(d->coll && d->collType == Data::Collection::Bibtex && !m_macroName.isEmpty() && !d->text.isEmpty()) {
+ Data::BibtexCollection* c = static_cast<Data::BibtexCollection*>(d->coll.data());
+ c->addMacro(m_macroName, d->text);
+ }
+ return true;
+}
+
+StateHandler* EntryHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(d->coll->hasField(localName_)) {
+ return new FieldValueHandler(d);
+ }
+ return new FieldValueContainerHandler(d);
+}
+
+bool EntryHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ // the entries must come after the fields
+ if(!d->coll || d->coll->fields().isEmpty()) {
+ myWarning() << "EntryHandler::start() - entries must come after fields are defined" << endl;
+ // TODO: i18n
+ d->error = TQString::fromLatin1("File format error: entries must come after fields are defined");
+ return false;
+ }
+ int id = attValue(atts_, "id").toInt();
+ Data::EntryPtr entry;
+ if(id > 0) {
+ entry = new Data::Entry(d->coll, id);
+ } else {
+ entry = new Data::Entry(d->coll);
+ }
+ d->entries.append(entry);
+ return true;
+}
+
+bool EntryHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+StateHandler* FieldValueContainerHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(d->coll->hasField(localName_)) {
+ return new FieldValueHandler(d);
+ }
+ return new FieldValueContainerHandler(d);
+}
+
+bool FieldValueContainerHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ return true;
+}
+
+bool FieldValueContainerHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+StateHandler* FieldValueHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("year") ||
+ localName_ == Latin1Literal("month") ||
+ localName_ == Latin1Literal("day")) {
+ return new DateValueHandler(d);
+ } else if(localName_ == Latin1Literal("column")) {
+ return new TableColumnHandler(d);
+ }
+ return 0;
+}
+
+bool FieldValueHandler::start(const TQString&, const TQString&, const TQString& localName_, const TQXmlAttributes& atts_) {
+ d->currentField = d->coll->fieldByName(localName_);
+ m_i18n = attValue(atts_, "i18n") == Latin1Literal("true");
+ m_validateISBN = attValue(atts_, "validate") != Latin1Literal("no");
+ return true;
+}
+
+bool FieldValueHandler::end(const TQString&, const TQString& localName_, const TQString&) {
+ Data::FieldPtr f = d->coll->fieldByName(localName_);
+ if(!f) {
+ myWarning() << "FieldValueHandler::end() - no field named " << localName_ << endl;
+ return true;
+ }
+ // if it's a derived value, no field value is added
+ if(f->type() == Data::Field::Dependent) {
+ return true;
+ }
+
+ Data::EntryPtr entry = d->entries.back();
+ Q_ASSERT(entry);
+ TQString fieldName = localName_;
+ TQString fieldValue = d->text;
+
+ if(d->syntaxVersion < 2 && fieldName == Latin1Literal("keywords")) {
+ // in version 2, "keywords" changed to "keyword"
+ fieldName = TQString::fromLatin1("keyword");
+ } else if(d->syntaxVersion < 4 && f->type() == Data::Field::Bool) {
+ // in version 3 and prior, checkbox attributes had no text(), set it to "true"
+ fieldValue = TQString::fromLatin1("true");
+ } else if(d->syntaxVersion < 8 && f->type() == Data::Field::Rating) {
+ // in version 8, old rating fields get changed
+ bool ok;
+ uint i = Tellico::toUInt(fieldValue, &ok);
+ if(ok) {
+ fieldValue = TQString::number(i);
+ }
+ } else if(!d->textBuffer.isEmpty()) {
+ // for dates and tables, the value is built up from child elements
+#ifndef NDEBUG
+ if(!d->text.isEmpty()) {
+ myWarning() << "FieldValueHandler::end() - ignoring value for field " << localName_ << ": " << d->text << endl;
+ }
+#endif
+ fieldValue = d->textBuffer;
+ d->textBuffer = TQString();
+ }
+ // this is not an else branch, the data may be in the textBuffer
+ if(d->syntaxVersion < 9 && d->coll->type() == Data::Collection::Album && fieldName == Latin1Literal("track")) {
+ // yes, this assumes the artist has already been set
+ fieldValue += TQString::fromLatin1("::");
+ fieldValue += entry->field(TQString::fromLatin1("artist"));
+ }
+ // special case: if the i18n attribute equals true, then translate the title, description, and category
+ if(m_i18n) {
+ fieldValue = i18n(fieldValue.utf8());
+ }
+ // special case for isbn fields, go ahead and validate
+ if(m_validateISBN && fieldName == Latin1Literal("isbn")) {
+ ISBNValidator val(0);
+ val.fixup(fieldValue);
+ }
+ if(fieldValue.isEmpty()) {
+ return true;
+ }
+ // for fields with multiple values, we need to add on the new value
+ TQString oldValue = entry->field(fieldName);
+ if(!oldValue.isEmpty()) {
+ fieldValue = oldValue + TQString::fromLatin1("; ") + fieldValue;
+ }
+ entry->setField(fieldName, fieldValue);
+ return true;
+}
+
+bool DateValueHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ return true;
+}
+
+bool DateValueHandler::end(const TQString&, const TQString& localName_, const TQString&) {
+ // the data value is y-m-d even if there are no date values
+ if(d->textBuffer.isEmpty()) {
+ d->textBuffer = TQString::fromLatin1("--");
+ }
+ TQStringList tokens = TQStringList::split('-', d->textBuffer, true /* allow empty */);
+ Q_ASSERT(tokens.size() == 3);
+ if(localName_ == Latin1Literal("year")) {
+ tokens[0] = d->text;
+ } else if(localName_ == Latin1Literal("month")) {
+ tokens[1] = d->text;
+ } else if(localName_ == Latin1Literal("day")) {
+ tokens[2] = d->text;
+ }
+ d->textBuffer = tokens.join(TQChar('-'));
+ return true;
+}
+
+bool TableColumnHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ return true;
+}
+
+bool TableColumnHandler::end(const TQString&, const TQString&, const TQString&) {
+ // for old collections, if the second column holds the track length, bump it to next column
+ if(d->syntaxVersion < 9 &&
+ d->coll->type() == Data::Collection::Album &&
+ d->currentField->name() == Latin1Literal("track") &&
+ !d->textBuffer.isEmpty() &&
+ d->textBuffer.contains(TQString::fromLatin1("::")) == 0) {
+ TQRegExp rx(TQString::fromLatin1("\\d+:\\d\\d"));
+ if(rx.exactMatch(d->text)) {
+ d->text += TQString::fromLatin1("::");
+ d->text += d->entries.back()->field(TQString::fromLatin1("artist"));
+ }
+ }
+
+ if(!d->textBuffer.isEmpty()) {
+ d->textBuffer += TQString::fromLatin1("::");
+ }
+ d->textBuffer += d->text;
+ return true;
+}
+
+StateHandler* ImagesHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("image")) {
+ return new ImageHandler(d);
+ }
+ return 0;
+}
+
+bool ImagesHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ // reset variable that gets updated in the image handler
+ d->hasImages = false;
+ return true;
+}
+
+bool ImagesHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+bool ImageHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ m_format = attValue(atts_, "format");
+ m_link = attValue(atts_, "link") == Latin1Literal("true");
+ // idClean() already calls shareString()
+ m_imageId = m_link ? shareString(attValue(atts_, "id"))
+ : Data::Image::idClean(attValue(atts_, "id"));
+ m_width = attValue(atts_, "width").toInt();
+ m_height = attValue(atts_, "height").toInt();
+ return true;
+}
+
+bool ImageHandler::end(const TQString&, const TQString&, const TQString&) {
+ bool readInfo = true;
+ if(d->loadImages) {
+ TQByteArray ba;
+ KCodecs::base64Decode(TQCString(d->text.latin1()), ba);
+ if(!ba.isEmpty()) {
+ TQString result = ImageFactory::addImage(ba, m_format, m_imageId);
+ if(result.isEmpty()) {
+ myDebug() << "TellicoImporter::readImage(XML) - null image for " << m_imageId << endl;
+ }
+ d->hasImages = true;
+ readInfo = false;
+ }
+ }
+ if(readInfo) {
+ // a width or height of 0 is ok here
+ Data::ImageInfo info(m_imageId, m_format.latin1(), m_width, m_height, m_link);
+ ImageFactory::cacheImageInfo(info);
+ }
+ return true;
+}
+
+StateHandler* FiltersHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("filter")) {
+ return new FilterHandler(d);
+ }
+ return 0;
+}
+
+bool FiltersHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ return true;
+}
+
+bool FiltersHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+StateHandler* FilterHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("rule")) {
+ return new FilterRuleHandler(d);
+ }
+ return 0;
+}
+
+bool FilterHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ d->filter = new Filter(Filter::MatchAny);
+ d->filter->setName(attValue(atts_, "name"));
+
+ if(attValue(atts_, "match") == Latin1Literal("all")) {
+ d->filter->setMatch(Filter::MatchAll);
+ }
+ return true;
+}
+
+bool FilterHandler::end(const TQString&, const TQString&, const TQString&) {
+ if(d->coll && !d->filter->isEmpty()) {
+ d->coll->addFilter(d->filter);
+ }
+ d->filter = FilterPtr();
+ return true;
+}
+
+bool FilterRuleHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ TQString field = attValue(atts_, "field");
+ // empty field means match any of them
+ TQString pattern = attValue(atts_, "pattern");
+ // empty pattern is bad
+ if(pattern.isEmpty()) {
+ myWarning() << "FilterRuleHandler::start() - empty rule!" << endl;
+ return true;
+ }
+ TQString function = attValue(atts_, "function").lower();
+ FilterRule::Function func;
+ if(function == Latin1Literal("contains")) {
+ func = FilterRule::FuncContains;
+ } else if(function == Latin1Literal("notcontains")) {
+ func = FilterRule::FuncNotContains;
+ } else if(function == Latin1Literal("equals")) {
+ func = FilterRule::FuncEquals;
+ } else if(function == Latin1Literal("notequals")) {
+ func = FilterRule::FuncNotEquals;
+ } else if(function == Latin1Literal("regexp")) {
+ func = FilterRule::FuncRegExp;
+ } else if(function == Latin1Literal("notregexp")) {
+ func = FilterRule::FuncNotRegExp;
+ } else {
+ myWarning() << "FilterRuleHandler::start() - invalid rule function: " << function << endl;
+ return true;
+ }
+ d->filter->append(new FilterRule(field, pattern, func));
+ return true;
+}
+
+bool FilterRuleHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+StateHandler* BorrowersHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("borrower")) {
+ return new BorrowerHandler(d);
+ }
+ return 0;
+}
+
+bool BorrowersHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) {
+ return true;
+}
+
+bool BorrowersHandler::end(const TQString&, const TQString&, const TQString&) {
+ return true;
+}
+
+StateHandler* BorrowerHandler::nextHandlerImpl(const TQString&, const TQString& localName_, const TQString&) {
+ if(localName_ == Latin1Literal("loan")) {
+ return new LoanHandler(d);
+ }
+ return 0;
+}
+
+bool BorrowerHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ TQString name = attValue(atts_, "name");
+ TQString uid = attValue(atts_, "uid");
+ d->borrower = new Data::Borrower(name, uid);
+
+ return true;
+}
+
+bool BorrowerHandler::end(const TQString&, const TQString&, const TQString&) {
+ if(d->coll && !d->borrower->isEmpty()) {
+ d->coll->addBorrower(d->borrower);
+ }
+ d->borrower = Data::BorrowerPtr();
+ return true;
+}
+
+bool LoanHandler::start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes& atts_) {
+ m_id = attValue(atts_, "entryRef").toInt();
+ m_uid = attValue(atts_, "uid");
+ m_loanDate = attValue(atts_, "loanDate");
+ m_dueDate = attValue(atts_, "dueDate");
+ m_inCalendar = attValue(atts_, "calendar") == Latin1Literal("true");
+ return true;
+}
+
+bool LoanHandler::end(const TQString&, const TQString&, const TQString&) {
+ Data::EntryPtr entry = d->coll->entryById(m_id);
+ if(!entry) {
+ myWarning() << "LoanHandler::end() - no entry with id = " << m_id << endl;
+ return true;
+ }
+ TQDate loanDate, dueDate;
+ if(!m_loanDate.isEmpty()) {
+ loanDate = TQDate::fromString(m_loanDate, TQt::ISODate);
+ }
+ if(!m_dueDate.isEmpty()) {
+ dueDate = TQDate::fromString(m_dueDate, TQt::ISODate);
+ }
+
+ Data::LoanPtr loan = new Data::Loan(entry, loanDate, dueDate, d->text);
+ loan->setUID(m_uid);
+ loan->setInCalendar(m_inCalendar);
+ d->borrower->addLoan(loan);
+ return true;
+}
+
diff --git a/src/translators/xmlstatehandler.h b/src/translators/xmlstatehandler.h
new file mode 100644
index 0000000..8b5c137
--- /dev/null
+++ b/src/translators/xmlstatehandler.h
@@ -0,0 +1,345 @@
+/***************************************************************************
+ copyright : (C) 2008 by Robby Stephenson
+ email : robby@periapsis.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of version 2 of the GNU General Public License as *
+ * published by the Free Software Foundation; *
+ * *
+ ***************************************************************************/
+
+#ifndef TELLICO_IMPORT_XMLSTATEHANDLER_H
+#define TELLICO_IMPORT_XMLSTATEHANDLER_H
+
+#ifdef QT_NO_CAST_ASCII
+#define HAD_QT_NO_CAST_ASCII
+#undef QT_NO_CAST_ASCII
+#endif
+
+#include <tqxml.h>
+
+#ifdef HAD_QT_NO_CAST_ASCII
+#define QT_NO_CAST_ASCII
+#undef HAD_QT_NO_CAST_ASCII
+#endif
+
+#include "../datavectors.h"
+
+namespace Tellico {
+ namespace Import {
+ namespace SAX {
+
+class StateData {
+public:
+ TQString text;
+ TQString error;
+ TQString ns; // namespace
+ TQString textBuffer;
+ uint syntaxVersion;
+ TQString collTitle;
+ int collType;
+ TQString entryName;
+ Data::CollPtr coll;
+ Data::FieldVec fields;
+ Data::FieldPtr currentField;
+ Data::EntryVec entries;
+ FilterPtr filter;
+ Data::BorrowerPtr borrower;
+ bool defaultFields;
+ bool loadImages;
+ bool hasImages;
+};
+
+class StateHandler {
+public:
+ StateHandler(StateData* data) : d(data) {}
+ virtual ~StateHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) = 0;
+ virtual bool end(const TQString&, const TQString&, const TQString&) = 0;
+
+ StateHandler* nextHandler(const TQString&, const TQString&, const TQString&);
+protected:
+ StateData* d;
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&) { return 0; }
+};
+
+class NullHandler : public StateHandler {
+public:
+ NullHandler(StateData* data) : StateHandler(data) {}
+ virtual ~NullHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) { return true; }
+ virtual bool end(const TQString&, const TQString&, const TQString&) { return true; }
+};
+
+class RootHandler : public StateHandler {
+public:
+ RootHandler(StateData* data) : StateHandler(data) {}
+ virtual ~RootHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&) { return true; }
+ virtual bool end(const TQString&, const TQString&, const TQString&) { return true; }
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class DocumentHandler : public StateHandler {
+public:
+ DocumentHandler(StateData* data) : StateHandler(data) {}
+ virtual ~DocumentHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class CollectionHandler : public StateHandler {
+public:
+ CollectionHandler(StateData* data) : StateHandler(data) {}
+ virtual ~CollectionHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class FieldsHandler : public StateHandler {
+public:
+ FieldsHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FieldsHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class FieldHandler : public StateHandler {
+public:
+ FieldHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FieldHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class FieldPropertyHandler : public StateHandler {
+public:
+ FieldPropertyHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FieldPropertyHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ TQString m_propertyName;
+};
+
+class BibtexPreambleHandler : public StateHandler {
+public:
+ BibtexPreambleHandler(StateData* data) : StateHandler(data) {}
+ virtual ~BibtexPreambleHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+};
+
+class BibtexMacrosHandler : public StateHandler {
+public:
+ BibtexMacrosHandler(StateData* data) : StateHandler(data) {}
+ virtual ~BibtexMacrosHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class BibtexMacroHandler : public StateHandler {
+public:
+ BibtexMacroHandler(StateData* data) : StateHandler(data) {}
+ virtual ~BibtexMacroHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ TQString m_macroName;
+};
+
+class EntryHandler : public StateHandler {
+public:
+ EntryHandler(StateData* data) : StateHandler(data) {}
+ virtual ~EntryHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class FieldValueContainerHandler : public StateHandler {
+public:
+ FieldValueContainerHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FieldValueContainerHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class FieldValueHandler : public StateHandler {
+public:
+ FieldValueHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FieldValueHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+ bool m_i18n;
+ bool m_validateISBN;
+};
+
+class DateValueHandler : public StateHandler {
+public:
+ DateValueHandler(StateData* data) : StateHandler(data) {}
+ virtual ~DateValueHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+};
+
+class TableColumnHandler : public StateHandler {
+public:
+ TableColumnHandler(StateData* data) : StateHandler(data) {}
+ virtual ~TableColumnHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+};
+
+class ImagesHandler : public StateHandler {
+public:
+ ImagesHandler(StateData* data) : StateHandler(data) {}
+ virtual ~ImagesHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class ImageHandler : public StateHandler {
+public:
+ ImageHandler(StateData* data) : StateHandler(data) {}
+ virtual ~ImageHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ TQString m_format;
+ bool m_link;
+ TQString m_imageId;
+ int m_width;
+ int m_height;
+};
+
+class FiltersHandler : public StateHandler {
+public:
+ FiltersHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FiltersHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class FilterHandler : public StateHandler {
+public:
+ FilterHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FilterHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class FilterRuleHandler : public StateHandler {
+public:
+ FilterRuleHandler(StateData* data) : StateHandler(data) {}
+ virtual ~FilterRuleHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+};
+
+class BorrowersHandler : public StateHandler {
+public:
+ BorrowersHandler(StateData* data) : StateHandler(data) {}
+ virtual ~BorrowersHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class BorrowerHandler : public StateHandler {
+public:
+ BorrowerHandler(StateData* data) : StateHandler(data) {}
+ virtual ~BorrowerHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ virtual StateHandler* nextHandlerImpl(const TQString&, const TQString&, const TQString&);
+};
+
+class LoanHandler : public StateHandler {
+public:
+ LoanHandler(StateData* data) : StateHandler(data) {}
+ virtual ~LoanHandler() {}
+
+ virtual bool start(const TQString&, const TQString&, const TQString&, const TQXmlAttributes&);
+ virtual bool end(const TQString&, const TQString&, const TQString&);
+
+private:
+ int m_id;
+ TQString m_uid;
+ TQString m_loanDate;
+ TQString m_dueDate;
+ bool m_inCalendar;
+};
+
+ }
+ }
+}
+#endif
diff --git a/src/translators/xsltexporter.cpp b/src/translators/xsltexporter.cpp
index c08ee0f..b0642b3 100644
--- a/src/translators/xsltexporter.cpp
+++ b/src/translators/xsltexporter.cpp
@@ -18,6 +18,8 @@
#include <tdelocale.h>
#include <kurlrequester.h>
+#include <kuser.h>
+#include <tdeconfig.h>
#include <tqlabel.h>
#include <tqgroupbox.h>
@@ -49,6 +51,9 @@ bool XSLTExporter::exec() {
}
// XSLTHandler handler(FileHandler::readXMLFile(url));
XSLTHandler handler(u);
+ handler.addStringParam("date", TQDate::currentDate().toString(TQt::ISODate).latin1());
+ handler.addStringParam("time", TQTime::currentTime().toString(TQt::ISODate).latin1());
+ handler.addStringParam("user", KUser(KUser::UseRealUserID).loginName().latin1());
TellicoXMLExporter exporter;
exporter.setEntries(entries());
@@ -75,6 +80,25 @@ TQWidget* XSLTExporter::widget(TQWidget* parent_, const char* name_/*=0*/) {
m_URLRequester = new KURLRequester(box);
TQWhatsThis::add(m_URLRequester, i18n("Choose the XSLT file used to transform the Tellico XML data."));
+ TQString filter = i18n("*.xsl|XSL Files (*.xsl)") + TQChar('\n');
+ filter += i18n("*|All Files");
+ m_URLRequester->setFilter(filter);
+ m_URLRequester->setMode(static_cast<KFile::Mode>(KFile::File | KFile::ExistingOnly));
+ if(!m_xsltFile.isEmpty()) {
+ m_URLRequester->setURL(m_xsltFile);
+ }
+
l->addStretch(1);
return m_widget;
}
+
+void XSLTExporter::readOptions(TDEConfig* config_) {
+ TDEConfigGroup group(config_, TQString::fromLatin1("ExportOptions - %1").arg(formatString()));
+ m_xsltFile = group.readEntry("Last File", TQString());
+}
+
+void XSLTExporter::saveOptions(TDEConfig* config_) {
+ TDEConfigGroup group(config_, TQString::fromLatin1("ExportOptions - %1").arg(formatString()));
+ m_xsltFile = m_URLRequester->url();
+ group.writeEntry("Last File", m_xsltFile);
+}
diff --git a/src/translators/xsltexporter.h b/src/translators/xsltexporter.h
index b14afd3..8b808e5 100644
--- a/src/translators/xsltexporter.h
+++ b/src/translators/xsltexporter.h
@@ -34,9 +34,13 @@ public:
virtual TQWidget* widget(TQWidget* parent, const char* name=0);
+ virtual void readOptions(TDEConfig* cfg);
+ virtual void saveOptions(TDEConfig* cfg);
+
private:
TQWidget* m_widget;
KURLRequester* m_URLRequester;
+ TQString m_xsltFile;
};
} // end namespace
diff --git a/src/upcvalidator.cpp b/src/upcvalidator.cpp
index 73cc0d6..e3aca4e 100644
--- a/src/upcvalidator.cpp
+++ b/src/upcvalidator.cpp
@@ -13,6 +13,7 @@
#include "upcvalidator.h"
#include "isbnvalidator.h"
+#include "tellico_debug.h"
#include <kmdcodec.h>
@@ -24,7 +25,7 @@ UPCValidator::UPCValidator(TQObject* parent_, const char* name_/*=0*/)
TQValidator::State UPCValidator::validate(TQString& input_, int& pos_) const {
// check if it's a cuecat first
- State catState = decodeCat(input_);
+ State catState = CueCat::decode(input_);
if(catState == Acceptable) {
pos_ = input_.length();
return catState;
@@ -91,18 +92,18 @@ void UPCValidator::fixup(TQString& input_) const {
}
}
-TQValidator::State UPCValidator::decodeCat(TQString& input_) const {
+TQValidator::State Tellico::CueCat::decode(TQString& input_) {
if(input_.length() < 3) {
- return Intermediate;
+ return TQValidator::Intermediate;
}
if(!input_.startsWith(TQString::fromLatin1(".C3"))) { // all cuecat codes start with .C3
- return Invalid;
+ return TQValidator::Invalid;
}
const int periods = input_.contains('.');
if(periods < 4) {
- return Intermediate; // not enough yet
+ return TQValidator::Intermediate; // not enough yet
} else if(periods > 4) {
- return Invalid;
+ return TQValidator::Invalid;
}
// ok, let's have a go, take the third token
@@ -127,7 +128,7 @@ TQValidator::State UPCValidator::decodeCat(TQString& input_) const {
}
input_ = code;
- return Acceptable;
+ return TQValidator::Acceptable;
}
#include "upcvalidator.moc"
diff --git a/src/upcvalidator.h b/src/upcvalidator.h
index 5931c79..854dc62 100644
--- a/src/upcvalidator.h
+++ b/src/upcvalidator.h
@@ -37,11 +37,14 @@ signals:
void signalISBN();
private:
- State decodeCat(TQString& str) const;
-
bool m_checkISBN : 1;
mutable bool m_isbn : 1;
};
+class CueCat {
+public:
+ static TQValidator::State decode(TQString& str);
+};
+
} // end namespace
#endif