diff options
275 files changed, 1 insertions, 47626 deletions
diff --git a/configure.ac b/configure.ac index 093dd7ae2..04241810d 100644 --- a/configure.ac +++ b/configure.ac @@ -297,13 +297,6 @@ LIBTRACKER_REMOTE_REQUIRED="glib-2.0 >= $GLIB_REQUIRED PKG_CHECK_MODULES(LIBTRACKER_REMOTE, [$LIBTRACKER_REMOTE_REQUIRED]) -# Check requirements for libtracker-extract -LIBTRACKER_EXTRACT_REQUIRED="glib-2.0 >= $GLIB_REQUIRED - gio-unix-2.0 >= $GLIB_REQUIRED - gmodule-2.0 >= $GLIB_REQUIRED" - -PKG_CHECK_MODULES(LIBTRACKER_EXTRACT, [$LIBTRACKER_EXTRACT_REQUIRED]) - # Check requirements for libtracker-fts LIBTRACKER_FTS_REQUIRED="glib-2.0 >= $GLIB_REQUIRED gio-unix-2.0 >= $GLIB_REQUIRED @@ -354,56 +347,6 @@ PKG_CHECK_MODULES(TRACKER_STORE, [$TRACKER_STORE_REQUIRED]) TRACKER_STORE_LIBS="$TRACKER_STORE_LIBS -lz -lm" -# Check requirements for tracker-extract -TRACKER_EXTRACT_REQUIRED="glib-2.0 >= $GLIB_REQUIRED - gio-unix-2.0 >= $GLIB_REQUIRED - gmodule-2.0 >= $GLIB_REQUIRED" - -PKG_CHECK_MODULES(TRACKER_EXTRACT, [$TRACKER_EXTRACT_REQUIRED]) - -TRACKER_EXTRACT_MODULES_DIR="${libdir}/tracker-${TRACKER_API_VERSION}/extract-modules" -AC_SUBST(TRACKER_EXTRACT_MODULES_DIR) - -# NOTE: We don't use ${TRACKER_API_VERSION} because other content like -# the ontology is installed to the same location. -TRACKER_EXTRACT_RULES_DIR="${datadir}/tracker/extract-rules" -AC_SUBST(TRACKER_EXTRACT_RULES_DIR) - -# Check requirements for tracker-extract modules -TRACKER_EXTRACT_MODULES_REQUIRED="glib-2.0 >= $GLIB_REQUIRED" - -PKG_CHECK_MODULES(TRACKER_EXTRACT_MODULES, [$TRACKER_EXTRACT_MODULES_REQUIRED]) - -# Check requirements for tracker-writeback -TRACKER_WRITEBACK_REQUIRED="glib-2.0 >= $GLIB_REQUIRED - gio-unix-2.0 >= $GLIB_REQUIRED - gmodule-2.0 >= $GLIB_REQUIRED" - -PKG_CHECK_MODULES(TRACKER_WRITEBACK, [$TRACKER_WRITEBACK_REQUIRED]) - -# Check requirements for tracker-miner-fs -TRACKER_MINER_FS_REQUIRED="glib-2.0 >= $GLIB_REQUIRED - gio-unix-2.0 >= $GLIB_REQUIRED - gmodule-2.0 >= $GLIB_REQUIRED" - -PKG_CHECK_MODULES(TRACKER_MINER_FS, [$TRACKER_MINER_FS_REQUIRED]) - -TRACKER_MINER_FS_LIBS="$TRACKER_MINER_FS_LIBS -lz -lm" - -# Check requirements for tracker-miner-apps -TRACKER_MINER_APPS_REQUIRED="glib-2.0 >= $GLIB_REQUIRED - gio-unix-2.0 >= $GLIB_REQUIRED" - -PKG_CHECK_MODULES(TRACKER_MINER_APPS, [$TRACKER_MINER_APPS_REQUIRED]) - -# Check requirements for tracker-miner-rss -TRACKER_MINER_RSS_REQUIRED="glib-2.0 >= $GLIB_REQUIRED - libgrss >= $LIBGRSS_REQUIRED" - -PKG_CHECK_MODULES(TRACKER_MINER_RSS, [$TRACKER_MINER_RSS_REQUIRED], - [have_tracker_miner_rss=yes], - [have_tracker_miner_rss=no]) - # Check we have Vala valac command we need VALA_MIN_VERSION=0.18.0 AM_PROG_VALAC([$VALA_MIN_VERSION]) @@ -968,1178 +911,11 @@ fi AM_CONDITIONAL(HAVE_NETWORK_MANAGER, test "x$have_network_manager" = "xyes") ################################################################## -# Check for libtracker-extract: libexif -################################################################## - -AC_ARG_ENABLE(libexif, - AS_HELP_STRING([--enable-libexif], - [enable extractor for exif metadata [[default=auto]]]), - [enable_libexif=$enableval], - [enable_libexif=auto]) - -if test "x$enable_libexif" != "xno" ; then - PKG_CHECK_MODULES(LIBEXIF, - [libexif >= $LIBEXIF_REQUIRED], - [have_libexif=yes], - [have_libexif=no]) - - LIBTRACKER_EXTRACT_CFLAGS="$LIBTRACKER_EXTRACT_CFLAGS $LIBEXIF_CFLAGS" - LIBTRACKER_EXTRACT_LIBS="$LIBTRACKER_EXTRACT_LIBS $LIBEXIF_LIBS" - - if test "x$have_libexif" = "xyes"; then - AC_DEFINE(HAVE_LIBEXIF, [], [Define if we have libexif]) - fi -else - have_libexif="no (disabled)" -fi - -if test "x$enable_libexif" = "xyes"; then - if test "x$have_libexif" != "xyes"; then - AC_MSG_ERROR([Could not find libexif >= $LIBEXIF_REQUIRED.]) - fi -fi - -AM_CONDITIONAL(HAVE_EXIF, test "x$have_libexif" = "xyes") - -################################################################## -# Check for libtracker-extract: libiptcdata -################################################################## - -AC_ARG_ENABLE(libiptcdata, - AS_HELP_STRING([--enable-libiptcdata], - [enable extractor for iptc metadata [[default=auto]]]), - [enable_libiptcdata=$enableval], - [enable_libiptcdata=auto]) - -if test "x$enable_libiptcdata" != "xno" ; then - PKG_CHECK_MODULES(LIBIPTCDATA, - [libiptcdata], - [have_libiptcdata=yes], - [have_libiptcdata=no]) - - LIBTRACKER_EXTRACT_CFLAGS="$LIBTRACKER_EXTRACT_CFLAGS $LIBIPTCDATA_CFLAGS" - LIBTRACKER_EXTRACT_LIBS="$LIBTRACKER_EXTRACT_LIBS $LIBIPTCDATA_LIBS" - - if test "x$have_libiptcdata" = "xyes"; then - AC_DEFINE(HAVE_LIBIPTCDATA, [], [Define if we have libiptcdata]) - fi -else - have_libiptcdata="no (disabled)" -fi - -if test "x$enable_libiptcdata" = "xyes"; then - if test "x$have_libiptcdata" != "xyes"; then - AC_MSG_ERROR([Could not find libiptcdata.]) - fi -fi - -AM_CONDITIONAL(HAVE_IPTC, test "x$have_libiptcdata" = "xyes") - -################################################################## -# Check for libtracker-extract, tracker-writeback: exempi -################################################################## - -AC_ARG_ENABLE(exempi, - AS_HELP_STRING([--enable-exempi], - [enable extractor for XMP metadata [[default=auto]]]), - [enable_exempi=$enableval], - [enable_exempi=auto]) - -if test "x$enable_exempi" != "xno" ; then - PKG_CHECK_MODULES(EXEMPI, - [exempi-2.0 >= $EXEMPI_REQUIRED], - [have_exempi=yes], - [have_exempi=no]) - - TRACKER_WRITEBACK_CFLAGS="$TRACKER_WRITEBACK_CFLAGS $EXEMPI_CFLAGS" - TRACKER_WRITEBACK_LIBS="$TRACKER_WRITEBACK_LIBS $EXEMPI_LIBS" - - LIBTRACKER_EXTRACT_CFLAGS="$LIBTRACKER_EXTRACT_CFLAGS $EXEMPI_CFLAGS" - LIBTRACKER_EXTRACT_LIBS="$LIBTRACKER_EXTRACT_LIBS $EXEMPI_LIBS" - - if test "x$have_exempi" = "xyes"; then - AC_DEFINE(HAVE_EXEMPI, [], [Define if we have exempi]) - fi -else - have_exempi="no (disabled)" -fi - -if test "x$enable_exempi" = "xyes"; then - if test "x$have_exempi" != "xyes"; then - AC_MSG_ERROR([Could not find exempi >= $EXEMPI_REQUIRED.]) - fi -fi - -AM_CONDITIONAL(HAVE_EXEMPI, test "x$have_exempi" = "xyes") - -################################################################## -# Check for tracker-miner-fs -################################################################## - -have_tracker_miner_fs="yes" - -AC_ARG_ENABLE(miner_fs, - AS_HELP_STRING([--enable-miner-fs], - [enable File System miner [[default=yes]]]), - [enable_miner_fs=$enableval], - [enable_miner_fs=yes]) - -enable_tracker_miner_fs=$enable_miner_fs - -if test "x$enable_tracker_miner_fs" = "xyes"; then - if test "x$have_tracker_miner_fs" != "xyes"; then - AC_MSG_ERROR([Could not find tracker-miner-fs dependencies ($TRACKER_MINER_FS_REQUIRED).]) - fi -else - if test "x$enable_tracker_miner_fs" = "xno"; then - have_tracker_miner_fs="no (disabled)" - fi -fi - -AM_CONDITIONAL(HAVE_TRACKER_MINER_FS, test "x$have_tracker_miner_fs" = "xyes") - -################################################################## -# Check for tracker-extract -################################################################## - -have_tracker_extract="yes" - -AC_ARG_ENABLE(tracker-extract, - AS_HELP_STRING([--enable-extract], - [enable Extractor miner [[default=yes]]]), - [enable_tracker_extract=$enableval], - [enable_tracker_extract=yes]) - -if test "x$enable_tracker_extract" = "xyes"; then - if test "x$have_tracker_extract" != "xyes"; then - AC_MSG_ERROR([Could not find tracker-extract dependencies ($TRACKER_EXTRACT_REQUIRED).]) - fi -else - if test "x$enable_tracker_extract" = "xno"; then - have_tracker_extract="no (disabled)" - fi -fi - -AM_CONDITIONAL(HAVE_TRACKER_EXTRACT, test "x$have_tracker_extract" = "xyes") - -################################################################## -# Check for tracker-writeback -################################################################## - -have_tracker_writeback="yes" - -AC_ARG_ENABLE(tracker-writeback, - AS_HELP_STRING([--enable-tracker-writeback], - [enable writeback [[default=yes]]]), - [enable_tracker_writeback=$enableval], - [enable_tracker_writeback=yes]) - -if test "x$enable_tracker_writeback" = "xyes"; then - if test "x$have_tracker_writeback" != "xyes"; then - AC_MSG_ERROR([Could not find tracker-writeback dependencies ($TRACKER_WRITEBACK_REQUIRED).]) - fi -else - if test "x$enable_tracker_writeback" = "xno"; then - have_tracker_writeback="no (disabled)" - fi -fi - -AM_CONDITIONAL(HAVE_TRACKER_WRITEBACK, test "x$have_tracker_writeback" = "xyes") - -################################################################## -# Check for tracker-miner-apps -################################################################## - -have_tracker_miner_apps="yes" - -AC_ARG_ENABLE(miner_apps, - AS_HELP_STRING([--enable-miner-apps], - [enable Application miner [[default=yes]]]), - [enable_miner_apps=$enableval], - [enable_miner_apps=yes]) - -enable_tracker_miner_apps=$enable_miner_apps - -if test "x$enable_tracker_miner_apps" = "xyes"; then - if test "x$have_tracker_miner_apps" != "xyes"; then - AC_MSG_ERROR([Could not find tracker-miner-apps dependencies ($TRACKER_MINER_APPS_REQUIRED).]) - fi -else - if test "x$enable_tracker_miner_apps" = "xno"; then - have_tracker_miner_apps="no (disabled)" - fi -fi - -AM_CONDITIONAL(HAVE_TRACKER_MINER_APPS, test "x$have_tracker_miner_apps" = "xyes") - -################################################################## -# Check for tracker-miner-rss -################################################################## - -AC_ARG_ENABLE([miner_rss], - AS_HELP_STRING([--enable-miner-rss], - [enable RSS data miner [[default=auto]]]), - [enable_miner_rss=$enableval], - [enable_miner_rss=auto]) - -enable_tracker_miner_rss=$enable_miner_rss - -if test "x$enable_tracker_miner_rss" = "xyes" ; then - if test "x$have_tracker_miner_rss" != "xyes"; then - AC_MSG_ERROR([Could not find tracker-miner-rss dependencies ($TRACKER_MINER_RSS_REQUIRED).]) - fi -else - if test "x$enable_tracker_miner_rss" = "xno" ; then - have_tracker_miner_rss="no (disabled)" - fi -fi - -AM_CONDITIONAL(HAVE_TRACKER_MINER_RSS, test "x$have_tracker_miner_rss" = "xyes") - -#################################################################### -# Check for tracker-writeback: Taglib for audio writeback support -#################################################################### - -AC_ARG_ENABLE(taglib, - AS_HELP_STRING([--enable-taglib], - [enable writeback for audio files [[default=auto]]]), - [enable_taglib=$enableval], - [enable_taglib=auto]) - -if test "x$enable_taglib" != "xno" ; then - PKG_CHECK_MODULES(TAGLIB, - [taglib_c >= $TAGLIB_REQUIRED], - [have_taglib=yes], - [have_taglib=no]) - - TRACKER_WRITEBACK_CFLAGS="$TRACKER_WRITEBACK_CFLAGS $TAGLIB_CFLAGS" - TRACKER_WRITEBACK_LIBS="$TRACKER_WRITEBACK_LIBS $TAGLIB_LIBS" -else - have_taglib="no (disabled)" -fi - -AM_CONDITIONAL(HAVE_TAGLIB, test "x$have_taglib" = "xyes") - -################################################################## # Check for tracker-resdump ################################################################## AM_CONDITIONAL(HAVE_TRACKER_RESDUMP, test "$have_tracker_resdump" = "yes") -#################################################################### -#################################################################### -#################################################################### -# This section is for tracker-extract dependencies -#################################################################### -#################################################################### -#################################################################### - -#################################################################### -# Check for tracker-extract: enca for defect Russian/Cyrillic in MP3s -#################################################################### - -AC_ARG_ENABLE(enca, - AS_HELP_STRING([--enable-enca], - [enable libenca for Cyrillic language detection in MP3s [[default=auto]]]), - [enable_enca=$enableval], - [enable_enca=auto]) - -if test "x$enable_enca" != "xno" ; then - PKG_CHECK_MODULES(ENCA, [enca >= 1.9], have_enca=yes, have_enca=no) - - LIBTRACKER_EXTRACT_CFLAGS="$LIBTRACKER_EXTRACT_CFLAGS $ENCA_CFLAGS" - LIBTRACKER_EXTRACT_LIBS="$LIBTRACKER_EXTRACT_LIBS $ENCA_LIBS" - - if test "x$have_enca" = "xyes"; then - AC_DEFINE(HAVE_ENCA, [], [Enca language detection aid]) - fi -else - have_enca="no (disabled)" -fi - -AC_ARG_ENABLE(icu-charset-detection, - AS_HELP_STRING([--enable-icu-charset-detection], - [enable libicu for charset detection in MP3s [[default=auto]]]), - [enable_icu_charset_detection=$enableval], - [enable_icu_charset_detection=auto]) - -if test "x$have_libicu" = "xyes"; then - if test "x$enable_icu_charset_detection" != "xno"; then - have_libicu_charset_detection="yes" - AC_DEFINE(HAVE_LIBICU_CHARSET_DETECTION, [], [ICU language detection aid]) - else - have_libicu_charset_detection="no" - fi -fi - -if test "x$have_enca" = "xyes" || test "x$have_libicu_charset_detection" = "xyes"; then - have_charset_detection="yes" -else - have_charset_detection="no" -fi - -AM_CONDITIONAL(HAVE_ENCA, test "$have_enca" = "yes") -AM_CONDITIONAL(HAVE_LIBICU_CHARSET_DETECTION, test "$have_libicu_charset_detection" = "yes") - -################################################################## -# Check for tracker-extract: libxml2 for XML/HTML extractor -################################################################## - -AC_ARG_ENABLE(libxml2, - AS_HELP_STRING([--enable-libxml2], - [enable extractor for HTML/XML metadata [[default=yes]]]), - [enable_libxml2=$enableval], - [enable_libxml2=yes]) - -if test "x$enable_libxml2" != "xno"; then - PKG_CHECK_MODULES(LIBXML2, - [libxml-2.0 >= $LIBXML2_REQUIRED], - [have_libxml2=yes], - [have_libxml2=no]) - AC_SUBST(LIBXML2_CFLAGS) - AC_SUBST(LIBXML2_LIBS) - - if test "x$have_libxml2" = "xyes"; then - AC_DEFINE(HAVE_LIBXML2, [], [Define if we have libxml2]) - fi -else - have_libxml2="no (disabled)" -fi - -if test "x$enable_libxml2" = "xyes"; then - if test "x$have_libxml2" != "xyes"; then - AC_MSG_ERROR([Could not find libxml2 >= $LIBXML2_REQUIRED.]) - fi -fi - -AM_CONDITIONAL(HAVE_LIBXML2, test "x$have_libxml2" = "xyes") - -#################################################################### -# Check for tracker-extract: gstreamer/etc -#################################################################### - -AC_ARG_ENABLE(generic-media-extractor, - AS_HELP_STRING([--enable-generic-media-extractor=ARG], - [enables one of the (gstreamer, libav, auto) generic media extractor backends [[default=auto]]]), - [enable_generic_media_extractor=$enableval], - [enable_generic_media_extractor=auto]) - -PKG_CHECK_MODULES(GSTREAMER, - [gstreamer-1.0 >= $GSTREAMER_REQUIRED - gstreamer-tag-1.0 >= $GSTREAMER_REQUIRED], - [have_libgstreamer=yes], - [have_libgstreamer=no]) - -AC_SUBST(GSTREAMER_CFLAGS) -AC_SUBST(GSTREAMER_LIBS) - -PKG_CHECK_MODULES(AVFORMAT, - [libavformat >= 0.8.4], - [have_libavformat=yes], - [have_libavformat=no]) - -AC_SUBST(AVFORMAT_CFLAGS) -AC_SUBST(AVFORMAT_LIBS) - -PKG_CHECK_MODULES(AVCODEC, - [libavcodec >= 0.8.4], - [have_libavcodec=yes], - [have_libavcodec=no]) - -AC_SUBST(AVCODEC_CFLAGS) -AC_SUBST(AVCODEC_LIBS) - -PKG_CHECK_MODULES(AVUTIL, - [libavutil >= 0.8.4], - [have_libavutil=yes], - [have_libavutil=no]) - -AC_SUBST(AVUTIL_CFLAGS) -AC_SUBST(AVUTIL_LIBS) - -if test "x$enable_generic_media_extractor" = "xauto"; then - if test "$have_libgstreamer" = "yes"; then - have_generic_media_handler="yes" - generic_media_handler_name="GStreamer" - elif test "$have_libav" = "yes"; then - generic_media_handler_name="libav" - have_generic_media_handler="yes" - else - have_generic_media_handler="no" - generic_media_handler_name="none" - fi -elif test "x$enable_generic_media_extractor" = "xgstreamer"; then - if test "$have_libgstreamer" = "yes"; then - generic_media_handler_name="GStreamer" - have_generic_media_handler="yes" - else - AC_MSG_ERROR([Could not find GStreamer >= $GSTREAMER_REQUIRED]) - fi -elif test "x$enable_generic_media_extractor" = "xlibav"; then - if test "$have_libavformat" = "yes" && test "$have_libavcodec" = "yes" && test "$have_libavutil" = "yes"; then - generic_media_handler_name="libav" - have_generic_media_handler="yes" - else - AC_MSG_ERROR([Could not find libav]) - fi -else - have_generic_media_handler="no" - generic_media_handler_name="none" -fi - -if test "$generic_media_handler_name" = "GStreamer"; then - AC_DEFINE(HAVE_GSTREAMER, [], [Define if we have GStreamer]) - AM_CONDITIONAL(HAVE_GSTREAMER, true) - AM_CONDITIONAL(HAVE_LIBAV, false) -elif test "$generic_media_handler_name" = "libav"; then - AC_DEFINE(HAVE_LIBAV, [], [Define if we have libav]) - AM_CONDITIONAL(HAVE_LIBAV, true) - AM_CONDITIONAL(HAVE_GSTREAMER, false) -else - AM_CONDITIONAL(HAVE_LIBAV, false) - AM_CONDITIONAL(HAVE_GSTREAMER, false) -fi - -########################################################################### -# Check for gstreamer backend: tagreadbin/decodebin2/discoverer/gupnp-dlna -########################################################################### - -AC_ARG_WITH([gstreamer-backend], - AS_HELP_STRING([--with-gstreamer-backend], - [enables one of the (gupnp-dlna, discoverer) GStreamer backends [[default=discoverer]]]), - [with_gstreamer_backend=$withval], - [with_gstreamer_backend=discoverer]) - -if test "$generic_media_handler_name" != "GStreamer"; then - AC_MSG_WARN([No need to specify a GStreamer backend if not using GStreamer]) - gstreamer_backend="N/A" -else - case "x$with_gstreamer_backend" in - "xdiscoverer") - PKG_CHECK_MODULES(GSTREAMER_PBUTILS, - [gstreamer-pbutils-1.0 >= $GSTREAMER_REQUIRED], - [have_gstreamer_pbutils=yes], - [have_gstreamer_pbutils=no]) - AC_SUBST(GSTREAMER_PBUTILS_CFLAGS) - AC_SUBST(GSTREAMER_PBUTILS_LIBS) - - if test "x$have_gstreamer_pbutils" != "xyes"; then - AC_MSG_ERROR([Could not find GStreamer pbutils]) - fi - - gstreamer_backend="Discoverer" - AC_DEFINE(GSTREAMER_BACKEND_DISCOVERER, [], [Define that GStreamer Discoverer should be used]) - ;; - "xgupnp-dlna") - PKG_CHECK_MODULES(GUPNP_DLNA, - [gupnp-dlna-2.0 >= $GUPNP_DLNA_REQUIRED gupnp-dlna-gst-2.0 >= $GUPNP_DLNA_REQUIRED], - [have_gupnp_dlna=yes], - [have_gupnp_dlna=no]) - AC_SUBST(GUPNP_DLNA_CFLAGS) - AC_SUBST(GUPNP_DLNA_LIBS) - - if test "x$have_gupnp_dlna" = "xyes"; then - gstreamer_backend="GUPnP-DLNA" - AC_DEFINE(GSTREAMER_BACKEND_GUPNP_DLNA, [], [Define that GUPnP-DLNA should be used]) - else - AC_MSG_ERROR([Could not find GUPnP-DLNA >= $GUPNP_DLNA_REQUIRED]) - fi - ;; - # Invalid option value - *) AC_MSG_ERROR([Wrong value for --with-gstreamer-backend: $with_gstreamer_backend]) ;; - esac -fi - -AM_CONDITIONAL(HAVE_GUPNP_DLNA, test "x$gstreamer_backend" = "xGUPnP-DLNA") -AM_CONDITIONAL(HAVE_GSTREAMER_PBUTILS, test "x$gstreamer_backend" = "xDiscoverer") - -#################################################################### -# Check for tracker-extract: support .ps.gz files -#################################################################### - -AC_ARG_ENABLE([unzip_psgz_files], - AS_HELP_STRING([--enable-unzip-ps-gz-files], - [enable extractor for PS.GZ metadata [[default=auto]]]), - [enable_unzip_psgz_files=$enableval], - [enable_unzip_psgz_files=auto]) - -if test x$enable_unzip_psgz_files != "xno"; then - AC_DEFINE(USING_UNZIPPSFILES, 1, [Unzip ps.gz files]) -fi - -################################################################## -# Check for tracker-extract: poppler for PDF -################################################################## - -AC_ARG_ENABLE(poppler, - AS_HELP_STRING([--enable-poppler], - [enable extractor for PDF metadata [[default=auto]]]), - [enable_poppler=$enableval], - [enable_poppler=auto]) - -if test "x$enable_poppler" != "xno" ; then - PKG_CHECK_MODULES(POPPLER, - [poppler-glib >= $POPPLER_REQUIRED], - [have_poppler=yes], - [have_poppler=no]) - - AC_SUBST(POPPLER_CFLAGS) - AC_SUBST(POPPLER_LIBS) - - if test "x$have_poppler" = "xyes"; then - AC_DEFINE(HAVE_POPPLER, [], [Define if we have poppler-glib]) - fi -else - have_poppler="no (disabled)" -fi - -if test "x$enable_poppler" = "xyes"; then - if test "x$have_poppler" != "xyes"; then - AC_MSG_ERROR([Could not find poppler-glib >= $POPPLER_REQUIRED.]) - fi -fi - -AM_CONDITIONAL(HAVE_POPPLER, test "x$have_poppler" = "xyes") - -################################################################## -# Check for tracker-extract: libgxps for XPS -################################################################## - -AC_ARG_ENABLE(libgxps, - AS_HELP_STRING([--enable-libgxps], - [enable extractor for XPS metadata [[default=auto]]]), - [enable_libgxps=$enableval], - [enable_libgxps=auto]) - -if test "x$enable_libgxps" != "xno" ; then - PKG_CHECK_MODULES(LIBGXPS, - [libgxps], - [have_libgxps=yes], - [have_libgxps=no]) - - AC_SUBST(LIBGXPS_CFLAGS) - AC_SUBST(LIBGXPS_LIBS) - - if test "x$have_libgxps" = "xyes"; then - AC_DEFINE(HAVE_LIBGXPS, [], [Define if we have libgxps]) - fi -else - have_libgxps="no (disabled)" -fi - -if test "x$enable_libgxps" = "xyes"; then - if test "x$have_libgxps" != "xyes"; then - AC_MSG_ERROR([Could not find libgxps.]) - fi -fi - -AM_CONDITIONAL(HAVE_LIBGXPS, test "x$have_libgxps" = "xyes") - -################################################################## -# Check for tracker-extract: libgsf -################################################################## - -AC_ARG_ENABLE(libgsf, - AS_HELP_STRING([--enable-libgsf], - [enable extractor for GSF metadata (MSOffice, LibreOffice, EPub) [[default=auto]]]), - [enable_libgsf=$enableval], - [enable_libgsf=auto]) - -if test "x$enable_libgsf" != "xno" ; then - PKG_CHECK_MODULES(LIBGSF, - [libgsf-1 >= $LIBGSF_REQUIRED], - [have_libgsf=yes], - [have_libgsf=no]) - - AC_SUBST(LIBGSF_CFLAGS) - AC_SUBST(LIBGSF_LIBS) - - if test "x$have_libgsf" = "xyes"; then - AC_DEFINE(HAVE_LIBGSF, [], [Define if we have libgsf]) - fi -else - have_libgsf="no (disabled)" -fi - -if test "x$enable_libgsf" = "xyes"; then - if test "x$have_libgsf" != "xyes"; then - AC_MSG_ERROR([Could not find libgsf >= $LIBGSF_REQUIRED.]) - fi -fi - -AM_CONDITIONAL(HAVE_LIBGSF, test "x$have_libgsf" = "xyes") - -################################################################## -# Check for tracker-extract: libosinfo -################################################################## - -AC_ARG_ENABLE(libosinfo, - AS_HELP_STRING([--enable-libosinfo], - [enable extractor for ISO metadata [[default=auto]]]), - [enable_libosinfo=$enableval], - [enable_libosinfo=auto]) - -if test "x$enable_libosinfo" != "xno" ; then - PKG_CHECK_MODULES(LIBOSINFO, - [libosinfo-1.0 >= $LIBOSINFO_REQUIRED], - [have_libosinfo=yes], - [have_libosinfo=no]) - - AC_SUBST(LIBOSINFO_CFLAGS) - AC_SUBST(LIBOSINFO_LIBS) - - if test "x$have_libosinfo" = "xyes"; then - AC_DEFINE(HAVE_LIBOSINFO, [], [Define if we have libosinfo]) - fi -else - have_libosinfo="no (disabled)" -fi - -if test "x$enable_libosinfo" = "xyes"; then - if test "x$have_libosinfo" != "xyes"; then - AC_MSG_ERROR([Could not find libosinfo >= $LIBOSINFO_REQUIRED.]) - fi -fi - -AM_CONDITIONAL(HAVE_LIBOSINFO, test "x$have_libosinfo" = "xyes") - -################################################################## -# Check for tracker-extract: libgif -################################################################## - -# FIXME: This should be package based. Unfortunately in several main -# distros, it is not. - -OLD_CFLAGS="$CFLAGS" -OLD_LDFLAGS="$LDFLAGS" -OLD_LIBS="$LIBS" -CFLAGS="" -LDFLAGS="" -LIBS="" - -AC_ARG_ENABLE(libgif, - AS_HELP_STRING([--enable-libgif], - [enable extractor for GIF metadata [[default=auto]]]), - [enable_libgif=$enableval], - [enable_libgif=auto]) - -if test "x$enable_libgif" != "xno" ; then - AC_CHECK_HEADER(gif_lib.h, - AC_CHECK_LIB(gif, DGifOpen)) - - have_libgif=${ac_cv_lib_gif_DGifOpen:-no} - - LIBGIF_CFLAGS="$CFLAGS" - LIBGIF_LIBS="$LIBS" - - AC_SUBST(LIBGIF_CFLAGS) - AC_SUBST(LIBGIF_LIBS) - - if test "x$have_libgif" = "xyes"; then - AC_DEFINE(HAVE_LIBGIF, [], [Define if we have libgif]) - fi -else - have_libgif="no (disabled)" -fi - -if test "x$enable_libgif" = "xyes"; then - if test "x$have_libgif" != "xyes"; then - AC_MSG_ERROR([Could not find libgif >= $LIBGIF_REQUIRED.]) - fi -fi - -AM_CONDITIONAL(HAVE_LIBGIF, test "x$have_libgif" = "xyes") - -CFLAGS="$OLD_CFLAGS" -LDFLAGS="$OLD_LDFLAGS" -LIBS="$OLD_LIBS" - -################################################################## -# Check for tracker-extract: libjpeg -################################################################## - -# FIXME: This should be package based. Unfortunately in several main -# distros, it is not. - -OLD_CFLAGS="$CFLAGS" -OLD_LDFLAGS="$LDFLAGS" -OLD_LIBS="$LIBS" -CFLAGS="" -LDFLAGS="" -LIBS="" - -AC_ARG_ENABLE(libjpeg, - AS_HELP_STRING([--enable-libjpeg], - [enable extractor for JPEG metadata [[default=auto]]]), - [enable_libjpeg=$enableval], - [enable_libjpeg=auto]) - -if test "x$enable_libjpeg" != "xno" ; then - AC_CHECK_HEADER(jpeglib.h, - AC_CHECK_LIB(jpeg, jpeg_CreateCompress)) - - have_libjpeg=${ac_cv_lib_jpeg_jpeg_CreateCompress:-no} - - LIBJPEG_CFLAGS="$CFLAGS" - LIBJPEG_LIBS="$LIBS" - - AC_SUBST(LIBJPEG_CFLAGS) - AC_SUBST(LIBJPEG_LIBS) - - if test "x$have_libjpeg" = "xyes"; then - AC_DEFINE(HAVE_LIBJPEG, [], [Define if we have libjpeg]) - fi -else - have_libjpeg="no (disabled)" -fi - -if test "x$enable_libjpeg" = "xyes"; then - if test "x$have_libjpeg" != "xyes"; then - AC_MSG_ERROR([Could not find libjpeg >= $LIBJPEG_REQUIRED.]) - fi -fi - -AM_CONDITIONAL(HAVE_LIBJPEG, test "x$have_libjpeg" = "xyes") - -CFLAGS="$OLD_CFLAGS" -LDFLAGS="$OLD_LDFLAGS" -LIBS="$OLD_LIBS" - -################################################################## -# Check for tracker-extract: libtiff -################################################################## - -# FIXME: This should be package based. Unfortunately in several main -# distros, it is not. - -OLD_CFLAGS="$CFLAGS" -OLD_LDFLAGS="$LDFLAGS" -OLD_LIBS="$LIBS" -CFLAGS="" -LDFLAGS="" -LIBS="" - -AC_ARG_ENABLE(libtiff, - AS_HELP_STRING([--enable-libtiff], - [enable extractor for TIFF metadata [[default=auto]]]), - [enable_libtiff=$enableval], - [enable_libtiff=auto]) - -if test "x$enable_libtiff" != "xno" ; then - AC_CHECK_HEADER(tiff.h, - AC_CHECK_LIB(tiff, TIFFOpen)) - - have_libtiff=${ac_cv_lib_tiff_TIFFOpen:-no} - - LIBTIFF_CFLAGS="$CFLAGS" - LIBTIFF_LIBS="$LIBS" - - AC_SUBST(LIBTIFF_CFLAGS) - AC_SUBST(LIBTIFF_LIBS) - - if test "x$have_libtiff" = "xyes"; then - AC_DEFINE(HAVE_LIBTIFF, [], [Define if we have libtiff]) - fi -else - have_libtiff="no (disabled)" -fi - -if test "x$enable_libtiff" = "xyes"; then - if test "x$have_libtiff" != "xyes"; then - AC_MSG_ERROR([Could not find libtiff >= $LIBTIFF_REQUIRED.]) - fi -fi - -AM_CONDITIONAL(HAVE_LIBTIFF, test "x$have_libtiff" = "xyes") - -CFLAGS="$OLD_CFLAGS" -LDFLAGS="$OLD_LDFLAGS" -LIBS="$OLD_LIBS" - -################################################################## -# Check for tracker-extract: libpng -################################################################## - -# FIXME: This should be package based. Unfortunately in several main -# distros, it is not. - -OLD_CFLAGS="$CFLAGS" -OLD_LDFLAGS="$LDFLAGS" -OLD_LIBS="$LIBS" -CFLAGS="" -LDFLAGS="" -LIBS="" - -AC_ARG_ENABLE(libpng, - AS_HELP_STRING([--enable-libpng], - [enable extractor for PNG metadata [[default=auto]]]), - [enable_libpng=$enableval], - [enable_libpng=auto]) - -if test "x$enable_libpng" != "xno" ; then - AC_CHECK_HEADER(png.h, - AC_CHECK_LIB(png, png_create_read_struct)) - - have_libpng=${ac_cv_lib_png_png_create_read_struct:-no} - - LIBPNG_CFLAGS="$CFLAGS" - LIBPNG_LIBS="$LIBS" - - AC_SUBST(LIBPNG_CFLAGS) - AC_SUBST(LIBPNG_LIBS) - - if test "x$have_libpng" = "xyes"; then - AC_DEFINE(HAVE_LIBPNG, [], [Define if we have libpng]) - fi -else - have_libpng="no (disabled)" -fi - -if test "x$enable_libpng" = "xyes"; then - if test "x$have_libpng" != "xyes"; then - AC_MSG_ERROR([Could not find libpng >= $LIBPNG_REQUIRED.]) - fi -fi - -AM_CONDITIONAL(HAVE_LIBPNG, test "x$have_libpng" = "xyes") - -CFLAGS="$OLD_CFLAGS" -LDFLAGS="$OLD_LDFLAGS" -LIBS="$OLD_LIBS" - -################################################################## -# Check for tracker-extract: vorbis -################################################################## - -AC_ARG_ENABLE(libvorbis, - AS_HELP_STRING([--enable-libvorbis], - [enable extractor for OGG metadata (Vorbis) [[default=no]]]), - [enable_libvorbis=$enableval], - [enable_libvorbis=no]) - -if test "x$enable_libvorbis" != "xno" ; then - PKG_CHECK_MODULES(LIBVORBIS, - [vorbisfile >= $LIBVORBIS_REQUIRED], - [have_libvorbis=yes], - [have_libvorbis=no]) - - AC_SUBST(LIBVORBIS_CFLAGS) - AC_SUBST(LIBVORBIS_LIBS) - - if test "x$have_libvorbis" = "xyes"; then - AC_DEFINE(HAVE_LIBVORBIS, [], [Define if we have libvorbis]) - fi -else - have_libvorbis="no (disabled)" -fi - -if test "x$enable_libvorbis" = "xyes"; then - if test "x$have_libvorbis" != "xyes"; then - AC_MSG_ERROR([Could not find libvorbis >= $LIBVORBIS_REQUIRED.]) - fi -fi - -AM_CONDITIONAL(HAVE_LIBVORBIS, test "x$have_libvorbis" = "xyes") - -#################################################################### -# Check for tracker-extract: flac -#################################################################### - -AC_ARG_ENABLE(libflac, - AS_HELP_STRING([--enable-libflac], - [enable extractor for FLAC metadata [[default=no]]]), - [enable_libflac=$enableval], - [enable_libflac=no]) - -if test "x$enable_libflac" != "xno" ; then - PKG_CHECK_MODULES(LIBFLAC, - [flac >= $LIBFLAC_REQUIRED], - [have_libflac=yes], - [have_libflac=no]) - AC_SUBST(LIBFLAC_CFLAGS) - AC_SUBST(LIBFLAC_LIBS) - - if test "x$have_libflac" = "xyes"; then - AC_DEFINE(HAVE_LIBFLAC, [], [Define if we have libflac]) - fi -else - have_libflac="no (disabled)" -fi - -if test "x$enable_libflac" = "xyes"; then - if test "x$have_libflac" != "xyes"; then - AC_MSG_ERROR([Could not find libflac >= $LIBFLAC_REQUIRED.]) - fi -fi - -AM_CONDITIONAL(HAVE_LIBFLAC, test "x$have_libflac" = "xyes") - -#################################################################### -# Check for tracker-extract-gstreamer: libcue -#################################################################### - -AC_ARG_ENABLE(libcue, - AS_HELP_STRING([--enable-libcue], - [enable external cuesheet parsing [[default=auto]]]), - [enable_libcue=$enableval], - [enable_libcue=auto]) - -if test "x$enable_libcue" != "xno" ; then - PKG_CHECK_MODULES(LIBCUE, - [libcue], - [have_libcue=yes], - [have_libcue=no]) - - AC_SUBST(LIBCUE_CFLAGS) - AC_SUBST(LIBCUE_LIBS) - - if test "x$have_libcue" = "xyes"; then - AC_DEFINE(HAVE_LIBCUE, [], [Define if we have libcue]) - - PKG_CHECK_EXISTS([libcue >= 2.0.0], have_libcue2=yes, have_libcue2=no) - if test "x$have_libcue2" = "xyes"; then - AC_DEFINE(HAVE_LIBCUE2, [], [Define if we have libcue 2 or up]) - fi - fi -else - have_libcue="no (disabled)" -fi - -if test "x$enable_libcue" = "xyes"; then - if test "x$have_libcue" != "xyes"; then - AC_MSG_ERROR([Could not find libcue.]) - fi -fi - -#################################################################### -# Check for tracker-extract: AbiWord -#################################################################### - -AC_ARG_ENABLE(abiword, - AS_HELP_STRING([--enable-abiword], - [enable extractor for ABW metadata (AbiWord) [[default=auto]]]), - [enable_abiword=$enableval], - [enable_abiword=auto]) - -if test "x$enable_abiword" != "xno" ; then - AC_SUBST(ABIWORD_CFLAGS) - AC_SUBST(ABIWORD_LIBS) - AC_DEFINE(HAVE_ABIWORD, [], [Define if we have AbiWord extractor]) - have_abiword=yes -else - have_abiword="no (disabled)" -fi - -AM_CONDITIONAL(HAVE_ABIWORD, test "x$have_abiword" = "xyes") - -#################################################################### -# Check for tracker-extract: DVI -#################################################################### - -AC_ARG_ENABLE(dvi, - AS_HELP_STRING([--enable-dvi], - [enable extractor for DVI metadata [[default=auto]]]), - [enable_dvi=$enableval], - [enable_dvi=auto]) - -if test "x$enable_dvi" != "xno"; then - AC_SUBST(DVI_CFLAGS) - AC_SUBST(DVI_LIBS) - AC_DEFINE(HAVE_DVI, [], [Define if we have DVI extractor]) - have_dvi=yes -else - have_dvi="no (disabled)" -fi - -AM_CONDITIONAL(HAVE_DVI, test "x$have_dvi" = "xyes") - -#################################################################### -# Check for tracker-extract: mp3 -#################################################################### - -AC_ARG_ENABLE(mp3, - AS_HELP_STRING([--enable-mp3], - [enable extractor for MP3 metadata [[default=auto]]]), - [enable_mp3=$enableval], - [enable_mp3=auto]) - -if test "x$enable_mp3" != "xno"; then - AC_SUBST(MP3_CFLAGS) - AC_SUBST(MP3_LIBS) - AC_DEFINE(HAVE_MP3, [], [Define if we have MP3 extractor]) - have_mp3=yes -else - have_mp3="no (disabled)" -fi - -AM_CONDITIONAL(HAVE_MP3, test "x$have_mp3" = "xyes") - -#################################################################### -# Check for tracker-extract: ps -#################################################################### - -AC_ARG_ENABLE(ps, - AS_HELP_STRING([--enable-ps], - [enable extractor for PS metadata [[default=auto]]]), - [enable_ps=$enableval], - [enable_ps=auto]) - -if test "x$enable_ps" != "xno"; then - AC_SUBST(PS_CFLAGS) - AC_SUBST(PS_LIBS) - AC_DEFINE(HAVE_PS, [], [Define if we have PS extractor]) - have_ps=yes -else - have_ps="no (disabled)" -fi - -AM_CONDITIONAL(HAVE_PS, test "x$have_ps" = "xyes") - -#################################################################### -# Check for tracker-extract: text -#################################################################### - -AC_ARG_ENABLE(text, - AS_HELP_STRING([--enable-text], - [enable extractor for TXT metadata [[default=auto]]]), - [enable_text=$enableval], - [enable_text=auto]) - -if test "x$enable_text" != "xno"; then - AC_SUBST(TEXT_CFLAGS) - AC_SUBST(TEXT_LIBS) - AC_DEFINE(HAVE_TEXT, [], [Define if we have text extractor]) - have_text=yes -else - have_text="no (disabled)" -fi - -AM_CONDITIONAL(HAVE_TEXT, test "x$have_text" = "xyes") - -#################################################################### -# Check for tracker-extract: icon -#################################################################### - -AC_ARG_ENABLE(icon, - AS_HELP_STRING([--enable-icon], - [enable extractor for ICO metadata [[default=auto]]]), - [enable_icon=$enableval], - [enable_icon=auto]) - -if test "x$enable_icon" != "xno"; then - AC_SUBST(ICON_CFLAGS) - AC_SUBST(ICON_LIBS) - AC_DEFINE(HAVE_ICON, [], [Define if we have ICON extractor]) - have_icon=yes -else - have_icon="no (disabled)" -fi - -AM_CONDITIONAL(HAVE_ICON, test "x$have_icon" = "xyes") - -#################################################################### -# Check for tracker-extract, tracker-writeback: totem-pl-parser -#################################################################### - -AC_ARG_ENABLE(playlist, - AS_HELP_STRING([--enable-playlist], - [enable extractor for Playlist metadata [[default=auto]]]), - [enable_playlist=$enableval], - [enable_playlist=auto]) - -if test "x$enable_playlist" != "xno" ; then - PKG_CHECK_MODULES(TOTEM_PL_PARSER, - [totem-plparser - glib-2.0 >= $GLIB_REQUIRED - gobject-2.0 >= $GLIB_REQUIRED], - [have_playlist=yes], - [have_playlist=no]) - - TRACKER_WRITEBACK_CFLAGS="$TRACKER_WRITEBACK_CFLAGS $TOTEM_PL_PARSER_CFLAGS" - TRACKER_WRITEBACK_LIBS="$TRACKER_WRITEBACK_LIBS $TOTEM_PL_PARSER_LIBS" - - AC_SUBST(TOTEM_PL_PARSER_CFLAGS) - AC_SUBST(TOTEM_PL_PARSER_LIBS) - - if test "x$have_playlist" = "xyes"; then - AC_DEFINE(HAVE_TOTEM_PL_PARSER, [], [Define if we have Totem PL parser]) - fi -else - have_playlist="no (disabled)" -fi - -if test "x$enable_playlist" = "xyes"; then - if test "x$have_playlist" != "xyes"; then - AC_MSG_ERROR([Could not find Totem PL parser.]) - fi -fi - -AM_CONDITIONAL(HAVE_TOTEM_PL_PARSER, test "x$have_playlist" = "xyes") - -##################################################################### -# Check for tracker-extract: Guarantee existence of certain metadata -##################################################################### - -# Currently guarantees (for extraction): -# - nie:title for music and video files -# - nie:contentCreated for music, video and image files - -AC_ARG_ENABLE(guarantee-metadata, - AS_HELP_STRING([--enable-guarantee-metadata], - [enable guaranteed existence of some metadata, e.g. nie:title from files [[default=no]]]), - [enable_guarantee_metadata=$enableval], - [enable_guarantee_metadata=no]) - -if test "x$enable_guarantee_metadata" != "xno"; then - AC_DEFINE(GUARANTEE_METADATA, 1, [Guarantee existence of some metadata]) -fi - -#################################################################### -# Check if we should use initctl or sysvinit -#################################################################### - -# Check for initcl -AC_PATH_PROG(INITCTL, initctl, []) -AC_SUBST(INITCTL) -AM_CONDITIONAL(HAVE_UPSTART, test "x$INITCTL" != "x") - -#################################################################### -# Check whether we should install artwork -#################################################################### - -AC_ARG_ENABLE(artwork, - AS_HELP_STRING([--enable-artwork], - [install artwork, e.g. data/icons/* [[default=auto]]]), - [enable_artwork=$enableval], - [enable_artwork=auto]) - -if test "x$enable_artwork" != "xno"; then - AC_DEFINE(HAVE_ARTWORK, [], [Define if we should install artwork]) - have_artwork=yes -else - have_artwork="no (disabled)" -fi - -AM_CONDITIONAL(HAVE_ARTWORK, test "x$have_artwork" = "xyes") - -################################################################## -# Check for libseccomp -################################################################## - -PKG_CHECK_MODULES(LIBSECCOMP, - [libseccomp >= 2.0], - [have_libseccomp=yes], - [have_libseccomp=no]) - -if test "$have_libseccomp" = "yes"; then - LIBTRACKER_COMMON_LIBS="$LIBTRACKER_COMMON_LIBS $LIBSECCOMP_LIBS" - LIBTRACKER_COMMON_CFLAGS="$LIBTRACKER_COMMON_CFLAGS $LIBSECCOMP_CFLAGS" - AC_DEFINE(HAVE_LIBSECCOMP, [], [Define if we have libseccomp]) -# seccomp is a linux thing -elif test "$tracker_os_linux" = "yes"; then - AC_MSG_ERROR([Libseccomp is mandatory for sandboxed metadata extraction]) -fi - ################################################################## # Write generated files ################################################################## @@ -2173,23 +949,15 @@ AC_CONFIG_FILES([ src/libtracker-remote/Makefile src/libtracker-sparql-backend/Makefile src/libtracker-fts/Makefile - src/libtracker-extract/Makefile src/libtracker-miner/Makefile src/libtracker-miner/tracker-miner.pc src/Makefile - src/miners/Makefile - src/miners/fs/Makefile - src/miners/apps/Makefile - src/miners/rss/Makefile src/ontologies/Makefile src/tracker-store/Makefile src/tracker/Makefile - src/tracker-extract/Makefile - src/tracker-writeback/Makefile tests/common/Makefile tests/gvdb/Makefile tests/libtracker-common/Makefile - tests/libtracker-extract/Makefile tests/libtracker-data/Makefile tests/libtracker-data/aggregates/Makefile tests/libtracker-data/algebra/Makefile @@ -2225,13 +993,6 @@ AC_CONFIG_FILES([ tests/functional-tests/common/utils/configuration.py tests/functional-tests/common/utils/Makefile tests/functional-tests/unittest2/Makefile - tests/functional-tests/test-extraction-data/Makefile - tests/functional-tests/test-extraction-data/audio/Makefile - tests/functional-tests/test-extraction-data/images/Makefile - tests/functional-tests/test-extraction-data/office/Makefile - tests/functional-tests/test-extraction-data/video/Makefile - tests/functional-tests/test-extraction-data/playlists/Makefile - tests/functional-tests/test-writeback-data/Makefile tests/functional-tests/test-ontologies/Makefile tests/functional-tests/test-ontologies/basic/Makefile tests/functional-tests/test-ontologies/property-range-int-to-string/Makefile @@ -2249,7 +1010,6 @@ AC_CONFIG_FILES([ tests/functional-tests/ttl/Makefile tests/Makefile tests/tracker-steroids/Makefile - tests/tracker-writeback/Makefile utils/Makefile utils/ontology/Makefile utils/data-generators/Makefile @@ -2293,56 +1053,8 @@ Feature Support: Build with SQLite FTS support: $have_tracker_fts (built-in FTS: $have_builtin_fts5) Build with Stemming support: $have_libstemmer - Install artwork $have_artwork - Bash completion support: $with_bash_completion_dir ($BASH_COMPLETION_DIR) -Data Miners / Writebacks: - - FS (File System): $have_tracker_miner_fs - Applications: $have_tracker_miner_apps - RSS: $have_tracker_miner_rss - - Extract (secondary extraction): $have_tracker_extract - Writeback (writing changes back): $have_tracker_writeback" - -if test "x$enable_tracker_extract" != "xno" ; then -echo " -Metadata Extractors: - - Support PNG: $have_libpng - Support PDF: $have_poppler - Support XPS: $have_libgxps - Support GIF: $have_libgif (xmp: $have_exempi) - Support JPEG: $have_libjpeg (xmp: $have_exempi, exif: $have_libexif, iptc: $have_libiptcdata) - Support TIFF: $have_libtiff (xmp: $have_exempi, exif: yes, iptc: $have_libiptcdata) - Support Vorbis (ogg/etc): $have_libvorbis - Support Flac: $have_libflac - Support MS & Open Office: $have_libgsf - Support XML / HTML: $have_libxml2 - Support embedded / sidecar XMP: $have_exempi - Support generic media formats: $have_generic_media_handler ($generic_media_handler_name) (backend: $gstreamer_backend) - Support cue sheet parsing: $have_libcue (libcue2.0: $have_libcue2) - Support playlists (w/ Totem): $have_playlist - Support ISO image parsing: $have_libosinfo - Support AbiWord document parsing: $have_abiword - Support DVI parsing: $have_dvi - Support MP3 parsing: $have_mp3 - Support MP3 tag charset detection: $have_charset_detection (icu: $have_libicu_charset_detection, enca: $have_enca) - Support PS parsing: $have_ps - Support text parsing: $have_text - Support icon parsing: $have_icon" -fi - -if test "x$enable_tracker_writeback" != "xno" ; then -echo " -Writeback Formats: - - Audio files using Taglib: $have_taglib - XMP: $have_exempi" -fi - -echo " Frameworks / Options: Support Guaranteed Metadata $enable_guarantee_metadata (e.g. guess nie:title from files) diff --git a/docs/manpages/Makefile.am b/docs/manpages/Makefile.am index 31c654527..b719e47d0 100644 --- a/docs/manpages/Makefile.am +++ b/docs/manpages/Makefile.am @@ -1,9 +1,5 @@ -tmrss = tracker-miner-rss.1 - common = \ - tracker-extract.1 \ tracker-info.1 \ - tracker-miner-fs.1 \ tracker-daemon.1 \ tracker-search.1 \ tracker-sparql.1 \ @@ -12,20 +8,12 @@ common = \ tracker-store.1 \ tracker-tag.1 \ tracker-reset.1 \ - tracker-index.1 \ - tracker-writeback.1 + tracker-index.1 # Require only common and enabled manpages man_MANS = $(common) -if HAVE_TRACKER_MINER_RSS -man_MANS += $(tmrss) -endif - # Make sure even disabled manpages get distributed EXTRA_DIST = \ $(common) \ - $(tp) \ - $(tn) \ - $(tmrss) \ meson.build diff --git a/po/POTFILES.in b/po/POTFILES.in index 47d9b3ee1..95953cd2e 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -13,23 +13,6 @@ src/libtracker-miner/tracker-miner-fs.c src/libtracker-miner/tracker-miner-object.c src/libtracker-miner/tracker-miner-online.c src/libtracker-miner/tracker-miner-proxy.c -src/miners/apps/org.freedesktop.Tracker1.Miner.Applications.service.in.in -src/miners/apps/tracker-main.c -src/miners/apps/tracker-miner-apps.desktop.in.in -src/miners/fs/org.freedesktop.Tracker1.Miner.Files.service.in.in -src/miners/fs/org.freedesktop.Tracker.Miner.Files.gschema.xml.in -src/miners/fs/tracker-main.c -src/miners/fs/tracker-miner-files.c -src/miners/fs/tracker-miner-fs.desktop.in.in -src/miners/rss/org.freedesktop.Tracker1.Miner.RSS.service.in.in -src/miners/rss/tracker-main.c -src/miners/rss/tracker-miner-rss.c -src/miners/rss/tracker-miner-rss.desktop.in.in -src/tracker-extract/org.freedesktop.Tracker1.Miner.Extract.service.in.in -src/tracker-extract/org.freedesktop.Tracker.Extract.gschema.xml.in -src/tracker-extract/tracker-extract.c -src/tracker-extract/tracker-main.c -src/tracker-extract/tracker-extract.desktop.in.in src/tracker-store/tracker-main.vala src/tracker-store/tracker-store.desktop.in.in src/tracker-store/org.freedesktop.Tracker.Store.gschema.xml.in @@ -48,5 +31,3 @@ src/tracker/tracker-sparql.c src/tracker/tracker-sql.c src/tracker/tracker-status.c src/tracker/tracker-tag.c -src/tracker-writeback/tracker-main.c -src/tracker-writeback/org.freedesktop.Tracker.Writeback.gschema.xml.in diff --git a/src/Makefile.am b/src/Makefile.am index 3ff5e7cf5..22b6ad84f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -13,22 +13,11 @@ SUBDIRS = \ libtracker-direct \ libtracker-remote \ libtracker-sparql-backend \ - libtracker-extract \ libtracker-miner \ libtracker-control \ tracker \ - miners \ tracker-store -if HAVE_TRACKER_EXTRACT -SUBDIRS += tracker-extract -endif - -if HAVE_TRACKER_WRITEBACK -SUBDIRS += tracker-writeback -endif - EXTRA_DIST = \ meson.build \ - create-miner-symlinks.sh \ install-generated-header.sh diff --git a/src/create-miner-symlinks.sh b/src/create-miner-symlinks.sh deleted file mode 100644 index 7233a028a..000000000 --- a/src/create-miner-symlinks.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -# Post-install script for install stuff that Meson doesn't support directly. -# -# We can't pass the necessary variables directly to the script, so we -# substitute them using configure_file(). It's a bit of a Heath Robinson hack. - -set -e - -dbus_services_dir="$1" -tracker_miner_services_dir="$2" - -mkdir -p ${DESTDIR}/${tracker_miner_services_dir} -ln -sf "${dbus_services_dir}/tracker-extract.service" "${DESTDIR}/${tracker_miner_services_dir}/tracker-extract.service" diff --git a/src/libtracker-common/Makefile.am b/src/libtracker-common/Makefile.am index 8b00ee83d..df7593704 100644 --- a/src/libtracker-common/Makefile.am +++ b/src/libtracker-common/Makefile.am @@ -28,7 +28,6 @@ libtracker_common_la_SOURCES = \ tracker-ioprio.c \ tracker-log.c \ tracker-sched.c \ - tracker-seccomp.c \ tracker-type-utils.c \ tracker-utils.c \ tracker-locale.c \ @@ -45,7 +44,6 @@ noinst_HEADERS = \ tracker-domain-ontology.h \ tracker-file-utils.h \ tracker-sched.h \ - tracker-seccomp.h \ tracker-type-utils.h \ tracker-utils.h \ tracker-locale.h \ diff --git a/src/libtracker-common/meson.build b/src/libtracker-common/meson.build index b0411cc25..c9a1defb9 100644 --- a/src/libtracker-common/meson.build +++ b/src/libtracker-common/meson.build @@ -26,7 +26,6 @@ tracker_common_sources = [ 'tracker-locale.c', 'tracker-parser-utils.c', 'tracker-language.c', - 'tracker-seccomp.c', enums[0], enums[1], tracker_common_parser_sha1_header, ] diff --git a/src/libtracker-common/tracker-common.h b/src/libtracker-common/tracker-common.h index 47191fd44..5a97e9894 100644 --- a/src/libtracker-common/tracker-common.h +++ b/src/libtracker-common/tracker-common.h @@ -37,7 +37,6 @@ #include "tracker-log.h" #include "tracker-parser.h" #include "tracker-sched.h" -#include "tracker-seccomp.h" #include "tracker-type-utils.h" #include "tracker-utils.h" #include "tracker-locale.h" diff --git a/src/libtracker-common/tracker-seccomp.c b/src/libtracker-common/tracker-seccomp.c deleted file mode 100644 index ec873f5e0..000000000 --- a/src/libtracker-common/tracker-seccomp.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (C) 2016, Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include "tracker-seccomp.h" - -#ifdef HAVE_LIBSECCOMP - -#include <stdlib.h> -#include <stdio.h> -#include <stddef.h> -#include <string.h> -#include <unistd.h> -#include <errno.h> - -#include <sys/types.h> -#include <sys/prctl.h> -#include <sys/syscall.h> -#include <sys/socket.h> -#include <fcntl.h> - -#include <seccomp.h> - -#define ALLOW_RULE(call) G_STMT_START { \ - int allow_rule_syscall_number = seccomp_syscall_resolve_name (G_STRINGIFY (call)); \ - if (allow_rule_syscall_number == __NR_SCMP_ERROR || \ - seccomp_rule_add (ctx, SCMP_ACT_ALLOW, allow_rule_syscall_number, 0) < 0) \ - goto out; \ -} G_STMT_END - -#define ERROR_RULE(call, error) G_STMT_START { \ - int error_rule_syscall_number = seccomp_syscall_resolve_name (G_STRINGIFY (call)); \ - if (error_rule_syscall_number == __NR_SCMP_ERROR || \ - seccomp_rule_add (ctx, SCMP_ACT_ERRNO (error), error_rule_syscall_number, 0) < 0) \ - goto out; \ -} G_STMT_END - -gboolean -tracker_seccomp_init (void) -{ - scmp_filter_ctx ctx; - - ctx = seccomp_init (SCMP_ACT_TRAP); - if (ctx == NULL) - return FALSE; - - /* Memory management */ - ALLOW_RULE (brk); - ALLOW_RULE (mmap); - ALLOW_RULE (mmap2); - ALLOW_RULE (munmap); - ALLOW_RULE (mremap); - ALLOW_RULE (mprotect); - ALLOW_RULE (madvise); - ERROR_RULE (mlock, EPERM); - ERROR_RULE (mlock2, EPERM); - ERROR_RULE (munlock, EPERM); - ERROR_RULE (mlockall, EPERM); - ERROR_RULE (munlockall, EPERM); - /* Process management */ - ALLOW_RULE (exit_group); - ALLOW_RULE (getuid); - ALLOW_RULE (getuid32); - ALLOW_RULE (geteuid); - ALLOW_RULE (geteuid32); - ALLOW_RULE (getppid); - ALLOW_RULE (gettid); - ALLOW_RULE (getpid); - ALLOW_RULE (exit); - ALLOW_RULE (getrusage); - ALLOW_RULE (getrlimit); - /* Basic filesystem access */ - ALLOW_RULE (fstat); - ALLOW_RULE (fstat64); - ALLOW_RULE (stat); - ALLOW_RULE (stat64); - ALLOW_RULE (statfs); - ALLOW_RULE (statfs64); - ALLOW_RULE (lstat); - ALLOW_RULE (lstat64); - ALLOW_RULE (access); - ALLOW_RULE (getdents); - ALLOW_RULE (getdents64); - ALLOW_RULE (readlink); - ALLOW_RULE (readlinkat); - ALLOW_RULE (utime); - ALLOW_RULE (time); - ALLOW_RULE (fsync); - ALLOW_RULE (umask); - /* Processes and threads */ - ALLOW_RULE (clone); - ALLOW_RULE (futex); - ALLOW_RULE (set_robust_list); - ALLOW_RULE (rt_sigaction); - ALLOW_RULE (rt_sigprocmask); - ALLOW_RULE (sched_yield); - ALLOW_RULE (sched_getaffinity); - ALLOW_RULE (nanosleep); - ALLOW_RULE (waitid); - ALLOW_RULE (waitpid); - ALLOW_RULE (wait4); - /* Main loops */ - ALLOW_RULE (poll); - ALLOW_RULE (ppoll); - ALLOW_RULE (fcntl); - ALLOW_RULE (fcntl64); - ALLOW_RULE (eventfd); - ALLOW_RULE (eventfd2); - ALLOW_RULE (pipe); - ALLOW_RULE (pipe2); - /* System */ - ALLOW_RULE (uname); - ALLOW_RULE (sysinfo); - ALLOW_RULE (prctl); - ALLOW_RULE (getrandom); - ALLOW_RULE (clock_gettime); - ALLOW_RULE (clock_getres); - ALLOW_RULE (gettimeofday); - /* Descriptors */ - ALLOW_RULE (close); - ALLOW_RULE (read); - ALLOW_RULE (pread64); - ALLOW_RULE (lseek); - ALLOW_RULE (_llseek); - ALLOW_RULE (fadvise64); - ALLOW_RULE (write); - ALLOW_RULE (writev); - ALLOW_RULE (dup); - ALLOW_RULE (dup2); - ALLOW_RULE (dup3); - /* Needed by some GStreamer modules doing crazy stuff, less - * scary thanks to the restriction below about sockets being - * local. - */ - ALLOW_RULE (connect); - ALLOW_RULE (send); - ALLOW_RULE (sendto); - ALLOW_RULE (sendmsg); - ALLOW_RULE (recv); - ALLOW_RULE (recvmsg); - ALLOW_RULE (recvfrom); - ALLOW_RULE (getsockname); - ALLOW_RULE (getpeername); - ALLOW_RULE (shutdown); - - /* Special requirements for socket/socketpair, only on AF_UNIX/AF_LOCAL */ - if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1, - SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)) < 0) - goto out; - if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socket), 1, - SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)) < 0) - goto out; - if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 1, - SCMP_CMP(0, SCMP_CMP_EQ, AF_UNIX)) < 0) - goto out; - if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(socketpair), 1, - SCMP_CMP(0, SCMP_CMP_EQ, AF_LOCAL)) < 0) - goto out; - - /* Special requirements for ioctl, allowed on stdout/stderr */ - if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, - SCMP_CMP(0, SCMP_CMP_EQ, 1)) < 0) - goto out; - if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(ioctl), 1, - SCMP_CMP(0, SCMP_CMP_EQ, 2)) < 0) - goto out; - - /* Special requirements for open/openat, allow O_RDONLY calls, - * but fail if write permissions are requested. - */ - if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 1, - SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) < 0) - goto out; - if (seccomp_rule_add (ctx, SCMP_ACT_ERRNO (EACCES), SCMP_SYS(open), 1, - SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) < 0) - goto out; - if (seccomp_rule_add (ctx, SCMP_ACT_ERRNO (EACCES), SCMP_SYS(open), 1, - SCMP_CMP(1, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) < 0) - goto out; - - if (seccomp_rule_add (ctx, SCMP_ACT_ALLOW, SCMP_SYS(openat), 1, - SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY | O_RDWR, 0)) < 0) - goto out; - if (seccomp_rule_add (ctx, SCMP_ACT_ERRNO (EACCES), SCMP_SYS(openat), 1, - SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_WRONLY, O_WRONLY)) < 0) - goto out; - if (seccomp_rule_add (ctx, SCMP_ACT_ERRNO (EACCES), SCMP_SYS(openat), 1, - SCMP_CMP(2, SCMP_CMP_MASKED_EQ, O_RDWR, O_RDWR)) < 0) - goto out; - - g_debug ("Loading seccomp rules."); - - if (seccomp_load (ctx) >= 0) - return TRUE; - -out: - g_critical ("Failed to load seccomp rules."); - seccomp_release (ctx); - return FALSE; -} - -#else /* HAVE_LIBSECCOMP */ - -gboolean -tracker_seccomp_init (void) -{ - g_warning ("No seccomp support compiled-in."); - return TRUE; -} - -#endif /* HAVE_LIBSECCOMP */ diff --git a/src/libtracker-common/tracker-seccomp.h b/src/libtracker-common/tracker-seccomp.h deleted file mode 100644 index 0e0333024..000000000 --- a/src/libtracker-common/tracker-seccomp.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2016, Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_SECCOMP_H__ -#define __TRACKER_SECCOMP_H__ - -#include <glib.h> - -G_BEGIN_DECLS - -#if !defined (__LIBTRACKER_COMMON_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "only <libtracker-common/tracker-common.h> must be included directly." -#endif - -gboolean tracker_seccomp_init (void); - -G_END_DECLS - -#endif /* __TRACKER_SECCOMP_H__ */ diff --git a/src/libtracker-extract/Makefile.am b/src/libtracker-extract/Makefile.am deleted file mode 100644 index 45f507c1c..000000000 --- a/src/libtracker-extract/Makefile.am +++ /dev/null @@ -1,69 +0,0 @@ -AM_CPPFLAGS = \ - $(BUILD_CFLAGS) \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - -DSHAREDIR=\""$(datadir)"\" \ - -DTRACKER_EXTRACTOR_RULES_DIR=\""$(TRACKER_EXTRACT_RULES_DIR)"\" \ - -DTRACKER_EXTRACTORS_DIR=\""$(TRACKER_EXTRACT_MODULES_DIR)"\" \ - $(LIBTRACKER_EXTRACT_CFLAGS) - -libtracker_extractdir = $(libdir)/tracker-$(TRACKER_API_VERSION) -libtracker_extract_LTLIBRARIES = libtracker-extract.la - -libtracker_extract_la_LIBADD = \ - $(top_builddir)/src/libtracker-sparql-backend/libtracker-sparql-@TRACKER_API_VERSION@.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(LIBTRACKER_EXTRACT_LIBS) - -libtracker_extract_la_SOURCES = \ - tracker-data.h \ - tracker-encoding.c \ - tracker-encoding.h \ - tracker-exif.c \ - tracker-exif.h \ - tracker-extract.h \ - tracker-extract-info.c \ - tracker-extract-info.h \ - tracker-guarantee.c \ - tracker-guarantee.h \ - tracker-iptc.c \ - tracker-iptc.h \ - tracker-module-manager.c \ - tracker-module-manager.h \ - tracker-resource-helpers.c \ - tracker-resource-helpers.h \ - tracker-utils.c \ - tracker-utils.h \ - tracker-xmp.c \ - tracker-xmp.h - -noinst_HEADERS = \ - tracker-data.h \ - tracker-encoding.h \ - tracker-exif.h \ - tracker-extract-info.h \ - tracker-extract.h \ - tracker-guarantee.h \ - tracker-iptc.h \ - tracker-module-manager.h \ - tracker-utils.h \ - tracker-xmp.h - -if HAVE_ENCA -libtracker_extract_la_SOURCES += \ - tracker-encoding-enca.c \ - tracker-encoding-enca.h -endif - -if HAVE_LIBICU_CHARSET_DETECTION -libtracker_extract_la_SOURCES += \ - tracker-encoding-libicu.c \ - tracker-encoding-libicu.h -AM_CPPFLAGS += \ - $(LIBICU_CFLAGS) -libtracker_extract_la_LIBADD += \ - $(LIBICU_LIBS) -endif - -EXTRA_DIST = meson.build diff --git a/src/libtracker-extract/meson.build b/src/libtracker-extract/meson.build deleted file mode 100644 index 8de8cf2b1..000000000 --- a/src/libtracker-extract/meson.build +++ /dev/null @@ -1,47 +0,0 @@ -libtracker_extract_sources = [ - 'tracker-encoding.c', - 'tracker-exif.c', - 'tracker-extract-info.c', - 'tracker-guarantee.c', - 'tracker-iptc.c', - 'tracker-module-manager.c', - 'tracker-resource-helpers.c', - 'tracker-utils.c', - 'tracker-xmp.c', -] - -if charset_library_name == 'enca' - libtracker_extract_sources += 'tracker-encoding-enca.c' -elif charset_library_name == 'icu' - libtracker_extract_sources += 'tracker-encoding-libicu.c' -endif - -tracker_extract_dependencies = [charset_library, gmodule] - -if exempi.found() - tracker_extract_dependencies += exempi -endif - -if libexif.found() - tracker_extract_dependencies += libexif -endif - -if libiptcdata.found() - tracker_extract_dependencies += libiptcdata -endif - -libtracker_extract = library('tracker-extract', - libtracker_extract_sources, - dependencies: [tracker_common_dep, tracker_sparql_dep] + tracker_extract_dependencies, - c_args: tracker_c_args + [ - '-DTRACKER_EXTRACTOR_RULES_DIR="@0@"'.format(tracker_extract_rules_dir), - '-DTRACKER_EXTRACTORS_DIR="@0@"'.format(tracker_extract_modules_dir) - ], - install: true, - install_rpath: tracker_internal_libs_dir, -) - -tracker_extract_dep = declare_dependency( - link_with: libtracker_extract, - dependencies: [tracker_sparql_dep] + tracker_extract_dependencies, - include_directories: srcinc) diff --git a/src/libtracker-extract/tracker-data.h b/src/libtracker-extract/tracker-data.h deleted file mode 100644 index d0609d4b3..000000000 --- a/src/libtracker-extract/tracker-data.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __LIBTRACKER_EXTRACT_DATA_H__ -#define __LIBTRACKER_EXTRACT_DATA_H__ - -#if !defined (__LIBTRACKER_EXTRACT_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "only <libtracker-extract/tracker-extract.h> must be included directly." -#endif - -#include <libtracker-sparql/tracker-resource.h> -#include <libtracker-sparql/tracker-sparql.h> -#include "tracker-module-manager.h" -#include "tracker-extract-info.h" - -G_BEGIN_DECLS - -/** - * SECTION:tracker-extract - * @title: libtracker-extract - * @stability: Unstable - * @include: libtracker-extract/tracker-extract.h - * - * The libtracker-extract library is an internal, private library for Tracker - * metadata extraction modules. Third party applications should not link - * against libtracker-extract, because its API may change at any time. - * - * If you want to insert metadata into the Tracker store from a 3rd party - * application, look at the TrackerDecorator class from libtracker-miner. - */ - -gboolean tracker_extract_module_init (GError **error); -gboolean tracker_extract_module_shutdown (void); - -/** - * tracker_extract_get_metadata: - * @info: a #TrackerExtractInfo object - * - * This function must be provided by ALL extractors. This is merely - * the declaration of the function which must be written by each - * extractor. - * - * This is checked by tracker-extract by looking up the symbols for - * each started plugin and making sure this function exists. - * - * The @info parameter contains required information for the - * extraction and a location to store the results. The - * tracker_extract_info_get_metadata_builder() function returns a - * #TrackerSparqlBuilder constructed through - * tracker_sparql_builder_new_embedded_insert(). The subject - * is already set to be the file URN, so implementations of this - * function should just provide predicate/object(s) pairs. The - * triples contained in this object at the end of the function will be - * merged with further file information from miners. - * - * Whenever any of the inserted triples rely on entities that - * should also be provided by this extractor (for example, album - * or artist information from a song), such insertions should be - * added to the preupdate object returned by - * tracker_extract_info_get_preupdate_builder(). This is a - * #TrackerSparqlBuilder created through - * tracker_sparql_builder_new_update(). - * - * NOTE: If upgrading from 0.10, this function replaces the old - * function named tracker_extract_get_data() and has a few subtle - * differences. First, there is a return value for success and the - * parameters are contained in @info instead of being passed - * individually. Second, the extractor is passed the detected - * MIME type of the file being extracted. - * - * Returns: %TRUE if the extraction succeeded, %FALSE otherwise. - * - * Since: 0.12 - */ -gboolean tracker_extract_get_metadata (TrackerExtractInfo *info); - -G_END_DECLS - -#endif /* __LIBTRACKER_EXTRACT_DATA_H__ */ diff --git a/src/libtracker-extract/tracker-encoding-enca.c b/src/libtracker-extract/tracker-encoding-enca.c deleted file mode 100644 index 8bc4f3ee4..000000000 --- a/src/libtracker-extract/tracker-encoding-enca.c +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2011 Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <glib.h> -#include "tracker-encoding-enca.h" - -#include <enca.h> - -gchar * -tracker_encoding_guess_enca (const gchar *buffer, - gsize size) -{ - gchar *encoding = NULL; - const gchar **langs; - gsize s; - gsize i; - - langs = enca_get_languages (&s); - - for (i = 0; i < s && !encoding; i++) { - EncaAnalyser analyser; - EncaEncoding eencoding; - - analyser = enca_analyser_alloc (langs[i]); - eencoding = enca_analyse_const (analyser, (guchar *)buffer, size); - - if (enca_charset_is_known (eencoding.charset)) { - encoding = g_strdup (enca_charset_name (eencoding.charset, - ENCA_NAME_STYLE_ICONV)); - } - - enca_analyser_free (analyser); - } - - free (langs); - - if (encoding) - g_debug ("Guessing charset as '%s'", encoding); - - return encoding; -} diff --git a/src/libtracker-extract/tracker-encoding-enca.h b/src/libtracker-extract/tracker-encoding-enca.h deleted file mode 100644 index af839781f..000000000 --- a/src/libtracker-extract/tracker-encoding-enca.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2011 Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __LIBTRACKER_EXTRACT_ENCODING_ENCA_H__ -#define __LIBTRACKER_EXTRACT_ENCODING_ENCA_H__ - -#include <glib.h> - -G_BEGIN_DECLS - -G_GNUC_INTERNAL -gchar *tracker_encoding_guess_enca (const gchar *buffer, - gsize size); - -G_END_DECLS - -#endif /* __LIBTRACKER_EXTRACT_ENCODING_ENCA_H__ */ diff --git a/src/libtracker-extract/tracker-encoding-libicu.c b/src/libtracker-extract/tracker-encoding-libicu.c deleted file mode 100644 index 3490dac23..000000000 --- a/src/libtracker-extract/tracker-encoding-libicu.c +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2013 Carlos Garnacho <carlos@lanedo.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include "unicode/utypes.h" -#include "unicode/localpointer.h" -#include "unicode/uenum.h" -#include "unicode/ucsdet.h" - -#include <glib.h> -#include "tracker-encoding-libicu.h" - -gchar * -tracker_encoding_guess_icu (const gchar *buffer, - gsize size, - gdouble *confidence) -{ - UCharsetDetector *detector = NULL; - const UCharsetMatch *match; - gchar *charset = NULL; - UErrorCode status = 0; - const char *p_match = NULL; - int32_t conf = 0; - - detector = ucsdet_open (&status); - - if (U_FAILURE (status)) - goto failure; - - if (size >= G_MAXINT32) - goto failure; - - ucsdet_setText (detector, buffer, (int32_t) size, &status); - - if (U_FAILURE (status)) - goto failure; - - match = ucsdet_detect (detector, &status); - - if (match == NULL || U_FAILURE (status)) - goto failure; - - p_match = ucsdet_getName (match, &status); - - if (p_match == NULL || U_FAILURE (status)) - goto failure; - - conf = ucsdet_getConfidence (match, &status); - - if (U_FAILURE (status)) - goto failure; - - charset = g_strdup ((const gchar *) p_match); - - if (charset) - g_debug ("Guessing charset as '%s' (Confidence: %f)", - charset, (gdouble) conf / 100); - -failure: - if (confidence) - *confidence = (gdouble) conf / 100; - - if (detector) - ucsdet_close (detector); - - return charset; -} diff --git a/src/libtracker-extract/tracker-encoding-libicu.h b/src/libtracker-extract/tracker-encoding-libicu.h deleted file mode 100644 index 3b3f94256..000000000 --- a/src/libtracker-extract/tracker-encoding-libicu.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (C) 2013 Carlos Garnacho <carlos@lanedo.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __LIBTRACKER_EXTRACT_ENCODING_ICU_H__ -#define __LIBTRACKER_EXTRACT_ENCODING_ICU_H__ - -#include <glib.h> - -G_BEGIN_DECLS - -G_GNUC_INTERNAL -gchar *tracker_encoding_guess_icu (const gchar *buffer, - gsize size, - gdouble *confidence); - -G_END_DECLS - -#endif /* __LIBTRACKER_EXTRACT_ENCODING_ICU_H__ */ diff --git a/src/libtracker-extract/tracker-encoding.c b/src/libtracker-extract/tracker-encoding.c deleted file mode 100644 index f01576773..000000000 --- a/src/libtracker-extract/tracker-encoding.c +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (C) 2011 Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <glib.h> -#include "tracker-encoding.h" - -#ifdef HAVE_ENCA -#include "tracker-encoding-enca.h" -#endif - -#ifdef HAVE_LIBICU_CHARSET_DETECTION -#include "tracker-encoding-libicu.h" -#endif - -gboolean -tracker_encoding_can_guess (void) -{ -#if defined (HAVE_ENCA) || defined (HAVE_LIBICU_CHARSET_DETECTION) - return TRUE; -#else - return FALSE; -#endif -} - -gchar * -tracker_encoding_guess (const gchar *buffer, - gsize size, - gdouble *confidence) -{ - gchar *encoding = NULL; - gdouble conf = 1; - -#ifdef HAVE_LIBICU_CHARSET_DETECTION - encoding = tracker_encoding_guess_icu (buffer, size, &conf); -#endif /* HAVE_LIBICU_CHARSET_DETECTION */ - -#ifdef HAVE_ENCA - if (!encoding || conf < 0.5) { - conf = 1; - g_free (encoding); - encoding = tracker_encoding_guess_enca (buffer, size); - } -#endif /* HAVE_ENCA */ - - if (confidence) - *confidence = conf; - - return encoding; -} diff --git a/src/libtracker-extract/tracker-encoding.h b/src/libtracker-extract/tracker-encoding.h deleted file mode 100644 index ed7e51e17..000000000 --- a/src/libtracker-extract/tracker-encoding.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2011 Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __LIBTRACKER_EXTRACT_ENCODING_H__ -#define __LIBTRACKER_EXTRACT_ENCODING_H__ - -#if !defined (__LIBTRACKER_EXTRACT_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "only <libtracker-extract/tracker-extract.h> must be included directly." -#endif - -#include <glib.h> - -G_BEGIN_DECLS - -/* Returns TRUE if there is some method available to guess encodings */ -gboolean tracker_encoding_can_guess (void); - -/* Returns NULL if it couldn't guess it */ -gchar *tracker_encoding_guess (const gchar *buffer, - gsize size, - gdouble *confidence); - -G_END_DECLS - -#endif /* __LIBTRACKER_EXTRACT_ENCODING_H__ */ diff --git a/src/libtracker-extract/tracker-exif.c b/src/libtracker-extract/tracker-exif.c deleted file mode 100644 index 3e70169e1..000000000 --- a/src/libtracker-extract/tracker-exif.c +++ /dev/null @@ -1,643 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <string.h> -#include <ctype.h> - -#include "tracker-exif.h" -#include "tracker-utils.h" - -#ifdef HAVE_LIBEXIF - -#include <libexif/exif-data.h> - -#define EXIF_DATE_FORMAT "%Y:%m:%d %H:%M:%S" - -/** - * SECTION:tracker-exif - * @title: Exif - * @short_description: Exchangeable Image File Format (EXIF) - * @stability: Stable - * @include: libtracker-extract/tracker-extract.h - * - * Exchangeable Image File Format (EXIF) is a specification for the - * image file format used by digital cameras. The specification uses - * the existing JPEG, TIFF Rev. 6.0, and RIFF WAV file formats, with - * the addition of specific metadata tags. It is not supported in JPEG - * 2000, PNG, or GIF. - * - * This API is provided to remove code duplication between extractors - * using these standards. - **/ - -static gchar * -get_date (ExifData *exif, - ExifTag tag) -{ - ExifEntry *entry = exif_data_get_entry (exif, tag); - - if (entry) { - gchar buf[1024]; - - exif_entry_get_value (entry, buf, 1024); - /* From: ex; date "2007:04:15 15:35:58" - * To : ex. "2007-04-15T17:35:58+0200 where +0200 is offset w.r.t gmt */ - return tracker_date_format_to_iso8601 (buf, EXIF_DATE_FORMAT); - } - - return NULL; -} - -static gchar * -get_focal_length (ExifData *exif, - ExifTag tag) -{ - ExifEntry *entry = exif_data_get_entry (exif, tag); - - if (entry) { - gchar buf[1024]; - const gchar *end; - exif_entry_get_value (entry, buf, 1024); - end = g_strstr_len (buf, 1024, " mm"); - if (end) { - return g_strndup (buf, end - buf); - } else { - return NULL; - } - } - - return NULL; -} - -static gchar * -get_flash (ExifData *exif, - ExifTag tag) -{ - ExifEntry *entry = exif_data_get_entry (exif, tag); - - if (entry) { - ExifByteOrder order; - gushort flash; - - order = exif_data_get_byte_order (exif); - flash = exif_get_short (entry->data, order); - - switch (flash) { - case 0x0000: /* No flash */ - case 0x0005: /* Without strobe */ - case 0x0008: /* Flash did not fire */ - case 0x0010: /* Flash in compulsory mode, did not fire */ - case 0x0018: /* Flash in auto mode, did not fire */ - case 0x0058: /* Only red-eye reduction mode */ - return g_strdup ("nmm:flash-off"); - default: - return g_strdup ("nmm:flash-on"); - } - } - - return NULL; -} - -static gchar * -get_fnumber (ExifData *exif, - ExifTag tag) -{ - ExifEntry *entry = exif_data_get_entry (exif, tag); - - if (entry) { - gchar buf[1024]; - gchar *new_fn; - - exif_entry_get_value (entry, buf, 1024); - - if (strlen (buf) <= 0) { - return NULL; - } - - new_fn = g_strdup (buf); - - if (new_fn[0] == 'F') { - new_fn[0] = ' '; - } else if (buf[0] == 'f' && new_fn[1] == '/') { - new_fn[0] = new_fn[1] = ' '; - } - - return g_strstrip (new_fn); - } - - return NULL; -} - -static gchar * -get_exposure_time (ExifData *exif, - ExifTag tag) -{ - ExifEntry *entry = exif_data_get_entry (exif, tag); - - if (entry) { - gchar buf[1024]; - gchar *sep; - - exif_entry_get_value (entry, buf, 1024); - - sep = strchr (buf, '/'); - - if (sep) { - gdouble fraction; - - fraction = g_ascii_strtod (sep + 1, NULL); - - if (fraction > 0.0) { - gdouble val; - gchar bufr[G_ASCII_DTOSTR_BUF_SIZE]; - - val = 1.0f / fraction; - g_ascii_dtostr (bufr, sizeof(bufr), val); - - return g_strdup (bufr); - } - } - - return g_strdup (buf); - } - - return NULL; -} - -static gchar * -get_orientation (ExifData *exif, - ExifTag tag) -{ - ExifEntry *entry = exif_data_get_entry (exif, tag); - - if (entry) { - ExifByteOrder order; - gushort orientation; - - order = exif_data_get_byte_order (exif); - orientation = exif_get_short (entry->data, order); - - switch (orientation) { - case 1: - return g_strdup ("nfo:orientation-top"); - case 2: - return g_strdup ("nfo:orientation-top-mirror"); - case 3: - return g_strdup ("nfo:orientation-bottom"); - case 4: - return g_strdup ("nfo:orientation-bottom-mirror"); - case 5: - return g_strdup ("nfo:orientation-left-mirror"); - case 6: - return g_strdup ("nfo:orientation-right"); - case 7: - return g_strdup ("nfo:orientation-right-mirror"); - case 8: - return g_strdup ("nfo:orientation-left"); - default: - return g_strdup ("nfo:orientation-top"); - } - } - - return NULL; -} - -static gchar * -get_metering_mode (ExifData *exif, - ExifTag tag) -{ - ExifEntry *entry = exif_data_get_entry (exif, tag); - - if (entry) { - ExifByteOrder order; - gushort metering; - - order = exif_data_get_byte_order (exif); - metering = exif_get_short (entry->data, order); - - switch (metering) { - case 1: - return g_strdup ("nmm:metering-mode-average"); - case 2: - return g_strdup ("nmm:metering-mode-center-weighted-average"); - case 3: - return g_strdup ("nmm:metering-mode-spot"); - case 4: - return g_strdup ("nmm:metering-mode-multispot"); - case 5: - return g_strdup ("nmm:metering-mode-pattern"); - case 6: - return g_strdup ("nmm:metering-mode-partial"); - default: - return g_strdup ("nmm:metering-mode-other"); - } - } - - return NULL; -} - -static gchar * -get_white_balance (ExifData *exif, - ExifTag tag) -{ - ExifEntry *entry = exif_data_get_entry (exif, tag); - - if (entry) { - ExifByteOrder order; - gushort white_balance; - - order = exif_data_get_byte_order (exif); - white_balance = exif_get_short (entry->data, order); - - if (white_balance == 0) - return g_strdup ("nmm:white-balance-auto"); - - /* Found in the field: sunny, fluorescent, incandescent, cloudy. - * These will this way also yield as manual. */ - return g_strdup ("nmm:white-balance-manual"); - } - - return NULL; -} - -static gchar * -get_gps_coordinate (ExifData *exif, - ExifTag tag, - ExifTag reftag) -{ - ExifEntry *entry = exif_data_get_entry (exif, tag); - ExifEntry *refentry = exif_data_get_entry (exif, reftag); - - if (entry && refentry) { - ExifByteOrder order; - ExifRational degrees, minutes, seconds; - gfloat f; - gchar ref; - - if (entry->size == 24) { - order = exif_data_get_byte_order (exif); - degrees = exif_get_rational (entry->data, order); - minutes = exif_get_rational (entry->data + 8, order); - seconds = exif_get_rational (entry->data + 16, order); - ref = exif_get_short (refentry->data, order); - - /* Avoid ridiculous values */ - if (degrees.denominator == 0 || - minutes.denominator == 0 || - seconds.denominator == 0) { - return NULL; - } - - f = (gdouble) degrees.numerator / degrees.denominator + - (gdouble) minutes.numerator / (minutes.denominator * 60) + - (gdouble) seconds.numerator / (seconds.denominator * 60 * 60); - - if (ref == 'S' || ref == 'W') { - f = -1 * f; - } - - return g_strdup_printf ("%f", f); - } else { - gchar buf[25] = { 0 }; - - /* Incomplete data or it doesn't exist, fall - * back to exif_entry_get_value() for safety. - */ - exif_entry_get_value (entry, buf, sizeof (buf) - 1); - - if (buf[0] == '\0') { - g_message ("EXIF GPS coordinate information is non-existent but EXIF tag '%s' was found, " - "possible broken EXIF data?", - exif_tag_get_name (tag)); - } else { - g_message ("EXIF GPS coordinate information is partial, " - "got EXIF tag '%s' with value '%s', " - "expected with degrees, minutes and seconds", - exif_tag_get_name (tag), - buf); - } - - g_message ("EXIF GPS coordinate information could not be extracted with tag '%s'", - exif_tag_get_name (tag)); - } - } - - return NULL; -} - -static gchar * -get_gps_altitude (ExifData *exif, - ExifTag tag, - ExifTag reftag) -{ - ExifEntry *entry = exif_data_get_entry (exif, tag); - ExifEntry *refentry = exif_data_get_entry (exif, reftag); - - if (entry) { - ExifByteOrder order; - ExifRational c; - gfloat f; - - order = exif_data_get_byte_order (exif); - c = exif_get_rational (entry->data, order); - - /* Avoid ridiculous values */ - if (c.denominator == 0) { - return NULL; - } - - f = (double)c.numerator/c.denominator; - - /* Strictly speaking it is invalid not to have this - but.. let's try to cope here */ - if (refentry) { - ExifShort ref; - ref = exif_get_short (refentry->data, order); - if (ref == 1) { - f = -1 * f; - } - } - return g_strdup_printf ("%f", f); - } - - return NULL; -} - -static gint -get_int (ExifData *exif, - ExifTag tag) -{ - ExifEntry *entry = exif_data_get_entry (exif, tag); - - if (entry) { - ExifByteOrder order; - - order = exif_data_get_byte_order (exif); - return (gint) exif_get_short (entry->data, order); - } - - return -1; -} - - -static gchar * -get_value (ExifData *exif, - ExifTag tag) -{ - ExifEntry *entry = exif_data_get_entry (exif, tag); - - if (entry) { - gchar buf[1024]; - - exif_entry_get_value (entry, buf, 1024); - - return g_strdup (buf); - } - - return NULL; -} - -#endif /* HAVE_LIBEXIF */ - -static gboolean -parse_exif (const unsigned char *buffer, - size_t len, - const gchar *uri, - TrackerExifData *data) -{ -#ifdef HAVE_LIBEXIF - ExifData *exif; -#endif - - memset (data, 0, sizeof (TrackerExifData)); - -#ifdef HAVE_LIBEXIF - - exif = exif_data_new (); - - g_return_val_if_fail (exif != NULL, FALSE); - - exif_data_set_option (exif, EXIF_DATA_OPTION_IGNORE_UNKNOWN_TAGS); - exif_data_unset_option (exif, EXIF_DATA_OPTION_FOLLOW_SPECIFICATION); - exif_data_set_option (exif, EXIF_DATA_OPTION_DONT_CHANGE_MAKER_NOTE); - - exif_data_load_data (exif, (unsigned char *) buffer, len); - - /* Unused in the current only user of this code (JPeg extractor) - if (!data->y_dimension) - data->y_dimension = get_value (exif, EXIF_TAG_PIXEL_Y_DIMENSION); - if (!data->x_dimension) - data->x_dimension = get_value (exif, EXIF_TAG_PIXEL_X_DIMENSION); - if (!data->image_width) - data->image_width = get_value (exif, EXIF_TAG_RELATED_IMAGE_WIDTH); - */ - - if (!data->document_name) - data->document_name = get_value (exif, EXIF_TAG_DOCUMENT_NAME); - if (!data->time) - data->time = get_date (exif, EXIF_TAG_DATE_TIME); - if (!data->time_original) - data->time_original = get_date (exif, EXIF_TAG_DATE_TIME_ORIGINAL); - if (!data->artist) - data->artist = get_value (exif, EXIF_TAG_ARTIST); - if (!data->user_comment) - data->user_comment = get_value (exif, EXIF_TAG_USER_COMMENT); - if (!data->description) - data->description = get_value (exif, EXIF_TAG_IMAGE_DESCRIPTION); - if (!data->make) - data->make = get_value (exif, EXIF_TAG_MAKE); - if (!data->model) - data->model = get_value (exif, EXIF_TAG_MODEL); - if (!data->orientation) - data->orientation = get_orientation (exif, EXIF_TAG_ORIENTATION); - if (!data->exposure_time) - data->exposure_time = get_exposure_time (exif, EXIF_TAG_EXPOSURE_TIME); - if (!data->fnumber) - data->fnumber = get_fnumber (exif, EXIF_TAG_FNUMBER); - if (!data->flash) - data->flash = get_flash (exif, EXIF_TAG_FLASH); - if (!data->focal_length) - data->focal_length = get_focal_length (exif, EXIF_TAG_FOCAL_LENGTH); - if (!data->iso_speed_ratings) - data->iso_speed_ratings = get_value (exif, EXIF_TAG_ISO_SPEED_RATINGS); - if (!data->metering_mode) - data->metering_mode = get_metering_mode (exif, EXIF_TAG_METERING_MODE); - if (!data->white_balance) - data->white_balance = get_white_balance (exif, EXIF_TAG_WHITE_BALANCE); - if (!data->copyright) { - gchar *strip_off; - data->copyright = get_value (exif, EXIF_TAG_COPYRIGHT); - if (data->copyright) { - /* Exif catenates this to the string, noticed the - * string change from below in libexif 0.6.20 */ - strip_off = strstr (data->copyright, " (Photographer) - [None] (Editor)"); - if (strip_off) { - *strip_off = '\0'; - } else { - /* Fall back to old string */ - strip_off = strstr (data->copyright, " (Photographer) - (Editor)"); - - if (strip_off) { - *strip_off = '\0'; - } - } - } - } - if (!data->software) - data->software = get_value (exif, EXIF_TAG_SOFTWARE); - - if (!data->resolution_unit) - data->resolution_unit = get_int (exif, EXIF_TAG_RESOLUTION_UNIT); - if (!data->x_resolution) - data->x_resolution = get_value (exif, EXIF_TAG_X_RESOLUTION); - if (!data->y_resolution) - data->y_resolution = get_value (exif, EXIF_TAG_Y_RESOLUTION); - - if(!data->gps_altitude) - data->gps_altitude = get_gps_altitude (exif, EXIF_TAG_GPS_ALTITUDE, EXIF_TAG_GPS_ALTITUDE_REF); - if(!data->gps_latitude) - data->gps_latitude = get_gps_coordinate (exif, EXIF_TAG_GPS_LATITUDE, EXIF_TAG_GPS_LATITUDE_REF); - if(!data->gps_longitude) - data->gps_longitude = get_gps_coordinate (exif, EXIF_TAG_GPS_LONGITUDE, EXIF_TAG_GPS_LONGITUDE_REF); - if(!data->gps_direction) - data->gps_direction = get_value (exif, EXIF_TAG_GPS_IMG_DIRECTION); - - exif_data_free (exif); -#endif /* HAVE_LIBEXIF */ - - return TRUE; -} - -#ifndef TRACKER_DISABLE_DEPRECATED - -/** - * tracker_exif_read: - * @buffer: a chunk of data with exif data in it. - * @len: the size of @buffer. - * @uri: the URI this is related to. - * @data: a pointer to a TrackerExifData struture to populate. - * - * This function takes @len bytes of @buffer and runs it through the - * EXIF library. The result is that @data is populated with the EXIF - * data found in @uri. - * - * Returns: %TRUE if the @data was populated successfully, otherwise - * %FALSE is returned. - * - * Since: 0.8 - * - * Deprecated: 0.9. Use tracker_exif_new() instead. - **/ -gboolean -tracker_exif_read (const unsigned char *buffer, - size_t len, - const gchar *uri, - TrackerExifData *data) -{ - g_return_val_if_fail (buffer != NULL, FALSE); - g_return_val_if_fail (len > 0, FALSE); - g_return_val_if_fail (uri != NULL, FALSE); - g_return_val_if_fail (data != NULL, FALSE); - - return parse_exif (buffer, len, uri, data); -} - -#endif /* TRACKER_DISABLE_DEPRECATED */ - -/** - * tracker_exif_new: - * @buffer: a chunk of data with exif data in it. - * @len: the size of @buffer. - * @uri: the URI this is related to. - * - * This function takes @len bytes of @buffer and runs it through the - * EXIF library. - * - * Returns: a newly allocated #TrackerExifData struct if EXIF data was - * found, %NULL otherwise. Free the returned struct with tracker_exif_free(). - * - * Since: 0.10 - **/ -TrackerExifData * -tracker_exif_new (const guchar *buffer, - size_t len, - const gchar *uri) -{ - TrackerExifData *data; - - g_return_val_if_fail (buffer != NULL, NULL); - g_return_val_if_fail (len > 0, NULL); - g_return_val_if_fail (uri != NULL, NULL); - - data = g_new0 (TrackerExifData, 1); - - if (!parse_exif (buffer, len, uri, data)) { - tracker_exif_free (data); - return NULL; - } - - return data; -} - -/** - * tracker_exif_free: - * @data: a #TrackerExifData - * - * Frees @data and all #TrackerExifData members. %NULL will produce a - * a warning. - * - * Since: 0.10 - **/ -void -tracker_exif_free (TrackerExifData *data) -{ - g_return_if_fail (data != NULL); - - g_free (data->y_dimension); - g_free (data->x_dimension); - g_free (data->image_width); - g_free (data->document_name); - g_free (data->time); - g_free (data->time_original); - g_free (data->artist); - g_free (data->user_comment); - g_free (data->description); - g_free (data->make); - g_free (data->model); - g_free (data->orientation); - g_free (data->exposure_time); - g_free (data->fnumber); - g_free (data->flash); - g_free (data->focal_length); - g_free (data->iso_speed_ratings); - g_free (data->metering_mode); - g_free (data->white_balance); - g_free (data->copyright); - g_free (data->software); - g_free (data->x_resolution); - g_free (data->y_resolution); - g_free (data->gps_altitude); - g_free (data->gps_latitude); - g_free (data->gps_longitude); - g_free (data->gps_direction); - - g_free (data); -} diff --git a/src/libtracker-extract/tracker-exif.h b/src/libtracker-extract/tracker-exif.h deleted file mode 100644 index 7d007111b..000000000 --- a/src/libtracker-extract/tracker-exif.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __LIBTRACKER_EXTRACT_EXIF_H__ -#define __LIBTRACKER_EXTRACT_EXIF_H__ - -#if !defined (__LIBTRACKER_EXTRACT_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "only <libtracker-extract/tracker-extract.h> must be included directly." -#endif - -#include <glib.h> - -G_BEGIN_DECLS - -/** - * TrackerExifData: - * @y_dimension: Y dimension. - * @x_dimension: X dimension. - * @image_width: Image width. - * @document_name: Document name. - * @time: Time. - * @time_original: Original time. - * @artist: Artist. - * @user_comment: User-provided comment. - * @description: Description. - * @make: Make info. - * @model: Model info. - * @orientation: Orientation. - * @exposure_time: Exposure time. - * @fnumber: Focal ratio - * @flash: Flash info. - * @focal_length: Focal length. - * @iso_speed_ratings: ISO speed ratings. - * @metering_mode: Metering mode. - * @white_balance: White balance. - * @copyright: Copyright. - * @software: Software used. - * @x_resolution: Horizontal resolution. - * @y_resolution: Vertical resolution. - * @resolution_unit: Resolution units. - * @gps_altitude: GPS altitude. - * @gps_latitude: GPS latitude. - * @gps_longitude: GPS longitude. - * @gps_direction: GPS direction information. - * - * Structure defining EXIF data. - */ -typedef struct { - gchar *y_dimension; - gchar *x_dimension; - gchar *image_width; - gchar *document_name; - gchar *time; - gchar *time_original; - gchar *artist; - gchar *user_comment; - gchar *description; - gchar *make; - gchar *model; - gchar *orientation; - gchar *exposure_time; - gchar *fnumber; - gchar *flash; - gchar *focal_length; - gchar *iso_speed_ratings; - gchar *metering_mode; - gchar *white_balance; - gchar *copyright; - gchar *software; - gchar *x_resolution; - gchar *y_resolution; - gint resolution_unit; - - /* ABI barrier (don't change things above this) */ - gchar *gps_altitude; - gchar *gps_latitude; - gchar *gps_longitude; - gchar *gps_direction; -} TrackerExifData; - -TrackerExifData * tracker_exif_new (const guchar *buffer, - size_t len, - const gchar *uri); -void tracker_exif_free (TrackerExifData *data); - -#ifndef TRACKER_DISABLE_DEPRECATED - -gboolean tracker_exif_read (const unsigned char *buffer, - size_t len, - const gchar *uri, - TrackerExifData *data) G_GNUC_DEPRECATED; - -#endif /* TRACKER_DISABLE_DEPRECATED */ - -G_END_DECLS - -#endif /* __LIBTRACKER_EXTRACT_EXIF_H__ */ diff --git a/src/libtracker-extract/tracker-extract-info.c b/src/libtracker-extract/tracker-extract-info.c deleted file mode 100644 index 8e445ecad..000000000 --- a/src/libtracker-extract/tracker-extract-info.c +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright (C) 2011, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * Author: Carlos Garnacho <carlos@lanedo.com> - */ - -#include "config.h" - -#include "tracker-extract-info.h" - -/** - * SECTION:tracker-extract-info - * @title: TrackerExtractInfo - * @short_description: struct used to pass information to and from - * a Tracker extract module - * @stability: Stable - * @include: libtracker-extract/tracker-extract.h - * - * The #TrackerExtractInfo structure is used to pass information - * on the file being extracted to an extractor module and contains - * objects to hold the SPARQL updates generated by the extractor. - **/ - - -struct _TrackerExtractInfo -{ - TrackerResource *resource; - - GFile *file; - gchar *mimetype; - - gint ref_count; -}; - -G_DEFINE_BOXED_TYPE (TrackerExtractInfo, tracker_extract_info, - tracker_extract_info_ref, tracker_extract_info_unref) - -/** - * tracker_extract_info_new: - * @file: a #GFile - * @mimetype: mimetype for @file - * @graph: SPARQL graph used for inserting data - * - * Returns a newly created #TrackerExtractInfo - * - * Returns: (transfer full): (boxed): A newly allocated #TrackerExtractInfo - * - * Since: 0.12 - **/ -TrackerExtractInfo * -tracker_extract_info_new (GFile *file, - const gchar *mimetype) -{ - TrackerExtractInfo *info; - - g_return_val_if_fail (G_IS_FILE (file), NULL); - - info = g_slice_new0 (TrackerExtractInfo); - info->file = g_object_ref (file); - info->mimetype = g_strdup (mimetype); - - info->resource = NULL; - - info->ref_count = 1; - - return info; -} - -/** - * tracker_extract_info_ref: - * @info: a #TrackerExtractInfo - * - * Increases the reference count of @info - * - * Returns: A new reference to @info - * - * Since: 0.12 - **/ -TrackerExtractInfo * -tracker_extract_info_ref (TrackerExtractInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - - g_atomic_int_inc (&info->ref_count); - - return info; -} - -/** - * tracker_extract_info_unref: - * @info: a #TrackerExtractInfo - * - * Decreases the reference count of @info, freeing all its associated resources - * if it reaches 0. - * - * Since: 0.12 - **/ -void -tracker_extract_info_unref (TrackerExtractInfo *info) -{ - g_return_if_fail (info != NULL); - - if (g_atomic_int_dec_and_test (&info->ref_count)) { - g_object_unref (info->file); - g_free (info->mimetype); - - if (info->resource) - g_object_unref (info->resource); - - g_slice_free (TrackerExtractInfo, info); - } -} - -/** - * tracker_extract_info_get_file: - * @info: a #TrackerExtractInfo - * - * Returns a #GFile pointing to the file being affected - * by the metadata extraction represented by @info - * - * Returns: (transfer none): The file being inspected - * - * Since: 0.12 - **/ -GFile * -tracker_extract_info_get_file (TrackerExtractInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - - return info->file; -} - -/** - * tracker_extract_info_get_mimetype: - * @info: a #TrackerExtractInfo - * - * Returns the mimetype being used for the file - * metadata extraction. - * - * Returns: (transfer none): the mimetype being used - * for extraction. - * - * Since: 0.12 - **/ -const gchar * -tracker_extract_info_get_mimetype (TrackerExtractInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - - return info->mimetype; -} - - -/** - * tracker_extract_info_get_resource: - * @info: a #TrackerExtractInfo - * - * Returns the #TrackerResource representing metadata about the file - * associated with this #TrackerExtractInfo, or %NULL if - * tracker_extract_info_set_metadata() was not yet called. - * - * Returns: (transfer none): a #TrackerResource instance - * - * Since: 1.10 - */ -TrackerResource * -tracker_extract_info_get_resource (TrackerExtractInfo *info) -{ - return info->resource; -} - -/** - * tracker_extract_info_set_resource: - * @info: a #TrackerExtractInfo - * @resource: a #TrackerResource - * - * Adds the #TrackerResource with results from the extraction to this - * #TrackerExtractInfo. - * - * Information about the file itself should be represented by properties of - * @resource itself. It's expected this resource will have nfo:FileDataObject - * as one of its types. This @resource can have related resources attached to - * it. - * - * In most cases, a file contains a single logical resource. Most MP3 files - * contain one song, for example. In this case you set all properties on the - * one @resource. - * - * In more complex cases, a single physical resource (i.e. a file) contains multiple - * logical resources: for example, an MBOX file holding multiple emails, or - * an audio file containing an entire CD. In this case you should treat each - * logical resource as its own #TrackerResource. Only properties of the file - * itself should be set on @resource. You then relate each logical - * #TrackerResource to the main @resource using the nie:isStoredAs property. - * - * FIXME: you need a way to delete the logical resources when re-extracting a - * file -- still need to decide on API for that. - * - * Since: 1.10 - **/ -void -tracker_extract_info_set_resource (TrackerExtractInfo *info, - TrackerResource *resource) -{ - g_object_ref (resource); - info->resource = resource; -} diff --git a/src/libtracker-extract/tracker-extract-info.h b/src/libtracker-extract/tracker-extract-info.h deleted file mode 100644 index 537efb3b4..000000000 --- a/src/libtracker-extract/tracker-extract-info.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2011, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * Author: Carlos Garnacho <carlos@lanedo.com> - */ - -#ifndef __LIBTRACKER_EXTRACT_INFO_H__ -#define __LIBTRACKER_EXTRACT_INFO_H__ - -#if !defined (__LIBTRACKER_EXTRACT_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "only <libtracker-extract/tracker-extract.h> must be included directly." -#endif - -#include <libtracker-sparql/tracker-sparql.h> -#include <gio/gio.h> - -G_BEGIN_DECLS - -typedef struct _TrackerExtractInfo TrackerExtractInfo; - -GType tracker_extract_info_get_type (void) G_GNUC_CONST; - -TrackerExtractInfo * tracker_extract_info_new (GFile *file, - const gchar *mimetype); -TrackerExtractInfo * tracker_extract_info_ref (TrackerExtractInfo *info); -void tracker_extract_info_unref (TrackerExtractInfo *info); -GFile * tracker_extract_info_get_file (TrackerExtractInfo *info); -const gchar * tracker_extract_info_get_mimetype (TrackerExtractInfo *info); - -TrackerResource * tracker_extract_info_get_resource (TrackerExtractInfo *info); -void tracker_extract_info_set_resource (TrackerExtractInfo *info, - TrackerResource *resource); - -G_END_DECLS - -#endif /* __LIBTRACKER_EXTRACT_INFO_H__ */ diff --git a/src/libtracker-extract/tracker-extract.h b/src/libtracker-extract/tracker-extract.h deleted file mode 100644 index 32c40bb1f..000000000 --- a/src/libtracker-extract/tracker-extract.h +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __LIBTRACKER_EXTRACT_H__ -#define __LIBTRACKER_EXTRACT_H__ - -#include <glib.h> - -#define __LIBTRACKER_EXTRACT_INSIDE__ - -#include "tracker-data.h" -#include "tracker-encoding.h" -#include "tracker-exif.h" -#include "tracker-extract-info.h" -#include "tracker-module-manager.h" -#include "tracker-guarantee.h" -#include "tracker-iptc.h" -#include "tracker-resource-helpers.h" -#include "tracker-utils.h" -#include "tracker-xmp.h" - -#undef __LIBTRACKER_EXTRACT_INSIDE__ - -#endif /* __LIBTRACKER_EXTRACT_H__ */ diff --git a/src/libtracker-extract/tracker-guarantee.c b/src/libtracker-extract/tracker-guarantee.c deleted file mode 100644 index 841b6639d..000000000 --- a/src/libtracker-extract/tracker-guarantee.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <string.h> - -#include <glib.h> - -#include <libtracker-common/tracker-file-utils.h> -#include <libtracker-common/tracker-date-time.h> - -#include "tracker-guarantee.h" - -#ifdef GUARANTEE_METADATA - -static gchar * -get_title_from_file (const gchar *uri) -{ - gchar *filename; - gchar *basename; - gchar *p; - - filename = g_filename_from_uri (uri, NULL, NULL); - basename = g_filename_display_basename (filename); - g_free (filename); - - p = strrchr (basename, '.'); - if (p) { - if (p == basename) { - p = g_strdup (&basename[1]); - g_free (basename); - basename = p; - } else { - *p = '\0'; - } - } - - return g_strdelimit (basename, "_", ' '); -} - -static gchar * -get_date_from_file_mtime (const gchar *uri) -{ - gchar *date; - guint64 mtime; - - mtime = tracker_file_get_mtime_uri (uri); - - date = tracker_date_to_string ((time_t) mtime); - - return date; -} - -#endif /* GUARANTEE_METADATA */ - -/** - * tracker_guarantee_resource_title_from_file: - * @resource: the relevant #TrackerResource - * @key: the property URI to set - * @current_value: the current data to check before looking at @uri. - * @uri: a string representing a URI to use - * @p_new_value: pointer to a string which receives the new title, or - * %NULL - * - * Checks @current_value to make sure it is usable (i.e. not %NULL or an - * empty string). If it is not usable, then @uri is parsed to guarantee a - * metadata value for @key. - * - * Parses the file pointed to by @uri and uses the basename - * (before the "." and extension of the file) as the title. If the - * title has any "_" characters, they are also converted into spaces. - * - * This function only operates if Tracker was compiled with - * --enable-guarantee-metadata enabled at configure-time. - * - * Returns: %TRUE on success and content was added to @metadata, otherwise %FALSE. - * - * Since: 1.10 - **/ -gboolean -tracker_guarantee_resource_title_from_file (TrackerResource *resource, - const gchar *key, - const gchar *current_value, - const gchar *uri, - gchar **p_new_value) -{ - gboolean success = TRUE; - -#ifdef GUARANTEE_METADATA - g_return_val_if_fail (resource != NULL, FALSE); - g_return_val_if_fail (key != NULL, FALSE); - g_return_val_if_fail (uri != NULL, FALSE); - - if (current_value && *current_value != '\0') { - tracker_resource_set_string (resource, key, current_value); - - if (p_new_value != NULL) { - *p_new_value = g_strdup (current_value); - } - } else { - gchar *value; - - value = get_title_from_file (uri); - - if (value && value[0] != '\0') { - tracker_resource_set_string (resource, key, value); - } else { - success = FALSE; - } - - if (p_new_value != NULL) { - *p_new_value = value; - } else { - g_free (value); - } - } -#else /* GUARANTEE_METADATA */ - if (current_value && *current_value != '\0') { - tracker_resource_set_string (resource, key, current_value); - - if (p_new_value != NULL) { - *p_new_value = g_strdup (current_value); - } - } else { - success = FALSE; - } -#endif /* GUARANTEE_METADATA */ - - return success; -} - -/** - * tracker_guarantee_resource_date_from_file_mtime: - * @resource: the relevant #TrackerResource - * @key: the property URI to set - * @current_value: the current data to check before looking at @uri - * @uri: a string representing a URI to use - * - * Checks @current_value to make sure it is sane (i.e. not %NULL or an - * empty string). If it is, then @uri is parsed to guarantee a - * metadata value for @key. - * - * When parsing @uri, stat() is called on the file to create a - * date based on the file's mtime. - * - * This function only operates if Tracker was compiled with - * --enable-guarantee-metadata enabled at configure-time. - * - * Returns: %TRUE on success and content was added to @metadata, otherwise %FALSE. - * - * Since: 1.10 - **/ -gboolean -tracker_guarantee_resource_date_from_file_mtime (TrackerResource *resource, - const gchar *key, - const gchar *current_value, - const gchar *uri) -{ - gboolean success = TRUE; - -#ifdef GUARANTEE_METADATA - g_return_val_if_fail (resource != NULL, FALSE); - g_return_val_if_fail (key != NULL, FALSE); - g_return_val_if_fail (uri != NULL, FALSE); - - if (current_value && *current_value != '\0') { - tracker_resource_set_string (resource, key, current_value); - } else { - gchar *value; - - value = get_date_from_file_mtime (uri); - - if (value && *value != '\0') { - tracker_resource_set_string (resource, key, value); - } else { - success = FALSE; - } - - g_free (value); - } -#else /* GUARANTEE_METADATA */ - if (current_value && *current_value != '\0') { - tracker_resource_set_string (resource, key, current_value); - } else { - success = FALSE; - } -#endif /* GUARANTEE_METADATA */ - - return success; -} - -gboolean -tracker_guarantee_resource_utf8_string (TrackerResource *resource, - const gchar *key, - const gchar *value) -{ - const gchar *end; - gchar *str; - - if (!g_utf8_validate (value, -1, &end)) { - if (end == value) - return FALSE; - - str = g_strndup (value, end - value); - tracker_resource_set_string (resource, key, str); - g_free (str); - } else { - tracker_resource_set_string (resource, key, value); - } - - return TRUE; -} diff --git a/src/libtracker-extract/tracker-guarantee.h b/src/libtracker-extract/tracker-guarantee.h deleted file mode 100644 index 6846e80aa..000000000 --- a/src/libtracker-extract/tracker-guarantee.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include <stdio.h> - -#ifndef __LIBTRACKER_EXTRACT_GUARANTEE__ -#define __LIBTRACKER_EXTRACT_GUARANTEE_H__ - -#if !defined (__LIBTRACKER_EXTRACT_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "only <libtracker-extract/tracker-extract.h> must be included directly." -#endif - -#include "tracker-data.h" - -G_BEGIN_DECLS - -gboolean tracker_guarantee_resource_title_from_file (TrackerResource *resource, - const gchar *key, - const gchar *current_value, - const gchar *uri, - gchar **p_new_value); -gboolean tracker_guarantee_resource_date_from_file_mtime (TrackerResource *resource, - const gchar *key, - const gchar *current_value, - const gchar *uri); -gboolean tracker_guarantee_resource_utf8_string (TrackerResource *resource, - const gchar *key, - const gchar *value); - -G_END_DECLS - -#endif /* __LIBTRACKER_EXTRACT_GUARANTEE_H__ */ diff --git a/src/libtracker-extract/tracker-iptc.c b/src/libtracker-extract/tracker-iptc.c deleted file mode 100644 index 68edda780..000000000 --- a/src/libtracker-extract/tracker-iptc.c +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <string.h> - -#include "tracker-iptc.h" -#include "tracker-utils.h" - -#ifdef HAVE_LIBIPTCDATA - -#include <libiptcdata/iptc-data.h> -#include <libiptcdata/iptc-dataset.h> - -#define IPTC_DATE_FORMAT "%Y %m %d" - -/** - * SECTION:tracker-iptc - * @title: IPTC - * @short_description: Information Interchange Model (IIM) / - * International Press Telecommunications Council (IPTC) - * @stability: Stable - * @include: libtracker-extract/tracker-extract.h - * - * The Information Interchange Model (IIM) is a file structure and set - * of metadata attributes that can be applied to text, images and - * other media types. It was developed in the early 1990s by the - * International Press Telecommunications Council (IPTC) to expedite - * the international exchange of news among newspapers and news - * agencies. - * - * The full IIM specification includes a complex data structure and a - * set of metadata definitions. - * - * Although IIM was intended for use with all types of news items — - * including simple text articles — a subset found broad worldwide - * acceptance as the standard embedded metadata used by news and - * commercial photographers. Information such as the name of the - * photographer, copyright information and the caption or other - * description can be embedded either manually or automatically. - * - * IIM metadata embedded in images are often referred to as "IPTC - * headers," and can be easily encoded and decoded by most popular - * photo editing software. - * - * The Extensible Metadata Platform (XMP) has largely superseded IIM's - * file structure, but the IIM image attributes are defined in the - * IPTC Core schema for XMP and most image manipulation programs keep - * the XMP and non-XMP IPTC attributes synchronized. - * - * This API is provided to remove code duplication between extractors - * using these standards. - **/ - -static const gchar * -fix_iptc_orientation (const gchar *orientation) -{ - if (g_strcmp0 (orientation, "P") == 0) { - return "nfo:orientation-left"; - } - - return "nfo:orientation-top"; /* We take this as default */ -} - -static void -foreach_dataset (IptcDataSet *dataset, - void *user_data) -{ - TrackerIptcData *data = user_data; - gchar mbuffer[1024]; - - /* The meaning of dataset->tag DEPENDS on the value of dataset->record. - * See iptc-tag.h for the relationship. - * - * Now, We only want record-2 tags, otherwise we'll end up mixing - * for example IPTC_TAG_CITY and IPTC_TAG_CHARACTER_SET, which BOTH - * have a value of 90. */ - if (dataset->record != IPTC_RECORD_APP_2) - return; - - switch (dataset->tag) { - case IPTC_TAG_KEYWORDS: - if (!data->keywords) { - iptc_dataset_get_as_str (dataset, mbuffer, 1024); - data->keywords = g_strdup (mbuffer); - } else { - gchar *tmp = data->keywords; - iptc_dataset_get_as_str (dataset, mbuffer, 1024); - data->keywords = g_strdup_printf ("%s, %s", data->keywords, mbuffer); - g_free (tmp); - } - break; - - case IPTC_TAG_DATE_CREATED: - if (!data->date_created) { - iptc_dataset_get_as_str (dataset, mbuffer, 1024); - /* From: ex; date "2007 04 15" - * To : ex. "2007-04-15T00:00:00+0200 where +0200 is offset w.r.t gmt */ - data->date_created = tracker_date_format_to_iso8601 (mbuffer, IPTC_DATE_FORMAT); - } - break; - - case IPTC_TAG_BYLINE: - if (!data->byline) { - iptc_dataset_get_as_str (dataset, mbuffer, 1024); - data->byline = g_strdup (mbuffer); - } - break; - - case IPTC_TAG_CREDIT: - if (!data->credit) { - iptc_dataset_get_as_str (dataset, mbuffer, 1024); - data->credit = g_strdup (mbuffer); - } - break; - - case IPTC_TAG_COPYRIGHT_NOTICE: - if (!data->copyright_notice) { - iptc_dataset_get_as_str (dataset, mbuffer, 1024); - data->copyright_notice = g_strdup (mbuffer); - } - break; - - case IPTC_TAG_IMAGE_ORIENTATION: - if (!data->image_orientation) { - iptc_dataset_get_as_str (dataset, mbuffer, 1024); - data->image_orientation = g_strdup (fix_iptc_orientation (mbuffer)); - } - break; - - case IPTC_TAG_BYLINE_TITLE: - if (!data->byline_title) { - iptc_dataset_get_as_str (dataset, mbuffer, 1024); - data->byline_title = g_strdup (mbuffer); - } - break; - - case IPTC_TAG_CITY: - if (!data->city) { - iptc_dataset_get_as_str (dataset, mbuffer, 1024); - data->city = g_strdup (mbuffer); - } - break; - - case IPTC_TAG_STATE: - if (!data->state) { - iptc_dataset_get_as_str (dataset, mbuffer, 1024); - data->state = g_strdup (mbuffer); - } - break; - - case IPTC_TAG_SUBLOCATION: - if (!data->sublocation) { - iptc_dataset_get_as_str (dataset, mbuffer, 1024); - data->sublocation = g_strdup (mbuffer); - } - break; - - case IPTC_TAG_COUNTRY_NAME: - if (!data->country_name) { - iptc_dataset_get_as_str (dataset, mbuffer, 1024); - data->country_name = g_strdup (mbuffer); - } - break; - - case IPTC_TAG_CONTACT: - if (!data->contact) { - iptc_dataset_get_as_str (dataset, mbuffer, 1024); - data->contact = g_strdup (mbuffer); - } - break; - - default: - break; - } -} - -#endif /* HAVE_LIBIPTCDATA */ - -static gboolean -parse_iptc (const unsigned char *buffer, - size_t len, - const gchar *uri, - TrackerIptcData *data) -{ -#ifdef HAVE_LIBIPTCDATA - IptcData *iptc; -#endif /* HAVE_LIBIPTCDATA */ - - memset (data, 0, sizeof (TrackerIptcData)); - -#ifdef HAVE_LIBIPTCDATA - - /* FIXME According to valgrind this is leaking (together with the unref). - * Problem in libiptc (I replaced this with the _free equivalent) */ - - iptc = iptc_data_new (); - - if (!iptc) - return FALSE; - - if (iptc_data_load (iptc, buffer, len) < 0) { - iptc_data_free (iptc); - return FALSE; - } - - iptc_data_foreach_dataset (iptc, foreach_dataset, data); - iptc_data_free (iptc); -#endif /* HAVE_LIBIPTCDATA */ - - return TRUE; -} - -#ifndef TRACKER_DISABLE_DEPRECATED - -// LCOV_EXCL_START - -/** - * tracker_iptc_read: - * @buffer: a chunk of data with iptc data in it. - * @len: the size of @buffer. - * @uri: the URI this is related to. - * @data: a pointer to a TrackerIptcData struture to populate. - * - * This function takes @len bytes of @buffer and runs it through the - * IPTC library. The result is that @data is populated with the IPTC - * data found in @uri. - * - * Returns: %TRUE if the @data was populated successfully, otherwise - * %FALSE is returned. - * - * Since: 0.8 - * - * Deprecated: 0.9. Use tracker_iptc_new() instead. - **/ -gboolean -tracker_iptc_read (const unsigned char *buffer, - size_t len, - const gchar *uri, - TrackerIptcData *data) -{ - g_return_val_if_fail (buffer != NULL, FALSE); - g_return_val_if_fail (len > 0, FALSE); - g_return_val_if_fail (uri != NULL, FALSE); - g_return_val_if_fail (data != NULL, FALSE); - - return parse_iptc (buffer, len, uri, data); -} - -// LCOV_EXCL_STOP - -#endif /* TRACKER_DISABLE_DEPRECATED */ - -/** - * tracker_iptc_new: - * @buffer: a chunk of data with iptc data in it. - * @len: the size of @buffer. - * @uri: the URI this is related to. - * - * This function takes @len bytes of @buffer and runs it through the - * IPTC library. - * - * Returns: a newly allocated #TrackerIptcData struct if IPTC data was - * found, %NULL otherwise. Free the returned struct with - * tracker_iptc_free(). - * - * Since: 0.10 - **/ -TrackerIptcData * -tracker_iptc_new (const guchar *buffer, - gsize len, - const gchar *uri) -{ - TrackerIptcData *data; - - g_return_val_if_fail (buffer != NULL, NULL); - g_return_val_if_fail (len > 0, NULL); - g_return_val_if_fail (uri != NULL, NULL); - - data = g_new0 (TrackerIptcData, 1); - - if (!parse_iptc (buffer, len, uri, data)) { - tracker_iptc_free (data); - return NULL; - } - - return data; -} - -/** - * tracker_iptc_free: - * @data: a #TrackerIptcData - * - * Frees @data and all #TrackerIptcData members. %NULL will produce a - * a warning. - * - * Since: 0.10 - **/ -void -tracker_iptc_free (TrackerIptcData *data) -{ - g_return_if_fail (data != NULL); - - g_free (data->keywords); - g_free (data->date_created); - g_free (data->byline); - g_free (data->credit); - g_free (data->copyright_notice); - g_free (data->image_orientation); - g_free (data->byline_title); - g_free (data->city); - g_free (data->state); - g_free (data->sublocation); - g_free (data->country_name); - g_free (data->contact); - - g_free (data); -} diff --git a/src/libtracker-extract/tracker-iptc.h b/src/libtracker-extract/tracker-iptc.h deleted file mode 100644 index 534e495d6..000000000 --- a/src/libtracker-extract/tracker-iptc.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __LIBTRACKER_EXTRACT_IPTC_H__ -#define __LIBTRACKER_EXTRACT_IPTC_H__ - -#if !defined (__LIBTRACKER_EXTRACT_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "only <libtracker-extract/tracker-extract.h> must be included directly." -#endif - -#include <glib.h> - -/* IPTC Information Interchange Model */ - -G_BEGIN_DECLS - -/** - * TrackerIptcData: - * @keywords: Keywords. - * @date_created: Date created. - * @byline: Byline. - * @credit: Credits. - * @copyright_notice: Copyright. - * @image_orientation: Image orientation. - * @byline_title: Byline title. - * @city: City. - * @state: State. - * @sublocation: Sublocation. - * @country_name: Country. - * @contact: Contact info. - * - * Structure defining IPTC data. - */ -typedef struct { - gchar *keywords; - gchar *date_created; - gchar *byline; - gchar *credit; - gchar *copyright_notice; - gchar *image_orientation; - gchar *byline_title; - gchar *city; - gchar *state; - gchar *sublocation; - gchar *country_name; - gchar *contact; -} TrackerIptcData; - -TrackerIptcData *tracker_iptc_new (const guchar *buffer, - gsize len, - const gchar *uri); -void tracker_iptc_free (TrackerIptcData *data); - -#ifndef TRACKER_DISABLE_DEPRECATED - -gboolean tracker_iptc_read (const unsigned char *buffer, - size_t len, - const gchar *uri, - TrackerIptcData *data) G_GNUC_DEPRECATED; - -#endif /* TRACKER_DISABLE_DEPRECATED */ - -G_END_DECLS - -#endif /* __LIBTRACKER_EXTRACT_IPTC_H__ */ diff --git a/src/libtracker-extract/tracker-module-manager.c b/src/libtracker-extract/tracker-module-manager.c deleted file mode 100644 index b3803fe3f..000000000 --- a/src/libtracker-extract/tracker-module-manager.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <string.h> - -#include "tracker-module-manager.h" - -#define EXTRACTOR_FUNCTION "tracker_extract_get_metadata" -#define INIT_FUNCTION "tracker_extract_module_init" -#define SHUTDOWN_FUNCTION "tracker_extract_module_shutdown" - -typedef struct { - const gchar *module_path; /* intern string */ - GList *patterns; - GStrv fallback_rdf_types; -} RuleInfo; - -typedef struct { - GModule *module; - TrackerExtractMetadataFunc extract_func; - TrackerExtractInitFunc init_func; - TrackerExtractShutdownFunc shutdown_func; -} ModuleInfo; - -static gboolean dummy_extract_func (TrackerExtractInfo *info); - -static ModuleInfo dummy_module = { - NULL, dummy_extract_func, NULL, NULL -}; - -static GHashTable *modules = NULL; -static GHashTable *mimetype_map = NULL; -static gboolean initialized = FALSE; -static GArray *rules = NULL; - -struct _TrackerMimetypeInfo { - const GList *rules; - const GList *cur; - - ModuleInfo *cur_module_info; -}; - -static gboolean -dummy_extract_func (TrackerExtractInfo *info) -{ - return TRUE; -} - -static gboolean -load_extractor_rule (GKeyFile *key_file, - GError **error) -{ - GError *local_error = NULL; - gchar *module_path, **mimetypes; - gsize n_mimetypes, i; - RuleInfo rule = { 0 }; - - module_path = g_key_file_get_string (key_file, "ExtractorRule", "ModulePath", &local_error); - - if (local_error) { - if (!g_error_matches (local_error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_KEY_NOT_FOUND)) { - g_propagate_error (error, local_error); - return FALSE; - } else { - /* Ignore */ - g_clear_error (&local_error); - } - } - - if (module_path && - !G_IS_DIR_SEPARATOR (module_path[0])) { - gchar *tmp; - const gchar *extractors_dir; - - extractors_dir = g_getenv ("TRACKER_EXTRACTORS_DIR"); - if (G_LIKELY (extractors_dir == NULL)) { - extractors_dir = TRACKER_EXTRACTORS_DIR; - } else { - g_message ("Extractor rules directory is '%s' (set in env)", extractors_dir); - } - - tmp = g_build_filename (extractors_dir, module_path, NULL); - g_free (module_path); - module_path = tmp; - } - - mimetypes = g_key_file_get_string_list (key_file, "ExtractorRule", "MimeTypes", &n_mimetypes, &local_error); - - if (!mimetypes) { - g_free (module_path); - - if (local_error) { - g_propagate_error (error, local_error); - } - - return FALSE; - } - - rule.fallback_rdf_types = g_key_file_get_string_list (key_file, "ExtractorRule", "FallbackRdfTypes", NULL, NULL); - - /* Construct the rule */ - rule.module_path = g_intern_string (module_path); - - for (i = 0; i < n_mimetypes; i++) { - GPatternSpec *pattern; - - pattern = g_pattern_spec_new (mimetypes[i]); - rule.patterns = g_list_prepend (rule.patterns, pattern); - } - - if (G_UNLIKELY (!rules)) { - rules = g_array_new (FALSE, TRUE, sizeof (RuleInfo)); - } - - g_array_append_val (rules, rule); - g_strfreev (mimetypes); - g_free (module_path); - - return TRUE; -} - -gboolean -tracker_extract_module_manager_init (void) -{ - const gchar *extractors_dir, *name; - GList *files = NULL, *l; - GError *error = NULL; - GDir *dir; - - if (initialized) { - return TRUE; - } - - if (!g_module_supported ()) { - g_error ("Modules are not supported for this platform"); - return FALSE; - } - - extractors_dir = g_getenv ("TRACKER_EXTRACTOR_RULES_DIR"); - if (G_LIKELY (extractors_dir == NULL)) { - extractors_dir = TRACKER_EXTRACTOR_RULES_DIR; - } else { - g_message ("Extractor rules directory is '%s' (set in env)", extractors_dir); - } - - dir = g_dir_open (extractors_dir, 0, &error); - - if (!dir) { - g_error ("Error opening extractor rules directory: %s", error->message); - g_error_free (error); - return FALSE; - } - - while ((name = g_dir_read_name (dir)) != NULL) { - files = g_list_insert_sorted (files, (gpointer) name, (GCompareFunc) g_strcmp0); - } - - g_message ("Loading extractor rules... (%s)", extractors_dir); - - for (l = files; l; l = l->next) { - GKeyFile *key_file; - const gchar *name; - gchar *path; - - name = l->data; - - if (!g_str_has_suffix (l->data, ".rule")) { - g_message (" Skipping file '%s', no '.rule' suffix", name); - continue; - } - - path = g_build_filename (extractors_dir, name, NULL); - key_file = g_key_file_new (); - - if (!g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &error) || - !load_extractor_rule (key_file, &error)) { - g_warning (" Could not load extractor rule file '%s': %s", name, error->message); - g_clear_error (&error); - } else { - g_debug (" Loaded rule '%s'", name); - } - - g_key_file_free (key_file); - g_free (path); - } - - g_message ("Extractor rules loaded"); - g_list_free (files); - g_dir_close (dir); - - /* Initialize miscellaneous data */ - mimetype_map = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, - NULL); - initialized = TRUE; - - return TRUE; -} - -static GList * -lookup_rules (const gchar *mimetype) -{ - GList *mimetype_rules = NULL; - RuleInfo *info; - gchar *reversed; - gint len, i; - - if (!rules) { - return NULL; - } - - if (mimetype_map) { - mimetype_rules = g_hash_table_lookup (mimetype_map, mimetype); - - if (mimetype_rules) { - return mimetype_rules; - } - } - - reversed = g_strdup (mimetype); - g_strreverse (reversed); - len = strlen (mimetype); - - /* Apply the rules! */ - for (i = 0; i < rules->len; i++) { - GList *l; - - info = &g_array_index (rules, RuleInfo, i); - - for (l = info->patterns; l; l = l->next) { - if (g_pattern_match (l->data, len, mimetype, reversed)) { - /* Match, store for future queries and return */ - mimetype_rules = g_list_prepend (mimetype_rules, info); - } - } - } - - if (mimetype_rules) { - mimetype_rules = g_list_reverse (mimetype_rules); - g_hash_table_insert (mimetype_map, g_strdup (mimetype), mimetype_rules); - } - - g_free (reversed); - - return mimetype_rules; -} - -GStrv -tracker_extract_module_manager_get_fallback_rdf_types (const gchar *mimetype) -{ - GList *l, *list; - GHashTable *rdf_types; - gchar **types, *type; - GHashTableIter iter; - gint i; - - if (!initialized && - !tracker_extract_module_manager_init ()) { - return NULL; - } - - list = lookup_rules (mimetype); - rdf_types = g_hash_table_new (g_str_hash, g_str_equal); - - for (l = list; l; l = l->next) { - RuleInfo *r_info = l->data; - - if (r_info->fallback_rdf_types == NULL) - continue; - - for (i = 0; r_info->fallback_rdf_types[i]; i++) { - g_debug ("Adding RDF type: %s, for module: %s", - r_info->fallback_rdf_types[i], - r_info->module_path); - g_hash_table_insert (rdf_types, - r_info->fallback_rdf_types[i], - r_info->fallback_rdf_types[i]); - } - - /* We only want the first RDF types matching */ - break; - } - - g_hash_table_iter_init (&iter, rdf_types); - types = g_new0 (gchar*, g_hash_table_size (rdf_types) + 1); - i = 0; - - while (g_hash_table_iter_next (&iter, (gpointer*) &type, NULL)) { - types[i] = g_strdup (type); - i++; - } - - g_hash_table_unref (rdf_types); - - return types; -} - -static ModuleInfo * -load_module (RuleInfo *info) -{ - ModuleInfo *module_info = NULL; - - if (!info->module_path) { - return &dummy_module; - } - - if (modules) { - module_info = g_hash_table_lookup (modules, info->module_path); - } - - if (!module_info) { - GModule *module; - GError *init_error = NULL; - - /* Load the module */ - module = g_module_open (info->module_path, G_MODULE_BIND_LOCAL); - - if (!module) { - g_warning ("Could not load module '%s': %s", - info->module_path, - g_module_error ()); - return NULL; - } - - g_module_make_resident (module); - - module_info = g_slice_new0 (ModuleInfo); - module_info->module = module; - - if (!g_module_symbol (module, EXTRACTOR_FUNCTION, (gpointer *) &module_info->extract_func)) { - g_warning ("Could not load module '%s': Function %s() was not found, is it exported?", - g_module_name (module), EXTRACTOR_FUNCTION); - g_slice_free (ModuleInfo, module_info); - return NULL; - } - - g_module_symbol (module, INIT_FUNCTION, (gpointer *) &module_info->init_func); - g_module_symbol (module, SHUTDOWN_FUNCTION, (gpointer *) &module_info->shutdown_func); - - if (module_info->init_func && - !(module_info->init_func) (&init_error)) { - g_critical ("Could not initialize module %s: %s", - g_module_name (module_info->module), - (init_error) ? init_error->message : "No error given"); - - g_clear_error (&init_error); - g_slice_free (ModuleInfo, module_info); - return NULL; - } - - /* Add it to the cache */ - if (G_UNLIKELY (!modules)) { - /* Key is an intern string, so - * pointer comparison suffices - */ - modules = g_hash_table_new (NULL, NULL); - } - - g_hash_table_insert (modules, (gpointer) info->module_path, module_info); - } - - return module_info; -} - -static gboolean -initialize_first_module (TrackerMimetypeInfo *info) -{ - ModuleInfo *module_info = NULL; - - /* Actually iterates through the list loaded + initialized module */ - while (info->cur && !module_info) { - module_info = load_module (info->cur->data); - - if (!module_info) { - info->cur = info->cur->next; - } - } - - info->cur_module_info = module_info; - return (info->cur_module_info != NULL); -} - -/** - * tracker_extract_module_manager_get_mimetype_handlers: - * @mimetype: a mimetype string - * - * Returns a #TrackerMimetypeInfo struct containing information about - * the modules that handle @mimetype, or %NULL if no modules handle - * @mimetype. - * - * The modules are ordered from most to least specific, and the - * returned #TrackerMimetypeInfo already points to the first - * module. - * - * Returns: (transfer full): (free-function: tracker_mimetype_info_free): (allow-none): - * A #TrackerMimetypeInfo holding the information about the different - * modules handling @mimetype, or %NULL if no modules handle @mimetype. - * - * Since: 0.12 - **/ -TrackerMimetypeInfo * -tracker_extract_module_manager_get_mimetype_handlers (const gchar *mimetype) -{ - TrackerMimetypeInfo *info; - GList *mimetype_rules; - - g_return_val_if_fail (mimetype != NULL, NULL); - - mimetype_rules = lookup_rules (mimetype); - - if (!mimetype_rules) { - return NULL; - } - - info = g_slice_new0 (TrackerMimetypeInfo); - info->rules = mimetype_rules; - info->cur = info->rules; - - if (!initialize_first_module (info)) { - tracker_mimetype_info_free (info); - info = NULL; - } - - return info; -} - -/** - * tracker_mimetype_info_get_module: - * @info: a #TrackerMimetypeInfo - * @extract_func: (out): (allow-none): return value for the extraction function - * - * Returns the #GModule that @info is currently pointing to, if @extract_func is - * not %NULL, it will be filled in with the pointer to the metadata extraction - * function. - * - * Returns: The %GModule currently pointed to by @info. - * - * Since: 0.12 - **/ -GModule * -tracker_mimetype_info_get_module (TrackerMimetypeInfo *info, - TrackerExtractMetadataFunc *extract_func) -{ - g_return_val_if_fail (info != NULL, NULL); - - if (!info->cur_module_info) { - return NULL; - } - - if (extract_func) { - *extract_func = info->cur_module_info->extract_func; - } - - return info->cur_module_info->module; -} - -/** - * tracker_mimetype_info_iter_next: - * @info: a #TrackerMimetypeInfo - * - * Iterates to the next module handling the mimetype. - * - * Returns: %TRUE if there is a next module. - * - * Since: 0.12 - **/ -gboolean -tracker_mimetype_info_iter_next (TrackerMimetypeInfo *info) -{ - g_return_val_if_fail (info != NULL, FALSE); - - if (info->cur->next) { - info->cur = info->cur->next; - return initialize_first_module (info); - } - - return FALSE; -} - -void -tracker_mimetype_info_free (TrackerMimetypeInfo *info) -{ - g_return_if_fail (info != NULL); - - g_slice_free (TrackerMimetypeInfo, info); -} - -void -tracker_module_manager_load_modules (void) -{ - RuleInfo *rule_info; - guint i; - - g_return_if_fail (initialized == TRUE); - - for (i = 0; i < rules->len; i++) { - rule_info = &g_array_index (rules, RuleInfo, i); - load_module (rule_info); - } -} diff --git a/src/libtracker-extract/tracker-module-manager.h b/src/libtracker-extract/tracker-module-manager.h deleted file mode 100644 index 19305ffb3..000000000 --- a/src/libtracker-extract/tracker-module-manager.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2011, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_EXTRACT_MODULE_MANAGER_H__ -#define __TRACKER_EXTRACT_MODULE_MANAGER_H__ - -#if !defined (__LIBTRACKER_EXTRACT_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "only <libtracker-extract/tracker-extract.h> must be included directly." -#endif - -#include <glib.h> -#include <gmodule.h> - -#include <libtracker-sparql/tracker-sparql.h> -#include "tracker-extract-info.h" - -G_BEGIN_DECLS - -typedef struct _TrackerMimetypeInfo TrackerMimetypeInfo; - -typedef gboolean (* TrackerExtractInitFunc) (GError **error); -typedef void (* TrackerExtractShutdownFunc) (void); - -typedef gboolean (* TrackerExtractMetadataFunc) (TrackerExtractInfo *info); - - -gboolean tracker_extract_module_manager_init (void) G_GNUC_CONST; - -TrackerMimetypeInfo * tracker_extract_module_manager_get_mimetype_handlers (const gchar *mimetype); -GStrv tracker_extract_module_manager_get_fallback_rdf_types (const gchar *mimetype); - -GModule * tracker_mimetype_info_get_module (TrackerMimetypeInfo *info, - TrackerExtractMetadataFunc *extract_func); -gboolean tracker_mimetype_info_iter_next (TrackerMimetypeInfo *info); -void tracker_mimetype_info_free (TrackerMimetypeInfo *info); - -void tracker_module_manager_load_modules (void); - -G_END_DECLS - -#endif /* __TRACKER_EXTRACT_MODULE_MANAGER_H__ */ diff --git a/src/libtracker-extract/tracker-resource-helpers.c b/src/libtracker-extract/tracker-resource-helpers.c deleted file mode 100644 index 485cde58d..000000000 --- a/src/libtracker-extract/tracker-resource-helpers.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (C) 2016, Sam Thursfield <sam@afuera.me.uk> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "tracker-resource-helpers.h" -#include "tracker-guarantee.h" - -/** - * SECTION:tracker-resource-helpers - * @title: Resource Helpers - * @short_description: Helpers for describing certain common kinds of resource. - * @stability: Stable - * @include: libtracker-extract/tracker-extract.h - * - * Some common patterns for resources used in Tracker extractors have helper - * functions defined in this module. - */ - -/** - * tracker_extract_new_music_artist: - * @name: the name of the artist - * - * Create a new nmm:Artist resource. The URI will be set based on the URI, so - * there will only be one resource representing the artist in the Tracker store. - * - * Returns: a newly allocated #TrackerResource instance, of type nmm:Artist. - * - * Since: 1.10 - */ -TrackerResource * -tracker_extract_new_artist (const char *name) -{ - TrackerResource *artist; - gchar *uri; - - g_return_val_if_fail (name != NULL, NULL); - - uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", name); - - artist = tracker_resource_new (uri); - - tracker_resource_set_uri (artist, "rdf:type", "nmm:Artist"); - tracker_resource_set_string (artist, "nmm:artistName", name); - - g_free (uri); - - return artist; -} - -/** - * tracker_extract_new_contact: - * @fullname: the full name of the contact - * - * Create a new nco:Contact resource. The URI is based on @fullname, so only - * one instance will exist in the Tracker store. - * - * This is used for describing people or organisations, and can be used with - * many fields including nco:artist, nco:creator, nco:publisher, and - * nco:representative. - * - * Returns: a newly allocated #TrackerResource instance, of type nco:Contact - * - * Since: 1.10 - */ -TrackerResource * -tracker_extract_new_contact (const char *fullname) -{ - TrackerResource *publisher; - gchar *uri; - - g_return_val_if_fail (fullname != NULL, NULL); - - uri = tracker_sparql_escape_uri_printf ("urn:contact:%s", fullname); - - publisher = tracker_resource_new (uri); - - tracker_resource_set_uri (publisher, "rdf:type", "nco:Contact"); - tracker_guarantee_resource_utf8_string (publisher, "nco:fullname", fullname); - - g_free (uri); - - return publisher; -} - -/** - * tracker_extract_new_equipment: - * @make: (allow none): the manufacturer of the equipment, or %NULL - * @model: (allow none): the model name of the equipment, or %NULL - * - * Create a new nfo:Equipment resource. The URI is based on @make and @model, - * so only one instance will exist in the Tracker store. At least one of @make - * and @model must be non-%NULL. - * - * This is useful for describing equipment used to create something, for - * example the camera that was used to take a photograph. - * - * Returns: a newly allocated #TrackerResource instance, of type nfo:Equipment - * - * Since: 1.10 - */ -TrackerResource * -tracker_extract_new_equipment (const char *make, - const char *model) -{ - TrackerResource *equipment; - gchar *equip_uri; - - g_return_val_if_fail (make != NULL || model != NULL, NULL); - - equip_uri = tracker_sparql_escape_uri_printf ("urn:equipment:%s:%s:", make ? make : "", model ? model : ""); - - equipment = tracker_resource_new (equip_uri); - tracker_resource_set_uri (equipment, "rdf:type", "nfo:Equipment"); - - if (make) { - tracker_resource_set_string (equipment, "nfo:manufacturer", make); - } - - if (model) { - tracker_resource_set_string (equipment, "nfo:model", model); - } - - g_free (equip_uri); - - return equipment; -} - -/** - * tracker_extract_new_location: - * @street_address: (allow none): main part of postal address, or %NULL - * @state: (allow none): regional part of postal address, or %NULL - * @city: (allow none): locality part of postal address, or %NULL - * @country: (allow none): country of postal address, or %NULL - * @gps_altitude: (allow none): altitude (following WGS 84 reference) as a string, or %NULL - * @gps_latitude: (allow none): latitude as a string, or %NULL - * @gps_longitude: (allow none): longitude as a string, or %NULL - * - * Create a new slo:GeoLocation resource, with the given postal address and/or - * GPS coordinates. - * - * No validation is done here -- it's up to you to ensure the postal address - * and GPS coordinates describe the same thing. - * - * Returns: a newly allocated #TrackerResource instance, of type slo:GeoLocation - * - * Since: 1.10 - */ -TrackerResource * -tracker_extract_new_location (const char *street_address, - const char *state, - const char *city, - const char *country, - const char *gps_altitude, - const char *gps_latitude, - const char *gps_longitude) -{ - TrackerResource *location; - - g_return_val_if_fail (street_address != NULL || state != NULL || city != NULL || - country != NULL || gps_altitude != NULL || - gps_latitude != NULL || gps_longitude != NULL, NULL); - - location = tracker_resource_new (NULL); - tracker_resource_set_uri (location, "rdf:type", "slo:GeoLocation"); - - if (street_address || state || country || city) { - TrackerResource *address; - gchar *addruri; - - addruri = tracker_sparql_get_uuid_urn (); - address = tracker_resource_new (addruri); - - tracker_resource_set_string (address, "rdf:type", "nco:PostalAddress"); - - g_free (addruri); - - if (address) { - tracker_resource_set_string (address, "nco:streetAddress", street_address); - } - - if (state) { - tracker_resource_set_string (address, "nco:region", state); - } - - if (city) { - tracker_resource_set_string (address, "nco:locality", city); - } - - if (country) { - tracker_resource_set_string (address, "nco:country", country); - } - - tracker_resource_set_relation (location, "slo:postalAddress", address); - g_object_unref (address); - } - - if (gps_altitude) { - tracker_resource_set_string (location, "slo:altitude", gps_altitude); - } - - if (gps_latitude) { - tracker_resource_set_string (location, "slo:latitude", gps_latitude); - } - - if (gps_longitude) { - tracker_resource_set_string (location, "slo:longitude", gps_longitude); - } - - return location; -} - -/** - * tracker_extract_new_music_album_disc: - * @album_title: title of the album - * @album_artist: (allow none): a #TrackerResource for the album artist, or %NULL - * @disc_number: disc number of this disc (the first / only disc in a set should be 1, not 0) - * @date: (allow none):The release date, or %NULL - * - * Create new nmm:MusicAlbumDisc and nmm:MusicAlbum resources. The resources are - * given fixed URIs based on @album_title and @disc_number, so they will be - * merged with existing entries when serialized to SPARQL and sent to the - * Tracker store. - * - * You can get the album resource from the disc resource by calling: - * - * tracker_resource_get_first_relation (album_disc, "nmm:albumDiscAlbum"); - * - * Returns: a newly allocated #TrackerResource instance, of type nmm:MusicAlbumDisc - * - * Since: 1.10 - */ -TrackerResource * -tracker_extract_new_music_album_disc (const char *album_title, - TrackerResource *album_artist, - int disc_number, - const char *date) -{ - GString *album_uri, *disc_uri; - const gchar *album_artist_name = NULL; - gchar *tmp_album_uri, *tmp_disc_uri; - - TrackerResource *album, *album_disc; - - g_return_val_if_fail (album_title != NULL, NULL); - - if (album_artist) - album_artist_name = tracker_resource_get_first_string (album_artist, - "nmm:artistName"); - - album_uri = g_string_new ("urn:album:"); - - g_string_append (album_uri, album_title); - - if (album_artist_name) - g_string_append_printf (album_uri, ":%s", album_artist_name); - - if (date) - g_string_append_printf (album_uri, ":%s", date); - - tmp_album_uri = tracker_sparql_escape_uri (album_uri->str); - album = tracker_resource_new (tmp_album_uri); - - tracker_resource_set_uri (album, "rdf:type", "nmm:MusicAlbum"); - tracker_resource_set_string (album, "nie:title", album_title); - - if (album_artist) - tracker_resource_add_relation (album, "nmm:albumArtist", album_artist); - - disc_uri = g_string_new ("urn:album-disc:"); - - g_string_append (disc_uri, album_title); - - if (album_artist_name) - g_string_append_printf (disc_uri, ":%s", album_artist_name); - - if (date) - g_string_append_printf (disc_uri, ":%s", date); - - g_string_append_printf (disc_uri, ":Disc%d", disc_number); - - tmp_disc_uri = tracker_sparql_escape_uri (disc_uri->str); - album_disc = tracker_resource_new (tmp_disc_uri); - - tracker_resource_set_uri (album_disc, "rdf:type", "nmm:MusicAlbumDisc"); - tracker_resource_set_int (album_disc, "nmm:setNumber", disc_number > 0 ? disc_number : 1); - tracker_resource_add_relation (album_disc, "nmm:albumDiscAlbum", album); - - g_free (tmp_album_uri); - g_free (tmp_disc_uri); - g_string_free (album_uri, TRUE); - g_string_free (disc_uri, TRUE); - - g_object_unref (album); - - return album_disc; -} - -/** - * tracker_extract_new_tag: - * @label: the label of the tag - * - * Create a new nao:Tag resource. The URI will be set based on the tag label, - * so there will only be one resource representing the tag in the Tracker store. - * - * Returns: a newly allocated #TrackerResource instance, of type nao:Tag. - * - * Since: 1.10 - */ -TrackerResource * -tracker_extract_new_tag (const char *label) -{ - TrackerResource *tag; - char *uri; - - uri = tracker_sparql_escape_uri_printf ("urn:tag:%s", label); - tag = tracker_resource_new (uri); - - tracker_resource_set_uri (tag, "rdf:type", "nao:Tag"); - tracker_guarantee_resource_utf8_string (tag, "nao:prefLabel", label); - - g_free (uri); - return tag; -} diff --git a/src/libtracker-extract/tracker-resource-helpers.h b/src/libtracker-extract/tracker-resource-helpers.h deleted file mode 100644 index dc5b0dc33..000000000 --- a/src/libtracker-extract/tracker-resource-helpers.h +++ /dev/null @@ -1,41 +0,0 @@ - -/* - * Copyright (C) 2016, Sam Thursfield <sam@afuera.me.uk> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __LIBTRACKER_EXTRACT_RESOURCE_HELPERS_H__ -#define __LIBTRACKER_EXTRACT_RESOURCE_HELPERS_H__ - -#if !defined (__LIBTRACKER_EXTRACT_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "only <libtracker-extract/tracker-extract.h> must be included directly." -#endif - -#include <libtracker-sparql/tracker-sparql.h> - -G_BEGIN_DECLS - -TrackerResource *tracker_extract_new_artist (const char *name); -TrackerResource *tracker_extract_new_contact (const char *fullname); -TrackerResource *tracker_extract_new_equipment (const char *make, const char *model); -TrackerResource *tracker_extract_new_location (const char *address, const char *state, const char *city, const char *country, const char *gps_altitude, const char *gps_latitude, const char *gps_longitude); -TrackerResource *tracker_extract_new_music_album_disc (const char *album_title, TrackerResource *album_artist, int disc_number, const char *date); -TrackerResource *tracker_extract_new_tag (const char *label); - -G_END_DECLS - -#endif /* __LIBTRACKER_EXTRACT_RESOURCE_HELPERS_H__ */ diff --git a/src/libtracker-extract/tracker-utils.c b/src/libtracker-extract/tracker-utils.c deleted file mode 100644 index 500234c21..000000000 --- a/src/libtracker-extract/tracker-utils.c +++ /dev/null @@ -1,979 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#define _XOPEN_SOURCE -#define _XOPEN_SOURCE_EXTENDED 1 /* strptime is XPG4v2 */ - -#include <time.h> -#include <string.h> -#include <stdio.h> - -#include <libtracker-common/tracker-utils.h> -#include <libtracker-common/tracker-date-time.h> - -#include "tracker-utils.h" - -#ifndef HAVE_GETLINE - -#include <stddef.h> -#include <stdlib.h> -#include <limits.h> -#include <errno.h> - -#undef getdelim -#undef getline - -#define GROW_BY 80 - -#endif /* HAVE_GETLINE */ - -#define DATE_FORMAT_ISO8601 "%Y-%m-%dT%H:%M:%S%z" - -/** - * SECTION:tracker-utils - * @title: Data utilities - * @short_description: Functions for coalescing, merging, date - * handling and normalizing - * @stability: Stable - * @include: libtracker-extract/tracker-extract.h - * - * This API is provided to facilitate common more general functions - * which extractors may find useful. These functions are also used by - * the in-house extractors quite frequently. - **/ - -static const char *months[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" -}; - -static const char imonths[] = { - '1', '2', '3', '4', '5', - '6', '7', '8', '9', '0', '1', '2' -}; - - -/** - * tracker_coalesce_strip: - * @n_values: the number of @... supplied - * @...: the string pointers to coalesce - * - * This function iterates through a series of string pointers passed - * using @... and returns the first which is not %NULL, not empty - * (i.e. "") and not comprised of one or more spaces (i.e. " "). - * - * The returned value is stripped using g_strstrip(). It is MOST - * important NOT to pass constant string pointers to this function! - * - * Returns: the first string pointer from those provided which - * matches, otherwise %NULL. - * - * Since: 0.10 - **/ -const gchar * -tracker_coalesce_strip (gint n_values, - ...) -{ - va_list args; - gint i; - const gchar *result = NULL; - - va_start (args, n_values); - - for (i = 0; i < n_values; i++) { - gchar *value; - - value = va_arg (args, gchar *); - if (!result && !tracker_is_blank_string (value)) { - result = (const gchar *) g_strstrip (value); - break; - } - } - - va_end (args); - - return result; -} - -// LCOV_EXCL_START - -/** - * tracker_coalesce: - * @n_values: the number of @Varargs supplied - * @...: the string pointers to coalesce - * - * This function iterates through a series of string pointers passed - * using @... and returns the first which is not %NULL, not empty - * (i.e. "") and not comprised of one or more spaces (i.e. " "). - * - * The returned value is stripped using g_strstrip(). All other values - * supplied are freed. It is MOST important NOT to pass constant - * string pointers to this function! - * - * Returns: the first string pointer from those provided which - * matches, otherwise %NULL. - * - * Since: 0.8 - * - * Deprecated: 0.10: Use tracker_coalesce_strip() instead. - * - **/ -gchar * -tracker_coalesce (gint n_values, - ...) -{ - va_list args; - gint i; - gchar *result = NULL; - - va_start (args, n_values); - - for (i = 0; i < n_values; i++) { - gchar *value; - - value = va_arg (args, gchar *); - if (!result && !tracker_is_blank_string (value)) { - result = g_strstrip (value); - } else { - g_free (value); - } - } - - va_end (args); - - return result; -} -// LCOV_EXCL_STOP - -/** - * tracker_merge_const: - * @delimiter: the delimiter to use when merging - * @n_values: the number of @... supplied - * @...: the string pointers to merge - * - * This function iterates through a series of string pointers passed - * using @... and returns a newly allocated string of the merged - * strings. - * - * The @delimiter can be %NULL. If specified, it will be used in - * between each merged string in the result. - * - * Returns: a newly-allocated string holding the result which should - * be freed with g_free() when finished with, otherwise %NULL. - * - * Since: 0.10 - **/ -gchar * -tracker_merge_const (const gchar *delimiter, - gint n_values, - ...) -{ - va_list args; - gint i; - GString *str = NULL; - - va_start (args, n_values); - - for (i = 0; i < n_values; i++) { - gchar *value; - - value = va_arg (args, gchar *); - if (value) { - if (!str) { - str = g_string_new (value); - } else { - if (delimiter) { - g_string_append (str, delimiter); - } - g_string_append (str, value); - } - } - } - - va_end (args); - - if (!str) { - return NULL; - } - - return g_string_free (str, FALSE); -} - -// LCOV_EXCL_START - -/** - * tracker_merge: - * @delimiter: the delimiter to use when merging - * @n_values: the number of @... supplied - * @...: the string pointers to merge - * - * This function iterates through a series of string pointers passed - * using @... and returns a newly allocated string of the merged - * strings. All passed strings are freed (don't pass const values)/ - * - * The @delimiter can be %NULL. If specified, it will be used in - * between each merged string in the result. - * - * Returns: a newly-allocated string holding the result which should - * be freed with g_free() when finished with, otherwise %NULL. - * - * Since: 0.8 - * - * Deprecated: 0.10: Use tracker_merge_const() instead. - **/ -gchar * -tracker_merge (const gchar *delimiter, - gint n_values, - ...) -{ - va_list args; - gint i; - GString *str = NULL; - - va_start (args, n_values); - - for (i = 0; i < n_values; i++) { - gchar *value; - - value = va_arg (args, gchar *); - if (value) { - if (!str) { - str = g_string_new (value); - } else { - if (delimiter) { - g_string_append (str, delimiter); - } - g_string_append (str, value); - } - g_free (value); - } - } - - va_end (args); - - if (!str) { - return NULL; - } - - return g_string_free (str, FALSE); -} - -/** - * tracker_text_normalize: - * @text: the text to normalize - * @max_words: the maximum words of @text to normalize - * @n_words: the number of words actually normalized - * - * This function iterates through @text checking for UTF-8 validity - * using g_utf8_get_char_validated(). For each character found, the - * %GUnicodeType is checked to make sure it is one fo the following - * values: - * <itemizedlist> - * <listitem><para>%G_UNICODE_LOWERCASE_LETTER</para></listitem> - * <listitem><para>%G_UNICODE_MODIFIER_LETTER</para></listitem> - * <listitem><para>%G_UNICODE_OTHER_LETTER</para></listitem> - * <listitem><para>%G_UNICODE_TITLECASE_LETTER</para></listitem> - * <listitem><para>%G_UNICODE_UPPERCASE_LETTER</para></listitem> - * </itemizedlist> - * - * All other symbols, punctuation, marks, numbers and separators are - * stripped. A regular space (i.e. " ") is used to separate the words - * in the returned string. - * - * The @n_words can be %NULL. If specified, it will be populated with - * the number of words that were normalized in the result. - * - * Returns: a newly-allocated string holding the result which should - * be freed with g_free() when finished with, otherwise %NULL. - * - * Since: 0.8 - * - * Deprecated: 0.10: Use tracker_text_validate_utf8() instead. - **/ -gchar * -tracker_text_normalize (const gchar *text, - guint max_words, - guint *n_words) -{ - GString *string; - gboolean in_break = TRUE; - gunichar ch; - gint words = 0; - - string = g_string_new (NULL); - - while ((ch = g_utf8_get_char_validated (text, -1)) > 0) { - GUnicodeType type; - - type = g_unichar_type (ch); - - if (type == G_UNICODE_LOWERCASE_LETTER || - type == G_UNICODE_MODIFIER_LETTER || - type == G_UNICODE_OTHER_LETTER || - type == G_UNICODE_TITLECASE_LETTER || - type == G_UNICODE_UPPERCASE_LETTER) { - /* Append regular chars */ - g_string_append_unichar (string, ch); - in_break = FALSE; - } else if (!in_break) { - /* Non-regular char found, treat as word break */ - g_string_append_c (string, ' '); - in_break = TRUE; - words++; - - if (words > max_words) { - break; - } - } - - text = g_utf8_find_next_char (text, NULL); - } - - if (n_words) { - if (!in_break) { - /* Count the last word */ - words += 1; - } - *n_words = words; - } - - return g_string_free (string, FALSE); -} - -// LCOV_EXCL_STOP - -/** - * tracker_text_validate_utf8: - * @text: the text to validate - * @text_len: length of @text, or -1 if NUL-terminated - * @str: the string where to place the validated UTF-8 characters, or %NULL if - * not needed. - * @valid_len: Output number of valid UTF-8 bytes found, or %NULL if not needed - * - * This function iterates through @text checking for UTF-8 validity - * using g_utf8_validate(), appends the first chunk of valid characters - * to @str, and gives the number of valid UTF-8 bytes in @valid_len. - * - * Returns: %TRUE if some bytes were found to be valid, %FALSE otherwise. - * - * Since: 0.10 - **/ -gboolean -tracker_text_validate_utf8 (const gchar *text, - gssize text_len, - GString **str, - gsize *valid_len) -{ - gsize len_to_validate; - - g_return_val_if_fail (text, FALSE); - - len_to_validate = text_len >= 0 ? text_len : strlen (text); - - if (len_to_validate > 0) { - const gchar *end = text; - - /* Validate string, getting the pointer to first non-valid character - * (if any) or to the end of the string. */ - g_utf8_validate (text, len_to_validate, &end); - if (end > text) { - /* If str output required... */ - if (str) { - /* Create string to output if not already as input */ - *str = (*str == NULL ? - g_string_new_len (text, end - text) : - g_string_append_len (*str, text, end - text)); - } - - /* If utf8 len output required... */ - if (valid_len) { - *valid_len = end - text; - } - - return TRUE; - } - } - - return FALSE; -} - -/** - * tracker_date_format_to_iso8601: - * @date_string: the date in a string pointer - * @format: the format of the @date_string - * - * This function uses strptime() to create a time tm structure using - * @date_string and @format. - * - * Returns: a newly-allocated string with the time represented in - * ISO8601 date format which should be freed with g_free() when - * finished with, otherwise %NULL. - * - * Since: 0.8 - **/ -gchar * -tracker_date_format_to_iso8601 (const gchar *date_string, - const gchar *format) -{ - gchar *result; - struct tm date_tm = { 0 }; - - g_return_val_if_fail (date_string != NULL, NULL); - g_return_val_if_fail (format != NULL, NULL); - - if (strptime (date_string, format, &date_tm) == 0) { - return NULL; - } - - /* If the input format string doesn't parse timezone information with - * either %z or %Z, strptime() won't set the tm_gmtoff member in the - * broken-down time, and the value during initialization (0) will be - * left. This effectively means that every broken-down time obtained - * with strptime() without parsing timezone information will be based - * on UTC, instead of being treated as localtime. In order to fix this - * and set the correct value for the offset w.r.t gmt, we can just - * use mktime() to fill in the daylight saving flag as well as the - * gmt offset value. */ - if (!strstr (format, "%z") && !strstr (format, "%Z")) { - /* tm_isdst not set by strptime(), we set -1 on it in order to ask - * mktime to 'normalize' its contents and fill in the gmt offset - * and daylight saving time information */ - date_tm.tm_isdst = -1; - - /* Note: no real problem if mktime() fails. In this case, tm_isdst - * will be -1, and therefore strftime() will not write the timezone - * information, which is equally right to represent localtime. */ - mktime (&date_tm); - } - - result = g_malloc (sizeof (char) * 25); - strftime (result, 25, DATE_FORMAT_ISO8601 , &date_tm); - return result; -} - -static gboolean -is_int (const gchar *str) -{ - gint i, len; - - if (!str || str[0] == '\0') { - return FALSE; - } - - len = strlen (str); - - for (i = 0; i < len; i++) { - if (!g_ascii_isdigit (str[i])) { - return FALSE; - } - } - - return TRUE ; -} - -static gint -parse_month (const gchar *month) -{ - gint i; - - for (i = 0; i < 12; i++) { - if (!strncmp (month, months[i], 3)) { - return i; - } - } - - return -1; -} - -/* Determine date format and convert to ISO 8601 format */ -/* FIXME We should handle all the fractions here (see ISO 8601), as well as YYYY:DDD etc */ - -/** - * tracker_date_guess: - * @date_string: the date in a string pointer - * - * This function uses a number of methods to try and guess the date - * held in @date_string. The @date_string must be at least 5 - * characters in length or longer for any guessing to be attempted. - * Some of the string formats guessed include: - * - * <itemizedlist> - * <listitem><para>"YYYY-MM-DD" (Simple format)</para></listitem> - * <listitem><para>"20050315113224-08'00'" (PDF format)</para></listitem> - * <listitem><para>"20050216111533Z" (PDF format)</para></listitem> - * <listitem><para>"Mon Feb 9 10:10:00 2004" (Microsoft Office format)</para></listitem> - * <listitem><para>"2005:04:29 14:56:54" (Exif format)</para></listitem> - * <listitem><para>"YYYY-MM-DDThh:mm:ss.ff+zz:zz</para></listitem> - * </itemizedlist> - * - * Returns: a newly-allocated string with the time represented in - * ISO8601 date format which should be freed with g_free() when - * finished with, otherwise %NULL. - * - * Since: 0.8 - **/ -gchar * -tracker_date_guess (const gchar *date_string) -{ - gchar buf[30]; - gint len; - GError *error = NULL; - - if (!date_string) { - return NULL; - } - - len = strlen (date_string); - - /* We cannot format a date without at least a four digit - * year. - */ - if (len < 4) { - return NULL; - } - - /* Check for year only dates (EG ID3 music tags might have - * Audio.ReleaseDate as 4 digit year) - */ - if (len == 4) { - if (is_int (date_string)) { - buf[0] = date_string[0]; - buf[1] = date_string[1]; - buf[2] = date_string[2]; - buf[3] = date_string[3]; - buf[4] = '-'; - buf[5] = '0'; - buf[6] = '1'; - buf[7] = '-'; - buf[8] = '0'; - buf[9] = '1'; - buf[10] = 'T'; - buf[11] = '0'; - buf[12] = '0'; - buf[13] = ':'; - buf[14] = '0'; - buf[15] = '0'; - buf[16] = ':'; - buf[17] = '0'; - buf[18] = '0'; - buf[19] = 'Z'; - buf[20] = '\0'; - - tracker_string_to_date (buf, NULL, &error); - - if (error != NULL) { - g_error_free (error); - return NULL; - } - - return g_strdup (buf); - } else { - return NULL; - } - } else if (len == 10) { - /* Check for date part only YYYY-MM-DD */ - buf[0] = date_string[0]; - buf[1] = date_string[1]; - buf[2] = date_string[2]; - buf[3] = date_string[3]; - buf[4] = '-'; - buf[5] = date_string[5]; - buf[6] = date_string[6]; - buf[7] = '-'; - buf[8] = date_string[8]; - buf[9] = date_string[9]; - buf[10] = 'T'; - buf[11] = '0'; - buf[12] = '0'; - buf[13] = ':'; - buf[14] = '0'; - buf[15] = '0'; - buf[16] = ':'; - buf[17] = '0'; - buf[18] = '0'; - buf[19] = '\0'; - - tracker_string_to_date (buf, NULL, &error); - - if (error != NULL) { - g_error_free (error); - return NULL; - } - - return g_strdup (buf); - } else if (len == 14) { - /* Check for pdf format EG 20050315113224-08'00' or - * 20050216111533Z - */ - buf[0] = date_string[0]; - buf[1] = date_string[1]; - buf[2] = date_string[2]; - buf[3] = date_string[3]; - buf[4] = '-'; - buf[5] = date_string[4]; - buf[6] = date_string[5]; - buf[7] = '-'; - buf[8] = date_string[6]; - buf[9] = date_string[7]; - buf[10] = 'T'; - buf[11] = date_string[8]; - buf[12] = date_string[9]; - buf[13] = ':'; - buf[14] = date_string[10]; - buf[15] = date_string[11]; - buf[16] = ':'; - buf[17] = date_string[12]; - buf[18] = date_string[13]; - buf[19] = '\0'; - - tracker_string_to_date (buf, NULL, &error); - - if (error != NULL) { - g_error_free (error); - return NULL; - } - - return g_strdup (buf); - } else if (len == 15 && date_string[14] == 'Z') { - buf[0] = date_string[0]; - buf[1] = date_string[1]; - buf[2] = date_string[2]; - buf[3] = date_string[3]; - buf[4] = '-'; - buf[5] = date_string[4]; - buf[6] = date_string[5]; - buf[7] = '-'; - buf[8] = date_string[6]; - buf[9] = date_string[7]; - buf[10] = 'T'; - buf[11] = date_string[8]; - buf[12] = date_string[9]; - buf[13] = ':'; - buf[14] = date_string[10]; - buf[15] = date_string[11]; - buf[16] = ':'; - buf[17] = date_string[12]; - buf[18] = date_string[13]; - buf[19] = 'Z'; - buf[20] = '\0'; - - tracker_string_to_date (buf, NULL, &error); - - if (error != NULL) { - g_error_free (error); - return NULL; - } - - return g_strdup (buf); - } else if (len == 21 && (date_string[14] == '-' || date_string[14] == '+' )) { - buf[0] = date_string[0]; - buf[1] = date_string[1]; - buf[2] = date_string[2]; - buf[3] = date_string[3]; - buf[4] = '-'; - buf[5] = date_string[4]; - buf[6] = date_string[5]; - buf[7] = '-'; - buf[8] = date_string[6]; - buf[9] = date_string[7]; - buf[10] = 'T'; - buf[11] = date_string[8]; - buf[12] = date_string[9]; - buf[13] = ':'; - buf[14] = date_string[10]; - buf[15] = date_string[11]; - buf[16] = ':'; - buf[17] = date_string[12]; - buf[18] = date_string[13]; - buf[19] = date_string[14]; - buf[20] = date_string[15]; - buf[21] = date_string[16]; - buf[22] = ':'; - buf[23] = date_string[18]; - buf[24] = date_string[19]; - buf[25] = '\0'; - - tracker_string_to_date (buf, NULL, &error); - - if (error != NULL) { - g_error_free (error); - return NULL; - } - - return g_strdup (buf); - } else if ((len == 24) && (date_string[3] == ' ')) { - /* Check for msoffice date format "Mon Feb 9 10:10:00 2004" */ - gint num_month; - gchar mon1; - gchar day1; - - num_month = parse_month (date_string + 4); - - if (num_month < 0) { - return NULL; - } - - mon1 = imonths[num_month]; - - if (date_string[8] == ' ') { - day1 = '0'; - } else { - day1 = date_string[8]; - } - - buf[0] = date_string[20]; - buf[1] = date_string[21]; - buf[2] = date_string[22]; - buf[3] = date_string[23]; - buf[4] = '-'; - - if (num_month < 10) { - buf[5] = '0'; - buf[6] = mon1; - } else { - buf[5] = '1'; - buf[6] = mon1; - } - - buf[7] = '-'; - buf[8] = day1; - buf[9] = date_string[9]; - buf[10] = 'T'; - buf[11] = date_string[11]; - buf[12] = date_string[12]; - buf[13] = ':'; - buf[14] = date_string[14]; - buf[15] = date_string[15]; - buf[16] = ':'; - buf[17] = date_string[17]; - buf[18] = date_string[18]; - buf[19] = '\0'; - - tracker_string_to_date (buf, NULL, &error); - - if (error != NULL) { - g_error_free (error); - return NULL; - } - - return g_strdup (buf); - } else if ((len == 19) && (date_string[4] == ':') && (date_string[7] == ':')) { - /* Check for Exif date format "2005:04:29 14:56:54" */ - buf[0] = date_string[0]; - buf[1] = date_string[1]; - buf[2] = date_string[2]; - buf[3] = date_string[3]; - buf[4] = '-'; - buf[5] = date_string[5]; - buf[6] = date_string[6]; - buf[7] = '-'; - buf[8] = date_string[8]; - buf[9] = date_string[9]; - buf[10] = 'T'; - buf[11] = date_string[11]; - buf[12] = date_string[12]; - buf[13] = ':'; - buf[14] = date_string[14]; - buf[15] = date_string[15]; - buf[16] = ':'; - buf[17] = date_string[17]; - buf[18] = date_string[18]; - buf[19] = '\0'; - - tracker_string_to_date (buf, NULL, &error); - - if (error != NULL) { - g_error_free (error); - return NULL; - } - - return g_strdup (buf); - } - - tracker_string_to_date (date_string, NULL, &error); - - if (error != NULL) { - g_error_free (error); - return NULL; - } - - return g_strdup (date_string); -} - -#ifndef HAVE_GETLINE - -static gint -my_igetdelim (gchar **linebuf, - gsize *linebufsz, - gint delimiter, - FILE *file) -{ - gint ch; - gint idx; - - if ((file == NULL || linebuf == NULL || *linebuf == NULL || *linebufsz == 0) && - !(*linebuf == NULL && *linebufsz == 0)) { - errno = EINVAL; - return -1; - } - - if (*linebuf == NULL && *linebufsz == 0) { - *linebuf = g_malloc (GROW_BY); - - if (!*linebuf) { - errno = ENOMEM; - return -1; - } - - *linebufsz += GROW_BY; - } - - idx = 0; - - while ((ch = fgetc (file)) != EOF) { - /* Grow the line buffer as necessary */ - while (idx > *linebufsz - 2) { - *linebuf = g_realloc (*linebuf, *linebufsz += GROW_BY); - - if (!*linebuf) { - errno = ENOMEM; - return -1; - } - } - (*linebuf)[idx++] = (gchar) ch; - - if ((gchar) ch == delimiter) { - break; - } - } - - if (idx != 0) { - (*linebuf)[idx] = 0; - } else if ( ch == EOF ) { - return -1; - } - - return idx; -} - -#endif /* HAVE_GETLINE */ - -/** - * tracker_getline: - * @lineptr: Buffer to write into - * @n: Max bytes of linebuf - * @stream: Filestream to read from - * - * Reads an entire line from stream, storing the address of the buffer - * containing the text into *lineptr. The buffer is null-terminated - * and includes the newline character, if one was found. - * - * Read GNU getline()'s manpage for more information - * - * Returns: the number of characters read, including the delimiter - * character, but not including the terminating %NULL byte. This value - * can be used to handle embedded %NULL bytes in the line read. Upon - * failure, -1 is returned. - * - * Since: 0.10 - **/ -gssize -tracker_getline (gchar **lineptr, - gsize *n, - FILE *stream) -{ -#ifndef HAVE_GETLINE - return my_igetdelim (lineptr, n, '\n', stream); -#else /* HAVE_GETLINE */ - return getline (lineptr, n, stream); -#endif /* HAVE_GETLINE */ -} - -/** - * tracker_keywords_parse: - * @store: Array where to store the keywords - * @keywords: Keywords line to parse - * - * Parses a keywords line into store, avoiding duplicates and stripping leading - * and trailing spaces from keywords. Allowed delimiters are , and ; - * - * Since: 0.10 - **/ -void -tracker_keywords_parse (GPtrArray *store, - const gchar *keywords) -{ - gchar *orig, *keywords_d; - char *saveptr, *p; - size_t len; - - keywords_d = orig = g_strdup (keywords); - p = keywords_d; - keywords_d = strchr (keywords_d, '"'); - - if (keywords_d) { - keywords_d++; - } else { - keywords_d = p; - } - - len = strlen (keywords_d); - if (len > 0 && keywords_d[len - 1] == '"') { - keywords_d[len - 1] = '\0'; - } - - for (p = strtok_r (keywords_d, ",;", &saveptr); p; - p = strtok_r (NULL, ",;", &saveptr)) { - guint i; - gboolean found = FALSE; - gchar *p_do = g_strdup (p); - gchar *p_dup = p_do; - guint len = strlen (p_dup); - - if (*p_dup == ' ') - p_dup++; - - if (p_dup[len-1] == ' ') - p_dup[len-1] = '\0'; - - /* ignore keywords containing invalid UTF-8 */ - if (!g_utf8_validate (p_dup, -1, NULL)) { - g_free (p_do); - continue; - } - - for (i = 0; i < store->len; i++) { - const gchar *earlier = g_ptr_array_index (store, i); - if (g_strcmp0 (earlier, p_dup) == 0) { - found = TRUE; - break; - } - } - - if (!found) { - g_ptr_array_add (store, g_strdup (p_dup)); - } - - g_free (p_do); - } - - g_free (orig); -} diff --git a/src/libtracker-extract/tracker-utils.h b/src/libtracker-extract/tracker-utils.h deleted file mode 100644 index 28d333771..000000000 --- a/src/libtracker-extract/tracker-utils.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include <stdio.h> - -#ifndef __LIBTRACKER_EXTRACT_UTILS_H__ -#define __LIBTRACKER_EXTRACT_UTILS_H__ - -#if !defined (__LIBTRACKER_EXTRACT_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "only <libtracker-extract/tracker-extract.h> must be included directly." -#endif - -G_BEGIN_DECLS - -#ifndef TRACKER_DISABLE_DEPRECATED -gchar* tracker_coalesce (gint n_values, - ...) G_GNUC_DEPRECATED; -gchar* tracker_merge (const gchar *delimiter, - gint n_values, - ...) G_GNUC_DEPRECATED; -gchar* tracker_text_normalize (const gchar *text, - guint max_words, - guint *n_words) G_GNUC_DEPRECATED; -#endif /* TRACKER_DISABLE_DEPRECATED */ - -gboolean tracker_text_validate_utf8 (const gchar *text, - gssize text_len, - GString **str, - gsize *valid_len); -gchar* tracker_date_guess (const gchar *date_string); -gchar* tracker_date_format_to_iso8601 (const gchar *date_string, - const gchar *format); -const gchar* tracker_coalesce_strip (gint n_values, - ...); -gchar* tracker_merge_const (const gchar *delimiter, - gint n_values, - ...); -gssize tracker_getline (gchar **lineptr, - gsize *n, - FILE *stream); -void tracker_keywords_parse (GPtrArray *store, - const gchar *keywords); - -G_END_DECLS - -#endif /* __LIBTRACKER_EXTRACT_UTILS_H__ */ diff --git a/src/libtracker-extract/tracker-xmp.c b/src/libtracker-extract/tracker-xmp.c deleted file mode 100644 index 911f3d7cf..000000000 --- a/src/libtracker-extract/tracker-xmp.c +++ /dev/null @@ -1,1165 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <locale.h> - -#include <libtracker-common/tracker-utils.h> - -#include "tracker-resource-helpers.h" -#include "tracker-xmp.h" -#include "tracker-utils.h" - -#ifdef HAVE_EXEMPI - -#define NS_XMP_REGIONS "http://www.metadataworkinggroup.com/schemas/regions/" -#define NS_ST_DIM "http://ns.adobe.com/xap/1.0/sType/Dimensions#" -#define NS_ST_AREA "http://ns.adobe.com/xmp/sType/Area#" - -#define REGION_LIST_REGEX "^mwg-rs:Regions/mwg-rs:RegionList\\[(\\d+)\\]" - -#include <exempi/xmp.h> -#include <exempi/xmpconsts.h> - -/** - * SECTION:tracker-xmp - * @title: XMP - * @short_description: Extensible Metadata Platform (XMP) - * @stability: Stable - * @include: libtracker-extract/tracker-extract.h - * - * The Adobe Extensible Metadata Platform (XMP) is a standard, created - * by Adobe Systems Inc., for processing and storing standardized and - * proprietary information relating to the contents of a file. - * - * XMP standardizes the definition, creation, and processing of - * extensible metadata. Serialized XMP can be embedded into a - * significant number of popular file formats, without breaking their - * readability by non-XMP-aware applications. Embedding metadata ("the - * truth is in the file") avoids many problems that occur when - * metadata is stored separately. XMP is used in PDF, photography and - * photo editing applications. - * - * This API is provided to remove code duplication between extractors - * using these standards. - **/ - -static void iterate (XmpPtr xmp, - XmpIteratorPtr iter, - const gchar *uri, - TrackerXmpData *data, - gboolean append); -static void iterate_simple (const gchar *uri, - TrackerXmpData *data, - const gchar *schema, - const gchar *path, - const gchar *value, - gboolean append); - -static const gchar * -fix_metering_mode (const gchar *mode) -{ - gint value; - value = atoi(mode); - - switch (value) { - case 0: - return "nmm:metering-mode-other"; - case 1: - return "nmm:metering-mode-average"; - case 2: - return "nmm:metering-mode-center-weighted-average"; - case 3: - return "nmm:metering-mode-spot"; - case 4: - return "nmm:metering-mode-multispot"; - case 5: - return "nmm:metering-mode-pattern"; - case 6: - return "nmm:metering-mode-partial"; - } - - return "nmm:metering-mode-other"; -} - -static const gchar * -fix_flash (const gchar *flash) -{ - static const gint fired_mask = 0x1; - gint value; - - value = atoi (flash); - - if (value & fired_mask) { - return "nmm:flash-on"; - } else { - return "nmm:flash-off"; - } -} - -static const gchar * -fix_white_balance (const gchar *wb) -{ - if (g_strcmp0 (wb, "1") == 0) { - return "nmm:white-balance-manual"; - } else { - return "nmm:white-balance-auto"; - } -} - -static gchar * -gps_coordinate_dup (const gchar *coordinates) -{ - static GRegex *reg = NULL; - GMatchInfo *info = NULL; - - if (!reg) { - reg = g_regex_new ("([0-9]+),([0-9]+.[0-9]+)([A-Z])", 0, 0, NULL); - } - - if (g_regex_match (reg, coordinates, 0, &info)) { - gchar *deg,*min,*ref; - gdouble r,d,m; - - deg = g_match_info_fetch (info, 1); - min = g_match_info_fetch (info, 2); - ref = g_match_info_fetch (info, 3); - - d = atof (deg); - m = atof (min); - - r = d + m/60; - - if ( (ref[0] == 'S') || (ref[0] == 'W')) { - r = r * -1; - } - - g_free (deg); - g_free (min); - g_free (ref); - g_match_info_free (info); - - return g_strdup_printf ("%f", r); - } else { - g_match_info_free (info); - return NULL; - } -} - -/* We have an array, now recursively iterate over it's children. Set - * 'append' to true so that all values of the array are added under - * one entry. - */ -static void -iterate_array (XmpPtr xmp, - const gchar *uri, - TrackerXmpData *data, - const gchar *schema, - const gchar *path) -{ - XmpIteratorPtr iter; - - iter = xmp_iterator_new (xmp, schema, path, XMP_ITER_JUSTCHILDREN); - iterate (xmp, iter, uri, data, TRUE); - xmp_iterator_free (iter); -} - -/* We have an array, now recursively iterate over it's children. Set - * 'append' to false so that only one item is used. - */ -static void -iterate_alt_text (XmpPtr xmp, - const gchar *uri, - TrackerXmpData *data, - const gchar *schema, - const gchar *path) -{ - XmpIteratorPtr iter; - - iter = xmp_iterator_new (xmp, schema, path, XMP_ITER_JUSTCHILDREN); - iterate (xmp, iter, uri, data, FALSE); - xmp_iterator_free (iter); -} - -static gchar * -div_str_dup (const gchar *value) -{ - gchar *ret; - gchar *ptr = strchr (value, '/'); - - if (ptr) { - gchar *cpy = g_strdup (value); - gint a, b; - - cpy [ptr - value] = '\0'; - a = atoi (cpy); - b = atoi (cpy + (ptr - value) + 1); - - if (b != 0) { - ret = g_strdup_printf ("%G", ((gdouble)((gdouble) a / (gdouble) b))); - } else { - ret = NULL; - } - - g_free (cpy); - } else { - ret = g_strdup (value); - } - - return ret; -} - -/* We have a simple element, but need to iterate over the qualifiers */ -static void -iterate_simple_qual (XmpPtr xmp, - const gchar *uri, - TrackerXmpData *data, - const gchar *schema, - const gchar *path, - const gchar *value, - gboolean append) -{ - XmpIteratorPtr iter; - XmpStringPtr the_path; - XmpStringPtr the_prop; - static gchar *locale = NULL; - gboolean ignore_element = FALSE; - - iter = xmp_iterator_new (xmp, schema, path, XMP_ITER_JUSTCHILDREN | XMP_ITER_JUSTLEAFNAME); - - the_path = xmp_string_new (); - the_prop = xmp_string_new (); - - if (G_UNLIKELY (!locale)) { - locale = g_strdup (setlocale (LC_ALL, NULL)); - - if (!locale) { - locale = g_strdup ("C"); - } else { - gchar *sep; - - sep = strchr (locale, '.'); - - if (sep) { - locale[sep - locale] = '\0'; - } - - sep = strchr (locale, '_'); - - if (sep) { - locale[sep - locale] = '-'; - } - } - } - - while (xmp_iterator_next (iter, NULL, the_path, the_prop, NULL)) { - const gchar *qual_path = xmp_string_cstr (the_path); - const gchar *qual_value = xmp_string_cstr (the_prop); - - if (g_ascii_strcasecmp (qual_path, "xml:lang") == 0) { - /* Is this a language we should ignore? */ - if (g_ascii_strcasecmp (qual_value, "x-default") != 0 && - g_ascii_strcasecmp (qual_value, "x-repair") != 0 && - g_ascii_strcasecmp (qual_value, locale) != 0) { - ignore_element = TRUE; - break; - } - } - } - - if (!ignore_element) { - iterate_simple (uri, data, schema, path, value, append); - } - - xmp_string_free (the_prop); - xmp_string_free (the_path); - - xmp_iterator_free (iter); -} - -static const gchar * -fix_orientation (const gchar *orientation) -{ - if (orientation && g_ascii_strcasecmp (orientation, "1") == 0) { - return "nfo:orientation-top"; - } else if (orientation && g_ascii_strcasecmp (orientation, "2") == 0) { - return "nfo:orientation-top-mirror"; - } else if (orientation && g_ascii_strcasecmp (orientation, "3") == 0) { - return "nfo:orientation-bottom"; - } else if (orientation && g_ascii_strcasecmp (orientation, "4") == 0) { - return "nfo:orientation-bottom-mirror"; - } else if (orientation && g_ascii_strcasecmp (orientation, "5") == 0) { - return "nfo:orientation-left-mirror"; - } else if (orientation && g_ascii_strcasecmp (orientation, "6") == 0) { - return "nfo:orientation-right"; - } else if (orientation && g_ascii_strcasecmp (orientation, "7") == 0) { - return "nfo:orientation-right-mirror"; - } else if (orientation && g_ascii_strcasecmp (orientation, "8") == 0) { - return "nfo:orientation-left"; - } - - return "nfo:orientation-top"; -} - -/* - * In a path like: mwg-rs:Regions/mwg-rs:RegionList[2]/mwg-rs:Area/stArea:x - * this function returns the "2" from RegionsList[2] - * Note: The first element from a list is 1 - */ -static gint -get_region_counter (const gchar *path) -{ - static GRegex *regex = NULL; - GMatchInfo *match_info = NULL; - gchar *match; - gint result; - - if (!regex) { - regex = g_regex_new (REGION_LIST_REGEX, 0, 0, NULL); - } - - if (!g_regex_match (regex, path, 0, &match_info)) { - g_match_info_free (match_info); - return -1; - } - - match = g_match_info_fetch (match_info, 1); - result = g_strtod (match, NULL); - - g_free (match); - g_match_info_free (match_info); - - return result; -} - - - -/* We have a simple element. Add any data we know about to the - * hash table. - */ -static void -iterate_simple (const gchar *uri, - TrackerXmpData *data, - const gchar *schema, - const gchar *path, - const gchar *value, - gboolean append) -{ - gchar *name; - const gchar *p; - gchar *propname; - - p = strchr (path, ':'); - if (!p) { - return; - } - - name = g_strdup (p + 1); - - /* For 'dc:subject[1]' the name will be 'subject'. - * This rule doesn't work for RegionLists - */ - p = strrchr (name, '['); - if (p) { - name[p - name] = '\0'; - } - - /* Exif basic scheme */ - if (g_ascii_strcasecmp (schema, NS_EXIF) == 0) { - if (!data->title2 && g_ascii_strcasecmp (name, "Title") == 0) { - data->title2 = g_strdup (value); - } else if (g_ascii_strcasecmp (name, "DateTimeOriginal") == 0 && !data->time_original) { - data->time_original = tracker_date_guess (value); - } else if (!data->artist && g_ascii_strcasecmp (name, "Artist") == 0) { - data->artist = g_strdup (value); - /* } else if (g_ascii_strcasecmp (name, "Software") == 0) { - tracker_statement_list_insert (metadata, uri, - "Image:Software", value);*/ - } else if (!data->make && g_ascii_strcasecmp (name, "Make") == 0) { - data->make = g_strdup (value); - } else if (!data->model && g_ascii_strcasecmp (name, "Model") == 0) { - data->model = g_strdup (value); - } else if (!data->flash && g_ascii_strcasecmp (name, "Flash") == 0) { - data->flash = g_strdup (fix_flash (value)); - } else if (!data->metering_mode && g_ascii_strcasecmp (name, "MeteringMode") == 0) { - data->metering_mode = g_strdup (fix_metering_mode (value)); - /* } else if (g_ascii_strcasecmp (name, "ExposureProgram") == 0) { - tracker_statement_list_insert (metadata, uri, - "Image:ExposureProgram", value);*/ - } else if (!data->exposure_time && g_ascii_strcasecmp (name, "ExposureTime") == 0) { - data->exposure_time = div_str_dup (value); - } else if (!data->fnumber && g_ascii_strcasecmp (name, "FNumber") == 0) { - data->fnumber = div_str_dup (value); - } else if (!data->focal_length && g_ascii_strcasecmp (name, "FocalLength") == 0) { - data->focal_length = div_str_dup (value); - } else if (!data->iso_speed_ratings && g_ascii_strcasecmp (name, "ISOSpeedRatings") == 0) { - data->iso_speed_ratings = div_str_dup (value); - } else if (!data->white_balance && g_ascii_strcasecmp (name, "WhiteBalance") == 0) { - data->white_balance = g_strdup (fix_white_balance (value)); - } else if (!data->copyright && g_ascii_strcasecmp (name, "Copyright") == 0) { - data->copyright = g_strdup (value); - } else if (!data->gps_altitude && g_ascii_strcasecmp (name, "GPSAltitude") == 0) { - data->gps_altitude = div_str_dup (value); - } else if (!data->gps_altitude_ref && g_ascii_strcasecmp (name, "GPSAltitudeRef") == 0) { - data->gps_altitude_ref = g_strdup (value); - } else if (!data->gps_latitude && g_ascii_strcasecmp (name, "GPSLatitude") == 0) { - data->gps_latitude = gps_coordinate_dup (value); - } else if (!data->gps_longitude && g_ascii_strcasecmp (name, "GPSLongitude") == 0) { - data->gps_longitude = gps_coordinate_dup (value); - } else if (!data->gps_direction && g_ascii_strcasecmp (name, "GPSImgDirection") == 0) { - data->gps_direction = div_str_dup (value); - } - /* TIFF */ - } else if (g_ascii_strcasecmp (schema, NS_TIFF) == 0) { - if (!data->orientation && g_ascii_strcasecmp (name, "Orientation") == 0) { - data->orientation = g_strdup (fix_orientation (value)); - } - /* PDF*/ - } else if (g_ascii_strcasecmp (schema, NS_PDF) == 0) { - if (g_ascii_strcasecmp (name, "keywords") == 0) { - if (data->pdf_keywords) { - gchar *temp = g_strdup_printf ("%s, %s", value, data->pdf_keywords); - g_free (data->pdf_keywords); - data->pdf_keywords = temp; - } else { - data->pdf_keywords = g_strdup (value); - } - } else - if (!data->pdf_title && g_ascii_strcasecmp (name, "title") == 0) { - data->pdf_title = g_strdup (value); - } - /* Dublin Core */ - } else if (g_ascii_strcasecmp (schema, NS_DC) == 0) { - if (!data->title && g_ascii_strcasecmp (name, "title") == 0) { - data->title = g_strdup (value); - } else if (!data->rights && g_ascii_strcasecmp (name, "rights") == 0) { - data->rights = g_strdup (value); - } else if (!data->creator && g_ascii_strcasecmp (name, "creator") == 0) { - data->creator = g_strdup (value); - } else if (!data->description && g_ascii_strcasecmp (name, "description") == 0) { - data->description = g_strdup (value); - } else if (!data->date && g_ascii_strcasecmp (name, "date") == 0) { - data->date = tracker_date_guess (value); - } else if (g_ascii_strcasecmp (name, "keywords") == 0) { - if (data->keywords) { - gchar *temp = g_strdup_printf ("%s, %s", value, data->keywords); - g_free (data->keywords); - data->keywords = temp; - } else { - data->keywords = g_strdup (value); - } - } else if (g_ascii_strcasecmp (name, "subject") == 0) { - if (data->subject) { - gchar *temp = g_strdup_printf ("%s, %s", value, data->subject); - g_free (data->subject); - data->subject = temp; - } else { - data->subject = g_strdup (value); - } - } else if (!data->publisher && g_ascii_strcasecmp (name, "publisher") == 0) { - data->publisher = g_strdup (value); - } else if (!data->contributor && g_ascii_strcasecmp (name, "contributor") == 0) { - data->contributor = g_strdup (value); - } else if (!data->type && g_ascii_strcasecmp (name, "type") == 0) { - data->type = g_strdup (value); - } else if (!data->format && g_ascii_strcasecmp (name, "format") == 0) { - data->format = g_strdup (value); - } else if (!data->identifier && g_ascii_strcasecmp (name, "identifier") == 0) { - data->identifier = g_strdup (value); - } else if (!data->source && g_ascii_strcasecmp (name, "source") == 0) { - data->source = g_strdup (value); - } else if (!data->language && g_ascii_strcasecmp (name, "language") == 0) { - data->language = g_strdup (value); - } else if (!data->relation && g_ascii_strcasecmp (name, "relation") == 0) { - data->relation = g_strdup (value); - } else if (!data->coverage && g_ascii_strcasecmp (name, "coverage") == 0) { - data->coverage = g_strdup (value); - } - /* Creative Commons */ - } else if (g_ascii_strcasecmp (schema, NS_CC) == 0) { - if (!data->license && g_ascii_strcasecmp (name, "license") == 0) { - data->license = g_strdup (value); - } - /* TODO: A lot of these location fields are pretty vague and ambigious. - * We should go through them one by one and ensure that all of them are - * used sanely */ - - /* Photoshop TODO: is this needed anyway? */ - } else if (g_ascii_strcasecmp (schema, NS_PHOTOSHOP) == 0) { - if (!data->city && g_ascii_strcasecmp (name, "City") == 0) { - data->city = g_strdup (value); - } else if (!data->country && g_ascii_strcasecmp (name, "Country") == 0) { - data->country = g_strdup (value); - } else if (!data->state && g_ascii_strcasecmp (name, "State") == 0) { - data->state = g_strdup (value); - } else if (!data->address && g_ascii_strcasecmp (name, "Location") == 0) { - data->address = g_strdup (value); - } - /* IPTC4XMP scheme - GeoClue / location stuff, TODO */ - } else if (g_ascii_strcasecmp (schema, NS_IPTC4XMP) == 0) { - if (!data->city && g_ascii_strcasecmp (name, "City") == 0) { - data->city = g_strdup (value); - } else if (!data->country && g_ascii_strcasecmp (name, "Country") == 0) { - data->country = g_strdup (value); - } else if (!data->country && g_ascii_strcasecmp (name, "CountryName") == 0) { - data->country = g_strdup (value); - } else if (!data->country && g_ascii_strcasecmp (name, "PrimaryLocationName") == 0) { - data->country = g_strdup (value); - } else if (!data->state && g_ascii_strcasecmp (name, "State") == 0) { - data->state = g_strdup (value); - } else if (!data->state && g_ascii_strcasecmp (name, "Province") == 0) { - data->state = g_strdup (value); - } else if (!data->address && g_ascii_strcasecmp (name, "Sublocation") == 0) { - data->address = g_strdup (value); - } - } else if (g_ascii_strcasecmp (schema, NS_XAP) == 0) { - if (!data->rating && g_ascii_strcasecmp (name, "Rating") == 0) { - data->rating = g_strdup (value); - } - } else if (g_ascii_strcasecmp (schema, NS_XMP_REGIONS) == 0) { - if (g_str_has_prefix (path, "mwg-rs:Regions/mwg-rs:RegionList")) { - TrackerXmpRegion *current_region; - gint position = get_region_counter (path); - - if (position == -1) { - g_free (name); - return; - } - - /* First time a property appear for a region, we create the region */ - current_region = g_slist_nth_data (data->regions, position-1); - if (current_region == NULL) { - current_region = g_slice_new0 (TrackerXmpRegion); - data->regions = g_slist_append (data->regions, current_region); - } - - propname = g_strdup (strrchr (path, '/') + 1); - - if (!current_region->title && g_ascii_strcasecmp (propname, "mwg-rs:Name") == 0) { - current_region->title = g_strdup (value); - } else if (!current_region->description && g_ascii_strcasecmp (propname, "mwg-rs:Description") == 0) { - current_region->description = g_strdup (value); - } else if (!current_region->x && g_ascii_strcasecmp (propname, "stArea:x") == 0) { - current_region->x = g_strdup (value); - } else if (!current_region->y && g_ascii_strcasecmp (propname, "stArea:y") == 0) { - current_region->y = g_strdup (value); - } else if (!current_region->width && g_ascii_strcasecmp (propname, "stArea:w") == 0) { - current_region->width = g_strdup (value); - } else if (!current_region->height && g_ascii_strcasecmp (propname, "stArea:h") == 0) { - current_region->height = g_strdup (value); - - /* Spec not clear about units - * } else if (!current_region->unit - * && g_ascii_strcasecmp (propname, "stArea:unit") == 0) { - * current_region->unit = g_strdup (value); - * - * we consider it always comes normalized - */ - } else if (!current_region->type && g_ascii_strcasecmp (propname, "mwg-rs:Type") == 0) { - current_region->type = g_strdup (value); - } else if (!current_region->link_class && !current_region->link_uri && - g_str_has_prefix (strrchr (path, ']') + 2, "mwg-rs:Extensions")) { - current_region->link_class = g_strdup (propname); - current_region->link_uri = g_strdup (value); - } - - g_free (propname); - } - } - - g_free (name); -} - - -/* Iterate over the XMP, dispatching to the appropriate element type - * (simple, simple w/qualifiers, or an array) handler. - */ -static void -iterate (XmpPtr xmp, - XmpIteratorPtr iter, - const gchar *uri, - TrackerXmpData *data, - gboolean append) -{ - XmpStringPtr the_schema = xmp_string_new (); - XmpStringPtr the_path = xmp_string_new (); - XmpStringPtr the_prop = xmp_string_new (); - - uint32_t opt; - - while (xmp_iterator_next (iter, the_schema, the_path, the_prop, &opt)) { - const gchar *schema = xmp_string_cstr (the_schema); - const gchar *path = xmp_string_cstr (the_path); - const gchar *value = xmp_string_cstr (the_prop); - - if (XMP_IS_PROP_SIMPLE (opt)) { - if (!tracker_is_empty_string (path)) { - if (XMP_HAS_PROP_QUALIFIERS (opt)) { - iterate_simple_qual (xmp, uri, data, schema, path, value, append); - } else { - iterate_simple (uri, data, schema, path, value, append); - } - } - } else if (XMP_IS_PROP_ARRAY (opt)) { - if (XMP_IS_ARRAY_ALTTEXT (opt)) { - iterate_alt_text (xmp, uri, data, schema, path); - xmp_iterator_skip (iter, XMP_ITER_SKIPSUBTREE); - } else { - iterate_array (xmp, uri, data, schema, path); - - /* Some dc: elements are handled as arrays by exempi. - * In those cases, to avoid duplicated values, is easier - * to skip the subtree. - */ - if (g_ascii_strcasecmp (schema, NS_DC) == 0) { - xmp_iterator_skip (iter, XMP_ITER_SKIPSUBTREE); - } - } - } - } - - xmp_string_free (the_prop); - xmp_string_free (the_path); - xmp_string_free (the_schema); -} - -static void -register_namespace (const gchar *ns_uri, - const gchar *suggested_prefix) -{ - if (!xmp_namespace_prefix (ns_uri, NULL)) { - xmp_register_namespace (ns_uri, suggested_prefix, NULL); - } -} - -#endif /* HAVE_EXEMPI */ - -static gboolean -parse_xmp (const gchar *buffer, - size_t len, - const gchar *uri, - TrackerXmpData *data) -{ -#ifdef HAVE_EXEMPI - XmpPtr xmp; -#endif /* HAVE_EXEMPI */ - - memset (data, 0, sizeof (TrackerXmpData)); - -#ifdef HAVE_EXEMPI - - xmp_init (); - - register_namespace (NS_XMP_REGIONS, "mwg-rs"); - register_namespace (NS_ST_DIM, "stDim"); - register_namespace (NS_ST_AREA, "stArea"); - - xmp = xmp_new_empty (); - xmp_parse (xmp, buffer, len); - - if (xmp != NULL) { - XmpIteratorPtr iter; - - iter = xmp_iterator_new (xmp, NULL, NULL, XMP_ITER_PROPERTIES); - iterate (xmp, iter, uri, data, FALSE); - xmp_iterator_free (iter); - xmp_free (xmp); - } - - xmp_terminate (); -#endif /* HAVE_EXEMPI */ - - return TRUE; -} - -#ifndef TRACKER_DISABLE_DEPRECATED - -// LCOV_EXCL_START - -/** - * tracker_xmp_read: - * @buffer: a chunk of data with xmp data in it. - * @len: the size of @buffer. - * @uri: the URI this is related to. - * @data: a pointer to a TrackerXmpData structure to populate. - * - * This function takes @len bytes of @buffer and runs it through the - * XMP library. The result is that @data is populated with the XMP - * data found in @uri. - * - * Returns: %TRUE if the @data was populated successfully, otherwise - * %FALSE is returned. - * - * Since: 0.8 - * - * Deprecated: 0.9. Use tracker_xmp_new() instead. - **/ -gboolean -tracker_xmp_read (const gchar *buffer, - size_t len, - const gchar *uri, - TrackerXmpData *data) -{ - g_return_val_if_fail (buffer != NULL, FALSE); - g_return_val_if_fail (len > 0, FALSE); - g_return_val_if_fail (uri != NULL, FALSE); - g_return_val_if_fail (data != NULL, FALSE); - - return parse_xmp (buffer, len, uri, data); -} - -// LCOV_EXCL_STOP - -#endif /* TRACKER_DISABLE_DEPRECATED */ - -static void -xmp_region_free (gpointer data) -{ - TrackerXmpRegion *region = (TrackerXmpRegion *) data; - - g_free (region->title); - g_free (region->description); - g_free (region->type); - g_free (region->x); - g_free (region->y); - g_free (region->width); - g_free (region->height); - g_free (region->link_class); - g_free (region->link_uri); - - g_slice_free (TrackerXmpRegion, region); -} - - -/** - * tracker_xmp_new: - * @buffer: a chunk of data with xmp data in it. - * @len: the size of @buffer. - * @uri: the URI this is related to. - * - * This function takes @len bytes of @buffer and runs it through the - * XMP library. - * - * Returns: a newly allocated #TrackerXmpData struct if XMP data was - * found, %NULL otherwise. Free the returned struct with tracker_xmp_free(). - * - * Since: 0.10 - **/ -TrackerXmpData * -tracker_xmp_new (const gchar *buffer, - gsize len, - const gchar *uri) -{ - TrackerXmpData *data; - - g_return_val_if_fail (buffer != NULL, NULL); - g_return_val_if_fail (len > 0, NULL); - g_return_val_if_fail (uri != NULL, NULL); - - data = g_new0 (TrackerXmpData, 1); - - if (!parse_xmp (buffer, len, uri, data)) { - tracker_xmp_free (data); - return NULL; - } - - return data; -} - -/** - * tracker_xmp_free: - * @data: a #TrackerXmpData struct - * - * Frees @data and all #TrackerXmpData members. %NULL will produce a - * a warning. - * - * Since: 0.10 - **/ -void -tracker_xmp_free (TrackerXmpData *data) -{ - g_return_if_fail (data != NULL); - - g_free (data->title); - g_free (data->rights); - g_free (data->creator); - g_free (data->description); - g_free (data->date); - g_free (data->keywords); - g_free (data->subject); - g_free (data->publisher); - g_free (data->contributor); - g_free (data->type); - g_free (data->format); - g_free (data->identifier); - g_free (data->source); - g_free (data->language); - g_free (data->relation); - g_free (data->coverage); - g_free (data->license); - g_free (data->pdf_title); - g_free (data->pdf_keywords); - g_free (data->title2); - g_free (data->time_original); - g_free (data->artist); - g_free (data->make); - g_free (data->model); - g_free (data->orientation); - g_free (data->flash); - g_free (data->metering_mode); - g_free (data->exposure_time); - g_free (data->fnumber); - g_free (data->focal_length); - g_free (data->iso_speed_ratings); - g_free (data->white_balance); - g_free (data->copyright); - g_free (data->rating); - g_free (data->address); - g_free (data->country); - g_free (data->state); - g_free (data->city); - g_free (data->gps_altitude); - g_free (data->gps_altitude_ref); - g_free (data->gps_latitude); - g_free (data->gps_longitude); - g_free (data->gps_direction); - - g_slist_free_full (data->regions, xmp_region_free); - g_free (data); -} - - -static const gchar * -fix_region_type (const gchar *region_type) -{ - if (region_type == NULL) { - return "nfo:region-content-undefined"; - } - - if (g_ascii_strncasecmp (region_type, "Face", 4) == 0) { - return "nfo:roi-content-face"; - } else if (g_ascii_strncasecmp (region_type, "Pet", 3) == 0) { - return "nfo:roi-content-pet"; - } else if (g_ascii_strncasecmp (region_type, "Focus", 5) == 0) { - return "nfo:roi-content-focus"; - } else if (g_ascii_strncasecmp (region_type, "BarCode", 7) == 0) { - return "nfo:roi-content-barcode"; - } - - return "nfo:roi-content-undefined"; -} - - -/** - * tracker_xmp_apply_to_resource: - * @resource: the #TrackerResource to apply XMP data to. - * @data: the data to push into @resource. - * - * This function applies all data in @data to @resource. - * - * This function also calls tracker_xmp_apply_regions_to_resource(), so there - * is no need to call both functions. - * - * Returns: %TRUE if the @data was applied to @resource successfully, - * otherwise %FALSE is returned. - * - * Since: 1.10 - **/ -gboolean -tracker_xmp_apply_to_resource (TrackerResource *resource, - TrackerXmpData *data) -{ - GPtrArray *keywords; - guint i; - - g_return_val_if_fail (TRACKER_IS_RESOURCE (resource), FALSE); - g_return_val_if_fail (data != NULL, FALSE); - - keywords = g_ptr_array_new (); - - if (data->keywords) { - tracker_keywords_parse (keywords, data->keywords); - } - - if (data->subject) { - tracker_keywords_parse (keywords, data->subject); - } - - if (data->pdf_keywords) { - tracker_keywords_parse (keywords, data->pdf_keywords); - } - - for (i = 0; i < keywords->len; i++) { - TrackerResource *label; - gchar *p; - - p = g_ptr_array_index (keywords, i); - label = tracker_extract_new_tag (p); - - tracker_resource_set_relation (resource, "nao:hasTag", label); - - g_free (p); - g_object_unref (label); - } - g_ptr_array_free (keywords, TRUE); - - if (data->publisher) { - TrackerResource *publisher; - - publisher = tracker_extract_new_contact (data->publisher); - tracker_resource_set_relation (resource, "nco:publisher", publisher); - g_object_unref (publisher); - } - - if (data->type) { - tracker_resource_set_string (resource, "dc:type", data->type); - } - - if (data->format) { - tracker_resource_set_string (resource, "dc:format", data->format); - } - - if (data->identifier) { - tracker_resource_set_string (resource, "dc:identifier", data->identifier); - } - - if (data->source) { - tracker_resource_set_string (resource, "dc:source", data->source); - } - - if (data->language) { - tracker_resource_set_string (resource, "dc:language", data->language); - } - - if (data->relation) { - tracker_resource_set_string (resource, "dc:relation", data->relation); - } - - if (data->coverage) { - tracker_resource_set_string (resource, "dc:coverage", data->coverage); - } - - if (data->license) { - tracker_resource_set_string (resource, "dc:license", data->license); - } - - if (data->make || data->model) { - TrackerResource *equipment; - - equipment = tracker_extract_new_equipment (data->make, data->model); - tracker_resource_set_relation (resource, "nfo:equipment", equipment); - g_object_unref (equipment); - } - - if (data->title || data->title2 || data->pdf_title) { - const gchar *final_title = tracker_coalesce_strip (3, data->title, - data->title2, - data->pdf_title); - - tracker_resource_set_string (resource, "nie:title", final_title); - } - - if (data->orientation) { - TrackerResource *orientation; - - orientation = tracker_resource_new (data->orientation); - tracker_resource_set_relation (resource, "nfo:orientation", orientation); - g_object_unref (orientation); - } - - if (data->rights || data->copyright) { - const gchar *final_rights = tracker_coalesce_strip (2, data->copyright, data->rights); - - tracker_resource_set_string (resource, "nie:copyright", final_rights); - } - - if (data->white_balance) { - TrackerResource *white_balance; - - white_balance = tracker_resource_new (data->white_balance); - tracker_resource_set_relation (resource, "nmm:meteringMode", white_balance); - g_object_unref (white_balance); - } - - if (data->fnumber) { - tracker_resource_set_string (resource, "nmm:fnumber", data->fnumber); - } - - if (data->flash) { - TrackerResource *flash; - - flash = tracker_resource_new (data->flash); - tracker_resource_set_relation (resource, "nmm:flash", flash); - g_object_unref (flash); - } - - if (data->focal_length) { - tracker_resource_set_string (resource, "nmm:focalLength", data->focal_length); - } - - if (data->artist || data->contributor) { - TrackerResource *contributor; - const gchar *final_artist = tracker_coalesce_strip (2, data->artist, data->contributor); - - contributor = tracker_extract_new_contact (final_artist); - tracker_resource_set_relation (resource, "nco:contributor", contributor); - g_object_unref (contributor); - } - - if (data->exposure_time) { - tracker_resource_set_string (resource, "nmm:exposureTime", data->exposure_time); - } - - if (data->iso_speed_ratings) { - tracker_resource_set_string (resource, "nmm:isoSpeed", data->iso_speed_ratings); - } - - if (data->date || data->time_original) { - const gchar *final_date = tracker_coalesce_strip (2, data->date, - data->time_original); - - tracker_resource_set_string (resource, "nie:contentCreated", final_date); - } - - if (data->description) { - tracker_resource_set_string (resource, "nie:description", data->description); - } - - if (data->metering_mode) { - TrackerResource *metering; - - metering = tracker_resource_new (data->metering_mode); - tracker_resource_set_relation (resource, "nmm:meteringMode", metering); - g_object_unref (metering); - } - - if (data->creator) { - TrackerResource *creator; - - creator = tracker_extract_new_contact (data->creator); - tracker_resource_set_relation (resource, "nco:creator", creator); - g_object_unref (creator); - } - - if (data->address || data->state || data->country || data->city || - data->gps_altitude || data->gps_latitude || data->gps_longitude) { - TrackerResource *geopoint; - - geopoint = tracker_extract_new_location (data->address, data->state, data->city, - data->country, data->gps_altitude, data->gps_latitude, data->gps_longitude); - tracker_resource_set_relation (resource, "slo:location", geopoint); - g_object_unref (geopoint); - } - - if (data->gps_direction) { - tracker_resource_set_string (resource, "nfo:heading", data->gps_direction); - } - - if (data->regions) { - tracker_xmp_apply_regions_to_resource (resource, data); - } - - return TRUE; -} - -/** - * tracker_xmp_apply_regions_to_resource: - * @resource: the #TrackerResource object to apply XMP data to. - * @data: the data to push into @resource - * - * This function applies all regional @data to @resource. Regional data exists - * for image formats like JPEG, PNG, etc. where parts of the image refer to - * areas of interest. This can be people's faces, places to focus, barcodes, - * etc. The regional data describes the title, height, width, X, Y and can - * occur multiple times in a given file. - * - * This data usually is standardized between image formats and that's - * what makes this function different to tracker_xmp_apply_to_resource() which - * is useful for XMP files only. - * - * Returns: %TRUE if the @data was applied to @resource successfully, otherwise - * %FALSE is returned. - * - * Since: 1.10 - **/ -gboolean -tracker_xmp_apply_regions_to_resource (TrackerResource *resource, - TrackerXmpData *data) -{ - GSList *iter; - - g_return_val_if_fail (TRACKER_IS_RESOURCE (resource), FALSE); - g_return_val_if_fail (data != NULL, FALSE); - - if (!data->regions) { - return TRUE; - } - - for (iter = data->regions; iter != NULL; iter = iter->next) { - TrackerResource *region_resource; - TrackerXmpRegion *region; - gchar *uuid; - - region = (TrackerXmpRegion *) iter->data; - uuid = tracker_sparql_get_uuid_urn (); - - region_resource = tracker_resource_new (uuid); - tracker_resource_set_uri (region_resource, "rdf:type", "nfo:RegionOfInterest"); - - g_free (uuid); - - if (region->title) { - tracker_resource_set_string (region_resource, "nie:title", region->title); - } - - if (region->description) { - tracker_resource_set_string (region_resource, "nie:description", region->description); - } - - if (region->type) { - tracker_resource_set_string (region_resource, "nfo:regionOfInterestType", fix_region_type (region->type)); - } - - if (region->x) { - tracker_resource_set_string (region_resource, "nfo:regionOfInterestX", region->x); - } - - if (region->y) { - tracker_resource_set_string (region_resource, "nfo:regionOfInterestY", region->y); - } - - if (region->width) { - tracker_resource_set_string (region_resource, "nfo:regionOfInterestWidth", region->width); - } - - if (region->height) { - tracker_resource_set_string (region_resource, "nfo:regionOfInterestHeight", region->height); - } - - if (region->link_uri && region->link_class) { - tracker_resource_set_string (region_resource, "nfo:roiRefersTo", region->link_uri); - } - - tracker_resource_add_relation (resource, "nfo:hasRegionOfInterest", region_resource); - g_object_unref (region_resource); - } - - return TRUE; -} diff --git a/src/libtracker-extract/tracker-xmp.h b/src/libtracker-extract/tracker-xmp.h deleted file mode 100644 index 3a3016d75..000000000 --- a/src/libtracker-extract/tracker-xmp.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __LIBTRACKER_EXTRACT_XMP_H__ -#define __LIBTRACKER_EXTRACT_XMP_H__ - -#if !defined (__LIBTRACKER_EXTRACT_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "only <libtracker-extract/tracker-extract.h> must be included directly." -#endif - -#include <libtracker-sparql/tracker-sparql.h> - -G_BEGIN_DECLS - -/** - * TrackerXmpData: - * @title: Value for the dc:title property. - * @rights: Value for the dc:rights property. - * @creator: Value for the dc:creator property. - * @description: Value for the dc:description property. - * @date: Value for the dc:date property. - * @keywords: Value for the dc:keywords property. - * @subject: Value for the dc:subject property. - * @publisher: Value for the dc:publisher property. - * @contributor: Value for the dc:contributor property. - * @type: Value for the dc:type property. - * @format: Value for the dc:format property. - * @identifier: Value for the dc:identifier property. - * @source: Value for the dc:source property. - * @language: Value for the dc:language property. - * @relation: Value for the dc:relation property. - * @coverage: Value for the dc:coverage property. - * @license: Value for the nie:license property. - * @pdf_title: Title of the PDF. - * @pdf_keywords: Keywords in the PDF. - * @title2: Title from the EXIF data. - * @time_original: Original time from the EXIF data. - * @artist: Artist from the EXIF data. - * @make: Make info from the EXIF data. - * @model: Model from the EXIF data. - * @orientation: Orientation info from the EXIF data. - * @flash: Flash info from the EXIF data. - * @metering_mode: Metering mode from the EXIF data. - * @exposure_time: Exposure time from the EXIF data. - * @fnumber: Focal ratio from the EXIF data. - * @focal_length: Focal length from the EXIF data. - * @iso_speed_ratings: ISO speed ratings from the EXIF data. - * @white_balance: White balance info from the EXIF data. - * @copyright: Copyright info from the EXIF data. - * @rating: Rating. - * @address: Address. - * @country: Country. - * @state: State. - * @city: City. - * @gps_altitude: GPS altitude. - * @gps_altitude_ref: GPS altitude reference. - * @gps_latitude: GPS latitude. - * @gps_longitude: GPS longitude. - * @gps_direction: GPS direction information. - * @regions: List of #TrackerXmpRegion items. - * - * Structure defining XMP data of a given file. - */ -typedef struct { - /* NS_DC */ - gchar *title; - gchar *rights; - gchar *creator; - gchar *description; - gchar *date; - gchar *keywords; - gchar *subject; - gchar *publisher; - gchar *contributor; - gchar *type; - gchar *format; - gchar *identifier; - gchar *source; - gchar *language; - gchar *relation; - gchar *coverage; - - /* NS_CC */ - gchar *license; - - /* NS_PDF */ - gchar *pdf_title; - gchar *pdf_keywords; - - /* NS_EXIF */ - gchar *title2; - gchar *time_original; - gchar *artist; - gchar *make; - gchar *model; - gchar *orientation; - gchar *flash; - gchar *metering_mode; - gchar *exposure_time; - gchar *fnumber; - gchar *focal_length; - gchar *iso_speed_ratings; - gchar *white_balance; - gchar *copyright; - - /* TODO NS_XAP*/ - gchar *rating; - - /* TODO NS_IPTC4XMP */ - /* TODO NS_PHOTOSHOP */ - gchar *address; - gchar *country; - gchar *state; - gchar *city; - - /* ABI barrier (don't change things above this) */ - gchar *gps_altitude; - gchar *gps_altitude_ref; - gchar *gps_latitude; - gchar *gps_longitude; - gchar *gps_direction; - - /* List of TrackerXmpRegion */ - GSList *regions; -} TrackerXmpData; - -/** - * TrackerXmpRegion: - * @title: Title of the region. - * @description: Description of the region. - * @type: Type of the region. - * @x: X axis position. - * @y: Y axis position. - * @width: Width. - * @height: Height. - * @link_class: Link class. - * @link_uri: Link URI. - * - * Structure defining data of a given region in a #TrackerXmpData. - */ -typedef struct { - gchar *title; - gchar *description; - gchar *type; - gchar *x; - gchar *y; - gchar *width; - gchar *height; - gchar *link_class; - gchar *link_uri; -} TrackerXmpRegion; - -TrackerXmpData *tracker_xmp_new (const gchar *buffer, - gsize len, - const gchar *uri); -void tracker_xmp_free (TrackerXmpData *data); - -gboolean tracker_xmp_apply_to_resource (TrackerResource *resource, - TrackerXmpData *data); -gboolean tracker_xmp_apply_regions_to_resource (TrackerResource *resource, - TrackerXmpData *data); - -#ifndef TRACKER_DISABLE_DEPRECATED - -gboolean tracker_xmp_read (const gchar *buffer, - size_t len, - const gchar *uri, - TrackerXmpData *data) G_GNUC_DEPRECATED; - -#endif /* TRACKER_DISABLE_DEPRECATED */ - -G_END_DECLS - -#endif /* __LIBTRACKER_EXTRACT_XMP_H__ */ diff --git a/src/meson.build b/src/meson.build index f18903bfc..00f0ec565 100644 --- a/src/meson.build +++ b/src/meson.build @@ -20,18 +20,6 @@ subdir('libtracker-sparql-backend') # Public libtracker-miner library subdir('libtracker-miner') -# Internal data extraction helpers -subdir('libtracker-extract') - -# Public data extract tool & modules -subdir('tracker-extract') - -# Public miners -subdir('miners') - -# Public metadata writeback tool & modiles -subdir('tracker-writeback') - # Internal control library subdir('libtracker-control') @@ -40,5 +28,3 @@ subdir('tracker') # Public shared database subdir('tracker-store') - -meson.add_install_script('create-miner-symlinks.sh', dbus_services_dir, tracker_miner_services_dir) diff --git a/src/miners/Makefile.am b/src/miners/Makefile.am deleted file mode 100644 index cbeba5430..000000000 --- a/src/miners/Makefile.am +++ /dev/null @@ -1,15 +0,0 @@ -SUBDIRS = - -if HAVE_TRACKER_MINER_FS -SUBDIRS += fs -endif - -if HAVE_TRACKER_MINER_APPS -SUBDIRS += apps -endif - -if HAVE_TRACKER_MINER_RSS -SUBDIRS += rss -endif - -EXTRA_DIST = meson.build diff --git a/src/miners/apps/.gitignore b/src/miners/apps/.gitignore deleted file mode 100644 index 2d014f80d..000000000 --- a/src/miners/apps/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tracker-miner-apps -*.service diff --git a/src/miners/apps/Makefile.am b/src/miners/apps/Makefile.am deleted file mode 100644 index bf0becf2f..000000000 --- a/src/miners/apps/Makefile.am +++ /dev/null @@ -1,73 +0,0 @@ -AM_CPPFLAGS = \ - $(BUILD_CFLAGS) \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - -DSHAREDIR=\""$(datadir)"\" \ - -DLOCALEDIR=\""$(localedir)"\" \ - -DLIBEXEC_PATH=\""$(libexecdir)"\" \ - $(TRACKER_MINER_APPS_CFLAGS) - -libexec_PROGRAMS = tracker-miner-apps - -tracker_miner_apps_SOURCES = \ - tracker-main.c \ - tracker-miner-applications.c \ - tracker-miner-applications.h - -tracker_miner_apps_LDADD = \ - $(top_builddir)/src/libtracker-miner/libtracker-miner-@TRACKER_API_VERSION@.la \ - $(top_builddir)/src/libtracker-sparql-backend/libtracker-sparql-@TRACKER_API_VERSION@.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_MINER_APPS_LIBS) - -# DBus interfaces (XML files) and services -%.service.in: %.service.in.in - @sed -e "s|@libexecdir[@]|${libexecdir}|" $< > $@ - -servicedir = $(DBUS_SERVICES_DIR) -service_DATA = org.freedesktop.Tracker1.Miner.Applications.service - -INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -d -u' -@INTLTOOL_SERVICE_RULE@ - -tracker-miner-apps.service: tracker-miner-apps.service.in Makefile - @sed -e "s|@libexecdir[@]|${libexecdir}|" $< > $@ - -systemd_userdir = $(prefix)/lib/systemd/user -systemd_user_DATA = tracker-miner-apps.service - -install-data-hook: - $(MKDIR_P) "$(DESTDIR)$(datadir)/tracker/miners" && \ - $(LN_S) -f "$(servicedir)/$(service_DATA)" \ - "$(DESTDIR)$(datadir)/tracker/miners/$(service_DATA)" - -uninstall-local: - $(RM) "$(DESTDIR)$(datadir)/tracker/miners/$(service_DATA)" && \ - $(RM) "$(servicedir)/$(service_DATA)" - -# Desktop files: First we fix the VERSION and libexecdir -%.desktop.in: %.desktop.in.in - @sed -e "s|@libexecdir[@]|${libexecdir}|" \ - -e "s|@VERSION[@]|${VERSION}|" $< > $@ - -autostartdir = $(sysconfdir)/xdg/autostart -autostart_DATA = tracker-miner-apps.desktop - -@INTLTOOL_DESKTOP_RULE@ - -# Dist / Clean rules for all data -CLEANFILES = \ - $(autostart_DATA) \ - $(autostart_DATA:.desktop=.desktop.in) \ - $(service_DATA) \ - $(service_DATA:.service=.service.in) \ - $(systemd_user_DATA) \ - $(NULL) - -EXTRA_DIST = \ - $(autostart_DATA:.desktop=.desktop.in.in) \ - $(service_DATA:.service=.service.in.in) \ - $(systemd_user_DATA:.service=.service.in) \ - meson.build \ - $(NULL) diff --git a/src/miners/apps/meson.build b/src/miners/apps/meson.build deleted file mode 100644 index 51ddd5203..000000000 --- a/src/miners/apps/meson.build +++ /dev/null @@ -1,45 +0,0 @@ -sources = [ - 'tracker-main.c', - 'tracker-miner-applications.c', -] - -executable('tracker-miner-apps', sources, - dependencies: [tracker_common_dep, tracker_miner_dep, tracker_sparql_dep], - c_args: tracker_c_args, - install: true, - install_dir: get_option('libexecdir'), - install_rpath: tracker_internal_libs_dir, -) - -dbus_service_file_untranslated = configure_file( - input: 'org.freedesktop.Tracker1.Miner.Applications.service.in.in', - output: 'org.freedesktop.Tracker1.Miner.Applications.service.in', - configuration: conf) - -dbus_service_file = custom_target('tracker-miner-apps-dbus-service-file', - input: dbus_service_file_untranslated, - output: 'org.freedesktop.Tracker1.Miner.Applications.service', - command: ['intltool-merge', '--quiet', '--desktop-style', '--utf8', join_paths(meson.source_root(), 'po'), '@INPUT@', '@OUTPUT@'], - install: true, - install_dir: dbus_services_dir) - -desktop_file_untranslated = configure_file( - input: 'tracker-miner-apps.desktop.in.in', - output: 'tracker-miner-apps.desktop.in', - configuration: conf) - -desktop_file = custom_target('tracker-miner-apps-desktop-file', - input: desktop_file_untranslated, - output: 'tracker-miner-apps.desktop', - command: ['intltool-merge', '--quiet', '--desktop-style', '--utf8', join_paths(meson.source_root(), 'po'), '@INPUT@', '@OUTPUT@'], - install: true, - install_dir: join_paths(get_option('sysconfdir'), 'xdg/autostart')) - -if install_systemd_user_services - configure_file( - input: 'tracker-miner-apps.service.in', - output: 'tracker-miner-apps.service', - configuration: conf, - install: true, - install_dir: systemd_user_services_dir) -endif diff --git a/src/miners/apps/org.freedesktop.Tracker1.Miner.Applications.service.in.in b/src/miners/apps/org.freedesktop.Tracker1.Miner.Applications.service.in.in deleted file mode 100644 index 13e26c3e0..000000000 --- a/src/miners/apps/org.freedesktop.Tracker1.Miner.Applications.service.in.in +++ /dev/null @@ -1,10 +0,0 @@ -[D-BUS Service] -Name=org.freedesktop.Tracker1.Miner.Applications -Exec=@libexecdir@/tracker-miner-apps -SystemdService=tracker-miner-apps.service - -# Miner details needed for tracker-control -Path=/org/freedesktop/Tracker1/Miner/Applications -NameSuffix=Miner.Applications -_DisplayName=Applications -_Comment=Applications data miner diff --git a/src/miners/apps/tracker-main.c b/src/miners/apps/tracker-main.c deleted file mode 100644 index 8f0a55668..000000000 --- a/src/miners/apps/tracker-main.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (C) 2014, Lanedo GmbH. <martyn@lanedo.com> - - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <stdlib.h> -#include <locale.h> -#include <errno.h> - -#include <glib.h> -#include <glib-unix.h> -#include <glib-object.h> -#include <glib/gi18n.h> - -#include <libtracker-common/tracker-common.h> - -#include <libtracker-miner/tracker-miner.h> - -#include "tracker-miner-applications.h" - -#define ABOUT \ - "Tracker " PACKAGE_VERSION "\n" - -#define LICENSE \ - "This program is free software and comes without any warranty.\n" \ - "It is licensed under version 2 or later of the General Public " \ - "License which can be viewed at:\n" \ - "\n" \ - " http://www.gnu.org/licenses/gpl.txt\n" - -#define DBUS_NAME_SUFFIX "Miner.Applications" -#define DBUS_PATH "/org/freedesktop/Tracker1/Miner/Applications" - -static GMainLoop *main_loop; - -static gint verbosity = -1; -static gboolean no_daemon; -static gboolean version; -static gchar *domain_ontology_name = NULL; - -static GOptionEntry entries[] = { - { "verbosity", 'v', 0, - G_OPTION_ARG_INT, &verbosity, - N_("Logging, 0 = errors only, " - "1 = minimal, 2 = detailed and 3 = debug (default=0)"), - NULL }, - { "no-daemon", 'n', 0, - G_OPTION_ARG_NONE, &no_daemon, - N_("Runs until all applications are indexed and then exits"), - NULL }, - { "domain-ontology", 'd', 0, - G_OPTION_ARG_STRING, &domain_ontology_name, - N_("Runs for an specific domain ontology"), - NULL }, - { "version", 'V', 0, - G_OPTION_ARG_NONE, &version, - N_("Displays version information"), - NULL }, - { NULL } -}; - -static gboolean -signal_handler (gpointer user_data) -{ - int signo = GPOINTER_TO_INT (user_data); - - static gboolean in_loop = FALSE; - - /* Die if we get re-entrant signals handler calls */ - if (in_loop) { - _exit (EXIT_FAILURE); - } - - switch (signo) { - case SIGTERM: - case SIGINT: - in_loop = TRUE; - g_main_loop_quit (main_loop); - - /* Fall through */ - default: - if (g_strsignal (signo)) { - g_print ("\n"); - g_print ("Received signal:%d->'%s'\n", - signo, - g_strsignal (signo)); - } - break; - } - - return G_SOURCE_CONTINUE; -} - -static void -initialize_signal_handler (void) -{ -#ifndef G_OS_WIN32 - g_unix_signal_add (SIGTERM, signal_handler, GINT_TO_POINTER (SIGTERM)); - g_unix_signal_add (SIGINT, signal_handler, GINT_TO_POINTER (SIGINT)); -#endif /* G_OS_WIN32 */ -} - -static void -initialize_priority_and_scheduling (TrackerSchedIdle sched_idle, - gboolean first_time_index) -{ - /* Set CPU priority */ - if (sched_idle == TRACKER_SCHED_IDLE_ALWAYS || - (sched_idle == TRACKER_SCHED_IDLE_FIRST_INDEX && first_time_index)) { - tracker_sched_idle (); - } - - /* Set disk IO priority and scheduling */ - tracker_ioprio_init (); - - /* Set process priority: - * The nice() function uses attribute "warn_unused_result" and - * so complains if we do not check its returned value. But it - * seems that since glibc 2.2.4, nice() can return -1 on a - * successful call so we have to check value of errno too. - * Stupid... - */ - - g_message ("Setting priority nice level to 19"); - - errno = 0; - if (nice (19) == -1 && errno != 0) { - const gchar *str = g_strerror (errno); - - g_message ("Couldn't set nice value to 19, %s", - str ? str : "no error given"); - } -} - -static void -miner_finished_cb (TrackerMinerFS *fs, - gdouble seconds_elapsed, - guint total_directories_found, - guint total_directories_ignored, - guint total_files_found, - guint total_files_ignored, - gpointer user_data) -{ - g_info ("Finished mining in seconds:%f, total directories:%d, total files:%d", - seconds_elapsed, - total_directories_found, - total_files_found); - - if (no_daemon && main_loop) { - g_main_loop_quit (main_loop); - } -} - -static void -on_domain_vanished (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - GMainLoop *loop = user_data; - g_main_loop_quit (loop); -} - -int -main (gint argc, gchar *argv[]) -{ - TrackerMiner *miner_applications; - GOptionContext *context; - GError *error = NULL; - gchar *log_filename = NULL; - GDBusConnection *connection; - TrackerMinerProxy *proxy; - TrackerDomainOntology *domain_ontology; - gchar *dbus_name; - - main_loop = NULL; - - setlocale (LC_ALL, ""); - - bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); - - /* Set timezone info */ - tzset (); - - /* Translators: this messagge will apper immediately after the - * usage string - Usage: COMMAND <THIS_MESSAGE> - */ - context = g_option_context_new (_("— start the application data miner")); - - g_option_context_add_main_entries (context, entries, NULL); - g_option_context_parse (context, &argc, &argv, &error); - g_option_context_free (context); - - if (error) { - g_printerr ("%s\n", error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - if (version) { - g_print ("\n" ABOUT "\n" LICENSE "\n"); - return EXIT_SUCCESS; - } - - tracker_sparql_connection_set_domain (domain_ontology_name); - - domain_ontology = tracker_domain_ontology_new (domain_ontology_name, NULL, &error); - if (error) { - g_critical ("Could not load domain ontology '%s': %s", - domain_ontology_name, error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, &error); - if (error) { - g_critical ("Could not create DBus connection: %s\n", - error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - tracker_log_init (verbosity, &log_filename); - if (log_filename) { - g_message ("Using log file:'%s'", log_filename); - g_free (log_filename); - } - - /* This makes sure we don't steal all the system's resources */ - initialize_priority_and_scheduling (TRACKER_SCHED_IDLE_ALWAYS, FALSE); - - main_loop = g_main_loop_new (NULL, FALSE); - - if (domain_ontology && domain_ontology_name) { - g_bus_watch_name_on_connection (connection, domain_ontology_name, - G_BUS_NAME_WATCHER_FLAGS_NONE, - NULL, on_domain_vanished, - main_loop, NULL); - } - - g_message ("Checking if we're running as a daemon:"); - g_message (" %s %s", - no_daemon ? "No" : "Yes", - no_daemon ? "(forced by command line)" : ""); - - /* Create miner for applications */ - miner_applications = tracker_miner_applications_new (&error); - if (!miner_applications) { - g_critical ("Couldn't create new applications miner, '%s'", - error ? error->message : "unknown error"); - tracker_log_shutdown (); - return EXIT_FAILURE; - } - - proxy = tracker_miner_proxy_new (miner_applications, connection, DBUS_PATH, NULL, &error); - if (!proxy) { - g_critical ("Couldn't create miner DBus proxy: %s", error->message); - g_error_free (error); - tracker_log_shutdown (); - return EXIT_FAILURE; - } - - g_signal_connect (miner_applications, "finished", - G_CALLBACK (miner_finished_cb), - NULL); - - /* Request DBus name */ - dbus_name = tracker_domain_ontology_get_domain (domain_ontology, DBUS_NAME_SUFFIX); - - if (!tracker_dbus_request_name (connection, dbus_name, &error)) { - g_critical ("Could not request DBus name '%s': %s", - dbus_name, error->message); - g_error_free (error); - g_free (dbus_name); - return EXIT_FAILURE; - } - - g_free (dbus_name); - - initialize_signal_handler (); - - /* Go, go, go! */ - tracker_miner_start (miner_applications); - g_main_loop_run (main_loop); - - g_message ("Shutdown started"); - - g_main_loop_unref (main_loop); - g_object_unref (G_OBJECT (miner_applications)); - g_object_unref (connection); - g_object_unref (proxy); - g_object_unref (domain_ontology); - - tracker_log_shutdown (); - - g_print ("\nOK\n\n"); - - return EXIT_SUCCESS; -} diff --git a/src/miners/apps/tracker-miner-applications.c b/src/miners/apps/tracker-miner-applications.c deleted file mode 100644 index 8c52b7795..000000000 --- a/src/miners/apps/tracker-miner-applications.c +++ /dev/null @@ -1,970 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <libtracker-common/tracker-common.h> - -#include "tracker-miner-applications.h" - -#define LOCALE_FILENAME "locale-for-miner-apps.txt" - -#define GROUP_DESKTOP_ENTRY "Desktop Entry" - -#define APPLICATION_DATASOURCE_URN "urn:nepomuk:datasource:84f20000-1241-11de-8c30-0800200c9a66" -#define APPLET_DATASOURCE_URN "urn:nepomuk:datasource:192bd060-1f9a-11de-8c30-0800200c9a66" -#define SOFTWARE_CATEGORY_URN_PREFIX "urn:software-category:" -#define THEME_ICON_URN_PREFIX "urn:theme-icon:" - -static void miner_applications_initable_iface_init (GInitableIface *iface); -static gboolean miner_applications_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error); -static gboolean miner_applications_process_file (TrackerMinerFS *fs, - GFile *file, - GTask *task); -static gboolean miner_applications_process_file_attributes (TrackerMinerFS *fs, - GFile *file, - GTask *task); -static gchar * miner_applications_remove_file (TrackerMinerFS *fs, - GFile *file); - -static GQuark miner_applications_error_quark = 0; - -typedef struct ProcessApplicationData ProcessApplicationData; - -struct ProcessApplicationData { - TrackerMinerFS *miner; - GFile *file; - TrackerSparqlBuilder *sparql; - GCancellable *cancellable; - GKeyFile *key_file; - gchar *type; - GTask *task; -}; - -static GInitableIface* miner_applications_initable_parent_iface; - -G_DEFINE_TYPE_WITH_CODE (TrackerMinerApplications, tracker_miner_applications, TRACKER_TYPE_MINER_FS, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - miner_applications_initable_iface_init)); - -static void -tracker_miner_applications_class_init (TrackerMinerApplicationsClass *klass) -{ - TrackerMinerFSClass *miner_fs_class = TRACKER_MINER_FS_CLASS (klass); - - miner_fs_class->process_file = miner_applications_process_file; - miner_fs_class->process_file_attributes = miner_applications_process_file_attributes; - miner_fs_class->remove_file = miner_applications_remove_file; - - miner_applications_error_quark = g_quark_from_static_string ("TrackerMinerApplications"); -} - -static void -tracker_miner_applications_init (TrackerMinerApplications *ma) -{ -} - -static void -miner_applications_initable_iface_init (GInitableIface *iface) -{ - miner_applications_initable_parent_iface = g_type_interface_peek_parent (iface); - iface->init = miner_applications_initable_init; -} - -static void -miner_applications_basedir_add (TrackerMinerFS *fs, - const gchar *basedir) -{ - TrackerIndexingTree *indexing_tree; - GFile *file; - gchar *path; - - indexing_tree = tracker_miner_fs_get_indexing_tree (fs); - - /* Add $dir/applications */ - path = g_build_filename (basedir, "applications", NULL); - file = g_file_new_for_path (path); - g_message (" Adding:'%s'", path); - - tracker_indexing_tree_add (indexing_tree, file, - TRACKER_DIRECTORY_FLAG_RECURSE | - TRACKER_DIRECTORY_FLAG_MONITOR | - TRACKER_DIRECTORY_FLAG_CHECK_MTIME); - g_object_unref (file); - g_free (path); - - /* Add $dir/desktop-directories */ - path = g_build_filename (basedir, "desktop-directories", NULL); - file = g_file_new_for_path (path); - g_message (" Adding:'%s'", path); - tracker_indexing_tree_add (indexing_tree, file, - TRACKER_DIRECTORY_FLAG_RECURSE | - TRACKER_DIRECTORY_FLAG_MONITOR | - TRACKER_DIRECTORY_FLAG_CHECK_MTIME); - g_object_unref (file); - g_free (path); -} - -static void -miner_applications_add_directories (TrackerMinerFS *fs) -{ - const gchar * const *xdg_dirs; - const gchar *user_data_dir; - gint i; - - g_message ("Setting up applications to iterate from XDG system directories"); - - /* Add all XDG system and local dirs */ - xdg_dirs = g_get_system_data_dirs (); - - for (i = 0; xdg_dirs[i]; i++) { - miner_applications_basedir_add (fs, xdg_dirs[i]); - } - - g_message ("Setting up applications to iterate from XDG user directories"); - - user_data_dir = g_get_user_data_dir (); - if (user_data_dir) { - miner_applications_basedir_add (fs, user_data_dir); - } -} - -static void -miner_finished_cb (TrackerMinerFS *fs, - gdouble seconds_elapsed, - guint total_directories_found, - guint total_directories_ignored, - guint total_files_found, - guint total_files_ignored, - gpointer user_data) -{ - /* Save locale, if it changes the variation in the desktop - * file languages needs to be re-indexed. - */ - GError *error = NULL; - gchar *locale = tracker_locale_get (TRACKER_LOCALE_LANGUAGE); - gchar *locale_file = g_build_filename (g_get_user_cache_dir (), "tracker", LOCALE_FILENAME, NULL); - - g_message ("Saving locale used to index applications"); - g_message (" Creating locale file '%s'", locale_file); - - if (locale == NULL) { - locale = g_strdup (""); - } - - if (!g_file_set_contents (locale_file, locale, -1, &error)) { - g_message (" Could not set file contents, %s", - error ? error->message : "no error given"); - g_clear_error (&error); - } - - g_free (locale); - g_free (locale_file); -} - -/* If a reset is requested, we will remove from the store all items previously - * inserted by the tracker-miner-applications, this is: - * (a) all elements which are nfo:softwareIcon of a given nfo:Software - * (b) all nfo:Software in our graph - * (c) all elements which are nfo:softwareCategoryIcon of a given nfo:SoftwareCategory - * (d) all nfo:SoftwareCategory in our graph - */ -static void -miner_applications_reset (TrackerMiner *miner) -{ - GError *error = NULL; - TrackerSparqlBuilder *sparql; - - sparql = tracker_sparql_builder_new_update (); - - /* (a) all elements which are nfo:softwareIcon of a given nfo:Software */ - tracker_sparql_builder_delete_open (sparql, TRACKER_OWN_GRAPH_URN); - tracker_sparql_builder_subject_variable (sparql, "icon"); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "rdfs:Resource"); - tracker_sparql_builder_delete_close (sparql); - - tracker_sparql_builder_where_open (sparql); - tracker_sparql_builder_subject_variable (sparql, "software"); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:Software"); - tracker_sparql_builder_subject_variable (sparql, "icon"); - tracker_sparql_builder_predicate (sparql, "nfo:softwareIcon"); - tracker_sparql_builder_object_variable (sparql, "software"); - tracker_sparql_builder_where_close (sparql); - - /* (b) all nfo:Software in our graph */ - tracker_sparql_builder_delete_open (sparql, TRACKER_OWN_GRAPH_URN); - tracker_sparql_builder_subject_variable (sparql, "software"); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "rdfs:Resource"); - tracker_sparql_builder_delete_close (sparql); - - tracker_sparql_builder_where_open (sparql); - tracker_sparql_builder_subject_variable (sparql, "software"); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:Software"); - tracker_sparql_builder_where_close (sparql); - - /* (c) all elements which are nfo:softwareCategoryIcon of a given nfo:SoftwareCategory */ - tracker_sparql_builder_delete_open (sparql, TRACKER_OWN_GRAPH_URN); - tracker_sparql_builder_subject_variable (sparql, "icon"); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "rdfs:Resource"); - tracker_sparql_builder_delete_close (sparql); - - tracker_sparql_builder_where_open (sparql); - tracker_sparql_builder_subject_variable (sparql, "category"); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:SoftwareCategory"); - tracker_sparql_builder_subject_variable (sparql, "icon"); - tracker_sparql_builder_predicate (sparql, "nfo:softwareCategoryIcon"); - tracker_sparql_builder_object_variable (sparql, "category"); - tracker_sparql_builder_where_close (sparql); - - /* (d) all nfo:SoftwareCategory in our graph */ - tracker_sparql_builder_delete_open (sparql, TRACKER_OWN_GRAPH_URN); - tracker_sparql_builder_subject_variable (sparql, "category"); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "rdfs:Resource"); - tracker_sparql_builder_delete_close (sparql); - - tracker_sparql_builder_where_open (sparql); - tracker_sparql_builder_subject_variable (sparql, "category"); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:SoftwareCategory"); - tracker_sparql_builder_where_close (sparql); - - /* Execute a sync update, we don't want the apps miner to start before - * we finish this. */ - tracker_sparql_connection_update (tracker_miner_get_connection (miner), - tracker_sparql_builder_get_result (sparql), - G_PRIORITY_HIGH, - NULL, - &error); - - if (error) { - /* Some error happened performing the query, not good */ - g_critical ("Couldn't reset mined applications: %s", - error ? error->message : "unknown error"); - g_error_free (error); - } - - g_object_unref (sparql); -} - -static gboolean -detect_locale_changed (TrackerMiner *miner) -{ - gchar *locale_file; - gchar *previous_locale = NULL; - gchar *current_locale; - gboolean changed; - - locale_file = g_build_filename (g_get_user_cache_dir (), "tracker", LOCALE_FILENAME, NULL); - - if (G_LIKELY (g_file_test (locale_file, G_FILE_TEST_EXISTS))) { - gchar *contents; - - /* Check locale is correct */ - if (G_LIKELY (g_file_get_contents (locale_file, &contents, NULL, NULL))) { - if (contents && - contents[0] == '\0') { - g_critical (" Empty locale file found at '%s'", locale_file); - g_free (contents); - } else { - /* Re-use contents */ - previous_locale = contents; - } - } else { - g_critical (" Could not get content of file '%s'", locale_file); - } - } else { - g_message (" Could not find locale file:'%s'", locale_file); - } - - g_free (locale_file); - - current_locale = tracker_locale_get (TRACKER_LOCALE_LANGUAGE); - - /* Note that having both to NULL is actually valid, they would default - * to the unicode collation without locale-specific stuff. */ - if (g_strcmp0 (previous_locale, current_locale) != 0) { - g_message ("Locale change detected from '%s' to '%s'...", - previous_locale, current_locale); - changed = TRUE; - } else { - g_message ("Current and previous locales match: '%s'", previous_locale); - changed = FALSE; - } - - g_free (current_locale); - g_free (previous_locale); - - if (changed) { - g_message ("Locale change detected, so resetting miner to " - "remove all previously created items..."); - miner_applications_reset (miner); - } - - return changed; -} - -static gboolean -miner_applications_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - TrackerMinerFS *fs; - GError *inner_error = NULL; - TrackerIndexingTree *indexing_tree; - - fs = TRACKER_MINER_FS (initable); - indexing_tree = tracker_miner_fs_get_indexing_tree (fs); - - /* Set up files filter, deny every file, but - * those with a .desktop/directory extension - */ - tracker_indexing_tree_set_default_policy (indexing_tree, - TRACKER_FILTER_FILE, - TRACKER_FILTER_POLICY_DENY); - tracker_indexing_tree_add_filter (indexing_tree, - TRACKER_FILTER_FILE, - "*.desktop"); - tracker_indexing_tree_add_filter (indexing_tree, - TRACKER_FILTER_FILE, - "*.directory"); - - /* Chain up parent's initable callback before calling child's one */ - if (!miner_applications_initable_parent_iface->init (initable, cancellable, &inner_error)) { - g_propagate_error (error, inner_error); - return FALSE; - } - - g_signal_connect (fs, "finished", - G_CALLBACK (miner_finished_cb), - NULL); - - miner_applications_add_directories (fs); - - /* If the locales changed, we need to reset things first */ - detect_locale_changed (TRACKER_MINER (fs)); - - return TRUE; -} - -static void -insert_data_from_desktop_file (TrackerSparqlBuilder *sparql, - const gchar *subject, - const gchar *metadata_key, - GKeyFile *desktop_file, - const gchar *key, - const gchar *locale) -{ - gchar *str; - - if (locale) { - /* Try to get the key with our desired LANG locale... */ - str = g_key_file_get_locale_string (desktop_file, GROUP_DESKTOP_ENTRY, key, locale, NULL); - /* If our desired locale failed, use the list of LANG locales prepared by GLib - * (will return untranslated string if none of the locales available) */ - if (!str) { - str = g_key_file_get_locale_string (desktop_file, GROUP_DESKTOP_ENTRY, key, NULL, NULL); - } - } else { - str = g_key_file_get_string (desktop_file, GROUP_DESKTOP_ENTRY, key, NULL); - } - - if (str) { - tracker_sparql_builder_subject_iri (sparql, subject); - tracker_sparql_builder_predicate_iri (sparql, metadata_key); - tracker_sparql_builder_object_string (sparql, str); - g_free (str); - } -} - -static GKeyFile * -get_desktop_key_file (GFile *file, - gchar **type, - GError **error) -{ - GKeyFile *key_file; - gchar *path; - gchar *str; - - path = g_file_get_path (file); - key_file = g_key_file_new (); - *type = NULL; - - if (!g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, NULL)) { - g_set_error (error, miner_applications_error_quark, 0, "Couldn't load desktop file:'%s'", path); - g_key_file_free (key_file); - g_free (path); - return NULL; - } - - str = g_key_file_get_string (key_file, GROUP_DESKTOP_ENTRY, "Type", NULL); - - if (G_UNLIKELY (!str)) { - *type = NULL; - - g_set_error_literal (error, miner_applications_error_quark, 0, "Desktop file doesn't contain type"); - g_key_file_free (key_file); - g_free (path); - return NULL; - } else { - /* Sanitize type */ - *type = g_strstrip (str); - } - - g_free (path); - - return key_file; -} - -static void -process_directory (ProcessApplicationData *data, - GFileInfo *file_info, - GError **error) -{ - TrackerSparqlBuilder *sparql; - gchar *urn, *path, *uri; - - sparql = data->sparql; - - path = g_file_get_path (data->file); - uri = g_file_get_uri (data->file); - urn = tracker_sparql_escape_uri_printf ("urn:applications-dir:%s", path); - - tracker_sparql_builder_insert_silent_open (sparql, TRACKER_OWN_GRAPH_URN); - - tracker_sparql_builder_subject_iri (sparql, urn); - - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:FileDataObject"); - tracker_sparql_builder_object (sparql, "nie:DataObject"); - tracker_sparql_builder_object (sparql, "nie:Folder"); - - tracker_sparql_builder_predicate (sparql, "tracker:available"); - tracker_sparql_builder_object_boolean (sparql, TRUE); - - tracker_sparql_builder_predicate (sparql, "nie:isStoredAs"); - tracker_sparql_builder_object_iri (sparql, urn); - - tracker_sparql_builder_predicate (sparql, "nie:url"); - tracker_sparql_builder_object_string (sparql, uri); - - if (file_info) { - guint64 time; - - time = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_MODIFIED); - tracker_sparql_builder_predicate (sparql, "nfo:fileLastModified"); - tracker_sparql_builder_object_date (sparql, (time_t *) &time); - } - - tracker_sparql_builder_insert_close (data->sparql); - - g_free (path); - g_free (urn); - g_free (uri); -} - -static void -process_desktop_file (ProcessApplicationData *data, - GFileInfo *file_info, - GError **error) -{ - TrackerSparqlBuilder *sparql; - GKeyFile *key_file; - GFile *parent; - gchar *name = NULL; - gchar *path; - gchar *type; - gchar *filename; - gchar *uri = NULL; - GStrv cats; - gsize cats_len; - gboolean is_software = TRUE; - const gchar *parent_urn; - gchar *lang; - - sparql = data->sparql; - key_file = data->key_file; - type = data->type; - - path = g_file_get_path (data->file); - - /* Retrieve LANG locale setup */ - lang = tracker_locale_get (TRACKER_LOCALE_LANGUAGE); - - /* Try to get the categories with our desired LANG locale... */ - cats = g_key_file_get_locale_string_list (key_file, GROUP_DESKTOP_ENTRY, "Categories", lang, &cats_len, NULL); - if (!cats) { - /* If our desired locale failed, use the list of LANG locales prepared by GLib - * (will return untranslated string if none of the locales available) */ - cats = g_key_file_get_locale_string_list (key_file, GROUP_DESKTOP_ENTRY, "Categories", NULL, &cats_len, NULL); - } - - /* NOTE: We sanitize categories later on when iterating them */ - - if (!name) { - /* Try to get the name with our desired LANG locale... */ - name = g_key_file_get_locale_string (key_file, GROUP_DESKTOP_ENTRY, "Name", lang, NULL); - if (!name) { - /* If our desired locale failed, use the list of LANG locales prepared by GLib - * (will return untranslated string if none of the locales available) */ - name = g_key_file_get_locale_string (key_file, GROUP_DESKTOP_ENTRY, "Name", NULL, NULL); - } - } - - /* Sanitize name */ - if (name) { - g_strstrip (name); - } - - if (name && g_ascii_strcasecmp (type, "Directory") == 0) { - gchar *canonical_uri = tracker_sparql_escape_uri_printf (SOFTWARE_CATEGORY_URN_PREFIX "%s", path); - gchar *icon = g_key_file_get_string (key_file, GROUP_DESKTOP_ENTRY, "Icon", NULL); - - uri = canonical_uri; - tracker_sparql_builder_insert_silent_open (sparql, TRACKER_OWN_GRAPH_URN); - tracker_sparql_builder_subject_iri (sparql, uri); - - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:SoftwareCategory"); - - if (icon) { - gchar *escaped_icon; - gchar *icon_uri; - - /* Sanitize icon */ - g_strstrip (icon); - - escaped_icon = g_uri_escape_string (icon, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE); - - icon_uri = g_strdup_printf (THEME_ICON_URN_PREFIX "%s", escaped_icon); - - tracker_sparql_builder_subject_iri (sparql, icon_uri); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:Image"); - - tracker_sparql_builder_subject_iri (sparql, uri); - tracker_sparql_builder_predicate (sparql, "nfo:softwareCategoryIcon"); - tracker_sparql_builder_object_iri (sparql, icon_uri); - - g_free (icon_uri); - g_free (escaped_icon); - g_free (icon); - } - - is_software = FALSE; - } else if (name && g_ascii_strcasecmp (type, "Application") == 0) { - uri = g_file_get_uri (data->file); - tracker_sparql_builder_insert_silent_open (sparql, TRACKER_OWN_GRAPH_URN); - - tracker_sparql_builder_subject_iri (sparql, APPLICATION_DATASOURCE_URN); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nie:DataSource"); - - tracker_sparql_builder_subject_iri (sparql, uri); - - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:SoftwareApplication"); - tracker_sparql_builder_object (sparql, "nie:DataObject"); - - tracker_sparql_builder_predicate (sparql, "nie:dataSource"); - tracker_sparql_builder_object_iri (sparql, APPLICATION_DATASOURCE_URN); - } else if (name && g_ascii_strcasecmp (type, "Link") == 0) { - gchar *url = g_key_file_get_string (key_file, GROUP_DESKTOP_ENTRY, "URL", NULL); - - if (url) { - uri = g_file_get_uri (data->file); - tracker_sparql_builder_insert_silent_open (sparql, TRACKER_OWN_GRAPH_URN); - - tracker_sparql_builder_subject_iri (sparql, uri); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:Bookmark"); - - tracker_sparql_builder_predicate (sparql, "nfo:bookmarks"); - tracker_sparql_builder_object_iri (sparql, url); - - tracker_sparql_builder_predicate (sparql, "nie:dataSource"); - tracker_sparql_builder_object_iri (sparql, APPLICATION_DATASOURCE_URN); - - is_software = FALSE; - - g_free (url); - } else { - g_warning ("Invalid desktop file: '%s'", uri); - g_warning (" Type 'Link' requires a URL"); - } - } else { - /* Invalid type, all valid types are already listed above */ - uri = g_file_get_uri (data->file); - tracker_sparql_builder_insert_silent_open (sparql, TRACKER_OWN_GRAPH_URN); - - tracker_sparql_builder_subject_iri (sparql, APPLICATION_DATASOURCE_URN); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nie:DataSource"); - - tracker_sparql_builder_subject_iri (sparql, uri); - - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:SoftwareApplication"); - tracker_sparql_builder_object (sparql, "nie:DataObject"); - - tracker_sparql_builder_predicate (sparql, "nie:dataSource"); - tracker_sparql_builder_object_iri (sparql, APPLICATION_DATASOURCE_URN); - - if (name) { - /* If we got a name, then the issue comes from the type. - * As we're defaulting to Application here, we just g_debug() the problem. */ - g_debug ("Invalid desktop file: '%s'", uri); - g_debug (" Type '%s' is not part of the desktop file specification (expected 'Application', 'Link' or 'Directory')", type); - g_debug (" Defaulting to 'Application'"); - } else { - /* If we didn't get a name, the problem is more severe as we don't default it - * to anything, so we g_warning() it. */ - g_warning ("Invalid desktop file: '%s'", uri); - g_warning (" Couldn't get name, missing key (Name)"); - } - } - - if (uri) { - gchar *delete_properties_sparql; - gchar *desktop_file_uri; - - tracker_sparql_builder_predicate (sparql, "a"); - - if (is_software) { - tracker_sparql_builder_object (sparql, "nfo:Executable"); - } - - tracker_sparql_builder_object (sparql, "nfo:FileDataObject"); - tracker_sparql_builder_object (sparql, "nie:DataObject"); - - /* Apparently this gets added by the file-module ATM - tracker_sparql_builder_predicate (sparql, "tracker:available"); - tracker_sparql_builder_object_boolean (sparql, TRUE); */ - - /* We should always always have a proper name if the desktop file is correct - * w.r.t to the Freedesktop specs, but sometimes this is not true, so - * instead of passing wrong stuff to the SPARQL builder, we avoid it. - * If we don't have a proper name, we already warned it before. */ - if (name) { - tracker_sparql_builder_predicate (sparql, "nie:title"); - tracker_sparql_builder_object_string (sparql, name); - } - - if (is_software) { - gchar *icon; - - insert_data_from_desktop_file (sparql, - uri, - TRACKER_PREFIX_NIE "comment", - key_file, - "Comment", - lang); - insert_data_from_desktop_file (sparql, - uri, - TRACKER_PREFIX_NFO "softwareCmdLine", - key_file, - "Exec", - lang); - - icon = g_key_file_get_string (key_file, GROUP_DESKTOP_ENTRY, "Icon", NULL); - - if (icon) { - gchar *escaped_icon; - gchar *icon_uri; - - /* Sanitize icon */ - g_strstrip (icon); - - escaped_icon = g_uri_escape_string (icon, G_URI_RESERVED_CHARS_ALLOWED_IN_PATH, FALSE); - - icon_uri = g_strdup_printf (THEME_ICON_URN_PREFIX "%s", escaped_icon); - - tracker_sparql_builder_subject_iri (sparql, icon_uri); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:Image"); - - tracker_sparql_builder_subject_iri (sparql, uri); - tracker_sparql_builder_predicate (sparql, "nfo:softwareIcon"); - tracker_sparql_builder_object_iri (sparql, icon_uri); - - g_free (icon_uri); - g_free (escaped_icon); - g_free (icon); - } - } - - if (cats) { - gsize i; - - for (i = 0 ; cats[i] && i < cats_len ; i++) { - gchar *cat_uri; - gchar *cat; - - cat = cats[i]; - - if (!cat) { - continue; - } - - /* Sanitize category */ - g_strstrip (cat); - - cat_uri = tracker_sparql_escape_uri_printf (SOFTWARE_CATEGORY_URN_PREFIX "%s", cat); - - /* There are also .desktop - * files that describe these categories, but we can handle - * preemptively creating them if we visit a app .desktop - * file that mentions one that we don't yet know about */ - - tracker_sparql_builder_subject_iri (sparql, cat_uri); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:SoftwareCategory"); - - tracker_sparql_builder_predicate (sparql, "nie:title"); - tracker_sparql_builder_object_string (sparql, cat); - - tracker_sparql_builder_subject_iri (sparql, uri); - tracker_sparql_builder_predicate (sparql, "nie:isLogicalPartOf"); - tracker_sparql_builder_object_iri (sparql, cat_uri); - - g_free (cat_uri); - } - } - - filename = g_filename_display_basename (path); - tracker_sparql_builder_predicate (sparql, "nfo:fileName"); - tracker_sparql_builder_object_string (sparql, filename); - g_free (filename); - - /* The URL of the DataObject */ - desktop_file_uri = g_file_get_uri (data->file); - tracker_sparql_builder_predicate (sparql, "nie:url"); - tracker_sparql_builder_object_string (sparql, desktop_file_uri); - - /* Laying the link between the IE and the DO */ - tracker_sparql_builder_subject_iri (sparql, uri); - tracker_sparql_builder_predicate (sparql, "nie:isStoredAs"); - tracker_sparql_builder_object_iri (sparql, desktop_file_uri); - - - g_free (desktop_file_uri); - - /* Prepend a delete statement to delete previous properties from - * the miner, if any. - */ - delete_properties_sparql = - g_strdup_printf ("DELETE {" - " GRAPH <%s> {" - " <%s> ?p ?o" - " } " - "} " - "WHERE {" - " GRAPH <%s> {" - " <%s> ?p ?o" - " FILTER (?p != rdf:type && ?p != nie:contentCreated)" - " } " - "} " - "DELETE {" - " <%s> nie:url ?o" - "} WHERE {" - " <%s> nie:url ?o" - "}", - TRACKER_OWN_GRAPH_URN, uri, - TRACKER_OWN_GRAPH_URN, uri, - uri, uri); - - tracker_sparql_builder_prepend (sparql, delete_properties_sparql); - g_free (delete_properties_sparql); - } - - if (file_info) { - guint64 time; - - time = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_MODIFIED); - tracker_sparql_builder_predicate (sparql, "nfo:fileLastModified"); - tracker_sparql_builder_object_date (sparql, (time_t *) &time); - } - - parent = g_file_get_parent (data->file); - parent_urn = tracker_miner_fs_query_urn (TRACKER_MINER_FS (data->miner), parent); - g_object_unref (parent); - - if (parent_urn) { - tracker_sparql_builder_predicate (sparql, "nfo:belongsToContainer"); - tracker_sparql_builder_object_iri (sparql, parent_urn); - } - - tracker_sparql_builder_insert_close (sparql); - - g_strfreev (cats); - - g_free (uri); - g_free (path); - g_free (name); - g_free (lang); -} - -static void -process_application_data_free (ProcessApplicationData *data) -{ - g_object_unref (data->miner); - g_object_unref (data->file); - g_object_unref (data->sparql); - g_object_unref (data->cancellable); - g_object_unref (data->task); - g_free (data->type); - - if (data->key_file) { - g_key_file_free (data->key_file); - } - - g_slice_free (ProcessApplicationData, data); -} - -static void -process_file_cb (GObject *object, - GAsyncResult *result, - gpointer user_data) -{ - ProcessApplicationData *data; - GFileInfo *file_info; - GError *error = NULL; - GFile *file; - - data = user_data; - file = G_FILE (object); - file_info = g_file_query_info_finish (file, result, &error); - - if (error) { - tracker_miner_fs_notify_finish (TRACKER_MINER_FS (data->miner), data->task, NULL, error); - process_application_data_free (data); - return; - } - - if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY) { - process_directory (data, file_info, &error); - } else { - data->key_file = get_desktop_key_file (file, &data->type, &error); - if (!data->key_file) { - gchar *uri; - - uri = g_file_get_uri (file); - g_warning ("Couldn't properly parse desktop file '%s': '%s'", - uri, - error ? error->message : "unknown error"); - g_free (uri); - g_clear_error (&error); - - error = g_error_new_literal (miner_applications_error_quark, 0, "File is not a key file"); - } else if (g_key_file_get_boolean (data->key_file, GROUP_DESKTOP_ENTRY, "Hidden", NULL)) { - error = g_error_new_literal (miner_applications_error_quark, 0, "Desktop file is 'hidden', not gathering metadata for it"); - } else { - process_desktop_file (data, file_info, &error); - } - } - - tracker_miner_fs_notify_finish (TRACKER_MINER_FS (data->miner), data->task, - tracker_sparql_builder_get_result (data->sparql), - error); - process_application_data_free (data); - - if (file_info) { - g_object_unref (file_info); - } -} - -static gboolean -miner_applications_process_file (TrackerMinerFS *fs, - GFile *file, - GTask *task) -{ - ProcessApplicationData *data; - const gchar *attrs; - - data = g_slice_new0 (ProcessApplicationData); - data->miner = g_object_ref (fs); - data->sparql = tracker_sparql_builder_new_update (); - data->file = g_object_ref (file); - data->cancellable = g_object_ref (g_task_get_cancellable (task)); - data->task = g_object_ref (task); - - attrs = G_FILE_ATTRIBUTE_TIME_MODIFIED "," - G_FILE_ATTRIBUTE_STANDARD_TYPE; - - g_file_query_info_async (file, - attrs, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - G_PRIORITY_DEFAULT, - data->cancellable, - process_file_cb, - data); - - return TRUE; -} - -static gboolean -miner_applications_process_file_attributes (TrackerMinerFS *fs, - GFile *file, - GTask *task) -{ - gchar *uri; - - /* We don't care about file attribute changes here */ - uri = g_file_get_uri (file); - g_debug ("Ignoring file attribute changes in '%s'", uri); - g_free (uri); - - return FALSE; -} - -static gchar * -miner_applications_remove_file (TrackerMinerFS *fs, - GFile *file) -{ - gchar *uri, *sparql; - - uri = g_file_get_uri (file); - sparql = g_strdup_printf ("DELETE {" - " ?u a rdfs:Resource" - "} WHERE {" - " ?u nie:url \"%s\"" - "}", uri); - g_free (uri); - - return sparql; -} - -TrackerMiner * -tracker_miner_applications_new (GError **error) -{ - return g_initable_new (TRACKER_TYPE_MINER_APPLICATIONS, - NULL, - error, - "processing-pool-wait-limit", 10, - "processing-pool-ready-limit", 100, - NULL); -} diff --git a/src/miners/apps/tracker-miner-applications.h b/src/miners/apps/tracker-miner-applications.h deleted file mode 100644 index acf7ac6aa..000000000 --- a/src/miners/apps/tracker-miner-applications.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_MINER_FS_APPLICATIONS_H__ -#define __TRACKER_MINER_FS_APPLICATIONS_H__ - -#include <libtracker-miner/tracker-miner.h> - -G_BEGIN_DECLS - -#define TRACKER_TYPE_MINER_APPLICATIONS (tracker_miner_applications_get_type()) -#define TRACKER_MINER_APPLICATIONS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_MINER_APPLICATIONS, TrackerMinerApplications)) -#define TRACKER_MINER_APPLICATIONS_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_MINER_APPLICATIONS, TrackerMinerApplicationsClass)) -#define TRACKER_IS_MINER_APPLICATIONS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_MINER_APPLICATIONS)) -#define TRACKER_IS_MINER_APPLICATIONS_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_MINER_APPLICATIONS)) -#define TRACKER_MINER_APPLICATIONS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_MINER_APPLICATIONS, TrackerMinerApplicationsClass)) - -typedef struct _TrackerMinerApplications TrackerMinerApplications; -typedef struct _TrackerMinerApplicationsClass TrackerMinerApplicationsClass; - -struct _TrackerMinerApplications { - TrackerMinerFS parent_instance; - gpointer locale_notification_id; -}; - -struct _TrackerMinerApplicationsClass { - TrackerMinerFSClass parent_class; -}; - -GType tracker_miner_applications_get_type (void) G_GNUC_CONST; -TrackerMiner *tracker_miner_applications_new (GError **error); -gboolean tracker_miner_applications_detect_locale_changed (TrackerMiner *miner); - -G_END_DECLS - -#endif /* __TRACKER_MINER_FS_APPLICATIONS_H__ */ diff --git a/src/miners/apps/tracker-miner-apps.desktop.in.in b/src/miners/apps/tracker-miner-apps.desktop.in.in deleted file mode 100644 index 12b49ea5f..000000000 --- a/src/miners/apps/tracker-miner-apps.desktop.in.in +++ /dev/null @@ -1,18 +0,0 @@ -[Desktop Entry] -_Name=Tracker Application Miner -_Comment=Indexes information about applications installed -Icon= -Exec=@libexecdir@/tracker-miner-apps -Terminal=false -Type=Application -Categories=Utility; -X-GNOME-Autostart-enabled=true -X-KDE-autostart-after=panel -X-KDE-StartupNotify=false -X-KDE-UniqueApplet=true -NoDisplay=true -OnlyShowIn=GNOME;KDE;XFCE;X-IVI;Unity; -X-GNOME-Bugzilla-Bugzilla=GNOME -X-GNOME-Bugzilla-Product=tracker -X-GNOME-Bugzilla-Component=Miners -X-GNOME-Bugzilla-Version=@VERSION@ diff --git a/src/miners/apps/tracker-miner-apps.service.in b/src/miners/apps/tracker-miner-apps.service.in deleted file mode 100644 index 49b78c0a5..000000000 --- a/src/miners/apps/tracker-miner-apps.service.in +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Tracker applications data miner - -[Service] -Type=dbus -BusName=org.freedesktop.Tracker1.Miner.Applications -ExecStart=@libexecdir@/tracker-miner-apps -Restart=on-failure -# Don't restart after tracker daemon -k (aka tracker-control -k) -RestartPreventExitStatus=SIGKILL diff --git a/src/miners/fs/.gitignore b/src/miners/fs/.gitignore deleted file mode 100644 index 019715094..000000000 --- a/src/miners/fs/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -tracker-miner-fs -*.service -*.xml -*.valid -*.cfg.5 diff --git a/src/miners/fs/Makefile.am b/src/miners/fs/Makefile.am deleted file mode 100644 index 9ba5e97b0..000000000 --- a/src/miners/fs/Makefile.am +++ /dev/null @@ -1,124 +0,0 @@ -AM_CPPFLAGS = \ - $(BUILD_CFLAGS) \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - -DSHAREDIR=\""$(datadir)"\" \ - -DLOCALEDIR=\""$(localedir)"\" \ - -DLIBEXEC_PATH=\""$(libexecdir)"\" \ - $(TRACKER_MINER_FS_CFLAGS) - -libexec_PROGRAMS = tracker-miner-fs - -# Prefer UPower for the power data if it's available, else fall back to HAL -if HAVE_UPOWER -power_headers = \ - tracker-power.h -power_sources = \ - tracker-power-upower.c -else -if HAVE_HAL -power_headers = \ - tracker-power.h -power_sources = \ - tracker-power-hal.c -endif -endif - -tracker_miner_fs_SOURCES = \ - $(power_sources) \ - $(power_headers) \ - tracker-config.c \ - tracker-config.h \ - tracker-extract-watchdog.c \ - tracker-extract-watchdog.h \ - tracker-main.c \ - tracker-miner-files.c \ - tracker-miner-files.h \ - tracker-miner-files-index.c \ - tracker-miner-files-index.h \ - tracker-miner-files-peer-listener.c \ - tracker-miner-files-peer-listener.h \ - tracker-storage.c \ - tracker-storage.h \ - tracker-thumbnailer.c \ - tracker-thumbnailer.h \ - tracker-writeback-listener.c \ - tracker-writeback-listener.h \ - tracker-writeback-dispatcher.c \ - tracker-writeback-dispatcher.h \ - tracker-writeback.c \ - tracker-writeback.h - -tracker_miner_fs_LDADD = \ - $(top_builddir)/src/libtracker-miner/libtracker-miner-@TRACKER_API_VERSION@.la \ - $(top_builddir)/src/libtracker-sparql-backend/libtracker-sparql-@TRACKER_API_VERSION@.la \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-data/libtracker-data.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_MINER_FS_LIBS) - -# DBus interfaces (XML files) and services -configdir = $(datadir)/tracker -config_DATA = tracker-miner-files-index.xml - -%.service.in: %.service.in.in - @sed -e "s|@libexecdir[@]|${libexecdir}|" $< > $@ - -servicedir = $(DBUS_SERVICES_DIR) -service_DATA = org.freedesktop.Tracker1.Miner.Files.service - -INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -d -u' -@INTLTOOL_SERVICE_RULE@ - -tracker-miner-fs.service: tracker-miner-fs.service.in Makefile - @sed -e "s|@libexecdir[@]|${libexecdir}|" $< > $@ - -systemd_userdir = $(prefix)/lib/systemd/user -systemd_user_DATA = tracker-miner-fs.service - -install-data-hook: - $(MKDIR_P) "$(DESTDIR)$(datadir)/tracker/miners" && \ - $(LN_S) -f "$(servicedir)/$(service_DATA)" \ - "$(DESTDIR)$(datadir)/tracker/miners/$(service_DATA)" - -uninstall-local: - $(RM) "$(DESTDIR)$(datadir)/tracker/miners/$(service_DATA)" && \ - $(RM) "$(servicedir)/$(service_DATA)" - -# Desktop files: First we fix the VERSION and libexecdir -%.desktop.in: %.desktop.in.in - @sed -e "s|@libexecdir[@]|${libexecdir}|" \ - -e "s|@VERSION[@]|${VERSION}|" $< > $@ - -autostartdir = $(sysconfdir)/xdg/autostart -autostart_DATA = tracker-miner-fs.desktop - -@INTLTOOL_DESKTOP_RULE@ - -# Configuration / GSettings -gsettings_ENUM_NAMESPACE = org.freedesktop.Tracker -gsettings_ENUM_FILES = $(top_srcdir)/src/libtracker-common/tracker-enums.h - -gsettings_SCHEMAS = org.freedesktop.Tracker.Miner.Files.gschema.xml - -@INTLTOOL_XML_NOMERGE_RULE@ - -@GSETTINGS_RULES@ - -# Dist / Clean rules for all data -CLEANFILES = \ - $(autostart_DATA) \ - $(autostart_DATA:.desktop=.desktop.in) \ - $(service_DATA) \ - $(service_DATA:.service=.service.in) \ - $(systemd_user_DATA) \ - $(gsettings_SCHEMAS) - -EXTRA_DIST = \ - $(autostart_DATA:.desktop=.desktop.in.in) \ - $(config_DATA) \ - $(service_DATA:.service=.service.in.in) \ - $(systemd_user_DATA:.service=.service.in) \ - $(gsettings_SCHEMAS:.xml=.xml.in) \ - meson.build diff --git a/src/miners/fs/meson.build b/src/miners/fs/meson.build deleted file mode 100644 index 65bc6c73b..000000000 --- a/src/miners/fs/meson.build +++ /dev/null @@ -1,79 +0,0 @@ -sources = [ - 'tracker-config.c', - 'tracker-extract-watchdog.c', - 'tracker-main.c', - 'tracker-miner-files.c', - 'tracker-miner-files-index.c', - 'tracker-miner-files-peer-listener.c', - 'tracker-storage.c', - 'tracker-thumbnailer.c', - 'tracker-writeback-listener.c', - 'tracker-writeback-dispatcher.c', - 'tracker-writeback.c', -] - -tracker_miner_fs_deps = [ - tracker_common_dep, - tracker_miner_dep, - tracker_extract_dep -] - -if battery_detection_library_name == 'upower' - sources += 'tracker-power-upower.c' - tracker_miner_fs_deps += upower -elif battery_detection_library_name == 'hal' - sources += 'tracker-power-hal.c' - tracker_miner_fs_deps += hal -endif - -executable('tracker-miner-fs', sources, - dependencies: tracker_miner_fs_deps, - c_args: tracker_c_args, - install: true, - install_dir: get_option('libexecdir'), - install_rpath: tracker_internal_libs_dir, -) - -install_data( - sources: 'tracker-miner-files-index.xml', - install_dir: join_paths(get_option('datadir'), 'tracker')) - -dbus_service_file_untranslated = configure_file( - input: 'org.freedesktop.Tracker1.Miner.Files.service.in.in', - output: 'org.freedesktop.Tracker1.Miner.Files.service.in', - configuration: conf) - -dbus_service_file = custom_target('tracker-miner-files-dbus-service-file', - input: dbus_service_file_untranslated, - output: 'org.freedesktop.Tracker1.Miner.Files.service', - command: ['intltool-merge', '--quiet', '--desktop-style', '--utf8', join_paths(meson.source_root(), 'po'), '@INPUT@', '@OUTPUT@'], - install: true, - install_dir: dbus_services_dir) - -desktop_file_untranslated = configure_file( - input: 'tracker-miner-fs.desktop.in.in', - output: 'tracker-miner-fs.desktop.in', - configuration: conf) - -desktop_file = custom_target('tracker-miner-fs-desktop-file', - input: desktop_file_untranslated, - output: 'tracker-miner-fs.desktop', - command: ['intltool-merge', '--quiet', '--desktop-style', '--utf8', join_paths(meson.source_root(), 'po'), '@INPUT@', '@OUTPUT@'], - install: true, - install_dir: join_paths(get_option('sysconfdir'), 'xdg/autostart')) - -custom_target('tracker-miner-fs-settings-schema', - input: 'org.freedesktop.Tracker.Miner.Files.gschema.xml.in', - output: 'org.freedesktop.Tracker.Miner.Files.gschema.xml', - command: ['intltool-merge', '--quiet', '--xml-style', '--utf8', join_paths(meson.source_root(), 'po'), '@INPUT@', '@OUTPUT@'], - install: true, - install_dir: join_paths(get_option('datadir'), 'glib-2.0', 'schemas')) - -if install_systemd_user_services - configure_file( - input: 'tracker-miner-fs.service.in', - output: 'tracker-miner-fs.service', - configuration: conf, - install: true, - install_dir: systemd_user_services_dir) -endif diff --git a/src/miners/fs/org.freedesktop.Tracker.Miner.Files.gschema.xml.in b/src/miners/fs/org.freedesktop.Tracker.Miner.Files.gschema.xml.in deleted file mode 100644 index 44a7472d9..000000000 --- a/src/miners/fs/org.freedesktop.Tracker.Miner.Files.gschema.xml.in +++ /dev/null @@ -1,162 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -Copyright (C) 2011, Nokia <ivan.frade@nokia.com> - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. ---> -<schemalist> - <schema id="org.freedesktop.Tracker.Miner.Files" path="/org/freedesktop/tracker/miner/files/" gettext-domain="tracker"> - <key name="verbosity" enum="org.freedesktop.Tracker.TrackerVerbosity"> - <default>'errors'</default> - <_summary>Log verbosity</_summary> - <_description>Log verbosity.</_description> - </key> - - <key name="initial-sleep" type="i"> - <_summary>Initial sleep</_summary> - <_description>Initial sleep time, in seconds.</_description> - <range min="0" max="1000"/> - <default>15</default> - </key> - - <key name="sched-idle" enum="org.freedesktop.Tracker.TrackerSchedIdle"> - <default>'first-index'</default> - <_summary>Scheduler priority when idle</_summary> - <_description> - The scheduler is the kernel component that decides which - runnable application will be executed by the CPU next. Each - application has an associated scheduling policy and priority. - </_description> - </key> - - <key name="throttle" type="i"> - <_summary>Throttle</_summary> - <_description>Indexing speed, the higher the slower.</_description> - <range min="0" max="20"/> - <default>0</default> - </key> - - <key name="low-disk-space-limit" type="i"> - <_summary>Low disk space limit</_summary> - <_description>Disk space threshold in percent at which to pause indexing, or -1 to disable.</_description> - <range min="-1" max="100"/> - <default>-1</default> - </key> - - <key name="crawling-interval" type="i"> - <_summary>Crawling interval</_summary> - <_description> - Interval in days to check whether the filesystem is up to date in the database. - 0 forces crawling anytime, -1 forces it only after unclean shutdowns, and -2 - disables it entirely. - </_description> - <range min="-2" max="365"/> - <default>-1</default> - </key> - - <key name="removable-days-threshold" type="i"> - <_summary>Removable devices’ data permanence threshold</_summary> - <_description> - Threshold in days after which files from removables devices - will be removed from database if not mounted. 0 means never, - maximum is 365. - </_description> - <range min="0" max="365"/> - <default>3</default> - </key> - - <key name="enable-monitors" type="b"> - <_summary>Enable monitors</_summary> - <_description>Set to false to completely disable any file monitoring</_description> - <default>true</default> - </key> - - <key name="enable-writeback" type="b"> - <_summary>Enable writeback</_summary> - <_description>Set to false to completely disable any file writeback</_description> - <default>true</default> - </key> - - <key name="index-removable-devices" type="b"> - <_summary>Index removable devices</_summary> - <_description>Set to true to enable indexing mounted directories for removable devices.</_description> - <default>false</default> - </key> - - <key name="index-optical-discs" type="b"> - <_summary>Index optical discs</_summary> - <_description> - Set to true to enable indexing CDs, DVDs, and generally optical media - (if removable devices are not indexed, optical discs won’t be either) - </_description> - <default>false</default> - </key> - - <key name="index-on-battery" type="b"> - <_summary>Index when running on battery</_summary> - <_description>Set to true to index while running on battery</_description> - <default>true</default> - </key> - - <key name="index-on-battery-first-time" type="b"> - <_summary>Perform initial indexing when running on battery</_summary> - <_description>Set to true to index while running on battery for the first time only</_description> - <default>true</default> - </key> - - <key name="index-recursive-directories" type="as"> - <_summary>Directories to index recursively</_summary> - <_description> - List of directories to index recursively, Special values include: - &DESKTOP, &DOCUMENTS, &DOWNLOAD, &MUSIC, &PICTURES, - &PUBLIC_SHARE, &TEMPLATES, &VIDEOS. - - See /etc/xdg/user-dirs.defaults and $HOME/.config/user-dirs.default - </_description> - <default>[ '&DESKTOP', '&DOCUMENTS', '&DOWNLOAD', '&MUSIC', '&PICTURES', '&VIDEOS' ]</default> - </key> - - <key name="index-single-directories" type="as"> - <_summary>Directories to index non-recursively</_summary> - <_description> - List of directories to index without inspecting subfolders, Special values include: - &DESKTOP, &DOCUMENTS, &DOWNLOAD, &MUSIC, &PICTURES, - &PUBLIC_SHARE, &TEMPLATES, &VIDEOS. - - See /etc/xdg/user-dirs.defaults and $HOME/.config/user-dirs.default - </_description> - <default>[ '$HOME' ]</default> - </key> - - <key name="ignored-files" type="as"> - <_summary>Ignored files</_summary> - <_description>List of file patterns to avoid</_description> - <default>[ '*~', '*.o', '*.la', '*.lo' , '*.loT', '*.in', '*.csproj', '*.m4', '*.rej', '*.gmo', '*.orig', '*.pc', '*.omf', '*.aux', '*.tmp', '*.po', '*.vmdk', '*.vm*', '*.nvram', '*.part', '*.rcore', '*.lzo', 'autom4te', 'conftest', 'confstat', 'Makefile', 'SCCS', 'ltmain.sh', 'libtool', 'config.status', 'confdefs.h', 'configure', '#*#', '~$*.doc?', '~$*.dot?', '~$*.xls?', '~$*.xlt?', '~$*.xlam', '~$*.ppt?', '~$*.pot?', '~$*.ppam', '~$*.ppsm', '~$*.ppsx', '~$*.vsd?', '~$*.vss?', '~$*.vst?', '*.desktop', '*.directory' ]</default> - </key> - - <key name="ignored-directories" type="as"> - <_summary>Ignored directories</_summary> - <_description>List of directories to avoid</_description> - <default>[ 'po', 'CVS', 'core-dumps', 'lost+found' ]</default> - </key> - - <key name="ignored-directories-with-content" type="as"> - <_summary>Ignored directories with content</_summary> - <_description>Avoid any directory containing a file blacklisted here</_description> - <default>[ '.trackerignore', '.git' ]</default> - </key> - </schema> -</schemalist> diff --git a/src/miners/fs/org.freedesktop.Tracker1.Miner.Files.service.in.in b/src/miners/fs/org.freedesktop.Tracker1.Miner.Files.service.in.in deleted file mode 100644 index a61719947..000000000 --- a/src/miners/fs/org.freedesktop.Tracker1.Miner.Files.service.in.in +++ /dev/null @@ -1,10 +0,0 @@ -[D-BUS Service] -Name=org.freedesktop.Tracker1.Miner.Files -Exec=@libexecdir@/tracker-miner-fs -SystemdService=tracker-miner-fs.service - -# Miner details needed for tracker-control -Path=/org/freedesktop/Tracker1/Miner/Files -NameSuffix=Miner.Files -_DisplayName=File System -_Comment=File system data miner diff --git a/src/miners/fs/tracker-config.c b/src/miners/fs/tracker-config.c deleted file mode 100644 index 415b9004b..000000000 --- a/src/miners/fs/tracker-config.c +++ /dev/null @@ -1,1239 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * Copyright (C) 2014, Lanedo <martyn@lanedo.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <string.h> -#include <stdlib.h> - -#include <glib.h> -#include <gio/gio.h> - -#define G_SETTINGS_ENABLE_BACKEND -#include <gio/gsettingsbackend.h> - -#include <libtracker-common/tracker-common.h> - -#include "tracker-config.h" - -#define CONFIG_SCHEMA "org.freedesktop.Tracker.Miner.Files" -#define CONFIG_PATH "/org/freedesktop/tracker/miner/files/" - -/* Default values */ -#define DEFAULT_VERBOSITY 0 -#define DEFAULT_SCHED_IDLE 1 -#define DEFAULT_INITIAL_SLEEP 15 /* 0->1000 */ -#define DEFAULT_ENABLE_MONITORS TRUE -#define DEFAULT_THROTTLE 0 /* 0->20 */ -#define DEFAULT_INDEX_REMOVABLE_DEVICES FALSE -#define DEFAULT_INDEX_OPTICAL_DISCS FALSE -#define DEFAULT_INDEX_ON_BATTERY FALSE -#define DEFAULT_INDEX_ON_BATTERY_FIRST_TIME TRUE -#define DEFAULT_LOW_DISK_SPACE_LIMIT 1 /* 0->100 / -1 */ -#define DEFAULT_CRAWLING_INTERVAL -1 /* 0->365 / -1 / -2 */ -#define DEFAULT_REMOVABLE_DAYS_THRESHOLD 3 /* 1->365 / 0 */ -#define DEFAULT_ENABLE_WRITEBACK FALSE - -typedef struct { - /* IMPORTANT: There are 3 versions of the directories: - * 1. a GStrv stored in GSettings - * 2. a GSList stored here which is the GStrv without any - * aliases or duplicates resolved. - * 3. a GSList stored here which has duplicates and aliases - * resolved. - */ - GSList *index_recursive_directories; - GSList *index_recursive_directories_unfiltered; - GSList *index_single_directories; - GSList *index_single_directories_unfiltered; - GSList *ignored_directories; - GSList *ignored_directories_with_content; - GSList *ignored_files; - - /* Convenience data */ - GSList *ignored_directory_patterns; - GSList *ignored_directory_paths; - GSList *ignored_file_patterns; - GSList *ignored_file_paths; -} TrackerConfigPrivate; - -static void config_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); -static void config_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); -static void config_finalize (GObject *object); -static void config_constructed (GObject *object); -static void config_set_index_recursive_directories (TrackerConfig *config, - GSList *roots); -static void config_set_index_single_directories (TrackerConfig *config, - GSList *roots); -static void config_set_ignored_directories (TrackerConfig *config, - GSList *roots); -static void config_set_ignored_directories_with_content (TrackerConfig *config, - GSList *roots); -static void config_set_ignored_files (TrackerConfig *config, - GSList *files); - -enum { - PROP_0, - - /* General */ - PROP_VERBOSITY, - PROP_SCHED_IDLE, - PROP_INITIAL_SLEEP, - - /* Monitors */ - PROP_ENABLE_MONITORS, - - /* Indexing */ - PROP_THROTTLE, - PROP_INDEX_ON_BATTERY, - PROP_INDEX_ON_BATTERY_FIRST_TIME, - PROP_INDEX_REMOVABLE_DEVICES, - PROP_INDEX_OPTICAL_DISCS, - PROP_LOW_DISK_SPACE_LIMIT, - PROP_INDEX_RECURSIVE_DIRECTORIES, - PROP_INDEX_SINGLE_DIRECTORIES, - PROP_IGNORED_DIRECTORIES, - PROP_IGNORED_DIRECTORIES_WITH_CONTENT, - PROP_IGNORED_FILES, - PROP_CRAWLING_INTERVAL, - PROP_REMOVABLE_DAYS_THRESHOLD, - - /* Writeback */ - PROP_ENABLE_WRITEBACK - -}; - -G_DEFINE_TYPE (TrackerConfig, tracker_config, G_TYPE_SETTINGS) - -static void -tracker_config_class_init (TrackerConfigClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = config_set_property; - object_class->get_property = config_get_property; - object_class->finalize = config_finalize; - object_class->constructed = config_constructed; - - /* General */ - g_object_class_install_property (object_class, - PROP_VERBOSITY, - g_param_spec_enum ("verbosity", - "Log verbosity", - "Log verbosity (0=errors, 1=minimal, 2=detailed, 3=debug)", - TRACKER_TYPE_VERBOSITY, - DEFAULT_VERBOSITY, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_SCHED_IDLE, - g_param_spec_enum ("sched-idle", - "Scheduler priority when idle", - "Scheduler priority when idle (0=always, 1=first-index, 2=never)", - TRACKER_TYPE_SCHED_IDLE, - DEFAULT_SCHED_IDLE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_INITIAL_SLEEP, - g_param_spec_int ("initial-sleep", - "Initial sleep", - "Time in seconds before crawling filesystem (0->1000)", - 0, - 1000, - DEFAULT_INITIAL_SLEEP, - G_PARAM_READWRITE)); - - /* Monitors */ - g_object_class_install_property (object_class, - PROP_ENABLE_MONITORS, - g_param_spec_boolean ("enable-monitors", - "Enable monitors", - "Set to false to completely disable any monitoring", - DEFAULT_ENABLE_MONITORS, - G_PARAM_READWRITE)); - - /* Indexing */ - g_object_class_install_property (object_class, - PROP_THROTTLE, - g_param_spec_int ("throttle", - "Throttle", - "Sets the indexing speed (0->20, where 20=slowest speed)", - 0, - 20, - DEFAULT_THROTTLE, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_INDEX_ON_BATTERY, - g_param_spec_boolean ("index-on-battery", - "Index on battery", - "Set to true to index while running on battery", - DEFAULT_INDEX_ON_BATTERY, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_INDEX_ON_BATTERY_FIRST_TIME, - g_param_spec_boolean ("index-on-battery-first-time", - "Index on battery first time", - "Set to true to index while running on battery for the first time only", - DEFAULT_INDEX_ON_BATTERY_FIRST_TIME, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_INDEX_REMOVABLE_DEVICES, - g_param_spec_boolean ("index-removable-devices", - "index removable devices", - "Set to true to enable traversing mounted directories for removable devices\n" - "(this includes optical discs)", - DEFAULT_INDEX_REMOVABLE_DEVICES, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_INDEX_OPTICAL_DISCS, - g_param_spec_boolean ("index-optical-discs", - "index optical discs", - "Set to true to enable traversing CDs, DVDs, and generally optical media\n" - "(if removable devices are not indexed, optical discs won't be either)", - DEFAULT_INDEX_OPTICAL_DISCS, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_LOW_DISK_SPACE_LIMIT, - g_param_spec_int ("low-disk-space-limit", - "Low disk space limit", - "Pause indexer when disk space is <= this value\n" - "(0->100, value is in % of $HOME file system, -1=disable pausing)", - -1, - 100, - DEFAULT_LOW_DISK_SPACE_LIMIT, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_INDEX_RECURSIVE_DIRECTORIES, - g_param_spec_boxed ("index-recursive-directories", - "Index recursive directories", - " List of directories to crawl recursively for indexing (separator=;)\n" - " Special values include: (see /etc/xdg/user-dirs.defaults & $HOME/.config/user-dirs.default)\n" - " &DESKTOP\n" - " &DOCUMENTS\n" - " &DOWNLOAD\n" - " &MUSIC\n" - " &PICTURES\n" - " &PUBLIC_SHARE\n" - " &TEMPLATES\n" - " &VIDEOS\n" - " If $HOME is the default below, it is because $HOME/.config/user-dirs.default was missing.", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_INDEX_SINGLE_DIRECTORIES, - g_param_spec_boxed ("index-single-directories", - "Index single directories", - " List of directories to index but not sub-directories for changes (separator=;)\n" - " Special values used for IndexRecursiveDirectories can also be used here", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_IGNORED_DIRECTORIES, - g_param_spec_boxed ("ignored-directories", - "Ignored directories", - " List of directories to NOT crawl for indexing (separator=;)", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_IGNORED_DIRECTORIES_WITH_CONTENT, - g_param_spec_boxed ("ignored-directories-with-content", - "Ignored directories with content", - " List of directories to NOT crawl for indexing based on child files (separator=;)", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_IGNORED_FILES, - g_param_spec_boxed ("ignored-files", - "Ignored files", - " List of files to NOT index (separator=;)", - G_TYPE_STRV, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_CRAWLING_INTERVAL, - g_param_spec_int ("crawling-interval", - "Crawling interval", - " Interval in days to check the filesystem is up to date in the database," - " maximum is 365, default is -1.\n" - " -2 = crawling is disabled entirely\n" - " -1 = crawling *may* occur on startup (if not cleanly shutdown)\n" - " 0 = crawling is forced", - -2, - 365, - DEFAULT_CRAWLING_INTERVAL, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_REMOVABLE_DAYS_THRESHOLD, - g_param_spec_int ("removable-days-threshold", - "Removable days threshold", - " Threshold in days after which files from removables devices" - " will be removed from database if not mounted. 0 means never, " - " maximum is 365.", - 0, - 365, - DEFAULT_REMOVABLE_DAYS_THRESHOLD, - G_PARAM_READWRITE)); - - /* Writeback */ - g_object_class_install_property (object_class, - PROP_ENABLE_WRITEBACK, - g_param_spec_boolean ("enable-writeback", - "Enable Writeback", - "Set to false to disable writeback", - DEFAULT_ENABLE_WRITEBACK, - G_PARAM_READWRITE)); - - g_type_class_add_private (object_class, sizeof (TrackerConfigPrivate)); -} - -static void -tracker_config_init (TrackerConfig *object) -{ - object->priv = G_TYPE_INSTANCE_GET_PRIVATE (object, TRACKER_TYPE_CONFIG, TrackerConfigPrivate); -} - -static void -config_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - TrackerConfig *config = TRACKER_CONFIG (object); - - switch (param_id) { - /* General */ - /* NOTE: We handle these because we have to be able - * to save these based on command line overrides. - */ - case PROP_VERBOSITY: - tracker_config_set_verbosity (config, g_value_get_enum (value)); - break; - case PROP_INITIAL_SLEEP: - tracker_config_set_initial_sleep (config, g_value_get_int (value)); - break; - - /* Indexing */ - /* NOTE: We handle these specifically because we - * create convenience data around these lists. - */ - case PROP_INDEX_RECURSIVE_DIRECTORIES: { - GStrv strv = g_value_get_boxed (value); - GSList *dirs = tracker_string_list_to_gslist (strv, -1); - - config_set_index_recursive_directories (config, dirs); - - g_slist_foreach (dirs, (GFunc) g_free, NULL); - g_slist_free (dirs); - - break; - } - case PROP_INDEX_SINGLE_DIRECTORIES: { - GStrv strv = g_value_get_boxed (value); - GSList *dirs = tracker_string_list_to_gslist (strv, -1); - - config_set_index_single_directories (config, dirs); - - g_slist_foreach (dirs, (GFunc) g_free, NULL); - g_slist_free (dirs); - break; - } - case PROP_IGNORED_DIRECTORIES: { - GStrv strv = g_value_get_boxed (value); - GSList *dirs = tracker_string_list_to_gslist (strv, -1); - - config_set_ignored_directories (config, dirs); - - g_slist_foreach (dirs, (GFunc) g_free, NULL); - g_slist_free (dirs); - break; - } - case PROP_IGNORED_DIRECTORIES_WITH_CONTENT: { - GStrv strv = g_value_get_boxed (value); - GSList *dirs = tracker_string_list_to_gslist (strv, -1); - - config_set_ignored_directories_with_content (config, dirs); - - g_slist_foreach (dirs, (GFunc) g_free, NULL); - g_slist_free (dirs); - break; - } - case PROP_IGNORED_FILES: { - GStrv strv = g_value_get_boxed (value); - GSList *files = tracker_string_list_to_gslist (strv, -1); - - config_set_ignored_files (config, files); - - g_slist_foreach (files, (GFunc) g_free, NULL); - g_slist_free (files); - break; - } - default: - /* We don't care about the others... we don't save anyway. */ - break; - }; -} - -static void -config_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - TrackerConfig *config = TRACKER_CONFIG (object); - TrackerConfigPrivate *priv = config->priv; - - switch (param_id) { - /* General */ - case PROP_VERBOSITY: - g_value_set_enum (value, tracker_config_get_verbosity (config)); - break; - case PROP_SCHED_IDLE: - g_value_set_enum (value, tracker_config_get_sched_idle (config)); - break; - case PROP_INITIAL_SLEEP: - g_value_set_int (value, tracker_config_get_initial_sleep (config)); - break; - - /* Montors */ - case PROP_ENABLE_MONITORS: - g_value_set_boolean (value, tracker_config_get_enable_monitors (config)); - break; - - /* Indexing */ - case PROP_THROTTLE: - g_value_set_int (value, tracker_config_get_throttle (config)); - break; - case PROP_INDEX_ON_BATTERY: - g_value_set_boolean (value, tracker_config_get_index_on_battery (config)); - break; - case PROP_INDEX_ON_BATTERY_FIRST_TIME: - g_value_set_boolean (value, tracker_config_get_index_on_battery_first_time (config)); - break; - case PROP_INDEX_REMOVABLE_DEVICES: - g_value_set_boolean (value, tracker_config_get_index_removable_devices (config)); - break; - case PROP_INDEX_OPTICAL_DISCS: - g_value_set_boolean (value, tracker_config_get_index_optical_discs (config)); - break; - case PROP_LOW_DISK_SPACE_LIMIT: - g_value_set_int (value, tracker_config_get_low_disk_space_limit (config)); - break; - case PROP_INDEX_RECURSIVE_DIRECTORIES: - g_value_take_boxed (value, tracker_gslist_to_string_list (priv->index_recursive_directories_unfiltered)); - break; - case PROP_INDEX_SINGLE_DIRECTORIES: - g_value_take_boxed (value, tracker_gslist_to_string_list (priv->index_single_directories_unfiltered)); - break; - case PROP_IGNORED_DIRECTORIES: - g_value_take_boxed (value, tracker_gslist_to_string_list (priv->ignored_directories)); - break; - case PROP_IGNORED_DIRECTORIES_WITH_CONTENT: - g_value_take_boxed (value, tracker_gslist_to_string_list (priv->ignored_directories_with_content)); - break; - case PROP_IGNORED_FILES: - g_value_take_boxed (value, tracker_gslist_to_string_list (priv->ignored_files)); - break; - case PROP_CRAWLING_INTERVAL: - g_value_set_int (value, tracker_config_get_crawling_interval (config)); - break; - case PROP_REMOVABLE_DAYS_THRESHOLD: - g_value_set_int (value, tracker_config_get_removable_days_threshold (config)); - break; - - /* Writeback */ - case PROP_ENABLE_WRITEBACK: - g_value_set_boolean (value, tracker_config_get_enable_writeback (config)); - break; - - /* Did we miss any new properties? */ - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - }; -} - -static void -config_finalize (GObject *object) -{ - TrackerConfigPrivate *priv; - - priv = TRACKER_CONFIG (object)->priv; - - g_slist_foreach (priv->ignored_file_patterns, - (GFunc) g_pattern_spec_free, - NULL); - g_slist_free (priv->ignored_file_patterns); - - g_slist_foreach (priv->ignored_file_paths, - (GFunc) g_free, - NULL); - g_slist_free (priv->ignored_file_paths); - - g_slist_foreach (priv->ignored_directory_patterns, - (GFunc) g_pattern_spec_free, - NULL); - g_slist_free (priv->ignored_directory_patterns); - - g_slist_foreach (priv->ignored_directory_paths, - (GFunc) g_free, - NULL); - g_slist_free (priv->ignored_directory_paths); - - g_slist_foreach (priv->ignored_files, (GFunc) g_free, NULL); - g_slist_free (priv->ignored_files); - - g_slist_foreach (priv->ignored_directories_with_content, (GFunc) g_free, NULL); - g_slist_free (priv->ignored_directories_with_content); - - g_slist_foreach (priv->ignored_directories, (GFunc) g_free, NULL); - g_slist_free (priv->ignored_directories); - - g_slist_foreach (priv->index_single_directories, (GFunc) g_free, NULL); - g_slist_free (priv->index_single_directories); - - g_slist_foreach (priv->index_single_directories_unfiltered, (GFunc) g_free, NULL); - g_slist_free (priv->index_single_directories_unfiltered); - - g_slist_foreach (priv->index_recursive_directories, (GFunc) g_free, NULL); - g_slist_free (priv->index_recursive_directories); - - g_slist_foreach (priv->index_recursive_directories_unfiltered, (GFunc) g_free, NULL); - g_slist_free (priv->index_recursive_directories_unfiltered); - - (G_OBJECT_CLASS (tracker_config_parent_class)->finalize) (object); -} - -static GSList * -dir_mapping_get (GSList *dirs, - gboolean is_recursive) -{ - GSList *filtered = NULL; - GSList *evaluated_dirs, *l; - - if (dirs) { - filtered = tracker_path_list_filter_duplicates (dirs, ".", is_recursive); - } - - evaluated_dirs = NULL; - - for (l = filtered; l; l = l->next) { - gchar *path_to_use; - - path_to_use = tracker_path_evaluate_name (l->data); - - if (path_to_use) { - evaluated_dirs = g_slist_prepend (evaluated_dirs, path_to_use); - } - } - - g_slist_foreach (filtered, (GFunc) g_free, NULL); - g_slist_free (filtered); - - return g_slist_reverse (evaluated_dirs); -} - -static void -config_set_ignored_file_conveniences (TrackerConfig *config) -{ - TrackerConfigPrivate *priv; - GSList *l; - GSList *paths = NULL; - GSList *patterns = NULL; - - priv = config->priv; - - g_slist_foreach (priv->ignored_file_patterns, - (GFunc) g_pattern_spec_free, - NULL); - g_slist_free (priv->ignored_file_patterns); - - g_slist_foreach (priv->ignored_file_paths, - (GFunc) g_free, - NULL); - g_slist_free (priv->ignored_file_paths); - - for (l = priv->ignored_files; l; l = l->next) { - const gchar *str = l->data; - - if (!str) { - continue; - } - - if (G_LIKELY (*str != G_DIR_SEPARATOR)) { - GPatternSpec *spec; - - spec = g_pattern_spec_new (l->data); - patterns = g_slist_prepend (patterns, spec); - } else { - paths = g_slist_prepend (paths, g_strdup (l->data)); - } - } - - priv->ignored_file_patterns = g_slist_reverse (patterns); - priv->ignored_file_paths = g_slist_reverse (paths); -} - -static void -config_set_ignored_directory_conveniences (TrackerConfig *config) -{ - TrackerConfigPrivate *priv; - GSList *l; - GSList *patterns = NULL; - GSList *paths = NULL; - - priv = config->priv; - - g_slist_foreach (priv->ignored_directory_patterns, - (GFunc) g_pattern_spec_free, - NULL); - g_slist_free (priv->ignored_directory_patterns); - - g_slist_foreach (priv->ignored_directory_paths, - (GFunc) g_free, - NULL); - g_slist_free (priv->ignored_directory_paths); - - for (l = priv->ignored_directories; l; l = l->next) { - const gchar *str = l->data; - - if (!str) { - continue; - } - - if (G_LIKELY (*str != G_DIR_SEPARATOR)) { - GPatternSpec *spec; - - spec = g_pattern_spec_new (l->data); - patterns = g_slist_prepend (patterns, spec); - } else { - paths = g_slist_prepend (paths, g_strdup (l->data)); - } - } - - priv->ignored_directory_patterns = g_slist_reverse (patterns); - priv->ignored_directory_paths = g_slist_reverse (paths); -} - -static void -config_constructed (GObject *object) -{ - GSettings *settings; - - (G_OBJECT_CLASS (tracker_config_parent_class)->constructed) (object); - - settings = G_SETTINGS (object); - - /* NOTE: Without the _delay() call the updates to settings - * from tracker-preferences may not happen before we notify - * about the property change from _set_*() APIs. This is - * because the GValue in set_property() is not up to date at - * the time we are called back. Quite fscking stupid really if - * you ask me. - * - * NOTE: We need this. If we don't we can't have local - * settings which are *NOT* stored in the GSettings database. - * We need this for overriding things like verbosity on start - * up. - */ - if (G_LIKELY (!g_getenv ("TRACKER_USE_CONFIG_FILES"))) { - g_settings_delay (settings); - } - - /* Set up bindings: - * - * What's interesting here is that 'verbosity' and - * 'initial-sleep' are command line arguments that can be - * overridden, so we don't update the config when we set them - * from main() because it's a session configuration only, not - * a permanent one. To do this we use the flag - * G_SETTINGS_BIND_GET_NO_CHANGES. - * - * For the other settings, we don't bind the - * G_SETTINGS_BIND_SET because we don't want to save anything, - * ever, we only want to know about updates to the settings as - * they're changed externally. The only time this may be - * different is where we use the environment variable - * TRACKER_USE_CONFIG_FILES and we want to write a config - * file for convenience. But this is only necessary if the - * config is different to the default. - */ - g_settings_bind (settings, "verbosity", object, "verbosity", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_GET_NO_CHANGES); - g_settings_bind (settings, "sched-idle", object, "sched-idle", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "initial-sleep", object, "initial-sleep", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_GET_NO_CHANGES); - g_settings_bind (settings, "throttle", object, "throttle", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "low-disk-space-limit", object, "low-disk-space-limit", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "crawling-interval", object, "crawling-interval", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "low-disk-space-limit", object, "low-disk-space-limit", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "removable-days-threshold", object, "removable-days-threshold", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "enable-monitors", object, "enable-monitors", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "enable-writeback", object, "enable-writeback", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "index-removable-devices", object, "index-removable-devices", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "index-optical-discs", object, "index-optical-discs", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "index-on-battery", object, "index-on-battery", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "index-on-battery-first-time", object, "index-on-battery-first-time", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "index-recursive-directories", object, "index-recursive-directories", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "index-single-directories", object, "index-single-directories", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "ignored-files", object, "ignored-files", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "ignored-directories", object, "ignored-directories", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "ignored-directories-with-content", object, "ignored-directories-with-content", G_SETTINGS_BIND_GET); - - config_set_ignored_file_conveniences (TRACKER_CONFIG (object)); - config_set_ignored_directory_conveniences (TRACKER_CONFIG (object)); -} - -TrackerConfig * -tracker_config_new (void) -{ - TrackerConfig *config = NULL; - - /* FIXME: should we unset GSETTINGS_BACKEND env var? */ - - if (G_UNLIKELY (g_getenv ("TRACKER_USE_CONFIG_FILES"))) { - GSettingsBackend *backend; - gchar *filename, *basename; - gboolean need_to_save; - - basename = g_strdup_printf ("%s.cfg", g_get_prgname ()); - filename = g_build_filename (g_get_user_config_dir (), "tracker", basename, NULL); - g_free (basename); - - need_to_save = g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE; - - backend = g_keyfile_settings_backend_new (filename, CONFIG_PATH, "General"); - g_info ("Using config file '%s'", filename); - g_free (filename); - - config = g_object_new (TRACKER_TYPE_CONFIG, - "backend", backend, - "schema-id", CONFIG_SCHEMA, - "path", CONFIG_PATH, - NULL); - g_object_unref (backend); - - if (need_to_save) { - g_info (" Config file does not exist, using default values..."); - } - } else { - config = g_object_new (TRACKER_TYPE_CONFIG, - "schema-id", CONFIG_SCHEMA, - "path", CONFIG_PATH, - NULL); - } - - return config; -} - -gint -tracker_config_get_verbosity (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_VERBOSITY); - - return g_settings_get_enum (G_SETTINGS (config), "verbosity"); -} - -gint -tracker_config_get_sched_idle (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_SCHED_IDLE); - - return g_settings_get_enum (G_SETTINGS (config), "sched-idle"); -} - -gint -tracker_config_get_initial_sleep (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_INITIAL_SLEEP); - - return g_settings_get_int (G_SETTINGS (config), "initial-sleep"); -} - -gboolean -tracker_config_get_enable_monitors (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_ENABLE_MONITORS); - - return g_settings_get_boolean (G_SETTINGS (config), "enable-monitors"); -} - -gboolean -tracker_config_get_enable_writeback (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_ENABLE_WRITEBACK); - - return g_settings_get_boolean (G_SETTINGS (config), "enable-writeback"); -} - -gint -tracker_config_get_throttle (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_THROTTLE); - - return g_settings_get_int (G_SETTINGS (config), "throttle"); -} - -gboolean -tracker_config_get_index_on_battery (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_INDEX_ON_BATTERY); - - return g_settings_get_boolean (G_SETTINGS (config), "index-on-battery"); -} - -gboolean -tracker_config_get_index_on_battery_first_time (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_INDEX_ON_BATTERY_FIRST_TIME); - - return g_settings_get_boolean (G_SETTINGS (config), "index-on-battery-first-time"); -} - -gboolean -tracker_config_get_index_removable_devices (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_INDEX_REMOVABLE_DEVICES); - - return g_settings_get_boolean (G_SETTINGS (config), "index-removable-devices"); -} - -gboolean -tracker_config_get_index_optical_discs (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_INDEX_OPTICAL_DISCS); - - return g_settings_get_boolean (G_SETTINGS (config), "index-optical-discs"); -} - -gint -tracker_config_get_low_disk_space_limit (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_LOW_DISK_SPACE_LIMIT); - - return g_settings_get_int (G_SETTINGS (config), "low-disk-space-limit"); -} - -GSList * -tracker_config_get_index_recursive_directories (TrackerConfig *config) -{ - TrackerConfigPrivate *priv; - - g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL); - - priv = config->priv; - - return priv->index_recursive_directories; -} - -GSList * -tracker_config_get_index_single_directories (TrackerConfig *config) -{ - TrackerConfigPrivate *priv; - - g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL); - - priv = config->priv; - - return priv->index_single_directories; -} - -GSList * -tracker_config_get_ignored_directories (TrackerConfig *config) -{ - TrackerConfigPrivate *priv; - - g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL); - - priv = config->priv; - - return priv->ignored_directories; -} - -GSList * -tracker_config_get_ignored_directories_with_content (TrackerConfig *config) -{ - TrackerConfigPrivate *priv; - - g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL); - - priv = config->priv; - - return priv->ignored_directories_with_content; -} - -GSList * -tracker_config_get_ignored_files (TrackerConfig *config) -{ - TrackerConfigPrivate *priv; - - g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL); - - priv = config->priv; - - return priv->ignored_files; -} - -gint -tracker_config_get_crawling_interval (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_CRAWLING_INTERVAL); - - return g_settings_get_int (G_SETTINGS (config), "crawling-interval"); -} - -gint -tracker_config_get_removable_days_threshold (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), DEFAULT_REMOVABLE_DAYS_THRESHOLD); - - return g_settings_get_int (G_SETTINGS (config), "removable-days-threshold"); -} - -void -tracker_config_set_verbosity (TrackerConfig *config, - gint value) -{ - g_return_if_fail (TRACKER_IS_CONFIG (config)); - - g_settings_set_enum (G_SETTINGS (config), "verbosity", value); - g_object_notify (G_OBJECT (config), "verbosity"); -} - -void -tracker_config_set_initial_sleep (TrackerConfig *config, - gint value) -{ - g_return_if_fail (TRACKER_IS_CONFIG (config)); - - g_settings_set_int (G_SETTINGS (config), "initial-sleep", value); - g_object_notify (G_OBJECT (config), "initial-sleep"); -} - -static void -rebuild_filtered_lists (TrackerConfig *config) -{ - TrackerConfigPrivate *priv; - GSList *old_list; - - /* This function does 3 things: - * 1. Convert aliases like &DESKTOP to real paths - * 2. Filter and remove duplicates - * 3. Save the new list to the lists we return with public API - * - * Importantly, we: - * 1. Only notify on changes. - * 2. Don't update the unfiltered lists (since they have aliases) - */ - priv = config->priv; - - /* Filter single directories first, checking duplicates */ - old_list = priv->index_single_directories; - priv->index_single_directories = NULL; - - if (priv->index_single_directories_unfiltered) { - GSList *mapped_dirs = dir_mapping_get (priv->index_single_directories_unfiltered, FALSE); - - priv->index_single_directories = - tracker_path_list_filter_duplicates (mapped_dirs, ".", FALSE); - - if (mapped_dirs) { - g_slist_foreach (mapped_dirs, (GFunc) g_free, NULL); - g_slist_free (mapped_dirs); - } - } - - if (!tracker_gslist_with_string_data_equal (old_list, priv->index_single_directories)) { - g_object_notify (G_OBJECT (config), "index-single-directories"); - } - - if (old_list) { - g_slist_foreach (old_list, (GFunc) g_free, NULL); - g_slist_free (old_list); - } - - /* Filter recursive directories */ - old_list = priv->index_recursive_directories; - priv->index_recursive_directories = NULL; - - if (priv->index_recursive_directories_unfiltered) { - GSList *l, *checked_dirs = NULL; - GSList *mapped_dirs; - - /* First, translate aliases */ - mapped_dirs = dir_mapping_get (priv->index_recursive_directories_unfiltered, TRUE); - - /* Second, remove elements already in single directories */ - for (l = mapped_dirs; l; l = l->next) { - if (g_slist_find_custom (priv->index_single_directories, - l->data, - (GCompareFunc) g_strcmp0) != NULL) { - g_message ("Path '%s' being removed from recursive directories " - "list, as it also exists in single directories list", - (gchar *) l->data); - } else { - checked_dirs = g_slist_prepend (checked_dirs, l->data); - } - } - - g_slist_free (mapped_dirs); - checked_dirs = g_slist_reverse (checked_dirs); - - /* Third, clean up any duplicates */ - priv->index_recursive_directories = - tracker_path_list_filter_duplicates (checked_dirs, ".", TRUE); - - g_slist_foreach (checked_dirs, (GFunc) g_free, NULL); - g_slist_free (checked_dirs); - } - - if (!tracker_gslist_with_string_data_equal (old_list, priv->index_recursive_directories)) { - g_object_notify (G_OBJECT (config), "index-recursive-directories"); - } - - if (old_list) { - g_slist_foreach (old_list, (GFunc) g_free, NULL); - g_slist_free (old_list); - } -} - -static void -config_set_index_recursive_directories (TrackerConfig *config, - GSList *roots) -{ - TrackerConfigPrivate *priv; - GSList *l; - gboolean equal; - - g_return_if_fail (TRACKER_IS_CONFIG (config)); - - priv = config->priv; - - l = priv->index_recursive_directories_unfiltered; - - equal = tracker_gslist_with_string_data_equal (roots, l); - - if (!roots) { - priv->index_recursive_directories_unfiltered = NULL; - } else { - priv->index_recursive_directories_unfiltered = - tracker_gslist_copy_with_string_data (roots); - } - - g_slist_foreach (l, (GFunc) g_free, NULL); - g_slist_free (l); - - if (equal) { - return; - } - - rebuild_filtered_lists (config); -} - -static void -config_set_index_single_directories (TrackerConfig *config, - GSList *roots) -{ - TrackerConfigPrivate *priv; - GSList *l; - gboolean equal; - - g_return_if_fail (TRACKER_IS_CONFIG (config)); - - priv = config->priv; - - l = priv->index_single_directories_unfiltered; - - equal = tracker_gslist_with_string_data_equal (roots, l); - - if (!roots) { - priv->index_single_directories_unfiltered = NULL; - } else { - priv->index_single_directories_unfiltered = - tracker_gslist_copy_with_string_data (roots); - } - - g_slist_foreach (l, (GFunc) g_free, NULL); - g_slist_free (l); - - if (equal) { - return; - } - - rebuild_filtered_lists (config); -} - -static void -config_set_ignored_directories (TrackerConfig *config, - GSList *roots) -{ - TrackerConfigPrivate *priv; - GSList *l; - gboolean equal; - - g_return_if_fail (TRACKER_IS_CONFIG (config)); - - priv = config->priv; - - l = priv->ignored_directories; - - equal = tracker_gslist_with_string_data_equal (roots, l); - - if (!roots) { - priv->ignored_directories = NULL; - } else { - priv->ignored_directories = - tracker_gslist_copy_with_string_data (roots); - } - - g_slist_foreach (l, (GFunc) g_free, NULL); - g_slist_free (l); - - if (equal) { - return; - } - - /* Re-set up the GPatternSpec list */ - config_set_ignored_directory_conveniences (config); - - g_object_notify (G_OBJECT (config), "ignored-directories"); -} - -static void -config_set_ignored_directories_with_content (TrackerConfig *config, - GSList *roots) -{ - TrackerConfigPrivate *priv; - GSList *l; - gboolean equal; - - g_return_if_fail (TRACKER_IS_CONFIG (config)); - - priv = config->priv; - - l = priv->ignored_directories_with_content; - - equal = tracker_gslist_with_string_data_equal (roots, l); - - if (!roots) { - priv->ignored_directories_with_content = NULL; - } else { - priv->ignored_directories_with_content = - tracker_gslist_copy_with_string_data (roots); - } - - g_slist_foreach (l, (GFunc) g_free, NULL); - g_slist_free (l); - - if (equal) { - return; - } - - g_object_notify (G_OBJECT (config), "ignored-directories-with-content"); -} - -static void -config_set_ignored_files (TrackerConfig *config, - GSList *files) -{ - TrackerConfigPrivate *priv; - GSList *l; - gboolean equal; - - g_return_if_fail (TRACKER_IS_CONFIG (config)); - - priv = config->priv; - - l = priv->ignored_files; - - equal = tracker_gslist_with_string_data_equal (files, l); - - if (!files) { - priv->ignored_files = NULL; - } else { - priv->ignored_files = - tracker_gslist_copy_with_string_data (files); - } - - g_slist_foreach (l, (GFunc) g_free, NULL); - g_slist_free (l); - - if (equal) { - return; - } - - /* Re-set up the GPatternSpec list */ - config_set_ignored_file_conveniences (config); - - g_object_notify (G_OBJECT (config), "ignored-files"); -} - -/* - * Convenience functions - */ - -GSList * -tracker_config_get_ignored_directory_patterns (TrackerConfig *config) -{ - TrackerConfigPrivate *priv; - - g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL); - - priv = config->priv; - - return priv->ignored_directory_patterns; -} - -GSList * -tracker_config_get_ignored_file_patterns (TrackerConfig *config) -{ - TrackerConfigPrivate *priv; - - g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL); - - priv = config->priv; - - return priv->ignored_file_patterns; -} - -GSList * -tracker_config_get_ignored_directory_paths (TrackerConfig *config) -{ - TrackerConfigPrivate *priv; - - g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL); - - priv = config->priv; - - return priv->ignored_directory_paths; -} - -GSList * -tracker_config_get_ignored_file_paths (TrackerConfig *config) -{ - TrackerConfigPrivate *priv; - - g_return_val_if_fail (TRACKER_IS_CONFIG (config), NULL); - - priv = config->priv; - - return priv->ignored_file_paths; -} diff --git a/src/miners/fs/tracker-config.h b/src/miners/fs/tracker-config.h deleted file mode 100644 index 9a5190b29..000000000 --- a/src/miners/fs/tracker-config.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright (C) 2009%, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_MINER_FS_CONFIG_H__ -#define __TRACKER_MINER_FS_CONFIG_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -#define TRACKER_TYPE_CONFIG (tracker_config_get_type ()) -#define TRACKER_CONFIG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_CONFIG, TrackerConfig)) -#define TRACKER_CONFIG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TRACKER_TYPE_CONFIG, TrackerConfigClass)) -#define TRACKER_IS_CONFIG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_CONFIG)) -#define TRACKER_IS_CONFIG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TRACKER_TYPE_CONFIG)) -#define TRACKER_CONFIG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_CONFIG, TrackerConfigClass)) - -typedef struct TrackerConfig TrackerConfig; -typedef struct TrackerConfigClass TrackerConfigClass; - -struct TrackerConfig { - GSettings parent; - gpointer priv; -}; - -struct TrackerConfigClass { - GSettingsClass parent_class; -}; - -GType tracker_config_get_type (void) G_GNUC_CONST; - -TrackerConfig *tracker_config_new (void); - -gint tracker_config_get_verbosity (TrackerConfig *config); -gint tracker_config_get_sched_idle (TrackerConfig *config); -gint tracker_config_get_initial_sleep (TrackerConfig *config); -gboolean tracker_config_get_enable_monitors (TrackerConfig *config); -gint tracker_config_get_throttle (TrackerConfig *config); -gboolean tracker_config_get_index_on_battery (TrackerConfig *config); -gboolean tracker_config_get_index_on_battery_first_time (TrackerConfig *config); -gboolean tracker_config_get_index_removable_devices (TrackerConfig *config); -gboolean tracker_config_get_index_optical_discs (TrackerConfig *config); -gboolean tracker_config_get_index_mounted_directories (TrackerConfig *config); -gint tracker_config_get_low_disk_space_limit (TrackerConfig *config); -GSList * tracker_config_get_index_recursive_directories (TrackerConfig *config); -GSList * tracker_config_get_index_single_directories (TrackerConfig *config); -GSList * tracker_config_get_ignored_directories (TrackerConfig *config); -GSList * tracker_config_get_ignored_directories_with_content (TrackerConfig *config); -GSList * tracker_config_get_ignored_files (TrackerConfig *config); -gint tracker_config_get_crawling_interval (TrackerConfig *config); -gint tracker_config_get_removable_days_threshold (TrackerConfig *config); -gboolean tracker_config_get_enable_writeback (TrackerConfig *config); - -void tracker_config_set_verbosity (TrackerConfig *config, - gint value); -void tracker_config_set_initial_sleep (TrackerConfig *config, - gint value); - -/* - * Convenience functions: - */ - -/* The _patterns() APIs return GPatternSpec pointers for basename - * pattern matching. - */ -GSList * tracker_config_get_ignored_directory_patterns (TrackerConfig *config); -GSList * tracker_config_get_ignored_file_patterns (TrackerConfig *config); - -/* The _paths() APIs return string pointers for full paths matching */ -GSList * tracker_config_get_ignored_directory_paths (TrackerConfig *config); -GSList * tracker_config_get_ignored_file_paths (TrackerConfig *config); - -G_END_DECLS - -#endif /* __TRACKER_MINER_FS_CONFIG_H__ */ diff --git a/src/miners/fs/tracker-extract-watchdog.c b/src/miners/fs/tracker-extract-watchdog.c deleted file mode 100644 index 4c8acddc8..000000000 --- a/src/miners/fs/tracker-extract-watchdog.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2016, Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include "tracker-extract-watchdog.h" - -#include <libtracker-common/tracker-common.h> -#include <libtracker-miner/tracker-miner.h> - -struct _TrackerExtractWatchdog { - GObject parent_class; - guint extractor_watchdog_id; - guint timeout_id; - gboolean initializing; -}; - -static void extract_watchdog_start (TrackerExtractWatchdog *watchdog, - gboolean autostart); - -G_DEFINE_TYPE (TrackerExtractWatchdog, tracker_extract_watchdog, G_TYPE_OBJECT) - -static void -extract_watchdog_stop (TrackerExtractWatchdog *watchdog) -{ - if (watchdog->extractor_watchdog_id) { - g_bus_unwatch_name (watchdog->extractor_watchdog_id); - watchdog->extractor_watchdog_id = 0; - } -} - -static gboolean -extract_watchdog_name_vanished_timeout (gpointer user_data) -{ - TrackerExtractWatchdog *watchdog = user_data; - - watchdog->timeout_id = 0; - extract_watchdog_start (watchdog, TRUE); - - return G_SOURCE_REMOVE; -} - -static void -extract_watchdog_name_appeared (GDBusConnection *conn, - const gchar *name, - const gchar *name_owner, - gpointer user_data) -{ - TrackerExtractWatchdog *watchdog = user_data; - - if (watchdog->initializing) - watchdog->initializing = FALSE; -} - -static void -extract_watchdog_name_vanished (GDBusConnection *conn, - const gchar *name, - gpointer user_data) -{ - TrackerExtractWatchdog *watchdog = user_data; - - /* If connection is lost, there's not much we can startup */ - if (conn == NULL) - return; - - /* We will ignore the first call after initialization, as we - * don't want to autostart tracker-extract in this case (useful - * for debugging purposes). - */ - if (watchdog->initializing) { - watchdog->initializing = FALSE; - return; - } - - g_debug ("tracker-extract vanished, restarting after grace period."); - - /* Close the name watch, so we'll create another one that will - * autostart the service if it not already running. - */ - extract_watchdog_stop (watchdog); - - /* Give a period of grace before restarting, so we allow replacing - * from eg. a terminal. - */ - watchdog->timeout_id = - g_timeout_add_seconds (1, extract_watchdog_name_vanished_timeout, - watchdog); -} - -static void -extract_watchdog_start (TrackerExtractWatchdog *watchdog, - gboolean autostart) -{ - g_debug ("Setting up watch on tracker-extract (autostart: %s)", - autostart ? "yes" : "no"); - - watchdog->extractor_watchdog_id = - g_bus_watch_name (TRACKER_IPC_BUS, - TRACKER_MINER_DBUS_NAME_PREFIX "Extract", - (autostart ? - G_BUS_NAME_WATCHER_FLAGS_AUTO_START : - G_BUS_NAME_WATCHER_FLAGS_NONE), - extract_watchdog_name_appeared, - extract_watchdog_name_vanished, - watchdog, NULL); -} - -static void -tracker_extract_watchdog_finalize (GObject *object) -{ - TrackerExtractWatchdog *watchdog = TRACKER_EXTRACT_WATCHDOG (object); - - extract_watchdog_stop (watchdog); - - if (watchdog->timeout_id) { - g_source_remove (watchdog->timeout_id); - } - - G_OBJECT_CLASS (tracker_extract_watchdog_parent_class)->finalize (object); -} - -static void -tracker_extract_watchdog_class_init (TrackerExtractWatchdogClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = tracker_extract_watchdog_finalize; -} - -static void -tracker_extract_watchdog_init (TrackerExtractWatchdog *watchdog) -{ - watchdog->initializing = TRUE; - extract_watchdog_start (watchdog, FALSE); -} - -TrackerExtractWatchdog * -tracker_extract_watchdog_new (void) -{ - return g_object_new (TRACKER_TYPE_EXTRACT_WATCHDOG, - NULL); -} diff --git a/src/miners/fs/tracker-extract-watchdog.h b/src/miners/fs/tracker-extract-watchdog.h deleted file mode 100644 index 1dab018b2..000000000 --- a/src/miners/fs/tracker-extract-watchdog.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2016, Red Hat Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_EXTRACT_WATCHDOG_H__ -#define __TRACKER_EXTRACT_WATCHDOG_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -#define TRACKER_TYPE_EXTRACT_WATCHDOG (tracker_extract_watchdog_get_type ()) - -G_DECLARE_FINAL_TYPE (TrackerExtractWatchdog, - tracker_extract_watchdog, - TRACKER, EXTRACT_WATCHDOG, - GObject) - -TrackerExtractWatchdog * tracker_extract_watchdog_new (void); - -G_END_DECLS - -#endif /* __TRACKER_EXTRACT_WATCHDOG_H__ */ diff --git a/src/miners/fs/tracker-main.c b/src/miners/fs/tracker-main.c deleted file mode 100644 index db0386847..000000000 --- a/src/miners/fs/tracker-main.c +++ /dev/null @@ -1,923 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <string.h> -#include <stdlib.h> -#include <locale.h> -#include <errno.h> -#include <sys/types.h> -#include <unistd.h> - -#include <glib.h> -#include <glib-unix.h> -#include <glib-object.h> -#include <glib/gi18n.h> - -#include <libtracker-common/tracker-common.h> -#include <libtracker-sparql/tracker-sparql.h> -#include <libtracker-miner/tracker-miner.h> - -#include <libtracker-data/tracker-db-manager.h> - -#include "tracker-config.h" -#include "tracker-miner-files.h" -#include "tracker-miner-files-index.h" -#include "tracker-writeback.h" - -#define ABOUT \ - "Tracker " PACKAGE_VERSION "\n" - -#define LICENSE \ - "This program is free software and comes without any warranty.\n" \ - "It is licensed under version 2 or later of the General Public " \ - "License which can be viewed at:\n" \ - "\n" \ - " http://www.gnu.org/licenses/gpl.txt\n" - -#define SECONDS_PER_DAY 60 * 60 * 24 - -#define DBUS_NAME_SUFFIX "Miner.Files" -#define DBUS_PATH "/org/freedesktop/Tracker1/Miner/Files" - -static void miner_handle_next (void); - -static GMainLoop *main_loop; -static GSList *miners; -static GSList *current_miner; -static gboolean finished_miners; - -static gint verbosity = -1; -static gint initial_sleep = -1; -static gboolean no_daemon; -static gchar *eligible; -static gboolean version; -static guint miners_timeout_id = 0; -static gboolean do_crawling = FALSE; -static gchar *domain_ontology_name = NULL; - -static GOptionEntry entries[] = { - { "verbosity", 'v', 0, - G_OPTION_ARG_INT, &verbosity, - N_("Logging, 0 = errors only, " - "1 = minimal, 2 = detailed and 3 = debug (default=0)"), - NULL }, - { "initial-sleep", 's', 0, - G_OPTION_ARG_INT, &initial_sleep, - N_("Initial sleep time in seconds, " - "0->1000 (default=15)"), - NULL }, - { "no-daemon", 'n', 0, - G_OPTION_ARG_NONE, &no_daemon, - N_("Runs until all configured locations are indexed and then exits"), - NULL }, - { "eligible", 'e', 0, - G_OPTION_ARG_FILENAME, &eligible, - N_("Checks if FILE is eligible for being mined based on configuration"), - N_("FILE") }, - { "domain-ontology", 'd', 0, - G_OPTION_ARG_STRING, &domain_ontology_name, - N_("Runs for an specific domain ontology"), - NULL }, - { "version", 'V', 0, - G_OPTION_ARG_NONE, &version, - N_("Displays version information"), - NULL }, - { NULL } -}; - -static void -sanity_check_option_values (TrackerConfig *config) -{ - g_message ("General options:"); - g_message (" Verbosity ............................ %d", - tracker_config_get_verbosity (config)); - g_message (" Sched Idle ........................... %d", - tracker_config_get_sched_idle (config)); - g_message (" Initial Sleep ........................ %d", - tracker_config_get_initial_sleep (config)); - - g_message ("Indexer options:"); - g_message (" Throttle level ....................... %d", - tracker_config_get_throttle (config)); - g_message (" Indexing while on battery ............ %s (first time only = %s)", - tracker_config_get_index_on_battery (config) ? "yes" : "no", - tracker_config_get_index_on_battery_first_time (config) ? "yes" : "no"); - - if (tracker_config_get_low_disk_space_limit (config) == -1) { - g_message (" Low disk space limit ................. Disabled"); - } else { - g_message (" Low disk space limit ................. %d%%", - tracker_config_get_low_disk_space_limit (config)); - } -} - -static gboolean -signal_handler (gpointer user_data) -{ - int signo = GPOINTER_TO_INT (user_data); - - static gboolean in_loop = FALSE; - - /* Die if we get re-entrant signals handler calls */ - if (in_loop) { - _exit (EXIT_FAILURE); - } - - switch (signo) { - case SIGTERM: - case SIGINT: - in_loop = TRUE; - g_main_loop_quit (main_loop); - - /* Fall through */ - default: - if (g_strsignal (signo)) { - g_print ("\n"); - g_print ("Received signal:%d->'%s'\n", - signo, - g_strsignal (signo)); - } - break; - } - - return G_SOURCE_CONTINUE; -} - -static void -initialize_signal_handler (void) -{ -#ifndef G_OS_WIN32 - g_unix_signal_add (SIGTERM, signal_handler, GINT_TO_POINTER (SIGTERM)); - g_unix_signal_add (SIGINT, signal_handler, GINT_TO_POINTER (SIGINT)); -#endif /* G_OS_WIN32 */ -} - -static void -initialize_priority_and_scheduling (TrackerSchedIdle sched_idle, - gboolean first_time_index) -{ - /* Set CPU priority */ - if (sched_idle == TRACKER_SCHED_IDLE_ALWAYS || - (sched_idle == TRACKER_SCHED_IDLE_FIRST_INDEX && first_time_index)) { - tracker_sched_idle (); - } - - /* Set disk IO priority and scheduling */ - tracker_ioprio_init (); - - /* Set process priority: - * The nice() function uses attribute "warn_unused_result" and - * so complains if we do not check its returned value. But it - * seems that since glibc 2.2.4, nice() can return -1 on a - * successful call so we have to check value of errno too. - * Stupid... - */ - - g_message ("Setting priority nice level to 19"); - - errno = 0; - if (nice (19) == -1 && errno != 0) { - const gchar *str = g_strerror (errno); - - g_message ("Couldn't set nice value to 19, %s", - str ? str : "no error given"); - } -} - -static gboolean -should_crawl (TrackerConfig *config, - gboolean *forced) -{ - gint crawling_interval; - - crawling_interval = tracker_config_get_crawling_interval (config); - - g_message ("Checking whether to crawl file system based on configured crawling interval:"); - - if (crawling_interval == -2) { - g_message (" Disabled"); - return FALSE; - } else if (crawling_interval == -1) { - g_message (" Maybe (depends on a clean last shutdown)"); - return TRUE; - } else if (crawling_interval == 0) { - g_message (" Forced"); - - if (forced) { - *forced = TRUE; - } - - return TRUE; - } else { - guint64 then, now; - - then = tracker_miner_files_get_last_crawl_done (); - - if (then < 1) { - return TRUE; - } - - now = (guint64) time (NULL); - - if (now < then + (crawling_interval * SECONDS_PER_DAY)) { - g_message (" Postponed"); - return FALSE; - } else { - g_message (" (More than) %d days after last crawling, enabled", crawling_interval); - return FALSE; - } - } -} - -static void -miner_handle_next (void) -{ - if (finished_miners) { - return; - } - - if (!current_miner) { - current_miner = miners; - } else { - current_miner = current_miner->next; - } - - if (!current_miner) { - finished_miners = TRUE; - - g_message ("All miners are now finished"); - - /* We're not sticking around for file updates, so stop - * the mainloop and exit. - */ - if (no_daemon && main_loop) { - g_main_loop_quit (main_loop); - } - - return; - } - - if (!tracker_miner_is_started (current_miner->data)) { - g_message ("Starting next miner..."); - tracker_miner_start (current_miner->data); - } -} - -static gboolean -miner_handle_first_cb (gpointer data) -{ - miners_timeout_id = 0; - miner_handle_next (); - return FALSE; -} - -static void -miner_handle_first (TrackerConfig *config, - gboolean do_mtime_checking) -{ - gint initial_sleep; - - if (!do_mtime_checking) { - g_debug ("Avoiding initial sleep, no mtime check needed"); - miner_handle_next (); - return; - } - - /* If requesting to run as no-daemon, start right away */ - if (no_daemon) { - miner_handle_next (); - return; - } - - /* If no need to initially sleep, start right away */ - initial_sleep = tracker_config_get_initial_sleep (config); - - if (initial_sleep <= 0) { - miner_handle_next (); - return; - } - - g_debug ("Performing initial sleep of %d seconds", - initial_sleep); - miners_timeout_id = g_timeout_add_seconds (initial_sleep, - miner_handle_first_cb, - NULL); -} - -static void -miner_finished_cb (TrackerMinerFS *fs, - gdouble seconds_elapsed, - guint total_directories_found, - guint total_directories_ignored, - guint total_files_found, - guint total_files_ignored, - gpointer user_data) -{ - g_info ("Finished mining in seconds:%f, total directories:%d, total files:%d", - seconds_elapsed, - total_directories_found, - total_files_found); - - if (TRACKER_IS_MINER_FILES (fs) && do_crawling) { - tracker_miner_files_set_last_crawl_done (TRUE); - } - - miner_handle_next (); -} - -static void -finalize_miner (TrackerMiner *miner) -{ - g_object_unref (G_OBJECT (miner)); -} - -static GList * -get_dir_children_as_gfiles (const gchar *path) -{ - GList *children = NULL; - GDir *dir; - - dir = g_dir_open (path, 0, NULL); - - if (dir) { - const gchar *basename; - - while ((basename = g_dir_read_name (dir)) != NULL) { - GFile *child; - gchar *str; - - str = g_build_filename (path, basename, NULL); - child = g_file_new_for_path (str); - g_free (str); - - children = g_list_prepend (children, child); - } - - g_dir_close (dir); - } - - return children; -} - -static void -dummy_log_handler (const gchar *domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer user_data) -{ - return; -} - -static void -check_eligible (void) -{ - TrackerConfig *config; - GFile *file; - GFileInfo *info; - GError *error = NULL; - gchar *path; - guint log_handler_id; - gboolean exists = TRUE; - gboolean is_dir; - gboolean print_dir_check; - gboolean print_dir_check_with_content; - gboolean print_file_check; - gboolean print_monitor_check; - gboolean would_index = TRUE; - gboolean would_notice = TRUE; - - /* Set log handler for library messages */ - log_handler_id = g_log_set_handler (NULL, - G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL, - dummy_log_handler, - NULL); - - g_log_set_default_handler (dummy_log_handler, NULL); - - /* Start check */ - file = g_file_new_for_commandline_arg (eligible); - info = g_file_query_info (file, - G_FILE_ATTRIBUTE_STANDARD_TYPE, - G_FILE_QUERY_INFO_NONE, - NULL, - &error); - - if (error) { - if (error->code == G_IO_ERROR_NOT_FOUND) { - exists = FALSE; - } - - g_error_free (error); - } - - if (info) { - is_dir = g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY; - g_object_unref (info); - } else { - /* Assume not a dir */ - is_dir = FALSE; - } - - config = tracker_config_new (); - path = g_file_get_path (file); - - if (exists) { - if (is_dir) { - print_dir_check = TRUE; - print_dir_check_with_content = TRUE; - print_file_check = FALSE; - print_monitor_check = TRUE; - } else { - print_dir_check = FALSE; - print_dir_check_with_content = FALSE; - print_file_check = TRUE; - print_monitor_check = TRUE; - } - } else { - print_dir_check = TRUE; - print_dir_check_with_content = FALSE; - print_file_check = TRUE; - print_monitor_check = TRUE; - } - - g_print (exists ? - _("Data object “%s” currently exists") : - _("Data object “%s” currently does not exist"), - path); - - g_print ("\n"); - - if (print_dir_check) { - gboolean check; - - check = tracker_miner_files_check_directory (file, - tracker_config_get_index_recursive_directories (config), - tracker_config_get_index_single_directories (config), - tracker_config_get_ignored_directory_paths (config), - tracker_config_get_ignored_directory_patterns (config)); - g_print (" %s\n", - check ? - _("Directory is eligible to be mined (based on rules)") : - _("Directory is NOT eligible to be mined (based on rules)")); - - would_index &= check; - } - - if (print_dir_check_with_content) { - GList *children; - gboolean check; - - children = get_dir_children_as_gfiles (path); - - check = tracker_miner_files_check_directory_contents (file, - children, - tracker_config_get_ignored_directories_with_content (config)); - - g_list_foreach (children, (GFunc) g_object_unref, NULL); - g_list_free (children); - - g_print (" %s\n", - check ? - _("Directory is eligible to be mined (based on contents)") : - _("Directory is NOT eligible to be mined (based on contents)")); - - would_index &= check; - } - - if (print_monitor_check) { - gboolean check = TRUE; - - check &= tracker_config_get_enable_monitors (config); - - if (check) { - GSList *dirs_to_check, *l; - gboolean is_covered_single; - gboolean is_covered_recursive; - - is_covered_single = FALSE; - dirs_to_check = tracker_config_get_index_single_directories (config); - - for (l = dirs_to_check; l && !is_covered_single; l = l->next) { - GFile *dir; - GFile *parent; - - parent = g_file_get_parent (file); - dir = g_file_new_for_path (l->data); - is_covered_single = g_file_equal (parent, dir) || g_file_equal (file, dir); - - g_object_unref (dir); - g_object_unref (parent); - } - - is_covered_recursive = FALSE; - dirs_to_check = tracker_config_get_index_recursive_directories (config); - - for (l = dirs_to_check; l && !is_covered_recursive; l = l->next) { - GFile *dir; - - dir = g_file_new_for_path (l->data); - is_covered_recursive = g_file_has_prefix (file, dir) || g_file_equal (file, dir); - g_object_unref (dir); - } - - check &= is_covered_single || is_covered_recursive; - } - - if (exists && is_dir) { - g_print (" %s\n", - check ? - _("Directory is eligible to be monitored (based on config)") : - _("Directory is NOT eligible to be monitored (based on config)")); - } else if (exists && !is_dir) { - g_print (" %s\n", - check ? - _("File is eligible to be monitored (based on config)") : - _("File is NOT eligible to be monitored (based on config)")); - } else { - g_print (" %s\n", - check ? - _("File or Directory is eligible to be monitored (based on config)") : - _("File or Directory is NOT eligible to be monitored (based on config)")); - } - - would_notice &= check; - } - - if (print_file_check) { - gboolean check; - - check = tracker_miner_files_check_file (file, - tracker_config_get_ignored_file_paths (config), - tracker_config_get_ignored_file_patterns (config)); - - g_print (" %s\n", - check ? - _("File is eligible to be mined (based on rules)") : - _("File is NOT eligible to be mined (based on rules)")); - - would_index &= check; - } - - g_print ("\n" - "%s: %s\n" - "%s: %s\n" - "\n", - _("Would be indexed"), - would_index ? _("Yes") : _("No"), - _("Would be monitored"), - would_notice ? _("Yes") : _("No")); - - if (log_handler_id != 0) { - /* Unset log handler */ - g_log_remove_handler (NULL, log_handler_id); - } - - g_free (path); - g_object_unref (config); - g_object_unref (file); -} - -static gboolean -store_is_available (void) -{ - GDBusConnection *connection; - GDBusProxy *proxy; - gchar *name_owner; - - connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, NULL); - - if (!connection) { - return FALSE; - } - - proxy = g_dbus_proxy_new_sync (connection, - G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, - NULL, - "org.freedesktop.Tracker1", - "/org/freedesktop/Tracker1/Status", - "org.freedesktop.Tracker1.Status", - NULL, NULL); - - if (!proxy) { - g_object_unref (connection); - return FALSE; - } - - name_owner = g_dbus_proxy_get_name_owner (proxy); - - g_object_unref (connection); - g_object_unref (proxy); - - if (name_owner) { - g_free (name_owner); - return TRUE; - } - - return FALSE; -} - -static gboolean -miner_needs_check (TrackerMiner *miner, - gboolean store_available) -{ - /* Reasons to not mark ourselves as cleanly shutdown include: - * - * 1. Still crawling or with files to process in our queues. - * 2. We crash (out of our control usually anyway). - * 3. At least one of the miners is PAUSED, we have - * to exclude the situations where the miner is - * exclusively paused due to the store not being - * available, but the miner is actually done. - */ - if (!tracker_miner_is_paused (miner)) { - if (TRACKER_IS_MINER_FS (miner) && - tracker_miner_fs_has_items_to_process (TRACKER_MINER_FS (miner))) { - /* There are items left to process */ - return TRUE; - } - - /* FIXME: We currently don't check the applications - * miner if we are finished before returning TRUE/FALSE here, should - * we? - */ - - /* We consider the miner finished */ - return FALSE; - } else { - if (store_available) { - /* Paused for other reasons, so probably not done */ - return TRUE; - } else { - /* Check whether there are more pause - * reasons than the store being out. - */ - return tracker_miner_is_paused (miner); - } - } -} - -static void -on_domain_vanished (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - GMainLoop *loop = user_data; - g_main_loop_quit (loop); -} - -int -main (gint argc, gchar *argv[]) -{ - TrackerConfig *config; - TrackerMiner *miner_files; - TrackerMinerFilesIndex *miner_files_index; - GOptionContext *context; - GError *error = NULL; - gchar *log_filename = NULL; - gboolean do_mtime_checking; - gboolean force_mtime_checking = FALSE; - gboolean store_available; - TrackerMinerProxy *proxy; - GDBusConnection *connection; - TrackerDomainOntology *domain_ontology; - gchar *dbus_name; - - main_loop = NULL; - - setlocale (LC_ALL, ""); - - bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); - - /* Set timezone info */ - tzset (); - - /* Translators: this messagge will apper immediately after the - * usage string - Usage: COMMAND <THIS_MESSAGE> - */ - context = g_option_context_new (_("— start the tracker indexer")); - - g_option_context_add_main_entries (context, entries, NULL); - g_option_context_parse (context, &argc, &argv, &error); - g_option_context_free (context); - - if (error) { - g_printerr ("%s\n", error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - if (version) { - g_print ("\n" ABOUT "\n" LICENSE "\n"); - return EXIT_SUCCESS; - } - - if (eligible) { - check_eligible (); - return EXIT_SUCCESS; - } - - tracker_sparql_connection_set_domain (domain_ontology_name); - - domain_ontology = tracker_domain_ontology_new (domain_ontology_name, NULL, &error); - if (error) { - g_critical ("Could not load domain ontology '%s': %s", - domain_ontology_name, error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, &error); - if (error) { - g_critical ("Could not create DBus connection: %s\n", - error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - /* Initialize logging */ - config = tracker_config_new (); - - if (verbosity > -1) { - tracker_config_set_verbosity (config, verbosity); - } - - if (initial_sleep > -1) { - tracker_config_set_initial_sleep (config, initial_sleep); - } - - tracker_log_init (tracker_config_get_verbosity (config), - &log_filename); - if (log_filename) { - g_message ("Using log file:'%s'", log_filename); - g_free (log_filename); - } - - sanity_check_option_values (config); - - /* This makes sure we don't steal all the system's resources */ - initialize_priority_and_scheduling (tracker_config_get_sched_idle (config), - tracker_miner_files_get_first_index_done () == FALSE); - - main_loop = g_main_loop_new (NULL, FALSE); - - if (domain_ontology && domain_ontology_name) { - g_bus_watch_name_on_connection (connection, domain_ontology_name, - G_BUS_NAME_WATCHER_FLAGS_NONE, - NULL, on_domain_vanished, - main_loop, NULL); - } - - g_message ("Checking if we're running as a daemon:"); - g_message (" %s %s", - no_daemon ? "No" : "Yes", - no_daemon ? "(forced by command line)" : ""); - - /* Create new TrackerMinerFiles object */ - miner_files = tracker_miner_files_new (config, &error); - if (!miner_files) { - g_critical ("Couldn't create new Files miner: '%s'", - error ? error->message : "unknown error"); - g_object_unref (config); - tracker_log_shutdown (); - return EXIT_FAILURE; - } - - proxy = tracker_miner_proxy_new (miner_files, connection, DBUS_PATH, NULL, &error); - if (error) { - g_critical ("Couldn't create miner proxy: %s", error->message); - g_error_free (error); - g_object_unref (config); - g_object_unref (miner_files); - tracker_log_shutdown (); - return EXIT_FAILURE; - } - - tracker_writeback_init (TRACKER_MINER_FILES (miner_files), - config, - &error); - - if (error) { - g_critical ("Couldn't create writeback handling: '%s'", - error ? error->message : "unknown error"); - g_object_unref (config); - g_object_unref (miner_files); - tracker_log_shutdown (); - return EXIT_FAILURE; - } - - /* Create new TrackerMinerFilesIndex object */ - miner_files_index = tracker_miner_files_index_new (TRACKER_MINER_FILES (miner_files)); - if (!miner_files_index) { - g_object_unref (miner_files); - tracker_writeback_shutdown (); - g_object_unref (config); - tracker_log_shutdown (); - return EXIT_FAILURE; - } - - /* Request DBus name */ - dbus_name = tracker_domain_ontology_get_domain (domain_ontology, DBUS_NAME_SUFFIX); - - if (!tracker_dbus_request_name (connection, dbus_name, &error)) { - g_critical ("Could not request DBus name '%s': %s", - dbus_name, error->message); - g_error_free (error); - g_free (dbus_name); - return EXIT_FAILURE; - } - - g_free (dbus_name); - - /* Check if we should crawl and if we should force mtime - * checking based on the config. - */ - do_crawling = should_crawl (config, &force_mtime_checking); - - /* Get the last shutdown state to see if we need to perform a - * full mtime check against the db or not. - * - * Set to TRUE here in case we crash and miss file system - * events. - */ - g_message ("Checking whether to force mtime checking during crawling (based on last clean shutdown):"); - - /* Override the shutdown state decision based on the config */ - if (force_mtime_checking) { - do_mtime_checking = TRUE; - } else { - do_mtime_checking = tracker_miner_files_get_need_mtime_check (); - } - - g_message (" %s %s", - do_mtime_checking ? "Yes" : "No", - force_mtime_checking ? "(forced from config)" : ""); - - /* Set the need for an mtime check to TRUE so we check in the - * event of a crash, this is changed back on shutdown if - * everything appears to be fine. - */ - tracker_miner_files_set_need_mtime_check (TRUE); - - /* Configure files miner */ - tracker_miner_files_set_mtime_checking (TRACKER_MINER_FILES (miner_files), do_mtime_checking); - g_signal_connect (miner_files, "finished", - G_CALLBACK (miner_finished_cb), - NULL); - - miners = g_slist_prepend (miners, miner_files); - - if (do_crawling) - miner_handle_first (config, do_mtime_checking); - - initialize_signal_handler (); - - /* Go, go, go! */ - g_main_loop_run (main_loop); - - g_message ("Shutdown started"); - - store_available = store_is_available (); - - if (miners_timeout_id == 0 && - !miner_needs_check (miner_files, store_available)) { - tracker_miner_files_set_need_mtime_check (FALSE); - } - - g_main_loop_unref (main_loop); - g_object_unref (config); - g_object_unref (miner_files_index); - - g_slist_foreach (miners, (GFunc) finalize_miner, NULL); - g_slist_free (miners); - - g_object_unref (proxy); - g_object_unref (connection); - g_object_unref (domain_ontology); - - tracker_writeback_shutdown (); - tracker_log_shutdown (); - - g_print ("\nOK\n\n"); - - return EXIT_SUCCESS; -} diff --git a/src/miners/fs/tracker-miner-files-index.c b/src/miners/fs/tracker-miner-files-index.c deleted file mode 100644 index 5497c780f..000000000 --- a/src/miners/fs/tracker-miner-files-index.c +++ /dev/null @@ -1,584 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <libtracker-common/tracker-dbus.h> -#include <libtracker-sparql/tracker-sparql.h> -#include <libtracker-miner/tracker-miner.h> - -#include "tracker-miner-files-index.h" -#include "tracker-miner-files-peer-listener.h" - - -static const gchar introspection_xml[] = - "<node>" - " <interface name='org.freedesktop.Tracker1.Miner.Files.Index'>" - " <method name='ReindexMimeTypes'>" - " <arg type='as' name='mime_types' direction='in' />" - " </method>" - " <method name='IndexFile'>" - " <arg type='s' name='file_uri' direction='in' />" - " </method>" - " <method name='IndexFileForProcess'>" - " <arg type='s' name='file_uri' direction='in' />" - " </method>" - " </interface>" - "</node>"; - -/* If defined, then a file provided to be indexed MUST be a child in - * an configured path. if undefined, any file can be indexed, however - * it is up to applications to maintain files outside the configured - * locations. - */ -#undef REQUIRE_LOCATION_IN_CONFIG - -typedef struct { - TrackerDBusRequest *request; - GDBusMethodInvocation *invocation; - TrackerSparqlConnection *connection; - TrackerMinerFiles *miner_files; -} MimeTypesData; - -typedef struct { - TrackerMinerFiles *files_miner; - TrackerMinerFilesPeerListener *peer_listener; - GDBusConnection *d_connection; - GDBusNodeInfo *introspection_data; - guint registration_id; - gchar *full_name; - gchar *full_path; -} TrackerMinerFilesIndexPrivate; - -enum { - PROP_0, - PROP_FILES_MINER -}; - -#define TRACKER_MINER_FILES_INDEX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_MINER_FILES_INDEX, TrackerMinerFilesIndexPrivate)) - -static void index_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); -static void index_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); -static void index_finalize (GObject *object); - -G_DEFINE_TYPE(TrackerMinerFilesIndex, tracker_miner_files_index, G_TYPE_OBJECT) - -static void -tracker_miner_files_index_class_init (TrackerMinerFilesIndexClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = index_finalize; - object_class->set_property = index_set_property; - object_class->get_property = index_get_property; - - g_object_class_install_property (object_class, - PROP_FILES_MINER, - g_param_spec_object ("files_miner", - "files_miner", - "The FS Miner", - TRACKER_TYPE_MINER_FILES, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_type_class_add_private (klass, sizeof (TrackerMinerFilesIndexPrivate)); -} - -static void -index_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - TrackerMinerFilesIndexPrivate *priv; - - priv = TRACKER_MINER_FILES_INDEX_GET_PRIVATE (object); - - switch (param_id) { - case PROP_FILES_MINER: - priv->files_miner = g_value_dup_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - - -static void -index_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - TrackerMinerFilesIndexPrivate *priv; - - priv = TRACKER_MINER_FILES_INDEX_GET_PRIVATE (object); - - switch (param_id) { - case PROP_FILES_MINER: - g_value_set_object (value, priv->files_miner); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -index_finalize (GObject *object) -{ - TrackerMinerFilesIndexPrivate *priv = TRACKER_MINER_FILES_INDEX_GET_PRIVATE (object); - - if (priv->registration_id != 0) { - g_dbus_connection_unregister_object (priv->d_connection, - priv->registration_id); - } - - if (priv->introspection_data) { - g_dbus_node_info_unref (priv->introspection_data); - } - - if (priv->d_connection) { - g_object_unref (priv->d_connection); - } - - g_clear_object (&priv->peer_listener); - g_free (priv->full_name); - g_free (priv->full_path); - - g_object_unref (priv->files_miner); -} - -static MimeTypesData * -mime_types_data_new (TrackerDBusRequest *request, - GDBusMethodInvocation *invocation, - TrackerSparqlConnection *connection, - TrackerMinerFiles *miner_files) -{ - MimeTypesData *mtd; - - mtd = g_slice_new0 (MimeTypesData); - - mtd->miner_files = g_object_ref (miner_files); - mtd->request = request; - mtd->invocation = invocation; - mtd->connection = g_object_ref (connection); - - return mtd; -} - -static void -mime_types_data_destroy (gpointer data) -{ - MimeTypesData *mtd; - - mtd = data; - - g_object_unref (mtd->miner_files); - g_object_unref (mtd->connection); - - g_slice_free (MimeTypesData, mtd); -} - -static void -mime_types_cb (GObject *object, - GAsyncResult *result, - gpointer user_data) -{ - MimeTypesData *mtd = user_data; - TrackerSparqlCursor *cursor; - GError *error = NULL; - - cursor = tracker_sparql_connection_query_finish (TRACKER_SPARQL_CONNECTION (object), - result, - &error); - - if (cursor) { - tracker_dbus_request_comment (mtd->request, - "Found files that will need reindexing"); - - while (tracker_sparql_cursor_next (cursor, NULL, NULL)) { - GFile *file; - const gchar *url; - - url = tracker_sparql_cursor_get_string (cursor, 0, NULL); - file = g_file_new_for_uri (url); - tracker_miner_fs_check_file (TRACKER_MINER_FS (mtd->miner_files), - file, G_PRIORITY_HIGH, FALSE); - g_object_unref (file); - } - - tracker_dbus_request_end (mtd->request, NULL); - g_dbus_method_invocation_return_value (mtd->invocation, NULL); - } else { - tracker_dbus_request_end (mtd->request, error); - g_dbus_method_invocation_return_gerror (mtd->invocation, error); - } - - mime_types_data_destroy (user_data); -} - -static void -tracker_miner_files_index_reindex_mime_types (TrackerMinerFilesIndex *miner, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - TrackerMinerFilesIndexPrivate *priv; - GString *query; - GError *inner_error = NULL; - TrackerSparqlConnection *connection; - TrackerDBusRequest *request; - gint len, i; - GStrv mime_types = NULL; - - priv = TRACKER_MINER_FILES_INDEX_GET_PRIVATE (miner); - - g_variant_get (parameters, "(^a&s)", &mime_types); - - len = mime_types ? g_strv_length (mime_types) : 0; - - tracker_gdbus_async_return_if_fail (len > 0, invocation); - - request = tracker_g_dbus_request_begin (invocation, "%s(%d mime types)", - __FUNCTION__, - len); - - connection = tracker_sparql_connection_get (NULL, &inner_error); - - if (!connection) { - g_free (mime_types); - tracker_dbus_request_end (request, inner_error); - g_dbus_method_invocation_return_gerror (invocation, inner_error); - g_error_free (inner_error); - return; - } - - tracker_dbus_request_comment (request, - "Attempting to reindex the following mime types:"); - - query = g_string_new ("SELECT ?url " - "WHERE {" - " ?resource nie:url ?url ;" - " nie:mimeType ?mime ." - " FILTER("); - - for (i = 0; i < len; i++) { - tracker_dbus_request_comment (request, " %s", mime_types[i]); - g_string_append_printf (query, "?mime = '%s'", mime_types[i]); - - if (i < len - 1) { - g_string_append (query, " || "); - } - } - - g_string_append (query, ") }"); - - /* FIXME: save last call id */ - tracker_sparql_connection_query_async (connection, - query->str, - NULL, - mime_types_cb, - mime_types_data_new (request, - invocation, - connection, - priv->files_miner)); - - g_string_free (query, TRUE); - g_object_unref (connection); - g_free (mime_types); -} - -static void -handle_method_call_index_file (TrackerMinerFilesIndex *miner, - GDBusMethodInvocation *invocation, - GVariant *parameters, - gboolean watch_source) -{ - TrackerMinerFilesIndexPrivate *priv; - TrackerDBusRequest *request; - GFile *file; - GFileInfo *file_info; - gboolean is_dir; - gboolean do_checks = FALSE; - GError *internal_error; - const gchar *file_uri; - - priv = TRACKER_MINER_FILES_INDEX_GET_PRIVATE (miner); - - g_variant_get (parameters, "(&s)", &file_uri); - - tracker_gdbus_async_return_if_fail (file_uri != NULL, invocation); - - request = tracker_g_dbus_request_begin (invocation, "%s(uri:'%s')", __FUNCTION__, file_uri); - - file = g_file_new_for_uri (file_uri); - - file_info = g_file_query_info (file, - G_FILE_ATTRIBUTE_STANDARD_TYPE, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, NULL); - - if (!file_info) { - internal_error = g_error_new_literal (1, 0, "File does not exist"); - tracker_dbus_request_end (request, internal_error); - g_dbus_method_invocation_return_gerror (invocation, internal_error); - - g_error_free (internal_error); - - g_object_unref (file); - - return; - } - - is_dir = (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY); - g_object_unref (file_info); - -#ifdef REQUIRE_LOCATION_IN_CONFIG - do_checks = TRUE; - if (!tracker_miner_files_is_file_eligible (priv->files_miner, file)) { - internal_error = g_error_new_literal (1, 0, "File is not eligible to be indexed"); - tracker_dbus_request_end (request, internal_error); - g_dbus_method_invocation_return_gerror (invocation, internal_error); - - g_error_free (internal_error); - - g_object_unref (file); - - return; - } -#endif /* REQUIRE_LOCATION_IN_CONFIG */ - - if (is_dir) { - TrackerIndexingTree *indexing_tree; - TrackerDirectoryFlags flags; - gboolean is_watched, needs_watch = FALSE; - GFile *root; - - indexing_tree = tracker_miner_fs_get_indexing_tree (TRACKER_MINER_FS (priv->files_miner)); - root = tracker_indexing_tree_get_root (indexing_tree, file, &flags); - - /* If the directory had already subscribers, we want to add all - * further watches, so the directory survives as long as there's - * watchers. - */ - is_watched = tracker_miner_files_peer_listener_is_file_watched (priv->peer_listener, file); - - /* Check whether the requested dir is not over a (recursively) - * watched directory already, in that case we don't add the - * directory (nor add a watch if we're positive it comes from - * config). - */ - if (!root || - (!(flags & TRACKER_DIRECTORY_FLAG_RECURSE) && - !g_file_equal (root, file) && - !g_file_has_parent (file, root))) { - tracker_indexing_tree_add (indexing_tree, file, - TRACKER_DIRECTORY_FLAG_RECURSE | - TRACKER_DIRECTORY_FLAG_PRIORITY | - TRACKER_DIRECTORY_FLAG_CHECK_MTIME | - TRACKER_DIRECTORY_FLAG_MONITOR); - needs_watch = TRUE; - } else { - tracker_indexing_tree_notify_update (indexing_tree, file, TRUE); - } - - if (watch_source && (is_watched || needs_watch)) { - tracker_miner_files_peer_listener_add_watch (priv->peer_listener, - g_dbus_method_invocation_get_sender (invocation), - file); - } - } else { - tracker_miner_fs_check_file (TRACKER_MINER_FS (priv->files_miner), - file, G_PRIORITY_HIGH, do_checks); - } - - tracker_dbus_request_end (request, NULL); - g_dbus_method_invocation_return_value (invocation, NULL); - - g_object_unref (file); -} - -static void -handle_method_call (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) -{ - TrackerMinerFilesIndex *miner = user_data; - - tracker_gdbus_async_return_if_fail (miner != NULL, invocation); - tracker_gdbus_async_return_if_fail (TRACKER_IS_MINER_FILES_INDEX (miner), invocation); - - if (g_strcmp0 (method_name, "ReindexMimeTypes") == 0) { - tracker_miner_files_index_reindex_mime_types (miner, invocation, parameters); - } else if (g_strcmp0 (method_name, "IndexFile") == 0) { - handle_method_call_index_file (miner, invocation, parameters, FALSE); - } else if (g_strcmp0 (method_name, "IndexFileForProcess") == 0) { - handle_method_call_index_file (miner, invocation, parameters, TRUE); - } else { - g_assert_not_reached (); - } -} - -static void -peer_listener_unwatch_file (TrackerMinerFilesPeerListener *listener, - GFile *file, - gpointer user_data) -{ - TrackerMinerFilesIndexPrivate *priv; - TrackerIndexingTree *indexing_tree; - - priv = TRACKER_MINER_FILES_INDEX_GET_PRIVATE (user_data); - indexing_tree = tracker_miner_fs_get_indexing_tree (TRACKER_MINER_FS (priv->files_miner)); - tracker_indexing_tree_remove (indexing_tree, file); -} - -static void -indexing_tree_directory_remove (TrackerIndexingTree *indexing_tree, - GFile *file, - gpointer user_data) -{ - TrackerMinerFilesIndexPrivate *priv; - - priv = TRACKER_MINER_FILES_INDEX_GET_PRIVATE (user_data); - tracker_miner_files_peer_listener_remove_file (priv->peer_listener, file); -} - -static GVariant * -handle_get_property (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *property_name, - GError **error, - gpointer user_data) -{ - g_assert_not_reached (); - return NULL; -} - -static gboolean -handle_set_property (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *property_name, - GVariant *value, - GError **error, - gpointer user_data) -{ - g_assert_not_reached (); - return TRUE; -} - -static void -tracker_miner_files_index_init (TrackerMinerFilesIndex *object) -{ -} - -TrackerMinerFilesIndex * -tracker_miner_files_index_new (TrackerMinerFiles *miner_files) -{ - GObject *miner; - TrackerMinerFilesIndexPrivate *priv; - gchar *full_path, *full_name; - GError *error = NULL; - TrackerIndexingTree *indexing_tree; - GDBusInterfaceVTable interface_vtable = { - handle_method_call, - handle_get_property, - handle_set_property - }; - - miner = g_object_new (TRACKER_TYPE_MINER_FILES_INDEX, - "files-miner", miner_files, - NULL); - - priv = TRACKER_MINER_FILES_INDEX_GET_PRIVATE (miner); - - priv->d_connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, &error); - - if (!priv->d_connection) { - g_critical ("Could not connect to the D-Bus session bus, %s", - error ? error->message : "no error given."); - g_clear_error (&error); - g_object_unref (miner); - return NULL; - } - - priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, &error); - if (!priv->introspection_data) { - g_critical ("Could not create node info from introspection XML, %s", - error ? error->message : "no error given."); - g_clear_error (&error); - return NULL; - } - - full_name = g_strconcat (TRACKER_MINER_DBUS_NAME_PREFIX, "Files.Index", NULL); - priv->full_name = full_name; - - /* Register the service name for the miner */ - full_path = g_strconcat (TRACKER_MINER_DBUS_PATH_PREFIX, "Files/Index", NULL); - - g_message ("Registering D-Bus object..."); - g_message (" Path:'%s'", full_path); - g_message (" Object Type:'%s'", G_OBJECT_TYPE_NAME (miner)); - - priv->registration_id = - g_dbus_connection_register_object (priv->d_connection, - full_path, - priv->introspection_data->interfaces[0], - &interface_vtable, - miner, - NULL, - &error); - - if (error) { - g_critical ("Could not register the D-Bus object %s, %s", - full_path, - error ? error->message : "no error given."); - g_clear_error (&error); - g_object_unref (miner); - return NULL; - } - - priv->full_path = full_path; - - priv->peer_listener = tracker_miner_files_peer_listener_new (priv->d_connection); - g_signal_connect (priv->peer_listener, "unwatch-file", - G_CALLBACK (peer_listener_unwatch_file), miner); - - indexing_tree = tracker_miner_fs_get_indexing_tree (TRACKER_MINER_FS (miner_files)); - g_signal_connect (indexing_tree, "directory-removed", - G_CALLBACK (indexing_tree_directory_remove), miner); - - return (TrackerMinerFilesIndex *) miner; -} diff --git a/src/miners/fs/tracker-miner-files-index.h b/src/miners/fs/tracker-miner-files-index.h deleted file mode 100644 index 447d9e293..000000000 --- a/src/miners/fs/tracker-miner-files-index.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_MINER_FS_FILES_INDEX_H__ -#define __TRACKER_MINER_FS_FILES_INDEX_H__ - -#include <glib-object.h> - -#include "tracker-miner-files.h" - -G_BEGIN_DECLS - -#define TRACKER_TYPE_MINER_FILES_INDEX (tracker_miner_files_index_get_type ()) -#define TRACKER_MINER_FILES_INDEX(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TRACKER_TYPE_MINER_FILES_INDEX, TrackerMinerFilesIndex)) -#define TRACKER_MINER_FILES_INDEX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TRACKER_TYPE_DBUS_MINER_FILES_INDEX, TrackerMinerFilesIndexClass)) -#define TRACKER_IS_MINER_FILES_INDEX(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TRACKER_TYPE_MINER_FILES_INDEX)) -#define TRACKER_IS_MINER_FILES_INDEX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TRACKER_TYPE_MINER_FILES_INDEX)) -#define TRACKER_MINER_FILES_INDEX_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TRACKER_TYPE_MINER_FILES_INDEX, TrackerMinerFilesIndexClass)) - -typedef struct TrackerMinerFilesIndex TrackerMinerFilesIndex; -typedef struct TrackerMinerFilesIndexClass TrackerMinerFilesIndexClass; - -struct TrackerMinerFilesIndex { - GObject parent; -}; - -struct TrackerMinerFilesIndexClass { - GObjectClass parent; -}; - -GType tracker_miner_files_index_get_type (void); -TrackerMinerFilesIndex *tracker_miner_files_index_new (TrackerMinerFiles *miner_files); - -G_END_DECLS - -#endif /* __TRACKER_MINER_FS_FILES_INDEX_H__ */ diff --git a/src/miners/fs/tracker-miner-files-index.xml b/src/miners/fs/tracker-miner-files-index.xml deleted file mode 100644 index 4e02ba3d7..000000000 --- a/src/miners/fs/tracker-miner-files-index.xml +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<node name="/"> - <interface name="org.freedesktop.Tracker1.Miner.Files.Index"> - <method name="ReindexMimeTypes"> - <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> - <arg type="as" name="mime_types" direction="in" /> - </method> - <method name="IndexFile"> - <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> - <arg type="s" name="file_uri" direction="in" /> - </method> - <method name="IndexFileForProcess"> - <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> - <arg type="s" name="file_uri" direction="in" /> - </method> - </interface> -</node> diff --git a/src/miners/fs/tracker-miner-files-peer-listener.c b/src/miners/fs/tracker-miner-files-peer-listener.c deleted file mode 100644 index 7a1467789..000000000 --- a/src/miners/fs/tracker-miner-files-peer-listener.c +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright (C) 2015, Carlos Garnacho - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * Author: Carlos Garnacho <carlosg@gnome.org> - */ - -/* TrackerMinerFilesPeerListener is a helper object to keep track - * of the DBus callers that request directories to be indexed. The - * ::unwatch-file will be emitted as soon as there's no further - * requestors on a directory, be it due to disconnections, or due - * to other reasons (tracker_indexing_tree_remove() being called - * externally, eg. when the directory being monitored is unmounted). - */ - -#include "tracker-miner-files-peer-listener.h" - -enum { - PROP_CONNECTION = 1 -}; - -enum { - WATCH_FILE, - UNWATCH_FILE, - N_SIGNALS -}; - -static guint signals[N_SIGNALS] = { 0 }; - -typedef struct { - gchar *dbus_name; - GPtrArray *files; /* Array of GFiles, actually owned by FilePeersData */ - guint watch_id; -} PeerFilesData; - -typedef struct { - GFile *file; - GPtrArray *peers; /* Array of dbus names, actually owned by PeerFilesData */ -} FilePeersData; - -typedef struct { - GDBusConnection *d_connection; - GHashTable *peer_files; /* dbus name -> PeerFilesData */ - GHashTable *file_peers; /* GFile -> FilePeersData */ -} TrackerMinerFilesPeerListenerPrivate; - -G_DEFINE_TYPE_WITH_PRIVATE (TrackerMinerFilesPeerListener, - tracker_miner_files_peer_listener, - G_TYPE_OBJECT) - -static void -on_app_disappeared_cb (GDBusConnection *conn, - const gchar *dbus_name, - gpointer user_data) -{ - TrackerMinerFilesPeerListener *listener = user_data; - - tracker_miner_files_peer_listener_remove_dbus_name (listener, dbus_name); -} - -static PeerFilesData * -peer_files_data_new (const gchar *dbus_name, - TrackerMinerFilesPeerListener *listener) -{ - TrackerMinerFilesPeerListenerPrivate *priv; - PeerFilesData *data; - - priv = tracker_miner_files_peer_listener_get_instance_private (listener); - - data = g_slice_new0 (PeerFilesData); - data->dbus_name = g_strdup (dbus_name); - data->files = g_ptr_array_new (); - data->watch_id = g_bus_watch_name_on_connection (priv->d_connection, - dbus_name, 0, NULL, - on_app_disappeared_cb, - listener, NULL); - return data; -} - -static void -peer_files_data_free (PeerFilesData *data) -{ - g_bus_unwatch_name (data->watch_id); - g_ptr_array_unref (data->files); - g_free (data->dbus_name); - g_slice_free (PeerFilesData, data); -} - -static void -peer_files_data_add_file (PeerFilesData *data, - GFile *file) -{ - g_ptr_array_add (data->files, file); -} - -static void -peer_files_data_remove_file (PeerFilesData *data, - GFile *file) -{ - gint i; - - for (i = 0; i < data->files->len; i++) { - if (file != g_ptr_array_index (data->files, i)) - continue; - - g_ptr_array_remove_index (data->files, i); - break; - } -} - -static FilePeersData * -file_peers_data_new (GFile *file) -{ - FilePeersData *data; - - g_return_val_if_fail (G_IS_FILE (file), NULL); - - data = g_slice_new0 (FilePeersData); - data->file = g_object_ref (file); - data->peers = g_ptr_array_new (); - - return data; -} - -static void -file_peers_data_free (FilePeersData *data) -{ - g_object_unref (data->file); - g_ptr_array_unref (data->peers); - g_slice_free (FilePeersData, data); -} - -static void -file_peers_data_add_dbus_name (FilePeersData *data, - gchar *dbus_name) -{ - g_ptr_array_add (data->peers, dbus_name); -} - -static void -file_peers_data_remove_dbus_name (FilePeersData *data, - gchar *dbus_name) -{ - gint i; - - for (i = 0; i < data->peers->len; i++) { - if (dbus_name != g_ptr_array_index (data->peers, i)) - continue; - - g_ptr_array_remove_index (data->peers, i); - break; - } -} - -static void -tracker_miner_files_peer_listener_finalize (GObject *object) -{ - TrackerMinerFilesPeerListener *listener; - TrackerMinerFilesPeerListenerPrivate *priv; - - listener = TRACKER_MINER_FILES_PEER_LISTENER (object); - priv = tracker_miner_files_peer_listener_get_instance_private (listener); - g_hash_table_destroy (priv->peer_files); - g_hash_table_destroy (priv->file_peers); - g_object_unref (priv->d_connection); - - G_OBJECT_CLASS (tracker_miner_files_peer_listener_parent_class)->finalize (object); -} - -static void -tracker_miner_files_peer_listener_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - TrackerMinerFilesPeerListenerPrivate *priv; - TrackerMinerFilesPeerListener *listener; - - listener = TRACKER_MINER_FILES_PEER_LISTENER (object); - priv = tracker_miner_files_peer_listener_get_instance_private (listener); - - switch (prop_id) { - case PROP_CONNECTION: - priv->d_connection = g_value_dup_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -tracker_miner_files_peer_listener_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - TrackerMinerFilesPeerListenerPrivate *priv; - TrackerMinerFilesPeerListener *listener; - - listener = TRACKER_MINER_FILES_PEER_LISTENER (object); - priv = tracker_miner_files_peer_listener_get_instance_private (listener); - - switch (prop_id) { - case PROP_CONNECTION: - g_value_set_object (value, priv->d_connection); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -tracker_miner_files_peer_listener_class_init (TrackerMinerFilesPeerListenerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = tracker_miner_files_peer_listener_finalize; - object_class->set_property = tracker_miner_files_peer_listener_set_property; - object_class->get_property = tracker_miner_files_peer_listener_get_property; - - g_object_class_install_property (object_class, - PROP_CONNECTION, - g_param_spec_object ("connection", - "Connection", - "Connection", - G_TYPE_DBUS_CONNECTION, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - signals[WATCH_FILE] = - g_signal_new ("watch-file", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_FILE); - signals[UNWATCH_FILE] = - g_signal_new ("unwatch-file", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, 0, - NULL, NULL, NULL, - G_TYPE_NONE, 1, G_TYPE_FILE); -} - -static void -tracker_miner_files_peer_listener_init (TrackerMinerFilesPeerListener *listener) -{ - TrackerMinerFilesPeerListenerPrivate *priv; - - priv = tracker_miner_files_peer_listener_get_instance_private (listener); - priv->peer_files = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, - (GDestroyNotify) peer_files_data_free); - priv->file_peers = g_hash_table_new_full (g_file_hash, - (GEqualFunc) g_file_equal, NULL, - (GDestroyNotify) file_peers_data_free); -} - -TrackerMinerFilesPeerListener * -tracker_miner_files_peer_listener_new (GDBusConnection *connection) -{ - return g_object_new (TRACKER_TYPE_MINER_FILES_PEER_LISTENER, - "connection", connection, - NULL); -} - -static void -unwatch_file (TrackerMinerFilesPeerListener *listener, - GFile *file) -{ - TrackerMinerFilesPeerListenerPrivate *priv; - - priv = tracker_miner_files_peer_listener_get_instance_private (listener); - - g_object_ref (file); - g_hash_table_remove (priv->file_peers, file); - g_signal_emit (listener, signals[UNWATCH_FILE], 0, file); - g_object_unref (file); -} - -void -tracker_miner_files_peer_listener_add_watch (TrackerMinerFilesPeerListener *listener, - const gchar *dbus_name, - GFile *file) -{ - TrackerMinerFilesPeerListenerPrivate *priv; - PeerFilesData *peer_data; - FilePeersData *file_data; - - g_return_if_fail (TRACKER_IS_MINER_FILES_PEER_LISTENER (listener)); - g_return_if_fail (G_IS_FILE (file)); - g_return_if_fail (dbus_name != NULL); - - priv = tracker_miner_files_peer_listener_get_instance_private (listener); - - peer_data = g_hash_table_lookup (priv->peer_files, dbus_name); - file_data = g_hash_table_lookup (priv->file_peers, file); - - if (!peer_data) { - peer_data = peer_files_data_new (dbus_name, listener); - g_hash_table_insert (priv->peer_files, - peer_data->dbus_name, peer_data); - } - - if (!file_data) { - gchar *uri; - - file_data = file_peers_data_new (file); - g_hash_table_insert (priv->file_peers, - file_data->file, file_data); - g_signal_emit (listener, signals[WATCH_FILE], 0, file_data->file); - - uri = g_file_get_uri (file); - g_debug ("Client '%s' requests watch on '%s'", dbus_name, uri); - g_free (uri); - } - - peer_files_data_add_file (peer_data, file_data->file); - file_peers_data_add_dbus_name (file_data, peer_data->dbus_name); -} - -void -tracker_miner_files_peer_listener_remove_watch (TrackerMinerFilesPeerListener *listener, - const gchar *dbus_name, - GFile *file) -{ - TrackerMinerFilesPeerListenerPrivate *priv; - PeerFilesData *peer_data; - FilePeersData *file_data; - - g_return_if_fail (TRACKER_IS_MINER_FILES_PEER_LISTENER (listener)); - g_return_if_fail (G_IS_FILE (file)); - g_return_if_fail (dbus_name != NULL); - - priv = tracker_miner_files_peer_listener_get_instance_private (listener); - - peer_data = g_hash_table_lookup (priv->peer_files, dbus_name); - file_data = g_hash_table_lookup (priv->file_peers, file); - - if (!file_data || !peer_data) - return; - - peer_files_data_remove_file (peer_data, file_data->file); - file_peers_data_remove_dbus_name (file_data, peer_data->dbus_name); - - if (peer_data->files->len == 0) - g_hash_table_remove (priv->peer_files, peer_data->dbus_name); - - if (file_data->peers->len == 0) - unwatch_file (listener, file_data->file); -} - -void -tracker_miner_files_peer_listener_remove_dbus_name (TrackerMinerFilesPeerListener *listener, - const gchar *dbus_name) -{ - TrackerMinerFilesPeerListenerPrivate *priv; - PeerFilesData *peer_data; - FilePeersData *file_data; - GFile *file; - gint i; - - g_return_if_fail (TRACKER_IS_MINER_FILES_PEER_LISTENER (listener)); - g_return_if_fail (dbus_name != NULL); - - priv = tracker_miner_files_peer_listener_get_instance_private (listener); - peer_data = g_hash_table_lookup (priv->peer_files, dbus_name); - - if (!peer_data) - return; - - g_debug ("Removing all watches from client '%s'", dbus_name); - - for (i = 0; i < peer_data->files->len; i++) { - file = g_ptr_array_index (peer_data->files, i); - file_data = g_hash_table_lookup (priv->file_peers, file); - - if (!file_data) - continue; - - file_peers_data_remove_dbus_name (file_data, peer_data->dbus_name); - - if (file_data->peers->len == 0) - unwatch_file (listener, file_data->file); - } - - g_hash_table_remove (priv->peer_files, dbus_name); -} - -void -tracker_miner_files_peer_listener_remove_file (TrackerMinerFilesPeerListener *listener, - GFile *file) -{ - TrackerMinerFilesPeerListenerPrivate *priv; - PeerFilesData *peer_data; - FilePeersData *file_data; - const gchar *dbus_name; - gchar *uri; - gint i; - - g_return_if_fail (TRACKER_IS_MINER_FILES_PEER_LISTENER (listener)); - g_return_if_fail (G_IS_FILE (file)); - - priv = tracker_miner_files_peer_listener_get_instance_private (listener); - file_data = g_hash_table_lookup (priv->file_peers, file); - - if (!file_data || file_data->peers->len == 0) - return; - - uri = g_file_get_uri (file); - g_debug ("Removing client listeners for file '%s'", uri); - g_free (uri); - - for (i = 0; i < file_data->peers->len; i++) { - dbus_name = g_ptr_array_index (file_data->peers, i); - peer_data = g_hash_table_lookup (priv->peer_files, dbus_name); - - if (!peer_data) - continue; - - peer_files_data_remove_file (peer_data, file_data->file); - - if (peer_data->files->len == 0) - g_hash_table_remove (priv->peer_files, dbus_name); - } - - unwatch_file (listener, file); -} - -gboolean -tracker_miner_files_peer_listener_is_file_watched (TrackerMinerFilesPeerListener *listener, - GFile *file) -{ - TrackerMinerFilesPeerListenerPrivate *priv; - - g_return_val_if_fail (TRACKER_IS_MINER_FILES_PEER_LISTENER (listener), FALSE); - g_return_val_if_fail (G_IS_FILE (file), FALSE); - - priv = tracker_miner_files_peer_listener_get_instance_private (listener); - - return g_hash_table_lookup (priv->file_peers, file) != NULL; -} diff --git a/src/miners/fs/tracker-miner-files-peer-listener.h b/src/miners/fs/tracker-miner-files-peer-listener.h deleted file mode 100644 index 7a23d328d..000000000 --- a/src/miners/fs/tracker-miner-files-peer-listener.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2015, Carlos Garnacho - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * Author: Carlos Garnacho <carlosg@gnome.org> - */ - -#ifndef __TRACKER_MINER_FILES_PEER_LISTENER_H__ -#define __TRACKER_MINER_FILES_PEER_LISTENER_H__ - -#include <glib-object.h> -#include <gio/gio.h> - -#define TRACKER_TYPE_MINER_FILES_PEER_LISTENER (tracker_miner_files_peer_listener_get_type ()) -#define TRACKER_MINER_FILES_PEER_LISTENER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TRACKER_TYPE_MINER_FILES_PEER_LISTENER, TrackerMinerFilesPeerListener)) -#define TRACKER_MINER_FILES_PEER_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TRACKER_TYPE_DBUS_MINER_FILES_PEER_LISTENER, TrackerMinerFilesPeerListenerClass)) -#define TRACKER_IS_MINER_FILES_PEER_LISTENER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TRACKER_TYPE_MINER_FILES_PEER_LISTENER)) -#define TRACKER_IS_MINER_FILES_PEER_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TRACKER_TYPE_MINER_FILES_PEER_LISTENER)) -#define TRACKER_MINER_FILES_PEER_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TRACKER_TYPE_MINER_FILES_PEER_LISTENER, TrackerMinerFilesPeerListenerClass)) - -typedef struct _TrackerMinerFilesPeerListener TrackerMinerFilesPeerListener; -typedef struct _TrackerMinerFilesPeerListenerClass TrackerMinerFilesPeerListenerClass; - -struct _TrackerMinerFilesPeerListener { - GObject parent_instance; -}; - -struct _TrackerMinerFilesPeerListenerClass { - GObjectClass parent_class; -}; - -GType tracker_miner_files_peer_listener_get_type (void) G_GNUC_CONST; - -TrackerMinerFilesPeerListener * - tracker_miner_files_peer_listener_new (GDBusConnection *connection); - -void tracker_miner_files_peer_listener_add_watch (TrackerMinerFilesPeerListener *listener, - const gchar *dbus_name, - GFile *file); -void tracker_miner_files_peer_listener_remove_watch (TrackerMinerFilesPeerListener *listener, - const gchar *dbus_name, - GFile *file); - -void tracker_miner_files_peer_listener_remove_dbus_name (TrackerMinerFilesPeerListener *listener, - const gchar *dbus_name); -void tracker_miner_files_peer_listener_remove_file (TrackerMinerFilesPeerListener *listener, - GFile *file); -gboolean tracker_miner_files_peer_listener_is_file_watched (TrackerMinerFilesPeerListener *listener, - GFile *file); - -#endif /* __TRACKER_MINER_FILES_PEER_LISTENER_H__ */ diff --git a/src/miners/fs/tracker-miner-files.c b/src/miners/fs/tracker-miner-files.c deleted file mode 100644 index 87eb6ae11..000000000 --- a/src/miners/fs/tracker-miner-files.c +++ /dev/null @@ -1,3557 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <sys/statvfs.h> -#include <fcntl.h> -#ifdef __linux__ -#include <sys/ioctl.h> -#include <linux/msdos_fs.h> -#endif /* __linux__ */ -#include <unistd.h> - -#include <glib/gi18n.h> -#include <glib/gstdio.h> - -#include <gio/gio.h> -#include <gio/gunixfdlist.h> -#include <gio/gunixinputstream.h> - -#include <libtracker-common/tracker-common.h> -#include <libtracker-sparql/tracker-ontologies.h> -#include <libtracker-extract/tracker-extract.h> - -#include <libtracker-data/tracker-db-manager.h> - -#include "tracker-power.h" -#include "tracker-miner-files.h" -#include "tracker-config.h" -#include "tracker-storage.h" -#include "tracker-extract-watchdog.h" -#include "tracker-thumbnailer.h" - -#define DISK_SPACE_CHECK_FREQUENCY 10 -#define SECONDS_PER_DAY 86400 - -/* Stamp files to know crawling/indexing state */ -#define FIRST_INDEX_FILENAME "first-index.txt" -#define LAST_CRAWL_FILENAME "last-crawl.txt" -#define NEED_MTIME_CHECK_FILENAME "no-need-mtime-check.txt" - -#define TRACKER_MINER_FILES_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_MINER_FILES, TrackerMinerFilesPrivate)) - -static GQuark miner_files_error_quark = 0; - -typedef struct ProcessFileData ProcessFileData; - -struct ProcessFileData { - TrackerMinerFiles *miner; - TrackerSparqlBuilder *sparql; - GCancellable *cancellable; - GFile *file; - gchar *mime_type; - GTask *task; -}; - -struct TrackerMinerFilesPrivate { - TrackerConfig *config; - TrackerStorage *storage; - TrackerExtractWatchdog *extract_watchdog; - - GVolumeMonitor *volume_monitor; - - GSList *index_recursive_directories; - GSList *index_single_directories; - - guint disk_space_check_id; - gboolean disk_space_pause; - - gboolean low_battery_pause; - -#if defined(HAVE_UPOWER) || defined(HAVE_HAL) - TrackerPower *power; -#endif /* defined(HAVE_UPOWER) || defined(HAVE_HAL) */ - gulong finished_handler; - - GDBusConnection *connection; - - GQuark quark_mount_point_uuid; - - guint force_recheck_id; - - gboolean mtime_check; - gboolean index_removable_devices; - gboolean index_optical_discs; - guint volumes_changed_id; - - gboolean mount_points_initialized; - - guint stale_volumes_check_id; - - GList *extraction_queue; - - TrackerThumbnailer *thumbnailer; - - GHashTable *writeback_tasks; - gboolean paused_for_writeback; -}; - -typedef struct { - GMainLoop *main_loop; - TrackerMiner *miner; -} ThumbnailMoveData; - -enum { - VOLUME_MOUNTED_IN_STORE = 1 << 0, - VOLUME_MOUNTED = 1 << 1 -}; - -enum { - PROP_0, - PROP_CONFIG -}; - -enum { - WRITEBACK, - N_SIGNALS -}; - -static guint signals[N_SIGNALS] = { 0 }; - -static void miner_files_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); -static void miner_files_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); -static void miner_files_finalize (GObject *object); -static void miner_files_initable_iface_init (GInitableIface *iface); -static gboolean miner_files_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error); -static void mount_pre_unmount_cb (GVolumeMonitor *volume_monitor, - GMount *mount, - TrackerMinerFiles *mf); - -static void mount_point_added_cb (TrackerStorage *storage, - const gchar *uuid, - const gchar *mount_point, - const gchar *mount_name, - gboolean removable, - gboolean optical, - gpointer user_data); -static void mount_point_removed_cb (TrackerStorage *storage, - const gchar *uuid, - const gchar *mount_point, - gpointer user_data); -#if defined(HAVE_UPOWER) || defined(HAVE_HAL) -static void check_battery_status (TrackerMinerFiles *fs); -static void battery_status_cb (GObject *object, - GParamSpec *pspec, - gpointer user_data); -static void index_on_battery_cb (GObject *object, - GParamSpec *pspec, - gpointer user_data); -#endif /* defined(HAVE_UPOWER) || defined(HAVE_HAL) */ -static void init_mount_points (TrackerMinerFiles *miner); -static void init_stale_volume_removal (TrackerMinerFiles *miner); -static void disk_space_check_start (TrackerMinerFiles *mf); -static void disk_space_check_stop (TrackerMinerFiles *mf); -static void low_disk_space_limit_cb (GObject *gobject, - GParamSpec *arg1, - gpointer user_data); -static void index_recursive_directories_cb (GObject *gobject, - GParamSpec *arg1, - gpointer user_data); -static void index_single_directories_cb (GObject *gobject, - GParamSpec *arg1, - gpointer user_data); -static gboolean miner_files_force_recheck_idle (gpointer user_data); -static void trigger_recheck_cb (GObject *gobject, - GParamSpec *arg1, - gpointer user_data); -static void index_volumes_changed_cb (GObject *gobject, - GParamSpec *arg1, - gpointer user_data); -static gboolean miner_files_process_file (TrackerMinerFS *fs, - GFile *file, - GTask *task); -static gboolean miner_files_process_file_attributes (TrackerMinerFS *fs, - GFile *file, - GTask *task); -static gchar * miner_files_remove_children (TrackerMinerFS *fs, - GFile *file); -static gchar * miner_files_remove_file (TrackerMinerFS *fs, - GFile *file); -static gchar * miner_files_move_file (TrackerMinerFS *fs, - GFile *file, - GFile *source_file, - gboolean recursive); -static void miner_files_finished (TrackerMinerFS *fs, - gdouble elapsed, - gint directories_found, - gint directories_ignored, - gint files_found, - gint files_ignored); -static void miner_finished_cb (TrackerMinerFS *fs, - gdouble seconds_elapsed, - guint total_directories_found, - guint total_directories_ignored, - guint total_files_found, - guint total_files_ignored, - gpointer user_data); - -static gboolean miner_files_in_removable_media_remove_by_type (TrackerMinerFiles *miner, - TrackerStorageType type); -static void miner_files_in_removable_media_remove_by_date (TrackerMinerFiles *miner, - const gchar *date); - -static void miner_files_add_removable_or_optical_directory (TrackerMinerFiles *mf, - const gchar *mount_path, - const gchar *uuid); - -static void miner_files_update_filters (TrackerMinerFiles *files); - - -static GInitableIface* miner_files_initable_parent_iface; - -G_DEFINE_TYPE_WITH_CODE (TrackerMinerFiles, tracker_miner_files, TRACKER_TYPE_MINER_FS, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - miner_files_initable_iface_init)); - -static void -sync_writeback_pause_state (TrackerMinerFiles *mf) -{ - guint n_writeback_tasks = g_hash_table_size (mf->private->writeback_tasks); - - if (n_writeback_tasks > 0 && !mf->private->paused_for_writeback) { - tracker_miner_pause (TRACKER_MINER (mf)); - mf->private->paused_for_writeback = TRUE; - } else if (n_writeback_tasks == 0 && mf->private->paused_for_writeback) { - mf->private->paused_for_writeback = FALSE; - tracker_miner_resume (TRACKER_MINER (mf)); - } -} - -static void -writeback_remove_recursively (TrackerMinerFiles *mf, - GFile *file) -{ - GHashTableIter iter; - GFile *writeback_file; - - if (g_hash_table_size (mf->private->writeback_tasks) == 0) - return; - - /* Remove and cancel writeback tasks in this directory */ - g_hash_table_iter_init (&iter, mf->private->writeback_tasks); - while (g_hash_table_iter_next (&iter, (gpointer*) &writeback_file, NULL)) { - if (g_file_equal (writeback_file, file) || - g_file_has_prefix (writeback_file, file)) { - g_hash_table_iter_remove (&iter); - } - } - - sync_writeback_pause_state (mf); -} - -static gboolean -miner_files_filter_event (TrackerMinerFS *fs, - TrackerMinerFSEventType type, - GFile *file, - GFile *source_file) -{ - TrackerMinerFiles *mf = TRACKER_MINER_FILES (fs); - GCancellable *cancellable; - - switch (type) { - case TRACKER_MINER_FS_EVENT_CREATED: - break; - case TRACKER_MINER_FS_EVENT_UPDATED: - /* If the file is in the writeback task pool, this is the - * file update applying it, so the event should be filtered - * out. - */ - if (g_hash_table_lookup_extended (mf->private->writeback_tasks, file, - NULL, (gpointer*) &cancellable)) { - if (!cancellable) { - /* The task was already notified, we can remove - * it now, so later updates will be processed. - */ - g_hash_table_remove (mf->private->writeback_tasks, file); - sync_writeback_pause_state (mf); - } - - /* There is a writeback task, pending or satisfied. - * Either way, this update should be ignored. - */ - return TRUE; - } - break; - case TRACKER_MINER_FS_EVENT_DELETED: - writeback_remove_recursively (mf, file); - break; - case TRACKER_MINER_FS_EVENT_MOVED: - /* If the origin file is also being written back, - * cancel it as this is an external operation. - */ - writeback_remove_recursively (mf, source_file); - break; - } - - return FALSE; -} - -static void -tracker_miner_files_class_init (TrackerMinerFilesClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - TrackerMinerFSClass *miner_fs_class = TRACKER_MINER_FS_CLASS (klass); - - object_class->finalize = miner_files_finalize; - object_class->get_property = miner_files_get_property; - object_class->set_property = miner_files_set_property; - - miner_fs_class->process_file = miner_files_process_file; - miner_fs_class->process_file_attributes = miner_files_process_file_attributes; - miner_fs_class->finished = miner_files_finished; - miner_fs_class->remove_file = miner_files_remove_file; - miner_fs_class->remove_children = miner_files_remove_children; - miner_fs_class->move_file = miner_files_move_file; - miner_fs_class->filter_event = miner_files_filter_event; - - /** - * TrackerMinerFiles::writeback-file: - * @miner: the #TrackerMinerFiles - * @file: a #GFile - * @rdf_types: the set of RDF types - * @results: (element-type GStrv): a set of results prepared by the preparation query - * @cancellable: a #GCancellable - * - * The ::writeback-file signal is emitted whenever a file must be written - * back - * - * Returns: %TRUE on success, %FALSE otherwise - **/ - signals[WRITEBACK] = - g_signal_new ("writeback", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - 0, NULL, - NULL, - NULL, - G_TYPE_NONE, - 4, - G_TYPE_FILE, - G_TYPE_STRV, - G_TYPE_PTR_ARRAY, - G_TYPE_CANCELLABLE); - - g_object_class_install_property (object_class, - PROP_CONFIG, - g_param_spec_object ("config", - "Config", - "Config", - TRACKER_TYPE_CONFIG, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_type_class_add_private (klass, sizeof (TrackerMinerFilesPrivate)); - - miner_files_error_quark = g_quark_from_static_string ("TrackerMinerFiles"); -} - -static void -cancel_and_unref (gpointer data) -{ - GCancellable *cancellable = data; - - if (cancellable) { - g_cancellable_cancel (cancellable); - g_object_unref (cancellable); - } -} - -static void -tracker_miner_files_init (TrackerMinerFiles *mf) -{ - TrackerMinerFilesPrivate *priv; - - priv = mf->private = TRACKER_MINER_FILES_GET_PRIVATE (mf); - - priv->storage = tracker_storage_new (); - - g_signal_connect (priv->storage, "mount-point-added", - G_CALLBACK (mount_point_added_cb), - mf); - - g_signal_connect (priv->storage, "mount-point-removed", - G_CALLBACK (mount_point_removed_cb), - mf); - -#if defined(HAVE_UPOWER) || defined(HAVE_HAL) - priv->power = tracker_power_new (); - - g_signal_connect (priv->power, "notify::on-low-battery", - G_CALLBACK (battery_status_cb), - mf); - g_signal_connect (priv->power, "notify::on-battery", - G_CALLBACK (battery_status_cb), - mf); -#endif /* defined(HAVE_UPOWER) || defined(HAVE_HAL) */ - - priv->finished_handler = g_signal_connect_after (mf, "finished", - G_CALLBACK (miner_finished_cb), - NULL); - - priv->volume_monitor = g_volume_monitor_get (); - g_signal_connect (priv->volume_monitor, "mount-pre-unmount", - G_CALLBACK (mount_pre_unmount_cb), - mf); - - priv->mtime_check = TRUE; - priv->quark_mount_point_uuid = g_quark_from_static_string ("tracker-mount-point-uuid"); - - priv->writeback_tasks = g_hash_table_new_full (g_file_hash, - (GEqualFunc) g_file_equal, - NULL, cancel_and_unref); -} - -static void -miner_files_initable_iface_init (GInitableIface *iface) -{ - miner_files_initable_parent_iface = g_type_interface_peek_parent (iface); - iface->init = miner_files_initable_init; -} - -static gboolean -miner_files_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - TrackerMinerFiles *mf; - TrackerMinerFS *fs; - TrackerIndexingTree *indexing_tree; - TrackerDirectoryFlags flags; - GError *inner_error = NULL; - GSList *mounts = NULL; - GSList *dirs; - GSList *m; - - /* Chain up parent's initable callback before calling child's one */ - if (!miner_files_initable_parent_iface->init (initable, cancellable, &inner_error)) { - g_propagate_error (error, inner_error); - return FALSE; - } - - mf = TRACKER_MINER_FILES (initable); - fs = TRACKER_MINER_FS (initable); - indexing_tree = tracker_miner_fs_get_indexing_tree (fs); - tracker_indexing_tree_set_filter_hidden (indexing_tree, TRUE); - g_signal_connect_swapped (indexing_tree, "directory-removed", - G_CALLBACK (writeback_remove_recursively), mf); - - miner_files_update_filters (mf); - - /* Set up extractor and signals */ - mf->private->connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, &inner_error); - if (!mf->private->connection) { - g_propagate_error (error, inner_error); - g_prefix_error (error, - "Could not connect to the D-Bus session bus. "); - return FALSE; - } - - /* We must have a configuration setup here */ - if (G_UNLIKELY (!mf->private->config)) { - g_set_error (error, - TRACKER_MINER_ERROR, - 0, - "No config set for miner %s", - G_OBJECT_TYPE_NAME (mf)); - return FALSE; - } - - /* Setup mount points, we MUST have config set up before we - * init mount points because the config is used in that - * function. - */ - mf->private->index_removable_devices = tracker_config_get_index_removable_devices (mf->private->config); - - /* Note that if removable devices not indexed, optical discs - * will also never be indexed */ - mf->private->index_optical_discs = (mf->private->index_removable_devices ? - tracker_config_get_index_optical_discs (mf->private->config) : - FALSE); - - init_mount_points (mf); - - /* If this happened AFTER we have initialized mount points, initialize - * stale volume removal now. */ - if (mf->private->mount_points_initialized) { - init_stale_volume_removal (mf); - } - - if (mf->private->index_removable_devices) { - /* Get list of roots for removable devices (excluding optical) */ - mounts = tracker_storage_get_device_roots (mf->private->storage, - TRACKER_STORAGE_REMOVABLE, - TRUE); - } - - if (mf->private->index_optical_discs) { - /* Get list of roots for removable+optical devices */ - m = tracker_storage_get_device_roots (mf->private->storage, - TRACKER_STORAGE_OPTICAL | TRACKER_STORAGE_REMOVABLE, - TRUE); - mounts = g_slist_concat (mounts, m); - } - -#if defined(HAVE_UPOWER) || defined(HAVE_HAL) - check_battery_status (mf); -#endif /* defined(HAVE_UPOWER) || defined(HAVE_HAL) */ - - g_message ("Setting up directories to iterate from config (IndexSingleDirectory)"); - - /* Fill in directories to inspect */ - dirs = tracker_config_get_index_single_directories (mf->private->config); - - /* Copy in case of config changes */ - mf->private->index_single_directories = tracker_gslist_copy_with_string_data (dirs); - - for (; dirs; dirs = dirs->next) { - GFile *file; - - /* Do some simple checks for silly locations */ - if (strcmp (dirs->data, "/dev") == 0 || - strcmp (dirs->data, "/lib") == 0 || - strcmp (dirs->data, "/proc") == 0 || - strcmp (dirs->data, "/sys") == 0) { - continue; - } - - if (g_str_has_prefix (dirs->data, g_get_tmp_dir ())) { - continue; - } - - /* Make sure we don't crawl volumes. */ - if (mounts) { - gboolean found = FALSE; - - for (m = mounts; m && !found; m = m->next) { - found = strcmp (m->data, dirs->data) == 0; - } - - if (found) { - g_message (" Duplicate found:'%s' - same as removable device path", - (gchar*) dirs->data); - continue; - } - } - - g_message (" Adding:'%s'", (gchar*) dirs->data); - - file = g_file_new_for_path (dirs->data); - - flags = TRACKER_DIRECTORY_FLAG_NONE; - - if (tracker_config_get_enable_monitors (mf->private->config)) { - flags |= TRACKER_DIRECTORY_FLAG_MONITOR; - } - - if (mf->private->mtime_check) { - flags |= TRACKER_DIRECTORY_FLAG_CHECK_MTIME; - } - - tracker_indexing_tree_add (indexing_tree, file, flags); - g_object_unref (file); - } - - g_message ("Setting up directories to iterate from config (IndexRecursiveDirectory)"); - - dirs = tracker_config_get_index_recursive_directories (mf->private->config); - - /* Copy in case of config changes */ - mf->private->index_recursive_directories = tracker_gslist_copy_with_string_data (dirs); - - for (; dirs; dirs = dirs->next) { - GFile *file; - - /* Do some simple checks for silly locations */ - if (strcmp (dirs->data, "/dev") == 0 || - strcmp (dirs->data, "/lib") == 0 || - strcmp (dirs->data, "/proc") == 0 || - strcmp (dirs->data, "/sys") == 0) { - continue; - } - - if (g_str_has_prefix (dirs->data, g_get_tmp_dir ())) { - continue; - } - - /* Make sure we don't crawl volumes. */ - if (mounts) { - gboolean found = FALSE; - - for (m = mounts; m && !found; m = m->next) { - found = strcmp (m->data, dirs->data) == 0; - } - - if (found) { - g_message (" Duplicate found:'%s' - same as removable device path", - (gchar*) dirs->data); - continue; - } - } - - g_message (" Adding:'%s'", (gchar*) dirs->data); - - file = g_file_new_for_path (dirs->data); - - flags = TRACKER_DIRECTORY_FLAG_RECURSE; - - if (tracker_config_get_enable_monitors (mf->private->config)) { - flags |= TRACKER_DIRECTORY_FLAG_MONITOR; - } - - if (mf->private->mtime_check) { - flags |= TRACKER_DIRECTORY_FLAG_CHECK_MTIME; - } - - tracker_indexing_tree_add (indexing_tree, file, flags); - g_object_unref (file); - } - - /* Add mounts */ - g_message ("Setting up directories to iterate from devices/discs"); - - if (!mf->private->index_removable_devices) { - g_message (" Removable devices are disabled in the config"); - - /* Make sure we don't have any resource in a volume of the given type */ - miner_files_in_removable_media_remove_by_type (mf, TRACKER_STORAGE_REMOVABLE); - } - - if (!mf->private->index_optical_discs) { - g_message (" Optical discs are disabled in the config"); - - /* Make sure we don't have any resource in a volume of the given type */ - miner_files_in_removable_media_remove_by_type (mf, TRACKER_STORAGE_REMOVABLE | TRACKER_STORAGE_OPTICAL); - } - - for (m = mounts; m; m = m->next) { - miner_files_add_removable_or_optical_directory (mf, - (gchar *) m->data, - NULL); - } - - /* We want to get notified when config changes */ - - g_signal_connect (mf->private->config, "notify::low-disk-space-limit", - G_CALLBACK (low_disk_space_limit_cb), - mf); - g_signal_connect (mf->private->config, "notify::index-recursive-directories", - G_CALLBACK (index_recursive_directories_cb), - mf); - g_signal_connect (mf->private->config, "notify::index-single-directories", - G_CALLBACK (index_single_directories_cb), - mf); - g_signal_connect (mf->private->config, "notify::ignored-directories", - G_CALLBACK (trigger_recheck_cb), - mf); - g_signal_connect (mf->private->config, "notify::ignored-directories-with-content", - G_CALLBACK (trigger_recheck_cb), - mf); - g_signal_connect (mf->private->config, "notify::ignored-files", - G_CALLBACK (trigger_recheck_cb), - mf); - g_signal_connect (mf->private->config, "notify::enable-monitors", - G_CALLBACK (trigger_recheck_cb), - mf); - g_signal_connect (mf->private->config, "notify::index-removable-devices", - G_CALLBACK (index_volumes_changed_cb), - mf); - g_signal_connect (mf->private->config, "notify::index-optical-discs", - G_CALLBACK (index_volumes_changed_cb), - mf); - g_signal_connect (mf->private->config, "notify::removable-days-threshold", - G_CALLBACK (index_volumes_changed_cb), - mf); - -#if defined(HAVE_UPOWER) || defined(HAVE_HAL) - - g_signal_connect (mf->private->config, "notify::index-on-battery", - G_CALLBACK (index_on_battery_cb), - mf); - g_signal_connect (mf->private->config, "notify::index-on-battery-first-time", - G_CALLBACK (index_on_battery_cb), - mf); - -#endif /* defined(HAVE_UPOWER) || defined(HAVE_HAL) */ - - g_slist_foreach (mounts, (GFunc) g_free, NULL); - g_slist_free (mounts); - - disk_space_check_start (mf); - - mf->private->extract_watchdog = tracker_extract_watchdog_new (); - mf->private->thumbnailer = tracker_thumbnailer_new (); - - return TRUE; -} - -static void -miner_files_set_property (GObject *object, - guint prop_id, - const GValue *value, - GParamSpec *pspec) -{ - TrackerMinerFilesPrivate *priv; - - priv = TRACKER_MINER_FILES_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_CONFIG: - priv->config = g_value_dup_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -miner_files_get_property (GObject *object, - guint prop_id, - GValue *value, - GParamSpec *pspec) -{ - TrackerMinerFilesPrivate *priv; - - priv = TRACKER_MINER_FILES_GET_PRIVATE (object); - - switch (prop_id) { - case PROP_CONFIG: - g_value_set_object (value, priv->config); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -miner_files_finalize (GObject *object) -{ - TrackerMinerFiles *mf; - TrackerMinerFilesPrivate *priv; - - mf = TRACKER_MINER_FILES (object); - priv = mf->private; - - g_clear_object (&priv->extract_watchdog); - - if (priv->config) { - g_signal_handlers_disconnect_by_func (priv->config, - low_disk_space_limit_cb, - NULL); - g_object_unref (priv->config); - } - - disk_space_check_stop (TRACKER_MINER_FILES (object)); - - if (priv->index_recursive_directories) { - g_slist_foreach (priv->index_recursive_directories, (GFunc) g_free, NULL); - g_slist_free (priv->index_recursive_directories); - } - - if (priv->index_single_directories) { - g_slist_foreach (priv->index_single_directories, (GFunc) g_free, NULL); - g_slist_free (priv->index_single_directories); - } - -#if defined(HAVE_UPOWER) || defined(HAVE_HAL) - if (priv->power) { - g_object_unref (priv->power); - } -#endif /* defined(HAVE_UPOWER) || defined(HAVE_HAL) */ - - if (priv->storage) { - g_object_unref (priv->storage); - } - - if (priv->volume_monitor) { - g_signal_handlers_disconnect_by_func (priv->volume_monitor, - mount_pre_unmount_cb, - object); - g_object_unref (priv->volume_monitor); - } - - if (priv->force_recheck_id) { - g_source_remove (priv->force_recheck_id); - priv->force_recheck_id = 0; - } - - if (priv->stale_volumes_check_id) { - g_source_remove (priv->stale_volumes_check_id); - priv->stale_volumes_check_id = 0; - } - - if (priv->thumbnailer) { - g_object_unref (priv->thumbnailer); - } - - g_list_free (priv->extraction_queue); - g_hash_table_destroy (priv->writeback_tasks); - - G_OBJECT_CLASS (tracker_miner_files_parent_class)->finalize (object); -} - -static void -ensure_mount_point_exists (TrackerMinerFiles *miner, - GFile *mount_point, - GString *accumulator) -{ - gchar *iri; - gchar *uri; - - uri = g_file_get_uri (mount_point); - - /* Query the store for the URN of the mount point */ - iri = tracker_miner_fs_query_urn (TRACKER_MINER_FS (miner), - mount_point); - - if (iri) { - /* If exists, just return, nothing else to do */ - g_message ("Mount point '%s' already exists in store: '%s'", - uri, iri); - g_free (iri); - } else { - /* If it doesn't exist, we need to create it */ - g_message ("Mount point '%s' does not exist in store, need to create it", - uri); - - /* Create a nfo:Folder for the mount point */ - g_string_append_printf (accumulator, - "INSERT SILENT INTO <" TRACKER_OWN_GRAPH_URN "> {" - " _:file a nfo:FileDataObject, nie:InformationElement, nfo:Folder ; " - " nie:isStoredAs _:file ; " - " nie:url \"%s\" ; " - " nie:mimeType \"inode/directory\" ; " - " nfo:fileLastModified \"1981-06-05T02:20:00Z\" . " - "}", - uri); - } - - g_free (uri); -} - -static void -set_up_mount_point_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - TrackerSparqlConnection *connection = TRACKER_SPARQL_CONNECTION (source); - gchar *removable_device_urn = user_data; - GError *error = NULL; - - tracker_sparql_connection_update_finish (connection, result, &error); - - if (error) { - g_critical ("Could not set mount point in database '%s', %s", - removable_device_urn, - error->message); - g_error_free (error); - } - - g_free (removable_device_urn); -} - -static void -set_up_mount_point_type (TrackerMinerFiles *miner, - const gchar *removable_device_urn, - gboolean removable, - gboolean optical, - GString *accumulator) -{ - if (!accumulator) { - return; - } - - g_debug ("Mount point type being set in DB for URN '%s'", - removable_device_urn); - - g_string_append_printf (accumulator, - "DELETE { <%s> tracker:isRemovable ?unknown } WHERE { <%s> a tracker:Volume; tracker:isRemovable ?unknown } ", - removable_device_urn, removable_device_urn); - - g_string_append_printf (accumulator, - "INSERT INTO <" TRACKER_OWN_GRAPH_URN "> { <%s> a tracker:Volume; tracker:isRemovable %s } ", - removable_device_urn, removable ? "true" : "false"); - - g_string_append_printf (accumulator, - "DELETE { <%s> tracker:isOptical ?unknown } WHERE { <%s> a tracker:Volume; tracker:isOptical ?unknown } ", - removable_device_urn, removable_device_urn); - - g_string_append_printf (accumulator, - "INSERT INTO <" TRACKER_OWN_GRAPH_URN "> { <%s> a tracker:Volume; tracker:isOptical %s } ", - removable_device_urn, optical ? "true" : "false"); -} - -static void -set_up_mount_point (TrackerMinerFiles *miner, - const gchar *removable_device_urn, - const gchar *mount_point, - const gchar *mount_name, - gboolean mounted, - GString *accumulator) -{ - GString *queries; - - queries = g_string_new (NULL); - - if (mounted) { - g_debug ("Mount point state (MOUNTED) being set in DB for URN '%s' (mount_point: %s)", - removable_device_urn, - mount_point ? mount_point : "unknown"); - - if (mount_point) { - GFile *file; - gchar *uri; - - file = g_file_new_for_path (mount_point); - uri = g_file_get_uri (file); - - /* Before assigning a nfo:FileDataObject as tracker:mountPoint for - * the volume, make sure the nfo:FileDataObject exists in the store */ - ensure_mount_point_exists (miner, file, queries); - - g_string_append_printf (queries, - "DELETE { " - " <%s> tracker:mountPoint ?u " - "} WHERE { " - " ?u a nfo:FileDataObject; " - " nie:url \"%s\" " - "} ", - removable_device_urn, uri); - - g_string_append_printf (queries, - "DELETE { <%s> a rdfs:Resource } " - "INSERT { " - " <%s> a tracker:Volume; " - " tracker:mountPoint ?u " - "} WHERE { " - " ?u a nfo:FileDataObject; " - " nie:url \"%s\" " - "} ", - removable_device_urn, removable_device_urn, uri); - - g_object_unref (file); - g_free (uri); - } - - g_string_append_printf (queries, - "DELETE { <%s> tracker:isMounted ?unknown } WHERE { <%s> a tracker:Volume; tracker:isMounted ?unknown } ", - removable_device_urn, removable_device_urn); - - if (mount_name) { - g_string_append_printf (queries, - "INSERT INTO <" TRACKER_OWN_GRAPH_URN "> { <%s> a tracker:Volume; tracker:isMounted true; nie:title \"%s\" } ", - removable_device_urn, mount_name); - } else { - g_string_append_printf (queries, - "INSERT INTO <" TRACKER_OWN_GRAPH_URN "> { <%s> a tracker:Volume; tracker:isMounted true } ", - removable_device_urn); - } - - g_string_append_printf (queries, - "INSERT { GRAPH <" TRACKER_OWN_GRAPH_URN "> { ?do tracker:available true } } WHERE { ?do nie:dataSource <%s> } ", - removable_device_urn); - } else { - gchar *now; - - g_debug ("Mount point state (UNMOUNTED) being set in DB for URN '%s'", - removable_device_urn); - - now = tracker_date_to_string (time (NULL)); - - g_string_append_printf (queries, - "DELETE { <%s> tracker:unmountDate ?unknown } WHERE { <%s> a tracker:Volume; tracker:unmountDate ?unknown } ", - removable_device_urn, removable_device_urn); - - g_string_append_printf (queries, - "INSERT INTO <" TRACKER_OWN_GRAPH_URN "> { <%s> a tracker:Volume; tracker:unmountDate \"%s\" } ", - removable_device_urn, now); - - g_string_append_printf (queries, - "DELETE { <%s> tracker:isMounted ?unknown } WHERE { <%s> a tracker:Volume; tracker:isMounted ?unknown } ", - removable_device_urn, removable_device_urn); - - g_string_append_printf (queries, - "INSERT INTO <" TRACKER_OWN_GRAPH_URN "> { <%s> a tracker:Volume; tracker:isMounted false } ", - removable_device_urn); - - g_string_append_printf (queries, - "DELETE { ?do tracker:available true } WHERE { ?do nie:dataSource <%s> } ", - removable_device_urn); - - g_free (now); - } - - if (accumulator) { - g_string_append_printf (accumulator, "%s ", queries->str); - } else { - tracker_sparql_connection_update_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - queries->str, - G_PRIORITY_LOW, - NULL, - set_up_mount_point_cb, - g_strdup (removable_device_urn)); - } - - g_string_free (queries, TRUE); -} - -static void -init_mount_points_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - GError *error = NULL; - - tracker_sparql_connection_update_finish (TRACKER_SPARQL_CONNECTION (source), - result, - &error); - - if (error) { - g_critical ("Could not initialize currently active mount points: %s", - error->message); - g_error_free (error); - } else { - /* Mount points correctly initialized */ - (TRACKER_MINER_FILES (user_data))->private->mount_points_initialized = TRUE; - /* If this happened AFTER we have a proper config, initialize - * stale volume removal now. */ - if ((TRACKER_MINER_FILES (user_data))->private->config) { - init_stale_volume_removal (TRACKER_MINER_FILES (user_data)); - } - } -} - -static void -init_mount_points (TrackerMinerFiles *miner_files) -{ - TrackerMiner *miner = TRACKER_MINER (miner_files); - TrackerMinerFilesPrivate *priv; - GHashTable *volumes; - GHashTableIter iter; - gpointer key, value; - GString *accumulator; - GError *error = NULL; - TrackerSparqlCursor *cursor; - GSList *uuids, *u; - - g_debug ("Initializing mount points..."); - - /* First, get all mounted volumes, according to tracker-store (SYNC!) */ - cursor = tracker_sparql_connection_query (tracker_miner_get_connection (miner), - "SELECT ?v WHERE { ?v a tracker:Volume ; tracker:isMounted true }", - NULL, &error); - if (error) { - g_critical ("Could not obtain the mounted volumes: %s", error->message); - g_error_free (error); - return; - } - - priv = TRACKER_MINER_FILES_GET_PRIVATE (miner); - - volumes = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - NULL); - - - /* Make sure the root partition is always set to mounted, as GIO won't - * report it as a proper mount */ - g_hash_table_insert (volumes, - g_strdup (TRACKER_DATASOURCE_URN_NON_REMOVABLE_MEDIA), - GINT_TO_POINTER (VOLUME_MOUNTED)); - - while (tracker_sparql_cursor_next (cursor, NULL, NULL)) { - gint state; - const gchar *urn; - - state = VOLUME_MOUNTED_IN_STORE; - - urn = tracker_sparql_cursor_get_string (cursor, 0, NULL); - - if (!urn) - continue; - - if (strcmp (urn, TRACKER_DATASOURCE_URN_NON_REMOVABLE_MEDIA) == 0) { - /* Report non-removable media to be mounted by HAL as well */ - state |= VOLUME_MOUNTED; - } - - g_hash_table_replace (volumes, g_strdup (urn), GINT_TO_POINTER (state)); - } - - g_object_unref (cursor); - - /* Then, get all currently mounted non-REMOVABLE volumes, according to GIO */ - uuids = tracker_storage_get_device_uuids (priv->storage, 0, TRUE); - for (u = uuids; u; u = u->next) { - const gchar *uuid; - gchar *non_removable_device_urn; - gint state; - - uuid = u->data; - non_removable_device_urn = g_strdup_printf (TRACKER_PREFIX_DATASOURCE_URN "%s", uuid); - - state = GPOINTER_TO_INT (g_hash_table_lookup (volumes, non_removable_device_urn)); - state |= VOLUME_MOUNTED; - - g_hash_table_replace (volumes, non_removable_device_urn, GINT_TO_POINTER (state)); - } - - g_slist_foreach (uuids, (GFunc) g_free, NULL); - g_slist_free (uuids); - - /* Then, get all currently mounted REMOVABLE volumes, according to GIO */ - if (priv->index_removable_devices) { - uuids = tracker_storage_get_device_uuids (priv->storage, TRACKER_STORAGE_REMOVABLE, FALSE); - for (u = uuids; u; u = u->next) { - const gchar *uuid; - gchar *removable_device_urn; - gint state; - - uuid = u->data; - removable_device_urn = g_strdup_printf (TRACKER_PREFIX_DATASOURCE_URN "%s", uuid); - - state = GPOINTER_TO_INT (g_hash_table_lookup (volumes, removable_device_urn)); - state |= VOLUME_MOUNTED; - - g_hash_table_replace (volumes, removable_device_urn, GINT_TO_POINTER (state)); - } - - g_slist_foreach (uuids, (GFunc) g_free, NULL); - g_slist_free (uuids); - } - - accumulator = g_string_new (NULL); - g_hash_table_iter_init (&iter, volumes); - - /* Finally, set up volumes based on the composed info */ - while (g_hash_table_iter_next (&iter, &key, &value)) { - const gchar *urn = key; - gint state = GPOINTER_TO_INT (value); - - if ((state & VOLUME_MOUNTED) && - !(state & VOLUME_MOUNTED_IN_STORE)) { - const gchar *mount_point = NULL; - TrackerStorageType type = 0; - - /* Note: is there any case where the urn doesn't have our - * datasource prefix? */ - if (g_str_has_prefix (urn, TRACKER_PREFIX_DATASOURCE_URN)) { - const gchar *uuid; - - uuid = urn + strlen (TRACKER_PREFIX_DATASOURCE_URN); - mount_point = tracker_storage_get_mount_point_for_uuid (priv->storage, uuid); - type = tracker_storage_get_type_for_uuid (priv->storage, uuid); - } - - if (urn) { - if (mount_point) { - g_debug ("Mount point state incorrect in DB for URN '%s', " - "currently it is mounted on '%s'", - urn, - mount_point); - } else { - g_debug ("Mount point state incorrect in DB for URN '%s', " - "currently it is mounted", - urn); - } - - /* Set mount point state */ - set_up_mount_point (TRACKER_MINER_FILES (miner), - urn, - mount_point, - NULL, - TRUE, - accumulator); - - /* Set mount point type */ - set_up_mount_point_type (TRACKER_MINER_FILES (miner), - urn, - TRACKER_STORAGE_TYPE_IS_REMOVABLE (type), - TRACKER_STORAGE_TYPE_IS_OPTICAL (type), - accumulator); - - if (mount_point) { - TrackerIndexingTree *indexing_tree; - TrackerDirectoryFlags flags; - GFile *file; - - indexing_tree = tracker_miner_fs_get_indexing_tree (TRACKER_MINER_FS (miner)); - flags = TRACKER_DIRECTORY_FLAG_RECURSE | - TRACKER_DIRECTORY_FLAG_CHECK_MTIME | - TRACKER_DIRECTORY_FLAG_PRESERVE; - - if (tracker_config_get_enable_monitors (miner_files->private->config)) { - flags |= TRACKER_DIRECTORY_FLAG_MONITOR; - } - - /* Add the current mount point as reported to have incorrect - * state. We will force mtime checks on this mount points, - * even if no-mtime-check-needed was set. */ - file = g_file_new_for_path (mount_point); - if (tracker_miner_files_is_file_eligible (miner_files, file)) { - tracker_indexing_tree_add (indexing_tree, - file, - flags); - } - g_object_unref (file); - } - } - } else if (!(state & VOLUME_MOUNTED) && - (state & VOLUME_MOUNTED_IN_STORE)) { - if (urn) { - g_debug ("Mount point state incorrect in DB for URN '%s', " - "currently it is NOT mounted", - urn); - set_up_mount_point (TRACKER_MINER_FILES (miner), - urn, - NULL, - NULL, - FALSE, - accumulator); - /* There's no need to force mtime check in these inconsistent - * mount points, as they are not mounted right now. */ - } - } - } - - if (accumulator->str[0] != '\0') { - tracker_sparql_connection_update_async (tracker_miner_get_connection (miner), - accumulator->str, - G_PRIORITY_LOW, - NULL, - init_mount_points_cb, - miner); - } else { - /* Note. Not initializing stale volume removal timeout because - * we do not have the configuration setup yet */ - (TRACKER_MINER_FILES (miner))->private->mount_points_initialized = TRUE; - } - - g_string_free (accumulator, TRUE); - g_hash_table_unref (volumes); -} - -static gboolean -cleanup_stale_removable_volumes_cb (gpointer user_data) -{ - TrackerMinerFiles *miner = TRACKER_MINER_FILES (user_data); - gint n_days_threshold; - time_t n_days_ago; - gchar *n_days_ago_as_string; - - n_days_threshold = tracker_config_get_removable_days_threshold (miner->private->config); - - if (n_days_threshold == 0) - return TRUE; - - n_days_ago = (time (NULL) - (SECONDS_PER_DAY * n_days_threshold)); - n_days_ago_as_string = tracker_date_to_string (n_days_ago); - - g_message ("Running stale volumes check..."); - - miner_files_in_removable_media_remove_by_date (miner, n_days_ago_as_string); - - g_free (n_days_ago_as_string); - - return TRUE; -} - -static void -init_stale_volume_removal (TrackerMinerFiles *miner) -{ - /* If disabled, make sure we don't do anything */ - if (tracker_config_get_removable_days_threshold (miner->private->config) == 0) { - g_message ("Stale volume check is disabled"); - return; - } - - /* Run right away the first check */ - cleanup_stale_removable_volumes_cb (miner); - - g_message ("Initializing stale volume check timeout..."); - - /* Then, setup new timeout event every day */ - miner->private->stale_volumes_check_id = - g_timeout_add_seconds (SECONDS_PER_DAY + 1, - cleanup_stale_removable_volumes_cb, - miner); -} - - -static void -mount_point_removed_cb (TrackerStorage *storage, - const gchar *uuid, - const gchar *mount_point, - gpointer user_data) -{ - TrackerMinerFiles *miner = user_data; - TrackerIndexingTree *indexing_tree; - gchar *urn; - GFile *mount_point_file; - - urn = g_strdup_printf (TRACKER_PREFIX_DATASOURCE_URN "%s", uuid); - g_debug ("Mount point removed for URN '%s'", urn); - - mount_point_file = g_file_new_for_path (mount_point); - - /* Tell TrackerMinerFS to skip monitoring everything under the mount - * point (in case there was no pre-unmount notification) */ - indexing_tree = tracker_miner_fs_get_indexing_tree (TRACKER_MINER_FS (miner)); - tracker_indexing_tree_remove (indexing_tree, mount_point_file); - - /* Set mount point status in tracker-store */ - set_up_mount_point (miner, urn, mount_point, NULL, FALSE, NULL); - - g_free (urn); - g_object_unref (mount_point_file); -} - -static void -mount_point_added_cb (TrackerStorage *storage, - const gchar *uuid, - const gchar *mount_point, - const gchar *mount_name, - gboolean removable, - gboolean optical, - gpointer user_data) -{ - TrackerMinerFiles *miner = user_data; - TrackerMinerFilesPrivate *priv; - gchar *urn; - GString *queries; - - priv = TRACKER_MINER_FILES_GET_PRIVATE (miner); - - urn = g_strdup_printf (TRACKER_PREFIX_DATASOURCE_URN "%s", uuid); - g_message ("Mount point added for URN '%s'", urn); - - if (removable && !priv->index_removable_devices) { - g_message (" Not crawling, removable devices disabled in config"); - } else if (optical && !priv->index_optical_discs) { - g_message (" Not crawling, optical devices discs disabled in config"); - } else if (!removable && !optical) { - TrackerIndexingTree *indexing_tree; - TrackerDirectoryFlags flags; - GFile *mount_point_file; - GSList *l; - - mount_point_file = g_file_new_for_path (mount_point); - indexing_tree = tracker_miner_fs_get_indexing_tree (TRACKER_MINER_FS (miner)); - - /* Check if one of the recursively indexed locations is in - * the mounted path, or if the mounted path is inside - * a recursively indexed directory... */ - for (l = tracker_config_get_index_recursive_directories (miner->private->config); - l; - l = g_slist_next (l)) { - GFile *config_file; - - config_file = g_file_new_for_path (l->data); - flags = TRACKER_DIRECTORY_FLAG_RECURSE | - TRACKER_DIRECTORY_FLAG_CHECK_MTIME | - TRACKER_DIRECTORY_FLAG_PRESERVE; - - if (tracker_config_get_enable_monitors (miner->private->config)) { - flags |= TRACKER_DIRECTORY_FLAG_MONITOR; - } - - if (g_file_equal (config_file, mount_point_file) || - g_file_has_prefix (config_file, mount_point_file)) { - /* If the config path is contained inside the mount path, - * then add the config path to re-check */ - g_message (" Re-check of configured path '%s' needed (recursively)", - (gchar *) l->data); - tracker_indexing_tree_add (indexing_tree, - config_file, - flags); - } else if (g_file_has_prefix (mount_point_file, config_file)) { - /* If the mount path is contained inside the config path, - * then add the mount path to re-check */ - g_message (" Re-check of path '%s' needed (inside configured path '%s')", - mount_point, - (gchar *) l->data); - tracker_indexing_tree_add (indexing_tree, - config_file, - flags); - } - g_object_unref (config_file); - } - - /* Check if one of the non-recursively indexed locations is in - * the mount path... */ - for (l = tracker_config_get_index_single_directories (miner->private->config); - l; - l = g_slist_next (l)) { - GFile *config_file; - - flags = TRACKER_DIRECTORY_FLAG_CHECK_MTIME; - - if (tracker_config_get_enable_monitors (miner->private->config)) { - flags |= TRACKER_DIRECTORY_FLAG_MONITOR; - } - - config_file = g_file_new_for_path (l->data); - if (g_file_equal (config_file, mount_point_file) || - g_file_has_prefix (config_file, mount_point_file)) { - g_message (" Re-check of configured path '%s' needed (non-recursively)", - (gchar *) l->data); - tracker_indexing_tree_add (indexing_tree, - config_file, - flags); - } - g_object_unref (config_file); - } - - g_object_unref (mount_point_file); - } else { - g_message (" Adding directories in removable/optical media to crawler's queue"); - miner_files_add_removable_or_optical_directory (miner, - mount_point, - uuid); - } - - queries = g_string_new (""); - set_up_mount_point (miner, urn, mount_point, mount_name, TRUE, queries); - set_up_mount_point_type (miner, urn, removable, optical, queries); - tracker_sparql_connection_update_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - queries->str, - G_PRIORITY_LOW, - NULL, - set_up_mount_point_cb, - g_strdup (urn)); - g_string_free (queries, TRUE); - g_free (urn); -} - -#if defined(HAVE_UPOWER) || defined(HAVE_HAL) - -static void -set_up_throttle (TrackerMinerFiles *mf, - gboolean enable) -{ - gdouble throttle; - gint config_throttle; - - config_throttle = tracker_config_get_throttle (mf->private->config); - throttle = (1.0 / 20) * config_throttle; - - if (enable) { - throttle += 0.25; - } - - throttle = CLAMP (throttle, 0, 1); - - g_debug ("Setting new throttle to %0.3f", throttle); - tracker_miner_fs_set_throttle (TRACKER_MINER_FS (mf), throttle); -} - -static void -check_battery_status (TrackerMinerFiles *mf) -{ - gboolean on_battery, on_low_battery; - gboolean should_pause = FALSE; - gboolean should_throttle = FALSE; - - on_low_battery = tracker_power_get_on_low_battery (mf->private->power); - on_battery = tracker_power_get_on_battery (mf->private->power); - - if (!on_battery) { - g_message ("Running on AC power"); - should_pause = FALSE; - should_throttle = FALSE; - } else if (on_low_battery) { - g_message ("Running on LOW Battery, pausing"); - should_pause = TRUE; - should_throttle = TRUE; - } else { - should_throttle = TRUE; - - /* Check if miner should be paused based on configuration */ - if (!tracker_config_get_index_on_battery (mf->private->config)) { - if (!tracker_config_get_index_on_battery_first_time (mf->private->config)) { - g_message ("Running on battery, but not enabled, pausing"); - should_pause = TRUE; - } else if (tracker_miner_files_get_first_index_done ()) { - g_message ("Running on battery and first-time index " - "already done, pausing"); - should_pause = TRUE; - } else { - g_message ("Running on battery, but first-time index not " - "already finished, keeping on"); - } - } else { - g_message ("Running on battery"); - } - } - - if (should_pause) { - /* Don't try to pause again */ - if (!mf->private->low_battery_pause) { - mf->private->low_battery_pause = TRUE; - tracker_miner_pause (TRACKER_MINER (mf)); - } - } else { - /* Don't try to resume again */ - if (mf->private->low_battery_pause) { - tracker_miner_resume (TRACKER_MINER (mf)); - mf->private->low_battery_pause = FALSE; - } - } - - set_up_throttle (mf, should_throttle); -} - -/* Called when battery status change is detected */ -static void -battery_status_cb (GObject *object, - GParamSpec *pspec, - gpointer user_data) -{ - TrackerMinerFiles *mf = user_data; - - check_battery_status (mf); -} - -/* Called when battery-related configuration change is detected */ -static void -index_on_battery_cb (GObject *object, - GParamSpec *pspec, - gpointer user_data) -{ - TrackerMinerFiles *mf = user_data; - - check_battery_status (mf); -} - -#endif /* defined(HAVE_UPOWER) || defined(HAVE_HAL) */ - -/* Called when mining has finished the first time */ -static void -miner_finished_cb (TrackerMinerFS *fs, - gdouble seconds_elapsed, - guint total_directories_found, - guint total_directories_ignored, - guint total_files_found, - guint total_files_ignored, - gpointer user_data) -{ - TrackerMinerFiles *mf = TRACKER_MINER_FILES (fs); - - /* Create stamp file if not already there */ - if (!tracker_miner_files_get_first_index_done ()) { - tracker_miner_files_set_first_index_done (TRUE); - } - - /* And remove the signal handler so that it's not - * called again */ - if (mf->private->finished_handler) { - g_signal_handler_disconnect (fs, mf->private->finished_handler); - mf->private->finished_handler = 0; - } - -#if defined(HAVE_UPOWER) || defined(HAVE_HAL) - check_battery_status (mf); -#endif /* defined(HAVE_UPOWER) || defined(HAVE_HAL) */ -} - -static void -mount_pre_unmount_cb (GVolumeMonitor *volume_monitor, - GMount *mount, - TrackerMinerFiles *mf) -{ - TrackerIndexingTree *indexing_tree; - GFile *mount_root; - gchar *uri; - - mount_root = g_mount_get_root (mount); - uri = g_file_get_uri (mount_root); - g_message ("Pre-unmount requested for '%s'", uri); - - indexing_tree = tracker_miner_fs_get_indexing_tree (TRACKER_MINER_FS (mf)); - tracker_indexing_tree_remove (indexing_tree, mount_root); - g_object_unref (mount_root); - - g_free (uri); -} - -static gboolean -disk_space_check (TrackerMinerFiles *mf) -{ - gint limit; - gchar *data_dir; - gdouble remaining; - - limit = tracker_config_get_low_disk_space_limit (mf->private->config); - - if (limit < 1) { - return FALSE; - } - - /* Get % of remaining space in the partition where the cache is */ - data_dir = g_build_filename (g_get_user_cache_dir (), "tracker", NULL); - remaining = tracker_file_system_get_remaining_space_percentage (data_dir); - g_free (data_dir); - - if (remaining <= limit) { - g_message ("WARNING: Available disk space (%lf%%) is below " - "configured threshold for acceptable working (%d%%)", - remaining, limit); - return TRUE; - } - - return FALSE; -} - -static gboolean -disk_space_check_cb (gpointer user_data) -{ - TrackerMinerFiles *mf = user_data; - - if (disk_space_check (mf)) { - /* Don't try to pause again */ - if (!mf->private->disk_space_pause) { - mf->private->disk_space_pause = TRUE; - tracker_miner_pause (TRACKER_MINER (mf)); - } - } else { - /* Don't try to resume again */ - if (mf->private->disk_space_pause) { - tracker_miner_resume (TRACKER_MINER (mf)); - mf->private->disk_space_pause = FALSE; - } - } - - return TRUE; -} - -static void -disk_space_check_start (TrackerMinerFiles *mf) -{ - gint limit; - - if (mf->private->disk_space_check_id != 0) { - return; - } - - limit = tracker_config_get_low_disk_space_limit (mf->private->config); - - if (limit != -1) { - g_message ("Starting disk space check for every %d seconds", - DISK_SPACE_CHECK_FREQUENCY); - mf->private->disk_space_check_id = - g_timeout_add_seconds (DISK_SPACE_CHECK_FREQUENCY, - disk_space_check_cb, - mf); - - /* Call the function now too to make sure we have an - * initial value too! - */ - disk_space_check_cb (mf); - } else { - g_message ("Not setting disk space, configuration is set to -1 (disabled)"); - } -} - -static void -disk_space_check_stop (TrackerMinerFiles *mf) -{ - if (mf->private->disk_space_check_id) { - g_message ("Stopping disk space check"); - g_source_remove (mf->private->disk_space_check_id); - mf->private->disk_space_check_id = 0; - } -} - -static void -low_disk_space_limit_cb (GObject *gobject, - GParamSpec *arg1, - gpointer user_data) -{ - TrackerMinerFiles *mf = user_data; - - disk_space_check_cb (mf); -} - -static void -indexing_tree_update_filter (TrackerIndexingTree *indexing_tree, - TrackerFilterType filter, - GSList *new_elems) -{ - tracker_indexing_tree_clear_filters (indexing_tree, filter); - - while (new_elems) { - tracker_indexing_tree_add_filter (indexing_tree, filter, - new_elems->data); - new_elems = new_elems->next; - } -} - -static void -miner_files_update_filters (TrackerMinerFiles *files) -{ - TrackerIndexingTree *indexing_tree; - GSList *list; - - indexing_tree = tracker_miner_fs_get_indexing_tree (TRACKER_MINER_FS (files)); - - /* Ignored files */ - list = tracker_config_get_ignored_files (files->private->config); - indexing_tree_update_filter (indexing_tree, TRACKER_FILTER_FILE, list); - - /* Ignored directories */ - list = tracker_config_get_ignored_directories (files->private->config); - indexing_tree_update_filter (indexing_tree, - TRACKER_FILTER_DIRECTORY, - list); - - /* Directories with content */ - list = tracker_config_get_ignored_directories_with_content (files->private->config); - indexing_tree_update_filter (indexing_tree, - TRACKER_FILTER_PARENT_DIRECTORY, - list); -} - -static void -update_directories_from_new_config (TrackerMinerFS *mf, - GSList *new_dirs, - GSList *old_dirs, - gboolean recurse) -{ - TrackerMinerFilesPrivate *priv; - TrackerDirectoryFlags flags = 0; - TrackerIndexingTree *indexing_tree; - GSList *sl; - - priv = TRACKER_MINER_FILES_GET_PRIVATE (mf); - indexing_tree = tracker_miner_fs_get_indexing_tree (mf); - - g_message ("Updating %s directories changed from configuration", - recurse ? "recursive" : "single"); - - /* First remove all directories removed from the config */ - for (sl = old_dirs; sl; sl = sl->next) { - const gchar *path; - - path = sl->data; - - /* If we are not still in the list, remove the dir */ - if (!tracker_string_in_gslist (path, new_dirs)) { - GFile *file; - - g_message (" Removing directory: '%s'", path); - - file = g_file_new_for_path (path); - - /* First, remove the preserve flag, it might be - * set on configuration directories within mount - * points, as data should be persistent across - * unmounts. - */ - tracker_indexing_tree_get_root (indexing_tree, - file, &flags); - - if ((flags & TRACKER_DIRECTORY_FLAG_PRESERVE) != 0) { - flags &= ~(TRACKER_DIRECTORY_FLAG_PRESERVE); - tracker_indexing_tree_add (indexing_tree, - file, flags); - } - - /* Fully remove item (monitors and from store), - * now that there's no preserve flag. - */ - tracker_indexing_tree_remove (indexing_tree, file); - g_object_unref (file); - } - } - - flags = TRACKER_DIRECTORY_FLAG_NONE; - - if (recurse) { - flags |= TRACKER_DIRECTORY_FLAG_RECURSE; - } - - if (tracker_config_get_enable_monitors (priv->config)) { - flags |= TRACKER_DIRECTORY_FLAG_MONITOR; - } - - if (priv->mtime_check) { - flags |= TRACKER_DIRECTORY_FLAG_CHECK_MTIME; - } - - /* Second add directories which are new */ - for (sl = new_dirs; sl; sl = sl->next) { - const gchar *path; - - path = sl->data; - - /* If we are now in the list, add the dir */ - if (!tracker_string_in_gslist (path, old_dirs)) { - GFile *file; - - g_message (" Adding directory:'%s'", path); - - file = g_file_new_for_path (path); - tracker_indexing_tree_add (indexing_tree, file, flags); - g_object_unref (file); - } - } -} - -static void -index_recursive_directories_cb (GObject *gobject, - GParamSpec *arg1, - gpointer user_data) -{ - TrackerMinerFilesPrivate *private; - GSList *new_dirs, *old_dirs; - - private = TRACKER_MINER_FILES_GET_PRIVATE (user_data); - - new_dirs = tracker_config_get_index_recursive_directories (private->config); - old_dirs = private->index_recursive_directories; - - update_directories_from_new_config (TRACKER_MINER_FS (user_data), - new_dirs, - old_dirs, - TRUE); - - /* Re-set the stored config in case it changes again */ - if (private->index_recursive_directories) { - g_slist_foreach (private->index_recursive_directories, (GFunc) g_free, NULL); - g_slist_free (private->index_recursive_directories); - } - - private->index_recursive_directories = tracker_gslist_copy_with_string_data (new_dirs); -} - -static void -index_single_directories_cb (GObject *gobject, - GParamSpec *arg1, - gpointer user_data) -{ - TrackerMinerFilesPrivate *private; - GSList *new_dirs, *old_dirs; - - private = TRACKER_MINER_FILES_GET_PRIVATE (user_data); - - new_dirs = tracker_config_get_index_single_directories (private->config); - old_dirs = private->index_single_directories; - - update_directories_from_new_config (TRACKER_MINER_FS (user_data), - new_dirs, - old_dirs, - FALSE); - - /* Re-set the stored config in case it changes again */ - if (private->index_single_directories) { - g_slist_foreach (private->index_single_directories, (GFunc) g_free, NULL); - g_slist_free (private->index_single_directories); - } - - private->index_single_directories = tracker_gslist_copy_with_string_data (new_dirs); -} - -static gboolean -miner_files_force_recheck_idle (gpointer user_data) -{ - TrackerMinerFiles *miner_files = user_data; - TrackerIndexingTree *indexing_tree; - GList *roots, *l; - - miner_files_update_filters (miner_files); - - indexing_tree = tracker_miner_fs_get_indexing_tree (TRACKER_MINER_FS (miner_files)); - roots = tracker_indexing_tree_list_roots (indexing_tree); - - for (l = roots; l; l = l->next) { - GFile *root = l->data; - - tracker_indexing_tree_notify_update (indexing_tree, root, FALSE); - } - - miner_files->private->force_recheck_id = 0; - g_list_free (roots); - - return FALSE; -} - -static void -trigger_recheck_cb (GObject *gobject, - GParamSpec *arg1, - gpointer user_data) -{ - TrackerMinerFiles *mf = user_data; - - g_message ("Ignored content related configuration changed, checking index..."); - - if (mf->private->force_recheck_id == 0) { - /* Set idle so multiple changes in the config lead to one recheck */ - mf->private->force_recheck_id = - g_idle_add (miner_files_force_recheck_idle, mf); - } -} - -static gboolean -index_volumes_changed_idle (gpointer user_data) -{ - TrackerMinerFiles *mf = user_data; - GSList *mounts_removed = NULL; - GSList *mounts_added = NULL; - gboolean new_index_removable_devices; - gboolean new_index_optical_discs; - - g_message ("Volume related configuration changed, updating..."); - - /* Read new config values. Note that if removable devices is FALSE, - * optical discs will also always be FALSE. */ - new_index_removable_devices = tracker_config_get_index_removable_devices (mf->private->config); - new_index_optical_discs = (new_index_removable_devices ? - tracker_config_get_index_optical_discs (mf->private->config) : - FALSE); - - /* Removable devices config changed? */ - if (mf->private->index_removable_devices != new_index_removable_devices) { - GSList *m; - - /* Get list of roots for currently mounted removable devices - * (excluding optical) */ - m = tracker_storage_get_device_roots (mf->private->storage, - TRACKER_STORAGE_REMOVABLE, - TRUE); - /* Set new config value */ - mf->private->index_removable_devices = new_index_removable_devices; - - if (mf->private->index_removable_devices) { - /* If previously not indexing and now indexing, need to re-check - * current mounted volumes, add new monitors and index new files - */ - mounts_added = m; - } else { - /* If previously indexing and now not indexing, need to re-check - * current mounted volumes, remove monitors and remove all resources - * from the store belonging to a removable device - */ - mounts_removed = m; - - /* And now, single sparql update to remove all resources - * corresponding to removable devices (includes those - * not currently mounted) */ - miner_files_in_removable_media_remove_by_type (mf, TRACKER_STORAGE_REMOVABLE); - } - } - - /* Optical discs config changed? */ - if (mf->private->index_optical_discs != new_index_optical_discs) { - GSList *m; - - /* Get list of roots for removable devices (excluding optical) */ - m = tracker_storage_get_device_roots (mf->private->storage, - TRACKER_STORAGE_REMOVABLE | TRACKER_STORAGE_OPTICAL, - TRUE); - - /* Set new config value */ - mf->private->index_optical_discs = new_index_optical_discs; - - if (mf->private->index_optical_discs) { - /* If previously not indexing and now indexing, need to re-check - * current mounted volumes, add new monitors and index new files - */ - mounts_added = g_slist_concat (mounts_added, m); - } else { - /* If previously indexing and now not indexing, need to re-check - * current mounted volumes, remove monitors and remove all resources - * from the store belonging to a optical disc - */ - mounts_removed = g_slist_concat (mounts_removed, m); - - /* And now, single sparql update to remove all resources - * corresponding to removable+optical devices (includes those - * not currently mounted) */ - miner_files_in_removable_media_remove_by_type (mf, TRACKER_STORAGE_REMOVABLE | TRACKER_STORAGE_OPTICAL); - } - } - - /* Tell TrackerMinerFS to stop monitoring the given removed mount paths, if any */ - if (mounts_removed) { - TrackerIndexingTree *indexing_tree; - GSList *sl; - - indexing_tree = tracker_miner_fs_get_indexing_tree (TRACKER_MINER_FS (mf)); - - for (sl = mounts_removed; sl; sl = g_slist_next (sl)) { - GFile *mount_point_file; - - mount_point_file = g_file_new_for_path (sl->data); - tracker_indexing_tree_remove (indexing_tree, - mount_point_file); - g_object_unref (mount_point_file); - } - - g_slist_foreach (mounts_removed, (GFunc) g_free, NULL); - g_slist_free (mounts_removed); - } - - /* Tell TrackerMinerFS to start monitoring the given added mount paths, if any */ - if (mounts_added) { - GSList *sl; - - for (sl = mounts_added; sl; sl = g_slist_next (sl)) { - miner_files_add_removable_or_optical_directory (mf, - (gchar *) sl->data, - NULL); - } - - g_slist_foreach (mounts_added, (GFunc) g_free, NULL); - g_slist_free (mounts_added); - } - - mf->private->volumes_changed_id = 0; - - /* Check if the stale volume removal configuration changed from enabled to disabled - * or from disabled to enabled */ - if (tracker_config_get_removable_days_threshold (mf->private->config) == 0 && - mf->private->stale_volumes_check_id != 0) { - /* From having the check enabled to having it disabled, remove the timeout */ - g_debug (" Stale volume removal now disabled, removing timeout"); - g_source_remove (mf->private->stale_volumes_check_id); - mf->private->stale_volumes_check_id = 0; - } else if (tracker_config_get_removable_days_threshold (mf->private->config) > 0 && - mf->private->stale_volumes_check_id == 0) { - g_debug (" Stale volume removal now enabled, initializing timeout"); - /* From having the check disabled to having it enabled, so fire up the - * timeout. */ - init_stale_volume_removal (TRACKER_MINER_FILES (mf)); - } - - return FALSE; -} - -static void -index_volumes_changed_cb (GObject *gobject, - GParamSpec *arg1, - gpointer user_data) -{ - TrackerMinerFiles *miner_files = user_data; - - if (miner_files->private->volumes_changed_id == 0) { - /* Set idle so multiple changes in the config lead to one check */ - miner_files->private->volumes_changed_id = - g_idle_add (index_volumes_changed_idle, miner_files); - } -} - -static const gchar * -miner_files_get_file_urn (TrackerMinerFiles *miner, - GFile *file, - gboolean *is_iri) -{ - const gchar *urn; - - urn = tracker_miner_fs_get_urn (TRACKER_MINER_FS (miner), file); - *is_iri = TRUE; - - if (!urn) { - /* This is a new insertion, use anonymous URNs to store files */ - urn = "_:file"; - *is_iri = FALSE; - } - - return urn; -} - -static void -miner_files_add_to_datasource (TrackerMinerFiles *mf, - GFile *file, - TrackerSparqlBuilder *sparql) -{ - TrackerMinerFilesPrivate *priv; - const gchar *removable_device_uuid; - gchar *removable_device_urn, *uri; - const gchar *urn; - gboolean is_iri; - - priv = TRACKER_MINER_FILES_GET_PRIVATE (mf); - uri = g_file_get_uri (file); - - removable_device_uuid = tracker_storage_get_uuid_for_file (priv->storage, file); - - if (removable_device_uuid) { - removable_device_urn = g_strdup_printf (TRACKER_PREFIX_DATASOURCE_URN "%s", - removable_device_uuid); - } else { - removable_device_urn = g_strdup (TRACKER_DATASOURCE_URN_NON_REMOVABLE_MEDIA); - } - - urn = miner_files_get_file_urn (mf, file, &is_iri); - - if (is_iri) { - tracker_sparql_builder_subject_iri (sparql, urn); - } else { - tracker_sparql_builder_subject (sparql, urn); - } - - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:FileDataObject"); - - tracker_sparql_builder_predicate (sparql, "nie:dataSource"); - tracker_sparql_builder_object_iri (sparql, removable_device_urn); - - tracker_sparql_builder_predicate (sparql, "tracker:available"); - tracker_sparql_builder_object_boolean (sparql, TRUE); - - g_free (removable_device_urn); - g_free (uri); -} - -static void -miner_files_add_rdf_types (TrackerSparqlBuilder *sparql, - GFile *file, - const gchar *mime_type) -{ - GStrv rdf_types; - gint i = 0; - - rdf_types = tracker_extract_module_manager_get_fallback_rdf_types (mime_type); - - if (!rdf_types) - return; - - if (rdf_types[0]) { - tracker_sparql_builder_predicate (sparql, "a"); - - while (rdf_types[i]) { - tracker_sparql_builder_object (sparql, rdf_types[i]); - i++; - } - } - - g_strfreev (rdf_types); -} - -static void -process_file_data_free (ProcessFileData *data) -{ - g_object_unref (data->miner); - g_object_unref (data->sparql); - g_object_unref (data->cancellable); - g_object_unref (data->file); - g_object_unref (data->task); - g_free (data->mime_type); - g_slice_free (ProcessFileData, data); -} - -static void -sparql_builder_finish (ProcessFileData *data, - const gchar *preupdate, - const gchar *postupdate, - const gchar *sparql, - const gchar *where) -{ - const gchar *uuid; - - if (sparql && *sparql) { - gboolean is_iri; - const gchar *urn; - - urn = miner_files_get_file_urn (data->miner, data->file, &is_iri); - - if (is_iri) { - gchar *str; - - str = g_strdup_printf ("<%s>", urn); - tracker_sparql_builder_append (data->sparql, str); - g_free (str); - } else { - tracker_sparql_builder_append (data->sparql, urn); - } - - tracker_sparql_builder_append (data->sparql, sparql); - } - - tracker_sparql_builder_graph_close (data->sparql); - tracker_sparql_builder_insert_close (data->sparql); - - if (where && *where) { - tracker_sparql_builder_where_open (data->sparql); - tracker_sparql_builder_append (data->sparql, where); - tracker_sparql_builder_where_close (data->sparql); - } - - /* Prepend preupdate queries */ - if (preupdate && *preupdate) { - tracker_sparql_builder_prepend (data->sparql, preupdate); - } - - /* Append postupdate */ - if (postupdate && *postupdate) { - tracker_sparql_builder_append (data->sparql, postupdate); - } - - uuid = g_object_get_qdata (G_OBJECT (data->file), - data->miner->private->quark_mount_point_uuid); - - /* File represents a mount point */ - if (G_UNLIKELY (uuid)) { - GString *queries; - gchar *removable_device_urn, *uri; - - removable_device_urn = g_strdup_printf (TRACKER_PREFIX_DATASOURCE_URN "%s", uuid); - uri = g_file_get_uri (G_FILE (data->file)); - queries = g_string_new (""); - - g_string_append_printf (queries, - "DELETE { " - " <%s> tracker:mountPoint ?unknown " - "} WHERE { " - " <%s> a tracker:Volume; " - " tracker:mountPoint ?unknown " - "} ", - removable_device_urn, removable_device_urn); - - g_string_append_printf (queries, - "INSERT { GRAPH <%s> {" - " <%s> a tracker:Volume; " - " tracker:mountPoint ?u " - "} } WHERE { " - " ?u a nfo:FileDataObject; " - " nie:url \"%s\" " - "} ", - removable_device_urn, removable_device_urn, uri); - - tracker_sparql_builder_append (data->sparql, queries->str); - g_string_free (queries, TRUE); - g_free (removable_device_urn); - g_free (uri); - } -} - -static void -process_file_cb (GObject *object, - GAsyncResult *result, - gpointer user_data) -{ - TrackerMinerFilesPrivate *priv; - TrackerSparqlBuilder *sparql; - ProcessFileData *data; - const gchar *mime_type, *urn, *parent_urn; - GFileInfo *file_info; - guint64 time_; - GFile *file, *parent; - gchar *uri; - GError *error = NULL; - gboolean is_iri; - gboolean is_directory; - - data = user_data; - file = G_FILE (object); - sparql = data->sparql; - file_info = g_file_query_info_finish (file, result, &error); - priv = TRACKER_MINER_FILES (data->miner)->private; - - if (error) { - /* Something bad happened, notify about the error */ - tracker_miner_fs_notify_finish (TRACKER_MINER_FS (data->miner), data->task, NULL, error); - priv->extraction_queue = g_list_remove (priv->extraction_queue, data); - process_file_data_free (data); - return; - } - - uri = g_file_get_uri (file); - mime_type = g_file_info_get_content_type (file_info); - urn = miner_files_get_file_urn (TRACKER_MINER_FILES (data->miner), file, &is_iri); - - data->mime_type = g_strdup (mime_type); - - if (is_iri) { - gchar *delete_properties_sparql; - - /* Update: delete all statements inserted by miner except: - * - rdf:type statements as they could cause implicit deletion of user data - * - nie:contentCreated so it persists across updates - * - * Additionally, delete also nie:url as it might have been set by 3rd parties, - * and it's used to know whether a file is known to tracker or not. - */ - delete_properties_sparql = - g_strdup_printf ("DELETE {" - " GRAPH <%s> {" - " <%s> ?p ?o" - " } " - "} " - "WHERE {" - " GRAPH <%s> {" - " <%s> ?p ?o" - " FILTER (?p != rdf:type && ?p != nie:contentCreated)" - " } " - "} " - "DELETE {" - " <%s> nie:url ?o" - "} WHERE {" - " <%s> nie:url ?o" - "}", - TRACKER_OWN_GRAPH_URN, urn, - TRACKER_OWN_GRAPH_URN, urn, - urn, urn); - - tracker_sparql_builder_prepend (sparql, delete_properties_sparql); - g_free (delete_properties_sparql); - } - - tracker_sparql_builder_insert_silent_open (sparql, NULL); - tracker_sparql_builder_graph_open (sparql, TRACKER_OWN_GRAPH_URN); - - if (is_iri) { - tracker_sparql_builder_subject_iri (sparql, urn); - } else { - tracker_sparql_builder_subject (sparql, urn); - } - - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:FileDataObject"); - tracker_sparql_builder_object (sparql, "nie:InformationElement"); - - is_directory = (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY ? - TRUE : FALSE); - if (is_directory) { - tracker_sparql_builder_object (sparql, "nfo:Folder"); - } - - parent = g_file_get_parent (file); - parent_urn = tracker_miner_fs_query_urn (TRACKER_MINER_FS (data->miner), parent); - g_object_unref (parent); - - if (parent_urn) { - tracker_sparql_builder_predicate (sparql, "nfo:belongsToContainer"); - tracker_sparql_builder_object_iri (sparql, parent_urn); - } - - tracker_sparql_builder_predicate (sparql, "nfo:fileName"); - tracker_sparql_builder_object_string (sparql, g_file_info_get_display_name (file_info)); - - tracker_sparql_builder_predicate (sparql, "nfo:fileSize"); - tracker_sparql_builder_object_int64 (sparql, g_file_info_get_size (file_info)); - - time_ = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_MODIFIED); - tracker_sparql_builder_predicate (sparql, "nfo:fileLastModified"); - tracker_sparql_builder_object_date (sparql, (time_t *) &time_); - - time_ = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_ACCESS); - tracker_sparql_builder_predicate (sparql, "nfo:fileLastAccessed"); - tracker_sparql_builder_object_date (sparql, (time_t *) &time_); - - /* Laying the link between the IE and the DO. We use IE = DO */ - tracker_sparql_builder_predicate (sparql, "nie:isStoredAs"); - if (is_iri) { - tracker_sparql_builder_object_iri (sparql, urn); - } else { - tracker_sparql_builder_object (sparql, urn); - } - - /* The URL of the DataObject (because IE = DO, this is correct) */ - tracker_sparql_builder_predicate (sparql, "nie:url"); - tracker_sparql_builder_object_string (sparql, uri); - - tracker_sparql_builder_predicate (sparql, "nie:mimeType"); - tracker_sparql_builder_object_string (sparql, mime_type); - - miner_files_add_to_datasource (data->miner, file, sparql); - - miner_files_add_rdf_types (sparql, file, mime_type); - - sparql_builder_finish (data, NULL, NULL, NULL, NULL); - tracker_miner_fs_notify_finish (TRACKER_MINER_FS (data->miner), data->task, - tracker_sparql_builder_get_result (sparql), - NULL); - - priv->extraction_queue = g_list_remove (priv->extraction_queue, data); - process_file_data_free (data); - - g_object_unref (file_info); - g_free (uri); -} - -static gboolean -miner_files_process_file (TrackerMinerFS *fs, - GFile *file, - GTask *task) -{ - TrackerMinerFilesPrivate *priv; - ProcessFileData *data; - const gchar *attrs; - - data = g_slice_new0 (ProcessFileData); - data->miner = g_object_ref (fs); - data->cancellable = g_object_ref (g_task_get_cancellable (task)); - data->sparql = tracker_sparql_builder_new_update (); - data->file = g_object_ref (file); - data->task = g_object_ref (task); - - priv = TRACKER_MINER_FILES (fs)->private; - priv->extraction_queue = g_list_prepend (priv->extraction_queue, data); - - attrs = G_FILE_ATTRIBUTE_STANDARD_TYPE "," - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," - G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," - G_FILE_ATTRIBUTE_STANDARD_SIZE "," - G_FILE_ATTRIBUTE_TIME_MODIFIED "," - G_FILE_ATTRIBUTE_TIME_ACCESS; - - g_file_query_info_async (file, - attrs, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - G_PRIORITY_DEFAULT, - data->cancellable, - process_file_cb, - data); - - return TRUE; -} - -static void -process_file_attributes_cb (GObject *object, - GAsyncResult *result, - gpointer user_data) -{ - TrackerSparqlBuilder *sparql; - ProcessFileData *data; - const gchar *urn; - GFileInfo *file_info; - guint64 time_; - GFile *file; - gchar *uri; - GError *error = NULL; - gboolean is_iri; - - data = user_data; - file = G_FILE (object); - sparql = data->sparql; - file_info = g_file_query_info_finish (file, result, &error); - - if (error) { - /* Something bad happened, notify about the error */ - tracker_miner_fs_notify_finish (TRACKER_MINER_FS (data->miner), data->task, NULL, error); - process_file_data_free (data); - return; - } - - uri = g_file_get_uri (file); - urn = miner_files_get_file_urn (TRACKER_MINER_FILES (data->miner), file, &is_iri); - - /* We MUST have an IRI in attributes updating */ - if (!is_iri) { - error = g_error_new_literal (miner_files_error_quark, - 0, - "Received request to update attributes but no IRI available!"); - /* Notify about the error */ - tracker_miner_fs_notify_finish (TRACKER_MINER_FS (data->miner), data->task, NULL, error); - process_file_data_free (data); - return; - } - - /* Update nfo:fileLastModified */ - tracker_sparql_builder_delete_open (sparql, NULL); - tracker_sparql_builder_subject_iri (sparql, urn); - tracker_sparql_builder_predicate (sparql, "nfo:fileLastModified"); - tracker_sparql_builder_object_variable (sparql, "lastmodified"); - tracker_sparql_builder_delete_close (sparql); - tracker_sparql_builder_where_open (sparql); - tracker_sparql_builder_subject_iri (sparql, urn); - tracker_sparql_builder_predicate (sparql, "nfo:fileLastModified"); - tracker_sparql_builder_object_variable (sparql, "lastmodified"); - tracker_sparql_builder_where_close (sparql); - tracker_sparql_builder_insert_open (sparql, NULL); - tracker_sparql_builder_graph_open (sparql, TRACKER_OWN_GRAPH_URN); - tracker_sparql_builder_subject_iri (sparql, urn); - time_ = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_MODIFIED); - tracker_sparql_builder_predicate (sparql, "nfo:fileLastModified"); - tracker_sparql_builder_object_date (sparql, (time_t *) &time_); - tracker_sparql_builder_graph_close (sparql); - tracker_sparql_builder_insert_close (sparql); - - /* Update nfo:fileLastAccessed */ - tracker_sparql_builder_delete_open (sparql, NULL); - tracker_sparql_builder_subject_iri (sparql, urn); - tracker_sparql_builder_predicate (sparql, "nfo:fileLastAccessed"); - tracker_sparql_builder_object_variable (sparql, "lastaccessed"); - tracker_sparql_builder_delete_close (sparql); - tracker_sparql_builder_where_open (sparql); - tracker_sparql_builder_subject_iri (sparql, urn); - tracker_sparql_builder_predicate (sparql, "nfo:fileLastAccessed"); - tracker_sparql_builder_object_variable (sparql, "lastaccessed"); - tracker_sparql_builder_where_close (sparql); - tracker_sparql_builder_insert_open (sparql, NULL); - tracker_sparql_builder_graph_open (sparql, TRACKER_OWN_GRAPH_URN); - tracker_sparql_builder_subject_iri (sparql, urn); - time_ = g_file_info_get_attribute_uint64 (file_info, G_FILE_ATTRIBUTE_TIME_ACCESS); - tracker_sparql_builder_predicate (sparql, "nfo:fileLastAccessed"); - tracker_sparql_builder_object_date (sparql, (time_t *) &time_); - tracker_sparql_builder_graph_close (sparql); - tracker_sparql_builder_insert_close (sparql); - - /* Delete data sources from other miners/decorators */ - tracker_sparql_builder_delete_open (sparql, NULL); - tracker_sparql_builder_subject_iri (sparql, urn); - tracker_sparql_builder_predicate (sparql, "nie:dataSource"); - tracker_sparql_builder_object_variable (sparql, "datasource"); - tracker_sparql_builder_delete_close (sparql); - tracker_sparql_builder_where_open (sparql); - tracker_sparql_builder_subject_iri (sparql, urn); - tracker_sparql_builder_predicate (sparql, "nie:dataSource"); - tracker_sparql_builder_object_variable (sparql, "datasource"); - tracker_sparql_builder_where_close (sparql); - - g_object_unref (file_info); - g_free (uri); - - /* Notify about the success */ - tracker_miner_fs_notify_finish (TRACKER_MINER_FS (data->miner), data->task, - tracker_sparql_builder_get_result (sparql), - NULL); - - process_file_data_free (data); -} - -static gboolean -miner_files_process_file_attributes (TrackerMinerFS *fs, - GFile *file, - GTask *task) -{ - ProcessFileData *data; - const gchar *attrs; - - data = g_slice_new0 (ProcessFileData); - data->miner = g_object_ref (fs); - data->cancellable = g_object_ref (g_task_get_cancellable (task)); - data->sparql = tracker_sparql_builder_new_update (); - data->file = g_object_ref (file); - data->task = g_object_ref (task); - - /* Query only attributes that may change in an ATTRIBUTES_UPDATED event */ - attrs = G_FILE_ATTRIBUTE_TIME_MODIFIED "," - G_FILE_ATTRIBUTE_TIME_ACCESS; - - g_file_query_info_async (file, - attrs, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - G_PRIORITY_DEFAULT, - data->cancellable, - process_file_attributes_cb, - data); - - return TRUE; -} - -static void -miner_files_finished (TrackerMinerFS *fs, - gdouble elapsed, - gint directories_found, - gint directories_ignored, - gint files_found, - gint files_ignored) -{ - TrackerMinerFilesPrivate *priv = TRACKER_MINER_FILES (fs)->private; - - if (priv->thumbnailer) - tracker_thumbnailer_send (priv->thumbnailer); - - tracker_miner_files_set_last_crawl_done (TRUE); -} - -static gchar * -create_delete_sparql (GFile *file, - gboolean delete_self, - gboolean delete_children) -{ - GString *sparql; - gchar *uri; - - g_return_val_if_fail (delete_self || delete_children, NULL); - - uri = g_file_get_uri (file); - sparql = g_string_new ("DELETE {" - " ?f a rdfs:Resource . " - " ?ie a rdfs:Resource " - "} WHERE {" - " ?f a rdfs:Resource ; " - " nie:url ?u . " - " ?ie nie:isStoredAs ?f . " - " FILTER ("); - - if (delete_self) - g_string_append_printf (sparql, "?u = \"%s\" ", uri); - - if (delete_children) { - if (delete_self) - g_string_append (sparql, " || "); - - g_string_append_printf (sparql, "STRSTARTS (?u, \"%s/\")", uri); - } - - g_string_append (sparql, ")}"); - g_free (uri); - - return g_string_free (sparql, FALSE); -} - -static gchar * -miner_files_remove_children (TrackerMinerFS *fs, - GFile *file) -{ - return create_delete_sparql (file, FALSE, TRUE); -} - -static gchar * -miner_files_remove_file (TrackerMinerFS *fs, - GFile *file) -{ - TrackerMinerFilesPrivate *priv = TRACKER_MINER_FILES (fs)->private; - - if (priv->thumbnailer) { - gchar *uri; - - uri = g_file_get_uri (file); - tracker_thumbnailer_remove_add (priv->thumbnailer, uri, NULL); - g_free (uri); - } - - return create_delete_sparql (file, TRUE, TRUE); -} - -static void -move_thumbnails_cb (GObject *object, - GAsyncResult *result, - gpointer user_data) -{ - ThumbnailMoveData *data = user_data; - TrackerMinerFilesPrivate *priv = TRACKER_MINER_FILES (data->miner)->private; - GError *error = NULL; - - TrackerSparqlCursor *cursor = tracker_sparql_connection_query_finish (TRACKER_SPARQL_CONNECTION (object), result, &error); - - if (error) { - g_critical ("Could move thumbnails: %s", error->message); - g_error_free (error); - } else { - while (tracker_sparql_cursor_next (cursor, NULL, NULL)) { - const gchar *src, *dst, *mimetype; - - src = tracker_sparql_cursor_get_string (cursor, 0, NULL); - dst = tracker_sparql_cursor_get_string (cursor, 1, NULL); - mimetype = tracker_sparql_cursor_get_string (cursor, 2, NULL); - - if (priv->thumbnailer) { - tracker_thumbnailer_move_add (priv->thumbnailer, - src, mimetype, dst); - } - } - } - - g_object_unref (cursor); - g_main_loop_quit (data->main_loop); -} - -static gchar * -miner_files_move_file (TrackerMinerFS *fs, - GFile *file, - GFile *source_file, - gboolean recursive) -{ - TrackerMinerFilesPrivate *priv = TRACKER_MINER_FILES (fs)->private; - GString *sparql = g_string_new (NULL); - const gchar *new_parent_iri; - gchar *uri, *source_uri, *display_name; - gchar *source_iri; - gchar *path, *basename; - GFile *new_parent; - - uri = g_file_get_uri (file); - source_uri = g_file_get_uri (source_file); - source_iri = tracker_miner_fs_query_urn (fs, source_file); - - if (priv->thumbnailer) { - GFileInfo *file_info; - - file_info = g_file_query_info (file, - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, NULL); - tracker_thumbnailer_move_add (priv->thumbnailer, source_uri, - g_file_info_get_content_type (file_info), - uri); - g_object_unref (file_info); - - if (recursive) { - ThumbnailMoveData move_data; - gchar *query; - - g_debug ("Moving thumbnails within '%s'", uri); - - /* Push all moved files to thumbnailer */ - move_data.main_loop = g_main_loop_new (NULL, FALSE); - move_data.miner = TRACKER_MINER (fs); - - query = g_strdup_printf ("SELECT ?url ?new_url nie:mimeType(?u) {" - " ?u a rdfs:Resource ;" - " nie:url ?url ." - " BIND (CONCAT (\"%s/\", SUBSTR (?url, STRLEN (\"%s/\") + 1)) AS ?new_url) ." - " FILTER (STRSTARTS (?url, \"%s/\"))" - "}", - uri, source_uri, source_uri); - - tracker_sparql_connection_query_async (tracker_miner_get_connection (TRACKER_MINER (fs)), - query, - NULL, - move_thumbnails_cb, - &move_data); - - g_main_loop_run (move_data.main_loop); - g_main_loop_unref (move_data.main_loop); - g_free (query); - } - } - - path = g_file_get_path (file); - basename = g_filename_display_basename (path); - display_name = tracker_sparql_escape_string (basename); - g_free (basename); - g_free (path); - - g_string_append_printf (sparql, - "DELETE { " - " <%s> nfo:fileName ?f ; " - " nie:url ?u ; " - " nie:isStoredAs ?s ; " - " nfo:belongsToContainer ?b" - "} WHERE { " - " <%s> nfo:fileName ?f ; " - " nie:url ?u ; " - " nie:isStoredAs ?s . " - " OPTIONAL { <%s> nfo:belongsToContainer ?b }" - "} ", - source_iri, source_iri, source_iri); - - /* Get new parent information */ - new_parent = g_file_get_parent (file); - new_parent_iri = tracker_miner_fs_query_urn (fs, new_parent); - - g_string_append_printf (sparql, - "INSERT INTO <" TRACKER_OWN_GRAPH_URN "> {" - " <%s> nfo:fileName \"%s\" ; " - " nie:url \"%s\" ; " - " nie:isStoredAs <%s> ", - source_iri, display_name, uri, source_iri); - - if (new_parent && new_parent_iri) { - g_string_append_printf (sparql, "; nfo:belongsToContainer \"%s\"", - new_parent_iri); - } - - g_string_append (sparql, "}"); - - if (recursive) { - g_string_append_printf (sparql, - " DELETE {" - " ?u nie:url ?url " - "} INSERT { " - " GRAPH <" TRACKER_OWN_GRAPH_URN "> {" - " ?u nie:url ?new_url " - " }" - "} WHERE {" - " ?u a rdfs:Resource;" - " nie:url ?url ." - " BIND (CONCAT (\"%s/\", SUBSTR (?url, STRLEN (\"%s/\") + 1)) AS ?new_url) ." - " FILTER (STRSTARTS (?url, \"%s/\"))" - "} ", - uri, source_uri, source_uri); - } - - g_free (uri); - g_free (source_uri); - g_free (display_name); - g_clear_object (&new_parent); - - return g_string_free (sparql, FALSE); -} - -TrackerMiner * -tracker_miner_files_new (TrackerConfig *config, - GError **error) -{ - return g_initable_new (TRACKER_TYPE_MINER_FILES, - NULL, - error, - "root", NULL, - "config", config, - "processing-pool-wait-limit", 10, - "processing-pool-ready-limit", 100, - NULL); -} - -gboolean -tracker_miner_files_check_file (GFile *file, - GSList *ignored_file_paths, - GSList *ignored_file_patterns) -{ - GSList *l; - gchar *basename; - gchar *path; - gboolean should_process; - - should_process = FALSE; - basename = NULL; - path = NULL; - - if (tracker_file_is_hidden (file)) { - /* Ignore hidden files */ - goto done; - } - - path = g_file_get_path (file); - - for (l = ignored_file_paths; l; l = l->next) { - if (strcmp (l->data, path) == 0) { - goto done; - } - } - - basename = g_file_get_basename (file); - - for (l = ignored_file_patterns; l; l = l->next) { - if (g_pattern_match_string (l->data, basename)) { - goto done; - } - } - - should_process = TRUE; - -done: - g_free (basename); - g_free (path); - - return should_process; -} - -gboolean -tracker_miner_files_check_directory (GFile *file, - GSList *index_recursive_directories, - GSList *index_single_directories, - GSList *ignored_directory_paths, - GSList *ignored_directory_patterns) -{ - GSList *l; - gchar *basename; - gchar *path; - gboolean should_process; - gboolean is_hidden; - - should_process = FALSE; - basename = NULL; - - path = g_file_get_path (file); - - /* First we check the GIO hidden check. This does a number of - * things for us which is good (like checking ".foo" dirs). - */ - is_hidden = tracker_file_is_hidden (file); - -#ifdef __linux__ - /* Second we check if the file is on FAT and if the hidden - * attribute is set. GIO does this but ONLY on a Windows OS, - * not for Windows files under a Linux OS, so we have to check - * anyway. - */ - if (!is_hidden) { - int fd; - - fd = g_open (path, O_RDONLY, 0); - if (fd != -1) { - __u32 attrs; - - if (ioctl (fd, FAT_IOCTL_GET_ATTRIBUTES, &attrs) == 0) { - is_hidden = attrs & ATTR_HIDDEN ? TRUE : FALSE; - } - - close (fd); - } - } -#endif /* __linux__ */ - - if (is_hidden) { - /* FIXME: We need to check if the file is actually a - * config specified location before blanket ignoring - * all hidden files. - */ - if (tracker_string_in_gslist (path, index_recursive_directories)) { - should_process = TRUE; - } - - if (tracker_string_in_gslist (path, index_single_directories)) { - should_process = TRUE; - } - - /* Ignore hidden dirs */ - goto done; - } - - for (l = ignored_directory_paths; l; l = l->next) { - if (strcmp (l->data, path) == 0) { - goto done; - } - } - - basename = g_file_get_basename (file); - - for (l = ignored_directory_patterns; l; l = l->next) { - if (g_pattern_match_string (l->data, basename)) { - goto done; - } - } - - /* Check module directory ignore patterns */ - should_process = TRUE; - -done: - g_free (basename); - g_free (path); - - return should_process; -} - -gboolean -tracker_miner_files_check_directory_contents (GFile *parent, - GList *children, - GSList *ignored_content) -{ - GSList *l; - - if (!ignored_content) { - return TRUE; - } - - while (children) { - gchar *basename; - - basename = g_file_get_basename (children->data); - - for (l = ignored_content; l; l = l->next) { - if (g_strcmp0 (basename, l->data) == 0) { - gchar *parent_uri; - - parent_uri = g_file_get_uri (parent); - /* g_debug ("Directory '%s' ignored since it contains a file named '%s'", */ - /* parent_uri, basename); */ - - g_free (parent_uri); - g_free (basename); - - return FALSE; - } - } - - children = children->next; - g_free (basename); - } - - return TRUE; -} - -gboolean -tracker_miner_files_monitor_directory (GFile *file, - gboolean enable_monitors, - GSList *directories_to_check) -{ - if (!enable_monitors) { - return FALSE; - } - - /* We'll only get this signal for the directories where check_directory() - * and check_directory_contents() returned TRUE, so by default we want - * these directories to be indexed. */ - - return TRUE; -} - -static void -remove_files_in_removable_media_cb (GObject *object, - GAsyncResult *result, - gpointer user_data) -{ - GError *error = NULL; - - tracker_sparql_connection_update_finish (TRACKER_SPARQL_CONNECTION (object), result, &error); - - if (error) { - g_critical ("Could not remove files in volumes: %s", error->message); - g_error_free (error); - } -} - -static gboolean -miner_files_in_removable_media_remove_by_type (TrackerMinerFiles *miner, - TrackerStorageType type) -{ - gboolean removable; - gboolean optical; - - removable = TRACKER_STORAGE_TYPE_IS_REMOVABLE (type); - optical = TRACKER_STORAGE_TYPE_IS_OPTICAL (type); - - /* Only remove if any of the flags was TRUE */ - if (removable || optical) { - GString *queries; - - g_debug (" Removing all resources in store from %s ", - optical ? "optical discs" : "removable devices"); - - queries = g_string_new (""); - - /* Delete all resources where nie:dataSource is a volume - * of the given type */ - g_string_append_printf (queries, - "DELETE { " - " ?f a rdfs:Resource . " - " ?ie a rdfs:Resource " - "} WHERE { " - " ?v a tracker:Volume ; " - " tracker:isRemovable %s ; " - " tracker:isOptical %s . " - " ?f nie:dataSource ?v . " - " ?ie nie:isStoredAs ?f " - "}", - removable ? "true" : "false", - optical ? "true" : "false"); - - tracker_sparql_connection_update_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - queries->str, - G_PRIORITY_LOW, - NULL, - remove_files_in_removable_media_cb, - NULL); - - g_string_free (queries, TRUE); - - return TRUE; - } - - return FALSE; -} - -static void -miner_files_in_removable_media_remove_by_date (TrackerMinerFiles *miner, - const gchar *date) -{ - GString *queries; - - g_debug (" Removing all resources in store from removable or " - "optical devices not mounted after '%s'", - date); - - queries = g_string_new (""); - - /* Delete all resources where nie:dataSource is a volume - * which was last unmounted before the given date */ - g_string_append_printf (queries, - "DELETE { " - " ?f a rdfs:Resource . " - " ?ie a rdfs:Resource " - "} WHERE { " - " ?v a tracker:Volume ; " - " tracker:isRemovable true ; " - " tracker:isMounted false ; " - " tracker:unmountDate ?d . " - " ?f nie:dataSource ?v . " - " ?ie nie:isStoredAs ?f " - " FILTER ( ?d < \"%s\") " - "}", - date); - - tracker_sparql_connection_update_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - queries->str, - G_PRIORITY_LOW, - NULL, - remove_files_in_removable_media_cb, - NULL); - - g_string_free (queries, TRUE); -} - -static void -miner_files_add_removable_or_optical_directory (TrackerMinerFiles *mf, - const gchar *mount_path, - const gchar *uuid) -{ - TrackerIndexingTree *indexing_tree; - TrackerDirectoryFlags flags; - GFile *mount_point_file; - - mount_point_file = g_file_new_for_path (mount_path); - - /* UUID may be NULL, and if so, get it */ - if (!uuid) { - uuid = tracker_storage_get_uuid_for_file (mf->private->storage, - mount_point_file); - if (!uuid) { - g_critical ("Couldn't get UUID for mount point '%s'", - mount_path); - g_object_unref (mount_point_file); - return; - } - } - - indexing_tree = tracker_miner_fs_get_indexing_tree (TRACKER_MINER_FS (mf)); - flags = TRACKER_DIRECTORY_FLAG_RECURSE | - TRACKER_DIRECTORY_FLAG_CHECK_MTIME | - TRACKER_DIRECTORY_FLAG_PRESERVE | - TRACKER_DIRECTORY_FLAG_PRIORITY; - - if (tracker_config_get_enable_monitors (mf->private->config)) { - flags |= TRACKER_DIRECTORY_FLAG_MONITOR; - } - - g_object_set_qdata_full (G_OBJECT (mount_point_file), - mf->private->quark_mount_point_uuid, - g_strdup (uuid), - (GDestroyNotify) g_free); - - g_message (" Adding removable/optical: '%s'", mount_path); - tracker_indexing_tree_add (indexing_tree, - mount_point_file, - flags); - g_object_unref (mount_point_file); -} - -gboolean -tracker_miner_files_is_file_eligible (TrackerMinerFiles *miner, - GFile *file) -{ - TrackerConfig *config; - GFile *dir; - GFileInfo *file_info; - gboolean is_dir; - - file_info = g_file_query_info (file, - G_FILE_ATTRIBUTE_STANDARD_TYPE, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, NULL); - - if (!file_info) { - /* file does not exist */ - return FALSE; - } - - is_dir = (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY); - g_object_unref (file_info); - - g_object_get (miner, - "config", &config, - NULL); - - if (is_dir) { - dir = g_object_ref (file); - } else { - if (!tracker_miner_files_check_file (file, - tracker_config_get_ignored_file_paths (config), - tracker_config_get_ignored_file_patterns (config))) { - /* file is not eligible to be indexed */ - g_object_unref (config); - return FALSE; - } - - dir = g_file_get_parent (file); - } - - if (dir) { - gboolean found = FALSE; - GSList *l; - - if (!tracker_miner_files_check_directory (dir, - tracker_config_get_index_recursive_directories (config), - tracker_config_get_index_single_directories (config), - tracker_config_get_ignored_directory_paths (config), - tracker_config_get_ignored_directory_patterns (config))) { - /* file is not eligible to be indexed */ - g_object_unref (dir); - g_object_unref (config); - return FALSE; - } - - l = tracker_config_get_index_recursive_directories (config); - - while (l && !found) { - GFile *config_dir; - - config_dir = g_file_new_for_path ((gchar *) l->data); - - if (g_file_equal (dir, config_dir) || - g_file_has_prefix (dir, config_dir)) { - found = TRUE; - } - - g_object_unref (config_dir); - l = l->next; - } - - l = tracker_config_get_index_single_directories (config); - - while (l && !found) { - GFile *config_dir; - - config_dir = g_file_new_for_path ((gchar *) l->data); - - if (g_file_equal (dir, config_dir)) { - found = TRUE; - } - - g_object_unref (config_dir); - l = l->next; - } - - g_object_unref (dir); - - if (!found) { - /* file is not eligible to be indexed */ - g_object_unref (config); - return FALSE; - } - } - - g_object_unref (config); - - /* file is eligible to be indexed */ - return TRUE; -} - -inline static gchar * -get_first_index_filename (void) -{ - return g_build_filename (g_get_user_cache_dir (), - "tracker", - FIRST_INDEX_FILENAME, - NULL); -} - -/** - * tracker_miner_files_get_first_index_done: - * - * Check if first full index of files was already done. - * - * Returns: %TRUE if a first full index have been done, %FALSE otherwise. - **/ -gboolean -tracker_miner_files_get_first_index_done (void) -{ - gboolean exists; - gchar *filename; - - filename = get_first_index_filename (); - exists = g_file_test (filename, G_FILE_TEST_EXISTS); - g_free (filename); - - return exists; -} - -/** - * tracker_miner_files_set_first_index_done: - * - * Set the status of the first full index of files. Should be set to - * %FALSE if the index was never done or if a reindex is needed. When - * the index is completed, should be set to %TRUE. - **/ -void -tracker_miner_files_set_first_index_done (gboolean done) -{ - gboolean already_exists; - gchar *filename; - - filename = get_first_index_filename (); - already_exists = g_file_test (filename, G_FILE_TEST_EXISTS); - - if (done && !already_exists) { - GError *error = NULL; - - /* If done, create stamp file if not already there */ - if (!g_file_set_contents (filename, PACKAGE_VERSION, -1, &error)) { - g_warning (" Could not create file:'%s' failed, %s", - filename, - error->message); - g_error_free (error); - } else { - g_info (" First index file:'%s' created", filename); - } - } else if (!done && already_exists) { - /* If NOT done, remove stamp file */ - g_info (" Removing first index file:'%s'", filename); - - if (g_remove (filename)) { - g_warning (" Could not remove file:'%s': %m", - filename); - } - } - - g_free (filename); -} - -static inline gchar * -get_last_crawl_filename (void) -{ - return g_build_filename (g_get_user_cache_dir (), - "tracker", - LAST_CRAWL_FILENAME, - NULL); -} - -/** - * tracker_miner_files_get_last_crawl_done: - * - * Check when last crawl was performed. - * - * Returns: time_t() value when last crawl occurred, otherwise 0. - **/ -guint64 -tracker_miner_files_get_last_crawl_done (void) -{ - gchar *filename; - gchar *content; - guint64 then; - - filename = get_last_crawl_filename (); - - if (!g_file_get_contents (filename, &content, NULL, NULL)) { - g_info (" No previous timestamp, crawling forced"); - return 0; - } - - then = g_ascii_strtoull (content, NULL, 10); - g_free (content); - - return then; -} - -/** - * tracker_miner_files_set_last_crawl_done: - * - * Set the status of the first full index of files. Should be set to - * %FALSE if the index was never done or if a reindex is needed. When - * the index is completed, should be set to %TRUE. - **/ -void -tracker_miner_files_set_last_crawl_done (gboolean done) -{ - gboolean already_exists; - gchar *filename; - - filename = get_last_crawl_filename (); - already_exists = g_file_test (filename, G_FILE_TEST_EXISTS); - - if (done && !already_exists) { - GError *error = NULL; - gchar *content; - - content = g_strdup_printf ("%" G_GUINT64_FORMAT, (guint64) time (NULL)); - - /* If done, create stamp file if not already there */ - if (!g_file_set_contents (filename, content, -1, &error)) { - g_warning (" Could not create file:'%s' failed, %s", - filename, - error->message); - g_error_free (error); - } else { - g_info (" Last crawl file:'%s' created", filename); - } - - g_free (content); - } else if (!done && already_exists) { - /* If NOT done, remove stamp file */ - g_info (" Removing last crawl file:'%s'", filename); - - if (g_remove (filename)) { - g_warning (" Could not remove file:'%s': %m", - filename); - } - } - - g_free (filename); -} - -inline static gchar * -get_need_mtime_check_filename (void) -{ - return g_build_filename (g_get_user_cache_dir (), - "tracker", - NEED_MTIME_CHECK_FILENAME, - NULL); -} - -/** - * tracker_miner_files_get_need_mtime_check: - * - * Check if the miner-fs was cleanly shutdown or not. - * - * Returns: %TRUE if we need to check mtimes for directories against - * the database on the next start for the miner-fs, %FALSE otherwise. - **/ -gboolean -tracker_miner_files_get_need_mtime_check (void) -{ - gboolean exists; - gchar *filename; - - filename = get_need_mtime_check_filename (); - exists = g_file_test (filename, G_FILE_TEST_EXISTS); - g_free (filename); - - /* Existence of the file means we cleanly shutdown before and - * don't need to do the mtime check again on this start. - */ - return !exists; -} - -/** - * tracker_miner_files_set_need_mtime_check: - * @needed: a #gboolean - * - * If the next start of miner-fs should perform a full mtime check - * against each directory found and those in the database (for - * complete synchronisation), then @needed should be #TRUE, otherwise - * #FALSE. - * - * Creates a file in $HOME/.cache/tracker/ if an mtime check is not - * needed. The idea behind this is that a check is forced if the file - * is not cleaned up properly on shutdown (i.e. due to a crash or any - * other uncontrolled shutdown reason). - **/ -void -tracker_miner_files_set_need_mtime_check (gboolean needed) -{ - gboolean already_exists; - gchar *filename; - - filename = get_need_mtime_check_filename (); - already_exists = g_file_test (filename, G_FILE_TEST_EXISTS); - - /* !needed = add file - * needed = remove file - */ - if (!needed && !already_exists) { - GError *error = NULL; - - /* Create stamp file if not already there */ - if (!g_file_set_contents (filename, PACKAGE_VERSION, -1, &error)) { - g_warning (" Could not create file:'%s' failed, %s", - filename, - error->message); - g_error_free (error); - } else { - g_info (" Need mtime check file:'%s' created", filename); - } - } else if (needed && already_exists) { - /* Remove stamp file */ - g_info (" Removing need mtime check file:'%s'", filename); - - if (g_remove (filename)) { - g_warning (" Could not remove file:'%s': %m", - filename); - } - } - - g_free (filename); -} - -void -tracker_miner_files_set_mtime_checking (TrackerMinerFiles *mf, - gboolean mtime_check) -{ - mf->private->mtime_check = mtime_check; -} - -void -tracker_miner_files_writeback_file (TrackerMinerFiles *mf, - GFile *file, - GStrv rdf_types, - GPtrArray *results) -{ - GCancellable *cancellable; - - if (!g_hash_table_contains (mf->private->writeback_tasks, file)) { - cancellable = g_cancellable_new (); - g_hash_table_insert (mf->private->writeback_tasks, file, cancellable); - sync_writeback_pause_state (mf); - g_signal_emit (mf, signals[WRITEBACK], 0, file, rdf_types, - results, cancellable); - } -} - -/** - * tracker_miner_files_writeback_notify: - * @fs: a #TrackerMinerFS - * @file: a #GFile - * @error: a #GError with the error that happened during processing, or %NULL. - * - * Notifies @fs that all writing back on @file has been finished, if any error - * happened during file data processing, it should be passed in @error, else - * that parameter will contain %NULL to reflect success. - **/ -void -tracker_miner_files_writeback_notify (TrackerMinerFiles *mf, - GFile *file, - const GError *error) -{ - GCancellable *cancellable; - - g_return_if_fail (TRACKER_IS_MINER_FILES (mf)); - g_return_if_fail (G_IS_FILE (file)); - - cancellable = g_hash_table_lookup (mf->private->writeback_tasks, file); - - if (!cancellable) - return; - - if (error) { - gchar *uri = g_file_get_uri (file); - g_warning ("Writeback on %s got error: %s\n", - uri, error->message); - g_free (uri); - } - - /* Drop the cancellable, it will be detected on the next file - * update in miner_files_filter_event(). - */ - g_hash_table_steal (mf->private->writeback_tasks, file); - g_hash_table_insert (mf->private->writeback_tasks, file, NULL); - g_object_unref (cancellable); -} diff --git a/src/miners/fs/tracker-miner-files.h b/src/miners/fs/tracker-miner-files.h deleted file mode 100644 index c67140774..000000000 --- a/src/miners/fs/tracker-miner-files.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_MINER_FS_FILES_H__ -#define __TRACKER_MINER_FS_FILES_H__ - -#include <libtracker-miner/tracker-miner.h> - -#include "tracker-config.h" - -G_BEGIN_DECLS - -#define TRACKER_TYPE_MINER_FILES (tracker_miner_files_get_type()) -#define TRACKER_MINER_FILES(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_MINER_FILES, TrackerMinerFiles)) -#define TRACKER_MINER_FILES_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_MINER_FILES, TrackerMinerFilesClass)) -#define TRACKER_IS_MINER_FILES(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_MINER_FILES)) -#define TRACKER_IS_MINER_FILES_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_MINER_FILES)) -#define TRACKER_MINER_FILES_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_MINER_FILES, TrackerMinerFilesClass)) - -typedef struct TrackerMinerFiles TrackerMinerFiles; -typedef struct TrackerMinerFilesClass TrackerMinerFilesClass; -typedef struct TrackerMinerFilesPrivate TrackerMinerFilesPrivate; - -struct TrackerMinerFiles { - TrackerMinerFS parent_instance; - TrackerMinerFilesPrivate *private; -}; - -struct TrackerMinerFilesClass { - TrackerMinerFSClass parent_class; -}; - -GType tracker_miner_files_get_type (void) G_GNUC_CONST; - -TrackerMiner *tracker_miner_files_new (TrackerConfig *config, - GError **error); - -/* Convenience functions for --eligible tracker-miner-fs cmdline */ -gboolean tracker_miner_files_check_file (GFile *file, - GSList *ignored_file_paths, - GSList *ignored_file_patterns); -gboolean tracker_miner_files_check_directory (GFile *file, - GSList *index_recursive_directories, - GSList *index_single_directories, - GSList *ignored_directory_paths, - GSList *ignored_directory_patterns); -gboolean tracker_miner_files_check_directory_contents (GFile *parent, - GList *children, - GSList *ignored_content); -gboolean tracker_miner_files_monitor_directory (GFile *file, - gboolean enable_monitors, - GSList *directories_to_check); -gboolean tracker_miner_files_is_file_eligible (TrackerMinerFiles *miner, - GFile *file); - -/* Global functions to handle timestamp files */ -gboolean tracker_miner_files_get_first_index_done (void); -void tracker_miner_files_set_first_index_done (gboolean done); - -guint64 tracker_miner_files_get_last_crawl_done (void); -void tracker_miner_files_set_last_crawl_done (gboolean done); - -gboolean tracker_miner_files_get_need_mtime_check (void); -void tracker_miner_files_set_need_mtime_check (gboolean needed); - -void tracker_miner_files_set_mtime_checking (TrackerMinerFiles *miner, - gboolean mtime_checking); - -void tracker_miner_files_writeback_file (TrackerMinerFiles *mf, - GFile *file, - GStrv rdf_types, - GPtrArray *results); -void tracker_miner_files_writeback_notify (TrackerMinerFiles *mf, - GFile *file, - const GError *error); - -G_END_DECLS - -#endif /* __TRACKER_MINER_FS_FILES_H__ */ diff --git a/src/miners/fs/tracker-miner-fs.desktop.in.in b/src/miners/fs/tracker-miner-fs.desktop.in.in deleted file mode 100644 index 29d5364c6..000000000 --- a/src/miners/fs/tracker-miner-fs.desktop.in.in +++ /dev/null @@ -1,18 +0,0 @@ -[Desktop Entry] -_Name=Tracker File System Miner -_Comment=Crawls and processes files on the file system -Icon= -Exec=@libexecdir@/tracker-miner-fs -Terminal=false -Type=Application -Categories=Utility; -X-GNOME-Autostart-enabled=true -X-KDE-autostart-after=panel -X-KDE-StartupNotify=false -X-KDE-UniqueApplet=true -NoDisplay=true -OnlyShowIn=GNOME;KDE;XFCE;X-IVI;Unity; -X-GNOME-Bugzilla-Bugzilla=GNOME -X-GNOME-Bugzilla-Product=tracker -X-GNOME-Bugzilla-Component=Miners -X-GNOME-Bugzilla-Version=@VERSION@ diff --git a/src/miners/fs/tracker-miner-fs.service.in b/src/miners/fs/tracker-miner-fs.service.in deleted file mode 100644 index fad973a04..000000000 --- a/src/miners/fs/tracker-miner-fs.service.in +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Tracker file system data miner - -[Service] -Type=dbus -BusName=org.freedesktop.Tracker1.Miner.Files -ExecStart=@libexecdir@/tracker-miner-fs -Restart=on-failure -# Don't restart after tracker daemon -k (aka tracker-control -k) -RestartPreventExitStatus=SIGKILL diff --git a/src/miners/fs/tracker-power-hal.c b/src/miners/fs/tracker-power-hal.c deleted file mode 100644 index c5e15ba1b..000000000 --- a/src/miners/fs/tracker-power-hal.c +++ /dev/null @@ -1,551 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#ifdef HAVE_HAL - -#include <string.h> - -#include <libhal.h> - -#include <libtracker-common/tracker-log.h> -#include <libtracker-common/tracker-utils.h> - -#include "tracker-power.h" - -#define CAPABILITY_AC_ADAPTER "ac_adapter" -#define CAPABILITY_BATTERY "battery" - -#define PROP_AC_ADAPTER_ON "ac_adapter.present" -#define PROP_BATT_PERCENTAGE "battery.charge_level.percentage" - -#define BATTERY_LOW_THRESHOLD 0.05f - -#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_POWER, TrackerPowerPriv)) - -typedef struct { - LibHalContext *context; - DBusConnection *connection; - - GHashTable *batteries; - - gchar *ac_adapter_udi; - gboolean on_battery; - gdouble battery_percentage; -} TrackerPowerPriv; - -static void tracker_power_finalize (GObject *object); -static void hal_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); -static gboolean hal_setup_ac_adapters (TrackerPower *power); -static gboolean hal_setup_batteries (TrackerPower *power); - -static void hal_battery_modify (TrackerPower *power, - const gchar *udi); -static void hal_battery_remove (TrackerPower *power, - const gchar *udi); - -static void hal_device_added_cb (LibHalContext *context, - const gchar *udi); -static void hal_device_removed_cb (LibHalContext *context, - const gchar *udi); -static void hal_device_property_modified_cb (LibHalContext *context, - const char *udi, - const char *key, - dbus_bool_t is_removed, - dbus_bool_t is_added); - -enum { - PROP_0, - PROP_ON_BATTERY, - PROP_ON_LOW_BATTERY -}; - -G_DEFINE_TYPE (TrackerPower, tracker_power, G_TYPE_OBJECT); - -static void -tracker_power_class_init (TrackerPowerClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = tracker_power_finalize; - object_class->get_property = hal_get_property; - - g_object_class_install_property (object_class, - PROP_ON_BATTERY, - g_param_spec_boolean ("on-battery", - "Battery in use", - "Whether the battery is being used", - FALSE, - G_PARAM_READABLE)); - g_object_class_install_property (object_class, - PROP_ON_LOW_BATTERY, - g_param_spec_boolean ("on-low-battery", - "Battery low", - "Whether the battery is low", - FALSE, - G_PARAM_READABLE)); - - g_type_class_add_private (object_class, sizeof (TrackerPowerPriv)); -} - -static void -tracker_power_init (TrackerPower *power) -{ - TrackerPowerPriv *priv; - DBusError error; - - g_message ("Initializing HAL Power..."); - - priv = GET_PRIV (power); - - priv->batteries = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, - NULL); - - dbus_error_init (&error); - - priv->connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error); - if (dbus_error_is_set (&error)) { - g_critical ("Could not get the system D-Bus connection, %s", - error.message); - dbus_error_free (&error); - return; - } - - dbus_connection_set_exit_on_disconnect (priv->connection, FALSE); - dbus_connection_setup_with_g_main (priv->connection, NULL); - - priv->context = libhal_ctx_new (); - - if (!priv->context) { - g_critical ("Could not create HAL context"); - return; - } - - libhal_ctx_set_user_data (priv->context, power); - libhal_ctx_set_dbus_connection (priv->context, priv->connection); - - if (!libhal_ctx_init (priv->context, &error)) { - if (dbus_error_is_set (&error)) { - g_critical ("Could not initialize the HAL context, %s", - error.message); - dbus_error_free (&error); - } else { - g_critical ("Could not initialize the HAL context, " - "no error, is hald running?"); - } - - libhal_ctx_free (priv->context); - priv->context = NULL; - return; - } - - - /* Volume and property notification callbacks */ - g_message ("HAL monitors set for devices added/removed/mounted/umounted..."); - libhal_ctx_set_device_added (priv->context, hal_device_added_cb); - libhal_ctx_set_device_removed (priv->context, hal_device_removed_cb); - libhal_ctx_set_device_property_modified (priv->context, hal_device_property_modified_cb); - - /* Get all AC adapters info and set them up */ - if (!hal_setup_ac_adapters (power)) { - return; - } - - /* Get all battery devices and set them up */ - if (!hal_setup_batteries (power)) { - return; - } -} - -static void -tracker_power_finalize (GObject *object) -{ - TrackerPowerPriv *priv; - - priv = GET_PRIV (object); - - if (priv->batteries) { - g_hash_table_unref (priv->batteries); - } - - g_free (priv->ac_adapter_udi); - - if (priv->context) { - libhal_ctx_shutdown (priv->context, NULL); - libhal_ctx_set_user_data (priv->context, NULL); - libhal_ctx_free (priv->context); - } - - if (priv->connection) { - dbus_connection_unref (priv->connection); - } - - (G_OBJECT_CLASS (tracker_power_parent_class)->finalize) (object); -} - -static void -hal_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - TrackerPowerPriv *priv; - - priv = GET_PRIV (object); - - switch (param_id) { - case PROP_ON_BATTERY: - g_value_set_boolean (value, priv->on_battery); - break; - case PROP_ON_LOW_BATTERY: - /* hardcoded to 5% */ - g_value_set_boolean (value, priv->battery_percentage < BATTERY_LOW_THRESHOLD); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - }; -} - -static gboolean -hal_setup_ac_adapters (TrackerPower *power) -{ - TrackerPowerPriv *priv; - DBusError error; - gchar **devices, **p; - gint num; - - priv = GET_PRIV (power); - - dbus_error_init (&error); - - devices = libhal_find_device_by_capability (priv->context, - CAPABILITY_AC_ADAPTER, - &num, - &error); - - if (dbus_error_is_set (&error)) { - g_critical ("Could not get AC adapter capable devices, %s", - error.message); - dbus_error_free (&error); - return FALSE; - } - - g_message ("HAL found %d AC adapter capable devices", num); - - if (!devices || !devices[0]) { - libhal_free_string_array (devices); - - priv->on_battery = FALSE; - g_object_notify (G_OBJECT (power), "on-battery"); - - priv->ac_adapter_udi = NULL; - - return TRUE; - } - - for (p = devices; *p; p++) { - if (!priv->ac_adapter_udi) { - /* For now just use the first one we find */ - priv->ac_adapter_udi = g_strdup (*p); - - g_message (" Device '%s' (default)", *p); - } else { - g_message (" Device '%s'", *p); - } - } - - libhal_free_string_array (devices); - - /* Make sure we watch changes to the battery use */ - libhal_device_add_property_watch (priv->context, - priv->ac_adapter_udi, - &error); - - if (dbus_error_is_set (&error)) { - g_critical ("Could not add device:'%s' to property watch, %s", - priv->ac_adapter_udi, error.message); - dbus_error_free (&error); - return FALSE; - } - - /* Get current state, are we using the battery now? */ - priv->on_battery = !libhal_device_get_property_bool (priv->context, - priv->ac_adapter_udi, - PROP_AC_ADAPTER_ON, - NULL); - - g_message ("HAL reports system is currently powered by %s", - priv->on_battery ? "battery" : "AC adapter"); - - g_object_notify (G_OBJECT (power), "on-battery"); - - return TRUE; -} - -static gboolean -hal_setup_batteries (TrackerPower *power) -{ - TrackerPowerPriv *priv; - DBusError error; - gchar **devices, **p; - gint num; - - priv = GET_PRIV (power); - - dbus_error_init (&error); - - devices = libhal_find_device_by_capability (priv->context, - CAPABILITY_BATTERY, - &num, - &error); - - if (dbus_error_is_set (&error)) { - g_critical ("Could not get Battery HAL info, %s", - error.message); - dbus_error_free (&error); - return FALSE; - } - - g_message ("HAL found %d batteries", num); - - if (!devices || !devices[0]) { - libhal_free_string_array (devices); - return TRUE; - } - - for (p = devices; *p; p++) { - g_message (" Device '%s'", *p); - - hal_battery_modify (power, *p); - libhal_device_add_property_watch (priv->context, *p, &error); - - if (dbus_error_is_set (&error)) { - g_critical ("Could not add device:'%s' to property watch, %s", - *p, error.message); - dbus_error_free (&error); - } - } - - libhal_free_string_array (devices); - - return TRUE; -} - -static void -hal_battery_notify (TrackerPower *power) -{ - TrackerPowerPriv *priv; - GList *values, *v; - gint percentage, n_values; - gdouble old_percentage; - - priv = GET_PRIV (power); - percentage = n_values = 0; - - values = g_hash_table_get_values (priv->batteries); - - for (v = values; v; v = v->next) { - percentage += GPOINTER_TO_INT (v->data); - n_values++; - } - - old_percentage = priv->battery_percentage; - - if (n_values > 0) { - priv->battery_percentage = (gdouble) percentage / n_values; - priv->battery_percentage /= 100; - } else { - priv->battery_percentage = 0; - } - - /* only notify when we cross the threshold up or down */ - if ((priv->battery_percentage > BATTERY_LOW_THRESHOLD && - old_percentage <= BATTERY_LOW_THRESHOLD) || - (priv->battery_percentage <= BATTERY_LOW_THRESHOLD && - old_percentage > BATTERY_LOW_THRESHOLD)) { - g_object_notify (G_OBJECT (power), "on-low-battery"); - } - - g_list_free (values); -} - -static void -hal_battery_modify (TrackerPower *power, - const gchar *udi) -{ - TrackerPowerPriv *priv; - gint percentage; - - priv = GET_PRIV (power); - percentage = libhal_device_get_property_int (priv->context, udi, - PROP_BATT_PERCENTAGE, - NULL); - - g_hash_table_insert (priv->batteries, - g_strdup (udi), - GINT_TO_POINTER (percentage)); - - hal_battery_notify (power); -} - -static void -hal_battery_remove (TrackerPower *power, - const gchar *udi) -{ - TrackerPowerPriv *priv; - - priv = GET_PRIV (power); - - g_hash_table_remove (priv->batteries, udi); - hal_battery_notify (power); -} - -static void -hal_device_added_cb (LibHalContext *context, - const gchar *udi) -{ - TrackerPower *power; - - power = libhal_ctx_get_user_data (context); - - if (libhal_device_query_capability (context, udi, CAPABILITY_BATTERY, NULL)) { - hal_battery_modify (power, udi); - } -} - -static void -hal_device_removed_cb (LibHalContext *context, - const gchar *udi) -{ - TrackerPower *power; - TrackerPowerPriv *priv; - - power = (TrackerPower*) libhal_ctx_get_user_data (context); - priv = GET_PRIV (power); - - if (g_hash_table_lookup (priv->batteries, udi)) { - hal_battery_remove (power, udi); - } -} - -static void -hal_device_property_modified_cb (LibHalContext *context, - const char *udi, - const char *key, - dbus_bool_t is_removed, - dbus_bool_t is_added) -{ - TrackerPower *power; - TrackerPowerPriv *priv; - DBusError error; - - power = (TrackerPower*) libhal_ctx_get_user_data (context); - priv = GET_PRIV (power); - - dbus_error_init (&error); - - if (priv->ac_adapter_udi && strcmp (priv->ac_adapter_udi, udi) == 0) { - /* Property change is on the AC adapter */ - priv->on_battery = !libhal_device_get_property_bool (priv->context, - priv->ac_adapter_udi, - PROP_AC_ADAPTER_ON, - &error); - g_message ("HAL reports system is now powered by %s", - priv->on_battery ? "battery" : "AC adapter"); - - g_object_notify (G_OBJECT (power), "on-battery"); - - if (dbus_error_is_set (&error)) { - g_critical ("Could not get device property:'%s' for udi:'%s', %s", - udi, PROP_AC_ADAPTER_ON, error.message); - dbus_error_free (&error); - return; - } - } else if (g_hash_table_lookup (priv->batteries, udi)) { - /* Property change is on any battery */ - if (strcmp (key, PROP_BATT_PERCENTAGE) == 0) { - hal_battery_modify (power, udi); - } - } -} - -/** - * tracker_power_new: - * - * Creates a new instance of #TrackerPower. - * - * Returns: The newly created #TrackerPower. - **/ -TrackerPower * -tracker_power_new () -{ - return g_object_new (TRACKER_TYPE_POWER, NULL); -} - -/** - * tracker_hal_get_on_battery: - * @power: A #TrackerPower. - * - * Returns whether the computer battery (if any) is currently in use. - * - * Returns: #TRUE if the computer is running on battery power. - **/ -gboolean -tracker_power_get_on_battery (TrackerPower *power) -{ - TrackerPowerPriv *priv; - - g_return_val_if_fail (TRACKER_IS_POWER (power), TRUE); - - priv = GET_PRIV (power); - - return priv->on_battery; -} - -/** - * tracker_power_get_on_low_battery: - * @power: A #TrackerPower - * - * Returns whether the computer has batteries. - * - * Returns: #TRUE if the computer has batteries available. - **/ -gboolean -tracker_power_get_on_low_battery (TrackerPower *power) -{ - TrackerPowerPriv *priv; - - g_return_val_if_fail (TRACKER_IS_POWER (power), TRUE); - - priv = GET_PRIV (power); - - return (priv->battery_percentage < BATTERY_LOW_THRESHOLD); -} - -#endif /* HAVE_HAL */ diff --git a/src/miners/fs/tracker-power-upower.c b/src/miners/fs/tracker-power-upower.c deleted file mode 100644 index cc5a41265..000000000 --- a/src/miners/fs/tracker-power-upower.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#ifdef HAVE_UPOWER - -#include <upower.h> - -#include "tracker-power.h" - -#define GET_PRIV(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_POWER, TrackerPowerPriv)) - -typedef struct { - UpClient *client; -#ifndef HAVE_UP_CLIENT_GET_ON_LOW_BATTERY - UpDevice *composite_device; -#endif - gboolean on_battery; - gboolean on_low_battery; -} TrackerPowerPriv; - -static void tracker_power_finalize (GObject *object); -static void tracker_power_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); -#ifdef HAVE_UP_CLIENT_GET_ON_LOW_BATTERY -static void tracker_power_client_changed_cb (UpClient *client, - TrackerPower *power); -#endif /* HAVE_UP_CLIENT_GET_ON_LOW_BATTERY */ - -enum { - PROP_0, - PROP_ON_BATTERY, - PROP_ON_LOW_BATTERY -}; - -G_DEFINE_TYPE (TrackerPower, tracker_power, G_TYPE_OBJECT); - -static void -tracker_power_class_init (TrackerPowerClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = tracker_power_finalize; - object_class->get_property = tracker_power_get_property; - - g_object_class_install_property (object_class, - PROP_ON_BATTERY, - g_param_spec_boolean ("on-battery", - "Battery in use", - "Whether the battery is being used", - FALSE, - G_PARAM_READABLE)); - - g_object_class_install_property (object_class, - PROP_ON_LOW_BATTERY, - g_param_spec_boolean ("on-low-battery", - "Battery low", - "Whether the battery is low", - FALSE, - G_PARAM_READABLE)); - - g_type_class_add_private (object_class, sizeof (TrackerPowerPriv)); -} - -#ifndef HAVE_UP_CLIENT_GET_ON_LOW_BATTERY -static void -on_on_battery_changed (UpClient *client, - GParamSpec *pspec, - TrackerPower *power) -{ - TrackerPowerPriv *priv = GET_PRIV (power); - gboolean on_battery; - - on_battery = up_client_get_on_battery (priv->client); - if (on_battery != priv->on_battery) { - priv->on_battery = on_battery; - g_object_notify (G_OBJECT (power), "on-battery"); - } -} - -static void -on_warning_level_changed (UpDevice *device, - GParamSpec *pspec, - TrackerPower *power) -{ - TrackerPowerPriv *priv = GET_PRIV (power); - UpDeviceLevel warning_level; - gboolean on_low_battery; - - g_object_get (priv->composite_device, "warning-level", &warning_level, NULL); - on_low_battery = warning_level >= UP_DEVICE_LEVEL_LOW; - if (on_low_battery != priv->on_low_battery) { - priv->on_low_battery = on_low_battery; - g_object_notify (G_OBJECT (power), "on-low-battery"); - } -} -#endif /* !HAVE_UP_CLIENT_GET_ON_LOW_BATTERY */ - -static void -tracker_power_init (TrackerPower *power) -{ - TrackerPowerPriv *priv; - - g_message ("Initializing UPower..."); - - priv = GET_PRIV (power); - - /* connect to a UPower instance */ - priv->client = up_client_new (); -#ifdef HAVE_UP_CLIENT_GET_ON_LOW_BATTERY - g_signal_connect (priv->client, "changed", - G_CALLBACK (tracker_power_client_changed_cb), power); - tracker_power_client_changed_cb (priv->client, power); -#else - g_signal_connect (priv->client, "notify::on-battery", - G_CALLBACK (on_on_battery_changed), power); - on_on_battery_changed (priv->client, NULL, power); - priv->composite_device = up_client_get_display_device (priv->client); - g_signal_connect (priv->composite_device, "notify::warning-level", - G_CALLBACK (on_warning_level_changed), power); - on_warning_level_changed (priv->composite_device, NULL, power); -#endif /* HAVE_UP_CLIENT_GET_ON_LOW_BATTERY */ -} - -static void -tracker_power_finalize (GObject *object) -{ - TrackerPowerPriv *priv; - - priv = GET_PRIV (object); - -#ifndef HAVE_UP_CLIENT_GET_ON_LOW_BATTERY - g_object_unref (priv->composite_device); -#endif /* HAVE_UP_CLIENT_GET_ON_LOW_BATTERY */ - - g_object_unref (priv->client); - - (G_OBJECT_CLASS (tracker_power_parent_class)->finalize) (object); -} - -static void -tracker_power_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - TrackerPowerPriv *priv; - - priv = GET_PRIV (object); - - switch (param_id) { - case PROP_ON_BATTERY: - g_value_set_boolean (value, priv->on_battery); - break; - case PROP_ON_LOW_BATTERY: - g_value_set_boolean (value, priv->on_low_battery); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - }; -} - -#ifdef HAVE_UP_CLIENT_GET_ON_LOW_BATTERY -static void -tracker_power_client_changed_cb (UpClient *client, - TrackerPower *power) -{ - TrackerPowerPriv *priv; - gboolean on_battery; - gboolean on_low_battery; - - priv = GET_PRIV (power); - - /* get the on-battery state */ - on_battery = up_client_get_on_battery (priv->client); - if (on_battery != priv->on_battery) { - priv->on_battery = on_battery; - g_object_notify (G_OBJECT (power), "on-battery"); - } - - /* get the on-low-battery state */ - on_low_battery = up_client_get_on_low_battery (priv->client); - if (on_low_battery != priv->on_low_battery) { - priv->on_low_battery = on_low_battery; - g_object_notify (G_OBJECT (power), "on-low-battery"); - } -} -#endif /* HAVE_UP_CLIENT_GET_ON_LOW_BATTERY */ - -/** - * tracker_power_new: - * - * Creates a new instance of #TrackerPower. - * - * Returns: The newly created #TrackerPower. - **/ -TrackerPower * -tracker_power_new () -{ - return g_object_new (TRACKER_TYPE_POWER, NULL); -} - -/** - * tracker_power_get_on_battery: - * @power: A #TrackerPower. - * - * Returns whether the computer battery (if any) is currently in use. - * - * Returns: #TRUE if the computer is running on battery power. - **/ -gboolean -tracker_power_get_on_battery (TrackerPower *power) -{ - TrackerPowerPriv *priv; - - g_return_val_if_fail (TRACKER_IS_POWER (power), TRUE); - - priv = GET_PRIV (power); - - return priv->on_battery; -} - -/** - * tracker_power_get_on_low_battery: - * @power: A #TrackerPower - * - * Returns whether the computer has batteries. - * - * Returns: #TRUE if the computer has batteries available. - **/ -gboolean -tracker_power_get_on_low_battery (TrackerPower *power) -{ - TrackerPowerPriv *priv; - - g_return_val_if_fail (TRACKER_IS_POWER (power), TRUE); - - priv = GET_PRIV (power); - - return priv->on_low_battery; -} - -#endif /* HAVE_UPOWER */ diff --git a/src/miners/fs/tracker-power.h b/src/miners/fs/tracker-power.h deleted file mode 100644 index 7440b9e95..000000000 --- a/src/miners/fs/tracker-power.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_MINER_FS_POWER_H__ -#define __TRACKER_MINER_FS_POWER_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -#if !defined (__LIBTRACKER_COMMON_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "only <libtracker-common/tracker-common.h> must be included directly." -#endif - -#define TRACKER_TYPE_POWER (tracker_power_get_type ()) -#define TRACKER_POWER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_POWER, TrackerPower)) -#define TRACKER_POWER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TRACKER_TYPE_POWER, TrackerPowerClass)) -#define TRACKER_IS_POWER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_POWER)) -#define TRACKER_IS_POWER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TRACKER_TYPE_POWER)) -#define TRACKER_POWER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_POWER, TrackerPowerClass)) - -typedef struct _TrackerPower TrackerPower; -typedef struct _TrackerPowerClass TrackerPowerClass; - -struct _TrackerPower { - GObject parent; -}; - -struct _TrackerPowerClass { - GObjectClass parent_class; -}; - -GType tracker_power_get_type (void) G_GNUC_CONST; - -TrackerPower *tracker_power_new (void); - -gboolean tracker_power_get_on_battery (TrackerPower *power); -gboolean tracker_power_get_on_low_battery (TrackerPower *power); - -G_END_DECLS - -#endif /* __TRACKER_MINER_FS_POWER_H__ */ diff --git a/src/miners/fs/tracker-storage.c b/src/miners/fs/tracker-storage.c deleted file mode 100644 index 9ec59dbfd..000000000 --- a/src/miners/fs/tracker-storage.c +++ /dev/null @@ -1,1105 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <string.h> - -#include <gio/gio.h> -#include <gio/gunixmounts.h> - -#include <libtracker-common/tracker-log.h> - -#include "tracker-storage.h" - -/** - * SECTION:tracker-storage - * @short_description: Removable storage and mount point convenience API - * @include: libtracker-miner/tracker-miner.h - * - * This API is a convenience to to be able to keep track of volumes - * which are mounted and also the type of removable media available. - * The API is built upon the top of GIO's #GMount, #GDrive and #GVolume API. - **/ - -#define TRACKER_STORAGE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_STORAGE, TrackerStoragePrivate)) - -typedef struct { - GVolumeMonitor *volume_monitor; - - GNode *mounts; - GHashTable *mounts_by_uuid; - GHashTable *unmount_watchdogs; -} TrackerStoragePrivate; - -typedef struct { - gchar *mount_point; - gchar *uuid; - guint unmount_timer_id; - guint removable : 1; - guint optical : 1; -} MountInfo; - -typedef struct { - const gchar *path; - GNode *node; -} TraverseData; - -typedef struct { - GSList *roots; - TrackerStorageType type; - gboolean exact_match; -} GetRoots; - -typedef struct { - TrackerStorage *storage; - GMount *mount; -} UnmountCheckData; - -static void tracker_storage_finalize (GObject *object); -static gboolean mount_info_free (GNode *node, - gpointer user_data); -static void mount_node_free (GNode *node); -static gboolean mounts_setup (TrackerStorage *storage); -static void mount_added_cb (GVolumeMonitor *monitor, - GMount *mount, - gpointer user_data); -static void mount_removed_cb (GVolumeMonitor *monitor, - GMount *mount, - gpointer user_data); -static void mount_pre_removed_cb (GVolumeMonitor *monitor, - GMount *mount, - gpointer user_data); - -enum { - MOUNT_POINT_ADDED, - MOUNT_POINT_REMOVED, - LAST_SIGNAL -}; - -static guint signals[LAST_SIGNAL] = {0}; - -G_DEFINE_TYPE (TrackerStorage, tracker_storage, G_TYPE_OBJECT); - -static void -tracker_storage_class_init (TrackerStorageClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = tracker_storage_finalize; - - signals[MOUNT_POINT_ADDED] = - g_signal_new ("mount-point-added", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - NULL, - G_TYPE_NONE, - 5, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_BOOLEAN, - G_TYPE_BOOLEAN); - - signals[MOUNT_POINT_REMOVED] = - g_signal_new ("mount-point-removed", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - 0, - NULL, NULL, - NULL, - G_TYPE_NONE, - 2, - G_TYPE_STRING, - G_TYPE_STRING); - - g_type_class_add_private (object_class, sizeof (TrackerStoragePrivate)); -} - -static void -tracker_storage_init (TrackerStorage *storage) -{ - TrackerStoragePrivate *priv; - - g_message ("Initializing Storage..."); - - priv = TRACKER_STORAGE_GET_PRIVATE (storage); - - priv->mounts = g_node_new (NULL); - - priv->mounts_by_uuid = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, - NULL); - priv->unmount_watchdogs = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) g_source_remove); - - priv->volume_monitor = g_volume_monitor_get (); - - /* Volume and property notification callbacks */ - g_signal_connect_object (priv->volume_monitor, "mount-removed", - G_CALLBACK (mount_removed_cb), storage, 0); - g_signal_connect_object (priv->volume_monitor, "mount-pre-unmount", - G_CALLBACK (mount_pre_removed_cb), storage, 0); - g_signal_connect_object (priv->volume_monitor, "mount-added", - G_CALLBACK (mount_added_cb), storage, 0); - - g_message ("Mount monitors set up for to watch for added, removed and pre-unmounts..."); - - /* Get all mounts and set them up */ - if (!mounts_setup (storage)) { - return; - } -} - -static void -tracker_storage_finalize (GObject *object) -{ - TrackerStoragePrivate *priv; - - priv = TRACKER_STORAGE_GET_PRIVATE (object); - - g_hash_table_destroy (priv->unmount_watchdogs); - - if (priv->mounts_by_uuid) { - g_hash_table_unref (priv->mounts_by_uuid); - } - - if (priv->mounts) { - mount_node_free (priv->mounts); - } - - if (priv->volume_monitor) { - g_object_unref (priv->volume_monitor); - } - - (G_OBJECT_CLASS (tracker_storage_parent_class)->finalize) (object); -} - -static void -mount_node_free (GNode *node) -{ - g_node_traverse (node, - G_POST_ORDER, - G_TRAVERSE_ALL, - -1, - mount_info_free, - NULL); - - g_node_destroy (node); -} - -static gboolean -mount_node_traverse_func (GNode *node, - gpointer user_data) -{ - TraverseData *data; - MountInfo *info; - - if (!node->data) { - /* Root node */ - return FALSE; - } - - data = user_data; - info = node->data; - - if (g_str_has_prefix (data->path, info->mount_point)) { - data->node = node; - return TRUE; - } - - return FALSE; -} - -static GNode * -mount_node_find (GNode *root, - const gchar *path) -{ - TraverseData data = { path, NULL }; - - g_node_traverse (root, - G_POST_ORDER, - G_TRAVERSE_ALL, - -1, - mount_node_traverse_func, - &data); - - return data.node; -} - -static gboolean -mount_info_free (GNode *node, - gpointer user_data) -{ - MountInfo *info; - - info = node->data; - - if (info) { - g_free (info->mount_point); - g_free (info->uuid); - - g_slice_free (MountInfo, info); - } - - return FALSE; -} - -static MountInfo * -mount_info_find (GNode *root, - const gchar *path) -{ - GNode *node; - - node = mount_node_find (root, path); - return (node) ? node->data : NULL; -} - -static TrackerStorageType -mount_info_get_type (MountInfo *info) -{ - TrackerStorageType mount_type = 0; - - if (info->removable) { - mount_type |= TRACKER_STORAGE_REMOVABLE; - } - - if (info->optical) { - mount_type |= TRACKER_STORAGE_OPTICAL; - } - - return mount_type; -} - -static gchar * -mount_point_normalize (const gchar *mount_point) -{ - gchar *mp; - - /* Normalize all mount points to have a / at the end */ - if (g_str_has_suffix (mount_point, G_DIR_SEPARATOR_S)) { - mp = g_strdup (mount_point); - } else { - mp = g_strconcat (mount_point, G_DIR_SEPARATOR_S, NULL); - } - - return mp; -} - -static GNode * -mount_add_hierarchy (GNode *root, - const gchar *uuid, - const gchar *mount_point, - gboolean removable, - gboolean optical) -{ - MountInfo *info; - GNode *node; - gchar *mp; - - mp = mount_point_normalize (mount_point); - node = mount_node_find (root, mp); - - if (!node) { - node = root; - } - - info = g_slice_new (MountInfo); - info->mount_point = mp; - info->uuid = g_strdup (uuid); - info->removable = removable; - info->optical = optical; - - return g_node_append_data (node, info); -} - -static void -mount_add_new (TrackerStorage *storage, - const gchar *uuid, - const gchar *mount_point, - const gchar *mount_name, - gboolean removable_device, - gboolean optical_disc) -{ - TrackerStoragePrivate *priv; - GNode *node; - - priv = TRACKER_STORAGE_GET_PRIVATE (storage); - - node = mount_add_hierarchy (priv->mounts, uuid, mount_point, removable_device, optical_disc); - g_hash_table_insert (priv->mounts_by_uuid, g_strdup (uuid), node); - - g_signal_emit (storage, - signals[MOUNT_POINT_ADDED], - 0, - uuid, - mount_point, - mount_name, - removable_device, - optical_disc, - NULL); -} - -static gchar * -mount_guess_content_type (GMount *mount, - gboolean *is_optical, - gboolean *is_multimedia, - gboolean *is_blank) -{ - gchar *content_type = NULL; - gchar **guess_type; - - *is_optical = FALSE; - *is_multimedia = FALSE; - *is_blank = FALSE; - - /* This function has 2 purposes: - * - * 1. Detect if we are using optical media - * 2. Detect if we are video or music, we can't index those types - * - * We try to determine the content type because we don't want - * to store Volume information in Tracker about DVDs and media - * which has no real data for us to mine. - * - * Generally, if is_multimedia is TRUE then we end up ignoring - * the media. - */ - guess_type = g_mount_guess_content_type_sync (mount, TRUE, NULL, NULL); - - if (guess_type) { - gint i = 0; - - while (!content_type && guess_type[i]) { - if (!g_strcmp0 (guess_type[i], "x-content/image-picturecd")) { - /* Images */ - content_type = g_strdup (guess_type[i]); - } else if (!g_strcmp0 (guess_type[i], "x-content/video-bluray") || - !g_strcmp0 (guess_type[i], "x-content/video-dvd") || - !g_strcmp0 (guess_type[i], "x-content/video-hddvd") || - !g_strcmp0 (guess_type[i], "x-content/video-svcd") || - !g_strcmp0 (guess_type[i], "x-content/video-vcd")) { - /* Videos */ - *is_multimedia = TRUE; - content_type = g_strdup (guess_type[i]); - } else if (!g_strcmp0 (guess_type[i], "x-content/audio-cdda") || - !g_strcmp0 (guess_type[i], "x-content/audio-dvd") || - !g_strcmp0 (guess_type[i], "x-content/audio-player")) { - /* Audios */ - *is_multimedia = TRUE; - content_type = g_strdup (guess_type[i]); - } else if (!g_strcmp0 (guess_type[i], "x-content/blank-bd") || - !g_strcmp0 (guess_type[i], "x-content/blank-cd") || - !g_strcmp0 (guess_type[i], "x-content/blank-dvd") || - !g_strcmp0 (guess_type[i], "x-content/blank-hddvd")) { - /* Blank */ - *is_blank = TRUE; - content_type = g_strdup (guess_type[i]); - } else if (!g_strcmp0 (guess_type[i], "x-content/software") || - !g_strcmp0 (guess_type[i], "x-content/unix-software") || - !g_strcmp0 (guess_type[i], "x-content/win32-software")) { - /* NOTE: This one is a guess, can we - * have this content type on - * none-optical mount points? - */ - content_type = g_strdup (guess_type[i]); - } else { - /* else, keep on with the next guess, if any */ - i++; - } - } - - /* If we didn't have an exact match on possible guessed content types, - * then use the first one returned (best guess always first) if any */ - if (!content_type && guess_type[0]) { - content_type = g_strdup (guess_type[0]); - } - - g_strfreev (guess_type); - } - - if (content_type) { - if (strstr (content_type, "vcd") || - strstr (content_type, "cdda") || - strstr (content_type, "dvd") || - strstr (content_type, "bluray")) { - *is_optical = TRUE; - } - } else { - GUnixMountEntry *entry; - gchar *mount_path; - GFile *mount_root; - - /* No content type was guessed, try to find out - * at least whether it's an optical media or not - */ - mount_root = g_mount_get_root (mount); - mount_path = g_file_get_path (mount_root); - - /* FIXME: Try to assume we have a unix mount :( - * EEK, once in a while, I have to write crack, oh well - */ - if (mount_path && - (entry = g_unix_mount_at (mount_path, NULL)) != NULL) { - const gchar *filesystem_type; - gchar *device_path = NULL; - GVolume *volume; - - volume = g_mount_get_volume (mount); - filesystem_type = g_unix_mount_get_fs_type (entry); - g_debug (" Using filesystem type:'%s'", - filesystem_type); - - /* Volume may be NULL */ - if (volume) { - device_path = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE); - g_debug (" Using device path:'%s'", - device_path); - g_object_unref (volume); - } - - /* NOTE: This code was taken from guess_mount_type() - * in GIO's gunixmounts.c and adapted purely for - * guessing optical media. We don't use the guessing - * code for other types such as MEMSTICKS, ZIPs, - * IPODs, etc. - * - * This code may need updating over time since it is - * very situational depending on how distributions - * mount their devices and how devices are named in - * /dev. - */ - if (strcmp (filesystem_type, "udf") == 0 || - strcmp (filesystem_type, "iso9660") == 0 || - strcmp (filesystem_type, "cd9660") == 0 || - (device_path && - (g_str_has_prefix (device_path, "/dev/cdrom") || - g_str_has_prefix (device_path, "/dev/acd") || - g_str_has_prefix (device_path, "/dev/cd")))) { - *is_optical = TRUE; - } else if (device_path && - g_str_has_prefix (device_path, "/vol/")) { - const gchar *name; - - name = mount_path + strlen ("/"); - - if (g_str_has_prefix (name, "cdrom")) { - *is_optical = TRUE; - } - } else { - gchar *basename = g_path_get_basename (mount_path); - - if (g_str_has_prefix (basename, "cdr") || - g_str_has_prefix (basename, "cdwriter") || - g_str_has_prefix (basename, "burn") || - g_str_has_prefix (basename, "dvdr")) { - *is_optical = TRUE; - } - - g_free (basename); - } - - g_free (device_path); - g_free (mount_path); - g_unix_mount_free (entry); - } else { - g_debug (" No GUnixMountEntry found, needed for detecting if optical media... :("); - g_free (mount_path); - } - - g_object_unref (mount_root); - } - - return content_type; -} - -static void -mount_add (TrackerStorage *storage, - GMount *mount) -{ - TrackerStoragePrivate *priv; - GFile *root; - GVolume *volume; - gchar *mount_name, *mount_path, *uuid; - gboolean is_optical = FALSE; - gboolean is_removable = FALSE; - - /* Get mount name */ - mount_name = g_mount_get_name (mount); - - /* Get root path of the mount */ - root = g_mount_get_root (mount); - mount_path = g_file_get_path (root); - - g_debug ("Found '%s' mounted on path '%s'", - mount_name, - mount_path); - - /* Do not process shadowed mounts! */ - if (g_mount_is_shadowed (mount)) { - g_debug (" Skipping shadowed mount '%s'", mount_name); - g_object_unref (root); - g_free (mount_path); - g_free (mount_name); - return; - } - - priv = TRACKER_STORAGE_GET_PRIVATE (storage); - - /* fstab partitions may not have corresponding - * GVolumes, so volume may be NULL */ - volume = g_mount_get_volume (mount); - if (volume) { - /* GMount with GVolume */ - - /* Try to get UUID from the Volume. - * Note that g_volume_get_uuid() is NOT equivalent */ - uuid = g_volume_get_identifier (volume, - G_VOLUME_IDENTIFIER_KIND_UUID); - if (!uuid) { - gchar *content_type; - gboolean is_multimedia; - gboolean is_blank; - - /* Optical discs usually won't have UUID in the GVolume */ - content_type = mount_guess_content_type (mount, &is_optical, &is_multimedia, &is_blank); - is_removable = TRUE; - - /* We don't index content which is video, music or blank */ - if (!is_multimedia && !is_blank) { - uuid = g_compute_checksum_for_string (G_CHECKSUM_MD5, - mount_name, - -1); - g_debug (" No UUID, generated:'%s' (based on mount name)", uuid); - g_debug (" Assuming GVolume has removable media, if wrong report a bug! " - "content type is '%s'", - content_type); - } else { - g_debug (" Being ignored because mount with volume is music/video/blank " - "(content type:%s, optical:%s, multimedia:%s, blank:%s)", - content_type, - is_optical ? "yes" : "no", - is_multimedia ? "yes" : "no", - is_blank ? "yes" : "no"); - } - - g_free (content_type); - } else { - /* Any other removable media will have UUID in the - * GVolume. Note that this also may include some - * partitions in the machine which have GVolumes - * associated to the GMounts. We also check a drive - * exists to be sure the device is local. */ - GDrive *drive; - - drive = g_volume_get_drive (volume); - - if (drive) { - /* We can't mount/unmount system volumes, so tag - * them as non removable. */ - is_removable = g_volume_can_mount (volume); - g_debug (" Found mount with volume and drive which %s be mounted: " - "Assuming it's %s removable, if wrong report a bug!", - is_removable ? "can" : "cannot", - is_removable ? "" : "not"); - g_object_unref (drive); - } else { - /* Note: not sure when this can happen... */ - g_debug (" Mount with volume but no drive, " - "assuming not a removable device, " - "if wrong report a bug!"); - is_removable = FALSE; - } - } - - g_object_unref (volume); - } else { - /* GMount without GVolume. - * Note: Never found a case where this g_mount_get_uuid() returns - * non-NULL... :-) */ - uuid = g_mount_get_uuid (mount); - if (!uuid) { - if (mount_path) { - gchar *content_type; - gboolean is_multimedia; - gboolean is_blank; - - content_type = mount_guess_content_type (mount, &is_optical, &is_multimedia, &is_blank); - - /* Note: for GMounts without GVolume, is_blank should NOT be considered, - * as it may give unwanted results... */ - if (!is_multimedia) { - uuid = g_compute_checksum_for_string (G_CHECKSUM_MD5, - mount_path, - -1); - g_debug (" No UUID, generated:'%s' (based on mount path)", uuid); - } else { - g_debug (" Being ignored because mount is music/video " - "(content type:%s, optical:%s, multimedia:%s)", - content_type, - is_optical ? "yes" : "no", - is_multimedia ? "yes" : "no"); - } - - g_free (content_type); - } else { - g_debug (" Being ignored because mount has no GVolume (i.e. not user mountable) " - "and has no mount root path available"); - } - } - } - - /* If we got something to be used as UUID, then add the mount - * to the TrackerStorage */ - if (uuid && mount_path && !g_hash_table_lookup (priv->mounts_by_uuid, uuid)) { - g_debug (" Adding mount point with UUID: '%s', removable: %s, optical: %s, path: '%s'", - uuid, - is_removable ? "yes" : "no", - is_optical ? "yes" : "no", - mount_path); - mount_add_new (storage, uuid, mount_path, mount_name, is_removable, is_optical); - } else { - g_debug (" Skipping mount point with UUID: '%s', path: '%s', already managed: '%s'", - uuid ? uuid : "none", - mount_path ? mount_path : "none", - (uuid && g_hash_table_lookup (priv->mounts_by_uuid, uuid)) ? "yes" : "no"); - } - - g_free (mount_name); - g_free (mount_path); - g_free (uuid); - g_object_unref (root); -} - -static gboolean -mounts_setup (TrackerStorage *storage) -{ - TrackerStoragePrivate *priv; - GList *mounts, *lm; - - priv = TRACKER_STORAGE_GET_PRIVATE (storage); - - mounts = g_volume_monitor_get_mounts (priv->volume_monitor); - - if (!mounts) { - g_message ("No mounts found to iterate"); - return TRUE; - } - - /* Iterate over all available mounts and add them. - * Note that GVolumeMonitor shows only those mounts which are - * actually mounted. */ - for (lm = mounts; lm; lm = g_list_next (lm)) { - mount_add (storage, lm->data); - g_object_unref (lm->data); - } - - g_list_free (mounts); - - return TRUE; -} - -static void -mount_added_cb (GVolumeMonitor *monitor, - GMount *mount, - gpointer user_data) -{ - mount_add (user_data, mount); -} - -static void -mount_remove (TrackerStorage *storage, - GMount *mount) -{ - TrackerStoragePrivate *priv; - MountInfo *info; - GNode *node; - GFile *file; - gchar *name; - gchar *mount_point; - gchar *mp; - - priv = TRACKER_STORAGE_GET_PRIVATE (storage); - - file = g_mount_get_root (mount); - mount_point = g_file_get_path (file); - name = g_mount_get_name (mount); - - mp = mount_point_normalize (mount_point); - node = mount_node_find (priv->mounts, mp); - g_free (mp); - - if (node) { - info = node->data; - - g_message ("Mount:'%s' with UUID:'%s' now unmounted from:'%s'", - name, - info->uuid, - mount_point); - - g_signal_emit (storage, signals[MOUNT_POINT_REMOVED], 0, info->uuid, mount_point, NULL); - - g_hash_table_remove (priv->mounts_by_uuid, info->uuid); - mount_node_free (node); - } else { - g_message ("Mount:'%s' now unmounted from:'%s' (was not tracked)", - name, - mount_point); - } - - g_free (name); - g_free (mount_point); - g_object_unref (file); -} - -static void -mount_removed_cb (GVolumeMonitor *monitor, - GMount *mount, - gpointer user_data) -{ - TrackerStorage *storage; - TrackerStoragePrivate *priv; - - storage = user_data; - priv = TRACKER_STORAGE_GET_PRIVATE (storage); - - mount_remove (storage, mount); - - /* Unmount suceeded, remove the pending check */ - g_hash_table_remove (priv->unmount_watchdogs, mount); -} - -static gboolean -unmount_failed_cb (gpointer user_data) -{ - UnmountCheckData *data = user_data; - TrackerStoragePrivate *priv; - - /* If this timeout gets to be executed, this is due - * to a pre-unmount signal with no corresponding - * unmount in a timely fashion, we assume this is - * due to an error, and add back the still mounted - * path. - */ - priv = TRACKER_STORAGE_GET_PRIVATE (data->storage); - - g_warning ("Unmount operation failed, adding back mount point..."); - - mount_add (data->storage, data->mount); - - g_hash_table_remove (priv->unmount_watchdogs, data->mount); - return FALSE; -} - -static void -mount_pre_removed_cb (GVolumeMonitor *monitor, - GMount *mount, - gpointer user_data) -{ - TrackerStorage *storage; - TrackerStoragePrivate *priv; - UnmountCheckData *data; - guint id; - - storage = user_data; - priv = TRACKER_STORAGE_GET_PRIVATE (storage); - - mount_remove (storage, mount); - - /* Add check for failed unmounts */ - data = g_new (UnmountCheckData, 1); - data->storage = storage; - data->mount = mount; - - id = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT_IDLE + 10, 3, - unmount_failed_cb, - data, (GDestroyNotify) g_free); - g_hash_table_insert (priv->unmount_watchdogs, data->mount, - GUINT_TO_POINTER (id)); -} - -/** - * tracker_storage_new: - * - * Creates a new instance of #TrackerStorage. - * - * Returns: The newly created #TrackerStorage. - * - * Since: 0.8 - **/ -TrackerStorage * -tracker_storage_new (void) -{ - return g_object_new (TRACKER_TYPE_STORAGE, NULL); -} - -static void -get_mount_point_by_uuid_foreach (gpointer key, - gpointer value, - gpointer user_data) -{ - GetRoots *gr; - GNode *node; - MountInfo *info; - TrackerStorageType mount_type; - - gr = user_data; - node = value; - info = node->data; - mount_type = mount_info_get_type (info); - - /* is mount of the type we're looking for? */ - if ((gr->exact_match && mount_type == gr->type) || - (!gr->exact_match && (mount_type & gr->type))) { - gchar *normalized_mount_point; - gint len; - - normalized_mount_point = g_strdup (info->mount_point); - len = strlen (normalized_mount_point); - - /* Don't include trailing slashes */ - if (len > 2 && normalized_mount_point[len - 1] == G_DIR_SEPARATOR) { - normalized_mount_point[len - 1] = '\0'; - } - - gr->roots = g_slist_prepend (gr->roots, normalized_mount_point); - } -} - -/** - * tracker_storage_get_device_roots: - * @storage: A #TrackerStorage - * @type: A #TrackerStorageType - * @exact_match: if all devices should exactly match the types - * - * Returns: (transfer full) (element-type utf8): a #GSList of strings - * containing the root directories for devices with @type based on - * @exact_match. Each element must be freed using g_free() and the - * list itself through g_slist_free(). - * - * Since: 0.8 - **/ -GSList * -tracker_storage_get_device_roots (TrackerStorage *storage, - TrackerStorageType type, - gboolean exact_match) -{ - TrackerStoragePrivate *priv; - GetRoots gr; - - g_return_val_if_fail (TRACKER_IS_STORAGE (storage), NULL); - - priv = TRACKER_STORAGE_GET_PRIVATE (storage); - - gr.roots = NULL; - gr.type = type; - gr.exact_match = exact_match; - - g_hash_table_foreach (priv->mounts_by_uuid, - get_mount_point_by_uuid_foreach, - &gr); - - return gr.roots; -} - -/** - * tracker_storage_get_device_uuids: - * @storage: A #TrackerStorage - * @type: A #TrackerStorageType - * @exact_match: if all devices should exactly match the types - * - * Returns: (transfer full) (element-type utf8): a #GSList of - * strings containing the UUID for devices with @type based - * on @exact_match. Each element must be freed using g_free() - * and the list itself through g_slist_free(). - * - * Since: 0.8 - **/ -GSList * -tracker_storage_get_device_uuids (TrackerStorage *storage, - TrackerStorageType type, - gboolean exact_match) -{ - TrackerStoragePrivate *priv; - GHashTableIter iter; - gpointer key, value; - GSList *uuids; - - g_return_val_if_fail (TRACKER_IS_STORAGE (storage), NULL); - - priv = TRACKER_STORAGE_GET_PRIVATE (storage); - - uuids = NULL; - - g_hash_table_iter_init (&iter, priv->mounts_by_uuid); - - while (g_hash_table_iter_next (&iter, &key, &value)) { - const gchar *uuid; - GNode *node; - MountInfo *info; - TrackerStorageType mount_type; - - uuid = key; - node = value; - info = node->data; - - mount_type = mount_info_get_type (info); - - /* is mount of the type we're looking for? */ - if ((exact_match && mount_type == type) || - (!exact_match && (mount_type & type))) { - uuids = g_slist_prepend (uuids, g_strdup (uuid)); - } - } - - return uuids; -} - -/** - * tracker_storage_get_mount_point_for_uuid: - * @storage: A #TrackerStorage - * @uuid: A string pointer to the UUID for the %GVolume. - * - * Returns: The mount point for @uuid, this should not be freed. - * - * Since: 0.8 - **/ -const gchar * -tracker_storage_get_mount_point_for_uuid (TrackerStorage *storage, - const gchar *uuid) -{ - TrackerStoragePrivate *priv; - GNode *node; - MountInfo *info; - - g_return_val_if_fail (TRACKER_IS_STORAGE (storage), NULL); - g_return_val_if_fail (uuid != NULL, NULL); - - priv = TRACKER_STORAGE_GET_PRIVATE (storage); - - node = g_hash_table_lookup (priv->mounts_by_uuid, uuid); - - if (!node) { - return NULL; - } - - info = node->data; - - return info->mount_point; -} - -/** - * tracker_storage_get_type_for_uuid: - * @storage: A #TrackerStorage - * @uuid: A string pointer to the UUID for the %GVolume. - * - * Returns: The type flags for @uuid. - * - * Since: 0.10 - **/ -TrackerStorageType -tracker_storage_get_type_for_uuid (TrackerStorage *storage, - const gchar *uuid) -{ - TrackerStoragePrivate *priv; - GNode *node; - TrackerStorageType type = 0; - - g_return_val_if_fail (TRACKER_IS_STORAGE (storage), 0); - g_return_val_if_fail (uuid != NULL, 0); - - priv = TRACKER_STORAGE_GET_PRIVATE (storage); - - node = g_hash_table_lookup (priv->mounts_by_uuid, uuid); - - if (node) { - MountInfo *info; - - info = node->data; - - if (info->removable) { - type |= TRACKER_STORAGE_REMOVABLE; - } - if (info->optical) { - type |= TRACKER_STORAGE_OPTICAL; - } - } - - return type; -} - -/** - * tracker_storage_get_uuid_for_file: - * @storage: A #TrackerStorage - * @file: a file - * - * Returns the UUID of the removable device for @file - * - * Returns: Returns the UUID of the removable device for @file, this - * should not be freed. - * - * Since: 0.8 - **/ -const gchar * -tracker_storage_get_uuid_for_file (TrackerStorage *storage, - GFile *file) -{ - TrackerStoragePrivate *priv; - gchar *path; - MountInfo *info; - - g_return_val_if_fail (TRACKER_IS_STORAGE (storage), FALSE); - - path = g_file_get_path (file); - - if (!path) { - return NULL; - } - - /* Normalize all paths to have a / at the end */ - if (!g_str_has_suffix (path, G_DIR_SEPARATOR_S)) { - gchar *norm_path; - - norm_path = g_strconcat (path, G_DIR_SEPARATOR_S, NULL); - g_free (path); - path = norm_path; - } - - priv = TRACKER_STORAGE_GET_PRIVATE (storage); - - info = mount_info_find (priv->mounts, path); - - if (!info) { - g_free (path); - return NULL; - } - - /* g_debug ("Mount for path '%s' is '%s' (UUID:'%s')", */ - /* path, info->mount_point, info->uuid); */ - - g_free (path); - - return info->uuid; -} - diff --git a/src/miners/fs/tracker-storage.h b/src/miners/fs/tracker-storage.h deleted file mode 100644 index f3101c08e..000000000 --- a/src/miners/fs/tracker-storage.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __LIBTRACKER_MINER_STORAGE_H__ -#define __LIBTRACKER_MINER_STORAGE_H__ - -#if !defined (__LIBTRACKER_MINER_H_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "Only <libtracker-miner/tracker-miner.h> can be included directly." -#endif - -#include <glib-object.h> -#include <gio/gio.h> - -G_BEGIN_DECLS - -/** - * TrackerStorageType: - * @TRACKER_STORAGE_REMOVABLE: Storage is a removable media - * @TRACKER_STORAGE_OPTICAL: Storage is an optical disc - * - * Flags specifying properties of the type of storage. - * - * Since: 0.8 - */ -typedef enum { - TRACKER_STORAGE_REMOVABLE = 1 << 0, - TRACKER_STORAGE_OPTICAL = 1 << 1 -} TrackerStorageType; - -/** - * TRACKER_STORAGE_TYPE_IS_REMOVABLE: - * @type: Mask of TrackerStorageType flags - * - * Check if the given storage type is marked as being removable media. - * - * Returns: %TRUE if the storage is marked as removable media, %FALSE otherwise - * - * Since: 0.10 - */ -#define TRACKER_STORAGE_TYPE_IS_REMOVABLE(type) ((type & TRACKER_STORAGE_REMOVABLE) ? TRUE : FALSE) - -/** - * TRACKER_STORAGE_TYPE_IS_OPTICAL: - * @type: Mask of TrackerStorageType flags - * - * Check if the given storage type is marked as being optical disc - * - * Returns: %TRUE if the storage is marked as optical disc, %FALSE otherwise - * - * Since: 0.10 - */ -#define TRACKER_STORAGE_TYPE_IS_OPTICAL(type) ((type & TRACKER_STORAGE_OPTICAL) ? TRUE : FALSE) - - -#define TRACKER_TYPE_STORAGE (tracker_storage_get_type ()) -#define TRACKER_STORAGE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_STORAGE, TrackerStorage)) -#define TRACKER_STORAGE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TRACKER_TYPE_STORAGE, TrackerStorageClass)) -#define TRACKER_IS_STORAGE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_STORAGE)) -#define TRACKER_IS_STORAGE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TRACKER_TYPE_STORAGE)) -#define TRACKER_STORAGE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_STORAGE, TrackerStorageClass)) - -typedef struct _TrackerStorage TrackerStorage; -typedef struct _TrackerStorageClass TrackerStorageClass; - -/** - * TrackerStorage: - * @parent: parent object - * - * A storage API for using mount points and devices - **/ -struct _TrackerStorage { - GObject parent; -}; - -/** - * TrackerStorageClass: - * @parent_class: parent object class - * - * A storage class for #TrackerStorage. - **/ -struct _TrackerStorageClass { - GObjectClass parent_class; -}; - -GType tracker_storage_get_type (void) G_GNUC_CONST; -TrackerStorage * tracker_storage_new (void); -GSList * tracker_storage_get_device_roots (TrackerStorage *storage, - TrackerStorageType type, - gboolean exact_match); -GSList * tracker_storage_get_device_uuids (TrackerStorage *storage, - TrackerStorageType type, - gboolean exact_match); -const gchar * tracker_storage_get_mount_point_for_uuid (TrackerStorage *storage, - const gchar *uuid); -TrackerStorageType tracker_storage_get_type_for_uuid (TrackerStorage *storage, - const gchar *uuid); -const gchar * tracker_storage_get_uuid_for_file (TrackerStorage *storage, - GFile *file); - -G_END_DECLS - -#endif /* __LIBTRACKER_MINER_STORAGE_H__ */ diff --git a/src/miners/fs/tracker-thumbnailer.c b/src/miners/fs/tracker-thumbnailer.c deleted file mode 100644 index 6b678a43e..000000000 --- a/src/miners/fs/tracker-thumbnailer.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include "config.h" - -#include <string.h> - -#include <libtracker-common/tracker-dbus.h> - -#include "tracker-thumbnailer.h" - -/** - * SECTION:tracker-thumbnailer - * @short_description: Request the thumbnailer service creates or - * updates thumbnails. - * @include: libtracker-miner/tracker-miner.h - * - * This is a convenience API using D-Bus for creating and updating - * thumbnails for files being mined. It is also used to create - * thumbnails for album art found embedded in some medias. - * - * This follows the thumbnailer specification: - * http://live.gnome.org/ThumbnailerSpec - **/ - -#define THUMBCACHE_SERVICE "org.freedesktop.thumbnails.Cache1" -#define THUMBCACHE_PATH "/org/freedesktop/thumbnails/Cache1" -#define THUMBCACHE_INTERFACE "org.freedesktop.thumbnails.Cache1" - -#define THUMBMAN_SERVICE "org.freedesktop.thumbnails.Thumbnailer1" -#define THUMBMAN_PATH "/org/freedesktop/thumbnails/Thumbnailer1" -#define THUMBMAN_INTERFACE "org.freedesktop.thumbnails.Thumbnailer1" - -typedef struct { - GDBusProxy *cache_proxy; - GDBusProxy *manager_proxy; - GDBusConnection *connection; - - GStrv supported_mime_types; - - GSList *removes; - GSList *moves_to; - GSList *moves_from; - - guint request_id; - gboolean service_is_available; -} TrackerThumbnailerPrivate; - -static void tracker_thumbnailer_initable_iface_init (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (TrackerThumbnailer, tracker_thumbnailer, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - tracker_thumbnailer_initable_iface_init) - G_ADD_PRIVATE (TrackerThumbnailer)) - -static void -tracker_thumbnailer_finalize (GObject *object) -{ - TrackerThumbnailerPrivate *private; - TrackerThumbnailer *thumbnailer; - - thumbnailer = TRACKER_THUMBNAILER (object); - private = tracker_thumbnailer_get_instance_private (thumbnailer); - - if (private->cache_proxy) { - g_object_unref (private->cache_proxy); - } - - if (private->manager_proxy) { - g_object_unref (private->manager_proxy); - } - - if (private->connection) { - g_object_unref (private->connection); - } - - g_strfreev (private->supported_mime_types); - - g_slist_foreach (private->removes, (GFunc) g_free, NULL); - g_slist_free (private->removes); - - g_slist_foreach (private->moves_to, (GFunc) g_free, NULL); - g_slist_free (private->moves_to); - - g_slist_foreach (private->moves_from, (GFunc) g_free, NULL); - g_slist_free (private->moves_from); - - G_OBJECT_CLASS (tracker_thumbnailer_parent_class)->finalize (object); -} - -inline static gboolean -should_be_thumbnailed (GStrv list, - const gchar *mime) -{ - gboolean should_thumbnail; - guint i; - - if (!list) { - return TRUE; - } - - for (should_thumbnail = FALSE, i = 0; - should_thumbnail == FALSE && list[i] != NULL; - i++) { - if (g_ascii_strcasecmp (list[i], mime) == 0) { - should_thumbnail = TRUE; - } - } - - return should_thumbnail; -} - -static gboolean -tracker_thumbnailer_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - TrackerThumbnailerPrivate *private; - TrackerThumbnailer *thumbnailer; - GVariant *v; - - thumbnailer = TRACKER_THUMBNAILER (initable); - private = tracker_thumbnailer_get_instance_private (thumbnailer); - - /* Don't start at 0, start at 1. */ - private->request_id = 1; - private->service_is_available = FALSE; - - g_message ("Thumbnailer connections being set up... (using same bus as Tracker, i.e. session or system)"); - - private->connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, error); - - if (!private->connection) - return FALSE; - - private->cache_proxy = g_dbus_proxy_new_sync (private->connection, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, - NULL, - THUMBCACHE_SERVICE, - THUMBCACHE_PATH, - THUMBCACHE_INTERFACE, - NULL, - error); - if (!private->cache_proxy) { - g_clear_object (&private->connection); - return FALSE; - } - - private->manager_proxy = g_dbus_proxy_new_sync (private->connection, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES, - NULL, - THUMBMAN_SERVICE, - THUMBMAN_PATH, - THUMBMAN_INTERFACE, - NULL, - error); - - if (!private->manager_proxy) { - g_clear_object (&private->connection); - g_clear_object (&private->cache_proxy); - return FALSE; - } - - v = g_dbus_proxy_call_sync (private->manager_proxy, - "GetSupported", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - error); - - if (!v) { - g_clear_object (&private->connection); - g_clear_object (&private->cache_proxy); - g_clear_object (&private->manager_proxy); - return FALSE; - } else { - GStrv mime_types = NULL; - GStrv uri_schemes = NULL; - - g_variant_get (v, "(^a&s^a&s)", &uri_schemes, &mime_types); - - if (mime_types) { - GHashTable *hash; - GHashTableIter iter; - gpointer key, value; - guint i; - - /* The table that you receive may contain duplicate mime-types, because - * they are grouped against the uri_schemes table */ - - hash = g_hash_table_new (g_str_hash, g_str_equal); - - for (i = 0; mime_types[i] != NULL; i++) { - g_hash_table_insert (hash, mime_types[i], NULL); - } - - i = g_hash_table_size (hash); - g_message ("Thumbnailer supports %d mime types", i); - - g_hash_table_iter_init (&iter, hash); - private->supported_mime_types = (GStrv) g_new0 (gchar *, i + 1); - - i = 0; - while (g_hash_table_iter_next (&iter, &key, &value)) { - private->supported_mime_types[i] = g_strdup (key); - g_debug (" %s", (gchar *) key); - i++; - } - - g_hash_table_unref (hash); - - private->service_is_available = TRUE; - } - - g_free (mime_types); - g_free (uri_schemes); - - g_variant_unref (v); - } - - return TRUE; -} - -static void -tracker_thumbnailer_initable_iface_init (GInitableIface *iface) -{ - iface->init = tracker_thumbnailer_initable_init; -} - -static void -tracker_thumbnailer_class_init (TrackerThumbnailerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = tracker_thumbnailer_finalize; -} - -static void -tracker_thumbnailer_init (TrackerThumbnailer *thumbnailer) -{ -} - -/** - * tracker_thumbnailer_new: - * - * Creates a new #TrackerThumbnailer object that can be used to signal - * the system's thumbnailing daemon(s) via D-Bus to add or remove - * content that needs thumbnailing. - * - * For example, when mounting a USB thumb drive, content may not have - * thumbnails and this object allows the content of that thumb drive - * to be queued for processing. - * - * Returns: %TRUE if successfully stored to be reported, %FALSE otherwise. - * - * Since: 0.18. - */ -TrackerThumbnailer * -tracker_thumbnailer_new (void) -{ - return g_initable_new (TRACKER_TYPE_THUMBNAILER, NULL, NULL, NULL); -} - -/** - * tracker_thumbnailer_move_add: - * @thumbnailer: Thumbnailer object - * @from_uri: URI of the file before the move - * @mime_type: mime-type of the file - * @to_uri: URI of the file after the move - * - * Adds a new request to tell the thumbnailer that @from_uri was moved to - * @to_uri. Stored requests can be sent with tracker_thumbnailer_send(). - * - * Returns: #TRUE if successfully stored to be reported, #FALSE otherwise. - * - * Since: 0.8 - */ -gboolean -tracker_thumbnailer_move_add (TrackerThumbnailer *thumbnailer, - const gchar *from_uri, - const gchar *mime_type, - const gchar *to_uri) -{ - TrackerThumbnailerPrivate *private; - - /* mime_type can be NULL */ - g_return_val_if_fail (TRACKER_IS_THUMBNAILER (thumbnailer), FALSE); - g_return_val_if_fail (from_uri != NULL, FALSE); - g_return_val_if_fail (to_uri != NULL, FALSE); - - private = tracker_thumbnailer_get_instance_private (thumbnailer); - - if (!private->service_is_available) { - g_debug ("%s: Not thumbnailing ‘%s’ as service is unavailable.", - G_STRFUNC, from_uri); - return FALSE; - } - - if (mime_type && !should_be_thumbnailed (private->supported_mime_types, mime_type)) { - g_debug ("%s: Not thumbnailing ‘%s’ as MIME type ‘%s’ should " - "not be thumbnailed.", G_STRFUNC, from_uri, mime_type); - return FALSE; - } - - private->moves_from = g_slist_prepend (private->moves_from, g_strdup (from_uri)); - private->moves_to = g_slist_prepend (private->moves_to, g_strdup (to_uri)); - - g_debug ("Thumbnailer request to move uri from:'%s' to:'%s' queued", - from_uri, - to_uri); - - return TRUE; -} - -/** - * tracker_thumbnailer_remove_add: - * @thumbnailer: Thumbnailer object - * @uri: URI of the file - * @mime_type: mime-type of the file - * - * Adds a new request to tell the thumbnailer that @uri was removed. - * Stored requests can be sent with tracker_thumbnailer_send(). - * - * Returns: #TRUE if successfully stored to be reported, #FALSE otherwise. - * - * Since: 0.8 - */ -gboolean -tracker_thumbnailer_remove_add (TrackerThumbnailer *thumbnailer, - const gchar *uri, - const gchar *mime_type) -{ - TrackerThumbnailerPrivate *private; - - g_return_val_if_fail (TRACKER_IS_THUMBNAILER (thumbnailer), FALSE); - /* mime_type can be NULL */ - g_return_val_if_fail (uri != NULL, FALSE); - - private = tracker_thumbnailer_get_instance_private (thumbnailer); - - if (!private->service_is_available) { - g_debug ("%s: Not thumbnailing ‘%s’ as service is unavailable.", - G_STRFUNC, uri); - return FALSE; - } - - if (mime_type && !should_be_thumbnailed (private->supported_mime_types, mime_type)) { - g_debug ("%s: Not thumbnailing ‘%s’ as MIME type ‘%s’ should " - "not be thumbnailed.", G_STRFUNC, uri, mime_type); - return FALSE; - } - - private->removes = g_slist_prepend (private->removes, g_strdup (uri)); - - g_debug ("Thumbnailer request to remove uri:'%s', appended to queue", uri); - - return TRUE; -} - -/** - * tracker_thumbnailer_cleanup: - * @thumbnailer: Thumbnailer object - * @uri_prefix: URI prefix - * - * Tells thumbnailer to cleanup all thumbnails under @uri_prefix. - * - * Returns: #TRUE if successfully reported, #FALSE otherwise. - * - * Since: 0.8 - */ -gboolean -tracker_thumbnailer_cleanup (TrackerThumbnailer *thumbnailer, - const gchar *uri_prefix) -{ - TrackerThumbnailerPrivate *private; - - g_return_val_if_fail (TRACKER_IS_THUMBNAILER (thumbnailer), FALSE); - g_return_val_if_fail (uri_prefix != NULL, FALSE); - - private = tracker_thumbnailer_get_instance_private (thumbnailer); - - if (!private->service_is_available) { - return FALSE; - } - - private->request_id++; - - g_debug ("Thumbnailer cleaning up uri:'%s', request_id:%d...", - uri_prefix, - private->request_id); - - g_dbus_proxy_call (private->cache_proxy, - "Cleanup", - g_variant_new ("(s)", uri_prefix), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - NULL, - NULL); - - return TRUE; -} - -/** - * tracker_thumbnailer_send: - * @thumbnailer: Thumbnailer object - * - * Sends to the thumbnailer all stored requests. - * - * Since: 0.8 - */ -void -tracker_thumbnailer_send (TrackerThumbnailer *thumbnailer) -{ - TrackerThumbnailerPrivate *private; - guint list_len; - - g_return_if_fail (TRACKER_IS_THUMBNAILER (thumbnailer)); - - private = tracker_thumbnailer_get_instance_private (thumbnailer); - - if (!private->service_is_available) { - return; - } - - list_len = g_slist_length (private->removes); - - if (list_len > 0) { - GStrv uri_strv; - - uri_strv = tracker_dbus_slist_to_strv (private->removes); - - g_dbus_proxy_call (private->cache_proxy, - "Delete", - g_variant_new ("(^as)", uri_strv), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - NULL, - NULL); - - g_message ("Thumbnailer removes queue sent with %d items to thumbnailer daemon, request ID:%d...", - list_len, - private->request_id++); - - /* Clean up newly created GStrv */ - g_strfreev (uri_strv); - - /* Clean up privately held data */ - g_slist_foreach (private->removes, (GFunc) g_free, NULL); - g_slist_free (private->removes); - private->removes = NULL; - } - - list_len = g_slist_length (private->moves_from); - - if (list_len > 0) { - GStrv from_strv, to_strv; - - g_assert (list_len == g_slist_length (private->moves_to)); - - from_strv = tracker_dbus_slist_to_strv (private->moves_from); - to_strv = tracker_dbus_slist_to_strv (private->moves_to); - - g_dbus_proxy_call (private->cache_proxy, - "Move", - g_variant_new ("(^as^as)", from_strv, to_strv), - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, - NULL, - NULL); - - g_message ("Thumbnailer moves queue sent with %d items to thumbnailer daemon, request ID:%d...", - list_len, - private->request_id++); - - /* Clean up newly created GStrv */ - g_strfreev (from_strv); - g_strfreev (to_strv); - - /* Clean up privately held data */ - g_slist_foreach (private->moves_from, (GFunc) g_free, NULL); - g_slist_free (private->moves_from); - private->moves_from = NULL; - - g_slist_foreach (private->moves_to, (GFunc) g_free, NULL); - g_slist_free (private->moves_to); - private->moves_to = NULL; - } -} diff --git a/src/miners/fs/tracker-thumbnailer.h b/src/miners/fs/tracker-thumbnailer.h deleted file mode 100644 index b53dc2893..000000000 --- a/src/miners/fs/tracker-thumbnailer.h +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#ifndef __LIBTRACKER_MINER_THUMBNAILER_H__ -#define __LIBTRACKER_MINER_THUMBNAILER_H__ - -#if !defined (__LIBTRACKER_MINER_H_INSIDE__) && !defined (TRACKER_COMPILATION) -#error "Only <libtracker-miner/tracker-miner.h> can be included directly." -#endif - -#include <glib-object.h> - -G_BEGIN_DECLS - -#define TRACKER_TYPE_THUMBNAILER (tracker_thumbnailer_get_type()) -#define TRACKER_THUMBNAILER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_THUMBNAILER, TrackerThumbnailer)) -#define TRACKER_THUMBNAILER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_THUMBNAILER, TrackerThumbnailerClass)) -#define TRACKER_IS_THUMBNAILER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_THUMBNAILER)) -#define TRACKER_IS_THUMBNAILER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_THUMBNAILER)) -#define TRACKER_THUMBNAILER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_THUMBNAILER, TrackerThumbnailerClass)) - -typedef struct _TrackerThumbnailer TrackerThumbnailer; -typedef struct _TrackerThumbnailerClass TrackerThumbnailerClass; - -/** - * TrackerThumbnailer: - * @parent: parent object - * - * A class implementation for managing thumbnails when mining content. - **/ -struct _TrackerThumbnailer { - GObject parent; -}; - -/** - * TrackerThumbnailerClass: - * @parent: parent object class - * - * Prototype for the class. - **/ -struct _TrackerThumbnailerClass { - GObjectClass parent; -}; - - -GType tracker_thumbnailer_get_type (void) G_GNUC_CONST; -TrackerThumbnailer * - tracker_thumbnailer_new (void); - -void tracker_thumbnailer_send (TrackerThumbnailer *thumbnailer); -gboolean tracker_thumbnailer_move_add (TrackerThumbnailer *thumbnailer, - const gchar *from_uri, - const gchar *mime_type, - const gchar *to_uri); -gboolean tracker_thumbnailer_remove_add (TrackerThumbnailer *thumbnailer, - const gchar *uri, - const gchar *mime_type); -gboolean tracker_thumbnailer_cleanup (TrackerThumbnailer *thumbnailer, - const gchar *uri_prefix); - -G_END_DECLS - -#endif /* __LIBTRACKER_MINER_THUMBNAILER_H__ */ diff --git a/src/miners/fs/tracker-writeback-dispatcher.c b/src/miners/fs/tracker-writeback-dispatcher.c deleted file mode 100644 index 980ccceb6..000000000 --- a/src/miners/fs/tracker-writeback-dispatcher.c +++ /dev/null @@ -1,400 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <libtracker-common/tracker-dbus.h> -#include <libtracker-sparql/tracker-sparql.h> - -#include "tracker-writeback-dispatcher.h" -#include "tracker-miner-files.h" - -#define TRACKER_WRITEBACK_SERVICE "org.freedesktop.Tracker1.Writeback" -#define TRACKER_WRITEBACK_PATH "/org/freedesktop/Tracker1/Writeback" -#define TRACKER_WRITEBACK_INTERFACE "org.freedesktop.Tracker1.Writeback" - -typedef struct { - GFile *file; - TrackerMinerFiles *fs; - GPtrArray *results; - GStrv rdf_types; - TrackerWritebackDispatcher *self; /* weak */ - GCancellable *cancellable; - guint cancel_id; - guint retry_timeout; - guint retries; -} WritebackFileData; - -typedef struct { - TrackerMinerFiles *files_miner; - GDBusConnection *d_connection; - TrackerSparqlConnection *connection; -} TrackerWritebackDispatcherPrivate; - -enum { - PROP_0, - PROP_FILES_MINER -}; - -#define TRACKER_WRITEBACK_DISPATCHER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_WRITEBACK_DISPATCHER, TrackerWritebackDispatcherPrivate)) - -static void writeback_dispatcher_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); -static void writeback_dispatcher_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); -static void writeback_dispatcher_finalize (GObject *object); -static gboolean writeback_dispatcher_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error); -static void writeback_dispatcher_writeback_file (TrackerMinerFS *fs, - GFile *file, - GStrv rdf_types, - GPtrArray *results, - GCancellable *cancellable, - gpointer user_data); -static void self_weak_notify (gpointer data, - GObject *where_the_object_was); - -static void -writeback_dispatcher_initable_iface_init (GInitableIface *iface) -{ - iface->init = writeback_dispatcher_initable_init; -} - -G_DEFINE_TYPE_WITH_CODE (TrackerWritebackDispatcher, tracker_writeback_dispatcher, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - writeback_dispatcher_initable_iface_init)); - -static void -tracker_writeback_dispatcher_class_init (TrackerWritebackDispatcherClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = writeback_dispatcher_finalize; - object_class->set_property = writeback_dispatcher_set_property; - object_class->get_property = writeback_dispatcher_get_property; - - g_object_class_install_property (object_class, - PROP_FILES_MINER, - g_param_spec_object ("files_miner", - "files_miner", - "The FS Miner", - TRACKER_TYPE_MINER_FILES, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_type_class_add_private (klass, sizeof (TrackerWritebackDispatcherPrivate)); -} - -static void -writeback_dispatcher_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - TrackerWritebackDispatcherPrivate *priv; - - priv = TRACKER_WRITEBACK_DISPATCHER_GET_PRIVATE (object); - - switch (param_id) { - case PROP_FILES_MINER: - priv->files_miner = g_value_dup_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - - -static void -writeback_dispatcher_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - TrackerWritebackDispatcherPrivate *priv; - - priv = TRACKER_WRITEBACK_DISPATCHER_GET_PRIVATE (object); - - switch (param_id) { - case PROP_FILES_MINER: - g_value_set_object (value, priv->files_miner); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -writeback_dispatcher_finalize (GObject *object) -{ - TrackerWritebackDispatcherPrivate *priv = TRACKER_WRITEBACK_DISPATCHER_GET_PRIVATE (object); - - if (priv->connection) { - g_object_unref (priv->connection); - } - - if (priv->d_connection) { - g_object_unref (priv->d_connection); - } - - if (priv->files_miner) { - g_object_unref (priv->files_miner); - } -} - -static void -tracker_writeback_dispatcher_init (TrackerWritebackDispatcher *object) -{ -} - -static gboolean -writeback_dispatcher_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - TrackerWritebackDispatcherPrivate *priv; - GError *internal_error = NULL; - - priv = TRACKER_WRITEBACK_DISPATCHER_GET_PRIVATE (initable); - - priv->connection = tracker_sparql_connection_get (NULL, &internal_error); - - if (internal_error) { - g_propagate_error (error, internal_error); - return FALSE; - } - - priv->d_connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, &internal_error); - - if (internal_error) { - g_propagate_error (error, internal_error); - return FALSE; - } - - g_signal_connect_object (priv->files_miner, - "writeback", - G_CALLBACK (writeback_dispatcher_writeback_file), - initable, - G_CONNECT_AFTER); - - return TRUE; -} - -TrackerWritebackDispatcher * -tracker_writeback_dispatcher_new (TrackerMinerFiles *miner_files, - GError **error) -{ - GObject *miner; - GError *internal_error = NULL; - - miner = g_initable_new (TRACKER_TYPE_WRITEBACK_DISPATCHER, - NULL, - &internal_error, - "files-miner", miner_files, - NULL); - - if (internal_error) { - g_propagate_error (error, internal_error); - return NULL; - } - - return (TrackerWritebackDispatcher *) miner; -} - -static void -writeback_file_data_free (WritebackFileData *data) -{ - if (data->self) { - g_object_weak_unref (G_OBJECT (data->self), self_weak_notify, data); - } - - g_object_unref (data->fs); - g_object_unref (data->file); - g_strfreev (data->rdf_types); - g_ptr_array_unref (data->results); - g_cancellable_disconnect (data->cancellable, data->cancel_id); - g_object_unref (data->cancellable); - g_free (data); -} - -static void -self_weak_notify (gpointer data, GObject *where_the_object_was) -{ - WritebackFileData *udata = data; - - /* Shut down while retrying writeback */ - g_debug ("Shutdown occurred while retrying write-back (after unmount), not retrying anymore"); - - if (udata->retry_timeout != 0) { - g_source_remove (udata->retry_timeout); - } - - udata->self = NULL; - writeback_file_data_free (udata); -} - -static gboolean -retry_idle (gpointer user_data) -{ - WritebackFileData *data = user_data; - - tracker_miner_files_writeback_file (data->fs, - data->file, - data->rdf_types, - data->results); - - writeback_file_data_free (data); - - return FALSE; -} - -static void -writeback_file_finished (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - WritebackFileData *data = user_data; - GError *error = NULL; - - g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object), - res, &error); - - if (error && error->code == G_DBUS_ERROR_NO_REPLY && data->retries < 5) { - /* This happens in case of exit() of the tracker-writeback binary, which - * happens on unmount of the FS event, for example */ - - g_debug ("Retrying write-back after unmount (timeout in 5 seconds)"); - tracker_miner_files_writeback_notify (data->fs, data->file, NULL); - - data->retry_timeout = g_timeout_add_seconds (5, retry_idle, data); - data->retries++; - - } else { - tracker_miner_files_writeback_notify (data->fs, data->file, error); - writeback_file_data_free (data); - } -} - -static void -writeback_cancel_remote_operation (GCancellable *cancellable, - WritebackFileData *data) -{ - TrackerWritebackDispatcherPrivate *priv; - GDBusMessage *message; - gchar *uris[2]; - - priv = TRACKER_WRITEBACK_DISPATCHER_GET_PRIVATE (data->self); - - uris[0] = g_file_get_uri (data->file); - uris[1] = NULL; - - message = g_dbus_message_new_method_call (TRACKER_WRITEBACK_SERVICE, - TRACKER_WRITEBACK_PATH, - TRACKER_WRITEBACK_INTERFACE, - "CancelTasks"); - - g_dbus_message_set_body (message, g_variant_new ("(^as)", uris)); - g_dbus_connection_send_message (priv->d_connection, message, - G_DBUS_SEND_MESSAGE_FLAGS_NONE, - NULL, NULL); - g_free (uris[0]); -} - -static void -writeback_dispatcher_writeback_file (TrackerMinerFS *fs, - GFile *file, - GStrv rdf_types, - GPtrArray *results, - GCancellable *cancellable, - gpointer user_data) -{ - TrackerWritebackDispatcher *self = user_data; - TrackerWritebackDispatcherPrivate *priv; - gchar *uri; - guint i; - GVariantBuilder builder; - WritebackFileData *data = g_new (WritebackFileData, 1); - - priv = TRACKER_WRITEBACK_DISPATCHER_GET_PRIVATE (self); - - uri = g_file_get_uri (file); - g_debug ("Performing write-back for '%s'", uri); - - g_variant_builder_init (&builder, G_VARIANT_TYPE ("(sasaas)")); - - g_variant_builder_add (&builder, "s", uri); - - g_variant_builder_open (&builder, G_VARIANT_TYPE ("as")); - for (i = 0; rdf_types[i] != NULL; i++) { - g_variant_builder_add (&builder, "s", rdf_types[i]); - } - g_variant_builder_close (&builder); - - g_variant_builder_open (&builder, G_VARIANT_TYPE ("aas")); - - for (i = 0; i< results->len; i++) { - GStrv row = g_ptr_array_index (results, i); - guint y; - - g_variant_builder_open (&builder, G_VARIANT_TYPE ("as")); - for (y = 0; row[y] != NULL; y++) { - g_variant_builder_add (&builder, "s", row[y]); - } - - g_variant_builder_close (&builder); - } - - g_variant_builder_close (&builder); - - data->retries = 0; - data->retry_timeout = 0; - data->self = self; - g_object_weak_ref (G_OBJECT (data->self), self_weak_notify, data); - data->fs = g_object_ref (fs); - data->file = g_object_ref (file); - data->results = g_ptr_array_ref (results); - data->rdf_types = g_strdupv (rdf_types); - data->cancellable = g_object_ref (cancellable); - data->cancel_id = g_cancellable_connect (data->cancellable, - G_CALLBACK (writeback_cancel_remote_operation), - data, NULL); - - g_dbus_connection_call (priv->d_connection, - TRACKER_WRITEBACK_SERVICE, - TRACKER_WRITEBACK_PATH, - TRACKER_WRITEBACK_INTERFACE, - "PerformWriteback", - g_variant_builder_end (&builder), - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - cancellable, - (GAsyncReadyCallback) writeback_file_finished, - data); - - g_free (uri); -} diff --git a/src/miners/fs/tracker-writeback-dispatcher.h b/src/miners/fs/tracker-writeback-dispatcher.h deleted file mode 100644 index 9bfb5f340..000000000 --- a/src/miners/fs/tracker-writeback-dispatcher.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_MINER_FS_WRITEBACK_DISPATCHER_H__ -#define __TRACKER_MINER_FS_WRITEBACK_DISPATCHER_H__ - -#include <glib-object.h> - -#include "tracker-miner-files.h" - -G_BEGIN_DECLS - -#define TRACKER_TYPE_WRITEBACK_DISPATCHER (tracker_writeback_dispatcher_get_type ()) -#define TRACKER_WRITEBACK_DISPATCHER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TRACKER_TYPE_WRITEBACK_DISPATCHER, TrackerWritebackDispatcher)) -#define TRACKER_WRITEBACK_DISPATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TRACKER_TYPE_DBUS_WRITEBACK_DISPATCHER, TrackerWritebackDispatcherClass)) -#define TRACKER_IS_WRITEBACK_DISPATCHER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TRACKER_TYPE_WRITEBACK_DISPATCHER)) -#define TRACKER_IS_WRITEBACK_DISPATCHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TRACKER_TYPE_WRITEBACK_DISPATCHER)) -#define TRACKER_WRITEBACK_DISPATCHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TRACKER_TYPE_WRITEBACK_DISPATCHER, TrackerWritebackDispatcherClass)) - -typedef struct TrackerWritebackDispatcher TrackerWritebackDispatcher; -typedef struct TrackerWritebackDispatcherClass TrackerWritebackDispatcherClass; - -struct TrackerWritebackDispatcher { - GObject parent; -}; - -struct TrackerWritebackDispatcherClass { - GObjectClass parent; -}; - -GType tracker_writeback_dispatcher_get_type (void); -TrackerWritebackDispatcher *tracker_writeback_dispatcher_new (TrackerMinerFiles *miner_files, - GError **error); - -G_END_DECLS - -#endif /* __TRACKER_MINER_FS_WRITEBACK_DISPATCHER_H__ */ diff --git a/src/miners/fs/tracker-writeback-listener.c b/src/miners/fs/tracker-writeback-listener.c deleted file mode 100644 index c861cae78..000000000 --- a/src/miners/fs/tracker-writeback-listener.c +++ /dev/null @@ -1,543 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <libtracker-common/tracker-dbus.h> -#include <libtracker-sparql/tracker-sparql.h> - -#include "tracker-writeback-listener.h" -#include "tracker-miner-files.h" - -#define TRACKER_SERVICE "org.freedesktop.Tracker1" -#define TRACKER_RESOURCES_OBJECT "/org/freedesktop/Tracker1/Resources" -#define TRACKER_INTERFACE_RESOURCES "org.freedesktop.Tracker1.Resources" - -typedef struct { - gint32 subject_id; - gint32 *types; -} WritebackEvent; - -typedef struct { - TrackerMinerFiles *files_miner; - GDBusConnection *d_connection; - TrackerSparqlConnection *connection; - guint d_signal; - - GQueue *events; - guint event_dispatch_id; - guint querying : 1; -} TrackerWritebackListenerPrivate; - -typedef struct { - TrackerWritebackListener *self; - GStrv rdf_types; -} QueryData; - -enum { - PROP_0, - PROP_FILES_MINER -}; - -static void writeback_listener_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); -static void writeback_listener_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); -static void writeback_listener_finalize (GObject *object); -static gboolean writeback_listener_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error); -static void on_writeback_cb (GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data); - -static void check_start_idle (TrackerWritebackListener *self, - gboolean force); - -static void -writeback_listener_initable_iface_init (GInitableIface *iface) -{ - iface->init = writeback_listener_initable_init; -} - -G_DEFINE_TYPE_WITH_CODE (TrackerWritebackListener, tracker_writeback_listener, G_TYPE_OBJECT, - G_ADD_PRIVATE (TrackerWritebackListener) - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - writeback_listener_initable_iface_init)); - -static void -tracker_writeback_listener_class_init (TrackerWritebackListenerClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = writeback_listener_finalize; - object_class->set_property = writeback_listener_set_property; - object_class->get_property = writeback_listener_get_property; - - g_object_class_install_property (object_class, - PROP_FILES_MINER, - g_param_spec_object ("files_miner", - "files_miner", - "The FS Miner", - TRACKER_TYPE_MINER_FILES, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); -} - -static void -writeback_listener_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - TrackerWritebackListener *listener = TRACKER_WRITEBACK_LISTENER (object); - TrackerWritebackListenerPrivate *priv; - - priv = tracker_writeback_listener_get_instance_private (listener); - - switch (param_id) { - case PROP_FILES_MINER: - priv->files_miner = g_value_dup_object (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -writeback_listener_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - TrackerWritebackListener *listener = TRACKER_WRITEBACK_LISTENER (object); - TrackerWritebackListenerPrivate *priv; - - priv = tracker_writeback_listener_get_instance_private (listener); - - switch (param_id) { - case PROP_FILES_MINER: - g_value_set_object (value, priv->files_miner); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - } -} - -static void -free_event (WritebackEvent *event) -{ - g_free (event->types); - g_free (event); -} - -static void -writeback_listener_finalize (GObject *object) -{ - TrackerWritebackListener *listener = TRACKER_WRITEBACK_LISTENER (object); - TrackerWritebackListenerPrivate *priv; - - priv = tracker_writeback_listener_get_instance_private (listener); - - if (priv->event_dispatch_id) { - g_source_remove (priv->event_dispatch_id); - } - - g_queue_free_full (priv->events, (GDestroyNotify) free_event); - - if (priv->connection && priv->d_signal) { - g_dbus_connection_signal_unsubscribe (priv->d_connection, priv->d_signal); - } - - if (priv->connection) { - g_object_unref (priv->connection); - } - - if (priv->d_connection) { - g_object_unref (priv->d_connection); - } - - if (priv->files_miner) { - g_object_unref (priv->files_miner); - } -} - - -static void -tracker_writeback_listener_init (TrackerWritebackListener *object) -{ - TrackerWritebackListener *listener = TRACKER_WRITEBACK_LISTENER (object); - TrackerWritebackListenerPrivate *priv; - - priv = tracker_writeback_listener_get_instance_private (listener); - priv->events = g_queue_new (); -} - -static gboolean -writeback_listener_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - TrackerWritebackListener *listener = TRACKER_WRITEBACK_LISTENER (initable); - TrackerWritebackListenerPrivate *priv; - GError *internal_error = NULL; - - priv = tracker_writeback_listener_get_instance_private (listener); - - priv->connection = tracker_sparql_connection_get (NULL, &internal_error); - - if (internal_error) { - g_propagate_error (error, internal_error); - return FALSE; - } - - priv->d_connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, &internal_error); - - if (internal_error) { - g_propagate_error (error, internal_error); - return FALSE; - } - - priv->d_signal = g_dbus_connection_signal_subscribe (priv->d_connection, - TRACKER_SERVICE, - TRACKER_INTERFACE_RESOURCES, - "Writeback", - TRACKER_RESOURCES_OBJECT, - NULL, - G_DBUS_SIGNAL_FLAGS_NONE, - on_writeback_cb, - initable, - NULL); - - return TRUE; -} - -TrackerWritebackListener * -tracker_writeback_listener_new (TrackerMinerFiles *miner_files, - GError **error) -{ - GObject *miner; - GError *internal_error = NULL; - - miner = g_initable_new (TRACKER_TYPE_WRITEBACK_LISTENER, - NULL, - &internal_error, - "files-miner", miner_files, - NULL); - - if (internal_error) { - g_propagate_error (error, internal_error); - return NULL; - } - - return (TrackerWritebackListener *) miner; -} - -static QueryData* -query_data_new (TrackerWritebackListener *self) -{ - QueryData *data = g_slice_new0 (QueryData); - - data->self = g_object_ref (self); - - return data; -} - -static void -query_data_free (QueryData *data) -{ - g_object_unref (data->self); - if (data->rdf_types) { - g_strfreev (data->rdf_types); - } - g_slice_free (QueryData, data); -} - -static void -sparql_query_cb (GObject *object, - GAsyncResult *result, - gpointer user_data) -{ - QueryData *data = user_data; - TrackerWritebackListener *self = TRACKER_WRITEBACK_LISTENER (data->self); - TrackerWritebackListenerPrivate *priv; - TrackerSparqlCursor *cursor; - GError *error = NULL; - - priv = tracker_writeback_listener_get_instance_private (self); - - cursor = tracker_sparql_connection_query_finish (TRACKER_SPARQL_CONNECTION (object), result, &error); - - if (!error) { - guint cols = tracker_sparql_cursor_get_n_columns (cursor); - GPtrArray *results = NULL; - GFile *file = NULL; - - while (tracker_sparql_cursor_next (cursor, NULL, NULL)) { - GStrv row = NULL; - guint i; - - if (file == NULL) { - file = g_file_new_for_uri (tracker_sparql_cursor_get_string (cursor, 0, NULL)); - if (!g_file_query_exists (file, NULL)) { - g_object_unref (file); - g_message (" No files qualify for updates"); - query_data_free (data); - g_object_unref (cursor); - - check_start_idle (self, TRUE); - return; - } - } - - for (i = 0; i < cols; i++) { - if (!row) { - row = g_new0 (gchar*, cols); - } - row[i] = g_strdup (tracker_sparql_cursor_get_string (cursor, i, NULL)); - } - - if (!results) { - results = g_ptr_array_new_with_free_func ((GDestroyNotify) g_strfreev); - } - - g_ptr_array_add (results, row); - } - - if (results != NULL && results->len > 0) { - tracker_miner_files_writeback_file (priv->files_miner, - file, - data->rdf_types, - results); - } else { - g_message (" No files qualify for updates"); - } - - if (file) { - g_object_unref (file); - } - - if (results) { - g_ptr_array_unref (results); - } - - g_object_unref (cursor); - } else { - g_message (" No files qualify for updates (%s)", error->message); - g_error_free (error); - } - - query_data_free (data); - - check_start_idle (self, TRUE); -} - -static void -rdf_types_to_uris_cb (GObject *object, - GAsyncResult *result, - gpointer user_data) -{ - QueryData *data = user_data; - TrackerWritebackListener *self = TRACKER_WRITEBACK_LISTENER (data->self); - TrackerWritebackListenerPrivate *priv; - TrackerSparqlCursor *cursor; - TrackerSparqlConnection *connection; - GError *error = NULL; - gchar *query; - GArray *rdf_types; - gchar *subject = NULL; - - priv = tracker_writeback_listener_get_instance_private (self); - connection = priv->connection; - - cursor = tracker_sparql_connection_query_finish (connection, result, &error); - - if (error) - goto trouble; - - rdf_types = g_array_new (TRUE, TRUE, sizeof (gchar *)); - - while (tracker_sparql_cursor_next (cursor, NULL, NULL)) { - gchar *uri = g_strdup (tracker_sparql_cursor_get_string (cursor, 0, NULL)); - if (subject == NULL) { - subject = g_strdup (tracker_sparql_cursor_get_string (cursor, 1, NULL)); - } - g_array_append_val (rdf_types, uri); - } - - g_object_unref (cursor); - - data->rdf_types = (GStrv) rdf_types->data; - g_array_free (rdf_types, FALSE); - - if (subject == NULL) - goto trouble; - - query = g_strdup_printf ("SELECT ?url '%s' ?predicate ?object { " - "<%s> a nfo:FileDataObject . " - "<%s> ?predicate ?object ; nie:url ?url . " - "?predicate tracker:writeback true . " - "FILTER (NOT EXISTS { GRAPH <" TRACKER_OWN_GRAPH_URN "> " - "{ <%s> ?predicate ?object } }) } ", - subject, subject, subject, subject); - - tracker_sparql_connection_query_async (connection, - query, - NULL, - sparql_query_cb, - data); - - g_free (subject); - g_free (query); - - return; - -trouble: - if (error) { - g_message (" No files qualify for updates (%s)", error->message); - g_error_free (error); - } - query_data_free (data); - - check_start_idle (self, TRUE); -} - -static gboolean -process_event (gpointer user_data) -{ - TrackerWritebackListener *self = user_data; - TrackerWritebackListenerPrivate *priv; - WritebackEvent *event; - QueryData *data = NULL; - GString *query; - gboolean comma = FALSE; - gint i; - - priv = tracker_writeback_listener_get_instance_private (self); - event = g_queue_pop_head (priv->events); - priv->event_dispatch_id = 0; - - if (!event) - return G_SOURCE_REMOVE; - - data = query_data_new (self); - - /* Two queries are grouped together here to reduce the amount of - * queries that must be made. tracker:uri() is idd unrelated to - * the other part of the query (and is repeated each result, idd) */ - - query = g_string_new ("SELECT "); - g_string_append_printf (query, "?resource tracker:uri (%d) { " - "?resource a rdfs:Class . " - "FILTER (tracker:id (?resource) IN (", - event->subject_id); - - for (i = 0; event->types[i] != 0; i++) { - gint32 rdf_type = event->types[i]; - - if (comma) { - g_string_append_printf (query, ", %d", rdf_type); - } else { - g_string_append_printf (query, "%d", rdf_type); - comma = TRUE; - } - } - - g_string_append (query, ")) }"); - - tracker_sparql_connection_query_async (priv->connection, - query->str, - NULL, - rdf_types_to_uris_cb, - data); - g_string_free (query, TRUE); - free_event (event); - - return G_SOURCE_REMOVE; -} - -static void -check_start_idle (TrackerWritebackListener *self, - gboolean force) -{ - TrackerWritebackListenerPrivate *priv; - - priv = tracker_writeback_listener_get_instance_private (self); - - if (priv->event_dispatch_id != 0) - return; - if (priv->querying && !force) - return; - if (g_queue_is_empty (priv->events)) { - priv->querying = FALSE; - return; - } - - priv->querying = TRUE; - priv->event_dispatch_id = - g_idle_add_full (G_PRIORITY_LOW, - process_event, - self, NULL); -} - -static void -on_writeback_cb (GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) -{ - TrackerWritebackListener *self = TRACKER_WRITEBACK_LISTENER (user_data); - TrackerWritebackListenerPrivate *priv; - GVariantIter *iter1, *iter2; - gint32 subject_id; - - priv = tracker_writeback_listener_get_instance_private (self); - g_variant_get (parameters, "(a{iai})", &iter1); - - if (g_variant_iter_next (iter1, "{iai}", &subject_id, &iter2)) { - WritebackEvent *event = g_new (WritebackEvent, 1); - GArray *types = g_array_new (TRUE, TRUE, sizeof (gint32)); - gint32 rdf_type; - - while (g_variant_iter_loop (iter2, "i", &rdf_type)) - g_array_append_val (types, rdf_type); - - g_variant_iter_free (iter2); - event->subject_id = subject_id; - event->types = (gint32 *) g_array_free (types, FALSE); - g_queue_push_tail (priv->events, event); - } - - g_variant_iter_free (iter1); - check_start_idle (self, FALSE); -} diff --git a/src/miners/fs/tracker-writeback-listener.h b/src/miners/fs/tracker-writeback-listener.h deleted file mode 100644 index e1897c27e..000000000 --- a/src/miners/fs/tracker-writeback-listener.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_MINER_FS_WRITEBACK_LISTENER_H__ -#define __TRACKER_MINER_FS_WRITEBACK_LISTENER_H__ - -#include <glib-object.h> - -#include "tracker-miner-files.h" - -G_BEGIN_DECLS - -#define TRACKER_TYPE_WRITEBACK_LISTENER (tracker_writeback_listener_get_type ()) -#define TRACKER_WRITEBACK_LISTENER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TRACKER_TYPE_WRITEBACK_LISTENER, TrackerWritebackListener)) -#define TRACKER_WRITEBACK_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TRACKER_TYPE_DBUS_WRITEBACK_LISTENER, TrackerWritebackListenerClass)) -#define TRACKER_IS_WRITEBACK_LISTENER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TRACKER_TYPE_WRITEBACK_LISTENER)) -#define TRACKER_IS_WRITEBACK_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TRACKER_TYPE_WRITEBACK_LISTENER)) -#define TRACKER_WRITEBACK_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TRACKER_TYPE_WRITEBACK_LISTENER, TrackerWritebackListenerClass)) - -typedef struct TrackerWritebackListener TrackerWritebackListener; -typedef struct TrackerWritebackListenerClass TrackerWritebackListenerClass; - -struct TrackerWritebackListener { - GObject parent; -}; - -struct TrackerWritebackListenerClass { - GObjectClass parent; -}; - -GType tracker_writeback_listener_get_type (void); -TrackerWritebackListener *tracker_writeback_listener_new (TrackerMinerFiles *miner_files, - GError **error); - -G_END_DECLS - -#endif /* __TRACKER_MINER_FS_WRITEBACK_LISTENER_H__ */ diff --git a/src/miners/fs/tracker-writeback.c b/src/miners/fs/tracker-writeback.c deleted file mode 100644 index 84a598707..000000000 --- a/src/miners/fs/tracker-writeback.c +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <gio/gio.h> - -#include "tracker-writeback.h" -#include "tracker-writeback-listener.h" -#include "tracker-writeback-dispatcher.h" - -/* Listener listens for the Writeback signal coming from the store, it performs - * a few queries to get a set of changed values, and pushes the writeback task - * to miner-fs's queues. */ -static TrackerWritebackListener *listener = NULL; - -/* That task in miner-fs's queue callsback to the dispatcher. The dispatcher - * calls the external tracker-writeback process which does the actual write */ -static TrackerWritebackDispatcher *dispatcher = NULL; - -static gboolean enabled = FALSE; -static TrackerMinerFiles *gminer_files = NULL; -static TrackerConfig *gconfig = NULL; -static guint gsig = 0; - -static void -initialize_all (TrackerMinerFiles *miner_files, - GError **error) -{ - GError *internal_error = NULL; - - listener = tracker_writeback_listener_new (miner_files, &internal_error); - - if (!internal_error) { - dispatcher = tracker_writeback_dispatcher_new (miner_files, &internal_error); - } - - if (internal_error) { - if (listener) { - g_object_unref (listener); - listener = NULL; - } - g_propagate_error (error, internal_error); - } - enabled = TRUE; -} - -static void -shutdown_writeback (void) -{ - if (listener) { - g_object_unref (listener); - listener = NULL; - } - - if (dispatcher) { - g_object_unref (dispatcher); - dispatcher = NULL; - } - enabled = FALSE; -} - -static void -enable_writeback_cb (GObject *object, - GParamSpec *pspec, - gpointer user_data) -{ - if (enabled && !tracker_config_get_enable_monitors (gconfig)) { - shutdown_writeback (); - } - - if (!enabled && tracker_config_get_enable_monitors (gconfig)) { - GError *error = NULL; - - initialize_all (gminer_files, &error); - - if (error) { - g_critical ("Can't reenable Writeback: '%s'", error->message); - g_error_free (error); - } - } -} - -void -tracker_writeback_init (TrackerMinerFiles *miner_files, - TrackerConfig *config, - GError **error) -{ - GError *internal_error = NULL; - - if (tracker_config_get_enable_monitors (config)) { - initialize_all (miner_files, &internal_error); - } - - if (internal_error) { - g_propagate_error (error, internal_error); - } else { - gminer_files = g_object_ref (miner_files); - gconfig = g_object_ref (config); - gsig = g_signal_connect (gconfig, "notify::enable-writeback", - G_CALLBACK (enable_writeback_cb), - NULL); - } -} - -void -tracker_writeback_shutdown (void) -{ - shutdown_writeback (); - - if (gconfig) { - if (gsig) { - g_signal_handler_disconnect (gconfig, gsig); - } - g_object_unref (gconfig); - } - - if (gminer_files) { - g_object_unref (gminer_files); - } -} diff --git a/src/miners/fs/tracker-writeback.h b/src/miners/fs/tracker-writeback.h deleted file mode 100644 index aa1d12976..000000000 --- a/src/miners/fs/tracker-writeback.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_MINER_FS_WRITEBACK_H__ -#define __TRACKER_MINER_FS_WRITEBACK_H__ - -#include <libtracker-miner/tracker-miner.h> - -#include "tracker-config.h" - -#include "tracker-miner-files.h" - -G_BEGIN_DECLS - -void tracker_writeback_init (TrackerMinerFiles *miner_files, - TrackerConfig *config, - GError **error); -void tracker_writeback_shutdown (void); - -G_END_DECLS - -#endif /* __TRACKER_MINER_FS_WRITEBACK_H__ */ diff --git a/src/miners/meson.build b/src/miners/meson.build deleted file mode 100644 index d9384109d..000000000 --- a/src/miners/meson.build +++ /dev/null @@ -1,3 +0,0 @@ -subdir('fs') -subdir('rss') -subdir('apps') diff --git a/src/miners/rss/.gitignore b/src/miners/rss/.gitignore deleted file mode 100644 index 62c2dec7e..000000000 --- a/src/miners/rss/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tracker-miner-rss -*.service diff --git a/src/miners/rss/Makefile.am b/src/miners/rss/Makefile.am deleted file mode 100644 index 5b059e34c..000000000 --- a/src/miners/rss/Makefile.am +++ /dev/null @@ -1,73 +0,0 @@ -AM_CPPFLAGS = \ - $(BUILD_CFLAGS) \ - -DSHAREDIR=\""$(datadir)"\" \ - -DLOCALEDIR=\""$(localedir)"\" \ - -DLIBEXEC_PATH=\""$(libexecdir)"\" \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - $(TRACKER_MINER_RSS_CFLAGS) - -libexec_PROGRAMS = tracker-miner-rss - -tracker_miner_rss_SOURCES = \ - tracker-main.c \ - tracker-miner-rss.h \ - tracker-miner-rss.c - -tracker_miner_rss_LDADD = \ - $(top_builddir)/src/libtracker-sparql-backend/libtracker-sparql-@TRACKER_API_VERSION@.la \ - $(top_builddir)/src/libtracker-miner/libtracker-miner-@TRACKER_API_VERSION@.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_MINER_RSS_LIBS) - -# DBus interfaces (XML files) and services -%.service.in: %.service.in.in - @sed -e "s|@libexecdir[@]|${libexecdir}|" $< > $@ - -servicedir = $(DBUS_SERVICES_DIR) -service_DATA = org.freedesktop.Tracker1.Miner.RSS.service - -INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -d -u' -@INTLTOOL_SERVICE_RULE@ - -tracker-miner-rss.service: tracker-miner-rss.service.in Makefile - @sed -e "s|@libexecdir[@]|${libexecdir}|" $< > $@ - -systemd_userdir = $(prefix)/lib/systemd/user -systemd_user_DATA = tracker-miner-rss.service - -install-data-hook: - $(MKDIR_P) "$(DESTDIR)$(datadir)/tracker/miners" && \ - $(LN_S) -f "$(servicedir)/$(service_DATA)" \ - "$(DESTDIR)$(datadir)/tracker/miners/$(service_DATA)" - -uninstall-local: - $(RM) "$(DESTDIR)$(datadir)/tracker/miners/$(service_DATA)" && \ - $(RM) "$(servicedir)/$(service_DATA)" - -# Desktop files: First we fix the VERSION and libexecdir -%.desktop.in: %.desktop.in.in - @sed -e "s|@libexecdir[@]|${libexecdir}|" \ - -e "s|@VERSION[@]|${VERSION}|" $< > $@ - -autostartdir = $(sysconfdir)/xdg/autostart -autostart_DATA = tracker-miner-rss.desktop - -@INTLTOOL_DESKTOP_RULE@ - -# Dist / Clean rules for all data -CLEANFILES = \ - $(autostart_DATA) \ - $(autostart_DATA:.desktop=.desktop.in) \ - $(service_DATA) \ - $(service_DATA:.service=.service.in) \ - $(systemd_user_DATA) \ - $(NULL) - -EXTRA_DIST = \ - $(autostart_DATA:.desktop=.desktop.in.in) \ - $(service_DATA:.service=.service.in.in) \ - $(systemd_user_DATA:.service=.service.in) \ - meson.build \ - $(NULL) diff --git a/src/miners/rss/meson.build b/src/miners/rss/meson.build deleted file mode 100644 index 1e1172fc3..000000000 --- a/src/miners/rss/meson.build +++ /dev/null @@ -1,43 +0,0 @@ -sources = [ - 'tracker-main.c', - 'tracker-miner-rss.c', -] - -executable('tracker-miner-rss', sources, - dependencies: [libgrss, tracker_common_dep, tracker_miner_dep, tracker_extract_dep], - c_args: tracker_c_args, - install_rpath: tracker_internal_libs_dir, -) - -dbus_service_file_untranslated = configure_file( - input: 'org.freedesktop.Tracker1.Miner.RSS.service.in.in', - output: 'org.freedesktop.Tracker1.Miner.RSS.service.in', - configuration: conf) - -dbus_service_file = custom_target('tracker-miner-rss-dbus-service-file', - input: dbus_service_file_untranslated, - output: 'org.freedesktop.Tracker1.Miner.RSS.service', - command: ['intltool-merge', '--quiet', '--desktop-style', '--utf8', join_paths(meson.source_root(), 'po'), '@INPUT@', '@OUTPUT@'], - install: true, - install_dir: dbus_services_dir) - -desktop_file_untranslated = configure_file( - input: 'tracker-miner-rss.desktop.in.in', - output: 'tracker-miner-rss.desktop.in', - configuration: conf) - -desktop_file = custom_target('tracker-miner-rss-desktop-file', - input: desktop_file_untranslated, - output: 'tracker-miner-rss.desktop', - command: ['intltool-merge', '--quiet', '--desktop-style', '--utf8', join_paths(meson.source_root(), 'po'), '@INPUT@', '@OUTPUT@'], - install: true, - install_dir: join_paths(get_option('sysconfdir'), 'xdg/autostart')) - -if install_systemd_user_services - configure_file( - input: 'tracker-miner-rss.service.in', - output: 'tracker-miner-rss.service', - configuration: conf, - install: true, - install_dir: systemd_user_services_dir) -endif diff --git a/src/miners/rss/org.freedesktop.Tracker1.Miner.RSS.service.in.in b/src/miners/rss/org.freedesktop.Tracker1.Miner.RSS.service.in.in deleted file mode 100644 index 372c21965..000000000 --- a/src/miners/rss/org.freedesktop.Tracker1.Miner.RSS.service.in.in +++ /dev/null @@ -1,10 +0,0 @@ -[D-BUS Service] -Name=org.freedesktop.Tracker1.Miner.RSS -Exec=@libexecdir@/tracker-miner-rss -SystemdService=tracker-miner-rss.service - -# Miner details needed for tracker-control -Path=/org/freedesktop/Tracker1/Miner/RSS -NameSuffix=Miner.RSS -_DisplayName=RSS/ATOM Feeds -_Comment=Fetch RSS/ATOM Feeds diff --git a/src/miners/rss/tracker-main.c b/src/miners/rss/tracker-main.c deleted file mode 100644 index 850ed03c9..000000000 --- a/src/miners/rss/tracker-main.c +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (C) 2009/2010, Roberto Guido <madbob@users.barberaware.org> - * Michele Tameni <michele@amdplanet.it> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <stdlib.h> - -#include <locale.h> -#include <glib/gi18n.h> - -#include <libtracker-common/tracker-common.h> - -#include "tracker-miner-rss.h" - -#define DBUS_NAME_SUFFIX "Miner.RSS" -#define DBUS_PATH "/org/freedesktop/Tracker1/Miner/RSS" - -static gint verbosity = -1; -static gchar *add_feed; -static gchar *title; -static gchar *domain_ontology_name = NULL; - -static GOptionEntry entries[] = { - { "verbosity", 'v', 0, - G_OPTION_ARG_INT, &verbosity, - N_("Logging, 0 = errors only, " - "1 = minimal, 2 = detailed and 3 = debug (default=0)"), - NULL }, - { "add-feed", 'a', 0, - G_OPTION_ARG_STRING, &add_feed, - /* Translators: this is a "feed" as in RSS */ - N_("Add feed"), - N_("URL") }, - { "title", 't', 0, - G_OPTION_ARG_STRING, &title, - N_("Title to use (must be used with --add-feed)"), - NULL }, - { "domain-ontology", 'd', 0, - G_OPTION_ARG_STRING, &domain_ontology_name, - N_("Runs for an specific domain ontology"), - NULL }, - { NULL } -}; - -static void -on_domain_vanished (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - GMainLoop *loop = user_data; - g_main_loop_quit (loop); -} - -int -main (int argc, char **argv) -{ - gchar *log_filename; - GMainLoop *loop; - GOptionContext *context; - TrackerMinerRSS *miner; - GError *error = NULL; - GDBusConnection *connection; - TrackerMinerProxy *proxy; - TrackerDomainOntology *domain_ontology; - gchar *dbus_name; - - setlocale (LC_ALL, ""); - - bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); - tzset (); - - /* Translators: this messagge will apper immediately after the - * usage string - Usage: COMMAND <THIS_MESSAGE> - */ - context = g_option_context_new (_("— start the feeds indexer")); - g_option_context_add_main_entries (context, entries, NULL); - g_option_context_parse (context, &argc, &argv, NULL); - - if (title && !add_feed) { - gchar *help; - - help = g_option_context_get_help (context, TRUE, NULL); - g_option_context_free (context); - g_printerr ("%s", help); - g_free (help); - - return EXIT_FAILURE; - } - - g_option_context_free (context); - - tracker_sparql_connection_set_domain (domain_ontology_name); - - /* Command line stuff doesn't use logging, so we're using g_print*() */ - if (add_feed) { - TrackerSparqlConnection *connection; - GString *query; - - g_print ("Adding feed:\n" - " title:'%s'\n" - " url:'%s'\n", - title, - add_feed); - - connection = tracker_sparql_connection_get (NULL, &error); - - if (!connection) { - g_printerr ("%s: %s\n", - _("Could not establish a connection to Tracker"), - error ? error->message : _("No error given")); - g_clear_error (&error); - return EXIT_FAILURE; - } - - /* FIXME: Make interval configurable */ - query = g_string_new ("INSERT {" - " _:FeedSettings a mfo:FeedSettings ;" - " mfo:updateInterval 20 ." - " _:Feed a nie:DataObject, mfo:FeedChannel ;" - " mfo:feedSettings _:FeedSettings ;"); - - if (title) { - g_string_append_printf (query, "nie:title \"%s\";", title); - } - - g_string_append_printf (query, " nie:url \"%s\" }", add_feed); - - tracker_sparql_connection_update (connection, - query->str, - G_PRIORITY_DEFAULT, - NULL, - &error); - g_string_free (query, TRUE); - - if (error) { - g_printerr ("%s, %s\n", - _("Could not add feed"), - error->message); - g_error_free (error); - g_object_unref (connection); - - return EXIT_FAILURE; - } - - g_print ("Done\n"); - - return EXIT_SUCCESS; - } - - tracker_log_init (verbosity, &log_filename); - if (log_filename != NULL) { - g_message ("Using log file:'%s'", log_filename); - g_free (log_filename); - } - - domain_ontology = tracker_domain_ontology_new (domain_ontology_name, NULL, &error); - if (error) { - g_critical ("Could not load domain ontology '%s': %s", - domain_ontology_name, error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, &error); - if (error) { - g_critical ("Could not create DBus connection: %s\n", - error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - miner = tracker_miner_rss_new (&error); - if (!miner) { - g_critical ("Could not create new RSS miner: '%s', exiting...\n", - error ? error->message : "unknown error"); - return EXIT_FAILURE; - } - - tracker_miner_start (TRACKER_MINER (miner)); - proxy = tracker_miner_proxy_new (TRACKER_MINER (miner), connection, DBUS_PATH, NULL, &error); - if (error) { - g_critical ("Could not create miner DBus proxy: %s\n", error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - dbus_name = tracker_domain_ontology_get_domain (domain_ontology, DBUS_NAME_SUFFIX); - - if (!tracker_dbus_request_name (connection, dbus_name, &error)) { - g_critical ("Could not request DBus name '%s': %s", - dbus_name, error->message); - g_error_free (error); - g_free (dbus_name); - return EXIT_FAILURE; - } - - g_free (dbus_name); - - loop = g_main_loop_new (NULL, FALSE); - - if (domain_ontology && domain_ontology_name) { - g_bus_watch_name_on_connection (connection, domain_ontology_name, - G_BUS_NAME_WATCHER_FLAGS_NONE, - NULL, on_domain_vanished, - loop, NULL); - } - - g_main_loop_run (loop); - - tracker_log_shutdown (); - g_main_loop_unref (loop); - g_object_unref (miner); - g_object_unref (connection); - g_object_unref (proxy); - g_object_unref (domain_ontology); - - return EXIT_SUCCESS; -} diff --git a/src/miners/rss/tracker-miner-rss.c b/src/miners/rss/tracker-miner-rss.c deleted file mode 100644 index 3d87052cd..000000000 --- a/src/miners/rss/tracker-miner-rss.c +++ /dev/null @@ -1,1483 +0,0 @@ -/* - * Copyright (C) 2009/2010, Roberto Guido <madbob@users.barberaware.org> - * Michele Tameni <michele@amdplanet.it> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <stdio.h> - -#include <libgrss.h> - -#include <libtracker-common/tracker-dbus.h> -#include <libtracker-sparql/tracker-ontologies.h> -#include <libtracker-common/tracker-common.h> - -#include <glib/gi18n.h> - -#include "tracker-miner-rss.h" - -#define TRACKER_MINER_RSS_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_MINER_RSS, TrackerMinerRSSPrivate)) - -typedef struct _TrackerMinerRSSPrivate TrackerMinerRSSPrivate; - -struct _TrackerMinerRSSPrivate { - gboolean paused; - gboolean stopped; - gchar *last_status; - - GrssFeedsPool *pool; - gint now_fetching; - GDBusConnection *connection; - guint graph_updated_id; - - GHashTable *channel_updates; - GHashTable *channels; - - gint rdf_type_id; - gint mfo_feed_channel_id; -}; - -typedef struct { - TrackerMinerRSS *miner; - GrssFeedChannel *channel; - gint timeout_id; - GCancellable *cancellable; -} FeedChannelUpdateData; - -typedef struct { - TrackerMinerRSS *miner; - GrssFeedItem *item; - GCancellable *cancellable; -} FeedItemInsertData; - -typedef struct { - TrackerMinerRSS *miner; - GrssFeedChannel *channel; - GHashTable *items; -} FeedItemListInsertData; - -static void graph_updated_cb (GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data); -static void miner_started (TrackerMiner *miner); -static void miner_stopped (TrackerMiner *miner); -static void miner_paused (TrackerMiner *miner); -static void miner_resumed (TrackerMiner *miner); -static void retrieve_and_schedule_feeds (TrackerMinerRSS *miner, - GArray *channel_ids); -static gboolean feed_channel_changed_timeout_cb (gpointer user_data); -static void feed_channel_update_data_free (FeedChannelUpdateData *fcud); -static void feed_fetching_cb (GrssFeedsPool *pool, - GrssFeedChannel *feed, - gpointer user_data); -static void feed_ready_cb (GrssFeedsPool *pool, - GrssFeedChannel *feed, - GList *items, - gpointer user_data); -static const gchar *get_message_url (GrssFeedItem *item); - -G_DEFINE_TYPE (TrackerMinerRSS, tracker_miner_rss, TRACKER_TYPE_MINER_ONLINE) - -static void -parser_characters (void *data, - const xmlChar *ch, - int len) -{ - GString *string = data; - const gchar *str, *end; - - str = (gchar *)ch; - g_utf8_validate (str, len, &end); - - if (end > str) { - g_string_append_len (string, str, end - str); - } - - if (string->str[string->len - 1] != ' ') - g_string_append_c (string, ' '); -} - -static gchar * -parse_html_text (const gchar *html) -{ - GString *string; - htmlDocPtr doc; - xmlSAXHandler handler = { - NULL, /* internalSubset */ - NULL, /* isStandalone */ - NULL, /* hasInternalSubset */ - NULL, /* hasExternalSubset */ - NULL, /* resolveEntity */ - NULL, /* getEntity */ - NULL, /* entityDecl */ - NULL, /* notationDecl */ - NULL, /* attributeDecl */ - NULL, /* elementDecl */ - NULL, /* unparsedEntityDecl */ - NULL, /* setDocumentLocator */ - NULL, /* startDocument */ - NULL, /* endDocument */ - NULL, /* startElement */ - NULL, /* endElement */ - NULL, /* reference */ - parser_characters, /* characters */ - NULL, /* ignorableWhitespace */ - NULL, /* processingInstruction */ - NULL, /* comment */ - NULL, /* xmlParserWarning */ - NULL, /* xmlParserError */ - NULL, /* xmlParserError */ - NULL, /* getParameterEntity */ - NULL, /* cdataBlock */ - NULL, /* externalSubset */ - 1, /* initialized */ - NULL, /* private */ - NULL, /* startElementNsSAX2Func */ - NULL, /* endElementNsSAX2Func */ - NULL /* xmlStructuredErrorFunc */ - }; - - string = g_string_new (NULL); - doc = htmlSAXParseDoc ((xmlChar *) html, "UTF-8", &handler, string); - - if (doc) { - xmlFreeDoc (doc); - } - - return g_string_free (string, FALSE); -} - -static void -tracker_miner_rss_finalize (GObject *object) -{ - TrackerMinerRSSPrivate *priv; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (object); - - priv->stopped = TRUE; - g_free (priv->last_status); - g_object_unref (priv->pool); - - g_dbus_connection_signal_unsubscribe (priv->connection, priv->graph_updated_id); - g_object_unref (priv->connection); - - g_hash_table_unref (priv->channel_updates); - g_hash_table_unref (priv->channels); - - G_OBJECT_CLASS (tracker_miner_rss_parent_class)->finalize (object); -} - -static gint -get_class_id (TrackerSparqlConnection *conn, - const gchar *class) -{ - TrackerSparqlCursor *cursor; - GError *error = NULL; - gchar *query; - gint id = -1; - - query = g_strdup_printf ("select tracker:id (%s) {}", class); - cursor = tracker_sparql_connection_query (conn, query, NULL, &error); - g_free (query); - - if (error) { - g_critical ("Could not get class ID for '%s': %s\n", - class, error->message); - g_error_free (error); - return -1; - } - - if (tracker_sparql_cursor_next (cursor, NULL, NULL)) - id = tracker_sparql_cursor_get_integer (cursor, 0); - else - g_critical ("'%s' didn't resolve to a known class ID", class); - - g_object_unref (cursor); - - return id; -} - -static gboolean -miner_connected (TrackerMinerOnline *miner, - TrackerNetworkType network) -{ - return (network == TRACKER_NETWORK_TYPE_LAN); -} - -static void -tracker_miner_rss_class_init (TrackerMinerRSSClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - TrackerMinerClass *miner_class = TRACKER_MINER_CLASS (klass); - TrackerMinerOnlineClass *miner_online_class = TRACKER_MINER_ONLINE_CLASS (klass); - - object_class->finalize = tracker_miner_rss_finalize; - - miner_class->started = miner_started; - miner_class->stopped = miner_stopped; - miner_class->paused = miner_paused; - miner_class->resumed = miner_resumed; - - miner_online_class->connected = miner_connected; - - g_type_class_add_private (object_class, sizeof (TrackerMinerRSSPrivate)); -} - -static void -tracker_miner_rss_init (TrackerMinerRSS *object) -{ - GError *error = NULL; - TrackerMinerRSSPrivate *priv; - TrackerDomainOntology *domain_ontology; - gchar *dbus_name; - - g_message ("Initializing..."); - - priv = TRACKER_MINER_RSS_GET_PRIVATE (object); - - priv->connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, &error); - - if (!priv->connection) { - g_critical ("Could not connect to the D-Bus session bus, %s", - error ? error->message : "no error given."); - g_error_free (error); - return; - } - - /* Key object reference is cleaned up in value destroy func */ - priv->channel_updates = g_hash_table_new_full (g_direct_hash, - g_direct_equal, - NULL, - (GDestroyNotify) feed_channel_update_data_free); - priv->channels = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) g_object_unref); - - priv->pool = grss_feeds_pool_new (); - g_signal_connect (priv->pool, "feed-fetching", G_CALLBACK (feed_fetching_cb), object); - g_signal_connect (priv->pool, "feed-ready", G_CALLBACK (feed_ready_cb), object); - priv->now_fetching = 0; - - g_message ("Listening for GraphUpdated changes on D-Bus interface..."); - g_message (" arg0:'%s'", TRACKER_PREFIX_MFO "FeedChannel"); - - domain_ontology = tracker_domain_ontology_new (tracker_sparql_connection_get_domain (), - NULL, NULL); - dbus_name = tracker_domain_ontology_get_domain (domain_ontology, NULL); - - priv->graph_updated_id = - g_dbus_connection_signal_subscribe (priv->connection, - dbus_name, - "org.freedesktop.Tracker1.Resources", - "GraphUpdated", - "/org/freedesktop/Tracker1/Resources", - TRACKER_PREFIX_MFO "FeedChannel", - G_DBUS_SIGNAL_FLAGS_NONE, - graph_updated_cb, - object, - NULL); - g_free (dbus_name); - g_object_unref (domain_ontology); -} - -static void -delete_unbound_messages (TrackerMinerRSS *miner) -{ - tracker_sparql_connection_update_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - "DELETE { ?msg a rdfs:Resource." - " ?encl a rdfs:Resource. }" - "WHERE { ?msg a mfo:FeedMessage ;" - " mfo:enclosureList ?encl ." - " FILTER(!BOUND(nmo:communicationChannel(?msg)))" - "}", - G_PRIORITY_DEFAULT, - NULL, NULL, NULL); -} - -static void -delete_message_channels_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - TrackerMinerRSS *miner = user_data; - TrackerSparqlConnection *connection; - GError *error = NULL; - - connection = TRACKER_SPARQL_CONNECTION (source_object); - tracker_sparql_connection_update_finish (connection, res, &error); - - if (error != NULL) { - g_message ("Could not delete message channels: %s", error->message); - g_error_free (error); - return; - } - - delete_unbound_messages (miner); -} - -static void -delete_message_channels (TrackerMinerRSS *miner, - GArray *channel_ids) -{ - TrackerMinerRSSPrivate *priv; - GString *query, *ids_str; - GrssFeedChannel *channel; - gint i, id; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - ids_str = g_string_new (NULL); - query = g_string_new (NULL); - - for (i = 0; i < channel_ids->len; i++) { - id = g_array_index (channel_ids, gint, i); - if (i != 0) - g_string_append (ids_str, ","); - g_string_append_printf (ids_str, "%d", id); - - channel = g_hash_table_lookup (priv->channels, - GINT_TO_POINTER (id)); - - if (channel) { - g_hash_table_remove (priv->channel_updates, channel); - g_hash_table_remove (priv->channels, GINT_TO_POINTER (id)); - } - } - - g_string_append_printf (query, - "DELETE { ?msg nmo:communicationChannel ?chan }" - "WHERE { ?msg a mfo:FeedMessage;" - " nmo:communicationChannel ?chan ." - " FILTER (tracker:id(?chan) IN (%s))" - "}", ids_str->str); - - tracker_sparql_connection_update_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - query->str, G_PRIORITY_DEFAULT, - NULL, - delete_message_channels_cb, - miner); - g_string_free (ids_str, TRUE); - g_string_free (query, TRUE); -} - -static void -handle_deletes (TrackerMinerRSS *miner, - GVariantIter *iter) -{ - GArray *deleted = g_array_new (FALSE, FALSE, sizeof (gint)); - gint graph, subject, pred, object; - TrackerMinerRSSPrivate *priv; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - - while (g_variant_iter_next (iter, "(iiii)", - &graph, &subject, &pred, &object)) { - if (pred == priv->rdf_type_id && - object == priv->mfo_feed_channel_id) { - g_array_append_val (deleted, subject); - } - } - - if (deleted->len > 0) - delete_message_channels (miner, deleted); - - g_array_free (deleted, TRUE); -} - -static void -handle_updates (TrackerMinerRSS *miner, - GVariantIter *iter) -{ - GArray *updated = g_array_new (FALSE, FALSE, sizeof (gint)); - gint graph, subject, pred, object; - TrackerMinerRSSPrivate *priv; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - - while (g_variant_iter_next (iter, "(iiii)", - &graph, &subject, &pred, &object)) { - if (pred == priv->rdf_type_id && - object == priv->mfo_feed_channel_id) { - g_array_append_val (updated, subject); - } - } - - if (updated->len > 0) - retrieve_and_schedule_feeds (miner, updated); - - g_array_free (updated, TRUE); -} - -static void -graph_updated_cb (GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) -{ - TrackerMinerRSS *miner = TRACKER_MINER_RSS (user_data); - GVariantIter *deletes, *updates; - - g_variant_get (parameters, "(&sa(iiii)a(iiii))", NULL, &deletes, &updates); - handle_deletes (miner, deletes); - handle_updates (miner, updates); - g_variant_iter_free (deletes); - g_variant_iter_free (updates); -} - -static FeedChannelUpdateData * -feed_channel_update_data_new (TrackerMinerRSS *miner, - GrssFeedChannel *channel) -{ - FeedChannelUpdateData *fcud; - - fcud = g_slice_new0 (FeedChannelUpdateData); - fcud->miner = g_object_ref (miner); - fcud->channel = g_object_ref (channel); - fcud->timeout_id = g_timeout_add_seconds (2, feed_channel_changed_timeout_cb, fcud); - fcud->cancellable = g_cancellable_new (); - - return fcud; -} - -static void -feed_channel_update_data_free (FeedChannelUpdateData *fcud) -{ - if (!fcud) { - return; - } - - if (fcud->cancellable) { - g_cancellable_cancel (fcud->cancellable); - g_object_unref (fcud->cancellable); - } - - if (fcud->timeout_id) { - g_source_remove (fcud->timeout_id); - } - - if (fcud->channel) { - g_object_unref (fcud->channel); - } - - if (fcud->miner) { - g_object_unref (fcud->miner); - } - - g_slice_free (FeedChannelUpdateData, fcud); -} - -static FeedItemListInsertData * -feed_item_list_insert_data_new (TrackerMinerRSS *miner, - GrssFeedChannel *channel, - GList *items) -{ - FeedItemListInsertData *data; - GrssFeedItem *prev; - const gchar *url; - GList *l; - - data = g_slice_new0 (FeedItemListInsertData); - data->channel = channel; - data->miner = miner; - data->items = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_object_unref); - - /* Make items unique, keep most recent */ - for (l = items; l; l = l->next) { - url = get_message_url (l->data); - prev = g_hash_table_lookup (data->items, url); - - if (prev) { - /* Compare publish times */ - if (grss_feed_item_get_publish_time (l->data) <= - grss_feed_item_get_publish_time (prev)) - continue; - } - - g_hash_table_insert (data->items, g_strdup (url), - g_object_ref (l->data)); - } - - return data; -} - -static void -feed_item_list_insert_data_free (FeedItemListInsertData *data) -{ - g_hash_table_destroy (data->items); - g_slice_free (FeedItemListInsertData, data); -} - -static void -feed_channel_change_updated_time_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - TrackerMinerRSSPrivate *priv; - FeedChannelUpdateData *fcud; - GError *error = NULL; - - fcud = user_data; - priv = TRACKER_MINER_RSS_GET_PRIVATE (fcud->miner); - - tracker_sparql_connection_update_finish (TRACKER_SPARQL_CONNECTION (source), result, &error); - if (error != NULL) { - g_critical ("Could not change feed channel updated time, %s", error->message); - g_error_free (error); - } - - /* This will clean up the fcud data too */ - g_hash_table_remove (priv->channel_updates, fcud->channel); -} - -static gboolean -feed_channel_changed_timeout_cb (gpointer user_data) -{ - TrackerSparqlBuilder *sparql; - FeedChannelUpdateData *fcud; - gchar *uri; - time_t now; - - fcud = user_data; - fcud->timeout_id = 0; - - now = time (NULL); - uri = g_object_get_data (G_OBJECT (fcud->channel), "subject"); - - g_message ("Updating mfo:updatedTime for channel '%s'", grss_feed_channel_get_title (fcud->channel)); - - /* I hope there will be soon a SPARQL command to just update a - * value instead to delete and re-insert it - */ - - sparql = tracker_sparql_builder_new_update (); - tracker_sparql_builder_delete_open (sparql, NULL); - tracker_sparql_builder_subject_iri (sparql, uri); - tracker_sparql_builder_predicate (sparql, "mfo:updatedTime"); - tracker_sparql_builder_object_variable (sparql, "unknown"); - tracker_sparql_builder_delete_close (sparql); - tracker_sparql_builder_where_open (sparql); - tracker_sparql_builder_subject_iri (sparql, uri); - tracker_sparql_builder_predicate (sparql, "mfo:updatedTime"); - tracker_sparql_builder_object_variable (sparql, "unknown"); - tracker_sparql_builder_where_close (sparql); - - tracker_sparql_builder_insert_open (sparql, NULL); - tracker_sparql_builder_subject_iri (sparql, uri); - tracker_sparql_builder_predicate (sparql, "mfo:updatedTime"); - tracker_sparql_builder_object_date (sparql, &now); - tracker_sparql_builder_insert_close (sparql); - - tracker_sparql_connection_update_async (tracker_miner_get_connection (TRACKER_MINER (fcud->miner)), - tracker_sparql_builder_get_result (sparql), - G_PRIORITY_DEFAULT, - fcud->cancellable, - feed_channel_change_updated_time_cb, - fcud); - g_object_unref (sparql); - - return FALSE; -} - -static void -feed_channel_change_updated_time (TrackerMinerRSS *miner, - GrssFeedChannel *channel) -{ - TrackerMinerRSSPrivate *priv; - FeedChannelUpdateData *fcud; - - if (!channel) - return; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - - fcud = g_hash_table_lookup (priv->channel_updates, channel); - if (fcud) { - /* We already had an update for this channel in - * progress, so we just reset the timeout. - */ - g_source_remove (fcud->timeout_id); - fcud->timeout_id = g_timeout_add_seconds (2, - feed_channel_changed_timeout_cb, - fcud); - } else { - /* This is a new update for this channel */ - fcud = feed_channel_update_data_new (miner, channel); - g_hash_table_insert (priv->channel_updates, - fcud->channel, - fcud); - } -} - -static void -feed_fetching_cb (GrssFeedsPool *pool, - GrssFeedChannel *channel, - gpointer user_data) -{ - gint avail; - gdouble prog; - TrackerMinerRSS *miner; - TrackerMinerRSSPrivate *priv; - - miner = TRACKER_MINER_RSS (user_data); - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - avail = grss_feeds_pool_get_listened_num (priv->pool); - - priv->now_fetching++; - - if (priv->now_fetching > avail) - priv->now_fetching = avail; - - g_message ("Fetching channel details, source:'%s' (in progress: %d/%d)", - grss_feed_channel_get_source (channel), - priv->now_fetching, - avail); - - prog = ((gdouble) priv->now_fetching) / ((gdouble) avail); - g_object_set (miner, "progress", prog, "status", "Fetching…", NULL); -} - -static gchar * -sparql_add_website (TrackerSparqlBuilder *sparql, - const gchar *uri) -{ - gchar *website_urn; - - website_urn = tracker_sparql_escape_uri_printf ("urn:website:%s", uri); - - tracker_sparql_builder_insert_silent_open (sparql, NULL); - tracker_sparql_builder_subject_iri (sparql, website_urn); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nie:DataObject"); - tracker_sparql_builder_object (sparql, "nfo:Website"); - - tracker_sparql_builder_predicate (sparql, "nie:url"); - tracker_sparql_builder_object_unvalidated (sparql, uri); - - tracker_sparql_builder_insert_close (sparql); - - return website_urn; -} - -static void -sparql_add_contact (TrackerSparqlBuilder *sparql, - const gchar *alias, - GrssPerson *contact, - const gchar *website_urn, - gboolean is_iri) -{ - const gchar *name = grss_person_get_name (contact); - const gchar *email = grss_person_get_email (contact); - - tracker_sparql_builder_subject (sparql, alias); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nco:Contact"); - - tracker_sparql_builder_predicate (sparql, "nco:fullname"); - tracker_sparql_builder_object_unvalidated (sparql, name); - - if (email != NULL) { - tracker_sparql_builder_predicate (sparql, "nco:hasEmailAddress"); - - tracker_sparql_builder_object_blank_open (sparql); - - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nco:EmailAddress"); - - tracker_sparql_builder_predicate (sparql, "nco:emailAddress"); - tracker_sparql_builder_object_unvalidated (sparql, email); - tracker_sparql_builder_object_blank_close (sparql); - } - - if (website_urn) { - tracker_sparql_builder_predicate (sparql, "nco:websiteUrl"); - - if (is_iri) { - tracker_sparql_builder_object_iri (sparql, website_urn); - } else { - tracker_sparql_builder_object (sparql, website_urn); - } - } -} - -static void -sparql_add_enclosure (TrackerSparqlBuilder *sparql, - const gchar *subject, - GrssFeedEnclosure *enclosure) -{ - gchar *url; - gint length; - gchar * format; - - url = grss_feed_enclosure_get_url (enclosure); - length = grss_feed_enclosure_get_length (enclosure); - format = grss_feed_enclosure_get_format (enclosure); - - tracker_sparql_builder_subject (sparql, subject); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "mfo:Enclosure"); - tracker_sparql_builder_object (sparql, "nfo:RemoteDataObject"); - - tracker_sparql_builder_predicate (sparql, "mfo:remoteLink"); - tracker_sparql_builder_object_unvalidated (sparql, url); - - tracker_sparql_builder_predicate (sparql, "nfo:fileSize"); - tracker_sparql_builder_object_int64 (sparql, length); - - if (format != NULL) { - tracker_sparql_builder_predicate (sparql, "nie:mimeType"); - tracker_sparql_builder_object_unvalidated (sparql, format); - } - -} - -static gchar * -feed_message_create_update_channel_query (const gchar *item_urn, - GrssFeedItem *item) -{ - GrssFeedChannel *channel; - const gchar *channel_urn; - - channel = grss_feed_item_get_parent (item); - channel_urn = g_object_get_data (G_OBJECT (channel), "subject"); - - return g_strdup_printf ("INSERT SILENT { <%s> nmo:communicationChannel <%s> }", - item_urn, channel_urn); -} - -static gchar * -feed_message_create_delete_properties_query (const gchar *item_urn) -{ - return g_strdup_printf ("DELETE { <%s> ?p ?o }" - "WHERE { <%s> a mfo:FeedMessage ;" - " ?p ?o ." - " FILTER (?p != rdf:type &&" - " ?p != nmo:communicationChannel)" - "}", item_urn, item_urn); -} - -static TrackerSparqlBuilder * -feed_message_create_insert_builder (TrackerMinerRSS *miner, - GrssFeedItem *item, - const gchar *item_urn) -{ - time_t t; - gchar *uri; - const gchar *url; - GrssPerson *author; - gdouble latitude; - gdouble longitude; - const gchar *tmp_string; - TrackerSparqlBuilder *sparql; - GrssFeedChannel *channel; - gboolean has_geolocation; - const GList *contributors; - const GList *enclosures; - const GList *list, *l; - GList *contrib_aliases = NULL; - GList *enclosure_aliases = NULL; - GHashTable *websites; - GHashTable *enclosure_urls; - gboolean is_iri = FALSE; - gint i = 0; - - if (!item_urn) { - item_urn = "_:message"; - } else { - is_iri = TRUE; - } - - url = get_message_url (item); - g_message ("Inserting feed item for '%s'", url); - - websites = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_free); - g_hash_table_insert (websites, g_strdup (url), g_strdup (item_urn)); - - sparql = tracker_sparql_builder_new_update (); - author = grss_feed_item_get_author (item); - contributors = grss_feed_item_get_contributors (item); - channel = grss_feed_item_get_parent (item); - enclosures = grss_feed_item_get_enclosures (item); - - for (l = contributors; l; l = l->next) { - const gchar *person_url; - - person_url = grss_person_get_uri (l->data); - - if (!person_url) - continue; - - if (g_hash_table_lookup (websites, person_url)) - continue; - - g_hash_table_insert (websites, g_strdup (person_url), - sparql_add_website (sparql, person_url)); - } - - if (author && grss_person_get_uri (author)) { - const gchar *person_url; - - person_url = grss_person_get_uri (author); - - if (!g_hash_table_lookup (websites, person_url)) { - g_hash_table_insert (websites, g_strdup (person_url), - sparql_add_website (sparql, person_url)); - } - } - - has_geolocation = grss_feed_item_get_geo_point (item, &latitude, &longitude); - tracker_sparql_builder_insert_open (sparql, NULL); - - if (has_geolocation) { - g_message (" Geolocation, using longitude:%f, latitude:%f", - longitude, latitude); - - tracker_sparql_builder_subject (sparql, "_:location"); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "slo:GeoLocation"); - - tracker_sparql_builder_predicate (sparql, "slo:latitude"); - tracker_sparql_builder_object_double (sparql, latitude); - tracker_sparql_builder_predicate (sparql, "slo:longitude"); - tracker_sparql_builder_object_double (sparql, longitude); - } - - if (author != NULL) { - g_message (" Author:'%s'", grss_person_get_name (author)); - - if (grss_person_get_uri (author)) - tmp_string = g_hash_table_lookup (websites, grss_person_get_uri (author)); - else - tmp_string = NULL; - - sparql_add_contact (sparql, "_:author", author, tmp_string, - (tmp_string && tmp_string[0] != '_')); - } - - i = 0; - for (l = contributors; l; l = l->next) { - gchar *subject; - - g_debug (" Contributor:'%s'", grss_person_get_name (l->data)); - - subject = g_strdup_printf ("_:contrib%d", i++); - contrib_aliases = g_list_prepend (contrib_aliases, subject); - - if (grss_person_get_uri (l->data)) - tmp_string = g_hash_table_lookup (websites, grss_person_get_uri (l->data)); - else - tmp_string = NULL; - - sparql_add_contact (sparql, subject, l->data, tmp_string, - (tmp_string && tmp_string[0] != '_')); - - /* subject is not freed right now as it will be freed at the end of the - * method in a foreach loop over the contrib_aliases list */ - } - - enclosure_urls = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_free); - i = 0; - for (l = enclosures; l; l = l->next) { - gchar *subject; - gchar *url; - - url = grss_feed_enclosure_get_url (l->data); - - if (!g_hash_table_contains (enclosure_urls, url)) { - g_debug (" Enclosure:'%s'", url); - subject = g_strdup_printf ("_:enclosure%d", i++); - enclosure_aliases = g_list_prepend (enclosure_aliases, subject); - g_hash_table_insert (enclosure_urls, g_strdup (url), NULL); - - sparql_add_enclosure (sparql, subject, l->data); - - } - - /* subject is not freed right now as it will be freed at the end of the - * method in a foreach loop over the enclosure_aliases list */ - } - - if (is_iri) { - tracker_sparql_builder_subject_iri (sparql, item_urn); - } else { - tracker_sparql_builder_subject (sparql, item_urn); - } - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "mfo:FeedMessage"); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:RemoteDataObject"); - - if (has_geolocation == TRUE) { - tracker_sparql_builder_predicate (sparql, "slo:location"); - tracker_sparql_builder_object (sparql, "_:location"); - } - - tmp_string = grss_feed_item_get_title (item); - if (tmp_string != NULL) { - g_message (" Title:'%s'", tmp_string); - - tracker_sparql_builder_predicate (sparql, "nie:title"); - tracker_sparql_builder_object_unvalidated (sparql, tmp_string); - } - - if (author != NULL) { - tracker_sparql_builder_predicate (sparql, "nco:creator"); - tracker_sparql_builder_object (sparql, "_:author"); - } - - for (l = contrib_aliases; l; l = l->next) { - tracker_sparql_builder_predicate (sparql, "nco:contributor"); - tracker_sparql_builder_object (sparql, l->data); - } - - for (l = enclosure_aliases; l; l = l->next) { - tracker_sparql_builder_predicate (sparql, "mfo:enclosureList"); - tracker_sparql_builder_object (sparql, l->data); - } - - tmp_string = grss_feed_item_get_description (item); - if (tmp_string != NULL) { - gchar *plain_text; - - plain_text = parse_html_text (tmp_string); - tracker_sparql_builder_predicate (sparql, "nie:plainTextContent"); - tracker_sparql_builder_object_unvalidated (sparql, plain_text); - g_free (plain_text); - - tracker_sparql_builder_predicate (sparql, "nmo:htmlMessageContent"); - tracker_sparql_builder_object_unvalidated (sparql, tmp_string); - } - - if (url != NULL) { - tracker_sparql_builder_predicate (sparql, "nie:url"); - tracker_sparql_builder_object_unvalidated (sparql, url); - } - - /* TODO nmo:receivedDate and mfo:downloadedTime are the same? - * Ask for the MFO maintainer */ - - t = time (NULL); - - tracker_sparql_builder_predicate (sparql, "nmo:receivedDate"); - tracker_sparql_builder_object_date (sparql, &t); - - tracker_sparql_builder_predicate (sparql, "mfo:downloadedTime"); - tracker_sparql_builder_object_date (sparql, &t); - - t = grss_feed_item_get_publish_time (item); - tracker_sparql_builder_predicate (sparql, "nie:contentCreated"); - tracker_sparql_builder_object_date (sparql, &t); - - tracker_sparql_builder_predicate (sparql, "nmo:isRead"); - tracker_sparql_builder_object_boolean (sparql, FALSE); - - uri = g_object_get_data (G_OBJECT (channel), "subject"); - tracker_sparql_builder_predicate (sparql, "nmo:communicationChannel"); - tracker_sparql_builder_object_iri (sparql, uri); - - tmp_string = grss_feed_item_get_copyright (item); - if (tmp_string) { - tracker_sparql_builder_predicate (sparql, "nie:copyright"); - tracker_sparql_builder_object_unvalidated (sparql, tmp_string); - } - - list = grss_feed_item_get_categories (item); - for (l = list; l; l = l->next) { - tracker_sparql_builder_predicate (sparql, "nie:keyword"); - tracker_sparql_builder_object_unvalidated (sparql, l->data); - } - - tracker_sparql_builder_insert_close (sparql); - - g_list_free_full (contrib_aliases, g_free); - g_list_free_full (enclosure_aliases, g_free); - g_hash_table_destroy (websites); - g_hash_table_destroy (enclosure_urls); - - return sparql; -} - -static void -feed_channel_content_update_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - TrackerSparqlConnection *connection; - GPtrArray *errors, *array = user_data; - GError *error = NULL; - guint i; - - connection = TRACKER_SPARQL_CONNECTION (source); - errors = tracker_sparql_connection_update_array_finish (connection, - result, &error); - - if (error) { - g_warning ("Could not update feed items: %s", - error->message); - g_error_free (error); - } else { - for (i = 0; i < errors->len; i++) { - GError *error = g_ptr_array_index (errors, i); - - if (!error) - continue; - - g_warning ("Error in item %d of update: %s\nQuery: %s", i, - error->message, (gchar *) g_ptr_array_index (array, i)); - } - - g_ptr_array_unref (errors); - } - - g_ptr_array_unref (array); -} - -static void -check_feed_items_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - TrackerSparqlConnection *connection; - TrackerSparqlBuilder *sparql; - FeedItemListInsertData *data; - TrackerSparqlCursor *cursor; - GrssFeedItem *item; - GError *error = NULL; - GHashTableIter iter; - GPtrArray *array; - const gchar *str; - - data = user_data; - connection = TRACKER_SPARQL_CONNECTION (source_object); - cursor = tracker_sparql_connection_query_finish (connection, res, &error); - array = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); - - while (!error && tracker_sparql_cursor_next (cursor, NULL, &error)) { - const gchar *urn, *url, *date; - time_t time; - - urn = tracker_sparql_cursor_get_string (cursor, 0, NULL); - url = tracker_sparql_cursor_get_string (cursor, 1, NULL); - date = tracker_sparql_cursor_get_string (cursor, 2, NULL); - time = (time_t) tracker_string_to_date (date, NULL, NULL); - - item = g_hash_table_lookup (data->items, url); - - if (!item) - continue; - - if (time <= grss_feed_item_get_publish_time (item)) { - g_debug ("Item '%s' already up to date", url); - g_ptr_array_add (array, feed_message_create_update_channel_query (urn, item)); - } else { - g_debug ("Updating item '%s'", url); - - g_ptr_array_add (array, feed_message_create_delete_properties_query (urn)); - - sparql = feed_message_create_insert_builder (data->miner, - item, urn); - str = tracker_sparql_builder_get_result (sparql); - g_ptr_array_add (array, g_strdup (str)); - g_object_unref (sparql); - } - - g_hash_table_remove (data->items, url); - } - - if (cursor) { - g_object_unref (cursor); - } - - if (error) { - g_message ("Could check feed items, %s", error->message); - g_error_free (error); - feed_item_list_insert_data_free (data); - g_ptr_array_unref (array); - return; - } - - g_hash_table_iter_init (&iter, data->items); - - /* Insert all remaining items as new */ - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &item)) { - sparql = feed_message_create_insert_builder (data->miner, - item, NULL); - str = tracker_sparql_builder_get_result (sparql); - g_ptr_array_add (array, g_strdup (str)); - g_object_unref (sparql); - } - - if (array->len == 0) { - feed_item_list_insert_data_free (data); - g_ptr_array_unref (array); - return; - } - - tracker_sparql_connection_update_array_async (tracker_miner_get_connection (TRACKER_MINER (data->miner)), - (gchar **) array->pdata, - array->len, - G_PRIORITY_DEFAULT, NULL, - feed_channel_content_update_cb, - array); - feed_channel_change_updated_time (data->miner, data->channel); - feed_item_list_insert_data_free (data); -} - -static void -check_feed_items (TrackerMinerRSS *miner, - GrssFeedChannel *channel, - GList *items) -{ - FeedItemListInsertData *data; - GHashTableIter iter; - GrssFeedItem *item; - gboolean first = TRUE; - const gchar *url; - GString *query; - - data = feed_item_list_insert_data_new (miner, channel, items); - g_hash_table_iter_init (&iter, data->items); - - query = g_string_new ("SELECT ?msg nie:url(?msg)" - " nie:contentCreated(?msg) {" - " ?msg a rdfs:Resource ." - " FILTER (nie:url(?msg) IN ("); - - while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &item)) { - if (!first) - g_string_append_c (query, ','); - - url = get_message_url (item); - g_string_append_printf (query, "\"%s\"", url); - first = FALSE; - } - - g_string_append (query, "))}"); - - tracker_sparql_connection_query_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - query->str, NULL, - check_feed_items_cb, - data); - g_string_free (query, TRUE); -} - -static void -update_feed_channel_info (TrackerMinerRSS *miner, - GrssFeedChannel *channel) -{ - const gchar *subject, *str; - GString *update; - gchar *escaped; - time_t time; - - g_debug ("Updating mfo:FeedChannel for '%s'", - grss_feed_channel_get_title (channel)); - - subject = g_object_get_data (G_OBJECT (channel), "subject"); - update = g_string_new ("INSERT OR REPLACE { "); - - str = grss_feed_channel_get_title (channel); - if (str) { - escaped = tracker_sparql_escape_string (str); - g_string_append_printf (update, "<%s> nie:title \"%s\".", subject, escaped); - g_free (escaped); - } - - str = grss_feed_channel_get_format (channel); - if (str) { - escaped = tracker_sparql_escape_string (str); - g_string_append_printf (update, - "<%s> mfo:type [ a mfo:FeedType ;" - " mfo:name \"%s\"].", - subject, escaped); - g_free (escaped); - } - - str = grss_feed_channel_get_description (channel); - if (str) { - escaped = tracker_sparql_escape_string (str); - g_string_append_printf (update, "<%s> nie:description \"%s\".", subject, escaped); - g_free (escaped); - } - - str = grss_feed_channel_get_image (channel); - if (str) { - g_string_append_printf (update, "<%s> mfo:image \"%s\".", subject, str); - } - - str = grss_feed_channel_get_copyright (channel); - if (str) { - escaped = tracker_sparql_escape_string (str); - g_string_append_printf (update, "<%s> nie:copyright \"%s\".", subject, escaped); - g_free (escaped); - } - - time = grss_feed_channel_get_publish_time (channel); - - if (time != 0) { - escaped = tracker_date_to_string (time); - g_string_append_printf (update, "<%s> nmo:lastMessageDate \"%s\".", subject, escaped); - g_free (escaped); - } - - g_string_append (update, "}"); - - tracker_sparql_connection_update_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - update->str, G_PRIORITY_DEFAULT, - NULL, NULL, NULL); - g_string_free (update, TRUE); -} - -static void -feed_ready_cb (GrssFeedsPool *pool, - GrssFeedChannel *channel, - GList *items, - gpointer user_data) -{ - TrackerMinerRSS *miner; - TrackerMinerRSSPrivate *priv; - - miner = TRACKER_MINER_RSS (user_data); - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - - priv->now_fetching--; - - g_debug ("Feed fetched, %d remaining", priv->now_fetching); - - if (priv->now_fetching <= 0) { - priv->now_fetching = 0; - g_object_set (miner, "progress", 1.0, "status", "Idle", NULL); - } - - if (items == NULL) { - return; - } - - update_feed_channel_info (miner, channel); - - g_message ("Verifying channel:'%s' is up to date", - grss_feed_channel_get_title (channel)); - - check_feed_items (miner, channel, items); -} - -static void -feeds_retrieve_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - GList *channels; - TrackerSparqlCursor *cursor; - GError *error = NULL; - TrackerMinerRSSPrivate *priv; - GrssFeedChannel *chan; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (user_data); - cursor = tracker_sparql_connection_query_finish (TRACKER_SPARQL_CONNECTION (source_object), - res, - &error); - - if (error != NULL) { - g_message ("Could not retrieve feeds, %s", error->message); - g_error_free (error); - if (cursor) { - g_object_unref (cursor); - } - return; - } - - while (tracker_sparql_cursor_next (cursor, NULL, NULL)) { - const gchar *source; - const gchar *title; - const gchar *interval; - const gchar *subject; - gint mins, id; - - source = tracker_sparql_cursor_get_string (cursor, 0, NULL); - title = tracker_sparql_cursor_get_string (cursor, 1, NULL); - interval = tracker_sparql_cursor_get_string (cursor, 2, NULL); - subject = tracker_sparql_cursor_get_string (cursor, 3, NULL); - id = tracker_sparql_cursor_get_integer (cursor, 4); - - g_debug ("Indexing channel '%s'", source); - - if (g_hash_table_lookup (priv->channels, GINT_TO_POINTER (id))) - continue; - - chan = grss_feed_channel_new (); - g_object_set_data_full (G_OBJECT (chan), - "subject", - g_strdup (subject), - g_free); - grss_feed_channel_set_source (chan, g_strdup (source)); - - /* TODO How to manage feeds with an update mfo:updateInterval == 0 ? - * Here the interval is forced to be at least 1 minute, but perhaps those - * elements are to be considered "disabled" - */ - mins = strtoull (interval, NULL, 10); - if (mins <= 0) - mins = 1; - grss_feed_channel_set_update_interval (chan, mins); - - g_message (" '%s' (%s) - update interval of %s minutes", - title, - source, - interval); - - g_hash_table_insert (priv->channels, GINT_TO_POINTER (id), chan); - } - - if (g_hash_table_size (priv->channels) == 0) { - g_message ("No feeds set up, nothing more to do"); - } - - channels = g_hash_table_get_values (priv->channels); - grss_feeds_pool_listen (priv->pool, channels); - g_list_free (channels); - - g_object_unref (cursor); - - if (g_hash_table_size (priv->channels) == 0) { - g_object_set (user_data, "progress", 1.0, "status", "Idle", NULL); - } -} - -static void -retrieve_and_schedule_feeds (TrackerMinerRSS *miner, - GArray *channel_ids) -{ - GString *sparql; - gint i, id; - - g_message ("Retrieving and scheduling feeds..."); - - sparql = g_string_new ("SELECT ?url nie:title(?urn) ?interval ?urn tracker:id(?urn)" - "WHERE {" - " ?urn a mfo:FeedChannel ; " - " mfo:feedSettings ?settings ; " - " nie:url ?url . " - " ?settings mfo:updateInterval ?interval "); - - if (channel_ids && channel_ids->len > 0) { - g_string_append (sparql, ". FILTER (tracker:id(?urn) IN ("); - - for (i = 0; i < channel_ids->len; i++) { - id = g_array_index (channel_ids, gint, i); - if (i != 0) - g_string_append (sparql, ","); - g_string_append_printf (sparql, "%d", id); - } - - g_string_append (sparql, "))"); - } - - g_string_append_printf (sparql, "}"); - - tracker_sparql_connection_query_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - sparql->str, - NULL, - feeds_retrieve_cb, - miner); - g_string_free (sparql, TRUE); -} - -static const gchar * -get_message_url (GrssFeedItem *item) -{ - const gchar *url; - - grss_feed_item_get_real_source (item, &url, NULL); - if (url == NULL) - url = grss_feed_item_get_source (item); - return url; -} - -static void -miner_started (TrackerMiner *miner) -{ - TrackerMinerRSSPrivate *priv; - TrackerSparqlConnection *conn; - - g_object_set (miner, "progress", 0.0, "status", "Initializing", NULL); - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - conn = tracker_miner_get_connection (miner); - priv->rdf_type_id = get_class_id (conn, "rdf:type"); - priv->mfo_feed_channel_id = get_class_id (conn, "mfo:FeedChannel"); - retrieve_and_schedule_feeds (TRACKER_MINER_RSS (miner), NULL); - grss_feeds_pool_switch (priv->pool, TRUE); -} - -static void -miner_stopped (TrackerMiner *miner) -{ - TrackerMinerRSSPrivate *priv; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - grss_feeds_pool_switch (priv->pool, FALSE); - g_object_set (miner, "progress", 1.0, "status", "Idle", NULL); -} - -static void -miner_paused (TrackerMiner *miner) -{ - TrackerMinerRSSPrivate *priv; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - grss_feeds_pool_switch (priv->pool, FALSE); - - /* Save last status */ - g_free (priv->last_status); - g_object_get (miner, "status", &priv->last_status, NULL); - - /* Set paused */ - g_object_set (miner, "status", "Paused", NULL); -} - -static void -miner_resumed (TrackerMiner *miner) -{ - TrackerMinerRSSPrivate *priv; - - priv = TRACKER_MINER_RSS_GET_PRIVATE (miner); - grss_feeds_pool_switch (priv->pool, TRUE); - - /* Resume */ - g_object_set (miner, "status", priv->last_status ? priv->last_status : "Idle", NULL); -} - -TrackerMinerRSS * -tracker_miner_rss_new (GError **error) -{ - return g_initable_new (TRACKER_TYPE_MINER_RSS, - NULL, - error, - NULL); -} diff --git a/src/miners/rss/tracker-miner-rss.desktop.in.in b/src/miners/rss/tracker-miner-rss.desktop.in.in deleted file mode 100644 index 49be40191..000000000 --- a/src/miners/rss/tracker-miner-rss.desktop.in.in +++ /dev/null @@ -1,18 +0,0 @@ -[Desktop Entry] -_Name=Tracker RSS/ATOM Feeds Miner -_Comment=Fetch RSS/ATOM feeds -Icon= -Exec=@libexecdir@/tracker-miner-rss -Terminal=false -Type=Application -Categories=Utility; -X-GNOME-Autostart-enabled=false -X-KDE-autostart-after=panel -X-KDE-StartupNotify=false -X-KDE-UniqueApplet=true -NoDisplay=true -OnlyShowIn=GNOME;KDE;XFCE;Unity; -X-GNOME-Bugzilla-Bugzilla=GNOME -X-GNOME-Bugzilla-Product=tracker -X-GNOME-Bugzilla-Component=Miners -X-GNOME-Bugzilla-Version=@VERSION@ diff --git a/src/miners/rss/tracker-miner-rss.h b/src/miners/rss/tracker-miner-rss.h deleted file mode 100644 index 2271ec9da..000000000 --- a/src/miners/rss/tracker-miner-rss.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2009/2010, Roberto Guido <madbob@users.barberaware.org> - * Michele Tameni <michele@amdplanet.it> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_MINER_RSS_H__ -#define __TRACKER_MINER_RSS_H__ - -#include <libtracker-miner/tracker-miner.h> - -#include <libtracker-sparql/tracker-sparql.h> - -G_BEGIN_DECLS - -#define TRACKER_TYPE_MINER_RSS (tracker_miner_rss_get_type()) -#define TRACKER_MINER_RSS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_MINER_RSS, TrackerMinerRSS)) -#define TRACKER_MINER_RSS_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_MINER_RSS, TrackerMinerRSSClass)) -#define TRACKER_IS_MINER_RSS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_MINER_RSS)) -#define TRACKER_IS_MINER_RSS_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_MINER_RSS)) -#define TRACKER_MINER_RSS_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_MINER_RSS, TrackerMinerRSSClass)) - -typedef struct _TrackerMinerRSS TrackerMinerRSS; -typedef struct _TrackerMinerRSSClass TrackerMinerRSSClass; - -struct _TrackerMinerRSS { - TrackerMinerOnline parent; -}; - -struct _TrackerMinerRSSClass { - TrackerMinerOnlineClass parent; -}; - -GType tracker_miner_rss_get_type (void) G_GNUC_CONST; -TrackerMinerRSS *tracker_miner_rss_new (GError **error); - -G_END_DECLS - -#endif /* __TRACKER_MINER_RSS_H__ */ diff --git a/src/miners/rss/tracker-miner-rss.service.in b/src/miners/rss/tracker-miner-rss.service.in deleted file mode 100644 index 2bebf4cf5..000000000 --- a/src/miners/rss/tracker-miner-rss.service.in +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Tracker RSS/ATOM feed data miner - -[Service] -Type=dbus -BusName=org.freedesktop.Tracker1.Miner.RSS -ExecStart=@libexecdir@/tracker-miner-rss -Restart=on-failure -# Don't restart after tracker daemon -k (aka tracker-control -k) -RestartPreventExitStatus=SIGKILL diff --git a/src/tracker-extract/.gitignore b/src/tracker-extract/.gitignore deleted file mode 100644 index 7681b5af5..000000000 --- a/src/tracker-extract/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -tracker-extract -tracker-extract-priority-dbus-stamp -tracker-extract-priority-dbus.c -tracker-extract-priority-dbus.h -*.service -*.xml -*.valid -*.cfg.5 diff --git a/src/tracker-extract/10-abw.rule b/src/tracker-extract/10-abw.rule deleted file mode 100644 index 6702e0d86..000000000 --- a/src/tracker-extract/10-abw.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-abw.so -MimeTypes=application/x-abiword -FallbackRdfTypes=nfo:Document diff --git a/src/tracker-extract/10-bmp.rule b/src/tracker-extract/10-bmp.rule deleted file mode 100644 index 7ce022d7d..000000000 --- a/src/tracker-extract/10-bmp.rule +++ /dev/null @@ -1,5 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-bmp.so -MimeTypes=image/bmp -FallbackRdfTypes=nfo:Image;nmm:Photo; - diff --git a/src/tracker-extract/10-comics.rule b/src/tracker-extract/10-comics.rule deleted file mode 100644 index 9d2d05c02..000000000 --- a/src/tracker-extract/10-comics.rule +++ /dev/null @@ -1,3 +0,0 @@ -[ExtractorRule] -MimeTypes=application/x-cbr;application/x-cbz;application/x-cbt;application/x-cb7;application/vnd.comicbook+zip; -FallbackRdfTypes=nfo:EBook; diff --git a/src/tracker-extract/10-dvi.rule b/src/tracker-extract/10-dvi.rule deleted file mode 100644 index 5ce40af8d..000000000 --- a/src/tracker-extract/10-dvi.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-dvi.so -MimeTypes=application/x-dvi -FallbackRdfTypes=nfo:Document diff --git a/src/tracker-extract/10-ebooks.rule b/src/tracker-extract/10-ebooks.rule deleted file mode 100644 index d7a03d697..000000000 --- a/src/tracker-extract/10-ebooks.rule +++ /dev/null @@ -1,3 +0,0 @@ -[ExtractorRule] -MimeTypes=application/x-zip-compressed-fb2;application/x-fictionbook+xml;application/x-mobipocket-ebook;image/vnd.djvu+multipage; -FallbackRdfTypes=nfo:EBook;nfo:PaginatedTextDocument; diff --git a/src/tracker-extract/10-epub.rule b/src/tracker-extract/10-epub.rule deleted file mode 100644 index d19ebd637..000000000 --- a/src/tracker-extract/10-epub.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-epub.so -MimeTypes=application/epub+zip -FallbackRdfTypes=nfo:EBook;nfo:TextDocument; diff --git a/src/tracker-extract/10-flac.rule b/src/tracker-extract/10-flac.rule deleted file mode 100644 index 150301c07..000000000 --- a/src/tracker-extract/10-flac.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-flac.so -MimeTypes=audio/x-flac -FallbackRdfTypes=nmm:MusicPiece;nfo:Audio; diff --git a/src/tracker-extract/10-gif.rule b/src/tracker-extract/10-gif.rule deleted file mode 100644 index a88780b8e..000000000 --- a/src/tracker-extract/10-gif.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-gif.so -MimeTypes=image/gif -FallbackRdfTypes=nfo:Image;nmm:Photo; diff --git a/src/tracker-extract/10-html.rule b/src/tracker-extract/10-html.rule deleted file mode 100644 index e26f356f2..000000000 --- a/src/tracker-extract/10-html.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-html.so -MimeTypes=text/html;application/xhtml+xml; -FallbackRdfTypes=nfo:HtmlDocument diff --git a/src/tracker-extract/10-ico.rule b/src/tracker-extract/10-ico.rule deleted file mode 100644 index 47d71a19d..000000000 --- a/src/tracker-extract/10-ico.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-icon.so -MimeTypes=image/vnd.microsoft.icon -FallbackRdfTypes=nfo:Image;nfo:Icon; diff --git a/src/tracker-extract/10-jpeg.rule b/src/tracker-extract/10-jpeg.rule deleted file mode 100644 index 424d9e498..000000000 --- a/src/tracker-extract/10-jpeg.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-jpeg.so -MimeTypes=image/jpeg -FallbackRdfTypes=nfo:Image;nmm:Photo; diff --git a/src/tracker-extract/10-mp3.rule b/src/tracker-extract/10-mp3.rule deleted file mode 100644 index 015f798b2..000000000 --- a/src/tracker-extract/10-mp3.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-mp3.so -MimeTypes=audio/mpeg;audio/x-mp3; -FallbackRdfTypes=nmm:MusicPiece;nfo:Audio; diff --git a/src/tracker-extract/10-msoffice.rule b/src/tracker-extract/10-msoffice.rule deleted file mode 100644 index d65bcc04c..000000000 --- a/src/tracker-extract/10-msoffice.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-msoffice.so -MimeTypes=application/vnd.ms-word;application/vnd.ms-word.*;application/vnd.ms-powerpoint;application/vnd.ms-excel;application/vnd.ms-access;application/vnd.ms-publisher;application/vnd.ms-tnef;application/vnd.ms-word;application/vnd.ms-works;application/vnd.ms-wpl;application/msword; -FallbackRdfTypes=nfo:Document diff --git a/src/tracker-extract/10-oasis.rule b/src/tracker-extract/10-oasis.rule deleted file mode 100644 index d49f7bf54..000000000 --- a/src/tracker-extract/10-oasis.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-oasis.so -MimeTypes=application/vnd.oasis.opendocument.* -FallbackRdfTypes=nfo:PaginatedTextDocument diff --git a/src/tracker-extract/10-pdf.rule b/src/tracker-extract/10-pdf.rule deleted file mode 100644 index d9f2f49c8..000000000 --- a/src/tracker-extract/10-pdf.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-pdf.so -MimeTypes=application/pdf -FallbackRdfTypes=nfo:PaginatedTextDocument diff --git a/src/tracker-extract/10-png.rule b/src/tracker-extract/10-png.rule deleted file mode 100644 index c97a46aea..000000000 --- a/src/tracker-extract/10-png.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-png.so -MimeTypes=image/png;sketch/png; -FallbackRdfTypes=nfo:Image;nmm:Photo; diff --git a/src/tracker-extract/10-ps.rule b/src/tracker-extract/10-ps.rule deleted file mode 100644 index 874ceb16a..000000000 --- a/src/tracker-extract/10-ps.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-ps.so -MimeTypes=application/x-gzpostscript;application/postscript; -FallbackRdfTypes=nfo:PaginatedTextDocument diff --git a/src/tracker-extract/10-svg.rule b/src/tracker-extract/10-svg.rule deleted file mode 100644 index bff464413..000000000 --- a/src/tracker-extract/10-svg.rule +++ /dev/null @@ -1,3 +0,0 @@ -[ExtractorRule] -MimeTypes=image/svg+xml;image/svg+xml-compressed; -FallbackRdfTypes=nfo:Image;nfo:VectorImage; diff --git a/src/tracker-extract/10-tiff.rule b/src/tracker-extract/10-tiff.rule deleted file mode 100644 index ce331944d..000000000 --- a/src/tracker-extract/10-tiff.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-tiff.so -MimeTypes=image/tiff -FallbackRdfTypes=nfo:Image;nmm:Photo; diff --git a/src/tracker-extract/10-vorbis.rule b/src/tracker-extract/10-vorbis.rule deleted file mode 100644 index 48f99817e..000000000 --- a/src/tracker-extract/10-vorbis.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-vorbis.so -MimeTypes=audio/x-vorbis+ogg;application/ogg; -FallbackRdfTypes=nmm:MusicPiece;nfo:Audio; diff --git a/src/tracker-extract/10-xmp.rule b/src/tracker-extract/10-xmp.rule deleted file mode 100644 index e9288db52..000000000 --- a/src/tracker-extract/10-xmp.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-xmp.so -MimeTypes=application/rdf+xml - diff --git a/src/tracker-extract/10-xps.rule b/src/tracker-extract/10-xps.rule deleted file mode 100644 index 6bfdd2703..000000000 --- a/src/tracker-extract/10-xps.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-xps.so -MimeTypes=application/oxps;application/vnd.ms-xpsdocument; -FallbackRdfTypes=nfo:PaginatedTextDocument diff --git a/src/tracker-extract/11-iso.rule b/src/tracker-extract/11-iso.rule deleted file mode 100644 index 3a5c69ec6..000000000 --- a/src/tracker-extract/11-iso.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-iso.so -MimeTypes=application/x-cd-image -FallbackRdfTypes=nfo:FilesystemImage diff --git a/src/tracker-extract/11-msoffice-xml.rule b/src/tracker-extract/11-msoffice-xml.rule deleted file mode 100644 index 5df19f0e7..000000000 --- a/src/tracker-extract/11-msoffice-xml.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-msoffice-xml.so -MimeTypes=application/vnd.openxmlformats-officedocument.presentationml.presentation;application/vnd.openxmlformats-officedocument.presentationml.slideshow;application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;application/vnd.openxmlformats-officedocument.wordprocessingml.document; -FallbackRdfTypes=nfo:PaginatedTextDocument diff --git a/src/tracker-extract/15-gstreamer-guess.rule b/src/tracker-extract/15-gstreamer-guess.rule deleted file mode 100644 index ad71d03e7..000000000 --- a/src/tracker-extract/15-gstreamer-guess.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-gstreamer.so -MimeTypes=video/3gpp;video/mp4;video/x-ms-asf;application/vnd.ms-asf;application/vnd.rn-realmedia; -FallbackRdfTypes=nfo:Media;nfo:Video; diff --git a/src/tracker-extract/15-playlist.rule b/src/tracker-extract/15-playlist.rule deleted file mode 100644 index 8804f8708..000000000 --- a/src/tracker-extract/15-playlist.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-playlist.so -MimeTypes=audio/x-mpegurl;audio/mpegurl;audio/x-scpls;audio/x-pn-realaudio;application/ram;application/vnd.ms-wpl;application/smil;audio/x-ms-asx; -FallbackRdfTypes=nmm:Playlist;nfo:MediaList; diff --git a/src/tracker-extract/15-source-code.rule b/src/tracker-extract/15-source-code.rule deleted file mode 100644 index 60cde8bcd..000000000 --- a/src/tracker-extract/15-source-code.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-text.so -MimeTypes=text/x-csrc;text/x-c++src;text/x-chdr;text/x-vala;text/x-java;application/javascript;application/x-php;text/x-python;application/x-perl;application/x-shellscript;text/x-fortran;text/x-pascal; -FallbackRdfTypes=nfo:SourceCode;nfo:PlainTextDocument; diff --git a/src/tracker-extract/90-gstreamer-audio-generic.rule b/src/tracker-extract/90-gstreamer-audio-generic.rule deleted file mode 100644 index 4355f2c2a..000000000 --- a/src/tracker-extract/90-gstreamer-audio-generic.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-gstreamer.so -MimeTypes=audio/*; -FallbackRdfTypes=nmm:MusicPiece;nfo:Audio; diff --git a/src/tracker-extract/90-gstreamer-image-generic.rule b/src/tracker-extract/90-gstreamer-image-generic.rule deleted file mode 100644 index 642c3e0da..000000000 --- a/src/tracker-extract/90-gstreamer-image-generic.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-gstreamer.so -MimeTypes=image/*; -FallbackRdfTypes=nfo:Image;nmm:Photo; diff --git a/src/tracker-extract/90-gstreamer-video-generic.rule b/src/tracker-extract/90-gstreamer-video-generic.rule deleted file mode 100644 index 3d9e46217..000000000 --- a/src/tracker-extract/90-gstreamer-video-generic.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-gstreamer.so -MimeTypes=video/*; -FallbackRdfTypes=nmm:Video; diff --git a/src/tracker-extract/90-libav-audio-generic.rule b/src/tracker-extract/90-libav-audio-generic.rule deleted file mode 100644 index 59e94842c..000000000 --- a/src/tracker-extract/90-libav-audio-generic.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-libav.so -MimeTypes=audio/*; -FallbackRdfTypes=nmm:MusicPiece;nfo:Audio; diff --git a/src/tracker-extract/90-libav-video-generic.rule b/src/tracker-extract/90-libav-video-generic.rule deleted file mode 100644 index 675540c62..000000000 --- a/src/tracker-extract/90-libav-video-generic.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-libav.so -MimeTypes=video/*; -FallbackRdfTypes=nmm:Video; diff --git a/src/tracker-extract/90-text-generic.rule b/src/tracker-extract/90-text-generic.rule deleted file mode 100644 index e2fd5928b..000000000 --- a/src/tracker-extract/90-text-generic.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-text.so -MimeTypes=text/* -FallbackRdfTypes=nfo:Document;nfo:PlainTextDocument; diff --git a/src/tracker-extract/91-gstreamer-generic-dlna.rule b/src/tracker-extract/91-gstreamer-generic-dlna.rule deleted file mode 100644 index b25e84c34..000000000 --- a/src/tracker-extract/91-gstreamer-generic-dlna.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-gstreamer.so -MimeTypes=dlna/*; - diff --git a/src/tracker-extract/Makefile.am b/src/tracker-extract/Makefile.am deleted file mode 100644 index 9fd58564d..000000000 --- a/src/tracker-extract/Makefile.am +++ /dev/null @@ -1,637 +0,0 @@ -# -# _RULES_DIR = $(datadir)/tracker/extract-rules -# -rulesdir = $(TRACKER_EXTRACT_RULES_DIR) - -module_flags = $(DTAGS_LDFLAGS) -module -avoid-version -no-undefined - -AM_CPPFLAGS = \ - $(BUILD_CFLAGS) \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - -DLOCALEDIR=\""$(localedir)"\" \ - -DTRACKER_EXTRACTORS_DIR=\""$(TRACKER_EXTRACT_MODULES_DIR)"\" \ - $(TRACKER_EXTRACT_CFLAGS) - -# NOTE: The rules are here and not in another sub-directory because we -# only install rules for extractors we build. If we decouple this, it -# duplicates work and requires more maintenance to keep modules up to -# date. If you are adding a new rule then add it to both rules_files -# and then separately with the module below. -rules_files = \ - 10-abw.rule \ - 10-dvi.rule \ - 10-epub.rule \ - 10-flac.rule \ - 10-gif.rule \ - 10-html.rule \ - 10-ico.rule \ - 10-jpeg.rule \ - 10-mp3.rule \ - 10-msoffice.rule \ - 10-oasis.rule \ - 10-pdf.rule \ - 10-png.rule \ - 10-ps.rule \ - 10-svg.rule \ - 10-tiff.rule \ - 10-vorbis.rule \ - 10-xmp.rule \ - 10-xps.rule \ - 10-bmp.rule \ - 10-ebooks.rule \ - 10-comics.rule \ - 11-iso.rule \ - 11-msoffice-xml.rule \ - 15-gstreamer-guess.rule \ - 15-playlist.rule \ - 15-source-code.rule \ - 90-gstreamer-image-generic.rule \ - 90-gstreamer-audio-generic.rule \ - 90-gstreamer-video-generic.rule \ - 90-text-generic.rule \ - 90-libav-audio-generic.rule \ - 90-libav-video-generic.rule \ - 91-gstreamer-generic-dlna.rule - -# NOTE: -# We don't always link with libtracker-common, we only link -# against it if we directly use functions in the .so -# -# _MODULES_DIR = $(libdir)/tracker-$(TRACKER_API_VERSION)/extract-modules -# -extractmodulesdir = $(TRACKER_EXTRACT_MODULES_DIR) -extractmodules_LTLIBRARIES = # Empty -rules_DATA = # Empty - -if HAVE_LIBVORBIS -extractmodules_LTLIBRARIES += libextract-vorbis.la -rules_DATA += 10-vorbis.rule -endif - -if HAVE_LIBFLAC -extractmodules_LTLIBRARIES += libextract-flac.la -rules_DATA += 10-flac.rule -endif - -if HAVE_EXEMPI -extractmodules_LTLIBRARIES += libextract-xmp.la -rules_DATA += 10-xmp.rule -endif - -if HAVE_LIBGIF -extractmodules_LTLIBRARIES += libextract-gif.la -rules_DATA += 10-gif.rule -endif - -if HAVE_LIBJPEG -extractmodules_LTLIBRARIES += libextract-jpeg.la -rules_DATA += 10-jpeg.rule -endif - -if HAVE_LIBTIFF -extractmodules_LTLIBRARIES += libextract-tiff.la -rules_DATA += 10-tiff.rule -endif - -if HAVE_LIBXML2 -extractmodules_LTLIBRARIES += libextract-html.la -rules_DATA += 10-html.rule -endif - -if HAVE_LIBGSF -extractmodules_LTLIBRARIES += \ - libextract-epub.la \ - libextract-msoffice.la \ - libextract-msoffice-xml.la \ - libextract-oasis.la -rules_DATA += 10-epub.rule 10-oasis.rule 10-msoffice.rule 11-msoffice-xml.rule -endif - -if HAVE_LIBGXPS -extractmodules_LTLIBRARIES += libextract-xps.la -rules_DATA += 10-xps.rule -endif - -if HAVE_POPPLER -extractmodules_LTLIBRARIES += libextract-pdf.la -rules_DATA += 10-pdf.rule -endif - -if HAVE_GSTREAMER -extractmodules_LTLIBRARIES += libextract-gstreamer.la -rules_DATA += 10-svg.rule 15-gstreamer-guess.rule 90-gstreamer-image-generic.rule 90-gstreamer-audio-generic.rule 90-gstreamer-video-generic.rule -endif - -# Gstreamer with GUPnP-DLNA backend? -if HAVE_GUPNP_DLNA -rules_DATA += 91-gstreamer-generic-dlna.rule -endif - -if HAVE_TOTEM_PL_PARSER -extractmodules_LTLIBRARIES += libextract-playlist.la -rules_DATA += 15-playlist.rule -endif - -if HAVE_LIBOSINFO -extractmodules_LTLIBRARIES += libextract-iso.la -rules_DATA += 11-iso.rule -endif - -if HAVE_LIBPNG -extractmodules_LTLIBRARIES += libextract-png.la -rules_DATA += 10-png.rule -endif - -if HAVE_ABIWORD -extractmodules_LTLIBRARIES += libextract-abw.la -rules_DATA += 10-abw.rule -endif - -if HAVE_DVI -extractmodules_LTLIBRARIES += libextract-dvi.la -rules_DATA += 10-dvi.rule -endif - -if HAVE_MP3 -extractmodules_LTLIBRARIES += libextract-mp3.la -rules_DATA += 10-mp3.rule -endif - -if HAVE_PS -extractmodules_LTLIBRARIES += libextract-ps.la -rules_DATA += 10-ps.rule -endif - -if HAVE_TEXT -extractmodules_LTLIBRARIES += libextract-text.la -rules_DATA += 15-source-code.rule 90-text-generic.rule -endif - -if HAVE_ICON -extractmodules_LTLIBRARIES += libextract-icon.la -rules_DATA += 10-ico.rule -endif - -if HAVE_LIBAV -extractmodules_LTLIBRARIES += libextract-libav.la -rules_DATA += 90-libav-audio-generic.rule 90-libav-video-generic.rule -endif - -extractmodules_LTLIBRARIES += libextract-bmp.la -rules_DATA += 10-bmp.rule - -extractmodules_LTLIBRARIES += libextract-dummy.la -# Rule files using the dummy extractor -rules_DATA += 10-comics.rule -rules_DATA += 10-ebooks.rule - -# ABW -libextract_abw_la_SOURCES = tracker-extract-abw.c -libextract_abw_la_CFLAGS = $(TRACKER_EXTRACT_MODULES_CFLAGS) -libextract_abw_la_LDFLAGS = $(module_flags) -libextract_abw_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) - -# MP3 -libextract_mp3_la_SOURCES = tracker-extract-mp3.c -libextract_mp3_la_CFLAGS = $(TRACKER_EXTRACT_MODULES_CFLAGS) -libextract_mp3_la_LDFLAGS = $(module_flags) -libextract_mp3_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) - -# Vorbis (OGG) -libextract_vorbis_la_SOURCES = tracker-extract-vorbis.c -libextract_vorbis_la_CFLAGS = $(TRACKER_EXTRACT_MODULES_CFLAGS) -libextract_vorbis_la_LDFLAGS = $(module_flags) -libextract_vorbis_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(LIBVORBIS_LIBS) - -# Flac -libextract_flac_la_SOURCES = tracker-extract-flac.c -libextract_flac_la_CFLAGS = $(TRACKER_EXTRACT_MODULES_CFLAGS) -libextract_flac_la_LDFLAGS = $(module_flags) -libextract_flac_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(LIBFLAC_LIBS) - -# Oasis -libextract_oasis_la_SOURCES = tracker-extract-oasis.c -libextract_oasis_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(LIBGSF_CFLAGS) -libextract_oasis_la_LDFLAGS = $(module_flags) -libextract_oasis_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(LIBGSF_LIBS) - -# EPub -libextract_epub_la_SOURCES = tracker-extract-epub.c -libextract_epub_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(LIBGSF_CFLAGS) -libextract_epub_la_LDFLAGS = $(module_flags) -libextract_epub_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(LIBGSF_LIBS) - -# PNG -libextract_png_la_SOURCES = tracker-extract-png.c -libextract_png_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(LIBPNG_CFLAGS) -libextract_png_la_LDFLAGS = $(module_flags) -libextract_png_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(LIBPNG_LIBS) - - -# PS -libextract_ps_la_SOURCES = tracker-extract-ps.c -libextract_ps_la_CFLAGS = $(TRACKER_EXTRACT_MODULES_CFLAGS) -libextract_ps_la_LDFLAGS = $(module_flags) -libextract_ps_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) - -# XMP -libextract_xmp_la_SOURCES = tracker-extract-xmp.c -libextract_xmp_la_CFLAGS = $(TRACKER_EXTRACT_MODULES_CFLAGS) -libextract_xmp_la_LDFLAGS = $(module_flags) -libextract_xmp_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) - -# HTML -libextract_html_la_SOURCES = tracker-extract-html.c -libextract_html_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(LIBXML2_CFLAGS) -libextract_html_la_LDFLAGS = $(module_flags) -libextract_html_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(LIBXML2_LIBS) - -# MS Office -libextract_msoffice_la_SOURCES = tracker-extract-msoffice.c -libextract_msoffice_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(LIBGSF_CFLAGS) -libextract_msoffice_la_LDFLAGS = $(module_flags) -libextract_msoffice_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(LIBGSF_LIBS) - -# MS Office XML -libextract_msoffice_xml_la_SOURCES = tracker-extract-msoffice-xml.c -libextract_msoffice_xml_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(LIBGSF_CFLAGS) -libextract_msoffice_xml_la_LDFLAGS = $(module_flags) -libextract_msoffice_xml_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) - -# XPS -libextract_xps_la_SOURCES = tracker-extract-xps.c -libextract_xps_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(LIBGXPS_CFLAGS) -libextract_xps_la_LDFLAGS = $(module_flags) -libextract_xps_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(LIBGXPS_LIBS) - -# PDF -libextract_pdf_la_SOURCES = tracker-extract-pdf.c -libextract_pdf_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(POPPLER_CFLAGS) -libextract_pdf_la_LDFLAGS = $(module_flags) -libextract_pdf_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(POPPLER_LIBS) - -# DVI -libextract_dvi_la_SOURCES = tracker-extract-dvi.c -libextract_dvi_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) -libextract_dvi_la_LDFLAGS = $(module_flags) -libextract_dvi_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) - -# GStreamer -libextract_gstreamer_la_SOURCES = \ - tracker-extract-gstreamer.c \ - tracker-cue-sheet.h \ - tracker-cue-sheet.c -libextract_gstreamer_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(GSTREAMER_CFLAGS) \ - $(LIBCUE_CFLAGS) -libextract_gstreamer_la_LDFLAGS = $(module_flags) -libextract_gstreamer_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(GSTREAMER_LIBS) \ - $(LIBCUE_LIBS) - -# GStreamer with GUPnP-DLNA backend? -if HAVE_GUPNP_DLNA -libextract_gstreamer_la_CFLAGS += $(GUPNP_DLNA_CFLAGS) -libextract_gstreamer_la_LIBADD += $(GUPNP_DLNA_LIBS) -endif - -# GStreamer with Discoverer backend? -if HAVE_GSTREAMER_PBUTILS -libextract_gstreamer_la_CFLAGS += $(GSTREAMER_PBUTILS_CFLAGS) -libextract_gstreamer_la_LIBADD += $(GSTREAMER_PBUTILS_LIBS) -endif - -# GIF -libextract_gif_la_SOURCES = tracker-extract-gif.c -libextract_gif_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(LIBGIF_CFLAGS) -libextract_gif_la_LDFLAGS = $(module_flags) -libextract_gif_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(LIBGIF_LIBS) - -# JPEG -libextract_jpeg_la_SOURCES = tracker-extract-jpeg.c -libextract_jpeg_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(LIBJPEG_CFLAGS) -libextract_jpeg_la_LDFLAGS = $(module_flags) -libextract_jpeg_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(LIBJPEG_LIBS) - -# TIFF -libextract_tiff_la_SOURCES = tracker-extract-tiff.c $(xmp_sources) $(iptc_sources) -libextract_tiff_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(LIBTIFF_CFLAGS) -libextract_tiff_la_LDFLAGS = $(module_flags) -libextract_tiff_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(LIBTIFF_LIBS) - -# Playlists using totem-pl-parser -libextract_playlist_la_SOURCES = tracker-extract-playlist.c -libextract_playlist_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(TOTEM_PL_PARSER_CFLAGS) -libextract_playlist_la_LDFLAGS = $(module_flags) -libextract_playlist_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(TOTEM_PL_PARSER_LIBS) - -# TEXT -libextract_text_la_SOURCES = tracker-extract-text.c -libextract_text_la_CFLAGS = $(TRACKER_EXTRACT_MODULES_CFLAGS) -libextract_text_la_LDFLAGS = $(module_flags) -libextract_text_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) - -# ICON -libextract_icon_la_SOURCES = tracker-extract-icon.c -libextract_icon_la_CFLAGS = $(TRACKER_EXTRACT_MODULES_CFLAGS) -libextract_icon_la_LDFLAGS = $(module_flags) -libextract_icon_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) - -# ISO -libextract_iso_la_SOURCES = tracker-extract-iso.c -libextract_iso_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(LIBOSINFO_CFLAGS) - -libextract_iso_la_LDFLAGS = $(module_flags) -libextract_iso_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(LIBOSINFO_LIBS) - -# libav -libextract_libav_la_SOURCES = tracker-extract-libav.c -libextract_libav_la_CFLAGS = $(TRACKER_EXTRACT_MODULES_CFLAGS) \ - $(AVFORMAT_CFLAGS) \ - $(AVUTIL_CFLAGS) \ - $(AVCODEC_CFLAGS) -libextract_libav_la_LDFLAGS = $(module_flags) -libextract_libav_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) \ - $(AVFORMAT_LIBS) \ - $(AVUTIL_LIBS) \ - $(AVCODEC_LIBS) - - -# BMP -libextract_bmp_la_SOURCES = tracker-extract-bmp.c -libextract_bmp_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) -libextract_bmp_la_LDFLAGS = $(module_flags) -libextract_bmp_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) - -# Dummy -libextract_dummy_la_SOURCES = tracker-extract-dummy.c -libextract_dummy_la_CFLAGS = \ - $(TRACKER_EXTRACT_MODULES_CFLAGS) -libextract_dummy_la_LDFLAGS = $(module_flags) -libextract_dummy_la_LIBADD = \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_MODULES_LIBS) - -libexec_PROGRAMS = tracker-extract - -tracker_extract_SOURCES = \ - tracker-config.c \ - tracker-config.h \ - tracker-extract.c \ - tracker-extract.h \ - tracker-extract-controller.c \ - tracker-extract-controller.h \ - tracker-extract-decorator.c \ - tracker-extract-decorator.h \ - tracker-extract-persistence.c \ - tracker-extract-persistence.h \ - tracker-extract-priority-dbus.c \ - tracker-extract-priority-dbus.h \ - tracker-read.c \ - tracker-read.h \ - tracker-main.c \ - tracker-main.h - -tracker_extract_LDADD = \ - $(top_builddir)/src/libtracker-sparql-backend/libtracker-sparql-@TRACKER_API_VERSION@.la \ - $(top_builddir)/src/libtracker-miner/libtracker-miner-@TRACKER_API_VERSION@.la \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-data/libtracker-data.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_EXTRACT_LIBS) - -if HAVE_LIBGSF -tracker_extract_SOURCES += tracker-gsf.c tracker-gsf.h -tracker_extract_CFLAGS = $(LIBGSF_CFLAGS) -tracker_extract_LDADD += $(LIBGSF_LIBS) -endif - -# do nothing, output as a side-effect -tracker-extract-priority-dbus.c: tracker-extract-priority-dbus-stamp - @: - -tracker-extract-priority-dbus.h: tracker-extract-priority-dbus-stamp - @: - -tracker-extract-priority-dbus-stamp: Makefile.am $(top_srcdir)/src/tracker-extract/tracker-extract-priority.xml - $(AM_V_GEN) $(GDBUS_CODEGEN) \ - --interface-prefix org.freedesktop.Tracker1.Extract. \ - --generate-c-code tracker-extract-priority-dbus \ - --c-namespace TrackerExtractDBus \ - $(top_srcdir)/src/tracker-extract/tracker-extract-priority.xml - touch $@ - -BUILT_SOURCES = \ - tracker-extract-priority-dbus.c \ - tracker-extract-priority-dbus.h \ - tracker-extract-priority-dbus-stamp \ - $(NULL) - -CLEANFILES = $(BUILT_SOURCES) - -EXTRA_DIST = $(rules_files) - -# DBus interfaces (XML files) and services -configdir = $(datadir)/tracker -config_DATA = \ - tracker-extract-priority.xml - -%.service.in: %.service.in.in - @sed -e "s|@libexecdir[@]|${libexecdir}|" $< > $@ - -servicedir = $(DBUS_SERVICES_DIR) -service_DATA = org.freedesktop.Tracker1.Miner.Extract.service - -INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -d -u' -@INTLTOOL_SERVICE_RULE@ - -tracker-extract.service: tracker-extract.service.in Makefile - @sed -e "s|@libexecdir[@]|${libexecdir}|" $< > $@ - -systemd_userdir = $(prefix)/lib/systemd/user -systemd_user_DATA = tracker-extract.service - -install-data-hook: - $(MKDIR_P) "$(DESTDIR)$(datadir)/tracker/miners" && \ - $(LN_S) -f "$(servicedir)/$(service_DATA)" \ - "$(DESTDIR)$(datadir)/tracker/miners/$(service_DATA)" - -uninstall-local: - $(RM) "$(DESTDIR)$(datadir)/tracker/miners/$(service_DATA)" && \ - $(RM) "$(servicedir)/$(service_DATA)" - -# Desktop files: First we fix the VERSION and libexecdir -%.desktop.in: %.desktop.in.in - @sed -e "s|@libexecdir[@]|${libexecdir}|" \ - -e "s|@VERSION[@]|${VERSION}|" $< > $@ - -autostartdir = $(sysconfdir)/xdg/autostart -autostart_DATA = tracker-extract.desktop - -@INTLTOOL_DESKTOP_RULE@ - -# Configuration / GSettings -gsettings_ENUM_NAMESPACE = org.freedesktop.Tracker -gsettings_ENUM_FILES = $(top_srcdir)/src/libtracker-common/tracker-enums.h - -gsettings_SCHEMAS = org.freedesktop.Tracker.Extract.gschema.xml - -@INTLTOOL_XML_NOMERGE_RULE@ - -@GSETTINGS_RULES@ - -# Dist / Clean rules for all data -CLEANFILES += \ - $(autostart_DATA) \ - $(autostart_DATA:.desktop=.desktop.in) \ - $(service_DATA) \ - $(service_DATA:.service=.service.in) \ - $(systemd_user_DATA) \ - $(gsettings_SCHEMAS) - -EXTRA_DIST += \ - $(autostart_DATA:.desktop=.desktop.in.in) \ - $(config_DATA) \ - $(service_DATA:.service=.service.in.in) \ - $(systemd_user_DATA:.service=.service.in) \ - $(gsettings_SCHEMAS:.xml=.xml.in) \ - meson.build diff --git a/src/tracker-extract/meson.build b/src/tracker-extract/meson.build deleted file mode 100644 index f39073376..000000000 --- a/src/tracker-extract/meson.build +++ /dev/null @@ -1,206 +0,0 @@ -# Extract modules are tracked here as arrays with the following elements: -# -# [ name, source-files, rule-files, dependencies ] -# -# This might be nicer if Meson supported dictionary types. - -modules = [ - ['extract-bmp', 'tracker-extract-bmp.c', '10-bmp.rule', [tracker_common_dep]], - ['extract-dummy', 'tracker-extract-dummy.c', ['10-comics.rule', '10-ebooks.rule'], [tracker_common_dep]] -] - -if get_option('abiword') - modules += [['extract-abw', 'tracker-extract-abw.c', '10-abw.rule', [tracker_common_dep]]] -endif - -if get_option('dvi') - modules += [['extract-dvi', 'tracker-extract-dvi.c', '10-dvi.rule', [tracker_common_dep]]] -endif - -if libgsf.found() - modules += [['extract-epub', 'tracker-extract-epub.c', '10-epub.rule', [libgsf, tracker_common_dep]]] - modules += [['extract-msoffice', 'tracker-extract-msoffice.c', '10-msoffice.rule', [libgsf, tracker_common_dep]]] - modules += [['extract-msoffice-xml', 'tracker-extract-msoffice-xml.c', '11-msoffice-xml.rule', [libgsf, tracker_common_dep]]] - modules += [['extract-oasis', 'tracker-extract-oasis.c', '10-oasis.rule', [libgsf, tracker_common_dep]]] -endif - -if flac.found() - modules += [['extract-flac', 'tracker-extract-flac.c', '10-flac.rule', [flac, tracker_common_dep]]] -endif - -if libgif.found() - modules += [['extract-gif', 'tracker-extract-gif.c', '10-gif.rule', [libgif, tracker_common_dep]]] -endif - -if generic_media_handler_name == 'gstreamer' - sources = ['tracker-extract-gstreamer.c', 'tracker-cue-sheet.c'] - rules = ['10-svg.rule', '15-gstreamer-guess.rule', '90-gstreamer-image-generic.rule', '90-gstreamer-audio-generic.rule', '90-gstreamer-video-generic.rule'] - dependencies = [gstreamer, libcue, tracker_common_dep] - - if gstreamer_backend_name == 'GUPnP-DNLA' - rules += '91-gstreamer-generic-dnla.rule' - dependencies += gupnp_dnla - elif gstreamer_backend_name == 'discoverer' - dependencies += gstreamer_pbutils - endif - - modules += [['extract-gstreamer', sources, rules, dependencies]] -endif - -if libxml2.found() - modules += [['extract-html', 'tracker-extract-html.c', '10-html.rule', [libxml2]]] -endif - -if libjpeg.found() - modules += [['extract-jpeg', 'tracker-extract-jpeg.c', '10-jpeg.rule', [libjpeg, tracker_common_dep]]] -endif - -if generic_media_handler_name == 'libav' - rules = ['90-libav-audio-generic.rule', '90-libav-video-generic.rule'] - dependencies = [avcodec, avformat, avutil, tracker_common_dep] - modules += [['extract-libav', 'tracker-extract-libav.c', rules, dependencies]] -endif - -if get_option('icon') - modules += [['extract-icon', 'tracker-extract-icon.c', '10-ico.rule', []]] -endif - -if libosinfo.found() - modules += [['extract-iso', 'tracker-extract-iso.c', '11-iso.rule', [libosinfo]]] -endif - -if get_option('mp3') - modules += [['extract-mp3', 'tracker-extract-mp3.c', '10-mp3.rule', [tracker_common_dep]]] -endif - -if poppler.found() - modules += [['extract-pdf', 'tracker-extract-pdf.c', '10-pdf.rule', [poppler, tracker_common_dep]]] -endif - -if totem_plparser.found() - modules += [['extract-playlist', 'tracker-extract-playlist.c', '15-playlist.rule', [totem_plparser]]] -endif - -if libpng.found() - modules += [['extract-png', 'tracker-extract-png.c', '10-png.rule', [libpng, tracker_common_dep]]] -endif - -if get_option('ps') - modules += [['extract-ps', 'tracker-extract-ps.c', '10-ps.rule', [tracker_common_dep]]] -endif - -if get_option('text') - modules += [['extract-text', 'tracker-extract-text.c', ['15-source-code.rule', '90-text-generic.rule'], []]] -endif - -if libtiff.found() - modules += [['extract-tiff', 'tracker-extract-tiff.c', '10-tiff.rule', [libtiff, tracker_common_dep]]] -endif - -if libvorbis.found() - modules += [['extract-vorbis', 'tracker-extract-vorbis.c', '10-vorbis.rule', [libvorbis, tracker_common_dep]]] -endif - -if exempi.found() - modules += [['extract-xmp', 'tracker-extract-xmp.c', '10-xmp.rule', []]] -endif - -if libgxps.found() - modules += [['extract-xps', 'tracker-extract-xps.c', '10-xps.rule', [libgxps, tracker_common_dep]]] -endif - - -foreach module : modules - name = module[0] - sources = module[1] - rule = module[2] - dependencies = module[3] - - shared_module(name, sources, - c_args: tracker_c_args, - dependencies: [tracker_extract_dep] + dependencies, - include_directories: configinc, - install: true, - install_dir: tracker_extract_modules_dir) - - install_data(rule, install_dir: tracker_extract_rules_dir) -endforeach - -tracker_extract_priority_dbus = gnome.gdbus_codegen( - 'tracker-extract-priority-dbus', - 'tracker-extract-priority.xml', - interface_prefix: 'org.freedesktop.Tracker1.Extract.', - namespace: 'TrackerExtractDBus') - -tracker_extract_sources = [ - 'tracker-config.c', - 'tracker-extract.c', - 'tracker-extract-controller.c', - 'tracker-extract-decorator.c', - 'tracker-extract-persistence.c', - 'tracker-read.c', - 'tracker-main.c', - tracker_extract_priority_dbus -] - -tracker_extract_dependencies = [ - tracker_common_dep, tracker_data_dep, tracker_extract_dep, - tracker_miner_dep, tracker_sparql_dep -] - -if libgsf.found() - tracker_extract_sources += 'tracker-gsf.c' - tracker_extract_dependencies += libgsf -endif - -executable('tracker-extract', - tracker_extract_sources, - # Manually add the root dir to work around https://github.com/mesonbuild/meson/issues/1387 - c_args: tracker_c_args + ['-I' + meson.build_root()], - dependencies: tracker_extract_dependencies, - install: true, - install_dir: join_paths(get_option('prefix'), get_option('libexecdir'))) - -install_data( - 'tracker-extract-priority.xml', - install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'tracker')) - -dbus_service_file_untranslated = configure_file( - input: 'org.freedesktop.Tracker1.Miner.Extract.service.in.in', - output: 'org.freedesktop.Tracker1.Miner.Extract.service.in', - configuration: conf) - -dbus_service_file = custom_target('tracker-extract-dbus-service-file', - input: dbus_service_file_untranslated, - output: 'org.freedesktop.Tracker1.Miner.Extract.service', - command: ['intltool-merge', '--quiet', '--desktop-style', '--utf8', join_paths(meson.source_root(), 'po'), '@INPUT@', '@OUTPUT@'], - install: true, - install_dir: dbus_services_dir) - -desktop_file_untranslated = configure_file( - input: 'tracker-extract.desktop.in.in', - output: 'tracker-extract.desktop.in', - configuration: conf) - -desktop_file = custom_target('tracker-extract-desktop-file', - input: desktop_file_untranslated, - output: 'tracker-extract.desktop', - command: ['intltool-merge', '--quiet', '--desktop-style', '--utf8', join_paths(meson.source_root(), 'po'), '@INPUT@', '@OUTPUT@'], - install: true, - install_dir: join_paths(get_option('sysconfdir'), 'xdg/autostart')) - -custom_target('tracker-extract-settings-schema', - input: 'org.freedesktop.Tracker.Extract.gschema.xml.in', - output: 'org.freedesktop.Tracker.Extract.gschema.xml', - command: ['intltool-merge', '--quiet', '--xml-style', '--utf8', join_paths(meson.source_root(), 'po'), '@INPUT@', '@OUTPUT@'], - install: true, - install_dir: join_paths(get_option('datadir'), 'glib-2.0', 'schemas')) - -if install_systemd_user_services - configure_file( - input: 'tracker-extract.service.in', - output: 'tracker-extract.service', - configuration: conf, - install: true, - install_dir: systemd_user_services_dir) -endif diff --git a/src/tracker-extract/org.freedesktop.Tracker.Extract.gschema.xml.in b/src/tracker-extract/org.freedesktop.Tracker.Extract.gschema.xml.in deleted file mode 100644 index af8c0f0af..000000000 --- a/src/tracker-extract/org.freedesktop.Tracker.Extract.gschema.xml.in +++ /dev/null @@ -1,58 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -Copyright (C) 2011, Nokia <ivan.frade@nokia.com> - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. ---> -<schemalist> - <schema id="org.freedesktop.Tracker.Extract" path="/org/freedesktop/tracker/extract/" gettext-domain="tracker"> - <key name="verbosity" enum="org.freedesktop.Tracker.TrackerVerbosity"> - <default>'errors'</default> - <_summary>Log verbosity</_summary> - <_description>Log verbosity.</_description> - </key> - - <key name="sched-idle" enum="org.freedesktop.Tracker.TrackerSchedIdle"> - <default>'first-index'</default> - <_summary>Scheduler priority when idle</_summary> - <_description> - The scheduler is the kernel component that decides which - runnable application will be executed by the CPU next. Each - application has an associated scheduling policy and priority. - </_description> - </key> - - <key name="max-bytes" type="i"> - <_summary>Max bytes to extract</_summary> - <_description>Maximum number of UTF-8 bytes to extract.</_description> - <range min="0" max="10485760"/> - <default>1048576</default> - </key> - - <key name="max-media-art-width" type="i"> - <_summary>Max media art width</_summary> - <_description>Maximum width in pixels for any media art extracted. Anything bigger is resized. Set to -1 to disable saving media art from files. Setting to 0 sets no limit on the media art width.</_description> - <range min="-1" max="2048"/> - <default>0</default> - </key> - - <key name="wait-for-miner-fs" type="b"> - <_summary>Wait for FS miner to be done before extracting</_summary> - <_description>When true, tracker-extract will wait for tracker-miner-fs to be done crawling before extracting meta-data. This option is useful on constrained environment where it is important to list files as fast as possible and can wait to get meta-data later.</_description> - <default>false</default> - </key> - </schema> -</schemalist> diff --git a/src/tracker-extract/org.freedesktop.Tracker1.Miner.Extract.service.in.in b/src/tracker-extract/org.freedesktop.Tracker1.Miner.Extract.service.in.in deleted file mode 100644 index 32dd1dfd0..000000000 --- a/src/tracker-extract/org.freedesktop.Tracker1.Miner.Extract.service.in.in +++ /dev/null @@ -1,10 +0,0 @@ -[D-BUS Service] -Name=org.freedesktop.Tracker1.Miner.Extract -Exec=@libexecdir@/tracker-extract -SystemdService=tracker-extract.service - -# Miner details needed for tracker-control -Path=/org/freedesktop/Tracker1/Miner/Extract -NameSuffix=Miner.Extract -_DisplayName=Extractor -_Comment=Metadata extractor diff --git a/src/tracker-extract/tracker-config.c b/src/tracker-extract/tracker-config.c deleted file mode 100644 index 728925570..000000000 --- a/src/tracker-extract/tracker-config.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * Copyright (C) 2014, Lanedo <martyn@lanedo.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#define G_SETTINGS_ENABLE_BACKEND -#include <gio/gsettingsbackend.h> - -#include <libtracker-common/tracker-common.h> - -#include "tracker-config.h" - -#define CONFIG_SCHEMA "org.freedesktop.Tracker.Extract" -#define CONFIG_PATH "/org/freedesktop/tracker/extract/" - -static void config_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); -static void config_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); -static void config_finalize (GObject *object); -static void config_constructed (GObject *object); - -enum { - PROP_0, - PROP_VERBOSITY, - PROP_SCHED_IDLE, - PROP_MAX_BYTES, - PROP_MAX_MEDIA_ART_WIDTH, - PROP_WAIT_FOR_MINER_FS, -}; - -G_DEFINE_TYPE (TrackerConfig, tracker_config, G_TYPE_SETTINGS); - -static void -tracker_config_class_init (TrackerConfigClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = config_set_property; - object_class->get_property = config_get_property; - object_class->finalize = config_finalize; - object_class->constructed = config_constructed; - - /* General */ - g_object_class_install_property (object_class, - PROP_VERBOSITY, - g_param_spec_enum ("verbosity", - "Log verbosity", - "Log verbosity (0=errors, 1=minimal, 2=detailed, 3=debug)", - TRACKER_TYPE_VERBOSITY, - TRACKER_VERBOSITY_ERRORS, - G_PARAM_READWRITE)); - g_object_class_install_property (object_class, - PROP_SCHED_IDLE, - g_param_spec_enum ("sched-idle", - "Scheduler priority when idle", - "Scheduler priority when idle (0=always, 1=first-index, 2=never)", - TRACKER_TYPE_SCHED_IDLE, - TRACKER_SCHED_IDLE_FIRST_INDEX, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, - PROP_MAX_BYTES, - g_param_spec_int ("max-bytes", - "Max Bytes", - "Maximum number of UTF-8 bytes to extract per file [0->10485760]", - 0, 1024 * 1024 * 10, - 1024 * 1024, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, - PROP_MAX_MEDIA_ART_WIDTH, - g_param_spec_int ("max-media-art-width", - "Max Media Art Width", - " Maximum width of the Media Art to be generated (-1=disable, 0=original width, 1->2048=max pixel width)", - -1, - 2048, - 0, - G_PARAM_READWRITE)); - - g_object_class_install_property (object_class, - PROP_WAIT_FOR_MINER_FS, - g_param_spec_boolean ("wait-for-miner-fs", - "Wait for FS miner to be done before extracting", - "%TRUE to wait for tracker-miner-fs is done before extracting. %FAlSE otherwise", - FALSE, - G_PARAM_READWRITE)); -} - -static void -tracker_config_init (TrackerConfig *object) -{ -} - -static void -config_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - TrackerConfig *config = TRACKER_CONFIG (object); - - switch (param_id) { - /* General */ - /* NOTE: We handle these because we have to be able - * to save these based on command line overrides. - */ - case PROP_VERBOSITY: - tracker_config_set_verbosity (config, g_value_get_enum (value)); - break; - - /* We don't care about the others... we don't save anyway. */ - case PROP_SCHED_IDLE: - case PROP_MAX_BYTES: - case PROP_MAX_MEDIA_ART_WIDTH: - case PROP_WAIT_FOR_MINER_FS: - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - }; -} - -static void -config_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - TrackerConfig *config = TRACKER_CONFIG (object); - - switch (param_id) { - case PROP_VERBOSITY: - g_value_set_enum (value, - tracker_config_get_verbosity (config)); - break; - - case PROP_SCHED_IDLE: - g_value_set_enum (value, - tracker_config_get_sched_idle (config)); - break; - - case PROP_MAX_BYTES: - g_value_set_int (value, - tracker_config_get_max_bytes (config)); - break; - - case PROP_MAX_MEDIA_ART_WIDTH: - g_value_set_int (value, - tracker_config_get_max_media_art_width (config)); - break; - - case PROP_WAIT_FOR_MINER_FS: - g_value_set_boolean (value, - tracker_config_get_wait_for_miner_fs (config)); - break; - - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - }; -} - -static void -config_finalize (GObject *object) -{ - /* For now we do nothing here, we left this override in for - * future expansion. - */ - - (G_OBJECT_CLASS (tracker_config_parent_class)->finalize) (object); -} - -static void -config_constructed (GObject *object) -{ - GSettings *settings; - - (G_OBJECT_CLASS (tracker_config_parent_class)->constructed) (object); - - settings = G_SETTINGS (object); - - if (G_LIKELY (!g_getenv ("TRACKER_USE_CONFIG_FILES"))) { - g_settings_delay (settings); - } - - /* Set up bindings: - * - * What's interesting here is that 'verbosity' and - * 'initial-sleep' are command line arguments that can be - * overridden, so we don't update the config when we set them - * from main() because it's a session configuration only, not - * a permanent one. To do this we use the flag - * G_SETTINGS_BIND_GET_NO_CHANGES. - * - * For the other settings, we don't bind the - * G_SETTINGS_BIND_SET because we don't want to save anything, - * ever, we only want to know about updates to the settings as - * they're changed externally. The only time this may be - * different is where we use the environment variable - * TRACKER_USE_CONFIG_FILES and we want to write a config - * file for convenience. But this is only necessary if the - * config is different to the default. - */ - g_settings_bind (settings, "verbosity", object, "verbosity", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_GET_NO_CHANGES); - g_settings_bind (settings, "sched-idle", object, "sched-idle", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "max-media-art-width", object, "max-media-art-width", G_SETTINGS_BIND_GET); - g_settings_bind (settings, "wait-for-miner-fs", object, "wait-for-miner-fs", G_SETTINGS_BIND_GET); - - /* Cache settings accessed from extractor modules, we don't want - * the GSettings object accessed within these as it may trigger - * unintended open() calls. - */ - TRACKER_CONFIG (settings)->max_bytes = g_settings_get_int (settings, "max-bytes"); -} - -TrackerConfig * -tracker_config_new (void) -{ - TrackerConfig *config = NULL; - - /* FIXME: should we unset GSETTINGS_BACKEND env var? */ - - if (G_UNLIKELY (g_getenv ("TRACKER_USE_CONFIG_FILES"))) { - GSettingsBackend *backend; - gchar *filename, *basename; - gboolean need_to_save; - - basename = g_strdup_printf ("%s.cfg", g_get_prgname ()); - filename = g_build_filename (g_get_user_config_dir (), "tracker", basename, NULL); - g_free (basename); - - need_to_save = g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE; - - backend = g_keyfile_settings_backend_new (filename, CONFIG_PATH, "General"); - g_info ("Using config file '%s'", filename); - g_free (filename); - - config = g_object_new (TRACKER_TYPE_CONFIG, - "backend", backend, - "schema-id", CONFIG_SCHEMA, - "path", CONFIG_PATH, - NULL); - g_object_unref (backend); - - if (need_to_save) { - g_info (" Config file does not exist, using default values..."); - } - } else { - config = g_object_new (TRACKER_TYPE_CONFIG, - "schema-id", CONFIG_SCHEMA, - "path", CONFIG_PATH, - NULL); - } - - return config; -} - -gint -tracker_config_get_verbosity (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), TRACKER_VERBOSITY_ERRORS); - - return g_settings_get_enum (G_SETTINGS (config), "verbosity"); -} - -void -tracker_config_set_verbosity (TrackerConfig *config, - gint value) -{ - g_return_if_fail (TRACKER_IS_CONFIG (config)); - - g_settings_set_enum (G_SETTINGS (config), "verbosity", value); -} - -gint -tracker_config_get_sched_idle (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), TRACKER_SCHED_IDLE_FIRST_INDEX); - - return g_settings_get_enum (G_SETTINGS (config), "sched-idle"); -} - -gint -tracker_config_get_max_bytes (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), 0); - - return config->max_bytes; -} - -gint -tracker_config_get_max_media_art_width (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), 0); - - return g_settings_get_int (G_SETTINGS (config), "max-media-art-width"); -} - -gboolean -tracker_config_get_wait_for_miner_fs (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), FALSE); - - return g_settings_get_boolean (G_SETTINGS (config), "wait-for-miner-fs"); -} diff --git a/src/tracker-extract/tracker-config.h b/src/tracker-extract/tracker-config.h deleted file mode 100644 index c8af8ef57..000000000 --- a/src/tracker-extract/tracker-config.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_EXTRACT_CONFIG_H__ -#define __TRACKER_EXTRACT_CONFIG_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -#define TRACKER_TYPE_CONFIG (tracker_config_get_type ()) -#define TRACKER_CONFIG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_CONFIG, TrackerConfig)) -#define TRACKER_CONFIG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TRACKER_TYPE_CONFIG, TrackerConfigClass)) -#define TRACKER_IS_CONFIG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_CONFIG)) -#define TRACKER_IS_CONFIG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TRACKER_TYPE_CONFIG)) -#define TRACKER_CONFIG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_CONFIG, TrackerConfigClass)) - -typedef struct TrackerConfig TrackerConfig; -typedef struct TrackerConfigClass TrackerConfigClass; - -struct TrackerConfig { - GSettings parent; - gint max_bytes; -}; - -struct TrackerConfigClass { - GSettingsClass parent_class; -}; - -GType tracker_config_get_type (void) G_GNUC_CONST; - -TrackerConfig *tracker_config_new (void); -gint tracker_config_get_verbosity (TrackerConfig *config); -gint tracker_config_get_sched_idle (TrackerConfig *config); -gint tracker_config_get_max_bytes (TrackerConfig *config); -gint tracker_config_get_max_media_art_width (TrackerConfig *config); -gboolean tracker_config_get_wait_for_miner_fs (TrackerConfig *config); - -void tracker_config_set_verbosity (TrackerConfig *config, - gint value); - -G_END_DECLS - -#endif /* __TRACKER_EXTRACT_CONFIG_H__ */ - diff --git a/src/tracker-extract/tracker-cue-sheet.c b/src/tracker-extract/tracker-cue-sheet.c deleted file mode 100644 index 39722d959..000000000 --- a/src/tracker-extract/tracker-cue-sheet.c +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Copyright (C) 2011, ARQ Media <sam.thursfield@codethink.co.uk> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * Author: Sam Thursfield <sam.thursfield@codethink.co.uk> - */ - -#include "config.h" - -#include <stdlib.h> -#include <string.h> - -#include <glib.h> -#include <gio/gio.h> -#include <gst/gst.h> -#include <gst/tag/tag.h> - -#if defined(HAVE_LIBCUE2) -#include <libcue.h> -#elif defined(HAVE_LIBCUE) -#include <libcue/libcue.h> -#endif - -#include <libtracker-common/tracker-file-utils.h> - -#include "tracker-cue-sheet.h" - -TrackerToc * -tracker_toc_new (void) -{ - TrackerToc *toc; - - toc = g_slice_new (TrackerToc); - toc->tag_list = gst_tag_list_new_empty (); - toc->entry_list = NULL; - - return toc; -} - -void -tracker_toc_free (TrackerToc *toc) -{ - TrackerTocEntry *entry; - GList *n; - - if (!toc) { - return; - } - - for (n = toc->entry_list; n != NULL; n = n->next) { - entry = n->data; - gst_tag_list_free (entry->tag_list); - g_slice_free (TrackerTocEntry, entry); - } - - gst_tag_list_free (toc->tag_list); - g_list_free (toc->entry_list); - - g_slice_free (TrackerToc, toc); -} - -void -tracker_toc_add_entry (TrackerToc *toc, - GstTagList *tags, - gdouble start, - gdouble duration) -{ - TrackerTocEntry *toc_entry; - - toc_entry = g_slice_new (TrackerTocEntry); - toc_entry->tag_list = gst_tag_list_ref (tags); - toc_entry->start = start; - toc_entry->duration = duration; - - toc->entry_list = g_list_append (toc->entry_list, toc_entry); -} - -#if defined(HAVE_LIBCUE) - -static void -add_cdtext_string_tag (Cdtext *cd_text, - enum Pti index, - GstTagList *tag_list, - const gchar *tag) -{ - const gchar *text; - - text = cdtext_get (index, cd_text); - - if (text != NULL) { - gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, tag, text, NULL); - } -} - -static void -add_cdtext_comment_date_tag (Rem *cd_comments, -#if defined(HAVE_LIBCUE2) - enum RemType index, -#elif defined(HAVE_LIBCUE) - enum Cmt index, -#endif - GstTagList *tag_list, - const gchar *tag) -{ - const gchar *text; - gint year; - GDate *date; - - text = rem_get (index, cd_comments); - - if (text != NULL) { - year = atoi (text); - - if (year >= 1860) { - date = g_date_new_dmy (1, 1, year); - gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, tag, date, NULL); - g_date_free (date); - } - } -} - -static void -add_cdtext_comment_double_tag (Rem *cd_comments, -#if defined(HAVE_LIBCUE2) - enum RemType index, -#elif defined(HAVE_LIBCUE) - enum Cmt index, -#endif - GstTagList *tag_list, - const gchar *tag) -{ - const gchar *text; - gdouble value; - - text = rem_get (index, cd_comments); - - if (text != NULL) { - value = strtod (text, NULL); - - /* Shortcut: it just so happens that 0.0 is meaningless for the replay - * gain properties so we can get away with testing for errors this way. - */ - if (value != 0.0) - gst_tag_list_add (tag_list, GST_TAG_MERGE_REPLACE, tag, value, NULL); - } -} - -static void -set_album_tags_from_cdtext (GstTagList *tag_list, - Cdtext *cd_text, - Rem *cd_comments) -{ - if (cd_text != NULL) { - add_cdtext_string_tag (cd_text, PTI_TITLE, tag_list, GST_TAG_ALBUM); - add_cdtext_string_tag (cd_text, PTI_PERFORMER, tag_list, GST_TAG_ALBUM_ARTIST); - } - - if (cd_comments != NULL) { - add_cdtext_comment_date_tag (cd_comments, REM_DATE, tag_list, GST_TAG_DATE); - - add_cdtext_comment_double_tag (cd_comments, REM_REPLAYGAIN_ALBUM_GAIN, tag_list, GST_TAG_ALBUM_GAIN); - add_cdtext_comment_double_tag (cd_comments, REM_REPLAYGAIN_ALBUM_PEAK, tag_list, GST_TAG_ALBUM_PEAK); - } -} - -static void -set_track_tags_from_cdtext (GstTagList *tag_list, - Cdtext *cd_text, - Rem *cd_comments) -{ - if (cd_text != NULL) { - add_cdtext_string_tag (cd_text, PTI_TITLE, tag_list, GST_TAG_TITLE); - add_cdtext_string_tag (cd_text, PTI_PERFORMER, tag_list, GST_TAG_PERFORMER); - add_cdtext_string_tag (cd_text, PTI_COMPOSER, tag_list, GST_TAG_COMPOSER); - } - - if (cd_comments != NULL) { - add_cdtext_comment_double_tag (cd_comments, REM_REPLAYGAIN_TRACK_GAIN, tag_list, GST_TAG_TRACK_GAIN); - add_cdtext_comment_double_tag (cd_comments, REM_REPLAYGAIN_TRACK_PEAK, tag_list, GST_TAG_TRACK_PEAK); - } -} - -/* Some simple heuristics to fill in missing tag information. */ -static void -process_toc_tags (TrackerToc *toc) -{ - gint track_count; - - if (gst_tag_list_get_tag_size (toc->tag_list, GST_TAG_TRACK_COUNT) == 0) { - track_count = g_list_length (toc->entry_list); - gst_tag_list_add (toc->tag_list, - GST_TAG_MERGE_REPLACE, - GST_TAG_TRACK_COUNT, - track_count, - NULL); - } -} - -/* This function runs in two modes: for external CUE sheets, it will check - * the FILE field for each track and build a TrackerToc for all the tracks - * contained in @file_name. If @file_name does not appear in the CUE sheet, - * %NULL will be returned. For embedded CUE sheets, @file_name will be NULL - * the whole TOC will be returned regardless of any FILE information. - */ -static TrackerToc * -parse_cue_sheet_for_file (const gchar *cue_sheet, - const gchar *file_name) -{ - TrackerToc *toc; - TrackerTocEntry *toc_entry; - Cd *cd; - Track *track; - gint i; - - toc = NULL; - - cd = cue_parse_string (cue_sheet); - - if (cd == NULL) { - g_debug ("Unable to parse CUE sheet for %s.", - file_name ? file_name : "(embedded in FLAC)"); - return NULL; - } - - for (i = 1; i <= cd_get_ntrack (cd); i++) { - track = cd_get_track (cd, i); - - /* CUE sheets generally have the correct basename but wrong - * extension in the FILE field, so this is what we test for. - */ - if (file_name != NULL) { - if (!tracker_filename_casecmp_without_extension (file_name, - track_get_filename (track))) { - continue; - } - } - - if (track_get_mode (track) != MODE_AUDIO) - continue; - - if (toc == NULL) { - toc = tracker_toc_new (); - - set_album_tags_from_cdtext (toc->tag_list, - cd_get_cdtext (cd), - cd_get_rem (cd)); - } - - toc_entry = g_slice_new (TrackerTocEntry); - toc_entry->tag_list = gst_tag_list_new_empty (); - toc_entry->start = track_get_start (track) / 75.0; - toc_entry->duration = track_get_length (track) / 75.0; - - set_track_tags_from_cdtext (toc_entry->tag_list, - track_get_cdtext (track), - track_get_rem (track)); - - gst_tag_list_add (toc_entry->tag_list, - GST_TAG_MERGE_REPLACE, - GST_TAG_TRACK_NUMBER, - i, - NULL); - - - toc->entry_list = g_list_prepend (toc->entry_list, toc_entry); - } - - cd_delete (cd); - - if (toc != NULL) - toc->entry_list = g_list_reverse (toc->entry_list); - - return toc; -} - -TrackerToc * -tracker_cue_sheet_parse (const gchar *cue_sheet) -{ - TrackerToc *result; - - result = parse_cue_sheet_for_file (cue_sheet, NULL); - - if (result) - process_toc_tags (result); - - return result; -} - -static GList * -find_local_cue_sheets (GFile *audio_file) -{ - GFile *container; - GFile *cue_sheet; - GFileEnumerator *e; - GFileInfo *file_info; - gchar *container_path; - const gchar *file_name; - const gchar *file_content_type; - gchar *file_path; - GList *result = NULL; - GError *error = NULL; - - container = g_file_get_parent (audio_file); - container_path = g_file_get_path (container); - - e = g_file_enumerate_children (container, - "standard::*", - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, - &error); - - if (error != NULL) { - g_debug ("Unable to enumerate directory: %s", error->message); - g_object_unref (container); - g_error_free (error); - return NULL; - } - - while ((file_info = g_file_enumerator_next_file (e, NULL, NULL))) { - file_name = g_file_info_get_attribute_byte_string (file_info, - G_FILE_ATTRIBUTE_STANDARD_NAME); - - file_content_type = g_file_info_get_content_type (file_info); - - if (file_name == NULL || file_content_type == NULL) { - g_debug ("Unable to get info for file %s/%s", - container_path, - g_file_info_get_display_name (file_info)); - } else if (strcmp (file_content_type, "application/x-cue") == 0) { - file_path = g_build_filename (container_path, file_name, NULL); - cue_sheet = g_file_new_for_path (file_path); - result = g_list_prepend (result, cue_sheet); - g_free (file_path); - } - - g_object_unref (file_info); - } - - g_object_unref (e); - g_object_unref (container); - g_free (container_path); - - return result; -} - -TrackerToc * -tracker_cue_sheet_parse_uri (const gchar *uri) -{ - GFile *audio_file; - gchar *audio_file_name; - GList *cue_sheet_list; - TrackerToc *toc; - GError *error = NULL; - GList *n; - - audio_file = g_file_new_for_uri (uri); - audio_file_name = g_file_get_basename (audio_file); - - cue_sheet_list = find_local_cue_sheets (audio_file); - - toc = NULL; - - for (n = cue_sheet_list; n != NULL; n = n->next) { - GFile *cue_sheet_file; - gchar *buffer; - - cue_sheet_file = n->data; - - if (!g_file_load_contents (cue_sheet_file, NULL, &buffer, NULL, NULL, &error)) { - g_debug ("Unable to read cue sheet: %s", error->message); - g_error_free (error); - continue; - } - - toc = parse_cue_sheet_for_file (buffer, audio_file_name); - - g_free (buffer); - - if (toc != NULL) { - char *path = g_file_get_path (cue_sheet_file); - g_debug ("Using external CUE sheet: %s", path); - g_free (path); - break; - } - } - - g_list_foreach (cue_sheet_list, (GFunc) g_object_unref, NULL); - g_list_free (cue_sheet_list); - - g_object_unref (audio_file); - g_free (audio_file_name); - - if (toc) - process_toc_tags (toc); - - return toc; -} - -#else /* ! HAVE_LIBCUE */ - -TrackerToc * -tracker_cue_sheet_parse (const gchar *cue_sheet) -{ - return NULL; -} - -TrackerToc * -tracker_cue_sheet_parse_uri (const gchar *uri) -{ - return NULL; -} - -#endif /* ! HAVE_LIBCUE */ diff --git a/src/tracker-extract/tracker-cue-sheet.h b/src/tracker-extract/tracker-cue-sheet.h deleted file mode 100644 index efe0b46d0..000000000 --- a/src/tracker-extract/tracker-cue-sheet.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2011, ARQ Media <sam.thursfield@codethink.co.uk> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * Author: Sam Thursfield <sam.thursfield@codethink.co.uk> - */ - -#ifndef __TRACKER_EXTRACT_CUE_SHEET_H__ -#define __TRACKER_EXTRACT_CUE_SHEET_H__ - -#include <glib.h> -#include <gst/gst.h> -#include <gst/tag/tag.h> - -G_BEGIN_DECLS - -typedef struct { - /* Values in seconds */ - gdouble start; - gdouble duration; - GstTagList *tag_list; -} TrackerTocEntry; - -typedef struct { - GstTagList *tag_list; - GList *entry_list; -} TrackerToc; - -void tracker_toc_free (TrackerToc *toc); -TrackerToc *tracker_toc_new (void); - -void tracker_toc_add_entry (TrackerToc *toc, - GstTagList *tags, - gdouble start, - gdouble duration); - -TrackerToc *tracker_cue_sheet_parse (const gchar *cue_sheet); -TrackerToc *tracker_cue_sheet_parse_uri (const gchar *uri); - -G_END_DECLS - -#endif /* __TRACKER_EXTRACT_CUE_SHEET_H__ */ diff --git a/src/tracker-extract/tracker-extract-abw.c b/src/tracker-extract/tracker-extract-abw.c deleted file mode 100644 index d8172af2d..000000000 --- a/src/tracker-extract/tracker-extract-abw.c +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Copyright (C) 2007, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <errno.h> -#include <fcntl.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <sys/mman.h> - -#include <glib.h> -#include <glib/gstdio.h> - -#include <libtracker-common/tracker-file-utils.h> - -#include <libtracker-extract/tracker-extract.h> - -typedef struct AbwParserData AbwParserData; -typedef enum { - ABW_PARSER_TAG_UNHANDLED, - ABW_PARSER_TAG_TITLE, - ABW_PARSER_TAG_SUBJECT, - ABW_PARSER_TAG_CREATOR, - ABW_PARSER_TAG_KEYWORDS, - ABW_PARSER_TAG_DESCRIPTION, - ABW_PARSER_TAG_GENERATOR -} AbwParserTag; - -struct AbwParserData { - TrackerResource *resource; - GString *content; - gchar *uri; - - guint cur_tag; - guint in_text : 1; - guint has_title : 1; - guint has_subject : 1; - guint has_comment : 1; - guint has_generator : 1; -}; - -static void -abw_parser_start_elem (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - AbwParserData *data = user_data; - - if (g_strcmp0 (element_name, "m") == 0 && - g_strcmp0 (attribute_names[0], "key") == 0) { - if (g_strcmp0 (attribute_values[0], "dc.title") == 0) { - data->cur_tag = ABW_PARSER_TAG_TITLE; - } else if (g_strcmp0 (attribute_values[0], "dc.subject") == 0) { - data->cur_tag = ABW_PARSER_TAG_SUBJECT; - } else if (g_strcmp0 (attribute_values[0], "dc.creator") == 0) { - data->cur_tag = ABW_PARSER_TAG_CREATOR; - } else if (g_strcmp0 (attribute_values[0], "abiword.keywords") == 0) { - data->cur_tag = ABW_PARSER_TAG_KEYWORDS; - } else if (g_strcmp0 (attribute_values[0], "dc.description") == 0) { - data->cur_tag = ABW_PARSER_TAG_DESCRIPTION; - } else if (g_strcmp0 (attribute_values[0], "abiword.generator") == 0) { - data->cur_tag = ABW_PARSER_TAG_GENERATOR; - } - } else if (g_strcmp0 (element_name, "section") == 0) { - data->in_text = TRUE; - } -} - -static void -abw_parser_text (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - AbwParserData *data = user_data; - gchar *str; - - str = g_strndup (text, text_len); - - switch (data->cur_tag) { - case ABW_PARSER_TAG_TITLE: - if (data->has_title) { - g_warning ("Avoiding additional title (%s) in Abiword document '%s'", - str, data->uri); - } else { - data->has_title = TRUE; - tracker_resource_set_string (data->resource, "nie:title", str); - } - break; - case ABW_PARSER_TAG_SUBJECT: - if (data->has_subject) { - g_warning ("Avoiding additional subject (%s) in Abiword document '%s'", - str, data->uri); - } else { - data->has_subject = TRUE; - tracker_resource_set_string (data->resource, "nie:subject", str); - } - break; - case ABW_PARSER_TAG_CREATOR: { - TrackerResource *creator; - creator = tracker_extract_new_contact (str); - tracker_resource_set_relation (data->resource, "nco:creator", creator); - g_object_unref (creator); - - break; - } - case ABW_PARSER_TAG_DESCRIPTION: - if (data->has_comment) { - g_warning ("Avoiding additional comment (%s) in Abiword document '%s'", - str, data->uri); - } else { - data->has_comment = TRUE; - tracker_resource_set_string (data->resource, "nie:comment", str); - } - break; - case ABW_PARSER_TAG_GENERATOR: - if (data->has_generator) { - g_warning ("Avoiding additional generator (%s) in Abiword document '%s'", - str, data->uri); - } else { - data->has_generator = TRUE; - tracker_resource_set_string (data->resource, "nie:generator", str); - } - break; - case ABW_PARSER_TAG_KEYWORDS: - { - char *lasts, *keyword; - - for (keyword = strtok_r (str, ",; ", &lasts); keyword; - keyword = strtok_r (NULL, ",; ", &lasts)) { - tracker_resource_add_string (data->resource, "nie:keyword", keyword); - } - } - break; - default: - break; - } - - if (data->in_text) { - if (G_UNLIKELY (!data->content)) { - data->content = g_string_new (""); - } - - g_string_append_len (data->content, text, text_len); - } - - data->cur_tag = ABW_PARSER_TAG_UNHANDLED; - g_free (str); -} - -static GMarkupParser parser = { - abw_parser_start_elem, - NULL, - abw_parser_text, - NULL, NULL -}; - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - int fd; - gchar *filename, *contents; - gboolean retval = FALSE; - GFile *f; - gsize len; - struct stat st; - - f = tracker_extract_info_get_file (info); - filename = g_file_get_path (f); - - fd = tracker_file_open_fd (filename); - - if (fd == -1) { - g_warning ("Could not open abw file '%s': %s\n", - filename, - g_strerror (errno)); - g_free (filename); - return retval; - } - - if (fstat (fd, &st) == -1) { - g_warning ("Could not fstat abw file '%s': %s\n", - filename, - g_strerror (errno)); - close (fd); - g_free (filename); - return retval; - } - - if (st.st_size == 0) { - contents = NULL; - len = 0; - } else { - contents = (gchar *) mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (contents == NULL) { - g_warning ("Could not mmap abw file '%s': %s\n", - filename, - g_strerror (errno)); - close (fd); - g_free (filename); - return retval; - } - len = st.st_size; - } - - g_free (filename); - - if (contents) { - GError *error = NULL; - GMarkupParseContext *context; - AbwParserData data = { 0 }; - - data.uri = g_file_get_uri (f); - data.resource = tracker_resource_new (NULL); - - tracker_resource_add_uri (data.resource, "rdf:type", "nfo:Document"); - - context = g_markup_parse_context_new (&parser, 0, &data, NULL); - g_markup_parse_context_parse (context, contents, len, &error); - - if (error) { - g_warning ("Could not parse abw file: %s\n", error->message); - g_error_free (error); - } else { - if (data.content) { - tracker_resource_set_string (data.resource, "nie:plainTextContent", data.content->str); - g_string_free (data.content, TRUE); - } - - retval = TRUE; - } - - g_markup_parse_context_free (context); - g_free (data.uri); - - tracker_extract_info_set_resource (info, data.resource); - g_object_unref (data.resource); - } - - if (contents) { - munmap (contents, len); - } - - close (fd); - - return retval; -} diff --git a/src/tracker-extract/tracker-extract-bmp.c b/src/tracker-extract/tracker-extract-bmp.c deleted file mode 100644 index be7dc662d..000000000 --- a/src/tracker-extract/tracker-extract-bmp.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (C) 2013-2014 Jolla Ltd. <andrew.den.exter@jollamobile.com> - * Author: Philip Van Hoof <philip@codeminded.be> - * Author: Mingxiang Lin <paralmx@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <libtracker-common/tracker-common.h> -#include <libtracker-extract/tracker-extract.h> - -static gboolean -get_img_resolution (const GFile *file, - gint64 *width, - gint64 *height) -{ - GFileInputStream *stream; - GInputStream *inputstream; - GError *error = NULL; - char bfType[2] = { 0 }; - uint w, h; - - if (width) { - *width = 0; - } - - if (height) { - *height = 0; - } - - w = h = 0; - - stream = g_file_read ((GFile *)file, NULL, &error); - if (error) { - g_message ("Could not read BMP file, %s", error->message); - g_clear_error (&error); - return FALSE; - } - - inputstream = G_INPUT_STREAM (stream); - - if (!g_input_stream_read (inputstream, bfType, 2, NULL, &error)) { - g_message ("Could not read BMP header from stream, %s", error ? error->message : "No error given"); - g_clear_error (&error); - g_object_unref (stream); - return FALSE; - } - - if (bfType[0] != 'B' || bfType[1] != 'M') { - g_message ("Expected BMP header to read 'B' or 'M', can not continue"); - g_object_unref (stream); - return FALSE; - } - - if (!g_input_stream_skip (inputstream, 16, NULL, &error)) { - g_message ("Could not read 16 bytes from BMP header, %s", error ? error->message : "No error given"); - g_clear_error (&error); - g_object_unref (stream); - return FALSE; - } - - if (!g_input_stream_read (inputstream, &w, sizeof (uint), NULL, &error)) { - g_message ("Could not read width from BMP header, %s", error ? error->message : "No error given"); - g_clear_error (&error); - g_object_unref (stream); - return FALSE; - } - - if (!g_input_stream_read (inputstream, &h, sizeof (uint), NULL, &error)) { - g_message ("Could not read height from BMP header, %s", error ? error->message : "No error given"); - g_clear_error (&error); - g_object_unref (stream); - return FALSE; - } - - if (width) { - *width = w; - } - - if (height) { - *height = h; - } - - g_input_stream_close (inputstream, NULL, NULL); - g_object_unref (stream); - - return TRUE; -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerResource *image; - goffset size; - gchar *filename; - GFile *file; - gint64 width = 0, height = 0; - - file = tracker_extract_info_get_file (info); - if (!file) { - return FALSE; - } - - filename = g_file_get_path (file); - size = tracker_file_get_size (filename); - g_free (filename); - - if (size < 14) { - /* Smaller than BMP header, can't be a real BMP file */ - return FALSE; - } - - image = tracker_resource_new (NULL); - tracker_resource_add_uri (image, "rdf:type", "nfo:Image"); - tracker_resource_add_uri (image, "rdf:type", "nmm:Photo"); - - if (get_img_resolution (file, &width, &height)) { - if (width > 0) { - tracker_resource_set_int64 (image, "nfo:width", width); - } - - if (height > 0) { - tracker_resource_set_int64 (image, "nfo:height", height); - } - } - - tracker_extract_info_set_resource (info, image); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-controller.c b/src/tracker-extract/tracker-extract-controller.c deleted file mode 100644 index 9c03112bb..000000000 --- a/src/tracker-extract/tracker-extract-controller.c +++ /dev/null @@ -1,314 +0,0 @@ -/* - * Copyright (C) 2014 - Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include "tracker-extract-controller.h" - -#include "tracker-main.h" - -enum { - PROP_DECORATOR = 1, - PROP_CONNECTION, -}; - -struct TrackerExtractControllerPrivate { - TrackerDecorator *decorator; - TrackerConfig *config; - GCancellable *cancellable; - GDBusConnection *connection; - guint watch_id; - guint progress_signal_id; - gint paused; -}; - -G_DEFINE_TYPE (TrackerExtractController, tracker_extract_controller, G_TYPE_OBJECT) - -static void -files_miner_idleness_changed (TrackerExtractController *self, - gboolean idle) -{ - if (idle && self->priv->paused) { - tracker_miner_resume (TRACKER_MINER (self->priv->decorator)); - self->priv->paused = FALSE; - } else if (!idle && !self->priv->paused) { - self->priv->paused = FALSE; - tracker_miner_pause (TRACKER_MINER (self->priv->decorator)); - } -} - -static void -files_miner_status_changed (TrackerExtractController *self, - const gchar *status) -{ - files_miner_idleness_changed (self, g_str_equal (status, "Idle")); -} - -static void -files_miner_get_status_cb (GObject *source, - GAsyncResult *result, - gpointer user_data) -{ - TrackerExtractController *self = user_data; - GDBusConnection *conn = (GDBusConnection *) source; - GVariant *reply; - const gchar *status; - GError *error = NULL; - - reply = g_dbus_connection_call_finish (conn, result, &error); - if (!reply) { - g_debug ("Failed to get tracker-miner-fs status: %s", - error->message); - g_clear_error (&error); - } else { - g_variant_get (reply, "(&s)", &status); - files_miner_status_changed (self, status); - g_variant_unref (reply); - } - - g_clear_object (&self->priv->cancellable); - g_object_unref (self); -} - -static void -appeared_cb (GDBusConnection *connection, - const gchar *name, - const gchar *name_owner, - gpointer user_data) -{ - TrackerExtractController *self = user_data; - - /* Get initial status */ - self->priv->cancellable = g_cancellable_new (); - g_dbus_connection_call (connection, - "org.freedesktop.Tracker1.Miner.Files", - "/org/freedesktop/Tracker1/Miner/Files", - "org.freedesktop.Tracker1.Miner", - "GetStatus", - NULL, - G_VARIANT_TYPE ("(s)"), - G_DBUS_CALL_FLAGS_NO_AUTO_START, - -1, - self->priv->cancellable, - files_miner_get_status_cb, - g_object_ref (self)); -} - -static void -vanished_cb (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - TrackerExtractController *self = user_data; - - /* tracker-miner-fs vanished, we don't have anything to wait for - * anymore. */ - files_miner_idleness_changed (self, TRUE); -} - -static void -files_miner_progress_cb (GDBusConnection *connection, - const gchar *sender_name, - const gchar *object_path, - const gchar *interface_name, - const gchar *signal_name, - GVariant *parameters, - gpointer user_data) -{ - TrackerExtractController *self = user_data; - const gchar *status; - - g_return_if_fail (g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(sdi)"))); - - /* If we didn't get the initial status yet, ignore Progress signals */ - if (self->priv->cancellable) - return; - - g_variant_get (parameters, "(&sdi)", &status, NULL, NULL); - files_miner_status_changed (self, status); -} - -static void -disconnect_all (TrackerExtractController *self) -{ - GDBusConnection *conn = self->priv->connection; - - if (self->priv->watch_id != 0) - g_bus_unwatch_name (self->priv->watch_id); - self->priv->watch_id = 0; - - if (self->priv->progress_signal_id != 0) - g_dbus_connection_signal_unsubscribe (conn, - self->priv->progress_signal_id); - self->priv->progress_signal_id = 0; - - if (self->priv->cancellable) - g_cancellable_cancel (self->priv->cancellable); - g_clear_object (&self->priv->cancellable); -} - -static void -update_wait_for_miner_fs (TrackerExtractController *self) -{ - GDBusConnection *conn = self->priv->connection; - - if (tracker_config_get_wait_for_miner_fs (self->priv->config)) { - self->priv->progress_signal_id = - g_dbus_connection_signal_subscribe (conn, - "org.freedesktop.Tracker1.Miner.Files", - "org.freedesktop.Tracker1.Miner", - "Progress", - "/org/freedesktop/Tracker1/Miner/Files", - NULL, - G_DBUS_SIGNAL_FLAGS_NONE, - files_miner_progress_cb, - self, NULL); - - /* appeared_cb is guaranteed to be called even if the service - * was already running, so we'll start the miner from there. */ - self->priv->watch_id = g_bus_watch_name_on_connection (conn, - "org.freedesktop.Tracker1.Miner.Files", - G_BUS_NAME_WATCHER_FLAGS_NONE, - appeared_cb, - vanished_cb, - self, NULL); - } else { - disconnect_all (self); - files_miner_idleness_changed (self, TRUE); - } -} - -static void -tracker_extract_controller_constructed (GObject *object) -{ - TrackerExtractController *self = (TrackerExtractController *) object; - - G_OBJECT_CLASS (tracker_extract_controller_parent_class)->constructed (object); - - g_assert (self->priv->decorator != NULL); - - self->priv->config = g_object_ref (tracker_main_get_config ()); - g_signal_connect_object (self->priv->config, - "notify::wait-for-miner-fs", - G_CALLBACK (update_wait_for_miner_fs), - self, G_CONNECT_SWAPPED); - update_wait_for_miner_fs (self); -} - -static void -tracker_extract_controller_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - TrackerExtractController *self = (TrackerExtractController *) object; - - switch (param_id) { - case PROP_DECORATOR: - g_value_set_object (value, self->priv->decorator); - break; - case PROP_CONNECTION: - g_value_set_object (value, self->priv->connection); - break; - } -} - -static void -tracker_extract_controller_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - TrackerExtractController *self = (TrackerExtractController *) object; - - switch (param_id) { - case PROP_DECORATOR: - g_assert (self->priv->decorator == NULL); - self->priv->decorator = g_value_dup_object (value); - break; - case PROP_CONNECTION: - self->priv->connection = g_value_dup_object (value); - break; - } -} - -static void -tracker_extract_controller_dispose (GObject *object) -{ - TrackerExtractController *self = (TrackerExtractController *) object; - - disconnect_all (self); - g_clear_object (&self->priv->decorator); - g_clear_object (&self->priv->config); - - G_OBJECT_CLASS (tracker_extract_controller_parent_class)->dispose (object); -} - -static void -tracker_extract_controller_class_init (TrackerExtractControllerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = tracker_extract_controller_constructed; - object_class->dispose = tracker_extract_controller_dispose; - object_class->get_property = tracker_extract_controller_get_property; - object_class->set_property = tracker_extract_controller_set_property; - - g_object_class_install_property (object_class, - PROP_DECORATOR, - g_param_spec_object ("decorator", - "Decorator", - "Decorator", - TRACKER_TYPE_DECORATOR, - G_PARAM_STATIC_STRINGS | - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); - g_object_class_install_property (object_class, - PROP_CONNECTION, - g_param_spec_object ("connection", - "Connection", - "Connection", - G_TYPE_DBUS_CONNECTION, - G_PARAM_STATIC_STRINGS | - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); - - g_type_class_add_private (object_class, - sizeof (TrackerExtractControllerPrivate)); -} - -static void -tracker_extract_controller_init (TrackerExtractController *self) -{ - self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, - TRACKER_TYPE_EXTRACT_CONTROLLER, - TrackerExtractControllerPrivate); -} - -TrackerExtractController * -tracker_extract_controller_new (TrackerDecorator *decorator, - GDBusConnection *connection) -{ - g_return_val_if_fail (TRACKER_IS_DECORATOR (decorator), NULL); - - return g_object_new (TRACKER_TYPE_EXTRACT_CONTROLLER, - "decorator", decorator, - "connection", connection, - NULL); -} diff --git a/src/tracker-extract/tracker-extract-controller.h b/src/tracker-extract/tracker-extract-controller.h deleted file mode 100644 index 7d8a70816..000000000 --- a/src/tracker-extract/tracker-extract-controller.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2014 - Collabora Ltd. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_EXTRACT_CONTROLLER_H__ -#define __TRACKER_EXTRACT_CONTROLLER_H__ - -#include <gio/gio.h> - -#include "tracker-extract-decorator.h" - -G_BEGIN_DECLS - -#define TRACKER_TYPE_EXTRACT_CONTROLLER (tracker_extract_controller_get_type ()) -#define TRACKER_EXTRACT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_EXTRACT_CONTROLLER, TrackerExtractController)) -#define TRACKER_EXTRACT_CONTROLLER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_EXTRACT_CONTROLLER, TrackerExtractControllerClass)) -#define TRACKER_IS_EXTRACT_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_EXTRACT_CONTROLLER)) -#define TRACKER_IS_EXTRACT_CONTROLLER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_EXTRACT_CONTROLLER)) -#define TRACKER_EXTRACT_CONTROLLER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_EXTRACT_CONTROLLER, TrackerExtractControllerClass)) - -typedef struct TrackerExtractController TrackerExtractController; -typedef struct TrackerExtractControllerClass TrackerExtractControllerClass; -typedef struct TrackerExtractControllerPrivate TrackerExtractControllerPrivate; - -struct TrackerExtractController { - GObject parent_instance; - TrackerExtractControllerPrivate *priv; -}; - -struct TrackerExtractControllerClass { - GObjectClass parent_class; -}; - -GType tracker_extract_controller_get_type (void) G_GNUC_CONST; -TrackerExtractController * tracker_extract_controller_new (TrackerDecorator *decorator, - GDBusConnection *connection); - -G_END_DECLS - -#endif /* __TRACKER_EXTRACT_CONTROLLER_H__ */ diff --git a/src/tracker-extract/tracker-extract-decorator.c b/src/tracker-extract/tracker-extract-decorator.c deleted file mode 100644 index cfb51d797..000000000 --- a/src/tracker-extract/tracker-extract-decorator.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * Copyright (C) 2014 Carlos Garnacho <carlosg@gnome.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <libtracker-sparql/tracker-sparql.h> -#include <libtracker-extract/tracker-extract.h> - -#include "tracker-extract-decorator.h" -#include "tracker-extract-persistence.h" -#include "tracker-extract-priority-dbus.h" - -enum { - PROP_EXTRACTOR = 1 -}; - -#define TRACKER_EXTRACT_DATA_SOURCE TRACKER_PREFIX_TRACKER "extractor-data-source" -#define TRACKER_EXTRACT_FAILURE_DATA_SOURCE TRACKER_PREFIX_TRACKER "extractor-failure-data-source" -#define MAX_EXTRACTING_FILES 1 - -#define TRACKER_EXTRACT_DECORATOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_EXTRACT_DECORATOR, TrackerExtractDecoratorPrivate)) - -typedef struct _TrackerExtractDecoratorPrivate TrackerExtractDecoratorPrivate; -typedef struct _ExtractData ExtractData; - -struct _ExtractData { - TrackerDecorator *decorator; - TrackerDecoratorInfo *decorator_info; - GFile *file; -}; - -struct _TrackerExtractDecoratorPrivate { - TrackerExtract *extractor; - GTimer *timer; - guint n_extracting_files; - - TrackerExtractPersistence *persistence; - GHashTable *recovery_files; - - /* DBus name -> AppData */ - GHashTable *apps; - TrackerExtractDBusPriority *iface; -}; - -typedef struct { - guint watch_id; - gchar **rdf_types; -} AppData; - -/* Preferably classes with tracker:notify true, if an - * extractor module handles new ones, it must be added - * here. - */ -static const gchar *supported_classes[] = { - "nfo:Document", - "nfo:Audio", - "nfo:Image", - "nfo:Video", - "nfo:FilesystemImage", - "nmm:Playlist", - NULL -}; - -static GInitableIface *parent_initable_iface; - -static void decorator_get_next_file (TrackerDecorator *decorator); -static void tracker_extract_decorator_initable_iface_init (GInitableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (TrackerExtractDecorator, tracker_extract_decorator, - TRACKER_TYPE_DECORATOR_FS, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, tracker_extract_decorator_initable_iface_init)) - -static void -tracker_extract_decorator_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - TrackerExtractDecoratorPrivate *priv; - - priv = TRACKER_EXTRACT_DECORATOR (object)->priv; - - switch (param_id) { - case PROP_EXTRACTOR: - g_value_set_object (value, priv->extractor); - break; - } -} - -static void -tracker_extract_decorator_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - TrackerExtractDecoratorPrivate *priv; - - priv = TRACKER_EXTRACT_DECORATOR (object)->priv; - - switch (param_id) { - case PROP_EXTRACTOR: - priv->extractor = g_value_dup_object (value); - break; - } -} - -static void -tracker_extract_decorator_finalize (GObject *object) -{ - TrackerExtractDecoratorPrivate *priv; - - priv = TRACKER_EXTRACT_DECORATOR (object)->priv; - - if (priv->extractor) - g_object_unref (priv->extractor); - - if (priv->timer) - g_timer_destroy (priv->timer); - - g_object_unref (priv->iface); - g_hash_table_unref (priv->apps); - g_hash_table_unref (priv->recovery_files); - - G_OBJECT_CLASS (tracker_extract_decorator_parent_class)->finalize (object); -} - -static TrackerResource * -decorator_save_info (TrackerExtractDecorator *decorator, - TrackerDecoratorInfo *decorator_info, - TrackerExtractInfo *info) -{ - const gchar *urn; - TrackerResource *resource = NULL; - - g_set_object (&resource, tracker_extract_info_get_resource (info)); - - if (resource == NULL) { - g_message ("Extract module returned no resource for %s", - tracker_decorator_info_get_url (decorator_info)); - /* We must still insert something into the store so that the correct - * nie:dataSource triple get inserted. Otherwise, tracker-extract will - * try to re-extract this file every time it starts. - */ - resource = tracker_resource_new (NULL); - } - - urn = tracker_decorator_info_get_urn (decorator_info); - - tracker_resource_set_identifier (resource, urn); - tracker_resource_set_uri (resource, "nie:dataSource", - tracker_decorator_get_data_source (TRACKER_DECORATOR (decorator))); - - return resource; -} - -static void -get_metadata_cb (TrackerExtract *extract, - GAsyncResult *result, - ExtractData *data) -{ - TrackerExtractDecoratorPrivate *priv; - TrackerExtractInfo *info; - TrackerResource *resource; - GError *error = NULL; - gchar *sparql; - - priv = TRACKER_EXTRACT_DECORATOR (data->decorator)->priv; - info = tracker_extract_file_finish (extract, result, &error); - - tracker_extract_persistence_remove_file (priv->persistence, data->file); - g_hash_table_remove (priv->recovery_files, tracker_decorator_info_get_url (data->decorator_info)); - - if (error) { - if (error->domain == TRACKER_EXTRACT_ERROR) { - g_message ("Extraction failed: %s\n", error ? error->message : "no error given"); - tracker_decorator_info_complete (data->decorator_info, NULL); - g_clear_error (&error); - } else { - tracker_decorator_info_complete_error (data->decorator_info, error); - } - } else { - resource = decorator_save_info (TRACKER_EXTRACT_DECORATOR (data->decorator), - data->decorator_info, info); - sparql = tracker_resource_print_sparql_update (resource, NULL, - TRACKER_OWN_GRAPH_URN); - tracker_decorator_info_complete (data->decorator_info, sparql); - tracker_extract_info_unref (info); - g_object_unref (resource); - } - - priv->n_extracting_files--; - decorator_get_next_file (data->decorator); - - tracker_decorator_info_unref (data->decorator_info); - g_object_unref (data->file); - g_free (data); -} - -static GFile * -decorator_get_recovery_file (TrackerExtractDecorator *decorator, - TrackerDecoratorInfo *info) -{ - TrackerExtractDecoratorPrivate *priv; - GFile *file; - - priv = decorator->priv; - file = g_hash_table_lookup (priv->recovery_files, - tracker_decorator_info_get_url (info)); - - if (file) { - g_object_ref (file); - } else { - file = g_file_new_for_uri (tracker_decorator_info_get_url (info)); - } - - return file; -} - -static void -decorator_next_item_cb (TrackerDecorator *decorator, - GAsyncResult *result, - gpointer user_data) -{ - TrackerExtractDecoratorPrivate *priv; - TrackerDecoratorInfo *info; - GError *error = NULL; - ExtractData *data; - GTask *task; - - priv = TRACKER_EXTRACT_DECORATOR (decorator)->priv; - info = tracker_decorator_next_finish (decorator, result, &error); - - if (!info) { - priv->n_extracting_files--; - - if (error && - error->domain == tracker_decorator_error_quark ()) { - switch (error->code) { - case TRACKER_DECORATOR_ERROR_EMPTY: - g_message ("There are no further items to extract"); - break; - case TRACKER_DECORATOR_ERROR_PAUSED: - g_message ("Next item is on hold because miner is paused"); - } - } else if (error) { - g_warning ("Next item could not be processed, %s", error->message); - } - - g_clear_error (&error); - return; - } - - data = g_new0 (ExtractData, 1); - data->decorator = decorator; - data->decorator_info = info; - data->file = decorator_get_recovery_file (TRACKER_EXTRACT_DECORATOR (decorator), info); - task = tracker_decorator_info_get_task (info); - - g_message ("Extracting metadata for '%s'", tracker_decorator_info_get_url (info)); - - tracker_extract_persistence_add_file (priv->persistence, data->file); - - tracker_extract_file (priv->extractor, - tracker_decorator_info_get_url (info), - tracker_decorator_info_get_mimetype (info), - g_task_get_cancellable (task), - (GAsyncReadyCallback) get_metadata_cb, data); -} - -static void -decorator_get_next_file (TrackerDecorator *decorator) -{ - TrackerExtractDecoratorPrivate *priv; - guint available_items; - - priv = TRACKER_EXTRACT_DECORATOR (decorator)->priv; - - if (!tracker_miner_is_started (TRACKER_MINER (decorator)) || - tracker_miner_is_paused (TRACKER_MINER (decorator))) - return; - - available_items = tracker_decorator_get_n_items (decorator); - while (priv->n_extracting_files < MAX_EXTRACTING_FILES && - available_items > 0) { - priv->n_extracting_files++; - available_items--; - tracker_decorator_next (decorator, NULL, - (GAsyncReadyCallback) decorator_next_item_cb, - NULL); - } -} - -static void -tracker_extract_decorator_paused (TrackerMiner *miner) -{ - TrackerExtractDecoratorPrivate *priv; - - priv = TRACKER_EXTRACT_DECORATOR (miner)->priv; - g_message ("Decorator paused"); - - if (priv->timer) - g_timer_stop (priv->timer); -} - -static void -tracker_extract_decorator_resumed (TrackerMiner *miner) -{ - TrackerExtractDecoratorPrivate *priv; - - priv = TRACKER_EXTRACT_DECORATOR (miner)->priv; - g_message ("Decorator resumed, processing remaining %d items", - tracker_decorator_get_n_items (TRACKER_DECORATOR (miner))); - - if (priv->timer) - g_timer_continue (priv->timer); - - decorator_get_next_file (TRACKER_DECORATOR (miner)); -} - -static void -tracker_extract_decorator_items_available (TrackerDecorator *decorator) -{ - TrackerExtractDecoratorPrivate *priv; - - priv = TRACKER_EXTRACT_DECORATOR (decorator)->priv; - g_message ("Starting to process %d items", - tracker_decorator_get_n_items (decorator)); - - priv->timer = g_timer_new (); - if (tracker_miner_is_paused (TRACKER_MINER (decorator))) - g_timer_stop (priv->timer); - - decorator_get_next_file (decorator); -} - -static void -tracker_extract_decorator_finished (TrackerDecorator *decorator) -{ - TrackerExtractDecoratorPrivate *priv; - gchar *time_str; - - priv = TRACKER_EXTRACT_DECORATOR (decorator)->priv; - time_str = tracker_seconds_to_string ((gint) g_timer_elapsed (priv->timer, NULL), TRUE); - g_message ("Extraction finished in %s", time_str); - g_timer_destroy (priv->timer); - priv->timer = NULL; - g_free (time_str); -} - -static gboolean -strv_contains (const gchar * const *strv, - const gchar *needle) -{ - guint i; - - for (i = 0; strv[i] != NULL; i++) { - if (g_str_equal (strv[i], needle)) - return TRUE; - } - - return FALSE; -} - -static void -string_array_add (GPtrArray *array, - const gchar *str) -{ - guint i; - - for (i = 0; i < array->len; i++) { - if (g_str_equal (g_ptr_array_index (array, i), str)) - return; - } - - g_ptr_array_add (array, (gchar *) str); -} - -static void -priority_changed (TrackerExtractDecorator *decorator) -{ - TrackerExtractDecoratorPrivate *priv; - GPtrArray *array; - GHashTableIter iter; - gpointer value; - - priv = TRACKER_EXTRACT_DECORATOR (decorator)->priv; - - /* Construct an strv removing dups */ - array = g_ptr_array_new (); - g_hash_table_iter_init (&iter, priv->apps); - while (g_hash_table_iter_next (&iter, NULL, &value)) { - AppData *data = value; - guint i; - - for (i = 0; data->rdf_types[i] != NULL; i++) { - string_array_add (array, data->rdf_types[i]); - } - } - g_ptr_array_add (array, NULL); - - tracker_decorator_set_priority_rdf_types (TRACKER_DECORATOR (decorator), - (const gchar * const *) array->pdata); - - g_ptr_array_unref (array); -} - -static void -app_data_destroy (AppData *data) -{ - g_bus_unwatch_name (data->watch_id); - g_strfreev (data->rdf_types); - g_slice_free (AppData, data); -} - -static void -name_vanished_cb (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - TrackerExtractDecorator *decorator = user_data; - TrackerExtractDecoratorPrivate *priv; - - priv = TRACKER_EXTRACT_DECORATOR (decorator)->priv; - g_hash_table_remove (priv->apps, name); - priority_changed (decorator); -} - -static gboolean -handle_set_rdf_types_cb (TrackerExtractDBusPriority *iface, - GDBusMethodInvocation *invocation, - const gchar * const *rdf_types, - TrackerExtractDecorator *decorator) -{ - TrackerExtractDecoratorPrivate *priv; - const gchar *sender; - GDBusConnection *conn; - AppData *data; - guint i; - - priv = TRACKER_EXTRACT_DECORATOR (decorator)->priv; - sender = g_dbus_method_invocation_get_sender (invocation); - conn = g_dbus_method_invocation_get_connection (invocation); - - if (rdf_types[0] == NULL) { - g_hash_table_remove (priv->apps, sender); - goto out; - } - - /* Verify all types are supported */ - for (i = 0; rdf_types[i] != NULL; i++) { - if (!strv_contains (supported_classes, rdf_types[i])) { - g_dbus_method_invocation_return_error (invocation, - TRACKER_DBUS_ERROR, - TRACKER_DBUS_ERROR_ASSERTION_FAILED, - "Unsupported rdf:type %s", - rdf_types[i]); - return TRUE; - } - } - - data = g_hash_table_lookup (priv->apps, sender); - if (data == NULL) { - data = g_slice_new0 (AppData); - data->watch_id = g_bus_watch_name_on_connection (conn, - sender, - G_BUS_NAME_WATCHER_FLAGS_NONE, - NULL, - name_vanished_cb, - decorator, NULL); - g_hash_table_insert (priv->apps, - g_strdup (sender), - data); - } else { - g_strfreev (data->rdf_types); - } - - data->rdf_types = g_strdupv ((GStrv) rdf_types); - -out: - priority_changed (decorator); - - tracker_extract_dbus_priority_complete_set_rdf_types (iface, invocation); - - return TRUE; -} - -static gboolean -handle_clear_rdf_types_cb (TrackerExtractDBusPriority *iface, - GDBusMethodInvocation *invocation, - TrackerExtractDecorator *decorator) -{ - TrackerExtractDecoratorPrivate *priv; - const gchar *sender; - - priv = TRACKER_EXTRACT_DECORATOR (decorator)->priv; - sender = g_dbus_method_invocation_get_sender (invocation); - - g_hash_table_remove (priv->apps, sender); - priority_changed (decorator); - - tracker_extract_dbus_priority_complete_clear_rdf_types (iface, invocation); - - return TRUE; -} - -static void -tracker_extract_decorator_class_init (TrackerExtractDecoratorClass *klass) -{ - TrackerDecoratorClass *decorator_class = TRACKER_DECORATOR_CLASS (klass); - TrackerMinerClass *miner_class = TRACKER_MINER_CLASS (klass); - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = tracker_extract_decorator_finalize; - object_class->get_property = tracker_extract_decorator_get_property; - object_class->set_property = tracker_extract_decorator_set_property; - - miner_class->paused = tracker_extract_decorator_paused; - miner_class->resumed = tracker_extract_decorator_resumed; - - decorator_class->items_available = tracker_extract_decorator_items_available; - decorator_class->finished = tracker_extract_decorator_finished; - - g_object_class_install_property (object_class, - PROP_EXTRACTOR, - g_param_spec_object ("extractor", - "Extractor", - "Extractor", - TRACKER_TYPE_EXTRACT, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY)); - - g_type_class_add_private (object_class, - sizeof (TrackerExtractDecoratorPrivate)); -} - -static void -decorator_retry_file (GFile *file, - gpointer user_data) -{ - TrackerExtractDecorator *decorator = user_data; - TrackerExtractDecoratorPrivate *priv = decorator->priv; - gchar *path; - - path = g_file_get_uri (file); - g_hash_table_insert (priv->recovery_files, path, g_object_ref (file)); - tracker_decorator_fs_prepend_file (TRACKER_DECORATOR_FS (decorator), file); -} - -static void -decorator_ignore_file (GFile *file, - gpointer user_data) -{ - TrackerExtractDecorator *decorator = user_data; - TrackerSparqlConnection *conn; - GError *error = NULL; - gchar *uri, *query; - - uri = g_file_get_uri (file); - g_message ("Extraction on file '%s' has been attempted too many times, ignoring", uri); - - conn = tracker_miner_get_connection (TRACKER_MINER (decorator)); - query = g_strdup_printf ("INSERT { GRAPH <" TRACKER_OWN_GRAPH_URN "> {" - " ?urn nie:dataSource <" TRACKER_EXTRACT_DATA_SOURCE ">;" - " nie:dataSource <" TRACKER_EXTRACT_FAILURE_DATA_SOURCE ">." - "} } WHERE {" - " ?urn nie:url \"%s\"" - "}", uri); - - tracker_sparql_connection_update (conn, query, G_PRIORITY_DEFAULT, NULL, &error); - - if (error) { - g_warning ("Failed to update ignored file '%s': %s", - uri, error->message); - g_error_free (error); - } - - g_free (query); - g_free (uri); -} - -static void -tracker_extract_decorator_init (TrackerExtractDecorator *decorator) -{ - TrackerExtractDecoratorPrivate *priv; - - decorator->priv = priv = TRACKER_EXTRACT_DECORATOR_GET_PRIVATE (decorator); - priv->recovery_files = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_object_unref); -} - -static gboolean -tracker_extract_decorator_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - TrackerExtractDecorator *decorator; - TrackerExtractDecoratorPrivate *priv; - GDBusConnection *conn; - gboolean ret = TRUE; - - decorator = TRACKER_EXTRACT_DECORATOR (initable); - priv = decorator->priv; - - priv->apps = g_hash_table_new_full (g_str_hash, - g_str_equal, - g_free, - (GDestroyNotify) app_data_destroy); - - priv->iface = tracker_extract_dbus_priority_skeleton_new (); - g_signal_connect (priv->iface, "handle-set-rdf-types", - G_CALLBACK (handle_set_rdf_types_cb), - decorator); - g_signal_connect (priv->iface, "handle-clear-rdf-types", - G_CALLBACK (handle_clear_rdf_types_cb), - decorator); - - tracker_extract_dbus_priority_set_supported_rdf_types (priv->iface, - supported_classes); - - conn = g_bus_get_sync (TRACKER_IPC_BUS, NULL, error); - if (conn == NULL) { - ret = FALSE; - goto out; - } - - if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (priv->iface), - conn, - "/org/freedesktop/Tracker1/Extract/Priority", - error)) { - ret = FALSE; - goto out; - } - - /* Chainup to parent's init last, to have a chance to export our - * DBus interface before RequestName returns. Otherwise our iface - * won't be ready by the time the tracker-extract appear on the bus. */ - if (!parent_initable_iface->init (initable, cancellable, error)) { - ret = FALSE; - } - - priv->persistence = tracker_extract_persistence_initialize (decorator_retry_file, - decorator_ignore_file, - decorator); -out: - g_clear_object (&conn); - - return ret; -} - -static void -tracker_extract_decorator_initable_iface_init (GInitableIface *iface) -{ - parent_initable_iface = g_type_interface_peek_parent (iface); - iface->init = tracker_extract_decorator_initable_init; -} - -TrackerDecorator * -tracker_extract_decorator_new (TrackerExtract *extract, - GCancellable *cancellable, - GError **error) -{ - return g_initable_new (TRACKER_TYPE_EXTRACT_DECORATOR, - cancellable, error, - "data-source", TRACKER_EXTRACT_DATA_SOURCE, - "class-names", supported_classes, - "extractor", extract, - NULL); -} diff --git a/src/tracker-extract/tracker-extract-decorator.h b/src/tracker-extract/tracker-extract-decorator.h deleted file mode 100644 index 6d16eeb64..000000000 --- a/src/tracker-extract/tracker-extract-decorator.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2014 Carlos Garnacho <carlosg@gnome.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_EXTRACT_DECORATOR_H__ -#define __TRACKER_EXTRACT_DECORATOR_H__ - -#include <gio/gio.h> -#include <libtracker-miner/tracker-miner.h> - -#include "tracker-extract.h" - -G_BEGIN_DECLS - -#define TRACKER_TYPE_EXTRACT_DECORATOR (tracker_extract_decorator_get_type ()) -#define TRACKER_EXTRACT_DECORATOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_EXTRACT_DECORATOR, TrackerExtractDecorator)) -#define TRACKER_EXTRACT_DECORATOR_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_EXTRACT_DECORATOR, TrackerExtractDecoratorClass)) -#define TRACKER_IS_EXTRACT_DECORATOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_EXTRACT_DECORATOR)) -#define TRACKER_IS_EXTRACT_DECORATOR_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_EXTRACT_DECORATOR)) -#define TRACKER_EXTRACT_DECORATOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_EXTRACT_DECORATOR, TrackerExtractDecoratorClass)) - -typedef struct TrackerExtractDecorator TrackerExtractDecorator; -typedef struct TrackerExtractDecoratorClass TrackerExtractDecoratorClass; - -struct TrackerExtractDecorator { - TrackerDecoratorFS parent_instance; - gpointer priv; -}; - -struct TrackerExtractDecoratorClass { - TrackerDecoratorFSClass parent_class; -}; - -GType tracker_extract_decorator_get_type (void) G_GNUC_CONST; - -TrackerDecorator * tracker_extract_decorator_new (TrackerExtract *extractor, - GCancellable *cancellable, - GError **error); - -G_END_DECLS - -#endif /* __TRACKER_EXTRACT_DECORATOR_H__ */ diff --git a/src/tracker-extract/tracker-extract-dummy.c b/src/tracker-extract/tracker-extract-dummy.c deleted file mode 100644 index 392c4914d..000000000 --- a/src/tracker-extract/tracker-extract-dummy.c +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright (C) 2013-2014 Jolla Ltd. <andrew.den.exter@jollamobile.com> - * Author: Philip Van Hoof <philip@codeminded.be> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <libtracker-common/tracker-common.h> -#include <libtracker-extract/tracker-extract.h> - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - /* Nothing */ - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-dvi.c b/src/tracker-extract/tracker-extract-dvi.c deleted file mode 100644 index 48c6aef37..000000000 --- a/src/tracker-extract/tracker-extract-dvi.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (C) 2012, Red Hat, Inc. - * - * Code adapted from evince/backend/dvi/mdvi-lib/dviread.c - * Copyright (C) 2000, Matias Atria - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include <stdio.h> -#include <fcntl.h> -#include <string.h> -#include <unistd.h> - -#include <glib.h> -#include <gmodule.h> - -#include <libtracker-extract/tracker-extract.h> - -#define __PROTO(x) x -extern gulong fugetn __PROTO((FILE *, size_t)); - -#define fgetbyte(p) ((unsigned)getc(p)) -#define fuget4(p) fugetn((p), 4) -#define fuget3(p) fugetn((p), 3) -#define fuget2(p) fugetn((p), 2) -#define fuget1(p) fgetbyte(p) - - -#define DVI_ID 2 -#define DVI_TRAILER 223 -#define DVI_PRE 247 -#define DVI_POST 248 - -typedef struct { - char *filename; /* name of the DVI file */ - FILE *in; /* from here we read */ - char *fileid; /* from preamble */ - int npages; /* number of pages */ - int depth; /* recursion depth */ - gint32 num; /* numerator */ - gint32 den; /* denominator */ - gint32 dvimag; /* original magnification */ - int dvi_page_w; /* unscaled page width */ - int dvi_page_h; /* unscaled page height */ - int stacksize; /* stack depth */ -} DviContext; - -gulong -fugetn (FILE *p, size_t n) -{ - gulong v; - - v = fgetbyte(p); - while (--n > 0) { - v = (v << 8) | fgetbyte(p); - } - - return v; -} - -static char * -opendvi (const char *name) -{ - int len; - - len = strlen (name); - - /* if file ends with .dvi and it exists, that's it */ - if (len >= 4 && g_strcmp0 (name + len - 4, ".dvi") == 0) { - g_debug ("Opening filename:'%s'", name); - - if (access (name, R_OK) == 0) { - return g_strdup (name); - } - } - - return NULL; -} - -static void -mdvi_destroy_context (DviContext *dvi) -{ - g_free (dvi->filename); - g_free (dvi->fileid); - - if (dvi->in) { - fclose (dvi->in); - } - - g_free (dvi); -} - -static DviContext * -mdvi_init_context (const char *file) -{ - FILE *p; - gint32 arg; - int op; - int n; - DviContext *dvi; - char *filename; - - /* - * 1. Open the file and initialize the DVI context - */ - filename = opendvi (file); - if (filename == NULL) { - return NULL; - } - - p = fopen (filename, "rb"); - if (p == NULL) { - g_free (filename); - return NULL; - } - - dvi = g_new0 (DviContext, 1); - dvi->filename = filename; - dvi->in = p; - - /* - * 2. Read the preamble, extract scaling information - */ - if (fuget1 (p) != DVI_PRE) { - goto error; - } - - if ((arg = fuget1 (p)) != DVI_ID) { - g_message ("Unsupported DVI format (version %u)", arg); - goto error; - } - - /* get dimensions */ - dvi->num = fuget4 (p); - dvi->den = fuget4 (p); - dvi->dvimag = fuget4 (p); - - /* check that these numbers make sense */ - if (!dvi->num || !dvi->den || !dvi->dvimag) { - goto error; - } - - /* get the comment from the preamble */ - n = fuget1 (p); - dvi->fileid = g_malloc (n + 1); - fread (dvi->fileid, 1, n, p); - dvi->fileid[n] = 0; - g_debug ("Preamble Comment: '%s'", dvi->fileid); - - /* - * 3. Read postamble, extract page information (number of - * pages, dimensions) and stack depth. - */ - - /* jump to the end of the file */ - if (fseek (p, (long) - 1, SEEK_END) == -1) { - goto error; - } - - for (n = 0; (op = fuget1 (p)) == DVI_TRAILER; n++) { - if (fseek (p, (long) - 2, SEEK_CUR) < 0) { - break; - } - } - - if (op != arg || n < 4) { - goto error; - } - - /* get the pointer to postamble */ - fseek (p, (long) - 5, SEEK_CUR); - arg = fuget4 (p); - - /* jump to it */ - fseek (p, (long) arg, SEEK_SET); - if (fuget1 (p) != DVI_POST) { - goto error; - } - - fuget4 (p); /* offset */ - if (dvi->num != fuget4 (p) || - dvi->den != fuget4 (p) || - dvi->dvimag != fuget4 (p)) { - goto error; - } - dvi->dvi_page_h = fuget4 (p); - dvi->dvi_page_w = fuget4 (p); - dvi->stacksize = fuget2 (p); - dvi->npages = fuget2 (p); - - g_debug ("Postamble: %d pages", dvi->npages); - - return dvi; - -error: - mdvi_destroy_context (dvi); - return NULL; -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerResource *resource; - GFile *file; - gchar *filename; - DviContext *context; - - file = tracker_extract_info_get_file (info); - filename = g_file_get_path (file); - - context = mdvi_init_context (filename); - - if (context == NULL) { - g_warning ("Could not open dvi file '%s'\n", filename); - g_free (filename); - return FALSE; - } - - resource = tracker_resource_new (NULL); - - tracker_resource_add_uri (resource, "rdf:type", "nfo:PaginatedTextDocument"); - - tracker_resource_set_int64 (resource, "nfo:pageCount", context->npages); - - if (context->fileid) { - tracker_resource_set_string (resource, "nie:comment", context->fileid); - } - - mdvi_destroy_context (context); - - tracker_extract_info_set_resource (info, resource); - g_object_unref (resource); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-epub.c b/src/tracker-extract/tracker-extract-epub.c deleted file mode 100644 index 2e65e10bd..000000000 --- a/src/tracker-extract/tracker-extract-epub.c +++ /dev/null @@ -1,693 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include <libtracker-extract/tracker-extract.h> - -#include "tracker-main.h" -#include "tracker-gsf.h" -#include "tracker-read.h" - -#include <unistd.h> - -typedef enum { - OPF_TAG_TYPE_UNKNOWN, - OPF_TAG_TYPE_TITLE, - OPF_TAG_TYPE_CREATED, - - OPF_TAG_TYPE_AUTHOR, - OPF_TAG_TYPE_EDITOR, - OPF_TAG_TYPE_ILLUSTRATOR, - OPF_TAG_TYPE_CONTRIBUTOR, - - OPF_TAG_TYPE_LANGUAGE, - OPF_TAG_TYPE_SUBJECT, - OPF_TAG_TYPE_DESCRIPTION, - OPF_TAG_TYPE_UUID, - OPF_TAG_TYPE_ISBN, - OPF_TAG_TYPE_PUBLISHER, - OPF_TAG_TYPE_RATING /* calibre addition, should it be indexed? how? */ -} OPFTagType; - -typedef struct { - TrackerResource *resource; - gchar *uri; - - OPFTagType element; - GList *pages; - guint in_metadata : 1; - guint in_manifest : 1; - guint has_publisher : 1; - guint has_title : 1; - guint has_content_created : 1; - guint has_language : 1; - guint has_subject : 1; - guint has_description : 1; - guint has_identifier : 1; - gchar *savedstring; -} OPFData; - -typedef struct { - GString *contents; - gsize limit; -} OPFContentData; - -static inline OPFData * -opf_data_new (const char *uri, - TrackerResource *resource) -{ - OPFData *data = g_slice_new0 (OPFData); - - data->uri = g_strdup (uri); - data->resource = g_object_ref (resource); - - return data; -} - -static inline void -opf_data_clear_saved_string (OPFData *data) -{ - if (!data || !data->savedstring) { - return; - } - - g_free (data->savedstring); - data->savedstring = NULL; -} - -static inline void -opf_data_free (OPFData *data) -{ - if (!data) { - return; - } - - g_free (data->savedstring); - - g_list_foreach (data->pages, (GFunc) g_free, NULL); - g_list_free (data->pages); - - g_object_unref (data->resource); - g_free (data->uri); - - g_slice_free (OPFData, data); -} - -/* Methods to parse the container.xml file - * pointing to the real metadata/content - */ -static void -container_xml_start_element_handler (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - gchar **path_out = user_data; - gint i; - - if (g_strcmp0 (element_name, "rootfile") != 0) { - return; - } - - for (i = 0; attribute_names[i] != NULL; i++) { - if (g_strcmp0 (attribute_names[i], "full-path") == 0) { - if (!*path_out) { - *path_out = g_strdup (attribute_values[i]); - } - break; - } - } -} - -/* Methods to parse the OPF document metadata/layout */ -static void -opf_xml_start_element_handler (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - OPFData *data = user_data; - gint i; - gboolean has_role_attr = FALSE; - - if (g_strcmp0 (element_name, "metadata") == 0) { - data->in_metadata = TRUE; - } else if (g_strcmp0 (element_name, "manifest") == 0) { - data->in_manifest = TRUE; - } else if (data->in_metadata) { - /* epub metadata */ - if (g_strcmp0 (element_name, "dc:title") == 0) { - data->element = OPF_TAG_TYPE_TITLE; - } else if (g_strcmp0 (element_name, "dc:creator") == 0) { - for (i = 0; attribute_names[i] != NULL; i++) { - if (g_strcmp0 (attribute_names[i], "opf:file-as") == 0) { - g_debug ("Found creator file-as tag"); - data->savedstring = g_strdup (attribute_values[i]); - } else if (g_strcmp0 (attribute_names[i], "opf:role") == 0) { - has_role_attr = TRUE; - if (g_strcmp0 (attribute_values[i], "aut") == 0) { - data->element = OPF_TAG_TYPE_AUTHOR; - } else if (g_strcmp0 (attribute_values[i], "edt") == 0) { - data->element = OPF_TAG_TYPE_EDITOR; - } else if (g_strcmp0 (attribute_values[i], "ill") == 0) { - data->element = OPF_TAG_TYPE_ILLUSTRATOR; - } else { - data->element = OPF_TAG_TYPE_UNKNOWN; - opf_data_clear_saved_string (data); - g_debug ("Unknown role, skipping"); - } - } - } - if (!has_role_attr) { - data->element = OPF_TAG_TYPE_AUTHOR; - } - } else if (g_strcmp0 (element_name, "dc:date") == 0) { - for (i = 0; attribute_names[i] != NULL; i++) { - if (g_strcmp0 (attribute_names[i], "opf:event") == 0 && - g_strcmp0 (attribute_values[i], "original-publication") == 0) { - data->element = OPF_TAG_TYPE_CREATED; - break; - } - } - } else if (g_strcmp0 (element_name, "dc:publisher") == 0) { - data->element = OPF_TAG_TYPE_PUBLISHER; - } else if (g_strcmp0 (element_name, "dc:description") == 0) { - data->element = OPF_TAG_TYPE_DESCRIPTION; - } else if (g_strcmp0 (element_name, "dc:language") == 0) { - data->element = OPF_TAG_TYPE_LANGUAGE; - } else if (g_strcmp0 (element_name, "dc:identifier") == 0) { - data->element = OPF_TAG_TYPE_UUID; - for (i = 0; attribute_names[i] != NULL; i++) { - if (g_strcmp0 (attribute_names[i], "opf:scheme") == 0) { - if (g_ascii_strncasecmp (attribute_values[i], "isbn", 4) == 0) { - data->element = OPF_TAG_TYPE_ISBN; - } - } - } - /* } else if (g_strcmp0 (element_name, "meta") == 0) { */ - /* for (i = 0; attribute_names[i] != NULL; i++) { */ - /* if (g_strcmp0 (attribute_names[i], "name") == 0) { */ - /* if (g_strcmp0 (attribute_values[i], "calibre:rating") == 0) { */ - /* anybool = TRUE; */ - /* } */ - /* } else if (anybool && g_strcmp0 (attribute_names[i], "content")) { */ - /* data->element = OPF_TAG_TYPE_RATING; */ - /* data->savedstring = g_strdup (attribute_values[i]); */ - /* } */ - /* } */ - /* } else if (g_strcmp0 (element_name, "dc:subject") == 0) { */ - /* data->element = OPF_TAG_TYPE_SUBJECT; */ - } - } else if (data->in_manifest && - g_strcmp0 (element_name, "item") == 0) { - const gchar *rel_path = NULL; - gboolean is_xhtml = FALSE; - - /* Keep list of xhtml documents for plain text extraction */ - for (i = 0; attribute_names[i] != NULL; i++) { - if (g_strcmp0 (attribute_names[i], "href") == 0) { - rel_path = attribute_values[i]; - } else if (g_strcmp0 (attribute_names[i], "media-type") == 0 && - g_strcmp0 (attribute_values[i], "application/xhtml+xml") == 0) { - is_xhtml = TRUE; - } - } - - if (is_xhtml && rel_path) { - data->pages = g_list_append (data->pages, g_strdup (rel_path)); - } - } -} - -static void -opf_xml_end_element_handler (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - OPFData *data = user_data; - - if (g_strcmp0 (element_name, "metadata") == 0) { - data->in_metadata = FALSE; - } else if (g_strcmp0 (element_name, "manifest") == 0) { - data->in_manifest = FALSE; - } else { - data->element = OPF_TAG_TYPE_UNKNOWN; - } -} - -static void -opf_xml_text_handler (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - OPFData *data = user_data; - - switch (data->element) { - case OPF_TAG_TYPE_PUBLISHER: - if (data->has_publisher) { - g_warning ("Avoiding additional publisher (%s) in EPUB '%s'", - text, data->uri); - } else { - TrackerResource *publisher; - - publisher = tracker_resource_new (NULL); - tracker_resource_set_uri (publisher, "rdf:type", "nco:Contact"); - tracker_resource_set_string (publisher, "nco:fullname", text); - - tracker_resource_set_relation (data->resource, "nco:publisher", publisher); - g_object_unref (publisher); - - data->has_publisher = TRUE; - } - break; - case OPF_TAG_TYPE_AUTHOR: - case OPF_TAG_TYPE_EDITOR: - case OPF_TAG_TYPE_ILLUSTRATOR: - case OPF_TAG_TYPE_CONTRIBUTOR: { - TrackerResource *contact, *artist = NULL; - gchar *fname, *gname, *oname; - const gchar *fullname = NULL; - gchar *role_uri = NULL; - const gchar *role_str = NULL; - gint i, j = 0, len; - - fname = NULL; - gname = NULL; - oname = NULL; - - /* parse name. may not work for dissimilar cultures. */ - if (data->savedstring != NULL) { - fullname = data->savedstring; - - /* <family name>, <given name> <other name> */ - g_debug ("Parsing 'opf:file-as' attribute:'%s'", data->savedstring); - len = strlen (data->savedstring); - - for (i = 0; i < len; i++) { - if (data->savedstring[i] == ',') { - fname = g_strndup (data->savedstring, i); - g_debug ("Found family name:'%s'", fname); - - for (; data->savedstring[i] == ',' || data->savedstring[i] == ' '; i++); - j = i; - - break; - } - } - - if (i == len) { - fname = g_strdup (data->savedstring); - g_debug ("Found only one name"); - } else { - for (; i <= len; i++) { - if (i == len || data->savedstring[i] == ' ') { - gname = g_strndup (data->savedstring + j, i - j); - g_debug ("Found given name:'%s'", gname); - - for (; data->savedstring[i] == ',' || data->savedstring[i] == ' '; i++); - - if (i != len) { - oname = g_strdup (data->savedstring + i); - g_debug ("Found other name:'%s'", oname); - } - - break; - } - } - } - } else { - fullname = text; - - /* <given name> <other name> <family name> */ - g_debug ("Parsing name, no 'opf:file-as' found: '%s'", text); - - len = strlen (text); - - for (i = 0; i < len; i++) { - if (text[i] == ' ') { - gname = g_strndup (text, i); - g_debug ("Found given name:'%s'", gname); - j = i + 1; - - break; - } - } - - if (j == 0) { - fname = g_strdup (data->savedstring); - g_debug ("Found only one name:'%s'", fname); - } else { - for (i = len - 1; i >= j - 1; i--) { - if (text[i] == ' ') { - fname = g_strdup (text + i + 1); - g_debug ("Found family name:'%s'", fname); - - if (i > j) { - oname = g_strndup (text + j, i - j); - g_debug ("Found other name:'%s'", oname); - } - - break; - } - } - } - } - - /* Role details */ - role_uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", fullname); - - if (data->element == OPF_TAG_TYPE_AUTHOR) { - role_str = "nco:creator"; - } else if (data->element == OPF_TAG_TYPE_EDITOR && !data->has_publisher) { - /* Should this be nco:contributor ? - * 'Editor' is a bit vague here. - */ - role_str = "nco:publisher"; - } else if (data->element == OPF_TAG_TYPE_ILLUSTRATOR) { - /* There is no illustrator class, using contributor */ - role_str = "nco:contributor"; - } else { - g_assert ("Unknown role"); - } - - if (role_uri) { - artist = tracker_resource_new (role_uri); - tracker_resource_set_uri (artist, "rdf:type", "nmm:Artist"); - tracker_resource_set_string (artist, "nmm:artistName", fullname); - } - - /* Creator contact details */ - contact = tracker_resource_new (NULL); - tracker_resource_set_uri (contact, "rdf:type", "nco:PersonContact"); - tracker_resource_set_string (contact, "nco:fullname", fullname); - - if (fname) { - tracker_resource_set_string (contact, "nco:nameFamily", fname); - g_free (fname); - } - - if (gname) { - tracker_resource_set_string (contact, "nco:nameGiven", gname); - g_free (gname); - } - - if (oname) { - tracker_resource_set_string (contact, "nco:nameAdditional", oname); - g_free (oname); - } - - if (role_uri) { - tracker_resource_set_relation (contact, role_str, artist); - g_free (role_uri); - } - - tracker_resource_set_relation (data->resource, "nco:creator", contact); - g_clear_object (&artist); - g_object_unref (contact); - - break; - } - case OPF_TAG_TYPE_TITLE: - if (data->has_title) { - g_warning ("Avoiding additional title (%s) in EPUB '%s'", - text, data->uri); - } else { - data->has_title = TRUE; - tracker_resource_set_string (data->resource, "nie:title", text); - } - break; - case OPF_TAG_TYPE_CREATED: { - if (data->has_content_created) { - g_warning ("Avoiding additional creation time (%s) in EPUB '%s'", - text, data->uri); - } else { - gchar *date = tracker_date_guess (text); - - if (date) { - data->has_content_created = TRUE; - tracker_resource_set_string (data->resource, "nie:contentCreated", date); - g_free (date); - } else { - g_warning ("Could not parse creation time (%s) in EPUB '%s'", - text, data->uri); - } - } - break; - } - case OPF_TAG_TYPE_LANGUAGE: - if (data->has_language) { - g_warning ("Avoiding additional language (%s) in EPUB '%s'", - text, data->uri); - } else { - data->has_language = TRUE; - tracker_resource_set_string (data->resource, "nie:language", text); - } - break; - case OPF_TAG_TYPE_SUBJECT: - if (data->has_subject) { - g_warning ("Avoiding additional subject (%s) in EPUB '%s'", - text, data->uri); - } else { - data->has_subject = TRUE; - tracker_resource_set_string (data->resource, "nie:subject", text); - } - break; - case OPF_TAG_TYPE_DESCRIPTION: - if (data->has_description) { - g_warning ("Avoiding additional description (%s) in EPUB '%s'", - text, data->uri); - } else { - data->has_description = TRUE; - tracker_resource_set_string (data->resource, "nie:description", text); - } - break; - case OPF_TAG_TYPE_UUID: - case OPF_TAG_TYPE_ISBN: - if (data->has_identifier) { - g_warning ("Avoiding additional identifier (%s) in EPUB '%s'", - text, data->uri); - } else { - data->has_identifier = TRUE; - tracker_resource_set_string (data->resource, "nie:identifier", text); - } - break; - /* case OPF_TAG_TYPE_RATING: */ - case OPF_TAG_TYPE_UNKNOWN: - default: - break; - } - - opf_data_clear_saved_string (data); -} - -/* Methods to extract XHTML text content */ -static void -content_xml_text_handler (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - OPFContentData *content_data = user_data; - gsize written_bytes = 0; - - if (text_len <= 0) { - return; - } - - if (tracker_text_validate_utf8 (text, - MIN (text_len, content_data->limit), - &content_data->contents, - &written_bytes)) { - if (content_data->contents->str[content_data->contents->len - 1] != ' ') { - g_string_append_c (content_data->contents, ' '); - } - } - - content_data->limit -= written_bytes; -} - -static gchar * -extract_opf_path (const gchar *uri) -{ - GMarkupParseContext *context; - gchar *path = NULL; - GError *error = NULL; - GMarkupParser parser = { - container_xml_start_element_handler, - NULL, NULL, NULL, NULL - }; - - /* Create parsing context */ - context = g_markup_parse_context_new (&parser, 0, &path, NULL); - - /* Load the internal container file from the Zip archive, - * and parse it to extract the .opf file to get metadata from - */ - tracker_gsf_parse_xml_in_zip (uri, "META-INF/container.xml", context, &error); - g_markup_parse_context_free (context); - - if (error || !path) { - g_warning ("Could not get EPUB container.xml file: %s\n", - (error) ? error->message : "No error provided"); - g_error_free (error); - return NULL; - } - - return path; -} - -static gchar * -extract_opf_contents (const gchar *uri, - const gchar *content_prefix, - GList *content_files) -{ - OPFContentData content_data = { 0 }; - TrackerConfig *config; - GError *error = NULL; - GList *l; - GMarkupParser xml_parser = { - NULL, NULL, - content_xml_text_handler, - NULL, NULL - }; - - config = tracker_main_get_config (); - - content_data.contents = g_string_new (""); - content_data.limit = (gsize) tracker_config_get_max_bytes (config); - - g_debug ("Extracting up to %" G_GSIZE_FORMAT " bytes of content", content_data.limit); - - for (l = content_files; l; l = l->next) { - GMarkupParseContext *context; - gchar *path; - - context = g_markup_parse_context_new (&xml_parser, 0, &content_data, NULL); - - /* Page file is relative to OPF file location */ - path = g_build_filename (content_prefix, l->data, NULL); - tracker_gsf_parse_xml_in_zip (uri, path, context, &error); - - if (error) { - g_warning ("Error extracting EPUB contents (%s): %s", - path, error->message); - g_clear_error (&error); - } - g_free (path); - - g_markup_parse_context_free (context); - - if (content_data.limit <= 0) { - /* Reached plain text extraction limit */ - break; - } - } - - return g_string_free (content_data.contents, FALSE); -} - -static TrackerResource * -extract_opf (const gchar *uri, - const gchar *opf_path) -{ - TrackerResource *ebook; - GMarkupParseContext *context; - OPFData *data = NULL; - GError *error = NULL; - gchar *dirname, *contents; - GMarkupParser opf_parser = { - opf_xml_start_element_handler, - opf_xml_end_element_handler, - opf_xml_text_handler, - NULL, NULL - }; - - g_debug ("Extracting OPF file contents from EPUB '%s'", uri); - - ebook = tracker_resource_new (NULL); - tracker_resource_add_uri (ebook, "rdf:type", "nfo:EBook"); - - data = opf_data_new (uri, ebook); - - /* Create parsing context */ - context = g_markup_parse_context_new (&opf_parser, 0, data, NULL); - - /* Load the internal container file from the Zip archive, - * and parse it to extract the .opf file to get metadata from - */ - tracker_gsf_parse_xml_in_zip (uri, opf_path, context, &error); - g_markup_parse_context_free (context); - - if (error) { - g_warning ("Could not get EPUB '%s' file: %s\n", opf_path, - (error) ? error->message : "No error provided"); - g_error_free (error); - opf_data_free (data); - g_object_unref (ebook); - return NULL; - } - - dirname = g_path_get_dirname (opf_path); - contents = extract_opf_contents (uri, dirname, data->pages); - g_free (dirname); - - if (contents && *contents) { - tracker_resource_set_string (ebook, "nie:plainTextContent", contents); - } - - opf_data_free (data); - g_free (contents); - - return ebook; -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerResource *ebook; - gchar *opf_path, *uri; - GFile *file; - - file = tracker_extract_info_get_file (info); - uri = g_file_get_uri (file); - - opf_path = extract_opf_path (uri); - - if (!opf_path) { - g_free (uri); - return FALSE; - } - - ebook = extract_opf (uri, opf_path); - g_free (opf_path); - g_free (uri); - - tracker_extract_info_set_resource (info, ebook); - g_object_unref (ebook); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-flac.c b/src/tracker-extract/tracker-extract-flac.c deleted file mode 100644 index c29b26966..000000000 --- a/src/tracker-extract/tracker-extract-flac.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * Copyright (C) 2010, Intel Corporation - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <stdio.h> -#include <string.h> -#include <fcntl.h> -#include <stdlib.h> - -#include <glib.h> - -#include <FLAC/metadata.h> - -#include <libtracker-common/tracker-common.h> - -#include <libtracker-extract/tracker-extract.h> - -typedef struct { - gchar *title; - gchar *artist; - gchar *album; - gchar *albumartist; - gchar *trackcount; - gchar *tracknumber; - gchar *discno; - gchar *performer; - gchar *trackgain; - gchar *trackpeakgain; - gchar *albumgain; - gchar *albumpeakgain; - gchar *date; - gchar *comment; - gchar *genre; - gchar *mbalbumid; - gchar *mbartistid; - gchar *mbalbumartistid; - gchar *mbtrackid; - gchar *lyrics; - gchar *copyright; - gchar *license; - gchar *organisation; - gchar *location; - gchar *publisher; - guint samplerate; - guint channels; - guint bps; - guint64 total; -} FlacData; - -static void -parse_vorbis_comments (FLAC__StreamMetadata_VorbisComment *comment, - FlacData *fd) -{ - gint i; - - /* FIXME: I hate the amount of duplicating this does, complete - memory fragmentation. We should be able to use some - GStringChunks */ - for (i = 0; i < comment->num_comments; i++) { - FLAC__StreamMetadata_VorbisComment_Entry entry; - - entry = comment->comments[i]; - - /* entry.entry is the format NAME=metadata */ - if (g_ascii_strncasecmp (entry.entry, "title", 5) == 0) { - fd->title = g_strdup (entry.entry + 6); - } else if (g_ascii_strncasecmp (entry.entry, "artist=", 7) == 0) { - /* FIXME: Handle multiple instances of artist */ - if (fd->artist == NULL) { - fd->artist = g_strdup (entry.entry + 7); - } - } else if (g_ascii_strncasecmp (entry.entry, "album=", 6) == 0) { - fd->album = g_strdup (entry.entry + 6); - } else if (g_ascii_strncasecmp (entry.entry, "albumartist=", 12) == 0) { - fd->albumartist = g_strdup (entry.entry + 12); - } else if (g_ascii_strncasecmp (entry.entry, "trackcount", 10) == 0) { - fd->trackcount = g_strdup (entry.entry + 11); - } else if (g_ascii_strncasecmp (entry.entry, "tracknumber", 11) == 0) { - fd->tracknumber = g_strdup (entry.entry + 12); - } else if (g_ascii_strncasecmp (entry.entry, "discno", 6) == 0) { - fd->discno = g_strdup (entry.entry + 7); - } else if (fd->discno == NULL && g_ascii_strncasecmp(entry.entry, "discnumber", 10) == 0) { - fd->discno = g_strdup (entry.entry + 11); - } else if (g_ascii_strncasecmp (entry.entry, "performer", 9) == 0) { - /* FIXME: Handle multiple instances of performer */ - if (fd->performer == NULL) { - fd->performer = g_strdup (entry.entry + 10); - } - } else if (g_ascii_strncasecmp (entry.entry, "trackgain", 9) == 0) { - fd->trackgain = g_strdup (entry.entry + 10); - } else if (g_ascii_strncasecmp (entry.entry, "trackpeakgain", 13) == 0) { - fd->trackpeakgain = g_strdup (entry.entry + 14); - } else if (g_ascii_strncasecmp (entry.entry, "albumgain", 9) == 0) { - fd->albumgain = g_strdup (entry.entry + 10); - } else if (g_ascii_strncasecmp (entry.entry, "albumpeakgain", 13) == 0) { - fd->albumpeakgain = g_strdup (entry.entry + 14); - } else if (g_ascii_strncasecmp (entry.entry, "date", 4) == 0) { - fd->date = tracker_date_guess (entry.entry + 5); - } else if (g_ascii_strncasecmp (entry.entry, "comment", 7) == 0) { - fd->comment = g_strdup (entry.entry + 8); - } else if (g_ascii_strncasecmp (entry.entry, "genre", 5) == 0) { - fd->genre = g_strdup (entry.entry + 6); - } else if (g_ascii_strncasecmp (entry.entry, "mbalbumid", 9) == 0) { - fd->mbalbumid = g_strdup (entry.entry + 10); - } else if (g_ascii_strncasecmp (entry.entry, "mbartistid", 10) == 0) { - fd->mbartistid = g_strdup (entry.entry + 11); - } else if (g_ascii_strncasecmp (entry.entry, "mbalbumartistid", 15) == 0) { - fd->mbalbumartistid = g_strdup (entry.entry + 16); - } else if (g_ascii_strncasecmp (entry.entry, "mbtrackid", 9) == 0) { - fd->mbtrackid = g_strdup (entry.entry + 10); - } else if (g_ascii_strncasecmp (entry.entry, "lyrics", 6) == 0) { - fd->lyrics = g_strdup (entry.entry + 7); - } else if (g_ascii_strncasecmp (entry.entry, "copyright", 9) == 0) { - fd->copyright = g_strdup (entry.entry + 10); - } else if (g_ascii_strncasecmp (entry.entry, "license", 8) == 0) { - fd->license = g_strdup (entry.entry + 9); - } else if (g_ascii_strncasecmp (entry.entry, "organization", 12) == 0) { - fd->organisation = g_strdup (entry.entry + 13); - } else if (g_ascii_strncasecmp (entry.entry, "location", 8) == 0) { - fd->location = g_strdup (entry.entry + 9); - } else if (g_ascii_strncasecmp (entry.entry, "publisher", 9) == 0) { - fd->publisher = g_strdup (entry.entry + 10); - } - } -} - -static void -add_tuple (TrackerResource *metadata, - const char *predicate, - const char *object) -{ - if (object) { - tracker_resource_set_string (metadata, predicate, object); - } -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - FLAC__Metadata_SimpleIterator *iter; - FLAC__StreamMetadata *stream = NULL, *vorbis, *picture; - FLAC__bool success; - FlacData fd = { 0 }; - TrackerResource *metadata, *artist, *album_disc, *album, *album_artist; - gchar *filename, *uri; - const gchar *creator; - GFile *file; - goffset size; - - file = tracker_extract_info_get_file (info); - filename = g_file_get_path (file); - - size = tracker_file_get_size (filename); - - if (size < 18) { - g_free (filename); - return FALSE; - } - - iter = FLAC__metadata_simple_iterator_new (); - success = FLAC__metadata_simple_iterator_init (iter, filename, TRUE, TRUE); - g_free (filename); - - if (!success) { - FLAC__metadata_simple_iterator_delete (iter); - return FALSE; - } - - uri = g_file_get_uri (file); - - do { - switch (FLAC__metadata_simple_iterator_get_block_type (iter)) { - case FLAC__METADATA_TYPE_STREAMINFO: - stream = FLAC__metadata_simple_iterator_get_block (iter); - break; - - case FLAC__METADATA_TYPE_VORBIS_COMMENT: - vorbis = FLAC__metadata_simple_iterator_get_block (iter); - parse_vorbis_comments (&(vorbis->data.vorbis_comment), &fd); - FLAC__metadata_object_delete (vorbis); - break; - - case FLAC__METADATA_TYPE_PICTURE: - picture = FLAC__metadata_simple_iterator_get_block (iter); - /* Deal with picture */ - FLAC__metadata_object_delete (picture); - break; - - default: - break; - } - } while (FLAC__metadata_simple_iterator_next (iter)); - - metadata = tracker_resource_new (NULL); - tracker_resource_add_uri (metadata, "rdf:type", "nmm:MusicPiece"); - tracker_resource_add_uri (metadata, "rdf:type", "nfo:Audio"); - - FLAC__metadata_simple_iterator_delete (iter); - - creator = tracker_coalesce_strip (3, fd.artist, fd.albumartist, - fd.performer); - - if (creator) { - artist = tracker_extract_new_artist (creator); - - tracker_resource_set_relation (metadata, "nmm:performer", artist); - - g_object_unref (artist); - } - - if (fd.album) { - if (fd.albumartist) { - album_artist = tracker_extract_new_artist (fd.albumartist); - } else { - album_artist = NULL; - } - - album_disc = tracker_extract_new_music_album_disc (fd.album, - album_artist, - fd.discno ? atoi(fd.discno) : 1, - fd.date); - - album = tracker_resource_get_first_relation (album_disc, "nmm:albumDiscAlbum"); - - if (fd.trackcount) { - tracker_resource_set_string (album, "nmm:albumTrackCount", fd.trackcount); - } - - if (fd.albumgain) { - tracker_resource_set_double (album, "nmm:albumGain", atof (fd.albumgain)); - } - - if (fd.albumpeakgain) { - tracker_resource_set_double (album, "nmm:albumPeakGain", atof (fd.albumpeakgain)); - } - - tracker_resource_set_relation (metadata, "nmm:musicAlbum", album); - tracker_resource_set_relation (metadata, "nmm:musicAlbumDisc", album_disc); - - g_object_unref (album_disc); - g_clear_object (&album_artist); - } - - tracker_guarantee_resource_title_from_file (metadata, "nie:title", fd.title, uri, NULL); - add_tuple (metadata, "nmm:trackNumber", fd.tracknumber); - - /* FIXME: Trackgain/Trackpeakgain: commented out in vorbis */ - - add_tuple (metadata, "nie:comment", fd.comment); - add_tuple (metadata, "nie:contentCreated", fd.date); - add_tuple (metadata, "nfo:genre", fd.genre); - add_tuple (metadata, "nie:plainTextContent", fd.lyrics); - add_tuple (metadata, "nie:copyright", fd.copyright); - add_tuple (metadata, "nie:license", fd.license); - - if (fd.publisher) { - TrackerResource *publisher = tracker_extract_new_contact (fd.publisher); - - tracker_resource_set_relation (metadata, "dc:publisher", publisher); - - g_object_unref (publisher); - } - - if (stream) { - tracker_resource_set_int64 (metadata, "nfo:sampleRate", stream->data.stream_info.sample_rate); - tracker_resource_set_int64 (metadata, "nfo:channels", stream->data.stream_info.channels); - tracker_resource_set_int64 (metadata, "nfo:averageBitrate", stream->data.stream_info.bits_per_sample); - tracker_resource_set_int64 (metadata, "nfo:duration", stream->data.stream_info.total_samples / stream->data.stream_info.sample_rate); - } - - if (metadata) { - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - } - - g_free (fd.artist); - g_free (fd.album); - g_free (fd.albumartist); - g_free (fd.performer); - g_free (fd.title); - g_free (fd.trackcount); - g_free (fd.tracknumber); - g_free (fd.discno); - g_free (fd.trackgain); - g_free (fd.trackpeakgain); - g_free (fd.albumgain); - g_free (fd.albumpeakgain); - g_free (fd.date); - g_free (fd.comment); - g_free (fd.genre); - g_free (fd.mbalbumid); - g_free (fd.mbartistid); - g_free (fd.mbalbumartistid); - g_free (fd.mbtrackid); - g_free (fd.lyrics); - g_free (fd.copyright); - g_free (fd.license); - g_free (fd.organisation); - g_free (fd.location); - g_free (fd.publisher); - g_free (uri); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-gif.c b/src/tracker-extract/tracker-extract-gif.c deleted file mode 100644 index f260bd519..000000000 --- a/src/tracker-extract/tracker-extract-gif.c +++ /dev/null @@ -1,525 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <errno.h> -#include <fcntl.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> - -#include <gif_lib.h> - -#include <libtracker-common/tracker-common.h> - -#include <libtracker-extract/tracker-extract.h> - -#define XMP_MAGIC_TRAILER_LENGTH 256 -#define EXTENSION_RECORD_COMMENT_BLOCK_CODE 0xFE - -typedef struct { - const gchar *title; - const gchar *date; - const gchar *artist; -} MergeData; - -typedef struct { - gchar *width; - gchar *height; - gchar *comment; -} GifData; - -typedef struct { - unsigned int byteCount; - char *bytes; -} ExtBlock; - -static int -ext_block_append(ExtBlock *extBlock, - unsigned int len, - unsigned char extData[]) -{ - extBlock->bytes = realloc(extBlock->bytes,extBlock->byteCount+len); - if (extBlock->bytes == NULL) { - return (GIF_ERROR); - } - - memcpy(&(extBlock->bytes[extBlock->byteCount]), &extData[0], len); - extBlock->byteCount += len; - - return (GIF_OK); -} - -#if GIFLIB_MAJOR >= 5 -static inline void -gif_error (const gchar *action, int err) -{ - const char *str = GifErrorString (err); - if (str != NULL) { - g_message ("%s, error: '%s'", action, str); - } else { - g_message ("%s, undefined error %d", action, err); - } -} -#else /* GIFLIB_MAJOR >= 5 */ -static inline void print_gif_error() -{ -#if defined(GIFLIB_MAJOR) && defined(GIFLIB_MINOR) && ((GIFLIB_MAJOR == 4 && GIFLIB_MINOR >= 2) || GIFLIB_MAJOR > 4) - const char *str = GifErrorString (); - if (str != NULL) { - g_message ("GIF, error: '%s'", str); - } else { - g_message ("GIF, undefined error"); - } -#else - PrintGifError(); -#endif -} -#endif /* GIFLIB_MAJOR >= 5 */ - -/* giflib 5.1 changed the API of DGifCloseFile to take two arguments */ -#if !defined(GIFLIB_MAJOR) || \ - !(GIFLIB_MAJOR > 5 || (GIFLIB_MAJOR == 5 && GIFLIB_MINOR >= 1)) -#define DGifCloseFile(a, b) DGifCloseFile(a) -#endif - -static TrackerResource * -read_metadata (GifFileType *gifFile, - const gchar *uri) -{ - TrackerResource *metadata; - GifRecordType RecordType; - int frameheight; - int framewidth; - unsigned char *framedata = NULL; - GPtrArray *keywords; - guint i; - gint h; - int status; - MergeData md = { 0 }; - GifData gd = { 0 }; - TrackerXmpData *xd = NULL; - - do { - GifByteType *ExtData; - int ExtCode; - ExtBlock extBlock; - - if (DGifGetRecordType(gifFile, &RecordType) == GIF_ERROR) { -#if GIFLIB_MAJOR < 5 - print_gif_error (); -#else /* GIFLIB_MAJOR < 5 */ - gif_error ("Could not read next GIF record type", gifFile->Error); -#endif /* GIFLIB_MAJOR < 5 */ - return NULL; - } - - switch (RecordType) { - case IMAGE_DESC_RECORD_TYPE: - if (DGifGetImageDesc(gifFile) == GIF_ERROR) { -#if GIFLIB_MAJOR < 5 - print_gif_error(); -#else /* GIFLIB_MAJOR < 5 */ - gif_error ("Could not get GIF record information", gifFile->Error); -#endif /* GIFLIB_MAJOR < 5 */ - return NULL; - } - - framewidth = gifFile->Image.Width; - frameheight = gifFile->Image.Height; - - framedata = g_malloc_n (framewidth, sizeof(GifPixelType)); - for (h = 0; h < frameheight; h++) - { - if (DGifGetLine(gifFile, framedata, framewidth)==GIF_ERROR) { - g_free (framedata); -#if GIFLIB_MAJOR < 5 - print_gif_error(); -#else /* GIFLIB_MAJOR < 5 */ - gif_error ("Could not load a block of GIF pixes", gifFile->Error); -#endif /* GIFLIB_MAJOR < 5 */ - return NULL; - } - } - - gd.width = g_strdup_printf ("%d", framewidth); - gd.height = g_strdup_printf ("%d", frameheight); - - - g_free (framedata); - - break; - case EXTENSION_RECORD_TYPE: - extBlock.bytes = NULL; - extBlock.byteCount = 0; - - if ((status = DGifGetExtension (gifFile, &ExtCode, &ExtData)) != GIF_OK) { - g_warning ("Problem getting the extension"); - return NULL; - } -#if defined(HAVE_EXEMPI) - if (ExtData && *ExtData && - strncmp (&ExtData[1],"XMP Data",8) == 0) { - while (ExtData != NULL && status == GIF_OK ) { - if ((status = DGifGetExtensionNext (gifFile, &ExtData)) == GIF_OK) { - if (ExtData != NULL) { - if (ext_block_append (&extBlock, ExtData[0]+1, (char *) &(ExtData[0])) != GIF_OK) { - g_warning ("Problem with extension data"); - return NULL; - } - } - } - } - - xd = tracker_xmp_new (extBlock.bytes, - extBlock.byteCount-XMP_MAGIC_TRAILER_LENGTH, - uri); - - g_free (extBlock.bytes); - } else -#endif - /* See Section 24. Comment Extension. in the GIF format definition */ - if (ExtCode == EXTENSION_RECORD_COMMENT_BLOCK_CODE && - ExtData && *ExtData) { - guint block_count = 0; - - /* Merge all blocks */ - do { - block_count++; - - g_debug ("Comment Extension block found (#%u, %u bytes)", - block_count, - ExtData[0]); - if (ext_block_append (&extBlock, ExtData[0], (char *) &(ExtData[1])) != GIF_OK) { - g_warning ("Problem with Comment extension data"); - return NULL; - } - } while (((status = DGifGetExtensionNext(gifFile, &ExtData)) == GIF_OK) && - ExtData != NULL); - - /* Add last NUL byte */ - g_debug ("Comment Extension blocks found (%u) with %u bytes", - block_count, - extBlock.byteCount); - extBlock.bytes = g_realloc (extBlock.bytes, extBlock.byteCount + 1); - extBlock.bytes[extBlock.byteCount] = '\0'; - - /* Set commentt */ - gd.comment = extBlock.bytes; - } else { - do { - status = DGifGetExtensionNext(gifFile, &ExtData); - } while ( status == GIF_OK && ExtData != NULL); - } - break; - case TERMINATE_RECORD_TYPE: - break; - default: - break; - } - } while (RecordType != TERMINATE_RECORD_TYPE); - - - if (!xd) { - xd = g_new0 (TrackerXmpData, 1); - } - - md.title = tracker_coalesce_strip (3, xd->title, xd->title2, xd->pdf_title); - md.date = tracker_coalesce_strip (2, xd->date, xd->time_original); - md.artist = tracker_coalesce_strip (2, xd->artist, xd->contributor); - - metadata = tracker_resource_new (NULL); - tracker_resource_add_uri (metadata, "rdf:type", "nfo:Image"); - tracker_resource_add_uri (metadata, "rdf:type", "nmm:Photo"); - - if (xd->license) { - tracker_resource_set_string (metadata, "nie:license", xd->license); - } - - if (xd->creator) { - TrackerResource *creator = tracker_extract_new_contact (xd->creator); - - tracker_resource_set_relation (metadata, "nco:creator", creator); - - g_object_unref (creator); - } - - tracker_guarantee_resource_date_from_file_mtime (metadata, - "nie:contentCreated", - md.date, - uri); - - if (xd->description) { - tracker_resource_set_string (metadata, "nie:description", xd->description); - } - - if (xd->copyright) { - tracker_resource_set_string (metadata, "nie:copyright", xd->copyright); - } - - if (xd->make || xd->model) { - TrackerResource *equipment = tracker_extract_new_equipment (xd->make, xd->model); - - tracker_resource_set_relation (metadata, "nfo:equipment", equipment); - - g_object_unref (equipment); - } - - tracker_guarantee_resource_title_from_file (metadata, - "nie:title", - md.title, - uri, - NULL); - - if (md.artist) { - TrackerResource *artist = tracker_extract_new_contact (xd->creator); - - tracker_resource_add_relation (metadata, "nco:contributor", artist); - - g_object_unref (artist); - } - - if (xd->orientation) { - TrackerResource *orientation; - - orientation = tracker_resource_new (xd->orientation); - tracker_resource_set_relation (metadata, "nfo:orientation", orientation); - g_object_unref (orientation); - } - - if (xd->exposure_time) { - tracker_resource_set_string (metadata, "nmm:exposureTime", xd->exposure_time); - } - - if (xd->iso_speed_ratings) { - tracker_resource_set_string (metadata, "nmm:isoSpeed", xd->iso_speed_ratings); - } - - if (xd->white_balance) { - TrackerResource *white_balance; - - white_balance = tracker_resource_new (xd->white_balance); - tracker_resource_set_relation (metadata, "nmm:meteringMode", white_balance); - g_object_unref (white_balance); - } - - if (xd->fnumber) { - tracker_resource_set_string (metadata, "nmm:fnumber", xd->fnumber); - } - - if (xd->flash) { - TrackerResource *flash; - - flash = tracker_resource_new (xd->flash); - tracker_resource_set_relation (metadata, "nmm:flash", flash); - g_object_unref (flash); - } - - if (xd->focal_length) { - tracker_resource_set_string (metadata, "nmm:focalLength", xd->focal_length); - } - - if (xd->metering_mode) { - TrackerResource *metering; - - metering = tracker_resource_new (xd->metering_mode); - tracker_resource_set_relation (metadata, "nmm:meteringMode", metering); - g_object_unref (metering); - } - - keywords = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); - - if (xd->keywords) { - tracker_keywords_parse (keywords, xd->keywords); - } - - if (xd->pdf_keywords) { - tracker_keywords_parse (keywords, xd->pdf_keywords); - } - - if (xd->rating) { - tracker_resource_set_string (metadata, "nao:numericRating", xd->rating); - } - - if (xd->subject) { - tracker_keywords_parse (keywords, xd->subject); - } - - if (xd->regions) { - tracker_xmp_apply_regions_to_resource (metadata, xd); - } - - for (i = 0; i < keywords->len; i++) { - TrackerResource *tag; - const gchar *p; - - p = g_ptr_array_index (keywords, i); - tag = tracker_extract_new_tag (p); - - tracker_resource_set_relation (metadata, "nao:hasTag", tag); - - g_object_unref (tag); - } - g_ptr_array_free (keywords, TRUE); - - if (xd->publisher) { - TrackerResource *publisher = tracker_extract_new_contact (xd->creator); - - tracker_resource_add_relation (metadata, "nco:creator", publisher); - - g_object_unref (publisher); - } - - if (xd->type) { - tracker_resource_set_string (metadata, "dc:type", xd->type); - } - - if (xd->format) { - tracker_resource_set_string (metadata, "dc:format", xd->format); - } - - if (xd->identifier) { - tracker_resource_set_string (metadata, "dc:identifier", xd->identifier); - } - - if (xd->source) { - tracker_resource_set_string (metadata, "dc:source", xd->source); - } - - if (xd->language) { - tracker_resource_set_string (metadata, "dc:language", xd->language); - } - - if (xd->relation) { - tracker_resource_set_string (metadata, "dc:relation", xd->relation); - } - - if (xd->coverage) { - tracker_resource_set_string (metadata, "dc:coverage", xd->coverage); - } - - if (xd->address || xd->state || xd->country || xd->city || - xd->gps_altitude || xd->gps_latitude || xd-> gps_longitude) { - - TrackerResource *location = tracker_extract_new_location (xd->address, - xd->state, xd->city, xd->country, xd->gps_altitude, - xd->gps_latitude, xd->gps_longitude); - - tracker_resource_set_relation (metadata, "slo:location", location); - - g_object_unref (location); - } - - if (xd->gps_direction) { - tracker_resource_set_string (metadata, "nfo:heading", xd->gps_direction); - } - - if (gd.width) { - tracker_resource_set_string (metadata, "nfo:width", gd.width); - g_free (gd.width); - } - - if (gd.height) { - tracker_resource_set_string (metadata, "nfo:height", gd.height); - g_free (gd.height); - } - - if (gd.comment) { - tracker_guarantee_resource_utf8_string (metadata, "nie:comment", gd.comment); - g_free (gd.comment); - } - - tracker_xmp_free (xd); - - return metadata; -} - - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerResource *metadata; - goffset size; - GifFileType *gifFile = NULL; - gchar *filename, *uri; - GFile *file; - int fd; -#if GIFLIB_MAJOR >= 5 - int err; -#endif - - file = tracker_extract_info_get_file (info); - filename = g_file_get_path (file); - size = tracker_file_get_size (filename); - - if (size < 64) { - g_free (filename); - return FALSE; - } - - fd = tracker_file_open_fd (filename); - - if (fd == -1) { - g_warning ("Could not open GIF file '%s': %s\n", - filename, - g_strerror (errno)); - g_free (filename); - return FALSE; - } - -#if GIFLIB_MAJOR < 5 - if ((gifFile = DGifOpenFileHandle (fd)) == NULL) { - print_gif_error (); -#else /* GIFLIB_MAJOR < 5 */ - if ((gifFile = DGifOpenFileHandle (fd, &err)) == NULL) { - gif_error ("Could not open GIF file with handle", err); -#endif /* GIFLIB_MAJOR < 5 */ - g_free (filename); - close (fd); - return FALSE; - } - - g_free (filename); - - uri = g_file_get_uri (file); - - metadata = read_metadata (gifFile, uri); - - g_free (uri); - - if (DGifCloseFile (gifFile, NULL) != GIF_OK) { -#if GIFLIB_MAJOR < 5 - print_gif_error (); -#else /* GIFLIB_MAJOR < 5 */ - gif_error ("Could not close GIF file", gifFile->Error); -#endif /* GIFLIB_MAJOR < 5 */ - } - - if (metadata) { - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - } - - close (fd); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-gstreamer.c b/src/tracker-extract/tracker-extract-gstreamer.c deleted file mode 100644 index c389a1151..000000000 --- a/src/tracker-extract/tracker-extract-gstreamer.c +++ /dev/null @@ -1,1324 +0,0 @@ -/* - * Copyright (C) 2006, Laurent Aguerreche <laurent.aguerreche@free.fr> - * Copyright (C) 2007, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * Copyright (C) 2016, Sam Thursfield <sam@afuera.me.uk> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -/* Ensure we have a valid backend enabled */ -#if !defined(GSTREAMER_BACKEND_DISCOVERER) && \ - !defined(GSTREAMER_BACKEND_GUPNP_DLNA) -#error Not a valid GStreamer backend defined -#endif - -#include <string.h> -#include <stdio.h> -#include <stdlib.h> -#include <math.h> - -#include <glib.h> -#include <glib/gstdio.h> - -#if defined(GSTREAMER_BACKEND_DISCOVERER) || \ - defined(GSTREAMER_BACKEND_GUPNP_DLNA) -#define GST_USE_UNSTABLE_API -#include <gst/pbutils/pbutils.h> -#endif - -#if defined(GSTREAMER_BACKEND_GUPNP_DLNA) -#include <libgupnp-dlna/gupnp-dlna.h> -#include <libgupnp-dlna/gupnp-dlna-gst-utils.h> -#endif - -#include <gst/gst.h> -#include <gst/tag/tag.h> - -#include <libtracker-common/tracker-common.h> -#include <libtracker-extract/tracker-extract.h> - -#include "tracker-cue-sheet.h" - -/* We wait this long (seconds) for NULL state before freeing */ -#define TRACKER_EXTRACT_GUARD_TIMEOUT 3 - -/* An additional tag in gstreamer for the content source. Remove when in upstream */ -#ifndef GST_TAG_CLASSIFICATION -#define GST_TAG_CLASSIFICATION "classification" -#endif - -/* Some additional tagreadbin tags (FIXME until they are defined upstream)*/ -#ifndef GST_TAG_CHANNEL -#define GST_TAG_CHANNEL "channels" -#endif - -#ifndef GST_TAG_RATE -#define GST_TAG_RATE "rate" -#endif - -#ifndef GST_TAG_WIDTH -#define GST_TAG_WIDTH "width" -#endif - -#ifndef GST_TAG_HEIGHT -#define GST_TAG_HEIGHT "height" -#endif - -#ifndef GST_TAG_PIXEL_RATIO -#define GST_TAG_PIXEL_RATIO "pixel-aspect-ratio" -#endif - -#ifndef GST_TAG_FRAMERATE -#define GST_TAG_FRAMERATE "framerate" -#endif - -typedef enum { - EXTRACT_MIME_AUDIO, - EXTRACT_MIME_VIDEO, - EXTRACT_MIME_IMAGE, - EXTRACT_MIME_GUESS -} ExtractMime; - -typedef struct { - ExtractMime mime; - GstTagList *tagcache; - GstToc *gst_toc; - TrackerToc *toc; - gboolean is_content_encrypted; - - GSList *artist_list; - - GstSample *sample; - GstMapInfo info; - -#if defined(GSTREAMER_BACKEND_DISCOVERER) || \ - defined(GSTREAMER_BACKEND_GUPNP_DLNA) - gboolean has_image; - gboolean has_audio; - gboolean has_video; - GList *streams; -#endif - -#if defined(GSTREAMER_BACKEND_DISCOVERER) || \ - defined(GSTREAMER_BACKEND_GUPNP_DLNA) - GstDiscoverer *discoverer; -#endif - -#if defined(GSTREAMER_BACKEND_GUPNP_DLNA) - const gchar *dlna_profile; - const gchar *dlna_mime; -#endif - -#if defined(GSTREAMER_BACKEND_DISCOVERER) || \ - defined(GSTREAMER_BACKEND_GUPNP_DLNA) - gint64 duration; - gint audio_channels; - gint audio_samplerate; - gint height; - gint width; - gfloat aspect_ratio; - gfloat video_fps; -#endif -} MetadataExtractor; - -static void common_extract_stream_metadata (MetadataExtractor *extractor, - const gchar *uri, - TrackerResource *resource); - -static TrackerResource * -intern_artist (MetadataExtractor *extractor, - const gchar *artist_name) -{ - GSList *node; - TrackerResource *artist; - gchar *artist_uri; - - if (artist_name == NULL) - return NULL; - - artist_uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", artist_name); - - node = g_slist_find_custom (extractor->artist_list, artist_uri, - (GCompareFunc) tracker_resource_identifier_compare_func); - if (node) { - g_free (artist_uri); - return node->data; - } - - artist = tracker_extract_new_artist (artist_name); - g_free (artist_uri); - - extractor->artist_list = g_slist_prepend (extractor->artist_list, artist); - - return artist; -} - -static void -set_property_from_gst_tag (TrackerResource *resource, - const gchar *property_uri, - GstTagList *tag_list, - const gchar *tag) -{ - GValue value = G_VALUE_INIT; - - if (gst_tag_list_copy_value (&value, tag_list, tag)) { - tracker_resource_set_gvalue (resource, property_uri, &value); - g_value_unset (&value); - } -} - -static inline gboolean -get_gst_date_time_to_buf (GstDateTime *date_time, - gchar *buf, - size_t size) -{ - const gchar *offset_str; - gint year, month, day, hour, minute, second; - gfloat offset; - gboolean complete; - - offset_str = "+"; - year = hour = minute = second = 0; - month = day = 1; - offset = 0.0; - complete = TRUE; - - if (gst_date_time_has_year (date_time)) { - year = gst_date_time_get_year (date_time); - } else { - complete = FALSE; - } - - if (gst_date_time_has_month (date_time)) { - month = gst_date_time_get_month (date_time); - } else { - complete = FALSE; - } - - if (gst_date_time_has_day (date_time)) { - day = gst_date_time_get_day (date_time); - } else { - complete = FALSE; - } - - /* Hour and Minute data is retrieved by first checking the - * _has_time() API. - */ - - if (gst_date_time_has_second (date_time)) { - second = gst_date_time_get_second (date_time); - } else { - complete = FALSE; - } - - if (gst_date_time_has_time (date_time)) { - hour = gst_date_time_get_hour (date_time); - minute = gst_date_time_get_minute (date_time); - offset_str = gst_date_time_get_time_zone_offset (date_time) >= 0 ? "+" : ""; - offset = gst_date_time_get_time_zone_offset (date_time); - } else { - offset_str = "+"; - complete = FALSE; - } - - snprintf (buf, size, "%04d-%02d-%02dT%02d:%02d:%02d%s%02d:00", - year, - month, - day, - hour, - minute, - second, - offset_str, - (gint) offset); - - return complete; -} - -static void -add_date_time_gst_tag_with_mtime_fallback (TrackerResource *resource, - const gchar *uri, - const gchar *key, - GstTagList *tag_list, - const gchar *tag_date_time, - const gchar *tag_date) -{ - GstDateTime *date_time; - GDate *date; - gchar buf[26]; - - date_time = NULL; - date = NULL; - buf[0] = '\0'; - - if (gst_tag_list_get_date_time (tag_list, tag_date_time, &date_time)) { - gboolean complete; - - complete = get_gst_date_time_to_buf (date_time, buf, sizeof (buf)); - gst_date_time_unref (date_time); - - if (!complete) { - g_debug ("GstDateTime was not complete, parts of the date/time were missing (e.g. hours, minutes, seconds)"); - } - } else if (gst_tag_list_get_date (tag_list, tag_date, &date)) { - gboolean ret = FALSE; - - if (date && g_date_valid (date)) { - if (date->julian) - ret = g_date_valid_julian (date->julian_days); - if (date->dmy) - ret = g_date_valid_dmy (date->day, date->month, date->year); - } - - if (ret) { - /* GDate does not carry time zone information, assume UTC */ - g_date_strftime (buf, sizeof (buf), "%Y-%m-%dT%H:%M:%SZ", date); - } - } - - if (date) { - g_date_free (date); - } - - tracker_guarantee_resource_date_from_file_mtime (resource, key, buf, uri); -} - -static void -set_keywords_from_gst_tag (TrackerResource *resource, - GstTagList *tag_list) -{ - gboolean ret; - gchar *str; - - ret = gst_tag_list_get_string (tag_list, GST_TAG_KEYWORDS, &str); - - if (ret) { - GStrv keywords; - gint i = 0; - - keywords = g_strsplit_set (str, " ,", -1); - - while (keywords[i]) { - tracker_resource_add_string (resource, "nie:keyword", g_strstrip (keywords[i])); - i++; - } - - g_strfreev (keywords); - g_free (str); - } -} - -static gchar * -get_embedded_cue_sheet_data (GstTagList *tag_list) -{ - gint i, count; - gchar *buffer = NULL; - - count = gst_tag_list_get_tag_size (tag_list, GST_TAG_EXTENDED_COMMENT); - for (i = 0; i < count; i++) { - gst_tag_list_get_string_index (tag_list, GST_TAG_EXTENDED_COMMENT, i, &buffer); - - if (g_ascii_strncasecmp (buffer, "cuesheet=", 9) == 0) { - /* Use same functionality as g_strchug() here - * for cuesheet, to avoid allocating new - * memory but also to return the string and - * not have to jump past cuesheet= on the - * returned value. - */ - g_memmove (buffer, buffer + 9, strlen ((gchar *) buffer + 9) + 1); - - return buffer; - } - - g_free (buffer); - } - - return NULL; -} - -static TrackerToc * -translate_discoverer_toc (GstToc *gst_toc) -{ - const GList *entries, *l; - TrackerToc *toc; - gint i = 0; - - entries = gst_toc_get_entries (gst_toc); - if (!entries) - return NULL; - - toc = tracker_toc_new (); - - for (l = entries; l; l = l->next) { - GstTocEntry *entry = l->data; - GstTagList *tags, *copy = NULL; - gint64 start, stop; - - tags = gst_toc_entry_get_tags (entry); - - if (tags) { - copy = gst_tag_list_copy (tags); - - if (gst_tag_list_get_tag_size (copy, GST_TAG_TRACK_NUMBER) == 0) { - gst_tag_list_add (copy, GST_TAG_MERGE_REPLACE, - GST_TAG_TRACK_NUMBER, i + 1, - NULL); - } - } - - gst_toc_entry_get_start_stop_times (entry, &start, &stop); - tracker_toc_add_entry (toc, copy, (gdouble) start / GST_SECOND, - (gdouble) (stop - start) / GST_SECOND); - gst_tag_list_unref (copy); - i++; - } - - return toc; -} - -static TrackerResource * -extractor_get_geolocation (MetadataExtractor *extractor, - GstTagList *tag_list) -{ - TrackerResource *location = NULL; - gdouble lat, lon, alt; - gboolean has_coords; - - g_debug ("Retrieving geolocation metadata..."); - - has_coords = (gst_tag_list_get_double (tag_list, GST_TAG_GEO_LOCATION_LATITUDE, &lat) && - gst_tag_list_get_double (tag_list, GST_TAG_GEO_LOCATION_LONGITUDE, &lon) && - gst_tag_list_get_double (tag_list, GST_TAG_GEO_LOCATION_ELEVATION, &alt)); - - if (has_coords) { - location = tracker_resource_new (NULL); - tracker_resource_set_uri (location, "rdf:type", "slo:GeoLocation"); - - tracker_resource_set_double (location, "slo:latitude", lat); - tracker_resource_set_double (location, "slo:longitude", lon); - tracker_resource_set_double (location, "slo:altitude", alt); - } - - return location; -} - -static TrackerResource * -extractor_get_address (MetadataExtractor *extractor, - GstTagList *tag_list) -{ - TrackerResource *address = NULL; - gchar *country = NULL, *city = NULL, *sublocation = NULL; - - g_debug ("Retrieving address metadata..."); - - gst_tag_list_get_string (tag_list, GST_TAG_GEO_LOCATION_CITY, &city); - gst_tag_list_get_string (tag_list, GST_TAG_GEO_LOCATION_COUNTRY, &country); - gst_tag_list_get_string (tag_list, GST_TAG_GEO_LOCATION_SUBLOCATION, &sublocation); - - if (city || country || sublocation) { - gchar *address_uri = NULL; - - address_uri = tracker_sparql_get_uuid_urn (); - address = tracker_resource_new (address_uri); - - tracker_resource_set_string (address, "rdf:type", "nco:PostalAddress"); - - if (sublocation) { - tracker_resource_set_string (address, "nco:region", sublocation); - } - - if (city) { - tracker_resource_set_string (address, "nco:locality", city); - } - - if (country) { - tracker_resource_set_string (address, "nco:country", country); - } - } - - return address; -} - -static void -extractor_guess_content_type (MetadataExtractor *extractor) -{ - if (extractor->has_video) { - extractor->mime = EXTRACT_MIME_VIDEO; - } else if (extractor->has_audio) { - extractor->mime = EXTRACT_MIME_AUDIO; - } else if (extractor->has_image) { - extractor->mime = EXTRACT_MIME_IMAGE; - } else { - /* default to video */ - extractor->mime = EXTRACT_MIME_VIDEO; - } -} - -static void -extractor_apply_general_metadata (MetadataExtractor *extractor, - GstTagList *tag_list, - const gchar *file_url, - TrackerResource *resource, - TrackerResource **p_performer, - TrackerResource **p_composer) -{ - const gchar *performer_name = NULL; - gchar *performer_temp = NULL; - gchar *artist_temp = NULL; - gchar *composer_name = NULL; - gchar *genre = NULL; - gchar *title = NULL; - gchar *title_guaranteed = NULL; - - *p_composer = NULL; - *p_performer = NULL; - - gst_tag_list_get_string (tag_list, GST_TAG_PERFORMER, &performer_temp); - gst_tag_list_get_string (tag_list, GST_TAG_ARTIST, &artist_temp); - gst_tag_list_get_string (tag_list, GST_TAG_COMPOSER, &composer_name); - - performer_name = tracker_coalesce_strip (2, performer_temp, artist_temp); - - if (performer_name != NULL) { - *p_performer = intern_artist (extractor, performer_name); - } - - if (composer_name != NULL) { - *p_composer = intern_artist (extractor, composer_name); - } - - gst_tag_list_get_string (tag_list, GST_TAG_GENRE, &genre); - gst_tag_list_get_string (tag_list, GST_TAG_TITLE, &title); - - if (genre && g_strcmp0 (genre, "Unknown") != 0) { - tracker_resource_add_string (resource, "nfo:genre", genre); - } - - tracker_guarantee_resource_title_from_file (resource, - "nie:title", - title, - file_url, - &title_guaranteed); - - add_date_time_gst_tag_with_mtime_fallback (resource, - file_url, - "nie:contentCreated", - tag_list, - GST_TAG_DATE_TIME, - GST_TAG_DATE); - - set_property_from_gst_tag (resource, "nie:copyright", tag_list, GST_TAG_COPYRIGHT); - set_property_from_gst_tag (resource, "nie:license", tag_list, GST_TAG_LICENSE); - set_property_from_gst_tag (resource, "dc:coverage", tag_list, GST_TAG_LOCATION); - set_property_from_gst_tag (resource, "nie:comment", tag_list, GST_TAG_COMMENT); - - g_free (title_guaranteed); - g_free (performer_temp); - g_free (artist_temp); - g_free (composer_name); - g_free (genre); - g_free (title); -} - -static TrackerResource * -extractor_maybe_get_album_disc (MetadataExtractor *extractor, - GstTagList *tag_list) -{ - GstDateTime *datetime_temp = NULL; - TrackerResource *album = NULL, *album_artist = NULL, *album_disc = NULL; - gchar *album_artist_name = NULL; - gchar *album_datetime = NULL; - gchar *album_title = NULL; - gchar *track_artist_temp = NULL; - gboolean has_it; - guint volume_number; - - gst_tag_list_get_string (tag_list, GST_TAG_ALBUM, &album_title); - - if (!album_title) - return NULL; - - gst_tag_list_get_string (tag_list, GST_TAG_ALBUM_ARTIST, &album_artist_name); - gst_tag_list_get_string (tag_list, GST_TAG_ARTIST, &track_artist_temp); - gst_tag_list_get_date_time (tag_list, GST_TAG_DATE_TIME, &datetime_temp); - - if (datetime_temp) - album_datetime = gst_date_time_to_iso8601_string (datetime_temp); - album_artist = intern_artist (extractor, album_artist_name); - has_it = gst_tag_list_get_uint (tag_list, GST_TAG_ALBUM_VOLUME_NUMBER, &volume_number); - - album_disc = tracker_extract_new_music_album_disc (album_title, - album_artist, - has_it ? volume_number : 1, - album_datetime); - - album = tracker_resource_get_first_relation (album_disc, "nmm:albumDiscAlbum"); - set_property_from_gst_tag (album, "nmm:albumTrackCount", tag_list, GST_TAG_TRACK_COUNT); - set_property_from_gst_tag (album, "nmm:albumGain", extractor->tagcache, GST_TAG_ALBUM_GAIN); - set_property_from_gst_tag (album, "nmm:albumPeakGain", extractor->tagcache, GST_TAG_ALBUM_PEAK); - - g_clear_pointer (&datetime_temp, (GDestroyNotify) gst_date_time_unref); - g_free (album_artist_name); - g_free (album_datetime); - g_free (track_artist_temp); - - return album_disc; -} - -static TrackerResource * -extractor_get_equipment (MetadataExtractor *extractor, - GstTagList *tag_list) -{ - TrackerResource *equipment; - gchar *model = NULL, *manuf = NULL; - - gst_tag_list_get_string (tag_list, GST_TAG_DEVICE_MODEL, &model); - gst_tag_list_get_string (tag_list, GST_TAG_DEVICE_MANUFACTURER, &manuf); - - if (model == NULL && manuf == NULL) - return NULL; - - equipment = tracker_extract_new_equipment (manuf, model); - - g_free (model); - g_free (manuf); - - return equipment; -} - -static void -extractor_apply_audio_metadata (MetadataExtractor *extractor, - GstTagList *tag_list, - TrackerResource *audio, - TrackerResource *performer, - TrackerResource *composer, - TrackerResource *album_disc) -{ - set_property_from_gst_tag (audio, "nmm:trackNumber", tag_list, GST_TAG_TRACK_NUMBER); - set_property_from_gst_tag (audio, "nfo:codec", tag_list, GST_TAG_AUDIO_CODEC); - set_property_from_gst_tag (audio, "nfo:gain", tag_list, GST_TAG_TRACK_GAIN); - set_property_from_gst_tag (audio, "nfo:peakGain", tag_list, GST_TAG_TRACK_PEAK); - - if (performer) { - tracker_resource_set_relation (audio, "nmm:performer", performer); - } - - if (composer) { - tracker_resource_set_relation (audio, "nmm:composer", composer); - } - - if (album_disc) { - TrackerResource *album; - album = tracker_resource_get_first_relation (album_disc, "nmm:albumDiscAlbum"); - - tracker_resource_set_relation (audio, "nmm:musicAlbumDisc", album_disc); - tracker_resource_set_relation (audio, "nmm:musicAlbum", album); - } -} - -static void -extractor_apply_video_metadata (MetadataExtractor *extractor, - GstTagList *tag_list, - TrackerResource *video, - TrackerResource *performer, - TrackerResource *composer) -{ - set_property_from_gst_tag (video, "dc:source", tag_list, GST_TAG_CLASSIFICATION); - - if (performer) { - tracker_resource_set_relation (video, "nmm:leadActor", performer); - } - - if (composer) { - tracker_resource_set_relation (video, "nmm:director", composer); - } - - set_keywords_from_gst_tag (video, tag_list); -} - -static TrackerResource * -extract_track (MetadataExtractor *extractor, - TrackerTocEntry *toc_entry, - const gchar *file_url, - TrackerResource *album_disc) -{ - TrackerResource *track; - TrackerResource *track_performer = NULL, *track_composer = NULL; - gchar *track_uri; - - track_uri = tracker_sparql_get_uuid_urn (); - track = tracker_resource_new (track_uri); - - tracker_resource_add_uri (track, "rdf:type", "nmm:MusicPiece"); - tracker_resource_add_uri (track, "rdf:type", "nfo:Audio"); - - extractor_apply_general_metadata (extractor, - toc_entry->tag_list, - file_url, - track, - &track_performer, - &track_composer); - - extractor_apply_audio_metadata (extractor, - toc_entry->tag_list, - track, - track_performer, - track_composer, - album_disc); - - if (toc_entry->duration > 0) { - tracker_resource_set_int64 (track, "nfo:duration", (gint64)toc_entry->duration); - } else if (extractor->toc->entry_list && - toc_entry == g_list_last (extractor->toc->entry_list)->data) { - /* The last element may not have a duration, because it depends - * on the duration of the media file rather than info from the - * cue sheet. In this case figure the data out from the total - * duration. - */ - tracker_resource_set_int64 (track, "nfo:duration", (gint64)extractor->duration - toc_entry->start); - } - - tracker_resource_set_double (track, "nfo:audioOffset", toc_entry->start); - - g_free (track_uri); - - return track; -} - -#define CHUNK_N_BYTES (2 << 15) - -static guint64 -extract_gibest_hash (GFile *file) -{ - guint64 buffer[2][CHUNK_N_BYTES/8]; - GInputStream *stream = NULL; - gssize n_bytes, file_size; - GError *error = NULL; - guint64 hash = 0; - gint i; - - stream = G_INPUT_STREAM (g_file_read (file, NULL, &error)); - if (stream == NULL) - goto fail; - - /* Extract start/end chunks of the file */ - n_bytes = g_input_stream_read (stream, buffer[0], CHUNK_N_BYTES, NULL, &error); - if (n_bytes == -1) - goto fail; - - if (!g_seekable_seek (G_SEEKABLE (stream), -CHUNK_N_BYTES, G_SEEK_END, NULL, &error)) - goto fail; - - n_bytes = g_input_stream_read (stream, buffer[1], CHUNK_N_BYTES, NULL, &error); - if (n_bytes == -1) - goto fail; - - for (i = 0; i < G_N_ELEMENTS (buffer[0]); i++) - hash += buffer[0][i] + buffer[1][i]; - - file_size = g_seekable_tell (G_SEEKABLE (stream)); - - if (file_size < CHUNK_N_BYTES) - goto end; - - /* Include file size */ - hash += file_size; - g_object_unref (stream); - - return hash; - -fail: - g_warning ("Could not get file hash: %s\n", error ? error->message : "Unknown error"); - g_clear_error (&error); - -end: - g_clear_object (&stream); - return 0; -} - -static TrackerResource * -extract_metadata (MetadataExtractor *extractor, - const gchar *file_url) -{ - TrackerResource *resource; - - g_return_val_if_fail (extractor != NULL, NULL); - - resource = tracker_resource_new (NULL); - - if (extractor->toc) { - gst_tag_list_insert (extractor->tagcache, - extractor->toc->tag_list, - GST_TAG_MERGE_KEEP); - - if (g_list_length (extractor->toc->entry_list) == 1) { - /* If we only got one track, stick all the info together and - * forget about the table of contents - */ - TrackerTocEntry *toc_entry; - - toc_entry = extractor->toc->entry_list->data; - gst_tag_list_insert (extractor->tagcache, - toc_entry->tag_list, - GST_TAG_MERGE_KEEP); - - tracker_toc_free (extractor->toc); - extractor->toc = NULL; - } - } - - if (extractor->mime == EXTRACT_MIME_GUESS && !gst_tag_list_is_empty (extractor->tagcache)) { - extractor_guess_content_type (extractor); - } else { - /* Rely on the information from the discoverer rather than the - * mimetype, this is a safety net for those formats that fool - * mimetype sniffing (eg. .ogg suffixed OGG videos being detected - * as audio/ogg. - */ - if (extractor->mime == EXTRACT_MIME_AUDIO && extractor->has_video) { - g_debug ("mimetype says its audio, but has video frames. Falling back to video extraction."); - extractor->mime = EXTRACT_MIME_VIDEO; - } else if (extractor->mime == EXTRACT_MIME_VIDEO && - !extractor->has_video && extractor->has_audio) { - g_debug ("mimetype says its video, but has only audio. Falling back to audio extraction."); - extractor->mime = EXTRACT_MIME_AUDIO; - } - } - - if (extractor->mime == EXTRACT_MIME_GUESS) { - g_warning ("Cannot guess real stream type if no tags were read! " - "Defaulting to Video."); - tracker_resource_add_uri (resource, "rdf:type", "nmm:Video"); - } else { - if (extractor->mime == EXTRACT_MIME_AUDIO) { - /* Audio: don't make an nmm:MusicPiece for the file resource if it's - * actually a container for an entire album - we will make a - * nmm:MusicPiece for each of the tracks inside instead. - */ - tracker_resource_add_uri (resource, "rdf:type", "nfo:Audio"); - - if (extractor->toc == NULL || extractor->toc->entry_list == NULL) - tracker_resource_add_uri (resource, "rdf:type", "nmm:MusicPiece"); - } else if (extractor->mime == EXTRACT_MIME_VIDEO) { - tracker_resource_add_uri (resource, "rdf:type", "nmm:Video"); - } else { - tracker_resource_add_uri (resource, "rdf:type", "nfo:Image"); - tracker_resource_add_uri (resource, "rdf:type", "nmm:Photo"); - } - } - - if (!gst_tag_list_is_empty (extractor->tagcache)) { - GList *node; - TrackerResource *equipment; - TrackerResource *geolocation, *address; - TrackerResource *performer = NULL, *composer = NULL; - TrackerResource *album_disc; - - extractor_apply_general_metadata (extractor, - extractor->tagcache, - file_url, - resource, - &performer, - &composer); - - equipment = extractor_get_equipment (extractor, extractor->tagcache); - if (equipment) { - tracker_resource_set_relation (resource, "nfo:equipment", equipment); - g_object_unref (equipment); - } - - geolocation = extractor_get_geolocation (extractor, extractor->tagcache); - if (geolocation) { - tracker_resource_set_relation (resource, "slo:location", geolocation); - g_object_unref (geolocation); - } - - address = extractor_get_address (extractor, extractor->tagcache); - if (address) { - tracker_resource_set_relation (resource, "slo:postalAddress", address); - g_object_unref (address); - } - - if (extractor->mime == EXTRACT_MIME_VIDEO) { - extractor_apply_video_metadata (extractor, - extractor->tagcache, - resource, - performer, - composer); - } - - if (extractor->mime == EXTRACT_MIME_AUDIO) { - album_disc = extractor_maybe_get_album_disc (extractor, extractor->tagcache); - - extractor_apply_audio_metadata (extractor, - extractor->tagcache, - resource, - performer, - composer, - album_disc); - - /* If the audio file contains multiple tracks, we create the tracks - * as abstract information element types and relate them to the - * concrete nfo:FileDataObject using nie:isStoredAs. - */ - if (extractor->toc && g_list_length (extractor->toc->entry_list) > 1) { - for (node = extractor->toc->entry_list; node; node = node->next) { - TrackerResource *track; - - track = extract_track (extractor, node->data, file_url, album_disc); - tracker_resource_set_relation (track, "nie:isStoredAs", resource); - g_object_unref (track); - } - - tracker_resource_set_string (resource, "nie:url", file_url); - } - - if (album_disc) - g_object_unref (album_disc); - } - } - - /* OpenSubtitles compatible hash */ - if (extractor->mime == EXTRACT_MIME_VIDEO) { - guint64 hash; - GFile *file; - - file = g_file_new_for_uri (file_url); - hash = extract_gibest_hash (file); - g_object_unref (file); - - if (hash) { - TrackerResource *hash_resource; - char *hash_str; - - hash_resource = tracker_resource_new (NULL); - tracker_resource_set_uri (hash_resource, "rdf:type", "nfo:FileHash"); - - hash_str = g_strdup_printf ("%" G_GINT64_MODIFIER "x", hash); - tracker_resource_set_string (hash_resource, "nfo:hashValue", hash_str); - g_free (hash_str); - - tracker_resource_set_string (hash_resource, "nfo:hashAlgorithm", "gibest"); - - tracker_resource_set_relation (resource, "nfo:hasHash", hash_resource); - - g_object_unref (hash_resource); - } - } - - /* If content was encrypted, set it. */ -/* #warning TODO: handle encrypted content with the Discoverer/GUPnP-DLNA backends */ - - common_extract_stream_metadata (extractor, file_url, resource); - - return resource; -} - -#if defined(GSTREAMER_BACKEND_DISCOVERER) || \ - defined(GSTREAMER_BACKEND_GUPNP_DLNA) -static void -common_extract_stream_metadata (MetadataExtractor *extractor, - const gchar *uri, - TrackerResource *resource) -{ - if (extractor->mime == EXTRACT_MIME_AUDIO || - extractor->mime == EXTRACT_MIME_VIDEO) { - if (extractor->audio_channels >= 0) { - tracker_resource_set_int64 (resource, "nfo:channels", extractor->audio_channels); - } - - if (extractor->audio_samplerate >= 0) { - tracker_resource_set_int64 (resource, "nfo:sampleRate", extractor->audio_samplerate); - } - - if (extractor->duration >= 0) { - tracker_resource_set_int64 (resource, "nfo:duration", extractor->duration); - } - } - - if (extractor->mime == EXTRACT_MIME_VIDEO) { - if (extractor->video_fps >= 0) { - tracker_resource_set_double (resource, "nfo:frameRate", (gdouble)extractor->video_fps); - } - } - - if (extractor->mime == EXTRACT_MIME_IMAGE || - extractor->mime == EXTRACT_MIME_VIDEO) { - - if (extractor->width >= 0) { - tracker_resource_set_int64 (resource, "nfo:width", extractor->width); - } - - if (extractor->height >= 0) { - tracker_resource_set_int64 (resource, "nfo:height", extractor->height); - } - - if (extractor->aspect_ratio >= 0) { - tracker_resource_set_double (resource, "nfo:aspectRatio", (gdouble)extractor->aspect_ratio); - } - } - -#if defined(GSTREAMER_BACKEND_GUPNP_DLNA) - if (extractor->dlna_profile) { - tracker_resource_set_string (resource, "nmm:dlnaProfile", extractor->dlna_profile); - } else { - g_debug ("No DLNA profile found"); - } - - if (extractor->dlna_mime) { - tracker_resource_set_string (resource, "nmm:dlnaMime", extractor->dlna_mime); - } else { - g_debug ("No DLNA mime found"); - } -#endif /* GSTREAMER_BACKEND_GUPNP_DLNA */ -} - -#endif - -/* ----------------------- Discoverer/GUPnP-DLNA specific implementation --------------- */ - -#if defined(GSTREAMER_BACKEND_DISCOVERER) || \ - defined(GSTREAMER_BACKEND_GUPNP_DLNA) - -static void -discoverer_shutdown (MetadataExtractor *extractor) -{ - if (extractor->streams) - gst_discoverer_stream_info_list_free (extractor->streams); - if (extractor->discoverer) - g_object_unref (extractor->discoverer); -} - -static gchar * -get_discoverer_required_plugins_message (GstDiscovererInfo *info) -{ - GString *str; - gchar **plugins; - gchar *plugins_str; - - plugins = (gchar **) - gst_discoverer_info_get_missing_elements_installer_details (info); - - if (g_strv_length((gchar **)plugins) == 0) { - str = g_string_new ("No information available on which plugin is required."); - } else { - str = g_string_new("Required plugins: "); - plugins_str = g_strjoinv (", ", (gchar **)plugins); - g_string_append (str, plugins_str); - g_free (plugins_str); - } - - return g_string_free (str, FALSE); -} - -static gboolean -discoverer_init_and_run (MetadataExtractor *extractor, - const gchar *uri) -{ - GstDiscovererInfo *info; - const GstTagList *discoverer_tags; - const GstToc *gst_toc; - GError *error = NULL; - GList *l; - gchar *required_plugins_message; - - extractor->duration = -1; - extractor->audio_channels = -1; - extractor->audio_samplerate = -1; - extractor->height = -1; - extractor->width = -1; - extractor->video_fps = -1.0; - extractor->aspect_ratio = -1.0; - - extractor->has_image = FALSE; - extractor->has_video = FALSE; - extractor->has_audio = FALSE; - - extractor->discoverer = gst_discoverer_new (5 * GST_SECOND, &error); - if (!extractor->discoverer) { - g_warning ("Couldn't create discoverer: %s", - error ? error->message : "unknown error"); - g_clear_error (&error); - return FALSE; - } - -#if defined(GST_TYPE_DISCOVERER_FLAGS) - /* Tell the discoverer to use *only* Tagreadbin backend. - * See https://bugzilla.gnome.org/show_bug.cgi?id=656345 - */ - g_debug ("Using Tagreadbin backend in the GStreamer discoverer..."); - g_object_set (extractor->discoverer, - "flags", GST_DISCOVERER_FLAGS_EXTRACT_LIGHTWEIGHT, - NULL); -#endif - - info = gst_discoverer_discover_uri (extractor->discoverer, - uri, - &error); - - if (!info) { - g_warning ("Nothing discovered, bailing out"); - return TRUE; - } - - if (error) { - if (gst_discoverer_info_get_result(info) == GST_DISCOVERER_MISSING_PLUGINS) { - required_plugins_message = get_discoverer_required_plugins_message (info); - g_message ("Missing a GStreamer plugin for %s. %s", uri, - required_plugins_message); - g_free (required_plugins_message); - } else if (error->domain != GST_STREAM_ERROR || - (error->code != GST_STREAM_ERROR_TYPE_NOT_FOUND && - error->code != GST_STREAM_ERROR_WRONG_TYPE && - error->code != GST_STREAM_ERROR_DECODE)) { - g_warning ("Call to gst_discoverer_discover_uri(%s) failed: %s", - uri, error->message); - } - gst_discoverer_info_unref (info); - g_error_free (error); - return FALSE; - } - -#if defined(GSTREAMER_BACKEND_GUPNP_DLNA) - { - GUPnPDLNAProfile *profile; - GUPnPDLNAInformation *dlna_info; - GUPnPDLNAProfileGuesser *guesser; - - dlna_info = gupnp_dlna_gst_utils_information_from_discoverer_info (info); - guesser = gupnp_dlna_profile_guesser_new (TRUE, FALSE); - profile = gupnp_dlna_profile_guesser_guess_profile_from_info (guesser, dlna_info); - - if (profile) { - extractor->dlna_profile = gupnp_dlna_profile_get_name (profile); - extractor->dlna_mime = gupnp_dlna_profile_get_mime (profile); - } - - g_object_unref (guesser); - g_object_unref (dlna_info); - } -#endif - - gst_toc = gst_discoverer_info_get_toc (info); - if (gst_toc) - extractor->gst_toc = gst_toc_copy (gst_toc); - - extractor->duration = gst_discoverer_info_get_duration (info) / GST_SECOND; - - /* Retrieve global tags */ - discoverer_tags = gst_discoverer_info_get_tags (info); - - if (discoverer_tags) { - gst_tag_list_insert (extractor->tagcache, - discoverer_tags, - GST_TAG_MERGE_APPEND); - } - - /* Get list of Streams to iterate */ - extractor->streams = gst_discoverer_info_get_stream_list (info); - for (l = extractor->streams; l; l = g_list_next (l)) { - GstDiscovererStreamInfo *stream = l->data; - const GstTagList *stream_tags; - - if (G_TYPE_CHECK_INSTANCE_TYPE (stream, GST_TYPE_DISCOVERER_AUDIO_INFO)) { - GstDiscovererAudioInfo *audio = (GstDiscovererAudioInfo*)stream; - - extractor->has_audio = TRUE; - extractor->audio_samplerate = gst_discoverer_audio_info_get_sample_rate (audio); - extractor->audio_channels = gst_discoverer_audio_info_get_channels (audio); - } else if (G_TYPE_CHECK_INSTANCE_TYPE (stream, GST_TYPE_DISCOVERER_VIDEO_INFO)) { - GstDiscovererVideoInfo *video = (GstDiscovererVideoInfo*)stream; - - if (gst_discoverer_video_info_is_image (video)) { - extractor->has_image = TRUE; - } else { - extractor->has_video = TRUE; - if (gst_discoverer_video_info_get_framerate_denom (video) > 0) { - extractor->video_fps = (gfloat)(gst_discoverer_video_info_get_framerate_num (video) / - gst_discoverer_video_info_get_framerate_denom (video)); - } - extractor->width = gst_discoverer_video_info_get_width (video); - extractor->height = gst_discoverer_video_info_get_height (video); - if (gst_discoverer_video_info_get_par_denom (video) > 0) { - extractor->aspect_ratio = (gfloat)(gst_discoverer_video_info_get_par_num (video) / - gst_discoverer_video_info_get_par_denom (video)); - } - } - } else { - /* Unknown type - do nothing */ - } - - stream_tags = gst_discoverer_stream_info_get_tags (stream); - - if (stream_tags) { - gst_tag_list_insert (extractor->tagcache, - stream_tags, - GST_TAG_MERGE_APPEND); - } - } - - gst_discoverer_info_unref (info); - - return TRUE; -} - -#endif /* defined(GSTREAMER_BACKEND_DISCOVERER) || \ - defined(GSTREAMER_BACKEND_GUPNP_DLNA) */ - -static TrackerResource * -tracker_extract_gstreamer (const gchar *uri, - TrackerExtractInfo *info, - ExtractMime type) -{ - TrackerResource *main_resource = NULL; - MetadataExtractor *extractor; - GstBuffer *buffer; - gchar *cue_sheet; - gboolean success; - - g_return_val_if_fail (uri, NULL); - - extractor = g_slice_new0 (MetadataExtractor); - extractor->mime = type; - extractor->tagcache = gst_tag_list_new_empty (); - - g_debug ("GStreamer backend in use:"); - g_debug (" Discoverer/GUPnP-DLNA"); - success = discoverer_init_and_run (extractor, uri); - - if (success) { - cue_sheet = get_embedded_cue_sheet_data (extractor->tagcache); - - if (cue_sheet) { - g_debug ("Using embedded CUE sheet."); - extractor->toc = tracker_cue_sheet_parse (cue_sheet); - g_free (cue_sheet); - } - - if (extractor->toc == NULL) { - extractor->toc = tracker_cue_sheet_parse_uri (uri); - } - - if (extractor->toc == NULL && - extractor->gst_toc != NULL) { - extractor->toc = translate_discoverer_toc (extractor->gst_toc); - } - - main_resource = extract_metadata (extractor, uri); - } - - /* Clean up */ - if (extractor->sample) { - buffer = gst_sample_get_buffer (extractor->sample); - gst_buffer_unmap (buffer, &extractor->info); - gst_sample_unref (extractor->sample); - } - - gst_tag_list_free (extractor->tagcache); - - tracker_toc_free (extractor->toc); - - if (extractor->gst_toc) - gst_toc_unref (extractor->gst_toc); - - g_slist_foreach (extractor->artist_list, (GFunc)g_object_unref, NULL); - g_slist_free (extractor->artist_list); - - discoverer_shutdown (extractor); - - g_slice_free (MetadataExtractor, extractor); - - return main_resource; -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - GFile *file; - gchar *uri; - const gchar *mimetype; - TrackerResource *main_resource; - - file = tracker_extract_info_get_file (info); - uri = g_file_get_uri (file); - mimetype = tracker_extract_info_get_mimetype (info); - -#if defined(GSTREAMER_BACKEND_GUPNP_DLNA) - if (g_str_has_prefix (mimetype, "dlna/")) { - main_resource = tracker_extract_gstreamer (uri, info, EXTRACT_MIME_GUESS); - } else -#endif /* GSTREAMER_BACKEND_GUPNP_DLNA */ - - if (strcmp (mimetype, "video/3gpp") == 0 || - strcmp (mimetype, "video/mp4") == 0 || - strcmp (mimetype, "video/x-ms-asf") == 0 || - strcmp (mimetype, "application/vnd.ms-asf") == 0 || - strcmp (mimetype, "application/vnd.rn-realmedia") == 0) { - main_resource = tracker_extract_gstreamer (uri, info, EXTRACT_MIME_GUESS); - } else if (g_str_has_prefix (mimetype, "audio/")) { - main_resource = tracker_extract_gstreamer (uri, info, EXTRACT_MIME_AUDIO); - } else if (g_str_has_prefix (mimetype, "video/")) { - main_resource = tracker_extract_gstreamer (uri, info, EXTRACT_MIME_VIDEO); - } else if (g_str_has_prefix (mimetype, "image/")) { - main_resource = tracker_extract_gstreamer (uri, info, EXTRACT_MIME_IMAGE); - } else { - g_free (uri); - return FALSE; - } - - if (main_resource) { - tracker_extract_info_set_resource (info, main_resource); - g_object_unref (main_resource); - } - - g_free (uri); - return TRUE; -} - -G_MODULE_EXPORT gboolean -tracker_extract_module_init (GError **error) -{ - /* Lifted from totem-video-thumbnailer */ - const gchar *blacklisted[] = { - "vaapidecodebin", - "vaapidecode", - "vaapimpeg2dec", - "vaapih264dec", - "vaapivc1dec", - "vaapivp8dec", - "vaapivp9dec", - "vaapih265dec", - "bcmdec", - }; - GstRegistry *registry; - guint i; - - gst_init (NULL, NULL); - registry = gst_registry_get (); - - for (i = 0; i < G_N_ELEMENTS (blacklisted); i++) { - GstPluginFeature *feature = - gst_registry_find_feature (registry, - blacklisted[i], - GST_TYPE_ELEMENT_FACTORY); - if (feature) - gst_registry_remove_feature (registry, feature); - } - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-html.c b/src/tracker-extract/tracker-extract-html.c deleted file mode 100644 index 497f009a9..000000000 --- a/src/tracker-extract/tracker-extract-html.c +++ /dev/null @@ -1,317 +0,0 @@ -/* - * Copyright (C) 2007, Jason Kivlighn <jkivlighn@gmail.com> - * Copyright (C) 2008-2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <string.h> - -#include <glib.h> - -#include <libxml/HTMLparser.h> -#include <libtracker-common/tracker-utils.h> -#include <libtracker-extract/tracker-extract.h> - -#include "tracker-main.h" - -typedef enum { - READ_TITLE, - READ_IGNORE -} tag_type; - -typedef struct { - TrackerResource *metadata; - tag_type current; - guint in_body : 1; - guint has_license : 1; - guint has_description : 1; - GString *title; - GString *plain_text; - guint n_bytes_remaining; -} parser_data; - -static gboolean -has_attribute (const gchar **attrs, - const gchar *attr, - const gchar *val) -{ - gint i; - - if (!attrs || !attr || !val) { - return FALSE; - } - - for (i = 0; attrs[i] && attrs[i + 1]; i += 2) { - if (g_ascii_strcasecmp (attrs[i], attr) == 0) { - if (g_ascii_strcasecmp (attrs[i + 1], val) == 0) { - return TRUE; - } - } - } - - return FALSE; -} - -static const xmlChar * -lookup_attribute (const gchar **attrs, - const gchar *attr) -{ - gint i; - - if (!attrs || !attr) { - return NULL; - } - - for (i = 0; attrs[i] && attrs[i + 1]; i += 2) { - if (g_ascii_strcasecmp (attrs[i], attr) == 0) { - return attrs[i + 1]; - } - } - - return NULL; -} - -static void -parser_start_element (void *data, - const xmlChar *name_, - const xmlChar **attrs_) -{ - parser_data *pd = data; - const gchar *name = (const gchar*) name_; - const gchar **attrs = (const gchar**) attrs_; - - if (!pd || !name) { - return; - } - - /* Look for RDFa triple describing the license */ - if (g_ascii_strcasecmp (name, "a") == 0) { - /* This tag is a license. Ignore, however, if it is - * referring to another document. - */ - if (has_attribute (attrs, "rel", "license") && - has_attribute (attrs, "about", NULL) == FALSE) { - const xmlChar *href; - - href = lookup_attribute (attrs, "href"); - - if (href && !pd->has_license) { - tracker_resource_add_string (pd->metadata, "nie:license", href); - pd->has_license = TRUE; - } - } - } else if (g_ascii_strcasecmp (name, "title") == 0) { - pd->current = READ_TITLE; - } else if (g_ascii_strcasecmp (name, "meta") == 0) { - if (has_attribute (attrs, "name", "author")) { - const xmlChar *author; - - author = lookup_attribute (attrs, "content"); - - if (author) { - TrackerResource *creator = tracker_extract_new_contact (author); - - tracker_resource_add_relation (pd->metadata, "nco:creator", creator); - - g_object_unref (creator); - } - } - - if (has_attribute (attrs, "name", "description")) { - const xmlChar *desc; - - desc = lookup_attribute (attrs,"content"); - - if (desc && !pd->has_description) { - tracker_resource_set_string (pd->metadata, "nie:description", desc); - pd->has_description = TRUE; - } - } - - if (has_attribute (attrs, "name", "keywords")) { - const xmlChar* content = lookup_attribute (attrs, "content"); - - if (content) { - gchar **keywords; - gint i; - - keywords = g_strsplit (content, ",", -1); - if (keywords) { - for (i = 0; keywords[i] != NULL; i++) { - if (!keywords[i] || keywords[i] == '\0') { - continue; - } - - tracker_resource_add_string (pd->metadata, "nie:keyword", g_strstrip (keywords[i])); - } - - g_strfreev (keywords); - } - } - } - } else if (g_ascii_strcasecmp (name, "body") == 0) { - pd->in_body = TRUE; - } else if (g_ascii_strcasecmp (name, "script") == 0) { - /* Ignore javascript and such */ - pd->current = READ_IGNORE; - } -} - -static void -parser_end_element (void *data, - const xmlChar *name_) -{ - parser_data *pd = data; - const gchar *name = (const gchar*) name_; - - if (g_ascii_strcasecmp (name, "title") == 0 || - g_ascii_strcasecmp (name, "script") == 0) { - pd->current = -1; - } -} - -static void -parser_characters (void *data, - const xmlChar *ch, - int len) -{ - parser_data *pd = data; - - switch (pd->current) { - case READ_TITLE: - g_string_append (pd->title, ch); - break; - case READ_IGNORE: - break; - default: - if (pd->in_body && pd->n_bytes_remaining > 0) { - gsize text_len; - - text_len = strlen (ch); - - if (tracker_text_validate_utf8 (ch, - (pd->n_bytes_remaining < text_len ? - pd->n_bytes_remaining : - text_len), - &pd->plain_text, - NULL)) { - /* In the case of HTML, each string arriving this - * callback is independent to any other previous - * string, so need to add an explicit whitespace - * separator */ - g_string_append_c (pd->plain_text, ' '); - } - - if (pd->n_bytes_remaining > text_len) { - pd->n_bytes_remaining -= text_len; - } else { - pd->n_bytes_remaining = 0; - } - } - break; - } -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerResource *metadata; - GFile *file; - TrackerConfig *config; - htmlDocPtr doc; - parser_data pd; - gchar *filename; - xmlSAXHandler handler = { - NULL, /* internalSubset */ - NULL, /* isStandalone */ - NULL, /* hasInternalSubset */ - NULL, /* hasExternalSubset */ - NULL, /* resolveEntity */ - NULL, /* getEntity */ - NULL, /* entityDecl */ - NULL, /* notationDecl */ - NULL, /* attributeDecl */ - NULL, /* elementDecl */ - NULL, /* unparsedEntityDecl */ - NULL, /* setDocumentLocator */ - NULL, /* startDocument */ - NULL, /* endDocument */ - parser_start_element, /* startElement */ - parser_end_element, /* endElement */ - NULL, /* reference */ - parser_characters, /* characters */ - NULL, /* ignorableWhitespace */ - NULL, /* processingInstruction */ - NULL, /* comment */ - NULL, /* xmlParserWarning */ - NULL, /* xmlParserError */ - NULL, /* xmlParserError */ - NULL, /* getParameterEntity */ - NULL, /* cdataBlock */ - NULL, /* externalSubset */ - 1, /* initialized */ - NULL, /* private */ - NULL, /* startElementNsSAX2Func */ - NULL, /* endElementNsSAX2Func */ - NULL /* xmlStructuredErrorFunc */ - }; - - file = tracker_extract_info_get_file (info); - - metadata = tracker_resource_new (NULL); - tracker_resource_add_uri (metadata, "rdf:type", "nfo:HtmlDocument"); - - pd.metadata = metadata; - pd.current = -1; - pd.in_body = FALSE; - pd.plain_text = g_string_new (NULL); - pd.title = g_string_new (NULL); - - config = tracker_main_get_config (); - pd.n_bytes_remaining = tracker_config_get_max_bytes (config); - - filename = g_file_get_path (file); - doc = htmlSAXParseFile (filename, NULL, &handler, &pd); - g_free (filename); - - if (doc) { - xmlFreeDoc (doc); - } - - g_strstrip (pd.plain_text->str); - g_strstrip (pd.title->str); - - if (pd.title->str && - *pd.title->str != '\0') { - tracker_resource_set_string (metadata, "nie:title", pd.title->str); - } - - if (pd.plain_text->str && - *pd.plain_text->str != '\0') { - tracker_resource_set_string (metadata, "nie:plainTextContent", pd.plain_text->str); - } - - g_string_free (pd.plain_text, TRUE); - g_string_free (pd.title, TRUE); - - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-icon.c b/src/tracker-extract/tracker-extract-icon.c deleted file mode 100644 index 69ed5fdd4..000000000 --- a/src/tracker-extract/tracker-extract-icon.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <libtracker-common/tracker-file-utils.h> -#include <libtracker-extract/tracker-extract.h> - -#define ICON_HEADER_SIZE_16 3 -#define ICON_IMAGE_METADATA_SIZE_8 16 - -static gboolean -find_max_width_and_height (const gchar *uri, - guint *width, - guint *height) -{ - GError *error = NULL; - GFile *file; - GFileInputStream *stream; - guint n_images; - guint i; - guint16 header [ICON_HEADER_SIZE_16]; - - *width = 0; - *height = 0; - - file = g_file_new_for_uri (uri); - stream = g_file_read (file, NULL, &error); - if (error) { - g_message ("Could not read file '%s': %s", - uri, - error->message); - g_error_free (error); - g_object_unref (file); - - return FALSE; - } - - /* Header consists of: - * - 2bytes, reserved, must be 0 - * - 2bytes, image type (1:icon, 2:cursor, other values invalid) - * - 2bytes, number of images in the file. - * - * Right now we just need the number of images in the file. - */ - if (!g_input_stream_read_all (G_INPUT_STREAM (stream), - header, - ICON_HEADER_SIZE_16 * 2, - NULL, - NULL, - &error)) { - g_message ("Error reading icon header from stream: '%s'", - error->message); - g_error_free (error); - g_object_unref (stream); - g_object_unref (file); - return FALSE; - } - - n_images = GUINT16_FROM_LE (header[2]); - g_debug ("Found '%u' images in the icon file...", n_images); - - /* Loop images looking for the biggest one... */ - for (i = 0; i < n_images; i++) { - guint8 image_metadata [ICON_IMAGE_METADATA_SIZE_8]; - - /* Image metadata chunk consists of: - * - 1 byte, width in pixels, 0 means 256 - * - 1 byte, height in pixels, 0 means 256 - * - Plus some other stuff we don't care about... - */ - if (!g_input_stream_read_all (G_INPUT_STREAM (stream), - image_metadata, - ICON_IMAGE_METADATA_SIZE_8, - NULL, - NULL, - &error)) { - g_message ("Error reading icon image metadata '%u' from stream: '%s'", - i, - error->message); - g_error_free (error); - break; - } - - g_debug (" Image '%u'; width:%u height:%u", - i, - image_metadata[0], - image_metadata[1]); - - /* Width... */ - if (image_metadata[0] == 0) { - *width = 256; - } else if (image_metadata[0] > *width) { - *width = image_metadata[0]; - } - - /* Height... */ - if (image_metadata[1] == 0) { - *height = 256; - } else if (image_metadata[1] > *height) { - *height = image_metadata[1]; - } - } - - g_input_stream_close (G_INPUT_STREAM (stream), NULL, NULL); - g_object_unref (stream); - g_object_unref (file); - return TRUE; -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerResource *metadata; - guint max_width; - guint max_height; - GFile *file; - gchar *uri; - - file = tracker_extract_info_get_file (info); - uri = g_file_get_uri (file); - - metadata = tracker_resource_new (NULL); - - /* The Windows Icon file format may contain the same icon with different - * sizes inside, so there's no clear way of setting single width and - * height values. Thus, we set maximum sizes found. */ - tracker_resource_add_uri (metadata, "rdf:type", "nfo:Image"); - tracker_resource_add_uri (metadata, "rdf:type", "nfo:Icon"); - - if (find_max_width_and_height (uri, &max_width, &max_height)) { - if (max_width > 0) { - tracker_resource_set_int64 (metadata, "nfo:width", (gint64)max_width); - } - if (max_height > 0) { - tracker_resource_set_int64 (metadata, "nfo:height", (gint64)max_height); - } - } - - g_free (uri); - - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-iso.c b/src/tracker-extract/tracker-extract-iso.c deleted file mode 100644 index 66f3c629d..000000000 --- a/src/tracker-extract/tracker-extract-iso.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2011, 2014 Red Hat, Inc - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * Authors: Christophe Fergeau <cfergeau@redhat.com> - * Zeeshan Ali (Khattak) <zeeshanak@gnome.org> - */ - -#include "config.h" - -#include <stdio.h> - -#include <osinfo/osinfo.h> - -#include <gio/gio.h> - -#include <libtracker-extract/tracker-extract.h> -#include <libtracker-sparql/tracker-sparql.h> - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info_) -{ - /* NOTE: This function has to exist, tracker-extract checks - * the symbol table for this function and if it doesn't - * exist, the module is not loaded to be used as an extractor. - */ - - /* File information */ - GFile *file; - GError *error = NULL; - gchar *filename; - OsinfoLoader *loader = NULL; - OsinfoMedia *media; - OsinfoDb *db; - OsinfoOs *os; - OsinfoOsVariantList *variants; - - /* Data input */ - gboolean bootable; - const gchar *id; - const gchar *name; - GList *languages, *l; - TrackerResource *metadata; - - file = tracker_extract_info_get_file (info_); - filename = g_file_get_path (file); - - metadata = tracker_resource_new (NULL); - - media = osinfo_media_create_from_location (filename, NULL, &error); - if (error != NULL) { - if (error->code != OSINFO_MEDIA_ERROR_NOT_BOOTABLE) { - g_object_unref (metadata); - g_message ("Could not extract iso info from '%s': %s", - filename, error->message); - g_free (filename); - g_error_free (error); - return FALSE; - } - bootable = FALSE; - goto no_os; - } else { - bootable = TRUE; - } - g_free (filename); - - loader = osinfo_loader_new (); - osinfo_loader_process_default_path (loader, &error); - if (error != NULL) { - g_message ("Error loading libosinfo OS data: %s", - error->message); - g_error_free (error); - goto no_os; - } - g_warn_if_fail (media != NULL); - g_warn_if_fail (loader != NULL); - - db = osinfo_loader_get_db (loader); - osinfo_db_identify_media (db, media); - os = osinfo_media_get_os (media); - - if (os == NULL) - goto unknown_os; - - tracker_resource_add_uri (metadata, "rdf:type", "nfo:FilesystemImage"); - - variants = osinfo_media_get_os_variants (media); - if (osinfo_list_get_length (OSINFO_LIST (variants)) > 0) { - OsinfoEntity *variant; - - /* FIXME: Assuming first variant from multivariant medias. */ - variant = osinfo_list_get_nth (OSINFO_LIST (variants), 0); - name = osinfo_os_variant_get_name (OSINFO_OS_VARIANT (variant)); - } else { - name = osinfo_product_get_name (OSINFO_PRODUCT (os)); - } - - if (name != NULL) { - tracker_resource_set_string (metadata, "nie:title", name); - } - - if (osinfo_media_get_live (media)) { - tracker_resource_add_uri (metadata, "rdf:type", "nfo:OperatingSystem"); - } - - if (osinfo_media_get_installer (media)) { - tracker_resource_add_uri (metadata, "rdf:type", "osinfo:Installer"); - } - - tracker_resource_set_boolean (metadata, "nfo:isBootable", bootable); - - id = osinfo_entity_get_id (OSINFO_ENTITY (os)); - if (id != NULL) { - tracker_resource_set_string (metadata, "osinfo:id", id); - } - - id = osinfo_entity_get_id (OSINFO_ENTITY (media)); - if (id != NULL) { - tracker_resource_set_string (metadata, "osinfo:mediaId", id); - } - - languages = osinfo_media_get_languages (media); - for (l = languages; l != NULL; l = l->next) { - tracker_resource_add_string (metadata, "osinfo:language", (char *)l->data); - } - g_list_free (languages); - - g_object_unref (G_OBJECT (media)); - g_object_unref (G_OBJECT (loader)); - - tracker_extract_info_set_resource (info_, metadata); - g_object_unref (metadata); - - return TRUE; - -unknown_os: - name = osinfo_media_get_volume_id (media); - if (name != NULL) { - gchar *stripped = g_strdup (name); - - g_strstrip (stripped); - tracker_resource_set_string (metadata, "nie:title", stripped); - g_free (stripped); - } - -no_os: - if (media != NULL) { - g_object_unref (G_OBJECT (media)); - } - if (loader != NULL) { - g_object_unref (G_OBJECT (loader)); - } - - tracker_resource_add_uri (metadata, "rdf:type", "nfo:FilesystemImage"); - - tracker_resource_set_boolean (metadata, "nfo:isBootable", bootable); - - tracker_extract_info_set_resource (info_, metadata); - g_object_unref (metadata); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-jpeg.c b/src/tracker-extract/tracker-extract-jpeg.c deleted file mode 100644 index c6b07bf69..000000000 --- a/src/tracker-extract/tracker-extract-jpeg.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <stdio.h> -#include <setjmp.h> - -#include <jpeglib.h> - -#include <libtracker-common/tracker-common.h> -#include <libtracker-extract/tracker-extract.h> -#include <libtracker-sparql/tracker-sparql.h> - -#include "tracker-main.h" - -#define CM_TO_INCH 0.393700787 - -#ifdef HAVE_LIBEXIF -#define EXIF_NAMESPACE "Exif" -#define EXIF_NAMESPACE_LENGTH 4 -#endif /* HAVE_LIBEXIF */ - -#ifdef HAVE_EXEMPI -#define XMP_NAMESPACE "http://ns.adobe.com/xap/1.0/\x00" -#define XMP_NAMESPACE_LENGTH 29 -#endif /* HAVE_EXEMPI */ - -#ifdef HAVE_LIBIPTCDATA -#define PS3_NAMESPACE "Photoshop 3.0\0" -#define PS3_NAMESPACE_LENGTH 14 -#include <libiptcdata/iptc-jpeg.h> -#endif /* HAVE_LIBIPTCDATA */ - -typedef struct { - const gchar *make; - const gchar *model; - const gchar *title; - const gchar *orientation; - const gchar *copyright; - const gchar *white_balance; - const gchar *fnumber; - const gchar *flash; - const gchar *focal_length; - const gchar *artist; - const gchar *exposure_time; - const gchar *iso_speed_ratings; - const gchar *date; - const gchar *description; - const gchar *metering_mode; - const gchar *creator; - const gchar *comment; - const gchar *city; - const gchar *state; - const gchar *address; - const gchar *country; - const gchar *gps_altitude; - const gchar *gps_latitude; - const gchar *gps_longitude; - const gchar *gps_direction; -} MergeData; - -struct tej_error_mgr { - struct jpeg_error_mgr jpeg; - jmp_buf setjmp_buffer; -}; - -static void -extract_jpeg_error_exit (j_common_ptr cinfo) -{ - struct tej_error_mgr *h = (struct tej_error_mgr *) cinfo->err; - (*cinfo->err->output_message)(cinfo); - longjmp (h->setjmp_buffer, 1); -} - -static gboolean -guess_dlna_profile (gint width, - gint height, - const gchar **dlna_profile, - const gchar **dlna_mimetype) -{ - const gchar *profile = NULL; - - if (dlna_profile) { - *dlna_profile = NULL; - } - - if (dlna_mimetype) { - *dlna_mimetype = NULL; - } - - if (width <= 640 && height <= 480) { - profile = "JPEG_SM"; - } else if (width <= 1024 && height <= 768) { - profile = "JPEG_MED"; - } else if (width <= 4096 && height <= 4096) { - profile = "JPEG_LRG"; - } - - if (profile) { - if (dlna_profile) { - *dlna_profile = profile; - } - - if (dlna_mimetype) { - *dlna_mimetype = "image/jpeg"; - } - - return TRUE; - } - - return FALSE; -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - struct jpeg_decompress_struct cinfo; - struct tej_error_mgr tejerr; - struct jpeg_marker_struct *marker; - TrackerResource *metadata; - TrackerXmpData *xd = NULL; - TrackerExifData *ed = NULL; - TrackerIptcData *id = NULL; - MergeData md = { 0 }; - GFile *file; - FILE *f; - goffset size; - gchar *filename, *uri; - gchar *comment = NULL; - const gchar *dlna_profile, *dlna_mimetype; - GPtrArray *keywords; - gboolean success = TRUE; - guint i; - - file = tracker_extract_info_get_file (info); - filename = g_file_get_path (file); - - size = tracker_file_get_size (filename); - - if (size < 18) { - g_free (filename); - return FALSE; - } - - f = tracker_file_open (filename); - g_free (filename); - - if (!f) { - return FALSE; - } - - uri = g_file_get_uri (file); - - cinfo.err = jpeg_std_error (&tejerr.jpeg); - tejerr.jpeg.error_exit = extract_jpeg_error_exit; - if (setjmp (tejerr.setjmp_buffer)) { - success = FALSE; - goto fail; - } - - metadata = tracker_resource_new (NULL); - tracker_resource_add_uri (metadata, "rdf:type", "nfo:Image"); - tracker_resource_add_uri (metadata, "rdf:type", "nmm:Photo"); - - jpeg_create_decompress (&cinfo); - - jpeg_save_markers (&cinfo, JPEG_COM, 0xFFFF); - jpeg_save_markers (&cinfo, JPEG_APP0 + 1, 0xFFFF); - jpeg_save_markers (&cinfo, JPEG_APP0 + 13, 0xFFFF); - - jpeg_stdio_src (&cinfo, f); - - jpeg_read_header (&cinfo, TRUE); - - /* FIXME? It is possible that there are markers after SOS, - * but there shouldn't be. Should we decompress the whole file? - * - * jpeg_start_decompress(&cinfo); - * jpeg_finish_decompress(&cinfo); - * - * jpeg_calc_output_dimensions(&cinfo); - */ - - marker = (struct jpeg_marker_struct *) &cinfo.marker_list; - - while (marker) { - gchar *str; - gsize len; -#ifdef HAVE_LIBIPTCDATA - gsize offset; - guint sublen; -#endif /* HAVE_LIBIPTCDATA */ - - switch (marker->marker) { - case JPEG_COM: - g_free (comment); - comment = g_strndup ((gchar*) marker->data, marker->data_length); - break; - - case JPEG_APP0 + 1: - str = (gchar*) marker->data; - len = marker->data_length; - -#ifdef HAVE_LIBEXIF - if (strncmp (EXIF_NAMESPACE, str, EXIF_NAMESPACE_LENGTH) == 0) { - ed = tracker_exif_new ((guchar *) marker->data, len, uri); - } -#endif /* HAVE_LIBEXIF */ - -#ifdef HAVE_EXEMPI - if (strncmp (XMP_NAMESPACE, str, XMP_NAMESPACE_LENGTH) == 0) { - xd = tracker_xmp_new (str + XMP_NAMESPACE_LENGTH, - len - XMP_NAMESPACE_LENGTH, - uri); - } -#endif /* HAVE_EXEMPI */ - - break; - - case JPEG_APP0 + 13: - str = (gchar*) marker->data; - len = marker->data_length; -#ifdef HAVE_LIBIPTCDATA - if (len > 0 && strncmp (PS3_NAMESPACE, str, PS3_NAMESPACE_LENGTH) == 0) { - offset = iptc_jpeg_ps3_find_iptc (str, len, &sublen); - if (offset > 0 && sublen > 0) { - id = tracker_iptc_new (str + offset, sublen, uri); - } - } -#endif /* HAVE_LIBIPTCDATA */ - - break; - - default: - marker = marker->next; - continue; - } - - marker = marker->next; - } - - if (!ed) { - ed = g_new0 (TrackerExifData, 1); - } - - if (!xd) { - xd = g_new0 (TrackerXmpData, 1); - } - - if (!id) { - id = g_new0 (TrackerIptcData, 1); - } - - md.title = tracker_coalesce_strip (4, xd->title, ed->document_name, xd->title2, xd->pdf_title); - md.orientation = tracker_coalesce_strip (3, xd->orientation, ed->orientation, id->image_orientation); - md.copyright = tracker_coalesce_strip (4, xd->copyright, xd->rights, ed->copyright, id->copyright_notice); - md.white_balance = tracker_coalesce_strip (2, xd->white_balance, ed->white_balance); - md.fnumber = tracker_coalesce_strip (2, xd->fnumber, ed->fnumber); - md.flash = tracker_coalesce_strip (2, xd->flash, ed->flash); - md.focal_length = tracker_coalesce_strip (2, xd->focal_length, ed->focal_length); - md.artist = tracker_coalesce_strip (3, xd->artist, ed->artist, xd->contributor); - md.exposure_time = tracker_coalesce_strip (2, xd->exposure_time, ed->exposure_time); - md.iso_speed_ratings = tracker_coalesce_strip (2, xd->iso_speed_ratings, ed->iso_speed_ratings); - md.date = tracker_coalesce_strip (5, xd->date, xd->time_original, ed->time, id->date_created, ed->time_original); - md.description = tracker_coalesce_strip (2, xd->description, ed->description); - md.metering_mode = tracker_coalesce_strip (2, xd->metering_mode, ed->metering_mode); - md.city = tracker_coalesce_strip (2, xd->city, id->city); - md.state = tracker_coalesce_strip (2, xd->state, id->state); - md.address = tracker_coalesce_strip (2, xd->address, id->sublocation); - md.country = tracker_coalesce_strip (2, xd->country, id->country_name); - - /* FIXME We are not handling the altitude ref here for xmp */ - md.gps_altitude = tracker_coalesce_strip (2, xd->gps_altitude, ed->gps_altitude); - md.gps_latitude = tracker_coalesce_strip (2, xd->gps_latitude, ed->gps_latitude); - md.gps_longitude = tracker_coalesce_strip (2, xd->gps_longitude, ed->gps_longitude); - md.gps_direction = tracker_coalesce_strip (2, xd->gps_direction, ed->gps_direction); - md.creator = tracker_coalesce_strip (3, xd->creator, id->byline, id->credit); - md.comment = tracker_coalesce_strip (2, comment, ed->user_comment); - md.make = tracker_coalesce_strip (2, xd->make, ed->make); - md.model = tracker_coalesce_strip (2, xd->model, ed->model); - - /* Prioritize on native dimention in all cases */ - tracker_resource_set_int64 (metadata, "nfo:width", cinfo.image_width); - tracker_resource_set_int64 (metadata, "nfo:height", cinfo.image_height); - - if (guess_dlna_profile (cinfo.image_width, cinfo.image_height, &dlna_profile, &dlna_mimetype)) { - tracker_resource_set_string (metadata, "nmm:dlnaProfile", dlna_profile); - tracker_resource_set_string (metadata, "nmm:dlnaMime", dlna_mimetype); - } - - if (id->contact) { - TrackerResource *contact = tracker_extract_new_contact (id->contact); - tracker_resource_add_relation (metadata, "nco:contributor", contact); - g_object_unref (contact); - } - - keywords = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); - - if (xd->keywords) { - tracker_keywords_parse (keywords, xd->keywords); - } - - if (xd->pdf_keywords) { - tracker_keywords_parse (keywords, xd->pdf_keywords); - } - - if (xd->subject) { - tracker_keywords_parse (keywords, xd->subject); - } - - if (xd->publisher) { - TrackerResource *publisher = tracker_extract_new_contact (xd->publisher); - tracker_resource_add_relation (metadata, "nco:publisher", publisher); - g_object_unref (publisher); - } - - if (xd->type) { - tracker_resource_set_string (metadata, "dc:type", xd->type); - } - - if (xd->rating) { - tracker_resource_set_string (metadata, "nao:numericRating", xd->rating); - } - - if (xd->format) { - tracker_resource_set_string (metadata, "dc:format", xd->format); - } - - if (xd->identifier) { - tracker_resource_set_string (metadata, "dc:identifier", xd->identifier); - } - - if (xd->source) { - tracker_resource_set_string (metadata, "dc:source", xd->source); - } - - if (xd->language) { - tracker_resource_set_string (metadata, "dc:language", xd->language); - } - - if (xd->relation) { - tracker_resource_set_string (metadata, "dc:relation", xd->relation); - } - - if (xd->coverage) { - tracker_resource_set_string (metadata, "dc:coverage", xd->coverage); - } - - if (xd->license) { - tracker_resource_set_string (metadata, "nie:license", xd->license); - } - - if (xd->regions) { - tracker_xmp_apply_regions_to_resource (metadata, xd); - } - - if (id->keywords) { - tracker_keywords_parse (keywords, id->keywords); - } - - for (i = 0; i < keywords->len; i++) { - TrackerResource *tag; - const gchar *p; - - p = g_ptr_array_index (keywords, i); - tag = tracker_extract_new_tag (p); - - tracker_resource_add_relation (metadata, "nao:hasTag", tag); - - g_object_unref (tag); - } - g_ptr_array_free (keywords, TRUE); - - if (md.make || md.model) { - TrackerResource *equipment = tracker_extract_new_equipment (md.make, md.model); - tracker_resource_add_relation (metadata, "nfo:equipment", equipment); - g_object_unref (equipment); - } - - tracker_guarantee_resource_title_from_file (metadata, - "nie:title", - md.title, - uri, - NULL); - - if (md.orientation) { - TrackerResource *orientation; - - orientation = tracker_resource_new (md.orientation); - tracker_resource_set_relation (metadata, "nfo:orientation", orientation); - g_object_unref (orientation); - } - - if (md.copyright) { - tracker_resource_set_string (metadata, "nie:copyright", md.copyright); - } - - if (md.white_balance) { - TrackerResource *white_balance; - - white_balance = tracker_resource_new (md.white_balance); - tracker_resource_set_relation (metadata, "nmm:meteringMode", white_balance); - g_object_unref (white_balance); - } - - if (md.fnumber) { - gdouble value; - - value = g_strtod (md.fnumber, NULL); - tracker_resource_set_double (metadata, "nmm:fnumber", value); - } - - if (md.flash) { - TrackerResource *flash; - - flash = tracker_resource_new (md.flash); - tracker_resource_set_relation (metadata, "nmm:flash", flash); - g_object_unref (flash); - } - - if (md.focal_length) { - gdouble value; - - value = g_strtod (md.focal_length, NULL); - tracker_resource_set_double (metadata, "nmm:focalLength", value); - } - - if (md.artist) { - TrackerResource *artist = tracker_extract_new_contact (md.artist); - tracker_resource_add_relation (metadata, "nco:contributor", artist); - g_object_unref (artist); - } - - if (md.exposure_time) { - gdouble value; - - value = g_strtod (md.exposure_time, NULL); - tracker_resource_set_double (metadata, "nmm:exposureTime", value); - } - - if (md.iso_speed_ratings) { - gdouble value; - - value = g_strtod (md.iso_speed_ratings, NULL); - tracker_resource_set_double (metadata, "nmm:isoSpeed", value); - } - - tracker_guarantee_resource_date_from_file_mtime (metadata, - "nie:contentCreated", - md.date, - uri); - - if (md.description) { - tracker_resource_set_string(metadata, "nie:description", md.description); - } - - if (md.metering_mode) { - TrackerResource *metering; - - metering = tracker_resource_new (md.metering_mode); - tracker_resource_set_relation (metadata, "nmm:meteringMode", metering); - g_object_unref (metering); - } - - if (md.creator) { - TrackerResource *creator = tracker_extract_new_contact (md.creator); - tracker_resource_add_relation (metadata, "nco:creator", creator); - g_object_unref (creator); - - /* NOTE: We only have affiliation with - * nco:PersonContact and we are using - * nco:Contact here. - */ - - /* if (id->byline_title) { */ - /* tracker_sparql_builder_insert_open (preupdate, NULL); */ - - /* tracker_sparql_builder_subject (preupdate, "_:affiliation_by_line"); */ - /* tracker_sparql_builder_predicate (preupdate, "a"); */ - /* tracker_sparql_builder_object (preupdate, "nco:Affiliation"); */ - - /* tracker_sparql_builder_predicate (preupdate, "nco:title"); */ - /* tracker_sparql_builder_object_unvalidated (preupdate, id->byline_title); */ - - /* tracker_sparql_builder_insert_close (preupdate); */ - - /* tracker_sparql_builder_predicate (preupdate, "a"); */ - /* tracker_sparql_builder_object (preupdate, "nco:Contact"); */ - /* tracker_sparql_builder_predicate (preupdate, "nco:hasAffiliation"); */ - /* tracker_sparql_builder_object (preupdate, "_:affiliation_by_line"); */ - /* } */ - } - - if (md.comment) { - tracker_guarantee_resource_utf8_string (metadata, "nie:comment", md.comment); - } - - if (md.address || md.state || md.country || md.city || - md.gps_altitude || md.gps_latitude || md.gps_longitude) { - - TrackerResource *location = tracker_extract_new_location (md.address, - md.state, md.city, md.country, md.gps_altitude, - md.gps_latitude, md.gps_longitude); - - tracker_resource_add_relation (metadata, "slo:location", location); - - g_object_unref (location); - } - - if (md.gps_direction) { - tracker_resource_set_string (metadata, "nfo:heading", md.gps_direction); - } - - if (cinfo.density_unit != 0 || ed->x_resolution) { - gdouble value; - - if (cinfo.density_unit == 0) { - if (ed->resolution_unit != 3) - value = g_strtod (ed->x_resolution, NULL); - else - value = g_strtod (ed->x_resolution, NULL) * CM_TO_INCH; - } else { - if (cinfo.density_unit == 1) - value = cinfo.X_density; - else - value = cinfo.X_density * CM_TO_INCH; - } - - tracker_resource_set_double (metadata, "nfo:horizontalResolution", value); - } - - if (cinfo.density_unit != 0 || ed->y_resolution) { - gdouble value; - - if (cinfo.density_unit == 0) { - if (ed->resolution_unit != 3) - value = g_strtod (ed->y_resolution, NULL); - else - value = g_strtod (ed->y_resolution, NULL) * CM_TO_INCH; - } else { - if (cinfo.density_unit == 1) - value = cinfo.Y_density; - else - value = cinfo.Y_density * CM_TO_INCH; - } - - tracker_resource_set_double (metadata, "nfo:verticalResolution", value); - } - - jpeg_destroy_decompress (&cinfo); - - tracker_exif_free (ed); - tracker_xmp_free (xd); - tracker_iptc_free (id); - g_free (comment); - - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - -fail: - tracker_file_close (f, FALSE); - g_free (uri); - - return success; -} diff --git a/src/tracker-extract/tracker-extract-libav.c b/src/tracker-extract/tracker-extract-libav.c deleted file mode 100644 index 142427bc4..000000000 --- a/src/tracker-extract/tracker-extract-libav.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * Copyright (C) 2013-2014 Jolla Ltd. <andrew.den.exter@jollamobile.com> - * Author: Andrew den Exter <andrew.den.exter@jollamobile.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - - -#include <glib.h> - -#include <libtracker-sparql/tracker-ontologies.h> -#include <libtracker-common/tracker-utils.h> - -#include <libtracker-extract/tracker-extract.h> - -#include <libavcodec/avcodec.h> -#include <libavformat/avformat.h> -#include <libavutil/mathematics.h> - - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - GFile *file; - TrackerResource *metadata; - gchar *absolute_file_path; - gchar *content_created = NULL; - gchar *uri; - AVFormatContext *format = NULL; - AVStream *audio_stream = NULL; - AVStream *video_stream = NULL; - int audio_stream_index; - int video_stream_index; - AVDictionaryEntry *tag = NULL; - const char *title = NULL; - - av_register_all (); - - file = tracker_extract_info_get_file (info); - - uri = g_file_get_uri (file); - - absolute_file_path = g_file_get_path (file); - if (avformat_open_input (&format, absolute_file_path, NULL, NULL)) { - g_free (absolute_file_path); - g_free (uri); - return FALSE; - } - g_free (absolute_file_path); - - avformat_find_stream_info (format, NULL); - - audio_stream_index = av_find_best_stream (format, AVMEDIA_TYPE_AUDIO, -1, -1, NULL, 0); - if (audio_stream_index >= 0) { - audio_stream = format->streams[audio_stream_index]; - } - - video_stream_index = av_find_best_stream (format, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); - if (video_stream_index >= 0) { - video_stream = format->streams[video_stream_index]; - } - - if (!audio_stream && !video_stream) { - avformat_close_input (&format); - g_free (uri); - return FALSE; - } - - metadata = tracker_resource_new (NULL); - - if ((tag = av_dict_get (format->metadata, "creation_time", NULL, 0))) { - content_created = tracker_date_guess (tag->value); - if (content_created) { - tracker_resource_set_string (metadata, "nie:contentCreated", content_created); - } - } - - if (audio_stream) { - if (audio_stream->codec->sample_rate > 0) { - tracker_resource_set_int64 (metadata, "nfo:sampleRate", audio_stream->codec->sample_rate); - } - if (audio_stream->codec->channels > 0) { - tracker_resource_set_int64 (metadata, "nfo:channels", audio_stream->codec->channels); - } - } - - if (video_stream) { - tracker_resource_add_uri(metadata, "rdf:type", "nmm:Video"); - - if (video_stream->codec->width > 0 && video_stream->codec->height > 0) { - tracker_resource_set_int64 (metadata, "nfo:width", video_stream->codec->width); - tracker_resource_set_int64 (metadata, "nfo:height", video_stream->codec->height); - } - - if (video_stream->avg_frame_rate.num > 0) { - gdouble frame_rate = (gdouble) video_stream->avg_frame_rate.num - / video_stream->avg_frame_rate.den; - tracker_resource_set_double (metadata, "nfo:frameRate", frame_rate); - } - - if (video_stream->duration > 0) { - gint64 duration = av_rescale(video_stream->duration, video_stream->time_base.num, - video_stream->time_base.den); - tracker_resource_set_int64 (metadata, "nfo:duration", duration); - } - - if (video_stream->sample_aspect_ratio.num > 0) { - gdouble aspect_ratio = (gdouble) video_stream->sample_aspect_ratio.num - / video_stream->sample_aspect_ratio.den; - tracker_resource_set_double (metadata, "nfo:aspectRatio", aspect_ratio); - } - - if (video_stream->nb_frames > 0) { - tracker_resource_set_int64 (metadata, "nfo:frameCount", video_stream->nb_frames); - } - - if ((tag = av_dict_get (format->metadata, "synopsis", NULL, 0))) { - tracker_resource_set_string (metadata, "nmm:synopsis", tag->value); - } - - if ((tag = av_dict_get (format->metadata, "episode_sort", NULL, 0))) { - tracker_resource_set_int64 (metadata, "nmm:episodeNumber", atoi(tag->value)); - } - - if ((tag = av_dict_get (format->metadata, "season_number", NULL, 0))) { - tracker_resource_set_int64 (metadata, "nmm:season", atoi(tag->value)); - } - - } else if (audio_stream) { - TrackerResource *album_artist = NULL, *performer = NULL; - char *album_artist_name = NULL; - char *album_title = NULL; - - tracker_resource_add_uri (metadata, "rdf:type", "nmm:MusicPiece"); - tracker_resource_add_uri (metadata, "rdf:type", "nfo:Audio"); - - if (audio_stream->duration > 0) { - gint64 duration = av_rescale(audio_stream->duration, audio_stream->time_base.num, - audio_stream->time_base.den); - tracker_resource_set_int64 (metadata, "nfo:duration", duration); - } - - if ((tag = av_dict_get (format->metadata, "track", NULL, 0))) { - int track = atoi(tag->value); - if (track > 0) { - tracker_resource_set_int64 (metadata, "nmm:trackNumber", track); - } - } - - if ((tag = av_dict_get (format->metadata, "album", NULL, 0))) { - album_title = tag->value; - } - - if (album_title && (tag = av_dict_get (format->metadata, "album_artist", NULL, 0))) { - album_artist_name = tag->value; - album_artist = tracker_extract_new_artist (album_artist_name); - } - - if ((tag = av_dict_get (format->metadata, "artist", tag, 0))) { - performer = tracker_extract_new_artist (tag->value); - } - - if (!performer && (tag = av_dict_get (format->metadata, "performer", tag, 0))) { - performer = tracker_extract_new_artist (tag->value); - } - - if (performer) { - tracker_resource_set_relation (metadata, "nmm:performer", performer); - } - - if ((tag = av_dict_get (format->metadata, "composer", tag, 0))) { - TrackerResource *composer = tracker_extract_new_artist (tag->value); - tracker_resource_set_relation (metadata, "nmm:composer", composer); - g_object_unref (composer); - } - - if (album_title) { - int disc_number = 1; - TrackerResource *album_disc; - - if ((tag = av_dict_get (format->metadata, "disc", NULL, 0))) { - disc_number = atoi (tag->value); - } - - album_disc = tracker_extract_new_music_album_disc (album_title, album_artist, disc_number, content_created); - - tracker_resource_set_relation (metadata, "nmm:musicAlbumDisc", album_disc); - tracker_resource_set_relation (metadata, "nmm:musicAlbum", tracker_resource_get_first_relation (album_disc, "nmm:albumDiscAlbum")); - - g_object_unref (album_disc); - } - - if (performer) - g_object_unref (performer); - } - - if (format->bit_rate > 0) { - tracker_resource_set_int64 (metadata, "nfo:averageBitrate", format->bit_rate); - } - - if ((tag = av_dict_get (format->metadata, "comment", NULL, 0))) { - tracker_resource_set_string (metadata, "nie:comment", tag->value); - } - - if ((tag = av_dict_get (format->metadata, "copyright", NULL, 0))) { - tracker_resource_set_string (metadata, "nie:copyright", tag->value); - } - - if ((tag = av_dict_get (format->metadata, "description", NULL, 0))) { - tracker_resource_set_string (metadata, "nie:description", tag->value); - } - - if ((tag = av_dict_get (format->metadata, "genre", NULL, 0))) { - tracker_resource_set_string (metadata, "nfo:genre", tag->value); - } - - if ((tag = av_dict_get (format->metadata, "language", NULL, 0))) { - tracker_resource_set_string (metadata, "nfo:language", tag->value); - } - - if ((tag = av_dict_get (format->metadata, "title", NULL, 0))) { - title = tag->value; - } - - tracker_guarantee_resource_title_from_file (metadata, "nie:title", title, uri, NULL); - - g_free (content_created); - g_free (uri); - - avformat_close_input (&format); - - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-mp3.c b/src/tracker-extract/tracker-extract-mp3.c deleted file mode 100644 index 3cd0856ad..000000000 --- a/src/tracker-extract/tracker-extract-mp3.c +++ /dev/null @@ -1,2603 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008-2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> -#include <fcntl.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <errno.h> - -#include <glib.h> -#include <glib/gstdio.h> - -#ifndef G_OS_WIN32 -#include <sys/mman.h> -#endif /* G_OS_WIN32 */ - -#include <libtracker-common/tracker-common.h> - -#include <libtracker-extract/tracker-extract.h> - -#ifdef FRAME_ENABLE_TRACE -#warning Frame traces enabled -#endif /* FRAME_ENABLE_TRACE */ - -/* We mmap the beginning of the file and read separately the last 128 - * bytes for id3v1 tags. While these are probably cornercases the - * rationale is that we don't want to fault a whole page for the last - * 128 bytes and on the other we don't want to mmap the whole file - * with unlimited size (might need to create private copy in some - * special cases, finding continuous space etc). We now take 5 first - * MB of the file and assume that this is enough. In theory there is - * no maximum size as someone could embed 50 gigabytes of album art - * there. - */ - -#define MAX_FILE_READ 1024 * 1024 * 5 -#define MAX_MP3_SCAN_DEEP 16768 - -#define MAX_FRAMES_SCAN 512 -#define VBR_THRESHOLD 16 - -#define ID3V1_SIZE 128 - -typedef struct { - gchar *title; - gchar *artist; - gchar *album; - gchar *recording_time; - gchar *comment; - gchar *genre; - gchar *encoding; - gint track_number; -} id3tag; - -typedef struct { - gchar *album; - gchar *comment; - gchar *content_type; - gchar *copyright; - gchar *encoded_by; - guint32 length; - gchar *performer1; - gchar *performer2; - gchar *composer; - gchar *publisher; - gchar *recording_time; - gchar *release_time; - gchar *text, *toly; - gchar *title1; - gchar *title2; - gchar *title3; - gint track_number; - gint track_count; - gint set_number; - gint set_count; -} id3v2tag; - -typedef enum { - ID3V2_UNKNOWN, - ID3V2_COM, - ID3V2_PIC, - ID3V2_TAL, - ID3V2_TCO, - ID3V2_TCR, - ID3V2_TEN, - ID3V2_TLE, - ID3V2_TPB, - ID3V2_TP1, - ID3V2_TP2, - ID3V2_TRK, - ID3V2_TT1, - ID3V2_TT2, - ID3V2_TT3, - ID3V2_TXT, - ID3V2_TYE, -} id3v2frame; - -typedef enum { - ID3V24_UNKNOWN, - ID3V24_APIC, - ID3V24_COMM, - ID3V24_TALB, - ID3V24_TCOM, - ID3V24_TCON, - ID3V24_TCOP, - ID3V24_TDRC, - ID3V24_TDRL, - ID3V24_TENC, - ID3V24_TEXT, - ID3V24_TIT1, - ID3V24_TIT2, - ID3V24_TIT3, - ID3V24_TLEN, - ID3V24_TOLY, - ID3V24_TPE1, - ID3V24_TPE2, - ID3V24_TPUB, - ID3V24_TRCK, - ID3V24_TPOS, - ID3V24_TYER, -} id3v24frame; - -typedef struct { - size_t size; - size_t id3v2_size; - - const gchar *title; - const gchar *performer_name; - TrackerResource *performer; - const gchar *album_artist_name; - const gchar *lyricist_name; - TrackerResource *lyricist; - const gchar *album_name; - TrackerResource *album; - const gchar *genre; - const gchar *text; - const gchar *recording_time; - const gchar *encoded_by; - const gchar *copyright; - const gchar *publisher; - const gchar *comment; - const gchar *composer_name; - TrackerResource *composer; - gint track_number; - gint track_count; - gint set_number; - gint set_count; - - const unsigned char *media_art_data; - size_t media_art_size; - const gchar *media_art_mime; - - id3tag id3v1; - id3v2tag id3v22; - id3v2tag id3v23; - id3v2tag id3v24; -} MP3Data; - -enum { - MPEG_ERR, - MPEG_V1, - MPEG_V2, - MPEG_V25 -}; - -enum { - LAYER_ERR, - LAYER_1, - LAYER_2, - LAYER_3 -}; - -/* sorted array */ -static const struct { - const char *name; - id3v24frame frame; -} id3v24_frames[] = { - { "APIC", ID3V24_APIC }, - { "COMM", ID3V24_COMM }, - { "TALB", ID3V24_TALB }, - { "TCOM", ID3V24_TCOM }, - { "TCON", ID3V24_TCON }, - { "TCOP", ID3V24_TCOP }, - { "TDRC", ID3V24_TDRC }, - { "TDRL", ID3V24_TDRL }, - { "TENC", ID3V24_TENC }, - { "TEXT", ID3V24_TEXT }, - { "TIT1", ID3V24_TIT1 }, - { "TIT2", ID3V24_TIT2 }, - { "TIT3", ID3V24_TIT3 }, - { "TLEN", ID3V24_TLEN }, - { "TOLY", ID3V24_TOLY }, - { "TPE1", ID3V24_TPE1 }, - { "TPE2", ID3V24_TPE2 }, - { "TPOS", ID3V24_TPOS }, - { "TPUB", ID3V24_TPUB }, - { "TRCK", ID3V24_TRCK }, - { "TYER", ID3V24_TYER }, -}; - -/* sorted array */ -static const struct { - const char *name; - id3v2frame frame; -} id3v2_frames[] = { - { "COM", ID3V2_COM }, - { "PIC", ID3V2_PIC }, - { "TAL", ID3V2_TAL }, - { "TCO", ID3V2_TCO }, - { "TCR", ID3V2_TCR }, - { "TEN", ID3V2_TEN }, - { "TLE", ID3V2_TLE }, - { "TP1", ID3V2_TP1 }, - { "TP2", ID3V2_TP2 }, - { "TPB", ID3V2_TPB }, - { "TRK", ID3V2_TRK }, - { "TT1", ID3V2_TT1 }, - { "TT2", ID3V2_TT2 }, - { "TT3", ID3V2_TT3 }, - { "TXT", ID3V2_TXT }, - { "TYE", ID3V2_TYE }, -}; - -static const char *const genre_names[] = { - "Blues", - "Classic Rock", - "Country", - "Dance", - "Disco", - "Funk", - "Grunge", - "Hip-Hop", - "Jazz", - "Metal", - "New Age", - "Oldies", - "Other", - "Pop", - "R&B", - "Rap", - "Reggae", - "Rock", - "Techno", - "Industrial", - "Alternative", - "Ska", - "Death Metal", - "Pranks", - "Soundtrack", - "Euro-Techno", - "Ambient", - "Trip-Hop", - "Vocal", - "Jazz+Funk", - "Fusion", - "Trance", - "Classical", - "Instrumental", - "Acid", - "House", - "Game", - "Sound Clip", - "Gospel", - "Noise", - "Alt. Rock", - "Bass", - "Soul", - "Punk", - "Space", - "Meditative", - "Instrumental Pop", - "Instrumental Rock", - "Ethnic", - "Gothic", - "Darkwave", - "Techno-Industrial", - "Electronic", - "Pop-Folk", - "Eurodance", - "Dream", - "Southern Rock", - "Comedy", - "Cult", - "Gangsta Rap", - "Top 40", - "Christian Rap", - "Pop/Funk", - "Jungle", - "Native American", - "Cabaret", - "New Wave", - "Psychedelic", - "Rave", - "Showtunes", - "Trailer", - "Lo-Fi", - "Tribal", - "Acid Punk", - "Acid Jazz", - "Polka", - "Retro", - "Musical", - "Rock & Roll", - "Hard Rock", - "Folk", - "Folk/Rock", - "National Folk", - "Swing", - "Fast-Fusion", - "Bebob", - "Latin", - "Revival", - "Celtic", - "Bluegrass", - "Avantgarde", - "Gothic Rock", - "Progressive Rock", - "Psychedelic Rock", - "Symphonic Rock", - "Slow Rock", - "Big Band", - "Chorus", - "Easy Listening", - "Acoustic", - "Humour", - "Speech", - "Chanson", - "Opera", - "Chamber Music", - "Sonata", - "Symphony", - "Booty Bass", - "Primus", - "Porn Groove", - "Satire", - "Slow Jam", - "Club", - "Tango", - "Samba", - "Folklore", - "Ballad", - "Power Ballad", - "Rhythmic Soul", - "Freestyle", - "Duet", - "Punk Rock", - "Drum Solo", - "A Cappella", - "Euro-House", - "Dance Hall", - "Goa", - "Drum & Bass", - "Club-House", - "Hardcore", - "Terror", - "Indie", - "BritPop", - "Negerpunk", - "Polsk Punk", - "Beat", - "Christian Gangsta Rap", - "Heavy Metal", - "Black Metal", - "Crossover", - "Contemporary Christian", - "Christian Rock", - "Merengue", - "Salsa", - "Thrash Metal", - "Anime", - "JPop", - "Synthpop" -}; - -static const guint sync_mask = 0xE0FF; -static const guint mpeg_ver_mask = 0x1800; -static const guint mpeg_layer_mask = 0x600; -static const guint bitrate_mask = 0xF00000; -static const guint freq_mask = 0xC0000; -static const guint ch_mask = 0xC0000000; -static const guint pad_mask = 0x20000; - -static gint bitrate_table[16][6] = { - { 0, 0, 0, 0, 0, 0 }, - { 32, 32, 32, 32, 8, 8 }, - { 64, 48, 40, 48, 16, 16 }, - { 96, 56, 48, 56, 24, 24 }, - { 128, 64, 56, 64, 32, 32 }, - { 160, 80, 64, 80, 40, 40 }, - { 192, 96, 80, 96, 48, 48 }, - { 224, 112, 96, 112, 56, 56 }, - { 256, 128, 112, 128, 64, 64 }, - { 288, 160, 128, 144, 80, 80 }, - { 320, 192, 160, 160, 96, 96 }, - { 352, 224, 192, 176, 112, 112 }, - { 384, 256, 224, 192, 128, 128 }, - { 416, 320, 256, 224, 144, 144 }, - { 448, 384, 320, 256, 160, 160 }, - { -1, -1, -1, -1, -1, -1 } -}; - -static gint freq_table[4][3] = { - { 44100, 22050, 11025 }, - { 48000, 24000, 12000 }, - { 32000, 16000, 8000 }, - { -1, -1, -1 } -}; - -static gint spf_table[6] = { - 48, 144, 144, 48, 144, 72 -}; - -#ifndef HAVE_STRNLEN - -size_t -strnlen (const char *str, size_t max) -{ - const char *end = memchr (str, 0, max); - return end ? (size_t)(end - str) : max; -} - -#endif /* HAVE_STRNLEN */ - -/* Helpers to get data from BE */ -inline static guint32 -extract_uint32 (gconstpointer data) -{ - const guint32 *ptr = data; - return GUINT32_FROM_BE (*ptr); -} - -inline static guint16 -extract_uint16 (gconstpointer data) -{ - const guint16 *ptr = data; - return GUINT16_FROM_BE (*ptr); -} - -inline static guint32 -extract_uint32_7bit (gconstpointer data) -{ - const guchar *ptr = data; -#if (G_BYTE_ORDER == G_LITTLE_ENDIAN) - return (((ptr[0] & 0x7F) << 21) | - ((ptr[1] & 0x7F) << 14) | - ((ptr[2] & 0x7F) << 7) | - ((ptr[3] & 0x7F) << 0)); -#elif (G_BYTE_ORDER == G_BIG_ENDIAN) - return (((ptr[0] & 0x7F) << 0) | - ((ptr[1] & 0x7F) << 7) | - ((ptr[2] & 0x7F) << 14) | - ((ptr[3] & 0x7F) << 21)); -#else - g_warning ("Can't figure endianness"); - return 0; -#endif -} - -/* id3v20 is odd... */ -inline static guint32 -extract_uint32_3byte (gconstpointer data) -{ - const guchar *ptr = data; -#if (G_BYTE_ORDER == G_LITTLE_ENDIAN) - return ((ptr[0] << 16) | - (ptr[1] << 8) | - (ptr[2] << 0)); -#elif (G_BYTE_ORDER == G_BIG_ENDIAN) - return ((ptr[0] << 0) | - (ptr[1] << 8) | - (ptr[2] << 16)); -#else - g_warning ("Can't figure endianness"); - return 0; -#endif -} - -static void -id3tag_free (id3tag *tags) -{ - g_free (tags->title); - g_free (tags->artist); - g_free (tags->album); - g_free (tags->recording_time); - g_free (tags->comment); - g_free (tags->genre); - g_free (tags->encoding); -} - -static void -id3v2tag_free (id3v2tag *tags) -{ - g_free (tags->album); - g_free (tags->comment); - g_free (tags->content_type); - g_free (tags->copyright); - g_free (tags->performer1); - g_free (tags->performer2); - g_free (tags->composer); - g_free (tags->publisher); - g_free (tags->recording_time); - g_free (tags->release_time); - g_free (tags->encoded_by); - g_free (tags->text); - g_free (tags->toly); - g_free (tags->title1); - g_free (tags->title2); - g_free (tags->title3); -} - -static gboolean -guess_dlna_profile (gint bitrate, - gint frequency, - gint mpeg_version, - gint layer_version, - gint n_channels, - const gchar **dlna_profile, - const gchar **dlna_mimetype) -{ - if (mpeg_version == MPEG_V1 && - layer_version == LAYER_3 && - (bitrate >= 32000 && bitrate <= 320000) && - (n_channels == 1 || n_channels == 2) && - (frequency == freq_table[0][0] || - frequency == freq_table[1][0] || - frequency == freq_table[2][0])) { - *dlna_profile = "MP3"; - *dlna_mimetype = "audio/mpeg"; - return TRUE; - } - - if ((bitrate >= 8000 && bitrate <= 320000) && - (mpeg_version == MPEG_V1 || mpeg_version == MPEG_V2) && - (frequency == freq_table[0][0] || frequency == freq_table[0][1] || - frequency == freq_table[1][0] || frequency == freq_table[1][1] || - frequency == freq_table[2][0] || frequency == freq_table[2][1])) { - *dlna_profile = "MP3X"; - *dlna_mimetype = "audio/mpeg"; - return TRUE; - } - - return FALSE; -} - -static char * -read_id3v1_buffer (int fd, - goffset size) -{ - char *buffer; - guint bytes_read; - guint rc; - - if (size < 128) { - return NULL; - } - - if (lseek (fd, size - ID3V1_SIZE, SEEK_SET) < 0) { - return NULL; - } - - buffer = g_malloc (ID3V1_SIZE); - - if (!buffer) { - return NULL; - } - - bytes_read = 0; - - while (bytes_read < ID3V1_SIZE) { - rc = read (fd, - buffer + bytes_read, - ID3V1_SIZE - bytes_read); - if (rc == -1) { - if (errno != EINTR) { - g_free (buffer); - return NULL; - } - } else if (rc == 0) { - break; - } else { - bytes_read += rc; - } - } - - return buffer; -} - -/* Convert from UCS-2 to UTF-8 checking the BOM.*/ -static gchar * -ucs2_to_utf8(const gchar *data, guint len) -{ - const gchar *encoding = NULL; - guint16 c; - gboolean be; - gchar *utf8 = NULL; - - memcpy (&c, data, 2); - - switch (c) { - case 0xfeff: - case 0xfffe: - be = (G_BYTE_ORDER == G_BIG_ENDIAN); - be = (c == 0xfeff) ? be : !be; - encoding = be ? "UCS-2BE" : "UCS-2LE"; - data += 2; - len -= 2; - break; - default: - encoding = "UCS-2"; - break; - } - - utf8 = g_convert (data, len, "UTF-8", encoding, NULL, NULL, NULL); - - return utf8; -} - -/* Get the genre codes from regular expressions */ -static gboolean -get_genre_number (const char *str, guint *genre) -{ - static GRegex *regex1 = NULL; - static GRegex *regex2 = NULL; - GMatchInfo *info = NULL; - gchar *result = NULL; - - if (!regex1) { - regex1 = g_regex_new ("\\(([0-9]+)\\)", 0, 0, NULL); - } - - if (!regex2) { - regex2 = g_regex_new ("([0-9]+)\\z", 0, 0, NULL); - } - - if (g_regex_match (regex1, str, 0, &info)) { - result = g_match_info_fetch (info, 1); - if (result) { - *genre = atoi (result); - g_free (result); - g_match_info_free (info); - return TRUE; - } - } - - g_match_info_free (info); - - if (g_regex_match (regex2, str, 0, &info)) { - result = g_match_info_fetch (info, 1); - if (result) { - *genre = atoi (result); - g_free (result); - g_match_info_free (info); - return TRUE; - } - } - - g_match_info_free (info); - - return FALSE; -} - -static const gchar * -get_genre_name (guint number) -{ - if (number >= G_N_ELEMENTS (genre_names)) { - return NULL; - } - - return genre_names[number]; -} - -static void -un_unsync (const unsigned char *source, - size_t size, - unsigned char **destination, - size_t *dest_size) -{ - size_t offset; - gchar *dest; - size_t new_size; - - offset = 0; - *destination = g_malloc0 (size); - dest = *destination; - new_size = size; - - while (offset < size) { - *dest = source[offset]; - - if ((source[offset] == 0xFF) && - (source[offset + 1] == 0x00)) { - offset++; - new_size--; - } - dest++; - offset++; - } - - *dest_size = new_size; -} - -static gchar * -get_encoding (const gchar *data, - gsize size, - gboolean *encoding_found) -{ - gdouble confidence = 1; - gchar *encoding; - - /* Try to guess encoding */ - encoding = (data && size ? - tracker_encoding_guess (data, size, &confidence) : - NULL); - - if (confidence < 0.5) { - /* Confidence on the results was too low, bail out and - * fallback to the default ISO-8859-1/Windows-1252 encoding. - */ - g_free (encoding); - encoding = NULL; - } - - /* Notify if a proper detection was done */ - if (encoding_found) { - *encoding_found = (encoding ? TRUE : FALSE);; - } - - /* If no proper detection was done, return default */ - if (!encoding) { - /* Use Windows-1252 instead of ISO-8859-1 as the former is a - superset in terms of printable characters and some - applications use it to encode characters in ID3 tags */ - encoding = g_strdup ("Windows-1252"); - } - - return encoding; -} - -static gchar * -convert_to_encoding (const gchar *str, - gssize len, - const gchar *to_codeset, - const gchar *from_codeset, - gsize *bytes_read, - gsize *bytes_written, - GError **error_out) -{ - GError *error = NULL; - gchar *word; - - /* g_print ("%s for %s\n", from_codeset, str); */ - - word = g_convert (str, - len, - to_codeset, - from_codeset, - bytes_read, - bytes_written, - &error); - - if (error) { - gchar *encoding; - - encoding = get_encoding (str, len, NULL); - g_free (word); - - word = g_convert (str, - len, - to_codeset, - encoding, - bytes_read, - bytes_written, - error_out); - - g_free (encoding); - g_error_free (error); - } - - return word; -} - -static gboolean -get_id3 (const gchar *data, - size_t size, - id3tag *id3) -{ - gchar *encoding, *year; - const gchar *pos; - - if (!data) { - return FALSE; - } - - if (size < 128) { - return FALSE; - } - - pos = &data[size - 128]; - - if (strncmp ("TAG", pos, 3) != 0) { - return FALSE; - } - - /* Now convert all the data separately */ - pos += 3; - - /* We don't use our magic convert_to_encoding here because we - * have a better way to collect a bit more data before we let - * enca loose on it for v1. - */ - if (tracker_encoding_can_guess ()) { - GString *s; - gboolean encoding_was_found; - - /* Get the encoding for ALL the data we are extracting here */ - /* This wont work with encodings where a NUL byte may be actually valid, - * like UTF-16 */ - s = g_string_new_len (pos, strnlen (pos, 30)); - g_string_append_len (s, pos + 30, strnlen (pos+30, 30)); - g_string_append_len (s, pos + 60, strnlen (pos+60, 30)); - g_string_append_len (s, pos + 94, strnlen (pos+94, ((pos+94)[28] != 0) ? 30 : 28)); - - encoding = get_encoding (s->str, s->len, &encoding_was_found); - - if (encoding_was_found) { - id3->encoding = g_strdup (encoding); - } - - g_string_free (s, TRUE); - } else { - /* If we cannot guess encoding, don't even try it, just - * use the default one */ - encoding = get_encoding (NULL, 0, NULL); - } - - id3->title = g_convert (pos, 30, "UTF-8", encoding, NULL, NULL, NULL); - - pos += 30; - id3->artist = g_convert (pos, 30, "UTF-8", encoding, NULL, NULL, NULL); - - pos += 30; - id3->album = g_convert (pos, 30, "UTF-8", encoding, NULL, NULL, NULL); - - pos += 30; - year = g_convert (pos, 4, "UTF-8", encoding, NULL, NULL, NULL); - if (year && atoi (year) > 0) { - id3->recording_time = tracker_date_guess (year); - } - g_free (year); - - pos += 4; - - if (pos[28] != 0) { - id3->comment = g_convert (pos, 30, "UTF-8", encoding, NULL, NULL, NULL); - id3->track_number = 0; - } else { - gchar buf[5]; - - id3->comment = g_convert (pos, 28, "UTF-8", encoding, NULL, NULL, NULL); - - snprintf (buf, 5, "%d", pos[29]); - id3->track_number = atoi (buf); - } - - pos += 30; - id3->genre = g_strdup (get_genre_name ((guint) pos[0])); - - if (!id3->genre) { - id3->genre = g_strdup (""); - } - - g_free (encoding); - - return TRUE; -} - -/* - * For the MP3 frame header description, see - * http://www.mp3-tech.org/programmer/frame_header.html - */ -static gboolean -mp3_parse_header (const gchar *data, - size_t size, - size_t seek_pos, - const gchar *uri, - TrackerResource *resource, - MP3Data *filedata) -{ - const gchar *dlna_profile, *dlna_mimetype; - guint header; - gchar mpeg_ver = 0; - gchar layer_ver = 0; - gint spfp8 = 0; - guint padsize = 0; - gint idx_num = 0; - gint bitrate = 0; - guint avg_bps = 0; - gint vbr_flag = 0; - guint length = 0; - gint sample_rate = 0; - guint frame_size; - guint frames = 0; - size_t pos = 0; - gint n_channels; - - pos = seek_pos; - - memcpy (&header, &data[pos], sizeof (header)); - - switch (header & mpeg_ver_mask) { - case 0x1000: - mpeg_ver = MPEG_V2; - break; - case 0x1800: - mpeg_ver = MPEG_V1; - break; - case 0: - mpeg_ver = MPEG_V25; - break; - default: - /* unknown version */ - return FALSE; - } - - switch (header & mpeg_layer_mask) { - case 0x400: - layer_ver = LAYER_2; - padsize = 1; - break; - case 0x200: - layer_ver = LAYER_3; - padsize = 1; - break; - case 0x600: - layer_ver = LAYER_1; - padsize = 4; - break; - default: - /* unknown layer */ - return FALSE; - } - - if (mpeg_ver < 3) { - idx_num = (mpeg_ver - 1) * 3 + layer_ver - 1; - } else { - idx_num = 2 + layer_ver; - } - - spfp8 = spf_table[idx_num]; - - /* We assume mpeg version, layer and channels are constant in frames */ - do { - frames++; - - bitrate = 1000 * bitrate_table[(header & bitrate_mask) >> 20][idx_num]; - - /* Skip frame headers with bitrate index '0000' (free) or '1111' (bad) */ - if (bitrate <= 0) { - frames--; - return FALSE; - } - - sample_rate = freq_table[(header & freq_mask) >> 18][mpeg_ver - 1]; - - /* Skip frame headers with frequency index '11' (reserved) */ - if (sample_rate <= 0) { - frames--; - return FALSE; - } - - frame_size = spfp8 * bitrate / sample_rate + padsize*((header & pad_mask) >> 17); - avg_bps += bitrate / 1000; - - pos += frame_size; - - if (frames > MAX_FRAMES_SCAN) { - /* Optimization */ - break; - } - - if (avg_bps / frames != bitrate / 1000) { - vbr_flag = 1; - } - - if (pos + sizeof (header) > size) { - /* EOF */ - break; - } - - if ((!vbr_flag) && (frames > VBR_THRESHOLD)) { - break; - } - - memcpy(&header, &data[pos], sizeof (header)); - } while ((header & sync_mask) == sync_mask); - - /* At least 2 frames to check the right position */ - if (frames < 2) { - /* No valid frames */ - return FALSE; - } - - tracker_resource_set_string (resource, "nfo:codec", "MPEG"); - - n_channels = ((header & ch_mask) == ch_mask) ? 1 : 2; - - tracker_resource_set_int (resource, "nfo:channels", n_channels); - - avg_bps /= frames; - - if ((!vbr_flag && frames > VBR_THRESHOLD) || (frames > MAX_FRAMES_SCAN)) { - /* If not all frames scanned - * Note that bitrate is always > 0, checked before */ - length = (filedata->size - filedata->id3v2_size) / (avg_bps ? avg_bps : bitrate) / 125; - } else { - /* Note that sample_rate is always > 0, checked before */ - length = spfp8 * 8 * frames / sample_rate; - } - - tracker_resource_set_int64 (resource, "nfo:duration", length); - tracker_resource_set_int64 (resource, "nfo:sampleRate", sample_rate); - tracker_resource_set_int64 (resource, "nfo:averageBitrate", avg_bps*1000); - - if (guess_dlna_profile (bitrate, sample_rate, - mpeg_ver, layer_ver, n_channels, - &dlna_profile, &dlna_mimetype)) { - tracker_resource_set_string (resource, "nmm:dlnaProfile", dlna_profile); - tracker_resource_set_string (resource, "nmm:dlnaMime", dlna_mimetype); - } - - return TRUE; -} - -static gboolean -mp3_parse (const gchar *data, - size_t size, - size_t offset, - const gchar *uri, - TrackerResource *resource, - MP3Data *filedata) -{ - guint header; - guint counter = 0; - guint pos = offset; - - do { - /* Seek for frame start */ - if (pos + sizeof (header) > size) { - return FALSE; - } - - memcpy (&header, &data[pos], sizeof (header)); - - if ((header & sync_mask) == sync_mask) { - /* Found header sync */ - if (mp3_parse_header (data, size, pos, uri, resource, filedata)) { - return TRUE; - } - } - - pos++; - counter++; - } while (counter < MAX_MP3_SCAN_DEEP); - - return FALSE; -} - -static gssize -id3v2_nul_size (const gchar encoding) -{ - switch (encoding) { - case 0x01: - case 0x02: - /* UTF-16, string terminated by two NUL bytes */ - return 2; - default: - return 1; - } -} - -static gssize -id3v2_strlen (const gchar encoding, - const gchar *text, - gssize len) -{ - const gchar *pos; - - switch (encoding) { - case 0x01: - case 0x02: - - /* UTF-16, string terminated by two NUL bytes */ - pos = memmem (text, len, "\0\0\0", 3); - - if (pos == NULL) { - pos = memmem (text, len, "\0\0", 2); - } else { - pos++; - } - - if (pos != NULL) { - return pos - text; - } else { - return len; - } - default: - return strnlen (text, len); - } -} - -static gchar * -id3v24_text_to_utf8 (const gchar encoding, - const gchar *text, - gssize len, - id3tag *info) -{ - /* This byte describes the encoding - * try to convert strings to UTF-8 - * if it fails, then forget it. - * For UTF-16 if size odd assume invalid 00 term. - */ - - switch (encoding) { - case 0x00: - /* Use Windows-1252 instead of ISO-8859-1 as the former is a - superset in terms of printable characters and some - applications use it to encode characters in ID3 tags */ - return convert_to_encoding (text, - len, - "UTF-8", - info->encoding ? info->encoding : "Windows-1252", - NULL, NULL, NULL); - case 0x01 : - return convert_to_encoding (text, - len - len%2, - "UTF-8", - "UTF-16", - NULL, NULL, NULL); - case 0x02 : - return convert_to_encoding (text, - len - len%2, - "UTF-8", - "UTF-16BE", - NULL, NULL, NULL); - case 0x03 : - return strndup (text, len); - - default: - /* Bad encoding byte, - * try to convert from - * Windows-1252 - */ - return convert_to_encoding (text, - len, - "UTF-8", - info->encoding ? info->encoding : "Windows-1252", - NULL, NULL, NULL); - } -} - -static gchar * -id3v2_text_to_utf8 (const gchar encoding, - const gchar *text, - gssize len, - id3tag *info) -{ - /* This byte describes the encoding - * try to convert strings to UTF-8 - * if it fails, then forget it - * For UCS2 if size odd assume invalid 00 term. - */ - - switch (encoding) { - case 0x00: - /* Use Windows-1252 instead of ISO-8859-1 as the former is a - superset in terms of printable characters and some - applications use it to encode characters in ID3 tags */ - return convert_to_encoding (text, - len, - "UTF-8", - info->encoding ? info->encoding : "Windows-1252", - NULL, NULL, NULL); - case 0x01 : - /* return g_convert (text, */ - /* len, */ - /* "UTF-8", */ - /* "UCS-2", */ - /* NULL, NULL, NULL); */ - return ucs2_to_utf8 (text, len - len%2); - - default: - /* Bad encoding byte, - * try to convert from - * Windows-1252 - */ - return convert_to_encoding (text, - len, - "UTF-8", - info->encoding ? info->encoding : "Windows-1252", - NULL, NULL, NULL); - } -} - -static id3v24frame -id3v24_get_frame (const gchar *name) -{ - gint l, r, m; - - /* use binary search */ - - l = 0; - r = G_N_ELEMENTS (id3v24_frames) - 1; - m = 0; - - do { - m = (l + r) / 2; - if (strncmp (name, id3v24_frames[m].name, 4) < 0) { - /* left half */ - r = m - 1; - } else { - /* right half */ - l = m + 1; - } - } while (l <= r && strncmp (id3v24_frames[m].name, name, 4) != 0); - - if (strncmp (id3v24_frames[m].name, name, 4) == 0) { - return id3v24_frames[m].frame; - } else { - return ID3V24_UNKNOWN; - } -} - -static id3v2frame -id3v2_get_frame (const gchar *name) -{ - gint l, r, m; - - /* use binary search */ - - l = 0; - r = G_N_ELEMENTS (id3v2_frames) - 1; - m = 0; - - do { - m = (l + r) / 2; - if (strncmp (name, id3v2_frames[m].name, 3) < 0) { - /* left half */ - r = m - 1; - } else { - /* right half */ - l = m + 1; - } - } while (l <= r && strncmp (id3v2_frames[m].name, name, 3) != 0); - - if (strncmp (id3v2_frames[m].name, name, 3) == 0) { - return id3v2_frames[m].frame; - } else { - return ID3V2_UNKNOWN; - } -} - -static void -get_id3v24_tags (id3v24frame frame, - const gchar *data, - size_t csize, - id3tag *info, - const gchar *uri, - TrackerResource *resource, - MP3Data *filedata) -{ - id3v2tag *tag = &filedata->id3v24; - guint pos = 0; - - switch (frame) { - case ID3V24_APIC: { - /* embedded image */ - gchar text_type; - const gchar *mime; - gchar pic_type; - const gchar *desc; - guint offset; - gint mime_len; - - text_type = data[pos + 0]; - mime = &data[pos + 1]; - mime_len = strnlen (mime, csize - 1); - pic_type = data[pos + 1 + mime_len + 1]; - desc = &data[pos + 1 + mime_len + 1 + 1]; - - if (pic_type == 3 || (pic_type == 0 && filedata->media_art_size == 0)) { - offset = pos + 1 + mime_len + 2; - offset += id3v2_strlen (text_type, desc, csize - offset) + id3v2_nul_size (text_type); - - filedata->media_art_data = &data[offset]; - filedata->media_art_size = csize - offset; - filedata->media_art_mime = mime; - } - break; - } - - case ID3V24_COMM: { - gchar *word; - gchar text_encode; - const gchar *text_desc; - const gchar *text; - guint offset; - gint text_desc_len; - - text_encode = data[pos + 0]; /* $xx */ - text_desc = &data[pos + 4]; /* <text string according to encoding> $00 (00) */ - text_desc_len = id3v2_strlen (text_encode, text_desc, csize - 4); - - offset = 4 + text_desc_len + id3v2_nul_size (text_encode); - text = &data[pos + offset]; /* <full text string according to encoding> */ - - if (offset >= csize) - break; - - word = id3v24_text_to_utf8 (text_encode, text, csize - offset, info); - - if (!tracker_is_empty_string (word)) { - g_strstrip (word); - g_free (tag->comment); - tag->comment = word; - } else { - g_free (word); - } - break; - } - - default: { - gchar *word; - - /* text frames */ - word = id3v24_text_to_utf8 (data[pos], &data[pos + 1], csize - 1, info); - if (!tracker_is_empty_string (word)) { - g_strstrip (word); - } else { - /* Can't do anything without word. */ - g_free (word); - break; - } - -#ifdef FRAME_ENABLE_TRACE - g_debug ("ID3v2.4: Frame is %d, word is %s", frame, word); -#endif /* FRAME_ENABLE_TRACE */ - - switch (frame) { - case ID3V24_TALB: - tag->album = word; - break; - case ID3V24_TCON: { - gint genre; - - if (get_genre_number (word, &genre)) { - g_free (word); - word = g_strdup (get_genre_name (genre)); - } - if (word && strcasecmp (word, "unknown") != 0) { - tag->content_type = word; - } else { - g_free (word); - } - break; - } - case ID3V24_TCOP: - tag->copyright = word; - break; - case ID3V24_TDRC: - tag->recording_time = tracker_date_guess (word); - g_free (word); - break; - case ID3V24_TDRL: - tag->release_time = tracker_date_guess (word); - g_free (word); - break; - case ID3V24_TENC: - tag->encoded_by = word; - break; - case ID3V24_TEXT: - tag->text = word; - break; - case ID3V24_TOLY: - tag->toly = word; - break; - case ID3V24_TCOM: - tag->composer = word; - break; - case ID3V24_TIT1: - tag->title1 = word; - break; - case ID3V24_TIT2: - tag->title2 = word; - break; - case ID3V24_TIT3: - tag->title3 = word; - break; - case ID3V24_TLEN: - tag->length = atoi (word) / 1000; - g_free (word); - break; - case ID3V24_TPE1: - tag->performer1 = word; - break; - case ID3V24_TPE2: - tag->performer2 = word; - break; - case ID3V24_TPUB: - tag->publisher = word; - break; - case ID3V24_TRCK: { - gchar **parts; - - parts = g_strsplit (word, "/", 2); - if (parts[0]) { - tag->track_number = atoi (parts[0]); - if (parts[1]) { - tag->track_count = atoi (parts[1]); - } - } - g_strfreev (parts); - g_free (word); - - break; - } - case ID3V24_TPOS: { - gchar **parts; - - parts = g_strsplit (word, "/", 2); - if (parts[0]) { - tag->set_number = atoi (parts[0]); - if (parts[1]) { - tag->set_count = atoi (parts[1]); - } - } - g_strfreev (parts); - g_free (word); - - break; - } - case ID3V24_TYER: - if (atoi (word) > 0) { - tag->recording_time = tracker_date_guess (word); - } - g_free (word); - break; - default: - g_free (word); - } - } - } -} - -static void -get_id3v23_tags (id3v24frame frame, - const gchar *data, - size_t csize, - id3tag *info, - const gchar *uri, - TrackerResource *resource, - MP3Data *filedata) -{ - id3v2tag *tag = &filedata->id3v23; - guint pos = 0; - - switch (frame) { - case ID3V24_APIC: { - /* embedded image */ - gchar text_type; - const gchar *mime; - gchar pic_type; - const gchar *desc; - guint offset; - gint mime_len; - - text_type = data[pos + 0]; - mime = &data[pos + 1]; - mime_len = strnlen (mime, csize - 1); - pic_type = data[pos + 1 + mime_len + 1]; - desc = &data[pos + 1 + mime_len + 1 + 1]; - - if (pic_type == 3 || (pic_type == 0 && filedata->media_art_size == 0)) { - offset = pos + 1 + mime_len + 2; - offset += id3v2_strlen (text_type, desc, csize - offset) + id3v2_nul_size (text_type); - - filedata->media_art_data = &data[offset]; - filedata->media_art_size = csize - offset; - filedata->media_art_mime = mime; - } - break; - } - - case ID3V24_COMM: { - gchar *word; - gchar text_encode; - const gchar *text_desc; - const gchar *text; - guint offset; - gint text_desc_len; - - text_encode = data[pos + 0]; /* $xx */ - text_desc = &data[pos + 4]; /* <text string according to encoding> $00 (00) */ - text_desc_len = id3v2_strlen (text_encode, text_desc, csize - 4); - - offset = 4 + text_desc_len + id3v2_nul_size (text_encode); - text = &data[pos + offset]; /* <full text string according to encoding> */ - - word = id3v2_text_to_utf8 (text_encode, text, csize - offset, info); - - if (!tracker_is_empty_string (word)) { - g_strstrip (word); - g_free (tag->comment); - tag->comment = word; - } else { - g_free (word); - } - - break; - } - - default: { - gchar *word; - - /* text frames */ - word = id3v2_text_to_utf8 (data[pos], &data[pos + 1], csize - 1, info); - - if (!tracker_is_empty_string (word)) { - g_strstrip (word); - } else { - /* Can't do anything without word. */ - g_free (word); - break; - } - - -#ifdef FRAME_ENABLE_TRACE - g_debug ("ID3v2.3: Frame is %d, word is %s", frame, word); -#endif /* FRAME_ENABLE_TRACE */ - - switch (frame) { - case ID3V24_TALB: - tag->album = word; - break; - case ID3V24_TCON: { - gint genre; - - if (get_genre_number (word, &genre)) { - g_free (word); - word = g_strdup (get_genre_name (genre)); - } - if (word && strcasecmp (word, "unknown") != 0) { - tag->content_type = word; - } else { - g_free (word); - } - break; - } - case ID3V24_TCOP: - tag->copyright = word; - break; - case ID3V24_TENC: - tag->encoded_by = word; - break; - case ID3V24_TEXT: - tag->text = word; - break; - case ID3V24_TOLY: - tag->toly = word; - break; - case ID3V24_TCOM: - tag->composer = word; - break; - case ID3V24_TIT1: - tag->title1 = word; - break; - case ID3V24_TIT2: - tag->title2 = word; - break; - case ID3V24_TIT3: - tag->title3 = word; - break; - case ID3V24_TLEN: - tag->length = atoi (word) / 1000; - g_free (word); - break; - case ID3V24_TPE1: - tag->performer1 = word; - break; - case ID3V24_TPE2: - tag->performer2 = word; - break; - case ID3V24_TPUB: - tag->publisher = word; - break; - case ID3V24_TRCK: { - gchar **parts; - - parts = g_strsplit (word, "/", 2); - if (parts[0]) { - tag->track_number = atoi (parts[0]); - if (parts[1]) { - tag->track_count = atoi (parts[1]); - } - } - g_strfreev (parts); - g_free (word); - - break; - } - case ID3V24_TPOS: { - gchar **parts; - - parts = g_strsplit (word, "/", 2); - if (parts[0]) { - tag->set_number = atoi (parts[0]); - if (parts[1]) { - tag->set_count = atoi (parts[1]); - } - } - g_strfreev (parts); - g_free (word); - - break; - } - case ID3V24_TYER: - if (atoi (word) > 0) { - tag->recording_time = tracker_date_guess (word); - } - g_free (word); - break; - default: - g_free (word); - } - } - } -} - -static void -get_id3v20_tags (id3v2frame frame, - const gchar *data, - size_t csize, - id3tag *info, - const gchar *uri, - TrackerResource *resource, - MP3Data *filedata) -{ - id3v2tag *tag = &filedata->id3v22; - guint pos = 0; - - if (frame == ID3V2_PIC) { - /* embedded image */ - gchar text_type; - gchar pic_type; - const gchar *desc; - guint offset; - const gchar *mime; - - text_type = data[pos + 0]; - mime = &data[pos + 1]; - pic_type = data[pos + 1 + 3]; - desc = &data[pos + 1 + 3 + 1]; - - if (pic_type == 3 || (pic_type == 0 && filedata->media_art_size == 0)) { - offset = pos + 1 + 3 + 1; - offset += id3v2_strlen (text_type, desc, csize - offset) + id3v2_nul_size (text_type); - - filedata->media_art_data = &data[offset]; - filedata->media_art_size = csize - offset; - filedata->media_art_mime = mime; - } - } else { - /* text frames */ - gchar *word; - - word = id3v2_text_to_utf8 (data[pos], &data[pos + 1], csize - 1, info); - if (!tracker_is_empty_string (word)) { - g_strstrip (word); - } else { - /* Can't do anything without word. */ - return; - } - -#ifdef FRAME_ENABLE_TRACE - g_debug ("ID3v2.2: Frame is %d, word is %s", frame, word); -#endif /* FRAME_ENABLE_TRACE */ - - switch (frame) { - case ID3V2_COM: - tag->comment = word; - break; - case ID3V2_TAL: - tag->album = word; - break; - case ID3V2_TCO: { - gint genre; - - if (get_genre_number (word, &genre)) { - g_free (word); - word = g_strdup (get_genre_name (genre)); - } - - if (word && strcasecmp (word, "unknown") != 0) { - tag->content_type = word; - } else { - g_free (word); - } - - break; - } - case ID3V2_TCR: - tag->copyright = word; - break; - case ID3V2_TEN: - tag->encoded_by = word; - break; - case ID3V2_TLE: - tag->length = atoi (word) / 1000; - g_free (word); - break; - case ID3V2_TPB: - tag->publisher = word; - break; - case ID3V2_TP1: - tag->performer1 = word; - break; - case ID3V2_TP2: - tag->performer2 = word; - break; - case ID3V2_TRK: { - gchar **parts; - - parts = g_strsplit (word, "/", 2); - if (parts[0]) { - tag->track_number = atoi (parts[0]); - if (parts[1]) { - tag->track_count = atoi (parts[1]); - } - } - g_strfreev (parts); - g_free (word); - - break; - } - case ID3V2_TT1: - tag->title1 = word; - break; - case ID3V2_TT2: - tag->title2 = word; - break; - case ID3V2_TT3: - tag->title3 = word; - break; - case ID3V2_TXT: - tag->text = word; - break; - case ID3V2_TYE: - if (atoi (word) > 0) { - tag->recording_time = tracker_date_guess (word); - } - g_free (word); - break; - default: - g_free (word); - } - } -} - -static void -parse_id3v24 (const gchar *data, - size_t size, - id3tag *info, - const gchar *uri, - TrackerResource *resource, - MP3Data *filedata, - size_t *offset_delta) -{ - const gint header_size = 10; - const gint frame_size = 10; - gint unsync; - gint ext_header; - gint experimental; - guint tsize; - guint pos; - guint ext_header_size; - - /* Check header, expecting (in hex), 10 bytes long: - * - * $ 49 44 33 yy yy xx zz zz zz zz - * - * Where yy is less than $FF, xx is the 'flags' byte and zz is - * less than $80. - * - * Here yy is the version, so v24 == 04 00. - * - * MP3's look like this: - * - * [Header][?External Header?][Tags][Content] - */ - if ((size < 16) || - (data[0] != 0x49) || - (data[1] != 0x44) || - (data[2] != 0x33) || - (data[3] != 0x04) || - (data[4] != 0x00)) { - /* It's not an error, we might try another function - * if we have the wrong version header here. - */ - return; - } - - /* Get the flags (xx) in the header */ - unsync = (data[5] & 0x80) > 0; - ext_header = (data[5] & 0x40) > 0; - experimental = (data[5] & 0x20) > 0; - - /* Get the complete tag size (zz) in the header: - * Tag size is size of the complete tag after - * unsychronisation, including padding, excluding the header - * but not excluding the extended header (total tag size - 10) - */ - tsize = extract_uint32_7bit (&data[6]); - - /* We don't handle experimental cases */ - if (experimental) { - g_message ("[v24] Experimental MP3s are not extracted, doing nothing"); - return; - } - - /* Check if we can read even the first frame, The complete - * tag size (tsize) does not include the header which is 10 - * bytes, so we check that there is some content AFTER the - * headers. */ - if (tsize + header_size > size) { - g_message ("[v24] Expected MP3 tag size and header size to be within file size boundaries"); - return; - } - - /* Start after the header (10 bytes long) */ - pos = header_size; - - /* Completely optional */ - if (ext_header) { - /* Extended header is expected to be: - * Extended header size $xx xx xx xx (4 chars) - * Extended Flags $xx xx - * Size of padding $xx xx xx xx - */ - ext_header_size = extract_uint32_7bit (&data[10]); - - /* Where the 'Extended header size', currently 6 or 10 - * bytes, excludes itself. The 'Size of padding' is - * simply the total tag size excluding the frames and - * the headers, in other words the padding. - */ - if (tsize + header_size + ext_header_size > size) { - g_message ("[v24] Expected MP3 tag size and extended header size to be within file size boundaries"); - return; - } - - pos += ext_header_size; - } - - while (pos < tsize + header_size) { - const char *frame_name; - id3v24frame frame; - size_t csize; - unsigned short flags; - - /* Frames are 10 bytes each and made up of: - * Frame ID $xx xx xx xx (4 chars) - * Size $xx xx xx xx - * Flags $xx xx - */ - if (pos + frame_size > tsize + header_size) { - g_message ("[v24] Expected MP3 frame size (%d) to be within tag size (%d) boundaries, position = %d", - frame_size, - tsize + header_size, - pos); - break; - } - - frame_name = &data[pos]; - - /* We found padding after all frames */ - if (frame_name[0] == '\0') - break; - - /* We found a IDv2 footer */ - if (frame_name[0] == '3' && - frame_name[1] == 'D' && - frame_name[2] == 'I') - break; - - frame = id3v24_get_frame (frame_name); - - csize = (size_t) extract_uint32_7bit (&data[pos + 4]); - - if (pos + frame_size + csize > size) { - g_debug ("[v24] Size of current frame '%s' (%" G_GSIZE_FORMAT ") " - "exceeds file boundaries (%" G_GSIZE_FORMAT "), " - "not processing any more frames", - frame_name, csize, size); - break; - } - - flags = extract_uint16 (&data[pos + 8]); - - pos += frame_size; - - if (frame == ID3V24_UNKNOWN) { - /* Ignore unknown frames */ - g_debug ("[v24] Ignoring unknown frame '%s' (pos:%d, size:%" G_GSIZE_FORMAT ")", frame_name, pos, csize); - pos += csize; - continue; - } else { - g_debug ("[v24] Processing frame '%s'", frame_name); - } - - /* If content size is more than size of file, stop. If - * If content size is 0 then continue to next frame. */ - if (pos + csize > tsize + header_size) { - g_debug ("[v24] Position (%d) + content size (%" G_GSIZE_FORMAT ") > tag size (%d), not processing any more frames", pos, csize, tsize + header_size); - break; - } else if (csize == 0) { - g_debug ("[v24] Content size was 0, moving to next frame"); - continue; - } - - /* Frame flags expected are in format of: - * - * %abc00000 %ijk00000 - * - * a - Tag alter preservation - * b - File alter preservation - * c - Read only - * i - Compression - * j - Encryption - * k - Grouping identity - */ - if (((flags & 0x80) > 0) || - ((flags & 0x40) > 0)) { - g_debug ("[v23] Ignoring frame '%s', frame flags 0x80 or 0x40 found (compression / encryption)", frame_name); - pos += csize; - continue; - } - - if ((flags & 0x20) > 0) { - /* The "group" identifier, skip a byte */ - pos++; - csize--; - } - - if ((flags & 0x02) || unsync) { - size_t unsync_size; - gchar *body; - - un_unsync (&data[pos], csize, (unsigned char **) &body, &unsync_size); - get_id3v24_tags (frame, body, unsync_size, info, uri, resource, filedata); - g_free (body); - } else { - get_id3v24_tags (frame, &data[pos], csize, info, uri, resource, filedata); - } - - pos += csize; - } - - *offset_delta = tsize + header_size; -} - -static void -parse_id3v23 (const gchar *data, - size_t size, - id3tag *info, - const gchar *uri, - TrackerResource *resource, - MP3Data *filedata, - size_t *offset_delta) -{ - const gint header_size = 10; - const gint frame_size = 10; - gint unsync; - gint ext_header; - gint experimental; - guint tsize; - guint pos; - guint ext_header_size; - - /* Check header, expecting (in hex), 10 bytes long: - * - * $ 49 44 33 yy yy xx zz zz zz zz - * - * Where yy is less than $FF, xx is the 'flags' byte and zz is - * less than $80. - * - * Here yy is the version, so v23 == 03 00. - * - * MP3's look like this: - * - * [Header][?External Header?][Tags][Content] - */ - if ((size < 16) || - (data[0] != 0x49) || - (data[1] != 0x44) || - (data[2] != 0x33) || - (data[3] != 0x03) || - (data[4] != 0x00)) { - /* It's not an error, we might try another function - * if we have the wrong version header here. - */ - return; - } - - /* Get the flags (xx) in the header */ - unsync = (data[5] & 0x80) > 0; - ext_header = (data[5] & 0x40) > 0; - experimental = (data[5] & 0x20) > 0; - - /* Get the complete tag size (zz) in the header: - * Tag size is size of the complete tag after - * unsychronisation, including padding, excluding the header - * but not excluding the extended header (total tag size - 10) - */ - tsize = extract_uint32_7bit (&data[6]); - - /* We don't handle experimental cases */ - if (experimental) { - g_message ("[v23] Experimental MP3s are not extracted, doing nothing"); - return; - } - - /* Check if we can read even the first frame, The complete - * tag size (tsize) does not include the header which is 10 - * bytes, so we check that there is some content AFTER the - * headers. */ - if (tsize + header_size > size) { - g_message ("[v23] Expected MP3 tag size and header size to be within file size boundaries"); - return; - } - - /* Start after the header (10 bytes long) */ - pos = header_size; - - /* Completely optional */ - if (ext_header) { - /* Extended header is expected to be: - * Extended header size $xx xx xx xx (4 chars) - * Extended Flags $xx xx - * Size of padding $xx xx xx xx - */ - ext_header_size = extract_uint32 (&data[10]); - - /* Where the 'Extended header size', currently 6 or 10 - * bytes, excludes itself. The 'Size of padding' is - * simply the total tag size excluding the frames and - * the headers, in other words the padding. - */ - if (tsize + header_size + ext_header_size > size) { - g_message ("[v23] Expected MP3 tag size and extended header size to be within file size boundaries"); - return; - } - - pos += ext_header_size; - } - - while (pos < tsize + header_size) { - const char *frame_name; - id3v24frame frame; - size_t csize; - unsigned short flags; - - /* Frames are 10 bytes each and made up of: - * Frame ID $xx xx xx xx (4 chars) - * Size $xx xx xx xx - * Flags $xx xx - */ - if (pos + frame_size > tsize + header_size) { - g_message ("[v23] Expected MP3 frame size (%d) to be within tag size (%d) boundaries, position = %d", - frame_size, - tsize + header_size, - pos); - break; - } - - frame_name = &data[pos]; - - /* We found padding after all frames */ - if (frame_name[0] == '\0') - break; - - frame = id3v24_get_frame (frame_name); - - csize = (size_t) extract_uint32 (&data[pos + 4]); - - if (pos + frame_size + csize > size) { - g_debug ("[v23] Size of current frame '%s' (%" G_GSIZE_FORMAT ") " - "exceeds file boundaries (%" G_GSIZE_FORMAT "), " - "not processing any more frames", - frame_name, csize, size); - break; - } - - flags = extract_uint16 (&data[pos + 8]); - - pos += frame_size; - - if (frame == ID3V24_UNKNOWN) { - /* Ignore unknown frames */ - g_debug ("[v23] Ignoring unknown frame '%s' (pos:%d, size:%" G_GSIZE_FORMAT ")", frame_name, pos, csize); - pos += csize; - continue; - } else { - g_debug ("[v23] Processing frame '%s'", frame_name); - } - - /* If content size is more than size of file, stop. If - * If content size is 0 then continue to next frame. */ - if (pos + csize > tsize + header_size) { - g_debug ("[v23] Position (%d) + content size (%" G_GSIZE_FORMAT ") > tag size (%d), not processing any more frames", pos, csize, tsize + header_size); - break; - } else if (csize == 0) { - g_debug ("[v23] Content size was 0, moving to next frame"); - } - - /* Frame flags expected are in format of: - * - * %abc00000 %ijk00000 - * - * a - Tag alter preservation - * b - File alter preservation - * c - Read only - * i - Compression - * j - Encryption - * k - Grouping identity - */ - if (((flags & 0x80) > 0) || - ((flags & 0x40) > 0)) { - g_debug ("[v23] Ignoring frame '%s', frame flags 0x80 or 0x40 found (compression / encryption)", frame_name); - pos += csize; - continue; - } - - if ((flags & 0x20) > 0) { - /* The "group" identifier, skip a byte */ - pos++; - csize--; - } - - if ((flags & 0x02) || unsync) { - size_t unsync_size; - gchar *body; - - un_unsync (&data[pos], csize, (unsigned char **) &body, &unsync_size); - get_id3v23_tags (frame, body, unsync_size, info, uri, resource, filedata); - g_free (body); - } else { - get_id3v23_tags (frame, &data[pos], csize, info, uri, resource, filedata); - } - - pos += csize; - } - - *offset_delta = tsize + header_size; -} - -static void -parse_id3v20 (const gchar *data, - size_t size, - id3tag *info, - const gchar *uri, - TrackerResource *resource, - MP3Data *filedata, - size_t *offset_delta) -{ - const gint header_size = 10; - const gint frame_size = 6; - gint unsync; - guint tsize; - guint pos; - - if ((size < header_size + frame_size) || - (data[0] != 0x49) || - (data[1] != 0x44) || - (data[2] != 0x33) || - (data[3] != 0x02) || - (data[4] != 0x00)) { - /* It's not an error, we might try another function - * if we have the wrong version header here. - */ - return; - } - - unsync = (data[5] & 0x80) > 0; - tsize = extract_uint32_7bit (&data[6]); - - if (tsize > size - header_size) { - g_message ("[v20] Expected MP3 tag size and header size to be within file size boundaries"); - return; - } - - pos = header_size; - - while (pos < tsize + header_size) { - const char *frame_name; - id3v2frame frame; - size_t csize; - - if (pos + frame_size > tsize + header_size) { - g_message ("[v20] Expected MP3 frame size (%d) to be within tag size (%d) boundaries, position = %d", - frame_size, - tsize + header_size, - pos); - break; - } - - frame_name = &data[pos]; - - /* We found padding after all frames */ - if (frame_name[0] == '\0') - break; - - frame = id3v2_get_frame (frame_name); - - csize = (size_t) extract_uint32_3byte (&data[pos + 3]); - - if (csize > size - pos - frame_size) { - g_debug ("[v20] Size of current frame '%s' (%" G_GSIZE_FORMAT ") " - "exceeds file boundaries (%" G_GSIZE_FORMAT "), " - "not processing any more frames", - frame_name, csize, size); - break; - } - - pos += frame_size; - - if (frame == ID3V2_UNKNOWN) { - /* ignore unknown frames */ - g_debug ("[v20] Ignoring unknown frame '%s' (pos:%d, size:%" G_GSIZE_FORMAT ")", frame_name, pos, csize); - pos += csize; - continue; - } - - /* If content size is more than size of file, stop. If - * If content size is 0 then continue to next frame. */ - if (pos + csize > tsize + header_size) { - g_debug ("[v20] Position (%d) + content size (%" G_GSIZE_FORMAT ") > tag size (%d), not processing any more frames", pos, csize, tsize + header_size); - break; - } else if (csize == 0) { - g_debug ("[v20] Content size was 0, moving to next frame"); - } - - /* Early versions do not have unsynch per frame */ - if (unsync) { - size_t unsync_size; - gchar *body; - - un_unsync (&data[pos], csize, (unsigned char **) &body, &unsync_size); - get_id3v20_tags (frame, body, unsync_size, info, uri, resource, filedata); - g_free (body); - } else { - get_id3v20_tags (frame, &data[pos], csize, info, uri, resource, filedata); - } - - pos += csize; - } - - *offset_delta = tsize + header_size; -} - -static goffset -parse_id3v2 (const gchar *data, - size_t size, - id3tag *info, - const gchar *uri, - TrackerResource *resource, - MP3Data *filedata) -{ - gboolean done = FALSE; - size_t offset = 0; - - do { - size_t offset_delta = 0; - parse_id3v24 (data + offset, size - offset, info, uri, resource, filedata, &offset_delta); - parse_id3v23 (data + offset, size - offset, info, uri, resource, filedata, &offset_delta); - parse_id3v20 (data + offset, size - offset, info, uri, resource, filedata, &offset_delta); - - if (offset_delta == 0) { - done = TRUE; - filedata->id3v2_size = offset; - } else { - offset += offset_delta; - } - - } while (!done); - - return offset; -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - gchar *filename, *uri; - int fd; - void *buffer; - void *id3v1_buffer; - goffset size; - goffset buffer_size; - goffset audio_offset; - MP3Data md = { 0 }; - GFile *file; - gboolean parsed; - TrackerResource *main_resource; - - file = tracker_extract_info_get_file (info); - filename = g_file_get_path (file); - - size = tracker_file_get_size (filename); - - if (size == 0) { - g_free (filename); - return FALSE; - } - - md.size = size; - buffer_size = MIN (size, MAX_FILE_READ); - - fd = tracker_file_open_fd (filename); - - if (fd == -1) { - return FALSE; - } - -#ifndef G_OS_WIN32 - /* We don't use GLib's mmap because size can not be specified */ - buffer = mmap (NULL, - buffer_size, - PROT_READ, - MAP_PRIVATE, - fd, - 0); -#endif - - id3v1_buffer = read_id3v1_buffer (fd, size); - -#ifdef HAVE_POSIX_FADVISE - if (posix_fadvise (fd, 0, 0, POSIX_FADV_DONTNEED) != 0) - g_warning ("posix_fadvise() call failed: %m"); -#endif /* HAVE_POSIX_FADVISE */ - - close (fd); - - if (buffer == NULL || buffer == (void*) -1) { - g_free (filename); - return FALSE; - } - - if (!get_id3 (id3v1_buffer, ID3V1_SIZE, &md.id3v1)) { - /* Do nothing? */ - } - - g_free (id3v1_buffer); - - main_resource = tracker_resource_new (NULL); - - /* Get other embedded tags */ - uri = g_file_get_uri (file); - audio_offset = parse_id3v2 (buffer, buffer_size, &md.id3v1, uri, main_resource, &md); - - md.title = tracker_coalesce_strip (4, md.id3v24.title2, - md.id3v23.title2, - md.id3v22.title2, - md.id3v1.title); - - md.lyricist_name = tracker_coalesce_strip (4, md.id3v24.text, - md.id3v23.toly, - md.id3v23.text, - md.id3v22.text); - - md.composer_name = tracker_coalesce_strip (3, md.id3v24.composer, - md.id3v23.composer, - md.id3v22.composer); - - md.performer_name = tracker_coalesce_strip (4, md.id3v24.performer1, - md.id3v23.performer1, - md.id3v22.performer1, - md.id3v1.artist); - - md.album_artist_name = tracker_coalesce_strip (3, md.id3v24.performer2, - md.id3v23.performer2, - md.id3v22.performer2); - - md.album_name = tracker_coalesce_strip (4, md.id3v24.album, - md.id3v23.album, - md.id3v22.album, - md.id3v1.album); - - md.genre = tracker_coalesce_strip (7, md.id3v24.content_type, - md.id3v24.title1, - md.id3v23.content_type, - md.id3v23.title1, - md.id3v22.content_type, - md.id3v22.title1, - md.id3v1.genre); - - md.recording_time = tracker_coalesce_strip (7, md.id3v24.recording_time, - md.id3v24.release_time, - md.id3v23.recording_time, - md.id3v23.release_time, - md.id3v22.recording_time, - md.id3v22.release_time, - md.id3v1.recording_time); - - md.publisher = tracker_coalesce_strip (3, md.id3v24.publisher, - md.id3v23.publisher, - md.id3v22.publisher); - - md.copyright = tracker_coalesce_strip (3, md.id3v24.copyright, - md.id3v23.copyright, - md.id3v22.copyright); - - md.comment = tracker_coalesce_strip (7, md.id3v24.title3, - md.id3v24.comment, - md.id3v23.title3, - md.id3v23.comment, - md.id3v22.title3, - md.id3v22.comment, - md.id3v1.comment); - - md.encoded_by = tracker_coalesce_strip (3, md.id3v24.encoded_by, - md.id3v23.encoded_by, - md.id3v22.encoded_by); - - if (md.id3v24.track_number != 0) { - md.track_number = md.id3v24.track_number; - } else if (md.id3v23.track_number != 0) { - md.track_number = md.id3v23.track_number; - } else if (md.id3v22.track_number != 0) { - md.track_number = md.id3v22.track_number; - } else if (md.id3v1.track_number != 0) { - md.track_number = md.id3v1.track_number; - } - - if (md.id3v24.track_count != 0) { - md.track_count = md.id3v24.track_count; - } else if (md.id3v23.track_count != 0) { - md.track_count = md.id3v23.track_count; - } else if (md.id3v22.track_count != 0) { - md.track_count = md.id3v22.track_count; - } - - if (md.id3v24.set_number != 0) { - md.set_number = md.id3v24.set_number; - } else if (md.id3v23.set_number != 0) { - md.set_number = md.id3v23.set_number; - } else if (md.id3v22.set_number != 0) { - md.set_number = md.id3v22.set_number; - } - - if (md.id3v24.set_count != 0) { - md.set_count = md.id3v24.set_count; - } else if (md.id3v23.set_count != 0) { - md.set_count = md.id3v23.set_count; - } else if (md.id3v22.set_count != 0) { - md.set_count = md.id3v22.set_count; - } - - if (md.performer_name) { - md.performer = tracker_extract_new_artist (md.performer_name); - } - - if (md.composer_name) { - md.composer = tracker_extract_new_artist (md.composer_name); - } - - if (md.lyricist_name) { - md.lyricist = tracker_extract_new_artist (md.lyricist_name); - } - - if (md.album_name) { - TrackerResource *album_disc = NULL, *album_artist = NULL; - - if (md.album_artist_name) - album_artist = tracker_extract_new_artist (md.album_artist_name); - - album_disc = tracker_extract_new_music_album_disc (md.album_name, - album_artist, - md.set_number > 0 ? md.set_number : 1, - md.recording_time); - - md.album = tracker_resource_get_first_relation (album_disc, "nmm:albumDiscAlbum"); - - tracker_resource_set_relation (main_resource, "nmm:musicAlbum", md.album); - tracker_resource_set_relation (main_resource, "nmm:musicAlbumDisc", album_disc); - - if (md.track_count > 0) { - tracker_resource_set_int (md.album, "nmm:albumTrackCount", md.track_count); - } - - g_object_unref (album_disc); - g_clear_object (&album_artist); - } - - tracker_resource_add_uri (main_resource, "rdf:type", "nmm:MusicPiece"); - tracker_resource_add_uri (main_resource, "rdf:type", "nfo:Audio"); - - tracker_guarantee_resource_title_from_file (main_resource, - "nie:title", - md.title, - uri, - NULL); - - if (md.lyricist) { - tracker_resource_set_relation (main_resource, "nmm:lyricist", md.lyricist); - g_object_unref (md.lyricist); - } - - if (md.performer) { - tracker_resource_set_relation (main_resource, "nmm:performer", md.performer); - } - - if (md.composer) { - tracker_resource_set_relation (main_resource, "nmm:composer", md.composer); - g_object_unref (md.composer); - } - - if (md.album) { - tracker_resource_set_relation (main_resource, "nmm:musicAlbum", md.album); - } - - if (md.recording_time) { - tracker_resource_set_string (main_resource, "nie:contentCreated", md.recording_time); - } - - if (md.genre) { - tracker_resource_set_string (main_resource, "nfo:genre", md.genre); - } - - if (md.copyright) { - tracker_resource_set_string (main_resource, "nie:copyright", md.copyright); - } - - if (md.comment) { - tracker_resource_set_string (main_resource, "nie:comment", md.comment); - } - - if (md.publisher) { - TrackerResource *publisher = tracker_extract_new_contact (md.publisher); - tracker_resource_set_relation (main_resource, "nco:publisher", publisher); - g_object_unref(publisher); - } - - if (md.encoded_by) { - tracker_resource_set_string (main_resource, "nfo:encodedBy", md.encoded_by); - } - - if (md.track_number > 0) { - tracker_resource_set_int (main_resource, "nmm:trackNumber", md.track_number); - } - - /* Get mp3 stream info */ - parsed = mp3_parse (buffer, buffer_size, audio_offset, uri, main_resource, &md); - g_clear_object (&md.performer); - - id3v2tag_free (&md.id3v22); - id3v2tag_free (&md.id3v23); - id3v2tag_free (&md.id3v24); - id3tag_free (&md.id3v1); - -#ifndef G_OS_WIN32 - munmap (buffer, buffer_size); -#endif - - if (main_resource) { - tracker_extract_info_set_resource (info, main_resource); - g_object_unref (main_resource); - } - - g_free (filename); - g_free (uri); - - return parsed; -} diff --git a/src/tracker-extract/tracker-extract-msoffice-xml.c b/src/tracker-extract/tracker-extract-msoffice-xml.c deleted file mode 100644 index 1c6516c36..000000000 --- a/src/tracker-extract/tracker-extract-msoffice-xml.c +++ /dev/null @@ -1,900 +0,0 @@ -/* - * Copyright (C) 2008-2010 Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <string.h> - -#include <glib.h> - -#include <gsf/gsf.h> -#include <gsf/gsf-doc-meta-data.h> -#include <gsf/gsf-infile.h> -#include <gsf/gsf-infile-msole.h> -#include <gsf/gsf-input-stdio.h> -#include <gsf/gsf-msole-utils.h> -#include <gsf/gsf-utils.h> -#include <gsf/gsf-infile-zip.h> - -#include <libtracker-extract/tracker-extract.h> - -#include "tracker-main.h" -#include "tracker-gsf.h" - -typedef enum { - MS_OFFICE_XML_TAG_INVALID, - MS_OFFICE_XML_TAG_TITLE, - MS_OFFICE_XML_TAG_SUBJECT, - MS_OFFICE_XML_TAG_AUTHOR, - MS_OFFICE_XML_TAG_MODIFIED, - MS_OFFICE_XML_TAG_COMMENTS, - MS_OFFICE_XML_TAG_CREATED, - MS_OFFICE_XML_TAG_GENERATOR, - MS_OFFICE_XML_TAG_NUM_OF_PAGES, - MS_OFFICE_XML_TAG_NUM_OF_CHARACTERS, - MS_OFFICE_XML_TAG_NUM_OF_WORDS, - MS_OFFICE_XML_TAG_NUM_OF_LINES, - MS_OFFICE_XML_TAG_APPLICATION, - MS_OFFICE_XML_TAG_NUM_OF_PARAGRAPHS, - MS_OFFICE_XML_TAG_SLIDE_TEXT, - MS_OFFICE_XML_TAG_WORD_TEXT, - MS_OFFICE_XML_TAG_XLS_SHARED_TEXT, - MS_OFFICE_XML_TAG_DOCUMENT_CORE_DATA, - MS_OFFICE_XML_TAG_DOCUMENT_TEXT_DATA -} MsOfficeXMLTagType; - -typedef enum { - FILE_TYPE_INVALID, - FILE_TYPE_PPTX, - FILE_TYPE_PPSX, - FILE_TYPE_DOCX, - FILE_TYPE_XLSX -} MsOfficeXMLFileType; - -typedef struct { - /* Common constant stuff */ - const gchar *uri; - MsOfficeXMLFileType file_type; - - /* Tag type, reused by Content and Metadata parsers */ - MsOfficeXMLTagType tag_type; - - /* Metadata-parsing specific things */ - TrackerResource *metadata; - guint has_title : 1; - guint has_subject : 1; - guint has_publisher : 1; - guint has_comment : 1; - guint has_generator : 1; - guint has_page_count : 1; - guint has_char_count : 1; - guint has_word_count : 1; - guint has_line_count : 1; - guint has_content_created : 1; - guint has_content_last_modified : 1; - gboolean title_already_set; - gboolean generator_already_set; - - /* Content-parsing specific things */ - GString *content; - gulong bytes_pending; - gboolean style_element_present; - gboolean preserve_attribute_present; - GTimer *timer; - GList *parts; -} MsOfficeXMLParserInfo; - -static void msoffice_xml_content_parse_start (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error); -static void msoffice_xml_content_parse_stop (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error); -static void msoffice_xml_content_parse (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error); - -static void msoffice_xml_metadata_parse_start (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error); -static void msoffice_xml_metadata_parse_stop (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error); -static void msoffice_xml_metadata_parse (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error); - -static void msoffice_xml_content_types_parse_start (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error); - -static const GMarkupParser metadata_parser = { - msoffice_xml_metadata_parse_start, - msoffice_xml_metadata_parse_stop, - msoffice_xml_metadata_parse, - NULL, - NULL -}; - -static const GMarkupParser content_parser = { - msoffice_xml_content_parse_start, - msoffice_xml_content_parse_stop, - msoffice_xml_content_parse, - NULL, - NULL -}; - -static const GMarkupParser content_types_parser = { - msoffice_xml_content_types_parse_start, - NULL, - NULL, - NULL, - NULL -}; - -static GQuark maximum_size_error_quark = 0; - -/* ------------------------- CONTENT files parsing -----------------------------------*/ - -static void -msoffice_xml_content_parse_start (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - MsOfficeXMLParserInfo *info = user_data; - const gchar **a; - const gchar **v; - - switch (info->file_type) { - case FILE_TYPE_DOCX: - if (g_ascii_strcasecmp (element_name, "w:pStyle") == 0) { - for (a = attribute_names, v = attribute_values; *a; ++a, ++v) { - if (g_ascii_strcasecmp (*a, "w:val") != 0) { - continue; - } - - if (g_ascii_strncasecmp (*v, "Heading", 7) == 0) { - info->style_element_present = TRUE; - } else if (g_ascii_strncasecmp (*v, "TOC", 3) == 0) { - info->style_element_present = TRUE; - } else if (g_ascii_strncasecmp (*v, "Section", 7) == 0) { - info->style_element_present = TRUE; - } else if (g_ascii_strncasecmp (*v, "Title", 5) == 0) { - info->style_element_present = TRUE; - } else if (g_ascii_strncasecmp (*v, "Subtitle", 8) == 0) { - info->style_element_present = TRUE; - } - } - } else if (g_ascii_strcasecmp (element_name, "w:rStyle") == 0) { - for (a = attribute_names, v = attribute_values; *a; ++a, ++v) { - if (g_ascii_strcasecmp (*a, "w:val") != 0) { - continue; - } - - if (g_ascii_strncasecmp (*v, "SubtleEmphasis", 14) == 0) { - info->style_element_present = TRUE; - } else if (g_ascii_strncasecmp (*v, "SubtleReference", 15) == 0) { - info->style_element_present = TRUE; - } - } - } else if (g_ascii_strcasecmp (element_name, "w:sz") == 0) { - for (a = attribute_names, v = attribute_values; *a; ++a, ++v) { - if (g_ascii_strcasecmp (*a, "w:val") != 0) { - continue; - } - - if (atoi (*v) >= 38) { - info->style_element_present = TRUE; - } - } - } else if (g_ascii_strcasecmp (element_name, "w:smartTag") == 0) { - info->style_element_present = TRUE; - } else if (g_ascii_strcasecmp (element_name, "w:sdtContent") == 0) { - info->style_element_present = TRUE; - } else if (g_ascii_strcasecmp (element_name, "w:hyperlink") == 0) { - info->style_element_present = TRUE; - } else if (g_ascii_strcasecmp (element_name, "w:t") == 0) { - for (a = attribute_names, v = attribute_values; *a; ++a, ++v) { - if (g_ascii_strcasecmp (*a, "xml:space") != 0) { - continue; - } - - if (g_ascii_strncasecmp (*v, "preserve", 8) == 0) { - info->preserve_attribute_present = TRUE; - } - } - - info->tag_type = MS_OFFICE_XML_TAG_WORD_TEXT; - } - break; - - case FILE_TYPE_XLSX: - if (g_ascii_strcasecmp (element_name, "sheet") == 0) { - for (a = attribute_names, v = attribute_values; *a; ++a, ++v) { - if (g_ascii_strcasecmp (*a, "name") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_XLS_SHARED_TEXT; - } - } - - } else if (g_ascii_strcasecmp (element_name, "t") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_XLS_SHARED_TEXT; - } - break; - - case FILE_TYPE_PPTX: - case FILE_TYPE_PPSX: - info->tag_type = MS_OFFICE_XML_TAG_SLIDE_TEXT; - break; - - case FILE_TYPE_INVALID: - g_message ("Microsoft document type:%d invalid", info->file_type); - break; - } -} - -static void -msoffice_xml_content_parse_stop (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - MsOfficeXMLParserInfo *info = user_data; - - if (g_ascii_strcasecmp (element_name, "w:p") == 0) { - info->style_element_present = FALSE; - info->preserve_attribute_present = FALSE; - } - - /* Reset tag */ - info->tag_type = MS_OFFICE_XML_TAG_INVALID; -} - -static void -msoffice_xml_content_parse (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - MsOfficeXMLParserInfo *info = user_data; - gsize written_bytes = 0; - - /* If reached max bytes to extract, just return */ - if (info->bytes_pending == 0) { - g_set_error_literal (error, - maximum_size_error_quark, - 0, - "Maximum text limit reached"); - return; - } - - /* Create content string if not already done before */ - if (G_UNLIKELY (info->content == NULL)) { - info->content = g_string_new (""); - } - - switch (info->tag_type) { - case MS_OFFICE_XML_TAG_WORD_TEXT: - tracker_text_validate_utf8 (text, - MIN (text_len, info->bytes_pending), - &info->content, - &written_bytes); - g_string_append_c (info->content, ' '); - info->bytes_pending -= written_bytes; - break; - - case MS_OFFICE_XML_TAG_SLIDE_TEXT: - tracker_text_validate_utf8 (text, - MIN (text_len, info->bytes_pending), - &info->content, - &written_bytes); - g_string_append_c (info->content, ' '); - info->bytes_pending -= written_bytes; - break; - - case MS_OFFICE_XML_TAG_XLS_SHARED_TEXT: - if (atoi (text) == 0) { - tracker_text_validate_utf8 (text, - MIN (text_len, info->bytes_pending), - &info->content, - &written_bytes); - g_string_append_c (info->content, ' '); - info->bytes_pending -= written_bytes; - } - break; - - /* Ignore tags that may not happen inside the text subdocument */ - case MS_OFFICE_XML_TAG_TITLE: - case MS_OFFICE_XML_TAG_SUBJECT: - case MS_OFFICE_XML_TAG_AUTHOR: - case MS_OFFICE_XML_TAG_COMMENTS: - case MS_OFFICE_XML_TAG_CREATED: - case MS_OFFICE_XML_TAG_GENERATOR: - case MS_OFFICE_XML_TAG_APPLICATION: - case MS_OFFICE_XML_TAG_MODIFIED: - case MS_OFFICE_XML_TAG_NUM_OF_PAGES: - case MS_OFFICE_XML_TAG_NUM_OF_CHARACTERS: - case MS_OFFICE_XML_TAG_NUM_OF_WORDS: - case MS_OFFICE_XML_TAG_NUM_OF_LINES: - case MS_OFFICE_XML_TAG_NUM_OF_PARAGRAPHS: - case MS_OFFICE_XML_TAG_DOCUMENT_CORE_DATA: - case MS_OFFICE_XML_TAG_DOCUMENT_TEXT_DATA: - case MS_OFFICE_XML_TAG_INVALID: - break; - } -} - -/* ------------------------- METADATA files parsing -----------------------------------*/ - -static void -msoffice_xml_metadata_parse_start (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - MsOfficeXMLParserInfo *info = user_data; - - /* Setup the proper tag type */ - if (g_ascii_strcasecmp (element_name, "dc:title") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_TITLE; - } else if (g_ascii_strcasecmp (element_name, "dc:subject") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_SUBJECT; - } else if (g_ascii_strcasecmp (element_name, "dc:creator") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_AUTHOR; - } else if (g_ascii_strcasecmp (element_name, "dc:description") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_COMMENTS; - } else if (g_ascii_strcasecmp (element_name, "dcterms:created") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_CREATED; - } else if (g_ascii_strcasecmp (element_name, "meta:generator") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_GENERATOR; - } else if (g_ascii_strcasecmp (element_name, "dcterms:modified") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_MODIFIED; - } else if (g_ascii_strcasecmp (element_name, "Pages") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_NUM_OF_PAGES; - } else if (g_ascii_strcasecmp (element_name, "Slides") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_NUM_OF_PAGES; - } else if (g_ascii_strcasecmp (element_name, "Paragraphs") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_NUM_OF_PARAGRAPHS; - } else if (g_ascii_strcasecmp (element_name, "Characters") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_NUM_OF_CHARACTERS; - } else if (g_ascii_strcasecmp (element_name, "Words") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_NUM_OF_WORDS; - } else if (g_ascii_strcasecmp (element_name, "Lines") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_NUM_OF_LINES; - } else if (g_ascii_strcasecmp (element_name, "Application") == 0) { - info->tag_type = MS_OFFICE_XML_TAG_APPLICATION; - } else { - info->tag_type = MS_OFFICE_XML_TAG_INVALID; - } -} - -static void -msoffice_xml_metadata_parse_stop (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - /* Reset tag */ - ((MsOfficeXMLParserInfo *)user_data)->tag_type = MS_OFFICE_XML_TAG_INVALID; -} - -static void -msoffice_xml_metadata_parse (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - MsOfficeXMLParserInfo *info = user_data; - - switch (info->tag_type) { - /* Ignore tags that may not happen inside the core subdocument */ - case MS_OFFICE_XML_TAG_WORD_TEXT: - case MS_OFFICE_XML_TAG_SLIDE_TEXT: - case MS_OFFICE_XML_TAG_XLS_SHARED_TEXT: - break; - - case MS_OFFICE_XML_TAG_TITLE: - if (info->has_title) { - g_warning ("Avoiding additional title (%s) in MsOffice XML document '%s'", - text, info->uri); - } else { - info->has_title = TRUE; - tracker_resource_set_string (info->metadata, "nie:title", text); - } - break; - - case MS_OFFICE_XML_TAG_SUBJECT: - if (info->has_subject) { - g_warning ("Avoiding additional subject (%s) in MsOffice XML document '%s'", - text, info->uri); - } else { - info->has_subject = TRUE; - tracker_resource_set_string (info->metadata, "nie:subject", text); - } - break; - - case MS_OFFICE_XML_TAG_AUTHOR: - if (info->has_publisher) { - g_warning ("Avoiding additional publisher (%s) in MsOffice XML document '%s'", - text, info->uri); - } else { - TrackerResource *publisher = tracker_extract_new_contact (text); - - info->has_publisher = TRUE; - tracker_resource_set_relation (info->metadata, "nco:publisher", publisher); - - g_object_unref (publisher); - } - break; - - case MS_OFFICE_XML_TAG_COMMENTS: - if (info->has_comment) { - g_warning ("Avoiding additional comment (%s) in MsOffice XML document '%s'", - text, info->uri); - } else { - info->has_comment = TRUE; - tracker_resource_set_string (info->metadata, "nie:comment", text); - } - break; - - case MS_OFFICE_XML_TAG_CREATED: - if (info->has_content_created) { - g_warning ("Avoiding additional creation time (%s) in MsOffice XML document '%s'", - text, info->uri); - } else { - gchar *date; - - date = tracker_date_guess (text); - if (date) { - info->has_content_created = TRUE; - tracker_resource_set_string (info->metadata, "nie:contentCreated", date); - g_free (date); - } else { - g_warning ("Could not parse creation time (%s) from MsOffice XML document '%s'", - text, info->uri); - } - } - break; - - case MS_OFFICE_XML_TAG_GENERATOR: - if (info->has_generator) { - g_warning ("Avoiding additional generator (%s) in MsOffice XML document '%s'", - text, info->uri); - } else { - info->has_generator = TRUE; - tracker_resource_set_string (info->metadata, "nie:generator", text); - } - break; - - case MS_OFFICE_XML_TAG_APPLICATION: - /* FIXME: Same code as MS_OFFICE_XML_TAG_GENERATOR should be - * used, but nie:generator has max cardinality of 1 - * and this would cause errors. - */ - break; - - case MS_OFFICE_XML_TAG_MODIFIED: - if (info->has_content_last_modified) { - g_warning ("Avoiding additional last modification time (%s) in MsOffice XML document '%s'", - text, info->uri); - } else { - gchar *date; - - date = tracker_date_guess (text); - if (date) { - info->has_content_last_modified = TRUE; - tracker_resource_set_string (info->metadata, "nie:contentLastModified", date); - g_free (date); - } else { - g_warning ("Could not parse last modification time (%s) from MsOffice XML document '%s'", - text, info->uri); - } - } - break; - - case MS_OFFICE_XML_TAG_NUM_OF_PAGES: - if (info->has_page_count) { - g_warning ("Avoiding additional page count (%s) in MsOffice XML document '%s'", - text, info->uri); - } else { - info->has_page_count = TRUE; - tracker_resource_set_string (info->metadata, "nfo:pageCount", text); - } - break; - - case MS_OFFICE_XML_TAG_NUM_OF_CHARACTERS: - if (info->has_char_count) { - g_warning ("Avoiding additional character count (%s) in MsOffice XML document '%s'", - text, info->uri); - } else { - info->has_char_count = TRUE; - tracker_resource_set_string (info->metadata, "nfo:characterCount", text); - } - break; - - case MS_OFFICE_XML_TAG_NUM_OF_WORDS: - if (info->has_word_count) { - g_warning ("Avoiding additional word count (%s) in MsOffice XML document '%s'", - text, info->uri); - } else { - info->has_word_count = TRUE; - tracker_resource_set_string (info->metadata, "nfo:wordCount", text); - } - break; - - case MS_OFFICE_XML_TAG_NUM_OF_LINES: - if (info->has_line_count) { - g_warning ("Avoiding additional line count (%s) in MsOffice XML document '%s'", - text, info->uri); - } else { - info->has_line_count = TRUE; - tracker_resource_set_string (info->metadata, "nfo:lineCount", text); - } - break; - - case MS_OFFICE_XML_TAG_NUM_OF_PARAGRAPHS: - /* TODO: There is no ontology for this. */ - break; - - case MS_OFFICE_XML_TAG_DOCUMENT_CORE_DATA: - case MS_OFFICE_XML_TAG_DOCUMENT_TEXT_DATA: - /* Nothing as we are using it in defining type of data */ - break; - - case MS_OFFICE_XML_TAG_INVALID: - /* Here we cant use log otheriwse it will print for other non useful files */ - break; - } -} - -/* ------------------------- CONTENT-TYPES file parsing -----------------------------------*/ - -static gboolean -xml_read (MsOfficeXMLParserInfo *parser_info, - const gchar *xml_filename, - MsOfficeXMLTagType type) -{ - GMarkupParseContext *context; - - switch (type) { - case MS_OFFICE_XML_TAG_DOCUMENT_CORE_DATA: { - /* Reset these flags before going on */ - parser_info->tag_type = MS_OFFICE_XML_TAG_INVALID; - - context = g_markup_parse_context_new (&metadata_parser, - 0, - parser_info, - NULL); - break; - } - case MS_OFFICE_XML_TAG_DOCUMENT_TEXT_DATA: { - /* Reset these flags before going on */ - parser_info->tag_type = MS_OFFICE_XML_TAG_INVALID; - parser_info->style_element_present = FALSE; - parser_info->preserve_attribute_present = FALSE; - - context = g_markup_parse_context_new (&content_parser, - 0, - parser_info, - NULL); - break; - } - default: - context = NULL; - break; - } - - if (context) { - GError *error = NULL; - - /* Load the internal XML file from the Zip archive, and parse it - * using the given context */ - tracker_gsf_parse_xml_in_zip (parser_info->uri, - xml_filename, - context, - &error); - g_markup_parse_context_free (context); - - if (error) { - g_debug ("Parsing internal '%s' gave error: '%s'", - xml_filename, - error->message); - g_error_free (error); - } - } - - return TRUE; -} - -static gint -compare_slide_name (gconstpointer a, - gconstpointer b) -{ - gchar *col_a, *col_b; - gint result; - - col_a = g_utf8_collate_key_for_filename (a, -1); - col_b = g_utf8_collate_key_for_filename (b, -1); - result = strcmp (col_a, col_b); - - g_free (col_a); - g_free (col_b); - - return result; -} - -static void -msoffice_xml_content_types_parse_start (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - MsOfficeXMLParserInfo *info = user_data; - const gchar *part_name = NULL; - const gchar *content_type = NULL; - gint i; - - if (g_ascii_strcasecmp (element_name, "Override") != 0) { - return; - } - - /* Look for part name and content type */ - for (i = 0; attribute_names[i]; i++) { - if (g_ascii_strcasecmp (attribute_names[i], "PartName") == 0) { - part_name = attribute_values[i]; - } else if (g_ascii_strcasecmp (attribute_names[i], "ContentType") == 0) { - content_type = attribute_values[i]; - } - } - - /* Both part_name and content_type MUST be NON-NULL */ - if (!part_name || !content_type) { - g_message ("Invalid file (part_name:%s, content_type:%s)", - part_name ? part_name : "none", - content_type ? content_type : "none"); - return; - } - - /* Metadata part? */ - if ((g_ascii_strcasecmp (content_type, "application/vnd.openxmlformats-package.core-properties+xml") == 0) || - (g_ascii_strcasecmp (content_type, "application/vnd.openxmlformats-officedocument.extended-properties+xml") == 0)) { - xml_read (info, part_name + 1, MS_OFFICE_XML_TAG_DOCUMENT_CORE_DATA); - return; - } - - /* If the file type is unknown, skip trying to extract content */ - if (info->file_type == FILE_TYPE_INVALID) { - g_message ("Invalid file type, not extracting content from '%s'", - part_name + 1); - return; - } - - /* Content part? */ - if ((info->file_type == FILE_TYPE_DOCX && - g_ascii_strcasecmp (content_type, "application/vnd.openxmlformats-officedocument.wordprocessingml.document.main+xml") == 0) || - ((info->file_type == FILE_TYPE_PPTX || info->file_type == FILE_TYPE_PPSX) && - (g_ascii_strcasecmp (content_type, "application/vnd.openxmlformats-officedocument.presentationml.slide+xml") == 0 || - g_ascii_strcasecmp (content_type, "application/vnd.openxmlformats-officedocument.drawingml.diagramData+xml") == 0)) || - (info->file_type == FILE_TYPE_XLSX && - (g_ascii_strcasecmp (content_type, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml") == 0 || - g_ascii_strcasecmp (content_type, "application/vnd.openxmlformats-officedocument.spreadsheetml.sharedStrings+xml") == 0))) { - if (info->file_type == FILE_TYPE_PPTX) { - info->parts = g_list_insert_sorted (info->parts, g_strdup (part_name + 1), - compare_slide_name); - } else { - info->parts = g_list_append (info->parts, g_strdup (part_name + 1)); - } - } -} - -/* ------------------------- Main methods -----------------------------------*/ - -static MsOfficeXMLFileType -msoffice_xml_get_file_type (const gchar *uri) -{ - GFile *file; - GFileInfo *file_info; - const gchar *mime_used; - MsOfficeXMLFileType file_type; - - /* Get GFile from uri... */ - file = g_file_new_for_uri (uri); - if (!file) { - g_warning ("Could not create GFile for URI:'%s'", uri); - return FILE_TYPE_INVALID; - } - - /* Get GFileInfo from GFile... (synchronous) */ - file_info = g_file_query_info (file, - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, - G_FILE_QUERY_INFO_NONE, - NULL, - NULL); - g_object_unref (file); - if (!file_info) { - g_warning ("Could not get GFileInfo for URI:'%s'", uri); - return FILE_TYPE_INVALID; - } - - /* Get Content Type from GFileInfo. The constant string will be valid - * as long as the file info reference is valid */ - mime_used = g_file_info_get_content_type (file_info); - if (g_ascii_strcasecmp (mime_used, "application/vnd.openxmlformats-officedocument.wordprocessingml.document") == 0) { - /* MsOffice Word document */ - file_type = FILE_TYPE_DOCX; - } else if (g_ascii_strcasecmp (mime_used, "application/vnd.openxmlformats-officedocument.presentationml.presentation") == 0) { - /* MsOffice Powerpoint document */ - file_type = FILE_TYPE_PPTX; - } else if (g_ascii_strcasecmp (mime_used, "application/vnd.openxmlformats-officedocument.presentationml.slideshow") == 0) { - /* MsOffice Powerpoint (slideshow) document */ - file_type = FILE_TYPE_PPSX; - } else if (g_ascii_strcasecmp (mime_used, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") == 0) { - /* MsOffice Excel document */ - file_type = FILE_TYPE_XLSX; - } else { - g_message ("Mime type was not recognised:'%s'", mime_used); - file_type = FILE_TYPE_INVALID; - } - - g_object_unref (file_info); - - return file_type; -} - -static void -extract_content (MsOfficeXMLParserInfo *info) -{ - GList *parts; - - if (!info->parts) { - return; - } - - for (parts = info->parts; parts; parts = parts->next) { - const gchar *part_name; - - part_name = parts->data; - /* If reached max bytes to extract, don't event start parsing the file... just return */ - if (info->bytes_pending == 0) { - g_debug ("Skipping '%s' as already reached max bytes to extract", - part_name); - break; - } else if (g_timer_elapsed (info->timer, NULL) > 5) { - g_debug ("Skipping '%s' as already reached max time to extract", - part_name); - break; - } else { - xml_read (info, part_name, MS_OFFICE_XML_TAG_DOCUMENT_TEXT_DATA); - } - } -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *extract_info) -{ - MsOfficeXMLParserInfo info = { 0 }; - MsOfficeXMLFileType file_type; - TrackerResource *metadata; - TrackerConfig *config; - GMarkupParseContext *context = NULL; - GError *error = NULL; - GFile *file; - gchar *uri; - - if (G_UNLIKELY (maximum_size_error_quark == 0)) { - maximum_size_error_quark = g_quark_from_static_string ("maximum_size_error"); - } - - file = tracker_extract_info_get_file (extract_info); - uri = g_file_get_uri (file); - - /* Get current Content Type */ - file_type = msoffice_xml_get_file_type (uri); - - /* Setup conf */ - config = tracker_main_get_config (); - - g_debug ("Extracting MsOffice XML format..."); - - metadata = tracker_resource_new (NULL); - tracker_resource_add_uri (metadata, "rdf:type", "nfo:PaginatedTextDocument"); - - /* Setup Parser info */ - info.metadata = metadata; - info.file_type = file_type; - info.tag_type = MS_OFFICE_XML_TAG_INVALID; - info.style_element_present = FALSE; - info.preserve_attribute_present = FALSE; - info.uri = uri; - info.content = NULL; - info.title_already_set = FALSE; - info.generator_already_set = FALSE; - info.bytes_pending = tracker_config_get_max_bytes (config); - - /* Create content-type parser context */ - context = g_markup_parse_context_new (&content_types_parser, - 0, - &info, - NULL); - - info.timer = g_timer_new (); - /* Load the internal XML file from the Zip archive, and parse it - * using the given context */ - tracker_gsf_parse_xml_in_zip (uri, - "[Content_Types].xml", - context, - &error); - if (error) { - g_debug ("Parsing the content-types file gave an error: '%s'", - error->message); - g_error_free (error); - } - - extract_content (&info); - - /* If we got any content, add it */ - if (info.content) { - gchar *content; - - content = g_string_free (info.content, FALSE); - info.content = NULL; - - if (content) { - tracker_resource_set_string (metadata, "nie:plainTextContent", content); - g_free (content); - } - } - - if (info.parts) { - g_list_foreach (info.parts, (GFunc) g_free, NULL); - g_list_free (info.parts); - } - - g_timer_destroy (info.timer); - g_markup_parse_context_free (context); - g_free (uri); - - tracker_extract_info_set_resource (extract_info, metadata); - g_object_unref (metadata); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-msoffice.c b/src/tracker-extract/tracker-extract-msoffice.c deleted file mode 100644 index d2330c35f..000000000 --- a/src/tracker-extract/tracker-extract-msoffice.c +++ /dev/null @@ -1,1713 +0,0 @@ -/* - * Copyright (C) 2006, Edward Duffy <eduffy@gmail.com> - * Copyright (C) 2006, Laurent Aguerreche <laurent.aguerreche@free.fr> - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <errno.h> -#include <string.h> - -#include <glib.h> -#include <gsf/gsf.h> -#include <gsf/gsf-doc-meta-data.h> -#include <gsf/gsf-infile.h> -#include <gsf/gsf-infile-msole.h> -#include <gsf/gsf-input-stdio.h> -#include <gsf/gsf-msole-utils.h> -#include <gsf/gsf-utils.h> -#include <gsf/gsf-infile-zip.h> - -#include <libtracker-common/tracker-common.h> -#include <libtracker-extract/tracker-extract.h> - -#include "tracker-main.h" -#include "tracker-gsf.h" - -/* Powerpoint files comprise of structures. Each structure contains a - * header. Within that header is a record type that specifies what - * strcture it is. It is called record type. - * - * Here are are some record types and description of the structure - * (called atom) they contain. - */ - -/* An atom record that specifies Unicode characters with no high byte - * of a UTF-16 Unicode character. High byte is always 0. - * http://msdn.microsoft.com/en-us/library/dd947905%28v=office.12%29.aspx - */ -#define TEXTBYTESATOM_RECORD_TYPE 0x0FA8 - -/* An atom record that specifies Unicode characters. - * http://msdn.microsoft.com/en-us/library/dd772921%28v=office.12%29.aspx - */ -#define TEXTCHARSATOM_RECORD_TYPE 0x0FA0 - -/* A container record that specifies information about the powerpoint - * document. - */ -#define DOCUMENTCONTAINER_RECORD_TYPE 0x03E8 - -/* Variant type of record. Within Powerpoint text extraction we are - * interested of SlideListWithTextContainer type that contains the - * textual content of the slide(s). - */ -#define SLIDELISTWITHTEXT_RECORD_TYPE 0x0FF0 - -/** - * @brief Header for all powerpoint structures - * - * A structure at the beginning of each container record and each atom record in - * the file. The values in the record header and the context of the record are - * used to identify and interpret the record data that follows. - */ -typedef struct { - /** - * @brief An unsigned integer that specifies the version of the record - * data that follows the record header. A value of 0xF specifies that the - * record is a container record. - */ - guint recVer; - - /** - * @brief An unsigned integer that specifies the record instance data. - * Interpretation of the value is dependent on the particular record - * type. - */ - guint recInstance; - - /** - * @brief A RecordType enumeration that specifies the type of the record - * data that follows the record header. - */ - gint recType; - - /** - * @brief An unsigned integer that specifies the length, in bytes, of the - * record data that follows the record header. - */ - guint recLen; -} PowerPointRecordHeader; - -/* Excel spec record type to read shared string */ -typedef enum { - RECORD_TYPE_SST = 252, - RECORD_TYPE_CONTINUE = 60, - RECORD_TYPE_EOF = 10 -} ExcelRecordType; - -/* ExcelBiffHeader to read excel spec header */ -typedef struct { - ExcelRecordType id; - guint length; -} ExcelBiffHeader; - -/* ExtendendString Record offset in stream and length */ -typedef struct { - gsf_off_t offset; /* 64 bits!! */ - gsize length; -} ExcelExtendedStringRecord; - -typedef struct { - TrackerResource *metadata; - const gchar *uri; -} MetadataInfo; - -/* Valid range from \000 to \377 (0 to 255) */ -#define octal_ascii_triplet_is_valid(slash, a2, a1, a0) \ - (slash == '\\' && \ - a2 >= '0' && a2 <= '3' && \ - a1 >= '0' && a1 <= '7' && \ - a0 >= '0' && a0 <= '7') - -#define octal_ascii_triplet_to_decimal_int(a2, a1, a0) \ - ((a0 - '0') + 8 * ((a1 - '0') + 8 * (a2 - '0'))) - -/* - * So, we may get input strings with UTF-8 characters encoded in OCTAL and - * represented in ASCII, like this: - * K\303\230BENHAVNS UNIVERSITET - * which is equivalent to: - * KØBENHAVNS UNIVERSITET - */ -static void -msoffice_string_process_octal_triplets (guchar *str) -{ - guint i = 0; /* index in original string */ - guint j = 0; /* index in processed string */ - guint length = strlen (str); - - /* Changing the string IN PLACE, note that j<=i ALWAYS! */ - while (i < length) { - if (length - i >= 4 && - octal_ascii_triplet_is_valid (str[i], str[i+1], str[i+2], str[i+3])) { - /* Found a new octal triplet */ - str[j] = octal_ascii_triplet_to_decimal_int (str[i+1], str[i+2], str[i+3]); - i += 4; - } else if (i != j) { - /* We previously found an octal triplet, - * we need to update the string */ - str[j] = str[i]; - i++; - } else { - /* No need to update the string yet */ - i++; - } - j++; - } - /* New end of string */ - str[j]='\0'; -} - -static void -metadata_add_gvalue (TrackerResource *metadata, - const gchar *key, - GValue const *val, - const gchar *type, - const gchar *predicate, - gboolean is_date) -{ - gchar *s; - - g_return_if_fail (metadata != NULL); - g_return_if_fail (key != NULL); - - if (!val) { - return; - } - - s = g_strdup_value_contents (val); - - if (!s) { - return; - } - - if (!tracker_is_empty_string (s)) { - gchar *str_val; - - /* Some fun: strings are always written "str" with double quotes - * around, but not numbers! - */ - if (s[0] == '"') { - size_t len; - - len = strlen (s); - - if (s[len - 1] == '"') { - if (is_date) { - if (len > 2) { - gchar *str = g_strndup (s + 1, len - 2); - str_val = tracker_date_guess (str); - g_free (str); - } else { - str_val = NULL; - } - } else { - str_val = len > 2 ? g_strndup (s + 1, len - 2) : NULL; - } - } else { - /* We have a string that begins with a double - * quote but which finishes by something - * different... We copy the string from the - * beginning. - */ - if (is_date) { - str_val = tracker_date_guess (s); - } else { - str_val = g_strdup (s); - } - } - } else { - /* Here, we probably have a number */ - if (is_date) { - str_val = tracker_date_guess (s); - } else { - str_val = g_strdup (s); - } - } - - if (str_val) { - /* Process (in place) octal triplets if found */ - msoffice_string_process_octal_triplets (str_val); - - if (type && predicate) { - TrackerResource *child = tracker_resource_new (NULL); - tracker_resource_set_uri (child, "rdf:type", type); - tracker_resource_set_string (child, predicate, str_val); - - tracker_resource_add_relation (metadata, key, child); - - g_object_unref (child); - } else { - tracker_resource_set_string (metadata, key, str_val); - } - - g_free (str_val); - } - } - - g_free (s); -} - -static void -summary_metadata_cb (gpointer key, - gpointer value, - gpointer user_data) -{ - MetadataInfo *info = user_data; - GValue const *val; - - val = gsf_doc_prop_get_val (value); - - if (g_strcmp0 (key, "dc:title") == 0) { - metadata_add_gvalue (info->metadata, "nie:title", val, NULL, NULL, FALSE); - } else if (g_strcmp0 (key, "dc:subject") == 0) { - metadata_add_gvalue (info->metadata, "nie:subject", val, NULL, NULL, FALSE); - } else if (g_strcmp0 (key, "dc:creator") == 0) { - metadata_add_gvalue (info->metadata, "nco:creator", val, "nco:Contact", "nco:fullname", FALSE); - } else if (g_strcmp0 (key, "dc:keywords") == 0) { - gchar *keywords, *str = g_strdup_value_contents (val); - gchar *lasts, *keyw; - size_t len; - - keyw = keywords = str; - keywords = strchr (keywords, '"'); - - if (keywords) { - keywords++; - } else { - keywords = keyw; - } - - len = strlen (keywords); - if (keywords[len - 1] == '"') { - keywords[len - 1] = '\0'; - } - - for (keyw = strtok_r (keywords, ",; ", &lasts); keyw; - keyw = strtok_r (NULL, ",; ", &lasts)) { - tracker_resource_add_string (info->metadata, "nie:keyword", keyw); - } - - g_free (str); - } else if (g_strcmp0 (key, "dc:description") == 0) { - metadata_add_gvalue (info->metadata, "nie:comment", val, NULL, NULL, FALSE); - } else if (g_strcmp0 (key, "gsf:page-count") == 0) { - metadata_add_gvalue (info->metadata, "nfo:pageCount", val, NULL, NULL, FALSE); - } else if (g_strcmp0 (key, "gsf:word-count") == 0) { - metadata_add_gvalue (info->metadata, "nfo:wordCount", val, NULL, NULL, FALSE); - } else if (g_strcmp0 (key, "meta:creation-date") == 0) { - metadata_add_gvalue (info->metadata, "nie:contentCreated", val, NULL, NULL, TRUE); - } else if (g_strcmp0 (key, "meta:generator") == 0) { - metadata_add_gvalue (info->metadata, "nie:generator", val, NULL, NULL, FALSE); - } -} - -static void -document_metadata_cb (gpointer key, - gpointer value, - gpointer user_data) -{ - if (g_strcmp0 (key, "CreativeCommons_LicenseURL") == 0) { - MetadataInfo *info = user_data; - - metadata_add_gvalue (info->metadata, - "nie:license", - gsf_doc_prop_get_val (value), - NULL, - NULL, - FALSE); - } -} - -/** - * @brief Read 8 bit unsigned integer - * @param buffer data to read integer from - * @return 16 bit unsigned integer - */ -static guint -read_8bit (const guint8 *buffer) -{ - return buffer[0]; -} - -/** - * @brief Read 16 bit unsigned integer - * @param buffer data to read integer from - * @return 16 bit unsigned integer - */ -static guint16 -read_16bit (const guint8 *buffer) -{ - return buffer[0] + (buffer[1] << 8); -} - -/** - * @brief Read 32 bit unsigned integer - * @param buffer data to read integer from - * @return 32 bit unsigned integer - */ -static guint32 -read_32bit (const guint8 *buffer) -{ - return buffer[0] + (buffer[1] << 8) + (buffer[2] << 16) + (buffer[3] << 24); -} - -/** - * @brief Common conversion and normalization method for all msoffice type - * documents. - * @param buffer Input buffer with the string contents - * @param chunk_size Number of valid bytes in the input buffer - * @param is_ansi If %TRUE, input text should be encoded in CP1252, and - * in UTF-16 otherwise. - * @param p_bytes_remaining Pointer to #gsize specifying how many bytes - * should still be considered. - * @param p_content Pointer to a #GString where the output normalized words - * will be appended. - */ -static void -msoffice_convert_and_normalize_chunk (guint8 *buffer, - gsize chunk_size, - gboolean is_ansi, - gsize *bytes_remaining, - GString **content) -{ - gsize n_bytes_utf8; - gchar *converted_text; - GError *error = NULL; - - g_return_if_fail (buffer != NULL); - g_return_if_fail (chunk_size > 0); - g_return_if_fail (bytes_remaining != NULL); - g_return_if_fail (content != NULL); - - /* chunks can have different encoding - * - * TODO: Using g_iconv, this extra heap allocation could be - * avoided, re-using over and over again the same output buffer - * for the UTF-8 encoded string - */ - converted_text = g_convert (buffer, - chunk_size, - "UTF-8", - is_ansi ? "CP1252" : "UTF-16", - NULL, - &n_bytes_utf8, - &error); - - if (converted_text) { - gsize len_to_validate; - - len_to_validate = MIN (*bytes_remaining, n_bytes_utf8); - - if (tracker_text_validate_utf8 (converted_text, - len_to_validate, - content, - NULL)) { - /* A whitespace is added to separate next strings appended */ - g_string_append_c (*content, ' '); - } - - /* Update accumulated UTF-8 bytes read */ - *bytes_remaining -= len_to_validate; - g_free (converted_text); - } else { - g_warning ("Couldn't convert %" G_GSIZE_FORMAT " bytes from %s to UTF-8: %s", - chunk_size, - is_ansi ? "CP1252" : "UTF-16", - error ? error->message : "no error given"); - } - - /* Note that error may be set even if some converted text is - * available, due to G_CONVERT_ERROR_ILLEGAL_SEQUENCE for example */ - g_clear_error (&error); -} - -/** - * @brief Read header data from given stream - * @param stream Stream to read header data - * @param header Pointer to header where to store results - */ -static gboolean -ppt_read_header (GsfInput *stream, - PowerPointRecordHeader *header) -{ - guint8 buffer[8] = {0}; - - g_return_val_if_fail (stream, FALSE); - g_return_val_if_fail (header, FALSE); - g_return_val_if_fail (!gsf_input_eof (stream), FALSE); - - - /* Header is always 8 bytes, read it */ - g_return_val_if_fail (gsf_input_read (stream, 8, buffer), FALSE); - - /* Then parse individual details - * - * Record header is 8 bytes long. Data is split as follows: - * recVer (4 bits) - * recInstance (12 bits) - * recType (2 bytes) - * recLen (4 bytes) - * - * See RecordHeader for more detailed explanation of each field. - * - * Here we parse each of those fields. - */ - - header->recType = read_16bit (&buffer[2]); - header->recLen = read_32bit (&buffer[4]); - header->recVer = (read_16bit (buffer) & 0xF000) >> 12; - header->recInstance = read_16bit (buffer) & 0x0FFF; - - return TRUE; -} - -/** - * @brief Read powerpoint text from given stream. - * - * Powerpoint contains texts in either TextBytesAtom or TextCharsAtom. Below - * are excerpt from [MS-PPT].pdf file describing the ppt file struture: - * - * TextCharsAtom contains an array of UTF-16 Unicode [RFC2781] characters that - * specifies the characters of the corresponding text. The length, in bytes, of - * the array is specified by rh.recLen. The array MUST NOT contain the NUL - * character 0x0000. - * - * TextBytesAtom contains an array of bytes that specifies the characters of the - * corresponding text. Each item represents the low byte of a UTF-16 Unicode - * [RFC2781] character whose high byte is 0x00. The length, in bytes, of the - * array is specified by rh.recLen. The array MUST NOT contain a 0x00 byte. - * - * @param stream Stream to read text bytes/chars atom - * @return read text or NULL if no text was read. Has to be freed by the caller - */ -static void -ppt_read_text (GsfInput *stream, - guint8 **p_buffer, - gsize *p_buffer_size, - gsize *p_read_size) -{ - PowerPointRecordHeader header; - gsize required_size; - - g_return_if_fail (stream); - g_return_if_fail (p_buffer); - g_return_if_fail (p_buffer_size); - g_return_if_fail (p_read_size); - - /* First read the header that describes the structures type - * (TextBytesAtom or TextCharsAtom) and it's length. - */ - g_return_if_fail (ppt_read_header (stream, &header)); - - /* We only want header with type either TEXTBYTESATOM_RECORD_TYPE - * (TextBytesAtom) or TEXTCHARSATOM_RECORD_TYPE (TextCharsAtom). - * - * We don't care about anything else - */ - if (header.recType != TEXTBYTESATOM_RECORD_TYPE && - header.recType != TEXTCHARSATOM_RECORD_TYPE) { - return; - } - - /* Then we'll allocate data for the actual texts */ - if (header.recType == TEXTBYTESATOM_RECORD_TYPE) { - /* TextBytesAtom doesn't include high bytes propably in order to - * save space on the ppt files. We'll have to allocate double the - * size for it to get the high bytes - */ - required_size = header.recLen * 2; - } else { - required_size = header.recLen; - } - - /* Resize reused buffer if needed */ - if (required_size > *p_buffer_size) { - *p_buffer = g_realloc (*p_buffer, required_size); - *p_buffer_size = required_size; - } - - /* Then read the textual data from the stream */ - if (!gsf_input_read (stream, header.recLen, *p_buffer)) { - return; - } - - /* Again if we are reading TextBytesAtom we'll need to add those utf16 - * high bytes ourselves. They are zero as specified in [MS-PPT].pdf - * and this function's comments - */ - if (header.recType == TEXTBYTESATOM_RECORD_TYPE) { - gint i; - - for (i = 0; i < header.recLen; i++) { - /* We'll add an empty 0 byte between each byte in the array */ - (*p_buffer)[(header.recLen - i - 1) * 2] = (*p_buffer)[header.recLen - i - 1]; - (*p_buffer)[((header.recLen - i - 1) * 2) + 1] = '\0'; - } - } - - /* Set read size as output */ - *p_read_size = required_size; -} - -/** - * @brief Find a specific header from given stream - * @param stream Stream to parse headers from - * @param type1 first type of header to look for - * @param type2 convenience parameter if we are looking for either of two - * header types - * @param rewind if a proper header is found should this function seek - * to the start of the header (TRUE) - * @return TRUE if either of specified headers was found - */ -static gboolean -ppt_seek_header (GsfInput *stream, - gint type1, - gint type2, - gboolean rewind) -{ - PowerPointRecordHeader header; - - g_return_val_if_fail (stream,FALSE); - - /* Read until we reach eof */ - while (!gsf_input_eof (stream)) { - /* Read first header */ - g_return_val_if_fail (ppt_read_header (stream, &header), FALSE); - - /* Check if it's the correct type */ - if (header.recType == type1 || header.recType == type2) { - /* Sometimes it's needed to rewind to the start of the - * header - */ - if (rewind) { - gsf_input_seek (stream, -8, G_SEEK_CUR); - } - - return TRUE; - } - - /* If it's not the correct type, seek to the beginning of the - * next header - */ - g_return_val_if_fail (!gsf_input_seek (stream, - header.recLen, - G_SEEK_CUR), - FALSE); - } - - return FALSE; -} - -static gchar * -extract_powerpoint_content (GsfInfile *infile, - gsize max_bytes, - gboolean *is_encrypted) -{ - /* Try to find Powerpoint Document stream */ - GsfInput *stream; - GString *all_texts = NULL; - gsf_off_t last_document_container; - - /* If no content requested, return */ - if (max_bytes == 0) { - return NULL; - } - - stream = gsf_infile_child_by_name (infile, "PowerPoint Document"); - - if (is_encrypted) { - *is_encrypted = FALSE; - } - - if (!stream) { - return NULL; - } - - /* Powerpoint documents have a "editing history" stored within them. - * There is a structure that defines what changes were made each time - * but it is just easier to get the current/latest version just by - * finding the last occurrence of DocumentContainer structure - */ - last_document_container = -1; - - /* Read until we reach eof. */ - while (!gsf_input_eof (stream)) { - PowerPointRecordHeader header; - - /* - * We only read headers of data structures - */ - if (!ppt_read_header (stream, &header)) { - break; - } - - /* And we only care about headers with type 1000, - * DocumentContainer - */ - - if (header.recType == DOCUMENTCONTAINER_RECORD_TYPE) { - last_document_container = gsf_input_tell (stream); - } - - /* and then seek to the start of the next data - * structure so it is fast and we don't have to read - * through the whole file - */ - if (gsf_input_seek (stream, header.recLen, G_SEEK_CUR)) { - break; - } - } - - /* If a DocumentContainer was found and we are able to seek to it. - * - * Then we'll have to find the second header with type - * SLIDELISTWITHTEXT_RECORD_TYPE since DocumentContainer - * contains MasterListWithTextContainer and - * SlideListWithTextContainer structures with both having the - * same header type. We however only want - * SlideListWithTextContainer which contains the textual - * content of the power point file. - */ - if (last_document_container >= 0 && - !gsf_input_seek (stream, last_document_container, G_SEEK_SET) && - ppt_seek_header (stream, - SLIDELISTWITHTEXT_RECORD_TYPE, - SLIDELISTWITHTEXT_RECORD_TYPE, - FALSE) && - ppt_seek_header (stream, - SLIDELISTWITHTEXT_RECORD_TYPE, - SLIDELISTWITHTEXT_RECORD_TYPE, - FALSE)) { - gsize bytes_remaining = max_bytes; - guint8 *buffer = NULL; - gsize buffer_size = 0; - - /* - * Read while we have either TextBytesAtom or - * TextCharsAtom and we have read less than max_bytes - * (in UTF-8) - */ - while (bytes_remaining > 0 && - ppt_seek_header (stream, - TEXTBYTESATOM_RECORD_TYPE, - TEXTCHARSATOM_RECORD_TYPE, - TRUE)) { - gsize read_size = 0; - - /* Read the UTF-16 text in the reused buffer, and also get - * number of read bytes */ - ppt_read_text (stream, &buffer, &buffer_size, &read_size); - - /* Avoid empty strings */ - if (read_size > 0) { - /* Convert, normalize and limit max words & bytes. - * NOTE: `is_ansi' argument is FALSE, as the string is - * always in UTF-16 */ - msoffice_convert_and_normalize_chunk (buffer, - read_size, - FALSE, /* Always UTF-16 */ - &bytes_remaining, - &all_texts); - } - } - - g_free (buffer); - } - - g_object_unref (stream); - - return all_texts ? g_string_free (all_texts, FALSE) : NULL; -} - -static GsfInfile * -open_file (const gchar *filename, FILE *file) -{ - GsfInput *input; - GsfInfile *infile; - GError *error = NULL; - - input = gsf_input_stdio_new_FILE (filename, file, TRUE); - - if (!input) { - return NULL; - } - - infile = gsf_infile_msole_new (input, &error); - - if (error) { - if (error->domain != gsf_input_error_id ()) - g_warning ("Failed to open file '%s': %s", filename, error->message); - g_error_free (error); - } - - g_object_unref (input); - - return infile; -} - -/* This function was programmed by using ideas and algorithms from - * b2xtranslator project (http://b2xtranslator.sourceforge.net/) - */ -static gchar * -extract_msword_content (GsfInfile *infile, - gsize n_bytes, - gboolean *is_encrypted) -{ - GsfInput *document_stream, *table_stream; - gint16 i = 0; - guint8 tmp_buffer[4] = { 0 }; - gint fcClx, lcbClx; - guint8 *piece_table = NULL; - guint8 *clx = NULL; - gint lcb_piece_table; - gint piece_count = 0; - gint32 fc; - GString *content = NULL; - guint8 *text_buffer = NULL; - gint text_buffer_size = 0; - gsize n_bytes_remaining; - - /* If no content requested, return */ - if (n_bytes == 0) { - return NULL; - } - - document_stream = gsf_infile_child_by_name (infile, "WordDocument"); - if (document_stream == NULL) { - return NULL; - } - - /* abort if FIB can't be found from beginning of WordDocument stream */ - gsf_input_seek (document_stream, 0, G_SEEK_SET); - gsf_input_read (document_stream, 2, tmp_buffer); - if (read_16bit (tmp_buffer) != 0xa5ec) { - g_object_unref (document_stream); - return NULL; - } - - /* abort if document is encrypted */ - gsf_input_seek (document_stream, 11, G_SEEK_SET); - gsf_input_read (document_stream, 1, tmp_buffer); - if ((tmp_buffer[0] & 0x1) == 0x1) { - g_object_unref (document_stream); - *is_encrypted = TRUE; - return NULL; - } else - *is_encrypted = FALSE; - - /* document can have 0Table or 1Table or both. If flag 0x0200 is - * set to true in word 0x000A of the FIB then 1Table is used - */ - gsf_input_seek (document_stream, 0x000A, G_SEEK_SET); - gsf_input_read (document_stream, 2, tmp_buffer); - i = read_16bit (tmp_buffer); - - if ((i & 0x0200) == 0x0200) { - table_stream = gsf_infile_child_by_name (infile, "1Table"); - } else { - table_stream = gsf_infile_child_by_name (infile, "0Table"); - } - - if (table_stream == NULL) { - g_object_unref (G_OBJECT (document_stream)); - return NULL; - } - - /* find out location and length of piece table from FIB */ - gsf_input_seek (document_stream, 418, G_SEEK_SET); - gsf_input_read (document_stream, 4, tmp_buffer); - fcClx = read_32bit (tmp_buffer); - gsf_input_read (document_stream, 4, tmp_buffer); - lcbClx = read_32bit (tmp_buffer); - - /* If we got an invalid or empty length of piece table, just return - * as we cannot iterate over pieces */ - if (lcbClx <= 0) { - g_object_unref (document_stream); - g_object_unref (table_stream); - return NULL; - } - - /* copy the structure holding the piece table into the clx array. */ - clx = g_malloc (lcbClx); - gsf_input_seek (table_stream, fcClx, G_SEEK_SET); - gsf_input_read (table_stream, lcbClx, clx); - - /* find out piece table from clx and set piece_table -pointer to it */ - i = 0; - lcb_piece_table = 0; - - while (TRUE) { - if (clx[i] == 2) { - /* Nice, a proper structure with contents, no need to - * iterate more. */ - lcb_piece_table = read_32bit (clx + (i + 1)); - piece_table = clx + i + 5; - piece_count = (lcb_piece_table - 4) / 12; - break; - } else if (clx[i] == 1) { - /* Oh, a PRC structure with properties of text, not - * real text, so skip it */ - guint16 GrpPrl_len; - - GrpPrl_len = read_16bit (&clx[i+1]); - /* 3 is the length of clxt (1byte) and cbGrpprl(2bytes) */ - i = i + 3 + GrpPrl_len; - } else { - break; - } - } - - /* Iterate over pieces... - * Loop is halted whenever one of this conditions is met: - * a) Max bytes to be read reached - * b) No more pieces to read - */ - i = 0; - n_bytes_remaining = n_bytes; - while (n_bytes_remaining > 0 && - i < piece_count) { - guint8 *piece_descriptor; - gint piece_start; - gint piece_end; - gint piece_size; - gboolean is_ansi; - - /* logical position of the text piece in the document_stream */ - piece_start = read_32bit (piece_table + (i * 4)); - piece_end = read_32bit (piece_table + ((i + 1) * 4)); - - /* descriptor of single piece from piece table */ - piece_descriptor = piece_table + ((piece_count + 1) * 4) + (i * 8); - - /* file character position */ - fc = read_32bit (piece_descriptor + 2); - - /* second bit is set to 1 if text is saved in ANSI encoding */ - is_ansi = (fc & 0x40000000) == 0x40000000; - - /* modify file character position according to text encoding */ - if (!is_ansi) { - fc = (fc & 0xBFFFFFFF); - } else { - fc = (fc & 0xBFFFFFFF) >> 1; - } - - piece_size = piece_end - piece_start; - - /* NOTE: Very very long pieces may appear. In fact, a single - * piece document seems to be quite normal. Thus, we limit - * here the number of bytes to read from the stream, based - * on the maximum number of bytes in UTF-8. Assuming, then - * that a safe limit is 2*n_bytes_remaining if UTF-16 input, - * and just n_bytes_remaining in CP1251 input */ - piece_size = MIN (piece_size, n_bytes_remaining); - - /* UTF-16 uses twice as many bytes as CP1252 - * NOTE: Not quite sure about this. Some unicode points will be - * encoded using 4 bytes in UTF-16 */ - if (!is_ansi) { - piece_size *= 2; - } - - /* Avoid empty pieces */ - if (piece_size >= 1) { - - /* Re-allocate buffer to make it bigger if needed. - * This text buffer is re-used over and over in each - * iteration. */ - if (piece_size > text_buffer_size) { - text_buffer = g_realloc (text_buffer, piece_size); - text_buffer_size = piece_size; - } - - /* read and parse single text piece from document_stream */ - gsf_input_seek (document_stream, fc, G_SEEK_SET); - gsf_input_read (document_stream, piece_size, text_buffer); - - msoffice_convert_and_normalize_chunk (text_buffer, - piece_size, - is_ansi, - &n_bytes_remaining, - &content); - } - - /* Go on to next piece */ - i++; - } - - g_free (text_buffer); - g_object_unref (document_stream); - g_object_unref (table_stream); - g_free (clx); - - return content ? g_string_free (content, FALSE) : NULL; -} - -/* Reads and interprets the flags of a given string. May be - * used just to skip the fields, as when this bitmask-byte - * comes as the first byte of a new record. - * NOTE: For a detailed meaning of each field parsed here, - * take a look at the XLUnicodeRichExtendedString format: - * http://msdn.microsoft.com/en-us/library/dd943830.aspx - **/ -static void -read_excel_string_flags (GsfInput *stream, - gboolean *p_is_high_byte, - guint16 *p_c_run, - guint16 *p_cb_ext_rst) -{ - guint8 tmp_buffer[4] = { 0 }; - guint8 bit_mask; - gboolean is_ext_string; - gboolean is_rich_string; - - /* Note that output arguments may be NULL if we don't need - * their values... */ - - /* Reading 1 byte for mask */ - gsf_input_read (stream, 1, tmp_buffer); - bit_mask = read_8bit (tmp_buffer); - - /* Get flags */ - if (p_is_high_byte) { - *p_is_high_byte = (bit_mask & 0x01) == 0x01; - } - is_ext_string = (bit_mask & 0x04) == 0x04; - is_rich_string = (bit_mask & 0x08) == 0x08; - - /* If the c_run value is required as output, read it */ - if (p_c_run) { - if (is_rich_string) { - /* Reading 2 Bytes */ - gsf_input_read (stream, 2, tmp_buffer); - - /* Reading cRun */ - *p_c_run = read_16bit (tmp_buffer); - } else { - *p_c_run = 0; - } - } else if (is_rich_string) { - /* If not required, just skip those bytes */ - gsf_input_seek (stream, 2, G_SEEK_CUR); - } - - /* If the cb_ext_rst value is required as output, read it */ - if (p_cb_ext_rst) { - if (is_ext_string) { - /* Reading 4 Bytes */ - gsf_input_read (stream, 4, tmp_buffer); - - /* Reading cRun */ - *p_cb_ext_rst = read_16bit (tmp_buffer); - } else { - *p_cb_ext_rst = 0; - } - } else if (is_ext_string) { - /* If not required, just skip those bytes */ - gsf_input_seek (stream, 4, G_SEEK_CUR); - } -} - -/* Returns TRUE if record was changed. BUT, the value of the - * current_record should be checked by the caller to know - * if there are no more records */ -static gboolean -change_excel_record_if_needed (GsfInput *stream, - GArray *record_array, - guint *p_current_record) -{ - ExcelExtendedStringRecord *record; - - /* Get current record */ - record = &g_array_index (record_array, - ExcelExtendedStringRecord, - *p_current_record); - - /* We may already have surpassed the record, so adjust if so */ - if (gsf_input_tell (stream) >= (record->offset + record->length)) { - /* Switch records and read from the second one... */ - (*p_current_record)++; - - if (*p_current_record < record_array->len) { - record = &g_array_index (record_array, - ExcelExtendedStringRecord, - *p_current_record); - - gsf_input_seek (stream, record->offset, G_SEEK_SET); - } - - return TRUE; - } - - return FALSE; -} - -/* Returns TRUE if correctly read - * - * Note that p_current_record may get changed if the required - * bytes to read were split into two different records. - */ -static gboolean -read_excel_string (GsfInput *stream, - guint8 *buffer, - gsize chunk_size, - GArray *record_array, - guint *p_current_record) -{ - ExcelExtendedStringRecord *record; - gsf_off_t current_position; - gsf_off_t current_record_end; - - /* Record may have changed when we want to read the string contents - * This is a pretty special case, where the new CONTINUE record - * shouldn't start with a bitmask */ - if (change_excel_record_if_needed (stream, record_array, p_current_record) && - *p_current_record >= record_array->len) { - /* When reached max number of records, just return */ - return FALSE; - } - - /* Get current record */ - record = &g_array_index (record_array, - ExcelExtendedStringRecord, - *p_current_record); - - /* Compute current position in the stream and end of current record*/ - current_position = gsf_input_tell (stream); - current_record_end = record->offset + record->length; - - /* The best case is when the whole number of bytes to read are in the - * current record, as no record switching is therefore needed */ - if (current_position + chunk_size <= current_record_end) { - return gsf_input_read (stream, chunk_size, buffer) != NULL ? TRUE : FALSE; - } else if (current_record_end < current_position) { - /* Safety check, actually pretty important */ - return FALSE; - } else { - /* Read the string in two chunks */ - gsize chunk_size_first_record; - gsize chunk_size_second_record; - - /* Compute how much to read in each record */ - chunk_size_first_record = current_record_end - current_position; - chunk_size_second_record = chunk_size - chunk_size_first_record; - - /* g_debug ("Current position: %" GSF_OFF_T_FORMAT, current_position); */ - /* g_debug ("Current record index: %u", *p_current_record); */ - /* g_debug ("Current record start: %" GSF_OFF_T_FORMAT, record->offset); */ - /* g_debug ("Current record length: %" G_GSIZE_FORMAT, record->length); */ - /* g_debug ("Current record end: %" GSF_OFF_T_FORMAT, current_record_end); */ - /* g_debug ("Bytes to read: %" G_GSIZE_FORMAT, chunk_size); */ - /* g_debug ("Bytes to read (1st): %" G_GSIZE_FORMAT, chunk_size_first_record); */ - /* g_debug ("Bytes to read (2nd): %" G_GSIZE_FORMAT, chunk_size_second_record); */ - - /* Now, read from first record... */ - if (gsf_input_read (stream, - chunk_size_first_record, - buffer)) { - /* Now switch records and read from the second one... */ - (*p_current_record)++; - - if (*p_current_record < record_array->len) { - record = &g_array_index (record_array, - ExcelExtendedStringRecord, - *p_current_record); - - /* g_debug ("New record index: %u", *p_current_record); */ - /* g_debug ("New record start: %" GSF_OFF_T_FORMAT, record->offset); */ - /* g_debug ("New record length: %" G_GSIZE_FORMAT, record->length); */ - - /* Move stream pointer to the new location, beginning of next record */ - gsf_input_seek (stream, record->offset, G_SEEK_SET); - - /* Every CONTINUE records starts with a bitmask + optional fields that - * should be skipped properly */ - read_excel_string_flags (stream, NULL, NULL, NULL); - - /* And finally, read the second part */ - if (gsf_input_read (stream, - chunk_size_second_record, - &buffer[chunk_size_first_record])) { - /* All OK! */ - return TRUE; - } - } - } - - return FALSE; - } -} - - - -/** - * [MS-XLS] — v20090708 - * Excel Binary File Format (.xls) Structure Specification - * Copyright © 2009 Microsoft Corporation. - * Release: Wednesday, July 8, 2009 - * - * 2.5.293 XLUnicodeRichExtendedString - * This structure specifies a Unicode string, which can contain - * formatting information and phoneticstring data. - - * This structure‘s non-variable fields MUST be specified in the same - * record. This structure‘s variable fields can be extended with - * Continue records. A value from the table for fHighByte MUST be - * specified in the first byte of the continue field of the Continue - * record followed by the remaining portions of this structure‘s - * variable fields. - * 1 2 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * cch A B C D reserved2 cRun (optional) - * ... cbExtRst (optional) - * ... rgb (variable) - * ... - * rgRun (variable, optional) - * ... - * ExtRst (variable, optional) - * ... - * cch (2 bytes): An unsigned integer that specifies the count of - * characters in the string. - * - * A - fHighByte (1 bit): A bit that specifies whether the characters - * in rgb are double-byte characters. MUST be a value from the - * following table: - * - * Value Meaning - * 0x0 All the characters in the string have a high byte of 0x00 - * and only the low bytes are in rgb. - * 0x1 All the characters in the string are saved as double-byte - * characters in rgb. - * B - reserved1 (1 bit): MUST be zero, and MUST be ignored. - * C - fExtSt (1 bit): A bit that specifies whether the string - * contains phonetic string data. - * D - fRichSt (1 bit): A bit that specifies whether the string is a - * rich string and the string has at least two character formats - * applied. - * - * reserved2 (4 bits): MUST be zero, and MUST be ignored. - * - * cRun (2 bytes): An optional unsigned integer that specifies the - * number of elements in rgRun. MUST exist if and only if fRichSt is - * 0x1. - * - * cbExtRst (4 bytes): An optional signed integer that specifies the - * byte count of ExtRst. MUST exist if and only if fExtSt is 0x1. MUST - * be zero or greater. - * - * rgb (variable): An array of bytes that specifies the characters in - * the string. If fHighByte is 0x0, the size of the array is cch. If - * fHighByte is 0x1, the size of the array is cch*2. If fHighByte is - * 0x1 and rgb is extended with a Continue record the break MUST occur - * at the double-byte character boundary. - * - * rgRun (variable): An optional array of FormatRun structures that - * specifies the formatting for each text run. The number of elements - * in the array is cRun. MUST exist if and only if fRichSt is 0x1. - * - * ExtRst (variable): An optional ExtRst that specifies the phonetic - * string data. The size of this field is cbExtRst. MUST exist if and - * only if fExtSt is 0x1. - */ -static void -xls_get_extended_record_string (GsfInput *stream, - GArray *list, - gsize *p_bytes_remaining, - GString **p_content) -{ - ExcelExtendedStringRecord *record; - guint32 cst_unique; - guint parsing_record = 0; - guint8 tmp_buffer[4] = { 0 }; - guint i; - guint8 *buffer = NULL; - gsize buffer_size = 0; - - /* Parsing the record from the list */ - record = &g_array_index (list, ExcelExtendedStringRecord, parsing_record); - - /* First record parsing */ - if (gsf_input_seek (stream, record->offset, G_SEEK_SET)) { - return; - } - - /* Note: The first record is ALWAYS the SST, so coming with cst_total and - * cst_unique values. - * Some extra background: Records with data longer than 8,224 bytes MUST be - * split into several records, so in this case, if the SST record is big - * enough, it will have one or more CONTINUE records - * - * SST record: http://msdn.microsoft.com/en-us/library/dd773037%28v=office.12%29.aspx - * CONTINUE record: http://msdn.microsoft.com/en-us/library/dd949081%28v=office.12%29.aspx - **/ - - /* Skip cst total */ - gsf_input_read (stream, 4, tmp_buffer); - - /* Reading cst unique */ - gsf_input_read (stream, 4, tmp_buffer); - cst_unique = read_32bit (tmp_buffer); - - /* Iterate over chunks... - * Loop is halted whenever one of this conditions is met: - * a) Max bytes to be read reached - * b) No more chunks to read - */ - i = 0; - while (*p_bytes_remaining > 0 && - i < cst_unique) { - guint16 cch; - guint16 c_run; - guint16 cb_ext_rst; - gboolean is_high_byte; - gsize chunk_size; - - /* RECORD may have been changed here */ - if (change_excel_record_if_needed (stream, list, &parsing_record) && - parsing_record >= list->len) { - /* When reached max number of records, stop loop */ - break; - } - - /* Reading 2 bytes for cch */ - gsf_input_read (stream, 2, tmp_buffer); - - /* Reading cch - char count of current string */ - cch = read_16bit (tmp_buffer); - - /* Read string flags */ - read_excel_string_flags (stream, - &is_high_byte, - &c_run, - &cb_ext_rst); - - /* RECORD may have been changed here, but it is managed when reading the - * string contents */ - - - /* NOTE: In order to avoid reading unnecessary bytes, limit it based - * on the number of bytes remaining */ - chunk_size = MIN (cch, *p_bytes_remaining); - - /* If High Byte, chunk size *2 as stream is in UTF-16 */ - if (is_high_byte) { - chunk_size *= 2; - } - - /* If the new chunk size is longer than our reused buffer, - * make the buffer bigger */ - if (chunk_size > buffer_size) { - buffer = g_realloc (buffer, chunk_size); - buffer_size = chunk_size; - } - - /* Read the chunk! NOTE that it may be split in several records... */ - if (!read_excel_string (stream, buffer, chunk_size, list, &parsing_record)) { - break; - } - - /* Read whole stream in one operation */ - msoffice_convert_and_normalize_chunk (buffer, - chunk_size, - !is_high_byte, - p_bytes_remaining, - p_content); - - /* Formatting string */ - if (c_run > 0) { - /* rgRun (variable): An optional array of - * FormatRun structures that specifies the - * formatting for each ext run. The number of - * elements in the array is cRun. MUST exist - * if and only if fRichSt is 0x1. - * - * Note: As defined in MSDN, a FormatRun structure has a size - * of 4 bytes, so the size of this rgRun variable is really - * (4*cRun) bytes. - * http://msdn.microsoft.com/en-us/library/dd921712.aspx - * - * Skiping this as it will not be useful in - * our case. - */ - gsf_input_seek (stream, 4 * c_run, G_SEEK_CUR); - /* Note that we may be now out of the current record after having - * done this seek operation. */ - } - - /* ExtString */ - if (cb_ext_rst > 0) { - /* Again its not so clear may be it will not - * useful in our case. - */ - gsf_input_seek (stream, cb_ext_rst, G_SEEK_CUR); - /* Note that we may be now out of the current record after having - * done this seek operation. */ - } - - /* Go to next chunk */ - i++; - } - g_free(buffer); -} - -/** - * @brief Extract excel content from specified infile - * @param infile file to read summary from - * @param n_words number of max words to extract - * @param n_bytes max number of bytes to extract - * @param is_encrypted - * @Notes :- About SST record - * - * This record specifies string constants. - * [MS-XLS] — v20090708 - * Excel Binary File Format (.xls) Structure Specification - * Copyright © 2009 Microsoft Corporation. - * Release: Wednesday, July 8, 2009 - * - * Each string constant in this record has one or more references in - * the workbook, with the goal of improving performance in opening and - * saving the file. The LabelSst record specifies how to make a - * reference to a string in this record. - * 1 2 3 - * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 - * cstTotal - * cstUnique - * rgb (variable) - * ... - * cstTotal (4 bytes): A signed integer that specifies the total - * number of references in the workbook to the strings in the shared - * string table. MUST be greater than or equal to 0. - * - * cstUnique (4 bytes): A signed integer that specifies the number of - * unique strings in the shared string table. MUST be greater than or - * equal to 0. - * - * rgb (variable): An array of XLUnicodeRichExtendedString structures. - * Records in this array are unique. - */ -static gchar* -extract_excel_content (GsfInfile *infile, - gsize n_bytes, - gboolean *is_encrypted) -{ - ExcelBiffHeader header1; - GString *content = NULL; - GsfInput *stream; - guint saved_offset; - gsize n_bytes_remaining = n_bytes; - - /* If no content requested, return */ - if (n_bytes == 0) { - return NULL; - } - - stream = gsf_infile_child_by_name (infile, "Workbook"); - - if (!stream) { - return NULL; - } - - /* Read until we reach eof or any of our limits reached */ - while (n_bytes_remaining > 0 && - !gsf_input_eof (stream)) { - guint8 tmp_buffer[4] = { 0 }; - - /* Reading 4 bytes to read header */ - gsf_input_read (stream, 4, tmp_buffer); - header1.id = read_16bit (tmp_buffer); - header1.length = read_16bit (tmp_buffer + 2); - - /* g_debug ("id: %d , length %d", header.id, header.length); */ - - /* We are interested only in SST record */ - if (header1.id == RECORD_TYPE_SST) { - ExcelExtendedStringRecord record; - ExcelBiffHeader header2; - GArray *list; - guint length = 0; - - /* Saving length and offset so that will - * return to saved once we are done!! - */ - length = header1.length; - saved_offset = gsf_input_tell (stream); - - /* Saving ExtendendString Record offset and - * length. - */ - record.offset = gsf_input_tell (stream); - record.length = length; - - /* g_debug ("record.offset: %u record.length:%d", */ - /* record.offset, record.length); */ - - /* Allocation new array of ExtendendString Record */ - list = g_array_new (TRUE, TRUE, sizeof (ExcelExtendedStringRecord)); - - if (!list) { - break; - } - - g_array_append_val (list, record); - - /* Reading to parse continue record. - * - * Note: we are justing parsing notrequired - * to read data so passing null data - */ - gsf_input_seek (stream, length, G_SEEK_CUR); - - /* Reading & Assigning biff header 4 bytes */ - gsf_input_read (stream, 4, tmp_buffer); - - header2.id = read_16bit (tmp_buffer); - header2.length = read_16bit (tmp_buffer + 2); - - /* g_debug ("bf id :%d length:%d", header2.id, header2.length); */ - /* g_debug ("offset: %u", (guint) gsf_input_tell (stream)); */ - - while (header2.id == RECORD_TYPE_CONTINUE) { - /* Assigning to linkedlist we will use - * it to read data - */ - record.offset = gsf_input_tell (stream); - record.length = header2.length; - g_array_append_val (list, record); - - /* g_debug ("record.offset: %u record.length:%d", */ - /* record.offset, record.length); */ - - /* Then parse the data from the stream */ - gsf_input_seek (stream, header2.length, G_SEEK_CUR); - - /* Reading and assigning biff header */ - gsf_input_read (stream, 4, tmp_buffer); - header2.id = read_16bit (tmp_buffer); - header2.length = read_16bit (tmp_buffer + 2); - - /* g_debug ("bf id :%d length:%d", header2.id, header2.length); */ - }; - - /* Read extended string */ - xls_get_extended_record_string (stream, - list, - &n_bytes_remaining, - &content); - - g_array_unref (list); - - /* Restoring the old_offset */ - gsf_input_seek (stream, saved_offset, G_SEEK_SET); - break; - } - - /* Moving stream pointer to record length */ - if (gsf_input_seek (stream, header1.length, G_SEEK_CUR)) { - break; - } - } - - g_object_unref (stream); - - g_debug ("Bytes extracted: %" G_GSIZE_FORMAT, - n_bytes - n_bytes_remaining); - - return content ? g_string_free (content, FALSE) : NULL; -} - -/** - * @brief Extract summary OLE stream from specified uri - * @param metadata where to store summary - * @param infile file to read summary from - * @param uri uri of the file - */ -static gboolean -extract_summary (TrackerResource *metadata, - GsfInfile *infile, - const gchar *uri) -{ - GsfInput *stream; - - stream = gsf_infile_child_by_name (infile, "\05SummaryInformation"); - - if (stream) { - GsfDocMetaData *md; - MetadataInfo info; - GError *error = NULL; - - md = gsf_doc_meta_data_new (); - error = gsf_doc_meta_data_read_from_msole (md, stream); - - if (error) { - g_warning ("Could not extract summary information, %s", - error->message ? error->message : "no error given"); - - g_error_free (error); - g_object_unref (md); - g_object_unref (stream); - gsf_shutdown (); - - return FALSE; - } - - info.metadata = metadata; - info.uri = uri; - - gsf_doc_meta_data_foreach (md, summary_metadata_cb, &info); - - g_object_unref (md); - g_object_unref (stream); - } - - stream = gsf_infile_child_by_name (infile, "\05DocumentSummaryInformation"); - - if (stream) { - GsfDocMetaData *md; - MetadataInfo info; - GError *error = NULL; - - md = gsf_doc_meta_data_new (); - - error = gsf_doc_meta_data_read_from_msole (md, stream); - if (error) { - g_warning ("Could not extract document summary information, %s", - error->message ? error->message : "no error given"); - - g_error_free (error); - g_object_unref (md); - g_object_unref (stream); - gsf_shutdown (); - - return FALSE; - } - - info.metadata = metadata; - info.uri = uri; - - gsf_doc_meta_data_foreach (md, document_metadata_cb, &info); - - g_object_unref (md); - g_object_unref (stream); - } - - return TRUE; -} - -/** - * @brief Extract data from generic office files - * - * At the moment only extracts document summary from summary OLE stream. - * @param uri URI of the file to extract data - * @param metadata where to store extracted data to - */ -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerResource *metadata; - TrackerConfig *config; - GsfInfile *infile = NULL; - gchar *content = NULL, *uri; - gboolean is_encrypted = FALSE; - const gchar *mime_used; - gsize max_bytes; - GFile *file; - gchar *filename; - FILE *mfile; - - gsf_init (); - - mime_used = tracker_extract_info_get_mimetype (info); - - file = tracker_extract_info_get_file (info); - uri = g_file_get_uri (file); - - filename = g_filename_from_uri (uri, NULL, NULL); - - mfile = tracker_file_open (filename); - g_free (filename); - - if (!mfile) { - g_warning ("Can't open file from uri '%s': %s", - uri, g_strerror (errno)); - g_free (uri); - return FALSE; - } - - infile = open_file (uri, mfile); - if (!infile) { - gsf_shutdown (); - g_free (uri); - if (mfile) { - tracker_file_close (mfile, FALSE); - } - return FALSE; - } - - metadata = tracker_resource_new (NULL); - - tracker_resource_add_uri (metadata, "rdf:type", "nfo:PaginatedTextDocument"); - - /* Extracting summary */ - extract_summary (metadata, infile, uri); - - /* Set max bytes to read from content */ - config = tracker_main_get_config (); - max_bytes = tracker_config_get_max_bytes (config); - - if (g_ascii_strcasecmp (mime_used, "application/msword") == 0) { - /* Word file */ - content = extract_msword_content (infile, max_bytes, &is_encrypted); - } else if (g_ascii_strcasecmp (mime_used, "application/vnd.ms-powerpoint") == 0) { - /* PowerPoint file */ - tracker_resource_add_uri (metadata, "rdf:type", "nfo:Presentation"); - - content = extract_powerpoint_content (infile, max_bytes, &is_encrypted); - } else if (g_ascii_strcasecmp (mime_used, "application/vnd.ms-excel") == 0) { - /* Excel File */ - tracker_resource_add_uri(metadata, "rdf:type", "nfo:Spreadsheet"); - - content = extract_excel_content (infile, max_bytes, &is_encrypted); - } else { - g_message ("Mime type was not recognised:'%s'", mime_used); - } - - if (content) { - tracker_resource_set_string (metadata, "nie:plainTextContent", content); - g_free (content); - } - - if (is_encrypted) { - tracker_resource_set_boolean (metadata, "nfo:isContentEncrypted", TRUE); - } - - g_object_unref (infile); - g_free (uri); - gsf_shutdown (); - if (mfile) { - tracker_file_close (mfile, FALSE); - } - - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-oasis.c b/src/tracker-extract/tracker-extract-oasis.c deleted file mode 100644 index 704dd2ac5..000000000 --- a/src/tracker-extract/tracker-extract-oasis.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <libtracker-common/tracker-common.h> - -#include <libtracker-extract/tracker-extract.h> - -#include "tracker-main.h" -#include "tracker-gsf.h" -#include "tracker-read.h" - -#include <unistd.h> - -typedef enum { - ODT_TAG_TYPE_UNKNOWN, - ODT_TAG_TYPE_TITLE, - ODT_TAG_TYPE_SUBJECT, - ODT_TAG_TYPE_AUTHOR, - ODT_TAG_TYPE_KEYWORDS, - ODT_TAG_TYPE_COMMENTS, - ODT_TAG_TYPE_STATS, - ODT_TAG_TYPE_CREATED, - ODT_TAG_TYPE_GENERATOR, - ODT_TAG_TYPE_WORD_TEXT, - ODT_TAG_TYPE_SLIDE_TEXT, - ODT_TAG_TYPE_SPREADSHEET_TEXT, - ODT_TAG_TYPE_GRAPHICS_TEXT -} ODTTagType; - -typedef enum { - FILE_TYPE_INVALID, - FILE_TYPE_ODP, - FILE_TYPE_ODT, - FILE_TYPE_ODS, - FILE_TYPE_ODG -} ODTFileType; - -typedef struct { - TrackerResource *metadata; - ODTTagType current; - const gchar *uri; - guint has_title : 1; - guint has_subject : 1; - guint has_publisher : 1; - guint has_comment : 1; - guint has_generator : 1; - guint has_word_count : 1; - guint has_page_count : 1; - guint has_content_created : 1; -} ODTMetadataParseInfo; - -typedef struct { - ODTTagType current; - ODTFileType file_type; - GString *content; - gulong bytes_pending; -} ODTContentParseInfo; - -GQuark maximum_size_error_quark = 0; - -static void xml_start_element_handler_metadata (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error); -static void xml_end_element_handler_metadata (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error); -static void xml_text_handler_metadata (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error); -static void xml_start_element_handler_content (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error); -static void xml_end_element_handler_content (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error); -static void xml_text_handler_content (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error); -static void extract_oasis_content (const gchar *uri, - gulong total_bytes, - ODTFileType file_type, - TrackerResource *metadata); - -static void -extract_oasis_content (const gchar *uri, - gulong total_bytes, - ODTFileType file_type, - TrackerResource *metadata) -{ - gchar *content = NULL; - ODTContentParseInfo info; - GMarkupParseContext *context; - GError *error = NULL; - GMarkupParser parser = { - xml_start_element_handler_content, - xml_end_element_handler_content, - xml_text_handler_content, - NULL, - NULL - }; - - /* If no content requested, return */ - if (total_bytes == 0) { - return; - } - - /* Create parse info */ - info.current = ODT_TAG_TYPE_UNKNOWN; - info.file_type = file_type; - info.content = g_string_new (""); - info.bytes_pending = total_bytes; - - /* Create parsing context */ - context = g_markup_parse_context_new (&parser, 0, &info, NULL); - - /* Load the internal XML file from the Zip archive, and parse it - * using the given context */ - tracker_gsf_parse_xml_in_zip (uri, "content.xml", context, &error); - - if (!error || g_error_matches (error, maximum_size_error_quark, 0)) { - content = g_string_free (info.content, FALSE); - tracker_resource_set_string (metadata, "nie:plainTextContent", content); - } else { - g_warning ("Got error parsing XML file: %s\n", error->message); - g_string_free (info.content, TRUE); - } - - if (error) { - g_error_free (error); - } - - g_free (content); - g_markup_parse_context_free (context); -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *extract_info) -{ - TrackerResource *metadata; - TrackerConfig *config; - ODTMetadataParseInfo info = { 0 }; - ODTFileType file_type; - GFile *file; - gchar *uri; - const gchar *mime_used; - GMarkupParseContext *context; - GMarkupParser parser = { - xml_start_element_handler_metadata, - xml_end_element_handler_metadata, - xml_text_handler_metadata, - NULL, - NULL - }; - - if (G_UNLIKELY (maximum_size_error_quark == 0)) { - maximum_size_error_quark = g_quark_from_static_string ("maximum_size_error"); - } - - metadata = tracker_resource_new (NULL); - mime_used = tracker_extract_info_get_mimetype (extract_info); - - file = tracker_extract_info_get_file (extract_info); - uri = g_file_get_uri (file); - - /* Setup conf */ - config = tracker_main_get_config (); - - g_debug ("Extracting OASIS metadata and contents from '%s'", uri); - - /* First, parse metadata */ - - tracker_resource_add_uri (metadata, "rdf:type", "nfo:PaginatedTextDocument"); - - /* Create parse info */ - info.metadata = metadata; - info.current = ODT_TAG_TYPE_UNKNOWN; - info.uri = uri; - - /* Create parsing context */ - context = g_markup_parse_context_new (&parser, 0, &info, NULL); - - /* Load the internal XML file from the Zip archive, and parse it - * using the given context */ - tracker_gsf_parse_xml_in_zip (uri, "meta.xml", context, NULL); - g_markup_parse_context_free (context); - - if (g_ascii_strcasecmp (mime_used, "application/vnd.oasis.opendocument.text") == 0) { - file_type = FILE_TYPE_ODT; - } else if (g_ascii_strcasecmp (mime_used, "application/vnd.oasis.opendocument.presentation") == 0) { - file_type = FILE_TYPE_ODP; - } else if (g_ascii_strcasecmp (mime_used, "application/vnd.oasis.opendocument.spreadsheet") == 0) { - file_type = FILE_TYPE_ODS; - } else if (g_ascii_strcasecmp (mime_used, "application/vnd.oasis.opendocument.graphics") == 0) { - file_type = FILE_TYPE_ODG; - } else { - g_message ("Mime type was not recognised:'%s'", mime_used); - file_type = FILE_TYPE_INVALID; - } - - /* Extract content with the given limitations */ - extract_oasis_content (uri, - tracker_config_get_max_bytes (config), - file_type, - metadata); - - g_free (uri); - - tracker_extract_info_set_resource (extract_info, metadata); - g_object_unref (metadata); - - return TRUE; -} - -static void -xml_start_element_handler_metadata (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - ODTMetadataParseInfo *data = user_data; - - if (g_ascii_strcasecmp (element_name, "dc:title") == 0) { - data->current = ODT_TAG_TYPE_TITLE; - } else if (g_ascii_strcasecmp (element_name, "dc:subject") == 0) { - data->current = ODT_TAG_TYPE_SUBJECT; - } else if (g_ascii_strcasecmp (element_name, "dc:creator") == 0) { - data->current = ODT_TAG_TYPE_AUTHOR; - } else if (g_ascii_strcasecmp (element_name, "meta:keyword") == 0) { - data->current = ODT_TAG_TYPE_KEYWORDS; - } else if (g_ascii_strcasecmp (element_name, "dc:description") == 0) { - data->current = ODT_TAG_TYPE_COMMENTS; - } else if (g_ascii_strcasecmp (element_name, "meta:document-statistic") == 0) { - TrackerResource *metadata; - const gchar **a, **v; - - metadata = data->metadata; - - for (a = attribute_names, v = attribute_values; *a; ++a, ++v) { - if (g_ascii_strcasecmp (*a, "meta:word-count") == 0) { - if (data->has_word_count) { - g_warning ("Avoiding additional word count (%s) in OASIS document '%s'", - *v, data->uri); - } else { - data->has_word_count = TRUE; - tracker_resource_set_string (metadata, "nfo:wordCount", *v); - } - } else if (g_ascii_strcasecmp (*a, "meta:page-count") == 0) { - if (data->has_page_count) { - g_warning ("Avoiding additional page count (%s) in OASIS document '%s'", - *v, data->uri); - } else { - data->has_page_count = TRUE; - tracker_resource_set_string (metadata, "nfo:pageCount", *v); - } - } - } - - data->current = ODT_TAG_TYPE_STATS; - } else if (g_ascii_strcasecmp (element_name, "meta:creation-date") == 0) { - data->current = ODT_TAG_TYPE_CREATED; - } else if (g_ascii_strcasecmp (element_name, "meta:generator") == 0) { - data->current = ODT_TAG_TYPE_GENERATOR; - } else { - data->current = -1; - } -} - -static void -xml_end_element_handler_metadata (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - ((ODTMetadataParseInfo*) user_data)->current = -1; -} - -static void -xml_text_handler_metadata (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - ODTMetadataParseInfo *data; - TrackerResource *metadata; - gchar *date; - - data = user_data; - metadata = data->metadata; - - if (text_len == 0) { - /* ignore empty values */ - return; - } - - switch (data->current) { - case ODT_TAG_TYPE_TITLE: - if (data->has_title) { - g_warning ("Avoiding additional title (%s) in OASIS document '%s'", - text, data->uri); - } else { - data->has_title = TRUE; - tracker_resource_set_string (metadata, "nie:title", text); - } - break; - - case ODT_TAG_TYPE_SUBJECT: - if (data->has_subject) { - g_warning ("Avoiding additional subject (%s) in OASIS document '%s'", - text, data->uri); - } else { - data->has_subject = TRUE; - tracker_resource_set_string (metadata, "nie:subject", text); - } - break; - - case ODT_TAG_TYPE_AUTHOR: - if (data->has_publisher) { - g_warning ("Avoiding additional publisher (%s) in OASIS document '%s'", - text, data->uri); - } else { - TrackerResource *publisher = tracker_extract_new_contact (text); - - data->has_publisher = TRUE; - tracker_resource_set_relation (metadata, "nco:publisher", publisher); - - g_object_unref (publisher); - } - break; - - case ODT_TAG_TYPE_KEYWORDS: { - gchar *keywords; - gchar *lasts, *keyw; - - keywords = g_strdup (text); - - for (keyw = strtok_r (keywords, ",; ", &lasts); - keyw; - keyw = strtok_r (NULL, ",; ", &lasts)) { - tracker_resource_add_string (metadata, "nie:keyword", keyw); - } - - g_free (keywords); - - break; - } - - case ODT_TAG_TYPE_COMMENTS: - if (data->has_comment) { - g_warning ("Avoiding additional comment (%s) in OASIS document '%s'", - text, data->uri); - } else { - data->has_comment = TRUE; - tracker_resource_set_string (metadata, "nie:comment", text); - } - break; - - case ODT_TAG_TYPE_CREATED: - if (data->has_content_created) { - g_warning ("Avoiding additional creation time (%s) in OASIS document '%s'", - text, data->uri); - } else { - date = tracker_date_guess (text); - if (date) { - data->has_content_created = TRUE; - tracker_resource_set_string (metadata, "nie:contentCreated", date); - g_free (date); - } else { - g_warning ("Could not parse creation time (%s) in OASIS document '%s'", - text, data->uri); - } - } - break; - - case ODT_TAG_TYPE_GENERATOR: - if (data->has_generator) { - g_warning ("Avoiding additional creation time (%s) in OASIS document '%s'", - text, data->uri); - } else { - data->has_generator = TRUE; - tracker_resource_set_string (metadata, "nie:generator", text); - } - break; - - default: - case ODT_TAG_TYPE_STATS: - break; - } -} - -static void -xml_start_element_handler_content (GMarkupParseContext *context, - const gchar *element_name, - const gchar **attribute_names, - const gchar **attribute_values, - gpointer user_data, - GError **error) -{ - ODTContentParseInfo *data = user_data; - - switch (data->file_type) { - case FILE_TYPE_ODT: - if ((g_ascii_strcasecmp (element_name, "text:p") == 0) || - (g_ascii_strcasecmp (element_name, "text:h") == 0) || - (g_ascii_strcasecmp (element_name, "text:a") == 0) || - (g_ascii_strcasecmp (element_name, "text:span") == 0) || - (g_ascii_strcasecmp (element_name, "table:table-cell") == 0) || - (g_ascii_strcasecmp (element_name, "text:s") == 0) || - (g_ascii_strcasecmp (element_name, "text:tab") == 0) || - (g_ascii_strcasecmp (element_name, "text:line-break") == 0)) { - data->current = ODT_TAG_TYPE_WORD_TEXT; - } else { - data->current = -1; - } - break; - - case FILE_TYPE_ODP: - data->current = ODT_TAG_TYPE_SLIDE_TEXT; - break; - - case FILE_TYPE_ODS: - if (g_ascii_strncasecmp (element_name, "text", 4) == 0) { - data->current = ODT_TAG_TYPE_SPREADSHEET_TEXT; - } else { - data->current = -1; - } - break; - - case FILE_TYPE_ODG: - if (g_ascii_strncasecmp (element_name, "text", 4) == 0) { - data->current = ODT_TAG_TYPE_GRAPHICS_TEXT; - } else { - data->current = -1; - } - break; - - case FILE_TYPE_INVALID: - g_message ("Open Office Document type: %d invalid", data->file_type); - break; - } -} - -static void -xml_end_element_handler_content (GMarkupParseContext *context, - const gchar *element_name, - gpointer user_data, - GError **error) -{ - ODTContentParseInfo *data = user_data; - - /* Don't stop processing if it was a so-called 'empty' tag (e.g. <text:tab/>) */ - if (!((g_ascii_strcasecmp (element_name, "text:s") == 0) || - (g_ascii_strcasecmp (element_name, "text:tab") == 0) || - (g_ascii_strcasecmp (element_name, "text:line-break") == 0))) { - data->current = -1; - } - -} - -static void -xml_text_handler_content (GMarkupParseContext *context, - const gchar *text, - gsize text_len, - gpointer user_data, - GError **error) -{ - ODTContentParseInfo *data = user_data; - gsize written_bytes = 0; - - switch (data->current) { - case ODT_TAG_TYPE_WORD_TEXT: - case ODT_TAG_TYPE_SLIDE_TEXT: - case ODT_TAG_TYPE_SPREADSHEET_TEXT: - case ODT_TAG_TYPE_GRAPHICS_TEXT: - if (data->bytes_pending == 0) { - g_set_error_literal (error, - maximum_size_error_quark, 0, - "Maximum text limit reached"); - break; - } - - /* Look for valid UTF-8 text */ - if (tracker_text_validate_utf8 (text, - MIN (text_len, data->bytes_pending), - &data->content, - &written_bytes)) { - if (data->content->str[data->content->len - 1] != ' ') { - /* If some bytes found to be valid, append an extra whitespace - * as separator */ - g_string_append_c (data->content, ' '); - } - } - - data->bytes_pending -= written_bytes; - break; - - default: - break; - } -} diff --git a/src/tracker-extract/tracker-extract-pdf.c b/src/tracker-extract/tracker-extract-pdf.c deleted file mode 100644 index acce7c840..000000000 --- a/src/tracker-extract/tracker-extract-pdf.c +++ /dev/null @@ -1,622 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008-2011, Nokia <ivan.frade@nokia.com> - * Copyright (C) 2010, Amit Aggarwal <amitcs06@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <sys/mman.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/select.h> -#include <sys/wait.h> -#include <errno.h> -#include <fcntl.h> -#include <string.h> -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> - -#include <glib.h> -#include <glib/gstdio.h> -#include <glib/poppler.h> - -#include <gio/gunixoutputstream.h> -#include <gio/gunixinputstream.h> - -#include <libtracker-common/tracker-date-time.h> -#include <libtracker-common/tracker-utils.h> -#include <libtracker-common/tracker-file-utils.h> - -#include <libtracker-extract/tracker-extract.h> - -#include "tracker-main.h" - -/* Time in seconds before we stop processing content */ -#define EXTRACTION_PROCESS_TIMEOUT 10 - -typedef struct { - gchar *title; - gchar *subject; - gchar *creation_date; - gchar *author; - gchar *date; - gchar *keywords; -} PDFData; - -static void -read_toc (PopplerIndexIter *index, - GString **toc) -{ - if (!index) { - return; - } - - if (!*toc) { - *toc = g_string_new (""); - } - - do { - PopplerAction *action; - PopplerIndexIter *iter; - - action = poppler_index_iter_get_action (index); - - if (!action) { - continue; - } - - switch (action->type) { - case POPPLER_ACTION_GOTO_DEST: { - PopplerActionGotoDest *ag = (PopplerActionGotoDest *)action; - PopplerDest *agd = ag->dest; - - if (!tracker_is_empty_string (ag->title)) { - g_string_append_printf (*toc, "%s ", ag->title); - } - - if (!tracker_is_empty_string (agd->named_dest)) { - g_string_append_printf (*toc, "%s ", agd->named_dest); - } - - break; - } - - case POPPLER_ACTION_LAUNCH: { - PopplerActionLaunch *al = (PopplerActionLaunch *)action; - - if (!tracker_is_empty_string (al->title)) { - g_string_append_printf (*toc, "%s ", al->title); - } - - if (!tracker_is_empty_string (al->file_name)) { - g_string_append_printf (*toc, "%s ", al->file_name); - } - - if (!tracker_is_empty_string (al->params)) { - g_string_append_printf (*toc, "%s ", al->params); - } - - break; - } - - case POPPLER_ACTION_URI: { - PopplerActionUri *au = (PopplerActionUri *)action; - - if (!tracker_is_empty_string (au->uri)) { - g_string_append_printf (*toc, "%s ", au->uri); - } - - break; - } - - case POPPLER_ACTION_NAMED: { - PopplerActionNamed *an = (PopplerActionNamed *)action; - - if (!tracker_is_empty_string (an->title)) { - g_string_append_printf (*toc, "%s, ", an->title); - } - - if (!tracker_is_empty_string (an->named_dest)) { - g_string_append_printf (*toc, "%s ", an->named_dest); - } - - break; - } - - case POPPLER_ACTION_MOVIE: { - PopplerActionMovie *am = (PopplerActionMovie *)action; - - if (!tracker_is_empty_string (am->title)) { - g_string_append_printf (*toc, "%s ", am->title); - } - - break; - } - - case POPPLER_ACTION_NONE: - case POPPLER_ACTION_UNKNOWN: - case POPPLER_ACTION_GOTO_REMOTE: - case POPPLER_ACTION_RENDITION: - case POPPLER_ACTION_OCG_STATE: - case POPPLER_ACTION_JAVASCRIPT: - /* Do nothing */ - break; - } - - poppler_action_free (action); - iter = poppler_index_iter_get_child (index); - read_toc (iter, toc); - } while (poppler_index_iter_next (index)); - - poppler_index_iter_free (index); -} - -static void -read_outline (PopplerDocument *document, - TrackerResource *metadata) -{ - PopplerIndexIter *index; - GString *toc = NULL; - - index = poppler_index_iter_new (document); - - if (!index) { - return; - } - - read_toc (index, &toc); - - if (toc) { - if (toc->len > 0) { - tracker_resource_set_string (metadata, "nfo:tableOfContents", toc->str); - } - - g_string_free (toc, TRUE); - } -} - -static gchar * -extract_content_text (PopplerDocument *document, - gsize n_bytes) -{ - GString *string; - GTimer *timer; - gsize remaining_bytes; - gint n_pages, i; - gdouble elapsed; - - n_pages = poppler_document_get_n_pages (document); - string = g_string_new (""); - timer = g_timer_new (); - - for (i = 0, remaining_bytes = n_bytes, elapsed = g_timer_elapsed (timer, NULL); - i < n_pages && remaining_bytes > 0 && elapsed < EXTRACTION_PROCESS_TIMEOUT; - i++, elapsed = g_timer_elapsed (timer, NULL)) { - PopplerPage *page; - gsize written_bytes = 0; - gchar *text; - - page = poppler_document_get_page (document, i); - text = poppler_page_get_text (page); - - if (!text) { - g_object_unref (page); - continue; - } - - if (tracker_text_validate_utf8 (text, - MIN (strlen (text), remaining_bytes), - &string, - &written_bytes)) { - g_string_append_c (string, ' '); - } - - remaining_bytes -= written_bytes; - - g_debug ("Extracted %" G_GSIZE_FORMAT " bytes from page %d, " - "%" G_GSIZE_FORMAT " bytes remaining", - written_bytes, i, remaining_bytes); - - g_free (text); - g_object_unref (page); - } - - if (elapsed >= EXTRACTION_PROCESS_TIMEOUT) { - g_debug ("Extraction timed out, %d seconds reached", EXTRACTION_PROCESS_TIMEOUT); - } - - g_debug ("Content extraction finished: %d/%d pages indexed in %2.2f seconds, " - "%" G_GSIZE_FORMAT " bytes extracted", - i, - n_pages, - g_timer_elapsed (timer, NULL), - (n_bytes - remaining_bytes)); - - g_timer_destroy (timer); - - return g_string_free (string, FALSE); -} - -static void -write_pdf_data (PDFData data, - TrackerResource *metadata, - GPtrArray *keywords) -{ - if (!tracker_is_empty_string (data.title)) { - tracker_resource_set_string (metadata, "nie:title", data.title); - } - - if (!tracker_is_empty_string (data.subject)) { - tracker_resource_set_string (metadata, "nie:subject", data.subject); - } - - if (!tracker_is_empty_string (data.author)) { - TrackerResource *author = tracker_extract_new_contact (data.author); - tracker_resource_set_relation (metadata, "nco:creator", author); - g_object_unref (author); - } - - if (!tracker_is_empty_string (data.date)) { - tracker_resource_set_string (metadata, "nie:contentCreated", data.date); - } - - if (!tracker_is_empty_string (data.keywords)) { - tracker_keywords_parse (keywords, data.keywords); - } -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerConfig *config; - GTime creation_date; - GError *error = NULL; - TrackerResource *metadata; - TrackerXmpData *xd = NULL; - PDFData pd = { 0 }; /* actual data */ - PDFData md = { 0 }; /* for merging */ - PopplerDocument *document; - gchar *xml = NULL; - gchar *content, *uri; - guint n_bytes; - GPtrArray *keywords; - guint i; - GFile *file; - gchar *filename; - int fd; - gchar *contents = NULL; - gsize len; - struct stat st; - - file = tracker_extract_info_get_file (info); - filename = g_file_get_path (file); - - fd = tracker_file_open_fd (filename); - - if (fd == -1) { - g_warning ("Could not open pdf file '%s': %s\n", - filename, - g_strerror (errno)); - g_free (filename); - return FALSE; - } - - if (fstat (fd, &st) == -1) { - g_warning ("Could not fstat pdf file '%s': %s\n", - filename, - g_strerror (errno)); - close (fd); - g_free (filename); - return FALSE; - } - - if (st.st_size == 0) { - contents = NULL; - len = 0; - } else { - contents = (gchar *) mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (contents == NULL || contents == MAP_FAILED) { - g_warning ("Could not mmap pdf file '%s': %s\n", - filename, - g_strerror (errno)); - close (fd); - g_free (filename); - return FALSE; - } - len = st.st_size; - } - - g_free (filename); - uri = g_file_get_uri (file); - - document = poppler_document_new_from_data (contents, len, NULL, &error); - - if (error) { - if (error->code == POPPLER_ERROR_ENCRYPTED) { - metadata = tracker_resource_new (NULL); - - tracker_resource_add_uri (metadata, "rdf:type", "nfo:PaginatedTextDocument"); - tracker_resource_set_boolean (metadata, "nfo:isContentEncrypted", TRUE); - - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - - g_error_free (error); - g_free (uri); - close (fd); - - return TRUE; - } else { - g_warning ("Couldn't create PopplerDocument from uri:'%s', %s", - uri, - error->message ? error->message : "no error given"); - - g_error_free (error); - g_free (uri); - close (fd); - - return FALSE; - } - } - - if (!document) { - g_warning ("Could not create PopplerDocument from uri:'%s', " - "NULL returned without an error", - uri); - g_free (uri); - close (fd); - return FALSE; - } - - metadata = tracker_resource_new (NULL); - tracker_resource_add_uri (metadata, "rdf:type", "nfo:PaginatedTextDocument"); - - g_object_get (document, - "title", &pd.title, - "author", &pd.author, - "subject", &pd.subject, - "keywords", &pd.keywords, - "creation-date", &creation_date, - "metadata", &xml, - NULL); - - if (creation_date > 0) { - pd.creation_date = tracker_date_to_string ((time_t) creation_date); - } - - keywords = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); - - if (xml && *xml && - (xd = tracker_xmp_new (xml, strlen (xml), uri)) != NULL) { - /* The casts here are well understood and known */ - md.title = (gchar *) tracker_coalesce_strip (4, pd.title, xd->title, xd->title2, xd->pdf_title); - md.subject = (gchar *) tracker_coalesce_strip (2, pd.subject, xd->subject); - md.date = (gchar *) tracker_coalesce_strip (3, pd.creation_date, xd->date, xd->time_original); - md.author = (gchar *) tracker_coalesce_strip (2, pd.author, xd->creator); - - write_pdf_data (md, metadata, keywords); - - if (xd->keywords) { - tracker_keywords_parse (keywords, xd->keywords); - } - - if (xd->pdf_keywords) { - tracker_keywords_parse (keywords, xd->pdf_keywords); - } - - if (xd->publisher) { - TrackerResource *publisher = tracker_extract_new_contact (xd->publisher); - tracker_resource_set_relation (metadata, "nco:publisher", publisher); - g_object_unref (publisher); - } - - if (xd->type) { - tracker_resource_set_string (metadata, "dc:type", xd->type); - } - - if (xd->format) { - tracker_resource_set_string (metadata, "dc:format", xd->format); - } - - if (xd->identifier) { - tracker_resource_set_string (metadata, "dc:identifier", xd->identifier); - } - - if (xd->source) { - tracker_resource_set_string (metadata, "dc:source", xd->source); - } - - if (xd->language) { - tracker_resource_set_string (metadata, "dc:language", xd->language); - } - - if (xd->relation) { - tracker_resource_set_string (metadata, "dc:relation", xd->relation); - } - - if (xd->coverage) { - tracker_resource_set_string (metadata, "dc:coverage", xd->coverage); - } - - if (xd->license) { - tracker_resource_set_string (metadata, "nie:license", xd->license); - } - - if (xd->make || xd->model) { - TrackerResource *equipment = tracker_extract_new_equipment (xd->make, xd->model); - tracker_resource_set_relation (metadata, "nfo:equipment", equipment); - g_object_unref (equipment); - } - - if (xd->orientation) { - TrackerResource *orientation; - - orientation = tracker_resource_new (xd->orientation); - tracker_resource_set_relation (metadata, "nfo:orientation", orientation); - g_object_unref (orientation); - } - - if (xd->rights) { - tracker_resource_set_string (metadata, "nie:copyright", xd->rights); - } - - if (xd->white_balance) { - TrackerResource *white_balance; - - white_balance = tracker_resource_new (xd->white_balance); - tracker_resource_set_relation (metadata, "nmm:meteringMode", white_balance); - g_object_unref (white_balance); - } - - if (xd->fnumber) { - gdouble value; - - value = g_strtod (xd->fnumber, NULL); - tracker_resource_set_double (metadata, "nmm:fnumber", value); - } - - if (xd->flash) { - TrackerResource *flash; - - flash = tracker_resource_new (xd->flash); - tracker_resource_set_relation (metadata, "nmm:flash", flash); - g_object_unref (flash); - } - - if (xd->focal_length) { - gdouble value; - - value = g_strtod (xd->focal_length, NULL); - tracker_resource_set_double (metadata, "nmm:focalLength", value); - } - - /* Question: Shouldn't xd->Artist be merged with md.author instead? */ - - if (xd->artist || xd->contributor) { - TrackerResource *artist; - const gchar *artist_name; - - artist_name = tracker_coalesce_strip (2, xd->artist, xd->contributor); - - artist = tracker_extract_new_contact (artist_name); - - tracker_resource_set_relation (metadata, "nco:contributor", artist); - - g_object_unref (artist); - } - - if (xd->exposure_time) { - gdouble value; - - value = g_strtod (xd->exposure_time, NULL); - tracker_resource_set_double (metadata, "nmm:exposureTime", value); - } - - if (xd->iso_speed_ratings) { - gdouble value; - - value = g_strtod (xd->iso_speed_ratings, NULL); - tracker_resource_set_double (metadata, "nmm:isoSpeed", value); - } - - if (xd->description) { - tracker_resource_set_string (metadata, "nie:description", xd->description); - } - - if (xd->metering_mode) { - TrackerResource *metering; - - metering = tracker_resource_new (xd->metering_mode); - tracker_resource_set_relation (metadata, "nmm:meteringMode", metering); - g_object_unref (metering); - } - - if (xd->address || xd->state || xd->country || xd->city || - xd->gps_altitude || xd->gps_latitude || xd-> gps_longitude) { - - TrackerResource *location = tracker_extract_new_location (xd->address, - xd->state, xd->city, xd->country, xd->gps_altitude, - xd->gps_latitude, xd->gps_longitude); - - tracker_resource_set_relation (metadata, "slo:location", location); - - g_object_unref (location); - } - - if (xd->regions) { - tracker_xmp_apply_regions_to_resource (metadata, xd); - } - - tracker_xmp_free (xd); - } else { - /* So if we are here we have NO XMP data and we just - * write what we know from Poppler. - */ - write_pdf_data (pd, metadata, keywords); - } - - for (i = 0; i < keywords->len; i++) { - TrackerResource *tag; - const gchar *p; - - p = g_ptr_array_index (keywords, i); - tag = tracker_extract_new_tag (p); - - tracker_resource_add_relation (metadata, "nao:hasTag", tag); - - g_object_unref (tag); - } - g_ptr_array_free (keywords, TRUE); - - tracker_resource_set_int64 (metadata, "nfo:pageCount", poppler_document_get_n_pages(document)); - - config = tracker_main_get_config (); - n_bytes = tracker_config_get_max_bytes (config); - content = extract_content_text (document, n_bytes); - - if (content) { - tracker_resource_set_string (metadata, "nie:plainTextContent", content); - g_free (content); - } - - read_outline (document, metadata); - - g_free (xml); - g_free (pd.keywords); - g_free (pd.title); - g_free (pd.subject); - g_free (pd.creation_date); - g_free (pd.author); - g_free (pd.date); - g_free (uri); - - g_object_unref (document); - - if (contents) { - munmap (contents, len); - } - - close (fd); - - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-persistence.c b/src/tracker-extract/tracker-extract-persistence.c deleted file mode 100644 index 1dc542736..000000000 --- a/src/tracker-extract/tracker-extract-persistence.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (C) 2014 Carlos Garnacho <carlosg@gnome.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "tracker-extract-persistence.h" - -#define MAX_RETRIES 3 - -typedef struct _TrackerExtractPersistencePrivate TrackerExtractPersistencePrivate; - -struct _TrackerExtractPersistencePrivate -{ - GFile *tmp_dir; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (TrackerExtractPersistence, tracker_extract_persistence, G_TYPE_OBJECT) - -static GQuark n_retries_quark = 0; - -static void -tracker_extract_persistence_class_init (TrackerExtractPersistenceClass *klass) -{ - n_retries_quark = g_quark_from_static_string ("tracker-extract-n-retries-quark"); -} - -static void -tracker_extract_persistence_init (TrackerExtractPersistence *persistence) -{ - TrackerExtractPersistencePrivate *priv; - gchar *dirname, *tmp_path; - - priv = tracker_extract_persistence_get_instance_private (persistence); - - dirname = g_strdup_printf ("tracker-extract-files.%d", getuid ()); - tmp_path = g_build_filename (g_get_tmp_dir (), dirname, NULL); - g_free (dirname); - - if (g_mkdir_with_parents (tmp_path, 0700) != 0) { - g_critical ("The directory %s could not be created, or has the wrong permissions", - tmp_path); - g_assert_not_reached (); - } - - priv->tmp_dir = g_file_new_for_path (tmp_path); - g_free (tmp_path); -} - -static void -increment_n_retries (GFile *file) -{ - guint n_retries; - - n_retries = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (file), n_retries_quark)); - g_object_set_qdata (G_OBJECT (file), n_retries_quark, GUINT_TO_POINTER (n_retries + 1)); -} - -static GFile * -persistence_create_symlink_file (TrackerExtractPersistence *persistence, - GFile *file) -{ - TrackerExtractPersistencePrivate *priv; - guint n_retries = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (file), n_retries_quark)); - gchar *link_name, *path, *md5; - GFile *link_file; - - priv = tracker_extract_persistence_get_instance_private (persistence); - path = g_file_get_path (file); - md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, path, -1); - link_name = g_strdup_printf ("%d-%s", n_retries, md5); - link_file = g_file_get_child (priv->tmp_dir, link_name); - - g_free (link_name); - g_free (path); - g_free (md5); - - return link_file; -} - -static GFile * -persistence_symlink_get_file (GFileInfo *info) -{ - const gchar *symlink_name, *symlink_target; - gchar *md5, **items; - GFile *file = NULL; - guint n_retries; - - symlink_name = g_file_info_get_name (info); - symlink_target = g_file_info_get_symlink_target (info); - - if (!g_path_is_absolute (symlink_target)) { - g_critical ("Symlink paths must be absolute, '%s' points to '%s'", - symlink_name, symlink_target); - return NULL; - } - - md5 = g_compute_checksum_for_string (G_CHECKSUM_MD5, symlink_target, -1); - items = g_strsplit (symlink_name, "-", 2); - n_retries = g_strtod (items[0], NULL); - - if (g_strcmp0 (items[1], md5) == 0) { - file = g_file_new_for_path (symlink_target); - g_object_set_qdata (G_OBJECT (file), n_retries_quark, - GUINT_TO_POINTER (n_retries)); - } else { - g_critical ("path MD5 for '%s' doesn't match with symlink '%s'", - symlink_target, symlink_name); - } - - g_strfreev (items); - g_free (md5); - - return file; -} - -static gboolean -persistence_store_file (TrackerExtractPersistence *persistence, - GFile *file) -{ - GError *error = NULL; - gboolean success; - GFile *link_file; - gchar *path; - - increment_n_retries (file); - path = g_file_get_path (file); - link_file = persistence_create_symlink_file (persistence, file); - - success = g_file_make_symbolic_link (link_file, path, NULL, &error); - - if (!success) { - g_warning ("Could not save '%s' into failsafe persistence store: %s", - path, error ? error->message : "no error given"); - g_clear_error (&error); - } - - g_object_unref (link_file); - g_free (path); - - return success; -} - -static gboolean -persistence_remove_file (TrackerExtractPersistence *persistence, - GFile *file) -{ - GError *error = NULL; - GFile *link_file; - gboolean success; - - link_file = persistence_create_symlink_file (persistence, file); - success = g_file_delete (link_file, NULL, &error); - - if (!success) { - gchar *path = g_file_get_path (file); - - g_warning ("Could not delete '%s' from failsafe persistence store", - path); - g_free (path); - } - - g_object_unref (link_file); - - return success; -} - -static void -persistence_retrieve_files (TrackerExtractPersistence *persistence, - TrackerFileRecoveryFunc retry_func, - TrackerFileRecoveryFunc ignore_func, - gpointer user_data) -{ - TrackerExtractPersistencePrivate *priv; - GFileEnumerator *enumerator; - GFileInfo *info; - - priv = tracker_extract_persistence_get_instance_private (persistence); - enumerator = g_file_enumerate_children (priv->tmp_dir, - G_FILE_ATTRIBUTE_STANDARD_NAME "," - G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, NULL); - if (!enumerator) - return; - - while ((info = g_file_enumerator_next_file (enumerator, NULL, NULL)) != NULL) { - GFile *file, *symlink_file; - guint n_retries; - - symlink_file = g_file_enumerator_get_child (enumerator, info); - file = persistence_symlink_get_file (info); - - if (!file) { - /* If we got here, persistence_symlink_get_file() already emitted a g_critical */ - g_object_unref (symlink_file); - g_object_unref (info); - continue; - } - - /* Delete the symlink, it will get probably added back soon after, - * and n_retries incremented. - */ - g_file_delete (symlink_file, NULL, NULL); - g_object_unref (symlink_file); - - n_retries = GPOINTER_TO_UINT (g_object_get_qdata (G_OBJECT (file), n_retries_quark)); - - /* Trigger retry/ignore func for the symlink target */ - if (n_retries >= MAX_RETRIES) { - ignore_func (file, user_data); - } else { - retry_func (file, user_data); - } - - g_object_unref (file); - g_object_unref (info); - } - - g_file_enumerator_close (enumerator, NULL, NULL); - g_object_unref (enumerator); -} - -TrackerExtractPersistence * -tracker_extract_persistence_initialize (TrackerFileRecoveryFunc retry_func, - TrackerFileRecoveryFunc ignore_func, - gpointer user_data) -{ - static TrackerExtractPersistence *persistence = NULL; - - if (!persistence) { - persistence = g_object_new (TRACKER_TYPE_EXTRACT_PERSISTENCE, - NULL); - persistence_retrieve_files (persistence, - retry_func, ignore_func, - user_data); - } - - return persistence; -} - -void -tracker_extract_persistence_add_file (TrackerExtractPersistence *persistence, - GFile *file) -{ - g_return_if_fail (TRACKER_IS_EXTRACT_PERSISTENCE (persistence)); - g_return_if_fail (G_IS_FILE (file)); - - persistence_store_file (persistence, file); -} - -void -tracker_extract_persistence_remove_file (TrackerExtractPersistence *persistence, - GFile *file) -{ - g_return_if_fail (TRACKER_IS_EXTRACT_PERSISTENCE (persistence)); - g_return_if_fail (G_IS_FILE (file)); - - persistence_remove_file (persistence, file); -} diff --git a/src/tracker-extract/tracker-extract-persistence.h b/src/tracker-extract/tracker-extract-persistence.h deleted file mode 100644 index d5474af0d..000000000 --- a/src/tracker-extract/tracker-extract-persistence.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2014 Carlos Garnacho <carlosg@gnome.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_EXTRACT_PERSISTENCE_H__ -#define __TRACKER_EXTRACT_PERSISTENCE_H__ - -#include <gio/gio.h> - -G_BEGIN_DECLS - -#define TRACKER_TYPE_EXTRACT_PERSISTENCE (tracker_extract_persistence_get_type ()) -#define TRACKER_EXTRACT_PERSISTENCE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_EXTRACT_PERSISTENCE, TrackerExtractPersistence)) -#define TRACKER_EXTRACT_PERSISTENCE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_EXTRACT_PERSISTENCE, TrackerExtractPersistenceClass)) -#define TRACKER_IS_EXTRACT_PERSISTENCE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_EXTRACT_PERSISTENCE)) -#define TRACKER_IS_EXTRACT_PERSISTENCE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_EXTRACT_PERSISTENCE)) -#define TRACKER_EXTRACT_PERSISTENCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_EXTRACT_PERSISTENCE, TrackerExtractPersistenceClass)) - -typedef struct _TrackerExtractPersistence TrackerExtractPersistence; -typedef struct _TrackerExtractPersistenceClass TrackerExtractPersistenceClass; - -typedef void (* TrackerFileRecoveryFunc) (GFile *file, - gpointer user_data); - -struct _TrackerExtractPersistence -{ - GObject parent_instance; -}; - -struct _TrackerExtractPersistenceClass -{ - GObjectClass parent_class; -}; - -GType tracker_extract_persistence_get_type (void) G_GNUC_CONST; - -TrackerExtractPersistence * - tracker_extract_persistence_initialize (TrackerFileRecoveryFunc retry_func, - TrackerFileRecoveryFunc ignore_func, - gpointer user_data); - -void tracker_extract_persistence_add_file (TrackerExtractPersistence *persistence, - GFile *file); -void tracker_extract_persistence_remove_file (TrackerExtractPersistence *persistence, - GFile *file); - -G_END_DECLS - -#endif /* __TRACKER_EXTRACT_PERSISTENCE_H__ */ diff --git a/src/tracker-extract/tracker-extract-playlist.c b/src/tracker-extract/tracker-extract-playlist.c deleted file mode 100644 index 943b1ce17..000000000 --- a/src/tracker-extract/tracker-extract-playlist.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (C) 2007, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <string.h> -#include <stdlib.h> - -#include <glib.h> -#include <glib/gstdio.h> -#include <gio/gio.h> - -#include <totem-pl-parser.h> - -#include <libtracker-extract/tracker-extract.h> -#include <libtracker-extract/tracker-guarantee.h> - -#define PLAYLIST_PROPERTY_NO_TRACKS "entryCounter" -#define PLAYLIST_PROPERTY_DURATION "listDuration" -/* - FIXME Decide what to do with this in nepomuk - #define PLAYLIST_PROPERTY_CALCULATED "Playlist:ValidDuration" -*/ - -#define PLAYLIST_DEFAULT_NO_TRACKS 0 -#define PLAYLIST_DEFAULT_DURATION 0 - -typedef struct { - guint32 track_counter; - gint64 total_time; - gchar *title; - TrackerResource *metadata; -} PlaylistMetadata; - -static void -playlist_started (TotemPlParser *parser, - gchar *to_uri, - TotemPlParserMetadata *to_metadata, - gpointer user_data) -{ - PlaylistMetadata *data; - - data = (PlaylistMetadata *) user_data; - - /* Avoid looking up every time */ - data->title = g_strdup (g_hash_table_lookup (to_metadata, TOTEM_PL_PARSER_FIELD_TITLE)); -} - -static void -entry_parsed (TotemPlParser *parser, - gchar *to_uri, - GHashTable *to_metadata, - gpointer user_data) -{ - TrackerResource *entry; - PlaylistMetadata *data; - - data = (PlaylistMetadata *) user_data; - data->track_counter++; - - if (data->track_counter > 1000) { - /* limit playlists to 1000 entries for query performance reasons */ - g_message ("Playlist has > 1000 entries. Ignoring for performance reasons."); - return; - } - - entry = tracker_resource_new (NULL); - tracker_resource_set_uri (entry, "rdf:type", "nfo:MediaFileListEntry"); - tracker_resource_set_string (entry, "nfo:entryUrl", to_uri); - tracker_resource_set_int (entry, "nfo:listPosition", data->track_counter); - - if (data->track_counter == 1) { - /* This causes all existing relations to be deleted, when we serialize - * to SPARQL. */ - tracker_resource_set_relation (data->metadata, "nfo:hasMediaFileListEntry", entry); - } else { - tracker_resource_add_relation (data->metadata, "nfo:hasMediaFileListEntry", entry); - } - g_object_unref (entry); - - if (to_metadata) { - gchar *duration; - - duration = g_hash_table_lookup (to_metadata, TOTEM_PL_PARSER_FIELD_DURATION); - - if (duration == NULL) { - duration = g_hash_table_lookup (to_metadata, TOTEM_PL_PARSER_FIELD_DURATION_MS); - } - - if (duration != NULL) { - gint64 secs = totem_pl_parser_parse_duration (duration, FALSE); - - if (secs > 0) { - data->total_time += secs; - } - } - } -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TotemPlParser *pl; - TrackerResource *metadata; - PlaylistMetadata data; - GFile *file; - gchar *uri; - - pl = totem_pl_parser_new (); - file = tracker_extract_info_get_file (info); - uri = g_file_get_uri (file); - - metadata = data.metadata = tracker_resource_new (NULL); - - data.track_counter = PLAYLIST_DEFAULT_NO_TRACKS; - data.total_time = PLAYLIST_DEFAULT_DURATION; - data.title = NULL; - - g_object_set (pl, "recurse", FALSE, "disable-unsafe", TRUE, NULL); - - g_signal_connect (G_OBJECT (pl), "playlist-started", G_CALLBACK (playlist_started), &data); - g_signal_connect (G_OBJECT (pl), "entry-parsed", G_CALLBACK (entry_parsed), &data); - - tracker_resource_add_uri (metadata, "rdf:type", "nmm:Playlist"); - tracker_resource_add_uri (metadata, "rdf:type", "nfo:MediaList"); - - if (totem_pl_parser_parse (pl, uri, FALSE) == TOTEM_PL_PARSER_RESULT_SUCCESS) { - if (data.title != NULL) { - g_message ("Playlist title:'%s'", data.title); - tracker_resource_set_string (metadata, "nie:title", data.title); - g_free (data.title); - } else { - g_message ("Playlist has no title, attempting to get one from filename"); - tracker_guarantee_resource_title_from_file (metadata, "nie:title", NULL, uri, NULL); - } - - if (data.total_time > 0) { - tracker_resource_set_int64 (metadata, "nfo:listDuration", data.total_time); - } - - if (data.track_counter > 0) { - tracker_resource_set_int64 (metadata, "nfo:entryCounter", data.track_counter); - } - } else { - g_warning ("Playlist could not be parsed, no error given"); - } - - g_object_unref (pl); - g_free (uri); - - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-png.c b/src/tracker-extract/tracker-extract-png.c deleted file mode 100644 index 0e1976541..000000000 --- a/src/tracker-extract/tracker-extract-png.c +++ /dev/null @@ -1,729 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <png.h> - -#include <libtracker-common/tracker-file-utils.h> -#include <libtracker-common/tracker-date-time.h> -#include <libtracker-extract/tracker-extract.h> - -#define RFC1123_DATE_FORMAT "%d %B %Y %H:%M:%S %z" -#define CM_TO_INCH 0.393700787 - -typedef struct { - const gchar *title; - const gchar *copyright; - const gchar *creator; - const gchar *description; - const gchar *date; - const gchar *license; - const gchar *artist; - const gchar *make; - const gchar *model; - const gchar *orientation; - const gchar *white_balance; - const gchar *fnumber; - const gchar *flash; - const gchar *focal_length; - const gchar *exposure_time; - const gchar *iso_speed_ratings; - const gchar *metering_mode; - const gchar *comment; - const gchar *city; - const gchar *state; - const gchar *address; - const gchar *country; - const gchar *gps_direction; -} MergeData; - -typedef struct { - const gchar *author; - const gchar *creator; - const gchar *description; - const gchar *comment; - const gchar *copyright; - gchar *creation_time; - const gchar *title; - const gchar *disclaimer; - const gchar *software; -} PngData; - -static gchar * -rfc1123_to_iso8601_date (const gchar *date) -{ - /* From: ex. RFC1123 date: "22 May 1997 18:07:10 -0600" - * To : ex. ISO8601 date: "2007-05-22T18:07:10-0600" - */ - return tracker_date_format_to_iso8601 (date, RFC1123_DATE_FORMAT); -} - -#if defined(PNG_iTXt_SUPPORTED) && (defined(HAVE_EXEMPI) || defined(HAVE_LIBEXIF)) - -/* Handle raw profiles by Imagemagick (at least). Hex encoded with - * line-changes and other (undocumented/unofficial) twists. - */ -static gchar * -raw_profile_new (const gchar *input, - const guint input_length, - guint *output_length) -{ - static const gchar* const lut = "0123456789abcdef"; - gchar *output; - const gchar *ptr; - const gchar *length_ptr; - gsize size; - gchar *length_str; - guint length; - - size_t len; - size_t i; - size_t o; - char *p; - char *q; - - ptr = input; - - if (*ptr != '\n') { - return NULL; - } - - ptr++; - - if (!g_ascii_isalpha (*ptr)) { - return NULL; - } - - /* Skip the type string */ - do { - ptr++; - } while (g_ascii_isalpha (*ptr)); - - if (*ptr != '\n') { - return NULL; - } - - /* Hop over whitespaces */ - do { - ptr++; - } while (*ptr == ' '); - - if (!g_ascii_isdigit (*ptr)) { - return NULL; - } - - /* Get the length string */ - length_ptr = ptr; - size = 1; - - do { - ptr++; - size++; - } while (g_ascii_isdigit (*ptr)); - - length_str = g_strndup (length_ptr, size - 1); - - if (*ptr != '\n') { - return NULL; - } - - ptr++; - - length = atoi (length_str); - g_free (length_str); - - len = length; - i = 0; - o = 0; - - output = malloc (length + 1); /* A bit less with non-valid */ - - o = 0; - while (o < len) { - do { - gchar a = ptr[i]; - p = strchr (lut, a); - i++; - } while (p == 0); - - do { - gchar b = ptr[i]; - q = strchr (lut, b); - i++; - } while (q == 0); - - output[o] = (((p - lut) << 4) | (q - lut)); - o++; - } - - output[o] = '\0'; - *output_length = o; - - return output; -} - -#endif /* defined(PNG_iTXt_SUPPORTED) && (defined(HAVE_EXEMPI) || defined(HAVE_LIBEXIF)) */ - -static void -read_metadata (TrackerResource *metadata, - png_structp png_ptr, - png_infop info_ptr, - png_infop end_ptr, - const gchar *uri) -{ - MergeData md = { 0 }; - PngData pd = { 0 }; - TrackerExifData *ed = NULL; - TrackerXmpData *xd = NULL; - png_infop info_ptrs[2]; - png_textp text_ptr; - gint info_index; - gint num_text; - gint i; - gint found; - GPtrArray *keywords; - - info_ptrs[0] = info_ptr; - info_ptrs[1] = end_ptr; - - for (info_index = 0; info_index < 2; info_index++) { - if ((found = png_get_text (png_ptr, info_ptrs[info_index], &text_ptr, &num_text)) < 1) { - g_debug ("Calling png_get_text() returned %d (< 1)", found); - continue; - } - - for (i = 0; i < num_text; i++) { - if (!text_ptr[i].key || !text_ptr[i].text || text_ptr[i].text[0] == '\0') { - continue; - } - -#if defined(HAVE_EXEMPI) && defined(PNG_iTXt_SUPPORTED) - if (g_strcmp0 ("XML:com.adobe.xmp", text_ptr[i].key) == 0) { - /* ATM tracker_extract_xmp_read supports setting xd - * multiple times, keep it that way as here it's - * theoretically possible that the function gets - * called multiple times - */ - xd = tracker_xmp_new (text_ptr[i].text, - text_ptr[i].itxt_length, - uri); - - continue; - } - - if (g_strcmp0 ("Raw profile type xmp", text_ptr[i].key) == 0) { - gchar *xmp_buffer; - guint xmp_buffer_length = 0; - guint input_len; - - if (text_ptr[i].text_length) { - input_len = text_ptr[i].text_length; - } else { - input_len = text_ptr[i].itxt_length; - } - - xmp_buffer = raw_profile_new (text_ptr[i].text, - input_len, - &xmp_buffer_length); - - if (xmp_buffer) { - xd = tracker_xmp_new (xmp_buffer, - xmp_buffer_length, - uri); - } - - g_free (xmp_buffer); - - continue; - } -#endif /*HAVE_EXEMPI && PNG_iTXt_SUPPORTED */ - -#if defined(HAVE_LIBEXIF) && defined(PNG_iTXt_SUPPORTED) - if (g_strcmp0 ("Raw profile type exif", text_ptr[i].key) == 0) { - gchar *exif_buffer; - guint exif_buffer_length = 0; - guint input_len; - - if (text_ptr[i].text_length) { - input_len = text_ptr[i].text_length; - } else { - input_len = text_ptr[i].itxt_length; - } - - exif_buffer = raw_profile_new (text_ptr[i].text, - input_len, - &exif_buffer_length); - - if (exif_buffer) { - ed = tracker_exif_new (exif_buffer, - exif_buffer_length, - uri); - } - - g_free (exif_buffer); - - continue; - } -#endif /* HAVE_LIBEXIF && PNG_iTXt_SUPPORTED */ - - if (g_strcmp0 (text_ptr[i].key, "Author") == 0) { - pd.author = text_ptr[i].text; - continue; - } - - if (g_strcmp0 (text_ptr[i].key, "Creator") == 0) { - pd.creator = text_ptr[i].text; - continue; - } - - if (g_strcmp0 (text_ptr[i].key, "Description") == 0) { - pd.description = text_ptr[i].text; - continue; - } - - if (g_strcmp0 (text_ptr[i].key, "Comment") == 0) { - pd.comment = text_ptr[i].text; - continue; - } - - if (g_strcmp0 (text_ptr[i].key, "Copyright") == 0) { - pd.copyright = text_ptr[i].text; - continue; - } - - if (g_strcmp0 (text_ptr[i].key, "Creation Time") == 0) { - pd.creation_time = rfc1123_to_iso8601_date (text_ptr[i].text); - continue; - } - - if (g_strcmp0 (text_ptr[i].key, "Title") == 0) { - pd.title = text_ptr[i].text; - continue; - } - - if (g_strcmp0 (text_ptr[i].key, "Disclaimer") == 0) { - pd.disclaimer = text_ptr[i].text; - continue; - } - - if (g_strcmp0(text_ptr[i].key, "Software") == 0) { - pd.software = text_ptr[i].text; - continue; - } - } - } - - if (!ed) { - ed = g_new0 (TrackerExifData, 1); - } - - if (!xd) { - xd = g_new0 (TrackerXmpData, 1); - } - - md.creator = tracker_coalesce_strip (3, xd->creator, pd.creator, pd.author); - md.title = tracker_coalesce_strip (5, xd->title, pd.title, ed->document_name, xd->title2, xd->pdf_title); - md.copyright = tracker_coalesce_strip (3, xd->rights, pd.copyright, ed->copyright); - md.license = tracker_coalesce_strip (2, xd->license, pd.disclaimer); - md.description = tracker_coalesce_strip (3, xd->description, pd.description, ed->description); - md.date = tracker_coalesce_strip (5, xd->date, xd->time_original, pd.creation_time, ed->time, ed->time_original); - md.comment = tracker_coalesce_strip (2, pd.comment, ed->user_comment); - md.artist = tracker_coalesce_strip (3, xd->artist, ed->artist, xd->contributor); - md.orientation = tracker_coalesce_strip (2, xd->orientation, ed->orientation); - md.exposure_time = tracker_coalesce_strip (2, xd->exposure_time, ed->exposure_time); - md.iso_speed_ratings = tracker_coalesce_strip (2, xd->iso_speed_ratings, ed->iso_speed_ratings); - md.fnumber = tracker_coalesce_strip (2, xd->fnumber, ed->fnumber); - md.flash = tracker_coalesce_strip (2, xd->flash, ed->flash); - md.focal_length = tracker_coalesce_strip (2, xd->focal_length, ed->focal_length); - md.metering_mode = tracker_coalesce_strip (2, xd->metering_mode, ed->metering_mode); - md.white_balance = tracker_coalesce_strip (2, xd->white_balance, ed->white_balance); - md.make = tracker_coalesce_strip (2, xd->make, ed->make); - md.model = tracker_coalesce_strip (2, xd->model, ed->model); - - keywords = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); - - if (md.comment) { - tracker_resource_set_string (metadata, "nie:comment", md.comment); - } - - if (md.license) { - tracker_resource_set_string (metadata, "nie:license", md.license); - } - - /* TODO: add ontology and store this ed->software */ - - if (md.creator) { - TrackerResource *creator = tracker_extract_new_contact (md.creator); - - tracker_resource_set_relation (metadata, "nco:creator", creator); - - g_object_unref (creator); - } - - tracker_guarantee_resource_date_from_file_mtime (metadata, - "nie:contentCreated", - md.date, - uri); - - if (md.description) { - tracker_resource_set_string (metadata, "nie:description", md.description); - } - - if (md.copyright) { - tracker_resource_set_string (metadata, "nie:copyright", md.copyright); - } - - tracker_guarantee_resource_title_from_file (metadata, - "nie:title", - md.title, - uri, - NULL); - - if (md.make || md.model) { - TrackerResource *equipment = tracker_extract_new_equipment (md.make, md.model); - - tracker_resource_set_relation (metadata, "nfo:equipment", equipment); - - g_object_unref (equipment); - } - - if (md.artist) { - TrackerResource *artist = tracker_extract_new_contact (md.artist); - - tracker_resource_set_relation (metadata, "nco:contributor", artist); - - g_object_unref (artist); - } - - if (md.orientation) { - TrackerResource *orientation; - - orientation = tracker_resource_new (md.orientation); - tracker_resource_set_relation (metadata, "nfo:orientation", orientation); - g_object_unref (orientation); - } - - if (md.exposure_time) { - tracker_resource_set_string (metadata, "nmm:exposureTime", md.exposure_time); - } - - if (md.iso_speed_ratings) { - tracker_resource_set_string (metadata, "nmm:isoSpeed", md.iso_speed_ratings); - } - - if (md.white_balance) { - TrackerResource *white_balance; - - white_balance = tracker_resource_new (md.white_balance); - tracker_resource_set_relation (metadata, "nmm:meteringMode", white_balance); - g_object_unref (white_balance); - } - - if (md.fnumber) { - tracker_resource_set_string (metadata, "nmm:fnumber", md.fnumber); - } - - if (md.flash) { - TrackerResource *flash; - - flash = tracker_resource_new (md.flash); - tracker_resource_set_relation (metadata, "nmm:flash", flash); - g_object_unref (flash); - } - - if (md.focal_length) { - tracker_resource_set_string (metadata, "nmm:focalLength", md.focal_length); - } - - if (md.metering_mode) { - TrackerResource *metering; - - metering = tracker_resource_new (md.metering_mode); - tracker_resource_set_relation (metadata, "nmm:meteringMode", metering); - g_object_unref (metering); - } - - if (xd->keywords) { - tracker_keywords_parse (keywords, xd->keywords); - } - - if (xd->pdf_keywords) { - tracker_keywords_parse (keywords, xd->pdf_keywords); - } - - if (xd->rating) { - tracker_resource_set_string (metadata, "nao:numericRating", xd->rating); - } - - if (xd->subject) { - tracker_keywords_parse (keywords, xd->subject); - } - - if (xd->publisher) { - TrackerResource *publisher = tracker_extract_new_contact (xd->publisher); - - tracker_resource_set_relation (metadata, "nco:creator", publisher); - - g_object_unref (publisher); - } - - if (xd->type) { - tracker_resource_set_string (metadata, "dc:type", xd->type); - } - - if (xd->format) { - tracker_resource_set_string (metadata, "dc:format", xd->format); - } - - if (xd->identifier) { - tracker_resource_set_string (metadata, "dc:identifier", xd->identifier); - } - - if (xd->source) { - tracker_resource_set_string (metadata, "dc:source", xd->source); - } - - if (xd->language) { - tracker_resource_set_string (metadata, "dc:language", xd->language); - } - - if (xd->relation) { - tracker_resource_set_string (metadata, "dc:relation", xd->relation); - } - - if (xd->coverage) { - tracker_resource_set_string (metadata, "dc:coverage", xd->coverage); - } - - if (xd->address || xd->state || xd->country || xd->city || - xd->gps_altitude || xd->gps_latitude || xd-> gps_longitude) { - - TrackerResource *location = tracker_extract_new_location (xd->address, - xd->state, xd->city, xd->country, xd->gps_altitude, - xd->gps_latitude, xd-> gps_longitude); - - tracker_resource_set_relation (metadata, "slo:location", location); - - g_object_unref (location); - } - - if (xd->gps_direction) { - tracker_resource_set_string(metadata, "nfo:heading", xd->gps_direction); - } - - if (ed->x_resolution) { - gdouble value; - - value = ed->resolution_unit != 3 ? g_strtod (ed->x_resolution, NULL) : g_strtod (ed->x_resolution, NULL) * CM_TO_INCH; - tracker_resource_set_double (metadata, "nfo:horizontalResolution", value); - } - - if (ed->y_resolution) { - gdouble value; - - value = ed->resolution_unit != 3 ? g_strtod (ed->y_resolution, NULL) : g_strtod (ed->y_resolution, NULL) * CM_TO_INCH; - tracker_resource_set_double (metadata, "nfo:verticalResolution", value); - } - - if (xd->regions) { - tracker_xmp_apply_regions_to_resource (metadata, xd); - } - - for (i = 0; i < keywords->len; i++) { - TrackerResource *tag; - const gchar *p; - - p = g_ptr_array_index (keywords, i); - - tag = tracker_extract_new_tag (p); - - tracker_resource_set_relation (metadata, "nao:hasTag", tag); - - g_object_unref (tag); - } - g_ptr_array_free (keywords, TRUE); - - if (g_strcmp0(pd.software, "gnome-screenshot") == 0) { - tracker_resource_add_uri (metadata, "nie:isPartOf", "nfo:image-category-screenshot"); - } - - tracker_exif_free (ed); - tracker_xmp_free (xd); - g_free (pd.creation_time); -} - -static gboolean -guess_dlna_profile (gint depth, - gint width, - gint height, - const gchar **dlna_profile, - const gchar **dlna_mimetype) -{ - const gchar *profile = NULL; - - if (dlna_profile) { - *dlna_profile = NULL; - } - - if (dlna_mimetype) { - *dlna_mimetype = NULL; - } - - if (width == 120 && height == 120) { - profile = "PNG_LRG_ICO"; - } else if (width == 48 && height == 48) { - profile = "PNG_SM_ICO"; - } else if (width <= 160 && height <= 160) { - profile = "PNG_TN"; - } else if (depth <= 32 && width <= 4096 && height <= 4096) { - profile = "PNG_LRG"; - } - - if (profile) { - if (dlna_profile) { - *dlna_profile = profile; - } - - if (dlna_mimetype) { - *dlna_mimetype = "image/png"; - } - - return TRUE; - } - - return FALSE; -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerResource *metadata; - goffset size; - FILE *f; - png_structp png_ptr; - png_infop info_ptr; - png_infop end_ptr; - png_bytep row_data; - guint row; - png_uint_32 width, height; - gint bit_depth, color_type; - gint interlace_type, compression_type, filter_type; - const gchar *dlna_profile, *dlna_mimetype; - gchar *filename, *uri; - GFile *file; - - file = tracker_extract_info_get_file (info); - filename = g_file_get_path (file); - size = tracker_file_get_size (filename); - - if (size < 64) { - return FALSE; - } - - f = tracker_file_open (filename); - g_free (filename); - - if (!f) { - return FALSE; - } - - png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, - NULL, - NULL, - NULL); - if (!png_ptr) { - tracker_file_close (f, FALSE); - return FALSE; - } - - info_ptr = png_create_info_struct (png_ptr); - if (!info_ptr) { - png_destroy_read_struct (&png_ptr, NULL, NULL); - tracker_file_close (f, FALSE); - return FALSE; - } - - end_ptr = png_create_info_struct (png_ptr); - if (!end_ptr) { - png_destroy_read_struct (&png_ptr, &info_ptr, NULL); - tracker_file_close (f, FALSE); - return FALSE; - } - - if (setjmp (png_jmpbuf (png_ptr))) { - png_destroy_read_struct (&png_ptr, &info_ptr, &end_ptr); - tracker_file_close (f, FALSE); - return FALSE; - } - - png_init_io (png_ptr, f); - png_read_info (png_ptr, info_ptr); - - if (!png_get_IHDR (png_ptr, - info_ptr, - &width, - &height, - &bit_depth, - &color_type, - &interlace_type, - &compression_type, - &filter_type)) { - png_destroy_read_struct (&png_ptr, &info_ptr, &end_ptr); - tracker_file_close (f, FALSE); - return FALSE; - } - - /* Read the image. FIXME We should be able to skip this step and - * just get the info from the end. This causes some errors atm. - */ - row_data = png_malloc (png_ptr, png_get_rowbytes (png_ptr, info_ptr)); - for (row = 0; row < height; row++) - png_read_row (png_ptr, row_data, NULL); - png_free (png_ptr, row_data); - - png_read_end (png_ptr, end_ptr); - - metadata = tracker_resource_new (NULL); - - tracker_resource_add_uri (metadata, "rdf:type", "nfo:Image"); - tracker_resource_add_uri (metadata, "rdf:type", "nmm:Photo"); - - uri = g_file_get_uri (file); - - read_metadata (metadata, png_ptr, info_ptr, end_ptr, uri); - g_free (uri); - - tracker_resource_set_int64 (metadata, "nfo:width", width); - tracker_resource_set_int64 (metadata, "nfo:height", height); - - if (guess_dlna_profile (bit_depth, width, height, &dlna_profile, &dlna_mimetype)) { - tracker_resource_set_string (metadata, "nmm:dlnaProfile", dlna_profile); - tracker_resource_set_string (metadata, "nmm:dlnaMime", dlna_mimetype); - } - - png_destroy_read_struct (&png_ptr, &info_ptr, &end_ptr); - tracker_file_close (f, FALSE); - - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-priority.xml b/src/tracker-extract/tracker-extract-priority.xml deleted file mode 100644 index 2220177cb..000000000 --- a/src/tracker-extract/tracker-extract-priority.xml +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<node name="/"> - <interface name="org.freedesktop.Tracker1.Extract.Priority"> - <method name="SetRdfTypes"> - <arg type="as" name="rdf_types" direction="in" /> - </method> - <method name="ClearRdfTypes" /> - <property name="SupportedRdfTypes" type="as" access="read" /> - </interface> -</node> diff --git a/src/tracker-extract/tracker-extract-ps.c b/src/tracker-extract/tracker-extract-ps.c deleted file mode 100644 index f360f7e14..000000000 --- a/src/tracker-extract/tracker-extract-ps.c +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright (C) 2007, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008-2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <fcntl.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> - -#include <glib.h> -#include <glib/gstdio.h> - -#include <libtracker-common/tracker-common.h> -#include <libtracker-extract/tracker-extract.h> - -static gchar * -hour_day_str_day (const gchar *date) -{ - /* From: ex. date: "(18:07 Tuesday 22 May 2007)" - * To : ex. ISO8601 date: "2007-05-22T18:07:10-0600" - */ - return tracker_date_format_to_iso8601 (date, "(%H:%M %A %d %B %Y)"); -} - -static gchar * -day_str_month_day (const gchar *date) -{ - /* From: ex. date: "Tue May 22 18:07:10 2007" - * To : ex. ISO8601 date: "2007-05-22T18:07:10-0600" - */ - return tracker_date_format_to_iso8601 (date, "%A %B %d %H:%M:%S %Y"); -} - -static gchar * -day_month_year_date (const gchar *date) -{ - /* From: ex. date: "22 May 1997 18:07:10 -0600" - * To : ex. ISO8601 date: "2007-05-22T18:07:10-0600" - */ - return tracker_date_format_to_iso8601 (date, "%d %B %Y %H:%M:%S %z"); -} - -static gchar * -hour_month_day_date (const gchar *date) -{ - /* From: ex. date: "6:07 PM May 22, 2007" - * To : ex. ISO8601 date: "2007-05-22T18:07:10-0600" - */ - return tracker_date_format_to_iso8601 (date, "%I:%M %p %B %d, %Y"); -} - -static gchar * -date_to_iso8601 (const gchar *date) -{ - if (date && date[1] && date[2]) { - if (date[0] == '(') { - /* we have probably a date like - * "(18:07 Tuesday 22 May 2007)" - */ - return hour_day_str_day (date); - } else if (g_ascii_isalpha (date[0])) { - /* we have probably a date like - * "Tue May 22 18:07:10 2007" - */ - return day_str_month_day (date); - - } else if (date[1] == ' ' || date[2] == ' ') { - /* we have probably a date like - * "22 May 1997 18:07:10 -0600" - */ - return day_month_year_date (date); - - } else if (date[1] == ':' || date[2] == ':') { - /* we have probably a date like - * "6:07 PM May 22, 2007" - */ - return hour_month_day_date (date); - } - } - - return NULL; -} - -static TrackerResource * -extract_ps_from_filestream (FILE *f) -{ - TrackerResource *metadata; - gchar *line; - gsize length; - gssize read_char; - gsize accum; - gsize max_bytes; - - line = NULL; - length = 0; - - metadata = tracker_resource_new (NULL); - tracker_resource_add_uri (metadata, "rdf:type", "nfo:PaginatedTextDocument"); - - /* 20 MiB should be enough! (original safe limit) */ - accum = 0; - max_bytes = 20u << 20; - - /* Reuse the same buffer for all lines. Must be dynamically allocated with - * malloc family methods as getline() may re-size it with realloc() */ - length = 1024; - line = g_malloc (length); - - /* Halt the whole when one of these conditions is met: - * a) Reached max bytes to read - * b) No more lines to read - */ - while ((accum < max_bytes) && - (read_char = tracker_getline (&line, &length, f)) != -1) { - gboolean pageno_atend = FALSE; - gboolean header_finished = FALSE; - - /* Update accumulated bytes read */ - accum += read_char; - - line[read_char - 1] = '\0'; /* overwrite '\n' char */ - - if (!header_finished && strncmp (line, "%%Copyright:", 12) == 0) { - tracker_resource_set_string (metadata, "nie:copyright", line + 13); - } else if (!header_finished && strncmp (line, "%%Title:", 8) == 0) { - tracker_resource_set_string (metadata, "nie:title", line + 9); - } else if (!header_finished && strncmp (line, "%%Creator:", 10) == 0) { - TrackerResource *creator = tracker_extract_new_contact (line + 11); - tracker_resource_set_relation (metadata, "nco:creator", creator); - g_object_unref (creator); - } else if (!header_finished && strncmp (line, "%%CreationDate:", 15) == 0) { - gchar *date; - - date = date_to_iso8601 (line + 16); - if (date) { - tracker_resource_set_string (metadata, "nie:contentCreated", date); - g_free (date); - } - } else if (strncmp (line, "%%Pages:", 8) == 0) { - if (strcmp (line + 9, "(atend)") == 0) { - pageno_atend = TRUE; - } else { - gint64 page_count; - - page_count = g_ascii_strtoll (line + 9, NULL, 10); - tracker_resource_set_int (metadata, "nfo:pageCount", page_count); - } - } else if (strncmp (line, "%%EndComments", 14) == 0) { - header_finished = TRUE; - - if (!pageno_atend) { - break; - } - } - } - - /* Deallocate the buffer */ - if (line) { - g_free (line); - } - - return metadata; -} - - - -static TrackerResource * -extract_ps (const gchar *uri) -{ - TrackerResource *metadata; - FILE *f; - gchar *filename; - - filename = g_filename_from_uri (uri, NULL, NULL); - f = tracker_file_open (filename); - g_free (filename); - - if (!f) { - return NULL; - } - - /* Extract from filestream! */ - g_debug ("Extracting PS '%s'...", uri); - metadata = extract_ps_from_filestream (f); - - tracker_file_close (f, FALSE); - - return metadata; -} - -#ifdef USING_UNZIPPSFILES - -#include <errno.h> -#include <sys/time.h> -#include <sys/resource.h> - -static void -spawn_child_func (gpointer user_data) -{ - struct rlimit cpu_limit; - gint timeout = GPOINTER_TO_INT (user_data); - - if (timeout > 0) { - /* set cpu limit */ - getrlimit (RLIMIT_CPU, &cpu_limit); - cpu_limit.rlim_cur = timeout; - cpu_limit.rlim_max = timeout + 1; - - if (setrlimit (RLIMIT_CPU, &cpu_limit) != 0) { - g_critical ("Failed to set resource limit for CPU"); - } - - /* Have this as a precaution in cases where cpu limit has not - * been reached due to spawned app sleeping. - */ - alarm (timeout + 2); - } - - /* Set child's niceness to 19 */ - errno = 0; - - /* nice() uses attribute "warn_unused_result" and so complains - * if we do not check its returned value. But it seems that - * since glibc 2.2.4, nice() can return -1 on a successful call - * so we have to check value of errno too. Stupid... - */ - if (nice (19) == -1 && errno) { - g_warning ("Failed to set nice value"); - } -} - -static TrackerResource * -extract_ps_gz (const gchar *uri) -{ - TrackerResource *metadata = NULL; - FILE *fz; - gint fdz; - const gchar *argv[4]; - gchar *filename; - GError *error = NULL; - - filename = g_filename_from_uri (uri, NULL, NULL); - - /* TODO: we should be using libz for this instead */ - - argv[0] = "gunzip"; - argv[1] = "-c"; - argv[2] = filename; - argv[3] = NULL; - - /* Fork & spawn to gunzip the file */ - if (!g_spawn_async_with_pipes (g_get_tmp_dir (), - (gchar **) argv, - NULL, - G_SPAWN_SEARCH_PATH | G_SPAWN_STDERR_TO_DEV_NULL, - spawn_child_func, - GINT_TO_POINTER (10), - NULL, - NULL, - &fdz, - NULL, - &error)) { - g_warning ("Couldn't fork & spawn to gunzip '%s': %s", - uri, error ? error->message : NULL); - g_clear_error (&error); - } - /* Get FILE from FD */ - else if ((fz = fdopen (fdz, "r")) == NULL) { - g_warning ("Couldn't open FILE from FD (%s)...", uri); - close (fdz); - } - /* Extract from filestream! */ - else - { - g_debug ("Extracting compressed PS '%s'...", uri); - metadata = extract_ps_from_filestream (fz); -#ifdef HAVE_POSIX_FADVISE - if (posix_fadvise (fdz, 0, 0, POSIX_FADV_DONTNEED) != 0) - g_warning ("posix_fadvise() call failed: %m"); -#endif /* HAVE_POSIX_FADVISE */ - fclose (fz); - } - - g_free (filename); - - return metadata; -} - -#endif /* USING_UNZIPPSFILES */ - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerResource *metadata; - GFile *file; - gchar *uri; - const char *mimetype; - - file = tracker_extract_info_get_file (info); - mimetype = tracker_extract_info_get_mimetype (info); - uri = g_file_get_uri (file); - -#ifdef USING_UNZIPPSFILES - if (strcmp (mimetype, "application/x-gzpostscript") == 0) { - metadata = extract_ps_gz (uri); - } else -#endif /* USING_UNZIPPSFILES */ - { - metadata = extract_ps (uri); - } - - g_free (uri); - - if (metadata) { - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - } - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-text.c b/src/tracker-extract/tracker-extract-text.c deleted file mode 100644 index abcf4038d..000000000 --- a/src/tracker-extract/tracker-extract-text.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <errno.h> -#include <fcntl.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <sys/mman.h> - -#include <glib.h> -#include <glib/gstdio.h> - -#include <gio/gio.h> - -#include <libtracker-common/tracker-file-utils.h> - -#include <libtracker-extract/tracker-extract.h> - -#include "tracker-main.h" -#include "tracker-read.h" - -static gchar * -get_file_content (GFile *file, - gsize n_bytes) -{ - gchar *text, *uri, *path; - int fd; - - /* If no content requested, return */ - if (n_bytes == 0) { - return NULL; - } - - uri = g_file_get_uri (file); - - /* Get filename from URI */ - path = g_file_get_path (file); - - fd = tracker_file_open_fd (path); - - if (fd == -1) { - g_message ("Could not open file '%s': %s", - uri, - g_strerror (errno)); - g_free (uri); - g_free (path); - return NULL; - } - - g_debug (" Starting to read '%s' up to %" G_GSIZE_FORMAT " bytes...", - uri, n_bytes); - - /* Read up to n_bytes from stream. Output is always, always valid UTF-8, - * this function closes the FD. - */ - text = tracker_read_text_from_fd (fd, n_bytes); - g_free (uri); - g_free (path); - - return text; -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerResource *metadata; - TrackerConfig *config; - gchar *content; - - config = tracker_main_get_config (); - - content = get_file_content (tracker_extract_info_get_file (info), - tracker_config_get_max_bytes (config)); - - metadata = tracker_resource_new (NULL); - tracker_resource_add_uri (metadata, "rdf:type", "nfo:PlainTextDocument"); - tracker_resource_add_uri (metadata, "rdf:type", "nfo:FileDataObject"); - - if (content) { - tracker_resource_set_string (metadata, "nie:plainTextContent", content); - g_free (content); - } - - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-tiff.c b/src/tracker-extract/tracker-extract-tiff.c deleted file mode 100644 index 64ff89403..000000000 --- a/src/tracker-extract/tracker-extract-tiff.c +++ /dev/null @@ -1,657 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <errno.h> -#include <fcntl.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> - -#include <glib/gstdio.h> - -#include <tiffio.h> -#include <libtracker-common/tracker-common.h> -#include <libtracker-extract/tracker-extract.h> - -#define CM_TO_INCH 0.393700787 - -typedef enum { - TAG_TYPE_UNDEFINED = 0, - TAG_TYPE_STRING, - TAG_TYPE_UINT16, - TAG_TYPE_UINT32, - TAG_TYPE_DOUBLE, - TAG_TYPE_C16_UINT16 -} TagType; - -typedef struct { - const gchar *make; - const gchar *model; - const gchar *title; - const gchar *orientation; - const gchar *copyright; - const gchar *white_balance; - const gchar *fnumber; - const gchar *flash; - const gchar *focal_length; - const gchar *artist; - const gchar *exposure_time; - const gchar *iso_speed_ratings; - const gchar *date; - const gchar *description; - const gchar *metering_mode; - const gchar *creator; - const gchar *x_dimension; - const gchar *y_dimension; - const gchar *city; - const gchar *state; - const gchar *address; - const gchar *country; - const gchar *gps_altitude; - const gchar *gps_latitude; - const gchar *gps_longitude; - const gchar *gps_direction; -} MergeData; - -typedef struct { - gchar *artist; - gchar *copyright; - gchar *date; - gchar *title; - gchar *description; - gchar *width; - gchar *length; - gchar *make; - gchar *model; - gchar *orientation; -} TiffData; - -static void -tiff_data_free (TiffData *tags) -{ - g_free (tags->artist); - g_free (tags->copyright); - g_free (tags->date); - g_free (tags->title); - g_free (tags->description); - g_free (tags->width); - g_free (tags->length); - g_free (tags->make); - g_free (tags->model); - g_free (tags->orientation); -} - -static gchar * -get_flash (TIFF *image) -{ - guint16 data = 0; - - if (TIFFGetField (image, EXIFTAG_FLASH, &data)) { - switch (data) { - case 0x0001: - case 0x0009: - case 0x000D: - case 0x000F: - case 0x0019: - case 0x001D: - case 0x001F: - case 0x0041: - case 0x0045: - case 0x0047: - case 0x0049: - case 0x004D: - case 0x004F: - case 0x0059: - case 0x005F: - case 0x005D: - return g_strdup ("nmm:flash-on"); - default: - return g_strdup ("nmm:flash-off"); - } - } - - return NULL; -} - -static gchar * -get_orientation (TIFF *image) -{ - guint16 data = 0; - - if (TIFFGetField (image, TIFFTAG_ORIENTATION, &data)) { - switch (data) { - case 1: return g_strdup ("nfo:orientation-top"); - case 2: return g_strdup ("nfo:orientation-top-mirror"); - case 3: return g_strdup ("nfo:orientation-bottom"); - case 4: return g_strdup ("nfo:orientation-bottom-mirror"); - case 5: return g_strdup ("nfo:orientation-left-mirror"); - case 6: return g_strdup ("nfo:orientation-right"); - case 7: return g_strdup ("nfo:orientation-right-mirror"); - case 8: return g_strdup ("nfo:orientation-left"); - } - } - - return NULL; -} - -static gchar * -get_metering_mode (TIFF *image) -{ - guint16 data = 0; - - if (TIFFGetField (image, EXIFTAG_METERINGMODE, &data)) { - switch (data) { - case 1: return g_strdup ("nmm:metering-mode-average"); - case 2: return g_strdup ("nmm:metering-mode-center-weighted-average"); - case 3: return g_strdup ("nmm:metering-mode-spot"); - case 4: return g_strdup ("nmm:metering-mode-multispot"); - case 5: return g_strdup ("nmm:metering-mode-pattern"); - case 6: return g_strdup ("nmm:metering-mode-partial"); - default: - return g_strdup ("nmm:metering-mode-other"); - } - } - - return NULL; -} - -static gchar * -get_white_balance (TIFF *image) -{ - guint16 data = 0; - - if (TIFFGetField (image, EXIFTAG_WHITEBALANCE, &data)) { - if (data == 0) { - return g_strdup ("nmm:white-balance-auto"); - } else { - return g_strdup ("nmm:white-balance-manual"); - } - } - - return NULL; -} - -static gchar * -tag_to_string (TIFF *image, - guint tag, - TagType type) -{ - switch (type) { - case TAG_TYPE_STRING: { - gchar *data = NULL; - - if (TIFFGetField (image, tag, &data)) { - return g_strdup (data); - } - break; - } - - case TAG_TYPE_UINT16: { - guint16 data = 0; - - if (TIFFGetField (image, tag, &data)) { - return g_strdup_printf ("%i", data); - } - break; - } - - case TAG_TYPE_UINT32: { - guint32 data = 0; - - if (TIFFGetField (image, tag, &data)) { - return g_strdup_printf ("%i", data); - } - break; - } - - case TAG_TYPE_DOUBLE: { - gfloat data = 0; - - if (TIFFGetField (image, tag, &data)) { - return g_strdup_printf ("%f", data); - } - break; - } - - case TAG_TYPE_C16_UINT16: { - void *data = NULL; - guint16 count = 0; - - if (TIFFGetField (image, tag, &count, &data)) { - return g_strdup_printf ("%i", * (guint16*) data); - } - break; - } - - default: - break; - } - - return NULL; -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerResource *metadata; - TIFF *image; - TrackerXmpData *xd = NULL; - TrackerIptcData *id = NULL; - TrackerExifData *ed = NULL; - MergeData md = { 0 }; - TiffData td = { 0 }; - gchar *filename, *uri; - gchar *date; - glong exif_offset; - GPtrArray *keywords; - guint i; - GFile *file; - int fd; - -#ifdef HAVE_LIBIPTCDATA - gchar *iptc_offset; - guint32 iptc_size; -#endif - -#ifdef HAVE_EXEMPI - gchar *xmp_offset; - guint32 size; -#endif /* HAVE_EXEMPI */ - - file = tracker_extract_info_get_file (info); - filename = g_file_get_path (file); - - fd = tracker_file_open_fd (filename); - - if (fd == -1) { - g_warning ("Could not open tiff file '%s': %s\n", - filename, - g_strerror (errno)); - g_free (filename); - return FALSE; - } - - if ((image = TIFFFdOpen (fd, filename, "r")) == NULL){ - g_warning ("Could not open image:'%s'\n", filename); - g_free (filename); - close (fd); - return FALSE; - } - - metadata = tracker_resource_new (NULL); - tracker_resource_add_uri (metadata, "rdf:type", "nfo:Image"); - tracker_resource_add_uri (metadata, "rdf:type", "nmm:Photo"); - - uri = g_file_get_uri (file); - -#ifdef HAVE_LIBIPTCDATA - if (TIFFGetField (image, - TIFFTAG_RICHTIFFIPTC, - &iptc_size, - &iptc_offset)) { - if (TIFFIsByteSwapped(image) != 0) { - TIFFSwabArrayOfLong((uint32*) iptc_offset, - (unsigned long) iptc_size); - } - id = tracker_iptc_new (iptc_offset, 4 * iptc_size, uri); - } -#endif /* HAVE_LIBIPTCDATA */ - - if (!id) { - id = g_new0 (TrackerIptcData, 1); - } - - /* FIXME There are problems between XMP data embedded with different tools - due to bugs in the original spec (type) */ -#ifdef HAVE_EXEMPI - if (TIFFGetField (image, TIFFTAG_XMLPACKET, &size, &xmp_offset)) { - xd = tracker_xmp_new (xmp_offset, size, uri); - } -#endif /* HAVE_EXEMPI */ - - if (!xd) { - xd = g_new0 (TrackerXmpData, 1); - } - - ed = g_new0 (TrackerExifData, 1); - - /* Get Tiff specifics */ - td.width = tag_to_string (image, TIFFTAG_IMAGEWIDTH, TAG_TYPE_UINT32); - td.length = tag_to_string (image, TIFFTAG_IMAGELENGTH, TAG_TYPE_UINT32); - td.artist = tag_to_string (image, TIFFTAG_ARTIST, TAG_TYPE_STRING); - td.copyright = tag_to_string (image, TIFFTAG_COPYRIGHT, TAG_TYPE_STRING); - - date = tag_to_string (image, TIFFTAG_DATETIME, TAG_TYPE_STRING); - td.date = tracker_date_guess (date); - g_free (date); - - td.title = tag_to_string (image, TIFFTAG_DOCUMENTNAME, TAG_TYPE_STRING); - td.description = tag_to_string (image, TIFFTAG_IMAGEDESCRIPTION, TAG_TYPE_STRING); - td.make = tag_to_string (image, TIFFTAG_MAKE, TAG_TYPE_STRING); - td.model = tag_to_string (image, TIFFTAG_MODEL, TAG_TYPE_STRING); - td.orientation = get_orientation (image); - - /* Get Exif specifics */ - if (TIFFGetField (image, TIFFTAG_EXIFIFD, &exif_offset)) { - if (TIFFReadEXIFDirectory (image, exif_offset)) { - ed->exposure_time = tag_to_string (image, EXIFTAG_EXPOSURETIME, TAG_TYPE_DOUBLE); - ed->fnumber = tag_to_string (image, EXIFTAG_FNUMBER, TAG_TYPE_DOUBLE); - ed->iso_speed_ratings = tag_to_string (image, EXIFTAG_ISOSPEEDRATINGS, TAG_TYPE_C16_UINT16); - date = tag_to_string (image, EXIFTAG_DATETIMEORIGINAL, TAG_TYPE_STRING); - ed->time_original = tracker_date_guess (date); - g_free (date); - - ed->metering_mode = get_metering_mode (image); - ed->flash = get_flash (image); - ed->focal_length = tag_to_string (image, EXIFTAG_DATETIMEORIGINAL, TAG_TYPE_DOUBLE); - ed->white_balance = get_white_balance (image); - /* ed->software = tag_to_string (image, EXIFTAG_SOFTWARE, TAG_TYPE_STRING); */ - } - } - - TIFFClose (image); - g_free (filename); - - md.title = tracker_coalesce_strip (5, xd->title, xd->pdf_title, td.title, ed->document_name, xd->title2); - md.orientation = tracker_coalesce_strip (4, xd->orientation, td.orientation, ed->orientation, id->image_orientation); - md.copyright = tracker_coalesce_strip (4, xd->rights, td.copyright, ed->copyright, id->copyright_notice); - md.white_balance = tracker_coalesce_strip (2, xd->white_balance, ed->white_balance); - md.fnumber = tracker_coalesce_strip (2, xd->fnumber, ed->fnumber); - md.flash = tracker_coalesce_strip (2, xd->flash, ed->flash); - md.focal_length = tracker_coalesce_strip (2, xd->focal_length, ed->focal_length); - md.artist = tracker_coalesce_strip (4, xd->artist, td.artist, ed->artist, xd->contributor); - md.exposure_time = tracker_coalesce_strip (2, xd->exposure_time, ed->exposure_time); - md.iso_speed_ratings = tracker_coalesce_strip (2, xd->iso_speed_ratings, ed->iso_speed_ratings); - md.date = tracker_coalesce_strip (6, xd->date, xd->time_original, td.date, ed->time, id->date_created, ed->time_original); - md.description = tracker_coalesce_strip (3, xd->description, td.description, ed->description); - md.metering_mode = tracker_coalesce_strip (2, xd->metering_mode, ed->metering_mode); - md.city = tracker_coalesce_strip (2, xd->city, id->city); - md.state = tracker_coalesce_strip (2, xd->state, id->state); - md.address = tracker_coalesce_strip (2, xd->address, id->sublocation); - md.country = tracker_coalesce_strip (2, xd->country, id->country_name); - - /* FIXME We are not handling the altitude ref here for xmp */ - md.gps_altitude = tracker_coalesce_strip (2, xd->gps_altitude, ed->gps_altitude); - md.gps_latitude = tracker_coalesce_strip (2, xd->gps_latitude, ed->gps_latitude); - md.gps_longitude = tracker_coalesce_strip (2, xd->gps_longitude, ed->gps_longitude); - md.gps_direction = tracker_coalesce_strip (2, xd->gps_direction, ed->gps_direction); - md.creator = tracker_coalesce_strip (3, xd->creator, id->byline, id->credit); - md.x_dimension = tracker_coalesce_strip (2, td.width, ed->x_dimension); - md.y_dimension = tracker_coalesce_strip (2, td.length, ed->y_dimension); - md.make = tracker_coalesce_strip (3, xd->make, td.make, ed->make); - md.model = tracker_coalesce_strip (3, xd->model, td.model, ed->model); - - keywords = g_ptr_array_new_with_free_func ((GDestroyNotify) g_free); - - if (ed->user_comment) { - tracker_guarantee_resource_utf8_string (metadata, "nie:comment", ed->user_comment); - } - - if (md.x_dimension) { - tracker_resource_set_string (metadata, "nfo:width", md.x_dimension); - } - - if (md.y_dimension) { - tracker_resource_set_string (metadata, "nfo:height", md.y_dimension); - } - - if (xd->keywords) { - tracker_keywords_parse (keywords, xd->keywords); - } - - if (xd->pdf_keywords) { - tracker_keywords_parse (keywords, xd->pdf_keywords); - } - - if (xd->subject) { - tracker_keywords_parse (keywords, xd->subject); - } - - if (xd->publisher) { - TrackerResource *publisher = tracker_extract_new_contact (xd->publisher); - tracker_resource_set_relation (metadata, "nco:publisher", publisher); - g_object_unref (publisher); - } - - if (xd->type) { - tracker_resource_set_string (metadata, "dc:type", xd->type); - } - - if (xd->format) { - tracker_resource_set_string (metadata, "dc:format", xd->format); - } - - if (xd->identifier) { - tracker_resource_set_string (metadata, "dc:identifier", xd->identifier); - } - - if (xd->source) { - tracker_resource_set_string (metadata, "dc:source", xd->source); - } - - if (xd->language) { - tracker_resource_set_string (metadata, "dc:language", xd->language); - } - - if (xd->relation) { - tracker_resource_set_string (metadata, "dc:relation", xd->relation); - } - - if (xd->coverage) { - tracker_resource_set_string (metadata, "dc:coverage", xd->coverage); - } - - if (xd->rating) { - tracker_resource_set_string (metadata, "nao:numericRating", xd->rating); - } - - if (xd->license) { - tracker_resource_set_string (metadata, "nie:license", xd->license); - } - - if (xd->regions) { - tracker_xmp_apply_regions_to_resource (metadata, xd); - } - - if (md.address || md.state || md.country || md.city || - md.gps_altitude || md.gps_latitude || md.gps_longitude) { - TrackerResource *location; - - location = tracker_extract_new_location (md.address, md.state, - md.city, md.country, md.gps_altitude, md.gps_latitude, - md.gps_longitude); - - tracker_resource_set_relation (metadata, "slo:location", location); - - g_object_unref (location); - } - - if (md.gps_direction) { - tracker_resource_set_string (metadata, "nfo:heading", md.gps_direction); - } - - if (id->contact) { - TrackerResource *contact = tracker_extract_new_contact (id->contact); - - tracker_resource_set_relation (metadata, "nco:contributor", contact); - - g_object_unref (contact); - } - - if (id->keywords) { - tracker_keywords_parse (keywords, id->keywords); - } - - for (i = 0; i < keywords->len; i++) { - TrackerResource *tag; - const gchar *p; - - p = g_ptr_array_index (keywords, i); - tag = tracker_extract_new_tag (p); - - tracker_resource_set_relation (metadata, "nao:hasTag", tag); - - g_object_unref (tag); - } - g_ptr_array_free (keywords, TRUE); - - if (md.make || md.model) { - TrackerResource *equipment = tracker_extract_new_equipment (md.make, md.model); - - tracker_resource_set_relation (metadata, "nfo:equipment", equipment); - - g_object_unref (equipment); - } - - tracker_guarantee_resource_title_from_file (metadata, - "nie:title", - md.title, - uri, - NULL); - - if (md.orientation) { - TrackerResource *orientation; - - orientation = tracker_resource_new (md.orientation); - tracker_resource_set_relation (metadata, "nfo:orientation", orientation); - g_object_unref (orientation); - } - - if (md.copyright) { - tracker_guarantee_resource_utf8_string (metadata, "nie:copyright", md.copyright); - } - - if (md.white_balance) { - TrackerResource *white_balance; - - white_balance = tracker_resource_new (md.white_balance); - tracker_resource_set_relation (metadata, "nmm:meteringMode", white_balance); - g_object_unref (white_balance); - } - - if (md.fnumber) { - tracker_resource_set_string (metadata, "nmm:fnumber", md.fnumber); - } - - if (md.flash) { - TrackerResource *flash; - - flash = tracker_resource_new (md.flash); - tracker_resource_set_relation (metadata, "nmm:flash", flash); - g_object_unref (flash); - } - - if (md.focal_length) { - tracker_resource_set_string (metadata, "nmm:focalLength", md.focal_length); - } - - if (md.artist) { - TrackerResource *artist = tracker_extract_new_contact (md.artist); - - tracker_resource_set_relation (metadata, "nco:contributor", artist); - - g_object_unref (artist); - } - - if (md.exposure_time) { - tracker_resource_set_string (metadata, "nmm:exposureTime", md.exposure_time); - } - - if (md.iso_speed_ratings) { - tracker_resource_set_string (metadata, "nmm:isoSpeed", md.iso_speed_ratings); - } - - tracker_guarantee_resource_date_from_file_mtime (metadata, - "nie:contentCreated", - md.date, - uri); - - if (md.description) { - tracker_guarantee_resource_utf8_string (metadata, "nie:description", md.description); - } - - if (md.metering_mode) { - TrackerResource *metering; - - metering = tracker_resource_new (md.metering_mode); - tracker_resource_set_relation (metadata, "nmm:meteringMode", metering); - g_object_unref (metering); - } - - if (md.creator) { - TrackerResource *creator = tracker_extract_new_contact (md.creator); - - /* NOTE: We only have affiliation with - * nco:PersonContact and we are using - * nco:Contact here. - */ - - /* if (id->byline_title) { */ - /* tracker_sparql_builder_insert_open (preupdate, NULL); */ - - /* tracker_sparql_builder_subject (preupdate, "_:affiliation_by_line"); */ - /* tracker_sparql_builder_predicate (preupdate, "a"); */ - /* tracker_sparql_builder_object (preupdate, "nco:Affiliation"); */ - - /* tracker_sparql_builder_predicate (preupdate, "nco:title"); */ - /* tracker_sparql_builder_object_unvalidated (preupdate, id->byline_title); */ - - /* tracker_sparql_builder_insert_close (preupdate); */ - - /* tracker_sparql_builder_predicate (metadata, "a"); */ - /* tracker_sparql_builder_object (metadata, "nco:PersonContact"); */ - /* tracker_sparql_builder_predicate (metadata, "nco:hasAffiliation"); */ - /* tracker_sparql_builder_object (metadata, "_:affiliation_by_line"); */ - /* } */ - - tracker_resource_set_relation (metadata, "nco:creator", creator); - - g_object_unref (creator); - } - - if (ed->x_resolution) { - gdouble value; - - value = ed->resolution_unit != 3 ? g_strtod (ed->x_resolution, NULL) : g_strtod (ed->x_resolution, NULL) * CM_TO_INCH; - tracker_resource_set_double (metadata, "nfo:horizontalResolution", value); - } - - if (ed->y_resolution) { - gdouble value; - - value = ed->resolution_unit != 3 ? g_strtod (ed->y_resolution, NULL) : g_strtod (ed->y_resolution, NULL) * CM_TO_INCH; - tracker_resource_set_double (metadata, "nfo:verticalResolution", value); - } - - tiff_data_free (&td); - tracker_exif_free (ed); - tracker_xmp_free (xd); - tracker_iptc_free (id); - g_free (uri); - close (fd); - - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-vorbis.c b/src/tracker-extract/tracker-extract-vorbis.c deleted file mode 100644 index d1d084054..000000000 --- a/src/tracker-extract/tracker-extract-vorbis.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <stdio.h> -#include <string.h> -#include <fcntl.h> -#include <stdlib.h> - -#include <glib.h> - -#include <vorbis/vorbisfile.h> - -#include <libtracker-common/tracker-common.h> - -#include <libtracker-extract/tracker-extract.h> - -typedef struct { - const gchar *creator_name; - TrackerResource *creator; -} MergeData; - -typedef struct { - gchar *title; - gchar *artist; - gchar *album; - gchar *album_artist; - gchar *track_count; - gchar *track_number; - gchar *disc_number; - gchar *performer; - gchar *track_gain; - gchar *track_peak_gain; - gchar *album_gain; - gchar *album_peak_gain; - gchar *date; - gchar *comment; - gchar *genre; - gchar *codec; - gchar *codec_version; - gchar *sample_rate; - gchar *channels; - gchar *mb_album_id; - gchar *mb_artist_id; - gchar *mb_album_artist_id; - gchar *mb_track_id; - gchar *lyrics; - gchar *copyright; - gchar *license; - gchar *organization; - gchar *location; - gchar *publisher; -} VorbisData; - -static gchar * -ogg_get_comment (vorbis_comment *vc, - const gchar *label) -{ - gchar *tag; - gchar *utf_tag; - - if (vc && (tag = vorbis_comment_query (vc, label, 0)) != NULL) { - utf_tag = g_locale_to_utf8 (tag, -1, NULL, NULL, NULL); - /*g_free (tag);*/ - - return utf_tag; - } else { - return NULL; - } -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerResource *metadata; - VorbisData vd = { 0 }; - MergeData md = { 0 }; - FILE *f; - gchar *filename; - OggVorbis_File vf; - vorbis_comment *comment; - vorbis_info *vi; - unsigned int bitrate; - gint time; - GFile *file; - - file = tracker_extract_info_get_file (info); - filename = g_file_get_path (file); - f = tracker_file_open (filename); - g_free (filename); - - if (!f) { - return FALSE; - } - - if (ov_open (f, &vf, NULL, 0) < 0) { - tracker_file_close (f, FALSE); - return FALSE; - } - - metadata = tracker_resource_new (NULL); - tracker_resource_add_uri (metadata, "rdf:type", "nmm:MusicPiece"); - tracker_resource_add_uri (metadata, "rdf:type", "nfo:Audio"); - - if ((comment = ov_comment (&vf, -1)) != NULL) { - gchar *date; - - vd.title = ogg_get_comment (comment, "title"); - vd.artist = ogg_get_comment (comment, "artist"); - vd.album = ogg_get_comment (comment, "album"); - vd.album_artist = ogg_get_comment (comment, "albumartist"); - vd.track_count = ogg_get_comment (comment, "trackcount"); - vd.track_number = ogg_get_comment (comment, "tracknumber"); - vd.disc_number = ogg_get_comment (comment, "DiscNo"); - if (vd.disc_number == NULL) - vd.disc_number = ogg_get_comment (comment, "DiscNumber"); - vd.performer = ogg_get_comment (comment, "Performer"); - vd.track_gain = ogg_get_comment (comment, "TrackGain"); - vd.track_peak_gain = ogg_get_comment (comment, "TrackPeakGain"); - vd.album_gain = ogg_get_comment (comment, "AlbumGain"); - vd.album_peak_gain = ogg_get_comment (comment, "AlbumPeakGain"); - - date = ogg_get_comment (comment, "date"); - vd.date = tracker_date_guess (date); - g_free (date); - - vd.comment = ogg_get_comment (comment, "comment"); - vd.genre = ogg_get_comment (comment, "genre"); - vd.codec = ogg_get_comment (comment, "Codec"); - vd.codec_version = ogg_get_comment (comment, "CodecVersion"); - vd.sample_rate = ogg_get_comment (comment, "SampleRate"); - vd.channels = ogg_get_comment (comment, "Channels"); - vd.mb_album_id = ogg_get_comment (comment, "MBAlbumID"); - vd.mb_artist_id = ogg_get_comment (comment, "MBArtistID"); - vd.mb_album_artist_id = ogg_get_comment (comment, "MBAlbumArtistID"); - vd.mb_track_id = ogg_get_comment (comment, "MBTrackID"); - vd.lyrics = ogg_get_comment (comment, "Lyrics"); - vd.copyright = ogg_get_comment (comment, "Copyright"); - vd.license = ogg_get_comment (comment, "License"); - vd.organization = ogg_get_comment (comment, "Organization"); - vd.location = ogg_get_comment (comment, "Location"); - vd.publisher = ogg_get_comment (comment, "Publisher"); - - vorbis_comment_clear (comment); - } - - md.creator_name = tracker_coalesce_strip (3, vd.artist, vd.album_artist, vd.performer); - - if (md.creator_name) { - md.creator = tracker_extract_new_artist (md.creator_name); - - tracker_resource_set_relation (metadata, "nmm:performer", md.creator); - } - - if (vd.album) { - TrackerResource *album, *album_disc, *album_artist; - - if (vd.album_artist) { - album_artist = tracker_extract_new_artist (vd.album_artist); - } else { - album_artist = NULL; - } - - album_disc = tracker_extract_new_music_album_disc (vd.album, - album_artist, - vd.disc_number ? atoi(vd.disc_number) : 1, - vd.date); - - g_clear_object (&album_artist); - - album = tracker_resource_get_first_relation (album_disc, "nmm:albumDiscAlbum"); - - - if (vd.track_count) { - tracker_resource_set_string (album, "nmm:albumTrackCount", vd.track_count); - } - - if (vd.album_gain) { - tracker_resource_set_double (album, "nmm:albumGain", atof (vd.album_gain)); - } - - if (vd.album_peak_gain) { - tracker_resource_set_double (album, "nmm:albumPeakGain", atof (vd.album_peak_gain)); - } - - tracker_resource_set_relation (metadata, "nmm:musicAlbum", album); - tracker_resource_set_relation (metadata, "nmm:musicAlbumDisc", album_disc); - - g_object_unref (album_disc); - } - - g_free (vd.track_count); - g_free (vd.album_peak_gain); - g_free (vd.album_gain); - g_free (vd.disc_number); - - if (vd.title) { - tracker_resource_set_string (metadata, "nie:title", vd.title); - g_free (vd.title); - } - - if (vd.track_number) { - tracker_resource_set_string (metadata, "nmm:trackNumber", vd.track_number); - g_free (vd.track_number); - } - - if (vd.track_gain) { - /* TODO */ - g_free (vd.track_gain); - } - - if (vd.track_peak_gain) { - /* TODO */ - g_free (vd.track_peak_gain); - } - - if (vd.comment) { - tracker_resource_set_string (metadata, "nie:comment", vd.comment); - g_free (vd.comment); - } - - if (vd.date) { - tracker_resource_set_string (metadata, "nie:contentCreated", vd.date); - g_free (vd.date); - } - - if (vd.genre) { - tracker_resource_set_string (metadata, "nfo:genre", vd.genre); - g_free (vd.genre); - } - - if (vd.codec) { - tracker_resource_set_string (metadata, "nfo:codec", vd.codec); - g_free (vd.codec); - } - - if (vd.codec_version) { - /* TODO */ - g_free (vd.codec_version); - } - - if (vd.sample_rate) { - tracker_resource_set_string (metadata, "nfo:sampleRate", vd.sample_rate); - g_free (vd.sample_rate); - } - - if (vd.channels) { - tracker_resource_set_string (metadata, "nfo:channels", vd.channels); - g_free (vd.channels); - } - - if (vd.mb_album_id) { - /* TODO */ - g_free (vd.mb_album_id); - } - - if (vd.mb_artist_id) { - /* TODO */ - g_free (vd.mb_artist_id); - } - - if (vd.mb_album_artist_id) { - /* TODO */ - g_free (vd.mb_album_artist_id); - } - - if (vd.mb_track_id) { - /* TODO */ - g_free (vd.mb_track_id); - } - - if (vd.lyrics) { - tracker_resource_set_string (metadata, "nie:plainTextContent", vd.lyrics); - g_free (vd.lyrics); - } - - if (vd.copyright) { - tracker_resource_set_string (metadata, "nie:copyright", vd.copyright); - g_free (vd.copyright); - } - - if (vd.license) { - tracker_resource_set_string (metadata, "nie:license", vd.license); - g_free (vd.license); - } - - if (vd.organization) { - /* TODO */ - g_free (vd.organization); - } - - if (vd.location) { - /* TODO */ - g_free (vd.location); - } - - if (vd.publisher) { - TrackerResource *publisher = tracker_extract_new_contact (vd.publisher); - - tracker_resource_set_relation (metadata, "dc:publisher", publisher); - - g_object_unref (publisher); - } - - if ((vi = ov_info (&vf, 0)) != NULL ) { - bitrate = vi->bitrate_nominal / 1000; - - tracker_resource_set_int64 (metadata, "nfo:averageBitrate", (gint64) bitrate); - } - - /* Duration */ - if ((time = ov_time_total (&vf, -1)) != OV_EINVAL) { - tracker_resource_set_int64 (metadata, "nfo:duration", (gint64) time); - } - - g_free (vd.artist); - g_free (vd.album); - g_free (vd.album_artist); - g_free (vd.performer); - - g_object_unref (md.creator); - -#ifdef HAVE_POSIX_FADVISE - if (posix_fadvise (fileno (f), 0, 0, POSIX_FADV_DONTNEED) != 0) - g_warning ("posix_fadvise() call failed: %m"); -#endif /* HAVE_POSIX_FADVISE */ - - /* NOTE: This calls fclose on the file */ - ov_clear (&vf); - - tracker_extract_info_set_resource (info, metadata); - g_object_unref (metadata); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract-xmp.c b/src/tracker-extract/tracker-extract-xmp.c deleted file mode 100644 index 44c035c40..000000000 --- a/src/tracker-extract/tracker-extract-xmp.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (C) 2007, Jason Kivlighn <jkivlighn@gmail.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <errno.h> -#include <fcntl.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <unistd.h> -#include <sys/mman.h> - -#include <glib.h> -#include <glib/gstdio.h> - -#include <gio/gio.h> - -#include <libtracker-common/tracker-file-utils.h> - -#include <libtracker-extract/tracker-extract.h> - -/* This function is used to find the URI for a file.xmp file. The point here is - * that the URI for file.xmp is not file:///file.xmp but instead for example - * file:///file.jpeg or file:///file.png. The reason is that file.xmp is a - * sidekick, and a sidekick doesn't describe itself, it describes another file. */ - -static gchar * -find_orig_uri (const gchar *xmp_filename) -{ - GFile *file; - GFile *dir; - GFileEnumerator *iter; - GFileInfo *orig_info; - const gchar *filename_a; - gchar *found_file = NULL; - - file = g_file_new_for_path (xmp_filename); - dir = g_file_get_parent (file); - - orig_info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_NAME, - G_FILE_QUERY_INFO_NONE, - NULL, NULL); - - filename_a = g_file_info_get_name (orig_info); - - iter = g_file_enumerate_children (dir, G_FILE_ATTRIBUTE_STANDARD_NAME, - G_FILE_QUERY_INFO_NONE, - NULL, NULL); - - if (iter) { - GFileInfo *info; - - while ((info = g_file_enumerator_next_file (iter, NULL, NULL)) && !found_file) { - const gchar *filename_b; - const gchar *ext_a, *ext_b; - gchar *casefold_a, *casefold_b; - - /* OK, important: - * 1. Files can't be the same. - * 2. File names (without extension) must match - * 3. Something else? */ - - filename_b = g_file_info_get_name (info); - - ext_a = g_utf8_strrchr (filename_a, -1, '.'); - ext_b = g_utf8_strrchr (filename_b, -1, '.'); - - /* Look for extension */ - if (!ext_a || !ext_b) { - g_object_unref (info); - continue; - } - - /* Name part is the same length */ - if ((ext_a - filename_a) != (ext_b - filename_b)) { - g_object_unref (info); - continue; - } - - /* Check extensions are not the same (i.e. same len and ext) */ - if (g_strcmp0 (ext_a, ext_b) == 0) { - g_object_unref (info); - continue; - } - - /* Don't compare the ".xmp" with ".jpeg" and don't match the same file */ - - /* Now compare name (without ext) and make - * sure they are the same in a caseless - * compare. */ - - casefold_a = g_utf8_casefold (filename_a, (ext_a - filename_a)); - casefold_b = g_utf8_casefold (filename_b, (ext_b - filename_b)); - - if (g_strcmp0 (casefold_a, casefold_b) == 0) { - GFile *found; - - found = g_file_get_child (dir, filename_b); - found_file = g_file_get_uri (found); - g_object_unref (found); - } - - g_free (casefold_a); - g_free (casefold_b); - g_object_unref (info); - } - - g_object_unref (iter); - } - - g_object_unref (orig_info); - g_object_unref (file); - g_object_unref (dir); - - return found_file; -} - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerResource *resource; - TrackerXmpData *xd = NULL; - gchar *filename, *uri; - gchar *contents; - gsize length = 0; - GFile *file; - int fd; - struct stat st; - - file = tracker_extract_info_get_file (info); - filename = g_file_get_path (file); - - fd = tracker_file_open_fd (filename); - - if (fd == -1) { - g_warning ("Could not open xmp file '%s': %s\n", - filename, - g_strerror (errno)); - g_free (filename); - return FALSE; - } - - if (fstat (fd, &st) == -1) { - g_warning ("Could not fstat xmp file '%s': %s\n", - filename, - g_strerror (errno)); - close (fd); - g_free (filename); - return FALSE; - } - - if (st.st_size == 0) { - contents = NULL; - length = 0; - } else { - contents = (gchar *) mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (contents == NULL) { - g_warning ("Could not mmap xmp file '%s': %s\n", - filename, - g_strerror (errno)); - close (fd); - g_free (filename); - return FALSE; - } - length = st.st_size; - } - - uri = g_file_get_uri (file); - - if (contents) { - gchar *original_uri; - - original_uri = find_orig_uri (filename); - - /* If no orig file is found for the sidekick, we use the sidekick to - * describe itself instead, falling back to uri - */ - xd = tracker_xmp_new (contents, - length, - original_uri ? original_uri : uri); - - if (xd) { - resource = tracker_resource_new (NULL); - - tracker_xmp_apply_to_resource (resource, xd); - - tracker_extract_info_set_resource (info, resource); - g_object_unref (resource); - } - - g_free (original_uri); - tracker_xmp_free (xd); - g_free (filename); - g_free (uri); - - munmap (contents, length); - - close (fd); - - return TRUE; - } - - close (fd); - g_free (filename); - g_free (uri); - - return FALSE; -} diff --git a/src/tracker-extract/tracker-extract-xps.c b/src/tracker-extract/tracker-extract-xps.c deleted file mode 100644 index 096bdd11b..000000000 --- a/src/tracker-extract/tracker-extract-xps.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (C) 2012, Red Hat, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include <glib.h> -#include <gmodule.h> - -#include <libgxps/gxps.h> - -#include <libtracker-extract/tracker-extract.h> - -G_MODULE_EXPORT gboolean -tracker_extract_get_metadata (TrackerExtractInfo *info) -{ - TrackerResource *resource; - GXPSDocument *document; - GXPSFile *xps_file; - GFile *file; - gchar *filename; - GError *error = NULL; - - file = tracker_extract_info_get_file (info); - xps_file = gxps_file_new (file, &error); - filename = g_file_get_path (file); - - if (error != NULL) { - g_warning ("Unable to open '%s': %s", filename, error->message); - g_error_free (error); - g_free (filename); - return FALSE; - } - - document = gxps_file_get_document (xps_file, 0, &error); - g_object_unref (xps_file); - - if (error != NULL) { - g_warning ("Unable to read '%s': %s", filename, error->message); - g_error_free (error); - g_free (filename); - return FALSE; - } - - resource = tracker_resource_new (NULL); - tracker_resource_add_uri (resource, "rdf:type", "nfo:PaginatedTextDocument"); - tracker_resource_set_int64 (resource, "nfo:pageCount", gxps_document_get_n_pages (document)); - - g_object_unref (document); - g_free (filename); - - tracker_extract_info_set_resource (info, resource); - g_object_unref (resource); - - return TRUE; -} diff --git a/src/tracker-extract/tracker-extract.c b/src/tracker-extract/tracker-extract.c deleted file mode 100644 index 699e6f3c4..000000000 --- a/src/tracker-extract/tracker-extract.c +++ /dev/null @@ -1,767 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <string.h> -#include <unistd.h> - -#include <gmodule.h> -#include <glib/gi18n.h> -#include <gio/gio.h> - -#include <gio/gunixoutputstream.h> -#include <gio/gunixinputstream.h> -#include <gio/gunixfdlist.h> - -#include <libtracker-common/tracker-common.h> - -#include <libtracker-extract/tracker-extract.h> - -#include "tracker-extract.h" -#include "tracker-main.h" - -#ifdef THREAD_ENABLE_TRACE -#warning Main thread traces enabled -#endif /* THREAD_ENABLE_TRACE */ - -#define TRACKER_EXTRACT_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_EXTRACT, TrackerExtractPrivate)) - -G_DEFINE_QUARK (TrackerExtractError, tracker_extract_error) - -extern gboolean debug; - -typedef struct { - gint extracted_count; - gint failed_count; -} StatisticsData; - -typedef struct { - GHashTable *statistics_data; - GList *running_tasks; - - /* used to maintain the running tasks - * and stats from different threads - */ - GMutex task_mutex; - - /* Thread pool for multi-threaded extractors */ - GThreadPool *thread_pool; - - /* module -> async queue hashtable - * for single-threaded extractors - */ - GHashTable *single_thread_extractors; - - gboolean disable_shutdown; - gboolean disable_summary_on_finalize; - - gchar *force_module; - - gint unhandled_count; -} TrackerExtractPrivate; - -typedef struct { - TrackerExtract *extract; - GCancellable *cancellable; - GAsyncResult *res; - gchar *file; - gchar *mimetype; - - TrackerMimetypeInfo *mimetype_handlers; - - /* to be fed from mimetype_handlers */ - TrackerExtractMetadataFunc cur_func; - GModule *cur_module; - - guint signal_id; - guint success : 1; -} TrackerExtractTask; - -static void tracker_extract_finalize (GObject *object); -static void report_statistics (GObject *object); -static gboolean get_metadata (TrackerExtractTask *task); -static gboolean dispatch_task_cb (TrackerExtractTask *task); - - -G_DEFINE_TYPE(TrackerExtract, tracker_extract, G_TYPE_OBJECT) - -static void -tracker_extract_class_init (TrackerExtractClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = tracker_extract_finalize; - - g_type_class_add_private (object_class, sizeof (TrackerExtractPrivate)); -} - -static void -statistics_data_free (StatisticsData *data) -{ - g_slice_free (StatisticsData, data); -} - -static void -tracker_extract_init (TrackerExtract *object) -{ - TrackerExtractPrivate *priv; - - priv = TRACKER_EXTRACT_GET_PRIVATE (object); - priv->statistics_data = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) statistics_data_free); - priv->single_thread_extractors = g_hash_table_new (NULL, NULL); - priv->thread_pool = g_thread_pool_new ((GFunc) get_metadata, - NULL, 10, TRUE, NULL); - - g_mutex_init (&priv->task_mutex); -} - -static void -tracker_extract_finalize (GObject *object) -{ - TrackerExtractPrivate *priv; - - priv = TRACKER_EXTRACT_GET_PRIVATE (object); - - /* FIXME: Shutdown modules? */ - - g_hash_table_destroy (priv->single_thread_extractors); - g_thread_pool_free (priv->thread_pool, TRUE, FALSE); - - if (!priv->disable_summary_on_finalize) { - report_statistics (object); - } - - g_hash_table_destroy (priv->statistics_data); - - g_mutex_clear (&priv->task_mutex); - - G_OBJECT_CLASS (tracker_extract_parent_class)->finalize (object); -} - -static void -report_statistics (GObject *object) -{ - TrackerExtractPrivate *priv; - GHashTableIter iter; - gpointer key, value; - - priv = TRACKER_EXTRACT_GET_PRIVATE (object); - - g_mutex_lock (&priv->task_mutex); - - g_message ("--------------------------------------------------"); - g_message ("Statistics:"); - - g_hash_table_iter_init (&iter, priv->statistics_data); - - while (g_hash_table_iter_next (&iter, &key, &value)) { - GModule *module = key; - StatisticsData *data = value; - - if (data->extracted_count > 0 || data->failed_count > 0) { - const gchar *name, *name_without_path; - - name = g_module_name (module); - name_without_path = strrchr (name, G_DIR_SEPARATOR) + 1; - - g_message (" Module:'%s', extracted:%d, failures:%d", - name_without_path, - data->extracted_count, - data->failed_count); - } - } - - g_message ("Unhandled files: %d", priv->unhandled_count); - - if (priv->unhandled_count == 0 && - g_hash_table_size (priv->statistics_data) < 1) { - g_message (" No files handled"); - } - - g_message ("--------------------------------------------------"); - - g_mutex_unlock (&priv->task_mutex); -} - -TrackerExtract * -tracker_extract_new (gboolean disable_shutdown, - const gchar *force_module) -{ - TrackerExtract *object; - TrackerExtractPrivate *priv; - - if (!tracker_extract_module_manager_init ()) { - return NULL; - } - - /* Set extractors */ - object = g_object_new (TRACKER_TYPE_EXTRACT, NULL); - - priv = TRACKER_EXTRACT_GET_PRIVATE (object); - - priv->disable_shutdown = disable_shutdown; - priv->force_module = g_strdup (force_module); - - return object; -} - -static void -notify_task_finish (TrackerExtractTask *task, - gboolean success) -{ - TrackerExtract *extract; - TrackerExtractPrivate *priv; - StatisticsData *stats_data; - - extract = task->extract; - priv = TRACKER_EXTRACT_GET_PRIVATE (extract); - - /* Reports and ongoing tasks may be - * accessed from other threads. - */ - g_mutex_lock (&priv->task_mutex); - - if (task->cur_module) { - stats_data = g_hash_table_lookup (priv->statistics_data, - task->cur_module); - - if (!stats_data) { - stats_data = g_slice_new0 (StatisticsData); - g_hash_table_insert (priv->statistics_data, - task->cur_module, - stats_data); - } - - stats_data->extracted_count++; - - if (!success) { - stats_data->failed_count++; - } - } else { - priv->unhandled_count++; - } - - priv->running_tasks = g_list_remove (priv->running_tasks, task); - - g_mutex_unlock (&priv->task_mutex); -} - -static gboolean -get_file_metadata (TrackerExtractTask *task, - TrackerExtractInfo **info_out) -{ - TrackerExtractInfo *info; - GFile *file; - gchar *mime_used = NULL; - - *info_out = NULL; - - file = g_file_new_for_uri (task->file); - info = tracker_extract_info_new (file, task->mimetype); - g_object_unref (file); - - if (task->mimetype && *task->mimetype) { - /* We know the mime */ - mime_used = g_strdup (task->mimetype); - } else { - tracker_extract_info_unref (info); - return FALSE; - } - - /* Now we have sanity checked everything, actually get the - * data we need from the extractors. - */ - if (mime_used) { - if (task->cur_func) { - g_debug ("Using %s...", - task->cur_module ? - g_module_name (task->cur_module) : - "Dummy extraction"); - - task->success = (task->cur_func) (info); - } - - g_free (mime_used); - } - - if (!task->success) { - tracker_extract_info_unref (info); - info = NULL; - } - - *info_out = info; - - return task->success; -} - -/* This function is called on the thread calling g_cancellable_cancel() */ -static void -task_cancellable_cancelled_cb (GCancellable *cancellable, - TrackerExtractTask *task) -{ - TrackerExtractPrivate *priv; - TrackerExtract *extract; - - extract = task->extract; - priv = TRACKER_EXTRACT_GET_PRIVATE (extract); - - g_mutex_lock (&priv->task_mutex); - - if (g_list_find (priv->running_tasks, task)) { - g_message ("Cancelled task for '%s' was currently being " - "processed, _exit()ing immediately", - task->file); - _exit (0); - } - - g_mutex_unlock (&priv->task_mutex); -} - -static TrackerExtractTask * -extract_task_new (TrackerExtract *extract, - const gchar *uri, - const gchar *mimetype, - GCancellable *cancellable, - GAsyncResult *res, - GError **error) -{ - TrackerExtractTask *task; - gchar *mimetype_used; - - if (!mimetype || !*mimetype) { - GFile *file; - GFileInfo *info; - GError *internal_error = NULL; - - file = g_file_new_for_uri (uri); - info = g_file_query_info (file, - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, - G_FILE_QUERY_INFO_NONE, - NULL, - &internal_error); - - g_object_unref (file); - - if (internal_error) { - g_propagate_error (error, internal_error); - return NULL; - } - - mimetype_used = g_strdup (g_file_info_get_content_type (info)); - g_object_unref (info); - g_message ("MIME type guessed as '%s' (from GIO)", mimetype_used); - } else { - mimetype_used = g_strdup (mimetype); - g_message ("MIME type passed to us as '%s'", mimetype_used); - } - - task = g_slice_new0 (TrackerExtractTask); - task->cancellable = (cancellable) ? g_object_ref (cancellable) : NULL; - task->res = (res) ? g_object_ref (res) : NULL; - task->file = g_strdup (uri); - task->mimetype = mimetype_used; - task->extract = extract; - - if (task->cancellable) { - task->signal_id = g_cancellable_connect (cancellable, - G_CALLBACK (task_cancellable_cancelled_cb), - task, NULL); - } - - return task; -} - -static void -extract_task_free (TrackerExtractTask *task) -{ - if (task->cancellable && task->signal_id != 0) { - g_cancellable_disconnect (task->cancellable, task->signal_id); - } - - notify_task_finish (task, task->success); - - if (task->res) { - g_object_unref (task->res); - } - - if (task->cancellable) { - g_object_unref (task->cancellable); - } - - if (task->mimetype_handlers) { - tracker_mimetype_info_free (task->mimetype_handlers); - } - - g_free (task->mimetype); - g_free (task->file); - - g_slice_free (TrackerExtractTask, task); -} - -static gboolean -filter_module (TrackerExtract *extract, - GModule *module) -{ - TrackerExtractPrivate *priv; - gchar *module_basename, *filter_name; - gboolean filter; - - if (!module) { - return FALSE; - } - - priv = TRACKER_EXTRACT_GET_PRIVATE (extract); - - if (!priv->force_module) { - return FALSE; - } - - /* Module name is the full path to it */ - module_basename = g_path_get_basename (g_module_name (module)); - - if (g_str_has_prefix (priv->force_module, "lib") && - g_str_has_suffix (priv->force_module, "." G_MODULE_SUFFIX)) { - filter_name = g_strdup (priv->force_module); - } else { - filter_name = g_strdup_printf ("libextract-%s.so", - priv->force_module); - } - - filter = strcmp (module_basename, filter_name) != 0; - - if (filter) { - g_debug ("Module filtered out '%s' (due to --force-module='%s')", - module_basename, - filter_name); - } else { - g_debug ("Module used '%s' (due to --force-module='%s')", - module_basename, - filter_name); - } - - g_free (module_basename); - g_free (filter_name); - - return filter; -} - -static gboolean -get_metadata (TrackerExtractTask *task) -{ - TrackerExtractInfo *info; - -#ifdef THREAD_ENABLE_TRACE - g_debug ("Thread:%p --> '%s': Collected metadata", - g_thread_self (), - task->file); -#endif /* THREAD_ENABLE_TRACE */ - - if (g_task_return_error_if_cancelled (G_TASK (task->res))) { - extract_task_free (task); - return FALSE; - } - - if (!filter_module (task->extract, task->cur_module) && - get_file_metadata (task, &info)) { - g_task_return_pointer (G_TASK (task->res), info, - (GDestroyNotify) tracker_extract_info_unref); - extract_task_free (task); - } else { - /* Reinject the task into the main thread - * queue, so the next module kicks in. - */ - g_idle_add ((GSourceFunc) dispatch_task_cb, task); - } - - return FALSE; -} - -static gpointer -single_thread_get_metadata (GAsyncQueue *queue) -{ - if (!tracker_seccomp_init ()) - g_assert_not_reached (); - - while (TRUE) { - TrackerExtractTask *task; - - task = g_async_queue_pop (queue); -#ifdef THREAD_ENABLE_TRACE - g_debug ("Thread:%p --> '%s': Dispatching in dedicated thread", - g_thread_self(), task->file); -#endif /* THREAD_ENABLE_TRACE */ - get_metadata (task); - } - - return NULL; -} - -/* This function is executed in the main thread, decides the - * module that's going to be run for a given task, and dispatches - * the task according to the threading strategy of that module. - */ -static gboolean -dispatch_task_cb (TrackerExtractTask *task) -{ - TrackerExtractPrivate *priv; - GError *error = NULL; - GAsyncQueue *async_queue; - GModule *module; - -#ifdef THREAD_ENABLE_TRACE - g_debug ("Thread:%p (Main) <-- '%s': Handling task...\n", - g_thread_self (), - task->file); -#endif /* THREAD_ENABLE_TRACE */ - - priv = TRACKER_EXTRACT_GET_PRIVATE (task->extract); - - if (!task->mimetype) { - error = g_error_new (tracker_extract_error_quark (), - TRACKER_EXTRACT_ERROR_NO_MIMETYPE, - "No mimetype for '%s'", task->file); - } else { - if (!task->mimetype_handlers) { - /* First iteration for task, get the mimetype handlers */ - task->mimetype_handlers = tracker_extract_module_manager_get_mimetype_handlers (task->mimetype); - - if (!task->mimetype_handlers) { - error = g_error_new (tracker_extract_error_quark (), - TRACKER_EXTRACT_ERROR_NO_EXTRACTOR, - "No mimetype extractor handlers for uri:'%s' and mime:'%s'", - task->file, task->mimetype); - } - } else { - /* Any further iteration, should happen rarely if - * most specific handlers know nothing about the file - */ - if (!tracker_mimetype_info_iter_next (task->mimetype_handlers)) { - g_message ("There's no next extractor"); - - error = g_error_new (tracker_extract_error_quark (), - TRACKER_EXTRACT_ERROR_NO_EXTRACTOR, - "Could not get any metadata for uri:'%s' and mime:'%s'", - task->file, task->mimetype); - } else { - g_message ("Trying next extractor for '%s'", task->file); - } - } - } - - if (error) { - g_task_return_error (G_TASK (task->res), error); - extract_task_free (task); - - return FALSE; - } - - task->cur_module = module = tracker_mimetype_info_get_module (task->mimetype_handlers, &task->cur_func); - - if (!task->cur_func) { - g_warning ("Discarding task, no module able to handle '%s'", task->file); - priv->unhandled_count++; - extract_task_free (task); - return FALSE; - } - - async_queue = g_hash_table_lookup (priv->single_thread_extractors, module); - - if (!async_queue) { - GThread *thread; - - /* No thread created yet for this module, create it - * together with the async queue used to pass data to it - */ - async_queue = g_async_queue_new (); - thread = g_thread_try_new ("single", - (GThreadFunc) single_thread_get_metadata, - g_async_queue_ref (async_queue), - &error); - if (!thread) { - g_task_return_error (G_TASK (task->res), error); - extract_task_free (task); - return FALSE; - } - - /* We won't join the thread, so just unref it here */ - g_thread_unref (thread); - - g_hash_table_insert (priv->single_thread_extractors, module, async_queue); - } - - g_async_queue_push (async_queue, task); - - return FALSE; -} - -/* This function can be called in any thread */ -void -tracker_extract_file (TrackerExtract *extract, - const gchar *file, - const gchar *mimetype, - GCancellable *cancellable, - GAsyncReadyCallback cb, - gpointer user_data) -{ - GError *error = NULL; - TrackerExtractTask *task; - GTask *async_task; - - g_return_if_fail (TRACKER_IS_EXTRACT (extract)); - g_return_if_fail (file != NULL); - g_return_if_fail (cb != NULL); - -#ifdef THREAD_ENABLE_TRACE - g_debug ("Thread:%p <-- '%s': Processing file\n", - g_thread_self (), - file); -#endif /* THREAD_ENABLE_TRACE */ - - async_task = g_task_new (extract, cancellable, cb, user_data); - - task = extract_task_new (extract, file, mimetype, cancellable, - G_ASYNC_RESULT (async_task), &error); - - if (error) { - g_warning ("Could not get mimetype, %s", error->message); - g_task_return_error (async_task, error); - } else { - TrackerExtractPrivate *priv; - - priv = TRACKER_EXTRACT_GET_PRIVATE (task->extract); - - g_mutex_lock (&priv->task_mutex); - priv->running_tasks = g_list_prepend (priv->running_tasks, task); - g_mutex_unlock (&priv->task_mutex); - - g_idle_add ((GSourceFunc) dispatch_task_cb, task); - } - - /* Task takes a ref and if this fails, we want to unref anyway */ - g_object_unref (async_task); -} - -void -tracker_extract_get_metadata_by_cmdline (TrackerExtract *object, - const gchar *uri, - const gchar *mime, - TrackerSerializationFormat output_format) -{ - GError *error = NULL; - TrackerExtractPrivate *priv; - TrackerExtractTask *task; - TrackerExtractInfo *info; - gboolean no_data_or_modules = TRUE; - - priv = TRACKER_EXTRACT_GET_PRIVATE (object); - priv->disable_summary_on_finalize = TRUE; - - g_return_if_fail (uri != NULL); - - task = extract_task_new (object, uri, mime, NULL, NULL, &error); - - if (error) { - g_printerr ("%s, %s\n", - _("Metadata extraction failed"), - error->message); - g_error_free (error); - - return; - } - - task->mimetype_handlers = tracker_extract_module_manager_get_mimetype_handlers (task->mimetype); - if (task->mimetype_handlers) { - task->cur_module = tracker_mimetype_info_get_module (task->mimetype_handlers, &task->cur_func); - } - - while (task->cur_func) { - if (!filter_module (object, task->cur_module) && - get_file_metadata (task, &info)) { - TrackerResource *resource = tracker_extract_info_get_resource (info); - - if (resource == NULL) - break; - - no_data_or_modules = FALSE; - - if (output_format == TRACKER_SERIALIZATION_FORMAT_SPARQL) { - char *text; - - /* If this was going into the tracker-store we'd generate a unique ID - * here, so that the data persisted across file renames. - */ - tracker_resource_set_identifier (resource, uri); - - text = tracker_resource_print_sparql_update (resource, NULL, NULL); - - g_print ("%s\n", text); - - g_free (text); - } else if (output_format == TRACKER_SERIALIZATION_FORMAT_TURTLE) { - char *turtle; - - /* If this was going into the tracker-store we'd generate a unique ID - * here, so that the data persisted across file renames. - */ - tracker_resource_set_identifier (resource, uri); - - turtle = tracker_resource_print_turtle (resource, NULL); - - if (turtle) { - g_print ("%s\n", turtle); - g_free (turtle); - } - } - - tracker_extract_info_unref (info); - break; - } else { - if (!tracker_mimetype_info_iter_next (task->mimetype_handlers)) { - break; - } - - task->cur_module = tracker_mimetype_info_get_module (task->mimetype_handlers, - &task->cur_func); - } - } - - if (no_data_or_modules) { - g_printerr ("%s: %s\n", - uri, - _("No metadata or extractor modules found to handle this file")); - } - - extract_task_free (task); -} - -TrackerExtractInfo * -tracker_extract_file_finish (TrackerExtract *extract, - GAsyncResult *res, - GError **error) -{ - g_return_val_if_fail (TRACKER_IS_EXTRACT (extract), NULL); - g_return_val_if_fail (G_IS_ASYNC_RESULT (res), NULL); - g_return_val_if_fail (!error || !*error, NULL); - - return g_task_propagate_pointer (G_TASK (res), error); -} diff --git a/src/tracker-extract/tracker-extract.desktop.in.in b/src/tracker-extract/tracker-extract.desktop.in.in deleted file mode 100644 index 59fc0af2e..000000000 --- a/src/tracker-extract/tracker-extract.desktop.in.in +++ /dev/null @@ -1,18 +0,0 @@ -[Desktop Entry] -_Name=Tracker Metadata Extractor -_Comment=Extracts metadata from local files -Icon= -Exec=@libexecdir@/tracker-extract -Terminal=false -Type=Application -Categories=Utility; -X-GNOME-Autostart-enabled=true -X-KDE-autostart-after=panel -X-KDE-StartupNotify=false -X-KDE-UniqueApplet=true -NoDisplay=true -OnlyShowIn=GNOME;KDE;XFCE;X-IVI;Unity; -X-GNOME-Bugzilla-Bugzilla=GNOME -X-GNOME-Bugzilla-Product=tracker -X-GNOME-Bugzilla-Component=Extractor -X-GNOME-Bugzilla-Version=@VERSION@ diff --git a/src/tracker-extract/tracker-extract.h b/src/tracker-extract/tracker-extract.h deleted file mode 100644 index 229be4c8a..000000000 --- a/src/tracker-extract/tracker-extract.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKERD_EXTRACT_H__ -#define __TRACKERD_EXTRACT_H__ - -#include <gio/gio.h> -#include <libtracker-common/tracker-common.h> -#include <libtracker-extract/tracker-extract.h> - -#define TRACKER_EXTRACT_SERVICE "org.freedesktop.Tracker1.Extract" -#define TRACKER_EXTRACT_PATH "/org/freedesktop/Tracker1/Extract" -#define TRACKER_EXTRACT_INTERFACE "org.freedesktop.Tracker1.Extract" - -G_BEGIN_DECLS - -#define TRACKER_EXTRACT_ERROR (tracker_extract_error_quark ()) -#define TRACKER_TYPE_EXTRACT (tracker_extract_get_type ()) -#define TRACKER_EXTRACT(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), TRACKER_TYPE_EXTRACT, TrackerExtract)) -#define TRACKER_EXTRACT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TRACKER_TYPE_EXTRACT, TrackerExtractClass)) -#define TRACKER_IS_EXTRACT(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), TRACKER_TYPE_EXTRACT)) -#define TRACKER_IS_EXTRACT_CLASS(klass)(G_TYPE_CHECK_CLASS_TYPE ((klass), TRACKER_TYPE_EXTRACT)) -#define TRACKER_EXTRACT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TRACKER_TYPE_EXTRACT, TrackerExtractClass)) - -typedef struct TrackerExtract TrackerExtract; -typedef struct TrackerExtractClass TrackerExtractClass; - -typedef enum { - TRACKER_EXTRACT_ERROR_NO_MIMETYPE, - TRACKER_EXTRACT_ERROR_NO_EXTRACTOR -} TrackerExtractError; - -struct TrackerExtract { - GObject parent; -}; - -struct TrackerExtractClass { - GObjectClass parent; -}; - -GQuark tracker_extract_error_quark (void); -GType tracker_extract_get_type (void); -TrackerExtract *tracker_extract_new (gboolean disable_shutdown, - const gchar *force_module); - -void tracker_extract_file (TrackerExtract *extract, - const gchar *file, - const gchar *mimetype, - GCancellable *cancellable, - GAsyncReadyCallback cb, - gpointer user_data); -TrackerExtractInfo * - tracker_extract_file_finish (TrackerExtract *extract, - GAsyncResult *res, - GError **error); - -void tracker_extract_dbus_start (TrackerExtract *extract); -void tracker_extract_dbus_stop (TrackerExtract *extract); - -/* Not DBus API */ -void tracker_extract_get_metadata_by_cmdline (TrackerExtract *object, - const gchar *path, - const gchar *mime, - TrackerSerializationFormat output_format); - -G_END_DECLS - -#endif /* __TRACKERD_EXTRACT_H__ */ diff --git a/src/tracker-extract/tracker-extract.service.in b/src/tracker-extract/tracker-extract.service.in deleted file mode 100644 index b7bc6c140..000000000 --- a/src/tracker-extract/tracker-extract.service.in +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Tracker metadata extractor - -[Service] -Type=dbus -BusName=org.freedesktop.Tracker1.Miner.Extract -ExecStart=@libexecdir@/tracker-extract -Restart=on-failure -# Don't restart after tracker daemon -k (aka tracker-control -k) -RestartPreventExitStatus=SIGKILL diff --git a/src/tracker-extract/tracker-gsf.c b/src/tracker-extract/tracker-gsf.c deleted file mode 100644 index 592a37bb8..000000000 --- a/src/tracker-extract/tracker-gsf.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include <errno.h> -#include <string.h> - -#include <glib.h> - -#include <libtracker-common/tracker-file-utils.h> - -#include <gsf/gsf.h> -#include <gsf/gsf-infile.h> -#include <gsf/gsf-input-stdio.h> -#include <gsf/gsf-infile-zip.h> - -#include "tracker-gsf.h" - -/* Size of the buffer to use */ -#define XML_BUFFER_SIZE 8192 /* bytes */ -/* Note: 20 MBytes of max size is really assumed to be a safe limit. */ -#define XML_MAX_BYTES_READ (20u << 20) /* bytes */ - -/** - * based on find_member() from vsd_utils.c: - * http://vsdump.sourcearchive.com/documentation/0.0.44/vsd__utils_8c-source.html - */ -static GsfInput * -find_member (GsfInfile *arch, - gchar const *name) -{ - gchar const *slash; - - slash = strchr (name, '/'); - - if (slash) { - gchar *dirname; - GsfInput *member; - - dirname = g_strndup (name, slash - name); - - /** - * Ignore if the directory is the current one that is ".". - * Go to next direcotry if exists - */ - - if (strcmp (dirname, ".") == 0) { - member = find_member (arch, slash + 1); - } else if ((member = gsf_infile_child_by_name (arch, dirname)) != NULL) { - GsfInfile *dir; - - dir = GSF_INFILE (member); - member = find_member (dir, slash + 1); - g_object_unref (dir); - } - - g_free (dirname); - return member; - } else { - return gsf_infile_child_by_name (arch, name); - } -} - -/** - * tracker_gsf_parse_xml_in_zip: - * @zip_file_uri: URI of the ZIP archive - * @xml_filename: Name of the XML file stored inside the ZIP archive - * @context: Markup context to be used when parsing the XML - * - * This function reads and parses the contents of an XML file stored - * inside a ZIP compressed archive. Reading and parsing is done buffered, and - * maximum size of the uncompressed XML file is limited to be to 20MBytes. - */ -void -tracker_gsf_parse_xml_in_zip (const gchar *zip_file_uri, - const gchar *xml_filename, - GMarkupParseContext *context, - GError **err) -{ - gchar *filename; - GError *error = NULL; - GsfInfile *infile = NULL; - GsfInput *src = NULL; - GsfInput *member = NULL; - FILE *file; - - g_debug ("Parsing '%s' XML file contained inside zip archive...", - xml_filename); - - /* Get filename from the given URI */ - if ((filename = g_filename_from_uri (zip_file_uri, - NULL, &error)) == NULL) { - g_warning ("Can't get filename from uri '%s': %s", - zip_file_uri, error ? error->message : "no error given"); - } else { /* Create a new Input GSF object for the given file */ - - file = tracker_file_open (filename); - if (!file) { - g_warning ("Can't open file from uri '%s': %s", - zip_file_uri, g_strerror (errno)); - } else if ((src = gsf_input_stdio_new_FILE (filename, file, TRUE)) == NULL) { - g_warning ("Failed creating a GSF Input object for '%s': %s", - zip_file_uri, error ? error->message : "no error given"); - } - /* Input object is a Zip file */ - else if ((infile = gsf_infile_zip_new (src, &error)) == NULL) { - g_warning ("'%s' Not a zip file: %s", - zip_file_uri, error ? error->message : "no error given"); - } - /* Look for requested filename inside the ZIP file */ - else if ((member = find_member (infile, xml_filename)) == NULL) { - g_warning ("No member '%s' in zip file '%s'", - xml_filename, zip_file_uri); - } - /* Load whole contents of the internal file in the xml buffer */ - else { - guint8 buf[XML_BUFFER_SIZE]; - size_t remaining_size, chunk_size, accum; - - /* Get whole size of the contents to read */ - remaining_size = (size_t) gsf_input_size (GSF_INPUT (member)); - - /* Note that gsf_input_read() needs to be able to read ALL specified - * number of bytes, or it will fail */ - chunk_size = MIN (remaining_size, XML_BUFFER_SIZE); - - accum = 0; - while (!error && - accum <= XML_MAX_BYTES_READ && - chunk_size > 0 && - gsf_input_read (GSF_INPUT (member), chunk_size, buf) != NULL) { - - /* update accumulated count */ - accum += chunk_size; - - /* Pass the read stream to the context parser... */ - g_markup_parse_context_parse (context, buf, chunk_size, &error); - - /* update bytes to be read */ - remaining_size -= chunk_size; - chunk_size = MIN (remaining_size, XML_BUFFER_SIZE); - } - } - - if (file) { - tracker_file_close (file, FALSE); - } - } - - g_free (filename); - - if (error) - g_propagate_error (err, error); - if (infile) - g_object_unref (infile); - if (src) - g_object_unref (src); - if (member) - g_object_unref (member); -} - diff --git a/src/tracker-extract/tracker-gsf.h b/src/tracker-extract/tracker-gsf.h deleted file mode 100644 index bfc85ea64..000000000 --- a/src/tracker-extract/tracker-gsf.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_GSF_H__ -#define __TRACKER_GSF_H__ - -#include <glib.h> -#include <gsf/gsf.h> - -G_BEGIN_DECLS - -void tracker_gsf_parse_xml_in_zip (const gchar *zip_file_uri, - const gchar *xml_filename, - GMarkupParseContext *context, - GError **error); - -G_END_DECLS - -#endif /* __TRACKER_GSF_H__ */ - diff --git a/src/tracker-extract/tracker-main.c b/src/tracker-extract/tracker-main.c deleted file mode 100644 index 284c61929..000000000 --- a/src/tracker-extract/tracker-main.c +++ /dev/null @@ -1,492 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#define _XOPEN_SOURCE -#include <time.h> -#include <stdlib.h> -#include <locale.h> -#include <errno.h> -#include <sys/types.h> -#include <unistd.h> - -#include <glib-object.h> -#include <glib-unix.h> -#include <glib/gi18n.h> -#include <glib/gprintf.h> -#include <gio/gio.h> - -#ifndef G_OS_WIN32 -#include <sys/resource.h> -#endif - -#include <libtracker-common/tracker-common.h> - -#include <libtracker-data/tracker-db-manager.h> - -#include "tracker-config.h" -#include "tracker-main.h" -#include "tracker-extract.h" -#include "tracker-extract-controller.h" -#include "tracker-extract-decorator.h" - -#ifdef THREAD_ENABLE_TRACE -#warning Main thread traces enabled -#endif /* THREAD_ENABLE_TRACE */ - -#define ABOUT \ - "Tracker " PACKAGE_VERSION "\n" - -#define LICENSE \ - "This program is free software and comes without any warranty.\n" \ - "It is licensed under version 2 or later of the General Public " \ - "License which can be viewed at:\n" \ - "\n" \ - " http://www.gnu.org/licenses/gpl.txt\n" - -#define DBUS_NAME_SUFFIX "Miner.Extract" -#define DBUS_PATH "/org/freedesktop/Tracker1/Miner/Extract" - -static GMainLoop *main_loop; - -static gint verbosity = -1; -static gchar *filename; -static gchar *mime_type; -static gchar *force_module; -static gchar *output_format_name; -static gboolean version; -static gchar *domain_ontology_name = NULL; - -static TrackerConfig *config; - -static GOptionEntry entries[] = { - { "verbosity", 'v', 0, - G_OPTION_ARG_INT, &verbosity, - N_("Logging, 0 = errors only, " - "1 = minimal, 2 = detailed and 3 = debug (default = 0)"), - NULL }, - { "file", 'f', 0, - G_OPTION_ARG_FILENAME, &filename, - N_("File to extract metadata for"), - N_("FILE") }, - { "mime", 't', 0, - G_OPTION_ARG_STRING, &mime_type, - N_("MIME type for file (if not provided, this will be guessed)"), - N_("MIME") }, - { "force-module", 'm', 0, - G_OPTION_ARG_STRING, &force_module, - N_("Force a module to be used for extraction (e.g. “foo” for “foo.so”)"), - N_("MODULE") }, - { "output-format", 'o', 0, G_OPTION_ARG_STRING, &output_format_name, - N_("Output results format: “sparql”, or “turtle”"), - N_("FORMAT") }, - { "domain-ontology", 'd', 0, - G_OPTION_ARG_STRING, &domain_ontology_name, - N_("Runs for an specific domain ontology"), - NULL }, - { "version", 'V', 0, - G_OPTION_ARG_NONE, &version, - N_("Displays version information"), - NULL }, - { NULL } -}; - -static void -initialize_priority_and_scheduling (TrackerSchedIdle sched_idle, - gboolean first_time_index) -{ - /* Set CPU priority */ - if (sched_idle == TRACKER_SCHED_IDLE_ALWAYS || - (sched_idle == TRACKER_SCHED_IDLE_FIRST_INDEX && first_time_index)) { - tracker_sched_idle (); - } - - /* Set disk IO priority and scheduling */ - tracker_ioprio_init (); - - /* Set process priority: - * The nice() function uses attribute "warn_unused_result" and - * so complains if we do not check its returned value. But it - * seems that since glibc 2.2.4, nice() can return -1 on a - * successful call so we have to check value of errno too. - * Stupid... - */ - g_message ("Setting priority nice level to 19"); - - if (nice (19) == -1) { - const gchar *str = g_strerror (errno); - - g_message ("Couldn't set nice value to 19, %s", - str ? str : "no error given"); - } -} - -static void -initialize_directories (void) -{ - gchar *user_data_dir; - - /* NOTE: We don't create the database directories here, the - * tracker-db-manager does that for us. - */ - - user_data_dir = g_build_filename (g_get_user_data_dir (), - "tracker", - NULL); - - /* g_message ("Checking directory exists:'%s'", user_data_dir); */ - g_mkdir_with_parents (user_data_dir, 00755); - - g_free (user_data_dir); -} - -static gboolean -signal_handler (gpointer user_data) -{ - int signo = GPOINTER_TO_INT (user_data); - - static gboolean in_loop = FALSE; - - /* Die if we get re-entrant signals handler calls */ - if (in_loop) { - _exit (EXIT_FAILURE); - } - - switch (signo) { - case SIGTERM: - case SIGINT: - in_loop = TRUE; - g_main_loop_quit (main_loop); - - /* Fall through */ - default: - if (g_strsignal (signo)) { - g_print ("\n"); - g_print ("Received signal:%d->'%s'\n", - signo, - g_strsignal (signo)); - } - break; - } - - return G_SOURCE_CONTINUE; -} - -static void -initialize_signal_handler (void) -{ -#ifndef G_OS_WIN32 - g_unix_signal_add (SIGTERM, signal_handler, GINT_TO_POINTER (SIGTERM)); - g_unix_signal_add (SIGINT, signal_handler, GINT_TO_POINTER (SIGINT)); -#endif /* G_OS_WIN32 */ -} - -static void -log_handler (const gchar *domain, - GLogLevelFlags log_level, - const gchar *message, - gpointer user_data) -{ - switch (log_level) { - case G_LOG_LEVEL_WARNING: - case G_LOG_LEVEL_CRITICAL: - case G_LOG_LEVEL_ERROR: - case G_LOG_FLAG_RECURSION: - case G_LOG_FLAG_FATAL: - g_fprintf (stderr, "%s\n", message); - fflush (stderr); - break; - case G_LOG_LEVEL_MESSAGE: - case G_LOG_LEVEL_INFO: - case G_LOG_LEVEL_DEBUG: - case G_LOG_LEVEL_MASK: - default: - g_fprintf (stdout, "%s\n", message); - fflush (stdout); - break; - } -} - -static void -sanity_check_option_values (TrackerConfig *config) -{ - g_message ("General options:"); - g_message (" Verbosity ............................ %d", - tracker_config_get_verbosity (config)); - g_message (" Sched Idle ........................... %d", - tracker_config_get_sched_idle (config)); - g_message (" Max bytes (per file) ................. %d", - tracker_config_get_max_bytes (config)); -} - -TrackerConfig * -tracker_main_get_config (void) -{ - return config; -} - -static int -run_standalone (TrackerConfig *config) -{ - TrackerExtract *object; - GFile *file; - gchar *uri; - GEnumClass *enum_class; - GEnumValue *enum_value; - TrackerSerializationFormat output_format; - - /* Set log handler for library messages */ - g_log_set_default_handler (log_handler, NULL); - - /* Set the default verbosity if unset */ - if (verbosity == -1) { - verbosity = 3; - } - - if (!output_format_name) { - output_format_name = "turtle"; - } - - /* Look up the output format by name */ - enum_class = g_type_class_ref (TRACKER_TYPE_SERIALIZATION_FORMAT); - enum_value = g_enum_get_value_by_nick (enum_class, output_format_name); - g_type_class_unref (enum_class); - if (!enum_value) { - g_printerr (N_("Unsupported serialization format “%s”\n"), output_format_name); - return EXIT_FAILURE; - } - output_format = enum_value->value; - - tracker_locale_sanity_check (); - - /* This makes sure we don't steal all the system's resources */ - initialize_priority_and_scheduling (tracker_config_get_sched_idle (config), TRUE); - - file = g_file_new_for_commandline_arg (filename); - uri = g_file_get_uri (file); - - object = tracker_extract_new (TRUE, force_module); - - if (!object) { - g_object_unref (file); - g_free (uri); - return EXIT_FAILURE; - } - - tracker_extract_get_metadata_by_cmdline (object, uri, mime_type, output_format); - - g_object_unref (object); - g_object_unref (file); - g_free (uri); - - return EXIT_SUCCESS; -} - -static void -on_domain_vanished (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - GMainLoop *loop = user_data; - g_main_loop_quit (loop); -} - -int -main (int argc, char *argv[]) -{ - GOptionContext *context; - GError *error = NULL; - TrackerExtract *extract; - TrackerDecorator *decorator; - TrackerExtractController *controller; - gchar *log_filename = NULL; - GMainLoop *my_main_loop; - GDBusConnection *connection; - TrackerMinerProxy *proxy; - TrackerDomainOntology *domain_ontology; - gchar *dbus_name; - - bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); - - /* Translators: this message will appear immediately after the */ - /* usage string - Usage: COMMAND [OPTION]... <THIS_MESSAGE> */ - context = g_option_context_new (_("— Extract file meta data")); - - g_option_context_add_main_entries (context, entries, NULL); - g_option_context_parse (context, &argc, &argv, &error); - - if (!filename && mime_type) { - gchar *help; - - g_printerr ("%s\n\n", - _("Filename and mime type must be provided together")); - - help = g_option_context_get_help (context, TRUE, NULL); - g_option_context_free (context); - g_printerr ("%s", help); - g_free (help); - - return EXIT_FAILURE; - } - - g_option_context_free (context); - - if (version) { - g_print ("\n" ABOUT "\n" LICENSE "\n"); - return EXIT_SUCCESS; - } - - g_set_application_name ("tracker-extract"); - - setlocale (LC_ALL, ""); - - tracker_sparql_connection_set_domain (domain_ontology_name); - - domain_ontology = tracker_domain_ontology_new (domain_ontology_name, NULL, &error); - if (error) { - g_critical ("Could not load domain ontology '%s': %s", - domain_ontology_name, error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, &error); - if (error) { - g_critical ("Could not create DBus connection: %s\n", - error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - config = tracker_config_new (); - - /* Extractor command line arguments */ - if (verbosity > -1) { - tracker_config_set_verbosity (config, verbosity); - } - - tracker_log_init (tracker_config_get_verbosity (config), &log_filename); - if (log_filename != NULL) { - g_message ("Using log file:'%s'", log_filename); - g_free (log_filename); - } - - sanity_check_option_values (config); - - /* Set conditions when we use stand alone settings */ - if (filename) { - return run_standalone (config); - } - - /* Initialize subsystems */ - initialize_directories (); - - /* This makes sure we don't steal all the system's resources */ - initialize_priority_and_scheduling (tracker_config_get_sched_idle (config), TRUE); - - extract = tracker_extract_new (TRUE, force_module); - - if (!extract) { - g_object_unref (config); - tracker_log_shutdown (); - return EXIT_FAILURE; - } - - tracker_module_manager_load_modules (); - - decorator = tracker_extract_decorator_new (extract, NULL, &error); - - if (error) { - g_critical ("Could not start decorator: %s\n", error->message); - g_object_unref (config); - tracker_log_shutdown (); - return EXIT_FAILURE; - } - - proxy = tracker_miner_proxy_new (TRACKER_MINER (decorator), connection, DBUS_PATH, NULL, &error); - if (error) { - g_critical ("Could not create miner DBus proxy: %s\n", error->message); - g_error_free (error); - g_object_unref (decorator); - g_object_unref (config); - tracker_log_shutdown (); - return EXIT_FAILURE; - } - -#ifdef THREAD_ENABLE_TRACE - g_debug ("Thread:%p (Main) --- Waiting for extract requests...", - g_thread_self ()); -#endif /* THREAD_ENABLE_TRACE */ - - tracker_locale_sanity_check (); - - controller = tracker_extract_controller_new (decorator, connection); - tracker_miner_start (TRACKER_MINER (decorator)); - - /* Request DBus name */ - dbus_name = tracker_domain_ontology_get_domain (domain_ontology, DBUS_NAME_SUFFIX); - - if (!tracker_dbus_request_name (connection, dbus_name, &error)) { - g_critical ("Could not request DBus name '%s': %s", - dbus_name, error->message); - g_error_free (error); - g_free (dbus_name); - return EXIT_FAILURE; - } - - g_free (dbus_name); - - /* Main loop */ - main_loop = g_main_loop_new (NULL, FALSE); - - if (domain_ontology && domain_ontology_name) { - g_bus_watch_name_on_connection (connection, domain_ontology_name, - G_BUS_NAME_WATCHER_FLAGS_NONE, - NULL, on_domain_vanished, - main_loop, NULL); - } - - initialize_signal_handler (); - - g_main_loop_run (main_loop); - - my_main_loop = main_loop; - main_loop = NULL; - g_main_loop_unref (my_main_loop); - - tracker_miner_stop (TRACKER_MINER (decorator)); - - /* Shutdown subsystems */ - g_object_unref (extract); - g_object_unref (decorator); - g_object_unref (controller); - g_object_unref (proxy); - g_object_unref (connection); - g_object_unref (domain_ontology); - - tracker_log_shutdown (); - - g_object_unref (config); - - return EXIT_SUCCESS; -} diff --git a/src/tracker-extract/tracker-main.h b/src/tracker-extract/tracker-main.h deleted file mode 100644 index 77d798e3a..000000000 --- a/src/tracker-extract/tracker-main.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2006, Jamie McCracken <jamiemcc@gnome.org> - * Copyright (C) 2008, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_MAIN_H__ -#define __TRACKER_MAIN_H__ - -#include "tracker-config.h" - -G_BEGIN_DECLS - -/* This is used to not shutdown after the default of 30 seconds if we - * get more work to do. - */ -void tracker_main_quit_timeout_reset (void); - -/* Enables getting the config object from extractors */ -TrackerConfig *tracker_main_get_config (void); - -G_END_DECLS - -#endif /* __TRACKER_MAIN_H__ */ diff --git a/src/tracker-extract/tracker-read.c b/src/tracker-extract/tracker-read.c deleted file mode 100644 index 89ae1337a..000000000 --- a/src/tracker-extract/tracker-read.c +++ /dev/null @@ -1,384 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <string.h> -#include <unistd.h> -#include <fcntl.h> - -#include <glib.h> -#include <gio/gio.h> - -#include <libtracker-extract/tracker-extract.h> - -#include "tracker-read.h" - -/* Size of the buffer to use when reading, in bytes */ -#define BUFFER_SIZE 65535 - -static gchar * -get_string_from_guessed_encoding (const gchar *str, - gsize str_len, - gsize *utf8_len) -{ - const gchar *current = NULL; - - /* If we have embedded NULs try UTF-16 directly */ - if (memchr (str, '\0', str_len)) - current = "UTF-16"; - /* If locale charset is UTF-8, try with windows-1252. - * NOTE: g_get_charset() returns TRUE if locale charset is UTF-8 */ - else if (g_get_charset (¤t)) - current = "windows-1252"; - - while (current) { - gchar *utf8_str; - gsize bytes_read = 0; - gsize bytes_written = 0; - - utf8_str = g_convert (str, - str_len, - "UTF-8", - current, - &bytes_read, - &bytes_written, - NULL); - if (utf8_str && - str_len == bytes_read) { - g_debug ("Converted %" G_GSIZE_FORMAT " bytes in '%s' codeset " - "to %" G_GSIZE_FORMAT " bytes in UTF-8", - bytes_read, - current, - bytes_written); - *utf8_len = bytes_written; - return utf8_str; - } - g_free (utf8_str); - - g_debug ("Text not in '%s' encoding", current); - - if (!strcmp (current, "windows-1252") || - !strcmp (current, "UTF-16")) - /* If we tried windows-1252 or UTF-16, don't try anything else */ - current = NULL; - else - /* If we tried a locale encoding and didn't work, retry with - * windows-1252 */ - current = "windows-1252"; - } - - return NULL; -} - -/* Returns %TRUE if read operation should continue, %FALSE otherwise */ -static gboolean -process_chunk (const gchar *read_bytes, - gsize read_size, - gsize buffer_size, - gsize *remaining_size, - GString **s) -{ - /* If no more bytes to read, halt loop */ - if (read_size == 0) { - return FALSE; - } - - /* First of all, check if this is the first time we - * have tried to read the stream up to the BUFFER_SIZE - * limit. Then make sure that we read the maximum size - * of the buffer. If we don't do this, there is the - * case where we read 10 bytes in and it is just one - * line with no '\n'. Once we have confirmed this we - * check that the buffer has a '\n' to make sure the - * file is worth indexing. Similarly if the file has - * <= 3 bytes then we drop it. - * - * NOTE: We may have non-UTF8 content read (say, - * UTF-16LE), so we can't rely on methods which assume - * NUL-terminated strings, as g_strstr_len(). - */ - if (*s == NULL) { - if (read_size <= 3) { - g_debug (" File has less than 3 characters in it, " - "not indexing file"); - return FALSE; - } - - if (read_size == buffer_size) { - const gchar *i; - gboolean eol_found = FALSE; - - i = read_bytes; - while (i != &read_bytes[read_size - 1]) { - if (*i == '\n') { - eol_found = TRUE; - break; - } - i++; - } - - if (!eol_found) { - g_debug (" No '\\n' in the first %" G_GSSIZE_FORMAT " bytes, " - "not indexing file", - read_size); - return FALSE; - } - } - } - - /* Update remaining bytes */ - *remaining_size -= read_size; - - g_debug (" Read " - "%" G_GSSIZE_FORMAT " bytes from file, %" G_GSIZE_FORMAT " " - "bytes remaining until configured threshold is reached", - read_size, - *remaining_size); - - /* Append non-NIL terminated bytes */ - *s = (*s ? - g_string_append_len (*s, read_bytes, read_size) : - g_string_new_len (read_bytes, read_size)); - - return TRUE; -} - -static gchar * -process_whole_string (GString *s) -{ - gchar *utf8 = NULL; - gsize utf8_len = 0; - gsize n_valid_utf8_bytes = 0; - - /* Support also UTF-16 encoded text files, as the ones generated in - * Windows OS. We will only accept text files in UTF-16 which come - * with a proper BOM. */ - if (s->len > 2) { - GError *error = NULL; - - if (memcmp (s->str, "\xFF\xFE", 2) == 0) { - g_debug ("String comes in UTF-16LE, converting"); - utf8 = g_convert (&(s->str[2]), - s->len - 2, - "UTF-8", - "UTF-16LE", - NULL, - &utf8_len, - &error); - - } else if (memcmp (s->str, "\xFE\xFF", 2) == 0) { - g_debug ("String comes in UTF-16BE, converting"); - utf8 = g_convert (&(s->str[2]), - s->len - 2, - "UTF-8", - "UTF-16BE", - NULL, - &utf8_len, - &error); - } - - if (error) { - g_warning ("Couldn't convert string from UTF-16 to UTF-8...: %s", - error->message); - g_error_free (error); - g_string_free (s, TRUE); - return NULL; - } - } - - if (utf8) { - n_valid_utf8_bytes = utf8_len; - g_string_free (s, TRUE); - } else { - utf8_len = s->len; - utf8 = g_string_free (s, FALSE); - - /* Get number of valid UTF-8 bytes found */ - tracker_text_validate_utf8 (utf8, - utf8_len, - NULL, - &n_valid_utf8_bytes); - } - - /* A valid UTF-8 file will be that where all read bytes are valid, - * with a margin of 3 bytes for the last UTF-8 character which might - * have been cut. */ - if (utf8_len - n_valid_utf8_bytes > 3) { - gchar *from_guessed_str; - gsize from_guessed_str_len; - - /* If not UTF-8, try to get contents in guessed encoding - * (returns valid UTF-8) */ - from_guessed_str = get_string_from_guessed_encoding (utf8, - utf8_len, - &from_guessed_str_len); - g_free (utf8); - if (!from_guessed_str) - return NULL; - utf8 = from_guessed_str; - utf8_len = from_guessed_str_len; - } else if (n_valid_utf8_bytes < utf8_len) { - g_debug (" Truncating to last valid UTF-8 character " - "(%" G_GSSIZE_FORMAT "/%" G_GSSIZE_FORMAT " bytes)", - n_valid_utf8_bytes, - utf8_len); - utf8[n_valid_utf8_bytes] = '\0'; - utf8_len = n_valid_utf8_bytes; - } - - if (utf8_len < 1) { - g_free (utf8); - return NULL; - } - - return utf8; -} - -/** - * tracker_read_text_from_stream: - * @stream: input stream to read from - * @max_bytes: max number of bytes to read from @stream - * - * Reads up to @max_bytes from @stream, and validates the read text as proper - * UTF-8. - * - * If the input text is not UTF-8 it will also try to decode it based on the - * current locale, or windows-1252, or UTF-16. - * - * Returns: newly-allocated NUL-terminated UTF-8 string with the read text. - **/ -gchar * -tracker_read_text_from_stream (GInputStream *stream, - gsize max_bytes) -{ - GString *s = NULL; - gsize n_bytes_remaining = max_bytes; - - g_return_val_if_fail (stream, NULL); - g_return_val_if_fail (max_bytes > 0, NULL); - - /* Reading in chunks of BUFFER_SIZE - * Loop is halted whenever one of this conditions is met: - * a) Read bytes reached the maximum allowed (max_bytes) - * b) No more bytes to read - * c) Error reading - * d) Stream has less than 3 bytes - * e) Stream has a single line of BUFFER_SIZE bytes with no EOL - */ - while (n_bytes_remaining > 0) { - gchar buf[BUFFER_SIZE]; - GError *error = NULL; - gsize n_bytes_read; - - /* Read bytes from stream */ - if (!g_input_stream_read_all (stream, - buf, - MIN (BUFFER_SIZE, n_bytes_remaining), - &n_bytes_read, - NULL, - &error)) { - g_message ("Error reading from stream: '%s'", - error->message); - g_error_free (error); - break; - } - - /* Process read bytes, and halt loop if needed */ - if (!process_chunk (buf, - n_bytes_read, - BUFFER_SIZE, - &n_bytes_remaining, - &s)) { - break; - } - } - - /* Validate UTF-8 if something was read, and return it */ - return s ? process_whole_string (s) : NULL; -} - - -/** - * tracker_read_text_from_fd: - * @fd: input fd to read from - * @max_bytes: max number of bytes to read from @fd - * - * Reads up to @max_bytes from @fd, and validates the read text as proper - * UTF-8. Will also properly close the FD when finishes. - * - * If the input text is not UTF-8 it will also try to decode it based on the - * current locale, or windows-1252, or UTF-16. - * - * Returns: newly-allocated NUL-terminated UTF-8 string with the read text. - **/ -gchar * -tracker_read_text_from_fd (gint fd, - gsize max_bytes) -{ - FILE *fz; - GString *s = NULL; - gsize n_bytes_remaining = max_bytes; - - g_return_val_if_fail (max_bytes > 0, NULL); - - if ((fz = fdopen (fd, "r")) == NULL) { - g_warning ("Cannot read from FD... could not extract text"); - close (fd); - return NULL; - } - - /* Reading in chunks of BUFFER_SIZE - * Loop is halted whenever one of this conditions is met: - * a) Read bytes reached the maximum allowed (max_bytes) - * b) No more bytes to read - * c) Error reading - * d) Stream has less than 3 bytes - * e) Stream has a single line of BUFFER_SIZE bytes with no EOL - */ - while (n_bytes_remaining > 0) { - gchar buf[BUFFER_SIZE]; - gsize n_bytes_read; - - /* Read bytes */ - n_bytes_read = fread (buf, - 1, - MIN (BUFFER_SIZE, n_bytes_remaining), - fz); - - /* Process read bytes, and halt loop if needed */ - if (!process_chunk (buf, - n_bytes_read, - BUFFER_SIZE, - &n_bytes_remaining, - &s)) { - break; - } - } - - /* Close the file here */ -#ifdef HAVE_POSIX_FADVISE - if (posix_fadvise (fd, 0, 0, POSIX_FADV_DONTNEED) != 0) - g_warning ("posix_fadvise() call failed: %m"); -#endif /* HAVE_POSIX_FADVISE */ - fclose (fz); - - /* Validate UTF-8 if something was read, and return it */ - return s ? process_whole_string (s) : NULL; -} diff --git a/src/tracker-extract/tracker-read.h b/src/tracker-extract/tracker-read.h deleted file mode 100644 index 513801916..000000000 --- a/src/tracker-extract/tracker-read.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_READ_H__ -#define __TRACKER_READ_H__ - -#include <glib.h> -#include <gio/gio.h> - -G_BEGIN_DECLS - -gchar *tracker_read_text_from_stream (GInputStream *stream, - gsize max_bytes); - -gchar *tracker_read_text_from_fd (gint fd, - gsize max_bytes); - -G_END_DECLS - -#endif /* __TRACKER_READ_H__ */ diff --git a/src/tracker-store/org.freedesktop.Tracker.gschema.xml.in b/src/tracker-store/org.freedesktop.Tracker.gschema.xml.in index b9ddc1d12..e6007bbd2 100644 --- a/src/tracker-store/org.freedesktop.Tracker.gschema.xml.in +++ b/src/tracker-store/org.freedesktop.Tracker.gschema.xml.in @@ -22,10 +22,5 @@ Boston, MA 02110-1301, USA. <child name="db" schema="org.freedesktop.Tracker.DB"/> <child name="fts" schema="org.freedesktop.Tracker.FTS"/> <child name="store" schema="org.freedesktop.Tracker.Store"/> - <child name="extract" schema="org.freedesktop.Tracker.Extract"/> - <child name="writeback" schema="org.freedesktop.Tracker.Writeback"/> - <child name="miner" schema="org.freedesktop.Tracker.Miner"/> </schema> - - <schema id="org.freedesktop.Tracker.Miner" path="/org/freedesktop/tracker/miner/" /> </schemalist> diff --git a/src/tracker-writeback/.gitignore b/src/tracker-writeback/.gitignore deleted file mode 100644 index 6e569e743..000000000 --- a/src/tracker-writeback/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -tracker-writeback -*.service -*.xml -*.valid -*.cfg.5 diff --git a/src/tracker-writeback/Makefile.am b/src/tracker-writeback/Makefile.am deleted file mode 100644 index 1a36187e1..000000000 --- a/src/tracker-writeback/Makefile.am +++ /dev/null @@ -1,97 +0,0 @@ -module_flags = -module -avoid-version -no-undefined -modulesdir = $(libdir)/tracker-$(TRACKER_API_VERSION)/writeback-modules - -AM_CPPFLAGS = \ - $(BUILD_CFLAGS) \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - -DLOCALEDIR=\""$(localedir)"\" \ - -DMODULESDIR=\"$(modulesdir)\" \ - -DWRITEBACK_MODULES_DIR=\""$(modulesdir)"\" \ - $(TRACKER_WRITEBACK_CFLAGS) \ - $(LIBTRACKER_MINER_CFLAGS) - - -modules_LTLIBRARIES = - -# Audio files (MP3, MPC, FLAC, MP4, ASF, AIFF, WAV, TrueAudio, WavPack, -# Ogg FLAC, Ogg Vorbis and Speex) -if HAVE_TAGLIB -modules_LTLIBRARIES += libwriteback-taglib.la -libwriteback_taglib_la_SOURCES = tracker-writeback-taglib.c -libwriteback_taglib_la_LDFLAGS = $(module_flags) -libwriteback_taglib_la_LIBADD = $(BUILD_LIBS) $(GLIB2_LIBS) $(TAGLIB_LIBS) -endif - -# XMP -if HAVE_EXEMPI -modules_LTLIBRARIES += libwriteback-xmp.la -libwriteback_xmp_la_SOURCES = tracker-writeback-xmp.c -libwriteback_xmp_la_LDFLAGS = $(module_flags) -libwriteback_xmp_la_LIBADD = $(BUILD_LIBS) $(GLIB2_LIBS) $(EXEMPI_LIBS) -endif - -# Playlists -#if HAVE_TOTEM_PL_PARSER -#modules_LTLIBRARIES += libwriteback-playlist.la -#libwriteback_playlist_la_SOURCES = tracker-writeback-playlist.c -#libwriteback_playlist_la_LDFLAGS = $(module_flags) -#libwriteback_playlist_la_LIBADD = $(BUILD_LIBS) $(GLIB2_LIBS) $(TOTEM_PL_PARSER_LIBS) -#endif - -libexec_PROGRAMS = tracker-writeback - -tracker_writeback_SOURCES = \ - $(dbus_sources) \ - tracker-config.c \ - tracker-config.h \ - tracker-writeback-file.c \ - tracker-writeback-file.h \ - tracker-writeback-module.c \ - tracker-writeback-module.h \ - tracker-writeback.c \ - tracker-writeback.h \ - tracker-main.c - -tracker_writeback_LDADD = \ - $(top_builddir)/src/libtracker-sparql-backend/libtracker-sparql-@TRACKER_API_VERSION@.la \ - $(top_builddir)/src/libtracker-miner/libtracker-miner-@TRACKER_API_VERSION@.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_WRITEBACK_LIBS) - -# DBus interfaces (XML files) and services -configdir = $(datadir)/tracker -config_DATA = tracker-writeback.xml - -%.service: %.service.in - @sed -e "s|@libexecdir[@]|${libexecdir}|" $< > $@ - -servicedir = $(DBUS_SERVICES_DIR) -service_DATA = org.freedesktop.Tracker1.Writeback.service - -systemd_userdir = $(prefix)/lib/systemd/user -systemd_user_DATA = tracker-writeback.service - -# Configuration / GSettings -gsettings_ENUM_NAMESPACE = org.freedesktop.Tracker -gsettings_ENUM_FILES = $(top_srcdir)/src/libtracker-common/tracker-enums.h - -gsettings_SCHEMAS = org.freedesktop.Tracker.Writeback.gschema.xml - -@INTLTOOL_XML_NOMERGE_RULE@ - -@GSETTINGS_RULES@ - -# Dist / Clean rules for all data -CLEANFILES = \ - $(service_DATA) \ - $(systemd_user_DATA) \ - $(gsettings_SCHEMAS) - -EXTRA_DIST = \ - $(service_DATA:.service=.service.in) \ - $(systemd_user_DATA:.service=.service.in) \ - $(config_DATA) \ - $(gsettings_SCHEMAS:.xml=.xml.in) \ - meson.build diff --git a/src/tracker-writeback/meson.build b/src/tracker-writeback/meson.build deleted file mode 100644 index f5560bea5..000000000 --- a/src/tracker-writeback/meson.build +++ /dev/null @@ -1,76 +0,0 @@ -# Writeback modules are tracked here as arrays with the following elements: -# -# [ name, source-files, dependencies ] -# -# This might be nicer if Meson supported dictionary types. - -modules = [] - -if taglib.found() - modules += [['writeback-taglib', 'tracker-writeback-taglib.c', [tracker_common_dep, tracker_miner_dep, tracker_sparql_dep, taglib]]] -endif - -if exempi.found() - modules += [['writeback-xmp', 'tracker-writeback-xmp.c', [tracker_common_dep, tracker_miner_dep, tracker_sparql_dep, exempi]]] -endif - -foreach module : modules - name = module[0] - sources = module[1] - dependencies = module[2] - - shared_module(name, sources, - c_args: tracker_c_args, - dependencies: dependencies, - include_directories: configinc, - install: true, - install_dir: tracker_writeback_modules_dir) -endforeach - -tracker_writeback_sources = [ - 'tracker-config.c', - 'tracker-config.h', - 'tracker-writeback-file.c', - 'tracker-writeback-file.h', - 'tracker-writeback-module.c', - 'tracker-writeback-module.h', - 'tracker-writeback.c', - 'tracker-writeback.h', - 'tracker-main.c' -] - -executable('tracker-writeback', - tracker_writeback_sources, - c_args: tracker_c_args + [ - '-DWRITEBACK_MODULES_DIR="@0@"'.format(tracker_writeback_modules_dir), - ], - dependencies: [gmodule, tracker_common_dep, tracker_miner_dep, tracker_sparql_dep], - install: true, - install_dir: join_paths(get_option('prefix'), get_option('libexecdir'))) - -install_data( - 'tracker-writeback.xml', - install_dir: join_paths(get_option('prefix'), get_option('datadir'), 'tracker')) - -dbus_service_file = configure_file( - input: 'org.freedesktop.Tracker1.Writeback.service.in', - output: 'org.freedesktop.Tracker1.Writeback.service', - configuration: conf, - install: true, - install_dir: dbus_services_dir) - -custom_target('tracker-writeback-settings-schema', - input: 'org.freedesktop.Tracker.Writeback.gschema.xml.in', - output: 'org.freedesktop.Tracker.Writeback.gschema.xml', - command: ['intltool-merge', '--quiet', '--xml-style', '--utf8', join_paths(meson.source_root(), 'po'), '@INPUT@', '@OUTPUT@'], - install: true, - install_dir: join_paths(get_option('datadir'), 'glib-2.0', 'schemas')) - -if install_systemd_user_services - configure_file( - input: 'tracker-writeback.service.in', - output: 'tracker-writeback.service', - configuration: conf, - install: true, - install_dir: systemd_user_services_dir) -endif diff --git a/src/tracker-writeback/org.freedesktop.Tracker.Writeback.gschema.xml.in b/src/tracker-writeback/org.freedesktop.Tracker.Writeback.gschema.xml.in deleted file mode 100644 index 093e788ba..000000000 --- a/src/tracker-writeback/org.freedesktop.Tracker.Writeback.gschema.xml.in +++ /dev/null @@ -1,28 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- -Copyright (C) 2011, Nokia <ivan.frade@nokia.com> - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. - -This library 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 -Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public -License along with this library; if not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -Boston, MA 02110-1301, USA. ---> -<schemalist> - <schema id="org.freedesktop.Tracker.Writeback" path="/org/freedesktop/tracker/writeback/" gettext-domain="tracker"> - <key name="verbosity" enum="org.freedesktop.Tracker.TrackerVerbosity"> - <default>'errors'</default> - <_summary>Log verbosity</_summary> - <_description>Log verbosity.</_description> - </key> - </schema> -</schemalist> diff --git a/src/tracker-writeback/org.freedesktop.Tracker1.Writeback.service.in b/src/tracker-writeback/org.freedesktop.Tracker1.Writeback.service.in deleted file mode 100644 index 81a2ec271..000000000 --- a/src/tracker-writeback/org.freedesktop.Tracker1.Writeback.service.in +++ /dev/null @@ -1,4 +0,0 @@ -[D-BUS Service] -Name=org.freedesktop.Tracker1.Writeback -Exec=@libexecdir@/tracker-writeback -SystemdService=tracker-writeback.service diff --git a/src/tracker-writeback/tracker-config.c b/src/tracker-writeback/tracker-config.c deleted file mode 100644 index dce879835..000000000 --- a/src/tracker-writeback/tracker-config.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * Copyright (C) 2014, Lanedo <martyn@lanedo.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <string.h> -#include <stdlib.h> - -#include <glib.h> -#include <gio/gio.h> - -#define G_SETTINGS_ENABLE_BACKEND -#include <gio/gsettingsbackend.h> - -#include <libtracker-common/tracker-common.h> - -#include "tracker-config.h" - -#define CONFIG_SCHEMA "org.freedesktop.Tracker.Writeback" -#define CONFIG_PATH "/org/freedesktop/tracker/writeback/" - -static void config_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec); -static void config_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec); -static void config_finalize (GObject *object); -static void config_constructed (GObject *object); - -enum { - PROP_0, - PROP_VERBOSITY, -}; - -G_DEFINE_TYPE (TrackerConfig, tracker_config, G_TYPE_SETTINGS); - -static void -tracker_config_class_init (TrackerConfigClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->set_property = config_set_property; - object_class->get_property = config_get_property; - object_class->finalize = config_finalize; - object_class->constructed = config_constructed; - - g_object_class_install_property (object_class, - PROP_VERBOSITY, - g_param_spec_enum ("verbosity", - "Log verbosity", - "Log verbosity (0=errors, 1=minimal, 2=detailed, 3=debug)", - TRACKER_TYPE_VERBOSITY, - TRACKER_VERBOSITY_ERRORS, - G_PARAM_READWRITE)); -} - -static void -tracker_config_init (TrackerConfig *object) -{ -} - -static void -config_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (param_id) { - case PROP_VERBOSITY: - tracker_config_set_verbosity (TRACKER_CONFIG (object), - g_value_get_enum (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - }; -} - -static void -config_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - switch (param_id) { - case PROP_VERBOSITY: - g_value_set_enum (value, tracker_config_get_verbosity (TRACKER_CONFIG (object))); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); - break; - }; -} - -static void -config_finalize (GObject *object) -{ - (G_OBJECT_CLASS (tracker_config_parent_class)->finalize) (object); -} - -static void -config_constructed (GObject *object) -{ - GSettings *settings; - - (G_OBJECT_CLASS (tracker_config_parent_class)->constructed) (object); - - settings = G_SETTINGS (object); - - if (G_LIKELY (!g_getenv ("TRACKER_USE_CONFIG_FILES"))) { - g_settings_delay (settings); - } - - g_settings_bind (settings, "verbosity", object, "verbosity", G_SETTINGS_BIND_GET | G_SETTINGS_BIND_GET_NO_CHANGES); -} - -TrackerConfig * -tracker_config_new (void) -{ - TrackerConfig *config = NULL; - - /* FIXME: should we unset GSETTINGS_BACKEND env var? */ - - if (G_UNLIKELY (g_getenv ("TRACKER_USE_CONFIG_FILES"))) { - GSettingsBackend *backend; - gchar *filename, *basename; - gboolean need_to_save; - - basename = g_strdup_printf ("%s.cfg", g_get_prgname ()); - filename = g_build_filename (g_get_user_config_dir (), "tracker", basename, NULL); - g_free (basename); - - need_to_save = g_file_test (filename, G_FILE_TEST_EXISTS) == FALSE; - - backend = g_keyfile_settings_backend_new (filename, CONFIG_PATH, "General"); - g_info ("Using config file '%s'", filename); - g_free (filename); - - config = g_object_new (TRACKER_TYPE_CONFIG, - "backend", backend, - "schema-id", CONFIG_SCHEMA, - "path", CONFIG_PATH, - NULL); - g_object_unref (backend); - - if (need_to_save) { - g_info (" Config file does not exist, using default values..."); - } - } else { - config = g_object_new (TRACKER_TYPE_CONFIG, - "schema-id", CONFIG_SCHEMA, - "path", CONFIG_PATH, - NULL); - } - - return config; -} - -gint -tracker_config_get_verbosity (TrackerConfig *config) -{ - g_return_val_if_fail (TRACKER_IS_CONFIG (config), 0); - - return g_settings_get_enum (G_SETTINGS (config), "verbosity"); -} - -void -tracker_config_set_verbosity (TrackerConfig *config, - gint value) -{ - g_return_if_fail (TRACKER_IS_CONFIG (config)); - - g_settings_set_enum (G_SETTINGS (config), "verbosity", value); - g_object_notify (G_OBJECT (config), "verbosity"); -} diff --git a/src/tracker-writeback/tracker-config.h b/src/tracker-writeback/tracker-config.h deleted file mode 100644 index 93926822d..000000000 --- a/src/tracker-writeback/tracker-config.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2009%, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_WRITEBACK_CONFIG_H__ -#define __TRACKER_WRITEBACK_CONFIG_H__ - -#include <glib-object.h> -#include <gio/gio.h> - -G_BEGIN_DECLS - -#define TRACKER_TYPE_CONFIG (tracker_config_get_type ()) -#define TRACKER_CONFIG(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_CONFIG, TrackerConfig)) -#define TRACKER_CONFIG_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TRACKER_TYPE_CONFIG, TrackerConfigClass)) -#define TRACKER_IS_CONFIG(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_CONFIG)) -#define TRACKER_IS_CONFIG_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TRACKER_TYPE_CONFIG)) -#define TRACKER_CONFIG_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_CONFIG, TrackerConfigClass)) - -typedef struct TrackerConfig TrackerConfig; -typedef struct TrackerConfigClass TrackerConfigClass; - -struct TrackerConfig { - GSettings parent; -}; - -struct TrackerConfigClass { - GSettingsClass parent_class; -}; - -GType tracker_config_get_type (void) G_GNUC_CONST; - -TrackerConfig *tracker_config_new (void); - -gint tracker_config_get_verbosity (TrackerConfig *config); -void tracker_config_set_verbosity (TrackerConfig *config, - gint value); - -G_END_DECLS - -#endif /* __TRACKER_WRITEBACK_CONFIG_H__ */ diff --git a/src/tracker-writeback/tracker-main.c b/src/tracker-writeback/tracker-main.c deleted file mode 100644 index 2fb2be647..000000000 --- a/src/tracker-writeback/tracker-main.c +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <stdlib.h> -#include <locale.h> - -#include <glib/gi18n.h> - -#include <libtracker-common/tracker-log.h> - -#include "tracker-writeback.h" -#include "tracker-config.h" - -#define ABOUT \ - "Tracker " PACKAGE_VERSION "\n" - -#define LICENSE \ - "This program is free software and comes without any warranty.\n" \ - "It is licensed under version 2 or later of the General Public " \ - "License which can be viewed at:\n" \ - "\n" \ - " http://www.gnu.org/licenses/gpl.txt\n" - -#define QUIT_TIMEOUT 30 /* 1/2 minutes worth of seconds */ - -static gboolean version; -static gint verbosity = -1; -static gboolean disable_shutdown; - -static GOptionEntry entries[] = { - { "version", 'V', 0, - G_OPTION_ARG_NONE, &version, - N_("Displays version information"), - NULL }, - { "verbosity", 'v', 0, - G_OPTION_ARG_INT, &verbosity, - N_("Logging, 0 = errors only, " - "1 = minimal, 2 = detailed and 3 = debug (default=0)"), - NULL }, - /* Debug run is used to avoid that the mainloop exits, so that - * as a developer you can be relax when running the tool in gdb */ - { "disable-shutdown", 'd', 0, - G_OPTION_ARG_NONE, &disable_shutdown, - N_("Disable shutting down after 30 seconds of inactivity"), - NULL }, - { NULL } -}; - - -static void -sanity_check_option_values (TrackerConfig *config) -{ - g_message ("General options:"); - g_message (" Verbosity ............................ %d", - tracker_config_get_verbosity (config)); -} - -int -main (int argc, - char *argv[]) -{ - TrackerConfig *config; - TrackerController *controller; - GOptionContext *context; - GMainLoop *loop; - GError *error = NULL; - gchar *log_filename; - guint shutdown_timeout; - - /* Set up locale */ - setlocale (LC_ALL, ""); - - bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - textdomain (GETTEXT_PACKAGE); - - /* Translators: this message will appear immediately after the - * usage string - Usage: COMMAND <THIS_MESSAGE> - */ - context = g_option_context_new (_("— start the tracker writeback service")); - - g_option_context_add_main_entries (context, entries, NULL); - g_option_context_parse (context, &argc, &argv, &error); - g_option_context_free (context); - - if (version) { - g_print ("\n" ABOUT "\n" LICENSE "\n"); - return EXIT_SUCCESS; - } - - /* Initialize logging */ - config = tracker_config_new (); - - if (verbosity > -1) { - tracker_config_set_verbosity (config, verbosity); - } - - tracker_log_init (tracker_config_get_verbosity (config), - &log_filename); - if (log_filename != NULL) { - g_message ("Using log file:'%s'", log_filename); - g_free (log_filename); - } - - sanity_check_option_values (config); - - if (disable_shutdown) { - shutdown_timeout = 0; - } else { - shutdown_timeout = QUIT_TIMEOUT; - } - - controller = tracker_controller_new (shutdown_timeout, &error); - - if (error) { - g_critical ("Error creating controller: %s", error->message); - g_error_free (error); - return EXIT_FAILURE; - } - - g_message ("Main thread is: %p", g_thread_self ()); - - loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (loop); - - - tracker_log_shutdown (); - - g_object_unref (controller); - - g_main_loop_unref (loop); - - g_object_unref (config); - - return EXIT_SUCCESS; -} diff --git a/src/tracker-writeback/tracker-writeback-file.c b/src/tracker-writeback/tracker-writeback-file.c deleted file mode 100644 index 60fc250e5..000000000 --- a/src/tracker-writeback/tracker-writeback-file.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <stdio.h> -#include <fcntl.h> /* O_WRONLY */ - -#include <gio/gunixoutputstream.h> - -#include <libtracker-common/tracker-file-utils.h> -#include <libtracker-common/tracker-common.h> - -#include "tracker-writeback-file.h" - -static gboolean tracker_writeback_file_update_metadata (TrackerWriteback *writeback, - GPtrArray *values, - TrackerSparqlConnection *connection, - GCancellable *cancellable, - GError **error); - -G_DEFINE_ABSTRACT_TYPE (TrackerWritebackFile, tracker_writeback_file, TRACKER_TYPE_WRITEBACK) - -static void -tracker_writeback_file_class_init (TrackerWritebackFileClass *klass) -{ - TrackerWritebackClass *writeback_class = TRACKER_WRITEBACK_CLASS (klass); - - writeback_class->update_metadata = tracker_writeback_file_update_metadata; -} - -static void -tracker_writeback_file_init (TrackerWritebackFile *writeback_file) -{ -} - -static GFile * -create_temporary_file (GFile *file, - GFileInfo *file_info, - GError **in_error) -{ - GInputStream *input_stream; - GOutputStream *output_stream; - GFile *tmp_file, *parent; - gchar *dir, *name, *tmp_path; - guint32 mode; - gint fd; - GError *error = NULL; - - if (!g_file_is_native (file)) { - gchar *uri; - - uri = g_file_get_uri (file); - g_warning ("Could not create temporary file, file is not native: '%s'", uri); - g_free (uri); - - g_set_error (in_error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "Could not create temporary file, file is not native: '%s'", - uri); - - return NULL; - } - - /* Create input stream */ - input_stream = G_INPUT_STREAM (g_file_read (file, NULL, &error)); - - if (error) { - g_critical ("Could not create temporary file, %s", error->message); - g_propagate_error (in_error, error); - return NULL; - } - - /* Create output stream in a tmp file */ - parent = g_file_get_parent (file); - dir = g_file_get_path (parent); - g_object_unref (parent); - - name = g_file_get_basename (file); - tmp_path = g_strdup_printf ("%s" G_DIR_SEPARATOR_S ".tracker-XXXXXX.%s", - dir, name); - g_free (dir); - g_free (name); - - mode = g_file_info_get_attribute_uint32 (file_info, - G_FILE_ATTRIBUTE_UNIX_MODE); - fd = g_mkstemp_full (tmp_path, O_WRONLY, mode); - - output_stream = g_unix_output_stream_new (fd, TRUE); - - /* Splice the original file into the tmp file */ - g_output_stream_splice (output_stream, - input_stream, - G_OUTPUT_STREAM_SPLICE_CLOSE_SOURCE | - G_OUTPUT_STREAM_SPLICE_CLOSE_TARGET, - NULL, &error); - - g_object_unref (output_stream); - g_object_unref (input_stream); - - tmp_file = g_file_new_for_path (tmp_path); - g_free (tmp_path); - - if (error) { - g_critical ("Could not copy temporary file, %s", error->message); - g_propagate_error (in_error, error); - g_file_delete (tmp_file, NULL, NULL); - g_object_unref (tmp_file); - - return NULL; - } - - return tmp_file; -} - -static gboolean -tracker_writeback_file_update_metadata (TrackerWriteback *writeback, - GPtrArray *values, - TrackerSparqlConnection *connection, - GCancellable *cancellable, - GError **error) -{ - TrackerWritebackFileClass *writeback_file_class; - gboolean retval; - GFile *file, *tmp_file; - GFileInfo *file_info; - GStrv row; - const gchar * const *content_types; - const gchar *mime_type; - guint n; - GError *n_error = NULL; - - writeback_file_class = TRACKER_WRITEBACK_FILE_GET_CLASS (writeback); - - if (!writeback_file_class->update_file_metadata) { - g_critical ("%s doesn't implement update_file_metadata()", - G_OBJECT_TYPE_NAME (writeback)); - - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "%s doesn't implement update_file_metadata()", - G_OBJECT_TYPE_NAME (writeback)); - - return FALSE; - } - - if (!writeback_file_class->content_types) { - g_critical ("%s doesn't implement content_types()", - G_OBJECT_TYPE_NAME (writeback)); - - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "%s doesn't implement content_types()", - G_OBJECT_TYPE_NAME (writeback)); - - return FALSE; - } - - /* Get the file from the row */ - row = g_ptr_array_index (values, 0); - file = g_file_new_for_uri (row[0]); - - file_info = g_file_query_info (file, - G_FILE_ATTRIBUTE_UNIX_MODE "," - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," - G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, NULL); - - if (!file_info) { - g_object_unref (file); - - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "%s doesn't exist", - row[0]); - - return FALSE; - } - - if (!g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) { - g_object_unref (file_info); - g_object_unref (file); - - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "%s not writable", - row[0]); - - return FALSE; - } - - mime_type = g_file_info_get_content_type (file_info); - content_types = (writeback_file_class->content_types) (TRACKER_WRITEBACK_FILE (writeback)); - - retval = FALSE; - - for (n = 0; content_types[n] != NULL; n++) { - if (g_strcmp0 (mime_type, content_types[n]) == 0) { - retval = TRUE; - break; - } - } - - if (!retval) { - /* module does not support writeback for this file */ - g_object_unref (file_info); - g_object_unref (file); - - g_set_error_literal (error, - TRACKER_DBUS_ERROR, - TRACKER_DBUS_ERROR_UNSUPPORTED, - "Module does not support writeback for this file"); - - return FALSE; - } - - /* Copy to a temporary file so we can perform an atomic write on move */ - tmp_file = create_temporary_file (file, file_info, &n_error); - - if (!tmp_file) { - g_object_unref (file); - g_propagate_error (error, n_error); - g_object_unref (file_info); - return FALSE; - } - - retval = (writeback_file_class->update_file_metadata) (TRACKER_WRITEBACK_FILE (writeback), - tmp_file, - values, - connection, - cancellable, - &n_error); - - if (!retval) { - /* Delete the temporary file and preserve original */ - g_file_delete (tmp_file, NULL, NULL); - } else { - /* Move back the modified file to the original location. Correct UNIX - * mode has been set for tmp_file in create_temporary_file() already. - */ - g_file_move (tmp_file, file, - G_FILE_COPY_OVERWRITE, - NULL, NULL, NULL, NULL); - } - - g_object_unref (file_info); - g_object_unref (tmp_file); - g_object_unref (file); - - if (n_error) { - g_propagate_error (error, n_error); - } - - return retval; -} diff --git a/src/tracker-writeback/tracker-writeback-file.h b/src/tracker-writeback/tracker-writeback-file.h deleted file mode 100644 index 61fa8659c..000000000 --- a/src/tracker-writeback/tracker-writeback-file.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_WRITEBACK_FILE_H__ -#define __TRACKER_WRITEBACK_FILE_H__ - -#include <gio/gio.h> - -#include "tracker-writeback-module.h" - -G_BEGIN_DECLS - -#define TRACKER_TYPE_WRITEBACK_FILE (tracker_writeback_file_get_type()) -#define TRACKER_WRITEBACK_FILE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_WRITEBACK_FILE, TrackerWritebackFile)) -#define TRACKER_WRITEBACK_FILE_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_WRITEBACK_FILE, TrackerWritebackFileClass)) -#define TRACKER_IS_WRITEBACK_FILE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_WRITEBACK_FILE)) -#define TRACKER_IS_WRITEBACK_FILE_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_WRITEBACK_FILE)) -#define TRACKER_WRITEBACK_FILE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_WRITEBACK_FILE, TrackerWritebackFileClass)) - -typedef struct TrackerWritebackFile TrackerWritebackFile; -typedef struct TrackerWritebackFileClass TrackerWritebackFileClass; - -struct TrackerWritebackFile { - TrackerWriteback parent_instance; -}; - -struct TrackerWritebackFileClass { - TrackerWritebackClass parent_class; - - gboolean (* update_file_metadata) (TrackerWritebackFile *writeback_file, - GFile *file, - GPtrArray *values, - TrackerSparqlConnection *connection, - GCancellable *cancellable, - GError **error); - const gchar * const * (* content_types) (TrackerWritebackFile *writeback_file); - -}; - -GType tracker_writeback_file_get_type (void) G_GNUC_CONST; - -G_END_DECLS - -#endif /* __TRACKER_WRITEBACK_FILE_H__ */ diff --git a/src/tracker-writeback/tracker-writeback-module.c b/src/tracker-writeback/tracker-writeback-module.c deleted file mode 100644 index 3a1933ae3..000000000 --- a/src/tracker-writeback/tracker-writeback-module.c +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <gmodule.h> - -#include "tracker-writeback-module.h" - -static gboolean writeback_module_load (GTypeModule *module); -static void writeback_module_unload (GTypeModule *module); - -G_DEFINE_TYPE (TrackerWritebackModule, tracker_writeback_module, G_TYPE_TYPE_MODULE) - -G_DEFINE_ABSTRACT_TYPE (TrackerWriteback, tracker_writeback, G_TYPE_OBJECT) - - -static void -tracker_writeback_module_class_init (TrackerWritebackModuleClass *klass) -{ - GTypeModuleClass *module_class = G_TYPE_MODULE_CLASS (klass); - - module_class->load = writeback_module_load; - module_class->unload = writeback_module_unload; -} - -static void -tracker_writeback_module_init (TrackerWritebackModule *module) -{ -} - -static gboolean -writeback_module_load (GTypeModule *module) -{ - TrackerWritebackModule *writeback_module; - gchar *path; - - writeback_module = TRACKER_WRITEBACK_MODULE (module); - - path = g_build_filename (WRITEBACK_MODULES_DIR, writeback_module->name, NULL); - writeback_module->module = g_module_open (path, G_MODULE_BIND_LOCAL); - g_free (path); - - if (G_UNLIKELY (!writeback_module->module)) { - g_warning ("Could not load writeback module '%s': %s\n", - writeback_module->name, - g_module_error ()); - - return FALSE; - } - - g_module_make_resident (writeback_module->module); - - if (!g_module_symbol (writeback_module->module, "writeback_module_create", - (gpointer *) &writeback_module->create) || - !g_module_symbol (writeback_module->module, "writeback_module_get_rdf_types", - (gpointer *) &writeback_module->get_rdf_types)) { - g_warning ("Could not load module symbols for '%s': %s", - writeback_module->name, - g_module_error ()); - - return FALSE; - } - - g_message ("Loaded module:'%s'", writeback_module->name); - - return TRUE; -} - -static void -writeback_module_unload (GTypeModule *module) -{ - TrackerWritebackModule *writeback_module; - - writeback_module = TRACKER_WRITEBACK_MODULE (module); - - g_module_close (writeback_module->module); - writeback_module->module = NULL; - - g_message ("Unloaded module:'%s'", writeback_module->name); -} - -TrackerWritebackModule * -tracker_writeback_module_get (const gchar *name) -{ - static GHashTable *modules = NULL; - TrackerWritebackModule *module; - - g_return_val_if_fail (name != NULL, NULL); - - if (G_UNLIKELY (!modules)) { - modules = g_hash_table_new (g_str_hash, g_str_equal); - } - - module = g_hash_table_lookup (modules, name); - - if (G_UNLIKELY (!module)) { - module = g_object_new (TRACKER_TYPE_WRITEBACK_MODULE, NULL); - g_type_module_set_name (G_TYPE_MODULE (module), name); - module->name = g_strdup (name); - - g_hash_table_insert (modules, module->name, module); - } - - if (!g_type_module_use (G_TYPE_MODULE (module))) { - return NULL; - } - - return module; -} - -GList * -tracker_writeback_modules_list (void) -{ - GError *error = NULL; - const gchar *name; - GList *list = NULL; - GDir *dir; - - dir = g_dir_open (WRITEBACK_MODULES_DIR, 0, &error); - - if (error) { - g_critical ("Could not get writeback modules list: %s", error->message); - g_error_free (error); - return NULL; - } - - while ((name = g_dir_read_name (dir)) != NULL) { - if (!g_str_has_suffix (name, G_MODULE_SUFFIX)) { - continue; - } - - list = g_list_prepend (list, g_strdup (name)); - } - - g_dir_close (dir); - - return g_list_reverse (list); -} - -TrackerWriteback * -tracker_writeback_module_create (TrackerWritebackModule *module) -{ - return (module->create) (G_TYPE_MODULE (module)); -} - -const gchar * const * -tracker_writeback_module_get_rdf_types (TrackerWritebackModule *module) -{ - return (module->get_rdf_types) (); -} - -static void -tracker_writeback_class_init (TrackerWritebackClass *klass) -{ -} - -static void -tracker_writeback_init (TrackerWriteback *writeback) -{ -} - -gboolean -tracker_writeback_update_metadata (TrackerWriteback *writeback, - GPtrArray *values, - TrackerSparqlConnection *connection, - GCancellable *cancellable, - GError **error) -{ - g_return_val_if_fail (TRACKER_IS_WRITEBACK (writeback), FALSE); - g_return_val_if_fail (values != NULL, FALSE); - - if (TRACKER_WRITEBACK_GET_CLASS (writeback)->update_metadata) { - return TRACKER_WRITEBACK_GET_CLASS (writeback)->update_metadata (writeback, - values, - connection, - cancellable, - error); - } - - return FALSE; -} diff --git a/src/tracker-writeback/tracker-writeback-module.h b/src/tracker-writeback/tracker-writeback-module.h deleted file mode 100644 index 94e079e68..000000000 --- a/src/tracker-writeback/tracker-writeback-module.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_WRITEBACK_MODULE_H__ -#define __TRACKER_WRITEBACK_MODULE_H__ - -#include <glib.h> -#include <glib-object.h> - -#include <libtracker-miner/tracker-miner.h> -#include <libtracker-sparql/tracker-sparql.h> - -G_BEGIN_DECLS - -#define TRACKER_TYPE_WRITEBACK_MODULE (tracker_writeback_module_get_type ()) -#define TRACKER_WRITEBACK_MODULE(module) (G_TYPE_CHECK_INSTANCE_CAST ((module), TRACKER_TYPE_WRITEBACK_MODULE, TrackerWritebackModule)) - -#define TRACKER_TYPE_WRITEBACK (tracker_writeback_get_type()) -#define TRACKER_WRITEBACK(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_WRITEBACK, TrackerWriteback)) -#define TRACKER_WRITEBACK_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_WRITEBACK, TrackerWritebackClass)) -#define TRACKER_IS_WRITEBACK(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_WRITEBACK)) -#define TRACKER_IS_WRITEBACK_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_WRITEBACK)) -#define TRACKER_WRITEBACK_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_WRITEBACK, TrackerWritebackClass)) - -typedef struct TrackerWriteback TrackerWriteback; -typedef struct TrackerWritebackClass TrackerWritebackClass; -typedef struct TrackerWritebackModule TrackerWritebackModule; -typedef struct TrackerWritebackModuleClass TrackerWritebackModuleClass; - -struct TrackerWriteback { - GObject parent_instance; -}; - -struct TrackerWritebackClass { - GObjectClass parent_class; - - gboolean (* update_metadata) (TrackerWriteback *writeback, - GPtrArray *values, - TrackerSparqlConnection *connection, - GCancellable *cancellable, - GError **error); -}; - -struct TrackerWritebackModule { - GTypeModule parent_instance; - - GModule *module; - gchar *name; - - TrackerWriteback * (* create) (GTypeModule *module); - const gchar * const * (* get_rdf_types) (void); -}; - -struct TrackerWritebackModuleClass { - GTypeModuleClass parent_class; -}; - - -GType tracker_writeback_get_type (void) G_GNUC_CONST; -gboolean tracker_writeback_update_metadata (TrackerWriteback *writeback, - GPtrArray *values, - TrackerSparqlConnection *connection, - GCancellable *cancellable, - GError **error); - -/* Entry functions to be defined by modules */ -TrackerWriteback * writeback_module_create (GTypeModule *module); -const gchar * const * writeback_module_get_rdf_types (void); - -GType tracker_writeback_module_get_type (void) G_GNUC_CONST; - -TrackerWritebackModule *tracker_writeback_module_get (const gchar *name); -TrackerWriteback * tracker_writeback_module_create (TrackerWritebackModule *module); -const gchar * const * tracker_writeback_module_get_rdf_types (TrackerWritebackModule *module); -GList * tracker_writeback_modules_list (void); - -G_END_DECLS - -#endif /* __TRACKER_WRITEBACK_MODULE_H__ */ diff --git a/src/tracker-writeback/tracker-writeback-playlist.c b/src/tracker-writeback/tracker-writeback-playlist.c deleted file mode 100644 index 2fb8610b0..000000000 --- a/src/tracker-writeback/tracker-writeback-playlist.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * Authors: Philip Van Hoof <philip@codeminded.be> - */ - -#include "config.h" - -#include <string.h> - -#include <totem-pl-parser.h> - -#include <libtracker-sparql/tracker-ontologies.h> - -#include "tracker-writeback-file.h" - -#define TRACKER_TYPE_WRITEBACK_PLAYLIST (tracker_writeback_playlist_get_type ()) - -typedef struct TrackerWritebackPlaylist TrackerWritebackPlaylist; -typedef struct TrackerWritebackPlaylistClass TrackerWritebackPlaylistClass; -typedef struct PlaylistMap PlaylistMap; - -struct TrackerWritebackPlaylist { - TrackerWritebackFile parent_instance; -}; - -struct TrackerWritebackPlaylistClass { - TrackerWritebackFileClass parent_class; -}; - -struct PlaylistMap { - const gchar *mime_type; - TotemPlParserType playlist_type; -}; - -static GType tracker_writeback_playlist_get_type (void) G_GNUC_CONST; -static gboolean writeback_playlist_update_file_metadata (TrackerWritebackFile *wbf, - GFile *file, - GPtrArray *values, - TrackerSparqlConnection *connection, - GCancellable *cancellable, - GError **error); -static const gchar * const *writeback_playlist_content_types (TrackerWritebackFile *wbf); - -G_DEFINE_DYNAMIC_TYPE (TrackerWritebackPlaylist, tracker_writeback_playlist, TRACKER_TYPE_WRITEBACK_FILE); - -static void -tracker_writeback_playlist_class_init (TrackerWritebackPlaylistClass *klass) -{ - TrackerWritebackFileClass *writeback_file_class = TRACKER_WRITEBACK_FILE_CLASS (klass); - - writeback_file_class->update_file_metadata = writeback_playlist_update_file_metadata; - writeback_file_class->content_types = writeback_playlist_content_types; -} - -static void -tracker_writeback_playlist_class_finalize (TrackerWritebackPlaylistClass *klass) -{ -} - -static void -tracker_writeback_playlist_init (TrackerWritebackPlaylist *wbm) -{ -} - -static const gchar * const * -writeback_playlist_content_types (TrackerWritebackFile *wbf) -{ - static const gchar *content_types[] = { - "audio/x-mpegurl", - "audio/mpegurl", - "audio/x-scpls", - "application/xspf+xml", - "audio/x-iriver-pla", -#if 0 - "audio/x-pn-realaudio", - "application/ram", - "application/vnd.ms-wpl", - "application/smil", - "audio/x-ms-asx", -#endif - NULL - }; - - return content_types; -} - -static gboolean -get_playlist_type (GFile *file, - TotemPlParserType *type) -{ - GFileInfo *file_info; - const gchar *mime_type; - gint i; - PlaylistMap playlist_map[] = { - { "audio/x-mpegurl", TOTEM_PL_PARSER_M3U }, - { "audio/mpegurl", TOTEM_PL_PARSER_M3U }, - { "audio/x-scpls", TOTEM_PL_PARSER_PLS }, - { "application/xspf+xml", TOTEM_PL_PARSER_XSPF }, - { "audio/x-iriver-pla", TOTEM_PL_PARSER_IRIVER_PLA } - }; - - file_info = g_file_query_info (file, - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - NULL, NULL); - - if (!file_info) { - return FALSE; - } - - mime_type = g_file_info_get_content_type (file_info); - g_object_unref (file_info); - - if (!mime_type) { - return FALSE; - } - - for (i = 0; i < G_N_ELEMENTS (playlist_map); i++) { - if (strcmp (mime_type, playlist_map[i].mime_type) == 0) { - *type = playlist_map[i].playlist_type; - return TRUE; - } - } - - return FALSE; -} - -static void -rewrite_playlist (TrackerSparqlConnection *connection, - GFile *file, - const gchar *subject) -{ - TotemPlParserType type; - gchar *path; - TrackerSparqlCursor *cursor; - GError *error = NULL; - gchar *query; - - if (!get_playlist_type (file, &type)) { - return; - } - - path = g_file_get_path (file); - query = g_strdup_printf ("SELECT ?entry { ?unknown a nfo:MediaFileListEntry ; " - "nie:url '%s' ; " - "nfo:entryUrl ?entry" - "}", subject); - cursor = tracker_sparql_connection_query (connection, query, NULL, &error); - g_free (query); - - if (!error) { - TotemPlParser *parser; - TotemPlPlaylist *playlist; - TotemPlPlaylistIter iter; - guint amount = 0; - - parser = totem_pl_parser_new (); - playlist = totem_pl_playlist_new (); - - while (tracker_sparql_cursor_next (cursor, NULL, NULL)) { - totem_pl_playlist_append (playlist, &iter); - totem_pl_playlist_set (playlist, &iter, - TOTEM_PL_PARSER_FIELD_URI, - tracker_sparql_cursor_get_string (cursor, 0, NULL), - NULL); - amount++; - } - - if (amount > 0) { - totem_pl_parser_save (parser, playlist, file, NULL, type, &error); - } else { - /* TODO: Empty the file in @path */ - } - - if (error) { - g_critical ("Could not save playlist: %s\n", error->message); - g_error_free (error); - } - - g_object_unref (playlist); - g_object_unref (parser); - g_object_unref (cursor); - - } else { - g_clear_error (&error); - } - - g_free (path); -} - -static gboolean -writeback_playlist_update_file_metadata (TrackerWritebackFile *writeback_file, - GFile *file, - GPtrArray *values, - TrackerSparqlConnection *connection, - GCancellable *cancellable, - GError **error) -{ - guint n; - - for (n = 0; n < values->len; n++) { - const GStrv row = g_ptr_array_index (values, n); - if (g_strcmp0 (row[2], TRACKER_PREFIX_NFO "entryCounter") == 0) { - rewrite_playlist (connection, file, row[0]); - break; - } - } - - return TRUE; -} - -TrackerWriteback * -writeback_module_create (GTypeModule *module) -{ - tracker_writeback_playlist_register_type (module); - - return g_object_new (TRACKER_TYPE_WRITEBACK_PLAYLIST, NULL); -} - -const gchar * const * -writeback_module_get_rdf_types (void) -{ - static const gchar *rdftypes[] = { - TRACKER_PREFIX_NFO "MediaList", - TRACKER_PREFIX_NFO "MediaFileListEntry", - NULL - }; - - return rdftypes; -} diff --git a/src/tracker-writeback/tracker-writeback-taglib.c b/src/tracker-writeback/tracker-writeback-taglib.c deleted file mode 100644 index 0c30edda2..000000000 --- a/src/tracker-writeback/tracker-writeback-taglib.c +++ /dev/null @@ -1,289 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" - -#include <stdlib.h> - -#include <taglib/tag_c.h> - -#include <glib-object.h> - -#include <libtracker-sparql/tracker-ontologies.h> - -#include "tracker-writeback-file.h" - -#define TRACKER_TYPE_WRITEBACK_TAGLIB (tracker_writeback_taglib_get_type ()) - -typedef struct TrackerWritebackTaglib TrackerWritebackTaglib; -typedef struct TrackerWritebackTaglibClass TrackerWritebackTaglibClass; - -struct TrackerWritebackTaglib { - TrackerWritebackFile parent_instance; -}; - -struct TrackerWritebackTaglibClass { - TrackerWritebackFileClass parent_class; -}; - -static GType tracker_writeback_taglib_get_type (void) G_GNUC_CONST; -static gboolean writeback_taglib_update_file_metadata (TrackerWritebackFile *wbf, - GFile *file, - GPtrArray *values, - TrackerSparqlConnection *connection, - GCancellable *cancellable, - GError **error); -static const gchar * const *writeback_taglib_content_types (TrackerWritebackFile *wbf); -static gchar* writeback_taglib_get_artist_name (TrackerSparqlConnection *connection, - const gchar *urn); -static gchar* writeback_taglib_get_album_name (TrackerSparqlConnection *connection, - const gchar *urn); - -G_DEFINE_DYNAMIC_TYPE (TrackerWritebackTaglib, tracker_writeback_taglib, TRACKER_TYPE_WRITEBACK_FILE); - -static void -tracker_writeback_taglib_class_init (TrackerWritebackTaglibClass *klass) -{ - TrackerWritebackFileClass *writeback_file_class = TRACKER_WRITEBACK_FILE_CLASS (klass); - - writeback_file_class->update_file_metadata = writeback_taglib_update_file_metadata; - writeback_file_class->content_types = writeback_taglib_content_types; -} - -static void -tracker_writeback_taglib_class_finalize (TrackerWritebackTaglibClass *klass) -{ -} - -static void -tracker_writeback_taglib_init (TrackerWritebackTaglib *wbt) -{ -} - -static const gchar * const * -writeback_taglib_content_types (TrackerWritebackFile *wbf) -{ - static const gchar *content_types [] = { - "audio/x-mpc", - "audio/x-musepack", - "audio/mpc", - "audio/musepack", - "audio/mpeg", - "audio/x-mpeg", - "audio/mp3", - "audio/x-mp3", - "audio/mpeg3", - "audio/x-mpeg3", - "audio/mpg", - "audio/x-mpg", - "audio/x-mpegaudio", - "audio/flac", - "audio/mp4", - "audio/asf", - "application/asx", - "video/x-ms-asf-plugin", - "application/x-mplayer2", - "video/x-ms-asf", - "application/vnd.ms-asf", - "video/x-ms-asf-plugin", - "video/x-ms-wm", - "video/x-ms-wmx", - "audio/aiff", - "audio/x-aiff", - "sound/aiff", - "audio/rmf", - "audio/x-rmf", - "audio/x-pn-aiff", - "audio/x-gsm", - "audio/mid", - "audio/x-midi", - "audio/vnd.qcelp", - "audio/wav", - "audio/x-wav", - "audio/wave", - "audio/x-pn-wav", - "audio/tta", - "audio/x-tta", - "audio/ogg", - "application/ogg", - "audio/x-ogg", - "application/x-ogg", - "audio/x-speex", - NULL - }; - - return content_types; -} - -static gboolean -writeback_taglib_update_file_metadata (TrackerWritebackFile *writeback_file, - GFile *file, - GPtrArray *values, - TrackerSparqlConnection *connection, - GCancellable *cancellable, - GError **error) -{ - gboolean ret; - gchar *path; - TagLib_File *taglib_file = NULL; - TagLib_Tag *tag; - guint n; - - ret = FALSE; - path = g_file_get_path (file); - taglib_file = taglib_file_new (path); - - if (!taglib_file || !taglib_file_is_valid (taglib_file)) { - goto out; - } - - tag = taglib_file_tag (taglib_file); - - for (n = 0; n < values->len; n++) { - const GStrv row = g_ptr_array_index (values, n); - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NIE "title") == 0) { - taglib_tag_set_title (tag, row[3]); - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "performer") == 0) { - gchar *artist_name = writeback_taglib_get_artist_name (connection, row[3]); - - if (artist_name) { - taglib_tag_set_artist (tag, artist_name); - g_free (artist_name); - } - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "musicAlbum") == 0) { - gchar *album_name = writeback_taglib_get_album_name (connection, row[3]); - - if (album_name) { - taglib_tag_set_album (tag, album_name); - g_free (album_name); - } - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_RDFS "comment") == 0) { - taglib_tag_set_comment (tag, row[3]); - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "genre") == 0) { - taglib_tag_set_genre (tag, row[3]); - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "trackNumber") == 0) { - taglib_tag_set_track (tag, atoi (row[3])); - } - } - - taglib_file_save (taglib_file); - - ret = TRUE; - - out: - g_free (path); - if (taglib_file) { - taglib_file_free (taglib_file); - } - - return ret; -} - -static gchar* -writeback_taglib_get_from_query (TrackerSparqlConnection *connection, - const gchar *urn, - const gchar *query, - const gchar *errmsg) -{ - TrackerSparqlCursor *cursor; - GError *error = NULL; - gchar *value = NULL; - - cursor = tracker_sparql_connection_query (connection, - query, - NULL, - &error); - - if (error || !cursor || !tracker_sparql_cursor_next (cursor, NULL, NULL)) { - g_warning ("Couldn't find %s for artist with urn '%s', %s", - errmsg, - urn, - error ? error->message : "no such was found"); - - if (error) { - g_error_free (error); - } - } else { - value = g_strdup (tracker_sparql_cursor_get_string (cursor, 0, NULL)); - } - - g_object_unref (cursor); - - return value; -} - - -static gchar* -writeback_taglib_get_artist_name (TrackerSparqlConnection *connection, - const gchar *urn) -{ - gchar *val, *query; - - query = g_strdup_printf ("SELECT ?artistName WHERE {<%s> nmm:artistName ?artistName}", - urn); - val = writeback_taglib_get_from_query (connection, urn, query, "artist name"); - g_free (query); - - return val; -} - -static gchar* -writeback_taglib_get_album_name (TrackerSparqlConnection *connection, - const gchar *urn) -{ - gchar *val, *query; - - query = g_strdup_printf ("SELECT ?albumName WHERE {<%s> dc:title ?albumName}", - urn); - val = writeback_taglib_get_from_query (connection, urn, query, "album name"); - g_free (query); - - return val; -} - -TrackerWriteback * -writeback_module_create (GTypeModule *module) -{ - tracker_writeback_taglib_register_type (module); - - return g_object_new (TRACKER_TYPE_WRITEBACK_TAGLIB, NULL); -} - -const gchar * const * -writeback_module_get_rdf_types (void) -{ - static const gchar *rdftypes[] = { - TRACKER_PREFIX_NFO "Audio", - NULL - }; - - return rdftypes; -} diff --git a/src/tracker-writeback/tracker-writeback-xmp.c b/src/tracker-writeback/tracker-writeback-xmp.c deleted file mode 100644 index 6da1315ab..000000000 --- a/src/tracker-writeback/tracker-writeback-xmp.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * Authors: Philip Van Hoof <philip@codeminded.be> - */ - -#include "config.h" - -#include <locale.h> -#include <string.h> -#include <math.h> - -#include <exempi/xmp.h> -#include <exempi/xmpconsts.h> - -#include <glib-object.h> -#include <gio/gio.h> - -#include <libtracker-common/tracker-common.h> -#include <libtracker-sparql/tracker-ontologies.h> -#include <libtracker-sparql/tracker-sparql.h> - -#include "tracker-writeback-file.h" - -#define TRACKER_TYPE_WRITEBACK_XMP (tracker_writeback_xmp_get_type ()) - -typedef struct TrackerWritebackXMP TrackerWritebackXMP; -typedef struct TrackerWritebackXMPClass TrackerWritebackXMPClass; - -struct TrackerWritebackXMP { - TrackerWritebackFile parent_instance; -}; - -struct TrackerWritebackXMPClass { - TrackerWritebackFileClass parent_class; -}; - -static GType tracker_writeback_xmp_get_type (void) G_GNUC_CONST; -static gboolean writeback_xmp_update_file_metadata (TrackerWritebackFile *writeback_file, - GFile *file, - GPtrArray *values, - TrackerSparqlConnection *connection, - GCancellable *cancellable, - GError **error); -static const gchar * const *writeback_xmp_content_types (TrackerWritebackFile *writeback_file); - -G_DEFINE_DYNAMIC_TYPE (TrackerWritebackXMP, tracker_writeback_xmp, TRACKER_TYPE_WRITEBACK_FILE); - -static void -tracker_writeback_xmp_class_init (TrackerWritebackXMPClass *klass) -{ - TrackerWritebackFileClass *writeback_file_class = TRACKER_WRITEBACK_FILE_CLASS (klass); - - xmp_init (); - - writeback_file_class->update_file_metadata = writeback_xmp_update_file_metadata; - writeback_file_class->content_types = writeback_xmp_content_types; -} - -static void -tracker_writeback_xmp_class_finalize (TrackerWritebackXMPClass *klass) -{ - xmp_terminate (); -} - -static void -tracker_writeback_xmp_init (TrackerWritebackXMP *wbx) -{ -} - -static const gchar * const * -writeback_xmp_content_types (TrackerWritebackFile *wbf) -{ - static const gchar *content_types[] = { - "image/png", /* .png files */ - "sketch/png", /* .sketch.png files on Maemo*/ - "image/jpeg", /* .jpg & .jpeg files */ - "image/tiff", /* .tiff & .tif files */ - "video/mp4", /* .mp4 files */ - "video/3gpp", /* .3gpp files */ - "image/gif", /* .gif files */ - NULL - }; - - /* "application/pdf" .pdf files - "application/rdf+xml" .xmp files - "application/postscript" .ps files - "application/x-shockwave-flash" .swf files - "video/quicktime" .mov files - "video/mpeg" .mpeg & .mpg files - "audio/mpeg" .mp3, etc files */ - - return content_types; -} - -static gboolean -writeback_xmp_update_file_metadata (TrackerWritebackFile *wbf, - GFile *file, - GPtrArray *values, - TrackerSparqlConnection *connection, - GCancellable *cancellable, - GError **error) -{ - gchar *path; - guint n; - XmpFilePtr xmp_files; - XmpPtr xmp; -#ifdef DEBUG_XMP - XmpStringPtr str; -#endif - GString *keywords = NULL; - const gchar *urn = NULL; - - path = g_file_get_path (file); - - xmp_files = xmp_files_open_new (path, XMP_OPEN_FORUPDATE); - - if (!xmp_files) { - g_set_error (error, - G_IO_ERROR, - G_IO_ERROR_FAILED, - "Can't open '%s' for update with Exempi (Exempi error code = %d)", - path, - xmp_get_error ()); - g_free (path); - return FALSE; - } - - xmp = xmp_files_get_new_xmp (xmp_files); - - if (!xmp) { - xmp = xmp_new_empty (); - } - -#ifdef DEBUG_XMP - str = xmp_string_new (); - g_print ("\nBEFORE: ---- \n"); - xmp_serialize_and_format (xmp, str, 0, 0, "\n", "\t", 1); - g_print ("%s\n", xmp_string_cstr (str)); - xmp_string_free (str); -#endif - - for (n = 0; n < values->len; n++) { - const GStrv row = g_ptr_array_index (values, n); - - urn = row[1]; /* The urn is at 1 */ - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NIE "title") == 0) { - xmp_delete_property (xmp, NS_EXIF, "Title"); - xmp_set_property (xmp, NS_EXIF, "Title", row[3], 0); - xmp_delete_property (xmp, NS_DC, "title"); - xmp_set_property (xmp, NS_DC, "title", row[3], 0); - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NCO "creator") == 0) { - TrackerSparqlCursor *cursor; - GError *error = NULL; - gchar *query; - - query = g_strdup_printf ("SELECT ?fullname { " - " <%s> nco:fullname ?fullname " - "}", row[3]); - cursor = tracker_sparql_connection_query (connection, query, NULL, &error); - g_free (query); - if (!error) { - while (tracker_sparql_cursor_next (cursor, NULL, NULL)) { - xmp_delete_property (xmp, NS_DC, "creator"); - xmp_set_property (xmp, NS_DC, "creator", - tracker_sparql_cursor_get_string (cursor, 0, NULL), - 0); - } - } - g_object_unref (cursor); - g_clear_error (&error); - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NCO "contributor") == 0) { - TrackerSparqlCursor *cursor; - GError *error = NULL; - gchar *query; - - query = g_strdup_printf ("SELECT ?fullname { " - " <%s> nco:fullname ?fullname " - "}", row[3]); - - cursor = tracker_sparql_connection_query (connection, query, NULL, &error); - g_free (query); - if (!error) { - while (tracker_sparql_cursor_next (cursor, NULL, NULL)) { - xmp_delete_property (xmp, NS_DC, "contributor"); - xmp_set_property (xmp, NS_DC, "contributor", tracker_sparql_cursor_get_string (cursor, 0, NULL), 0); - } - } - g_object_unref (cursor); - g_clear_error (&error); - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NIE "description") == 0) { - xmp_delete_property (xmp, NS_DC, "description"); - xmp_set_property (xmp, NS_DC, "description", row[3], 0); - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NIE "copyright") == 0) { - xmp_delete_property (xmp, NS_EXIF, "Copyright"); - xmp_set_property (xmp, NS_EXIF, "Copyright", row[3], 0); - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NIE "comment") == 0) { - xmp_delete_property (xmp, NS_EXIF, "UserComment"); - xmp_set_property (xmp, NS_EXIF, "UserComment", row[3], 0); - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NIE "keyword") == 0) { - if (!keywords) { - keywords = g_string_new (row[3]); - } else { - g_string_append_printf (keywords, ", %s", row[3]); - } - } - - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NAO "hasTag") == 0) { - TrackerSparqlCursor *cursor; - GError *error = NULL; - gchar *query; - - query = g_strdup_printf ("SELECT ?label { " - " <%s> nao:prefLabel ?label " - "}", row[3]); - - cursor = tracker_sparql_connection_query (connection, query, NULL, &error); - g_free (query); - if (!error) { - while (tracker_sparql_cursor_next (cursor, NULL, NULL)) { - if (!keywords) { - keywords = g_string_new (tracker_sparql_cursor_get_string (cursor, 0, NULL)); - } else { - g_string_append_printf (keywords, ", %s", tracker_sparql_cursor_get_string (cursor, 0, NULL)); - } - } - } - g_object_unref (cursor); - g_clear_error (&error); - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NIE "contentCreated") == 0) { - xmp_delete_property (xmp, NS_EXIF, "Date"); - xmp_set_property (xmp, NS_EXIF, "Date", row[3], 0); - xmp_delete_property (xmp, NS_DC, "date"); - xmp_set_property (xmp, NS_DC, "date", row[3], 0); - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NFO "orientation") == 0) { - - xmp_delete_property (xmp, NS_EXIF, "Orientation"); - - if (g_strcmp0 (row[3], TRACKER_PREFIX_NFO "orientation-top") == 0) { - xmp_set_property (xmp, NS_EXIF, "Orientation", "top - left", 0); - } else if (g_strcmp0 (row[3], TRACKER_PREFIX_NFO "orientation-top-mirror") == 0) { - xmp_set_property (xmp, NS_EXIF, "Orientation", "top - right", 0); - } else if (g_strcmp0 (row[3], TRACKER_PREFIX_NFO "orientation-bottom") == 0) { - xmp_set_property (xmp, NS_EXIF, "Orientation", "bottom - left", 0); - } else if (g_strcmp0 (row[3], TRACKER_PREFIX_NFO "orientation-bottom-mirror") == 0) { - xmp_set_property (xmp, NS_EXIF, "Orientation", "bottom - right", 0); - } else if (g_strcmp0 (row[3], TRACKER_PREFIX_NFO "orientation-left-mirror") == 0) { - xmp_set_property (xmp, NS_EXIF, "Orientation", "left - top", 0); - } else if (g_strcmp0 (row[3], TRACKER_PREFIX_NFO "orientation-right") == 0) { - xmp_set_property (xmp, NS_EXIF, "Orientation", "right - top", 0); - } else if (g_strcmp0 (row[3], TRACKER_PREFIX_NFO "orientation-right-mirror") == 0) { - xmp_set_property (xmp, NS_EXIF, "Orientation", "right - bottom", 0); - } else if (g_strcmp0 (row[3], TRACKER_PREFIX_NFO "orientation-left") == 0) { - xmp_set_property (xmp, NS_EXIF, "Orientation", "left - bottom", 0); - } - } - -#ifdef SET_TYPICAL_CAMERA_FIELDS - /* Default we don't do this, we shouldn't overwrite fields that are - * typically set by the camera itself. What do we know (better) than - * the actual camera did, anyway? Even if the user overwrites them in - * the RDF store ... (does he know what he's doing anyway?) */ - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "meteringMode") == 0) { - - xmp_delete_property (xmp, NS_EXIF, "MeteringMode"); - - /* 0 = Unknown - 1 = Average - 2 = CenterWeightedAverage - 3 = Spot - 4 = MultiSpot - 5 = Pattern - 6 = Partial - 255 = other */ - - if (g_strcmp0 (row[3], TRACKER_PREFIX_NMM "metering-mode-center-weighted-average") == 0) { - xmp_set_property (xmp, NS_EXIF, "MeteringMode", "0", 0); - } else if (g_strcmp0 (row[3], TRACKER_PREFIX_NMM "metering-mode-average") == 0) { - xmp_set_property (xmp, NS_EXIF, "MeteringMode", "1", 0); - } else if (g_strcmp0 (row[3], TRACKER_PREFIX_NMM "metering-mode-spot") == 0) { - xmp_set_property (xmp, NS_EXIF, "MeteringMode", "3", 0); - } else if (g_strcmp0 (row[3], TRACKER_PREFIX_NMM "metering-mode-multispot") == 0) { - xmp_set_property (xmp, NS_EXIF, "MeteringMode", "4", 0); - } else if (g_strcmp0 (row[3], TRACKER_PREFIX_NMM "metering-mode-pattern") == 0) { - xmp_set_property (xmp, NS_EXIF, "MeteringMode", "5", 0); - } else if (g_strcmp0 (row[3], TRACKER_PREFIX_NMM "metering-mode-partial") == 0) { - xmp_set_property (xmp, NS_EXIF, "MeteringMode", "6", 0); - } else { - xmp_set_property (xmp, NS_EXIF, "MeteringMode", "255", 0); - } - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "whiteBalance") == 0) { - - xmp_delete_property (xmp, NS_EXIF, "WhiteBalance"); - - if (g_strcmp0 (row[3], TRACKER_PREFIX_NMM "white-balance-auto") == 0) { - /* 0 = Auto white balance - * 1 = Manual white balance */ - xmp_set_property (xmp, NS_EXIF, "WhiteBalance", "0", 0); - } else { - xmp_set_property (xmp, NS_EXIF, "WhiteBalance", "1", 0); - } - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "flash") == 0) { - - xmp_delete_property (xmp, NS_EXIF, "Flash"); - - if (g_strcmp0 (row[3], TRACKER_PREFIX_NMM "flash-on") == 0) { - /* 0 = Flash did not fire - * 1 = Flash fired */ - xmp_set_property (xmp, NS_EXIF, "Flash", "1", 0); - } else { - xmp_set_property (xmp, NS_EXIF, "Flash", "0", 0); - } - } - - - /* TODO: Don't write row[3] as-is here, read xmp_specification.pdf, - page 84 (bottom). */ - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "focalLength") == 0) { - xmp_delete_property (xmp, NS_EXIF, "FocalLength"); - xmp_set_property (xmp, NS_EXIF, "FocalLength", row[3], 0); - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "exposureTime") == 0) { - xmp_delete_property (xmp, NS_EXIF, "ExposureTime"); - xmp_set_property (xmp, NS_EXIF, "ExposureTime", row[3], 0); - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "isoSpeed") == 0) { - xmp_delete_property (xmp, NS_EXIF, "ISOSpeedRatings"); - xmp_set_property (xmp, NS_EXIF, "ISOSpeedRatings", row[3], 0); - } - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "fnumber") == 0) { - xmp_delete_property (xmp, NS_EXIF, "FNumber"); - xmp_set_property (xmp, NS_EXIF, "FNumber", row[3], 0); - } - - - /* Totally deprecated: this uses nfo:Equipment nowadays */ - if (g_strcmp0 (row[2], TRACKER_PREFIX_NMM "camera") == 0) { - gchar *work_on = g_strdup (row[3]); - gchar *ptr = strchr (work_on, ' '); - - if (ptr) { - - *ptr = '\0'; - ptr++; - - xmp_delete_property (xmp, NS_EXIF, "Make"); - xmp_set_property (xmp, NS_EXIF, "Make", work_on, 0); - xmp_delete_property (xmp, NS_EXIF, "Model"); - xmp_set_property (xmp, NS_EXIF, "Model", ptr, 0); - } else { - xmp_delete_property (xmp, NS_EXIF, "Make"); - xmp_delete_property (xmp, NS_EXIF, "Model"); - xmp_set_property (xmp, NS_EXIF, "Model", work_on, 0); - } - - g_free (work_on); - } -#endif /* SET_TYPICAL_CAMERA_FIELDS */ - - if (g_strcmp0 (row[2], TRACKER_PREFIX_NFO "heading") == 0) { - xmp_delete_property (xmp, NS_EXIF, "GPSImgDirection"); - xmp_set_property (xmp, NS_EXIF, "GPSImgDirection", row[3], 0); - } - } - - if (urn != NULL) { - TrackerSparqlCursor *cursor; - GError *error = NULL; - gchar *query; - - query = g_strdup_printf ("SELECT " - "nco:locality (?addr) " - "nco:region (?addr) " - "nco:streetAddress (?addr) " - "nco:country (?addr) " - "slo:altitude (?loc) " - "slo:longitude (?loc) " - "slo:latitude (?loc) " - "WHERE { <%s> slo:location ?loc . " - "?loc slo:postalAddress ?addr . }", - urn); - - cursor = tracker_sparql_connection_query (connection, query, NULL, &error); - g_free (query); - if (!error) { - if (tracker_sparql_cursor_next (cursor, NULL, NULL)) { - const gchar *city = NULL, *subl = NULL, *country = NULL, - *state = NULL, *altitude = NULL, *longitude = NULL, - *latitude = NULL; - - if (tracker_sparql_cursor_get_value_type (cursor, 0) != TRACKER_SPARQL_VALUE_TYPE_UNBOUND) { - city = tracker_sparql_cursor_get_string (cursor, 0, NULL); - } - - if (tracker_sparql_cursor_get_value_type (cursor, 1) != TRACKER_SPARQL_VALUE_TYPE_UNBOUND) { - state = tracker_sparql_cursor_get_string (cursor, 1, NULL); - } - - if (tracker_sparql_cursor_get_value_type (cursor, 2) != TRACKER_SPARQL_VALUE_TYPE_UNBOUND) { - subl = tracker_sparql_cursor_get_string (cursor, 2, NULL); - } - - if (tracker_sparql_cursor_get_value_type (cursor, 3) != TRACKER_SPARQL_VALUE_TYPE_UNBOUND) { - country = tracker_sparql_cursor_get_string (cursor, 3, NULL); - } - - if (tracker_sparql_cursor_get_value_type (cursor, 4) != TRACKER_SPARQL_VALUE_TYPE_UNBOUND) { - altitude = tracker_sparql_cursor_get_string (cursor, 4, NULL); - } - - if (tracker_sparql_cursor_get_value_type (cursor, 5) != TRACKER_SPARQL_VALUE_TYPE_UNBOUND) { - longitude = tracker_sparql_cursor_get_string (cursor, 5, NULL); - } - - if (tracker_sparql_cursor_get_value_type (cursor, 6) != TRACKER_SPARQL_VALUE_TYPE_UNBOUND) { - latitude = tracker_sparql_cursor_get_string (cursor, 6, NULL); - } - - /* TODO: A lot of these location fields are pretty vague and ambigious. - * We should go through them one by one and ensure that all of them are - * used sanely */ - - xmp_delete_property (xmp, NS_IPTC4XMP, "City"); - xmp_delete_property (xmp, NS_PHOTOSHOP, "City"); - if (city != NULL) { - xmp_set_property (xmp, NS_IPTC4XMP, "City", city, 0); - xmp_set_property (xmp, NS_PHOTOSHOP, "City", city, 0); - } - - xmp_delete_property (xmp, NS_IPTC4XMP, "State"); - xmp_delete_property (xmp, NS_IPTC4XMP, "Province"); - xmp_delete_property (xmp, NS_PHOTOSHOP, "State"); - if (state != NULL) { - xmp_set_property (xmp, NS_IPTC4XMP, "State", state, 0); - xmp_set_property (xmp, NS_IPTC4XMP, "Province", state, 0); - xmp_set_property (xmp, NS_PHOTOSHOP, "State", state, 0); - } - - xmp_delete_property (xmp, NS_IPTC4XMP, "SubLocation"); - xmp_delete_property (xmp, NS_PHOTOSHOP, "Location"); - if (subl != NULL) { - xmp_set_property (xmp, NS_IPTC4XMP, "SubLocation", subl, 0); - xmp_set_property (xmp, NS_PHOTOSHOP, "Location", subl, 0); - } - - xmp_delete_property (xmp, NS_PHOTOSHOP, "Country"); - xmp_delete_property (xmp, NS_IPTC4XMP, "Country"); - xmp_delete_property (xmp, NS_IPTC4XMP, "PrimaryLocationName"); - xmp_delete_property (xmp, NS_IPTC4XMP, "CountryName"); - if (country != NULL) { - xmp_set_property (xmp, NS_PHOTOSHOP, "Country", country, 0); - xmp_set_property (xmp, NS_IPTC4XMP, "Country", country, 0); - xmp_set_property (xmp, NS_IPTC4XMP, "PrimaryLocationName", country, 0); - xmp_set_property (xmp, NS_IPTC4XMP, "CountryName", country, 0); - } - - xmp_delete_property (xmp, NS_EXIF, "GPSAltitude"); - if (altitude != NULL) { - xmp_set_property (xmp, NS_EXIF, "GPSAltitude", altitude, 0); - } - - xmp_delete_property (xmp, NS_EXIF, "GPSLongitude"); - if (longitude != NULL) { - double coord = atof (longitude); - double degrees, minutes; - gchar *val; - - minutes = modf (coord, °rees); - - val = g_strdup_printf ("%3d,%f%c", - (int) fabs(degrees), - minutes, - coord >= 0 ? 'E' : 'W'); - - xmp_set_property (xmp, NS_EXIF, "GPSLongitude", val, 0); - - g_free (val); - } - - xmp_delete_property (xmp, NS_EXIF, "GPSLatitude"); - if (latitude != NULL) { - double coord = atof (latitude); - double degrees, minutes; - gchar *val; - - minutes = modf (coord, °rees); - - val = g_strdup_printf ("%3d,%f%c", - (int) fabs(degrees), - minutes, - coord >= 0 ? 'N' : 'S'); - - xmp_set_property (xmp, NS_EXIF, "GPSLatitude", val, 0); - - g_free (val); - } - } - } - - g_object_unref (cursor); - g_clear_error (&error); - } - - if (keywords) { - xmp_delete_property (xmp, NS_DC, "subject"); - xmp_set_property (xmp, NS_DC, "subject", keywords->str, 0); - g_string_free (keywords, TRUE); - } - -#ifdef DEBUG_XMP - g_print ("\nAFTER: ---- \n"); - str = xmp_string_new (); - xmp_serialize_and_format (xmp, str, 0, 0, "\n", "\t", 1); - g_print ("%s\n", xmp_string_cstr (str)); - xmp_string_free (str); - g_print ("\n --------- \n"); -#endif - - if (xmp_files_can_put_xmp (xmp_files, xmp)) { - xmp_files_put_xmp (xmp_files, xmp); - } - - /* Note: We don't currently use XMP_CLOSE_SAFEUPDATE because it uses - * a hidden temporary file in the same directory, which is then - * renamed to the final name. This triggers two events: - * - DELETE(A) + MOVE(.hidden->A) - * and we really don't want the first DELETE(A) here - */ - xmp_files_close (xmp_files, XMP_CLOSE_NOOPTION); - - xmp_free (xmp); - xmp_files_free (xmp_files); - g_free (path); - - return TRUE; -} - -TrackerWriteback * -writeback_module_create (GTypeModule *module) -{ - tracker_writeback_xmp_register_type (module); - - return g_object_new (TRACKER_TYPE_WRITEBACK_XMP, NULL); -} - -const gchar * const * -writeback_module_get_rdf_types (void) -{ - static const gchar *rdf_types[] = { - TRACKER_PREFIX_NFO "Image", - TRACKER_PREFIX_NFO "Audio", - TRACKER_PREFIX_NFO "Video", - NULL - }; - - return rdf_types; -} diff --git a/src/tracker-writeback/tracker-writeback.c b/src/tracker-writeback/tracker-writeback.c deleted file mode 100644 index 5bc2180b0..000000000 --- a/src/tracker-writeback/tracker-writeback.c +++ /dev/null @@ -1,936 +0,0 @@ -/* - * Copyright (C) 2011, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include "tracker-writeback.h" -#include "tracker-writeback-module.h" - -#include <libtracker-common/tracker-common.h> -#include <libtracker-miner/tracker-miner.h> -#include <libtracker-sparql/tracker-sparql.h> - -#include <gio/gio.h> - -#ifdef STAYALIVE_ENABLE_TRACE -#warning Stayalive traces enabled -#endif /* STAYALIVE_ENABLE_TRACE */ - -#ifdef THREAD_ENABLE_TRACE -#warning Controller thread traces enabled -#endif /* THREAD_ENABLE_TRACE */ - -typedef struct { - TrackerController *controller; - GCancellable *cancellable; - GDBusMethodInvocation *invocation; - TrackerDBusRequest *request; - gchar *subject; - GPtrArray *results; - TrackerSparqlConnection *connection; - GList *writeback_handlers; - guint cancel_id; - GError *error; -} WritebackData; - -typedef struct { - GMainContext *context; - GMainLoop *main_loop; - - GVolumeMonitor *volume_monitor; - - GDBusConnection *d_connection; - GDBusNodeInfo *introspection_data; - guint registration_id; - guint bus_name_id; - - GList *ongoing_tasks; - - guint shutdown_timeout; - GSource *shutdown_source; - - GCond initialization_cond; - GMutex initialization_mutex, mutex; - GError *initialization_error; - - guint initialized : 1; - - GHashTable *modules; - TrackerSparqlConnection *connection; - WritebackData *current; -} TrackerControllerPrivate; - -#define TRACKER_WRITEBACK_SERVICE "org.freedesktop.Tracker1.Writeback" -#define TRACKER_WRITEBACK_PATH "/org/freedesktop/Tracker1/Writeback" -#define TRACKER_WRITEBACK_INTERFACE "org.freedesktop.Tracker1.Writeback" - -static const gchar *introspection_xml = - "<node>" - " <interface name='org.freedesktop.Tracker1.Writeback'>" - " <method name='GetPid'>" - " <arg type='i' name='value' direction='out' />" - " </method>" - " <method name='PerformWriteback'>" - " <arg type='s' name='subject' direction='in' />" - " <arg type='as' name='rdf_types' direction='in' />" - " <arg type='aas' name='results' direction='in' />" - " </method>" - " <method name='CancelTasks'>" - " <arg type='as' name='subjects' direction='in' />" - " </method>" - " </interface>" - "</node>"; - -enum { - PROP_0, - PROP_SHUTDOWN_TIMEOUT, -}; - -static void tracker_controller_initable_iface_init (GInitableIface *iface); -static gboolean tracker_controller_dbus_start (TrackerController *controller, - GError **error); -static void tracker_controller_dbus_stop (TrackerController *controller); -static gboolean tracker_controller_start (TrackerController *controller, - GError **error); - -G_DEFINE_TYPE_WITH_CODE (TrackerController, tracker_controller, G_TYPE_OBJECT, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - tracker_controller_initable_iface_init)); - -static gboolean -tracker_controller_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - return tracker_controller_start (TRACKER_CONTROLLER (initable), error); -} - -static void -tracker_controller_initable_iface_init (GInitableIface *iface) -{ - iface->init = tracker_controller_initable_init; -} - -static void -tracker_controller_finalize (GObject *object) -{ - TrackerControllerPrivate *priv; - TrackerController *controller; - - controller = TRACKER_CONTROLLER (object); - priv = controller->priv; - - if (priv->shutdown_source) { - g_source_destroy (priv->shutdown_source); - priv->shutdown_source = NULL; - } - - tracker_controller_dbus_stop (controller); - - g_object_unref (priv->volume_monitor); - g_hash_table_unref (priv->modules); - - g_main_loop_unref (priv->main_loop); - g_main_context_unref (priv->context); - - g_cond_clear (&priv->initialization_cond); - g_mutex_clear (&priv->initialization_mutex); - g_mutex_clear (&priv->mutex); - - G_OBJECT_CLASS (tracker_controller_parent_class)->finalize (object); -} - -static void -tracker_controller_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - TrackerControllerPrivate *priv = TRACKER_CONTROLLER (object)->priv; - - switch (param_id) { - case PROP_SHUTDOWN_TIMEOUT: - g_value_set_uint (value, priv->shutdown_timeout); - break; - } -} - -static void -tracker_controller_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - TrackerControllerPrivate *priv = TRACKER_CONTROLLER (object)->priv; - - switch (param_id) { - case PROP_SHUTDOWN_TIMEOUT: - priv->shutdown_timeout = g_value_get_uint (value); - break; - } -} - -static void -tracker_controller_class_init (TrackerControllerClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = tracker_controller_finalize; - object_class->get_property = tracker_controller_get_property; - object_class->set_property = tracker_controller_set_property; - - g_object_class_install_property (object_class, - PROP_SHUTDOWN_TIMEOUT, - g_param_spec_uint ("shutdown-timeout", - "Shutdown timeout", - "Shutdown timeout, 0 to disable", - 0, 1000, 0, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); - - g_type_class_add_private (object_class, sizeof (TrackerControllerPrivate)); -} - -static void -task_cancellable_cancelled_cb (GCancellable *cancellable, - WritebackData *data) -{ - TrackerControllerPrivate *priv; - - priv = data->controller->priv; - - g_mutex_lock (&priv->mutex); - - if (priv->current == data) { - g_message ("Cancelled writeback task for '%s' was currently being " - "processed, _exit()ing immediately", - data->subject); - _exit (0); - } - - g_mutex_unlock (&priv->mutex); -} - - -static WritebackData * -writeback_data_new (TrackerController *controller, - GList *writeback_handlers, - TrackerSparqlConnection *connection, - const gchar *subject, - GPtrArray *results, - GDBusMethodInvocation *invocation, - TrackerDBusRequest *request) -{ - WritebackData *data; - - data = g_slice_new (WritebackData); - data->cancellable = g_cancellable_new (); - data->controller = g_object_ref (controller); - data->subject = g_strdup (subject); - data->results = g_ptr_array_ref (results); - data->invocation = invocation; - data->connection = g_object_ref (connection); - data->writeback_handlers = writeback_handlers; - data->request = request; - data->error = NULL; - - data->cancel_id = g_cancellable_connect (data->cancellable, - G_CALLBACK (task_cancellable_cancelled_cb), - data, NULL); - - return data; -} - -static void -writeback_data_free (WritebackData *data) -{ - /* We rely on data->invocation being freed through - * the g_dbus_method_invocation_return_* methods - */ - g_cancellable_disconnect (data->cancellable, data->cancel_id); - g_free (data->subject); - g_object_unref (data->connection); - g_ptr_array_unref (data->results); - g_object_unref (data->cancellable); - - g_list_foreach (data->writeback_handlers, (GFunc) g_object_unref, NULL); - g_list_free (data->writeback_handlers); - - if (data->error) { - g_error_free (data->error); - } - g_slice_free (WritebackData, data); -} - -static void -cancel_tasks (TrackerController *controller, - const gchar *subject, - GFile *file) -{ - TrackerControllerPrivate *priv; - GList *elem; - - priv = controller->priv; - - for (elem = priv->ongoing_tasks; elem; elem = elem->next) { - WritebackData *data = elem->data; - - if (g_strcmp0 (subject, data->subject) == 0) { - g_message ("Cancelling not yet processed task ('%s')", - data->subject); - g_cancellable_cancel (data->cancellable); - } - - if (file) { - guint i; - for (i = 0; i < data->results->len; i++) { - GStrv row = g_ptr_array_index (data->results, i); - if (row[0] != NULL) { - GFile *task_file; - task_file = g_file_new_for_uri (row[0]); - if (g_file_equal (task_file, file) || - g_file_has_prefix (task_file, file)) { - /* Mount path contains some file being processed */ - g_message ("Cancelling task ('%s')", row[0]); - g_cancellable_cancel (data->cancellable); - } - g_object_unref (task_file); - } - } - } - } -} - -static void -mount_point_removed_cb (GVolumeMonitor *monitor, - GMount *mount, - gpointer user_data) -{ - GFile *mount_file; - - mount_file = g_mount_get_root (mount); - cancel_tasks (TRACKER_CONTROLLER (user_data), NULL, mount_file); - g_object_unref (mount_file); -} - -static gboolean -reset_shutdown_timeout_cb (gpointer user_data) -{ - TrackerControllerPrivate *priv; - -#ifdef STAYALIVE_ENABLE_TRACE - g_debug ("Stayalive --- time has expired"); -#endif /* STAYALIVE_ENABLE_TRACE */ - - g_message ("Shutting down due to no activity"); - - priv = TRACKER_CONTROLLER (user_data)->priv; - g_main_loop_quit (priv->main_loop); - - return FALSE; -} - -static void -reset_shutdown_timeout (TrackerController *controller) -{ - TrackerControllerPrivate *priv; - GSource *source; - - priv = controller->priv; - - if (priv->shutdown_timeout == 0) { - return; - } - -#ifdef STAYALIVE_ENABLE_TRACE - g_debug ("Stayalive --- (Re)setting timeout"); -#endif /* STAYALIVE_ENABLE_TRACE */ - - if (priv->shutdown_source) { - g_source_destroy (priv->shutdown_source); - priv->shutdown_source = NULL; - } - - source = g_timeout_source_new_seconds (priv->shutdown_timeout); - g_source_set_callback (source, - reset_shutdown_timeout_cb, - controller, NULL); - - g_source_attach (source, priv->context); - priv->shutdown_source = source; -} - -static void -tracker_controller_init (TrackerController *controller) -{ - TrackerControllerPrivate *priv; - - priv = controller->priv = G_TYPE_INSTANCE_GET_PRIVATE (controller, - TRACKER_TYPE_CONTROLLER, - TrackerControllerPrivate); - - priv->context = g_main_context_new (); - priv->main_loop = g_main_loop_new (priv->context, FALSE); - - priv->volume_monitor = g_volume_monitor_get (); - g_signal_connect_object (priv->volume_monitor, "mount-removed", - G_CALLBACK (mount_point_removed_cb), controller, 0); - - g_cond_init (&priv->initialization_cond); - g_mutex_init (&priv->initialization_mutex); - g_mutex_init (&priv->mutex); -} - -static void -handle_method_call_get_pid (TrackerController *controller, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - TrackerDBusRequest *request; - pid_t value; - - request = tracker_g_dbus_request_begin (invocation, - "%s()", - __FUNCTION__); - - reset_shutdown_timeout (controller); - value = getpid (); - tracker_dbus_request_debug (request, - "PID is %d", - value); - - tracker_dbus_request_end (request, NULL); - - g_dbus_method_invocation_return_value (invocation, - g_variant_new ("(i)", (gint) value)); -} - -static gboolean -perform_writeback_cb (gpointer user_data) -{ - TrackerControllerPrivate *priv; - WritebackData *data; - - data = user_data; - priv = data->controller->priv; - priv->ongoing_tasks = g_list_remove (priv->ongoing_tasks, data); - - if (data->error == NULL) { - g_dbus_method_invocation_return_value (data->invocation, NULL); - } else { - g_dbus_method_invocation_return_gerror (data->invocation, data->error); - } - - tracker_dbus_request_end (data->request, NULL); - - g_mutex_lock (&priv->mutex); - priv->current = NULL; - g_mutex_unlock (&priv->mutex); - - writeback_data_free (data); - - return FALSE; -} - -static gboolean -sparql_rdf_types_match (const gchar * const *module_types, - const gchar * const *rdf_types) -{ - guint n; - - for (n = 0; rdf_types[n] != NULL; n++) { - guint i; - - for (i = 0; module_types[i] != NULL; i++) { - if (g_strcmp0 (module_types[i], rdf_types[n]) == 0) { - return TRUE; - } - } - } - - return FALSE; -} - -static void -io_writeback_job (GTask *task, - gpointer source_object, - gpointer task_data, - GCancellable *cancellable) -{ - WritebackData *data = task_data; - TrackerControllerPrivate *priv = data->controller->priv; - GError *error = NULL; - gboolean handled = FALSE; - GList *writeback_handlers; - - g_mutex_lock (&priv->mutex); - priv->current = data; - g_mutex_unlock (&priv->mutex); - - writeback_handlers = data->writeback_handlers; - - while (writeback_handlers) { - handled |= tracker_writeback_update_metadata (writeback_handlers->data, - data->results, - data->connection, - data->cancellable, - (error) ? NULL : &error); - writeback_handlers = writeback_handlers->next; - } - - if (!handled) { - if (error) { - data->error = error; - } else { - g_set_error_literal (&data->error, - TRACKER_DBUS_ERROR, - TRACKER_DBUS_ERROR_UNSUPPORTED, - "No writeback modules handled " - "successfully this file"); - } - } else { - g_clear_error (&error); - } - - g_idle_add (perform_writeback_cb, data); -} - -static void -handle_method_call_perform_writeback (TrackerController *controller, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - TrackerControllerPrivate *priv; - TrackerDBusRequest *request; - const gchar *subject; - GPtrArray *results = NULL; - GHashTableIter iter; - gpointer key, value; - GVariantIter *iter1, *iter2, *iter3; - GArray *rdf_types_array; - GStrv rdf_types; - gchar *rdf_type = NULL; - GList *writeback_handlers = NULL; - - priv = controller->priv; - - results = g_ptr_array_new_with_free_func ((GDestroyNotify) g_strfreev); - g_variant_get (parameters, "(&sasaas)", &subject, &iter1, &iter2); - - rdf_types_array = g_array_new (TRUE, TRUE, sizeof (gchar *)); - while (g_variant_iter_loop (iter1, "&s", &rdf_type)) { - g_array_append_val (rdf_types_array, rdf_type); - } - - rdf_types = (GStrv) rdf_types_array->data; - g_array_free (rdf_types_array, FALSE); - - while (g_variant_iter_loop (iter2, "as", &iter3)) { - GArray *row_array = g_array_new (TRUE, TRUE, sizeof (gchar *)); - gchar *cell = NULL; - - while (g_variant_iter_loop (iter3, "&s", &cell)) { - g_array_append_val (row_array, cell); - } - - g_ptr_array_add (results, row_array->data); - g_array_free (row_array, FALSE); - } - - g_variant_iter_free (iter1); - g_variant_iter_free (iter2); - - reset_shutdown_timeout (controller); - request = tracker_dbus_request_begin (NULL, "%s (%s)", __FUNCTION__, subject); - - g_hash_table_iter_init (&iter, priv->modules); - - while (g_hash_table_iter_next (&iter, &key, &value)) { - TrackerWritebackModule *module; - const gchar * const *module_types; - - module = value; - module_types = tracker_writeback_module_get_rdf_types (module); - - if (sparql_rdf_types_match (module_types, (const gchar * const *) rdf_types)) { - TrackerWriteback *writeback; - - g_message (" Updating metadata for subject:'%s' using module:'%s'", - subject, - module->name); - - writeback = tracker_writeback_module_create (module); - writeback_handlers = g_list_prepend (writeback_handlers, writeback); - } - } - - if (writeback_handlers != NULL) { - WritebackData *data; - GTask *task; - - data = writeback_data_new (controller, - writeback_handlers, - priv->connection, - subject, - results, - invocation, - request); - task = g_task_new (controller, data->cancellable, NULL, NULL); - - /* No need to free data here, it's done in the callback. */ - g_task_set_task_data (task, data, NULL); - g_task_run_in_thread (task, io_writeback_job); - g_object_unref (task); - } else { - char *rdf_types_string; - rdf_types_string = g_strjoinv (", ", rdf_types); - g_dbus_method_invocation_return_error (invocation, - TRACKER_DBUS_ERROR, - TRACKER_DBUS_ERROR_UNSUPPORTED, - "None of %i writeback modules matched any of the " - "given RDF types: %s", - g_hash_table_size (priv->modules), - rdf_types_string); - g_free (rdf_types_string); - } - - g_free (rdf_types); -} - -static void -handle_method_call_cancel_tasks (TrackerController *controller, - GDBusMethodInvocation *invocation, - GVariant *parameters) -{ - TrackerDBusRequest *request; - gchar **subjects; - gint i; - -#ifdef THREAD_ENABLE_TRACE - g_debug ("Thread:%p (Controller) --> Got Tasks cancellation request", - g_thread_self ()); -#endif /* THREAD_ENABLE_TRACE */ - - - g_variant_get (parameters, "(^as)", &subjects); - - request = tracker_dbus_request_begin (NULL, "%s (%s, ...)", __FUNCTION__, subjects[0]); - - for (i = 0; subjects[i] != NULL; i++) { - cancel_tasks (controller, subjects[i], NULL); - } - - g_strfreev (subjects); - tracker_dbus_request_end (request, NULL); - g_dbus_method_invocation_return_value (invocation, NULL); -} - -static void -handle_method_call (GDBusConnection *connection, - const gchar *sender, - const gchar *object_path, - const gchar *interface_name, - const gchar *method_name, - GVariant *parameters, - GDBusMethodInvocation *invocation, - gpointer user_data) -{ - TrackerController *controller = user_data; - - if (g_strcmp0 (method_name, "GetPid") == 0) { - handle_method_call_get_pid (controller, invocation, parameters); - } else if (g_strcmp0 (method_name, "PerformWriteback") == 0) { - handle_method_call_perform_writeback (controller, invocation, parameters); - } else if (g_strcmp0 (method_name, "CancelTasks") == 0) { - handle_method_call_cancel_tasks (controller, invocation, parameters); - } else { - g_warning ("Unknown method '%s' called", method_name); - } -} - -static void -controller_notify_main_thread (TrackerController *controller, - GError *error) -{ - TrackerControllerPrivate *priv; - - priv = controller->priv; - - g_mutex_lock (&priv->initialization_mutex); - - priv->initialized = TRUE; - priv->initialization_error = error; - - /* Notify about the initialization */ - g_cond_signal (&priv->initialization_cond); - g_mutex_unlock (&priv->initialization_mutex); -} - -static void -bus_name_acquired_cb (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - controller_notify_main_thread (TRACKER_CONTROLLER (user_data), NULL); -} - -static void -bus_name_vanished_cb (GDBusConnection *connection, - const gchar *name, - gpointer user_data) -{ - TrackerController *controller; - TrackerControllerPrivate *priv; - - controller = user_data; - priv = controller->priv; - - if (!priv->initialized) { - GError *error; - - error = g_error_new_literal (TRACKER_DBUS_ERROR, 0, - "Could not acquire bus name, " - "perhaps it's already taken?"); - controller_notify_main_thread (controller, error); - } else { - /* We're already in control of the program - * lifetime, so just quit the mainloop - */ - g_main_loop_quit (priv->main_loop); - } -} - -static gboolean -tracker_controller_dbus_start (TrackerController *controller, - GError **error) -{ - TrackerControllerPrivate *priv; - GError *err = NULL; - GDBusInterfaceVTable interface_vtable = { - handle_method_call, - NULL, NULL - }; - - priv = controller->priv; - - priv->connection = tracker_sparql_connection_get (NULL, &err); - - if (!priv->connection) { - g_propagate_error (error, err); - return FALSE; - } - - priv->d_connection = g_bus_get_sync (TRACKER_IPC_BUS, NULL, &err); - - if (!priv->d_connection) { - g_propagate_error (error, err); - return FALSE; - } - - priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, &err); - if (!priv->introspection_data) { - g_propagate_error (error, err); - return FALSE; - } - - g_message ("Registering D-Bus object..."); - g_message (" Path:'" TRACKER_WRITEBACK_PATH "'"); - g_message (" Object Type:'%s'", G_OBJECT_TYPE_NAME (controller)); - - priv->registration_id = - g_dbus_connection_register_object (priv->d_connection, - TRACKER_WRITEBACK_PATH, - priv->introspection_data->interfaces[0], - &interface_vtable, - controller, - NULL, - &err); - - if (err) { - g_critical ("Could not register the D-Bus object "TRACKER_WRITEBACK_PATH", %s", - err ? err->message : "no error given."); - g_propagate_error (error, err); - return FALSE; - } - - priv->bus_name_id = - g_bus_own_name_on_connection (priv->d_connection, - TRACKER_WRITEBACK_SERVICE, - G_BUS_NAME_OWNER_FLAGS_NONE, - bus_name_acquired_cb, - bus_name_vanished_cb, - controller, NULL); - - if (err) { - g_critical ("Could not own the D-Bus name "TRACKER_WRITEBACK_SERVICE", %s", - err ? err->message : "no error given."); - g_propagate_error (error, err); - return FALSE; - } - - return TRUE; -} - -static void -tracker_controller_dbus_stop (TrackerController *controller) -{ - TrackerControllerPrivate *priv; - - priv = controller->priv; - - if (priv->registration_id != 0) { - g_dbus_connection_unregister_object (priv->d_connection, - priv->registration_id); - } - - if (priv->bus_name_id != 0) { - g_bus_unown_name (priv->bus_name_id); - } - - if (priv->introspection_data) { - g_dbus_node_info_unref (priv->introspection_data); - } - - if (priv->d_connection) { - g_object_unref (priv->d_connection); - } - - if (priv->connection) { - g_object_unref (priv->connection); - } -} - -TrackerController * -tracker_controller_new (guint shutdown_timeout, - GError **error) -{ - return g_initable_new (TRACKER_TYPE_CONTROLLER, - NULL, error, - "shutdown-timeout", shutdown_timeout, - NULL); -} - -static gpointer -tracker_controller_thread_func (gpointer user_data) -{ - TrackerController *controller; - TrackerControllerPrivate *priv; - GError *error = NULL; - -#ifdef THREAD_ENABLE_TRACE - g_debug ("Thread:%p (Controller) --- Created, dispatching...", - g_thread_self ()); -#endif /* THREAD_ENABLE_TRACE */ - - controller = user_data; - priv = controller->priv; - g_main_context_push_thread_default (priv->context); - - reset_shutdown_timeout (controller); - - if (!tracker_controller_dbus_start (controller, &error)) { - /* Error has been filled in, so we return - * in this thread. The main thread will be - * notified about the error and exit. - */ - controller_notify_main_thread (controller, error); - return NULL; - } - - g_main_loop_run (priv->main_loop); - -#ifdef THREAD_ENABLE_TRACE - g_debug ("Thread:%p (Controller) --- Shutting down...", - g_thread_self ()); -#endif /* THREAD_ENABLE_TRACE */ - - g_object_unref (controller); - - /* This is where we exit, be it - * either through umount events on monitored - * files' volumes or the timeout being reached - */ - exit (0); - return NULL; -} - -static gboolean -tracker_controller_start (TrackerController *controller, - GError **error) -{ - TrackerControllerPrivate *priv; - GList *modules; - GThread *thread; - - priv = controller->priv; - - priv->modules = g_hash_table_new_full (g_str_hash, - g_str_equal, - (GDestroyNotify) g_free, - NULL); - - modules = tracker_writeback_modules_list (); - - while (modules) { - TrackerWritebackModule *module; - const gchar *path; - - path = modules->data; - module = tracker_writeback_module_get (path); - - if (module) { - g_hash_table_insert (priv->modules, g_strdup (path), module); - } - - modules = modules->next; - } - - thread = g_thread_try_new ("controller", - tracker_controller_thread_func, - controller, - error); - if (!thread) - return FALSE; - - /* We don't want to join it, so just unref the GThread */ - g_thread_unref (thread); - -#ifdef THREAD_ENABLE_TRACE - g_debug ("Thread:%p (Controller) --- Waiting for controller thread to initialize...", - g_thread_self ()); -#endif /* THREAD_ENABLE_TRACE */ - - /* Wait for the controller thread to notify initialization */ - g_mutex_lock (&priv->initialization_mutex); - while (!priv->initialized) - g_cond_wait (&priv->initialization_cond, &priv->initialization_mutex); - g_mutex_unlock (&priv->initialization_mutex); - - /* If there was any error resulting from initialization, propagate it */ - if (priv->initialization_error != NULL) { - g_propagate_error (error, priv->initialization_error); - return FALSE; - } - -#ifdef THREAD_ENABLE_TRACE - g_debug ("Thread:%p (Controller) --- Initialized", - g_thread_self ()); -#endif /* THREAD_ENABLE_TRACE */ - - return TRUE; -} diff --git a/src/tracker-writeback/tracker-writeback.h b/src/tracker-writeback/tracker-writeback.h deleted file mode 100644 index 5e439351b..000000000 --- a/src/tracker-writeback/tracker-writeback.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (C) 2011, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __TRACKER_WRITEBACK_CONTROLLER_H__ -#define __TRACKER_WRITEBACK_CONTROLLER_H__ - -#include <gio/gio.h> - -/* Not needed, but for now this keeps #include API backward compatible */ -#include "tracker-writeback-module.h" - -G_BEGIN_DECLS - -#define TRACKER_TYPE_CONTROLLER (tracker_controller_get_type ()) -#define TRACKER_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_CONTROLLER, TrackerController)) -#define TRACKER_CONTROLLER_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_CONTROLLER, TrackerControllerClass)) -#define TRACKER_IS_CONTROLLER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_CONTROLLER)) -#define TRACKER_IS_CONTROLLER_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_CONTROLLER)) -#define TRACKER_CONTROLLER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_CONTROLLER, TrackerControllerClass)) - -typedef struct TrackerController TrackerController; -typedef struct TrackerControllerClass TrackerControllerClass; - -struct TrackerController { - GObject parent_instance; - gpointer priv; -}; - -struct TrackerControllerClass { - GObjectClass parent_class; -}; - -GType tracker_controller_get_type (void) G_GNUC_CONST; - -TrackerController * tracker_controller_new (guint shutdown_timeout, - GError **error); - -G_END_DECLS - -#endif /* __TRACKER_WRITEBACK_CONTROLLER_H__ */ diff --git a/src/tracker-writeback/tracker-writeback.service.in b/src/tracker-writeback/tracker-writeback.service.in deleted file mode 100644 index bcb6ac1b8..000000000 --- a/src/tracker-writeback/tracker-writeback.service.in +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Tracker data writeback service - -[Service] -Type=dbus -BusName=org.freedesktop.Tracker1.Writeback -ExecStart=@libexecdir@/tracker-writeback -Restart=on-failure -# Don't restart after tracker daemon -k (aka tracker-control -k) -RestartPreventExitStatus=SIGKILL diff --git a/src/tracker-writeback/tracker-writeback.xml b/src/tracker-writeback/tracker-writeback.xml deleted file mode 100644 index 50d1aaec1..000000000 --- a/src/tracker-writeback/tracker-writeback.xml +++ /dev/null @@ -1,27 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<!-- -<busconfig> - <policy context="default"> - <deny send_interface="org.freedesktop.Tracker1.Indexer"/> - <allow send_destination="org.freedesktop.Tracker1"/> - </policy> -</busconfig> ---> - -<node name="/"> - <interface name="org.freedesktop.Tracker1.Writeback"> - <method name="GetPid"> - <annotation name="org.freedesktop.DBus.GLib.Async" value="true"/> - <arg type="i" name="value" direction="out" /> - </method> - <method name="PerformWriteback"> - <arg type="s" name="uri" direction="in" /> - <arg type="as" name="rdf_types" direction="in" /> - <arg type="aas" name="results" direction="in" /> - </method>" - <method name="CancelTasks"> - <arg type="as" name="uri" direction="in" /> - </method> - </interface> -</node> diff --git a/tests/Makefile.am b/tests/Makefile.am index 451ff9123..db6cf3002 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -13,14 +13,6 @@ if HAVE_TRACKER_FTS SUBDIRS += libtracker-fts endif -if HAVE_TRACKER_EXTRACT -SUBDIRS += libtracker-extract -endif - -if HAVE_TRACKER_WRITEBACK -SUBDIRS += tracker-writeback -endif - if DIST_FUNCTIONAL_TESTS SUBDIRS += functional-tests endif diff --git a/tests/functional-tests/Makefile.am b/tests/functional-tests/Makefile.am index c3dd296c7..8b1e72077 100644 --- a/tests/functional-tests/Makefile.am +++ b/tests/functional-tests/Makefile.am @@ -1,8 +1,6 @@ SUBDIRS = \ ipc \ common \ - test-extraction-data \ - test-writeback-data \ test-apps-data \ ttl \ unittest2 \ diff --git a/tests/functional-tests/test-extraction-data/Makefile.am b/tests/functional-tests/test-extraction-data/Makefile.am deleted file mode 100644 index dcd33f364..000000000 --- a/tests/functional-tests/test-extraction-data/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ -include $(top_srcdir)/Makefile.decl - -SUBDIRS = audio images office video - -if HAVE_TOTEM_PL_PARSER -SUBDIRS += playlists -endif diff --git a/tests/functional-tests/test-extraction-data/README b/tests/functional-tests/test-extraction-data/README deleted file mode 100644 index cfbc0e175..000000000 --- a/tests/functional-tests/test-extraction-data/README +++ /dev/null @@ -1,68 +0,0 @@ -test-extraction-data -==================== - -The python test will traverse recursively this directory, loading the .expected files as tests. - -.expected file format -===================== - -It is a .ini (.desktop) formatted file with two mandatory sections: TestFile and Metadata. - -The TestFile section contains the -* Filename (mandatory): relative path from the .expected of the file under test. -* Bugzilla (optional): reference to a bug related with the file. -* Comment (optional): brief description of why that file is in the test suite (problematic, format example...) -* ExpectedFailure (optional): If this key is present, we expect the extraction to fail. - If ExpectedFailure is included, it is recommended to fill the Bugzilla field! - -The Metadata section contains pairs of property=values with few special rules: -1. The ':' in the properties is replaced with ̈́_'. Note that in the values is ok to have ':'. - - E.G. nfo:duration=5 -> nfo_duration=5 - but a=nmm:Video -> a=nmm:Video - -2. If the property name is prefixed with '@' then the property is expected in the extraction, but the value - won't be checked. - - E.G. The extraction is: slo:location [a slo:GeoPoint; slo:postalAddress <urn:uuid:123-123>]; - - @slo_location= -> PASS slo:location is in the extraction - -3. If the property name is prefixed with '!' then the property is NOT expected in the extraction - If the negated property has a value, it forbids the exact value. Otherwise, it forbids the property at all. - - E.G. The extraction is: a nmm:Video; nfo:duration 50. - - !a=nmm:Audio -> PASS because there is no "a nmm:Audio" - !nfo_duration=12 -> PASS because duration has a different value - !nfo_duration= -> FAIL because there shouldn't be any nfo:duration at all - -4. The translation of the extraction results to a python dictionary is very basic. - It handles a couple of special cases, relevant for testing: - E.G. - - slo:location [a slo:GeoLocation; slo:PostalAddress "XXX"] -> slo_location_postalAddress=XXX - - Note 24/08/2011: Tags are translated as "nao_Tag=value, value, value" instead of - the old "nao_Tag_preflabel=value, value, value" - -5. There is (so far only) one constant defined to use in the values: - - @URNUUID@ meaning an automatic generated urn:uuid:1231-123-123 URL - [This constant must not be used with multiple-valued properties. The code only check the first result.] - -Example -====== - -Everything together should look like this: - -[TestFile] -Filename=x.mp4 -Bugzilla=GB#123123 -Comment=Video usually clasiffied as Audio by mistake - -[Metadata] -a=nmm:Video -!a=nmm:Audio -nfo_duration=123 - diff --git a/tests/functional-tests/test-extraction-data/audio/.mediaartlocal/album-15365c9f7577b1e80d1ce6181603ae26-97bc592b27a9ada2d9a4bb418ed0ebed.jpeg b/tests/functional-tests/test-extraction-data/audio/.mediaartlocal/album-15365c9f7577b1e80d1ce6181603ae26-97bc592b27a9ada2d9a4bb418ed0ebed.jpeg Binary files differdeleted file mode 100644 index 249076507..000000000 --- a/tests/functional-tests/test-extraction-data/audio/.mediaartlocal/album-15365c9f7577b1e80d1ce6181603ae26-97bc592b27a9ada2d9a4bb418ed0ebed.jpeg +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/audio/Jazz_Audio_OPLs0.expected b/tests/functional-tests/test-extraction-data/audio/Jazz_Audio_OPLs0.expected deleted file mode 100644 index 22a53eb53..000000000 --- a/tests/functional-tests/test-extraction-data/audio/Jazz_Audio_OPLs0.expected +++ /dev/null @@ -1,11 +0,0 @@ -[TestFile] -Filename=Jazz_Audio_OPLs0.pya -Bugzilla=NB#225208 -Comment=DRM protected audio file -# Downloaded from http://playready.directtaps.net/pr/public/ - -[Metadata] -a=nmm:MusicPiece -!a=nmm:Video -!a=nfo:Image -!a=nmm:Photo diff --git a/tests/functional-tests/test-extraction-data/audio/Jazz_Audio_OPLs0.pya b/tests/functional-tests/test-extraction-data/audio/Jazz_Audio_OPLs0.pya Binary files differdeleted file mode 100644 index 118e08714..000000000 --- a/tests/functional-tests/test-extraction-data/audio/Jazz_Audio_OPLs0.pya +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/audio/Makefile.am b/tests/functional-tests/test-extraction-data/audio/Makefile.am deleted file mode 100644 index 6cc53c892..000000000 --- a/tests/functional-tests/test-extraction-data/audio/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -audiotestdir = $(datadir)/tracker-tests/test-extraction-data/audio - -audiotest_DATA = \ - audio-test-1.mp3 \ - audio-test-1.expected \ - audio-test-2.mp3 \ - audio-test-2.expected \ - Jazz_Audio_OPLs0.pya \ - Jazz_Audio_OPLs0.expected \ - empty_albumi_song3.mp3 \ - empty_albumi_song3.expected - -EXTRA_DIST = \ - $(audiotest_DATA) diff --git a/tests/functional-tests/test-extraction-data/audio/audio-test-1.expected b/tests/functional-tests/test-extraction-data/audio/audio-test-1.expected deleted file mode 100644 index fda57c557..000000000 --- a/tests/functional-tests/test-extraction-data/audio/audio-test-1.expected +++ /dev/null @@ -1,17 +0,0 @@ -[TestFile] -Filename=audio-test-1.mp3 -Bugzilla= -Comment=Basic MP3 example - -[Metadata] -a=nmm:MusicPiece -nie_title=Simply Juvenile -nfo_genre=Pop -nie_copyright=none -nie_comment=I am for simple MP3 testing -nmm_trackNumber=13 -nfo_codec=MPEG -nfo_channels=1 -nfo_duration=15 -nfo_sampleRate=22050 -nfo_averageBitrate=32000 diff --git a/tests/functional-tests/test-extraction-data/audio/audio-test-1.mp3 b/tests/functional-tests/test-extraction-data/audio/audio-test-1.mp3 Binary files differdeleted file mode 100644 index bbd4c768d..000000000 --- a/tests/functional-tests/test-extraction-data/audio/audio-test-1.mp3 +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/audio/audio-test-2.expected b/tests/functional-tests/test-extraction-data/audio/audio-test-2.expected deleted file mode 100644 index 4edc82465..000000000 --- a/tests/functional-tests/test-extraction-data/audio/audio-test-2.expected +++ /dev/null @@ -1,16 +0,0 @@ -[TestFile] -Filename=audio-test-2.mp3 -Bugzilla=NB#177663 -Comment=Mp3 with id3v2 tags. Encoded wasn't extracted. - Binary cut with dd of the original file. - -[Metadata] -a=nmm:MusicPiece -nie_title=Vinegar -nfo_genre=Pop -nie_copyright=(P) 2008 Sony Music Entertainment Finland Oy -nmm_trackNumber=1 -nfo_codec=MPEG -nfo_channels=2 -nfo_sampleRate=44100 -nfo_averageBitrate=256000 diff --git a/tests/functional-tests/test-extraction-data/audio/audio-test-2.mp3 b/tests/functional-tests/test-extraction-data/audio/audio-test-2.mp3 Binary files differdeleted file mode 100644 index d8a176f72..000000000 --- a/tests/functional-tests/test-extraction-data/audio/audio-test-2.mp3 +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/audio/empty_albumi_song3.expected b/tests/functional-tests/test-extraction-data/audio/empty_albumi_song3.expected deleted file mode 100644 index b42a48059..000000000 --- a/tests/functional-tests/test-extraction-data/audio/empty_albumi_song3.expected +++ /dev/null @@ -1,9 +0,0 @@ -[TestFile] -Filename=empty_albumi_song3.mp3 -Bugzilla=NB#223536, NB#223148 -Comment=Mp3 with empty Artist and album. Made extractor crash. - -[Metadata] -a=nmm:MusicPiece -nie_title=song3 - diff --git a/tests/functional-tests/test-extraction-data/audio/empty_albumi_song3.mp3 b/tests/functional-tests/test-extraction-data/audio/empty_albumi_song3.mp3 Binary files differdeleted file mode 100644 index b19e2e662..000000000 --- a/tests/functional-tests/test-extraction-data/audio/empty_albumi_song3.mp3 +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/images/Makefile.am b/tests/functional-tests/test-extraction-data/images/Makefile.am deleted file mode 100644 index f9a2f143f..000000000 --- a/tests/functional-tests/test-extraction-data/images/Makefile.am +++ /dev/null @@ -1,41 +0,0 @@ -imagedir = $(datadir)/tracker-tests/test-extraction-data/images - -image_DATA = \ - test-image-2.png \ - test-image-2.expected - -gifs = \ - xmp-loaded-1.gif \ - xmp-loaded-1.expected \ - comment-extension-block.expected \ - comment-extension-block.gif \ - corrupted-image.gif \ - corrupted-image.expected - -tiffs = \ - test-image-3.tif \ - test-image-3.expected - -jpegs = \ - test-image-1.jpg \ - test-image-1.expected \ - test-iptcdata-records.jpg \ - test-iptcdata-records.expected - -if HAVE_LIBGIF -image_DATA += $(gifs) -endif - -if HAVE_LIBTIFF -image_DATA += $(tiffs) -endif - -if HAVE_LIBJPEG -image_DATA += $(jpegs) -endif - -EXTRA_DIST = \ - $(image_DATA) \ - $(gifs) \ - $(tiffs) \ - $(jpegs) diff --git a/tests/functional-tests/test-extraction-data/images/comment-extension-block.expected b/tests/functional-tests/test-extraction-data/images/comment-extension-block.expected deleted file mode 100644 index 7251f7021..000000000 --- a/tests/functional-tests/test-extraction-data/images/comment-extension-block.expected +++ /dev/null @@ -1,11 +0,0 @@ -[TestFile] -Filename=comment-extension-block.gif -Bugzilla=GB#633118 -Comment=In GIF comments can come in a special block that needs to be handled manually - -[Metadata] -a=nfo:Image -a=nmm:Photo -nfo_width=600 -nfo_height=450 -nie_comment=GIF image format only supports comments in 7-bit ASCII encoding! diff --git a/tests/functional-tests/test-extraction-data/images/comment-extension-block.gif b/tests/functional-tests/test-extraction-data/images/comment-extension-block.gif Binary files differdeleted file mode 100644 index 6bb41f813..000000000 --- a/tests/functional-tests/test-extraction-data/images/comment-extension-block.gif +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/images/corrupted-image.expected b/tests/functional-tests/test-extraction-data/images/corrupted-image.expected deleted file mode 100644 index bc1115983..000000000 --- a/tests/functional-tests/test-extraction-data/images/corrupted-image.expected +++ /dev/null @@ -1,7 +0,0 @@ -[TestFile] -Filename=corrupted-image.gif -Bugzilla=NB#184882 -Comment=This image make the extractor crash - -[Metadata] -a=nmm:Photo diff --git a/tests/functional-tests/test-extraction-data/images/corrupted-image.gif b/tests/functional-tests/test-extraction-data/images/corrupted-image.gif Binary files differdeleted file mode 100644 index d17920180..000000000 --- a/tests/functional-tests/test-extraction-data/images/corrupted-image.gif +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/images/roi.expected b/tests/functional-tests/test-extraction-data/images/roi.expected deleted file mode 100644 index 7f8d879d8..000000000 --- a/tests/functional-tests/test-extraction-data/images/roi.expected +++ /dev/null @@ -1,11 +0,0 @@ -[TestFile] -Filename=roi.jpg -Bugzilla= -Comment=JPG with regions of interest in the XMP - -[Metadata] -a=nfo:Image -a=nmm:Photo -nfo_hasRegionOfInterest=@URNUUID@ -nfo_width=128 -nfo_height=128 diff --git a/tests/functional-tests/test-extraction-data/images/roi.jpg b/tests/functional-tests/test-extraction-data/images/roi.jpg Binary files differdeleted file mode 100644 index ea0fb30b0..000000000 --- a/tests/functional-tests/test-extraction-data/images/roi.jpg +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/images/roi2.expected b/tests/functional-tests/test-extraction-data/images/roi2.expected deleted file mode 100644 index 52cf25233..000000000 --- a/tests/functional-tests/test-extraction-data/images/roi2.expected +++ /dev/null @@ -1,12 +0,0 @@ -[TestFile] -Filename=roi2.png -Bugzilla= -Comment=PNG with regions of interest in the XMP -ExpectedFailure= - -[Metadata] -a=nfo:Image -a=nmm:Photo -nfo_hasRegionOfInterest=@URNUUID@ -nfo_width=128 -nfo_height=128 diff --git a/tests/functional-tests/test-extraction-data/images/roi2.png b/tests/functional-tests/test-extraction-data/images/roi2.png Binary files differdeleted file mode 100644 index 0e761f240..000000000 --- a/tests/functional-tests/test-extraction-data/images/roi2.png +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/images/test-image-1.expected b/tests/functional-tests/test-extraction-data/images/test-image-1.expected deleted file mode 100644 index e4a08849c..000000000 --- a/tests/functional-tests/test-extraction-data/images/test-image-1.expected +++ /dev/null @@ -1,18 +0,0 @@ -[TestFile] -Filename=test-image-1.jpg -Bugzilla= -Comment=Basic jpeg example - -[Metadata] -a=nmm:Photo -nfo_width=699 -nfo_height=464 -nao_hasTag=test -nao_hasTag=tracker -nie_title=Kid -nmm_fnumber=5 -nmm_focalLength=5 -nie_comment=This is a for tracker test -slo_location_postalAddress=@URNUUID@ -nfo_horizontalResolution=20 -nfo_verticalResolution=20 diff --git a/tests/functional-tests/test-extraction-data/images/test-image-1.jpg b/tests/functional-tests/test-extraction-data/images/test-image-1.jpg Binary files differdeleted file mode 100644 index f1f917bb5..000000000 --- a/tests/functional-tests/test-extraction-data/images/test-image-1.jpg +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/images/test-image-2.expected b/tests/functional-tests/test-extraction-data/images/test-image-2.expected deleted file mode 100644 index f4ab5b6f7..000000000 --- a/tests/functional-tests/test-extraction-data/images/test-image-2.expected +++ /dev/null @@ -1,9 +0,0 @@ -[TestFile] -Filename=test-image-2.png -Bugzilla= -Comment=Basic png example - -[Metadata] -a=nmm:Photo -nfo_width=211 -nfo_height=217 diff --git a/tests/functional-tests/test-extraction-data/images/test-image-2.png b/tests/functional-tests/test-extraction-data/images/test-image-2.png Binary files differdeleted file mode 100644 index 7ff9788a0..000000000 --- a/tests/functional-tests/test-extraction-data/images/test-image-2.png +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/images/test-image-3.expected b/tests/functional-tests/test-extraction-data/images/test-image-3.expected deleted file mode 100644 index 7121a4ccc..000000000 --- a/tests/functional-tests/test-extraction-data/images/test-image-3.expected +++ /dev/null @@ -1,11 +0,0 @@ -[TestFile] -Filename=test-image-3.tif -Bugzilla= -Comment=Basic TIFF example - -[Metadata] -a=nmm:Photo -nfo_width=37 -nfo_height=39 -nie_title=/home/amit/Desktop/test-image-3.tif -nfo_orientation=nfo:orientation-top-mirror diff --git a/tests/functional-tests/test-extraction-data/images/test-image-3.tif b/tests/functional-tests/test-extraction-data/images/test-image-3.tif Binary files differdeleted file mode 100644 index 8d91556a7..000000000 --- a/tests/functional-tests/test-extraction-data/images/test-image-3.tif +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/images/test-iptcdata-records.expected b/tests/functional-tests/test-extraction-data/images/test-iptcdata-records.expected deleted file mode 100644 index e0ac05b27..000000000 --- a/tests/functional-tests/test-extraction-data/images/test-iptcdata-records.expected +++ /dev/null @@ -1,8 +0,0 @@ -[TestFile] -Filename=test-iptcdata-records.jpg -Bugzilla=NB#244267 -Comment=Location information shouldn't be retrieved from the image - -[Metadata] -a=nmm:Photo -!slo_location= diff --git a/tests/functional-tests/test-extraction-data/images/test-iptcdata-records.jpg b/tests/functional-tests/test-extraction-data/images/test-iptcdata-records.jpg Binary files differdeleted file mode 100644 index 8ef7c401f..000000000 --- a/tests/functional-tests/test-extraction-data/images/test-iptcdata-records.jpg +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/images/xmp-loaded-1.expected b/tests/functional-tests/test-extraction-data/images/xmp-loaded-1.expected deleted file mode 100644 index cb3d099e6..000000000 --- a/tests/functional-tests/test-extraction-data/images/xmp-loaded-1.expected +++ /dev/null @@ -1,19 +0,0 @@ -[TestFile] -Filename=xmp-loaded-1.gif -Bugzilla= -Comment=GIF with XMP metadata (injected with exiftool) - -[Metadata] -a=nfo:Image -a=nmm:Photo -nie_description=Test file for the tracker XMP extraction -nie_title=A random GIF -nao_hasTag=Cool -nao_hasTag=favourite -nao_hasTag=nice -dc_identifier=test-file-01-world-domination-path -dc_source=http://www.fotonatura.org/revista/articulos/293/3/ -dc_language=es_ES -dc_coverage=from Helsinki all around the world -nfo_width=165 -nfo_height=66 diff --git a/tests/functional-tests/test-extraction-data/images/xmp-loaded-1.gif b/tests/functional-tests/test-extraction-data/images/xmp-loaded-1.gif Binary files differdeleted file mode 100644 index 3ce2ef7b9..000000000 --- a/tests/functional-tests/test-extraction-data/images/xmp-loaded-1.gif +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/office/Makefile.am b/tests/functional-tests/test-extraction-data/office/Makefile.am deleted file mode 100644 index 33704ed1d..000000000 --- a/tests/functional-tests/test-extraction-data/office/Makefile.am +++ /dev/null @@ -1,26 +0,0 @@ -docs = \ - office-doc.doc \ - office-doc.expected \ - powerpoint.ppt \ - powerpoint.expected - -pdfs = \ - pdf-doc.pdf \ - pdf-doc.expected - -officetestdir = $(datadir)/tracker-tests/test-extraction-data/office - -# initialize variable for unconditional += appending -officetest_DATA = - -if HAVE_LIBGSF -officetest_DATA += $(docs) -endif - -if HAVE_POPPLER -officetest_DATA += $(pdfs) -endif - -EXTRA_DIST = \ - $(docs) \ - $(pdfs) diff --git a/tests/functional-tests/test-extraction-data/office/office-doc.doc b/tests/functional-tests/test-extraction-data/office/office-doc.doc Binary files differdeleted file mode 100644 index 8450cdd63..000000000 --- a/tests/functional-tests/test-extraction-data/office/office-doc.doc +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/office/office-doc.expected b/tests/functional-tests/test-extraction-data/office/office-doc.expected deleted file mode 100644 index df8528547..000000000 --- a/tests/functional-tests/test-extraction-data/office/office-doc.expected +++ /dev/null @@ -1,10 +0,0 @@ -[TestFile] -Filename=office-doc.doc -Comment=MS Office document (unknown version) - -[Metadata] -a=nfo:PaginatedTextDocument -nie_generator=Microsoft Word 10.0 -nfo_wordCount=3053 -nie_title=Public Comments on Performance Based Payments -nco_creator_fullname=capitadj diff --git a/tests/functional-tests/test-extraction-data/office/pdf-doc.expected b/tests/functional-tests/test-extraction-data/office/pdf-doc.expected deleted file mode 100644 index 3580ec32f..000000000 --- a/tests/functional-tests/test-extraction-data/office/pdf-doc.expected +++ /dev/null @@ -1,7 +0,0 @@ -[TestFile] -Filename=pdf-doc.pdf -Comment=PDF document from the office tools - -[Metadata] -a=nfo:PaginatedTextDocument -nfo_pageCount=22 diff --git a/tests/functional-tests/test-extraction-data/office/pdf-doc.pdf b/tests/functional-tests/test-extraction-data/office/pdf-doc.pdf Binary files differdeleted file mode 100644 index 064645c39..000000000 --- a/tests/functional-tests/test-extraction-data/office/pdf-doc.pdf +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/office/powerpoint.expected b/tests/functional-tests/test-extraction-data/office/powerpoint.expected deleted file mode 100644 index a21d8c306..000000000 --- a/tests/functional-tests/test-extraction-data/office/powerpoint.expected +++ /dev/null @@ -1,9 +0,0 @@ -[TestFile] -Filename=powerpoint.ppt -Comment=Powerpoint document (unknown version!) - -[Metadata] -a=nfo:PaginatedTextDocument -nie_generator=Microsoft PowerPoint -nfo_wordCount=573 -nie_title=ARTificial Life diff --git a/tests/functional-tests/test-extraction-data/office/powerpoint.ppt b/tests/functional-tests/test-extraction-data/office/powerpoint.ppt Binary files differdeleted file mode 100644 index 2fc0a733f..000000000 --- a/tests/functional-tests/test-extraction-data/office/powerpoint.ppt +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/playlists/Makefile.am b/tests/functional-tests/test-extraction-data/playlists/Makefile.am deleted file mode 100644 index b797684e2..000000000 --- a/tests/functional-tests/test-extraction-data/playlists/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -playlists = \ - playlist-test-1.m3u \ - playlist-test-1.expected - -if HAVE_TOTEM_PL_PARSER -playlisttestdir = $(datadir)/tracker-tests/test-extraction-data/playlists -playlisttest_DATA = $(playlists) -endif - -EXTRA_DIST = $(playlists) diff --git a/tests/functional-tests/test-extraction-data/playlists/playlist-test-1.expected b/tests/functional-tests/test-extraction-data/playlists/playlist-test-1.expected deleted file mode 100644 index fd822f84d..000000000 --- a/tests/functional-tests/test-extraction-data/playlists/playlist-test-1.expected +++ /dev/null @@ -1,13 +0,0 @@ -[TestFile] -Filename=playlist-test-1.m3u -Bugzilla= -Comment=Regular m3u playlist file - -[Metadata] -a=nmm:Playlist -nfo_entryCounter=5 -nfo_hasMediaFileListEntry_entryUrl=http://www.apnaradio.com/live/ApnaRadio.mp3 -nfo_hasMediaFileListEntry_entryUrl=http://live.apnaradio.com:6464 -nfo_hasMediaFileListEntry_entryUrl=http://live.apnaradio.com:2424 -nfo_hasMediaFileListEntry_entryUrl=http://www.apnaradio.com/live/MaintenanceE.mp3 -nfo_hasMediaFileListEntry_entryUrl=http://www.apnaradio.com/live/MaintenanceP.mp3 diff --git a/tests/functional-tests/test-extraction-data/playlists/playlist-test-1.m3u b/tests/functional-tests/test-extraction-data/playlists/playlist-test-1.m3u deleted file mode 100755 index 6107435c9..000000000 --- a/tests/functional-tests/test-extraction-data/playlists/playlist-test-1.m3u +++ /dev/null @@ -1,8 +0,0 @@ -[playlist] -File1=http://www.apnaradio.com/live/ApnaRadio.mp3 -File2=http://live.apnaradio.com:6464 -File3=http://live.apnaradio.com:2424 -File4=http://www.apnaradio.com/live/MaintenanceE.mp3 -File5=http://www.apnaradio.com/live/MaintenanceP.mp3 -NumberOfEntries=5 - diff --git a/tests/functional-tests/test-extraction-data/video/.mediaartlocal/video-fec11a5d1e731ccf459f459a9c86cc51-7215ee9c7d9dc229d2921a40e899ec5f.jpeg b/tests/functional-tests/test-extraction-data/video/.mediaartlocal/video-fec11a5d1e731ccf459f459a9c86cc51-7215ee9c7d9dc229d2921a40e899ec5f.jpeg Binary files differdeleted file mode 100644 index f1f917bb5..000000000 --- a/tests/functional-tests/test-extraction-data/video/.mediaartlocal/video-fec11a5d1e731ccf459f459a9c86cc51-7215ee9c7d9dc229d2921a40e899ec5f.jpeg +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/video/184505.expected b/tests/functional-tests/test-extraction-data/video/184505.expected deleted file mode 100644 index d62395df5..000000000 --- a/tests/functional-tests/test-extraction-data/video/184505.expected +++ /dev/null @@ -1,10 +0,0 @@ -[TestFile] -Filename=184505.mp4 -Bugzilla=NB#184505 -Comment=Video without audio stream. Seems to be clasified as Audio. - -[Metadata] -a=nmm:Video -!a=nmm:Audio -nfo_height=480 -nfo_width=864 diff --git a/tests/functional-tests/test-extraction-data/video/184505.mp4 b/tests/functional-tests/test-extraction-data/video/184505.mp4 Binary files differdeleted file mode 100644 index 7fc8151af..000000000 --- a/tests/functional-tests/test-extraction-data/video/184505.mp4 +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/video/Makefile.am b/tests/functional-tests/test-extraction-data/video/Makefile.am deleted file mode 100644 index 796cc3cc2..000000000 --- a/tests/functional-tests/test-extraction-data/video/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -videotestdir = $(datadir)/tracker-tests/test-extraction-data/video - -videotest_DATA = - -videos = \ - video-1.mp4 \ - video-1.expected \ - video-2.mov \ - video-2.expected - -# This should be GSTREAMER OR GSTREMER_HELIX OR USING_EXTERNAL_VIDEO_PLAYER -if HAVE_GSTREAMER -videotest_DATA += $(videos) -endif - -EXTRA_DIST = $(videos) diff --git a/tests/functional-tests/test-extraction-data/video/video-1.expected b/tests/functional-tests/test-extraction-data/video/video-1.expected deleted file mode 100644 index 59237d118..000000000 --- a/tests/functional-tests/test-extraction-data/video/video-1.expected +++ /dev/null @@ -1,9 +0,0 @@ -[TestFile] -Filename=video-1.mp4 -Comment=Just one standard mp4 -[Metadata] -a=nmm:Video -nie_title=MPEG-4-x264.mp4 -nfo_codec=MPEG-4 AAC audio -nfo_height=240 -nfo_width=320 diff --git a/tests/functional-tests/test-extraction-data/video/video-1.mp4 b/tests/functional-tests/test-extraction-data/video/video-1.mp4 Binary files differdeleted file mode 100644 index 915e4be13..000000000 --- a/tests/functional-tests/test-extraction-data/video/video-1.mp4 +++ /dev/null diff --git a/tests/functional-tests/test-extraction-data/video/video-2.expected b/tests/functional-tests/test-extraction-data/video/video-2.expected deleted file mode 100644 index ce8633514..000000000 --- a/tests/functional-tests/test-extraction-data/video/video-2.expected +++ /dev/null @@ -1,9 +0,0 @@ -[TestFile] -Filename=video-2.mov -Bugzilla=NB#181112 -Comment=Produces a Critical in Gstreamer freeing a component. - -[Metadata] -a=nmm:Video -nfo_height=144 -nfo_width=192 diff --git a/tests/functional-tests/test-extraction-data/video/video-2.mov b/tests/functional-tests/test-extraction-data/video/video-2.mov Binary files differdeleted file mode 100644 index 6e8eaa742..000000000 --- a/tests/functional-tests/test-extraction-data/video/video-2.mov +++ /dev/null diff --git a/tests/functional-tests/test-writeback-data/Makefile.am b/tests/functional-tests/test-writeback-data/Makefile.am deleted file mode 100644 index 9f34cc501..000000000 --- a/tests/functional-tests/test-writeback-data/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -wbtestdir = $(datadir)/tracker-tests/test-writeback-data/ - -wbtest_DATA = \ - writeback-test-1.jpeg \ - writeback-test-2.tif \ - writeback-test-4.png - -EXTRA_DIST = $(wbtest_DATA) diff --git a/tests/functional-tests/test-writeback-data/writeback-test-1.jpeg b/tests/functional-tests/test-writeback-data/writeback-test-1.jpeg Binary files differdeleted file mode 100644 index 160a9240d..000000000 --- a/tests/functional-tests/test-writeback-data/writeback-test-1.jpeg +++ /dev/null diff --git a/tests/functional-tests/test-writeback-data/writeback-test-2.tif b/tests/functional-tests/test-writeback-data/writeback-test-2.tif Binary files differdeleted file mode 100644 index 8d91556a7..000000000 --- a/tests/functional-tests/test-writeback-data/writeback-test-2.tif +++ /dev/null diff --git a/tests/functional-tests/test-writeback-data/writeback-test-4.png b/tests/functional-tests/test-writeback-data/writeback-test-4.png Binary files differdeleted file mode 100644 index 7ff9788a0..000000000 --- a/tests/functional-tests/test-writeback-data/writeback-test-4.png +++ /dev/null diff --git a/tests/libtracker-extract/.gitignore b/tests/libtracker-extract/.gitignore deleted file mode 100644 index d3fbec9bc..000000000 --- a/tests/libtracker-extract/.gitignore +++ /dev/null @@ -1,8 +0,0 @@ -tracker-encoding -tracker-test-utils -tracker-test-xmp -tracker-exif-test -tracker-extract-info-test -tracker-guarantee-test -tracker-iptc-test - diff --git a/tests/libtracker-extract/Makefile.am b/tests/libtracker-extract/Makefile.am deleted file mode 100644 index 932531f26..000000000 --- a/tests/libtracker-extract/Makefile.am +++ /dev/null @@ -1,70 +0,0 @@ -include $(top_srcdir)/Makefile.decl - -noinst_PROGRAMS += $(test_programs) - -test_programs = \ - tracker-test-utils \ - tracker-test-xmp \ - tracker-extract-info-test \ - tracker-guarantee-test - -if HAVE_EXIF -test_programs += tracker-exif-test -endif - -if HAVE_IPTC -if HAVE_LIBJPEG -test_programs += tracker-iptc-test -endif -endif - -if HAVE_ENCA -test_programs += tracker-encoding -endif - -AM_CPPFLAGS = \ - -DTOP_SRCDIR=\"$(abs_top_srcdir)\" \ - -DTOP_BUILDDIR=\"$(abs_top_builddir)\" \ - $(BUILD_CFLAGS) \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - -I$(top_srcdir)/tests/common \ - $(LIBTRACKER_EXTRACT_CFLAGS) - -LDADD = \ - $(top_builddir)/tests/common/libtracker-testcommon.la \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(top_builddir)/src/libtracker-extract/libtracker-extract.la \ - $(top_builddir)/src/libtracker-sparql-backend/libtracker-sparql-@TRACKER_API_VERSION@.la \ - $(BUILD_LIBS) \ - $(LIBTRACKER_EXTRACT_LIBS) - -tracker_encoding_SOURCES = tracker-encoding-test.c - -tracker_test_utils_SOURCES = tracker-test-utils.c - -tracker_test_xmp_SOURCES = tracker-test-xmp.c - -tracker_extract_info_test_SOURCES = tracker-extract-info-test.c - -tracker_exif_test_SOURCES = tracker-exif-test.c - -tracker_guarantee_test_SOURCES = tracker-guarantee-test.c - -tracker_iptc_test_SOURCES = tracker-iptc-test.c -tracker_iptc_test_LDADD = $(LDADD) $(LIBJPEG_LIBS) -tracker_iptc_test_CFLAGS = $(LIBJPEG_CFLAGS) - -EXTRA_DIST += \ - encoding-detect.bin \ - areas.xmp \ - areas-with-contacts.xmp \ - areas-ns.xmp \ - nb282393.xmp \ - nb282393_simple.xmp \ - exif-img.jpg \ - exif-free-img.jpg \ - guarantee-mtime-test.txt \ - getline-test.txt \ - iptc-img.jpg \ - meson.build diff --git a/tests/libtracker-extract/areas-ns.xmp b/tests/libtracker-extract/areas-ns.xmp deleted file mode 100644 index d558ee599..000000000 --- a/tests/libtracker-extract/areas-ns.xmp +++ /dev/null @@ -1,32 +0,0 @@ -<!-- Same XMP with areas but using a different namespace prefix --> -<x:xmpmeta - xmlns:x="adobe:ns:meta/" - xmlns:exif="http://ns.adobe.com/exif/1.0/" - xmlns:my-dym="http://ns.adobe.com/xap/1.0/sType/Dimensions#" - xmlns:my-area="http://ns.adobe.com/xmp/sType/Area#" - xmlns:my-ns="http://www.metadataworkinggroup.com/schemas/regions/"> - <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> - <rdf:Description rdf:about=""> - <my-ns:Regions rdf:parseType="Resource"> - <my-ns:AppliedToDimensions my-dym:w="4288" my-dym:h="2848" my-dym:unit="pixel"/> - <my-ns:RegionList> - <rdf:Bag> - <rdf:li rdf:parseType="Resource"> - <my-ns:Area my-area:x="0.5" my-area:y="0.5" my-area:w="0.06" - my-area:h="0.09" my-area:unit="normalized"/> - <my-ns:Type>Face</my-ns:Type> - <my-ns:Name>Average Joe</my-ns:Name> - </rdf:li> - <rdf:li rdf:parseType="Resource"> - <my-ns:Area my-area:x="0.51" my-area:y="0.51" my-area:w="0.01" - my-area:h="0.09" my-area:unit="normalized"/> - <my-ns:Type>Pet</my-ns:Type> - <my-ns:Name>Fidoz</my-ns:Name> - <my-ns:Description>Fido looks happy!</my-ns:Description> - </rdf:li> - </rdf:Bag> - </my-ns:RegionList> - </my-ns:Regions> - </rdf:Description> - </rdf:RDF> -</x:xmpmeta> diff --git a/tests/libtracker-extract/areas-with-contacts.xmp b/tests/libtracker-extract/areas-with-contacts.xmp deleted file mode 100644 index ca707702b..000000000 --- a/tests/libtracker-extract/areas-with-contacts.xmp +++ /dev/null @@ -1,53 +0,0 @@ -<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 8.60'> -<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'> - <rdf:Description rdf:about='' - xmlns:mwg-rs='http://www.metadataworkinggroup.com/schemas/regions/' - xmlns:rdfs='http://www.w3.org/2000/01/rdf-schema#' - xmlns:stArea='http://ns.adobe.com/xmp/sType/Area#' - xmlns:stDim='http://ns.adobe.com/xap/1.0/sType/Dimensions#' - xmlns:nco='http://www.semanticdesktop.org/ontologies/2007/03/22/nco#' - xmlns:xmpRights='http://ns.adobe.com/xap/1.0/rights/'> - <mwg-rs:Regions rdf:parseType='Resource'> - <mwg-rs:AppliedToDimensions rdf:parseType='Resource'> - <stDim:h>2848</stDim:h> - <stDim:unit>pixel</stDim:unit> - <stDim:w>4288</stDim:w> - </mwg-rs:AppliedToDimensions> - <mwg-rs:RegionList> - <rdf:Bag> - <rdf:li rdf:parseType='Resource'> - <mwg-rs:Area rdf:parseType='Resource'> - <stArea:h>0.17</stArea:h> - <stArea:unit>normalized</stArea:unit> - <stArea:w>0.15</stArea:w> - <stArea:x>0.3</stArea:x> - <stArea:y>0.4</stArea:y> - </mwg-rs:Area> - <mwg-rs:Extensions rdf:parseType='Resource'> - <nco:PersonContact>urn:uuid:1</nco:PersonContact> - </mwg-rs:Extensions> - <mwg-rs:Name>Albert Einstein</mwg-rs:Name> - <mwg-rs:Type>Face</mwg-rs:Type> - <rdfs:seeAlso rdf:resource='dc:subject'/> - </rdf:li> - <rdf:li rdf:parseType='Resource'> - <mwg-rs:Area rdf:parseType='Resource'> - <stArea:h>0.15</stArea:h> - <stArea:unit>normalized</stArea:unit> - <stArea:w>0.17</stArea:w> - <stArea:x>0.4</stArea:x> - <stArea:y>0.3</stArea:y> - </mwg-rs:Area> - <mwg-rs:Extensions rdf:parseType='Resource'> - <nco:PersonContact>urn:uuid:2</nco:PersonContact> - </mwg-rs:Extensions> - <mwg-rs:Name>Dilbert</mwg-rs:Name> - <mwg-rs:Type>Face</mwg-rs:Type> - <rdfs:seeAlso rdf:resource='dc:subject'/> - </rdf:li> - </rdf:Bag> - </mwg-rs:RegionList> - </mwg-rs:Regions> - </rdf:Description> -</rdf:RDF> -</x:xmpmeta> diff --git a/tests/libtracker-extract/areas.xmp b/tests/libtracker-extract/areas.xmp deleted file mode 100644 index e6a996c02..000000000 --- a/tests/libtracker-extract/areas.xmp +++ /dev/null @@ -1,31 +0,0 @@ -<x:xmpmeta - xmlns:x="adobe:ns:meta/" - xmlns:exif="http://ns.adobe.com/exif/1.0/" - xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#" - xmlns:stArea="http://ns.adobe.com/xmp/sType/Area#" - xmlns:mwg-rs="http://www.metadataworkinggroup.com/schemas/regions/"> - <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> - <rdf:Description rdf:about=""> - <mwg-rs:Regions rdf:parseType="Resource"> - <mwg-rs:AppliedToDimensions stDim:w="4288" stDim:h="2848" stDim:unit="pixel"/> - <mwg-rs:RegionList> - <rdf:Bag> - <rdf:li rdf:parseType="Resource"> - <mwg-rs:Area stArea:x="0.5" stArea:y="0.5" stArea:w="0.06" - stArea:h="0.09" stArea:unit="normalized"/> - <mwg-rs:Type>Face</mwg-rs:Type> - <mwg-rs:Name>John Doe</mwg-rs:Name> - </rdf:li> - <rdf:li rdf:parseType="Resource"> - <mwg-rs:Area stArea:x="0.51" stArea:y="0.51" stArea:w="0.01" - stArea:h="0.09" stArea:unit="normalized"/> - <mwg-rs:Type>Pet</mwg-rs:Type> - <mwg-rs:Name>Fido</mwg-rs:Name> - <mwg-rs:Description>Fido looks happy!</mwg-rs:Description> - </rdf:li> - </rdf:Bag> - </mwg-rs:RegionList> - </mwg-rs:Regions> - </rdf:Description> - </rdf:RDF> -</x:xmpmeta> diff --git a/tests/libtracker-extract/encoding-detect.bin b/tests/libtracker-extract/encoding-detect.bin deleted file mode 100644 index 530d5a381..000000000 --- a/tests/libtracker-extract/encoding-detect.bin +++ /dev/null @@ -1 +0,0 @@ -ÊîñìîíàâòRadiotrance (Ðàäèîòðàíñ)Ê Çâ¸çäàì
\ No newline at end of file diff --git a/tests/libtracker-extract/exif-free-img.jpg b/tests/libtracker-extract/exif-free-img.jpg Binary files differdeleted file mode 100644 index 6ac4a4565..000000000 --- a/tests/libtracker-extract/exif-free-img.jpg +++ /dev/null diff --git a/tests/libtracker-extract/exif-img.jpg b/tests/libtracker-extract/exif-img.jpg Binary files differdeleted file mode 100644 index 2a3c7cc31..000000000 --- a/tests/libtracker-extract/exif-img.jpg +++ /dev/null diff --git a/tests/libtracker-extract/getline-test.txt b/tests/libtracker-extract/getline-test.txt deleted file mode 100644 index 62d617f65..000000000 --- a/tests/libtracker-extract/getline-test.txt +++ /dev/null @@ -1,3 +0,0 @@ -Line 1 -line 2 -line 3 diff --git a/tests/libtracker-extract/guarantee-mtime-test.txt b/tests/libtracker-extract/guarantee-mtime-test.txt deleted file mode 100644 index 587be6b4c..000000000 --- a/tests/libtracker-extract/guarantee-mtime-test.txt +++ /dev/null @@ -1 +0,0 @@ -x diff --git a/tests/libtracker-extract/iptc-img.jpg b/tests/libtracker-extract/iptc-img.jpg Binary files differdeleted file mode 100644 index d40001062..000000000 --- a/tests/libtracker-extract/iptc-img.jpg +++ /dev/null diff --git a/tests/libtracker-extract/meson.build b/tests/libtracker-extract/meson.build deleted file mode 100644 index 6859510c5..000000000 --- a/tests/libtracker-extract/meson.build +++ /dev/null @@ -1,59 +0,0 @@ -test_c_args = tracker_c_args + [ - '-DTOP_BUILDDIR="@0@/"'.format(meson.build_root()), - '-DTOP_SRCDIR="@0@/"'.format(meson.source_root()), -] - -guarantee_test = executable('tracker-guarantee-test', - 'tracker-guarantee-test.c', - dependencies: [tracker_common_dep, tracker_extract_dep], - c_args: test_c_args, -) -test('extract-guarantee', guarantee_test) - -extract_info_test = executable('tracker-extract-info-test', - 'tracker-extract-info-test.c', - dependencies: [tracker_common_dep, tracker_extract_dep], - c_args: test_c_args, -) -test('extract-info-test', extract_info_test) - -utils_test = executable('tracker-test-utils', - 'tracker-test-utils.c', - dependencies: [tracker_common_dep, tracker_extract_dep], - c_args: test_c_args, -) -test('extract-utils', utils_test) - -xmp_test = executable('tracker-test-xmp', - 'tracker-test-xmp.c', - dependencies: [tracker_common_dep, tracker_extract_dep], - c_args: test_c_args, -) -test('extract-xmp', xmp_test) - -if libexif.found() - exif_test = executable('tracker-exif-test', - 'tracker-exif-test.c', - dependencies: [tracker_common_dep, tracker_extract_dep], - c_args: test_c_args, - ) - test('extract-exif', exif_test) -endif - -if libiptcdata.found() and libjpeg.found() - iptc_test = executable('tracker-iptc-test', - 'tracker-iptc-test.c', - dependencies: [tracker_common_dep, tracker_extract_dep, libjpeg], - c_args: test_c_args, - ) - test('extract-iptc', iptc_test) -endif - -if charset_library_name != 'none' - encoding_test = executable('tracker-encoding-test', - 'tracker-encoding-test.c', - dependencies: [tracker_common_dep, tracker_extract_dep], - c_args: test_c_args, - ) - test('extract-encoding', encoding_test) -endif diff --git a/tests/libtracker-extract/nb282393.xmp b/tests/libtracker-extract/nb282393.xmp deleted file mode 100644 index bd006f1c8..000000000 --- a/tests/libtracker-extract/nb282393.xmp +++ /dev/null @@ -1,105 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2"> - <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> - <rdf:Description rdf:about="" - xmlns:xmp="http://ns.adobe.com/xap/1.0/" - xmlns:tiff="http://ns.adobe.com/tiff/1.0/" - xmlns:exif="http://ns.adobe.com/exif/1.0/" - xmlns:mwg-rs="http://www.metadataworkinggroup.com/schemas/regions/" - xmlns:stArea="http://ns.adobe.com/xmp/sType/Area#" - xmlns:nco="http://www.semanticdesktop.org/ontologies/2007/03/22/nco#" - xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#" - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmp:CreateDate="2011-09-11T11:29:48" - xmp:ModifyDate="2011-09-13T15:33:39" - xmp:Rating="0" - tiff:NativeDigest="256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;7ED55293F2FB266034F7E47E457379EF" - tiff:Orientation="1" - tiff:YCbCrPositioning="2" - tiff:XResolution="72/1" - tiff:YResolution="72/1" - tiff:ResolutionUnit="2" - tiff:DateTime="2011-09-13T15:33:39" - tiff:Make="Canon" - tiff:Model="Canon PowerShot S95" - exif:NativeDigest="36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;47F59181CDFD6A141145DA200B8C041D" - exif:ExifVersion="0230" - exif:FlashpixVersion="0100" - exif:ColorSpace="1" - exif:CompressedBitsPerPixel="3/1" - exif:PixelXDimension="150" - exif:PixelYDimension="200" - exif:DateTimeOriginal="2011-09-11T11:29:48" - exif:DateTimeDigitized="2011-09-11T11:29:48" - exif:ExposureTime="1/800" - exif:FNumber="40/10" - exif:ShutterSpeedValue="309/32" - exif:ApertureValue="128/32" - exif:ExposureBiasValue="0/3" - exif:MaxApertureValue="116/32" - exif:MeteringMode="5" - exif:FocalLength="12845/1000" - exif:FocalPlaneXResolution="3648000/292" - exif:FocalPlaneYResolution="2736000/219" - exif:FocalPlaneResolutionUnit="2" - exif:SensingMethod="2" - exif:FileSource="3" - exif:CustomRendered="0" - exif:ExposureMode="0" - exif:WhiteBalance="0" - exif:DigitalZoomRatio="3648/3648" - exif:SceneCaptureType="0"> - <exif:Flash - exif:Fired="False" - exif:Return="0" - exif:Mode="2" - exif:Function="False" - exif:RedEyeMode="False"/> - <exif:ComponentsConfiguration> - <rdf:Seq> - <rdf:li>1</rdf:li> - <rdf:li>2</rdf:li> - <rdf:li>3</rdf:li> - <rdf:li>0</rdf:li> - </rdf:Seq> - </exif:ComponentsConfiguration> - <exif:UserComment> - <rdf:Alt> - <rdf:li xml:lang="x-default"/> - </rdf:Alt> - </exif:UserComment> - <exif:ISOSpeedRatings> - <rdf:Seq> - <rdf:li>80</rdf:li> - </rdf:Seq> - </exif:ISOSpeedRatings> - <mwg-rs:Regions rdf:parseType="Resource"> - <mwg-rs:RegionList> - <rdf:Bag> - <rdf:li> - <rdf:Description - mwg-rs:Name=" " - mwg-rs:Type=""> - <mwg-rs:Area - stArea:x="0.433333" - stArea:y="0.370000" - stArea:h="0.440000" - stArea:w="0.586667"/> - <mwg-rs:Extensions - nco:PersonContact="urn:uuid:840a3c05-6cc6-48a1-bb56-fc50fae3345a"/> - </rdf:Description> - </rdf:li> - </rdf:Bag> - </mwg-rs:RegionList> - <mwg-rs:AppliedToDimensions - stDim:h="200" - stDim:w="150"/> - </mwg-rs:Regions> - <dc:description> - <rdf:Alt> - <rdf:li xml:lang="x-default"> </rdf:li> - </rdf:Alt> - </dc:description> - </rdf:Description> - </rdf:RDF> -</x:xmpmeta> diff --git a/tests/libtracker-extract/nb282393_simple.xmp b/tests/libtracker-extract/nb282393_simple.xmp deleted file mode 100644 index 9309a1813..000000000 --- a/tests/libtracker-extract/nb282393_simple.xmp +++ /dev/null @@ -1,37 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="XMP Core 4.4.0-Exiv2"> - <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> - <rdf:Description rdf:about="" - xmlns:tiff="http://ns.adobe.com/tiff/1.0/" - xmlns:exif="http://ns.adobe.com/exif/1.0/" - xmlns:mwg-rs="http://www.metadataworkinggroup.com/schemas/regions/" - xmlns:stArea="http://ns.adobe.com/xmp/sType/Area#" - xmlns:nco="http://www.semanticdesktop.org/ontologies/2007/03/22/nco#" - xmlns:stDim="http://ns.adobe.com/xap/1.0/sType/Dimensions#" - tiff:NativeDigest="256,257,258,259,262,274,277,284,530,531,282,283,296,301,318,319,529,532,306,270,271,272,305,315,33432;D41D8CD98F00B204E9800998ECF8427E" - exif:NativeDigest="36864,40960,40961,37121,37122,40962,40963,37510,40964,36867,36868,33434,33437,34850,34852,34855,34856,37377,37378,37379,37380,37381,37382,37383,37384,37385,37386,37396,41483,41484,41486,41487,41488,41492,41493,41495,41728,41729,41730,41985,41986,41987,41988,41989,41990,41991,41992,41993,41994,41995,41996,42016,0,2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,20,22,23,24,25,26,27,28,30;D41D8CD98F00B204E9800998ECF8427E"> - <mwg-rs:Regions rdf:parseType="Resource"> - <mwg-rs:RegionList> - <rdf:Bag> - <rdf:li> - <rdf:Description - mwg-rs:Name=" " - mwg-rs:Type=""> - <mwg-rs:Area - stArea:x="0.440000" - stArea:y="0.365000" - stArea:h="0.440000" - stArea:w="0.586667"/> - <mwg-rs:Extensions - nco:PersonContact="urn:uuid:840a3c05-6cc6-48a1-bb56-fc50fae3345a"/> - </rdf:Description> - </rdf:li> - </rdf:Bag> - </mwg-rs:RegionList> - <mwg-rs:AppliedToDimensions - stDim:h="200" - stDim:w="150"/> - </mwg-rs:Regions> - </rdf:Description> - </rdf:RDF> -</x:xmpmeta> diff --git a/tests/libtracker-extract/tracker-encoding-test.c b/tests/libtracker-extract/tracker-encoding-test.c deleted file mode 100644 index cd1408890..000000000 --- a/tests/libtracker-extract/tracker-encoding-test.c +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include "config.h" - -#include <glib-object.h> -#include <libtracker-extract/tracker-encoding.h> -#include <libtracker-common/tracker-locale.h> -#include <locale.h> - -static void -test_encoding_guessing () -{ - gchar *output; - GMappedFile *file = NULL; - gchar *prefix, *filen; - - prefix = g_build_path (G_DIR_SEPARATOR_S, TOP_SRCDIR, "tests", "libtracker-extract", NULL); - filen = g_build_filename (prefix, "encoding-detect.bin", NULL); - - file = g_mapped_file_new (filen, FALSE, NULL); - - output = tracker_encoding_guess (g_mapped_file_get_contents (file), - g_mapped_file_get_length (file), - NULL); - - g_assert_cmpstr (output, ==, "UTF-8"); - - g_mapped_file_unref (file); - - g_free (prefix); - g_free (filen); - g_free (output); -} - -static void -test_encoding_can_guess (void) -{ - /* This just duplicates the function code... */ -#if defined (HAVE_ENCA) || defined (HAVE_LIBICU_CHARSET_DETECTION) - g_assert (tracker_encoding_can_guess ()); -#else - g_assert (!tracker_encoding_can_guess ()); -#endif -} - -int -main (int argc, char **argv) -{ - g_test_init (&argc, &argv, NULL); - - setlocale (LC_ALL, ""); - g_test_add_func ("/libtracker-extract/tracker-encoding/encoding_guessing", - test_encoding_guessing); - g_test_add_func ("/libtracker-extract/tracker-encoding/can_guess", - test_encoding_can_guess); - - return g_test_run (); -} diff --git a/tests/libtracker-extract/tracker-exif-test.c b/tests/libtracker-extract/tracker-exif-test.c deleted file mode 100644 index b56c01176..000000000 --- a/tests/libtracker-extract/tracker-exif-test.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2011, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include <glib-object.h> - -#include <libtracker-extract/tracker-extract.h> - -static void -test_exif_parse (void) -{ - TrackerExifData *exif; - gchar *blob; - gsize length; - - - g_assert (g_file_get_contents (TOP_SRCDIR "/tests/libtracker-extract/exif-img.jpg", &blob, &length, NULL)); - - exif = tracker_exif_new ((guchar *)blob, length, "test://file"); - - /* Ignored on purpose on the code (?) */ - //g_assert_cmpstr (exif->x_dimension, ==, ); - //g_assert_cmpstr (exif->y_dimenstion, ==, ); - //g_assert_cmpstr (exif->image_width, ==, ); - - g_assert_cmpstr (exif->document_name, ==, "test-documentname"); - //g_assert_cmpstr (exif->time, ==, "test-documentname"); - g_assert (exif->time_original); - g_assert_cmpstr (exif->artist, ==, "EXIFspec"); // -Exif:Artist - g_assert_cmpstr (exif->user_comment, ==, "libexif demonstration image"); - g_assert_cmpstr (exif->description, ==, "Justfortest"); //-Exif:ImageDescription - g_assert_cmpstr (exif->make, ==, "Nikon"); //-Exif:Make - g_assert_cmpstr (exif->model, ==, "SD3000"); //-Exif:Model - g_assert_cmpstr (exif->orientation, ==, "nfo:orientation-left-mirror"); //-n -Exif:Orientation=5 - g_assert_cmpstr (exif->exposure_time, ==, "0.002"); // -Exif:ExposureTime=1/500 - g_assert_cmpstr (exif->fnumber, ==, "5.6"); // -Exif:FNumber - g_assert_cmpstr (exif->flash, ==, "nmm:flash-off"); // -n -Exif:Flash=88 - g_assert_cmpstr (exif->focal_length, ==, "35.0"); // -n -Exif:FocalLength=35 - g_assert_cmpstr (exif->iso_speed_ratings, ==, "400"); // -n -Exif:ISO=400 - g_assert_cmpstr (exif->metering_mode, ==, "nmm:metering-mode-multispot"); // -n -Exif:MeteringMode=4 - g_assert_cmpstr (exif->white_balance, ==, "nmm:white-balance-auto"); // -n -Exif:WhiteBalance=0 - g_assert_cmpstr (exif->copyright, ==, "From the exif demo with exiftool metadata"); // -Exif:Copyright - g_assert_cmpstr (exif->software, ==, "bunchof1s"); // -Exif:Software - g_assert_cmpstr (exif->x_resolution, ==, "72"); - g_assert_cmpstr (exif->y_resolution, ==, "72"); - g_assert_cmpint (exif->resolution_unit, ==, 2); - - g_assert_cmpstr (exif->gps_altitude, ==, "237.000000"); // -n -exif:gpsaltitude=237 - g_assert_cmpstr (exif->gps_latitude, ==, "-42.500000"); // -exif:gpslatitude="42 30 0.00" -exif:gpslatituderef=S - g_assert_cmpstr (exif->gps_longitude, ==, "-10.166675"); // -exif:gpslongitude="10 10 0.03" -exif:gpslongituderef=W - g_assert_cmpstr (exif->gps_direction, ==, "12.3"); // -n -Exif:GPSImgDirection=12.3 - - tracker_exif_free (exif); -} - -static void -test_exif_parse_empty (void) -{ - TrackerExifData *exif; - gchar *blob; - gsize length; - - g_assert (g_file_get_contents (TOP_SRCDIR "/tests/libtracker-extract/exif-free-img.jpg", &blob, &length, NULL)); - - exif = tracker_exif_new ((guchar *)blob, length, "test://file"); - - tracker_exif_free (exif); -} - -int -main (int argc, char **argv) -{ - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/libtracker-extract/exif/parse", - test_exif_parse); - g_test_add_func ("/libtracker-extract/exif/parse_empty", - test_exif_parse_empty); - - return g_test_run (); -} diff --git a/tests/libtracker-extract/tracker-extract-info-test.c b/tests/libtracker-extract/tracker-extract-info-test.c deleted file mode 100644 index d189d44c3..000000000 --- a/tests/libtracker-extract/tracker-extract-info-test.c +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (C) 2011, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include <glib.h> - -#include <libtracker-extract/tracker-extract.h> - -static void -test_extract_info_setters (void) -{ - TrackerExtractInfo *info, *info_ref; - GFile *file; - - file = g_file_new_for_path ("./imaginary-file-2"); - - info = tracker_extract_info_new (file, "imaginary/mime"); - info_ref = tracker_extract_info_ref (info); - - g_assert (g_file_equal (file, tracker_extract_info_get_file (info))); - - g_assert_cmpstr (tracker_extract_info_get_mimetype (info), ==, "imaginary/mime"); - - tracker_extract_info_unref (info_ref); - tracker_extract_info_unref (info); - - g_object_unref (file); -} - -static void -test_extract_info_empty_objects (void) -{ - TrackerExtractInfo *info, *info_ref; - GFile *file; - - file = g_file_new_for_path ("./imaginary-file"); - - info = tracker_extract_info_new (file, "imaginary/mime"); - info_ref = tracker_extract_info_ref (info); - - tracker_extract_info_unref (info_ref); - tracker_extract_info_unref (info); - - g_object_unref (file); -} - -int -main (int argc, char **argv) -{ - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/libtracker-extract/extract-info/empty_objects", - test_extract_info_empty_objects); - g_test_add_func ("/libtracker-extract/extract-info/setters", - test_extract_info_setters); - - return g_test_run (); -} diff --git a/tests/libtracker-extract/tracker-guarantee-test.c b/tests/libtracker-extract/tracker-guarantee-test.c deleted file mode 100644 index b296d39de..000000000 --- a/tests/libtracker-extract/tracker-guarantee-test.c +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2011, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ -#include "config.h" - -#include <locale.h> - -#include <glib.h> - -#include <libtracker-sparql/tracker-sparql.h> -#include <libtracker-extract/tracker-guarantee.h> - -typedef struct { - const gchar *test_name; - gchar *uri; - const gchar *extracted; - const gchar *expected; - TrackerResource *resource; -} TestInfo; - -TestInfo title_tests [] = { - { "normal-extraction", "file:///a/b/a_video_with_metadata.avi", "extracted title", "extracted title" }, - { "empty-extraction", "file:///a/b/a_video_with_no_metadata.avi", NULL, "a video with no metadata" }, - { "underscore-separators", "file:///a/b/a_video_with_no_metadata.avi", "", "a video with no metadata" }, - { "dot-separators", "file:///a/b/a.video.with.no.metadata.avi", NULL, "a.video.with.no.metadata" }, - { "no-extension", "file:///a/b/a video without extension", NULL, "a video without extension" }, - { "hidden-files", "file:///a/b/.hidden_file", NULL, "hidden file" }, - - { NULL, NULL, NULL } -}; - -TestInfo date_tests [] = { - { "date-normal", "file:///does/not/matter/here", NULL, "2011-10-10T12:13:14Z0300" }, - { "date-is-null", NULL, NULL, NULL }, - { "date-is-empty-string", NULL, NULL, NULL }, - { NULL, NULL, NULL } -}; - -static void -test_title (TestInfo *info, - gconstpointer context) -{ -#ifdef GUARANTEE_METADATA - gchar *title_guaranteed; - gboolean title_retrieved; - - title_retrieved = tracker_guarantee_resource_title_from_file (info->resource, "nie:title", info->extracted, info->uri, &title_guaranteed); - g_assert_true (title_retrieved); - - g_assert_cmpstr (tracker_resource_get_first_string (info->resource, "nie:title"), ==, info->expected); - g_assert_cmpstr (title_guaranteed, ==, info->expected); - - g_free (title_guaranteed); -#else /* GUARANTEE_METADATA */ - g_test_skip ("Not built with --enable-guarantee-metadata"); -#endif /* GUARANTEE_METADATA */ -} - -static void -test_date (TestInfo *info, - gconstpointer context) -{ -#ifdef GUARANTEE_METADATA - gboolean date_retrieved; - - date_retrieved = tracker_guarantee_resource_date_from_file_mtime (info->resource, "test:mtime", info->extracted, info->uri); - g_assert_true (date_retrieved); - - /* mtime can change in the file so we just check that the property is in the output */ - g_assert_nonnull (tracker_resource_get_first_string (info->resource, "test:mtime")); -#else /* GUARANTEE_METADATA */ - g_test_skip ("Not built with --enable-guarantee-metadata"); -#endif /* GUARANTEE_METADATA */ -} - -static void -setup (TestInfo *info, - gint i) -{ - info->resource = tracker_resource_new (NULL); - g_assert_nonnull (info->resource); - - if (strstr (info->test_name, "date")) { - GFile *f; - - f = g_file_new_for_path (TOP_SRCDIR "/tests/libtracker-extract/guarantee-mtime-test.txt"); - info->uri = g_file_get_uri (f); - g_object_unref (f); - } -} - -static void -setup_title (TestInfo *info, - gconstpointer context) -{ - gint i = GPOINTER_TO_INT (context); - - *info = title_tests[i]; - setup (info, i); -} - -static void -setup_date (TestInfo *info, - gconstpointer context) -{ - gint i = GPOINTER_TO_INT (context); - - *info = date_tests[i]; - setup (info, i); -} - -static void -teardown (TestInfo *info, - gconstpointer context) -{ - if (strstr (info->test_name, "date")) { - g_free (info->uri); - } - - g_object_unref (info->resource); -} - -int -main (int argc, char** argv) -{ - gint i; - - setlocale (LC_COLLATE, "en_US.utf8"); - - g_test_init (&argc, &argv, NULL); - - for (i = 0; title_tests[i].test_name != NULL; i++) { - gchar *testpath; - - testpath = g_strdup_printf ("/libtracker-extract/guarantee/title/%s", title_tests[i].test_name); - g_test_add (testpath, TestInfo, GINT_TO_POINTER(i), setup_title, test_title, teardown); - g_free (testpath); - } - - for (i = 0; date_tests[i].test_name != NULL; i++) { - gchar *testpath; - - testpath = g_strdup_printf ("/libtracker-extract/guarantee/date/%s", date_tests[i].test_name); - g_test_add (testpath, TestInfo, GINT_TO_POINTER(i), setup_date, test_date, teardown); - g_free (testpath); - } - - return g_test_run (); -} diff --git a/tests/libtracker-extract/tracker-iptc-test.c b/tests/libtracker-extract/tracker-iptc-test.c deleted file mode 100644 index 2306c08fd..000000000 --- a/tests/libtracker-extract/tracker-iptc-test.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2011, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <stdio.h> -#include <string.h> -#include <setjmp.h> - -#include <jpeglib.h> - -#include <glib.h> -#include <gio/gio.h> -#include <libtracker-extract/tracker-iptc.h> - -#define PS3_NAMESPACE "Photoshop 3.0\0" -#define PS3_NAMESPACE_LENGTH 14 -#include <libiptcdata/iptc-jpeg.h> - -struct tej_error_mgr { - struct jpeg_error_mgr jpeg; - jmp_buf setjmp_buffer; -}; - - -static void -extract_jpeg_error_exit (j_common_ptr cinfo) -{ - struct tej_error_mgr *h = (struct tej_error_mgr *) cinfo->err; - (*cinfo->err->output_message)(cinfo); - longjmp (h->setjmp_buffer, 1); -} - -/* - * libiptcdata doesn't scan the file until find the IPTC blob. - * We need to find the blob ourselves. This code comes from tracker-extract-jpeg - */ -static TrackerIptcData * -load_iptc_blob (const gchar *filename) -{ - struct jpeg_decompress_struct cinfo; - struct tej_error_mgr tejerr; - struct jpeg_marker_struct *marker; - TrackerIptcData *id = NULL; - FILE *f; - gchar *uri; - GFile *file; - - file = g_file_new_for_path (filename); - uri = g_file_get_uri (file); - g_object_unref (file); - - f = fopen (filename, "r"); - - cinfo.err = jpeg_std_error (&tejerr.jpeg); - tejerr.jpeg.error_exit = extract_jpeg_error_exit; - if (setjmp (tejerr.setjmp_buffer)) { - fclose (f); - g_free (uri); - return NULL; - } - - jpeg_create_decompress (&cinfo); - - jpeg_save_markers (&cinfo, JPEG_COM, 0xFFFF); - jpeg_save_markers (&cinfo, JPEG_APP0 + 1, 0xFFFF); - jpeg_save_markers (&cinfo, JPEG_APP0 + 13, 0xFFFF); - - jpeg_stdio_src (&cinfo, f); - - jpeg_read_header (&cinfo, TRUE); - - marker = (struct jpeg_marker_struct *) &cinfo.marker_list; - - while (marker) { - gchar *str; - gsize len; - gint offset; - guint sublen; - - switch (marker->marker) { - case JPEG_COM: - break; - - case JPEG_APP0 + 1: - break; - - case JPEG_APP0 + 13: - str = (gchar*) marker->data; - len = marker->data_length; - if (len > 0 && strncmp (PS3_NAMESPACE, str, PS3_NAMESPACE_LENGTH) == 0) { - offset = iptc_jpeg_ps3_find_iptc ((guchar *)str, len, &sublen); - if (offset > 0 && sublen > 0) { - id = tracker_iptc_new ((const guchar *)str + offset, sublen, uri); - } - } - break; - - default: - marker = marker->next; - continue; - } - - marker = marker->next; - } - - g_free (uri); - fclose (f); - - return id; -} - -static void -test_iptc_extraction (void) -{ - TrackerIptcData *data; - - data = load_iptc_blob (TOP_SRCDIR "/tests/libtracker-extract/iptc-img.jpg"); - g_assert (data); - - g_assert_cmpstr (data->keywords, ==, "Coverage, test"); - g_assert (g_str_has_prefix (data->date_created, "2011-10-22")); - g_assert_cmpstr (data->byline, ==, "BylineValue"); - g_assert_cmpstr (data->byline_title, ==, "BylineTitleValue"); - g_assert_cmpstr (data->credit, ==, "CreditValue"); - g_assert_cmpstr (data->copyright_notice, ==, "IptcToolAuthors"); - g_assert_cmpstr (data->image_orientation, ==, "nfo:orientation-left"); - g_assert_cmpstr (data->city, ==, "Helsinki"); - g_assert_cmpstr (data->state, ==, "N/A"); - g_assert_cmpstr (data->sublocation, ==, "Ruoholahti"); - g_assert_cmpstr (data->country_name, ==, "Finland"); - g_assert_cmpstr (data->contact, ==, "Dilbert"); - - tracker_iptc_free (data); -} - -int -main (int argc, char **argv) -{ - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/libtracker-extract/iptc/extraction", - test_iptc_extraction); - return g_test_run (); -} diff --git a/tests/libtracker-extract/tracker-test-utils.c b/tests/libtracker-extract/tracker-test-utils.c deleted file mode 100644 index 33cd685d8..000000000 --- a/tests/libtracker-extract/tracker-test-utils.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright (C) 2009, Nokia <ivan.frade@nokia.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - * Authors: Philip Van Hoof <philip@codeminded.be> - */ - -#include "config.h" - -#include <time.h> -#include <string.h> - -#include <glib-object.h> - -#include <libtracker-extract/tracker-extract.h> - -static void -test_guess_date_failures_subprocess () -{ - gchar *result; - - result = tracker_date_guess (NULL); - g_free (result); -} - -static void -test_guess_date_failures () -{ - g_test_trap_subprocess ("/libtracker-extract/tracker-utils/guess_date_failures/subprocess", 0, G_TEST_SUBPROCESS_INHERIT_STDERR); - g_test_trap_assert_passed (); - - /* Should be NO output when using NULL with tracker_date_guess() */ -} - -static void -test_guess_date (void) -{ - gchar *result; - - result = tracker_date_guess (""); - g_assert (result == NULL); - - result = tracker_date_guess ("2008-06-14"); - g_assert_cmpstr (result, ==, "2008-06-14T00:00:00"); - g_free (result); - - result = tracker_date_guess ("20080614000000"); - g_assert_cmpstr (result, ==, "2008-06-14T00:00:00"); - g_free (result); - - result = tracker_date_guess ("20080614000000Z"); - g_assert_cmpstr (result, ==, "2008-06-14T00:00:00Z"); - g_free (result); - - result = tracker_date_guess ("Mon Jun 14 04:20:20 2008"); /* MS Office */ - g_assert_cmpstr (result, ==, "2008-06-14T04:20:20"); - g_free (result); - - result = tracker_date_guess ("2008:06:14 04:20:20"); /* Exif style */ - g_assert_cmpstr (result, ==, "2008-06-14T04:20:20"); - g_free (result); - - result = tracker_date_guess ("2010"); - g_assert_cmpstr (result, ==, "2010-01-01T00:00:00Z"); - g_free (result); - - result = tracker_date_guess ("201a"); - g_assert (!result); - - result = tracker_date_guess ("A2010"); - g_assert (!result); - - /* Guessing from the code */ - result = tracker_date_guess ("20100318010203-00:03Z"); - g_assert_cmpstr (result, ==, "2010-03-18T01:02:03-00:03"); - g_free (result); - - result = tracker_date_guess ("20100318010203+00:03Z"); - g_assert_cmpstr (result, ==, "2010-03-18T01:02:03+00:03"); - g_free (result); - - /* "YYYY-MM-DDThh:mm:ss.ff+zz:zz" */ - result = tracker_date_guess ("2010-03-18T01:02:03.10-00:03"); - g_assert_cmpstr (result, ==, "2010-03-18T01:02:03.10-00:03"); - g_free (result); - - result = tracker_date_guess ("2010-03-18T01:02:03.100"); - g_assert_cmpstr (result, ==, "2010-03-18T01:02:03.100"); - g_free (result); -} - -static void -test_text_validate_utf8 () -{ - GString *s = NULL; - gsize utf8_len = 0; - gint i; - gboolean result; - const gchar *valid_utf8[] = { - "GNU's not Unix", - "abcdefghijklmnopqrstuvwxyz0123456789?!,.-_", - "\xF0\x90\x80\x80", - "\x41" "\xCE\xA9" "\xE8\xAA\x9E" "\xF0\x90\x8E\x84", - NULL - }; - - /* If text is empty, FALSE should be returned */ - result = tracker_text_validate_utf8 ("", 0, NULL, NULL); - g_assert_cmpuint (result, ==, 0); - - /* If a fully valid UTF-8 string is given as input, output - * length should be equal to the input length, and the - * output GString should contain exactly the same contents - * as the input */ - for (i = 0; valid_utf8[i] != NULL; i++) { - s = NULL; - utf8_len = 0; - result = tracker_text_validate_utf8 (valid_utf8[i], - strlen (valid_utf8[i]), - &s, - &utf8_len); - g_assert_cmpuint (result, ==, 1); - g_assert_cmpuint (utf8_len, ==, strlen (valid_utf8[i])); - g_assert (s); - g_assert_cmpuint (s->len, ==, strlen (valid_utf8[i])); - g_assert_cmpstr (s->str, ==, valid_utf8[i]); - g_string_free (s, TRUE); - } - - /* Same as previous, passing -1 as input text length */ - for (i = 0; valid_utf8[i] != NULL; i++) { - s = NULL; - utf8_len = 0; - result = tracker_text_validate_utf8 (valid_utf8[i], - -1, - &s, - &utf8_len); - g_assert_cmpuint (result, ==, 1); - g_assert_cmpuint (utf8_len, ==, strlen (valid_utf8[i])); - g_assert (s); - g_assert_cmpuint (s->len, ==, strlen (valid_utf8[i])); - g_assert_cmpstr (s->str, ==, valid_utf8[i]); - g_string_free (s, TRUE); - } - - /* Same as previous, only wanting output text */ - for (i = 0; valid_utf8[i] != NULL; i++) { - s = NULL; - result = tracker_text_validate_utf8 (valid_utf8[i], - -1, - &s, - NULL); - g_assert_cmpuint (result, ==, 1); - g_assert (s); - g_assert_cmpuint (s->len, ==, strlen (valid_utf8[i])); - g_assert_cmpstr (s->str, ==, valid_utf8[i]); - g_string_free (s, TRUE); - } - - /* Same as previous, only wanting number of valid UTF-8 bytes */ - for (i = 0; valid_utf8[i] != NULL; i++) { - utf8_len = 0; - result = tracker_text_validate_utf8 (valid_utf8[i], - -1, - NULL, - &utf8_len); - g_assert_cmpuint (result, ==, 1); - g_assert_cmpuint (utf8_len, ==, strlen (valid_utf8[i])); - } - - /* If the input string starts with non-valid UTF-8 already, FALSE - * should be returned */ - result = tracker_text_validate_utf8 ("\xF0\x90\x80" "a", -1, NULL, NULL); - g_assert_cmpuint (result, ==, 0); - - /* If the input string suddenly has some non-valid UTF-8 bytes, - * TRUE should be returned, and the outputs should contain only info - * about the valid first chunk of UTF-8 bytes */ - s = NULL; - utf8_len = 0; - result = tracker_text_validate_utf8 ("abcdefghijk" "\xF0\x90\x80" "a", - -1, - &s, - &utf8_len); - g_assert_cmpuint (result, ==, 1); - g_assert_cmpuint (utf8_len, ==, strlen ("abcdefghijk")); - g_assert (s); - g_assert_cmpuint (s->len, ==, strlen ("abcdefghijk")); - g_assert_cmpstr (s->str, ==, "abcdefghijk"); - g_string_free (s, TRUE); -} - -static void -test_date_to_iso8601 () -{ - /* Not much to test here because it uses strptime/strftime */ - gchar *result; - - result = tracker_date_format_to_iso8601 ("2010:03:13 12:12:12", "%Y:%m:%d %H:%M:%S"); - g_assert (g_str_has_prefix (result, "2010-03-13T12:12:12")); - g_assert_cmpint (strlen (result), <=, 25); - - /* Pattern and string don't match */ - result = tracker_date_format_to_iso8601 ("2010:03:13 12:12", "%Y:%m:%d %H:%M:%S"); - g_assert (result == NULL); -} - -static void -test_coalesce_strip () -{ - /* Used in other tests, but this one can try some corner cases */ - g_assert (!tracker_coalesce_strip (0, NULL)); - - /* Allocate, do not use constant strings */ - char *e = g_strdup (""); - char *a = g_strdup ("a"); - g_assert_cmpstr (tracker_coalesce_strip (2, e, a, NULL), ==, "a"); - g_free (e); - g_free (a); -} - -static void -test_merge_const () -{ - gchar *result; - - result = tracker_merge_const ("*", 3, "a", "b", NULL); - g_assert_cmpstr (result, ==, "a*b"); - g_free (result); - - result = tracker_merge_const ("****", 3, "a", "b", NULL); - g_assert_cmpstr (result, ==, "a****b"); - g_free (result); - - result = tracker_merge_const (NULL, 3, "a", "b", NULL); - g_assert_cmpstr (result, ==, "ab"); - g_free (result); - - result = tracker_merge_const ("", 3, "a", "b", NULL); - g_assert_cmpstr (result, ==, "ab"); - g_free (result); - - result = tracker_merge_const ("*", 0, NULL); - g_assert (!result); -} - -static void -test_getline (void) -{ - FILE *f; - gchar *line = NULL; - gsize n = 0; - - f = fopen (TOP_SRCDIR "/tests/libtracker-extract/getline-test.txt", "r"); - g_assert_cmpint (tracker_getline (&line, &n, f), >, 0); - g_assert_cmpstr (line, ==, "Line 1\n"); - - g_assert_cmpint (tracker_getline (&line, &n, f), >, 0); - g_assert_cmpstr (line, ==, "line 2\n"); - - g_assert_cmpint (tracker_getline (&line, &n, f), >, 0); - g_assert_cmpstr (line, ==, "line 3\n"); -} - -int -main (int argc, char **argv) -{ - gint result; - - g_test_init (&argc, &argv, NULL); - - g_test_add_func ("/libtracker-extract/tracker-utils/guess_date", - test_guess_date); - g_test_add_func ("/libtracker-extract/tracker-utils/guess_date_failures", - test_guess_date_failures); - g_test_add_func ("/libtracker-extract/tracker-utils/guess_date_failures/subprocess", - test_guess_date_failures_subprocess); - g_test_add_func ("/libtracker-extract/tracker-utils/text-validate-utf8", - test_text_validate_utf8); - g_test_add_func ("/libtracker-extract/tracker-utils/date_to_iso8601", - test_date_to_iso8601); - g_test_add_func ("/libtracker-extract/tracker-utils/coalesce_strip", - test_coalesce_strip); - g_test_add_func ("/libtracker-extract/tracker-utils/merge_const", - test_merge_const); - g_test_add_func ("/libtracker-extract/tracker-utils/getline", - test_getline); - result = g_test_run (); - - return result; -} diff --git a/tests/libtracker-extract/tracker-test-xmp.c b/tests/libtracker-extract/tracker-test-xmp.c deleted file mode 100644 index 0cf7afcc2..000000000 --- a/tests/libtracker-extract/tracker-test-xmp.c +++ /dev/null @@ -1,588 +0,0 @@ -/* - * Copyright (C) 2010, Nokia <ivan.frade@nokia.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library 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 library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "config.h" - -#include <glib-object.h> - -#include <libtracker-extract/tracker-extract.h> - -#define BROKEN_XMP "This is not even XML" -#define EXAMPLE_XMP \ -" <x:xmpmeta " \ -" xmlns:x=\'adobe:ns:meta/\'" \ -" xmlns:dc=\"http://purl.org/dc/elements/1.1/\"" \ -" xmlns:xmp=\"http://ns.adobe.com/xap/1.0/\"" \ -" xmlns:exif=\"http://ns.adobe.com/exif/1.0/\"" \ -" xmlns:tiff=\"http://ns.adobe.com/tiff/1.0/\">" \ -" <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">" \ -" <rdf:Description rdf:about=\"\">" \ -" <dc:format>application/pdf</dc:format>" \ -" <dc:title>Title of the content</dc:title>" \ -" <dc:rights>CC share alike</dc:rights> " \ -" <dc:description>Description of the content</dc:description>" \ -" <dc:date>2010-03-18T15:17:04Z</dc:date>" \ -" <dc:keywords>test, data, xmp</dc:keywords>" \ -" <dc:subject>Subject of the content</dc:subject>" \ -" <dc:publisher>A honest developer</dc:publisher>" \ -" <dc:contributor>A honest contributor</dc:contributor>" \ -" <dc:type>PhysicalObject</dc:type>" \ -" <dc:identifier>12345</dc:identifier>" \ -" <dc:source>My dirty mind</dc:source>" \ -" <dc:language>Spanglish</dc:language>" \ -" <dc:relation>Single</dc:relation>" \ -" <dc:coverage>Pretty high after this test</dc:coverage>" \ -" <dc:creator>The ultimate creator</dc:creator>" \ -" <exif:Title>Title in exif</exif:Title>" \ -" <exif:DateTimeOriginal>2010-03-18T15:17:04Z</exif:DateTimeOriginal>" \ -" <exif:Artist>Artist in exif</exif:Artist>" \ -" <exif:Make>Make in exif</exif:Make>" \ -" <exif:Model>Model in exif</exif:Model>" \ -" <exif:Flash>0</exif:Flash>" \ -" <exif:MeteringMode>3</exif:MeteringMode>" \ -" <exif:ExposureTime>1000</exif:ExposureTime>" \ -" <exif:FNumber>12</exif:FNumber>" \ -" <exif:FocalLength>50</exif:FocalLength>" \ -" <exif:ISOSpeedRatings>400</exif:ISOSpeedRatings>" \ -" <exif:WhiteBalance>1</exif:WhiteBalance>" \ -" <exif:Copyright>Copyright in exif</exif:Copyright>" \ -" <tiff:Orientation>1</tiff:Orientation>" \ -" <xmp:CreateDate>2002-08-15T17:10:04Z</xmp:CreateDate>" \ -" </rdf:Description> " \ -" </rdf:RDF> " \ -" </x:xmpmeta>" - -#define METERING_MODE_XMP \ -" <x:xmpmeta " \ -" xmlns:x=\'adobe:ns:meta/\'" \ -" xmlns:exif=\"http://ns.adobe.com/exif/1.0/\">" \ -" <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">" \ -" <rdf:Description rdf:about=\"\">" \ -" <exif:MeteringMode>%d</exif:MeteringMode>" \ -" </rdf:Description>" \ -" </rdf:RDF></x:xmpmeta> " - -#define ORIENTATION_XMP \ -" <x:xmpmeta " \ -" xmlns:x=\'adobe:ns:meta/\'" \ -" xmlns:tiff=\"http://ns.adobe.com/tiff/1.0/\">" \ -" <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">" \ -" <rdf:Description rdf:about=\"\">" \ -" <tiff:Orientation>%s</tiff:Orientation>" \ -" </rdf:Description>" \ -" </rdf:RDF></x:xmpmeta> " - - -typedef struct { - const gchar *exif_value; - const gchar *nepomuk_translation; -} ExifNepomuk; - -static ExifNepomuk METERING_MODES [] = { - {"0", "nmm:metering-mode-other"}, - {"1", "nmm:metering-mode-average"}, - {"2", "nmm:metering-mode-center-weighted-average"}, - {"3", "nmm:metering-mode-spot"}, - {"4", "nmm:metering-mode-multispot"}, - {"5", "nmm:metering-mode-pattern"}, - {"6", "nmm:metering-mode-partial"}, - {NULL, NULL} -}; - -static ExifNepomuk ORIENTATIONS [] = { - {"2", "nfo:orientation-top-mirror"}, - {"3", "nfo:orientation-bottom"}, - {"4", "nfo:orientation-bottom-mirror"}, - {"5", "nfo:orientation-left-mirror"}, - {"6", "nfo:orientation-right"}, - {"7", "nfo:orientation-right-mirror"}, - {"8", "nfo:orientation-left"}, - {"invalid value", "nfo:orientation-top"} -}; - -static TrackerXmpData * -get_example_expected (void) -{ - TrackerXmpData *data; - - data = g_new0 (TrackerXmpData, 1); - - /* NS_DC */ - data->title = g_strdup ("Title of the content"); - data->rights = g_strdup ("CC share alike"); - data->creator = g_strdup ("The ultimate creator"); - data->description = g_strdup ("Description of the content"); - data->date = g_strdup ("2010-03-18T15:17:04Z"); - data->keywords = g_strdup ("test, data, xmp"); - data->subject = g_strdup ("Subject of the content"); - - data->publisher = g_strdup ("A honest developer"); /* publisher */ - data->contributor = g_strdup ("A honest contributor"); - data->type = NULL ; - data->format = g_strdup ("application/pdf"); - data->identifier = g_strdup ("12345"); - data->source = g_strdup ("My dirty mind"); - data->language = g_strdup ("Spanglish"); - data->relation = g_strdup ("Single"); - data->coverage = g_strdup ("Pretty high after this test"); - - /* NS_CC */ - data->license = NULL; - - /* NS_PDF */ - data->pdf_title = NULL; - data->pdf_keywords = NULL; - - /* NS_EXIF*/ - data->title2 = g_strdup ("Title in exif"); - data->time_original = g_strdup ("2010-03-18T15:17:04Z"); - data->artist = g_strdup ("Artist in exif"); - data->make = g_strdup ("Make in exif"); - data->model = g_strdup ("Model in exif"); - data->orientation = g_strdup ("nfo:orientation-top"); - data->flash = g_strdup ("nmm:flash-off"); - data->metering_mode = g_strdup ("nmm:metering-mode-spot"); - data->exposure_time = g_strdup ("1000"); /* exposure time */ - data->fnumber = g_strdup ("12"); /* fnumber */ - data->focal_length = g_strdup ("50"); /* focal length */ - - data->iso_speed_ratings = g_strdup ("400"); /* iso speed rating */ - data->white_balance = g_strdup ("nmm:white-balance-manual"); - data->copyright = g_strdup ("Copyright in exif"); - - /* NS_XAP */ - data->rating = NULL; - - /* NS_IPTC4XMP */ - /* NS_PHOTOSHOP */ - data->address = NULL; /* address */ - data->country = NULL; /* country */ - data->state = NULL; /* state */ - data->city = NULL; /* city */ - - return data; -}; - -static void -test_parsing_xmp_invalid_file_subprocess (void) -{ - TrackerXmpData *data; - - data = tracker_xmp_new (BROKEN_XMP, strlen (BROKEN_XMP), "test://file"); - g_assert (data != NULL); - - tracker_xmp_free (data); -} - -static void -test_parsing_xmp_invalid_file (void) -{ - g_test_trap_subprocess ("/libtracker-extract/tracker-xmp/parsing_xmp_invalid_file/subprocess", 0, 0); - g_test_trap_assert_passed (); - g_test_trap_assert_stderr ("*parsing failure*"); -} - -static void -test_parsing_xmp (void) -{ - TrackerXmpData *data; - TrackerXmpData *expected; - - data = tracker_xmp_new (EXAMPLE_XMP, strlen (EXAMPLE_XMP), "test://file"); - expected = get_example_expected (); - - /* NS_DC */ - g_assert_cmpstr (data->format, ==, expected->format); - g_assert_cmpstr (data->title, ==, expected->title); - g_assert_cmpstr (data->rights, ==, expected->rights); - g_assert_cmpstr (data->description, ==, expected->description); - g_assert_cmpstr (data->date, ==, expected->date); - g_assert_cmpstr (data->keywords, ==, expected->keywords); - g_assert_cmpstr (data->subject, ==, expected->subject); - g_assert_cmpstr (data->publisher, ==, expected->publisher); - g_assert_cmpstr (data->contributor, ==, expected->contributor); - g_assert_cmpstr (data->identifier, ==, expected->identifier); - g_assert_cmpstr (data->source, ==, expected->source); - g_assert_cmpstr (data->language, ==, expected->language); - g_assert_cmpstr (data->relation, ==, expected->relation); - g_assert_cmpstr (data->coverage, ==, expected->coverage); - g_assert_cmpstr (data->creator, ==, expected->creator); - - /* NS_EXIF*/ - g_assert_cmpstr (data->title2, ==, expected->title2); - g_assert_cmpstr (data->time_original, ==, expected->time_original); - g_assert_cmpstr (data->artist, ==, expected->artist); - g_assert_cmpstr (data->make, ==, expected->make); - g_assert_cmpstr (data->model, ==, expected->model); - g_assert_cmpstr (data->orientation, ==, expected->orientation); - g_assert_cmpstr (data->flash, ==, expected->flash); - g_assert_cmpstr (data->metering_mode, ==, expected->metering_mode); - g_assert_cmpstr (data->exposure_time, ==, expected->exposure_time); - g_assert_cmpstr (data->fnumber, ==, expected->fnumber); - g_assert_cmpstr (data->focal_length, ==, expected->focal_length); - - g_assert_cmpstr (data->iso_speed_ratings, ==, expected->iso_speed_ratings); - g_assert_cmpstr (data->white_balance, ==, expected->white_balance); - g_assert_cmpstr (data->copyright, ==, expected->copyright); - - tracker_xmp_free (expected); - tracker_xmp_free (data); -} - -static void -test_xmp_metering_mode (void) -{ - gint i; - - for (i = 0; METERING_MODES[i].exif_value != NULL; i++) { - TrackerXmpData *data; - gchar *xmp; - - xmp = g_strdup_printf (METERING_MODE_XMP, i); - data = tracker_xmp_new (xmp, strlen (xmp), "local://file"); - g_free (xmp); - - g_assert_cmpstr (data->metering_mode, ==, METERING_MODES[i].nepomuk_translation); - tracker_xmp_free (data); - } -} - -static void -test_xmp_orientation (void) -{ - guint i; - - for (i = 0; i < G_N_ELEMENTS (ORIENTATIONS); i++) { - TrackerXmpData *data; - gchar *xmp; - - xmp = g_strdup_printf (ORIENTATION_XMP, ORIENTATIONS[i].exif_value); - data = tracker_xmp_new (xmp, strlen (xmp), "local://file"); - g_free (xmp); - - g_assert_cmpstr (data->orientation, ==, ORIENTATIONS[i].nepomuk_translation); - tracker_xmp_free (data); - } -} - -static void -test_xmp_apply (void) -{ - TrackerResource *resource; - TrackerResource *artist; - TrackerXmpData *data; - - resource = tracker_resource_new ("urn:uuid:test"); - - data = tracker_xmp_new (EXAMPLE_XMP, strlen (EXAMPLE_XMP), "urn:uuid:test"); - g_assert (data != NULL); - - g_assert (tracker_xmp_apply_to_resource (resource, data)); - - /* We just check a few of the properties at random. */ - g_assert_cmpstr (tracker_resource_get_first_string (resource, "nie:description"), ==, - "Description of the content"); - - artist = tracker_resource_get_first_relation (resource, "nco:contributor"); - g_assert_cmpstr (tracker_resource_get_first_string(artist, "nco:fullname"), ==, - "Artist in exif"); - - tracker_xmp_free (data); -} - -static void -test_xmp_apply_location (void) -{ - TrackerXmpData data = { 0, }; - TrackerResource *resource, *location, *address; - - data.address = g_strdup ("Itamerenkatu 11-13"); - data.city = g_strdup ("Helsinki"); - data.state = g_strdup ("N/A"); - data.country = g_strdup ("Findland"); - - resource = tracker_resource_new ("urn:uuid:test"); - - g_assert (tracker_xmp_apply_to_resource (resource, &data)); - - location = tracker_resource_get_first_relation (resource, "slo:location"); - address = tracker_resource_get_first_relation (location, "slo:postalAddress"); - - g_assert_cmpstr (tracker_resource_get_first_string (address, "nco:streetAddress"), ==, data.address); - g_assert_cmpstr (tracker_resource_get_first_string (address, "nco:region"), ==, data.state); - g_assert_cmpstr (tracker_resource_get_first_string (address, "nco:locality"), ==, data.city); - g_assert_cmpstr (tracker_resource_get_first_string (address, "nco:country"), ==, data.country); -} - - -static void -test_xmp_regions (void) -{ - TrackerXmpData *data; - TrackerXmpRegion *region; - - GFile *f; - gchar *contents; - gsize size; - gchar *filepath; - - filepath = g_build_filename (TOP_SRCDIR, "tests", "libtracker-extract", "areas.xmp", NULL); - f = g_file_new_for_path (filepath); - g_assert (g_file_load_contents (f, NULL, &contents, &size, NULL, NULL)); - g_object_unref (f); - g_free (filepath); - - data = tracker_xmp_new (contents, size, "test://file"); - - g_free (contents); - - g_assert_cmpint (2, ==, g_slist_length (data->regions)); - - region = g_slist_nth_data (data->regions, 1); - g_assert_cmpstr (region->x, ==, "0.51"); - g_assert_cmpstr (region->y, ==, "0.51"); - g_assert_cmpstr (region->width, ==, "0.01"); - g_assert_cmpstr (region->height, ==, "0.09"); - g_assert_cmpstr (region->type, ==, "Pet"); - g_assert_cmpstr (region->title, ==, "Fido"); - g_assert_cmpstr (region->description, ==, "Fido looks happy!"); - - region = g_slist_nth_data (data->regions, 0); - g_assert_cmpstr (region->x, ==, "0.5"); - g_assert_cmpstr (region->y, ==, "0.5"); - g_assert_cmpstr (region->width, ==, "0.06"); - g_assert_cmpstr (region->height, ==, "0.09"); - g_assert_cmpstr (region->type, ==, "Face"); - g_assert_cmpstr (region->title, ==, "John Doe"); - - tracker_xmp_free (data); -} - -static void -test_xmp_regions_quill (void) -{ - TrackerXmpData *data; - TrackerXmpRegion *region; - - GFile *f; - gchar *contents; - gsize size; - gchar *filepath; - - filepath = g_build_filename (TOP_SRCDIR, "tests", "libtracker-extract", "areas-with-contacts.xmp", NULL); - f = g_file_new_for_path (filepath); - g_assert (g_file_load_contents (f, NULL, &contents, &size, NULL, NULL)); - g_object_unref (f); - g_free (filepath); - - data = tracker_xmp_new (contents, size, "test://file"); - - g_free (contents); - - g_assert_cmpint (2, ==, g_slist_length (data->regions)); - - region = g_slist_nth_data (data->regions, 1); - g_assert_cmpstr (region->x, ==, "0.4"); - g_assert_cmpstr (region->y, ==, "0.3"); - g_assert_cmpstr (region->width, ==, "0.17"); - g_assert_cmpstr (region->height, ==, "0.15"); - g_assert_cmpstr (region->type, ==, "Face"); - g_assert_cmpstr (region->title, ==, "Dilbert"); - g_assert_cmpstr (region->link_class, ==, "nco:PersonContact"); - g_assert_cmpstr (region->link_uri, ==, "urn:uuid:2"); - - region = g_slist_nth_data (data->regions, 0); - g_assert_cmpstr (region->x, ==, "0.3"); - g_assert_cmpstr (region->y, ==, "0.4"); - g_assert_cmpstr (region->width, ==, "0.15"); - g_assert_cmpstr (region->height, ==, "0.17"); - g_assert_cmpstr (region->type, ==, "Face"); - g_assert_cmpstr (region->title, ==, "Albert Einstein"); - g_assert_cmpstr (region->link_class, ==, "nco:PersonContact"); - g_assert_cmpstr (region->link_uri, ==, "urn:uuid:1"); - - tracker_xmp_free (data); -} - -static void -test_xmp_regions_ns_prefix (void) -{ - TrackerXmpData *data; - TrackerXmpRegion *region; - - GFile *f; - gchar *contents; - gsize size; - gchar *filepath; - - filepath = g_build_filename (TOP_SRCDIR, "tests", "libtracker-extract", "areas-ns.xmp", NULL); - f = g_file_new_for_path (filepath); - g_assert(g_file_load_contents (f, NULL, &contents, &size, NULL, NULL)); - g_object_unref (f); - g_free (filepath); - - data = tracker_xmp_new (contents, size, "test://file"); - - g_free (contents); - - g_assert_cmpint (2, ==, g_slist_length (data->regions)); - - region = g_slist_nth_data (data->regions, 1); - g_assert_cmpstr (region->x, ==, "0.51"); - g_assert_cmpstr (region->y, ==, "0.51"); - g_assert_cmpstr (region->width, ==, "0.01"); - g_assert_cmpstr (region->height, ==, "0.09"); - g_assert_cmpstr (region->type, ==, "Pet"); - g_assert_cmpstr (region->title, ==, "Fidoz"); - g_assert_cmpstr (region->description, ==, "Fido looks happy!"); - - region = g_slist_nth_data (data->regions, 0); - g_assert_cmpstr (region->x, ==, "0.5"); - g_assert_cmpstr (region->y, ==, "0.5"); - g_assert_cmpstr (region->width, ==, "0.06"); - g_assert_cmpstr (region->height, ==, "0.09"); - g_assert_cmpstr (region->type, ==, "Face"); - g_assert_cmpstr (region->title, ==, "Average Joe"); - - tracker_xmp_free (data); -} - -static void -test_xmp_regions_nb282393 () -{ - TrackerXmpData *data; - TrackerXmpRegion *region; - - GFile *f; - gchar *contents; - gsize size; - gchar *filepath; - - filepath = g_build_filename (TOP_SRCDIR, "tests", "libtracker-extract", "nb282393.xmp", NULL); - f = g_file_new_for_path (filepath); - g_assert(g_file_load_contents (f, NULL, &contents, &size, NULL, NULL)); - g_object_unref (f); - g_free (filepath); - - data = tracker_xmp_new (contents, size, "test://file"); - - g_free (contents); - - g_assert_cmpint (1, ==, g_slist_length (data->regions)); - - /* Regions are stacked while parsing.*/ - region = g_slist_nth_data (data->regions, 0); - g_assert_cmpstr (region->x, ==, "0.433333"); - g_assert_cmpstr (region->y, ==, "0.370000"); - g_assert_cmpstr (region->width, ==, "0.586667"); - g_assert_cmpstr (region->height, ==, "0.440000"); - g_assert_cmpstr (region->title, ==, " "); - - tracker_xmp_free (data); -} - -static void -test_xmp_regions_nb282393_2 () -{ - TrackerXmpData *data; - TrackerXmpRegion *region; - - GFile *f; - gchar *contents; - gsize size; - gchar *filepath; - - filepath = g_build_filename (TOP_SRCDIR, "tests", "libtracker-extract", "nb282393_simple.xmp", NULL); - f = g_file_new_for_path (filepath); - g_assert(g_file_load_contents (f, NULL, &contents, &size, NULL, NULL)); - g_object_unref (f); - g_free (filepath); - - data = tracker_xmp_new (contents, size, "test://file"); - - g_free (contents); - - g_assert_cmpint (1, ==, g_slist_length (data->regions)); - - /* Regions are stacked while parsing.*/ - region = g_slist_nth_data (data->regions, 0); - g_assert_cmpstr (region->x, ==, "0.440000"); - g_assert_cmpstr (region->y, ==, "0.365000"); - g_assert_cmpstr (region->width, ==, "0.586667"); - g_assert_cmpstr (region->height, ==, "0.440000"); - g_assert_cmpstr (region->title, ==, " "); - - g_assert_cmpstr (region->link_class, ==, "nco:PersonContact"); - g_assert_cmpstr (region->link_uri, ==, "urn:uuid:840a3c05-6cc6-48a1-bb56-fc50fae3345a"); - - tracker_xmp_free (data); -} - -int -main (int argc, - char **argv) -{ - gint result; - - g_test_init (&argc, &argv, NULL); - - g_test_message ("Testing XMP"); - -#ifdef HAVE_EXEMPI - - g_test_add_func ("/libtracker-extract/tracker-xmp/parsing_xmp", - test_parsing_xmp); - - g_test_add_func ("/libtracker-extract/tracker-xmp/parsing_xmp_invalid_file", - test_parsing_xmp_invalid_file); - g_test_add_func ("/libtracker-extract/tracker-xmp/parsing_xmp_invalid_file/subprocess", - test_parsing_xmp_invalid_file_subprocess); - - g_test_add_func ("/libtracker-extract/tracker-xmp/metering-mode", - test_xmp_metering_mode); - - g_test_add_func ("/libtracker-extract/tracker-xmp/orientation", - test_xmp_orientation); - - g_test_add_func ("/libtracker-extract/tracker-xmp/sparql_translation", - test_xmp_apply); - - g_test_add_func ("/libtracker-extract/tracker-xmp/xmp_regions", - test_xmp_regions); - - g_test_add_func ("/libtracker-extract/tracker-xmp/xmp_regions_2", - test_xmp_regions_quill); - - g_test_add_func ("/libtracker-extract/tracker-xmp/xmp_regions_crash_nb282393", - test_xmp_regions_nb282393); - - g_test_add_func ("/libtracker-extract/tracker-xmp/xmp_regions_crash_nb282393_2", - test_xmp_regions_nb282393_2); - - g_test_add_func ("/libtracker-extract/tracker-xmp/xmp_regions_ns_prefix", - test_xmp_regions_ns_prefix); - -#endif - g_test_add_func ("/libtracker-extract/tracker-xmp/sparql_translation_location", - test_xmp_apply_location); - - result = g_test_run (); - - return result; -} diff --git a/tests/meson.build b/tests/meson.build index 0730a1121..e3bdea8e8 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -4,10 +4,6 @@ subdir('gvdb') subdir('libtracker-common') subdir('libtracker-data') -if enable_extract - subdir('libtracker-extract') -endif - if enable_fts subdir('libtracker-fts') endif @@ -16,11 +12,6 @@ subdir('libtracker-miner') subdir('libtracker-sparql') subdir('tracker-steroids') -# The test case for writeback doesn't seem to work. -#if enable_writeback -# subdir('tracker-writeback') -#endif - if get_option('functional_tests') subdir('functional-tests') endif diff --git a/tests/tracker-writeback/01-writeback.py b/tests/tracker-writeback/01-writeback.py deleted file mode 100755 index 36713ec5b..000000000 --- a/tests/tracker-writeback/01-writeback.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python -# -# Copyright (C) 2009, Nokia <ivan.frade@nokia.com> -# -# This program is free software; you can redistribute it and/or -# modify it under the terms of the GNU General Public License -# as published by the Free Software Foundation; either version 2 -# of the License, or (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301, USA. -# - -import dbus -import unittest -import random -import os -import shutil -import re -import time -import commands - -TRACKER = 'org.freedesktop.Tracker1' -TRACKER_OBJ = '/org/freedesktop/Tracker1/Resources' -RESOURCES_IFACE = "org.freedesktop.Tracker1.Resources" - -class TestInsertion (unittest.TestCase): - - def setUp (self): - bus = dbus.SessionBus () - tracker = bus.get_object (TRACKER, TRACKER_OBJ) - self.resources = dbus.Interface (tracker, - dbus_interface=RESOURCES_IFACE); - - def test_simple_insertion (self): - try: - os.mkdir (os.getcwd() + "/tmp") - except: - print "" - - shutil.copy2 (os.getcwd() + "/data/test01.jpg", - os.getcwd() + "/tmp/test01.jpg") - - uri = "file://" + os.getcwd() + "/tmp/test01.jpg" - - insert = """INSERT { <%s> a nfo:Image, nmm:Photo, nfo:FileDataObject; - nie:isStoredAs <%s> ; - nie:url '%s' ; - nie:title 'test_title_1' ; - nco:creator [ a nco:Contact ; - nco:fullname 'test_fullname_1' ] ; - nie:description 'test_description_1' ; - nie:keyword 'test_keyword_1' ; - nie:keyword 'test_keyword_2' ; - nie:keyword 'test_keyword_3' ; - nie:contentCreated '2001-10-26T21:32:52' ; - nfo:orientation nfo:orientation-top-mirror ; - nmm:meteringMode nmm:metering-mode-average ; - nmm:whiteBalance nmm:white-balance-auto ; - nmm:flash nmm:flash-on ; - nmm:focalLength '1' ; - nmm:exposureTime '1' ; - nmm:isoSpeed '1' ; - nmm:fnumber '1' ; - nfo:equipment [ a nfo:Equipment ; nfo:model 'Some Test Model' ] ; - nco:contributor [ a nco:Contact ; - nco:fullname 'test_fullname_2' ] ; - nie:copyright 'test_copyright_1' - }""" % (uri, uri, uri) - - - self.resources.SparqlUpdate (insert) - - time.sleep (3) - - ret = os.system ("exiftool " + os.getcwd() + "/tmp/test01.jpg | grep test_title_1") - self.assertEqual (ret, 0) - - ret = os.system ("exiftool " + os.getcwd() + "/tmp/test01.jpg | grep test_fullname_1") - self.assertEqual (ret, 0) - - ret = os.system ("exiftool " + os.getcwd() + "/tmp/test01.jpg | grep test_description_1") - self.assertEqual (ret, 0) - - ret = os.system ("exiftool " + os.getcwd() + "/tmp/test01.jpg | grep test_keyword_1") - self.assertEqual (ret, 0) - - ret = os.system ("exiftool " + os.getcwd() + "/tmp/test01.jpg | grep test_keyword_2") - self.assertEqual (ret, 0) - - ret = os.system ("exiftool " + os.getcwd() + "/tmp/test01.jpg | grep test_keyword_3") - self.assertEqual (ret, 0) - -if __name__ == '__main__': - unittest.main() diff --git a/tests/tracker-writeback/Makefile.am b/tests/tracker-writeback/Makefile.am deleted file mode 100644 index e6256a7e3..000000000 --- a/tests/tracker-writeback/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -include $(top_srcdir)/Makefile.decl - -configdir = $(datadir)/tracker-tests - -config_SCRIPTS = \ - 01-writeback.py - -EXTRA_DIST += \ - $(config_SCRIPTS) diff --git a/tests/tracker-writeback/data/test01.jpg b/tests/tracker-writeback/data/test01.jpg Binary files differdeleted file mode 100644 index a62b7d4a0..000000000 --- a/tests/tracker-writeback/data/test01.jpg +++ /dev/null |