Update to upstream version 1.3.6

pull/1/head
Slávek Banko 10 years ago
parent 3c13229d98
commit 2e02da046d

@ -1,3 +1,84 @@
2009-09-26 Robby Stephenson <robby@periapsis.org>
* Updated Amazon fetcher to use authentication.
* Released Tellico 1.3.6
2009-02-14 Robby Stephenson <robby@periapsis.org>
* Released Tellico 1.3.5.
2009-02-04 Robby Stephenson <robby@periapsis.org>
* Reverted change from 2007 that merged entries by combining all values in multiple-value fields.
2009-02-02 Robby Stephenson <robby@periapsis.org>
* Fixed the CueCat decoder to work for ISBN searches, as well as UPC.
2009-01-30 Robby Stephenson <robby@periapsis.org>
* Updated Deliciour Library 1 importer to handle movies and games.
* Fixed Ubuntu bug#317822, don't mark collection modified when image is found in local data directory.
* Fixed query bug with z39.50 ISBN search.
2008-12-07 Robby Stephenson <robby@periapsis.org>
* Updated it.po, thanks to Valerio Ricci.
2008-10-23 Robby Stephenson <robby@periapsis.org>
* Added date, time, and username as available params for the XSLT export.
2008-09-13 Robby Stephenson <robby@periapsis.org>
* Released Tellico 1.3.4.
2008-09-04 Robby Stephenson <robby@periapsis.org>
* Fixed error with consecutive tabs in CSV import.
2008-08-26 Robby Stephenson <robby@periapsis.org>
* Fixed bug with image links in reports not being linked correctly.
2008-08-20 Robby Stephenson <robby@periapsis.org>
* Added minimal searching for board games from Amazon.
2008-08-07 Robby Stephenson <robby@periapsis.org>
* Changed Choice fields to sort by position in list.
2008-07-25 Robby Stephenson <robby@periapsis.org>
* Added ESC key for clearing quick filter.
* Improved drag/drop to match on file extension after checking mimetype.
2008-07-22 Robby Stephenson <robby@periapsis.org>
* Updated IMDb plot regexp.
2008-07-09 Robby Stephenson <robby@periapsis.org>
* Fixed EntryView to honor copy() command properly, for clipboard.
* Released Tellico 1.3.3.
2008-06-24 Robby Stephenson <robby@periapsis.org>
* Updated Porbase URL in z39.50 server list.
2008-06-13 Robby Stephenson <robby@periapsis.org>
* Updated drag-and-drop to allow HTTP urls.
2008-06-12 Robby Stephenson <robby@periapsis.org>
* Changed Arxiv fetcher to remove ID version number for results.
2008-06-07 Robby Stephenson <robby@periapsis.org>
* Fixed bug with merging file catalogs, to properly match on URL.
2008-05-24 Robby Stephenson <robby@periapsis.org> 2008-05-24 Robby Stephenson <robby@periapsis.org>
* Released Tellico 1.3.2.1. * Released Tellico 1.3.2.1.

@ -66,6 +66,9 @@
/* Define if you have libz */ /* Define if you have libz */
#undef HAVE_LIBZ #undef HAVE_LIBZ
/* Define to 1 if you have the <linux/videodev.h> header file. */
#undef HAVE_LINUX_VIDEODEV_H
/* Define to 1 if you have the <memory.h> header file. */ /* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H #undef HAVE_MEMORY_H
@ -174,6 +177,9 @@
/* Define to the version of this package. */ /* Define to the version of this package. */
#undef PACKAGE_VERSION #undef PACKAGE_VERSION
/* Define to 1 if the XML loader should use SAX */
#undef SAX_SUPPORT
/* The size of `char', as computed by sizeof. */ /* The size of `char', as computed by sizeof. */
#undef SIZEOF_CHAR #undef SIZEOF_CHAR

@ -40,7 +40,7 @@ dnl Perform program name transformation
AC_ARG_PROGRAM AC_ARG_PROGRAM
dnl Automake doc recommends to do this only here. (Janos) dnl Automake doc recommends to do this only here. (Janos)
AM_INIT_AUTOMAKE(tellico, 1.3.2.1) dnl searches for some needed programs AM_INIT_AUTOMAKE(tellico, 1.3.6) dnl searches for some needed programs
KDE_SET_PREFIX KDE_SET_PREFIX
@ -491,7 +491,8 @@ AC_ARG_WITH([ooo-dir],
AC_HELP_STRING([--with-ooo-dir=DIR], AC_HELP_STRING([--with-ooo-dir=DIR],
[where the OpenOffice.org program files are installed]), [where the OpenOffice.org program files are installed]),
[ac_ooo_libdir="${withval}/program" [ac_ooo_libdir="${withval}/program"
ac_ooo_datadir="${withval}/program"]) ac_ooo_datadir="${withval}/program"
ac_ooo_basisdir="${withval}/basis3.0"])
AC_ARG_WITH([ooo-libdir], AC_ARG_WITH([ooo-libdir],
AC_HELP_STRING([--with-ooo-libdir=DIR], AC_HELP_STRING([--with-ooo-libdir=DIR],
[where the OpenOffice.org program libraries are installed (<ooo-dir>/program)]), [where the OpenOffice.org program libraries are installed (<ooo-dir>/program)]),
@ -542,6 +543,13 @@ AC_CHECK_FILE([$ac_ooo_datadir/types.rdb],
[OFFICE_registry="$ac_ooo_datadir"/types.rdb], [OFFICE_registry="$ac_ooo_datadir"/types.rdb],
AC_MSG_ERROR([[types.rdb not found, try '--with-ooo-dir=OpenOffice.org_installation_path']])) AC_MSG_ERROR([[types.rdb not found, try '--with-ooo-dir=OpenOffice.org_installation_path']]))
AC_FIND_FILE([offapi.rdb],
[$ac_ooo_basisdir/program $ac_ooo_libdir $ac_ooo_datadir],
offapi_dir)
if test "$offapi_dir" != "NO"; then
OFFICE_registry="$OFFICE_registry $offapi_dir/offapi.rdb"
fi
dnl Substitute the values dnl Substitute the values
AC_SUBST(OFFICE_SDK_includes) AC_SUBST(OFFICE_SDK_includes)
AC_SUBST(OFFICE_libadd) AC_SUBST(OFFICE_libadd)
@ -562,7 +570,7 @@ AC_ARG_ENABLE(exempi,
) )
if test x$enable_libexempi = xyes; then if test x$enable_libexempi = xyes; then
KDE_PKG_CHECK_MODULES(EXEMPI, KDE_PKG_CHECK_MODULES(EXEMPI,
[exempi-2.0 >= 1.99.0], [exempi-2.0 >= 1.99.0],
[have_exempi=yes], [have_exempi=yes],
[have_exempi=no]) [have_exempi=no])
@ -586,8 +594,8 @@ AC_ARG_ENABLE(poppler,
) )
if test x$enable_libpoppler = xyes; then if test x$enable_libpoppler = xyes; then
KDE_PKG_CHECK_MODULES(POPPLER, KDE_PKG_CHECK_MODULES(POPPLER,
[poppler-qt >= 0.5], [poppler-tqt >= 0.5],
[have_poppler=yes], [have_poppler=yes],
[have_poppler=no]) [have_poppler=no])
AC_SUBST(POPPLER_LIBS) AC_SUBST(POPPLER_LIBS)
@ -609,12 +617,32 @@ AC_ARG_ENABLE(webcam,
[enable_webcam=no] [enable_webcam=no]
) )
if test x$enable_webcam = xyes; then
KDE_CHECK_HEADERS([linux/videodev.h],
[],
[enable_webcam="no"])
fi
AM_CONDITIONAL(ENABLE_WEBCAM, test $enable_webcam = yes) AM_CONDITIONAL(ENABLE_WEBCAM, test $enable_webcam = yes)
if test x$enable_webcam = xyes; then if test x$enable_webcam = xyes; then
AC_DEFINE(ENABLE_WEBCAM, 1, [Define to 1 if webcam support is enabled]) AC_DEFINE(ENABLE_WEBCAM, 1, [Define to 1 if webcam support is enabled])
fi fi
dnl ---------- END WEBCAM CHECK ---------- dnl ---------- END WEBCAM CHECK ----------
dnl ---------- SAX CHECK ----------
AC_ARG_ENABLE(sax,
AC_HELP_STRING([--enable-sax], [enable SAX document loading (experimental), default=disable]),
[enable_sax=$enableval],
[enable_sax=no]
)
if test x$enable_sax = xyes; then
AC_DEFINE(SAX_SUPPORT, 1, [Define to 1 if the XML loader should use SAX])
fi
dnl ---------- END SAX CHECK ----------
KDE_CREATE_SUBDIRSLIST KDE_CREATE_SUBDIRSLIST
AC_CONFIG_FILES([ Makefile ]) AC_CONFIG_FILES([ Makefile ])
AC_CONFIG_FILES([ doc/Makefile ]) AC_CONFIG_FILES([ doc/Makefile ])

@ -2,7 +2,7 @@
KDE_ENABLE_HIDDEN_VISIBILITY KDE_ENABLE_HIDDEN_VISIBILITY
AM_INIT_AUTOMAKE(tellico,1.3.2.1) AM_INIT_AUTOMAKE(tellico,1.3.6)
dnl AM_KDE_MIN_VERSION(MIN-VERSION-MAJOR, MIN-VERSION-MINOR, MIN-VERSION-MICRO) dnl AM_KDE_MIN_VERSION(MIN-VERSION-MAJOR, MIN-VERSION-MINOR, MIN-VERSION-MICRO)
dnl (taken from KMyMoney2) dnl (taken from KMyMoney2)
@ -428,7 +428,8 @@ AC_ARG_WITH([ooo-dir],
AC_HELP_STRING([--with-ooo-dir=DIR], AC_HELP_STRING([--with-ooo-dir=DIR],
[where the OpenOffice.org program files are installed]), [where the OpenOffice.org program files are installed]),
[ac_ooo_libdir="${withval}/program" [ac_ooo_libdir="${withval}/program"
ac_ooo_datadir="${withval}/program"]) ac_ooo_datadir="${withval}/program"
ac_ooo_basisdir="${withval}/basis3.0"])
AC_ARG_WITH([ooo-libdir], AC_ARG_WITH([ooo-libdir],
AC_HELP_STRING([--with-ooo-libdir=DIR], AC_HELP_STRING([--with-ooo-libdir=DIR],
[where the OpenOffice.org program libraries are installed (<ooo-dir>/program)]), [where the OpenOffice.org program libraries are installed (<ooo-dir>/program)]),
@ -479,6 +480,13 @@ AC_CHECK_FILE([$ac_ooo_datadir/types.rdb],
[OFFICE_registry="$ac_ooo_datadir"/types.rdb], [OFFICE_registry="$ac_ooo_datadir"/types.rdb],
AC_MSG_ERROR([[types.rdb not found, try '--with-ooo-dir=OpenOffice.org_installation_path']])) AC_MSG_ERROR([[types.rdb not found, try '--with-ooo-dir=OpenOffice.org_installation_path']]))
AC_FIND_FILE([offapi.rdb],
[$ac_ooo_basisdir/program $ac_ooo_libdir $ac_ooo_datadir],
offapi_dir)
if test "$offapi_dir" != "NO"; then
OFFICE_registry="$OFFICE_registry $offapi_dir/offapi.rdb"
fi
dnl Substitute the values dnl Substitute the values
AC_SUBST(OFFICE_SDK_includes) AC_SUBST(OFFICE_SDK_includes)
AC_SUBST(OFFICE_libadd) AC_SUBST(OFFICE_libadd)
@ -499,7 +507,7 @@ AC_ARG_ENABLE(exempi,
) )
if test x$enable_libexempi = xyes; then if test x$enable_libexempi = xyes; then
KDE_PKG_CHECK_MODULES(EXEMPI, KDE_PKG_CHECK_MODULES(EXEMPI,
[exempi-2.0 >= 1.99.0], [exempi-2.0 >= 1.99.0],
[have_exempi=yes], [have_exempi=yes],
[have_exempi=no]) [have_exempi=no])
@ -523,8 +531,8 @@ AC_ARG_ENABLE(poppler,
) )
if test x$enable_libpoppler = xyes; then if test x$enable_libpoppler = xyes; then
KDE_PKG_CHECK_MODULES(POPPLER, KDE_PKG_CHECK_MODULES(POPPLER,
[poppler-qt >= 0.5], [poppler-tqt >= 0.5],
[have_poppler=yes], [have_poppler=yes],
[have_poppler=no]) [have_poppler=no])
AC_SUBST(POPPLER_LIBS) AC_SUBST(POPPLER_LIBS)
@ -546,9 +554,36 @@ AC_ARG_ENABLE(webcam,
[enable_webcam=no] [enable_webcam=no]
) )
if test x$enable_webcam = xyes; then
KDE_CHECK_HEADERS([linux/videodev.h],
[],
[enable_webcam="no"])
fi
AM_CONDITIONAL(ENABLE_WEBCAM, test $enable_webcam = yes) AM_CONDITIONAL(ENABLE_WEBCAM, test $enable_webcam = yes)
if test x$enable_webcam = xyes; then if test x$enable_webcam = xyes; then
AC_DEFINE(ENABLE_WEBCAM, 1, [Define to 1 if webcam support is enabled]) AC_DEFINE(ENABLE_WEBCAM, 1, [Define to 1 if webcam support is enabled])
fi fi
dnl ---------- END WEBCAM CHECK ---------- dnl ---------- END WEBCAM CHECK ----------
dnl ---------- SAX CHECK ----------
AC_ARG_ENABLE(sax,
AC_HELP_STRING([--enable-sax], [enable SAX document loading (experimental), default=disable]),
[enable_sax=$enableval],
[enable_sax=no]
)
if test x$enable_sax = xyes; then
AC_DEFINE(SAX_SUPPORT, 1, [Define to 1 if the XML loader should use SAX])
fi
dnl ---------- END SAX CHECK ----------
dnl -------- fix TQTDCOPIDLNG ---------
if test "$kde_cv_tqt" = "no"; then
if test -z "$TQTDCOPIDLNG"; then
KDE_FIND_PATH(dcopidlng, TQTDCOPIDLNG, [$kde_default_bindirs], [KDE_MISSING_PROG_ERROR(dcopidlng)])
fi
fi

@ -2,4 +2,22 @@ To regenerate the message strings, type
make package-messages make package-messages
from the top-level directory from the top-level directory.
Please note that you need a special for KDE patched version of xgettext. You
can obtain it from http://packages.ubuntu.com/de/edgy/gettext-kde. Don't forget
to make this binary available as xgettext (instead of kde-xgettext) by e.g.
creating a link in your search path.
If you don't do this, code such as i18n("Comic Book Illustrator", "Artist")
would correspond to two separate strings "Comic Book Illustrator" and
"Artist" instead of a combined entry from which only the second one has to be
translated:
msgid ""
"_: Comic Book Illustrator\n"
"Artist"
msgstr "Künstler"
You also need the tool extractrc. In Debian it is available in the package
tdesdk-scripts.

@ -16,7 +16,7 @@ msgid ""
msgstr "" msgstr ""
"Project-Id-Version: de\n" "Project-Id-Version: de\n"
"POT-Creation-Date: 2008-01-26 10:52-0800\n" "POT-Creation-Date: 2008-01-26 10:52-0800\n"
"PO-Revision-Date: 2008-01-25 10:34+0100\n" "PO-Revision-Date: 2008-05-24 22:47+0200\n"
"Last-Translator: Jens Seidel <jensseidel@users.sf.net>\n" "Last-Translator: Jens Seidel <jensseidel@users.sf.net>\n"
"Language-Team: german <de@li.org>\n" "Language-Team: german <de@li.org>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
@ -1094,7 +1094,7 @@ msgstr "Mechanismus"
#: collections/boardgamecollection.cpp:66 #: collections/boardgamecollection.cpp:66
msgid "Designer" msgid "Designer"
msgstr "" msgstr "Designer"
#: collections/boardgamecollection.cpp:72 #: collections/boardgamecollection.cpp:72
msgid "Number of Players" msgid "Number of Players"
@ -1792,7 +1792,7 @@ msgstr ""
#: fetch/discogsfetcher.cpp:718 #: fetch/discogsfetcher.cpp:718
msgid "Discogs Link" msgid "Discogs Link"
msgstr "" msgstr "Discogs-Link"
#: newstuff/dialog.cpp:94 #: newstuff/dialog.cpp:94
msgid "Get Hot New Stuff" msgid "Get Hot New Stuff"
@ -1986,9 +1986,8 @@ msgid "Scanning audio files..."
msgstr "Taste Audio-Dateien ab ..." msgstr "Taste Audio-Dateien ab ..."
#: translators/audiofileimporter.cpp:129 #: translators/audiofileimporter.cpp:129
#, fuzzy
msgid "Bitrate" msgid "Bitrate"
msgstr "Bibtex" msgstr "Bitrate"
#: translators/audiofileimporter.cpp:160 translators/audiofileimporter.cpp:170 #: translators/audiofileimporter.cpp:160 translators/audiofileimporter.cpp:170
msgid "Tracks (Disc %1)" msgid "Tracks (Disc %1)"
@ -2023,14 +2022,12 @@ msgstr ""
#: translators/audiofileimporter.cpp:352 #: translators/audiofileimporter.cpp:352
msgid "Include &bitrate" msgid "Include &bitrate"
msgstr "" msgstr "&Bitrate inkludieren"
#: translators/audiofileimporter.cpp:353 #: translators/audiofileimporter.cpp:353
#, fuzzy
msgid "If checked, the bitrate for each track is added to the entries." msgid "If checked, the bitrate for each track is added to the entries."
msgstr "" msgstr ""
"Wenn markiert, werden die Datei-Namen für jede Spur zu den Einträgen " "Wenn markiert, wird die Bitrate für jede Spur zu den Einträgen hinzugefügt."
"hinzugefügt."
#: translators/csvexporter.cpp:40 #: translators/csvexporter.cpp:40
msgid "CSV" msgid "CSV"
@ -5369,7 +5366,7 @@ msgstr "Copac (Großbritannien und Irland)"
#: scripts.cpp:2 #: scripts.cpp:2
msgid "BoardGameGeek" msgid "BoardGameGeek"
msgstr "" msgstr "BoardGameGeek"
#: scripts.cpp:4 #: scripts.cpp:4
msgid "Dark Horse Comics" msgid "Dark Horse Comics"

1851
po/it.po

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,19 +1,22 @@
# translation of ru.po to Russian # translation of ru.po to Russian
# Copyright (C) 2007 Robby Stephenson <robby@periapsis.org>.
# Калимуллин Артур <kalimullin@gmail.com>, 2006. # Калимуллин Артур <kalimullin@gmail.com>, 2006.
# Kalimullin Artur <kalimullin@gmail.com>, 2006. # Kalimullin Artur <kalimullin@gmail.com>, 2006.
# Pesotsky Denis <St.MPA3b@gmail.com>, 2008. # Pesotsky Denis <St.MPA3b@gmail.com>, 2008.
# Copyright (C) 2007 Robby Stephenson <robby@periapsis.org>. # Denis Pesotsky <St.MPA3b@gmail.com>, 2008.
# Denis Pesotsky <denis@kde.ru>, 2008.
msgid "" msgid ""
msgstr "" msgstr ""
"Project-Id-Version: ru\n" "Project-Id-Version: ru\n"
"POT-Creation-Date: 2008-01-26 10:52-0800\n" "POT-Creation-Date: 2008-01-26 10:52-0800\n"
"PO-Revision-Date: 2008-03-21 00:44+0300\n" "PO-Revision-Date: 2008-10-22 21:27+0400\n"
"Last-Translator: Pesotsky Denis <St.MPA3b@gmail.com>\n" "Last-Translator: Denis Pesotsky <denis@kde.ru>\n"
"Language-Team: Russian <kde-russian@lists.kde.ru>\n" "Language-Team: Russian <kde-russian@lists.kde.ru>\n"
"MIME-Version: 1.0\n" "MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n" "Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n" "Content-Transfer-Encoding: 8bit\n"
"X-Generator: KBabel 1.11.4\n" "X-Generator: Lokalize 0.2\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
#: cite/lyxpipe.cpp:50 #: cite/lyxpipe.cpp:50
msgid "<qt>Tellico is unable to write to the server pipe at <b>%1</b>.</qt>" msgid "<qt>Tellico is unable to write to the server pipe at <b>%1</b>.</qt>"
@ -21,7 +24,7 @@ msgstr "<qt>Ошибка записи на канал сервера <b>%1</b>.<
#: cite/openoffice.cpp:82 #: cite/openoffice.cpp:82
msgid "Connecting to OpenOffice.org..." msgid "Connecting to OpenOffice.org..."
msgstr "Подсоединение к OpenOffice.org..." msgstr "Подсоединение к OpenOffice.org"
#: cite/openoffice.cpp:165 cite/openoffice.cpp:186 #: cite/openoffice.cpp:165 cite/openoffice.cpp:186
msgid "OpenOffice.org Connection" msgid "OpenOffice.org Connection"
@ -115,7 +118,7 @@ msgstr "Очистить"
#: gui/imagewidget.cpp:57 #: gui/imagewidget.cpp:57
msgid "Select Image..." msgid "Select Image..."
msgstr "Выбрать изображение..." msgstr "Выбрать изображение"
#: gui/imagewidget.cpp:63 #: gui/imagewidget.cpp:63
msgid "Save link only" msgid "Save link only"
@ -652,7 +655,7 @@ msgstr "Создан"
#: collections/filecatalog.cpp:89 #: collections/filecatalog.cpp:89
msgid "Modified" msgid "Modified"
msgstr "Модифицирован" msgstr "Изменён"
#: collections/filecatalog.cpp:93 #: collections/filecatalog.cpp:93
msgid "Meta Info" msgid "Meta Info"
@ -1780,7 +1783,7 @@ msgstr "Описание выделенного отображается зде
#: newstuff/dialog.cpp:224 #: newstuff/dialog.cpp:224
msgid "Downloading information..." msgid "Downloading information..."
msgstr "Загрузка информации..." msgstr "Загрузка информации"
#: controller.cpp:135 fetchdialog.cpp:226 fetchdialog.cpp:333 #: controller.cpp:135 fetchdialog.cpp:226 fetchdialog.cpp:333
#: fetchdialog.cpp:451 fetchdialog.cpp:506 newstuff/dialog.cpp:297 #: fetchdialog.cpp:451 fetchdialog.cpp:506 newstuff/dialog.cpp:297
@ -1796,7 +1799,7 @@ msgstr "Обновить"
#: newstuff/dialog.cpp:413 #: newstuff/dialog.cpp:413
msgid "Installing item..." msgid "Installing item..."
msgstr "Установка...." msgstr "Установка"
#: translators/bibteximporter.cpp:79 #: translators/bibteximporter.cpp:79
msgid "No valid bibtex entries were found" msgid "No valid bibtex entries were found"
@ -1913,7 +1916,7 @@ msgstr "Избранное"
#: translators/audiofileimporter.cpp:69 #: translators/audiofileimporter.cpp:69
msgid "Scanning audio files..." msgid "Scanning audio files..."
msgstr "Сканируются аудио-файлы..." msgstr "Сканируются аудио-файлы"
#: translators/audiofileimporter.cpp:129 #: translators/audiofileimporter.cpp:129
msgid "Bitrate" msgid "Bitrate"
@ -2025,7 +2028,7 @@ msgstr "Может быть использован любой другой ра
#: translators/filelistingimporter.cpp:63 #: translators/filelistingimporter.cpp:63
msgid "Scanning files..." msgid "Scanning files..."
msgstr "Сканируются файлы..." msgstr "Сканируются файлы"
#: translators/filelistingimporter.cpp:191 #: translators/filelistingimporter.cpp:191
msgid "File Listing Options" msgid "File Listing Options"
@ -2192,11 +2195,11 @@ msgstr ""
#: translators/importer.h:100 #: translators/importer.h:100
msgid "Loading data..." msgid "Loading data..."
msgstr "Загружаются данные..." msgstr "Загружаются данные"
#: translators/importer.h:100 #: translators/importer.h:100
msgid "Loading %1..." msgid "Loading %1..."
msgstr "Загружается %1..." msgstr "Загружается %1"
#: translators/bibtexexporter.cpp:48 #: translators/bibtexexporter.cpp:48
msgid "Bibtex" msgid "Bibtex"
@ -2484,7 +2487,7 @@ msgstr "не соответствует выражению"
#: filterdialog.cpp:90 #: filterdialog.cpp:90
msgid "Edit..." msgid "Edit..."
msgstr "Редактировать..." msgstr "Редактировать"
#: filterdialog.cpp:282 #: filterdialog.cpp:282
msgid "Advanced Filter" msgid "Advanced Filter"
@ -2540,11 +2543,11 @@ msgstr "Дата"
#: entryupdater.cpp:81 #: entryupdater.cpp:81
msgid "Updating %1..." msgid "Updating %1..."
msgstr "Обновление %1..." msgstr "Обновление %1"
#: entryupdater.cpp:83 #: entryupdater.cpp:83
msgid "Updating entries..." msgid "Updating entries..."
msgstr "Обновление записей..." msgstr "Обновление записей"
#: entryupdater.cpp:85 #: entryupdater.cpp:85
msgid "Update Entries" msgid "Update Entries"
@ -2552,7 +2555,7 @@ msgstr "Обновить записи"
#: entryupdater.cpp:99 #: entryupdater.cpp:99
msgid "Updating <b>%1</b>..." msgid "Updating <b>%1</b>..."
msgstr "Обновление <b>%1</b>..." msgstr "Обновление <b>%1</b>"
#: entryupdater.cpp:209 #: entryupdater.cpp:209
msgid "Select Match" msgid "Select Match"
@ -2875,11 +2878,11 @@ msgstr "Сохранить документ"
#: mainwindow.cpp:305 #: mainwindow.cpp:305
msgid "Save the document as a different file..." msgid "Save the document as a different file..."
msgstr "Сохранить документ в другой файл..." msgstr "Сохранить документ в другой файл"
#: mainwindow.cpp:307 #: mainwindow.cpp:307
msgid "Print the contents of the document..." msgid "Print the contents of the document..."
msgstr "Напечатать содержимое этого документа..." msgstr "Напечатать содержимое этого документа"
#: mainwindow.cpp:309 #: mainwindow.cpp:309
msgid "Quit the application" msgid "Quit the application"
@ -2891,7 +2894,7 @@ msgstr "Импортировать коллекцию из других форм
#: mainwindow.cpp:324 #: mainwindow.cpp:324
msgid "Import Tellico Data..." msgid "Import Tellico Data..."
msgstr "Импорт из файла Tellico..." msgstr "Импорт из файла Tellico"
#: mainwindow.cpp:325 #: mainwindow.cpp:325
msgid "Import another Tellico data file" msgid "Import another Tellico data file"
@ -2899,7 +2902,7 @@ msgstr "Импортировать из другой коллекции Tellico"
#: mainwindow.cpp:331 #: mainwindow.cpp:331
msgid "Import CSV Data..." msgid "Import CSV Data..."
msgstr "Импорт из CSV..." msgstr "Импорт из CSV"
#: mainwindow.cpp:332 #: mainwindow.cpp:332
msgid "Import a CSV file" msgid "Import a CSV file"
@ -2907,7 +2910,7 @@ msgstr "Импорт из файла CSV"
#: mainwindow.cpp:338 #: mainwindow.cpp:338
msgid "Import MODS Data..." msgid "Import MODS Data..."
msgstr "Импорт из MODS..." msgstr "Импорт из MODS"
#: mainwindow.cpp:339 #: mainwindow.cpp:339
msgid "Import a MODS data file" msgid "Import a MODS data file"
@ -2915,7 +2918,7 @@ msgstr "Импорт из файла MODS"
#: mainwindow.cpp:345 #: mainwindow.cpp:345
msgid "Import Alexandria Data..." msgid "Import Alexandria Data..."
msgstr "Импорт из файла Alexandria..." msgstr "Импорт из файла Alexandria"
#: mainwindow.cpp:346 #: mainwindow.cpp:346
msgid "Import data from the Alexandria book collection manager" msgid "Import data from the Alexandria book collection manager"
@ -2923,7 +2926,7 @@ msgstr "Импорт из менеджера коллекций книг Alexand
#: mainwindow.cpp:352 #: mainwindow.cpp:352
msgid "Import Delicious Library Data..." msgid "Import Delicious Library Data..."
msgstr "Импорт из файла Delicious..." msgstr "Импорт из файла Delicious"
#: mainwindow.cpp:353 #: mainwindow.cpp:353
msgid "Import data from Delicious Library" msgid "Import data from Delicious Library"
@ -2931,7 +2934,7 @@ msgstr "Импорт данных из файла Delicious"
#: mainwindow.cpp:359 #: mainwindow.cpp:359
msgid "Import Referencer Data..." msgid "Import Referencer Data..."
msgstr "Импорт из файла Referencer..." msgstr "Импорт из файла Referencer"
#: mainwindow.cpp:360 #: mainwindow.cpp:360
msgid "Import data from Referencer" msgid "Import data from Referencer"
@ -2939,7 +2942,7 @@ msgstr "Импортировать данные из Referencer"
#: mainwindow.cpp:366 #: mainwindow.cpp:366
msgid "Import Bibtex Data..." msgid "Import Bibtex Data..."
msgstr "Импорт из Bibtex..." msgstr "Импорт из Bibtex"
#: mainwindow.cpp:367 #: mainwindow.cpp:367
msgid "Import a bibtex bibliography file" msgid "Import a bibtex bibliography file"
@ -2947,7 +2950,7 @@ msgstr "Импортировать из файла библиографии bibt
#: mainwindow.cpp:373 #: mainwindow.cpp:373
msgid "Import Bibtexml Data..." msgid "Import Bibtexml Data..."
msgstr "Импорт из Bibtexml..." msgstr "Импорт из Bibtexml"
#: mainwindow.cpp:374 #: mainwindow.cpp:374
msgid "Import a Bibtexml bibliography file" msgid "Import a Bibtexml bibliography file"
@ -2955,7 +2958,7 @@ msgstr "Импортировать из файла библиографии Bibt
#: mainwindow.cpp:380 #: mainwindow.cpp:380
msgid "Import RIS Data..." msgid "Import RIS Data..."
msgstr "Импорт из RIS..." msgstr "Импорт из RIS"
#: mainwindow.cpp:381 #: mainwindow.cpp:381
msgid "Import an RIS reference file" msgid "Import an RIS reference file"
@ -2963,7 +2966,7 @@ msgstr "Импортировать из файла RIS"
#: mainwindow.cpp:387 #: mainwindow.cpp:387
msgid "Import PDF File..." msgid "Import PDF File..."
msgstr "Импорт из PDF..." msgstr "Импорт из PDF"
#: mainwindow.cpp:388 #: mainwindow.cpp:388
msgid "Import a PDF file" msgid "Import a PDF file"
@ -2971,7 +2974,7 @@ msgstr "Импортировать из файла PDF"
#: mainwindow.cpp:394 #: mainwindow.cpp:394
msgid "Import Audio File Metadata..." msgid "Import Audio File Metadata..."
msgstr "Импорт из данных аудио файла..." msgstr "Импорт из данных аудио файла"
#: mainwindow.cpp:395 #: mainwindow.cpp:395
msgid "Import meta-data from audio files" msgid "Import meta-data from audio files"
@ -2979,7 +2982,7 @@ msgstr "Импорт из данных тегов аудио файлов"
#: mainwindow.cpp:404 #: mainwindow.cpp:404
msgid "Import Audio CD Data..." msgid "Import Audio CD Data..."
msgstr "Импорт из Audio CD..." msgstr "Импорт из Audio CD"
#: mainwindow.cpp:405 #: mainwindow.cpp:405
msgid "Import audio CD information" msgid "Import audio CD information"
@ -2987,7 +2990,7 @@ msgstr "Импорт информации об Audio CD"
#: mainwindow.cpp:414 #: mainwindow.cpp:414
msgid "Import GCstar Data..." msgid "Import GCstar Data..."
msgstr "Импорт из файла GCstar..." msgstr "Импорт из файла GCstar"
#: mainwindow.cpp:415 #: mainwindow.cpp:415
msgid "Import a GCstar data file" msgid "Import a GCstar data file"
@ -2995,7 +2998,7 @@ msgstr "Импорт данных из файла GCstar"
#: mainwindow.cpp:421 #: mainwindow.cpp:421
msgid "Import Griffith Data..." msgid "Import Griffith Data..."
msgstr "Импорт из файла Griffith..." msgstr "Импорт из файла Griffith"
#: mainwindow.cpp:422 #: mainwindow.cpp:422
msgid "Import a Griffith database" msgid "Import a Griffith database"
@ -3003,7 +3006,7 @@ msgstr "Импортировать из файла Griffith"
#: mainwindow.cpp:428 #: mainwindow.cpp:428
msgid "Import Ant Movie Catalog Data..." msgid "Import Ant Movie Catalog Data..."
msgstr "Импорт из файла Ant..." msgstr "Импорт из файла Ant"
#: mainwindow.cpp:429 #: mainwindow.cpp:429
msgid "Import an Ant Movie Catalog data file" msgid "Import an Ant Movie Catalog data file"
@ -3011,7 +3014,7 @@ msgstr "Импортировать из файла менеджера колле
#: mainwindow.cpp:435 #: mainwindow.cpp:435
msgid "Import File Listing..." msgid "Import File Listing..."
msgstr "Импорт списка фалов..." msgstr "Импорт списка фалов"
#: mainwindow.cpp:436 #: mainwindow.cpp:436
msgid "Import information about files in a folder" msgid "Import information about files in a folder"
@ -3019,7 +3022,7 @@ msgstr "Импортировать информацию о файлах в па
#: mainwindow.cpp:442 #: mainwindow.cpp:442
msgid "Import XSL Transform..." msgid "Import XSL Transform..."
msgstr "Импорт из XSLT..." msgstr "Импорт из XSLT"
#: mainwindow.cpp:443 #: mainwindow.cpp:443
msgid "Import using an XSL Transform" msgid "Import using an XSL Transform"
@ -3036,7 +3039,7 @@ msgstr "Экспортировать данные коллекции в друг
#: mainwindow.cpp:461 #: mainwindow.cpp:461
msgid "Export to XML..." msgid "Export to XML..."
msgstr "Экспорт в XML..." msgstr "Экспорт в XML"
#: mainwindow.cpp:462 #: mainwindow.cpp:462
msgid "Export to a Tellico XML file" msgid "Export to a Tellico XML file"
@ -3044,7 +3047,7 @@ msgstr "Экспорт в XML-файл Tellico"
#: mainwindow.cpp:468 #: mainwindow.cpp:468
msgid "Export to Zip..." msgid "Export to Zip..."
msgstr "Экспорт в ZIP..." msgstr "Экспорт в ZIP"
#: mainwindow.cpp:469 #: mainwindow.cpp:469
msgid "Export to a Tellico Zip file" msgid "Export to a Tellico Zip file"
@ -3052,7 +3055,7 @@ msgstr "Экспорт в сжатый ZIP файл Tellico"
#: mainwindow.cpp:475 #: mainwindow.cpp:475
msgid "Export to HTML..." msgid "Export to HTML..."
msgstr "Экспорт в HTML..." msgstr "Экспорт в HTML"
#: mainwindow.cpp:476 #: mainwindow.cpp:476
msgid "Export to an HTML file" msgid "Export to an HTML file"
@ -3060,7 +3063,7 @@ msgstr "Экспорт в файл HTML"
#: mainwindow.cpp:482 #: mainwindow.cpp:482
msgid "Export to CSV..." msgid "Export to CSV..."
msgstr "Экспорт в CSV..." msgstr "Экспорт в CSV"
#: mainwindow.cpp:483 #: mainwindow.cpp:483
msgid "Export to a comma-separated values file" msgid "Export to a comma-separated values file"
@ -3068,7 +3071,7 @@ msgstr "Экспорт в текстовый файл с разделённым
#: mainwindow.cpp:489 #: mainwindow.cpp:489
msgid "Export to PilotDB..." msgid "Export to PilotDB..."
msgstr "Экспорт в PilotDB..." msgstr "Экспорт в PilotDB"
#: mainwindow.cpp:490 #: mainwindow.cpp:490
msgid "Export to a PilotDB database" msgid "Export to a PilotDB database"
@ -3076,7 +3079,7 @@ msgstr "Экспортировать в базу данных PilotDB"
#: mainwindow.cpp:496 #: mainwindow.cpp:496
msgid "Export to Alexandria..." msgid "Export to Alexandria..."
msgstr "Экспорт в Alexandria..." msgstr "Экспорт в Alexandria"
#: mainwindow.cpp:497 #: mainwindow.cpp:497
msgid "Export to an Alexandria library" msgid "Export to an Alexandria library"
@ -3084,7 +3087,7 @@ msgstr "Экспорт в библиотеку Alexandria"
#: mainwindow.cpp:503 #: mainwindow.cpp:503
msgid "Export to Bibtex..." msgid "Export to Bibtex..."
msgstr "Экспорт в Bibtex..." msgstr "Экспорт в Bibtex"
#: mainwindow.cpp:504 #: mainwindow.cpp:504
msgid "Export to a bibtex file" msgid "Export to a bibtex file"
@ -3092,7 +3095,7 @@ msgstr "Экспорт в файл Bibtex"
#: mainwindow.cpp:510 #: mainwindow.cpp:510
msgid "Export to Bibtexml..." msgid "Export to Bibtexml..."
msgstr "Экспорт в Bibtexml..." msgstr "Экспорт в Bibtexml"
#: mainwindow.cpp:511 #: mainwindow.cpp:511
msgid "Export to a Bibtexml file" msgid "Export to a Bibtexml file"
@ -3100,7 +3103,7 @@ msgstr "Экспорт в файл Bibtexml"
#: mainwindow.cpp:517 #: mainwindow.cpp:517
msgid "Export to ONIX..." msgid "Export to ONIX..."
msgstr "Экспорт в ONIX..." msgstr "Экспорт в ONIX"
#: mainwindow.cpp:518 #: mainwindow.cpp:518
msgid "Export to an ONIX file" msgid "Export to an ONIX file"
@ -3108,7 +3111,7 @@ msgstr "Экспорт в файл ONIX"
#: mainwindow.cpp:524 #: mainwindow.cpp:524
msgid "Export to GCfilms..." msgid "Export to GCfilms..."
msgstr "Экспорт в GCfilms..." msgstr "Экспорт в GCfilms"
#: mainwindow.cpp:525 #: mainwindow.cpp:525
msgid "Export to a GCfilms data file" msgid "Export to a GCfilms data file"
@ -3116,7 +3119,7 @@ msgstr "Экспорт в файл GCfilms"
#: mainwindow.cpp:531 #: mainwindow.cpp:531
msgid "Export to GCstar..." msgid "Export to GCstar..."
msgstr "Экспорт в GCStar..." msgstr "Экспорт в GCStar"
#: mainwindow.cpp:532 #: mainwindow.cpp:532
msgid "Export to a GCstar data file" msgid "Export to a GCstar data file"
@ -3124,7 +3127,7 @@ msgstr "Экспорт в файл GCfilms"
#: mainwindow.cpp:536 #: mainwindow.cpp:536
msgid "Export XSL Transform..." msgid "Export XSL Transform..."
msgstr "Экспорт в XSLT..." msgstr "Экспорт в XSLT"
#: mainwindow.cpp:537 #: mainwindow.cpp:537
msgid "Export using an XSL Transform" msgid "Export using an XSL Transform"
@ -3152,15 +3155,15 @@ msgstr "Отменить выделение записей в коллекции
#: mainwindow.cpp:556 #: mainwindow.cpp:556
msgid "Internet Search..." msgid "Internet Search..."
msgstr "Поиск в интернете..." msgstr "Поиск в интернете"
#: mainwindow.cpp:559 #: mainwindow.cpp:559
msgid "Search the internet..." msgid "Search the internet..."
msgstr "Повести поиск в интернете для создания новой записи в коллекции..." msgstr "Повести поиск в интернете для создания новой записи в коллекции"
#: mainwindow.cpp:561 #: mainwindow.cpp:561
msgid "Advanced &Filter..." msgid "Advanced &Filter..."
msgstr "Продвинутый &фильтр..." msgstr "Продвинутый &фильтр"
#: mainwindow.cpp:564 mainwindow.cpp:719 #: mainwindow.cpp:564 mainwindow.cpp:719
msgid "Filter the collection" msgid "Filter the collection"
@ -3168,7 +3171,7 @@ msgstr "Фильтр коллекции"
#: mainwindow.cpp:569 #: mainwindow.cpp:569
msgid "&New Entry..." msgid "&New Entry..."
msgstr "&Новая запись..." msgstr "&Новая запись"
#: mainwindow.cpp:572 #: mainwindow.cpp:572
msgid "Create a new entry" msgid "Create a new entry"
@ -3176,7 +3179,7 @@ msgstr "Создать новую запись"
#: controller.cpp:620 mainwindow.cpp:573 #: controller.cpp:620 mainwindow.cpp:573
msgid "&Edit Entry..." msgid "&Edit Entry..."
msgstr "&Редактировать запись..." msgstr "&Редактировать запись"
#: mainwindow.cpp:576 #: mainwindow.cpp:576
msgid "Edit the selected entries" msgid "Edit the selected entries"
@ -3208,7 +3211,7 @@ msgstr "Объединить выделенные записи"
#: mainwindow.cpp:591 #: mainwindow.cpp:591
msgid "&Generate Reports..." msgid "&Generate Reports..."
msgstr "Создать от&чет..." msgstr "Создать от&чет"
#: mainwindow.cpp:594 #: mainwindow.cpp:594
msgid "Generate collection reports" msgid "Generate collection reports"
@ -3216,7 +3219,7 @@ msgstr "Создать отчет о коллекции"
#: mainwindow.cpp:595 #: mainwindow.cpp:595
msgid "Check-&out..." msgid "Check-&out..."
msgstr "&Отдать в долг..." msgstr "&Отдать в долг"
#: mainwindow.cpp:598 #: mainwindow.cpp:598
msgid "Check-out the selected items" msgid "Check-out the selected items"
@ -3232,7 +3235,7 @@ msgstr "Вернуть из долга выделенные записи"
#: mainwindow.cpp:604 #: mainwindow.cpp:604
msgid "&Rename Collection..." msgid "&Rename Collection..."
msgstr "&Переименовать коллекцию..." msgstr "&Переименовать коллекцию"
#: mainwindow.cpp:607 #: mainwindow.cpp:607
msgid "Rename the collection" msgid "Rename the collection"
@ -3256,7 +3259,7 @@ msgstr "Конвертировать коллекцию книг в библио
#: mainwindow.cpp:616 #: mainwindow.cpp:616
msgid "String &Macros..." msgid "String &Macros..."
msgstr "Строчный &макрос..." msgstr "Строчный &макрос"
#: mainwindow.cpp:619 #: mainwindow.cpp:619
msgid "Edit the bibtex string macros" msgid "Edit the bibtex string macros"
@ -3357,7 +3360,7 @@ msgstr "Очистить фильтр"
#: mainwindow.cpp:710 #: mainwindow.cpp:710
msgid "Filter here..." msgid "Filter here..."
msgstr "Фильтр..." msgstr "Фильтр"
#: mainwindow.cpp:768 #: mainwindow.cpp:768
msgid "Groups" msgid "Groups"
@ -3399,11 +3402,11 @@ msgstr ""
#: mainwindow.cpp:1066 #: mainwindow.cpp:1066
msgid "Creating new document..." msgid "Creating new document..."
msgstr "Создание нового документа..." msgstr "Создание нового документа"
#: mainwindow.cpp:1098 mainwindow.cpp:1117 mainwindow.cpp:1135 #: mainwindow.cpp:1098 mainwindow.cpp:1117 mainwindow.cpp:1135
msgid "Opening file..." msgid "Opening file..."
msgstr "Открытие файла..." msgstr "Открытие файла"
#: mainwindow.cpp:1108 #: mainwindow.cpp:1108
msgid "Open File" msgid "Open File"
@ -3411,7 +3414,7 @@ msgstr "Открыть файл"
#: document.cpp:192 mainwindow.cpp:1215 #: document.cpp:192 mainwindow.cpp:1215
msgid "Saving file..." msgid "Saving file..."
msgstr "Сохранение файла...." msgstr "Сохранение файла."
#: mainwindow.cpp:1226 #: mainwindow.cpp:1226
msgid "" msgid ""
@ -3435,11 +3438,11 @@ msgstr "Сохранять изображения вместе с файлом"
#: mainwindow.cpp:1265 #: mainwindow.cpp:1265
msgid "Saving file with a new filename..." msgid "Saving file with a new filename..."
msgstr "Сохранение файла под другим именем..." msgstr "Сохранение файла под другим именем"
#: mainwindow.cpp:1303 mainwindow.cpp:1353 #: mainwindow.cpp:1303 mainwindow.cpp:1353
msgid "Printing..." msgid "Printing..."
msgstr "Идёт печать..." msgstr "Идёт печать"
#: mainwindow.cpp:1312 #: mainwindow.cpp:1312
msgid "" msgid ""
@ -3451,11 +3454,11 @@ msgstr ""
#: mainwindow.cpp:1337 #: mainwindow.cpp:1337
msgid "Processing document..." msgid "Processing document..."
msgstr "Подождите..." msgstr "Подождите"
#: mainwindow.cpp:1360 #: mainwindow.cpp:1360
msgid "Exiting..." msgid "Exiting..."
msgstr "Выход..." msgstr "Выход"
#: mainwindow.cpp:1498 #: mainwindow.cpp:1498
#, c-format #, c-format
@ -3490,7 +3493,7 @@ msgstr "Пожалуйста, проверьте свою инсталляцию
#: mainwindow.cpp:1849 #: mainwindow.cpp:1849
msgid "Importing data..." msgid "Importing data..."
msgstr "Импорт данных..." msgstr "Импорт данных"
#: mainwindow.cpp:1858 #: mainwindow.cpp:1858
msgid "Import File" msgid "Import File"
@ -3502,7 +3505,7 @@ msgstr "Импорт каталога"
#: mainwindow.cpp:1885 #: mainwindow.cpp:1885
msgid "Exporting data..." msgid "Exporting data..."
msgstr "Экспортирование данных..." msgstr "Экспортирование данных"
#: mainwindow.cpp:1907 #: mainwindow.cpp:1907
msgid "Export As" msgid "Export As"
@ -3522,7 +3525,7 @@ msgstr "Строка"
#: mainwindow.cpp:1999 #: mainwindow.cpp:1999
msgid "Creating citations..." msgid "Creating citations..."
msgstr "Идет создание цитат..." msgstr "Идет создание цитат"
#: mainwindow.cpp:2104 #: mainwindow.cpp:2104
msgid "Filters" msgid "Filters"
@ -3598,7 +3601,7 @@ msgstr "Удалить несколько записей"
#: controller.cpp:626 #: controller.cpp:626
msgid "&Edit Entries..." msgid "&Edit Entries..."
msgstr "&Редактировать записи..." msgstr "&Редактировать записи"
#: controller.cpp:627 #: controller.cpp:627
msgid "D&uplicate Entries" msgid "D&uplicate Entries"
@ -3862,7 +3865,7 @@ msgstr "Дополнительные &параметры:"
#: collectionfieldsdialog.cpp:217 #: collectionfieldsdialog.cpp:217
msgid "&Set..." msgid "&Set..."
msgstr "&Установить..." msgstr "&Установить"
#: collectionfieldsdialog.cpp:221 #: collectionfieldsdialog.cpp:221
msgid "" msgid ""
@ -4242,11 +4245,11 @@ msgstr ""
#: configdialog.cpp:380 #: configdialog.cpp:380
msgid "&Preview..." msgid "&Preview..."
msgstr "&Пред-просмотр..." msgstr "&Предпросмотр…"
#: configdialog.cpp:381 #: configdialog.cpp:381
msgid "Show a preview of the template" msgid "Show a preview of the template"
msgstr "Показать пред-просмотр шаблона" msgstr "Показать предпросмотр шаблона"
#: configdialog.cpp:398 #: configdialog.cpp:398
msgid "Font Options" msgid "Font Options"
@ -4294,7 +4297,7 @@ msgstr "Управление шаблонами"
#: configdialog.cpp:475 #: configdialog.cpp:475
msgid "Install..." msgid "Install..."
msgstr "Установить..." msgstr "Установить"
#: configdialog.cpp:478 #: configdialog.cpp:478
msgid "Click to install a new template directly." msgid "Click to install a new template directly."
@ -4302,7 +4305,7 @@ msgstr "Нажмите для установки шаблона."
#: configdialog.cpp:481 configdialog.cpp:537 #: configdialog.cpp:481 configdialog.cpp:537
msgid "Download..." msgid "Download..."
msgstr "Загрузить..." msgstr "Загрузить"
#: configdialog.cpp:484 #: configdialog.cpp:484
msgid "Click to download additional templates via the Internet." msgid "Click to download additional templates via the Internet."
@ -4310,7 +4313,7 @@ msgstr "Нажмите для загрузки дополнительных ша
#: configdialog.cpp:487 #: configdialog.cpp:487
msgid "Delete..." msgid "Delete..."
msgstr "Удалить..." msgstr "Удалить"
#: configdialog.cpp:490 #: configdialog.cpp:490
msgid "Click to select and remove installed templates." msgid "Click to select and remove installed templates."
@ -4346,7 +4349,7 @@ msgstr "&Ниже"
#: configdialog.cpp:528 #: configdialog.cpp:528
msgid "&New..." msgid "&New..."
msgstr "&Новый..." msgstr "&Новый"
#: configdialog.cpp:530 #: configdialog.cpp:530
msgid "Click to add a new data source." msgid "Click to add a new data source."
@ -4354,7 +4357,7 @@ msgstr "Нажмите для создания нового источника
#: configdialog.cpp:531 #: configdialog.cpp:531
msgid "&Modify..." msgid "&Modify..."
msgstr "&Редактировать..." msgstr "&Редактировать"
#: configdialog.cpp:533 #: configdialog.cpp:533
msgid "Click to modify the selected data source." msgid "Click to modify the selected data source."
@ -4390,7 +4393,7 @@ msgstr "Вернуть из долга"
#: loanview.cpp:76 #: loanview.cpp:76
msgid "Modify Loan..." msgid "Modify Loan..."
msgstr "Редактировать долг..." msgstr "Редактировать долг"
#: loanview.cpp:93 #: loanview.cpp:93
msgid "Borrower (Sort by Count)" msgid "Borrower (Sort by Count)"
@ -4556,7 +4559,7 @@ msgstr "Если отмечено, будет проведен многокра
#: fetchdialog.cpp:138 #: fetchdialog.cpp:138
msgid "Edit List..." msgid "Edit List..."
msgstr "Редактировать список..." msgstr "Редактировать список"
#: fetchdialog.cpp:140 #: fetchdialog.cpp:140
msgid "Click to open a text edit box for entering or editing multiple ISBN values." msgid "Click to open a text edit box for entering or editing multiple ISBN values."
@ -4606,11 +4609,11 @@ msgstr "Очистить все поля поиска и результаты"
#: fetchdialog.cpp:298 #: fetchdialog.cpp:298
msgid "Cancelling the search..." msgid "Cancelling the search..."
msgstr "Отмена поиска..." msgstr "Отмена поиска"
#: fetchdialog.cpp:313 fetchdialog.cpp:472 #: fetchdialog.cpp:313 fetchdialog.cpp:472
msgid "Searching..." msgid "Searching..."
msgstr "Поиск..." msgstr "Поиск"
#: fetchdialog.cpp:368 #: fetchdialog.cpp:368
msgid "The search returned no items." msgid "The search returned no items."
@ -4631,7 +4634,7 @@ msgstr "Никаких записей не было найдено по след
#: fetchdialog.cpp:443 fetchdialog.cpp:495 #: fetchdialog.cpp:443 fetchdialog.cpp:495
msgid "Fetching %1..." msgid "Fetching %1..."
msgstr "Загрузка %1..." msgstr "Загрузка %1"
#: fetchdialog.cpp:528 fetchdialog.cpp:708 #: fetchdialog.cpp:528 fetchdialog.cpp:708
msgid "No Internet sources are available for your current collection type." msgid "No Internet sources are available for your current collection type."
@ -4647,7 +4650,7 @@ msgstr "<qt>Введите значения ISBN/UPC, по одному в ст
#: fetchdialog.cpp:604 #: fetchdialog.cpp:604
msgid "&Load From File..." msgid "&Load From File..."
msgstr "&Загрузить из файла..." msgstr "&Загрузить из файла"
#: fetchdialog.cpp:605 #: fetchdialog.cpp:605
msgid "<qt>Load the list from a text file.</qt>" msgid "<qt>Load the list from a text file.</qt>"
@ -4805,15 +4808,15 @@ msgstr "Калимуллин Артур, Песоцкий Денис"
msgid "" msgid ""
"_: EMAIL OF TRANSLATORS\n" "_: EMAIL OF TRANSLATORS\n"
"Your emails" "Your emails"
msgstr "kalimullin@gmail.com, St.MPA3b@gmail.com" msgstr "kalimullin@gmail.com, denis@kde.ru"
#: entrymerger.cpp:35 #: entrymerger.cpp:35
msgid "Merging entries..." msgid "Merging entries..."
msgstr "Объединение записей..." msgstr "Объединение записей"
#: entrymerger.cpp:49 #: entrymerger.cpp:49
msgid "Total merged/scanned entries: %1/%2" msgid "Total merged/scanned entries: %1/%2"
msgstr "Всего записей объединено/просканировано: %1" msgstr "Всего записей объединено/просканировано: %1/%2"
#: tips.cpp:3 #: tips.cpp:3
msgid "" msgid ""
@ -4823,7 +4826,7 @@ msgid ""
"<p>Any other field which allows multiple values should be entered the\n" "<p>Any other field which allows multiple values should be entered the\n"
"same way, with a semi-colon (;) separating each value.</p>\n" "same way, with a semi-colon (;) separating each value.</p>\n"
msgstr "" msgstr ""
"<p>...что если книга имеет больше, чем одного автора, то вам следует " "<p>что если книга имеет больше, чем одного автора, то вам следует "
"разделять\n" "разделять\n"
"точкой с запятой (;). Таким образом, Tellico будет разделять их имена.</p>\n" "точкой с запятой (;). Таким образом, Tellico будет разделять их имена.</p>\n"
"<p>Любое другое поле также поддерживает эту функцию. Для этого вам следует\n" "<p>Любое другое поле также поддерживает эту функцию. Для этого вам следует\n"
@ -4835,7 +4838,7 @@ msgid ""
"<p>...that you can change which fields are shown in the list view by\n" "<p>...that you can change which fields are shown in the list view by\n"
"right-clicking on the column header.\n" "right-clicking on the column header.\n"
msgstr "" msgstr ""
"<p>...что вы можете выбрать какие поля следует показывать в списке записей,\n" "<p>что вы можете выбрать какие поля следует показывать в списке записей,\n"
"кликнув правой кнопкой мыши на заголовке \"таблицы\".\n" "кликнув правой кнопкой мыши на заголовке \"таблицы\".\n"
#: tips.cpp:16 #: tips.cpp:16
@ -4846,7 +4849,7 @@ msgid ""
"position of the field in the list, which affects the placement in the entry\n" "position of the field in the list, which affects the placement in the entry\n"
"editor.</p>\n" "editor.</p>\n"
msgstr "" msgstr ""
"<p>...что вы можете добавлять, редактировать или удалять поля в коллекции,\n" "<p>что вы можете добавлять, редактировать или удалять поля в коллекции,\n"
"используя Редактор полей. Кнопки стрелок позволяют вам менять позицию полей " "используя Редактор полей. Кнопки стрелок позволяют вам менять позицию полей "
"в списке,\n" "в списке,\n"
"которая влияет на расстановку в Редакторе записей.</p>\n" "которая влияет на расстановку в Редакторе записей.</p>\n"
@ -4861,7 +4864,7 @@ msgid ""
"\"contains\" \"Science Fiction\" (no quotes) and the second rule to\n" "\"contains\" \"Science Fiction\" (no quotes) and the second rule to\n"
"have \"Read\" \"does not contain\" \"true\" (no quotes).</p>\n" "have \"Read\" \"does not contain\" \"true\" (no quotes).</p>\n"
msgstr "" msgstr ""
"<p>...что если вы хотите отфильтровать записи по полю \"Выбор да/нет\",\n" "<p>что если вы хотите отфильтровать записи по полю \"Выбор да/нет\",\n"
"то должно использоваться значение \"да\". Например, если вы хотите " "то должно использоваться значение \"да\". Например, если вы хотите "
"посмотреть, какие детективы вы ещё не читали,\n" "посмотреть, какие детективы вы ещё не читали,\n"
"нажмите кнопку \"Соответствует всему следующему\",\n" "нажмите кнопку \"Соответствует всему следующему\",\n"
@ -4876,7 +4879,7 @@ msgid ""
"<p>To show only books which are by Weber or Bujold, for example, then\n" "<p>To show only books which are by Weber or Bujold, for example, then\n"
"type \"weber|bujold\" (no quotes) in the filter box.</p>\n" "type \"weber|bujold\" (no quotes) in the filter box.</p>\n"
msgstr "" msgstr ""
"<p>...что если в быстром фильтре используется символ, не входящий в слова " "<p>что если в быстром фильтре используется символ, не входящий в слова "
"(напр., ^)\n" "(напр., ^)\n"
"текст интерпретируется как регулярное выражение.</p>\n" "текст интерпретируется как регулярное выражение.</p>\n"
"<p>Например, чтобы посмотреть только книги, которые написали Пушкин и " "<p>Например, чтобы посмотреть только книги, которые написали Пушкин и "
@ -4888,7 +4891,7 @@ msgid ""
"<p>...that you can edit more than one entry at a time, by holding down\n" "<p>...that you can edit more than one entry at a time, by holding down\n"
"the Shift or Ctrl key and selecting multiple entries.</p>\n" "the Shift or Ctrl key and selecting multiple entries.</p>\n"
msgstr "" msgstr ""
"<p>...что за один раз вы можете отредактировать больше, чем одно поле.\n" "<p>что за один раз вы можете отредактировать больше, чем одно поле.\n"
"Для этого выделите несколько полей, зажимая клавиши Shift или Ctrl.</p>\n" "Для этого выделите несколько полей, зажимая клавиши Shift или Ctrl.</p>\n"
#: tips.cpp:45 #: tips.cpp:45
@ -4896,7 +4899,7 @@ msgid ""
"<p>...that you can convert an existing book collection to a bibliography,\n" "<p>...that you can convert an existing book collection to a bibliography,\n"
"which can then be exported to bibtex or Bibtexml format.</p>\n" "which can then be exported to bibtex or Bibtexml format.</p>\n"
msgstr "" msgstr ""
"<p>...что вы можете конвертировать текущую коллекцию книг в библиографию,\n" "<p>что вы можете конвертировать текущую коллекцию книг в библиографию,\n"
"которая может быть экспортирована в формат Bibtex или Bibtexml.</p>\n" "которая может быть экспортирована в формат Bibtex или Bibtexml.</p>\n"
#: tips.cpp:50 #: tips.cpp:50
@ -4904,7 +4907,7 @@ msgid ""
"<p>...that you can add, edit, and delete string macros for bibliographies.</" "<p>...that you can add, edit, and delete string macros for bibliographies.</"
"p>\n" "p>\n"
msgstr "" msgstr ""
"<p>...что вы можете добавлять, редактировать и удалять строковые макросы для " "<p>что вы можете добавлять, редактировать и удалять строковые макросы для "
"библиографий.</p>\n" "библиографий.</p>\n"
#: tips.cpp:54 #: tips.cpp:54
@ -4915,7 +4918,7 @@ msgid ""
"editors\n" "editors\n"
"to be sorted or printed together, for example.</p>\n" "to be sorted or printed together, for example.</p>\n"
msgstr "" msgstr ""
"<p>...что если более чем одно поле форматируется как \"имя\", то в " "<p>что если более чем одно поле форматируется как \"имя\", то в "
"коллекцию\n" "коллекцию\n"
"добавляется дополнительная группа \"Люди\", например, для сортировки и " "добавляется дополнительная группа \"Люди\", например, для сортировки и "
"печати вместе.</p>\n" "печати вместе.</p>\n"
@ -4927,7 +4930,7 @@ msgid ""
"CSS\n" "CSS\n"
"within the stylesheet governs things like the font, the margins, etc.</p>\n" "within the stylesheet governs things like the font, the margins, etc.</p>\n"
msgstr "" msgstr ""
"<p>...что вы можете менять внешний вид, печатаемых отчетов, редактируя\n" "<p>что вы можете менять внешний вид, печатаемых отчетов, редактируя\n"
"файл <tt>tellico-printing.xsl</tt>. Этот файл создает HTML и CSS\n" "файл <tt>tellico-printing.xsl</tt>. Этот файл создает HTML и CSS\n"
"с такими элементами как шрифт, размер и т.д. </p>\n" "с такими элементами как шрифт, размер и т.д. </p>\n"
@ -4936,12 +4939,12 @@ msgid ""
"<p>...that you can import using any generic XSL stylesheet which\n" "<p>...that you can import using any generic XSL stylesheet which\n"
"outputs a valid Tellico XML file.</p>\n" "outputs a valid Tellico XML file.</p>\n"
msgstr "" msgstr ""
"<p>...что вы можете импортировать, используя стандартный\n" "<p>что вы можете импортировать, используя стандартный\n"
"лист стилей XSL, на выходе получая правильный файл Tellico XML.</p>\n" "лист стилей XSL, на выходе получая правильный файл Tellico XML.</p>\n"
#: tips.cpp:71 #: tips.cpp:71
msgid "<p>...that double-clicking an entry item opens the Entry Editor.</p>\n" msgid "<p>...that double-clicking an entry item opens the Entry Editor.</p>\n"
msgstr "<p>...что двойной щелчок на записи открывает редактор записей.</p>\n" msgstr "<p>что двойной щелчок на записи открывает редактор записей.</p>\n"
#: tips.cpp:75 #: tips.cpp:75
msgid "" msgid ""
@ -4949,7 +4952,7 @@ msgid ""
"as\n" "as\n"
"&lt;b&gt;bold&lt;/b&gt; or &lt;i&gt;italic&lt;/i&gt;.</p>\n" "&lt;b&gt;bold&lt;/b&gt; or &lt;i&gt;italic&lt;/i&gt;.</p>\n"
msgstr "" msgstr ""
"<p>...что в любое поле типа \"Большой текст\" вы можете добавлять теги HTML, " "<p>что в любое поле типа \"Большой текст\" вы можете добавлять теги HTML, "
"такие как \n" "такие как \n"
"&lt;b&gt;жирный шрифт&lt;/b&gt; или &lt;i&gt;курсивный&lt;/i&gt;.</p>\n" "&lt;b&gt;жирный шрифт&lt;/b&gt; или &lt;i&gt;курсивный&lt;/i&gt;.</p>\n"
@ -4958,7 +4961,7 @@ msgid ""
"<p>...that in the Detailed View, you can press a letter on the\n" "<p>...that in the Detailed View, you can press a letter on the\n"
"keyboard to skip to the next entry that starts with that letter.</p>\n" "keyboard to skip to the next entry that starts with that letter.</p>\n"
msgstr "" msgstr ""
"<p>...что в подробном виде вы можете нажать кнопку буквы на клавиатуре для\n" "<p>что в подробном виде вы можете нажать кнопку буквы на клавиатуре для\n"
"перехода к записи, начинающейся с этой буквы.</p>\n" "перехода к записи, начинающейся с этой буквы.</p>\n"
#: tips.cpp:85 #: tips.cpp:85
@ -4973,9 +4976,9 @@ msgid ""
"types by respecting proper sorting at the same time. Consider for example\n" "types by respecting proper sorting at the same time. Consider for example\n"
"a number field followed by a text subfield with entries 3b, 14a.</p>\n" "a number field followed by a text subfield with entries 3b, 14a.</p>\n"
msgstr "" msgstr ""
"<p>...что вы можете использовать \"зависимые\" поля для комбинации\n" "<p>что вы можете использовать \"зависимые\" поля для комбинации\n"
"нескольких раздельных полей в одно. Просто выберите тип \"зависимый\" \n" "нескольких раздельных полей в одно. Просто выберите тип \"зависимый\" \n"
"и используйте описание вроде \"Значение: %{поле1}%{поле2}\", где %{...}\n" "и используйте описание вроде \"Значение: %{поле1}%{поле2}\", где %{}\n"
"заменяется на значение поля. Это полезно для использование различных\n" "заменяется на значение поля. Это полезно для использование различных\n"
"полей в одном поле, т.е. для лучшей группировки и для комбинации полей\n" "полей в одном поле, т.е. для лучшей группировки и для комбинации полей\n"
"различных типов с приоритетом правильной сортировки. Пример -\n" "различных типов с приоритетом правильной сортировки. Пример -\n"

@ -78,7 +78,7 @@ public:
const TQString& name() const { return m_name; } const TQString& name() const { return m_name; }
const LoanVec& loans() const { return m_loans; } const LoanVec& loans() const { return m_loans; }
bool isEmpty() const { return m_loans.isEmpty(); } 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); Data::LoanPtr loan(Data::ConstEntryPtr entry);
void addLoan(Data::LoanPtr loan); void addLoan(Data::LoanPtr loan);

@ -25,7 +25,7 @@ BorrowerItem::BorrowerItem(GUI::ListView* parent_, Data::BorrowerPtr borrower_)
setPixmap(0, SmallIcon(TQString::fromLatin1("kaddressbook"))); setPixmap(0, SmallIcon(TQString::fromLatin1("kaddressbook")));
} }
int BorrowerItem::count() const { size_t BorrowerItem::count() const {
return m_borrower ? m_borrower->count() : GUI::CountedItem::count(); return m_borrower ? m_borrower->count() : GUI::CountedItem::count();
} }

@ -29,7 +29,7 @@ public:
virtual bool isBorrowerItem() const { return true; } virtual bool isBorrowerItem() const { return true; }
Data::BorrowerPtr borrower() { return m_borrower; } Data::BorrowerPtr borrower() { return m_borrower; }
virtual int count() const; virtual size_t count() const;
virtual Data::EntryVec entries() const; virtual Data::EntryVec entries() const;
private: private:

@ -878,6 +878,9 @@ bool Collection::mergeEntry(EntryPtr e1, EntryPtr e2, bool overwrite_, bool askU
if(ret) { if(ret) {
e1->setField(field, vals1.join(TQString::fromLatin1("; "))); 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) { } else if(field->flags() & Data::Field::AllowMultiple) {
// if field F allows multiple values and not a Table (see above case), // 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) // 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(); // items1.sort();
e1->setField(field, items1.join(TQString::fromLatin1("; "))); e1->setField(field, items1.join(TQString::fromLatin1("; ")));
ret = true; ret = true;
#endif
} else if(askUser_ && e1->field(field) != e2->field(field)) { } else if(askUser_ && e1->field(field) != e2->field(field)) {
int ret = Kernel::self()->askAndMerge(e1, e2, field); int ret = Kernel::self()->askAndMerge(e1, e2, field);
if(ret == 0) { if(ret == 0) {

@ -254,7 +254,6 @@ CollectionFieldsDialog::CollectionFieldsDialog(Data::CollPtr coll_, TQWidget* pa
// need to stretch at bottom // need to stretch at bottom
vbox->setStretchFactor(new TQWidget(vbox), 1); vbox->setStretchFactor(new TQWidget(vbox), 1);
TDEAcceleratorManager::manage(vbox);
// keep a default collection // keep a default collection
m_defaultCollection = CollectionFactory::collection(m_coll->type(), true); m_defaultCollection = CollectionFactory::collection(m_coll->type(), true);
@ -279,6 +278,9 @@ CollectionFieldsDialog::~CollectionFieldsDialog() {
} }
void CollectionFieldsDialog::slotSelectInitial() { 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); m_fieldsBox->setSelected(0, true);
} }
@ -405,7 +407,7 @@ void CollectionFieldsDialog::slotNew() {
} }
TQString name = TQString::fromLatin1("custom") + TQString::number(m_newFields.count()+1); 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); TQString title = i18n("New Field") + TQString::fromLatin1(" %1").arg(count);
while(m_fieldsBox->findItem(title)) { while(m_fieldsBox->findItem(title)) {
++count; ++count;

@ -102,4 +102,21 @@ Tellico::Data::FieldVec FileCatalog::defaultFields() {
return list; 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" #include "filecatalog.moc"

@ -1,5 +1,5 @@
/*************************************************************************** /***************************************************************************
copyright : (C) 2005-2006 by Robby Stephenson copyright : (C) 2005-2008 by Robby Stephenson
email : robby@periapsis.org email : robby@periapsis.org
***************************************************************************/ ***************************************************************************/
@ -30,6 +30,7 @@ public:
FileCatalog(bool addFields, const TQString& title = TQString()); FileCatalog(bool addFields, const TQString& title = TQString());
virtual Type type() const { return File; } virtual Type type() const { return File; }
virtual int sameEntry(Data::EntryPtr entry1, Data::EntryPtr entry2) const;
static FieldVec defaultFields(); static FieldVec defaultFields();
}; };

@ -434,6 +434,7 @@ void Controller::slotDeleteSelectedEntries() {
int ret = KMessageBox::warningContinueCancel(Kernel::self()->widget(), str, i18n("Delete Entry"), int ret = KMessageBox::warningContinueCancel(Kernel::self()->widget(), str, i18n("Delete Entry"),
KGuiItem(i18n("&Delete"), TQString::fromLatin1("editdelete")), dontAsk); KGuiItem(i18n("&Delete"), TQString::fromLatin1("editdelete")), dontAsk);
if(ret != KMessageBox::Continue) { if(ret != KMessageBox::Continue) {
m_working = false;
return; return;
} }
} else { } else {
@ -448,6 +449,7 @@ void Controller::slotDeleteSelectedEntries() {
i18n("Delete Multiple Entries"), i18n("Delete Multiple Entries"),
KGuiItem(i18n("&Delete"), TQString::fromLatin1("editdelete")), dontAsk); KGuiItem(i18n("&Delete"), TQString::fromLatin1("editdelete")), dontAsk);
if(ret != KMessageBox::Continue) { if(ret != KMessageBox::Continue) {
m_working = false;
return; return;
} }
} }

@ -17,6 +17,8 @@ drophandler.h drophandler.cpp \
tellico-rename.upd tellico.upd \ tellico-rename.upd tellico.upd \
tellico-1-3-update.pl tellico-1-3-update.pl
dcopinterface_DCOPIDLNG = ALL
kde_kcfg_DATA = tellico_config.kcfg kde_kcfg_DATA = tellico_config.kcfg
updatedir = $(kde_datadir)/tdeconf_update updatedir = $(kde_datadir)/tdeconf_update

@ -25,11 +25,11 @@ static const char* const ApplicationInterface_ftable[16][3] = {
{ "bool", "exportHTML(TQString)", "exportHTML(TQString file)" }, { "bool", "exportHTML(TQString)", "exportHTML(TQString file)" },
{ "bool", "exportCSV(TQString)", "exportCSV(TQString file)" }, { "bool", "exportCSV(TQString)", "exportCSV(TQString file)" },
{ "bool", "exportPilotDB(TQString)", "exportPilotDB(TQString file)" }, { "bool", "exportPilotDB(TQString)", "exportPilotDB(TQString file)" },
{ "TQValueList<long int>", "selectedEntries()", "selectedEntries()" }, { "TQValueList<long>", "selectedEntries()", "selectedEntries()" },
{ "TQValueList<long int>", "filteredEntries()", "filteredEntries()" }, { "TQValueList<long>", "filteredEntries()", "filteredEntries()" },
{ "void", "openFile(TQString)", "openFile(TQString file)" }, { "void", "openFile(TQString)", "openFile(TQString file)" },
{ "void", "setFilter(TQString)", "setFilter(TQString text)" }, { "void", "setFilter(TQString)", "setFilter(TQString text)" },
{ "bool", "showEntry(long int)", "showEntry(long int id)" }, { "bool", "showEntry(long)", "showEntry(long id)" },
{ 0, 0, 0 } { 0, 0, 0 }
}; };
static const int ApplicationInterface_ftable_hiddens[15] = { 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 ); TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << exportPilotDB(arg0 ); _replyStream << exportPilotDB(arg0 );
} break; } break;
case 10: { // TQValueList<long int> selectedEntries() case 10: { // TQValueList<long> selectedEntries()
replyType = ApplicationInterface_ftable[10][0]; replyType = ApplicationInterface_ftable[10][0];
TQDataStream _replyStream( replyData, IO_WriteOnly ); TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << selectedEntries( ); _replyStream << selectedEntries( );
} break; } break;
case 11: { // TQValueList<long int> filteredEntries() case 11: { // TQValueList<long> filteredEntries()
replyType = ApplicationInterface_ftable[11][0]; replyType = ApplicationInterface_ftable[11][0];
TQDataStream _replyStream( replyData, IO_WriteOnly ); TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << filteredEntries( ); _replyStream << filteredEntries( );
@ -188,8 +188,8 @@ bool ApplicationInterface::process(const TQCString &fun, const TQByteArray &data
replyType = ApplicationInterface_ftable[13][0]; replyType = ApplicationInterface_ftable[13][0];
setFilter(arg0 ); setFilter(arg0 );
} break; } break;
case 14: { // bool showEntry(long int) case 14: { // bool showEntry(long)
long int arg0; long arg0;
TQDataStream arg( data, IO_ReadOnly ); TQDataStream arg( data, IO_ReadOnly );
if (arg.atEnd()) return false; if (arg.atEnd()) return false;
arg >> arg0; arg >> arg0;
@ -233,14 +233,14 @@ namespace Tellico {
static const int CollectionInterface_fhash = 11; static const int CollectionInterface_fhash = 11;
static const char* const CollectionInterface_ftable[9][3] = { static const char* const CollectionInterface_ftable[9][3] = {
{ "long int", "addEntry()", "addEntry()" }, { "long", "addEntry()", "addEntry()" },
{ "bool", "removeEntry(long int)", "removeEntry(long int entryID)" }, { "bool", "removeEntry(long)", "removeEntry(long entryID)" },
{ TQSTRINGLIST_OBJECT_NAME_STRING, "values(TQString)", "values(TQString fieldName)" }, { 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()" }, { TQSTRINGLIST_OBJECT_NAME_STRING, "bibtexKeys()", "bibtexKeys()" },
{ TQSTRING_OBJECT_NAME_STRING, "bibtexKey(long int)", "bibtexKey(long int entryID)" }, { TQSTRING_OBJECT_NAME_STRING, "bibtexKey(long)", "bibtexKey(long entryID)" },
{ "bool", "setFieldValue(long int,TQString,TQString)", "setFieldValue(long int entryID,TQString fieldName,TQString value)" }, { "bool", "setFieldValue(long,TQString,TQString)", "setFieldValue(long entryID,TQString fieldName,TQString value)" },
{ "bool", "addFieldValue(long int,TQString,TQString)", "addFieldValue(long int entryID,TQString fieldName,TQString value)" }, { "bool", "addFieldValue(long,TQString,TQString)", "addFieldValue(long entryID,TQString fieldName,TQString value)" },
{ 0, 0, 0 } { 0, 0, 0 }
}; };
static const int CollectionInterface_ftable_hiddens[8] = { 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 ); int* fp = fdict->find( fun );
switch ( fp?*fp:-1) { switch ( fp?*fp:-1) {
case 0: { // long int addEntry() case 0: { // long addEntry()
replyType = CollectionInterface_ftable[0][0]; replyType = CollectionInterface_ftable[0][0];
TQDataStream _replyStream( replyData, IO_WriteOnly ); TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << addEntry( ); _replyStream << addEntry( );
} break; } break;
case 1: { // bool removeEntry(long int) case 1: { // bool removeEntry(long)
long int arg0; long arg0;
TQDataStream arg( data, IO_ReadOnly ); TQDataStream arg( data, IO_ReadOnly );
if (arg.atEnd()) return false; if (arg.atEnd()) return false;
arg >> arg0; arg >> arg0;
@ -287,8 +287,8 @@ bool CollectionInterface::process(const TQCString &fun, const TQByteArray &data,
TQDataStream _replyStream( replyData, IO_WriteOnly ); TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << values(arg0 ); _replyStream << values(arg0 );
} break; } break;
case 3: { // TQStringList values(long int,TQString) case 3: { // TQStringList values(long,TQString)
long int arg0; long arg0;
TQString arg1; TQString arg1;
TQDataStream arg( data, IO_ReadOnly ); TQDataStream arg( data, IO_ReadOnly );
if (arg.atEnd()) return false; if (arg.atEnd()) return false;
@ -304,8 +304,8 @@ bool CollectionInterface::process(const TQCString &fun, const TQByteArray &data,
TQDataStream _replyStream( replyData, IO_WriteOnly ); TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << bibtexKeys( ); _replyStream << bibtexKeys( );
} break; } break;
case 5: { // TQString bibtexKey(long int) case 5: { // TQString bibtexKey(long)
long int arg0; long arg0;
TQDataStream arg( data, IO_ReadOnly ); TQDataStream arg( data, IO_ReadOnly );
if (arg.atEnd()) return false; if (arg.atEnd()) return false;
arg >> arg0; arg >> arg0;
@ -313,8 +313,8 @@ bool CollectionInterface::process(const TQCString &fun, const TQByteArray &data,
TQDataStream _replyStream( replyData, IO_WriteOnly ); TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << bibtexKey(arg0 ); _replyStream << bibtexKey(arg0 );
} break; } break;
case 6: { // bool setFieldValue(long int,TQString,TQString) case 6: { // bool setFieldValue(long,TQString,TQString)
long int arg0; long arg0;
TQString arg1; TQString arg1;
TQString arg2; TQString arg2;
TQDataStream arg( data, IO_ReadOnly ); TQDataStream arg( data, IO_ReadOnly );
@ -328,8 +328,8 @@ bool CollectionInterface::process(const TQCString &fun, const TQByteArray &data,
TQDataStream _replyStream( replyData, IO_WriteOnly ); TQDataStream _replyStream( replyData, IO_WriteOnly );
_replyStream << setFieldValue(arg0, arg1, arg2 ); _replyStream << setFieldValue(arg0, arg1, arg2 );
} break; } break;
case 7: { // bool addFieldValue(long int,TQString,TQString) case 7: { // bool addFieldValue(long,TQString,TQString)
long int arg0; long arg0;
TQString arg1; TQString arg1;
TQString arg2; TQString arg2;
TQDataStream arg( data, IO_ReadOnly ); TQDataStream arg( data, IO_ReadOnly );

@ -15,9 +15,13 @@
#include "../mainwindow.h" #include "../mainwindow.h"
#include "../tellico_kernel.h" #include "../tellico_kernel.h"
#include "../tellico_debug.h" #include "../tellico_debug.h"
#include "../translators/bibteximporter.h"
#include "../translators/risimporter.h"
#include <kurldrag.h> #include <kurldrag.h>
#include <kmimetype.h> #include <kmimetype.h>
#include <tdeio/netaccess.h>
#include <tdeio/job.h>
using Tellico::DropHandler; using Tellico::DropHandler;
@ -62,18 +66,37 @@ bool DropHandler::handleURL(const KURL::List& urls_) {
bool hasUnknown = false; bool hasUnknown = false;
KURL::List tc, pdf, bib, ris; KURL::List tc, pdf, bib, ris;
for(KURL::List::ConstIterator it = urls_.begin(); it != urls_.end(); ++it) { 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"))) { if(ptr->is(TQString::fromLatin1("application/x-tellico"))) {
tc << *it; tc << url;
} else if(ptr->is(TQString::fromLatin1("application/pdf"))) { } else if(ptr->is(TQString::fromLatin1("application/pdf"))) {
pdf << *it; pdf << url;
} else if(ptr->is(TQString::fromLatin1("text/x-bibtex")) || } else if(ptr->is(TQString::fromLatin1("text/x-bibtex")) ||
ptr->is(TQString::fromLatin1("application/x-bibtex"))) { ptr->is(TQString::fromLatin1("application/x-bibtex")) ||
bib << *it; ptr->is(TQString::fromLatin1("application/bibtex"))) {
bib << url;
} else if(ptr->is(TQString::fromLatin1("application/x-research-info-systems"))) { } 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 { } else {
myDebug() << "DropHandler::handleURL() - unrecognized type: " << ptr->name() << " (" << *it << ")" << endl; myDebug() << "DropHandler::handleURL() - unrecognized type: " << ptr->name() << " (" << url << ")" << endl;
hasUnknown = true; hasUnknown = true;
} }
} }

@ -15,6 +15,7 @@
#include "mainwindow.h" // needed for calling fileSave() #include "mainwindow.h" // needed for calling fileSave()
#include "collectionfactory.h" #include "collectionfactory.h"
#include "translators/tellicoimporter.h" #include "translators/tellicoimporter.h"
#include "translators/tellicosaximporter.h"
#include "translators/tellicozipexporter.h" #include "translators/tellicozipexporter.h"
#include "translators/tellicoxmlexporter.h" #include "translators/tellicoxmlexporter.h"
#include "collection.h" #include "collection.h"
@ -109,7 +110,12 @@ bool Document::openDocument(const KURL& url_) {
} }
delete m_importer; 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); m_importer = new Import::TellicoImporter(url_, m_loadAllImages);
#endif
CollPtr coll = m_importer->collection(); CollPtr coll = m_importer->collection();
// delayed image loading only works for zip files // 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())); TQTimer::singleShot(500, this, TQT_SLOT(slotLoadAllImages()));
} else { } else {
emit signalCollectionImagesLoaded(m_coll); emit signalCollectionImagesLoaded(m_coll);
m_importer->deleteLater();
m_importer = 0;
} }
return true; return true;
} }

@ -27,6 +27,7 @@
namespace Tellico { namespace Tellico {
namespace Import { namespace Import {
class TellicoImporter; class TellicoImporter;
class TellicoSaxImporter;
} }
namespace Data { namespace Data {
@ -227,7 +228,11 @@ private:
bool m_loadAllImages : 1; bool m_loadAllImages : 1;
KURL m_url; KURL m_url;
bool m_validFile : 1; bool m_validFile : 1;
#ifdef SAX_SUPPORT
TQGuardedPtr<Import::TellicoSaxImporter> m_importer;
#else
TQGuardedPtr<Import::TellicoImporter> m_importer; TQGuardedPtr<Import::TellicoImporter> m_importer;
#endif
bool m_cancelImageWriting : 1; bool m_cancelImageWriting : 1;
int m_fileFormat; int m_fileFormat;
bool m_allImagesOnDisk : 1; bool m_allImagesOnDisk : 1;

@ -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 // 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) && 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)))) { (f->type() == Field::Line && (f->flags() & Field::AllowCompletion)))) {
m_fields.insert(Tellico::shareString(name_), Tellico::shareString(value_)); m_fields.insert(Tellico::shareString(name_), Tellico::shareString(value_));
} else { } 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)) { if(f->name() == Latin1Literal("lccn") && LCCNValidator::formalize(s1) == LCCNValidator::formalize(s2)) {
return 5; 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) { if(f->formatFlag() == Field::FormatName) {
s1 = e1->field(f, true).lower(); s1 = e1->field(f, true).lower();
s2 = e2->field(f, true).lower(); s2 = e2->field(f, true).lower();

@ -84,11 +84,6 @@ public:
* The assignment operator is overloaded, since the id must be different. * The assignment operator is overloaded, since the id must be different.
*/ */
Entry& operator=(const Entry& other); 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(); ~Entry();
@ -231,6 +226,12 @@ public:
static TQString dependentValue(ConstEntryPtr e, const TQString& formatString, bool formatted); static TQString dependentValue(ConstEntryPtr e, const TQString& formatString, bool formatted);
private: 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; CollPtr m_coll;
long m_id; long m_id;
StringMap m_fields; StringMap m_fields;

@ -131,7 +131,7 @@ TQString EntryGroupItem::key(int col_, bool) const {
return m_key; return m_key;
} }
int EntryGroupItem::count() const { size_t EntryGroupItem::count() const {
return m_group ? m_group->count() : GUI::CountedItem::count(); return m_group ? m_group->count() : GUI::CountedItem::count();
} }

@ -51,7 +51,7 @@ public:
*/ */
virtual TQString key(int col, bool) const; virtual TQString key(int col, bool) const;
virtual int count() const; virtual size_t count() const;
virtual Data::EntryVec entries() const; virtual Data::EntryVec entries() const;
private: private:

@ -26,6 +26,7 @@
#include "document.h" #include "document.h"
#include "latin1literal.h" #include "latin1literal.h"
#include "../core/drophandler.h" #include "../core/drophandler.h"
#include "../tellico_debug.h"
#include <kstandarddirs.h> #include <kstandarddirs.h>
#include <krun.h> #include <krun.h>
@ -37,10 +38,22 @@
#include <tdelocale.h> #include <tdelocale.h>
#include <tqfile.h> #include <tqfile.h>
#include <tqclipboard.h>
using Tellico::EntryView; 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) { m_entry(0), m_handler(0), m_run(0), m_tempFile(0), m_useGradientImages(true), m_checkCommonFile(true) {
setJScriptEnabled(false); setJScriptEnabled(false);
setJavaEnabled(false); setJavaEnabled(false);

@ -20,6 +20,7 @@ class KTempFile;
#include "datavectors.h" #include "datavectors.h"
#include <tdehtml_part.h> #include <tdehtml_part.h>
#include <tdehtmlview.h>
#include <tqguardedptr.h> #include <tqguardedptr.h>
@ -103,5 +104,15 @@ private:
bool m_checkCommonFile : 1; 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 } //end namespace
#endif #endif

@ -10,7 +10,7 @@ libfetch_a_SOURCES = amazonfetcher.cpp animenfofetcher.cpp arxivfetcher.cpp \
discogsfetcher.cpp entrezfetcher.cpp execexternalfetcher.cpp fetcher.cpp fetchmanager.cpp \ discogsfetcher.cpp entrezfetcher.cpp execexternalfetcher.cpp fetcher.cpp fetchmanager.cpp \
gcstarpluginfetcher.cpp googlescholarfetcher.cpp ibsfetcher.cpp imdbfetcher.cpp \ gcstarpluginfetcher.cpp googlescholarfetcher.cpp ibsfetcher.cpp imdbfetcher.cpp \
isbndbfetcher.cpp messagehandler.cpp srufetcher.cpp yahoofetcher.cpp z3950connection.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)############ ####### tdevelop will overwrite this part!!! (end)############
@ -40,6 +40,8 @@ citebasefetcher.h citebasefetcher.cpp \
bibsonomyfetcher.h bibsonomyfetcher.cpp \ bibsonomyfetcher.h bibsonomyfetcher.cpp \
googlescholarfetcher.h googlescholarfetcher.cpp \ googlescholarfetcher.h googlescholarfetcher.cpp \
discogsfetcher.h discogsfetcher.cpp \ discogsfetcher.h discogsfetcher.cpp \
amazonrequest.h amazonrequest.cpp \
hmac_sha2.h hmac_sha2.c sha2.h sha2.c \
z3950-servers.cfg z3950-servers.cfg
appdir = $(kde_datadir)/tellico appdir = $(kde_datadir)/tellico

@ -12,6 +12,7 @@
***************************************************************************/ ***************************************************************************/
#include "amazonfetcher.h" #include "amazonfetcher.h"
#include "amazonrequest.h"
#include "messagehandler.h" #include "messagehandler.h"
#include "../translators/xslthandler.h" #include "../translators/xslthandler.h"
#include "../translators/tellicoimporter.h" #include "../translators/tellicoimporter.h"
@ -47,7 +48,6 @@
namespace { namespace {
static const int AMAZON_RETURNS_PER_REQUEST = 10; static const int AMAZON_RETURNS_PER_REQUEST = 10;
static const int AMAZON_MAX_RETURNS_TOTAL = 20; static const int AMAZON_MAX_RETURNS_TOTAL = 20;
static const char* AMAZON_ACCESS_KEY = "0834VQ4S71KYPVSYQD02";
static const char* AMAZON_ASSOC_TOKEN = "tellico-20"; static const char* AMAZON_ASSOC_TOKEN = "tellico-20";
// need to have these in the translation file // need to have these in the translation file
static const char* linkText = I18N_NOOP("Amazon Link"); 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_) AmazonFetcher::AmazonFetcher(Site site_, TQObject* parent_, const char* name_)
: Fetcher(parent_, name_), m_xsltHandler(0), m_site(site_), m_imageSize(MediumImage), : 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_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_countOffset(0), m_page(1), m_total(-1), m_numResults(0), m_job(0), m_started(false) {
m_name = siteData(site_).title; m_name = siteData(site_).title;
@ -109,7 +108,8 @@ bool AmazonFetcher::canFetch(int type) const {
|| type == Data::Collection::Bibtex || type == Data::Collection::Bibtex
|| type == Data::Collection::Album || type == Data::Collection::Album
|| type == Data::Collection::Video || type == Data::Collection::Video
|| type == Data::Collection::Game; || type == Data::Collection::Game
|| type == Data::Collection::BoardGame;
} }
void AmazonFetcher::readConfigHook(const TDEConfigGroup& config_) { void AmazonFetcher::readConfigHook(const TDEConfigGroup& config_) {
@ -117,6 +117,10 @@ void AmazonFetcher::readConfigHook(const TDEConfigGroup& config_) {
if(!s.isEmpty()) { if(!s.isEmpty()) {
m_access = s; m_access = s;
} }
s = config_.readEntry("SecretKey");
if(!s.isEmpty()) {
m_amazonKey = s;
}
s = config_.readEntry("AssocToken"); s = config_.readEntry("AssocToken");
if(!s.isEmpty()) { if(!s.isEmpty()) {
m_assoc = s; m_assoc = s;
@ -152,35 +156,41 @@ void AmazonFetcher::doSearch() {
// myDebug() << "AmazonFetcher::doSearch() - getting page " << m_page << endl; // myDebug() << "AmazonFetcher::doSearch() - getting page " << m_page << endl;
const SiteData& data = siteData(m_site); const SiteData& data = siteData(m_site);
KURL u = data.url;
u.addQueryItem(TQString::fromLatin1("Service"), TQString::fromLatin1("AWSECommerceService")); TQMap<TQString, TQString> params;
u.addQueryItem(TQString::fromLatin1("AssociateTag"), m_assoc); params.insert(TQString::fromLatin1("Service"), TQString::fromLatin1("AWSECommerceService"));
u.addQueryItem(TQString::fromLatin1("AWSAccessKeyId"), m_access); params.insert(TQString::fromLatin1("AssociateTag"), m_assoc);
u.addQueryItem(TQString::fromLatin1("Operation"), TQString::fromLatin1("ItemSearch")); params.insert(TQString::fromLatin1("AWSAccessKeyId"), m_access);
u.addQueryItem(TQString::fromLatin1("ResponseGroup"), TQString::fromLatin1("Large")); params.insert(TQString::fromLatin1("Operation"), TQString::fromLatin1("ItemSearch"));
u.addQueryItem(TQString::fromLatin1("ItemPage"), TQString::number(m_page)); params.insert(TQString::fromLatin1("ResponseGroup"), TQString::fromLatin1("Large"));
u.addQueryItem(TQString::fromLatin1("Version"), TQString::fromLatin1("2007-10-29")); 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(); const int type = Kernel::self()->collectionType();
switch(type) { switch(type) {
case Data::Collection::Book: case Data::Collection::Book:
case Data::Collection::ComicBook: case Data::Collection::ComicBook:
case Data::Collection::Bibtex: case Data::Collection::Bibtex:
u.addQueryItem(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("Books")); params.insert(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("Books"));
u.addQueryItem(TQString::fromLatin1("SortIndex"), TQString::fromLatin1("relevancerank")); params.insert(TQString::fromLatin1("SortIndex"), TQString::fromLatin1("relevancerank"));
break; break;
case Data::Collection::Album: case Data::Collection::Album:
u.addQueryItem(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("Music")); params.insert(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("Music"));
break; break;
case Data::Collection::Video: case Data::Collection::Video:
u.addQueryItem(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("Video")); params.insert(TQString::fromLatin1("SearchIndex"), TQString::fromLatin1("Video"));
u.addQueryItem(TQString::fromLatin1("SortIndex"), TQString::fromLatin1("relevancerank")); params.insert(TQString::fromLatin1("SortIndex"), TQString::fromLatin1("relevancerank"));
break; break;
case Data::Collection::Game: 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; break;
case Data::Collection::Coin: case Data::Collection::Coin:
@ -188,7 +198,6 @@ void AmazonFetcher::doSearch() {
case Data::Collection::Wine: case Data::Collection::Wine:
case Data::Collection::Base: case Data::Collection::Base:
case Data::Collection::Card: case Data::Collection::Card:
default:
message(i18n("%1 does not allow searching for this collection type.").arg(source()), MessageHandler::Warning); message(i18n("%1 does not allow searching for this collection type.").arg(source()), MessageHandler::Warning);
stop(); stop();
return; return;
@ -207,29 +216,28 @@ void AmazonFetcher::doSearch() {
switch(m_key) { switch(m_key) {
case Title: case Title:
u.addQueryItem(TQString::fromLatin1("Title"), value, mib); params.insert(TQString::fromLatin1("Title"), value);
break; break;
case Person: case Person:
if(type == Data::Collection::Video) { if(type == Data::Collection::Video) {
u.addQueryItem(TQString::fromLatin1("Actor"), value, mib); params.insert(TQString::fromLatin1("Actor"), value);
u.addQueryItem(TQString::fromLatin1("Director"), value, mib); params.insert(TQString::fromLatin1("Director"), value);
} else if(type == Data::Collection::Album) { } 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) { } else if(type == Data::Collection::Game) {
u.addQueryItem(TQString::fromLatin1("Manufacturer"), value, mib); params.insert(TQString::fromLatin1("Manufacturer"), value);
} else { // books and bibtex } else { // books and bibtex
TQString s = TQString::fromLatin1("author:%1 or publisher:%2").arg(value, value); TQString s = TQString::fromLatin1("author:%1 or publisher:%2").arg(value, value);
// u.addQueryItem(TQString::fromLatin1("Author"), value, mib); // params.insert(TQString::fromLatin1("Author"), value, mib);
// u.addQueryItem(TQString::fromLatin1("Publisher"), value, mib); // params.insert(TQString::fromLatin1("Publisher"), value, mib);
u.addQueryItem(TQString::fromLatin1("Power"), s, mib); params.insert(TQString::fromLatin1("Power"), s);
} }
break; break;
case ISBN: case ISBN:
{ {
u.removeQueryItem(TQString::fromLatin1("Operation")); params.insert(TQString::fromLatin1("Operation"), TQString::fromLatin1("ItemLookup"));
u.addQueryItem(TQString::fromLatin1("Operation"), TQString::fromLatin1("ItemLookup"));
TQString s = m_value; // not encValue!!! TQString s = m_value; // not encValue!!!
s.remove('-'); s.remove('-');
@ -260,47 +268,46 @@ void AmazonFetcher::doSearch() {
} }
} }
// the default search is by ASIN, which prohibits SearchIndex // the default search is by ASIN, which prohibits SearchIndex
u.removeQueryItem(TQString::fromLatin1("SearchIndex")); params.remove(TQString::fromLatin1("SearchIndex"));
} }
// limit to first 10 // limit to first 10
while(isbns.size() > 10) { while(isbns.size() > 10) {
isbns.pop_back(); isbns.pop_back();
} }
u.addQueryItem(TQString::fromLatin1("ItemId"), isbns.join(TQString::fromLatin1(","))); params.insert(TQString::fromLatin1("ItemId"), isbns.join(TQString::fromLatin1(",")));
if(isbn13) { if(isbn13) {
u.addQueryItem(TQString::fromLatin1("IdType"), TQString::fromLatin1("EAN")); params.insert(TQString::fromLatin1("IdType"), TQString::fromLatin1("EAN"));
} }
} }
break; break;
case UPC: case UPC:
{ {
u.removeQueryItem(TQString::fromLatin1("Operation")); params.insert(TQString::fromLatin1("Operation"), TQString::fromLatin1("ItemLookup"));
u.addQueryItem(TQString::fromLatin1("Operation"), TQString::fromLatin1("ItemLookup"));
// US allows UPC, all others are EAN // US allows UPC, all others are EAN
if(m_site == US) { if(m_site == US) {
u.addQueryItem(TQString::fromLatin1("IdType"), TQString::fromLatin1("UPC")); params.insert(TQString::fromLatin1("IdType"), TQString::fromLatin1("UPC"));
} else { } else {
u.addQueryItem(TQString::fromLatin1("IdType"), TQString::fromLatin1("EAN")); params.insert(TQString::fromLatin1("IdType"), TQString::fromLatin1("EAN"));
} }
TQString s = m_value; // not encValue!!! TQString s = m_value; // not encValue!!!
s.remove('-'); s.remove('-');
// limit to first 10 // limit to first 10
s.replace(TQString::fromLatin1("; "), TQString::fromLatin1(",")); s.replace(TQString::fromLatin1("; "), TQString::fromLatin1(","));
s = s.section(',', 0, 9); s = s.section(',', 0, 9);
u.addQueryItem(TQString::fromLatin1("ItemId"), s); params.insert(TQString::fromLatin1("ItemId"), s);
} }
break; break;
case Keyword: case Keyword:
u.addQueryItem(TQString::fromLatin1("Keywords"), m_value, mib); params.insert(TQString::fromLatin1("Keywords"), value);
break; break;
case Raw: case Raw:
{ {
TQString key = value.section('=', 0, 0).stripWhiteSpace(); TQString key = value.section('=', 0, 0).stripWhiteSpace();
TQString str = value.section('=', 1).stripWhiteSpace(); TQString str = value.section('=', 1).stripWhiteSpace();
u.addQueryItem(key, str, mib); params.insert(key, str);
} }
break; break;
@ -309,9 +316,11 @@ void AmazonFetcher::doSearch() {
stop(); stop();
return; 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&)), connect(m_job, TQT_SIGNAL(data(TDEIO::Job*, const TQByteArray&)),
TQT_SLOT(slotData(TDEIO::Job*, const TQByteArray&))); TQT_SLOT(slotData(TDEIO::Job*, const TQByteArray&)));
connect(m_job, TQT_SIGNAL(result(TDEIO::Job*)), connect(m_job, TQT_SIGNAL(result(TDEIO::Job*)),
@ -520,6 +529,12 @@ void AmazonFetcher::slotComplete(TDEIO::Job* job_) {
+ entry->field(TQString::fromLatin1("year")); + entry->field(TQString::fromLatin1("year"));
break; break;
case Data::Collection::BoardGame:
desc = entry->field(TQString::fromLatin1("publisher"))
+ TQChar('/')
+ entry->field(TQString::fromLatin1("year"));
break;
default: default:
break; break;
} }
@ -889,11 +904,25 @@ AmazonFetcher::ConfigWidget::ConfigWidget(TQWidget* parent_, const AmazonFetcher
TQWhatsThis::add(m_assocEdit, w); TQWhatsThis::add(m_assocEdit, w);
label->setBuddy(m_assocEdit); 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); l->setRowStretch(++row, 10);
if(fetcher_) { if(fetcher_) {
m_siteCombo->setCurrentData(fetcher_->m_site); m_siteCombo->setCurrentData(fetcher_->m_site);
m_assocEdit->setText(fetcher_->m_assoc); m_assocEdit->setText(fetcher_->m_assoc);
m_accessEdit->setText(fetcher_->m_access);
m_secretKeyEdit->setText(fetcher_->m_amazonKey);
m_imageCombo->setCurrentData(fetcher_->m_imageSize); m_imageCombo->setCurrentData(fetcher_->m_imageSize);
} else { // defaults } else { // defaults
m_assocEdit->setText(TQString::fromLatin1(AMAZON_ASSOC_TOKEN)); m_assocEdit->setText(TQString::fromLatin1(AMAZON_ASSOC_TOKEN));
@ -912,6 +941,14 @@ void AmazonFetcher::ConfigWidget::saveConfig(TDEConfigGroup& config_) {
if(!s.isEmpty()) { if(!s.isEmpty()) {
config_.writeEntry("AssocToken", s); 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(); n = m_imageCombo->currentData().toInt();
config_.writeEntry("Image Size", n); config_.writeEntry("Image Size", n);

@ -118,6 +118,7 @@ private:
ImageSize m_imageSize; ImageSize m_imageSize;
TQString m_access; TQString m_access;
TQString m_amazonKey;
TQString m_assoc; TQString m_assoc;
bool m_addLinkField; bool m_addLinkField;
int m_limit; int m_limit;
@ -151,6 +152,8 @@ private slots:
private: private:
KLineEdit* m_assocEdit; KLineEdit* m_assocEdit;
KLineEdit* m_accessEdit;
KLineEdit* m_secretKeyEdit;
GUI::ComboBox* m_siteCombo; GUI::ComboBox* m_siteCombo;
GUI::ComboBox* m_imageCombo; GUI::ComboBox* m_imageCombo;
}; };

@ -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;
}

@ -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

@ -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; return entry;
} }

@ -163,7 +163,15 @@ void CitebaseFetcher::slotComplete(TDEIO::Job* job_) {
} }
Tellico::Data::EntryPtr CitebaseFetcher::fetchEntry(uint uid_) { 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 { KURL CitebaseFetcher::searchURL(FetchKey key_, const TQString& value_) const {

@ -34,7 +34,7 @@
//#define ENTREZ_TEST //#define ENTREZ_TEST
namespace { 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_BASE_URL = "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/";
static const char* ENTREZ_SEARCH_CGI = "esearch.fcgi"; static const char* ENTREZ_SEARCH_CGI = "esearch.fcgi";
static const char* ENTREZ_SUMMARY_CGI = "esummary.fcgi"; static const char* ENTREZ_SUMMARY_CGI = "esummary.fcgi";

@ -92,8 +92,8 @@ private:
XSLTHandler* m_xsltHandler; XSLTHandler* m_xsltHandler;
TQString m_dbname; TQString m_dbname;
int m_start; size_t m_start;
int m_total; size_t m_total;
TQByteArray m_data; TQByteArray m_data;
TQMap<int, Data::EntryPtr> m_entries; // map from search result id to entry TQMap<int, Data::EntryPtr> m_entries; // map from search result id to entry

@ -28,7 +28,7 @@
#include <tqlayout.h> #include <tqlayout.h>
namespace { 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"; 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 text = TQString::fromUtf8(m_data, m_data.size());
TQString bibtex; 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) { 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)); KURL bibtexUrl(TQString::fromLatin1(SCHOLAR_BASE_URL), m_bibtexRx.cap(1));
// myDebug() << bibtexUrl << endl; // myDebug() << bibtexUrl << endl;

@ -83,9 +83,9 @@ private slots:
private: private:
void doSearch(); void doSearch();
int m_limit; size_t m_limit;
int m_start; size_t m_start;
int m_total; size_t m_total;
TQByteArray m_data; TQByteArray m_data;
TQMap<int, Data::EntryPtr> m_entries; TQMap<int, Data::EntryPtr> m_entries;

@ -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 */

@ -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 */

@ -156,7 +156,8 @@ void IBSFetcher::slotComplete(TDEIO::Job* job_) {
TQString s = Tellico::decodeHTML(TQString(m_data)); TQString s = Tellico::decodeHTML(TQString(m_data));
// really specific regexp // 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 anchorRx(TQString::fromLatin1("<a\\s+[^>]*href\\s*=\\s*[\"'](") +
TQRegExp::escape(pat) + TQRegExp::escape(pat) +
TQString::fromLatin1("[^\"]*)\"[^>]*><b>([^<]+)<"), false); TQString::fromLatin1("[^\"]*)\"[^>]*><b>([^<]+)<"), false);

@ -799,7 +799,7 @@ void IMDBFetcher::doPlot(const TQString& str_, Data::EntryPtr entry_, const KURL
TQString thisPlot; TQString thisPlot;
// match until next opening tag // 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); plotRx.setMinimal(true);
TQRegExp plotURLRx(TQString::fromLatin1("<a\\s+.*href\\s*=\\s*\".*/title/.*/plotsummary\""), false); TQRegExp plotURLRx(TQString::fromLatin1("<a\\s+.*href\\s*=\\s*\".*/title/.*/plotsummary\""), false);
plotURLRx.setMinimal(true); plotURLRx.setMinimal(true);
@ -828,6 +828,8 @@ void IMDBFetcher::doPlot(const TQString& str_, Data::EntryPtr entry_, const KURL
if(plotRx.search(plotPage) > -1) { if(plotRx.search(plotPage) > -1) {
TQString userPlot = plotRx.cap(1); TQString userPlot = plotRx.cap(1);
userPlot.remove(*s_tagRx); // remove HTML tags 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)); entry_->setField(TQString::fromLatin1("plot"), Tellico::decodeHTML(userPlot));
} }
} }

@ -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 */

@ -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 */

@ -43,9 +43,9 @@ Locale=it
Syntax=unimarc Syntax=unimarc
[porbase] [porbase]
Host=z3950.bn.pt Host=z3950.porbase.org
Port=210 Port=210
Database=bnd Database=Default
Name=Portuguese National Library Name=Portuguese National Library
Charset=iso-8859-1 Charset=iso-8859-1
Locale=pt Locale=pt

@ -175,13 +175,13 @@ void Z3950Fetcher::search(FetchKey key_, const TQString& value_) {
isbnList.insert(it, isbn10); isbnList.insert(it, isbn10);
} }
} }
const int count = isbnList.count(); const size_t count = isbnList.count();
if(count > 1) { if(count > 1) {
m_pqn = TQString::fromLatin1("@or "); 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]; m_pqn += TQString::fromLatin1(" @attr 1=7 ") + isbnList[i];
if(i < count-2) { if(count > 1 && i < count-2) {
m_pqn += TQString::fromLatin1(" @or"); m_pqn += TQString::fromLatin1(" @or");
} }
} }

@ -591,6 +591,10 @@ void FetchDialog::slotMultipleISBN(bool toggle_) {
m_valueLineEdit->setText(val); m_valueLineEdit->setText(val);
} }
m_editISBN->setEnabled(toggle_); m_editISBN->setEnabled(toggle_);
if(toggle_) {
// if we're editing multiple values, it makes sense to popup the dialog now
slotEditMultipleISBN();
}
} }
void FetchDialog::slotEditMultipleISBN() { void FetchDialog::slotEditMultipleISBN() {

@ -32,6 +32,7 @@ namespace {
using Tellico::Data::Field; using Tellico::Data::Field;
//these get overwritten, but are here since they're static //these get overwritten, but are here since they're static
TQStringList Field::s_articles;
TQStringList Field::s_articlesApos; TQStringList Field::s_articlesApos;
TQRegExp Field::s_delimiter = TQRegExp(TQString::fromLatin1("\\s*;\\s*")); TQRegExp Field::s_delimiter = TQRegExp(TQString::fromLatin1("\\s*;\\s*"));
@ -171,7 +172,7 @@ const TQString& Field::defaultValue() const {
} }
void Field::setDefaultValue(const TQString& value_) { 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_); setProperty(TQString::fromLatin1("default"), value_);
} }
} }
@ -260,8 +261,7 @@ TQString Field::formatTitle(const TQString& title_) {
if(Config::autoFormat()) { if(Config::autoFormat()) {
const TQString lower = newTitle.lower(); const TQString lower = newTitle.lower();
// TODO if the title has ",the" at the end, put it at the front // TODO if the title has ",the" at the end, put it at the front
const TQStringList& articles = Config::articleList(); for(TQStringList::ConstIterator it = s_articles.constBegin(); it != s_articles.constEnd(); ++it) {
for(TQStringList::ConstIterator it = articles.begin(); it != articles.end(); ++it) {
// assume white space is already stripped // assume white space is already stripped
// the articles are already in lower-case // the articles are already in lower-case
if(lower.startsWith(*it + TQChar(' '))) { if(lower.startsWith(*it + TQChar(' '))) {
@ -415,7 +415,7 @@ TQString Field::capitalize(TQString str_) {
TQString word = str_.mid(0, pos); TQString word = str_.mid(0, pos);
// now check to see if words starts with apostrophe list // 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)) { if(word.lower().startsWith(*it)) {
uint l = (*it).length(); uint l = (*it).length();
str_.replace(l, 1, str_.at(l).upper()); 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); word = str_.mid(pos+1, nextPos-pos-1);
bool aposMatch = false; bool aposMatch = false;
// now check to see if words starts with apostrophe list // 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)) { if(word.lower().startsWith(*it)) {
uint l = (*it).length(); uint l = (*it).length();
str_.replace(pos+l+1, 1, str_.at(pos+l+1).upper()); 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_) { TQString Field::sortKeyTitle(const TQString& title_) {
const TQString lower = title_.lower(); const TQString lower = title_.lower();
const TQStringList& articles = Config::articleList(); for(TQStringList::ConstIterator it = s_articles.constBegin(); it != s_articles.constEnd(); ++it) {
for(TQStringList::ConstIterator it = articles.begin(); it != articles.end(); ++it) {
// assume white space is already stripped // assume white space is already stripped
// the articles are already in lower-case // the articles are already in lower-case
if(lower.startsWith(*it + TQChar(' '))) { if(lower.startsWith(*it + TQChar(' '))) {
@ -464,7 +463,7 @@ TQString Field::sortKeyTitle(const TQString& title_) {
} }
} }
// check apostrophes, too // 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)) { if(lower.startsWith(*it)) {
return title_.mid((*it).length()); return title_.mid((*it).length());
} }
@ -474,9 +473,9 @@ TQString Field::sortKeyTitle(const TQString& title_) {
// articles should all be in lower-case // articles should all be in lower-case
void Field::articlesUpdated() { void Field::articlesUpdated() {
const TQStringList articles = Config::articleList(); s_articles = Config::articleList();
s_articlesApos.clear(); 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('\''))) { if((*it).endsWith(TQChar('\''))) {
s_articlesApos += (*it); s_articlesApos += (*it);
} }
@ -581,11 +580,10 @@ long Field::getID() {
} }
void Field::stripArticles(TQString& value) { void Field::stripArticles(TQString& value) {
const TQStringList articles = Config::articleList(); if(s_articles.isEmpty()) {
if(articles.isEmpty()) {
return; 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")); TQRegExp rx(TQString::fromLatin1("\\b") + *it + TQString::fromLatin1("\\b"));
value.remove(rx); value.remove(rx);
} }

@ -385,6 +385,7 @@ private:
FormatFlag m_formatFlag; FormatFlag m_formatFlag;
StringMap m_properties; StringMap m_properties;
static TQStringList s_articles;
// need to remember articles with apostrophes for capitalization // need to remember articles with apostrophes for capitalization
static TQStringList s_articlesApos; static TQStringList s_articlesApos;
static TQRegExp s_delimiter; static TQRegExp s_delimiter;

@ -39,8 +39,8 @@ public:
int column, int width, int align); int column, int width, int align);
virtual int width(const TQFontMetrics& fm, const TQListView* lv, int c) const; virtual int width(const TQFontMetrics& fm, const TQListView* lv, int c) const;
virtual int count() const { return childCount(); } virtual size_t count() const { return childCount(); }
virtual int realChildCount() const { return count(); } virtual size_t realChildCount() const { return count(); }
}; };
} // end namespace } // end namespace

@ -139,7 +139,7 @@ public:
ListViewItem(ListViewItem* parent, const TQString& text) : TDEListViewItem(parent, text), m_sortWeight(-1) {} ListViewItem(ListViewItem* parent, const TQString& text) : TDEListViewItem(parent, text), m_sortWeight(-1) {}
virtual ~ListViewItem(); virtual ~ListViewItem();
virtual int realChildCount() const { return childCount(); } virtual size_t realChildCount() const { return childCount(); }
virtual void clear(); virtual void clear();
virtual bool isEntryGroupItem() const { return false; } virtual bool isEntryGroupItem() const { return false; }

@ -29,6 +29,9 @@ TQTabBar* TabControl::tabBar() const {
void TabControl::setFocusToFirstChild() { void TabControl::setFocusToFirstChild() {
TQWidget* page = currentPage(); TQWidget* page = currentPage();
Q_ASSERT(page); Q_ASSERT(page);
if(!page) {
return;
}
TQObjectList* list = page->queryList(TQWIDGET_OBJECT_NAME_STRING); TQObjectList* list = page->queryList(TQWIDGET_OBJECT_NAME_STRING);
for(TQObjectListIt it(*list); it.current(); ++it) { for(TQObjectListIt it(*list); it.current(); ++it) {
TQWidget* w = TQT_TQWIDGET(it.current()); TQWidget* w = TQT_TQWIDGET(it.current());

@ -14,6 +14,7 @@
#include "image.h" #include "image.h"
#include "imagefactory.h" #include "imagefactory.h"
#include "tellico_debug.h" #include "tellico_debug.h"
#include "tellico_utils.h"
#include <kmdcodec.h> #include <kmdcodec.h>
#include <kpixmapio.h> #include <kpixmapio.h>
@ -105,7 +106,7 @@ TQByteArray Image::byteArray(const TQImage& img_, const TQCString& outputFormat_
TQString Image::idClean(const TQString& id_) { TQString Image::idClean(const TQString& id_) {
static const TQRegExp rx('[' + TQRegExp::escape(TQString::fromLatin1("/@<>#\"&%?={}|^~[]'`\\:+")) + ']'); static const TQRegExp rx('[' + TQRegExp::escape(TQString::fromLatin1("/@<>#\"&%?={}|^~[]'`\\:+")) + ']');
TQString clean = id_; TQString clean = id_;
return clean.remove(rx); return shareString(clean.remove(rx));
} }
void Image::setID(const TQString& id_) { void Image::setID(const TQString& id_) {

@ -316,7 +316,7 @@ bool ImageFactory::writeCachedImage(const TQString& id_, CacheDir dir_, bool for
const Tellico::Data::Image& ImageFactory::imageById(const TQString& id_) { const Tellico::Data::Image& ImageFactory::imageById(const TQString& id_) {
if(id_.isEmpty()) { if(id_.isEmpty()) {
myDebug() << "ImageFactory::imageById() - empty id" << endl; // myDebug() << "ImageFactory::imageById() - empty id" << endl;
return s_null; return s_null;
} }
// myLog() << "ImageFactory::imageById() - " << id_ << endl; // 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_)) { if((s_imageInfoMap.contains(id_) && s_imageInfoMap[id_].linkOnly) || !KURL::isRelativeURL(id_)) {
KURL u = id_; KURL u = id_;
if(u.isValid()) { 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 if(Config::imageLocation() == Config::ImagesInLocalDir) {
// and the image will exist in the data dir, but the app thinks everything should bool exists = TQFile::exists(localDir() + id_);
// be in the zip file instead if(exists) {
bool exists = TQFile::exists(dataDir() + id_); const Data::Image& img2 = addCachedImageImpl(id_, LocalDir);
if(exists) { if(img2.isNull()) {
// if we're loading from the application data dir, but images are being saved in the myDebug() << "ImageFactory::imageById() - tried to add from LocalDir, but failed: " << id_ << endl;
// data file instead, then consider the document to be modified since it needs } else {
// the image saved // myLog() << "...imageById() - found in local dir" << endl;
if(Config::imageLocation() != Config::ImagesInAppDir) { 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); 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); } else if(Config::imageLocation() == Config::ImagesInAppDir) {
if(img2.isNull()) { bool exists = TQFile::exists(dataDir() + id_);
myDebug() << "ImageFactory::imageById() - tried to add from DataDir, but failed: " << id_ << endl; if(exists) {
} else { const Data::Image& img2 = addCachedImageImpl(id_, DataDir);
// myLog() << "...imageById() - found in data dir" << endl; if(img2.isNull()) {
return img2; myDebug() << "ImageFactory::imageById() - tried to add from DataDir, but failed: " << id_ << endl;
} else {
// myLog() << "...imageById() - found in data dir" << endl;
return img2;
}
} }
} // not an else statement, it might be null
// if localDir() == DataDir(), then there's nothing left to check if(TQFile::exists(localDir() + id_)) {
if(localDir() == dataDir()) { // the img is in the other location
return s_null; // consider the document to be modified since it needs the image saved
}
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) {
Data::Document::self()->slotSetModified(true); Data::Document::self()->slotSetModified(true);
} const Data::Image& img2 = addCachedImageImpl(id_, LocalDir);
const Data::Image& img2 = addCachedImageImpl(id_, LocalDir); if(img2.isNull()) {
if(img2.isNull()) { myDebug() << "ImageFactory::imageById() - tried to add from LocalDir, but failed: " << id_ << endl;
myDebug() << "ImageFactory::imageById() - tried to add from LocalDir, but failed: " << id_ << endl; } else {
} else { // myLog() << "...imageById() - found in local dir" << endl;
// myLog() << "...imageById() - found in data dir" << endl; return img2;
return img2; }
} }
} }
myDebug() << "***ImageFactory::imageById() - not found: " << id_ << endl; myDebug() << "***ImageFactory::imageById() - not found: " << id_ << endl;

@ -12,6 +12,7 @@
***************************************************************************/ ***************************************************************************/
#include "isbnvalidator.h" #include "isbnvalidator.h"
#include "upcvalidator.h"
#include "tellico_debug.h" #include "tellico_debug.h"
using Tellico::ISBNValidator; using Tellico::ISBNValidator;
@ -58,6 +59,13 @@ ISBNValidator::ISBNValidator(TQObject* parent_, const char* name_/*=0*/)
} }
TQValidator::State ISBNValidator::validate(TQString& input_, int& pos_) const { 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")) || if(input_.startsWith(TQString::fromLatin1("978")) ||
input_.startsWith(TQString::fromLatin1("979"))) { input_.startsWith(TQString::fromLatin1("979"))) {
return validate13(input_, pos_); return validate13(input_, pos_);

@ -65,7 +65,7 @@ TQString LCCNValidator::formalize(const TQString& value_) {
// now check for non digits in the serial // now check for non digits in the serial
pos = 0; 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); TQString suffix = serial.mid(pos);
serial = serial.left(pos); serial = serial.left(pos);
// serial must be left-padded with zeros to 6 characters // serial must be left-padded with zeros to 6 characters

@ -48,6 +48,8 @@ Tellico::ListViewComparison* Tellico::ListViewComparison::create(Data::ConstFiel
return new DependentComparison(field_); return new DependentComparison(field_);
} else if(field_->type() == Data::Field::Date || field_->formatFlag() == Data::Field::FormatDate) { } else if(field_->type() == Data::Field::Date || field_->formatFlag() == Data::Field::FormatDate) {
return new ISODateComparison(field_); return new ISODateComparison(field_);
} else if(field_->type() == Data::Field::Choice) {
return new ChoiceComparison(field_);
} else if(field_->formatFlag() == Data::Field::FormatTitle) { } else if(field_->formatFlag() == Data::Field::FormatTitle) {
// Dependent could be title, so put this test after // Dependent could be title, so put this test after
return new TitleComparison(field_); return new TitleComparison(field_);
@ -277,3 +279,11 @@ int Tellico::ISODateComparison::compare(const TQString& str1, const TQString& st
} }
return 0; 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);
}

@ -112,5 +112,16 @@ protected:
virtual int compare(const TQString& str1, const TQString& str2); 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 #endif

@ -336,7 +336,7 @@ void MainWindow::initActions() {
action = new TDEAction(actionCollection(), "file_import_csv"); action = new TDEAction(actionCollection(), "file_import_csv");
action->setText(i18n("Import CSV Data...")); action->setText(i18n("Import CSV Data..."));
action->setToolTip(i18n("Import a CSV file")); action->setToolTip(i18n("Import a CSV file"));
action->setIcon(MIME_ICON("text/x-csv")); action->setIcon(MIME_ICON("text/csv"));
importMenu->insert(action); importMenu->insert(action);
connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map())); connect(action, TQT_SIGNAL(activated()), importMapper, TQT_SLOT(map()));
importMapper->setMapping(action, Import::CSV); importMapper->setMapping(action, Import::CSV);
@ -506,7 +506,7 @@ void MainWindow::initActions() {
action = new TDEAction(actionCollection(), "file_export_csv"); action = new TDEAction(actionCollection(), "file_export_csv");
action->setText(i18n("Export to CSV...")); action->setText(i18n("Export to CSV..."));
action->setToolTip(i18n("Export to a comma-separated values file")); 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); exportMenu->insert(action);
connect(action, TQT_SIGNAL(activated()), exportMapper, TQT_SLOT(map())); connect(action, TQT_SIGNAL(activated()), exportMapper, TQT_SLOT(map()));
exportMapper->setMapping(action, Export::CSV); exportMapper->setMapping(action, Export::CSV);
@ -750,6 +750,7 @@ void MainWindow::initActions() {
// want to update every time the filter text changes // want to update every time the filter text changes
connect(m_quickFilter, TQT_SIGNAL(textChanged(const TQString&)), connect(m_quickFilter, TQT_SIGNAL(textChanged(const TQString&)),
TQT_TQOBJECT(this), TQT_SLOT(slotQueueFilter())); TQT_TQOBJECT(this), TQT_SLOT(slotQueueFilter()));
m_quickFilter->installEventFilter(this); // intercept keyEvents
KWidgetAction* wAction = new KWidgetAction(m_quickFilter, i18n("Filter"), 0, 0, 0, KWidgetAction* wAction = new KWidgetAction(m_quickFilter, i18n("Filter"), 0, 0, 0,
actionCollection(), "quick_filter"); actionCollection(), "quick_filter");
@ -907,12 +908,12 @@ void MainWindow::saveOptions() {
Config::setGroupViewSortAscending(m_groupView->ascendingSort()); Config::setGroupViewSortAscending(m_groupView->ascendingSort());
if(m_loanView) { 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()); Config::setLoanViewSortAscending(m_loanView->ascendingSort());
} }
if(m_filterView) { 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()); Config::setFilterViewSortAscending(m_filterView->ascendingSort());
} }
@ -991,7 +992,7 @@ void MainWindow::saveCollectionOptions(Data::CollPtr coll_) {
configIndex = i; configIndex = i;
} }
} }
uint limit = TQMIN(urls.count(), Config::maxCustomURLSettings()); size_t limit = TQMIN(urls.count(), Config::maxCustomURLSettings());
for(uint i = 0; i < limit; ++i) { for(uint i = 0; i < limit; ++i) {
config.writeEntry(TQString::fromLatin1("URL_%1").arg(i), urls[i].url()); config.writeEntry(TQString::fromLatin1("URL_%1").arg(i), urls[i].url());
config.writeEntry(TQString::fromLatin1("Group By_%1").arg(i), groupBys[i]); config.writeEntry(TQString::fromLatin1("Group By_%1").arg(i), groupBys[i]);
@ -1531,11 +1532,11 @@ void MainWindow::slotEntryCount() {
return; return;
} }
int count = coll->entryCount(); size_t count = coll->entryCount();
TQString text = i18n("Total entries: %1").arg(count); TQString text = i18n("Total entries: %1").arg(count);
int selectCount = Controller::self()->selectedEntries().count(); size_t selectCount = Controller::self()->selectedEntries().count();
int filterCount = m_detailedView->visibleItems(); size_t filterCount = m_detailedView->visibleItems();
// if more than one book is selected, add the number of selected books // if more than one book is selected, add the number of selected books
if(filterCount < count && selectCount > 1) { if(filterCount < count && selectCount > 1) {
text += TQChar(' '); text += TQChar(' ');
@ -1847,6 +1848,10 @@ void MainWindow::setFilter(const TQString& text_) {
} else { } else {
// if it isn't valid, hold off on applying the filter // if it isn't valid, hold off on applying the filter
TQRegExp tx(text); TQRegExp tx(text);
if(!tx.isValid()) {
text = TQRegExp::escape(text);
tx.setPattern(text);
}
if(!tx.isValid()) { if(!tx.isValid()) {
myDebug() << "MainWindow::slotUpdateFilter() - invalid regexp: " << text << endl; myDebug() << "MainWindow::slotUpdateFilter() - invalid regexp: " << text << endl;
return; 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" #include "mainwindow.moc"

@ -123,6 +123,8 @@ public:
virtual void setFilter(const TQString& text); virtual void setFilter(const TQString& text);
virtual bool showEntry(long id); virtual bool showEntry(long id);
bool eventFilter(TQObject* watched, TQEvent* event);
public slots: public slots:
/** /**
* Initializes some stuff after the object is created. * Initializes some stuff after the object is created.

@ -197,7 +197,7 @@ void ReportDialog::slotSaveAs() {
if(!u.isEmpty() && u.isValid()) { if(!u.isEmpty() && u.isValid()) {
TDEConfigGroup config(TDEGlobal::config(), "ExportOptions"); TDEConfigGroup config(TDEGlobal::config(), "ExportOptions");
bool encode = config.readBoolEntry("EncodeUTF8", true); bool encode = config.readBoolEntry("EncodeUTF8", true);
int oldOpt = m_exporter->options(); long oldOpt = m_exporter->options();
// turn utf8 off // turn utf8 off
long options = oldOpt & ~Export::ExportUTF8; long options = oldOpt & ~Export::ExportUTF8;

@ -22,7 +22,7 @@
// std::clock_t // std::clock_t
#include <ctime> #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__) #if defined(__GNUC_PREREQ) && !defined(__GNUC_PREREQ__)
#define __GNUC_PREREQ__ __GNUC_PREREQ #define __GNUC_PREREQ__ __GNUC_PREREQ
#endif #endif

@ -16,7 +16,7 @@ METASOURCES = AUTO
DISTCLEANFILES = *~ *.Po $(CLEANFILES) DISTCLEANFILES = *~ *.Po $(CLEANFILES)
isbntest_SOURCES = isbntest.cpp 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_SOURCES = latin1test.cpp
latin1test_LDADD = $(LIB_QT) $(LIB_TDECORE) latin1test_LDADD = $(LIB_QT) $(LIB_TDECORE)

@ -12,9 +12,9 @@ libtranslators_a_SOURCES = alexandriaexporter.cpp alexandriaimporter.cpp \
filelistingimporter.cpp freedb_util.cpp freedbimporter.cpp gcfilmsexporter.cpp \ filelistingimporter.cpp freedb_util.cpp freedbimporter.cpp gcfilmsexporter.cpp \
gcfilmsimporter.cpp griffithimporter.cpp grs1importer.cpp htmlexporter.cpp libcsv.c \ gcfilmsimporter.cpp griffithimporter.cpp grs1importer.cpp htmlexporter.cpp libcsv.c \
onixexporter.cpp pdfimporter.cpp pilotdbexporter.cpp referencerimporter.cpp \ onixexporter.cpp pdfimporter.cpp pilotdbexporter.cpp referencerimporter.cpp \
risimporter.cpp tellico_xml.cpp tellicoimporter.cpp tellicoxmlexporter.cpp \ risimporter.cpp tellico_xml.cpp tellicoimporter.cpp tellicosaximporter.cpp \
tellicozipexporter.cpp textimporter.cpp xmlimporter.cpp xsltexporter.cpp xslthandler.cpp \ tellicoxmlexporter.cpp tellicoxmlhandler.cpp tellicozipexporter.cpp textimporter.cpp \
xsltimporter.cpp xmlimporter.cpp xmlstatehandler.cpp xsltexporter.cpp xslthandler.cpp xsltimporter.cpp
if !USE_LIBBTPARSE if !USE_LIBBTPARSE
SUBDIR_LIBBTPARSE = btparse SUBDIR_LIBBTPARSE = btparse
@ -51,7 +51,10 @@ dcimporter.h dcimporter.cpp griffithimporter.h \
griffithimporter.cpp griffith2tellico.py pdfimporter.h \ griffithimporter.cpp griffith2tellico.py pdfimporter.h \
pdfimporter.cpp referencerimporter.h referencerimporter.cpp \ pdfimporter.cpp referencerimporter.h referencerimporter.cpp \
libcsv.h libcsv.c \ 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)############ ####### tdevelop will overwrite this part!!! (end)############
@ -68,3 +71,4 @@ KDE_OPTIONS = noautodist
appdir = $(kde_datadir)/tellico appdir = $(kde_datadir)/tellico
app_DATA = bibtex-translation.xml app_DATA = bibtex-translation.xml
app_SCRIPTS = griffith2tellico.py app_SCRIPTS = griffith2tellico.py

@ -77,7 +77,7 @@ bool AlexandriaExporter::exec() {
ProgressItem& item = ProgressManager::self()->newProgressItem(this, TQString(), false); ProgressItem& item = ProgressManager::self()->newProgressItem(this, TQString(), false);
item.setTotalSteps(entries().count()); item.setTotalSteps(entries().count());
ProgressItem::Done done(this); 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; const bool showProgress = options() & ExportProgress;
GUI::CursorSaver cs; GUI::CursorSaver cs;

@ -308,5 +308,47 @@ TQWidget* BibtexImporter::widget(TQWidget* parent_, const char* name_/*=0*/) {
return m_widget; 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" #include "bibteximporter.moc"

@ -67,6 +67,8 @@ public:
virtual TQWidget* widget(TQWidget* parent, const char* name=0); virtual TQWidget* widget(TQWidget* parent, const char* name=0);
virtual bool canImport(int type) const; virtual bool canImport(int type) const;
static bool maybeBibtex(const KURL& url);
public slots: public slots:
void slotCancel(); void slotCancel();

@ -50,15 +50,26 @@ extern "C" {
using Tellico::Import::CSVImporter; using Tellico::Import::CSVImporter;
typedef int(*SpaceFunc)(char);
static void writeToken(char* buffer, size_t len, void* data); static void writeToken(char* buffer, size_t len, void* data);
static void writeRow(char buffer, 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 { class CSVImporter::Parser {
public: public:
Parser(const TQString& str) : stream(new TQTextIStream(&str)) { csv_init(&parser, 0); } Parser(const TQString& str) : stream(new TQTextIStream(&str)) { csv_init(&parser, 0); }
~Parser() { csv_free(parser); delete stream; stream = 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); }; void reset(const TQString& str) { delete stream; stream = new TQTextIStream(&str); };
bool hasNext() { return !stream->atEnd(); } bool hasNext() { return !stream->atEnd(); }
void skipLine() { stream->readLine(); } void skipLine() { stream->readLine(); }
@ -95,6 +106,21 @@ static void writeRow(char c, void* data) {
p->setRowDone(true); 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_), CSVImporter::CSVImporter(const KURL& url_) : Tellico::Import::TextImporter(url_),
m_coll(0), m_coll(0),
m_existingCollection(0), m_existingCollection(0),

@ -35,7 +35,9 @@ DeliciousImporter::DeliciousImporter(const KURL& url_) : XSLTImporter(url_) {
} }
bool DeliciousImporter::canImport(int type) const { 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() { Tellico::Data::CollPtr DeliciousImporter::collection() {
@ -51,7 +53,18 @@ Tellico::Data::CollPtr DeliciousImporter::collection() {
<< TQString::fromLatin1("Medium Covers/") << TQString::fromLatin1("Medium Covers/")
<< TQString::fromLatin1("Small Covers/") << TQString::fromLatin1("Small Covers/")
<< TQString::fromLatin1("Plain 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 uuidField = TQString::fromLatin1("uuid");
const TQString coverField = TQString::fromLatin1("cover"); const TQString coverField = TQString::fromLatin1("cover");
const bool isLocal = url().isLocalFile(); const bool isLocal = url().isLocalFile();

@ -365,7 +365,7 @@ FreeDBImporter::CDText FreeDBImporter::getCDText(const TQCString& drive_) {
} }
} }
if(cdtext.trackTitles.size() != cdtext.trackArtists.size()) { 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.trackTitles.resize(size);
cdtext.trackArtists.resize(size); cdtext.trackArtists.resize(size);
} }

@ -31,6 +31,7 @@
#include <tdeio/netaccess.h> #include <tdeio/netaccess.h>
#include <tdeapplication.h> #include <tdeapplication.h>
#include <tdelocale.h> #include <tdelocale.h>
#include <kuser.h>
#include <tqdom.h> #include <tqdom.h>
#include <tqgroupbox.h> #include <tqgroupbox.h>
@ -192,6 +193,9 @@ bool HTMLExporter::loadXSLTFile() {
m_handler = 0; m_handler = 0;
return false; 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) { if(m_exportEntryFiles) {
// export entries to same place as all the other date files // export entries to same place as all the other date files

@ -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 // 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 -" // however, at least one website (Springer) outputs RIS with no space after the final "ER -"
// so just strip the white space later // 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+-(.*)$")); TQRegExp rx(TQString::fromLatin1("^(\\w\\w)\\s+-(.*)$"));
TQString currLine, nextLine; TQString currLine, nextLine;
for(currLine = t.readLine(); !m_cancelled && !currLine.isNull(); currLine = nextLine, j += currLine.length()) { for(currLine = t.readLine(); !m_cancelled && !currLine.isNull(); currLine = nextLine, j += currLine.length()) {
@ -312,4 +312,25 @@ void RISImporter::slotCancel() {
m_cancelled = true; 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" #include "risimporter.moc"

@ -50,6 +50,8 @@ public:
virtual TQWidget* widget(TQWidget*, const char*) { return 0; } virtual TQWidget* widget(TQWidget*, const char*) { return 0; }
virtual bool canImport(int type) const; virtual bool canImport(int type) const;
static bool maybeRIS(const KURL& url);
public slots: public slots:
void slotCancel(); void slotCancel();

@ -63,6 +63,12 @@ TQString Tellico::XML::dtdTellico(int version) {
return TQString::fromLatin1("http://periapsis.org/tellico/dtd/v%1/tellico.dtd").arg(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_) { bool Tellico::XML::validXMLElementName(const TQString& name_) {
return xmlValidateNameValue((xmlChar *)name_.utf8().data()); return xmlValidateNameValue((xmlChar *)name_.utf8().data());
} }

@ -28,6 +28,8 @@ namespace Tellico {
TQString pubTellico(int version = syntaxVersion); TQString pubTellico(int version = syntaxVersion);
TQString dtdTellico(int version = syntaxVersion); TQString dtdTellico(int version = syntaxVersion);
bool versionConversion(uint from, uint to);
extern const TQString nsBookcase; extern const TQString nsBookcase;
extern const TQString nsDublinCore; extern const TQString nsDublinCore;
extern const TQString nsZing; extern const TQString nsZing;

@ -39,11 +39,6 @@
using Tellico::Import::TellicoImporter; 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_), TellicoImporter::TellicoImporter(const KURL& url_, bool loadAllImages_) : DataImporter(url_),
m_coll(0), m_loadAllImages(loadAllImages_), m_format(Unknown), m_modified(false), 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) { 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; m_format = Error;
return; 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 // 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. " 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 " "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; Data::FieldPtr field;
if(type == Data::Field::Choice) { 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"))); elem_.attribute(TQString::fromLatin1("allowed")));
if(isI18n) { if(isI18n) {
for(TQStringList::Iterator it = allowed.begin(); it != allowed.end(); ++it) { 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_) { void TellicoImporter::readImage(const TQDomElement& elem_, bool loadImage_) {
TQString format = elem_.attribute(TQString::fromLatin1("format")); TQString format = elem_.attribute(TQString::fromLatin1("format"));
const bool link = elem_.attribute(TQString::fromLatin1("link")) == Latin1Literal("true"); const bool link = elem_.attribute(TQString::fromLatin1("link")) == Latin1Literal("true");
TQString id = shareString(link ? elem_.attribute(TQString::fromLatin1("id")) // idClean() already calls shareString()
: Data::Image::idClean(elem_.attribute(TQString::fromLatin1("id")))); TQString id = link ? shareString(elem_.attribute(TQString::fromLatin1("id")))
: Data::Image::idClean(elem_.attribute(TQString::fromLatin1("id")));
bool readInfo = true; bool readInfo = true;
if(loadImage_) { if(loadImage_) {

@ -70,8 +70,6 @@ public slots:
void slotCancel(); void slotCancel();
private: private:
static bool versionConversion(uint from, uint to);
void loadXMLData(const TQByteArray& data, bool loadImages); void loadXMLData(const TQByteArray& data, bool loadImages);
void loadZipData(); void loadZipData();

@ -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"

@ -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

@ -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_;
}

@ -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

@ -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;
}

@ -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

@ -18,6 +18,8 @@
#include <tdelocale.h> #include <tdelocale.h>
#include <kurlrequester.h> #include <kurlrequester.h>
#include <kuser.h>
#include <tdeconfig.h>
#include <tqlabel.h> #include <tqlabel.h>
#include <tqgroupbox.h> #include <tqgroupbox.h>
@ -49,6 +51,9 @@ bool XSLTExporter::exec() {
} }
// XSLTHandler handler(FileHandler::readXMLFile(url)); // XSLTHandler handler(FileHandler::readXMLFile(url));
XSLTHandler handler(u); 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; TellicoXMLExporter exporter;
exporter.setEntries(entries()); exporter.setEntries(entries());
@ -75,6 +80,25 @@ TQWidget* XSLTExporter::widget(TQWidget* parent_, const char* name_/*=0*/) {
m_URLRequester = new KURLRequester(box); m_URLRequester = new KURLRequester(box);
TQWhatsThis::add(m_URLRequester, i18n("Choose the XSLT file used to transform the Tellico XML data.")); 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); l->addStretch(1);
return m_widget; 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);
}

@ -34,9 +34,13 @@ public:
virtual TQWidget* widget(TQWidget* parent, const char* name=0); virtual TQWidget* widget(TQWidget* parent, const char* name=0);
virtual void readOptions(TDEConfig* cfg);
virtual void saveOptions(TDEConfig* cfg);
private: private:
TQWidget* m_widget; TQWidget* m_widget;
KURLRequester* m_URLRequester; KURLRequester* m_URLRequester;
TQString m_xsltFile;
}; };
} // end namespace } // end namespace

@ -13,6 +13,7 @@
#include "upcvalidator.h" #include "upcvalidator.h"
#include "isbnvalidator.h" #include "isbnvalidator.h"
#include "tellico_debug.h"
#include <kmdcodec.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 { TQValidator::State UPCValidator::validate(TQString& input_, int& pos_) const {
// check if it's a cuecat first // check if it's a cuecat first
State catState = decodeCat(input_); State catState = CueCat::decode(input_);
if(catState == Acceptable) { if(catState == Acceptable) {
pos_ = input_.length(); pos_ = input_.length();
return catState; 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) { if(input_.length() < 3) {
return Intermediate; return TQValidator::Intermediate;
} }
if(!input_.startsWith(TQString::fromLatin1(".C3"))) { // all cuecat codes start with .C3 if(!input_.startsWith(TQString::fromLatin1(".C3"))) { // all cuecat codes start with .C3
return Invalid; return TQValidator::Invalid;
} }
const int periods = input_.contains('.'); const int periods = input_.contains('.');
if(periods < 4) { if(periods < 4) {
return Intermediate; // not enough yet return TQValidator::Intermediate; // not enough yet
} else if(periods > 4) { } else if(periods > 4) {
return Invalid; return TQValidator::Invalid;
} }
// ok, let's have a go, take the third token // ok, let's have a go, take the third token
@ -127,7 +128,7 @@ TQValidator::State UPCValidator::decodeCat(TQString& input_) const {
} }
input_ = code; input_ = code;
return Acceptable; return TQValidator::Acceptable;
} }
#include "upcvalidator.moc" #include "upcvalidator.moc"

@ -37,11 +37,14 @@ signals:
void signalISBN(); void signalISBN();
private: private:
State decodeCat(TQString& str) const;
bool m_checkISBN : 1; bool m_checkISBN : 1;
mutable bool m_isbn : 1; mutable bool m_isbn : 1;
}; };
class CueCat {
public:
static TQValidator::State decode(TQString& str);
};
} // end namespace } // end namespace
#endif #endif

@ -53,6 +53,9 @@
<xsl:variable name="lcletters">abcdefghijklmnopqrstuvwxyz</xsl:variable> <xsl:variable name="lcletters">abcdefghijklmnopqrstuvwxyz</xsl:variable>
<xsl:variable name="ucletters">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable> <xsl:variable name="ucletters">ABCDEFGHIJKLMNOPQRSTUVWXYZ</xsl:variable>
<!-- disable default behavior -->
<xsl:template match="text()|@*"></xsl:template>
<xsl:template match="/"> <xsl:template match="/">
<tellico syntaxVersion="10"> <tellico syntaxVersion="10">
<collection title="Amazon Import"> <collection title="Amazon Import">
@ -71,6 +74,9 @@
<xsl:when test="$mode='VideoGames'"> <xsl:when test="$mode='VideoGames'">
<xsl:text>11</xsl:text> <xsl:text>11</xsl:text>
</xsl:when> </xsl:when>
<xsl:when test="$mode='Toys'">
<xsl:text>13</xsl:text>
</xsl:when>
</xsl:choose> </xsl:choose>
</xsl:attribute> </xsl:attribute>
<fields> <fields>
@ -81,9 +87,19 @@
<field flags="0" title="Medium Image" category="Images" format="4" type="7" name="medium-image"/> <field flags="0" title="Medium Image" category="Images" format="4" type="7" name="medium-image"/>
<field flags="0" title="Large Image" category="Images" format="4" type="7" name="large-image"/> <field flags="0" title="Large Image" category="Images" format="4" type="7" name="large-image"/>
</fields> </fields>
<xsl:for-each select="//aws:Items/aws:Item"> <!-- results for board games need to be filtered -->
<xsl:apply-templates select="."/> <xsl:if test="$mode != 'Toys'">
</xsl:for-each> <xsl:for-each select="//aws:Items/aws:Item">
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:if>
<xsl:if test="$mode = 'Toys'">
<!-- only grab items in the board games category -->
<xsl:for-each select="//aws:Items/aws:Item[.//aws:BrowseNode/aws:Name='Board Games' or
.//aws:BrowseNode/aws:BrowseNodeId='166225011']">
<xsl:apply-templates select="."/>
</xsl:for-each>
</xsl:if>
</collection> </collection>
</tellico> </tellico>
</xsl:template> </xsl:template>
@ -496,6 +512,27 @@
</xsl:choose> </xsl:choose>
</certification> </certification>
</xsl:when> </xsl:when>
<xsl:when test="$mode='Toys'">
<publishers>
<publisher>
<xsl:value-of select="(aws:Label|aws:Brand|aws:Publisher|aws:Manufacturer)[1]"/>
</publisher>
</publishers>
<description>
<xsl:value-of select="../aws:EditorialReviews/aws:EditorialReview[1]/aws:Content"/>
<xsl:for-each select="aws:Feature">
<xsl:value-of select="."/>
<!-- if the last character is not punctuation, add a period -->
<xsl:if test="not(contains('.!?,/', substring(., string-length(.))))">
<xsl:text>.</xsl:text>
</xsl:if>
<xsl:text> </xsl:text>
</xsl:for-each>
</description>
</xsl:when>
</xsl:choose> </xsl:choose>
</xsl:template> </xsl:template>

@ -42,6 +42,10 @@
</tellico> </tellico>
</xsl:template> </xsl:template>
<!-- ignore unresolved queries -->
<xsl:template match="cr:query[@status='unresolved']">
</xsl:template>
<xsl:template match="cr:query"> <xsl:template match="cr:query">
<entry> <entry>

@ -21,17 +21,41 @@
doctype-public="-//Robby Stephenson/DTD Tellico V10.0//EN" doctype-public="-//Robby Stephenson/DTD Tellico V10.0//EN"
doctype-system="http://periapsis.org/tellico/dtd/v10/tellico.dtd"/> doctype-system="http://periapsis.org/tellico/dtd/v10/tellico.dtd"/>
<xsl:param name="item-type"/>
<xsl:template match="/"> <xsl:template match="/">
<tc:tellico syntaxVersion="10"> <tc:tellico syntaxVersion="10">
<tc:collection title="Delicious Library Import" type="2"> <!-- DL libraries can contain mixed types and right now, there's no way to do that in Tellico -->
<!-- so we're going to limit the export to whatever the type of the first item is -->
<xsl:variable name="item">
<xsl:choose>
<xsl:when test="string-length($item-type) &gt; 0">
<xsl:value-of select="$item-type"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="local-name(library/items/child::*[1])"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:comment><xsl:text>Choosing all items of type </xsl:text><xsl:value-of select="$item"/></xsl:comment>
<xsl:variable name="type">
<xsl:choose>
<xsl:when test="$item='book'">2</xsl:when>
<xsl:when test="$item='movie'">3</xsl:when>
<xsl:when test="$item='game'">11</xsl:when>
<xsl:otherwise>0</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<tc:collection title="Delicious Library Import">
<xsl:attribute name="type"><xsl:value-of select="$type"/></xsl:attribute>
<tc:fields> <tc:fields>
<tc:field name="_default"/> <tc:field name="_default"/>
<tc:field flags="0" title="Amazon Link" category="General" format="4" type="7" name="amazon" i18n="true"/> <tc:field flags="0" title="Amazon Link" category="General" format="4" type="7" name="amazon" i18n="true"/>
<tc:field flags="0" title="UUID" category="General" format="0" type="1" name="uuid"/> <tc:field flags="0" title="UUID" category="General" format="0" type="1" name="uuid"/>
</tc:fields> </tc:fields>
<xsl:for-each select="library/items/book"> <xsl:apply-templates select="library/items/child::*[local-name()=$item]"/>
<xsl:apply-templates select="."/>
</xsl:for-each>
</tc:collection> </tc:collection>
</tc:tellico> </tc:tellico>
</xsl:template> </xsl:template>
@ -56,7 +80,7 @@
<xsl:otherwise> <xsl:otherwise>
<xsl:value-of select="@title"/> <xsl:value-of select="@title"/>
</xsl:otherwise> </xsl:otherwise>
</xsl:choose> </xsl:choose>
</tc:title> </tc:title>
<tc:subtitle> <tc:subtitle>
@ -116,7 +140,7 @@
<tc:rating> <tc:rating>
<!-- tellico automatically rounds down --> <!-- tellico automatically rounds down -->
<xsl:value-of select="netrating"/> <xsl:value-of select="@netrating"/>
</tc:rating> </tc:rating>
<xsl:call-template name="split"> <xsl:call-template name="split">
@ -132,6 +156,219 @@
</tc:entry> </tc:entry>
</xsl:template> </xsl:template>
<xsl:template match="movie">
<tc:entry>
<tc:uuid>
<xsl:value-of select="@uuid"/>
</tc:uuid>
<tc:amazon>
<xsl:if test="@asin">
<xsl:value-of select="concat('http://www.amazon.com/dp/',@asin,'/?tag=tellico-20')"/>
</xsl:if>
</tc:amazon>
<tc:title>
<xsl:call-template name="strip-title">
<xsl:with-param name="title" select="@title"/>
</xsl:call-template>
</tc:title>
<tc:medium>
<xsl:value-of select="@aspect"/>
</tc:medium>
<xsl:call-template name="split">
<xsl:with-param name="name" select="'tc:director'"/>
<xsl:with-param name="value" select="@director"/>
</xsl:call-template>
<xsl:call-template name="split">
<xsl:with-param name="name" select="'tc:cast'"/>
<xsl:with-param name="value" select="@stars"/>
</xsl:call-template>
<xsl:if test="contains(@features, 'Widescreen')">
<tc:widescreen>true</tc:widescreen>
</xsl:if>
<xsl:if test="contains(@features, 'NTSC')">
<tc:format i18n="true">NTSC</tc:format>
</xsl:if>
<xsl:if test="contains(@features, 'PAL')">
<tc:format i18n="true">PAL</tc:format>
</xsl:if>
<xsl:if test="contains(@features, 'SECAM')">
<tc:format i18n="true">SECAM</tc:format>
</xsl:if>
<xsl:if test="contains(@features, 'Color')">
<tc:color i18n="true">Color</tc:color>
</xsl:if>
<xsl:if test="contains(@features, 'Black &amp; White')">
<tc:color i18n="true">Black &amp; White</tc:color>
</xsl:if>
<xsl:if test="contains(@features, '1.33:1')">
<tc:aspect-ratios>
<tc:aspect-ratio>1.33:1</tc:aspect-ratio>
</tc:aspect-ratios>
</xsl:if>
<xsl:if test="contains(@features, '1.85:1')">
<tc:aspect-ratios>
<tc:aspect-ratio>1.85:1</tc:aspect-ratio>
</tc:aspect-ratios>
</xsl:if>
<tc:audio-tracks>
<xsl:if test="contains(@features, 'Dolby')">
<tc:audio-track i18n="true">Dolby</tc:audio-track>
</xsl:if>
<xsl:if test="contains(@features, 'DTS')">
<tc:audio-track i18n="true">DTS</tc:audio-track>
</xsl:if>
</tc:audio-tracks>
<xsl:choose>
<xsl:when test="contains(@genre, 'Region 1')">
<tc:region i18n="true">Region 1</tc:region>
</xsl:when>
<xsl:when test="contains(@genre, 'Region 2')">
<tc:region i18n="true">Region 2</tc:region>
</xsl:when>
<xsl:when test="contains(@genre, 'Region 3')">
<tc:region i18n="true">Region 3</tc:region>
</xsl:when>
<xsl:when test="contains(@genre, 'Region 4')">
<tc:region i18n="true">Region 4</tc:region>
</xsl:when>
<xsl:when test="contains(@genre, 'Region 5')">
<tc:region i18n="true">Region 5</tc:region>
</xsl:when>
<xsl:when test="contains(@genre, 'Region 6')">
<tc:region i18n="true">Region 6</tc:region>
</xsl:when>
<xsl:when test="contains(@genre, 'Region 7')">
<tc:region i18n="true">Region 7</tc:region>
</xsl:when>
<xsl:when test="contains(@genre, 'Region 8')">
<tc:region i18n="true">Region 8</tc:region>
</xsl:when>
</xsl:choose>
<xsl:call-template name="split">
<xsl:with-param name="name" select="'tc:genre'"/>
<xsl:with-param name="value" select="@genre"/>
<xsl:with-param name="i18n" select="true()"/>
</xsl:call-template>
<xsl:call-template name="split">
<xsl:with-param name="name" select="'tc:studio'"/>
<xsl:with-param name="value" select="@publisher"/>
</xsl:call-template>
<tc:running-time>
<xsl:value-of select="@minutes"/>
</tc:running-time>
<tc:certification>
<xsl:value-of select="concat(@mpaarating, ' (US)')"/>
</tc:certification>
<tc:year>
<xsl:call-template name="year">
<xsl:with-param name="value" select="@theatricalDate"/>
</xsl:call-template>
</tc:year>
<tc:pur_price>
<xsl:value-of select="@price"/>
</tc:pur_price>
<tc:pur_date>
<xsl:value-of select="@purchaseDate"/>
</tc:pur_date>
<tc:rating>
<!-- tellico automatically rounds down -->
<xsl:value-of select="@netrating"/>
</tc:rating>
<xsl:call-template name="split">
<xsl:with-param name="name" select="'tc:nationality'"/>
<xsl:with-param name="value" select="@country"/>
</xsl:call-template>
<tc:plot>
<xsl:value-of select="description"/>
</tc:plot>
</tc:entry>
</xsl:template>
<xsl:template match="game">
<tc:entry>
<tc:uuid>
<xsl:value-of select="@uuid"/>
</tc:uuid>
<tc:amazon>
<xsl:if test="@asin">
<xsl:value-of select="concat('http://www.amazon.com/dp/',@asin,'/?tag=tellico-20')"/>
</xsl:if>
</tc:amazon>
<tc:title>
<xsl:value-of select="@title"/>
</tc:title>
<tc:platform>
<xsl:value-of select="@platform"/>
</tc:platform>
<tc:certification>
<xsl:value-of select="@esrbrating"/>
</tc:certification>
<xsl:call-template name="split">
<xsl:with-param name="name" select="'tc:genre'"/>
<xsl:with-param name="value" select="@genre"/>
<xsl:with-param name="i18n" select="true()"/>
</xsl:call-template>
<tc:pur_price>
<xsl:value-of select="@price"/>
</tc:pur_price>
<tc:pur_date>
<xsl:value-of select="@purchaseDate"/>
</tc:pur_date>
<tc:year>
<xsl:call-template name="year">
<xsl:with-param name="value" select="@published"/>
</xsl:call-template>
</tc:year>
<tc:rating>
<!-- tellico automatically rounds down -->
<xsl:value-of select="@netrating"/>
</tc:rating>
<tc:publisher>
<xsl:value-of select="@publisher"/>
</tc:publisher>
<tc:description>
<xsl:value-of select="description"/>
</tc:description>
</tc:entry>
</xsl:template>
<xsl:template name="split"> <xsl:template name="split">
<xsl:param name="name"/> <xsl:param name="name"/>
<xsl:param name="value"/> <xsl:param name="value"/>
@ -161,4 +398,38 @@
<xsl:value-of select="substring($numbers, string-length($numbers)-3, 4)"/> <xsl:value-of select="substring($numbers, string-length($numbers)-3, 4)"/>
</xsl:template> </xsl:template>
<xsl:template name="strip-title">
<xsl:param name="title"/>
<xsl:param name="chars" select="'[('"/>
<xsl:choose>
<xsl:when test="string-length($chars) = 0">
<xsl:value-of select="normalize-space($title)"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="strip-title">
<xsl:with-param name="title">
<xsl:call-template name="str-before">
<xsl:with-param name="value1" select="$title"/>
<xsl:with-param name="value2" select="substring($chars,1,1)"/>
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="chars" select="substring($chars,2)"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="str-before">
<xsl:param name="value1"/>
<xsl:param name="value2"/>
<xsl:choose>
<xsl:when test="string-length($value2) &gt; 0 and contains($value1, $value2)">
<xsl:value-of select="substring-before($value1, $value2)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$value1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet> </xsl:stylesheet>

@ -79,6 +79,11 @@
<tc:field flags="8" title="Original Title" category="General" format="1" type="1" name="origtitle" i18n="true"/> <tc:field flags="8" title="Original Title" category="General" format="1" type="1" name="origtitle" i18n="true"/>
<tc:field flags="0" title="Seen" category="Personal" format="4" type="4" name="seen" i18n="true"/> <tc:field flags="0" title="Seen" category="Personal" format="4" type="4" name="seen" i18n="true"/>
</xsl:when> </xsl:when>
<xsl:when test="@type='GCcoins'">
<!-- gcstar includes way more coin grades than tellico -->
<tc:field flags="2" title="Grade" category="General" format="4" type="3" name="grade"
allowed="Proof-65;Proof-60;Mint State-70;Mint State-69;Mint State-68;Mint State-67;Mint State-66;Mint State-65;Mint State-64;Mint State-63;Mint State-62;Mint State-61;Mint State-60;Almost Uncirculated-58;Almost Uncirculated-55;Almost Uncirculated-53;Almost Uncirculated-50;Extremely Fine-45;Extremely Fine-40;Very Fine-35;Very Fine-30;Very Fine-25;Very Fine-20;Fine-15;Fine-12;Very Good-10;Very Good-8;Good-6;Good-4;Fair"/>
</xsl:when>
</xsl:choose> </xsl:choose>
</tc:fields> </tc:fields>
<xsl:apply-templates select="item"/> <xsl:apply-templates select="item"/>
@ -477,6 +482,48 @@
</tc:num-players> </tc:num-players>
</xsl:template> </xsl:template>
<!-- coins -->
<xsl:template match="condition">
<!-- by default, Tellico includes
"Proof-65,Proof-60,Mint State-65,Mint State-60,"
"Almost Uncirculated-55,Almost Uncirculated-50,"
"Extremely Fine-40,Very Fine-30,Very Fine-20,Fine-12,"
"Very Good-8,Good-4,Fair" -->
<!-- GCStar doesn't appear to include proof grades -->
<tc:grade>
<xsl:choose>
<xsl:when test=".='70'">Mint State-70</xsl:when>
<xsl:when test=".='69'">Mint State-69</xsl:when>
<xsl:when test=".='68'">Mint State-68</xsl:when>
<xsl:when test=".='67'">Mint State-67</xsl:when>
<xsl:when test=".='66'">Mint State-66</xsl:when>
<xsl:when test=".='65'">Mint State-65</xsl:when>
<xsl:when test=".='64'">Mint State-64</xsl:when>
<xsl:when test=".='63'">Mint State-63</xsl:when>
<xsl:when test=".='62'">Mint State-62</xsl:when>
<xsl:when test=".='61'">Mint State-61</xsl:when>
<xsl:when test=".='60'">Mint State-60</xsl:when>
<xsl:when test=".='58'">Almost Uncirculated-58</xsl:when>
<xsl:when test=".='55'">Almost Uncirculated-55</xsl:when>
<xsl:when test=".='53'">Almost Uncirculated-53</xsl:when>
<xsl:when test=".='50'">Almost Uncirculated-50</xsl:when>
<xsl:when test=".='45'">Extremely Fine-45</xsl:when>
<xsl:when test=".='40'">Extremely Fine-40</xsl:when>
<xsl:when test=".='35'">Very Fine-35</xsl:when>
<xsl:when test=".='30'">Very Fine-30</xsl:when>
<xsl:when test=".='25'">Very Fine-25</xsl:when>
<xsl:when test=".='20'">Very Fine-20</xsl:when>
<xsl:when test=".='15'">Fine-15</xsl:when>
<xsl:when test=".='12'">Fine-12</xsl:when>
<xsl:when test=".='10'">Very Good-10</xsl:when>
<xsl:when test=".='8'">Very Good-8</xsl:when>
<xsl:when test=".='6'">Good-6</xsl:when>
<xsl:when test=".='4'">Good-4</xsl:when>
<xsl:when test=".&lt;4">Fair</xsl:when>
</xsl:choose>
</tc:grade>
</xsl:template>
<xsl:template name="year"> <xsl:template name="year">
<xsl:param name="value"/> <xsl:param name="value"/>
<!-- want to find a 4-digit number to treat as the year --> <!-- want to find a 4-digit number to treat as the year -->

@ -258,7 +258,10 @@
</xsl:attribute> </xsl:attribute>
<img> <img>
<xsl:attribute name="src"> <xsl:attribute name="src">
<xsl:value-of select="concat($imgdir, .)"/> <xsl:call-template name="image-link">
<xsl:with-param name="image" select="key('imagesById', .)"/>
<xsl:with-param name="dir" select="$imgdir"/>
</xsl:call-template>
</xsl:attribute> </xsl:attribute>
<xsl:call-template name="image-size"> <xsl:call-template name="image-size">
<xsl:with-param name="limit-width" select="$image-width"/> <xsl:with-param name="limit-width" select="$image-width"/>

@ -117,6 +117,7 @@
margin: 0px 0px 0px 0px; margin: 0px 0px 0px 0px;
padding: 0px 10px 0px 4px; padding: 0px 10px 0px 4px;
float: left; float: left;
min-height: 1em;
} }
span.bar { span.bar {
width: 590px; width: 590px;
@ -178,7 +179,7 @@
<xsl:for-each select="tc:fields/tc:field[boolean(floor(@flags div 2) mod 2)]"> <xsl:for-each select="tc:fields/tc:field[boolean(floor(@flags div 2) mod 2)]">
<xsl:call-template name="output-group"> <xsl:call-template name="output-group">
<xsl:with-param name="coll" select="$coll"/> <xsl:with-param name="coll" select="$coll"/>
<xsl:with-param name="fieldname" select="@name"/> <xsl:with-param name="field" select="."/>
</xsl:call-template> </xsl:call-template>
</xsl:for-each> </xsl:for-each>
@ -189,35 +190,49 @@
<xsl:template name="output-group"> <xsl:template name="output-group">
<xsl:param name="coll"/> <xsl:param name="coll"/>
<xsl:param name="fieldname"/> <xsl:param name="field"/>
<xsl:variable name="str"> <xsl:variable name="fieldname" select="$field/@name"/>
<xsl:choose> <xsl:variable name="value-expr">
<xsl:when test="boolean(floor(key('fieldsByName', $fieldname)/@flags mod 2))"> <xsl:for-each select="$coll/tc:entry">
<xsl:choose> <xsl:choose>
<xsl:when test="key('fieldsByName', $fieldname)/@type=8"> <!-- tables -->
<xsl:value-of select="concat('$coll/tc:entry/tc:',$fieldname,'s/tc:',$fieldname,'/tc:column[1]')"/> <xsl:when test="$field/@type=8">
</xsl:when> <xsl:for-each select="./*/*[local-name() = $fieldname]">
<xsl:otherwise> <value>
<xsl:value-of select="concat('$coll/tc:entry/tc:',$fieldname,'s/tc:',$fieldname)"/> <xsl:value-of select="tc:column[1]"/>
</xsl:otherwise> </value>
</xsl:choose> </xsl:for-each>
</xsl:when> </xsl:when>
<xsl:otherwise> <!-- multiple values...could also use "./*/*[local-name() = $fieldname]" -->
<xsl:value-of select="concat('$coll/tc:entry/tc:',$fieldname)"/> <xsl:when test="boolean(floor(key('fieldsByName', $fieldname)/@flags mod 2))">
</xsl:otherwise> <xsl:for-each select="./*/*[local-name() = $fieldname]">
</xsl:choose> <value>
<xsl:value-of select="."/>
</value>
</xsl:for-each>
</xsl:when>
<xsl:otherwise>
<value>
<xsl:call-template name="simple-field-value">
<xsl:with-param name="entry" select="."/>
<xsl:with-param name="field" select="$fieldname"/>
</xsl:call-template>
</value>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:variable> </xsl:variable>
<xsl:variable name="values" select="dyn:evaluate($str)"/>
<xsl:variable name="values" select="exsl:node-set($value-expr)/value"/>
<xsl:variable name="listing"> <xsl:variable name="listing">
<xsl:for-each select="$values[not(. = preceding::*)]"> <xsl:for-each select="$values[not(. = preceding-sibling::*)]">
<!-- speed sorting by ignoring groups with a count of 1 --> <!-- speed sorting by ignoring groups with a count of 1 -->
<xsl:variable name="c" select="count($values[. = current()])"/> <xsl:variable name="c" select="count($values[. = current()])"/>
<xsl:if test="$c &gt; 1"> <xsl:if test="$c &gt; 1">
<group> <group>
<xsl:attribute name="name"> <xsl:attribute name="name">
<xsl:call-template name="text-value"/> <xsl:value-of select="."/>
</xsl:attribute> </xsl:attribute>
<xsl:attribute name="count"> <xsl:attribute name="count">
<xsl:value-of select="$c"/> <xsl:value-of select="$c"/>
@ -229,11 +244,11 @@
<xsl:variable name="groups" select="exsl:node-set($listing)/group"/> <xsl:variable name="groups" select="exsl:node-set($listing)/group"/>
<xsl:variable name="total" select="count($groups)"/> <xsl:variable name="total" select="count($groups)"/>
<xsl:variable name="max"> <xsl:variable name="max">
<xsl:call-template name="max-count"> <xsl:call-template name="max-count">
<xsl:with-param name="nodes" select="$groups"/> <xsl:with-param name="nodes" select="$groups"/>
</xsl:call-template> </xsl:call-template>
</xsl:variable> </xsl:variable>
<xsl:if test="$total &gt; 2"> <xsl:if test="$total &gt; 2">
@ -305,17 +320,6 @@
</xsl:choose> </xsl:choose>
</xsl:template> </xsl:template>
<xsl:template name="text-value">
<xsl:choose>
<xsl:when test="text()">
<xsl:value-of select="text()"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="..//tc:column[1]"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet> </xsl:stylesheet>
<!-- Local Variables: --> <!-- Local Variables: -->
<!-- sgml-indent-step: 1 --> <!-- sgml-indent-step: 1 -->

@ -232,7 +232,10 @@
</xsl:attribute> </xsl:attribute>
<img> <img>
<xsl:attribute name="src"> <xsl:attribute name="src">
<xsl:value-of select="concat($imgdir, .)"/> <xsl:call-template name="image-link">
<xsl:with-param name="image" select="key('imagesById', .)"/>
<xsl:with-param name="dir" select="$imgdir"/>
</xsl:call-template>
</xsl:attribute> </xsl:attribute>
<xsl:call-template name="image-size"> <xsl:call-template name="image-size">
<xsl:with-param name="limit-width" select="$image-width"/> <xsl:with-param name="limit-width" select="$image-width"/>

@ -141,7 +141,10 @@
<xsl:if test="$id"> <xsl:if test="$id">
<img class="float"> <img class="float">
<xsl:attribute name="src"> <xsl:attribute name="src">
<xsl:value-of select="concat($imgdir, $id)"/> <xsl:call-template name="image-link">
<xsl:with-param name="image" select="key('imagesById', $id)"/>
<xsl:with-param name="dir" select="$imgdir"/>
</xsl:call-template>
</xsl:attribute> </xsl:attribute>
<xsl:call-template name="image-size"> <xsl:call-template name="image-size">
<xsl:with-param name="limit-width" select="$image-width"/> <xsl:with-param name="limit-width" select="$image-width"/>
@ -150,7 +153,7 @@
</xsl:call-template> </xsl:call-template>
</img> </img>
</xsl:if> </xsl:if>
<table> <table>
<thead> <thead>
<tr> <tr>
@ -163,8 +166,9 @@
<tbody> <tbody>
<!-- don't repeat title --> <!-- don't repeat title -->
<xsl:for-each select="$columns[. != 'title']"> <xsl:for-each select="$columns[. != 'title']">
<!-- no other images allowed --> <!-- no other images or paragraphs allowed -->
<xsl:if test="$entry/../tc:fields/tc:field[@name = current()]/@type != 10"> <xsl:variable name="ftype" select="$entry/../tc:fields/tc:field[@name = current()]/@type"/>
<xsl:if test="$ftype != 10 and $ftype != 2">
<xsl:call-template name="field-output"> <xsl:call-template name="field-output">
<xsl:with-param name="entry" select="$entry"/> <xsl:with-param name="entry" select="$entry"/>
<!-- can't use a key, the context is not the document --> <!-- can't use a key, the context is not the document -->

@ -193,7 +193,10 @@
<xsl:if test="$id"> <xsl:if test="$id">
<img class="float" alt=" "> <img class="float" alt=" ">
<xsl:attribute name="src"> <xsl:attribute name="src">
<xsl:value-of select="concat($imgdir, $id)"/> <xsl:call-template name="image-link">
<xsl:with-param name="image" select="key('imagesById', $id)"/>
<xsl:with-param name="dir" select="$imgdir"/>
</xsl:call-template>
</xsl:attribute> </xsl:attribute>
<xsl:call-template name="image-size"> <xsl:call-template name="image-size">
<xsl:with-param name="limit-width" select="$image-width"/> <xsl:with-param name="limit-width" select="$image-width"/>

@ -329,7 +329,10 @@
</xsl:attribute> </xsl:attribute>
<img> <img>
<xsl:attribute name="src"> <xsl:attribute name="src">
<xsl:value-of select="concat($imgdir, .)"/> <xsl:call-template name="image-link">
<xsl:with-param name="image" select="key('imagesById', .)"/>
<xsl:with-param name="dir" select="$imgdir"/>
</xsl:call-template>
</xsl:attribute> </xsl:attribute>
<xsl:call-template name="image-size"> <xsl:call-template name="image-size">
<xsl:with-param name="limit-width" select="$image-width"/> <xsl:with-param name="limit-width" select="$image-width"/>

@ -65,6 +65,9 @@
<xsl:when test="tc:tellico/tc:collection/@type=4"> <xsl:when test="tc:tellico/tc:collection/@type=4">
<xsl:text>GCmusics</xsl:text> <xsl:text>GCmusics</xsl:text>
</xsl:when> </xsl:when>
<xsl:when test="tc:tellico/tc:collection/@type=8">
<xsl:text>GCcoins</xsl:text>
</xsl:when>
</xsl:choose> </xsl:choose>
</xsl:variable> </xsl:variable>
<!-- grab all the applicable attributes once --> <!-- grab all the applicable attributes once -->
@ -80,7 +83,7 @@
<xsl:apply-templates select="tc:collection"/> <xsl:apply-templates select="tc:collection"/>
</xsl:template> </xsl:template>
<xsl:template match="tc:collection[@type&lt;2 or @type&gt;5]"> <xsl:template match="tc:collection[@type&lt;2 or @type&gt;5 and not(@type=8)]">
<xsl:message terminate="yes"> <xsl:message terminate="yes">
<xsl:text>GCstar export is not supported for this collection type.</xsl:text> <xsl:text>GCstar export is not supported for this collection type.</xsl:text>
</xsl:message> </xsl:message>
@ -147,6 +150,13 @@
</xsl:choose> </xsl:choose>
</xsl:attribute> </xsl:attribute>
</xsl:if> </xsl:if>
<!-- for coin grade, GCstar uses numbers only -->
<xsl:if test="tc:grade">
<xsl:attribute name="condition">
<!-- remove everything but numbers -->
<xsl:value-of select="translate(tc:grade,translate(tc:grade,'0123456789', ''),'')"/>
</xsl:attribute>
</xsl:if>
<!-- for books --> <!-- for books -->
<comments> <comments>

@ -127,8 +127,8 @@ sorttable = {
if (!document.createElement || !document.getElementsByTagName) return; if (!document.createElement || !document.getElementsByTagName) return;
sorttable.DATE_RE = /^(\d\d)[\/\.-](\d\d?)[\/\.-]((\d\d)?\d\d)$/; sorttable.DATE_RE = /^(\d\d?)[\/\.-](\d\d?)[\/\.-](\d{4}|\d\d)$/;
sorttable.YYMMDD_RE = /^((\d\d)?\d\d)[\/\.-](\d\d?)[\/\.-](\d\d)$/; sorttable.YYMMDD_RE = /^(\d{4}|\d\d)[\/\.-](\d\d?)[\/\.-](\d\d?)$/;
forEach(document.getElementsByTagName('table'), function(table) { forEach(document.getElementsByTagName('table'), function(table) {
if (table.className.search(/\bsortable\b/) != -1) { if (table.className.search(/\bsortable\b/) != -1) {
@ -371,7 +371,8 @@ sorttable = {
if (mtch) { if (mtch) {
y = mtch[1]; m = mtch[2]; d = mtch[3]; y = mtch[1]; m = mtch[2]; d = mtch[3];
// y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX // y2k notes: two digit years less than 50 are treated as 20XX, greater than 50 are treated as 19XX
if (parseInt(y) < 50) y = '20'+y; else y = '19'+y; if (y.length == 2)
if (parseInt(y) < 50) y = '20'+y; else y = '19'+y;
if (m.length == 1) m = '0'+m; if (m.length == 1) m = '0'+m;
if (d.length == 1) d = '0'+d; if (d.length == 1) d = '0'+d;
dt1 = y+m+d; dt1 = y+m+d;
@ -379,7 +380,8 @@ sorttable = {
mtch = b[0].match(sorttable.YYMMDD_RE); mtch = b[0].match(sorttable.YYMMDD_RE);
if (mtch) { if (mtch) {
y = mtch[1]; m = mtch[2]; d = mtch[3]; y = mtch[1]; m = mtch[2]; d = mtch[3];
if (parseInt(y) < 50) y = '20'+y; else y = '19'+y; if (y.length == 2)
if (parseInt(y) < 50) y = '20'+y; else y = '19'+y;
if (m.length == 1) m = '0'+m; if (m.length == 1) m = '0'+m;
if (d.length == 1) d = '0'+d; if (d.length == 1) d = '0'+d;
dt2 = y+m+d; dt2 = y+m+d;

@ -115,10 +115,7 @@
</xsl:if> </xsl:if>
</xsl:variable> </xsl:variable>
<!-- keys ends up useless since we're using exsl:node-set
<xsl:key name="fieldsByName" match="tc:field" use="@name"/>
<xsl:key name="imagesById" match="tc:image" use="@id"/> <xsl:key name="imagesById" match="tc:image" use="@id"/>
-->
<xsl:key name="entriesById" match="tc:entry" use="@id"/> <xsl:key name="entriesById" match="tc:entry" use="@id"/>
<!-- filename conversion is weird, need a variable for easy replacement --> <!-- filename conversion is weird, need a variable for easy replacement -->
@ -557,7 +554,10 @@
</xsl:attribute> </xsl:attribute>
<img> <img>
<xsl:attribute name="src"> <xsl:attribute name="src">
<xsl:value-of select="concat($imgdir, .)"/> <xsl:call-template name="image-link">
<xsl:with-param name="image" select="key('imagesById', .)"/>
<xsl:with-param name="dir" select="$imgdir"/>
</xsl:call-template>
</xsl:attribute> </xsl:attribute>
<xsl:attribute name="alt"> <xsl:attribute name="alt">
<xsl:value-of select="concat('[', $entry//tc:title[1], ']')"/> <xsl:value-of select="concat('[', $entry//tc:title[1], ']')"/>

@ -46,9 +46,12 @@
</xsl:template> </xsl:template>
<xsl:template match="cr:crossref"> <xsl:template match="cr:crossref">
<entry> <!-- if there's an error, or none found, a crossref element still shows up, with an error element -->
<xsl:apply-templates/> <xsl:if test="not(cr:error)">
</entry> <entry>
<xsl:apply-templates/>
</entry>
</xsl:if>
</xsl:template> </xsl:template>
<xsl:template match="cr:book"> <xsl:template match="cr:book">

Loading…
Cancel
Save