diff options
author | Carlos Garnacho <carlosg@gnome.org> | 2016-10-26 17:16:26 +0200 |
---|---|---|
committer | Carlos Garnacho <carlosg@gnome.org> | 2016-10-28 12:46:18 +0200 |
commit | fa7e5378af338ff3daa58daaf5655a33e07594ea (patch) | |
tree | 77ea2198149b4f27be6b59c04f672b4892a96141 | |
parent | 43813f3fab2413481d8b84b4b8f7261daaad8020 (diff) | |
download | tracker-fa7e5378af338ff3daa58daaf5655a33e07594ea.tar.gz |
*: Drop code not meant for this repo
This repo now contains the Tracker core: tracker-store and
all libraries.
383 files changed, 0 insertions, 60864 deletions
diff --git a/docs/manpages/tracker-miner-fs.1 b/docs/manpages/tracker-miner-fs.1 deleted file mode 100644 index 145d8f24d..000000000 --- a/docs/manpages/tracker-miner-fs.1 +++ /dev/null @@ -1,82 +0,0 @@ -.TH tracker-miner-fs 1 "September 2009" GNU "User Commands" - -.SH NAME -tracker-miner-fs \- Used to crawl the file system to mine data. - -.SH SYNOPSIS -\fBtracker-miner-fs\fR [\fIOPTION\fR...] - -.SH DESCRIPTION -.B tracker-miner-fs -is not supposed to be run by the user since it is started by -its .desktop file when the user logs in. It can also be started -manually of course for debugging purposes. You can not run more than -one instance of this at the same time. - -.B tracker-miner-fs -mines information about applications and files only. - -.SH OPTIONS -.TP -.B \-?, \-\-help -Show summary of options. -.TP -.B \-V, \-\-version -Returns the version of this binary. -.TP -.B \-v, \-\-verbosity={0|1|2|3} -Sets the logging level, 0=errors, 1=minimal, 2=detailed, 3=debug. -.TP -.B \-s, \-\-initial-sleep=SECONDS -Sets the initial sleep time before crawling the file system is -started. If the -.B \-\-no-daemon -option is used, this option is ignored. -.TP -.B \-n, \-\-no-daemon -Tells the miner to exit once all indexing has finished and the -database is up to date. This is not the default mode of operation for -the miner, usually it stays around acting like a daemon to monitor -file updates which may occur over time. This option renders the -.B \-\-initial-sleep -option moot. -.TP -.B \-e, \-\-eligible=FILE -Checks if -.B FILE -is eligible for being mined based on the current -configuration rules. In addition to this, it will check if -.B FILE -would be monitored for changes. This works with non-existing -.B FILE -arguments as well as existing -.B FILE -arguments. -.TP -.B \-d, \-\-disable-miner=MINER -Tells the daemon to disable the in-house miners it supports. Depending -on build options, this can be 'Files', 'Applications' -and 'Userguides'. This option can be provided more than once to -diasable multiple miners. Disable in this case means the miner is not -started, though all miners still register themselves on D-Bus and -appear there, no actual action is performed otherwise (such as -crawling, setting up monitors, or checking mtimes against the -file system). - -.SH ENVIRONMENT -.TP -.B TRACKER_USE_LOG_FILES -Don't just log to stdout and stderr, but to log files too which are -kept in $HOME/.local/share/tracker/. This came into effect in 0.15.3 -and 0.16.0. After this version of Tracker, logging to file (usually -useful for debugging) can only be done by declaring this environment -variable. -.TP -.B TRACKER_USE_CONFIG_FILES -Don't use GSettings, instead use a config file similar to how settings -were saved in 0.10.x. That is, a file which is much like an .ini file. -These are saved to $HOME/.config/tracker/ - -.SH SEE ALSO -.BR tracker-store (1), -.BR tracker-info (1). diff --git a/docs/manpages/tracker-writeback.1 b/docs/manpages/tracker-writeback.1 deleted file mode 100644 index 2d2a8a879..000000000 --- a/docs/manpages/tracker-writeback.1 +++ /dev/null @@ -1,44 +0,0 @@ -.TH tracker-writeback 1 "July 2011" GNU "User Commands" - -.SH NAME -tracker-writeback \- Used to write metadata set in Tracker back to -physical files. - -.SH SYNOPSIS -\fBtracker-writeback\fR [\fIOPTION\fR...] - -.SH DESCRIPTION -.B tracker-writeback -is not supposed to be run by the user since it is started by -its .desktop file when the user logs in. It can also be started -manually of course for debugging purposes. You can not run more than -one instance of this at the same time. - -.B tracker-writeback -writes metadata from the Tracker database back into files only. -Currently support is limited to XMP metadata (which covers PNG, JPEG, -TIFF, MP4 and 3GPP formats), play lists (which covers MPEGURL, SCPLS -and IRIVER formats) and taglib supported mime types (which covers MP3, -MP4, OGG, WAV, FLAC and some Windows media formats). - -Data is only written back if write-back is enabled in the -tracker-miner-fs configuration. - -.SH OPTIONS -.TP -.B \-?, \-\-help -Show summary of options. -.TP -.B \-V, \-\-version -Returns the version of this binary. -.TP -.B \-v, \-\-verbosity={0|1|2|3} -Sets the logging level, 0=errors, 1=minimal, 2=detailed, 3=debug. -.TP -.B \-d, \-\-disable-shutdown -Disable shutting down after 30 seconds of inactivity. - -.SH SEE ALSO -.BR tracker-store (1), -.BR tracker-miner-fs (1). -.BR tracker-extract (1). diff --git a/src/libtracker-extract/Makefile.am b/src/libtracker-extract/Makefile.am deleted file mode 100644 index 2c1d1fc3b..000000000 --- a/src/libtracker-extract/Makefile.am +++ /dev/null @@ -1,73 +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_MEEGOTOUCH -libtracker_extract_la_SOURCES += \ - tracker-encoding-meegotouch.cpp \ - tracker-encoding-meegotouch.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 diff --git a/src/libtracker-extract/tracker-data.h b/src/libtracker-extract/tracker-data.h deleted file mode 100644 index 05b00dbc1..000000000 --- a/src/libtracker-extract/tracker-data.h +++ /dev/null @@ -1,96 +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 (TrackerModuleThreadAwareness *thread_awareness_ret, - 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-meegotouch.cpp b/src/libtracker-extract/tracker-encoding-meegotouch.cpp deleted file mode 100644 index 6b881e735..000000000 --- a/src/libtracker-extract/tracker-encoding-meegotouch.cpp +++ /dev/null @@ -1,90 +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 <MCharsetDetector> -#include <MCharsetMatch> - -#include <glib.h> -#include <libtracker-common/tracker-locale.h> -#include "tracker-encoding-meegotouch.h" - -/* - * See http://apidocs.meego.com/git-tip/mtf/class_m_charset_detector.html - */ - -gchar * -tracker_encoding_guess_meegotouch (const gchar *buffer, - gsize size) -{ - /* Initialize detector */ - MCharsetDetector detector ((const char *)buffer, (int)size); - gchar *locale; - gchar *encoding = NULL; - - if (detector.hasError ()) { - g_warning ("Charset detector error when creating: %s", - detector.errorString ().toUtf8 (). data ()); - return NULL; - } - - locale = tracker_locale_get (TRACKER_LOCALE_LANGUAGE); - detector.setDeclaredLocale (locale); - - MCharsetMatch bestMatch = detector.detect (); - - if (detector.hasError ()) { - g_warning ("Charset detector error when detecting: %s", - detector.errorString ().toUtf8 (). data ()); - g_free (locale); - return NULL; - } - - if (bestMatch.confidence () > 30) { - encoding = g_strdup (bestMatch.name ().toUtf8 ().data ()); - -#if 0 - QList<MCharsetMatch> mCharsetMatchList = detector.detectAll(); - - if (detector.hasError ()) { - g_warning ("Charset detector error when detecting all: %s", - detector.errorString ().toUtf8 (). data ()); - } - - g_debug ("Detecting all charsets..."); - for (gint i = 0; i < mCharsetMatchList.size (); ++i) { - g_debug (" Charset '%s' with %d%% confidence...", - mCharsetMatchList[i].name (). toUtf8 ().data (), - mCharsetMatchList[i].confidence ()); - } -#endif - - g_debug ("Guessing charset as '%s' with %d%% confidence", - encoding, bestMatch.confidence ()); - } else { - g_debug ("Ignoring charset as '%s' with %d%% (< 30%%) confidence", - bestMatch.name ().toUtf8 ().data (), - bestMatch.confidence ()); - } - - g_free (locale); - - return encoding; -} diff --git a/src/libtracker-extract/tracker-encoding-meegotouch.h b/src/libtracker-extract/tracker-encoding-meegotouch.h deleted file mode 100644 index 6b6a9696d..000000000 --- a/src/libtracker-extract/tracker-encoding-meegotouch.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_MEEGOTOUCH_H__ -#define __LIBTRACKER_EXTRACT_ENCODING_MEEGOTOUCH_H__ - -#include <glib.h> - -G_BEGIN_DECLS - -G_GNUC_INTERNAL -gchar *tracker_encoding_guess_meegotouch (const gchar *buffer, - gsize size); - -G_END_DECLS - -#endif /* __LIBTRACKER_EXTRACT_ENCODING_MEEGOTOUCH_H__ */ diff --git a/src/libtracker-extract/tracker-encoding.c b/src/libtracker-extract/tracker-encoding.c deleted file mode 100644 index fe0b3429f..000000000 --- a/src/libtracker-extract/tracker-encoding.c +++ /dev/null @@ -1,76 +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_MEEGOTOUCH -#include "tracker-encoding-meegotouch.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_MEEGOTOUCH) || 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_MEEGOTOUCH - encoding = tracker_encoding_guess_meegotouch (buffer, size); -#endif /* HAVE_MEEGOTOUCH */ - -#ifdef HAVE_LIBICU_CHARSET_DETECTION - if (!encoding) - 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 90c2836f8..000000000 --- a/src/libtracker-extract/tracker-extract-info.c +++ /dev/null @@ -1,281 +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; - -#ifdef HAVE_LIBMEDIAART - MediaArtProcess *media_art_process; -#endif - - 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; - -#ifdef HAVE_LIBMEDIAART - info->media_art_process = NULL; -#endif - - 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); - -#ifdef HAVE_LIBMEDIAART - if (info->media_art_process) - g_object_unref (info->media_art_process); -#endif - - 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; -} - -#ifdef HAVE_LIBMEDIAART - -/** - * tracker_extract_info_get_media_art_process: - * @info: a #TrackerExtractInfo - * - * Returns the #MediaArtProcess object that can be used to retrieve - * and store media art caches found in extracted content. - * - * Returns: (transfer none): The #MediaArtProcess. This object should - * not be unreferenced. - * - * Since: 1.2 - **/ -MediaArtProcess * -tracker_extract_info_get_media_art_process (TrackerExtractInfo *info) -{ - g_return_val_if_fail (info != NULL, NULL); - return info->media_art_process; -} - -/** - * tracker_extract_info_set_media_art_process: - * @info: a #TrackerExtractInfo - * @media_art_process: a #MediaArtProcess. - * - * Use @media_art_process for caching and looking up media art. - * - * Since: 1.2 - **/ -void -tracker_extract_info_set_media_art_process (TrackerExtractInfo *info, - MediaArtProcess *media_art_process) -{ - g_return_if_fail (info != NULL); - g_return_if_fail (MEDIA_ART_IS_PROCESS (media_art_process)); - - if (info->media_art_process) { - g_object_unref (info->media_art_process); - } - - info->media_art_process = g_object_ref (media_art_process); -} - -#endif /* HAVE_LIBMEDIAART */ diff --git a/src/libtracker-extract/tracker-extract-info.h b/src/libtracker-extract/tracker-extract-info.h deleted file mode 100644 index 5036f8d42..000000000 --- a/src/libtracker-extract/tracker-extract-info.h +++ /dev/null @@ -1,63 +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> - -#ifdef HAVE_LIBMEDIAART -#include <libmediaart/mediaart.h> -#endif - -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); - -#ifdef HAVE_LIBMEDIAART - -MediaArtProcess * tracker_extract_info_get_media_art_process (TrackerExtractInfo *info); -void tracker_extract_info_set_media_art_process (TrackerExtractInfo *info, - MediaArtProcess *media_art_process); - -#endif /* HAVE_LIBMEDIAART */ - -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 175c83e54..000000000 --- a/src/libtracker-extract/tracker-module-manager.c +++ /dev/null @@ -1,595 +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; - TrackerModuleThreadAwareness thread_awareness; - TrackerExtractMetadataFunc extract_func; - TrackerExtractInitFunc init_func; - TrackerExtractShutdownFunc shutdown_func; - guint initialized : 1; -} ModuleInfo; - -static gboolean dummy_extract_func (TrackerExtractInfo *info); - -static ModuleInfo dummy_module = { - NULL, TRACKER_MODULE_MAIN_THREAD, - dummy_extract_func, NULL, NULL, TRUE -}; - -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, - gboolean initialize) -{ - 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; - - /* 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); - - /* 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); - } - - if (module_info && initialize && - !module_info->initialized) { - if (module_info->init_func) { - GError *error = NULL; - - if (!(module_info->init_func) (&module_info->thread_awareness, &error)) { - g_critical ("Could not initialize module %s: %s", - g_module_name (module_info->module), - (error) ? error->message : "No error given"); - - if (error) { - g_error_free (error); - } - - return NULL; - } - } else { - module_info->thread_awareness = TRACKER_MODULE_MAIN_THREAD; - } - - module_info->initialized = TRUE; - } - - return module_info; -} - -GModule * -tracker_extract_module_manager_get_for_mimetype (const gchar *mimetype, - TrackerExtractInitFunc *init_func, - TrackerExtractShutdownFunc *shutdown_func, - TrackerExtractMetadataFunc *extract_func) -{ - ModuleInfo *module_info = NULL; - GList *mimetype_rules; - - if (init_func) { - *init_func = NULL; - } - - if (shutdown_func) { - *shutdown_func = NULL; - } - - if (extract_func) { - *extract_func = NULL; - } - - if (!initialized && - !tracker_extract_module_manager_init ()) { - return NULL; - } - - mimetype_rules = lookup_rules (mimetype); - - if (!mimetype_rules) { - return NULL; - } - - module_info = load_module (mimetype_rules->data, FALSE); - - if (!module_info) { - return NULL; - } - - if (extract_func) { - *extract_func = module_info->extract_func; - } - - if (init_func) { - *init_func = module_info->init_func; - } - - if (shutdown_func) { - *shutdown_func = module_info->shutdown_func; - } - - return module_info->module; -} - -gboolean -tracker_extract_module_manager_mimetype_is_handled (const gchar *mimetype) -{ - GList *mimetype_rules; - - if (!initialized && - !tracker_extract_module_manager_init ()) { - return FALSE; - } - - mimetype_rules = lookup_rules (mimetype); - - return mimetype_rules != NULL; -} - -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, TRUE); - - 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 - * @thread_awareness: (out): (allow-none): thread awareness of the extractor module - * - * 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. If @thread_awareness is not %NULL, it will be filled in with the - * module thread awareness description. - * - * Returns: The %GModule currently pointed to by @info. - * - * Since: 0.12 - **/ -GModule * -tracker_mimetype_info_get_module (TrackerMimetypeInfo *info, - TrackerExtractMetadataFunc *extract_func, - TrackerModuleThreadAwareness *thread_awareness) -{ - 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; - } - - if (thread_awareness) { - *thread_awareness = info->cur_module_info->thread_awareness; - } - - 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); -} diff --git a/src/libtracker-extract/tracker-module-manager.h b/src/libtracker-extract/tracker-module-manager.h deleted file mode 100644 index f11618a04..000000000 --- a/src/libtracker-extract/tracker-module-manager.h +++ /dev/null @@ -1,91 +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 - -/** - * TrackerModuleThreadAwareness: - * @TRACKER_MODULE_NONE: Extractions are completed in the main event - * loop. - * @TRACKER_MODULE_MAIN_THREAD: Extractions will be dispatched in the - * main thread. - * @TRACKER_MODULE_SINGLE_THREAD: Extractions will be dispatched in a - * separate thread which is not the main thread. This means a new - * thread is created and used for all extractions with this value. - * @TRACKER_MODULE_MULTI_THREAD: A thread pool is used for all - * extractions of this module. This requires that the module is thread - * aware. - * - * Enumerates the different types of thread awareness which extractor - * modules need to be aware of. This is useful to know because it - * changes the way we queue and notify extractions with modules for - * metadata from files. - * - * Since: 0.14 - **/ -typedef enum { - TRACKER_MODULE_NONE, - TRACKER_MODULE_MAIN_THREAD, - TRACKER_MODULE_SINGLE_THREAD, - TRACKER_MODULE_MULTI_THREAD -} TrackerModuleThreadAwareness; - -typedef struct _TrackerMimetypeInfo TrackerMimetypeInfo; - -typedef gboolean (* TrackerExtractInitFunc) (TrackerModuleThreadAwareness *thread_awareness_ret, - GError **error); -typedef void (* TrackerExtractShutdownFunc) (void); - -typedef gboolean (* TrackerExtractMetadataFunc) (TrackerExtractInfo *info); - - -gboolean tracker_extract_module_manager_init (void) G_GNUC_CONST; -GModule * tracker_extract_module_manager_get_for_mimetype (const gchar *mimetype, - TrackerExtractInitFunc *init_func, - TrackerExtractShutdownFunc *shutdown_func, - TrackerExtractMetadataFunc *extract_func); - -gboolean tracker_extract_module_manager_mimetype_is_handled (const gchar *mimetype); - - -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, - TrackerModuleThreadAwareness *thread_awareness); -gboolean tracker_mimetype_info_iter_next (TrackerMimetypeInfo *info); -void tracker_mimetype_info_free (TrackerMimetypeInfo *info); - -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 3041c6445..000000000 --- a/src/libtracker-extract/tracker-resource-helpers.c +++ /dev/null @@ -1,304 +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) - * - * 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) -{ - char *album_uri, *disc_uri; - TrackerResource *album, *album_disc; - - g_return_val_if_fail (album_title != NULL, NULL); - - album_uri = tracker_sparql_escape_uri_printf ("urn:album:%s", album_title); - album = tracker_resource_new (album_uri); - - tracker_resource_set_uri (album, "rdf:type", "nmm:MusicAlbum"); - tracker_resource_set_string (album, "nmm:albumTitle", album_title); - - if (album_artist != NULL) { - tracker_resource_add_relation (album, "nmm:albumArtist", album_artist); - } - - disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:Disc%d", album_title, disc_number); - album_disc = tracker_resource_new (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 (disc_uri); - - 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 2051e8e93..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); -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 308fb5d99..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, - guint *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 76110ff94..000000000 --- a/src/libtracker-extract/tracker-xmp.c +++ /dev/null @@ -1,1148 +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) { - tracker_resource_set_string (resource, "nfo:orientation", data->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) { - tracker_resource_set_string (resource, "nmm:whiteBalance", data->white_balance); - } - - if (data->fnumber) { - tracker_resource_set_string (resource, "nmm:fnumber", data->fnumber); - } - - if (data->flash) { - tracker_resource_set_string (resource, "nmm:flash", data->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) { - tracker_resource_set_string (resource, "nmm:meteringMode", data->metering_mode); - } - - 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); - } - - 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/miners/Makefile.am b/src/miners/Makefile.am deleted file mode 100644 index 4c61a6330..000000000 --- a/src/miners/Makefile.am +++ /dev/null @@ -1,17 +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 - -if HAVE_TRACKER_MINER_USER_GUIDES -SUBDIRS += user-guides -endif 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 c39a05cf5..000000000 --- a/src/miners/apps/Makefile.am +++ /dev/null @@ -1,72 +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) \ - $(NULL) 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 9de0f9eb7..000000000 --- a/src/miners/apps/org.freedesktop.Tracker1.Miner.Applications.service.in.in +++ /dev/null @@ -1,9 +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 -_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 5bd944ae0..000000000 --- a/src/miners/apps/tracker-main.c +++ /dev/null @@ -1,246 +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" - -static GMainLoop *main_loop; - -static gint verbosity = -1; -static gboolean no_daemon; -static gboolean version; - -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 }, - { "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); - } -} - -int -main (gint argc, gchar *argv[]) -{ - TrackerMiner *miner_applications; - GOptionContext *context; - GError *error = NULL; - gchar *log_filename = NULL; - - 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_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); - - 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; - } - - g_signal_connect (miner_applications, "finished", - G_CALLBACK (miner_finished_cb), - NULL); - - 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)); - - 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 749d3e4d2..000000000 --- a/src/miners/apps/tracker-miner-applications.c +++ /dev/null @@ -1,1048 +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, - TrackerSparqlBuilder *sparql, - GCancellable *cancellable); -static gboolean miner_applications_process_file_attributes (TrackerMinerFS *fs, - GFile *file, - TrackerSparqlBuilder *sparql, - GCancellable *cancellable); - -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; -}; - -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_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); - } - -#ifdef HAVE_MEEGOTOUCH - /* NOTE: We don't use miner_applications_basedir_add() for - * this location because it is unique to MeeGoTouch. - */ - path = "/usr/lib/duicontrolpanel/"; - indexing_tree = tracker_miner_fs_get_indexing_tree (fs); - - g_message ("Setting up applications to iterate from MeegoTouch directories"); - g_message (" Adding:'%s'", path); - - file = g_file_new_for_path (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); -#endif /* HAVE_MEEGOTOUCH */ -} - -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 (includes both applications and maemo applets) - * (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 (includes both applications and maemo applets) */ - 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; - 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; -#ifdef HAVE_MEEGOTOUCH - gchar *logical_id = NULL; - gchar *translation_catalog = NULL; -#endif /* HAVE_MEEGOTOUCH */ - - 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 */ - -#ifdef HAVE_MEEGOTOUCH - /* If defined, start with the logical strings */ - logical_id = g_key_file_get_string (key_file, GROUP_DESKTOP_ENTRY, "X-MeeGo-Logical-Id", NULL); - translation_catalog = g_key_file_get_string (key_file, GROUP_DESKTOP_ENTRY, "X-MeeGo-Translation-Catalog", NULL); - - if (logical_id && translation_catalog) { - name = tracker_meego_translate (translation_catalog, logical_id); - } - - g_free (logical_id); - g_free (translation_catalog); -#endif /* HAVE_MEEGOTOUCH */ - - 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"); - } -#ifdef HAVE_MEEGOTOUCH - } else if (name && g_ascii_strcasecmp (type, "ControlPanelApplet") == 0) { - /* Special case control panel applets */ - /* The URI of the InformationElement should be a UUID URN */ - uri = g_file_get_uri (data->file); - tracker_sparql_builder_insert_silent_open (sparql, TRACKER_MINER_FS_GRAPH_URN); - - tracker_sparql_builder_subject_iri (sparql, APPLET_DATASOURCE_URN); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nie:DataSource"); - - /* TODO This is atm specific for Maemo */ - tracker_sparql_builder_subject_iri (sparql, uri); - - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "maemo:ControlPanelApplet"); - - tracker_sparql_builder_predicate (sparql, "nie:dataSource"); - tracker_sparql_builder_object_iri (sparql, APPLET_DATASOURCE_URN); - - /* This matches SomeApplet as Type= */ - } else if (name && g_str_has_suffix (type, "Applet")) { - /* The URI of the InformationElement should be a UUID URN */ - uri = g_file_get_uri (data->file); - tracker_sparql_builder_insert_silent_open (sparql, TRACKER_MINER_FS_GRAPH_URN); - - tracker_sparql_builder_subject_iri (sparql, APPLET_DATASOURCE_URN); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nie:DataSource"); - - /* TODO This is atm specific for Maemo */ - tracker_sparql_builder_subject_iri (sparql, uri); - - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "maemo:SoftwareApplet"); - - tracker_sparql_builder_predicate (sparql, "nie:dataSource"); - tracker_sparql_builder_object_iri (sparql, APPLET_DATASOURCE_URN); - - } else if (name && g_ascii_strcasecmp (type, "DUIApplication") == 0) { - - uri = g_file_get_uri (data->file); - tracker_sparql_builder_insert_silent_open (sparql, TRACKER_MINER_FS_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); -#endif /* HAVE_MEEGOTOUCH */ - } 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); -#ifdef HAVE_MEEGOTOUCH - g_warning (" Couldn't get name, missing or wrong key (X-MeeGo-Logical-Id, X-MeeGo-Translation-Catalog or Name)"); -#else - g_warning (" Couldn't get name, missing key (Name)"); -#endif - } - } - - 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 Meego or 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_urn = tracker_miner_fs_get_parent_urn (TRACKER_MINER_FS (data->miner), data->file); - - 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_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_file_notify (TRACKER_MINER_FS (data->miner), file, error); - process_application_data_free (data); - g_error_free (error); - 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_file_notify (TRACKER_MINER_FS (data->miner), data->file, error); - process_application_data_free (data); - - if (error) { - g_error_free (error); - } - - if (file_info) { - g_object_unref (file_info); - } -} - -static gboolean -miner_applications_process_file (TrackerMinerFS *fs, - GFile *file, - TrackerSparqlBuilder *sparql, - GCancellable *cancellable) -{ - ProcessApplicationData *data; - const gchar *attrs; - - data = g_slice_new0 (ProcessApplicationData); - data->miner = g_object_ref (fs); - data->sparql = g_object_ref (sparql); - data->file = g_object_ref (file); - data->cancellable = g_object_ref (cancellable); - - 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, - cancellable, - process_file_cb, - data); - - return TRUE; -} - -static gboolean -miner_applications_process_file_attributes (TrackerMinerFS *fs, - GFile *file, - TrackerSparqlBuilder *sparql, - GCancellable *cancellable) -{ - 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; -} - -TrackerMiner * -tracker_miner_applications_new (GError **error) -{ - return g_initable_new (TRACKER_TYPE_MINER_APPLICATIONS, - NULL, - error, - "name", "Applications", - "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 0c49814b1..000000000 --- a/src/miners/apps/tracker-miner-apps.desktop.in.in +++ /dev/null @@ -1,19 +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-Meego-Priority=Late -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-MEEGO-HS;X-MEEGO-NB;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 75060f169..000000000 --- a/src/miners/fs/Makefile.am +++ /dev/null @@ -1,128 +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-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-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 -if HAVE_LIBMEDIAART -requires="libmediaart-1.0" -else -requires= -endif - -%.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) \ - $(man_MANS) - -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) \ - $(man_MANS) - 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 009302b4d..000000000 --- a/src/miners/fs/org.freedesktop.Tracker1.Miner.Files.service.in.in +++ /dev/null @@ -1,9 +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 -_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-main.c b/src/miners/fs/tracker-main.c deleted file mode 100644 index f40ff5c68..000000000 --- a/src/miners/fs/tracker-main.c +++ /dev/null @@ -1,851 +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 - -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 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") }, - { "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_db_manager_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) && - tracker_miner_fs_get_initial_crawling (fs)) { - tracker_db_manager_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 OR the userguides 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_get_n_pause_reasons (miner) > 1; - } - } -} - -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 do_crawling; - gboolean force_mtime_checking = FALSE; - gboolean store_available; - - 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; - } - - /* 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_db_manager_get_first_index_done () == FALSE); - - main_loop = g_main_loop_new (NULL, FALSE); - - 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; - } - - 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; - } - - /* 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_db_manager_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_db_manager_set_need_mtime_check (TRUE); - - /* Configure files miner */ - tracker_miner_fs_set_initial_crawling (TRACKER_MINER_FS (miner_files), do_crawling); - tracker_miner_fs_set_mtime_checking (TRACKER_MINER_FS (miner_files), do_mtime_checking); - g_signal_connect (miner_files, "finished", - G_CALLBACK (miner_finished_cb), - NULL); - - miners = g_slist_prepend (miners, miner_files); - - 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_db_manager_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); - - 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 ea995f066..000000000 --- a/src/miners/fs/tracker-miner-files-index.c +++ /dev/null @@ -1,613 +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, 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, 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; - GVariant *reply; - guint32 rval; - 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; - } - - reply = g_dbus_connection_call_sync (priv->d_connection, - "org.freedesktop.DBus", - "/org/freedesktop/DBus", - "org.freedesktop.DBus", - "RequestName", - g_variant_new ("(su)", full_name, 0x4 /* DBUS_NAME_FLAG_DO_NOT_QUEUE */), - G_VARIANT_TYPE ("(u)"), - 0, -1, NULL, &error); - - if (error) { - g_critical ("Could not acquire name:'%s', %s", - full_name, - error->message); - g_clear_error (&error); - g_object_unref (miner); - return NULL; - } - - g_variant_get (reply, "(u)", &rval); - g_variant_unref (reply); - - if (rval != 1 /* DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER */) { - g_critical ("D-Bus service name:'%s' is already taken, " - "perhaps the daemon is already running?", - full_name); - 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 e0cd48d16..000000000 --- a/src/miners/fs/tracker-miner-files.c +++ /dev/null @@ -1,2945 +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" - -#define DISK_SPACE_CHECK_FREQUENCY 10 -#define SECONDS_PER_DAY 86400 - -#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; -}; - -struct TrackerMinerFilesPrivate { - TrackerConfig *config; - TrackerStorage *storage; - - GVolumeMonitor *volume_monitor; - - GSList *index_recursive_directories; - GSList *index_single_directories; - - guint disk_space_check_id; - guint disk_space_pause_cookie; - - guint low_battery_pause_cookie; - -#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 index_removable_devices; - gboolean index_optical_discs; - guint volumes_changed_id; - - gboolean mount_points_initialized; - - guint stale_volumes_check_id; - - GList *extraction_queue; -}; - -enum { - VOLUME_MOUNTED_IN_STORE = 1 << 0, - VOLUME_MOUNTED = 1 << 1 -}; - -enum { - PROP_0, - PROP_CONFIG -}; - -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, - TrackerSparqlBuilder *sparql, - GCancellable *cancellable); -static gboolean miner_files_process_file_attributes (TrackerMinerFS *fs, - GFile *file, - TrackerSparqlBuilder *sparql, - GCancellable *cancellable); -static gboolean miner_files_ignore_next_update_file (TrackerMinerFS *fs, - GFile *file, - TrackerSparqlBuilder *sparql, - GCancellable *cancellable); -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 -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->ignore_next_update_file = miner_files_ignore_next_update_file; - miner_fs_class->finished = miner_files_finished; - - 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 -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->quark_mount_point_uuid = g_quark_from_static_string ("tracker-mount-point-uuid"); -} - -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); - - 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 (tracker_miner_fs_get_mtime_checking (TRACKER_MINER_FS (mf))) { - 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 (tracker_miner_fs_get_mtime_checking (TRACKER_MINER_FS (mf))) { - 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); - - 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; - - 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; - } - - g_list_free (priv->extraction_queue); - - 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 <%s> { <%s> a tracker:Volume; tracker:isRemovable %s } ", - removable_device_urn, 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 <%s> { <%s> a tracker:Volume; tracker:isOptical %s } ", - removable_device_urn, 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 <%s> { <%s> a tracker:Volume; tracker:isMounted true; nie:title \"%s\" } ", - removable_device_urn, removable_device_urn, mount_name); - } else { - g_string_append_printf (queries, - "INSERT INTO <%s> { <%s> a tracker:Volume; tracker:isMounted true } ", - removable_device_urn, removable_device_urn); - } - - g_string_append_printf (queries, - "INSERT { GRAPH <%s> { ?do tracker:available true } } WHERE { ?do nie:dataSource <%s> } ", - removable_device_urn, 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 <%s> { <%s> a tracker:Volume; tracker:unmountDate \"%s\" } ", - removable_device_urn, 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 <%s> { <%s> a tracker:Volume; tracker:isMounted false } ", - removable_device_urn, 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_db_manager_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_cookie == 0) { - mf->private->low_battery_pause_cookie = - tracker_miner_pause (TRACKER_MINER (mf), - _("Low battery"), - NULL); - } - } else { - /* Don't try to resume again */ - if (mf->private->low_battery_pause_cookie != 0) { - tracker_miner_resume (TRACKER_MINER (mf), - mf->private->low_battery_pause_cookie, - NULL); - mf->private->low_battery_pause_cookie = 0; - } - } - - 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_db_manager_get_first_index_done ()) { - tracker_db_manager_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_cookie == 0) { - mf->private->disk_space_pause_cookie = - tracker_miner_pause (TRACKER_MINER (mf), - _("Low disk space"), - NULL); - } - } else { - /* Don't try to resume again */ - if (mf->private->disk_space_pause_cookie != 0) { - tracker_miner_resume (TRACKER_MINER (mf), - mf->private->disk_space_pause_cookie, - NULL); - mf->private->disk_space_pause_cookie = 0; - } - } - - 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 (tracker_miner_fs_get_mtime_checking (TRACKER_MINER_FS (mf))) { - 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_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; - 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_file_notify (TRACKER_MINER_FS (data->miner), file, error); - priv->extraction_queue = g_list_remove (priv->extraction_queue, data); - process_file_data_free (data); - g_error_free (error); - - 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_urn = tracker_miner_fs_get_parent_urn (TRACKER_MINER_FS (data->miner), file); - - 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_file_notify (TRACKER_MINER_FS (data->miner), data->file, 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, - TrackerSparqlBuilder *sparql, - GCancellable *cancellable) -{ - TrackerMinerFilesPrivate *priv; - ProcessFileData *data; - const gchar *attrs; - - data = g_slice_new0 (ProcessFileData); - data->miner = g_object_ref (fs); - data->cancellable = g_object_ref (cancellable); - data->sparql = g_object_ref (sparql); - data->file = g_object_ref (file); - - 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, - 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_file_notify (TRACKER_MINER_FS (data->miner), file, error); - process_file_data_free (data); - g_error_free (error); - 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_file_notify (TRACKER_MINER_FS (data->miner), file, error); - process_file_data_free (data); - g_error_free (error); - 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_file_notify (TRACKER_MINER_FS (data->miner), data->file, NULL); - - process_file_data_free (data); -} - -static gboolean -miner_files_process_file_attributes (TrackerMinerFS *fs, - GFile *file, - TrackerSparqlBuilder *sparql, - GCancellable *cancellable) -{ - ProcessFileData *data; - const gchar *attrs; - - data = g_slice_new0 (ProcessFileData); - data->miner = g_object_ref (fs); - data->cancellable = g_object_ref (cancellable); - data->sparql = g_object_ref (sparql); - data->file = g_object_ref (file); - - /* 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, - cancellable, - process_file_attributes_cb, - data); - - return TRUE; -} - -static gboolean -miner_files_ignore_next_update_file (TrackerMinerFS *fs, - GFile *file, - TrackerSparqlBuilder *sparql, - GCancellable *cancellable) -{ - const gchar *attrs; - const gchar *mime_type; - GFileInfo *file_info; - guint64 time_; - gchar *uri; - GError *error = NULL; - - 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; - - file_info = g_file_query_info (file, attrs, - G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, - cancellable, &error); - - if (error) { - g_warning ("Can't ignore-next-update: '%s'", error->message); - g_clear_error (&error); - return FALSE; - } - - uri = g_file_get_uri (file); - mime_type = g_file_info_get_content_type (file_info); - - /* For ignore-next-update we only write a few properties back. These properties - * should NEVER be marked as tracker:writeback in the ontology! (else you break - * the tracker-writeback feature) */ - - tracker_sparql_builder_insert_silent_open (sparql, TRACKER_OWN_GRAPH_URN); - - tracker_sparql_builder_subject_variable (sparql, "urn"); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:FileDataObject"); - - 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_); - - tracker_sparql_builder_predicate (sparql, "nie:mimeType"); - tracker_sparql_builder_object_string (sparql, mime_type); - - tracker_sparql_builder_insert_close (sparql); - - tracker_sparql_builder_where_open (sparql); - - tracker_sparql_builder_subject_variable (sparql, "urn"); - tracker_sparql_builder_predicate (sparql, "nie:url"); - tracker_sparql_builder_object_string (sparql, uri); - - tracker_sparql_builder_where_close (sparql); - - g_object_unref (file_info); - g_free (uri); - - return TRUE; -} - -static void -miner_files_finished (TrackerMinerFS *fs, - gdouble elapsed, - gint directories_found, - gint directories_ignored, - gint files_found, - gint files_ignored) -{ - tracker_db_manager_set_last_crawl_done (TRUE); -} - -TrackerMiner * -tracker_miner_files_new (TrackerConfig *config, - GError **error) -{ - return g_initable_new (TRACKER_TYPE_MINER_FILES, - NULL, - error, - "name", "Files", - "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; -} diff --git a/src/miners/fs/tracker-miner-files.h b/src/miners/fs/tracker-miner-files.h deleted file mode 100644 index e7cf5cbdc..000000000 --- a/src/miners/fs/tracker-miner-files.h +++ /dev/null @@ -1,74 +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); - -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 a1620f6ba..000000000 --- a/src/miners/fs/tracker-miner-fs.desktop.in.in +++ /dev/null @@ -1,19 +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-Meego-Priority=Late -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-MEEGO-HS;X-MEEGO-NB;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-writeback-dispatcher.c b/src/miners/fs/tracker-writeback-dispatcher.c deleted file mode 100644 index 60765da09..000000000 --- a/src/miners/fs/tracker-writeback-dispatcher.c +++ /dev/null @@ -1,402 +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-writeback-dispatcher.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; - TrackerMinerFS *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 gboolean 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-file", - 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_fs_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_fs_writeback_notify (data->fs, data->file, NULL); - - data->retry_timeout = g_timeout_add_seconds (5, retry_idle, data); - data->retries++; - - } else { - tracker_miner_fs_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 gboolean -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); - - return TRUE; -} 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 c7849b5ca..000000000 --- a/src/miners/fs/tracker-writeback-listener.c +++ /dev/null @@ -1,484 +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-writeback-listener.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 { - TrackerMinerFiles *files_miner; - GDBusConnection *d_connection; - TrackerSparqlConnection *connection; - guint d_signal; -} TrackerWritebackListenerPrivate; - -typedef struct { - TrackerWritebackListener *self; - GStrv rdf_types; -} QueryData; - -typedef struct { - GVariantIter *iter1; - TrackerWritebackListener *self; -} DelayedLoopData; - -enum { - PROP_0, - PROP_FILES_MINER -}; - -#define TRACKER_WRITEBACK_LISTENER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), TRACKER_TYPE_WRITEBACK_LISTENER, TrackerWritebackListenerPrivate)) - -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 -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_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)); - - g_type_class_add_private (klass, sizeof (TrackerWritebackListenerPrivate)); -} - -static void -writeback_listener_set_property (GObject *object, - guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - TrackerWritebackListenerPrivate *priv; - - priv = TRACKER_WRITEBACK_LISTENER_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_listener_get_property (GObject *object, - guint param_id, - GValue *value, - GParamSpec *pspec) -{ - TrackerWritebackListenerPrivate *priv; - - priv = TRACKER_WRITEBACK_LISTENER_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_listener_finalize (GObject *object) -{ - TrackerWritebackListenerPrivate *priv = TRACKER_WRITEBACK_LISTENER_GET_PRIVATE (object); - - 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) -{ -} - -static gboolean -writeback_listener_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - TrackerWritebackListenerPrivate *priv; - GError *internal_error = NULL; - - priv = TRACKER_WRITEBACK_LISTENER_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; - } - - 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_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); - 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_fs_writeback_file (TRACKER_MINER_FS (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); -} - -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; - - priv = TRACKER_WRITEBACK_LISTENER_GET_PRIVATE (self); - connection = priv->connection; - - cursor = tracker_sparql_connection_query_finish (connection, result, &error); - - if (!error) { - gchar *query; - GArray *rdf_types; - gchar *subject = NULL; - - 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); - - } else { - goto trouble; - } - - return; - -trouble: - if (error) { - g_message (" No files qualify for updates (%s)", error->message); - g_error_free (error); - } - query_data_free (data); -} - -static gboolean -delayed_loop_idle (gpointer user_data) -{ - DelayedLoopData *ldata = user_data; - GVariantIter *iter2; - gint subject_id = 0, rdf_type = 0; - - if (g_variant_iter_next (ldata->iter1, "{iai}", &subject_id, &iter2)) { - TrackerWritebackListenerPrivate *priv; - QueryData *data = NULL; - GString *query; - gboolean comma = FALSE; - - priv = TRACKER_WRITEBACK_LISTENER_GET_PRIVATE (ldata->self); - - data = query_data_new (ldata->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 (", - subject_id); - - while (g_variant_iter_loop (iter2, "i", &rdf_type)) { - 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); - - g_variant_iter_free (iter2); - - return TRUE; - } - - return FALSE; -} - -static void -delayed_loop_finished (gpointer user_data) -{ - DelayedLoopData *ldata = user_data; - g_variant_iter_free (ldata->iter1); - g_object_unref (ldata->self); - g_free (ldata); -} - -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); - DelayedLoopData *data = g_new (DelayedLoopData, 1); - - data->self = g_object_ref (self); - g_variant_get (parameters, "(a{iai})", &data->iter1); - - g_idle_add_full (G_PRIORITY_LOW, - delayed_loop_idle, - data, - delayed_loop_finished); -} 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/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 7a1e569fe..000000000 --- a/src/miners/rss/Makefile.am +++ /dev/null @@ -1,72 +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) \ - $(NULL) 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 7b59ba359..000000000 --- a/src/miners/rss/org.freedesktop.Tracker1.Miner.RSS.service.in.in +++ /dev/null @@ -1,9 +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 -_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 57c103925..000000000 --- a/src/miners/rss/tracker-main.c +++ /dev/null @@ -1,169 +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" - -static gint verbosity = -1; -static gchar *add_feed; -static gchar *title; - -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 }, - { NULL } -}; - -int -main (int argc, char **argv) -{ - gchar *log_filename; - GMainLoop *loop; - GOptionContext *context; - TrackerMinerRSS *miner; - GError *error = NULL; - - 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); - - /* 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); - } - - 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)); - - loop = g_main_loop_new (NULL, FALSE); - g_main_loop_run (loop); - - tracker_log_shutdown (); - g_main_loop_unref (loop); - g_object_unref (miner); - - 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 0706a6b69..000000000 --- a/src/miners/rss/tracker-miner-rss.c +++ /dev/null @@ -1,1406 +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 = 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; - - 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"); - - priv->graph_updated_id = - g_dbus_connection_signal_subscribe (priv->connection, - "org.freedesktop.Tracker1", - "org.freedesktop.Tracker1.Resources", - "GraphUpdated", - "/org/freedesktop/Tracker1/Resources", - TRACKER_PREFIX_MFO "FeedChannel", - G_DBUS_SIGNAL_FLAGS_NONE, - graph_updated_cb, - object, - NULL); -} - -static void -delete_unbound_messages (TrackerMinerRSS *miner) -{ - tracker_sparql_connection_update_async (tracker_miner_get_connection (TRACKER_MINER (miner)), - "DELETE { ?msg a rdfs:Resource }" - "WHERE { ?msg a mfo:FeedMessage ." - " 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 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 *list, *l; - GList *contrib_aliases = NULL; - GHashTable *websites; - gboolean is_iri = FALSE; - - 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); - - 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] != '_')); - } - - for (l = contributors; l; l = l->next) { - gchar *subject; - gint i = 0; - - 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] != '_')); - g_free (subject); - } - - 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); - } - - 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_foreach (contrib_aliases, (GFunc) g_free, NULL); - g_list_free (contrib_aliases); - g_hash_table_destroy (websites); - - 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, - "name", "RSS", - 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/miners/user-guides/.gitignore b/src/miners/user-guides/.gitignore deleted file mode 100644 index 53909a707..000000000 --- a/src/miners/user-guides/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tracker-miner-user-guides -*.service diff --git a/src/miners/user-guides/Makefile.am b/src/miners/user-guides/Makefile.am deleted file mode 100644 index b66194e7f..000000000 --- a/src/miners/user-guides/Makefile.am +++ /dev/null @@ -1,72 +0,0 @@ -AM_CPPFLAGS = \ - $(BUILD_CFLAGS) \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - -DSHAREDIR=\""$(datadir)"\" \ - -DLOCALEDIR=\""$(localedir)"\" \ - -DLIBEXEC_PATH=\""$(libexecdir)"\" \ - $(TRACKER_MINER_USER_GUIDES_CFLAGS) - -libexec_PROGRAMS = tracker-miner-user-guides - -tracker_miner_user_guides_SOURCES = \ - tracker-main.c \ - tracker-miner-user-guides.c \ - tracker-miner-user-guides.h - -tracker_miner_user_guides_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_USER_GUIDES_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.Userguides.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-user-guides.service: tracker-miner-user-guides.service.in Makefile - @sed -e "s|@libexecdir[@]|${libexecdir}|" $< > $@ - -systemd_userdir = $(prefix)/lib/systemd/user -systemd_user_DATA = tracker-miner-user-guides.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-user-guides.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) \ - $(NULL) diff --git a/src/miners/user-guides/org.freedesktop.Tracker1.Miner.Userguides.service.in.in b/src/miners/user-guides/org.freedesktop.Tracker1.Miner.Userguides.service.in.in deleted file mode 100644 index 047ed0fd7..000000000 --- a/src/miners/user-guides/org.freedesktop.Tracker1.Miner.Userguides.service.in.in +++ /dev/null @@ -1,9 +0,0 @@ -[D-BUS Service] -Name=org.freedesktop.Tracker1.Miner.Userguides -Exec=@libexecdir@/tracker-miner-user-guides -SystemdService=tracker-miner-user-guides.service - -# Miner details needed for tracker-control -Path=/org/freedesktop/Tracker1/Miner/Userguides -_DisplayName=Userguides -_Comment=Userguide data miner diff --git a/src/miners/user-guides/tracker-main.c b/src/miners/user-guides/tracker-main.c deleted file mode 100644 index b375165a8..000000000 --- a/src/miners/user-guides/tracker-main.c +++ /dev/null @@ -1,258 +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-user-guides.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" - -static GMainLoop *main_loop; - -static gint verbosity = -1; -static gboolean no_daemon; -static gboolean version; - -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 }, - { "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 gboolean -miner_start_cb (gpointer user_data) -{ - TrackerMiner *miner = user_data; - - initialize_signal_handler (); - - tracker_miner_start (miner); - - return FALSE; -} - -int -main (gint argc, gchar *argv[]) -{ - TrackerMiner *miner_user_guides; - GOptionContext *context; - GError *error = NULL; - gchar *log_filename = NULL; - - 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 user guides 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_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); - - 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 userguides */ - miner_user_guides = tracker_miner_userguides_new (&error); - if (!miner_user_guides) { - g_critical ("Couldn't create new user guides miner, '%s'", - error ? error->message : "unknown error"); - tracker_log_shutdown (); - return EXIT_FAILURE; - } - - tracker_miner_fs_set_mtime_checking (TRACKER_MINER_FS (miner_user_guides), TRUE); - - g_signal_connect (miner_user_guides, "finished", - G_CALLBACK (miner_finished_cb), - NULL); - - /* Go, go, go! */ - g_idle_add (miner_start_cb, miner_user_guides); - g_main_loop_run (main_loop); - - g_message ("Shutdown started"); - - g_main_loop_unref (main_loop); - g_object_unref (G_OBJECT (miner_user_guides)); - - tracker_log_shutdown (); - - g_print ("\nOK\n\n"); - - return EXIT_SUCCESS; -} diff --git a/src/miners/user-guides/tracker-miner-user-guides.c b/src/miners/user-guides/tracker-miner-user-guides.c deleted file mode 100644 index 7aa4af12e..000000000 --- a/src/miners/user-guides/tracker-miner-user-guides.c +++ /dev/null @@ -1,804 +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. - * - * Author: Martyn Russell <martyn@lanedo.com> - */ - -#include "config.h" - -#include <libxml/HTMLparser.h> - -#include <libtracker-common/tracker-common.h> - -#include "tracker-miner-user-guides.h" - -#define LOCALE_FILENAME "locale-for-miner-user-guides.txt" - -// FIXME: get this value from tracker conf -#define MAX_EXTRACT_SIZE 1024 * 1024 // 1 MiB -#define MAX_TITLE_LENGTH 1000 - -typedef struct { - gchar *uri; - GString *title; - gboolean in_text; - gboolean in_title; - GString *plain_text; - gssize max_length; -} ParserContext; - -typedef struct { - TrackerMinerFS *miner; - GFile *file; - TrackerSparqlBuilder *sparql; - GCancellable *cancellable; - gchar *type; -} ProcessUserguideData; - -static void miner_userguides_initable_iface_init (GInitableIface *iface); -static gboolean miner_userguides_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error); -static gboolean miner_userguides_process_file (TrackerMinerFS *fs, - GFile *file, - TrackerSparqlBuilder *sparql, - GCancellable *cancellable); -static gboolean miner_userguides_process_file_attributes (TrackerMinerFS *fs, - GFile *file, - TrackerSparqlBuilder *sparql, - GCancellable *cancellable); -static void parser_get_file_content (const gchar *uri, - gssize max_extract_size, - gchar **content, - gchar **title); - -static GQuark miner_userguides_error_quark = 0; - -static GInitableIface* miner_userguides_initable_parent_iface; - -G_DEFINE_TYPE_WITH_CODE (TrackerMinerUserguides, tracker_miner_userguides, TRACKER_TYPE_MINER_FS, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - miner_userguides_initable_iface_init)); - -static void -tracker_miner_userguides_class_init (TrackerMinerUserguidesClass *klass) -{ - TrackerMinerFSClass *miner_fs_class = TRACKER_MINER_FS_CLASS (klass); - - miner_fs_class->process_file = miner_userguides_process_file; - miner_fs_class->process_file_attributes = miner_userguides_process_file_attributes; - - miner_userguides_error_quark = g_quark_from_static_string ("TrackerMinerUserguides"); -} - -static void -tracker_miner_userguides_init (TrackerMinerUserguides *ma) -{ -} - -static void -miner_userguides_initable_iface_init (GInitableIface *iface) -{ - miner_userguides_initable_parent_iface = g_type_interface_peek_parent (iface); - iface->init = miner_userguides_initable_init; -} - -static inline gboolean -miner_userguides_basedir_add_path (TrackerMinerFS *fs, - const gchar *path, - const gchar *locale) -{ - if (g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { - TrackerIndexingTree *indexing_tree; - GFile *file; - - indexing_tree = tracker_miner_fs_get_indexing_tree (fs); - - g_message (" Adding:'%s'", path); - file = g_file_new_for_path (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); - - return TRUE; - } - - g_message (" No user guide found for locale:'%s' in this prefix", locale); - - return FALSE; -} - -static void -miner_userguides_basedir_add (TrackerMinerFS *fs, - const gchar *basedir) -{ - gchar *path; - gboolean added = FALSE; - - /* Do preliminary check on basedir */ - path = g_build_filename (basedir, "userguide", "contents", NULL); - if (!g_file_test (path, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) { - g_message (" No user guides in prefix:'%s'", path); - g_free (path); - return; - } - - g_free (path); - - /* Without MeeGoTouch, we simply index ALL content. */ -#ifdef HAVE_MEEGOTOUCH - gchar *locale; - - locale = tracker_meego_get_locale (); - - /* Order of which we try here: - * 1, make sure locale is set, otherwise default to 'en' - * 2, try the "xx_YY" of the current locale - * 3, try the "xx" of the current locale - * 4, default to 'en' for cases where current locale has no userguide - */ - - /* Step 1 */ - if (locale == NULL || *locale == '\0') { - g_message (" Locale was not set which is unexpected, defaulting to 'en'"); - g_free (locale); - locale = g_strdup ("en"); - } - - /* Step 2 */ - path = g_build_filename (basedir, "userguide", "contents", locale, NULL); - added = miner_userguides_basedir_add_path (fs, path, locale); - g_free (path); - - /* Step 3 */ - if (!added && strlen (locale) > 2) { - locale[2] = '\0'; - path = g_build_filename (basedir, "userguide", "contents", locale, NULL); - added = miner_userguides_basedir_add_path (fs, path, locale); - g_free (path); - } - - /* Step 4 */ - if (!added) { - g_message (" Locale has no user guide currently, defaulting to 'en'"); - path = g_build_filename (basedir, "userguide", "contents", "en", NULL); - added = miner_userguides_basedir_add_path (fs, path, "en"); - g_free (path); - } - - if (!added) { - g_message (" Default locale 'en' has no user guide in this prefix"); - } - - g_free (locale); -#endif /* HAVE_MEEGOTOUCH */ - - if (!added) { - /* Add $dir/userguide/contents */ - g_message (" MeeGoTouch is disabled, indexing all user guides..."); - path = g_build_filename (basedir, "userguide", "contents", NULL); - miner_userguides_basedir_add_path (fs, path, ""); - g_free (path); - } -} - -static void -miner_userguides_add_directories (TrackerMinerFS *fs) -{ - const gchar * const *xdg_dirs; - gint i; - - g_message ("Setting up user guides 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_userguides_basedir_add (fs, xdg_dirs[i]); - } -} - -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-userguides, this is: - * (a) Remove all resources which are a nfo:HelpDocument - * (b) Remove all unnecessary directories - */ -static void -miner_userguides_reset (TrackerMiner *miner) -{ - GError *error = NULL; - TrackerSparqlBuilder *sparql; - - sparql = tracker_sparql_builder_new_update (); - - /* (a) Remove all resources which are a nfo:HelpDocument */ - tracker_sparql_builder_delete_open (sparql, TRACKER_OWN_GRAPH_URN); - tracker_sparql_builder_subject_variable (sparql, "userguide"); - 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, "userguide"); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nfo:HelpDocument"); - tracker_sparql_builder_where_close (sparql); - - /* (b) Remove all unnecessary directories */ - /* TODO: Finish */ - - - /* Execute a sync update, we don't want the userguides 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 userguides: %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_userguides_reset (miner); - } - - return changed; -} - -static gboolean -miner_userguides_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, - "*.html"); - - /* Chain up parent's initable callback before calling child's one */ - if (!miner_userguides_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_userguides_add_directories (fs); - - /* If the locales changed, we need to reset things first */ - detect_locale_changed (TRACKER_MINER (fs)); - - return TRUE; -} - -static const gchar * -get_file_urn (TrackerMinerFS *miner, - GFile *file, - gboolean *is_iri) -{ - const gchar *urn; - - urn = tracker_miner_fs_get_urn (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 inline void -process_item (ProcessUserguideData *data, - GFileInfo *file_info, - gboolean is_dir, - GError **error) -{ - TrackerSparqlBuilder *sparql; - gchar *uri; - const gchar *mime_type; - const gchar *urn; - const gchar *parent_urn; - gboolean is_iri; - guint64 time_; - - sparql = data->sparql; - - uri = g_file_get_uri (data->file); - mime_type = g_file_info_get_content_type (file_info); - - urn = get_file_urn (data->miner, data->file, &is_iri); - - tracker_sparql_builder_insert_silent_open (sparql, NULL); - tracker_sparql_builder_graph_open (sparql, TRACKER_OWN_GRAPH_URN); - - if (is_iri) { - gchar *delete_properties_sparql; - - 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); - tracker_sparql_builder_subject_iri (sparql, urn); - - g_free (delete_properties_sparql); - } 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"); - - if (is_dir) { - tracker_sparql_builder_object (sparql, "nfo:Folder"); - } else { - tracker_sparql_builder_object (sparql, "nfo:HelpDocument"); - } - - parent_urn = tracker_miner_fs_get_parent_urn (TRACKER_MINER_FS (data->miner), data->file); - - 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); - - /* FIXME: Add nie:dataSource for switching different userguides? */ - tracker_sparql_builder_predicate (sparql, "tracker:available"); - tracker_sparql_builder_object_boolean (sparql, TRUE); - - if (!is_dir) { - gchar *content = NULL; - gchar *title = NULL; - - /* Get content */ - parser_get_file_content (uri, MAX_EXTRACT_SIZE, &content, &title); - - g_message ("Adding userguide:'%s', uri:'%s'", - title, - uri); - - if (title && title[0]) { - tracker_sparql_builder_predicate (sparql, "nie:title"); - tracker_sparql_builder_object_unvalidated (sparql, title); - } - - if (content && content[0]) { - tracker_sparql_builder_predicate (sparql, "nie:plainTextContent"); - tracker_sparql_builder_object_unvalidated (sparql, content); - } - - g_free (content); - g_free (title); - } else { - g_message ("Adding userguide directory:'%s'", uri); - } - - tracker_sparql_builder_graph_close (sparql); - tracker_sparql_builder_insert_close (sparql); - - g_free (uri); -} - -static void -process_userguide_data_free (ProcessUserguideData *data) -{ - g_object_unref (data->miner); - g_object_unref (data->file); - g_object_unref (data->sparql); - g_object_unref (data->cancellable); - - g_slice_free (ProcessUserguideData, data); -} - -static void -process_file_cb (GObject *object, - GAsyncResult *result, - gpointer user_data) -{ - ProcessUserguideData *data; - GFileInfo *file_info; - GError *error = NULL; - GFile *file; - gboolean is_dir; - - data = user_data; - file = G_FILE (object); - file_info = g_file_query_info_finish (file, result, &error); - - if (error) { - tracker_miner_fs_file_notify (TRACKER_MINER_FS (data->miner), file, error); - process_userguide_data_free (data); - g_error_free (error); - return; - } - - is_dir = g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY; - process_item (data, file_info, is_dir, &error); - - tracker_miner_fs_file_notify (TRACKER_MINER_FS (data->miner), data->file, error); - process_userguide_data_free (data); - - if (error) { - g_error_free (error); - } - - if (file_info) { - g_object_unref (file_info); - } -} - -static gboolean -miner_userguides_process_file (TrackerMinerFS *fs, - GFile *file, - TrackerSparqlBuilder *sparql, - GCancellable *cancellable) -{ - ProcessUserguideData *data; - const gchar *attrs; - - data = g_slice_new0 (ProcessUserguideData); - data->miner = g_object_ref (fs); - data->sparql = g_object_ref (sparql); - data->file = g_object_ref (file); - data->cancellable = g_object_ref (cancellable); - - 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, - cancellable, - process_file_cb, - data); - - return TRUE; -} - -static gboolean -miner_userguides_process_file_attributes (TrackerMinerFS *fs, - GFile *file, - TrackerSparqlBuilder *sparql, - GCancellable *cancellable) -{ - 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 void -parser_start_element (void *ctx, - const xmlChar *name, - const xmlChar **atts G_GNUC_UNUSED) -{ - const gchar *elem = (const gchar *) name; - ParserContext *pctx = ctx; - - if (g_strcmp0 (elem, "title") == 0) { - pctx->in_title = TRUE; - return; - } - - if (g_strcmp0 (elem, "body") == 0) { - pctx->in_text = TRUE; - return; - } -} - -static void -parser_end_element (void *ctx, - const xmlChar *name) -{ - const gchar *elem = (const gchar *) name; - ParserContext *pctx = ctx; - - if (g_strcmp0 (elem, "title") == 0) { - pctx->in_title = FALSE; - } -} - -static void -parser_characters (void *ctx, - const xmlChar *ch, - int len G_GNUC_UNUSED) -{ - ParserContext *pctx = ctx; - const gchar *str; - int len_to_append; - - if (pctx->in_title) { - const gchar *title = (const gchar *) ch; - - if (title[0]) { - g_string_append_len (pctx->title, - title, - MIN(strlen (title), MAX_TITLE_LENGTH)); - } - } - - if (!pctx->in_text) { - return; - } - - if ((gssize) pctx->plain_text->len >= pctx->max_length) { - return; - } - - str = (const gchar *) ch; - - if (!str || !str[0]) { - return; - } - - len_to_append = strlen (str); - - if ((gssize) pctx->plain_text->len + len_to_append > pctx->max_length) { - len_to_append = pctx->max_length - pctx->plain_text->len; - } - - g_string_append_len (pctx->plain_text, str, len_to_append); -} - -static void -parser_error (void *ctx, - const char *msg, - ...) -{ - ParserContext *pctx = ctx; - va_list args; - gchar *str; - - va_start (args, msg); - str = g_strdup_vprintf (msg, args); - va_end (args); - - g_critical ("Could not parse file '%s': %s", pctx->uri, str); - g_free (str); -} - -static void -parser_get_file_content (const gchar *uri, - gssize max_extract_size, - gchar **content, - gchar **title) -{ - GError *error = NULL; - gchar *filename; - ParserContext parser_ctx = { 0 }; - htmlSAXHandler sax_handler = { 0 }; - htmlDocPtr doc; - - /* TODO: utf8 sanitization */ - - filename = g_filename_from_uri (uri, NULL, &error); - - if (error) { - g_message ("Could not open '%s': %s", uri, error->message); - g_error_free (error); - g_free (filename); - return; - } - - parser_ctx.uri = g_strdup (uri); - parser_ctx.title = g_string_new (NULL); - parser_ctx.in_text = FALSE; - parser_ctx.in_title = FALSE; - parser_ctx.plain_text = g_string_new (NULL); - /* leave space for terminating 0 char */ - parser_ctx.max_length = max_extract_size - 1; - - sax_handler.startElement = parser_start_element; - sax_handler.endElement = parser_end_element; - sax_handler.characters = parser_characters; - sax_handler.error = parser_error; - - doc = NULL; - doc = htmlSAXParseFile (filename, "utf-8", &sax_handler, &parser_ctx); - g_free (filename); - - if (doc) { - xmlFreeDoc (doc); - } - - g_free (parser_ctx.uri); - - *title = g_string_free (parser_ctx.title, FALSE); - g_strstrip (*title); - - *content = g_string_free (parser_ctx.plain_text, FALSE); - g_strstrip (*content); -} - -TrackerMiner * -tracker_miner_userguides_new (GError **error) -{ - return g_initable_new (TRACKER_TYPE_MINER_USERGUIDES, - NULL, - error, - "name", "Userguides", - "processing-pool-wait-limit", 10, - "processing-pool-ready-limit", 100, - NULL); -} diff --git a/src/miners/user-guides/tracker-miner-user-guides.desktop.in.in b/src/miners/user-guides/tracker-miner-user-guides.desktop.in.in deleted file mode 100644 index 4274e1a41..000000000 --- a/src/miners/user-guides/tracker-miner-user-guides.desktop.in.in +++ /dev/null @@ -1,19 +0,0 @@ -[Desktop Entry] -_Name=Tracker User Guides Miner -_Comment=Crawls and processes user guides in shared areas -Icon= -Exec=@libexecdir@/tracker-miner-user-guides -Terminal=false -Type=Application -Categories=Utility; -X-Meego-Priority=Late -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-MEEGO-HS;X-MEEGO-NB;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/user-guides/tracker-miner-user-guides.h b/src/miners/user-guides/tracker-miner-user-guides.h deleted file mode 100644 index aeb5b7a84..000000000 --- a/src/miners/user-guides/tracker-miner-user-guides.h +++ /dev/null @@ -1,54 +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. - * - * Author: Martyn Russell <martyn@lanedo.com> - */ - -#ifndef __TRACKER_MINER_FS_USERGUIDES_H__ -#define __TRACKER_MINER_FS_USERGUIDES_H__ - -#include <libtracker-miner/tracker-miner.h> - -G_BEGIN_DECLS - -#define TRACKER_TYPE_MINER_USERGUIDES (tracker_miner_userguides_get_type()) -#define TRACKER_MINER_USERGUIDES(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_MINER_USERGUIDES, TrackerMinerUserguides)) -#define TRACKER_MINER_USERGUIDES_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_MINER_USERGUIDES, TrackerMinerUserguidesClass)) -#define TRACKER_IS_MINER_USERGUIDES(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TRACKER_TYPE_MINER_USERGUIDES)) -#define TRACKER_IS_MINER_USERGUIDES_CLASS(c) (G_TYPE_CHECK_CLASS_TYPE ((c), TRACKER_TYPE_MINER_USERGUIDES)) -#define TRACKER_MINER_USERGUIDES_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_MINER_USERGUIDES, TrackerMinerUserguidesClass)) - -typedef struct _TrackerMinerUserguides TrackerMinerUserguides; -typedef struct _TrackerMinerUserguidesClass TrackerMinerUserguidesClass; - -struct _TrackerMinerUserguides { - TrackerMinerFS parent_instance; - gpointer locale_notification_id; -}; - -struct _TrackerMinerUserguidesClass { - TrackerMinerFSClass parent_class; -}; - -GType tracker_miner_userguides_get_type (void) G_GNUC_CONST; -TrackerMiner *tracker_miner_userguides_new (GError **error); -gboolean tracker_miner_userguides_detect_locale_changed (TrackerMiner *miner); - -G_END_DECLS - -#endif /* __TRACKER_MINER_FS_USERGUIDES_H__ */ diff --git a/src/miners/user-guides/tracker-miner-user-guides.service.in b/src/miners/user-guides/tracker-miner-user-guides.service.in deleted file mode 100644 index 34f82dfab..000000000 --- a/src/miners/user-guides/tracker-miner-user-guides.service.in +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=Tracker user guides data miner - -[Service] -Type=dbus -BusName=org.freedesktop.Tracker1.Miner.UserGuides -ExecStart=@libexecdir@/tracker-miner-user-guides -Restart=on-failure -# Don't restart after tracker daemon -k (aka tracker-control -k) -RestartPreventExitStatus=SIGKILL diff --git a/src/plugins/Makefile.am b/src/plugins/Makefile.am deleted file mode 100644 index dc1e7aa31..000000000 --- a/src/plugins/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -SUBDIRS = - -if HAVE_TRACKER_MINER_EVOLUTION -SUBDIRS += evolution -endif - -if HAVE_TRACKER_MINER_THUNDERBIRD -SUBDIRS += thunderbird -endif - -if HAVE_TRACKER_MINER_FIREFOX -SUBDIRS += firefox -endif - -if HAVE_TRACKER_NAUTILUS_EXTENSION -SUBDIRS += nautilus -endif diff --git a/src/plugins/evolution/.gitignore b/src/plugins/evolution/.gitignore deleted file mode 100644 index 954b62057..000000000 --- a/src/plugins/evolution/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -*.eplug -*.service diff --git a/src/plugins/evolution/Makefile.am b/src/plugins/evolution/Makefile.am deleted file mode 100644 index dcdd886cd..000000000 --- a/src/plugins/evolution/Makefile.am +++ /dev/null @@ -1,74 +0,0 @@ -AM_CPPFLAGS = \ - $(BUILD_CFLAGS) \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - -DGETTEXT_PACKAGE="\"$(GETTEXT_PACKAGE)\"" \ - -DLOCALEDIR="\"$(localedir)\"" \ - $(TRACKER_MINER_EVOLUTION_CFLAGS) - -%.eplug.in: %.eplug.xml - LC_ALL=C $(INTLTOOL_MERGE) -x -u /tmp $< $@ - -%.eplug: %.eplug.in - sed -e "s|+PLUGIN_INSTALL_DIR+|$(TRACKER_MINER_EVOLUTION_INSTALL_DIR)|" \ - -e "s|+GETTEXT_PACKAGE+|$(GETTEXT_PACKAGE)|" \ - -e "s|+LOCALEDIR+|$(localedir)|" \ - $< > $@ - -eplugindir = $(TRACKER_MINER_EVOLUTION_INSTALL_DIR) - -eplugin_DATA = org-freedesktop-Tracker-evolution-plugin.eplug - -eplugin_LTLIBRARIES = liborg-freedesktop-Tracker-evolution-plugin.la - -# module_flags = -module -avoid-version -no-undefined - -liborg_freedesktop_Tracker_evolution_plugin_la_SOURCES = \ - tracker-evolution-plugin.c \ - tracker-evolution-plugin.h - -liborg_freedesktop_Tracker_evolution_plugin_la_LDFLAGS = -module -avoid-version -liborg_freedesktop_Tracker_evolution_plugin_la_LIBADD = \ - $(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_EVOLUTION_LIBS) - -BUILT_SOURCES = $(eplugin_DATA) - -CLEANFILES = \ - $(BUILT_SOURCES) \ - $(eplugin_DATA) - -EXTRA_DIST = org-freedesktop-Tracker-evolution-plugin.eplug.xml - -# 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.EMails.service - -INTLTOOL_SERVICE_RULE='%.service: %.service.in $(INTLTOOL_MERGE) $(wildcard $(top_srcdir)/po/*.po) ; $(INTLTOOL_MERGE) $(top_srcdir)/po $< [$]@ -d -u' -@INTLTOOL_SERVICE_RULE@ - -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)" - -# Dist / Clean rules for all data -CLEANFILES += \ - $(autostart_DATA) \ - $(desktop_in_files) \ - $(service_DATA) \ - $(service_DATA:.service=.service.in) - -EXTRA_DIST += \ - $(desktop_in_in_files) \ - $(service_DATA:.service=.service.in.in) diff --git a/src/plugins/evolution/org-freedesktop-Tracker-evolution-plugin.eplug.xml b/src/plugins/evolution/org-freedesktop-Tracker-evolution-plugin.eplug.xml deleted file mode 100644 index 658c2040f..000000000 --- a/src/plugins/evolution/org-freedesktop-Tracker-evolution-plugin.eplug.xml +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0"?> -<e-plugin-list> - <e-plugin id="org.freedesktop.Tracker1.evolution_plugin" - type="shlib" - location="+PLUGIN_INSTALL_DIR+/liborg-freedesktop-Tracker-evolution-plugin.so" - domain="+GETTEXT_PACKAGE+" - localedir="+LOCALEDIR+" - _name="Tracker" - load-on-startup="after-ui"> - - <_description>Push data to Tracker to make it queryable.</_description> - - <author name="Philip Van Hoof" email="philip@codeminded.be"/> - </e-plugin> -</e-plugin-list> diff --git a/src/plugins/evolution/org.freedesktop.Tracker1.Miner.EMails.service.in.in b/src/plugins/evolution/org.freedesktop.Tracker1.Miner.EMails.service.in.in deleted file mode 100644 index e9b233eed..000000000 --- a/src/plugins/evolution/org.freedesktop.Tracker1.Miner.EMails.service.in.in +++ /dev/null @@ -1,7 +0,0 @@ -[D-BUS Service] -Name=org.freedesktop.Tracker1.Miner.Emails - -# Miner details needed for tracker-control -Path=/org/freedesktop/Tracker1/Miner/Emails -_DisplayName=Emails -_Comment=Evolution Email miner diff --git a/src/plugins/evolution/tracker-evolution-plugin.c b/src/plugins/evolution/tracker-evolution-plugin.c deleted file mode 100644 index 94c6cc87b..000000000 --- a/src/plugins/evolution/tracker-evolution-plugin.c +++ /dev/null @@ -1,2583 +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. - * - * Authors: - * Philip Van Hoof <philip@codeminded.be> - * Martyn Russell <martyn@lanedo.com> - */ - -#include "config.h" - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/wait.h> -#include <fcntl.h> -#include <errno.h> -#include <signal.h> -#include <string.h> -#include <pthread.h> -#include <signal.h> -#include <time.h> -#include <inttypes.h> - -#include <glib/gi18n-lib.h> -#include <glib-object.h> -#include <gio/gio.h> - -#include <sqlite3.h> - -/* This is why you should seal your headers with one include for - * client sanity. This is the horendous shit we've had to put up with - * for years from the Evo shell API :( - */ -#if defined(EVOLUTION_SHELL_3_3_5) -#include <libemail-engine/e-mail-folder-utils.h> -#include <libemail-engine/e-mail-session.h> -#include <libemail-engine/mail-config.h> -#include <libemail-engine/mail-ops.h> -#include <libemail-utils/e-account-utils.h> -#elif defined(EVOLUTION_SHELL_3_2) -#include <mail/em-utils.h> -#include <mail/e-mail.h> -#include <mail/mail-config.h> -#include <mail/mail-ops.h> -#include <e-util/e-account-utils.h> -#elif defined(EVOLUTION_SHELL_2_91) -#include <mail/e-mail.h> -#include <mail/mail-config.h> -#include <mail/mail-ops.h> -#include <e-util/e-account-utils.h> -#else /* OLDER, mostly 2.32 or so */ -#include <mail/mail-config.h> -#include <mail/mail-ops.h> -#include <mail/mail-session.h> -#include <e-util/e-account-utils.h> -#endif - -/* Remaining includes which are in ALL versions: */ -#include <mail/e-mail-backend.h> -#include <shell/e-shell.h> - -#include <e-util/e-config.h> - -#include <libedataserver/e-account.h> -#include <libedataserver/e-account-list.h> -#include <libedataserver/eds-version.h> - -/* Back to sanity */ -#include <libtracker-sparql/tracker-ontologies.h> -#include <libtracker-sparql/tracker-sparql.h> - -#include <libtracker-common/tracker-date-time.h> -#include <libtracker-common/tracker-utils.h> -#include <libtracker-common/tracker-type-utils.h> - -#include "tracker-evolution-plugin.h" - -/* This runs in-process of evolution (in the mailer, as a EPlugin). It has - * access to the CamelSession using the external variable 'session'. The header - * mail/mail-session.h makes this variable public */ - -/* Note to people who are scared about this plugin using the CamelDB directly: - * The code uses camel_db_clone to create a new connection to the DB. We hope - * that's sufficient for not having to lock the store instances (sqlite3 has - * its own locks, and we only clone the db_r instance, we also only ever do - * reads, never writes). We hope that's sufficient for not having to get our - * code involved in Camel's cruel inneryard of having to lock the db_r ptr. */ - -#define TRACKER_SERVICE "org.freedesktop.Tracker1" -#define DATASOURCE_URN "urn:nepomuk:datasource:1cb1eb90-1241-11de-8c30-0800200c9a66" -#define TRACKER_EVOLUTION_GRAPH_URN "urn:uuid:9a96d750-5182-11e0-b8af-0800200c9a66" - -#define UIDS_CHUNK_SIZE 200 - -#define TRACKER_MINER_EVOLUTION_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), TRACKER_TYPE_MINER_EVOLUTION, TrackerMinerEvolutionPrivate)) - -/* Some helper-defines (Copied from cruel Camel code, might be wrong as soon as - * the cruel and nasty Camel coders decide to change the format of the fields in - * the database) - guys, encoding things in fields of a table in a database is - * cruel and prone to error. Anyway). */ - -#define CAMEL_CALLBACK(func) ((CamelObjectEventHookFunc) func) -#define EXTRACT_STRING(val) if (*part) part++; len=strtoul (part, &part, 10); if (*part) part++; val=g_strndup (part, len); part+=len; -#define EXTRACT_FIRST_DIGIT(val) val=strtoul (part, &part, 10); - -/* About the locks being used: Camel's API must be used in a multi-threaded - * fashion. Therefore it's necessary to guard against concurrent access of - * memory. Especially given that both the mainloop and the Camel-threads will - * be accessing the memory (mainloop for DBus calls, and Camel-threads mostly - * during registration of accounts and folders). I know this is cruel. I know. */ - -typedef struct { - GThreadPool *pool; - GList *items; - GMutex *mutex; - GFunc func, freeup; - gboolean dying; - GCancellable *cancel; -} ThreadPool; - -typedef struct { - TrackerMinerEvolution *self; /* weak */ - guint64 last_checkout; -} ClientRegistry; - -typedef struct { - TrackerMinerEvolution *self; - gchar *account_uri; - guint hook_id; -} OnSummaryChangedInfo; - -typedef struct { - OnSummaryChangedInfo *hook_info; - CamelFolder *folder; -} FolderRegistry; - -typedef struct { - EAccount *account; - TrackerMinerEvolution *self; - guint hook_id; - CamelStore *store; -} StoreRegistry; - -typedef struct { - TrackerMinerEvolution *self; - gchar *account_uri; - ClientRegistry *info; -} IntroductionInfo; - -typedef struct { - TrackerMinerEvolution *self; - gchar *uri; - gboolean old_state; - EAccount *account; -} RegisterInfo; - -typedef struct { - GHashTable *registered_folders; - GHashTable *cached_folders; - GHashTable *registered_stores; - GList *registered_clients; - EAccountList *accounts; - time_t last_time; - gboolean resuming, paused; - guint total_popped, of_total; - guint watch_name_id; - GCancellable *sparql_cancel; - GTimer *timer_since_stopped; -} TrackerMinerEvolutionPrivate; - -typedef struct { - IntroductionInfo *intro_info; - CamelStore *store; - CamelFolderInfo *iter; -} TryAgainInfo; - -typedef struct { - TrackerMinerEvolution *self; - gchar *account_uri; - CamelFolderInfo *iter; -} GetFolderInfo; - -typedef struct { - IntroductionInfo *intro_info; - CamelFolderInfo *iter; - CamelStore *store; -} WorkerThreadinfo; - -/* Prototype declarations */ -int e_plugin_lib_enable (EPlugin *ep, - int enable); - -static void register_account (TrackerMinerEvolution *self, - EAccount *account); -static void unregister_account (TrackerMinerEvolution *self, - EAccount *account); -static void miner_evolution_initable_iface_init (GInitableIface *iface); -static gboolean miner_evolution_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error); -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 miner_start_watching (TrackerMiner *miner); -static void miner_stop_watching (TrackerMiner *miner); - -static GInitableIface *miner_evolution_initable_parent_iface; -static TrackerMinerEvolution *manager = NULL; - -static GStaticRecMutex glock = G_STATIC_REC_MUTEX_INIT; -static guint register_count = 0; -static guint walk_count = 0; -static ThreadPool *folder_pool = NULL; - -#ifdef EVOLUTION_SHELL_2_91 -static EMailSession *session = NULL; -#endif - -G_DEFINE_TYPE_WITH_CODE (TrackerMinerEvolution, tracker_miner_evolution, TRACKER_TYPE_MINER, - G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, - miner_evolution_initable_iface_init)); - -/* First a bunch of helper functions. */ -static void -get_email_and_fullname (const gchar *line, - gchar **email, - gchar **fullname) -{ - gchar *ptr = g_utf8_strchr (line, -1, '<'); - - if (ptr) { - gchar *holder; - - holder = g_strdup (line); - ptr = g_utf8_strchr (holder, -1, '<'); - *ptr = '\0'; - ptr++; - *fullname = holder; - holder = ptr; - ptr = g_utf8_strchr (ptr, -1, '>'); - if (ptr) { - *ptr = '\0'; - } - *email = g_strdup (holder); - - } else { - *email = g_strdup (line); - *fullname = NULL; - } -} - -static void -folder_registry_free (FolderRegistry *registry) -{ - g_signal_handler_disconnect (registry->folder, registry->hook_info->hook_id); - g_object_unref (registry->folder); - g_free (registry->hook_info->account_uri); - g_slice_free (OnSummaryChangedInfo, registry->hook_info); - g_slice_free (FolderRegistry, registry); -} - -static FolderRegistry* -folder_registry_new (const gchar *account_uri, - CamelFolder *folder, - TrackerMinerEvolution *self) -{ - FolderRegistry *registry = g_slice_new (FolderRegistry); - - registry->hook_info = g_slice_new (OnSummaryChangedInfo); - registry->hook_info->account_uri = g_strdup (account_uri); - registry->hook_info->self = self; /* weak */ - registry->hook_info->hook_id = 0; - g_object_ref (folder); - registry->folder = folder; - - return registry; -} - -static void -thread_pool_exec (gpointer data, - gpointer user_data) -{ - ThreadPool *pool = user_data; - gboolean dying; - - g_mutex_lock (pool->mutex); - dying = pool->dying; - pool->items = g_list_remove (pool->items, data); - g_mutex_unlock (pool->mutex); - - if (!dying) - pool->func (data, pool->cancel); - - pool->freeup (data, pool->cancel); -} - -static ThreadPool* -thread_pool_new (GFunc func, - GFunc freeup, - GCompareDataFunc sorter) -{ - ThreadPool *wrap = g_new0 (ThreadPool, 1); - - wrap->pool = g_thread_pool_new (thread_pool_exec, wrap, 1, FALSE, NULL); - if (sorter) - g_thread_pool_set_sort_function (wrap->pool, sorter, NULL); - wrap->items = NULL; - wrap->dying = FALSE; - wrap->func = func; - wrap->freeup = freeup; - wrap->mutex = g_mutex_new (); - wrap->cancel = g_cancellable_new (); - - return wrap; -} - -static void -thread_pool_push (ThreadPool *pool, - gpointer item, - gpointer user_data) -{ - g_mutex_lock (pool->mutex); - pool->items = g_list_prepend (pool->items, item); - if (!pool->dying) - g_thread_pool_push (pool->pool, item, user_data); - g_mutex_unlock (pool->mutex); -} - -static gpointer -destroyer_thread (gpointer user_data) -{ - ThreadPool *pool = user_data; - - g_mutex_lock (pool->mutex); - g_thread_pool_free (pool->pool, TRUE, TRUE); - g_list_foreach (pool->items, pool->freeup, NULL); - g_mutex_unlock (pool->mutex); - - g_object_unref (pool->cancel); - g_free (pool); - - return NULL; -} - -static void -thread_pool_destroy (ThreadPool *pool) -{ - g_mutex_lock (pool->mutex); - g_cancellable_cancel (pool->cancel); - pool->dying = TRUE; - g_mutex_unlock (pool->mutex); - - g_thread_create (destroyer_thread, pool, FALSE, NULL); -} - -static void -send_sparql_update (TrackerMinerEvolution *self, - const gchar *sparql, - gint prio) -{ - TrackerMinerEvolutionPrivate *priv; - - /* FIXME: prio is unused */ - - g_static_rec_mutex_lock (&glock); - - priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (self); - - if (!priv->timer_since_stopped || g_timer_elapsed (priv->timer_since_stopped, NULL) > 5) { - TrackerSparqlConnection *connection; - - connection = tracker_miner_get_connection (TRACKER_MINER (self)); - - if (connection) { - tracker_sparql_connection_update (connection, - sparql, - G_PRIORITY_DEFAULT, - priv->sparql_cancel, - NULL); - } - } - - g_static_rec_mutex_unlock (&glock); -} - -static void -send_sparql_commit (TrackerMinerEvolution *self, - gboolean update) -{ - if (update) { - gchar *date_s = tracker_date_to_string (time (NULL)); - - /* TODO: We should probably do this per folder instead of a datasource - * for the entire Evolution store. This way if the user interrupts - * the synchronization, then at least the folders that are already - * finished don't have to be repeated next time. Right now an interrupt - * means starting over from scratch. */ - - gchar *update = g_strdup_printf ("DELETE { <" DATASOURCE_URN "> nie:contentLastModified ?d } " - "WHERE { <" DATASOURCE_URN "> a nie:InformationElement ; nie:contentLastModified ?d } \n" - "INSERT { <" DATASOURCE_URN "> a nie:InformationElement ; nie:contentLastModified \"%s\" }", - date_s); - - send_sparql_update (self, update, 0); - - g_free (update); - g_free (date_s); - } -} - -static void -add_contact (TrackerSparqlBuilder *sparql, - const gchar *predicate, - const gchar *uri, - const gchar *value) -{ - gchar *email = NULL; - gchar *fullname = NULL; - gchar *email_uri; - - get_email_and_fullname (value, &email, &fullname); - - email_uri = g_strdup_printf ("mailto:%s", email); - - tracker_sparql_builder_subject_iri (sparql, email_uri); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nco:EmailAddress"); - - tracker_sparql_builder_subject_iri (sparql, email_uri); - tracker_sparql_builder_predicate (sparql, "nco:emailAddress"); - tracker_sparql_builder_object_string (sparql, email); - - tracker_sparql_builder_subject_iri (sparql, uri); - tracker_sparql_builder_predicate (sparql, predicate); - - tracker_sparql_builder_object_blank_open (sparql); - - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nco:Contact"); - - if (fullname) { - tracker_sparql_builder_predicate (sparql, "nco:fullname"); - tracker_sparql_builder_object_string (sparql, fullname); - } - - tracker_sparql_builder_predicate (sparql, "nco:hasEmailAddress"); - tracker_sparql_builder_object_iri (sparql, email_uri); - - tracker_sparql_builder_object_blank_close (sparql); - g_free (email_uri); - - g_free (email); - g_free (fullname); -} - -static void -process_fields (TrackerSparqlBuilder *sparql, - const gchar *uid, - guint flags, - time_t sent, - const gchar *subject, - const gchar *from, - const gchar *to, - const gchar *cc, - const gchar *size, - CamelFolder *folder, - const gchar *uri) -{ - gchar **arr; - guint i; - - tracker_sparql_builder_subject_iri (sparql, DATASOURCE_URN); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nie:DataSource"); - - /* for contentLastModified */ - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nie:InformationElement"); - - tracker_sparql_builder_subject_iri (sparql, uri); - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nmo:Email"); - - tracker_sparql_builder_predicate (sparql, "a"); - tracker_sparql_builder_object (sparql, "nmo:MailboxDataObject"); - - tracker_sparql_builder_predicate (sparql, "tracker:available"); - tracker_sparql_builder_object_boolean (sparql, TRUE); - - /* Laying the link between the IE and the DO. We use IE = DO */ - tracker_sparql_builder_predicate (sparql, "nie:isStoredAs"); - tracker_sparql_builder_object_iri (sparql, uri); - - /* 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:dataSource"); - tracker_sparql_builder_object_iri (sparql, DATASOURCE_URN); - - if (size && g_utf8_validate (size, -1, NULL)) { - tracker_sparql_builder_predicate (sparql, "nie:byteSize"); - tracker_sparql_builder_object_string (sparql, size); - } - - if (subject && g_utf8_validate (subject, -1, NULL)) { - tracker_sparql_builder_predicate (sparql, "nmo:messageSubject"); - tracker_sparql_builder_object_string (sparql, subject); - } - - tracker_sparql_builder_predicate (sparql, "nmo:receivedDate"); - tracker_sparql_builder_object_date (sparql, &sent); - - tracker_sparql_builder_predicate (sparql, "nmo:isDeleted"); - tracker_sparql_builder_object_boolean (sparql, (flags & CAMEL_MESSAGE_DELETED)); - - tracker_sparql_builder_predicate (sparql, "nmo:isAnswered"); - tracker_sparql_builder_object_boolean (sparql, (flags & CAMEL_MESSAGE_ANSWERED)); - - tracker_sparql_builder_predicate (sparql, "nmo:isFlagged"); - tracker_sparql_builder_object_boolean (sparql, (flags & CAMEL_MESSAGE_FLAGGED)); - - tracker_sparql_builder_predicate (sparql, "nmo:isRead"); - tracker_sparql_builder_object_boolean (sparql, (flags & CAMEL_MESSAGE_SEEN)); - - /* - g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_UID)); - g_ptr_array_add (values_temp, g_strdup (uid)); - - g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_JUNK)); - g_ptr_array_add (values_temp, g_strdup ((flags & CAMEL_MESSAGE_JUNK) ? "True" : "False")); - - g_ptr_array_add (predicates_temp, g_strdup (TRACKER_EVOLUTION_PREDICATE_FORWARDED)); - g_ptr_array_add (values_temp, g_strdup ((flags & CAMEL_MESSAGE_FORWARDED) ? "True" : "False")); - */ - - if (to && (arr = g_strsplit (to, ",", -1)) != NULL) { - for (i = 0; arr[i]; i++) { - g_strstrip (arr[i]); - - if (g_utf8_validate (arr[i], -1, NULL)) { - add_contact (sparql, "nmo:to", uri, arr[i]); - } - } - g_strfreev (arr); - } - - if (from && g_utf8_validate (from, -1, NULL)) { - add_contact (sparql, "nmo:from", uri, from); - } - - if (cc && (arr = g_strsplit (cc, ",", -1)) != NULL) { - for (i = 0; arr[i]; i++) { - g_strstrip (arr[i]); - if (g_utf8_validate (arr[i], -1, NULL)) { - add_contact (sparql, "nmo:cc", uri, arr[i]); - } - } - g_strfreev (arr); - } -} - -static gchar * -message_uri_build (CamelFolder *folder, - const gchar *uid) -{ -#ifdef EVOLUTION_SHELL_3_2 - gchar *uri, *folder_uri; - - folder_uri = e_mail_folder_uri_from_folder (folder); - uri = g_strdup_printf ("%s#%s", folder_uri, uid); - g_free (folder_uri); - - return uri; -#else /* EVOLUTION_SHELL_3_2 */ - CamelURL *a_url, *url; - const gchar *path; - gchar *uri, *qry, *ppath; - - a_url = CAMEL_SERVICE (camel_folder_get_parent_store (folder))->url; - path = camel_folder_get_full_name (folder); - - ppath = g_strdup_printf ("/%s", path); - - /* This converts a CamelURL plus path and uid components to a Evolution - * compatible URL. Evolution has its own strange URL format, so .. ok */ - - url = camel_url_copy (a_url); - - /* This would be the right way, but em_uri_from_camel ignores ?uid=x parts, - * so instead we append it manually with a g_strdup_printf lower - * - * qry = g_strdup_printf ("uid=%s", uid); - * camel_url_set_query (url, qry); - * g_free (qry); */ - - camel_url_set_path (url, ppath); - g_free (ppath); - uri = camel_url_to_string (url, CAMEL_URL_HIDE_ALL); - - qry = em_uri_from_camel (uri); - g_free (uri); - uri = g_strdup_printf ("%s?uid=%s", qry, uid); - g_free (qry); - camel_url_free (url); - - return uri; -#endif /* EVOLUTION_SHELL_3_2 */ -} - -/* When new messages arrive to- or got deleted from the summary, called in - * mainloop or by a thread (unknown, depends on Camel and Evolution code that - * executes the reason why this signal gets emitted). - * - * This one is the reason why we registered all those folders during init below. - */ -static void -on_folder_summary_changed (CamelFolder *folder, - CamelFolderChangeInfo *changes, - gpointer user_data) -{ - OnSummaryChangedInfo *info = user_data; - CamelFolderSummary *summary; - GPtrArray *merged; - gboolean did_work; - guint i; - - if (!folder) - return; - - summary = folder->summary; - - merged = g_ptr_array_new (); - did_work = FALSE; - - /* the uid_added member contains the added-to-the-summary items */ - - if (changes->uid_added && changes->uid_added->len > 0) { - for (i = 0; i < changes->uid_added->len; i++) { - g_ptr_array_add (merged, changes->uid_added->pdata[i]); - } - } - - /* the uid_changed member contains the changed-in-the-summary items */ - - if (changes->uid_changed && changes->uid_changed->len > 0) { - guint y; - - for (i = 0; i < changes->uid_changed->len; i++) { - gboolean found = FALSE; - - for (y = 0; y < merged->len; y++) { - if (strcmp (merged->pdata[y], changes->uid_changed->pdata[i]) == 0) { - found = TRUE; - break; - } - } - - if (!found) { - g_ptr_array_add (merged, changes->uid_changed->pdata[i]); - } - } - } - - for (i = 0; i< merged->len; i++) { - const gchar *subject, *to, *from, *cc, *uid = NULL; - time_t sent; - guint flags; - CamelMessageInfo *linfo; - const CamelTag *ctags; - const CamelFlag *cflags; - gchar *full_sparql; - -#if EDS_CHECK_VERSION(3,3,1) - linfo = camel_folder_summary_get (summary, merged->pdata[i]); -#else - linfo = camel_folder_summary_uid (summary, merged->pdata[i]); -#endif - - if (linfo) { - uid = (gchar *) camel_message_info_uid (linfo); - } - - if (linfo && uid) { - gchar *uri; - gchar *size; - gchar *str; - const gchar *folder_name; - TrackerSparqlBuilder *sparql; - - subject = camel_message_info_subject (linfo); - to = camel_message_info_to (linfo); - from = camel_message_info_from (linfo); - cc = camel_message_info_cc (linfo); - flags = (guint) camel_message_info_flags (linfo); - - /* Camel returns a time_t, I think a uint64 is the best fit here */ - sent = camel_message_info_date_sent (linfo); - - /* Camel returns a uint32, so %u */ - size = g_strdup_printf ("%u", camel_message_info_size (linfo)); - - /* This is not a path but a URI, don't use the - * OS's directory separator here */ - - uri = message_uri_build (folder, uid); - - sparql = tracker_sparql_builder_new_update (); - - tracker_sparql_builder_insert_silent_open (sparql, NULL); - tracker_sparql_builder_graph_open (sparql, TRACKER_EVOLUTION_GRAPH_URN); - - process_fields (sparql, uid, flags, sent, subject, - from, to, cc, size, folder, uri); - - cflags = camel_message_info_user_flags (linfo); - while (cflags) { - tracker_sparql_builder_subject_iri (sparql, uri); - - tracker_sparql_builder_predicate (sparql, "nao:hasTag"); - tracker_sparql_builder_object_blank_open (sparql); - - tracker_sparql_builder_predicate (sparql, "rdf:type"); - tracker_sparql_builder_object (sparql, "nao:Tag"); - - tracker_sparql_builder_predicate (sparql, "nao:prefLabel"); - tracker_sparql_builder_object_string (sparql, cflags->name); - tracker_sparql_builder_object_blank_close (sparql); - - cflags = cflags->next; - } - - ctags = camel_message_info_user_tags (linfo); - while (ctags) { - tracker_sparql_builder_subject_iri (sparql, uri); - - tracker_sparql_builder_predicate (sparql, "nao:hasProperty"); - tracker_sparql_builder_object_blank_open (sparql); - - tracker_sparql_builder_predicate (sparql, "rdf:type"); - tracker_sparql_builder_object (sparql, "nao:Property"); - - tracker_sparql_builder_predicate (sparql, "nao:propertyName"); - tracker_sparql_builder_object_string (sparql, ctags->name); - - tracker_sparql_builder_predicate (sparql, "nao:propertyValue"); - tracker_sparql_builder_object_string (sparql, ctags->value); - - tracker_sparql_builder_object_blank_close (sparql); - ctags = ctags->next; - } - - tracker_sparql_builder_graph_close (sparql); - tracker_sparql_builder_insert_close (sparql); - - full_sparql = g_strdup_printf ("DELETE {" - " GRAPH <%s> {" - " <%s> ?p ?o" - " } " - "} " - "WHERE {" - " GRAPH <%s> {" - " <%s> ?p ?o" - " FILTER (?p != rdf:type && ?p != nie:contentCreated)" - " } " - "} " - "%s", - TRACKER_EVOLUTION_GRAPH_URN, - uri, - TRACKER_EVOLUTION_GRAPH_URN, - uri, - tracker_sparql_builder_get_result (sparql)); - - send_sparql_update (info->self, full_sparql, 100); - - g_free (full_sparql); - - /* FIXME: Actually report accurate percentages and don't spam */ - g_debug ("Tracker plugin setting progress to '%2.2f' and status to 'Updating an E-mail'", - (gdouble) i / merged->len); - -#ifdef EVOLUTION_SHELL_3_2 - folder_name = camel_folder_get_display_name (folder); -#else /* EVOLUTION_SHELL_3_2 */ - folder_name = camel_folder_get_name (folder); -#endif /* EVOLUTION_SHELL_3_2 */ - - if (folder_name && *folder_name) { - str = g_strdup_printf ("Updating E-mails for %s", - folder_name); - } else { - str = g_strdup ("Updating E-mails"); - } - - g_object_set (info->self, "progress", - (gdouble) i / merged->len, - "status", str, - NULL); - - g_free (str); - g_object_unref (sparql); - - g_free (size); - g_free (uri); - } - - if (linfo) - camel_message_info_free (linfo); - } - - /* Set flag if we did work here */ - did_work = merged->len > 0; - - g_ptr_array_free (merged, TRUE); - - /* the uid_removed member contains the removed-from-the-summary items */ - - if (changes->uid_removed && changes->uid_removed->len > 0) { - /* The FROM uri is not exactly right here, but we just want - * graph != NULL in tracker-store/tracker-writeback.c */ - GString *sparql = g_string_new (""); - - for (i = 0; i < changes->uid_removed->len; i++) { - gchar *uri; - - g_object_set (info->self, - "progress", (gdouble) i / changes->uid_removed->len, - "status", "Cleaning up deleted E-mails", - NULL); - - /* This is not a path but a URI, don't use the OS's - * directory separator here */ - uri = message_uri_build (folder, (char*) changes->uid_removed->pdata[i]); - - g_string_append_printf (sparql, "DELETE FROM <%s> { <%s> a rdfs:Resource }\n ", uri, uri); - g_free (uri); - } - - send_sparql_update (info->self, sparql->str, 100); - g_string_free (sparql, TRUE); - - /* Set flag if we did work here */ - did_work = TRUE; - } - - send_sparql_commit (info->self, FALSE); - - if (did_work) { - g_debug ("Tracker plugin setting progress to '1.0' and status to 'Idle'"); - g_object_set (info->self, "progress", 1.0, "status", "Idle", NULL); - } -} - -static gchar * -uids_to_chunk (GPtrArray *uids, - guint cur, - guint max) -{ - guint i; - GString *str = g_string_new (""); - - for (i = 0; i < max && i < uids->len; i++) { - if (i != 0) { - g_string_append (str, ", "); - } - g_string_append (str, g_ptr_array_index (uids, i)); - } - - return g_string_free (str, FALSE); -} - -/* Initial upload of more recent than last_checkout items, called in the mainloop */ -static void -introduce_walk_folders_in_folder (TrackerMinerEvolution *self, - CamelFolderInfo *iter, - CamelStore *store, - gchar *account_uri, - ClientRegistry *info, - GCancellable *cancel) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (self); - CamelDB *cdb_r; - gboolean did_work; - - if (g_cancellable_is_cancelled (cancel)) { - return; - } - - cdb_r = camel_db_clone (store->cdb_r, NULL); - did_work = FALSE; - - while (iter) { - guint uids_i; - guint count = 0; - guint ret = SQLITE_OK; - gchar *query, *status; - sqlite3_stmt *stmt = NULL; - GPtrArray *uids = g_ptr_array_new_with_free_func (g_free); - - /* might happen when folder is not loaded/opened yet */ - if (!priv->cached_folders || !g_hash_table_lookup (priv->cached_folders, iter->full_name)) { - iter = iter->next; - g_ptr_array_unref (uids); - continue; - } - - did_work = TRUE; - - query = sqlite3_mprintf ("SELECT uid FROM %Q " - "WHERE modified > %"G_GUINT64_FORMAT, - iter->full_name, - info->last_checkout); - -#ifdef EVOLUTION_SHELL_3_2 - status = g_strdup_printf ("Processing folder %s", iter->display_name); -#else /* EVOLUTION_SHELL_3_2 */ - status = g_strdup_printf ("Processing folder %s", iter->name); -#endif /* EVOLUTION_SHELL_3_2 */ - g_object_set (self, "progress", 0.01, "status", status, NULL); - - ret = sqlite3_prepare_v2 (cdb_r->db, query, -1, &stmt, NULL); - while (ret == SQLITE_OK || ret == SQLITE_BUSY || ret == SQLITE_ROW) { - gchar *uid; - - if (g_cancellable_is_cancelled (cancel)) - break; - ret = sqlite3_step (stmt); - if (ret == SQLITE_BUSY) { - usleep (10); - continue; - } - if ((ret != SQLITE_OK && ret != SQLITE_ROW) || ret == SQLITE_DONE) - break; - - uid = (gchar *) sqlite3_column_text (stmt, 0); - - if (uid) { - g_ptr_array_add (uids, g_strdup (uid)); - } - } - - sqlite3_finalize (stmt); - sqlite3_free (query); - - for (uids_i = 0; uids_i < uids->len; uids_i += UIDS_CHUNK_SIZE) { - gchar *uids_chunk = uids_to_chunk (uids, uids_i, UIDS_CHUNK_SIZE); - - /* This query is the culprint of the functionality: it fetches - * all the metadata from the summary table where modified is - * more recent than the client-registry's modseq. Note that we - * pass time(NULL) to all methods, which is why comparing - * against the modified column that Evolution > 2.25.5 stores - * works (otherwise this wouldn't work, of course). - * - * The idea is that only the changes must initially be pushed, - * not everything each time (which would be unefficient). The - * specification (http://live.gnome.org/Evolution/Metadata) - * allows this 'modseq' optimization (is in fact recommending - * it over using Cleanup() each time) */ - - /* TODO: add bodystructure and then prepare a full MIME structure - * using the NMO ontology, by parsing the bodystructure. - * Bodystructures can be found in %s_bodystructure when they - * exist (not guaranteed). In IMAP BODYSTRUCTURE format. */ - - query = sqlite3_mprintf ("SELECT uid, flags, read, deleted, " /* 0 - 3 */ - "replied, important, junk, attachment, " /* 4 - 7 */ - "size, dsent, dreceived, subject, " /* 8 - 11 */ - "mail_from, mail_to, mail_cc, mlist, " /* 12 - 15 */ - "labels, usertags " /* 16 - 17 */ - "FROM %Q " - "WHERE modified > %"G_GUINT64_FORMAT" " - "AND uid IN (%s)", - iter->full_name, - info->last_checkout, - uids_chunk); - - g_free (uids_chunk); - - ret = sqlite3_prepare_v2 (cdb_r->db, query, -1, &stmt, NULL); - - while (ret == SQLITE_OK || ret == SQLITE_BUSY || ret == SQLITE_ROW) { - TrackerSparqlBuilder *sparql = NULL; - gchar *subject, *to, *from, *cc, *uid, *size; - time_t sent; - gchar *part, *label, *p; - guint flags; - - if (g_cancellable_is_cancelled (cancel)) - break; - ret = sqlite3_step (stmt); - if (ret == SQLITE_BUSY) { - usleep (10); - continue; - } - if ((ret != SQLITE_OK && ret != SQLITE_ROW) || ret == SQLITE_DONE) - break; - - uid = (gchar *) sqlite3_column_text (stmt, 0); - - if (uid) { - CamelFolder *folder; - guint max = 0, j; - gchar *uri; - gboolean opened = FALSE; - gchar *full_sparql; - - flags = (guint ) sqlite3_column_int (stmt, 1); - size = (gchar *) sqlite3_column_text (stmt, 8); - sent = (time_t) sqlite3_column_int64 (stmt, 9); - subject = (gchar *) sqlite3_column_text (stmt, 11); - from = (gchar *) sqlite3_column_text (stmt, 12); - to = (gchar *) sqlite3_column_text (stmt, 13); - cc = (gchar *) sqlite3_column_text (stmt, 14); - - folder = g_hash_table_lookup (priv->cached_folders, iter->full_name); - - uri = message_uri_build (folder, uid); - - if (!sparql) { - sparql = tracker_sparql_builder_new_update (); - } - - tracker_sparql_builder_insert_silent_open (sparql, NULL); - tracker_sparql_builder_graph_open (sparql, TRACKER_EVOLUTION_GRAPH_URN); - - process_fields (sparql, uid, flags, sent, - subject, from, to, cc, size, - folder, uri); - - /* Extract User flags/labels */ - p = part = g_strdup ((const gchar *) sqlite3_column_text (stmt, 16)); - if (part) { - label = part; - for (j=0; part[j]; j++) { - - if (part[j] == ' ') { - part[j] = 0; - - if (!opened) { - tracker_sparql_builder_subject_iri (sparql, uri); - opened = TRUE; - } - - tracker_sparql_builder_predicate (sparql, "nao:hasTag"); - tracker_sparql_builder_object_blank_open (sparql); - - tracker_sparql_builder_predicate (sparql, "rdf:type"); - tracker_sparql_builder_object (sparql, "nao:Tag"); - - tracker_sparql_builder_predicate (sparql, "nao:prefLabel"); - tracker_sparql_builder_object_string (sparql, label); - tracker_sparql_builder_object_blank_close (sparql); - label = &(part[j+1]); - } - } - } - g_free (p); - - /* Extract User tags */ - p = part = g_strdup ((const gchar *) sqlite3_column_text (stmt, 17)); - EXTRACT_FIRST_DIGIT (max) - for (j = 0; j < max; j++) { - int len; - char *name, *value; - EXTRACT_STRING (name) - EXTRACT_STRING (value) - if (name && g_utf8_validate (name, -1, NULL) && - value && g_utf8_validate (value, -1, NULL)) { - - if (!opened) { - tracker_sparql_builder_subject_iri (sparql, uri); - opened = TRUE; - } - - tracker_sparql_builder_predicate (sparql, "nao:hasProperty"); - tracker_sparql_builder_object_blank_open (sparql); - - tracker_sparql_builder_predicate (sparql, "rdf:type"); - tracker_sparql_builder_object (sparql, "nao:Property"); - - tracker_sparql_builder_predicate (sparql, "nao:propertyName"); - tracker_sparql_builder_object_string (sparql, name); - - tracker_sparql_builder_predicate (sparql, "nao:propertyValue"); - tracker_sparql_builder_object_string (sparql, value); - - tracker_sparql_builder_object_blank_close (sparql); - } - g_free(name); - g_free(value); - } - - g_free (p); - - tracker_sparql_builder_graph_close (sparql); - tracker_sparql_builder_insert_close (sparql); - - full_sparql = g_strdup_printf ("DELETE {" - " GRAPH <%s> {" - " <%s> ?p ?o" - " } " - "} " - "WHERE {" - " GRAPH <%s> {" - " <%s> ?p ?o" - " FILTER (?p != rdf:type && ?p != nie:contentCreated)" - " } " - "} " - "%s", - TRACKER_EVOLUTION_GRAPH_URN, - uri, - TRACKER_EVOLUTION_GRAPH_URN, - uri, - tracker_sparql_builder_get_result (sparql)); - - g_free (uri); - count++; - send_sparql_update (self, full_sparql, 0); - g_free (full_sparql); - g_object_unref (sparql); - } - } - - g_debug ("Tracker plugin setting progress to '%f' and status to '%s'", - ((gdouble) uids_i / (gdouble) uids->len), - status); - g_object_set (self, "progress", - ((gdouble) uids_i / (gdouble) uids->len), - "status", status, - NULL); - - sqlite3_finalize (stmt); - sqlite3_free (query); - } - - send_sparql_commit (self, FALSE); - - if (iter->child) { - introduce_walk_folders_in_folder (self, iter->child, - store, - account_uri, info, - cancel); - } - - iter = iter->next; - g_ptr_array_unref (uids); - g_free (status); - } - - if (did_work) { - g_debug ("Tracker plugin setting progress to '1.0' and status to 'Idle'"); - g_object_set (self, "progress", 1.0, "status", "Idle", NULL); - } - - camel_db_close (cdb_r); -} - -/* Initial notify of deletes that are more recent than last_checkout, called in - * the mainloop */ - -static void -introduce_store_deal_with_deleted (TrackerMinerEvolution *self, - CamelStore *store, - char *account_uri, - gpointer user_data) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (self); - ClientRegistry *info = user_data; - gboolean more = TRUE; - gchar *query; - sqlite3_stmt *stmt = NULL; - CamelDB *cdb_r; - guint i, ret; - - query = sqlite3_mprintf ("SELECT uid, mailbox " - "FROM Deletes " - "WHERE modified > %" G_GUINT64_FORMAT, - info->last_checkout); - - /* This creates a thread apparently */ - cdb_r = camel_db_clone (store->cdb_r, NULL); - - sqlite3_prepare_v2 (cdb_r->db, query, -1, &stmt, NULL); - - ret = SQLITE_OK; - - while (more) { - GPtrArray *subjects_a = g_ptr_array_new (); - guint count = 0; - - more = FALSE; - - while (ret == SQLITE_OK || ret == SQLITE_BUSY || ret == SQLITE_ROW) { - CamelFolder *folder; - const gchar *uid; - const gchar *mailbox; - - ret = sqlite3_step (stmt); - - if (ret == SQLITE_BUSY) { - usleep (10); - continue; - } - - if ((ret != SQLITE_OK && ret != SQLITE_ROW) || ret == SQLITE_DONE) { - more = FALSE; - break; - } - - uid = (const gchar *) sqlite3_column_text (stmt, 0); - mailbox = (const gchar *) sqlite3_column_text (stmt, 1); - - folder = priv->cached_folders ? g_hash_table_lookup (priv->cached_folders, mailbox) : NULL; - - /* might happen when folder is not loaded/opened yet */ - if (!folder) { - more = FALSE; - break; - } - - /* This is not a path but a URI, don't use the OS's - * directory separator here */ - - g_ptr_array_add (subjects_a, - message_uri_build (folder, uid)); - - if (count > 100) { - more = TRUE; - break; - } - - count++; - - more = FALSE; - } - - if (count > 0) { - /* The FROM uri is not exactly right here, but we just want - * graph != NULL in tracker-store/tracker-writeback.c */ - - GString *sparql = g_string_new (""); - - for (i = 0; i < subjects_a->len; i++) { - g_string_append_printf (sparql, "DELETE FROM <%s> { <%s> a rdfs:Resource } \n", - (gchar *) g_ptr_array_index (subjects_a, i), - (gchar *) g_ptr_array_index (subjects_a, i)); - } - - g_string_append_c (sparql, '}'); - - send_sparql_update (self, sparql->str, 100); - g_string_free (sparql, TRUE); - - } - - g_ptr_array_free (subjects_a, TRUE); - - } - - send_sparql_commit (self, FALSE); - - sqlite3_finalize (stmt); - sqlite3_free (query); - - camel_db_close (cdb_r); -} - -/* Get the oldest date in all of the deleted-tables, called in the mainloop. We - * need this to test whether we should use Cleanup() or not. */ - -static guint64 -get_last_deleted_time (TrackerMinerEvolution *self) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (self); - guint64 smallest = (guint64) time (NULL); - - if (priv->accounts) { - EIterator *it; - - for (it = e_list_get_iterator (E_LIST (priv->accounts)); e_iterator_is_valid (it); e_iterator_next (it)) { - EAccount *account = (EAccount *) e_iterator_get (it); - CamelProvider *provider; - CamelStore *store; - char *uri; - CamelDB *cdb_r; - sqlite3_stmt *stmt = NULL; - gchar *query; - guint ret = SQLITE_OK; - guint64 latest = smallest; - - if (!account->enabled || !(uri = account->source->url)) - continue; - - if (!(provider = camel_provider_get(uri, NULL))) { - continue; - } - - if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE)) { - continue; - } - - if (!(store = (CamelStore *) camel_session_get_service (CAMEL_SESSION (session), -#ifdef EVOLUTION_SHELL_3_2 - account->uid))) { -#else /* EVOLUTION_SHELL_3_2 */ - uri, - CAMEL_PROVIDER_STORE, - NULL))) { -#endif /* EVOLUTION_SHELL_3_2 */ - continue; - } - - cdb_r = camel_db_clone (store->cdb_r, NULL); - - query = sqlite3_mprintf ("SELECT time " - "FROM Deletes " - "ORDER BY time LIMIT 1"); - - ret = sqlite3_prepare_v2 (cdb_r->db, query, -1, &stmt, NULL); - - ret = sqlite3_step (stmt); - - if (ret == SQLITE_OK || ret == SQLITE_ROW) { - latest = sqlite3_column_int64 (stmt, 0); - } - - if (latest < smallest) { - smallest = latest; - } - - sqlite3_finalize (stmt); - sqlite3_free (query); - - camel_db_close (cdb_r); - } - - g_object_unref (it); - } - - return smallest; -} - -#ifdef EVOLUTION_SHELL_3_2 -static void -register_on_get_folder (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - CamelFolder *folder = camel_store_get_folder_finish (CAMEL_STORE (source_object), res, NULL); -#else /* EVOLUTION_SHELL_3_2 */ -static void -register_on_get_folder (gchar *uri, - CamelFolder *folder, - gpointer user_data) -{ -#endif /* EVOLUTION_SHELL_3_2 */ - GetFolderInfo *info = user_data; - gchar *account_uri = info->account_uri; - CamelFolderInfo *iter = info->iter; - TrackerMinerEvolution *self = info->self; - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (self); - guint hook_id; - FolderRegistry *registry; - - if (!folder) { - goto fail_register; - } - - registry = folder_registry_new (account_uri, folder, self); - - if (!priv->registered_folders || !priv->cached_folders) { - goto not_ready; - } - - hook_id = g_signal_connect (folder, "changed", - G_CALLBACK (on_folder_summary_changed), - registry->hook_info); - registry->hook_info->hook_id = hook_id; - - g_hash_table_replace (priv->registered_folders, - GINT_TO_POINTER (hook_id), - registry); - - g_hash_table_replace (priv->cached_folders, - g_strdup (iter->full_name), - folder); - - not_ready: - fail_register: - - camel_folder_info_free (info->iter); - g_free (info->account_uri); - g_object_unref (info->self); - g_free (info); - - register_count--; -} - -static void -register_walk_folders_in_folder (TrackerMinerEvolution *self, - CamelFolderInfo *iter, - CamelStore *store, - gchar *account_uri) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (self); - - if (!priv->registered_folders) { - priv->registered_folders = g_hash_table_new_full (g_direct_hash, g_direct_equal, - (GDestroyNotify) NULL, - (GDestroyNotify) folder_registry_free); - - priv->cached_folders = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_object_unref); - } - - /* Recursively walks all the folders in store */ - - while (iter) { - GetFolderInfo *info = g_new0 (GetFolderInfo, 1); - - info->self = g_object_ref (self); - info->account_uri = g_strdup (account_uri); - info->iter = camel_folder_info_clone (iter); - - register_count++; - - /* This is asynchronous and hooked to the mail/ API, so nicely - * integrated with the Evolution UI application */ - -#ifdef EVOLUTION_SHELL_3_2 - camel_store_get_folder (store, - iter->full_name, - 0, - 0, - NULL, - register_on_get_folder, - info); -#else /* EVOLUTION_SHELL_3_2 */ - mail_get_folder ( -#ifdef EVOLUTION_SHELL_2_91 - session, -#endif /* EVOLUTION_SHELL_2_91 */ - iter->uri, - 0, - register_on_get_folder, - info, - mail_msg_unordered_push); -#endif /* EVOLUTION_SHELL_3_2 */ - - if (iter->child) { - register_walk_folders_in_folder (self, iter->child, - store, - account_uri); - } - - iter = iter->next; - } -} - -#ifdef EVOLUTION_SHELL_3_2 -static void -unregister_on_get_folder (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - CamelFolder *folder = camel_store_get_folder_finish (CAMEL_STORE (source_object), res, NULL); -#else /* EVOLUTION_SHELL_3_2 */ -static void -unregister_on_get_folder (gchar *uri, - CamelFolder *folder, - gpointer user_data) -{ -#endif /* EVOLUTION_SHELL_3_2 */ - GetFolderInfo *info = user_data; - CamelFolderInfo *titer = info->iter; - TrackerMinerEvolution *self = info->self; - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (self); - GHashTableIter iter; - gpointer key, value; - - if (!folder) { - goto fail_unregister; - } - - if (!priv->registered_folders) { - goto no_folders; - } - - g_hash_table_iter_init (&iter, priv->registered_folders); - while (g_hash_table_iter_next (&iter, &key, &value)) { - FolderRegistry *registry = value; - - if (folder == registry->folder) { - g_hash_table_remove (priv->cached_folders, titer->full_name); - g_hash_table_iter_remove (&iter); - break; - } - } - - no_folders: - fail_unregister: - - camel_folder_info_free (info->iter); - g_free (info->account_uri); - g_object_unref (info->self); - g_free (info); - - g_object_unref (folder); -} - -static void -unregister_walk_folders_in_folder (TrackerMinerEvolution *self, - CamelFolderInfo *titer, - CamelStore *store, - gchar *account_uri) -{ - /* Recursively walks all the folders in store */ - - while (titer) { - GetFolderInfo *info = g_new0 (GetFolderInfo, 1); - - info->self = g_object_ref (self); - info->account_uri = g_strdup (account_uri); - info->iter = camel_folder_info_clone (titer); - - /* This is asynchronous and hooked to the mail/ API, so nicely - * integrated with the Evolution UI application */ - -#ifdef EVOLUTION_SHELL_3_2 - camel_store_get_folder (store, - titer->full_name, - 0, - 0, - NULL, - unregister_on_get_folder, - info); -#else /* EVOLUTION_SHELL_3_2 */ - mail_get_folder ( -#ifdef EVOLUTION_SHELL_2_91 - session, -#endif /* EVOLUTION_SHELL_2_91 */ - titer->uri, - 0, - unregister_on_get_folder, - info, - mail_msg_unordered_push); -#endif /* EVOLUTION_SHELL_3_2 */ - - if (titer->child) { - unregister_walk_folders_in_folder (self, titer->child, - store, - account_uri); - } - - titer = titer->next; - } -} - -static void -client_registry_info_free (ClientRegistry *info) -{ - g_slice_free (ClientRegistry, info); -} - -static ClientRegistry* -client_registry_info_copy (ClientRegistry *info) -{ - ClientRegistry *ninfo = g_slice_new0 (ClientRegistry); - - ninfo->last_checkout = info->last_checkout; - - return ninfo; -} - -static void -free_introduction_info (IntroductionInfo *intro_info) -{ - client_registry_info_free (intro_info->info); - g_free (intro_info->account_uri); - g_object_unref (intro_info->self); - g_free (intro_info); -} - -static void -free_worker_thread_info (gpointer data, - gpointer user_data) -{ - WorkerThreadinfo *winfo = data; - - /* Ownership was transfered to us in try_again */ - free_introduction_info (winfo->intro_info); - g_object_unref (winfo->store); - camel_folder_info_free (winfo->iter); - g_free (winfo); -} - -static void -folder_worker (gpointer data, - gpointer user_data) -{ - WorkerThreadinfo *winfo = data; - - introduce_walk_folders_in_folder (winfo->intro_info->self, - winfo->iter, - winfo->store, - winfo->intro_info->account_uri, - winfo->intro_info->info, - user_data); - - send_sparql_commit (winfo->intro_info->self, TRUE); - - return; -} - -/* For info about this try-again stuff, look at on_got_folderinfo_introduce */ - -static gboolean -try_again (gpointer user_data) -{ - if (register_count == 0) { - TryAgainInfo *info = user_data; - WorkerThreadinfo *winfo = g_new (WorkerThreadinfo, 1); - - winfo->intro_info = info->intro_info; /* owner transfer */ - winfo->iter = info->iter; /* owner transfer */ - winfo->store = info->store; /* owner transfer */ - - if (!folder_pool) - folder_pool = thread_pool_new (folder_worker, free_worker_thread_info, NULL); - - thread_pool_push (folder_pool, winfo, NULL); - - return FALSE; - } - - return TRUE; -} - -#ifdef EVOLUTION_SHELL_3_2 -static void -on_got_folderinfo_introduce (GObject *source_object, - GAsyncResult *res, - gpointer data) -{ - CamelStore *store = CAMEL_STORE (source_object); - CamelFolderInfo *iter = camel_store_get_folder_info_finish (store, res, NULL); -#else /* EVOLUTION_SHELL_3_2 */ -static gboolean -on_got_folderinfo_introduce (CamelStore *store, - CamelFolderInfo *iter, - void *data) -{ -#endif /* EVOLUTION_SHELL_3_2 */ - TryAgainInfo *info = g_new0 (TryAgainInfo, 1); - - /* Ownership of these is transfered in try_again */ - - g_object_ref (store); - info->store = store; - /* This apparently creates a thread */ - info->iter = camel_folder_info_clone (iter); - info->intro_info = data; - - /* If a registrar is running while Evolution is starting up, we decide - * not to slow down Evolution's startup by immediately going through - * all CamelFolder instances (the UI is doing the same thing, we can - * better allow the UI to do this first, and cache the folders that - * way) - * - * Regretfully doesn't Evolution's plugin interfaces give me a better - * hook to detect the startup of the UI application of Evolution, else - * it would of course be better to use that instead. - * - * The register_count is the amount of folders that we register, a - * registry has been made asynchronous using the high-level API - * mail_get_folder, so in the callback we decrement the number, before - * the call we increment the number. If we're at zero, it means we're - * fully initialized. If not, we wait ten seconds and retry until - * finally we're fully initialized. (it's not as magic as it looks) */ - - if (register_count != 0) { - g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, 1, - try_again, info, - (GDestroyNotify) g_free); - } else { - try_again (info); - g_free (info); - } - -#ifdef EVOLUTION_SHELL_3_2 - camel_store_free_folder_info (store, iter); -#else /* EVOLUTION_SHELL_3_2 */ - return TRUE; -#endif /* EVOLUTION_SHELL_3_2 */ -} - -static void -introduce_account_to (TrackerMinerEvolution *self, - EAccount *account, - ClientRegistry *info) -{ - CamelProvider *provider; - CamelStore *store; - char *uri, *account_uri, *ptr; - IntroductionInfo *intro_info; - - if (!account->enabled || !(uri = account->source->url)) - return; - - if (!(provider = camel_provider_get(uri, NULL))) { - return; - } - - if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE)) - return; - - if (!(store = (CamelStore *) camel_session_get_service (CAMEL_SESSION (session), -#ifdef EVOLUTION_SHELL_3_2 - account->uid))) { -#else /* EVOLUTION_SHELL_3_2 */ - uri, - CAMEL_PROVIDER_STORE, - NULL))) { -#endif /* EVOLUTION_SHELL_3_2 */ - return; - } - - account_uri = g_strdup (uri); - - ptr = strchr (account_uri, ';'); - - if (ptr) - *ptr = '\0'; - - introduce_store_deal_with_deleted (self, store, account_uri, info); - - intro_info = g_new0 (IntroductionInfo, 1); - - intro_info->self = g_object_ref (self); - intro_info->info = client_registry_info_copy (info); - intro_info->account_uri = account_uri; /* is freed in on_got above */ - -#ifdef EVOLUTION_SHELL_3_2 - camel_store_get_folder_info (store, - NULL, - CAMEL_STORE_FOLDER_INFO_FAST | - CAMEL_STORE_FOLDER_INFO_RECURSIVE | - CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, - G_PRIORITY_DEFAULT, - NULL, - on_got_folderinfo_introduce, - intro_info); -#else /* EVOLUTION_SHELL_3_2 */ - mail_get_folderinfo (store, NULL, on_got_folderinfo_introduce, intro_info); -#endif /* EVOLUTION_SHELL_3_2 */ - -#ifndef EVOLUTION_SHELL_3_2 - g_object_unref (store); -#endif /* EVOLUTION_SHELL_3_2 */ - -} - -static void -introduce_account_to_all (TrackerMinerEvolution *self, - EAccount *account) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (self); - GList *copy = priv->registered_clients; - - while (copy) { - ClientRegistry *info = copy->data; - introduce_account_to (self, account, info); - copy = g_list_next (copy); - } - -} - -static void -introduce_accounts_to (TrackerMinerEvolution *self, - ClientRegistry *info) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (self); - EIterator *it; - - for (it = e_list_get_iterator (E_LIST (priv->accounts)); e_iterator_is_valid (it); e_iterator_next (it)) { - introduce_account_to (self, (EAccount *) e_iterator_get (it), info); - } - - g_object_unref (it); -} - -static void -register_client_second_half (ClientRegistry *info) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (info->self); - guint64 too_old = get_last_deleted_time (info->self); - - /* If registrar's modseq is too old, send Cleanup (). This means that - * we tell it to start over (it must invalidate what it has). */ - - if (info->last_checkout < too_old) { - send_sparql_update (info->self, "DELETE { ?s a rdfs:Resource } " - "WHERE { ?s nie:dataSource <" DATASOURCE_URN "> }", 0); - send_sparql_commit (info->self, FALSE); - - info->last_checkout = 0; - } - - priv->last_time = info->last_checkout; - - introduce_accounts_to (info->self, info); - - priv->registered_clients = - g_list_prepend (priv->registered_clients, info); -} - -static void -on_register_client_qry (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - TrackerSparqlCursor *cursor; - ClientRegistry *info = user_data; - TrackerMinerEvolutionPrivate *priv; - GError *error = NULL; - - priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (info->self); - cursor = tracker_sparql_connection_query_finish (TRACKER_SPARQL_CONNECTION (source_object), - res, &error); - - if (error) { - g_warning ("%s\n", error->message); - g_error_free (error); - g_slice_free (ClientRegistry, info); - if (cursor) { - g_object_unref (cursor); - } - return; - } - - if (!tracker_sparql_cursor_next (cursor, NULL, NULL)) { - if (priv->resuming) { - info->last_checkout = priv->last_time; - } else if (priv->resuming && priv->last_time != 0) { - info->last_checkout = priv->last_time; - } else { - info->last_checkout = 0; - } - } else { - do { - const gchar *str = tracker_sparql_cursor_get_string (cursor, 0, NULL); - GError *new_error = NULL; - - info->last_checkout = (guint64) tracker_string_to_date (str, NULL, &new_error); - - if (new_error) { - g_warning ("%s", new_error->message); - g_error_free (error); - g_object_unref (cursor); - return; - } - - break; - } while (tracker_sparql_cursor_next (cursor, NULL, NULL)); - } - - register_client_second_half (info); - - g_object_unref (cursor); -} - -static void -register_client (TrackerMinerEvolution *self) -{ - TrackerMinerEvolutionPrivate *priv; - TrackerSparqlConnection *connection; - ClientRegistry *info; - const gchar *query; - - priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (self); - - connection = tracker_miner_get_connection (TRACKER_MINER (self)); - if (!connection) { - return; - } - - info = g_slice_new0 (ClientRegistry); - info->self = self; /* weak */ - - priv->total_popped = 0; - priv->of_total = 0; - - query = "SELECT ?c " - "WHERE { <" DATASOURCE_URN "> nie:contentLastModified ?c }"; - - tracker_sparql_connection_query_async (connection, - query, - NULL, /* FIXME: should use a cancellable */ - on_register_client_qry, - info); -} - - -static void -on_folder_created (CamelStore *store, - void *event_data, - StoreRegistry *registry) -{ - unregister_account (registry->self, registry->account); - register_account (registry->self, registry->account); - introduce_account_to_all (registry->self, registry->account); -} - -static void -on_folder_deleted (CamelStore *store, - void *event_data, - StoreRegistry *registry) -{ - unregister_account (registry->self, registry->account); - register_account (registry->self, registry->account); - introduce_account_to_all (registry->self, registry->account); -} - -static void -on_folder_renamed (CamelStore *store, - gchar *old_name, - StoreRegistry *registry) -{ - unregister_account (registry->self, registry->account); - register_account (registry->self, registry->account); - introduce_account_to_all (registry->self, registry->account); -} - -static StoreRegistry* -store_registry_new (gpointer co, - EAccount *account, - TrackerMinerEvolution *self) -{ - StoreRegistry *registry = g_slice_new (StoreRegistry); - - registry->store = co; - registry->account = account; /* weak */ - registry->self = self; /* weak */ - g_object_ref (co); - - return registry; -} - -static void -store_registry_free (StoreRegistry *registry) -{ - g_signal_handler_disconnect (registry->store, registry->hook_id); - g_object_unref (registry->store); - g_slice_free (StoreRegistry, registry); -} - - -#ifdef EVOLUTION_SHELL_3_2 -static void -on_got_folderinfo_register (GObject *source_object, - GAsyncResult *res, - gpointer data) -{ - CamelStore *store = CAMEL_STORE (source_object); - CamelFolderInfo *iter = camel_store_get_folder_info_finish (store, res, NULL); -#else /* EVOLUTION_SHELL_3_2 */ -static gboolean -on_got_folderinfo_register (CamelStore *store, - CamelFolderInfo *iter, - void *data) -{ -#endif /* EVOLUTION_SHELL_3_2 */ - RegisterInfo *reg_info = data; - TrackerMinerEvolution *self = reg_info->self; - TrackerMinerEvolutionPrivate *priv; - EAccount *account = reg_info->account; - StoreRegistry *registry; - gchar *uri = reg_info->uri; - guint hook_id; - - priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (self); - - /* This is where it all starts for a registrar registering itself */ - - if (!priv->registered_stores) { - priv->registered_stores = g_hash_table_new_full (g_direct_hash, g_direct_equal, - (GDestroyNotify) NULL, - (GDestroyNotify) store_registry_free); - } - - /* Hook up catching folder changes in the store */ - registry = store_registry_new (store, account, self); - hook_id = g_signal_connect (store, "folder-created", - G_CALLBACK (on_folder_created), - registry); - registry->hook_id = hook_id; - g_hash_table_replace (priv->registered_stores, - GINT_TO_POINTER (hook_id), - registry); - - registry = store_registry_new (store, account, self); - hook_id = g_signal_connect (store, "folder-renamed", - G_CALLBACK (on_folder_renamed), - registry); - registry->hook_id = hook_id; - g_hash_table_replace (priv->registered_stores, - GINT_TO_POINTER (hook_id), - registry); - - registry = store_registry_new (store, account, self); - hook_id = g_signal_connect (store, "folder-deleted", - G_CALLBACK (on_folder_deleted), - registry); - registry->hook_id = hook_id; - g_hash_table_replace (priv->registered_stores, - GINT_TO_POINTER (hook_id), - registry); - - /* Register each folder to hook folder_changed everywhere (recursive) */ - register_walk_folders_in_folder (self, iter, store, uri); - - g_object_unref (reg_info->account); - g_object_unref (reg_info->self); - g_free (reg_info->uri); - g_free (reg_info); - - walk_count--; - -#ifdef EVOLUTION_SHELL_3_2 - camel_store_free_folder_info (store, iter); -#else /* EVOLUTION_SHELL_3_2 */ - return TRUE; -#endif /* EVOLUTION_SHELL_3_2 */ -} - -static void -register_account (TrackerMinerEvolution *self, - EAccount *account) -{ - CamelProvider *provider; - CamelStore *store; - char *uri; - RegisterInfo *reg_info; - - if (!account->enabled || !(uri = account->source->url)) { - return; - } - - if (!(provider = camel_provider_get (uri, NULL))) { - return; - } - - if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE)) { - return; - } - - if (!(store = (CamelStore *) camel_session_get_service (CAMEL_SESSION (session), -#ifdef EVOLUTION_SHELL_3_2 - account->uid))) { -#else /* EVOLUTION_SHELL_3_2 */ - uri, - CAMEL_PROVIDER_STORE, - NULL))) { -#endif /* EVOLUTION_SHELL_3_2 */ - return; - } - - reg_info = g_new0 (RegisterInfo, 1); - - reg_info->self = g_object_ref (self); - reg_info->uri = g_strdup (uri); - reg_info->account = g_object_ref (account); - - walk_count++; - - /* Get the account's folder-info and register it asynchronously */ -#ifdef EVOLUTION_SHELL_3_2 - camel_store_get_folder_info (store, - NULL, - CAMEL_STORE_FOLDER_INFO_FAST | - CAMEL_STORE_FOLDER_INFO_RECURSIVE | - CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, - G_PRIORITY_DEFAULT, - NULL, - on_got_folderinfo_register, - reg_info); -#else /* EVOLUTION_SHELL_3_2 */ - mail_get_folderinfo (store, NULL, on_got_folderinfo_register, reg_info); -#endif /* EVOLUTION_SHELL_3_2 */ - -#ifndef EVOLUTION_SHELL_3_2 - g_object_unref (store); -#endif /* EVOLUTION_SHELL_3_2 */ -} - -#ifdef EVOLUTION_SHELL_3_2 -static void -on_got_folderinfo_unregister (GObject *source_object, - GAsyncResult *res, - gpointer data) -{ - CamelStore *store = CAMEL_STORE (source_object); - CamelFolderInfo *titer = camel_store_get_folder_info_finish (store, res, NULL); -#else /* EVOLUTION_SHELL_3_2 */ -static gboolean -on_got_folderinfo_unregister (CamelStore *store, - CamelFolderInfo *titer, - void *data) -{ -#endif /* EVOLUTION_SHELL_3_2 */ - RegisterInfo *reg_info = data; - TrackerMinerEvolution *self = reg_info->self; - TrackerMinerEvolutionPrivate *priv; - gchar *uri = reg_info->uri; - GHashTableIter iter; - gpointer key, value; - - priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (self); - unregister_walk_folders_in_folder (self, titer, store, uri); - - if (priv->registered_stores) { - g_hash_table_iter_init (&iter, priv->registered_stores); - - while (g_hash_table_iter_next (&iter, &key, &value)) { - if (value == store) - g_hash_table_iter_remove (&iter); - } - } - - g_object_unref (reg_info->self); - g_free (reg_info->uri); - g_free (reg_info); - -#ifdef EVOLUTION_SHELL_3_2 - camel_store_free_folder_info (store, titer); -#else /* EVOLUTION_SHELL_3_2 */ - return TRUE; -#endif /* EVOLUTION_SHELL_3_2 */ -} - -static void -unregister_account (TrackerMinerEvolution *self, - EAccount *account) -{ - CamelProvider *provider; - CamelStore *store; - char *uri = account->source->url; - RegisterInfo *reg_info; - - if (!(provider = camel_provider_get(uri, NULL))) { - return; - } - - if (!(provider->flags & CAMEL_PROVIDER_IS_STORAGE)) - return; - - if (!(store = (CamelStore *) camel_session_get_service (CAMEL_SESSION (session), -#ifdef EVOLUTION_SHELL_3_2 - account->uid))) { -#else /* EVOLUTION_SHELL_3_2 */ - uri, - CAMEL_PROVIDER_STORE, - NULL))) { -#endif /* EVOLUTION_SHELL_3_2 */ - return; - } - - reg_info = g_new0 (RegisterInfo, 1); - - reg_info->self = g_object_ref (self); - reg_info->uri = g_strdup (uri); - reg_info->account = NULL; - - /* Get the account's folder-info and unregister asynchronously */ -#ifdef EVOLUTION_SHELL_3_2 - camel_store_get_folder_info (store, - NULL, - CAMEL_STORE_FOLDER_INFO_FAST | - CAMEL_STORE_FOLDER_INFO_RECURSIVE | - CAMEL_STORE_FOLDER_INFO_SUBSCRIBED, - G_PRIORITY_DEFAULT, - NULL, - on_got_folderinfo_unregister, - reg_info); -#else /* EVOLUTION_SHELL_3_2 */ - mail_get_folderinfo (store, NULL, on_got_folderinfo_unregister, reg_info); -#endif /* EVOLUTION_SHELL_3_2 */ - -#ifndef EVOLUTION_SHELL_3_2 - g_object_unref (store); -#endif /* EVOLUTION_SHELL_3_2 */ -} - -static void -on_account_added (EAccountList *list, - EAccount *account, - TrackerMinerEvolution *self) -{ - register_account (self, account); - introduce_account_to_all (self, account); -} - -static void -on_account_removed (EAccountList *list, - EAccount *account, - TrackerMinerEvolution *self) -{ - unregister_account (self, account); -} - -static void -on_account_changed (EAccountList *list, - EAccount *account, - TrackerMinerEvolution *self) -{ - unregister_account (self, account); - register_account (self, account); - introduce_account_to_all (self, account); -} - -static void -disable_plugin (void) -{ - g_debug ("Tracker plugin disabled"); - - if (folder_pool) { - ThreadPool *pool = folder_pool; - folder_pool = NULL; - thread_pool_destroy (pool); - } - - if (manager) { - g_object_unref (manager); - manager = NULL; - } -} - -static void -enable_plugin_real (void) -{ - GError *error = NULL; - - g_debug ("Tracker plugin creating new object..."); - - manager = g_initable_new (TRACKER_TYPE_MINER_EVOLUTION, - NULL, - &error, - "name", "Emails", - NULL); - - if (error) { - g_critical ("Could not start Tracker plugin, %s", error->message); - g_error_free (error); - return; - } - - tracker_miner_start (TRACKER_MINER (manager)); -} - -static gboolean -enable_plugin_try (gpointer user_data) -{ - if (walk_count == 0) { - enable_plugin_real (); - return FALSE; - } - - g_debug ("Tracker plugin already enabled, doing nothing"); - - return TRUE; -} - -static void -miner_prepare (TrackerMinerEvolutionPrivate *priv) -{ - if (priv->timer_since_stopped && g_timer_elapsed (priv->timer_since_stopped, NULL) > 5) { - g_timer_destroy (priv->timer_since_stopped); - priv->timer_since_stopped = NULL; - } -} - -static void -miner_cleanup (TrackerMinerEvolutionPrivate *priv) -{ - if (folder_pool) { - ThreadPool *pool = folder_pool; - - folder_pool = NULL; - thread_pool_destroy (pool); - } - - if (!priv->timer_since_stopped) { - priv->timer_since_stopped = g_timer_new (); - } - - if (priv->sparql_cancel) { - /* We reuse the cancellable */ - g_cancellable_cancel (priv->sparql_cancel); - } -} - -static void -enable_plugin (void) -{ - g_debug ("Tracker Evolution plugin enabled"); - - /* Deal with https://bugzilla.gnome.org/show_bug.cgi?id=606940 */ - - if (manager) { - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (manager); - - miner_cleanup (priv); - g_object_unref (manager); - } - - if (walk_count > 0) { - g_timeout_add_seconds_full (G_PRIORITY_DEFAULT, 1, enable_plugin_try, NULL, NULL); - } else { - enable_plugin_real (); - } -} - -int -e_plugin_lib_enable (EPlugin *ep, - int enabled) -{ - g_static_rec_mutex_lock (&glock); - - if (enabled) { - enable_plugin (); - } else { - disable_plugin (); - } - - g_static_rec_mutex_unlock (&glock); - - return 0; -} - -static void -miner_evolution_initable_iface_init (GInitableIface *iface) -{ - miner_evolution_initable_parent_iface = g_type_interface_peek_parent (iface); - iface->init = miner_evolution_initable_init; -} - -static gboolean -miner_evolution_initable_init (GInitable *initable, - GCancellable *cancellable, - GError **error) -{ - GError *inner_error = NULL; - - /* Chain up parent's initable callback before calling child's one */ - if (!miner_evolution_initable_parent_iface->init (initable, cancellable, &inner_error)) { - g_propagate_error (error, inner_error); - return FALSE; - } - - return TRUE; -} - -static void -tracker_miner_evolution_finalize (GObject *plugin) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (plugin); - - if (priv->registered_folders) { - g_hash_table_unref (priv->registered_folders); - g_hash_table_unref (priv->cached_folders); - priv->cached_folders = NULL; - priv->registered_folders = NULL; - } - - if (priv->registered_stores) { - g_hash_table_unref (priv->registered_stores); - priv->registered_stores = NULL; - } - - g_object_unref (priv->accounts); - - miner_cleanup (priv); - - if (priv->timer_since_stopped) { - g_timer_destroy (priv->timer_since_stopped); - priv->timer_since_stopped = NULL; - } - - if (priv->sparql_cancel) { - g_cancellable_cancel (priv->sparql_cancel); - g_object_unref (priv->sparql_cancel); - } - - G_OBJECT_CLASS (tracker_miner_evolution_parent_class)->finalize (plugin); -} - -static void -tracker_miner_evolution_class_init (TrackerMinerEvolutionClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - TrackerMinerClass *miner_class = TRACKER_MINER_CLASS (klass); - - g_setenv ("TRACKER_SPARQL_BACKEND", "bus", TRUE); - - miner_class->started = miner_started; - miner_class->stopped = miner_stopped; - miner_class->paused = miner_paused; - miner_class->resumed = miner_resumed; - - object_class->finalize = tracker_miner_evolution_finalize; - - g_type_class_add_private (object_class, sizeof (TrackerMinerEvolutionPrivate)); -} - -static void -tracker_miner_evolution_init (TrackerMinerEvolution *plugin) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (plugin); - EIterator *it; - -#ifdef EVOLUTION_SHELL_2_91 - if (!session) { - EShell *shell; - EShellBackend *shell_backend; - - shell = e_shell_get_default (); - shell_backend = e_shell_get_backend_by_name (shell, "mail"); - session = e_mail_backend_get_session (E_MAIL_BACKEND (shell_backend)); - } -#endif /* EVOLUTION_SHELL_2_91 */ - - priv->sparql_cancel = g_cancellable_new (); - - priv->last_time = 0; - priv->resuming = FALSE; - priv->paused = FALSE; - - priv->cached_folders = NULL; - priv->registered_folders = NULL; - priv->registered_stores = NULL; - priv->registered_clients = NULL; - - priv->accounts = g_object_ref (e_get_account_list ()); - - for (it = e_list_get_iterator (E_LIST (priv->accounts)); e_iterator_is_valid (it); e_iterator_next (it)) { - register_account (plugin, (EAccount *) e_iterator_get (it)); - } - - g_object_unref (it); - - g_signal_connect (priv->accounts, "account-added", - G_CALLBACK (on_account_added), plugin); - g_signal_connect (priv->accounts, "account-removed", - G_CALLBACK (on_account_removed), plugin); - g_signal_connect (priv->accounts, "account-changed", - G_CALLBACK (on_account_changed), plugin); -} - -static void -on_tracker_store_appeared (GDBusConnection *d_connection, - const gchar *name, - const gchar *name_owner, - gpointer user_data) - -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (user_data); - - miner_prepare (priv); - - register_client (user_data); -} - -static void -miner_start_watching (TrackerMiner *miner) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (miner); - - priv->watch_name_id = g_bus_watch_name (TRACKER_IPC_BUS, - TRACKER_SERVICE, - G_BUS_NAME_WATCHER_FLAGS_NONE, - on_tracker_store_appeared, - NULL, - miner, - NULL); -} - -static void -miner_stop_watching (TrackerMiner *miner) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (miner); - - if (priv->watch_name_id != 0) - g_bus_unwatch_name (priv->watch_name_id); - - miner_cleanup (priv); -} - -static void -miner_started (TrackerMiner *miner) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (miner); - - miner_prepare (priv); - - miner_start_watching (miner); - - g_debug ("Tracker plugin setting progress to '0.0' and status to 'Initializing'"); - g_object_set (miner, "progress", 0.0, "status", "Initializing", NULL); -} - -static void -miner_stopped (TrackerMiner *miner) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (miner); - - miner_paused (miner); - priv->paused = FALSE; -} - -static void -miner_paused (TrackerMiner *miner) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (miner); - - /* We don't really pause, we just completely stop */ - - miner_stop_watching (miner); - - priv->paused = TRUE; - priv->last_time = 0; - - miner_cleanup (priv); -} - -static gboolean -unset_resuming (gpointer data) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (data); - - priv->resuming = FALSE; - g_object_unref (data); - - return FALSE; -} - -static void -miner_resumed (TrackerMiner *miner) -{ - TrackerMinerEvolutionPrivate *priv = TRACKER_MINER_EVOLUTION_GET_PRIVATE (miner); - - /* We don't really resume, we just completely restart */ - - miner_prepare (priv); - - priv->resuming = TRUE; - priv->paused = FALSE; - priv->total_popped = 0; - priv->of_total = 0; - - g_debug ("Tracker plugin setting progress to '0.0' and status to 'Processing'"); - g_object_set (miner, "progress", 0.0, "status", _("Processing…"), NULL); - - miner_start_watching (miner); - - g_timeout_add_seconds (1, unset_resuming, g_object_ref (miner)); -} diff --git a/src/plugins/evolution/tracker-evolution-plugin.h b/src/plugins/evolution/tracker-evolution-plugin.h deleted file mode 100644 index dc78d6316..000000000 --- a/src/plugins/evolution/tracker-evolution-plugin.h +++ /dev/null @@ -1,51 +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. - * - * Authors: - * Philip Van Hoof <philip@codeminded.be> - */ - -#ifndef __TRACKER_MINER_EVOLUTION_H__ -#define __TRACKER_MINER_EVOLUTION_H__ - -#include <libtracker-miner/tracker-miner.h> - -#define TRACKER_TYPE_MINER_EVOLUTION (tracker_miner_evolution_get_type()) -#define TRACKER_MINER_EVOLUTION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TRACKER_TYPE_MINER_EVOLUTION, TrackerMinerEvolution)) -#define TRACKER_MINER_EVOLUTION_CLASS(c) (G_TYPE_CHECK_CLASS_CAST ((c), TRACKER_TYPE_MINER_EVOLUTION, TrackerMinerEvolutionClass)) -#define TRACKER_MINER_EVOLUTION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TRACKER_TYPE_MINER_EVOLUTION, TrackerMinerEvolutionClass)) - -G_BEGIN_DECLS - -typedef struct TrackerMinerEvolution TrackerMinerEvolution; -typedef struct TrackerMinerEvolutionClass TrackerMinerEvolutionClass; - -struct TrackerMinerEvolution { - TrackerMiner parent; -}; - -struct TrackerMinerEvolutionClass { - TrackerMinerClass parent; -}; - -GType tracker_miner_evolution_get_type (void); - - -G_END_DECLS - -#endif /* __TRACKER_MINER_EVOLUTION_H__ */ diff --git a/src/plugins/firefox/COPYRIGHT b/src/plugins/firefox/COPYRIGHT deleted file mode 100644 index 716e99751..000000000 --- a/src/plugins/firefox/COPYRIGHT +++ /dev/null @@ -1,15 +0,0 @@ -Tracker-Firefox - Tracker addon that exports data to Firefox -Copyright (C) 2011 Adrien Bustany <abustany@gnome.org> - -This program is free software: you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation, either version 2 of the License, or -(at your option) 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, see <http://www.gnu.org/licenses/>. diff --git a/src/plugins/firefox/Makefile.am b/src/plugins/firefox/Makefile.am deleted file mode 100644 index d45d19a82..000000000 --- a/src/plugins/firefox/Makefile.am +++ /dev/null @@ -1,17 +0,0 @@ -SUBDIRS = chrome defaults - -extensiondir = $(datadir)/xul-ext/trackerfox -extension_DATA = \ - install.rdf \ - chrome.manifest \ - README \ - COPYRIGHT - -EXTRA_DIST = $(extension_DATA) - -install-data-hook: - $(MKDIR_P) "$(DESTDIR)$(TRACKER_MINER_FIREFOX_INSTALL_DIR)" - $(LN_S) -f "$(extensiondir)" "$(DESTDIR)$(TRACKER_MINER_FIREFOX_INSTALL_DIR)/trackerfox@bustany.org" - -uninstall-hook: - $(RM) "$(DESTDIR)$(TRACKER_MINER_FIREFOX_INSTALL_DIR)/trackerfox@bustany.org" diff --git a/src/plugins/firefox/README b/src/plugins/firefox/README deleted file mode 100644 index 4c7658bbe..000000000 --- a/src/plugins/firefox/README +++ /dev/null @@ -1,8 +0,0 @@ -A simple bookmark exporter for Tracker - -This Firefox addon exports your bookmarks to Tracker, so that you can search -for them for example using tracker-needle. - -To generate the XPI from the git repository, use the following command: - -git archive --format=zip HEAD > tracker-firefox.xpi diff --git a/src/plugins/firefox/chrome.manifest b/src/plugins/firefox/chrome.manifest deleted file mode 100644 index ea1837ad1..000000000 --- a/src/plugins/firefox/chrome.manifest +++ /dev/null @@ -1,9 +0,0 @@ -content trackerfox chrome/content/ -skin trackerfox classic/1.0 chrome/skin/ -locale trackerfox en-US chrome/locale/en-US/ -locale trackerfox fr-FR chrome/locale/fr-FR/ -locale trackerfox es-ES chrome/locale/es-ES/ -locale trackerfox pl-PL chrome/locale/pl-PL/ - - -overlay chrome://browser/content/browser.xul chrome://trackerfox/content/ff-overlay.xul diff --git a/src/plugins/firefox/chrome/Makefile.am b/src/plugins/firefox/chrome/Makefile.am deleted file mode 100644 index 90fd0e7f3..000000000 --- a/src/plugins/firefox/chrome/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = skin locale content diff --git a/src/plugins/firefox/chrome/content/Makefile.am b/src/plugins/firefox/chrome/content/Makefile.am deleted file mode 100644 index 59db804cf..000000000 --- a/src/plugins/firefox/chrome/content/Makefile.am +++ /dev/null @@ -1,10 +0,0 @@ -extensiondir = $(datadir)/xul-ext/trackerfox/chrome/content -extension_DATA = \ - about.xul \ - bindings.js \ - bookmarks.js \ - ff-overlay.xul \ - namespace.js \ - plugin.js - -EXTRA_DIST = $(extension_DATA) diff --git a/src/plugins/firefox/chrome/content/about.xul b/src/plugins/firefox/chrome/content/about.xul deleted file mode 100644 index fc923a50d..000000000 --- a/src/plugins/firefox/chrome/content/about.xul +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> - -<!DOCTYPE dialog SYSTEM "chrome://trackerfox/locale/about.dtd"> - -<dialog title="&about; TrackerFox" orient="vertical" autostretch="always" onload="sizeToContent()" buttons="accept" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - <groupbox align="center" orient="horizontal"> - <vbox> - <text value="TrackerFox" style="font-weight: bold; font-size: x-large;"/> - <text value="&version; 1.0"/> - <separator class="thin"/> - <text value="&createdBy;" style="font-weight: bold;"/> - <text value="Adrien Bustany"/> - <separator class="thin"/> - </vbox> - </groupbox> -</dialog> diff --git a/src/plugins/firefox/chrome/content/bindings.js b/src/plugins/firefox/chrome/content/bindings.js deleted file mode 100644 index c809e2e18..000000000 --- a/src/plugins/firefox/chrome/content/bindings.js +++ /dev/null @@ -1,149 +0,0 @@ -if (!org.bustany.TrackerFox.TrackerSparql || !org.bustany.TrackerFox.TrackerSparql.__initialized) -org.bustany.TrackerFox.TrackerSparql = { - __initialized: true, - - _trackerSparqlPath1: "libtracker-sparql-1.0.so.0", - _trackerSparqlPath2: "libtracker-sparql-0.16.so.0", - _lib: null, - - init: function () { - var tracker = org.bustany.TrackerFox.TrackerSparql; - - // Safeguard just in case a fool would call that twice - if (tracker._lib) { - return true; - } - - Components.utils.import ("resource://gre/modules/ctypes.jsm"); - - try { - tracker._lib = ctypes.open (tracker._trackerSparqlPath1); - } catch (e) { - dump ("Could not load " + tracker._trackerSparqlPath1 + ": " + e + "\n"); - - try { - tracker._lib = ctypes.open (tracker._trackerSparqlPath2); - } catch (e) { - dump ("Could not load " + tracker._trackerSparqlPath2 + ": " + e + "\n"); - return false; - } - } - - // GLib types - tracker.Object = new ctypes.StructType ("GObject"); - tracker.Cancellable = new ctypes.StructType ("GCancellable"); - tracker.Error = new ctypes.StructType ("GError", [ - {domain : ctypes.uint32_t}, - {code : ctypes.int32_t}, - {message : ctypes.char.ptr} - ]); - tracker.AsyncResult = new ctypes.StructType ("GAsyncResult"); - tracker.AsyncReadyCallback = new ctypes.FunctionType( - ctypes.default_abi, - ctypes.void_t, - [ tracker.Object.ptr, tracker.AsyncResult.ptr, ctypes.voidptr_t ]); - - // TrackerSparql types - tracker.Connection = ctypes.StructType ("TrackerSparqlConnection"); - tracker.Cursor = ctypes.StructType ("TrackerSparqlCursor"); - - // GLib methods - tracker.object_unref = tracker._lib.declare ( - "g_object_unref", - ctypes.default_abi, - ctypes.void_t, - ctypes.void_t.ptr // Binding GObject* as a void* since we don't have GObject binding... - ); - - tracker.error_free = tracker._lib.declare ( - "g_error_free", - ctypes.default_abi, - ctypes.void_t, - tracker.Error.ptr - ); - - // TrackerSparql methods (name, ABI, args with first arg = return type) - tracker.connection_open = tracker._lib.declare ( - "tracker_sparql_connection_get", - ctypes.default_abi, - tracker.Connection.ptr, - tracker.Cancellable.ptr, - tracker.Error.ptr.ptr - ); - - tracker.connection_open_async = tracker._lib.declare ( - "tracker_sparql_connection_get_async", - ctypes.default_abi, - ctypes.void_t, - tracker.Cancellable.ptr, - tracker.AsyncReadyCallback.ptr, - ctypes.voidptr_t); - - tracker.connection_open_finish = tracker._lib.declare ( - "tracker_sparql_connection_get_finish", - ctypes.default_abi, - tracker.Connection.ptr, - tracker.AsyncResult.ptr, - tracker.Error.ptr.ptr); - - tracker.connection_query = tracker._lib.declare ( - "tracker_sparql_connection_query", - ctypes.default_abi, - tracker.Cursor.ptr, - tracker.Connection.ptr, - ctypes.char.ptr, - tracker.Cancellable.ptr, - tracker.Error.ptr.ptr - ); - - tracker.connection_update = tracker._lib.declare ( - "tracker_sparql_connection_update", - ctypes.default_abi, - ctypes.void_t, - tracker.Connection.ptr, - ctypes.char.ptr, - ctypes.int32_t, - tracker.Cancellable.ptr, - tracker.Error.ptr.ptr - ); - - tracker.cursor_next = tracker._lib.declare ( - "tracker_sparql_cursor_next", - ctypes.default_abi, - ctypes.bool, - tracker.Cursor.ptr, - tracker.Cancellable.ptr, - tracker.Error.ptr.ptr - ); - - tracker.cursor_get_string = tracker._lib.declare ( - "tracker_sparql_cursor_get_string", - ctypes.default_abi, - ctypes.char.ptr, - tracker.Cursor.ptr, - ctypes.int, - ctypes.long.ptr - ); - - tracker.escape_string = tracker._lib.declare ( - "tracker_sparql_escape_string", - ctypes.default_abi, - ctypes.char.ptr, - ctypes.char.ptr - ); - - return true; - }, - - shutdown: function () { - var tracker = org.bustany.TrackerFox.TrackerSparql; - - if (this._connection) { - tracker.object_unref(this._connection); - } - - if (this._lib) { - this._lib.close (); - } - } -} diff --git a/src/plugins/firefox/chrome/content/bookmarks.js b/src/plugins/firefox/chrome/content/bookmarks.js deleted file mode 100644 index eebf26a3f..000000000 --- a/src/plugins/firefox/chrome/content/bookmarks.js +++ /dev/null @@ -1,366 +0,0 @@ -if (!org.bustany.TrackerFox.Bookmarks || !org.bustany.TrackerFox.Bookmarks.__initialized) -org.bustany.TrackerFox.Bookmarks = { - __initialized: true, - - _tracker: org.bustany.TrackerFox.TrackerSparql, - _connection: null, - _dataSourceUrn: "urn:nepomuk:datasource:4754847fa79e41c6badc0bfc69e324d2", - - _bmService: null, - _histService: null, - - _observer: null, - - init: function (connection) { - this._connection = connection; - - this._bmService = Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"] - .getService (Components.interfaces.nsINavBookmarksService); - this._histService = Components.classes["@mozilla.org/browser/nav-history-service;1"] - .getService (Components.interfaces.nsINavHistoryService); - - if (!this.insertDataSource ()) { - return false; - } - - Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); - - this.setupObserver (); - - return true; - }, - - shutdown: function () { - if (this._observer) { - this._bmService.removeObserver (this._observer); - } - }, - - setupObserver: function () { - if (this._observer) { - return; - } - - this._observer = { - _attached: false, - - service: org.bustany.TrackerFox.Bookmarks, - - onItemAdded: function (itemId, parentId, index, itemType, uri) { - var bookmark = this.getBookmark (itemId, parentId, itemType, uri); - - if (!bookmark) { - dump ("Could not load new bookmark\n"); - return; - } - - this.service.insertBookmarks ([bookmark]); - }, - - onItemChanged: function (itemId, property, isAnnotation, newValue, lastModified, itemType) { - if (property == "") { - return; - } - - dump ("Bookmark changed " + property + "!\n"); - }, - - onItemRemoved: function (id, parentId, index, itemType) { - var bookmark = { itemId: id }; - - this.service.deleteBookmarks ([bookmark]); - }, - - getBookmark: function (itemId, parentId, itemType, uri) { - var bookmarks = this.service._bmService; - var history = this.service._histService; - - if (itemType != bookmarks.TYPE_BOOKMARK) { - return; - } - - // No idea how you get a full bookmark directly from its id - var query = history.getNewQuery (); - query.setFolders ([parentId], 1); - query.onlyBookmarked = true; - - if (uri) { - query.uri = uri; - } - - var options = history.getNewQueryOptions (); - options.queryType = options.QUERY_TYPE_BOOKMARKS; - var result = history.executeQuery (query, options); - var root = result.root; - root.containerOpen = true; - - var bookmark = null; - - for (var i = 0; i < root.childCount; ++i) { - var b = root.getChild (i); - - if (b.itemId == itemId) { - bookmark = b; - } - } - - if (!bookmark) { - dump ("Couldn't find the bookmark with id " + itemId + "!\n"); - } - - return bookmark; - }, - - QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsINavBookmarkObserver]) - }; - - this._bmService.addObserver (this._observer, false); - }, - - insertDataSource: function () { - var tracker = this._tracker; - - var error = new tracker.Error.ptr; - tracker.connection_update (this._connection, - "INSERT { <" + this._dataSourceUrn + "> " + - "a nie:DataSource; " + - "rdfs:label \"TrackerFox\"}", - 0, - null, - error.address ()); - - if (!error.isNull ()) { - this.handleError (error, "Can't insert DataSource"); - return false; - } - - return true; - }, - - syncBookmarks: function () { - var localBookmarks = this.getLocalBookmarks(); - var trackerBookmarks = this.getTrackerBookmarks (); - - // Quirky way of detecting an error - if (trackerBookmarks.length == 1 && trackerBookmarks[0] == null) { - return false; - } - - var trackerDict = {}; - var newBookmarks = new Array (); - var updatedBookmarks = new Array(); - var deletedBookmarks = new Array(); - - for (var i in trackerBookmarks) { - var bookmark = trackerBookmarks[i] - trackerDict[bookmark.itemId] = bookmark; - } - - for (var i = localBookmarks.length - 1; i >= 0; --i) { - var local = localBookmarks[i]; - var id = local.itemId.toString(); - - if (!trackerDict[id]) { - newBookmarks.push (local); - continue; - } - - var remote = trackerDict[id]; - - // We divide by 1000000 here since Tracker's resolution is second - if (Math.round(local.lastModified / 1000000) > (this.dateToPRTime(remote.lastModified) / 1000000)) { - updatedBookmarks.push (local); - } - - trackerDict[id] = null; - } - - for (var id in trackerDict) { - if (trackerDict[id]) { - deletedBookmarks.push (trackerDict[id]); - } - } - - this.insertBookmarks (newBookmarks); - this.updateBookmarks (updatedBookmarks); - this.deleteBookmarks (deletedBookmarks); - }, - - getLocalBookmarks: function (folder) { - var bookmarks = this._bmService; - var history = this._histService; - - const foldersToList = [bookmarks.toolbarFolder, - bookmarks.bookmarksMenuFolder, - bookmarks.unfiledBookmarksFolder]; - - var query = history.getNewQuery (); - query.setFolders (foldersToList, foldersToList.length); - var options = history.getNewQueryOptions (); - options.queryType = options.QUERY_TYPE_BOOKMARKS; - var result = history.executeQuery (query, options); - var root = result.root; - root.containerOpen = true; - - var bookmarks = new Array (); - - for (var i = 0; i < root.childCount; ++i) { - bookmarks.push (root.getChild (i)); - } - - return bookmarks; - }, - - // Returns a list of - // { - // urn: xxx - // itemId: xxx - // lastModified: xxx - // } - // - // or [ null ] in case of error - getTrackerBookmarks: function () { - var tracker = this._tracker; - - var error = new tracker.Error.ptr; - - var cursor = tracker.connection_query (this._connection, - "SELECT ?b nao:identifier(?b) nie:contentLastModified(?b) " + - "{ ?b a nfo:Bookmark ; " + - "nie:dataSource <" + this._dataSourceUrn + ">}", - null, - error.address ()); - - if (!error.isNull ()) { - this.handleError (error, "Can't get bookmarks from Tracker"); - return [null]; - } - - var bookmarks = new Array (); - - while (tracker.cursor_next (cursor, null, error.address())) { - if (!error.isNull ()) { - this.handleError (error, "Can't get bookmarks from Tracker") - return [null]; - } - - var bookmark = { - urn: tracker.cursor_get_string (cursor, 0, null).readString (), - itemId: tracker.cursor_get_string (cursor, 1, null).readString (), - lastModified: tracker.cursor_get_string (cursor, 2, null).readString () - }; - - bookmarks.push (bookmark); - } - - tracker.object_unref (cursor); - - return bookmarks; - }, - - insertBookmarks: function (bookmarks) { - if (bookmarks.length == 0) { - return; - } - - var tracker = this._tracker; - - var globalQuery = ""; - - for (var i in bookmarks) { - var bookmark = bookmarks[i]; - - var iri = "<urn:trackerfox:bookmark:" + bookmark.itemId + ">"; - - var query = "INSERT { _:rdo a nfo:RemoteDataObject; " + - "nie:url \"" + bookmark.uri + "\" }" + - "WHERE {FILTER(!EXISTS {?r nie:url \"" + bookmark.uri + "\"})}" + - "\n" + - "INSERT { " + iri + " a nfo:Bookmark, nie:DataObject; " + - "nie:dataSource <" + this._dataSourceUrn + ">; " + - "nie:usageCounter " + bookmark.accessCount + "; " + - "nie:contentCreated \"" + this.PRTimeToDate (bookmark.dateAdded).toISOString () + "\"; " + - "nao:identifier \"" + bookmark.itemId + "\"; " + - "nie:contentLastModified \"" + this.PRTimeToDate (bookmark.lastModified).toISOString () + "\"; " + - "nfo:bookmarks ?rdo"; - if (bookmark.time != 0) { - query += "; nie:contentAccessed \"" + this.PRTimeToDate (bookmark.time).toISOString () + "\""; - } - - if (bookmark.title != "") { - query += "; nie:title \"" + tracker.escape_string (bookmark.title).readString () + "\""; - } - - query += "} WHERE {?rdo nie:url \"" + bookmark.uri + "\"}\n\n"; - - globalQuery += query; - } - - var error = new tracker.Error.ptr; - tracker.connection_update (this._connection, - globalQuery, - 0, - null, - error.address ()); - - if (!error.isNull ()) { - this.handleError (error, "Can't save bookmarks"); - return; - } - }, - - updateBookmarks: function (bookmarks) { - if (bookmarks.length == 0) { - return; - } - - // FIXME: Not optimal - this.deleteBookmarks (bookmarks); - this.insertBookmarks (bookmarks); - }, - - deleteBookmarks: function (bookmarks) { - if (bookmarks.length == 0) { - return; - } - - var tracker = this._tracker; - - var globalQuery = ""; - - for (var i in bookmarks) { - var bookmark = bookmarks[i]; - - var iri = "<urn:trackerfox:bookmark:" + bookmark.itemId + ">"; - - globalQuery += "DELETE {" + iri + " a rdfs:Resource}\n\n"; - } - - var error = new tracker.Error.ptr; - tracker.connection_update (this._connection, - globalQuery, - 0, - null, - error.address ()); - - if (!error.isNull ()) { - this.handleError (error, "Can't save bookmarks"); - return; - } - }, - - handleError: function (error, message) { - var tracker = this._tracker; - - dump (message + ": " + error.contents.message.readString () + "\n"); - tracker.error_free(error); - }, - - dateToPRTime: function (date) { - return Date.parse (date) * 1000; - }, - - PRTimeToDate: function (date) { - return new Date (date / 1000); - } -} diff --git a/src/plugins/firefox/chrome/content/ff-overlay.xul b/src/plugins/firefox/chrome/content/ff-overlay.xul deleted file mode 100644 index d30759923..000000000 --- a/src/plugins/firefox/chrome/content/ff-overlay.xul +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<?xml-stylesheet href="chrome://trackerfox/skin/overlay.css" type="text/css"?> -<!DOCTYPE overlay SYSTEM "chrome://trackerfox/locale/overlay.dtd"> -<overlay id="trackerfox-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - <script src="namespace.js"/> - <script src="bindings.js"/> - <script src="bookmarks.js"/> - <script src="plugin.js"/> - - <stringbundleset id="stringbundleset"> - <stringbundle id="trackerfox-strings" src="chrome://trackerfox/locale/overlay.properties"/> - </stringbundleset> - - - - -</overlay> diff --git a/src/plugins/firefox/chrome/content/namespace.js b/src/plugins/firefox/chrome/content/namespace.js deleted file mode 100644 index 6e6dd1907..000000000 --- a/src/plugins/firefox/chrome/content/namespace.js +++ /dev/null @@ -1,5 +0,0 @@ -// Avoid polluting main namespace -if (!org) var org = {}; -if (!org.bustany) org.bustany = {}; -if (!org.bustany.TrackerFox) org.bustany.TrackerFox = {}; - diff --git a/src/plugins/firefox/chrome/content/plugin.js b/src/plugins/firefox/chrome/content/plugin.js deleted file mode 100644 index 62161f621..000000000 --- a/src/plugins/firefox/chrome/content/plugin.js +++ /dev/null @@ -1,80 +0,0 @@ -if (!org.bustany.TrackerFox.Plugin || !org.bustany.TrackerFox.Plugin.__initialized) -org.bustany.TrackerFox.Plugin={ - // Init barrier - __initialized: true, - - // Private members - _connection: null, - _tracker: org.bustany.TrackerFox.TrackerSparql, - _bookmarks: null, - - // Methods - onLoad: function () { - // initialization code - this.initialized = true; - this.strings = document.getElementById ("trackerfox-strings"); - - dump ("Initializing TrackerFox...\n"); - - if (!this.initTracker ()) { - dump ("Couldn't initialize Tracker!\n"); - return; - } - - // The rest of the init is done in onTrackerReady() - }, - - onUnload: function () { - dump ("Closing TrackerFox...\n"); - - var tracker = org.bustany.TrackerFox.TrackerSparql; - this._bookmarks.shutdown (); - tracker.shutdown (); - }, - - initTracker: function () { - var tracker = this._tracker; - - if (!tracker.init ()) { - dump ("Couldn't initialize tracker bindings, and I don't even know why :'(\n"); - return false; - } - - var plugin = this; - var callback_closure = function(source_object, result, user_data) { - plugin.onTrackerReady(source_object, result, user_data); - } - - tracker.readyCallback = tracker.AsyncReadyCallback.ptr(callback_closure) - tracker.connection_open_async(null, tracker.readyCallback, null); - - return true; - }, - - onTrackerReady: function(source_object, result, user_data) { - var tracker = this._tracker; - - var error = new tracker.Error.ptr; - this._connection = tracker.connection_open_finish (result, error.address()); - - if (!error.isNull ()) { - dump ("Could not initialize Tracker: " + error.contents.message.readString() + "\n"); - tracker.error_free(error); - return; - } - - // Tracker is OK, let's continue with the initialization - - this._bookmarks = org.bustany.TrackerFox.Bookmarks; - - if (!this._bookmarks.init (this._connection)) { - dump ("Couldn't initialize bookmarks service!\n"); - return; - } - - this._bookmarks.syncBookmarks(); - } -}; - -window.addEventListener ("load", function () { org.bustany.TrackerFox.Plugin.onLoad (); }, false); -window.addEventListener ("unload", function () { org.bustany.TrackerFox.Plugin.onUnload (); }, false); diff --git a/src/plugins/firefox/chrome/locale/Makefile.am b/src/plugins/firefox/chrome/locale/Makefile.am deleted file mode 100644 index 6f8bbae0e..000000000 --- a/src/plugins/firefox/chrome/locale/Makefile.am +++ /dev/null @@ -1,31 +0,0 @@ -# General -localesdir = $(datadir)/xul-ext/trackerfox/chrome/locale/ - -localesdata = \ - about.dtd \ - overlay.dtd \ - overlay.properties - -# locales = en-US es-ES fr-FR pl-PL - -# en-US -locale_en_USdir = $(localesdir)/en-US/ -locale_en_US_DATA = $(patsubst %,en-US/%,$(localesdata)) - -# es-ES -locale_es_ESdir = $(localesdir)/es-ES/ -locale_es_ES_DATA = $(patsubst %,es-ES/%,$(localesdata)) - -# fr-FR -locale_fr_FRdir = $(localesdir)/fr-FR/ -locale_fr_FR_DATA = $(patsubst %,fr-FR/%,$(localesdata)) - -# pl-PL -locale_pl_PLdir = $(localesdir)/pl-PL/ -locale_pl_PL_DATA = $(patsubst %,pl-PL/%,$(localesdata)) - -EXTRA_DIST = \ - $(locale_en_US_DATA) \ - $(locale_es_ES_DATA) \ - $(locale_fr_FR_DATA) \ - $(locale_pl_PL_DATA) diff --git a/src/plugins/firefox/chrome/locale/en-US/about.dtd b/src/plugins/firefox/chrome/locale/en-US/about.dtd deleted file mode 100644 index ddd4023af..000000000 --- a/src/plugins/firefox/chrome/locale/en-US/about.dtd +++ /dev/null @@ -1,4 +0,0 @@ -<!ENTITY about "About"> -<!ENTITY version "Version:"> -<!ENTITY createdBy "Created By:"> -<!ENTITY homepage "Home Page:"> diff --git a/src/plugins/firefox/chrome/locale/en-US/overlay.dtd b/src/plugins/firefox/chrome/locale/en-US/overlay.dtd deleted file mode 100644 index e69de29bb..000000000 --- a/src/plugins/firefox/chrome/locale/en-US/overlay.dtd +++ /dev/null diff --git a/src/plugins/firefox/chrome/locale/en-US/overlay.properties b/src/plugins/firefox/chrome/locale/en-US/overlay.properties deleted file mode 100644 index 1f8be1ee7..000000000 --- a/src/plugins/firefox/chrome/locale/en-US/overlay.properties +++ /dev/null @@ -1 +0,0 @@ -extensions.trackerfox@bustany.org.description=Search your bookmarks from Tracker diff --git a/src/plugins/firefox/chrome/locale/es-ES/about.dtd b/src/plugins/firefox/chrome/locale/es-ES/about.dtd deleted file mode 100644 index 3c813dcd4..000000000 --- a/src/plugins/firefox/chrome/locale/es-ES/about.dtd +++ /dev/null @@ -1,4 +0,0 @@ -<!ENTITY about "Acerca de"> -<!ENTITY version "Versión:"> -<!ENTITY createdBy "Creado por:"> -<!ENTITY homepage "Pagina internet:"> diff --git a/src/plugins/firefox/chrome/locale/es-ES/overlay.dtd b/src/plugins/firefox/chrome/locale/es-ES/overlay.dtd deleted file mode 100644 index e69de29bb..000000000 --- a/src/plugins/firefox/chrome/locale/es-ES/overlay.dtd +++ /dev/null diff --git a/src/plugins/firefox/chrome/locale/es-ES/overlay.properties b/src/plugins/firefox/chrome/locale/es-ES/overlay.properties deleted file mode 100644 index bbc33ac31..000000000 --- a/src/plugins/firefox/chrome/locale/es-ES/overlay.properties +++ /dev/null @@ -1 +0,0 @@ -extensions.trackerfox@bustany.org.description=Recherchez dans vos favoris depuis Tracker diff --git a/src/plugins/firefox/chrome/locale/fr-FR/about.dtd b/src/plugins/firefox/chrome/locale/fr-FR/about.dtd deleted file mode 100644 index e558c6c42..000000000 --- a/src/plugins/firefox/chrome/locale/fr-FR/about.dtd +++ /dev/null @@ -1,4 +0,0 @@ -<!ENTITY about "À propos"> -<!ENTITY version "Version:"> -<!ENTITY createdBy "Créé par:"> -<!ENTITY homepage "Page internet:"> diff --git a/src/plugins/firefox/chrome/locale/fr-FR/overlay.dtd b/src/plugins/firefox/chrome/locale/fr-FR/overlay.dtd deleted file mode 100644 index e69de29bb..000000000 --- a/src/plugins/firefox/chrome/locale/fr-FR/overlay.dtd +++ /dev/null diff --git a/src/plugins/firefox/chrome/locale/fr-FR/overlay.properties b/src/plugins/firefox/chrome/locale/fr-FR/overlay.properties deleted file mode 100644 index bbc33ac31..000000000 --- a/src/plugins/firefox/chrome/locale/fr-FR/overlay.properties +++ /dev/null @@ -1 +0,0 @@ -extensions.trackerfox@bustany.org.description=Recherchez dans vos favoris depuis Tracker diff --git a/src/plugins/firefox/chrome/locale/pl-PL/about.dtd b/src/plugins/firefox/chrome/locale/pl-PL/about.dtd deleted file mode 100644 index 4494fa9de..000000000 --- a/src/plugins/firefox/chrome/locale/pl-PL/about.dtd +++ /dev/null @@ -1,4 +0,0 @@ -<!ENTITY about "O rozszerzeniu"> -<!ENTITY version "Wersja:"> -<!ENTITY createdBy "Utworzone przez:"> -<!ENTITY homepage "Witryna:"> diff --git a/src/plugins/firefox/chrome/locale/pl-PL/overlay.dtd b/src/plugins/firefox/chrome/locale/pl-PL/overlay.dtd deleted file mode 100644 index e69de29bb..000000000 --- a/src/plugins/firefox/chrome/locale/pl-PL/overlay.dtd +++ /dev/null diff --git a/src/plugins/firefox/chrome/locale/pl-PL/overlay.properties b/src/plugins/firefox/chrome/locale/pl-PL/overlay.properties deleted file mode 100644 index f22fb2e9f..000000000 --- a/src/plugins/firefox/chrome/locale/pl-PL/overlay.properties +++ /dev/null @@ -1 +0,0 @@ -extensions.trackerfox@bustany.org.description=Przeszukiwanie zakładek w programie Tracker diff --git a/src/plugins/firefox/chrome/skin/Makefile.am b/src/plugins/firefox/chrome/skin/Makefile.am deleted file mode 100644 index bb05d7039..000000000 --- a/src/plugins/firefox/chrome/skin/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -extensiondir = $(datadir)/xul-ext/trackerfox/chrome/skin -extension_DATA = \ - overlay.css - -EXTRA_DIST = $(extension_DATA) diff --git a/src/plugins/firefox/chrome/skin/overlay.css b/src/plugins/firefox/chrome/skin/overlay.css deleted file mode 100644 index 399111f7d..000000000 --- a/src/plugins/firefox/chrome/skin/overlay.css +++ /dev/null @@ -1,22 +0,0 @@ -/* This is just an example. You shouldn't do this. */ -#trackerfox-hello -{ - color: red ! important; -} -#trackerfox-toolbar-button -{ - list-style-image: url("chrome://trackerfox/skin/toolbar-button.png"); - -moz-image-region: rect(0px 24px 24px 0px); -} -#trackerfox-toolbar-button:hover -{ - -moz-image-region: rect(24px 24px 48px 0px); -} -[iconsize="small"] #trackerfox-toolbar-button -{ - -moz-image-region: rect( 0px 40px 16px 24px); -} -[iconsize="small"] #trackerfox-toolbar-button:hover -{ - -moz-image-region: rect(24px 40px 40px 24px); -} diff --git a/src/plugins/firefox/defaults/Makefile.am b/src/plugins/firefox/defaults/Makefile.am deleted file mode 100644 index 287fa7162..000000000 --- a/src/plugins/firefox/defaults/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = preferences diff --git a/src/plugins/firefox/defaults/preferences/Makefile.am b/src/plugins/firefox/defaults/preferences/Makefile.am deleted file mode 100644 index 6b3756cf4..000000000 --- a/src/plugins/firefox/defaults/preferences/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -extensiondir = $(datadir)/xul-ext/trackerfox/defaults/preferences -extension_DATA = \ - prefs.js - -EXTRA_DIST = $(extension_DATA) diff --git a/src/plugins/firefox/defaults/preferences/prefs.js b/src/plugins/firefox/defaults/preferences/prefs.js deleted file mode 100644 index 86fedf3d6..000000000 --- a/src/plugins/firefox/defaults/preferences/prefs.js +++ /dev/null @@ -1,2 +0,0 @@ -// https://developer.mozilla.org/en/Localizing_extension_descriptions -pref("extensions.trackerfox@bustany.org.description", "chrome://trackerfox/locale/overlay.properties"); diff --git a/src/plugins/firefox/install.rdf.in b/src/plugins/firefox/install.rdf.in deleted file mode 100644 index 5cef11363..000000000 --- a/src/plugins/firefox/install.rdf.in +++ /dev/null @@ -1,20 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - <Description about="urn:mozilla:install-manifest"> - <em:id>trackerfox@bustany.org</em:id> - <em:type>2</em:type> - <em:name>TrackerFox</em:name> - <em:version>@VERSION@</em:version> - <em:creator>Adrien Bustany</em:creator> - <em:contributor></em:contributor> - <em:description>Makes your bookmarks searchable from Tracker</em:description> - <em:aboutURL>chrome://trackerfox/content/about.xul</em:aboutURL> - <em:targetApplication> - <Description> - <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> <!-- Firefox --> - <em:minVersion>4.0</em:minVersion> - <em:maxVersion>20.*</em:maxVersion> - </Description> - </em:targetApplication> - </Description> -</RDF> diff --git a/src/plugins/nautilus/Makefile.am b/src/plugins/nautilus/Makefile.am deleted file mode 100644 index 880998d37..000000000 --- a/src/plugins/nautilus/Makefile.am +++ /dev/null @@ -1,22 +0,0 @@ -AM_CPPFLAGS = \ - $(BUILD_CFLAGS) \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - $(TRACKER_NAUTILUS_EXTENSION_CFLAGS) - -nautilus_extensiondir = $(TRACKER_NAUTILUS_EXTENSION_INSTALL_DIR) - -nautilus_extension_LTLIBRARIES = libnautilus-tracker-tags.la - -libnautilus_tracker_tags_la_SOURCES = \ - tracker-tags-extension.c \ - tracker-tags-utils.c \ - tracker-tags-utils.h \ - tracker-tags-view.c \ - tracker-tags-view.h - -libnautilus_tracker_tags_la_LDFLAGS = -module -avoid-version -libnautilus_tracker_tags_la_LIBADD = \ - $(top_builddir)/src/libtracker-sparql-backend/libtracker-sparql-@TRACKER_API_VERSION@.la \ - $(BUILD_LIBS) \ - $(TRACKER_NAUTILUS_EXTENSION_LIBS) diff --git a/src/plugins/nautilus/tracker-tags-extension.c b/src/plugins/nautilus/tracker-tags-extension.c deleted file mode 100644 index 4364847e5..000000000 --- a/src/plugins/nautilus/tracker-tags-extension.c +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright (C) 2009, Debarshi Ray <debarshir@src.gnome.org> - * Copyright (C) 2009, Martyn Russell <martyn@lanedo.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 <gtk/gtk.h> -#include <glib/gi18n.h> - -#include <libnautilus-extension/nautilus-property-page-provider.h> - -#include <libtracker-sparql/tracker-sparql.h> - -#include "tracker-tags-utils.h" -#include "tracker-tags-view.h" - -#define TRACKER_TYPE_TAGS_EXTENSION (tracker_tags_extension_get_type ()) -#define TRACKER_TAGS_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRACKER_TYPE_TAGS_EXTENSION, TrackerTagsExtension)) -#define TRACKER_TAGS_EXTENSION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TRACKER_TYPE_TAGS_EXTENSION, TrackerTagsExtensionClass)) - -#define TRACKER_IS_TAGS_EXTENSION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRACKER_TYPE_TAGS_EXTENSION)) -#define TRACKER_IS_TAGS_EXTENSION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TRACKER_TYPE_TAGS_EXTENSION)) - -typedef struct _TrackerTagsExtension TrackerTagsExtension; -typedef struct _TrackerTagsExtensionClass TrackerTagsExtensionClass; - -struct _TrackerTagsExtension { - GObject parent; -}; - -struct _TrackerTagsExtensionClass { - GObjectClass parent; -}; - -GType tracker_tags_extension_get_type (void); -static void tracker_tags_extension_property_page_provider_iface_init (NautilusPropertyPageProviderIface *iface); - -G_DEFINE_DYNAMIC_TYPE_EXTENDED (TrackerTagsExtension, tracker_tags_extension, G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE (NAUTILUS_TYPE_PROPERTY_PAGE_PROVIDER, - tracker_tags_extension_property_page_provider_iface_init)); - -static GList * -extension_get_pages (NautilusPropertyPageProvider *provider, - GList *files) -{ - GList *property_pages = NULL; - GtkWidget *label; - GtkWidget *view; - NautilusPropertyPage *property_page; - - if (files == NULL) { - return NULL; - } - - label = gtk_label_new (_("Tags")); - view = tracker_tags_view_new (files); - gtk_widget_show (view); - property_page = nautilus_property_page_new ("tracker-tags", label, view); - property_pages = g_list_prepend (property_pages, property_page); - - return property_pages; -} - -static void -tracker_tags_extension_property_page_provider_iface_init (NautilusPropertyPageProviderIface *iface) -{ - iface->get_pages = extension_get_pages; -} - -static void -tracker_tags_extension_class_init (TrackerTagsExtensionClass *klass) -{ -} - -static void -tracker_tags_extension_class_finalize (TrackerTagsExtensionClass *klass) -{ -} - -static void -tracker_tags_extension_init (TrackerTagsExtension *self) -{ -} - -void -nautilus_module_initialize (GTypeModule *module) -{ - g_debug ("Initializing tracker-tags extension\n"); - tracker_tags_extension_register_type (module); - tracker_tags_view_register_types (module); -} - -void -nautilus_module_shutdown (void) -{ - g_debug ("Shutting down tracker-tags extension\n"); -} - -void -nautilus_module_list_types (const GType **types, - gint *num_types) -{ - static GType type_list[1]; - - type_list[0] = tracker_tags_extension_type_id; - *types = type_list; - *num_types = G_N_ELEMENTS (type_list); -} diff --git a/src/plugins/nautilus/tracker-tags-utils.c b/src/plugins/nautilus/tracker-tags-utils.c deleted file mode 100644 index 08f45a261..000000000 --- a/src/plugins/nautilus/tracker-tags-utils.c +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2009, Debarshi Ray <debarshir@src.gnome.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) 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 <string.h> - -#include <libnautilus-extension/nautilus-file-info.h> - -#include <libtracker-sparql/tracker-sparql.h> - -#include "tracker-tags-utils.h" - -/* Copied from src/libtracker-common/tracker-utils.c */ -inline gboolean -tracker_is_empty_string (const char *str) -{ - return str == NULL || str[0] == '\0'; -} - -/* Copied from src/libtracker-common/tracker-type-utils.c */ -gchar ** -tracker_glist_to_string_list_for_nautilus_files (GList *list) -{ - GList *l; - gchar **strv; - gint i; - - strv = g_new0 (gchar *, g_list_length (list) + 1); - - for (l = list, i = 0; l; l = l->next) { - if (!l->data) { - continue; - } - - strv[i++] = nautilus_file_info_get_uri (NAUTILUS_FILE_INFO (l->data)); - } - - strv[i] = NULL; - - return strv; -} - -/* Copied from src/tracker-utils/tracker-tags.c */ -gchar * -tracker_tags_get_filter_string (GStrv files, - const gchar *tag) -{ - GString *filter; - gint i, len; - - if (!files) { - return NULL; - } - - len = g_strv_length (files); - - if (len < 1) { - return NULL; - } - - filter = g_string_new (""); - - g_string_append_printf (filter, "FILTER ("); - - if (tag) { - g_string_append (filter, "("); - } - - for (i = 0; i < len; i++) { - g_string_append_printf (filter, "?f = \"%s\"", files[i]); - - if (i < len - 1) { - g_string_append (filter, " || "); - } - } - - if (tag) { - g_string_append_printf (filter, ") && ?t = <%s>", tag); - } - - g_string_append (filter, ")"); - - return g_string_free (filter, FALSE); -} - -gchar * -tracker_tags_escape_sparql_string (const gchar *str) -{ - gchar *escaped, *retval; - - escaped = tracker_sparql_escape_string (str); - retval = g_strdup_printf ("\"%s\"", escaped); - g_free (escaped); - - return retval; -} - -gchar * -tracker_tags_add_query (const gchar *tag_label) -{ - gchar *query; - gchar *tag_label_escaped; - - tag_label_escaped = tracker_tags_escape_sparql_string (tag_label); - query = g_strdup_printf ("INSERT { " - " _:tag a nao:Tag ;" - " nao:prefLabel %s ." - "} " - "WHERE {" - " OPTIONAL {" - " ?tag a nao:Tag ;" - " nao:prefLabel %s" - " } ." - " FILTER (!bound(?tag)) " - "}", - tag_label_escaped, - tag_label_escaped); - g_free (tag_label_escaped); - - return query; -} - -gchar * -tracker_tags_remove_query (const gchar *tag_label) -{ - gchar *query; - gchar *tag_label_escaped; - - tag_label_escaped = tracker_tags_escape_sparql_string (tag_label); - query = g_strdup_printf ("DELETE { " - " ?tag a rdfs:Resource " - "} " - "WHERE {" - " ?tag a nao:Tag ;" - " nao:prefLabel %s " - "}", - tag_label_escaped); - g_free (tag_label_escaped); - - return query; -} diff --git a/src/plugins/nautilus/tracker-tags-utils.h b/src/plugins/nautilus/tracker-tags-utils.h deleted file mode 100644 index 8d3c7ab3b..000000000 --- a/src/plugins/nautilus/tracker-tags-utils.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2009, Debarshi Ray <debarshir@src.gnome.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) 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. - */ - -#ifndef __TRACKER_TAGS_UTILS_H__ -#define __TRACKER_TAGS_UTILS_H__ - -#include <glib-object.h> - -G_BEGIN_DECLS - -inline gboolean tracker_is_empty_string (const char *str); -gchar ** tracker_glist_to_string_list_for_nautilus_files (GList *list); -gchar * tracker_tags_get_filter_string (GStrv files, - const gchar *tag); -gchar * tracker_tags_escape_sparql_string (const gchar *str); -gchar * tracker_tags_add_query (const gchar *tag_label); -gchar * tracker_tags_remove_query (const gchar *tag_label); - -G_END_DECLS - -#endif /* __TRACKER_TAGS_UTILS_H__ */ diff --git a/src/plugins/nautilus/tracker-tags-view.c b/src/plugins/nautilus/tracker-tags-view.c deleted file mode 100644 index d0bdd6e1e..000000000 --- a/src/plugins/nautilus/tracker-tags-view.c +++ /dev/null @@ -1,1180 +0,0 @@ -/* - * Copyright (C) 2009, Debarshi Ray <debarshir@src.gnome.org> - * 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. - */ - -#include "config.h" - -#include <string.h> - -#include <glib/gi18n.h> - -#include <libnautilus-extension/nautilus-file-info.h> - -#include <libtracker-sparql/tracker-sparql.h> - -#include "tracker-tags-utils.h" -#include "tracker-tags-view.h" - -#define TRACKER_TAGS_VIEW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), TRACKER_TYPE_TAGS_VIEW, TrackerTagsViewPrivate)) - -struct _TrackerTagsViewPrivate { - TrackerSparqlConnection *connection; - GCancellable *cancellable; - - GList *tag_data_requests; - - GList *files; - - GtkListStore *store; - - GtkWidget *button_add; - GtkWidget *button_remove; - GtkWidget *entry; - GtkWidget *view; -}; - -typedef struct { - TrackerTagsView *tv; - GCancellable *cancellable; - gchar *tag_id; - GtkTreeIter *iter; - gint items; - gboolean update; - gboolean selected; -} TagData; - -typedef struct { - TrackerTagsView *tv; - const gchar *tag; - gboolean found; - GtkTreeIter found_iter; -} FindTag; - -enum { - COL_SELECTION, - COL_TAG_ID, - COL_TAG_NAME, - COL_TAG_COUNT, - COL_TAG_COUNT_VALUE, - N_COLUMNS -}; - -enum { - SELECTION_INCONSISTENT = -1, - SELECTION_FALSE = 0, - SELECTION_TRUE -}; - -static void tracker_tags_view_finalize (GObject *object); -static void tracker_tags_view_register_type (GTypeModule *module); -static void tags_view_create_ui (TrackerTagsView *tv); -static void tag_data_free (TagData *td); - -G_DEFINE_DYNAMIC_TYPE (TrackerTagsView, tracker_tags_view, GTK_TYPE_VBOX) - -static void -tracker_tags_view_class_init (TrackerTagsViewClass *klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->finalize = tracker_tags_view_finalize; - - g_type_class_add_private (klass, sizeof (TrackerTagsViewPrivate)); -} - -static void -tracker_tags_view_class_finalize (TrackerTagsViewClass *klass) -{ -} - -static void -tracker_tags_view_init (TrackerTagsView *tv) -{ - TrackerTagsViewPrivate *private; - GError *error = NULL; - - private = TRACKER_TAGS_VIEW_GET_PRIVATE (tv); - - private->cancellable = g_cancellable_new (); - private->connection = tracker_sparql_connection_get (private->cancellable, - &error); - if (!private->connection) { - g_critical ("Couldn't get a proper SPARQL connection: '%s'", - error ? error->message : "unknown error"); - g_clear_error (&error); - } - - private->files = NULL; - - private->store = gtk_list_store_new (N_COLUMNS, - G_TYPE_INT, /* Selection type */ - G_TYPE_STRING, /* Tag ID */ - G_TYPE_STRING, /* Tag Name */ - G_TYPE_STRING, /* Tag Count String */ - G_TYPE_INT); /* Tag Count */ -} - -static void -tracker_tags_view_finalize (GObject *object) -{ - TrackerTagsViewPrivate *private = TRACKER_TAGS_VIEW_GET_PRIVATE (object); - - if (private->cancellable) { - g_cancellable_cancel (private->cancellable); - g_object_unref (private->cancellable); - private->cancellable = NULL; - } - - if (private->connection) { - g_object_unref (private->connection); - private->connection = NULL; - } - - if (private->files) { - nautilus_file_info_list_free (private->files); - private->files = NULL; - } - - if (private->tag_data_requests) { - g_list_foreach (private->tag_data_requests, (GFunc) tag_data_free, NULL); - g_list_free (private->tag_data_requests); - private->tag_data_requests = NULL; - } - - G_OBJECT_CLASS (tracker_tags_view_parent_class)->finalize (object); -} - -static TagData * -tag_data_new (const gchar *tag_id, - GtkTreeIter *iter, - gboolean update, - gboolean selected, - gint items, - TrackerTagsView *tv) -{ - TagData *td; - - td = g_slice_new (TagData); - - g_debug ("Creating tag data"); - - td->tv = tv; - td->cancellable = g_cancellable_new (); - td->tag_id = g_strdup (tag_id); - - if (iter) { - td->iter = gtk_tree_iter_copy (iter); - } else { - td->iter = NULL; - } - - td->items = items; - td->update = update; - td->selected = selected; - - return td; -} - -static void -tag_data_free (TagData *td) -{ - if (td->cancellable) { - g_cancellable_cancel (td->cancellable); - g_object_unref (td->cancellable); - } - - g_free (td->tag_id); - - if (td->iter) { - gtk_tree_iter_free (td->iter); - } - - g_slice_free (TagData, td); -} - -static TagData * -tag_data_copy (TagData *td) -{ - TagData *new_td; - - new_td = g_slice_new (TagData); - - new_td->tv = td->tv; - new_td->cancellable = g_cancellable_new (); - new_td->tag_id = g_strdup (td->tag_id); - - if (td->iter) { - new_td->iter = gtk_tree_iter_copy (td->iter); - } else { - new_td->iter = NULL; - } - - new_td->items = td->items; - new_td->update = td->update; - new_td->selected = td->selected; - - return new_td; -} - -static void -show_error_dialog (GError *error) -{ - GtkWidget *dialog; - const gchar *str; - - str = error->message ? error->message : _("No error given"); - - dialog = gtk_message_dialog_new (NULL, - 0, - GTK_MESSAGE_ERROR, - GTK_BUTTONS_OK, - "%s", - str); - g_signal_connect (dialog, "response", - G_CALLBACK (gtk_widget_destroy), NULL); - gtk_dialog_run (GTK_DIALOG (dialog)); -} - -static gboolean -tag_view_model_find_tag_foreach (GtkTreeModel *model, - GtkTreePath *path, - GtkTreeIter *iter, - FindTag *data) -{ - gchar *tag; - - gtk_tree_model_get (model, iter, - COL_TAG_NAME, &tag, - -1); - - if (!tag) { - return FALSE; - } - - if (data->tag && strcmp (data->tag, tag) == 0) { - data->found = TRUE; - data->found_iter = *iter; - - g_free (tag); - - return TRUE; - } - - g_free (tag); - - return FALSE; -} - -static gboolean -tag_view_model_find_tag (TrackerTagsView *tv, - const gchar *tag, - GtkTreeIter *iter) -{ - TrackerTagsViewPrivate *private; - GtkTreeView *view; - GtkTreeModel *model; - FindTag data; - - if (tracker_is_empty_string (tag)) { - return FALSE; - } - - data.tv = tv; - data.tag = tag; - data.found = FALSE; - - private = TRACKER_TAGS_VIEW_GET_PRIVATE (tv); - - view = GTK_TREE_VIEW (private->view); - model = gtk_tree_view_get_model (view); - - gtk_tree_model_foreach (model, - (GtkTreeModelForeachFunc) tag_view_model_find_tag_foreach, - &data); - - if (data.found == TRUE) { - *iter = data.found_iter; - return TRUE; - } - - return FALSE; -} - -static void -tags_view_tag_removed_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - TagData *td; - TrackerTagsViewPrivate *private; - GError *error = NULL; - - g_debug ("Update callback"); - - td = user_data; - private = TRACKER_TAGS_VIEW_GET_PRIVATE (td->tv); - - tracker_sparql_connection_update_finish (TRACKER_SPARQL_CONNECTION (source_object), - res, - &error); - - if (error) { - show_error_dialog (error); - g_error_free (error); - } else { - g_message ("Tag removed (id:'%s') from store", td->tag_id); - - gtk_list_store_remove (private->store, td->iter); - } - - private->tag_data_requests = g_list_remove (private->tag_data_requests, td); - tag_data_free (td); -} - -static void -tags_view_query_files_for_tag_id_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - TagData *td; - TrackerTagsViewPrivate *private; - TrackerSparqlCursor *cursor; - GtkTreeIter *iter; - GError *error = NULL; - gchar *str; - guint files_selected, files_with_tag, has_tag_in_selection; - - td = user_data; - private = TRACKER_TAGS_VIEW_GET_PRIVATE (td->tv); - iter = td->iter; - - cursor = tracker_sparql_connection_query_finish (TRACKER_SPARQL_CONNECTION (source_object), - res, - &error); - - if (error) { - show_error_dialog (error); - g_error_free (error); - - private->tag_data_requests = g_list_remove (private->tag_data_requests, td); - tag_data_free (td); - - if (cursor) { - g_object_unref (cursor); - } - - return; - } - - has_tag_in_selection = 0; - files_with_tag = 0; - files_selected = g_list_length (private->files); - - /* FIXME: make this async */ - while (tracker_sparql_cursor_next (cursor, - private->cancellable, - &error)) { - GList *l; - gboolean equal; - - files_with_tag++; - - for (l = private->files, equal = FALSE; l && !equal; l = l->next) { - gchar *uri; - const gchar *str; - - uri = nautilus_file_info_get_uri (NAUTILUS_FILE_INFO (l->data)); - - str = tracker_sparql_cursor_get_string (cursor, 0, NULL); - equal = g_strcmp0 (str, uri) == 0; - - if (equal) { - has_tag_in_selection++; - } - - g_free (uri); - } - } - - if (cursor) { - g_object_unref (cursor); - } - - if (error) { - show_error_dialog (error); - - g_error_free (error); - - return; - } - - g_debug ("Querying files with tag, in selection:%d, in total:%d, selected:%d", - has_tag_in_selection, files_with_tag, files_selected); - - if (has_tag_in_selection == 0) { - gtk_list_store_set (private->store, iter, - COL_SELECTION, SELECTION_FALSE, - -1); - } else if (files_selected != has_tag_in_selection) { - gtk_list_store_set (private->store, iter, - COL_SELECTION, SELECTION_INCONSISTENT, - -1); - } else { - gtk_list_store_set (private->store, iter, - COL_SELECTION, SELECTION_TRUE, - -1); - } - - str = g_strdup_printf ("%d", files_with_tag); - gtk_list_store_set (private->store, iter, - COL_TAG_COUNT, str, - COL_TAG_COUNT_VALUE, files_with_tag, - -1); - g_free (str); - - private->tag_data_requests = g_list_remove (private->tag_data_requests, td); - tag_data_free (td); -} - -static void -tags_view_query_files_for_tag_id (TagData *td) -{ - TrackerTagsViewPrivate *private; - gchar *query; - - private = TRACKER_TAGS_VIEW_GET_PRIVATE (td->tv); - - if (!private->connection) { - g_warning ("Can't query files for tag id '%s', " - "no SPARQL connection available", - td->tag_id); - return; - } - - query = g_strdup_printf ("SELECT ?url " - "WHERE {" - " ?urn a rdfs:Resource ;" - " nie:url ?url ;" - " nao:hasTag <%s> . " - "}", td->tag_id); - - tracker_sparql_connection_query_async (private->connection, - query, - td->cancellable, - tags_view_query_files_for_tag_id_cb, - td); - g_free (query); -} - -static void -tags_view_add_tags_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - TrackerTagsView *tv; - TrackerTagsViewPrivate *private; - TrackerSparqlCursor *cursor; - GError *error = NULL; - - g_debug ("Clearing tags in store"); - - tv = user_data; - private = TRACKER_TAGS_VIEW_GET_PRIVATE (tv); - - cursor = tracker_sparql_connection_query_finish (TRACKER_SPARQL_CONNECTION (source_object), - res, - &error); - - gtk_list_store_clear (private->store); - - if (error) { - show_error_dialog (error); - g_error_free (error); - - if (cursor) { - g_object_unref (cursor); - } - } else { - g_message ("Adding all tags..."); - - /* FIXME: make async */ - while (tracker_sparql_cursor_next (cursor, private->cancellable, NULL)) { - TagData *td; - GtkTreeIter iter; - const gchar *id, *label; - - id = tracker_sparql_cursor_get_string (cursor, 0, NULL); - label = tracker_sparql_cursor_get_string (cursor, 1, NULL); - - g_message ("Tag added (id:'%s' with label:'%s') to store", id, label); - - gtk_list_store_append (private->store, &iter); - gtk_list_store_set (private->store, &iter, - COL_TAG_ID, id, - COL_TAG_NAME, label, - COL_SELECTION, SELECTION_FALSE, - -1); - - td = tag_data_new (id, &iter, FALSE, TRUE, 1, tv); - private->tag_data_requests = - g_list_prepend (private->tag_data_requests, td); - - tags_view_query_files_for_tag_id (td); - } - - if (cursor) { - g_object_unref (cursor); - } - } -} - -static void -tags_view_model_update_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - TagData *td = user_data; - TrackerTagsView *tv = td->tv; - TrackerTagsViewPrivate *private; - GError *error = NULL; - - g_debug ("Update callback"); - - private = TRACKER_TAGS_VIEW_GET_PRIVATE (tv); - - tracker_sparql_connection_update_finish (TRACKER_SPARQL_CONNECTION (source_object), - res, - &error); - - if (error) { - show_error_dialog (error); - g_error_free (error); - } else { - const gchar *tag; - - tag = gtk_entry_get_text (GTK_ENTRY (private->entry)); - - if (!td->update) { - GtkTreeIter iter; - gchar *str; - - g_debug ("Setting tag selection state to ON (new)"); - - str = g_strdup_printf ("%d", td->items); - gtk_list_store_append (private->store, &iter); - gtk_list_store_set (private->store, &iter, - COL_TAG_ID, td->tag_id, - COL_TAG_NAME, tag, - COL_TAG_COUNT, str, - COL_TAG_COUNT_VALUE, td->items, - COL_SELECTION, SELECTION_TRUE, - -1); - g_free (str); - } else if (td->selected) { - TagData *td_copy; - - g_debug ("Setting tag selection state to ON"); - - gtk_list_store_set (private->store, td->iter, - COL_SELECTION, SELECTION_TRUE, - -1); - - td_copy = tag_data_copy (td); - private->tag_data_requests = - g_list_prepend (private->tag_data_requests, td_copy); - - tags_view_query_files_for_tag_id (td_copy); - } else { - TagData *td_copy; - - g_debug ("Setting tag selection state to FALSE"); - - gtk_list_store_set (private->store, td->iter, - COL_SELECTION, SELECTION_FALSE, - -1); - - td_copy = tag_data_copy (td); - private->tag_data_requests = - g_list_prepend (private->tag_data_requests, td_copy); - - tags_view_query_files_for_tag_id (td_copy); - } - } - - gtk_entry_set_text (GTK_ENTRY (private->entry), ""); - gtk_widget_set_sensitive (private->entry, TRUE); - - private->tag_data_requests = - g_list_remove (private->tag_data_requests, td); - tag_data_free (td); -} - -static void -tags_view_add_tag (TrackerTagsView *tv, - const gchar *tag) -{ - TrackerTagsViewPrivate *private; - TagData *td; - GString *query; - gint files; - - private = TRACKER_TAGS_VIEW_GET_PRIVATE (tv); - - if (!private->connection) { - g_warning ("Can't add tag '%s', " - "no SPARQL connection available", - tag); - return; - } - - gtk_widget_set_sensitive (private->entry, FALSE); - - files = g_list_length (private->files); - - if (files > 0) { - GStrv files; - gchar *tag_escaped; - gchar *filter; - guint i; - - query = g_string_new (""); - - files = tracker_glist_to_string_list_for_nautilus_files (private->files); - filter = tracker_tags_get_filter_string (files, NULL); - tag_escaped = tracker_tags_escape_sparql_string (tag); - - for (i = 0; files[i] != NULL; i++) { - g_string_append_printf (query, - "INSERT { _:file a nie:DataObject ; nie:url '%s' } " - "WHERE { " - " OPTIONAL {" - " ?file a nie:DataObject ;" - " nie:url '%s'" - " } ." - " FILTER (!bound(?file)) " - "} ", - files[i], files[i]); - } - - g_string_append_printf (query, - "INSERT { " - " _:tag a nao:Tag;" - " nao:prefLabel %s . " - "} " - "WHERE {" - " OPTIONAL {" - " ?tag a nao:Tag ;" - " nao:prefLabel %s" - " } ." - " FILTER (!bound(?tag)) " - "} " - "INSERT { " - " ?urn nao:hasTag ?label " - "} " - "WHERE {" - " ?urn nie:url ?f ." - " ?label nao:prefLabel %s " - " %s " - "}", - tag_escaped, - tag_escaped, - tag_escaped, - filter); - - g_free (tag_escaped); - g_free (filter); - g_strfreev (files); - } else { - query = g_string_new (tracker_tags_add_query (tag)); - } - - td = tag_data_new (NULL, NULL, FALSE, TRUE, files, tv); - private->tag_data_requests = - g_list_prepend (private->tag_data_requests, td); - - tracker_sparql_connection_update_async (private->connection, - query->str, - G_PRIORITY_DEFAULT, - td->cancellable, - tags_view_model_update_cb, - td); - - g_string_free (query, TRUE); -} - -static void -tags_view_model_toggle_cell_data_func (GtkTreeViewColumn *column, - GtkCellRenderer *cell_renderer, - GtkTreeModel *tree_model, - GtkTreeIter *iter, - gpointer user_data) -{ - GValue inconsistent = { 0 }; - gint selection; - - gtk_tree_model_get (tree_model, iter, COL_SELECTION, &selection, -1); - gtk_cell_renderer_toggle_set_active (GTK_CELL_RENDERER_TOGGLE (cell_renderer), - SELECTION_TRUE == selection); - - g_value_init (&inconsistent, G_TYPE_BOOLEAN); - g_value_set_boolean (&inconsistent, SELECTION_INCONSISTENT == selection); - g_object_set_property (G_OBJECT (cell_renderer), "inconsistent", &inconsistent); -} - -static void -tags_view_model_toggle_row (TrackerTagsView *tv, - GtkTreePath *path) -{ - TrackerTagsViewPrivate *private; - TagData *td; - GStrv files; - GtkTreeIter iter; - GtkTreeModel *model; - gchar *filter, *query; - gchar *id, *tag, *tag_escaped; - gint selection; - - private = TRACKER_TAGS_VIEW_GET_PRIVATE (tv); - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (private->view)); - - if (gtk_tree_model_get_iter (model, &iter, path) == FALSE) { - return; - } - - gtk_tree_model_get (model, &iter, - COL_SELECTION, &selection, - COL_TAG_ID, &id, - COL_TAG_NAME, &tag, - -1); - - selection = selection == SELECTION_FALSE ? SELECTION_TRUE : SELECTION_FALSE; - - tag_escaped = tracker_tags_escape_sparql_string (tag); - g_free (tag); - - files = tracker_glist_to_string_list_for_nautilus_files (private->files); - filter = tracker_tags_get_filter_string (files, NULL); - g_strfreev (files); - - if (selection) { - query = g_strdup_printf ("INSERT { " - " ?urn nao:hasTag ?label " - "} " - "WHERE {" - " ?urn nie:url ?f ." /* NB: ?f is used in filter. */ - " ?label nao:prefLabel %s ." - " %s " - "}", - tag_escaped, - filter); - } else { - TagData *td; - - query = g_strdup_printf ("DELETE { " - " ?urn nao:hasTag ?label " - "} " - "WHERE { " - " ?urn nie:url ?f ." /* NB: ?f is used in filter. */ - " ?label nao:prefLabel %s ." - " %s " - "}", - tag_escaped, - filter); - - /* Check if there are any files left with this tag and - * remove tag if not. - */ - td = tag_data_new (id, &iter, FALSE, TRUE, 1, tv); - private->tag_data_requests = - g_list_prepend (private->tag_data_requests, td); - - tags_view_query_files_for_tag_id (td); - } - - g_free (filter); - g_free (tag_escaped); - - gtk_widget_set_sensitive (private->entry, FALSE); - - if (!private->connection) { - g_warning ("Can't update tags, " - "no SPARQL connection available"); - g_free (id); - g_free (query); - return; - } - - g_debug ("Running query:'%s'", query); - - td = tag_data_new (id, &iter, TRUE, selection, 1, tv); - private->tag_data_requests = - g_list_prepend (private->tag_data_requests, td); - - tracker_sparql_connection_update_async (private->connection, - query, - G_PRIORITY_DEFAULT, - td->cancellable, - tags_view_model_update_cb, - td); - - g_free (id); - g_free (query); -} - -static void -tags_view_model_cell_toggled_cb (GtkCellRendererToggle *cell, - gchar *path_string, - TrackerTagsView *tv) -{ - GtkTreePath *path; - - path = gtk_tree_path_new_from_string (path_string); - tags_view_model_toggle_row (tv, path); - gtk_tree_path_free (path); -} - -static void -tags_view_model_row_activated_cb (GtkTreeView *view, - GtkTreePath *path, - GtkTreeViewColumn *column, - gpointer user_data) -{ - tags_view_model_toggle_row (user_data, path); -} - -static void -tags_view_entry_changed_cb (GtkEditable *editable, - TrackerTagsView *tv) -{ - TrackerTagsViewPrivate *private; - GtkTreeIter iter; - const gchar *tag; - - private = TRACKER_TAGS_VIEW_GET_PRIVATE (tv); - - tag = gtk_entry_get_text (GTK_ENTRY (private->entry)); - - if (tag_view_model_find_tag (tv, tag, &iter)) { - gtk_widget_set_sensitive (GTK_WIDGET (private->button_add), FALSE); - } else { - gtk_widget_set_sensitive (GTK_WIDGET (private->button_add), - !tracker_is_empty_string (tag)); - } -} - -static void -tags_view_entry_activate_cb (GtkEditable *editable, - TrackerTagsView *tv) -{ - TrackerTagsViewPrivate *private; - - private = TRACKER_TAGS_VIEW_GET_PRIVATE (tv); - - gtk_widget_activate (private->button_add); -} - -static void -tags_view_add_clicked_cb (GtkButton *button, - gpointer user_data) -{ - TrackerTagsView *tv; - TrackerTagsViewPrivate *private; - const gchar *tag; - - tv = user_data; - private = TRACKER_TAGS_VIEW_GET_PRIVATE (tv); - - tag = gtk_entry_get_text (GTK_ENTRY (private->entry)); - tags_view_add_tag (tv, tag); -} - -static void -tags_view_remove_tag (TrackerTagsView *tv, - TagData *td) -{ - TrackerTagsViewPrivate *private; - TagData *td_copy; - gchar *query; - - private = TRACKER_TAGS_VIEW_GET_PRIVATE (tv); - - if (!private->connection) { - g_warning ("Can't remove tag '%s', " - "no SPARQL connection available", - td->tag_id); - return; - } - - query = g_strdup_printf ("DELETE { " - " <%s> a rdfs:Resource " - "}", - td->tag_id); - - td_copy = tag_data_copy (td); - private->tag_data_requests = - g_list_prepend (private->tag_data_requests, td_copy); - - tracker_sparql_connection_update_async (private->connection, - query, - G_PRIORITY_DEFAULT, - td_copy->cancellable, - tags_view_tag_removed_cb, - td_copy); - g_free (query); -} - -static void -tags_view_remove_clicked_cb (GtkButton *button, - gpointer user_data) -{ - TrackerTagsView *tv; - TrackerTagsViewPrivate *private; - TagData *td; - GtkTreeIter iter; - GtkTreeSelection *select; - GtkTreeModel *model; - gchar *id; - - tv = user_data; - private = TRACKER_TAGS_VIEW_GET_PRIVATE (tv); - - select = gtk_tree_view_get_selection (GTK_TREE_VIEW (private->view)); - - if (gtk_tree_selection_get_selected (select, &model, &iter)) { - gtk_tree_model_get (GTK_TREE_MODEL (private->store), &iter, COL_TAG_ID, &id, -1); - - td = tag_data_new (id, &iter, FALSE, TRUE, 1, tv); - private->tag_data_requests = - g_list_prepend (private->tag_data_requests, td); - - tags_view_remove_tag (tv, td); - - private->tag_data_requests = - g_list_remove (private->tag_data_requests, td); - tag_data_free (td); - } -} - -static void -tags_view_model_row_selected_cb (GtkTreeSelection *selection, - gpointer user_data) -{ - TrackerTagsViewPrivate *private; - GtkTreeIter iter; - GtkTreeModel *model; - - private = TRACKER_TAGS_VIEW_GET_PRIVATE (user_data); - - if (gtk_tree_selection_get_selected (selection, &model, &iter)) { - gtk_widget_set_sensitive (GTK_WIDGET (private->button_remove), TRUE); - } else { - gtk_widget_set_sensitive (GTK_WIDGET (private->button_remove), FALSE); - } -} - -static void -tags_view_create_ui (TrackerTagsView *tv) -{ - TrackerTagsViewPrivate *private; - GtkCellRenderer *cell_renderer; - GtkTreeSelection *selection; - GtkTreeViewColumn *column; - GtkWidget *hbox; - GtkWidget *label; - GtkWidget *entry; - GtkWidget *button; - GtkWidget *scrolled_window; - GtkWidget *view; - gchar *str; - - private = TRACKER_TAGS_VIEW_GET_PRIVATE (tv); - - gtk_container_set_border_width (GTK_CONTAINER (tv), 6); - gtk_box_set_homogeneous (GTK_BOX (tv), FALSE); - gtk_box_set_spacing (GTK_BOX (tv), 6); - - /* Add entry/label part */ - str = g_strdup_printf (dngettext (NULL, - "_Set the tags you want to associate with the %d selected item:", - "_Set the tags you want to associate with the %d selected items:", - g_list_length (private->files)), - g_list_length (private->files)); - - label = gtk_label_new_with_mnemonic (str); - g_free (str); - gtk_label_set_line_wrap (GTK_LABEL (label), TRUE); - - gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5); - gtk_box_pack_start (GTK_BOX (tv), label, FALSE, TRUE, 0); - - hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12); - gtk_box_pack_start (GTK_BOX (tv), hbox, FALSE, TRUE, 0); - - entry = gtk_entry_new (); - gtk_box_pack_start (GTK_BOX (hbox), entry, TRUE, TRUE, 0); - - gtk_entry_set_activates_default (GTK_ENTRY (entry), TRUE); - gtk_label_set_mnemonic_widget (GTK_LABEL (label), entry); - - g_signal_connect (entry, "changed", - G_CALLBACK (tags_view_entry_changed_cb), - tv); - g_signal_connect (entry, "activate", - G_CALLBACK (tags_view_entry_activate_cb), - tv); - - button = gtk_button_new_from_stock (GTK_STOCK_ADD); - gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0); - - gtk_widget_set_can_default (button, TRUE); - gtk_widget_set_sensitive (button, FALSE); - - g_signal_connect (button, "clicked", - G_CALLBACK (tags_view_add_clicked_cb), - tv); - - private->button_add = button; - - button = gtk_button_new_from_stock (GTK_STOCK_REMOVE); - gtk_box_pack_start (GTK_BOX (hbox), button, FALSE, TRUE, 0); - - gtk_widget_set_sensitive (button, FALSE); - - g_signal_connect (button, "clicked", - G_CALLBACK (tags_view_remove_clicked_cb), - tv); - - private->button_remove = button; - - /* List */ - scrolled_window = gtk_scrolled_window_new (NULL, NULL); - gtk_box_pack_start (GTK_BOX (tv), scrolled_window, TRUE, TRUE, 0); - gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_POLICY_AUTOMATIC, - GTK_POLICY_AUTOMATIC); - gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), - GTK_SHADOW_IN); - - view = gtk_tree_view_new (); - gtk_container_add (GTK_CONTAINER (scrolled_window), view); - - /* List column: toggle */ - column = gtk_tree_view_column_new (); - gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); - - gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width (column, 50); - - cell_renderer = gtk_cell_renderer_toggle_new (); - g_signal_connect (cell_renderer, "toggled", - G_CALLBACK (tags_view_model_cell_toggled_cb), - tv); - - gtk_tree_view_column_pack_start (column, cell_renderer, TRUE); - gtk_tree_view_column_set_cell_data_func (column, - cell_renderer, - tags_view_model_toggle_cell_data_func, - NULL, - NULL); - gtk_cell_renderer_toggle_set_radio (GTK_CELL_RENDERER_TOGGLE (cell_renderer), FALSE); - - /* List column: tag */ - column = gtk_tree_view_column_new (); - gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); - - cell_renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_column_set_expand (column, TRUE); - gtk_tree_view_column_pack_start (column, cell_renderer, TRUE); - gtk_tree_view_column_add_attribute (column, cell_renderer, "text", COL_TAG_NAME); - - /* List column: count */ - column = gtk_tree_view_column_new (); - gtk_tree_view_append_column (GTK_TREE_VIEW (view), column); - - gtk_tree_view_column_set_sizing (column, GTK_TREE_VIEW_COLUMN_FIXED); - gtk_tree_view_column_set_fixed_width (column, 50); - - cell_renderer = gtk_cell_renderer_text_new (); - gtk_tree_view_column_pack_end (column, cell_renderer, FALSE); - gtk_tree_view_column_add_attribute (column, cell_renderer, "text", COL_TAG_COUNT); - - /* List settings */ - gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (view), FALSE); - gtk_tree_view_set_model (GTK_TREE_VIEW (view), - GTK_TREE_MODEL (private->store)); - - - selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (view)); - gtk_tree_selection_set_mode (selection, GTK_SELECTION_SINGLE); - g_signal_connect (view, "row-activated", - G_CALLBACK (tags_view_model_row_activated_cb), - tv); - - g_signal_connect (selection, "changed", - G_CALLBACK (tags_view_model_row_selected_cb), - tv); - - if (private->connection) { - tracker_sparql_connection_query_async (private->connection, - "SELECT ?urn ?label " - "WHERE {" - " ?urn a nao:Tag ;" - " nao:prefLabel ?label . " - "} ORDER BY ?label", - private->cancellable, - tags_view_add_tags_cb, - tv); - } else { - g_warning ("Can't query for tags, " - "no SPARQL connection available"); - } - - gtk_widget_show_all (GTK_WIDGET (tv)); - gtk_widget_grab_focus (entry); - - /* Save vars */ - private->entry = entry; - private->view = view; -} - -void -tracker_tags_view_register_types (GTypeModule *module) -{ - tracker_tags_view_register_type (module); -} - -GtkWidget * -tracker_tags_view_new (GList *files) -{ - TrackerTagsView *tv; - TrackerTagsViewPrivate *private; - - g_return_val_if_fail (files != NULL, NULL); - - g_debug ("New TrackerTagsView with %d files", g_list_length (files)); - tv = g_object_new (TRACKER_TYPE_TAGS_VIEW, NULL); - - private = TRACKER_TAGS_VIEW_GET_PRIVATE (tv); - private->files = nautilus_file_info_list_copy (files); - - tags_view_create_ui (tv); - - return GTK_WIDGET (tv); -} diff --git a/src/plugins/nautilus/tracker-tags-view.h b/src/plugins/nautilus/tracker-tags-view.h deleted file mode 100644 index 4052c0c02..000000000 --- a/src/plugins/nautilus/tracker-tags-view.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2009, Debarshi Ray <debarshir@src.gnome.org> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) 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. - */ - -#ifndef __TRACKER_TAGS_VIEW_H__ -#define __TRACKER_TAGS_VIEW_H__ - -#include <gtk/gtk.h> - -G_BEGIN_DECLS - -#define TRACKER_TYPE_TAGS_VIEW (tracker_tags_view_get_type ()) -#define TRACKER_TAGS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TRACKER_TYPE_TAGS_VIEW, TrackerTagsView)) -#define TRACKER_TAGS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TRACKER_TYPE_TAGS_VIEW, TrackerTagsViewClass)) -#define TRACKER_IS_TAGS_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TRACKER_TYPE_TAGS_VIEW)) -#define TRACKER_IS_TAGS_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TRACKER_TYPE_TAGS_VIEW)) - -typedef struct _TrackerTagsViewPrivate TrackerTagsViewPrivate; -typedef struct _TrackerTagsView TrackerTagsView; -typedef struct _TrackerTagsViewClass TrackerTagsViewClass; - -struct _TrackerTagsView { - GtkVBox parent; - TrackerTagsViewPrivate *private; -}; - -struct _TrackerTagsViewClass { - GtkVBoxClass parent; -}; - -GType tracker_tags_view_get_type (void); -GtkWidget *tracker_tags_view_new (GList *files); -void tracker_tags_view_register_types (GTypeModule *module); - -G_END_DECLS - -#endif /* __TRACKER_TAGS_VIEW_H__ */ diff --git a/src/plugins/thunderbird/Makefile.am b/src/plugins/thunderbird/Makefile.am deleted file mode 100644 index 2d8ea96ba..000000000 --- a/src/plugins/thunderbird/Makefile.am +++ /dev/null @@ -1,28 +0,0 @@ -SUBDIRS = chrome defaults - -extensiondir = $(datadir)/xul-ext/trackerbird -extension_DATA = \ - install.rdf \ - chrome.manifest \ - README - -mimefixdir = $(datadir)/applications/ -mimefix_DATA = trackerbird-launcher.desktop - -EXTRA_DIST = $(extension_DATA) $(mimefix_DATA) - -update-desktop-database: - @-if test -z "$(DESTDIR)"; then \ - echo "Updating .desktop database."; \ - update-desktop-database; \ - else \ - echo "*** .desktop database not updated. After (un)install, run this:"; \ - echo "*** update-desktop-database"; \ - fi - -install-data-hook: update-desktop-database - $(MKDIR_P) "$(DESTDIR)$(TRACKER_MINER_THUNDERBIRD_INSTALL_DIR)" - $(LN_S) -f "$(extensiondir)" "$(DESTDIR)$(TRACKER_MINER_THUNDERBIRD_INSTALL_DIR)/trackerbird@bustany.org" - -uninstall-hook: update-desktop-database - $(RM) "$(DESTDIR)$(TRACKER_MINER_THUNDERBIRD_INSTALL_DIR)/trackerbird@bustany.org" diff --git a/src/plugins/thunderbird/README b/src/plugins/thunderbird/README deleted file mode 100644 index 33100453b..000000000 --- a/src/plugins/thunderbird/README +++ /dev/null @@ -1,14 +0,0 @@ -A simple Thunderbird extension to export mails to Tracker. - -=== How to build a .xpi file === -From the src/plugins/thunderbird folder, run -git archive --format zip HEAD > tracker-thunderbird.xpi - -=== How to test the extension without installing it === -This method makes development much easier, since it avoids the hassle of -rebuilding the XPI everytime a change is made in the code: -In your Thunderbird profile directory, locate the extensions folder. In that -folder, create a file named trackerbird@bustany.org. In that file, put the full -path to the thunderbird plugin source folder, for example -/home/foobar/Projects/tracker/src/plugins/thunderbird/ -Note the trailing slash, it MUST be included for this method to work. diff --git a/src/plugins/thunderbird/chrome.manifest b/src/plugins/thunderbird/chrome.manifest deleted file mode 100644 index a5d88ad99..000000000 --- a/src/plugins/thunderbird/chrome.manifest +++ /dev/null @@ -1,10 +0,0 @@ -content trackerbird chrome/content/ -skin trackerbird classic/1.0 chrome/skin/ -locale trackerbird en-US chrome/locale/en-US/ -locale trackerbird de-DE chrome/locale/de-DE/ -locale trackerbird es-ES chrome/locale/es-ES/ -locale trackerbird fr-FR chrome/locale/fr-FR/ -locale trackerbird pl-PL chrome/locale/pl-PL/ - -overlay chrome://messenger/content/messenger.xul chrome://trackerbird/content/tb-overlay.xul - diff --git a/src/plugins/thunderbird/chrome/Makefile.am b/src/plugins/thunderbird/chrome/Makefile.am deleted file mode 100644 index 90fd0e7f3..000000000 --- a/src/plugins/thunderbird/chrome/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = skin locale content diff --git a/src/plugins/thunderbird/chrome/content/Makefile.am b/src/plugins/thunderbird/chrome/content/Makefile.am deleted file mode 100644 index 805d4142f..000000000 --- a/src/plugins/thunderbird/chrome/content/Makefile.am +++ /dev/null @@ -1,16 +0,0 @@ -extensiondir = $(datadir)/xul-ext/trackerbird/chrome/content -extension_DATA = \ - mailstore.js \ - options.xul \ - queue.js \ - namespace.js \ - about.xul \ - tb-overlay.xul \ - plugin.js \ - bindings.js \ - email-address-parser.js \ - persistent-store.js \ - ui.js \ - trackerstore.js - -EXTRA_DIST = $(extension_DATA) diff --git a/src/plugins/thunderbird/chrome/content/about.xul b/src/plugins/thunderbird/chrome/content/about.xul deleted file mode 100644 index 254caba31..000000000 --- a/src/plugins/thunderbird/chrome/content/about.xul +++ /dev/null @@ -1,18 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> - -<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> - -<!DOCTYPE dialog SYSTEM "chrome://trackerbird/locale/about.dtd"> - -<dialog title="&about; TrackerBird" orient="vertical" autostretch="always" onload="sizeToContent()" buttons="accept" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - <groupbox align="center" orient="horizontal"> - <vbox> - <text value="TrackerBird" style="font-weight: bold; font-size: x-large;"/> - <text value="&version; 1.0"/> - <separator class="thin"/> - <text value="&createdBy;" style="font-weight: bold;"/> - <text value="Adrien Bustany"/> - <separator class="thin"/> - </vbox> - </groupbox> -</dialog> diff --git a/src/plugins/thunderbird/chrome/content/bindings.js b/src/plugins/thunderbird/chrome/content/bindings.js deleted file mode 100644 index 0688e5bf8..000000000 --- a/src/plugins/thunderbird/chrome/content/bindings.js +++ /dev/null @@ -1,160 +0,0 @@ -if (!org.bustany.TrackerBird.TrackerSparql || !org.bustany.TrackerBird.TrackerSparql.__initialized) -org.bustany.TrackerBird.TrackerSparql = { - __initialized: true, - - _trackerSparqlPath1: "libtracker-sparql-1.0.so.0", - _trackerSparqlPath2: "libtracker-sparql-0.16.so.0", - _lib: null, - - init: function () { - var tracker = org.bustany.TrackerBird.TrackerSparql; - - // Safeguard just in case a fool would call that twice - if (tracker._lib) { - return true; - } - - Components.utils.import ("resource://gre/modules/ctypes.jsm"); - - try { - tracker._lib = ctypes.open (tracker._trackerSparqlPath1); - } catch (e) { - dump ("Could not load " + tracker._trackerSparqlPath1 + ": " + e + "\n"); - - try { - tracker._lib = ctypes.open (tracker._trackerSparqlPath2); - } catch (e) { - dump ("Could not load " + tracker._trackerSparqlPath2 + ": " + e + "\n"); - return false; - } - } - - // GLib types - tracker.Object = new ctypes.StructType ("GObject"); - tracker.Cancellable = new ctypes.StructType ("GCancellable"); - tracker.Error = new ctypes.StructType ("GError", [ - {domain : ctypes.uint32_t}, - {code : ctypes.int32_t}, - {message : ctypes.char.ptr} - ]); - tracker.AsyncResult = new ctypes.StructType ("GAsyncResult"); - tracker.AsyncReadyCallback = new ctypes.FunctionType( - ctypes.default_abi, - ctypes.void_t, - [ tracker.Object.ptr, tracker.AsyncResult.ptr, ctypes.voidptr_t ]); - - // TrackerSparql types - tracker.Connection = ctypes.StructType ("TrackerSparqlConnection"); - tracker.Cursor = ctypes.StructType ("TrackerSparqlCursor"); - - // GLib methods - tracker.free = tracker._lib.declare ( - "g_free", - ctypes.default_abi, - ctypes.void_t, - ctypes.voidptr_t - ); - - tracker.object_unref = tracker._lib.declare ( - "g_object_unref", - ctypes.default_abi, - ctypes.void_t, - tracker.Object.ptr - ); - - tracker.error_free = tracker._lib.declare ( - "g_error_free", - ctypes.default_abi, - ctypes.void_t, - tracker.Error.ptr - ); - - // TrackerSparql methods (name, ABI, args with first arg = return type) - tracker.connection_open = tracker._lib.declare ( - "tracker_sparql_connection_get", - ctypes.default_abi, - tracker.Connection.ptr, - tracker.Cancellable.ptr, - tracker.Error.ptr.ptr - ); - - tracker.connection_open_async = tracker._lib.declare ( - "tracker_sparql_connection_get_async", - ctypes.default_abi, - ctypes.void_t, - tracker.Cancellable.ptr, - tracker.AsyncReadyCallback.ptr, - ctypes.voidptr_t); - - tracker.connection_open_finish = tracker._lib.declare ( - "tracker_sparql_connection_get_finish", - ctypes.default_abi, - tracker.Connection.ptr, - tracker.AsyncResult.ptr, - tracker.Error.ptr.ptr); - - tracker.connection_query = tracker._lib.declare ( - "tracker_sparql_connection_query", - ctypes.default_abi, - tracker.Cursor.ptr, - tracker.Connection.ptr, - ctypes.char.ptr, - tracker.Cancellable.ptr, - tracker.Error.ptr.ptr - ); - - tracker.connection_update = tracker._lib.declare ( - "tracker_sparql_connection_update", - ctypes.default_abi, - ctypes.void_t, - tracker.Connection.ptr, - ctypes.char.ptr, - ctypes.int32_t, - tracker.Cancellable.ptr, - tracker.Error.ptr.ptr - ); - - tracker.cursor_next = tracker._lib.declare ( - "tracker_sparql_cursor_next", - ctypes.default_abi, - ctypes.bool, - tracker.Cursor.ptr, - tracker.Cancellable.ptr, - tracker.Error.ptr.ptr - ); - - tracker.cursor_get_string = tracker._lib.declare ( - "tracker_sparql_cursor_get_string", - ctypes.default_abi, - ctypes.char.ptr, - tracker.Cursor.ptr, - ctypes.int, - ctypes.long.ptr - ); - - tracker.escape_string = tracker._lib.declare ( - "tracker_sparql_escape_string", - ctypes.default_abi, - ctypes.char.ptr, - ctypes.char.ptr - ); - - dump ("TrackerSparql initialized successfully\n") - return true; - }, - - shutdown: function () { - var tracker = org.bustany.TrackerBird.TrackerSparql; - - if (this._connection) { - dump ("TrackerSparql closing connection\n") - tracker.object_unref(this._connection); - } - - if (this._lib) { - dump ("TrackerSparql closing library\n") - this._lib.close (); - } - dump ("TrackerSparql shut down successfully\n") - } -} diff --git a/src/plugins/thunderbird/chrome/content/email-address-parser.js b/src/plugins/thunderbird/chrome/content/email-address-parser.js deleted file mode 100644 index c604345b6..000000000 --- a/src/plugins/thunderbird/chrome/content/email-address-parser.js +++ /dev/null @@ -1,33 +0,0 @@ -if (!org.bustany.TrackerBird.EmailAddressParser || !org.bustany.TrackerBird.EmailAddressParser.__initialized) -org.bustany.TrackerBird.EmailAddressParser = { - // Init barrier - __initialized: true, - - // Parses an email address in a {name: address:} object - parse: function(str) { - var longAddr = /\s*(.*?)\s*<([^\x00-\x20\(\)<>@,;:\\"\[\]]+@[^\x00-\x20\(\)<>@,;:\\"\[\]]+)>\s*$/; - var addrSpec = /\s*([^\x00-\x20\(\)<>@,;:\\"\[\]]+@[^\x00-\x20\(\)<>@,;:\\"\[\]]+)\s*/; - - var matches = str.match(longAddr); - - if (matches != null) { - return { - name: matches[1].replace(/"(.+)"/, "$1"), - address: matches[2] - }; - } - - matches = str.match(addrSpec); - - if (matches != null) { - return { - name: "", - address: matches[1] - }; - } - - dump("Could not parse email address " + str + "\n"); - - return null; - } -} diff --git a/src/plugins/thunderbird/chrome/content/mailstore.js b/src/plugins/thunderbird/chrome/content/mailstore.js deleted file mode 100644 index 26c8bc43b..000000000 --- a/src/plugins/thunderbird/chrome/content/mailstore.js +++ /dev/null @@ -1,242 +0,0 @@ -if (!org.bustany.TrackerBird.MailStore || !org.bustany.TrackerBird.MailStore.__initialized) { - -Components.utils.import("resource:///modules/MailUtils.js"); - -org.bustany.TrackerBird.ContentRetriever = function(header, callback) { - this._header = header; - this._callback = callback; - this._contents = ""; -} - -org.bustany.TrackerBird.ContentRetriever.prototype = { - onStartRequest: function(request, ctx) { - }, - - onDataAvailable: function(request, context, inputStream, offset, count) { - var scriptableInputStream = - Components.classes["@mozilla.org/scriptableinputstream;1"]. - createInstance(Components.interfaces.nsIScriptableInputStream); - scriptableInputStream.init(inputStream); - var data = scriptableInputStream.read(count); - this._contents += data; - }, - - onStopRequest: function(request, ctx, status) { - // Basic html removing - this._contents = this._contents.replace(/<[^>]+?>/g, ""); - this._callback(this._header, this._contents); - }, - - QueryInterface: function (aIID) { - if (aIID.equals(Components.interfaces.nsIStreamListener) || - aIID.equals(Components.interfaces.nsISupports)) { - return this; - } - throw Components.results.NS_NOINTERFACE; - } -} - -org.bustany.TrackerBird.MailStore = { - // Init barrier - __initialized: true, - __console: Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService), - _log: function(msg) { - this.__console.logStringMessage(msg); - }, - - _trackerStore: org.bustany.TrackerBird.TrackerStore, - _persistentStore: org.bustany.TrackerBird.PersistentStore, - - _folderListener: { - OnItemAdded: function(parentItem, item) { - dump("Trackerbird: new item to be tracked\n"); - var store = org.bustany.TrackerBird.MailStore; - var hdr = item.QueryInterface(Components.interfaces.nsIMsgDBHdr); - - store._queue.addImmediate({ - callback: store._indexMessageCallback, - data: hdr - }); - }, - - OnItemRemoved: function(parentItem, item) { - dump("Trackerbird: item to be untracked\n"); - var store = org.bustany.TrackerBird.MailStore; - var hdr = item.QueryInterface(Components.interfaces.nsIMsgDBHdr); - - store._queue.addImmediate({ - callback: store._removeMessageCallback, - data: hdr - }); - }, - - OnItemPropertyChanged: function(item, property, oldValue, newValue) { - }, - - OnItemIntPropertyChanged: function(item, property, oldValue, newValue) { - }, - - OnItemBoolPropertyChanged: function(item, property, oldValue, newValue) { - }, - - OnItemUnicharPropertyChanged: function(item, property, oldValue, newValue) { - }, - - OnItemPropertyFlagChanged: function(header, property, oldValue, newValue) { - }, - - OnItemEvent: function(folder, event) { - } - }, - - _queue: null, - _walkFolderCallback: null, - _indexMessageCallback: null, - _indexMessageContentsCallback: null, - _removeMessageCallback: null, - - _prefs: null, - - init: function() { - dump ("Trackerbird initializing mailstore...\n") - // To get notifications - var mailSession = Components.classes["@mozilla.org/messenger/services/session;1"]. - getService(Components.interfaces.nsIMsgMailSession); - - mailSession.AddFolderListener(this._folderListener, - Components.interfaces.nsIFolderListener.all); - - this._prefs = Components.classes["@mozilla.org/preferences-service;1"] - .getService(Components.interfaces.nsIPrefService).getBranch("extensions.trackerbird."); - - var store = this; - this._queue = new org.bustany.TrackerBird.Queue(this._prefs.getIntPref("indexDelay")), - this._walkFolderCallback = function(item) { store.walkFolder(item); } - this._indexMessageCallback = function(msg) { store.indexMessage(msg); } - this._indexMessageContentsCallback = function(msg, contents) { - store.indexMessageContents(msg, contents); - } - this._removeMessageCallback = function(msg) { store.removeMessage(msg); } - - MailUtils.discoverFolders(); - dump ("Trackerbird mailstore initialized...\n") - this._log("trackerbird: mailstore initialized"); - return true; - }, - - listAllFolders: function() { - var store = this; - var servers = MailServices.accounts.allServers; - - for (var i = 0; i < servers.length; i++) { - var s = servers.queryElementAt(i, Components.interfaces.nsIMsgIncomingServer); - - var folders = Components.classes["@mozilla.org/array;1"]. - createInstance(Components.interfaces.nsIMutableArray); - s.rootFolder.ListDescendants(folders); - - for (var j = 0; j < folders.length; j++) { - var folder = folders.queryElementAt(j, Components.interfaces.nsIMsgFolder); - - this._queue.add({ - callback: store._walkFolderCallback, - data: folder - }); - } - } - - this._queue.add({ - callback: function() { - dump("Trackerbird walked all folders\n"); - store._log("trackerbird: walked all folders"); - }, - data: null - }) - }, - - walkFolder: function(folder) { - dump("Walking folder " + folder.prettiestName + "\n"); - - var db = folder.msgDatabase; - var enumerator = db.EnumerateMessages(); - var knownUris = this._persistentStore.getUrisForFolder(folder); - - var uriCache = {}; - - for (var i in knownUris) { - uriCache[knownUris[i]] = true; - } - - knownUris = null; - - while (enumerator.hasMoreElements()) { - var hdr = enumerator.getNext().QueryInterface(Components.interfaces.nsIMsgDBHdr); - - if (uriCache[folder.getUriForMsg(hdr)]) { - continue; - } - - this._queue.add({ - callback: this._indexMessageCallback, - data: hdr - }); - } - - // Close database - db = null; - }, - - /** - * This method indexes a new message. In order to do this, it has to retrieve its contents - * first. The contents is only available as a stream that has to be read first. - * When the contents has been read, indexMessageContents is called and the actual - * indexing happens. - */ - indexMessage: function(header) { - var folder = header.folder; - - var messenger = Components.classes["@mozilla.org/messenger;1"]. - createInstance(Components.interfaces.nsIMessenger); - var uri = folder.getUriForMsg(header); - var msgService = messenger.messageServiceFromURI(uri); - - // Streaming data into a nsScriptableInputStream and then reading from it here - // makes thunderbird hang sometimes, so continue asynchronously. - try { - var msgStream = new org.bustany.TrackerBird.ContentRetriever(header, this._indexMessageContentsCallback); - msgService.streamMessage(uri, msgStream, null, null, true, null); - } catch (ex) { - dump("Trackerbird could not get contents of message " + ex + "\n"); - } - }, - - /** - * Index the message by inserting it into our local store of indexed messages and - * into the tracker store. - */ - indexMessageContents: function(msg, contents) { - try { - if (this._trackerStore.storeMessage(msg, contents)) { - this._persistentStore.rememberMessage(msg); - } - } catch (ex) { - dump("Trackerbird failed to index message: " + ex + "\n"); - this._log("Trackerbird failed to index message: " + ex); - } - }, - - removeMessage: function(msg) { - this._trackerStore.deleteMessage(msg); - this._persistentStore.forgetMessage(msg); - }, - - shutdown: function() { - dump ("Trackerbird mailstore store shutting down...\n") - var mailSession = Components.classes["@mozilla.org/messenger/services/session;1"]. - getService(Components.interfaces.nsIMsgMailSession); - - mailSession.Remove(this._folderListener); - dump ("Trackerbird mailstore store shut down\n") - } -} -} diff --git a/src/plugins/thunderbird/chrome/content/namespace.js b/src/plugins/thunderbird/chrome/content/namespace.js deleted file mode 100644 index 29ed33da1..000000000 --- a/src/plugins/thunderbird/chrome/content/namespace.js +++ /dev/null @@ -1,5 +0,0 @@ -// Avoid polluting main namespace -if (!org) var org = {}; -if (!org.bustany) org.bustany = {}; -if (!org.bustany.TrackerBird) org.bustany.TrackerBird = {}; - diff --git a/src/plugins/thunderbird/chrome/content/options.xul b/src/plugins/thunderbird/chrome/content/options.xul deleted file mode 100644 index ef2a8dfce..000000000 --- a/src/plugins/thunderbird/chrome/content/options.xul +++ /dev/null @@ -1,11 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> -<!DOCTYPE prefwindow SYSTEM "chrome://trackerbird/locale/options.dtd"> -<prefwindow id="trackerbird-preferences" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" title="&prefwindow.title;"> - <prefpane id="pane1" label="&pane1.title;"> - <preferences> - <preference id="indexDelay" name="extensions.trackerbird.intpref" type="int"/> - </preferences> - <label accesskey="&indexDelay.accesskey;" control="textIndexDelay">&indexDelay.label;</label><textbox id="textIndexDelay" type="number" preference="indexDelay"/> - </prefpane> -</prefwindow> diff --git a/src/plugins/thunderbird/chrome/content/persistent-store.js b/src/plugins/thunderbird/chrome/content/persistent-store.js deleted file mode 100644 index 77313ae92..000000000 --- a/src/plugins/thunderbird/chrome/content/persistent-store.js +++ /dev/null @@ -1,186 +0,0 @@ -if (!org.bustany.TrackerBird.PersistentStore || !org.bustany.TrackerBird.PersistentStore.__initialized) -org.bustany.TrackerBird.PersistentStore = { - // Init barrier - __initialized: true, - __console: Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService), - _log: function(msg) { - this.__console.logStringMessage(msg); - }, - - _schemaVersion: 1, - - _db: null, - _rememberMessageStatement: null, - _forgetMessageStatement: null, - _fetchUrisStatement: null, - _insertMetaStatement: null, - _updateMetaStatement: null, - _selectMetaStatement: null, - - _transactionPending: false, - _nInsertsPending: 0, - - init: function() { - // Get profile directory - var file = Components.classes["@mozilla.org/file/directory_service;1"] - .getService(Components.interfaces.nsIProperties) - .get("ProfD", Components.interfaces.nsIFile); - file.append("trackerbird.sqlite"); - - var storageService = Components.classes["@mozilla.org/storage/service;1"] - .getService(Components.interfaces.mozIStorageService); - - this._db = storageService.openDatabase(file); - - if (!this._db) { - dump("Could not open DB file " + file + "\n"); - return false; - } - - this._db.executeSimpleSQL("CREATE TABLE IF NOT EXISTS knownMessages (folderUri VARCHAR(255), msgUri VARCHAR(255) NOT NULL UNIQUE);"); - this._db.executeSimpleSQL("CREATE TABLE IF NOT EXISTS meta (key VARCHAR(255) NOT NULL UNIQUE, value VARCHAR(255));"); - this._rememberMessageStatement = this._db.createStatement("INSERT INTO knownMessages VALUES (:folderUri, :msgUri)"); - this._forgetMessageStatement = this._db.createStatement("DELETE FROM knownMessages WHERE msgUri = :msgUri"); - this._fetchUrisStatement = this._db.createStatement("SELECT msgUri FROM knownMessages WHERE folderUri = :folderUri"); - this._insertMetaStatement = this._db.createStatement("INSERT OR IGNORE INTO meta VALUES (:key, :value)"); - this._updateMetaStatement = this._db.createStatement("INSERT OR REPLACE INTO meta VALUES (:key, :value)"); - this._selectMetaStatement = this._db.createStatement("SELECT value FROM meta WHERE key = :key"); - - this.insertDefaultSettings(); - - var currentSchemaVersion = this.getSetting("version"); - if (!currentSchemaVersion || (currentSchemaVersion < this._schemaVersion)) { - dump("Schema changed, reseting index\n"); - this._db.executeSimpleSQL("DELETE FROM knownMessages;"); - this.insertSetting("version", this._schemaVersion, true); - } - - dump ("Trackerbird persistent store initialized\n") - this._log("trackerbird: persistent store initialized") - return true; - }, - - shutdown: function() { - dump ("Trackerbird persistent store shutting down...\n") - this.endTransaction(); - this._rememberMessageStatement.finalize(); - this._forgetMessageStatement.finalize(); - this._fetchUrisStatement.finalize(); - this._insertMetaStatement.finalize(); - this._updateMetaStatement.finalize(); - this._selectMetaStatement.finalize(); - this._db.close(); - dump ("Trackerbird persistent store shut down\n") - }, - - rememberMessage: function(msg) { - var folder = msg.folder; - var stmt = this._rememberMessageStatement; - var uri = folder.getUriForMsg(msg); - - stmt.params.folderUri = folder.folderURL; - stmt.params.msgUri = uri; - - this.runUpdate(stmt); - }, - - forgetMessage: function(msg) { - var folder = msg.folder; - var stmt = this._forgetMessageStatement; - var uri = folder.getUriForMsg(msg); - - stmt.params.msgUri = uri; - - this.runUpdate(stmt); - }, - - runUpdate: function(stmt) { - this.startTransaction(); - - // execute() also calls reset() on the statement - stmt.execute(); - this._nInsertsPending ++; - - // Commit every 100 INSERTS - if (this._nInsertsPending > 100) { - this.endTransaction(); - this._nInsertsPending = 0; - } - }, - - getUrisForFolder: function(folder) { - var stmt = this._fetchUrisStatement; - var uris = []; - - this.endTransaction(); - - stmt.params.folderUri = folder.folderURL; - - while (stmt.step()) { - uris.push(stmt.row.msgUri); - } - - return uris; - }, - - startTransaction: function() { - if (this._transactionPending) { - return; - } - - this._db.beginTransaction(); - this._transactionPending = true; - }, - - endTransaction: function() { - if (!this._transactionPending) { - return; - } - - this._db.commitTransaction(); - this._transactionPending = false; - }, - - insertDefaultSettings: function() { - this.startTransaction(); - - // We perform "SILENT" inserts, ie don't replace any existing value - var stmt = this._insertMetaStatement; - - // Schema version - this.insertSetting("version", this._schemaVersion, false); - - this.endTransaction(); - }, - - insertSetting: function(key, value, replace) { - var stmt = (replace ? this._updateMetaStatement : this._insertMetaStatement); - - stmt.params.key = key; - stmt.params.value = value; - - try { - stmt.execute(); - } catch (e) { - dump("Couldn't save setting " + key + ": " + e + "\n"); - } - }, - - getSetting: function(key) { - var stmt = this._selectMetaStatement; - stmt.params.key = key; - - try { - if (!stmt.step()) { - return null; - } - - var value = stmt.row.value; - stmt.reset(); - return value; - } catch (e) { - dump("Could not get setting " + key + ": " + e + "\n"); - return null; - } - } -} diff --git a/src/plugins/thunderbird/chrome/content/plugin.js b/src/plugins/thunderbird/chrome/content/plugin.js deleted file mode 100644 index f2b337803..000000000 --- a/src/plugins/thunderbird/chrome/content/plugin.js +++ /dev/null @@ -1,106 +0,0 @@ -if (!org.bustany.TrackerBird.Plugin || !org.bustany.TrackerBird.Plugin.__initialized) -org.bustany.TrackerBird.Plugin = { - // Init barrier - __initialized: true, - - _trackerConnection: null, - _mailstore: org.bustany.TrackerBird.MailStore, - _persistentstore: org.bustany.TrackerBird.PersistentStore, - _trackerstore: org.bustany.TrackerBird.TrackerStore, - _ui: org.bustany.TrackerBird.Ui, - - onLoad: function() { - dump("Initialiazing TrackerBird...\n"); - - if (!this._ui.init()) { - dump("Could not initialize Ui\n"); - return; - } - - if (!this.initTracker()) { - this._ui.showMessage("cannotInit"); - return; - } - - // Rest of the init is done in onTrackerReady - }, - - onUnload: function() { - dump("Shutting down TrackerBird...\n"); - - if (this._persistentstore) { - this._persistentstore.shutdown(); - } - - if (this._mailstore) { - this._mailstore.shutdown(); - } - dump("TrackerBird shut down\n"); - }, - - initTracker: function() { - var tracker = org.bustany.TrackerBird.TrackerSparql; - - if (!tracker.init()) { - dump("Could not load Tracker libraries\n"); - return false; - } - - var plugin = this; - var callback_closure = function(source_object, result, user_data) { - plugin.onTrackerReady(source_object, result, user_data); - } - - tracker.readyCallback = tracker.AsyncReadyCallback.ptr(callback_closure); - tracker.connection_open_async(null, tracker.readyCallback, null); - - dump ("Tracker Plugin initialized successfully\n") - return true; - }, - - onTrackerReady: function(source_object, result, user_data) { - dump ("Tracker connection opened\n") - var tracker = org.bustany.TrackerBird.TrackerSparql; - - var error = new tracker.Error.ptr; - this._trackerConnection = tracker.connection_open_finish (result, error.address()); - - if (!error.isNull ()) { - dump ("Could not initialize Tracker: " + error.contents.message.readString() + "\n"); - this._ui.showMessage("cannotConnect"); - tracker.error_free(error); - return; - } - - // Tracker is ready, proceed with the rest of the init - - this._ui.showMessage("initializing"); - - if (!this._persistentstore.init()) { - this._ui.showMessage("cannotInitPersistent"); - dump("Could not initialize Persistent store\n"); - _persistentstore = null; - return; - } - - if (!this._trackerstore.init(this._trackerConnection)) { - dump("Could not initialize Tracker store\n"); - _trackerstore = null; - return; - } - - if (!this._mailstore.init()) { - this._ui.showMessage("cannotInitMail"); - dump("Could not initialize mail store\n"); - _mailstore = null; - return; - } - - this._ui.showMessage("starting"); - - this._mailstore.listAllFolders(); - } -} - -window.addEventListener("load", function () { org.bustany.TrackerBird.Plugin.onLoad(); }, false); -window.addEventListener("unload", function () { org.bustany.TrackerBird.Plugin.onUnload(); }, false); diff --git a/src/plugins/thunderbird/chrome/content/queue.js b/src/plugins/thunderbird/chrome/content/queue.js deleted file mode 100644 index 52ec37710..000000000 --- a/src/plugins/thunderbird/chrome/content/queue.js +++ /dev/null @@ -1,54 +0,0 @@ -org.bustany.TrackerBird.Queue = function(delay) { - this._ui = org.bustany.TrackerBird.Ui; - this.__console = Components.classes["@mozilla.org/consoleservice;1"].getService(Components.interfaces.nsIConsoleService); - this._log = function(msg) { - this.__console.logStringMessage(msg); - } - - this._delay = delay; - this._items = []; - this._active = false; - - var queue = this; - this._timerEvent = { notify: function(timer) { queue._active = false; queue.process(); } }; - this._queueTimer = Components.classes["@mozilla.org/timer;1"].createInstance(Components.interfaces.nsITimer); - dump("Trackerbird created queue with delay " + delay + "\n"); -} - -org.bustany.TrackerBird.Queue.prototype.add = function(item) { - this._items.push(item); - this.process(); -} - -org.bustany.TrackerBird.Queue.prototype.addImmediate = function(item) { - this._items.unshift(item); - this.process(); -} - -org.bustany.TrackerBird.Queue.prototype.process = function() { - if (this._items.length == 0) { - this._ui.showMessage("indexerIdle"); - return; - } - this._ui.showFormattedMessage("actionsRemaining", [this._items.length]); - - if (this._active) { - return; - } - this._active = true; - - var item = this._items.shift(); - - try { - item.callback(item.data); - } catch (ex) { - dump ("Trackbird could not execute: " + ex + "\n"); - this._log("Trackerbird could not execute: " + ex); - } - - this._queueTimer.initWithCallback(this._timerEvent, this._delay, Components.interfaces.nsITimer.TYPE_ONE_SHOT); -} - -org.bustany.TrackerBird.Queue.prototype.size = function() { - return this._items.length; -} diff --git a/src/plugins/thunderbird/chrome/content/tb-overlay.xul b/src/plugins/thunderbird/chrome/content/tb-overlay.xul deleted file mode 100644 index 8888a8fdf..000000000 --- a/src/plugins/thunderbird/chrome/content/tb-overlay.xul +++ /dev/null @@ -1,23 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<?xml-stylesheet href="chrome://trackerbird/skin/overlay.css" type="text/css"?> -<!DOCTYPE overlay SYSTEM "chrome://trackerbird/locale/overlay.dtd"> -<overlay id="trackerbird-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> - <script src="namespace.js"/> - <script src="bindings.js"/> - <script src="queue.js"/> - <script src="email-address-parser.js"/> - <script src="ui.js"/> - <script src="persistent-store.js"/> - <script src="trackerstore.js"/> - <script src="mailstore.js"/> - <script src="plugin.js"/> - - <stringbundleset id="stringbundleset"> - <stringbundle id="trackerbird-strings" src="chrome://trackerbird/locale/overlay.properties"/> - </stringbundleset> - - <statusbar id="status-bar"> - <statusbarpanel id="trackerbird-status-panel" label="&idle;"/> - </statusbar> - -</overlay> diff --git a/src/plugins/thunderbird/chrome/content/trackerstore.js b/src/plugins/thunderbird/chrome/content/trackerstore.js deleted file mode 100644 index 505a0c492..000000000 --- a/src/plugins/thunderbird/chrome/content/trackerstore.js +++ /dev/null @@ -1,178 +0,0 @@ -if (!org.bustany.TrackerBird.TrackerStore || !org.bustany.TrackerBird.TrackerStore.__initialized) -org.bustany.TrackerBird.TrackerStore = { - // Init barrier - __initialized: true, - - _graph: "urn:uuid:0aa84c52-396d-4c37-bc6c-8342699f810c", - - _addressParser: org.bustany.TrackerBird.EmailAddressParser, - - _tracker: org.bustany.TrackerBird.TrackerSparql, - _connection: null, - - _knownEmailAddresses: {}, - - init: function(connection) { - this._connection = connection; - return true; - }, - - storeMessage: function(header, contents) { - var folder = header.folder - var uri = encodeURI(folder.getUriForMsg(header)); - var fromEmailAddress; - var toEmailAddresses = []; - - var query = ""; - - fromEmailAddress = this._addressParser.parse(header.mime2DecodedAuthor); - if (fromEmailAddress) { - query += this.insertEmailAddress(fromEmailAddress); - } - - // FIXME: this is not bullet-proof, but will do for now - var unparsedRecipients = header.mime2DecodedRecipients.split(">,"); - for (var i in unparsedRecipients) { - var parsedAddress = this._addressParser.parse(unparsedRecipients[i] + ">"); - - if (parsedAddress) { - toEmailAddresses.push(parsedAddress); - query += this.insertEmailAddress(parsedAddress); - } - } - - - query += "INSERT { GRAPH <" + this._graph + "> {" - + this.baseQuery(uri, header) - + this.contactQuery("nmo:from", fromEmailAddress) - + this.contactsQuery("nmo:to", toEmailAddresses) - + this.contentsQuery(contents) - + "}}"; - - if ((header.flags & Components.interfaces.nsMsgMessageFlags.Offline) - || (header.folder instanceof Components.interfaces.nsIMsgLocalMailFolder)) { - // We can access mail body - } - - if (!this.runTrackerUpdate(query, - 100 /* batch */, - "Cannot save message in Tracker")) { - return false; - } - - dump("Trackerbird inserted message " + uri + "\n"); - return true; - }, - - deleteMessage: function(header) { - var folder = header.folder - var uri = encodeURI(folder.getUriForMsg(header)); - - var query = "DELETE {<" + uri +"> a rdfs:Resource}"; - - if (!this.runTrackerUpdate(query, - 100 /* batch */, - "Trackerbird cannot delete message from Tracker")) { - return false; - } - - dump("Trackerbird deleted message " + uri + "\n"); - return true; - }, - - runTrackerUpdate: function(query, priority, errorPrefix) { - var error = new this._tracker.Error.ptr; - this._tracker.connection_update(this._connection, - query, - priority, /* batch */ - null, - error.address()); - - if (!error.isNull()) { - dump(errorPrefix + ": " + error.contents.message.readString() + "\n"); - dump("Query was\n" + query + "\n"); - this._tracker.error_free(error); - return false; - } - - return true; - }, - - baseQuery: function(uri, hdr) { - var query = "<" + uri + "> a nmo:Email, nmo:MailboxDataObject" - + "; nie:url \"" + uri + "\" "; - - if (hdr.mime2DecodedSubject != "") { - query += "; nmo:messageSubject \"" - + this.escapeString(hdr.mime2DecodedSubject) - + "\" "; - } - - query += "; nmo:receivedDate \"" - + new Date(hdr.dateInSeconds * 1000).toISOString() - + "\" "; - - return query; - }, - - contactQuery: function(predicate, address) { - if (address == null) { - return ""; - } - - var nameSparql = ""; - - if (address.name != "") { - nameSparql = "; nco:fullname \"" - + this.escapeString(address.name) - + "\" "; - } - - var emailSparql = "; nco:hasEmailAddress <mailto:" - + address.address - + "> "; - - return "; " + predicate + " [ a nco:Contact " + nameSparql + emailSparql + "] "; - }, - - contactsQuery: function(predicate, addresses) { - var query = ""; - - for (var i in addresses) { - query += this.contactQuery(predicate, addresses[i]); - } - - return query; - }, - - contentsQuery: function(contents) { - if (contents == null) { - return ""; - } - - return "; nie:plainTextContent \"" - + this.escapeString(contents) - + "\" "; - }, - - escapeString: function(str) { - var cstr = this._tracker.escape_string(str); - var escaped = cstr.readString(); - this._tracker.free(cstr); - - return escaped; - }, - - insertEmailAddress: function(address) { - if (this._knownEmailAddresses[address.address]) { - return ""; - } - - var query = "INSERT { GRAPH <" + this._graph + "> {" - + "<" + address.address + "> a nco:EmailAddress" - + "; nco:emailAddress \"" + address.address + "\"}}\n"; - - this._knownEmailAddresses[address.address] = true; - return query; - } -} diff --git a/src/plugins/thunderbird/chrome/content/ui.js b/src/plugins/thunderbird/chrome/content/ui.js deleted file mode 100644 index 878d436e0..000000000 --- a/src/plugins/thunderbird/chrome/content/ui.js +++ /dev/null @@ -1,22 +0,0 @@ -if (!org.bustany.TrackerBird.Ui || !org.bustany.TrackerBird.Ui.__initialized) -org.bustany.TrackerBird.Ui = { - // Init barrier - __initialized: true, - - _statusPanel: null, - - init: function() { - this._statusPanel = document.getElementById("trackerbird-status-panel"); - this._strbundle = document.getElementById("trackerbird-strings"); - - return true; - }, - - showMessage: function(str) { - this._statusPanel.label = this._strbundle.getString(str); - }, - - showFormattedMessage: function(str, repls) { - this._statusPanel.label = this._strbundle.getFormattedString(str, repls); - } -} diff --git a/src/plugins/thunderbird/chrome/locale/Makefile.am b/src/plugins/thunderbird/chrome/locale/Makefile.am deleted file mode 100644 index 81e035527..000000000 --- a/src/plugins/thunderbird/chrome/locale/Makefile.am +++ /dev/null @@ -1,37 +0,0 @@ -# General -localesdir = $(datadir)/xul-ext/trackerbird/chrome/locale/ - -localesdata = \ - options.dtd \ - about.dtd \ - overlay.dtd \ - overlay.properties - -# locales = de-DE en-US es-ES fr-FR pl-PL - -# de-DE -locale_de_DEdir = $(localesdir)/de-DE/ -locale_de_DE_DATA = $(patsubst %,de-DE/%,$(localesdata)) - -# en-US -locale_en_USdir = $(localesdir)/en-US/ -locale_en_US_DATA = $(patsubst %,en-US/%,$(localesdata)) - -# es-ES -locale_es_ESdir = $(localesdir)/es-ES/ -locale_es_ES_DATA = $(patsubst %,es-ES/%,$(localesdata)) - -# fr-FR -locale_fr_FRdir = $(localesdir)/fr-FR/ -locale_fr_FR_DATA = $(patsubst %,fr-FR/%,$(localesdata)) - -# pl-PL -locale_pl_PLdir = $(localesdir)/pl-PL/ -locale_pl_PL_DATA = $(patsubst %,pl-PL/%,$(localesdata)) - -EXTRA_DIST = \ - $(locale_de_DE_DATA) \ - $(locale_en_US_DATA) \ - $(locale_es_ES_DATA) \ - $(locale_fr_FR_DATA) \ - $(locale_pl_PL_DATA) diff --git a/src/plugins/thunderbird/chrome/locale/de-DE/about.dtd b/src/plugins/thunderbird/chrome/locale/de-DE/about.dtd deleted file mode 100644 index c2368a288..000000000 --- a/src/plugins/thunderbird/chrome/locale/de-DE/about.dtd +++ /dev/null @@ -1,4 +0,0 @@ -<!ENTITY about "Über TrackerBird"> -<!ENTITY version "Version:"> -<!ENTITY createdBy "Autor:"> -<!ENTITY homepage "Home Page:"> diff --git a/src/plugins/thunderbird/chrome/locale/de-DE/options.dtd b/src/plugins/thunderbird/chrome/locale/de-DE/options.dtd deleted file mode 100644 index 21a49eb22..000000000 --- a/src/plugins/thunderbird/chrome/locale/de-DE/options.dtd +++ /dev/null @@ -1,4 +0,0 @@ -<!ENTITY prefwindow.title "TrackerBird Einstellungen"> -<!ENTITY pane1.title "TrackerBird Einstellungen"> -<!ENTITY indexDelay.label "Drossel (ms Pause zwischen Aktivitäten)"> -<!ENTITY indexDelay.accesskey "T"> diff --git a/src/plugins/thunderbird/chrome/locale/de-DE/overlay.dtd b/src/plugins/thunderbird/chrome/locale/de-DE/overlay.dtd deleted file mode 100644 index 2340655e7..000000000 --- a/src/plugins/thunderbird/chrome/locale/de-DE/overlay.dtd +++ /dev/null @@ -1,2 +0,0 @@ -<!ENTITY idle "Leerlauf"> -<!ENTITY indexing "Indiziere..."> diff --git a/src/plugins/thunderbird/chrome/locale/de-DE/overlay.properties b/src/plugins/thunderbird/chrome/locale/de-DE/overlay.properties deleted file mode 100644 index 89219a2c2..000000000 --- a/src/plugins/thunderbird/chrome/locale/de-DE/overlay.properties +++ /dev/null @@ -1,9 +0,0 @@ -actionsRemaining = %S verbleibende Aktivitäten -cannotConnect = Verbindung mit Tracker nicht möglich -cannotInit = Tracker-Initialisierung fehlgeschlagen -cannotInitMail = Mail-Speicher-Initialisierung fehlgeschlagen -cannotInitPersistent = DB-Initialisierung fehlgeschlagen -indexerIdle = Indexer im Leerlauf -indexing = Indiziere ... -initializing = Initialisiere ... -starting = Starte ... diff --git a/src/plugins/thunderbird/chrome/locale/en-US/about.dtd b/src/plugins/thunderbird/chrome/locale/en-US/about.dtd deleted file mode 100644 index ddd4023af..000000000 --- a/src/plugins/thunderbird/chrome/locale/en-US/about.dtd +++ /dev/null @@ -1,4 +0,0 @@ -<!ENTITY about "About"> -<!ENTITY version "Version:"> -<!ENTITY createdBy "Created By:"> -<!ENTITY homepage "Home Page:"> diff --git a/src/plugins/thunderbird/chrome/locale/en-US/options.dtd b/src/plugins/thunderbird/chrome/locale/en-US/options.dtd deleted file mode 100644 index 8d3425738..000000000 --- a/src/plugins/thunderbird/chrome/locale/en-US/options.dtd +++ /dev/null @@ -1,4 +0,0 @@ -<!ENTITY prefwindow.title "TrackerBird preferences"> -<!ENTITY pane1.title "TrackerBird preferences"> -<!ENTITY indexDelay.label "Throttle (ms to wait between each message)"> -<!ENTITY indexDelay.accesskey "T"> diff --git a/src/plugins/thunderbird/chrome/locale/en-US/overlay.dtd b/src/plugins/thunderbird/chrome/locale/en-US/overlay.dtd deleted file mode 100644 index a355b7486..000000000 --- a/src/plugins/thunderbird/chrome/locale/en-US/overlay.dtd +++ /dev/null @@ -1,2 +0,0 @@ -<!ENTITY idle "Not indexing"> -<!ENTITY indexing "Indexing..."> diff --git a/src/plugins/thunderbird/chrome/locale/en-US/overlay.properties b/src/plugins/thunderbird/chrome/locale/en-US/overlay.properties deleted file mode 100644 index 163b38d35..000000000 --- a/src/plugins/thunderbird/chrome/locale/en-US/overlay.properties +++ /dev/null @@ -1,9 +0,0 @@ -actionsRemaining = %S actions remaining -cannotConnect = Cannot connect to Tracker -cannotInit = Cannot initialize Tracker -cannotInitMail = Cannot initialize mail store -cannotInitPersistent = Cannot initialize persistent storage -indexerIdle = Indexer idle -indexing = Indexing... -initializing = Initializing... -starting = Starting... diff --git a/src/plugins/thunderbird/chrome/locale/es-ES/about.dtd b/src/plugins/thunderbird/chrome/locale/es-ES/about.dtd deleted file mode 100644 index 9b3d8e790..000000000 --- a/src/plugins/thunderbird/chrome/locale/es-ES/about.dtd +++ /dev/null @@ -1,4 +0,0 @@ -<!ENTITY about "Acerca de TrackerBird"> -<!ENTITY version "Versión:"> -<!ENTITY createdBy "Autor:"> -<!ENTITY homepage "Página web:"> diff --git a/src/plugins/thunderbird/chrome/locale/es-ES/options.dtd b/src/plugins/thunderbird/chrome/locale/es-ES/options.dtd deleted file mode 100644 index f7047d0b6..000000000 --- a/src/plugins/thunderbird/chrome/locale/es-ES/options.dtd +++ /dev/null @@ -1,4 +0,0 @@ -<!ENTITY prefwindow.title "Preferencias de TrackerBird"> -<!ENTITY pane1.title "Preferencias de TrackerBird"> -<!ENTITY indexDelay.label "Plazo (entre cada actividad, en ms)"> -<!ENTITY indexDelay.accesskey "T"> diff --git a/src/plugins/thunderbird/chrome/locale/es-ES/overlay.dtd b/src/plugins/thunderbird/chrome/locale/es-ES/overlay.dtd deleted file mode 100644 index 1f2cf9e9c..000000000 --- a/src/plugins/thunderbird/chrome/locale/es-ES/overlay.dtd +++ /dev/null @@ -1,2 +0,0 @@ -<!ENTITY idle "Ocio"> -<!ENTITY indexing "Indexando..."> diff --git a/src/plugins/thunderbird/chrome/locale/es-ES/overlay.properties b/src/plugins/thunderbird/chrome/locale/es-ES/overlay.properties deleted file mode 100644 index 37b8b3659..000000000 --- a/src/plugins/thunderbird/chrome/locale/es-ES/overlay.properties +++ /dev/null @@ -1,9 +0,0 @@ -actionsRemaining = %S tareas pendiente -cannotConnect = Imposible de conectarse a Tracker -cannotInit = Imposible de inicializar Tracker -cannotInitMail = Imposible de inicializar el almacenamiento de los mensajes -cannotInitPersistent = Imposible de inicializar la base de datos de los mensajes indexados -indexerIdle = Ocio -indexing = Indexando... -initializing = Inicializando... -starting = Arrancando... diff --git a/src/plugins/thunderbird/chrome/locale/fr-FR/about.dtd b/src/plugins/thunderbird/chrome/locale/fr-FR/about.dtd deleted file mode 100644 index 0928e764d..000000000 --- a/src/plugins/thunderbird/chrome/locale/fr-FR/about.dtd +++ /dev/null @@ -1,4 +0,0 @@ -<!ENTITY about "À propos de TrackerBird"> -<!ENTITY version "Version:"> -<!ENTITY createdBy "Auteur:"> -<!ENTITY homepage "Page d'accueil:"> diff --git a/src/plugins/thunderbird/chrome/locale/fr-FR/options.dtd b/src/plugins/thunderbird/chrome/locale/fr-FR/options.dtd deleted file mode 100644 index 41088f41f..000000000 --- a/src/plugins/thunderbird/chrome/locale/fr-FR/options.dtd +++ /dev/null @@ -1,4 +0,0 @@ -<!ENTITY prefwindow.title "Préférences de TrackerBird"> -<!ENTITY pane1.title "Préférences de TrackerBird"> -<!ENTITY indexDelay.label "Délai (attente entre chaque activité, en ms)"> -<!ENTITY indexDelay.accesskey "T"> diff --git a/src/plugins/thunderbird/chrome/locale/fr-FR/overlay.dtd b/src/plugins/thunderbird/chrome/locale/fr-FR/overlay.dtd deleted file mode 100644 index 57620884d..000000000 --- a/src/plugins/thunderbird/chrome/locale/fr-FR/overlay.dtd +++ /dev/null @@ -1,2 +0,0 @@ -<!ENTITY idle "Au repos"> -<!ENTITY indexing "Indexation en cours..."> diff --git a/src/plugins/thunderbird/chrome/locale/fr-FR/overlay.properties b/src/plugins/thunderbird/chrome/locale/fr-FR/overlay.properties deleted file mode 100644 index d2d7d7517..000000000 --- a/src/plugins/thunderbird/chrome/locale/fr-FR/overlay.properties +++ /dev/null @@ -1,9 +0,0 @@ -actionsRemaining = %S tâches restante(s) -cannotConnect = Impossible de se connecter à Tracker -cannotInit = Impossible d'initialiser Tracker -cannotInitMail = Impossible d'initialiser le stockage des messages -cannotInitPersistent = Impossible d'initialiser la base des message indexés -indexerIdle = Indexation au repos -indexing = Indexation en cours... -initializing = Initialisation en cours... -starting = Démarrage... diff --git a/src/plugins/thunderbird/chrome/locale/pl-PL/about.dtd b/src/plugins/thunderbird/chrome/locale/pl-PL/about.dtd deleted file mode 100644 index 4494fa9de..000000000 --- a/src/plugins/thunderbird/chrome/locale/pl-PL/about.dtd +++ /dev/null @@ -1,4 +0,0 @@ -<!ENTITY about "O rozszerzeniu"> -<!ENTITY version "Wersja:"> -<!ENTITY createdBy "Utworzone przez:"> -<!ENTITY homepage "Witryna:"> diff --git a/src/plugins/thunderbird/chrome/locale/pl-PL/options.dtd b/src/plugins/thunderbird/chrome/locale/pl-PL/options.dtd deleted file mode 100644 index ba1aad017..000000000 --- a/src/plugins/thunderbird/chrome/locale/pl-PL/options.dtd +++ /dev/null @@ -1,4 +0,0 @@ -<!ENTITY prefwindow.title "Preferencje rozszerzenia TrackerBird"> -<!ENTITY pane1.title "Preferencje rozszerzenia TrackerBird"> -<!ENTITY indexDelay.label "Czas oczekiwania między wiadomościami w milisekundach"> -<!ENTITY indexDelay.accesskey "C"> diff --git a/src/plugins/thunderbird/chrome/locale/pl-PL/overlay.dtd b/src/plugins/thunderbird/chrome/locale/pl-PL/overlay.dtd deleted file mode 100644 index e0e2e48c6..000000000 --- a/src/plugins/thunderbird/chrome/locale/pl-PL/overlay.dtd +++ /dev/null @@ -1,2 +0,0 @@ -<!ENTITY idle "Nie jest indeksowane"> -<!ENTITY indexing "Indeksowanie..."> diff --git a/src/plugins/thunderbird/chrome/locale/pl-PL/overlay.properties b/src/plugins/thunderbird/chrome/locale/pl-PL/overlay.properties deleted file mode 100644 index e72c923d2..000000000 --- a/src/plugins/thunderbird/chrome/locale/pl-PL/overlay.properties +++ /dev/null @@ -1,9 +0,0 @@ -actionsRemaining = Pozostało działań: %S -cannotConnect = Nie można połączyć z usługą Tracker -cannotInit = Nie można zainicjować usługi Tracker -cannotInitMail = Nie można zainicjować przechowalni poczty -cannotInitPersistent = Nie można zainicjować trwałej pamięci -indexerIdle = Nie jest indeksowane -indexing = Indeksowanie... -initializing = Inicjowanie... -starting = Rozpoczynanie... diff --git a/src/plugins/thunderbird/chrome/skin/Makefile.am b/src/plugins/thunderbird/chrome/skin/Makefile.am deleted file mode 100644 index 5ab9ac0a6..000000000 --- a/src/plugins/thunderbird/chrome/skin/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -extensiondir = $(datadir)/xul-ext/trackerbird/chrome/skin -extension_DATA = \ - overlay.css - -EXTRA_DIST = $(extension_DATA) diff --git a/src/plugins/thunderbird/chrome/skin/overlay.css b/src/plugins/thunderbird/chrome/skin/overlay.css deleted file mode 100644 index 7e72176c9..000000000 --- a/src/plugins/thunderbird/chrome/skin/overlay.css +++ /dev/null @@ -1,22 +0,0 @@ -/* This is just an example. You shouldn't do this. */ -#trackerbird-hello -{ - color: red ! important; -} -#trackerbird-toolbar-button -{ - list-style-image: url("chrome://trackerbird/skin/toolbar-button.png"); - -moz-image-region: rect(0px 24px 24px 0px); -} -#trackerbird-toolbar-button:hover -{ - -moz-image-region: rect(24px 24px 48px 0px); -} -[iconsize="small"] #trackerbird-toolbar-button -{ - -moz-image-region: rect( 0px 40px 16px 24px); -} -[iconsize="small"] #trackerbird-toolbar-button:hover -{ - -moz-image-region: rect(24px 40px 40px 24px); -} diff --git a/src/plugins/thunderbird/defaults/Makefile.am b/src/plugins/thunderbird/defaults/Makefile.am deleted file mode 100644 index 287fa7162..000000000 --- a/src/plugins/thunderbird/defaults/Makefile.am +++ /dev/null @@ -1 +0,0 @@ -SUBDIRS = preferences diff --git a/src/plugins/thunderbird/defaults/preferences/Makefile.am b/src/plugins/thunderbird/defaults/preferences/Makefile.am deleted file mode 100644 index 6f9a19eb1..000000000 --- a/src/plugins/thunderbird/defaults/preferences/Makefile.am +++ /dev/null @@ -1,5 +0,0 @@ -extensiondir = $(datadir)/xul-ext/trackerbird/defaults/preferences -extension_DATA = \ - prefs.js - -EXTRA_DIST = $(extension_DATA) diff --git a/src/plugins/thunderbird/defaults/preferences/prefs.js b/src/plugins/thunderbird/defaults/preferences/prefs.js deleted file mode 100644 index 1f9b5037f..000000000 --- a/src/plugins/thunderbird/defaults/preferences/prefs.js +++ /dev/null @@ -1,4 +0,0 @@ -pref("extensions.trackerbird.indexDelay", 100); - -// https://developer.mozilla.org/en/Localizing_extension_descriptions -pref("extensions.trackerbird@bustany.org.description", "chrome://trackerbird/locale/overlay.properties"); diff --git a/src/plugins/thunderbird/install.rdf.in b/src/plugins/thunderbird/install.rdf.in deleted file mode 100644 index ee315b60a..000000000 --- a/src/plugins/thunderbird/install.rdf.in +++ /dev/null @@ -1,21 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:em="http://www.mozilla.org/2004/em-rdf#"> - <Description about="urn:mozilla:install-manifest"> - <em:id>trackerbird@bustany.org</em:id> - <em:type>2</em:type> - <em:name>TrackerBird</em:name> - <em:version>@VERSION@</em:version> - <em:creator>Adrien Bustany</em:creator> - <em:contributor></em:contributor> - <em:description>Index your Thunderbird emails with Tracker</em:description> - <em:aboutURL>chrome://trackerbird/content/about.xul</em:aboutURL> - <em:optionsURL>chrome://trackerbird/content/options.xul</em:optionsURL> - <em:targetApplication> - <Description> - <em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id> <!-- Thunderbird --> - <em:minVersion>24.0</em:minVersion> - <em:maxVersion>24.*</em:maxVersion> - </Description> - </em:targetApplication> - </Description> -</RDF> diff --git a/src/plugins/thunderbird/trackerbird-launcher.desktop b/src/plugins/thunderbird/trackerbird-launcher.desktop deleted file mode 100644 index 4a5dda69d..000000000 --- a/src/plugins/thunderbird/trackerbird-launcher.desktop +++ /dev/null @@ -1,6 +0,0 @@ -[Desktop Entry] -Name=Trackerbird Launcher -Type=Application -Exec=thunderbird -mail %u -MimeType=x-scheme-handler/imap-message; -NoDisplay=true 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 6b4658814..000000000 --- a/src/tracker-extract/10-flac.rule +++ /dev/null @@ -1,4 +0,0 @@ -[ExtractorRule] -ModulePath=libextract-flac.so -MimeTypes=audio/flac;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 04593e157..000000000 --- a/src/tracker-extract/Makefile.am +++ /dev/null @@ -1,638 +0,0 @@ -# -# _RULES_DIR = $(datadir)/tracker/extract-rules -# -rulesdir = $(TRACKER_EXTRACT_RULES_DIR) - -module_flags = -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 $(escape_sources) -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 $(escape_sources) -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) \ - $(man_MANS) - -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) \ - $(man_MANS) 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 e436faa76..000000000 --- a/src/tracker-extract/org.freedesktop.Tracker1.Miner.Extract.service.in.in +++ /dev/null @@ -1,9 +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 -_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 cc3063393..000000000 --- a/src/tracker-extract/tracker-config.c +++ /dev/null @@ -1,323 +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-bytes", object, "max-bytes", 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); -} - -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 g_settings_get_int (G_SETTINGS (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 daf157488..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; - 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_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 544de2968..000000000 --- a/src/tracker-extract/tracker-cue-sheet.c +++ /dev/null @@ -1,450 +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) -{ - GList *node; - gint track_count; - - gchar *album_artist = NULL; - - 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); - } - - gst_tag_list_get_string (toc->tag_list, GST_TAG_ALBUM_ARTIST, &album_artist); - - for (node = toc->entry_list; node; node = node->next) { - TrackerTocEntry *entry = node->data; - - if (album_artist != NULL) { - if (gst_tag_list_get_tag_size (entry->tag_list, GST_TAG_ARTIST) == 0 && - gst_tag_list_get_tag_size (entry->tag_list, GST_TAG_PERFORMER) == 0) - gst_tag_list_add (entry->tag_list, - GST_TAG_MERGE_REPLACE, - GST_TAG_ARTIST, - album_artist, - NULL); - } - } - - g_free (album_artist); -} - -/* 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; - - g_file_load_contents (cue_sheet_file, NULL, &buffer, NULL, NULL, &error); - - if (error != NULL) { - 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 74db8de33..000000000 --- a/src/tracker-extract/tracker-extract-controller.c +++ /dev/null @@ -1,303 +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, -}; - -struct TrackerExtractControllerPrivate { - TrackerDecorator *decorator; - TrackerConfig *config; - GCancellable *cancellable; - guint watch_id; - guint progress_signal_id; - gint pause_cookie; -}; - -G_DEFINE_TYPE (TrackerExtractController, tracker_extract_controller, G_TYPE_OBJECT) - -static void -files_miner_idleness_changed (TrackerExtractController *self, - gboolean idle) -{ - if (idle && self->priv->pause_cookie != 0) { - tracker_miner_resume (TRACKER_MINER (self->priv->decorator), - self->priv->pause_cookie, - NULL); - self->priv->pause_cookie = 0; - } else if (!idle && self->priv->pause_cookie == 0) { - self->priv->pause_cookie = - tracker_miner_pause (TRACKER_MINER (self->priv->decorator), - "Wait for files miner", - NULL); - } -} - -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; - - conn = tracker_miner_get_dbus_connection (TRACKER_MINER (self->priv->decorator)); - - 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; - - conn = tracker_miner_get_dbus_connection (TRACKER_MINER (self->priv->decorator)); - - 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; - } -} - -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; - } -} - -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_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) -{ - g_return_val_if_fail (TRACKER_IS_DECORATOR (decorator), NULL); - - return g_object_new (TRACKER_TYPE_EXTRACT_CONTROLLER, - "decorator", decorator, - NULL); -} diff --git a/src/tracker-extract/tracker-extract-controller.h b/src/tracker-extract/tracker-extract-controller.h deleted file mode 100644 index 2fc078cca..000000000 --- a/src/tracker-extract/tracker-extract-controller.h +++ /dev/null @@ -1,54 +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); - -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 69bfb0de6..000000000 --- a/src/tracker-extract/tracker-extract-decorator.c +++ /dev/null @@ -1,691 +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 void -decorator_save_info (TrackerSparqlBuilder *sparql, - TrackerExtractDecorator *decorator, - TrackerDecoratorInfo *decorator_info, - TrackerExtractInfo *info) -{ - const gchar *urn; - TrackerResource *resource = NULL; - gchar *sparql_command; - - 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 (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))); - - sparql_command = tracker_resource_print_sparql_update ( - resource, NULL, TRACKER_OWN_GRAPH_URN); - tracker_sparql_builder_append (sparql, sparql_command); - - g_object_unref (resource); - g_free (sparql_command); -} - -static void -get_metadata_cb (TrackerExtract *extract, - GAsyncResult *result, - ExtractData *data) -{ - TrackerExtractDecoratorPrivate *priv; - TrackerExtractInfo *info; - GError *error = NULL; - GTask *task; - - priv = TRACKER_EXTRACT_DECORATOR (data->decorator)->priv; - task = tracker_decorator_info_get_task (data->decorator_info); - 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"); - g_task_return_boolean (task, FALSE); - g_clear_error (&error); - } else { - g_task_return_error (task, error); - } - } else { - decorator_save_info (g_task_get_task_data (task), - TRACKER_EXTRACT_DECORATOR (data->decorator), - data->decorator_info, info); - g_task_return_boolean (task, TRUE); - tracker_extract_info_unref (info); - } - - 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, - "name", "Extract", - "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 4f7b5cf32..000000000 --- a/src/tracker-extract/tracker-extract-epub.c +++ /dev/null @@ -1,690 +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); - - 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; - 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); - - 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 fcdd45a65..000000000 --- a/src/tracker-extract/tracker-extract-flac.c +++ /dev/null @@ -1,315 +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", 11) == 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); - - 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_object_unref (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); - } - - 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 d740c28fb..000000000 --- a/src/tracker-extract/tracker-extract-gif.c +++ /dev/null @@ -1,505 +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) { -#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) { - tracker_resource_set_string (metadata, "nfo:orientation", xd->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) { - tracker_resource_set_string (metadata, "nmm:whiteBalance", xd->white_balance); - } - - if (xd->fnumber) { - tracker_resource_set_string (metadata, "nmm:fnumber", xd->fnumber); - } - - if (xd->flash) { - tracker_resource_set_string (metadata, "nmm:flash", xd->flash); } - - if (xd->focal_length) { - tracker_resource_set_string (metadata, "nmm:focalLength", xd->focal_length); - } - - if (xd->metering_mode) { - tracker_resource_set_string (metadata, "nmm:meteringMode", xd->metering_mode); - } - - 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); - } - - 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 042a08b3c..000000000 --- a/src/tracker-extract/tracker-extract-gstreamer.c +++ /dev/null @@ -1,1487 +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> - -#ifdef HAVE_LIBMEDIAART -#include <libmediaart/mediaart.h> -#endif - -#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; - -#ifdef HAVE_LIBMEDIAART - MediaArtType media_art_type; - gchar *media_art_artist; - gchar *media_art_title; - - unsigned char *media_art_buffer; - guint media_art_buffer_size; - const gchar *media_art_buffer_mime; -#endif - - 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; - - g_return_val_if_fail (artist_name != NULL, 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) { - return node->data; - } - - artist = tracker_extract_new_artist (artist_name); - - 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; -} - -#ifdef HAVE_LIBMEDIAART - -static gboolean -get_embedded_media_art (MetadataExtractor *extractor) -{ - gboolean have_sample; - guint lindex; - - lindex = 0; - - do { - have_sample = gst_tag_list_get_sample_index (extractor->tagcache, GST_TAG_IMAGE, lindex, &extractor->sample); - - if (have_sample) { - GstBuffer *buffer; - const GstStructure *info_struct; - gint type; - - buffer = gst_sample_get_buffer (extractor->sample); - info_struct = gst_sample_get_info (extractor->sample); - if (gst_structure_get_enum (info_struct, - "image-type", - GST_TYPE_TAG_IMAGE_TYPE, - &type)) { - if (type == GST_TAG_IMAGE_TYPE_FRONT_COVER || - (type == GST_TAG_IMAGE_TYPE_UNDEFINED && - extractor->media_art_buffer_size == 0)) { - GstCaps *caps; - GstStructure *caps_struct; - - if (!gst_buffer_map (buffer, &extractor->info, GST_MAP_READ)) - return FALSE; - - caps = gst_sample_get_caps (extractor->sample); - caps_struct = gst_caps_get_structure (caps, 0); - - extractor->media_art_buffer = extractor->info.data; - extractor->media_art_buffer_size = extractor->info.size; - extractor->media_art_buffer_mime = gst_structure_get_name (caps_struct); - - return TRUE; - } - } - - lindex++; - } - - } while (have_sample); - - /* Fallback to the preview image */ - have_sample = gst_tag_list_get_sample_index (extractor->tagcache, GST_TAG_PREVIEW_IMAGE, 0, &extractor->sample); - - if (have_sample) { - GstBuffer *buffer; - GstCaps *caps; - GstStructure *caps_struct; - - buffer = gst_sample_get_buffer (extractor->sample); - caps = gst_sample_get_caps (extractor->sample); - caps_struct = gst_caps_get_structure (caps, 0); - - if (!gst_buffer_map (buffer, &extractor->info, GST_MAP_READ)) - return FALSE; - - extractor->media_art_buffer = extractor->info.data; - extractor->media_art_buffer_size = extractor->info.size; - extractor->media_art_buffer_mime = gst_structure_get_name (caps_struct); - - return TRUE; - } - - return FALSE; -} - -#endif - -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); - -#ifdef HAVE_LIBMEDIAART - if (extractor->media_art_type == MEDIA_ART_VIDEO) { - extractor->media_art_title = title_guaranteed; - } else { - g_free (title_guaranteed); - } -#else - g_free (title_guaranteed); -#endif - - 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) -{ - TrackerResource *album = NULL, *album_artist = NULL, *album_disc = NULL; - gchar *album_uri, *album_disc_uri; - gchar *album_artist_name; - gchar *album_title = NULL; - gchar *album_artist_temp = 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_temp); - gst_tag_list_get_string (tag_list, GST_TAG_ARTIST, &track_artist_temp); - - album_artist_name = g_strdup (tracker_coalesce_strip (2, album_artist_temp, track_artist_temp)); - - if (album_artist_name != NULL) { - album_artist = intern_artist (extractor, album_artist_name); - album_uri = tracker_sparql_escape_uri_printf ("urn:album:%s:%s", album_title, album_artist_name); - } else { - album_uri = tracker_sparql_escape_uri_printf ("urn:album:%s", album_title); - } - - album = tracker_resource_new (album_uri); - tracker_resource_set_uri (album, "rdf:type", "nmm:MusicAlbum"); - - /* FIXME: nmm:albumTitle is now deprecated, should use nie:title ?? */ - tracker_resource_set_string (album, "nmm:albumTitle", album_title); - - if (album_artist) { - tracker_resource_set_relation (album, "nmm:albumArtist", album_artist); - } - - set_property_from_gst_tag (album, "nmm:albumTrackCount", tag_list, GST_TAG_TRACK_COUNT); - - has_it = gst_tag_list_get_uint (tag_list, GST_TAG_ALBUM_VOLUME_NUMBER, &volume_number); - - if (album_artist) { - album_disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:%s:Disc%d", - album_title, album_artist, - has_it ? volume_number : 1); - } else { - album_disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:Disc%d", - album_title, - has_it ? volume_number : 1); - } - - album_disc = tracker_resource_new (album_disc_uri); - tracker_resource_set_uri (album_disc, "rdf:type", "nmm:MusicAlbumDisc"); - tracker_resource_set_int64 (album_disc, "nmm:setNumber", has_it ? volume_number : 1); - tracker_resource_set_relation (album_disc, "nmm:albumDiscAlbum", album); - - 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); - -#ifdef HAVE_LIBMEDIAART - extractor->media_art_artist = album_artist_name; - extractor->media_art_title = album_title; -#endif - - g_free (album_artist_temp); - 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); - -#ifdef HAVE_LIBMEDIAART - extractor->media_art_type = MEDIA_ART_NONE; -#endif - - if (extractor->toc) { - gst_tag_list_insert (extractor->tagcache, - extractor->toc->tag_list, - GST_TAG_MERGE_REPLACE); - - 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_REPLACE); - - 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"); - -#ifdef HAVE_LIBMEDIAART - extractor->media_art_type = MEDIA_ART_ALBUM; -#endif - } else if (extractor->mime == EXTRACT_MIME_VIDEO) { - tracker_resource_add_uri (resource, "rdf:type", "nmm:Video"); - -#ifdef HAVE_LIBMEDIAART - extractor->media_art_type = MEDIA_ART_VIDEO; -#endif - } 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); - -#ifdef HAVE_LIBMEDIAART - if (extractor->mime == EXTRACT_MIME_AUDIO) { - get_embedded_media_art (extractor); - } -#endif - - 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; - 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 - - extractor->gst_toc = gst_discoverer_info_get_toc (info); - if (extractor->gst_toc) - gst_toc_ref (extractor->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; - -#ifdef HAVE_LIBMEDIAART - MediaArtProcess *media_art_process; -#endif - - g_return_val_if_fail (uri, NULL); - - gst_init (NULL, NULL); - - extractor = g_slice_new0 (MetadataExtractor); - extractor->mime = type; - extractor->tagcache = gst_tag_list_new_empty (); - -#ifdef HAVE_LIBMEDIAART - media_art_process = tracker_extract_info_get_media_art_process (info); - extractor->media_art_type = MEDIA_ART_NONE; -#endif - - 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); - -#ifdef HAVE_LIBMEDIAART - if (extractor->media_art_type != MEDIA_ART_NONE && - (extractor->media_art_artist != NULL || - extractor->media_art_title != NULL)) { - GError *error = NULL; - gboolean success = TRUE; - - if (extractor->media_art_buffer) { - success = media_art_process_buffer (media_art_process, - extractor->media_art_type, - MEDIA_ART_PROCESS_FLAGS_NONE, - tracker_extract_info_get_file (info), - extractor->media_art_buffer, - extractor->media_art_buffer_size, - extractor->media_art_buffer_mime, - extractor->media_art_artist, - extractor->media_art_title, - NULL, - &error); - } else { - success = media_art_process_file (media_art_process, - extractor->media_art_type, - MEDIA_ART_PROCESS_FLAGS_NONE, - tracker_extract_info_get_file (info), - extractor->media_art_artist, - extractor->media_art_title, - NULL, - &error); - } - - if (!success || error) { - g_warning ("Could not process media art for '%s', %s", - uri, - error ? error->message : "No error given"); - g_clear_error (&error); - } - } -#endif - } - - /* Clean up */ -#ifdef HAVE_LIBMEDIAART - g_free (extractor->media_art_artist); - g_free (extractor->media_art_title); -#endif - - 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; -} 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 4f7dfa441..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] > *width) { - *height = image_metadata[0]; - } - } - - 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 bddb37620..000000000 --- a/src/tracker-extract/tracker-extract-jpeg.c +++ /dev/null @@ -1,567 +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) { - tracker_resource_set_string (metadata, "nfo:orientation", md.orientation); - } - - if (md.copyright) { - tracker_resource_set_string (metadata, "nie:copyright", md.copyright); - } - - if (md.white_balance) { - tracker_resource_set_string (metadata, "nmm:whiteBalance", md.white_balance); - } - - if (md.fnumber) { - gdouble value; - - value = g_strtod (md.fnumber, NULL); - tracker_resource_set_double (metadata, "nmm:fnumber", value); - } - - if (md.flash) { - tracker_resource_set_string (metadata, "nmm:flash", md.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) { - tracker_resource_set_string(metadata, "nmm:meteringMode", md.metering_mode); - } - - 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 b2597f9e1..000000000 --- a/src/tracker-extract/tracker-extract-libav.c +++ /dev/null @@ -1,287 +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> - -#ifdef HAVE_LIBMEDIAART -#include <tracker-media-art.h> -#endif - -#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 *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 (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 (!album_artist) { - album_artist_name = tag->value; - album_artist = performer; - } - } - - if (!performer && (tag = av_dict_get (format->metadata, "performer", tag, 0))) { - performer = tracker_extract_new_artist (tag->value); - if (!album_artist) { - album_artist_name = tag->value; - album_artist = performer; - } - } - - if (performer) { - tracker_resource_set_relation (metadata, "nmm:performer", performer); - } else if (album_artist) { - tracker_resource_set_relation (metadata, "nmm:performer", album_artist); - } - - 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); - - 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); - } - -#ifdef HAVE_LIBMEDIAART - if (album_artist || album_title) { - MediaArtProcess *media_art_process; - GError *error = NULL; - gboolean success; - - media_art_process = tracker_extract_info_get_media_art_process (info); - success = media_art_process_file (media_art_process, - MEDIA_ART_ALBUM, - MEDIA_ART_PROCESS_FLAGS_NONE, - file, - album_artist, - album_title, - &error); - - if (!success || error) { - g_warning ("Could not process media art for '%s', %s", - uri, - error ? error->message : "No error given"); - g_clear_error (&error); - } - } -#endif - - 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, "creation_time", NULL, 0))) { - gchar *content_created = tracker_date_guess (tag->value); - if (content_created) { - tracker_resource_set_string (metadata, "nie:contentCreated", content_created); - g_free (content_created); - } - } - - 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 (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 ef30342e9..000000000 --- a/src/tracker-extract/tracker-extract-mp3.c +++ /dev/null @@ -1,2623 +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 */ - -#ifdef HAVE_LIBMEDIAART -#include <libmediaart/mediaart.h> -#endif - -#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; - TrackerResource *album_artist; - 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; - - unsigned char *media_art_data; - size_t media_art_size; - 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 */ - -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 = g_malloc0 (csize - offset); - filedata->media_art_mime = g_strndup (mime, mime_len); - memcpy (filedata->media_art_data, &data[offset], csize - offset); - filedata->media_art_size = csize - offset; - } - 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 = g_malloc0 (csize - offset); - filedata->media_art_mime = g_strndup (mime, mime_len); - memcpy (filedata->media_art_data, &data[offset], csize - offset); - filedata->media_art_size = csize - offset; - } - 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_mime = g_strndup (mime, 3); - filedata->media_art_data = g_malloc0 (csize - offset); - memcpy (filedata->media_art_data, &data[offset], csize - offset); - filedata->media_art_size = csize - offset; - } - } 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 = (((data[6] & 0x7F) << 21) | - ((data[7] & 0x7F) << 14) | - ((data[8] & 0x7F) << 7) | - ((data[9] & 0x7F) << 0)); - - /* 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 = (((data[10] & 0x7F) << 21) | - ((data[11] & 0x7F) << 14) | - ((data[12] & 0x7F) << 7) | - ((data[13] & 0x7F) << 0)); - - /* 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 = (((data[pos+4] & 0x7F) << 21) | - ((data[pos+5] & 0x7F) << 14) | - ((data[pos+6] & 0x7F) << 7) | - ((data[pos+7] & 0x7F) << 0)); - - flags = (((unsigned char) (data[pos + 8]) << 8) + - ((unsigned char) (data[pos + 9]))); - - 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 = (((data[6] & 0x7F) << 21) | - ((data[7] & 0x7F) << 14) | - ((data[8] & 0x7F) << 7) | - ((data[9] & 0x7F) << 0)); - - /* 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 = (((unsigned char)(data[10]) << 24) | - ((unsigned char)(data[11]) << 16) | - ((unsigned char)(data[12]) << 8) | - ((unsigned char)(data[13]) << 0)); - - /* 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 = (((unsigned char)(data[pos + 4]) << 24) | - ((unsigned char)(data[pos + 5]) << 16) | - ((unsigned char)(data[pos + 6]) << 8) | - ((unsigned char)(data[pos + 7]) << 0) ); - - flags = (((unsigned char)(data[pos + 8]) << 8) + - ((unsigned char)(data[pos + 9]))); - - 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 < 16) || - (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 = (((data[6] & 0x7F) << 21) | - ((data[7] & 0x7F) << 14) | - ((data[8] & 0x7F) << 07) | - ((data[9] & 0x7F) << 00)); - - if (tsize + header_size > 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 = (((unsigned char)(data[pos + 3]) << 16) + - ((unsigned char)(data[pos + 4]) << 8) + - ((unsigned char)(data[pos + 5]) ) ); - - 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 - posix_fadvise (fd, 0, 0, POSIX_FADV_DONTNEED); -#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 (7, md.id3v24.performer1, - md.id3v24.performer2, - md.id3v23.performer1, - md.id3v23.performer2, - md.id3v22.performer1, - md.id3v22.performer2, - md.id3v1.artist); - - md.album_artist_name = tracker_coalesce_strip (4, md.id3v24.performer2, - md.id3v23.performer2, - md.id3v22.performer2, - md.performer_name); - - 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.album_artist_name) { - md.album_artist = tracker_extract_new_artist (md.album_artist_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) { - char *album_uri = tracker_sparql_escape_uri_printf ("urn:album:%s", md.album_name); - md.album = tracker_resource_new (album_uri); - - tracker_resource_set_uri (md.album, "rdf:type", "nmm:MusicAlbum"); - /* FIXME: nmm:albumTitle is now deprecated - * tracker_sparql_builder_predicate (preupdate, "nie:title"); - */ - tracker_resource_set_string (md.album, "nmm:albumTitle", md.album_name); - - if (md.album_artist) { - tracker_resource_set_relation (md.album, "nmm:albumArtist", md.album_artist); - g_object_unref (md.album_artist); - } - - if (md.track_count > 0) { - tracker_resource_set_int (md.album, "nmm:albumTrackCount", md.track_count); - } - } - - 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); - g_object_unref (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); - } - - if (md.album) { - TrackerResource *album_disc; - gchar *album_disc_uri; - - album_disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:Disc%d", - md.album_name, - md.set_number > 0 ? md.set_number : 1); - - album_disc = tracker_resource_new (album_disc_uri); - tracker_resource_set_uri (album_disc, "rdf:type", "nmm:MusicAlbumDisc"); - tracker_resource_set_int (album_disc, "nmm:setNumber", md.set_number > 0 ? md.set_number : 1); - tracker_resource_set_relation (album_disc, "nmm:albumDiscAlbum", md.album); - - tracker_resource_set_relation (main_resource, "nmm:musicAlbumDisc", album_disc); - - g_free (album_disc_uri); - g_object_unref (album_disc); - g_object_unref (md.album); - } - - /* Get mp3 stream info */ - parsed = mp3_parse (buffer, buffer_size, audio_offset, uri, main_resource, &md); - -#ifdef HAVE_LIBMEDIAART - if (parsed && (md.performer || md.album)) { - MediaArtProcess *media_art_process; - GError *error = NULL; - gboolean success = TRUE; - - media_art_process = tracker_extract_info_get_media_art_process (info); - - if (md.media_art_data) { - success = media_art_process_buffer (media_art_process, - MEDIA_ART_ALBUM, - MEDIA_ART_PROCESS_FLAGS_NONE, - file, - md.media_art_data, - md.media_art_size, - md.media_art_mime, - md.performer_name, - md.album_name, - NULL, - &error); - } else { - success = media_art_process_file (media_art_process, - MEDIA_ART_ALBUM, - MEDIA_ART_PROCESS_FLAGS_NONE, - file, - md.performer_name, - md.album_name, - NULL, - &error); - } - - if (!success || error) { - g_warning ("Could not process media art for '%s', %s", - uri, - error ? error->message : "No error given"); - g_clear_error (&error); - } - } -#endif - g_free (md.media_art_data); - g_free (md.media_art_mime); - - 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 976477c31..000000000 --- a/src/tracker-extract/tracker-extract-msoffice.c +++ /dev/null @@ -1,1714 +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 - **/ - - /* Reading cst total */ - gsf_input_read (stream, 4, tmp_buffer); - read_32bit (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 b6b4274f5..000000000 --- a/src/tracker-extract/tracker-extract-pdf.c +++ /dev/null @@ -1,606 +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) { - tracker_resource_set_string (metadata, "nfo:orientation", xd->orientation); - } - - if (xd->rights) { - tracker_resource_set_string (metadata, "nie:copyright", xd->rights); - } - - if (xd->white_balance) { - tracker_resource_set_string (metadata, "nmm:whiteBalance", xd->white_balance); - } - - if (xd->fnumber) { - gdouble value; - - value = g_strtod (xd->fnumber, NULL); - tracker_resource_set_double (metadata, "nmm:fnumber", value); - } - - if (xd->flash) { - tracker_resource_set_string (metadata, "nmm:flash", xd->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) { - tracker_resource_set_string (metadata, "nmm:meteringMode", xd->metering_mode); - } - - 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 2bf13cb21..000000000 --- a/src/tracker-extract/tracker-extract-png.c +++ /dev/null @@ -1,715 +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) { - tracker_resource_set_string (metadata, "nfo:orientation", md.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) { - tracker_resource_set_string (metadata, "nmm:whiteBalance", md.white_balance); - } - - if (md.fnumber) { - tracker_resource_set_string (metadata, "nmm:fnumber", md.fnumber); - } - - if (md.flash) { - tracker_resource_set_string (metadata, "nmm:flash", md.flash); } - - if (md.focal_length) { - tracker_resource_set_string (metadata, "nmm:focalLength", md.focal_length); - } - - if (md.metering_mode) { - tracker_resource_set_string (metadata, "nmm:meteringMode", md.metering_mode); - } - - - 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_set_string (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; - } - - 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_bytepp row_pointers; - 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, &info_ptr, 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_pointers = g_new0 (png_bytep, height); - - for (row = 0; row < height; row++) { - row_pointers[row] = png_malloc (png_ptr, - png_get_rowbytes (png_ptr,info_ptr)); - } - - png_read_image (png_ptr, row_pointers); - - for (row = 0; row < height; row++) { - png_free (png_ptr, row_pointers[row]); - } - - g_free (row_pointers); - - 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 aa3f62f3f..000000000 --- a/src/tracker-extract/tracker-extract-ps.c +++ /dev/null @@ -1,338 +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 - posix_fadvise (fdz, 0, 0, POSIX_FADV_DONTNEED); -#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 857daa47f..000000000 --- a/src/tracker-extract/tracker-extract-text.c +++ /dev/null @@ -1,116 +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_module_init (TrackerModuleThreadAwareness *thread_awareness_ret, - GError **error) -{ - *thread_awareness_ret = TRACKER_MODULE_MULTI_THREAD; - return TRUE; -} - -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 5acfe171f..000000000 --- a/src/tracker-extract/tracker-extract-tiff.c +++ /dev/null @@ -1,640 +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) { - tracker_resource_set_string (metadata, "nfo:orientation", md.orientation); - } - - if (md.copyright) { - tracker_guarantee_resource_utf8_string (metadata, "nie:copyright", md.copyright); - } - - if (md.white_balance) { - tracker_resource_set_string (metadata, "nmm:whiteBalance", md.white_balance); - } - - if (md.fnumber) { - tracker_resource_set_string (metadata, "nmm:fnumber", md.fnumber); - } - - if (md.flash) { - tracker_resource_set_string (metadata, "nmm:flash", md.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) { - tracker_resource_set_string (metadata, "nmm:meteringMode", md.metering_mode); - } - - 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 9c2b77831..000000000 --- a/src/tracker-extract/tracker-extract-vorbis.c +++ /dev/null @@ -1,386 +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> - -#ifdef HAVE_LIBMEDIAART -#include <libmediaart/mediaart.h> -#endif - -#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 if (md.creator) { - album_artist = g_object_ref (md.creator); - } else { - album_artist = NULL; - } - - album_disc = tracker_extract_new_music_album_disc (vd.album, - album_artist, - vd.disc_number ? atoi(vd.disc_number) : 1); - - g_object_unref (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); - } - -#ifdef HAVE_LIBMEDIAART - if ((vd.album_artist || vd.artist) || vd.album) { - MediaArtProcess *media_art_process; - GError *error = NULL; - gboolean success; - - media_art_process = tracker_extract_info_get_media_art_process (info); - - success = media_art_process_file (media_art_process, - MEDIA_ART_ALBUM, - MEDIA_ART_PROCESS_FLAGS_NONE, - file, - vd.album_artist ? vd.album_artist : vd.artist, - vd.album, - NULL, - &error); - - if (!success || error) { - gchar *uri; - - uri = g_file_get_uri (file); - g_warning ("Could not process media art for '%s', %s", - uri, - error ? error->message : "No error given"); - g_free (uri); - g_clear_error (&error); - } - } -#endif - - 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 - posix_fadvise (fileno (f), 0, 0, POSIX_FADV_DONTNEED); -#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 b32f34ff6..000000000 --- a/src/tracker-extract/tracker-extract.c +++ /dev/null @@ -1,847 +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; - -#ifdef HAVE_LIBMEDIAART - MediaArtProcess *media_art_process; -#endif -} 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); - -#ifdef HAVE_LIBMEDIAART - GError *error = NULL; - - priv->media_art_process = media_art_process_new (&error); - if (!priv->media_art_process || error) { - g_warning ("Could not initialize media art, %s", - error ? error->message : _("No error given")); - g_error_free (error); - } -#endif - - 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); - -#ifdef HAVE_LIBMEDIAART - if (priv->media_art_process) { - g_object_unref (priv->media_art_process); - } -#endif - - 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); - -#ifdef HAVE_LIBMEDIAART - tracker_extract_info_set_media_art_process (info, tracker_extract_get_media_art_process (task->extract)); -#endif - - 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 void -single_thread_get_metadata (GAsyncQueue *queue) -{ - 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); - } -} - -/* 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) -{ - TrackerModuleThreadAwareness thread_awareness; - TrackerExtractPrivate *priv; - GError *error = NULL; - 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, &thread_awareness); - - 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; - } - - switch (thread_awareness) { - case TRACKER_MODULE_NONE: - /* Error out */ - g_task_return_new_error (G_TASK (task->res), - tracker_extract_error_quark (), - TRACKER_EXTRACT_ERROR_NO_EXTRACTOR, - "Module '%s' initialization failed", - g_module_name (module)); - extract_task_free (task); - break; - case TRACKER_MODULE_MAIN_THREAD: - /* Dispatch the task right away in this thread */ -#ifdef THREAD_ENABLE_TRACE - g_debug ("Thread:%p (Main) <-- '%s': Dispatching in main thread", - g_thread_self(), task->file); -#endif /* THREAD_ENABLE_TRACE */ - get_metadata (task); - break; - case TRACKER_MODULE_SINGLE_THREAD: { - GAsyncQueue *async_queue; - - 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_object_unref (thread); - - g_hash_table_insert (priv->single_thread_extractors, module, async_queue); - } - - g_async_queue_push (async_queue, task); - break; - } - case TRACKER_MODULE_MULTI_THREAD: - /* Put task in thread pool */ -#ifdef THREAD_ENABLE_TRACE - g_debug ("Thread:%p (Main) --> '%s': Dispatching in thread pool", - g_thread_self(), task->file); -#endif /* THREAD_ENABLE_TRACE */ - g_thread_pool_push (priv->thread_pool, task, &error); - - if (error) { - g_task_return_error (G_TASK (task->res), error); - extract_task_free (task); - - return FALSE; - } - - break; - } - - 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); -} - -#ifdef HAVE_LIBMEDIAART - -MediaArtProcess * -tracker_extract_get_media_art_process (TrackerExtract *extract) -{ - TrackerExtractPrivate *priv; - - g_return_val_if_fail (TRACKER_IS_EXTRACT (extract), NULL); - - priv = TRACKER_EXTRACT_GET_PRIVATE (extract); - - return priv->media_art_process; -} - -#endif - -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, NULL); - } - - 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) { - TrackerSparqlBuilder *builder; - const char *text; - - builder = tracker_sparql_builder_new_update (); - - /* 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, - NULL); - } - } - - 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 f832b32a2..000000000 --- a/src/tracker-extract/tracker-extract.desktop.in.in +++ /dev/null @@ -1,19 +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-Meego-Priority=Late -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-MEEGO-HS;X-MEEGO-NB;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 882c601fc..000000000 --- a/src/tracker-extract/tracker-extract.h +++ /dev/null @@ -1,89 +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); - -#ifdef HAVE_LIBMEDIAART -MediaArtProcess * - tracker_extract_get_media_art_process (TrackerExtract *extract); -#endif - -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 d8e0f5f4b..000000000 --- a/src/tracker-extract/tracker-main.c +++ /dev/null @@ -1,429 +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 - -#ifdef HAVE_LIBMEDIAART -#include <libmediaart/mediaart.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" - -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 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") }, - { "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_init (); - - /* This makes sure we don't steal all the system's resources */ - initialize_priority_and_scheduling (tracker_config_get_sched_idle (config), - tracker_db_manager_get_first_index_done () == FALSE); - - 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); - tracker_locale_shutdown (); - 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); - - tracker_locale_shutdown (); - - return EXIT_SUCCESS; -} - -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; - - 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, ""); - - 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), - tracker_db_manager_get_first_index_done () == FALSE); - - extract = tracker_extract_new (TRUE, force_module); - - if (!extract) { - g_object_unref (config); - tracker_log_shutdown (); - return EXIT_FAILURE; - } - - 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; - } - -#ifdef THREAD_ENABLE_TRACE - g_debug ("Thread:%p (Main) --- Waiting for extract requests...", - g_thread_self ()); -#endif /* THREAD_ENABLE_TRACE */ - - tracker_locale_init (); - - controller = tracker_extract_controller_new (decorator); - tracker_miner_start (TRACKER_MINER (decorator)); - - /* Main loop */ - main_loop = g_main_loop_new (NULL, FALSE); - - 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 */ - tracker_locale_shutdown (); - - g_object_unref (extract); - g_object_unref (decorator); - g_object_unref (controller); - - 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 32db4596a..000000000 --- a/src/tracker-extract/tracker-read.c +++ /dev/null @@ -1,383 +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 - posix_fadvise (fd, 0, 0, POSIX_FADV_DONTNEED); -#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-needle/.gitignore b/src/tracker-needle/.gitignore deleted file mode 100644 index ef6283577..000000000 --- a/src/tracker-needle/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -tracker-needle -*.c -*.desktop.in -org.freedesktop.Tracker.Needle.gschema.valid -org.freedesktop.Tracker.Needle.gschema.xml -org.freedesktop.Tracker.enums.xml diff --git a/src/tracker-needle/Makefile.am b/src/tracker-needle/Makefile.am deleted file mode 100644 index 14d65cd89..000000000 --- a/src/tracker-needle/Makefile.am +++ /dev/null @@ -1,80 +0,0 @@ -SUBDIRS = icons - -bin_PROGRAMS = tracker-needle - -AM_VALAFLAGS = \ - --pkg gtk+-3.0 --pkg gio-2.0 \ - $(BUILD_VALAFLAGS) \ - $(top_srcdir)/src/libtracker-sparql/tracker-sparql-$(TRACKER_API_VERSION).vapi \ - config.vapi - -AM_CPPFLAGS = \ - $(BUILD_VALACFLAGS) \ - -D_XOPEN_SOURCE \ - -D_XOPEN_SOURCE_EXTENDED \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - -DTRACKER_UI_DIR=\"$(datadir)/tracker/\" \ - -DLOCALEDIR=\""$(localedir)"\" \ - -DSRCDIR=\"$(abs_srcdir)/\" \ - $(TRACKER_NEEDLE_CFLAGS) \ - -include config.h - -LDADD = \ - $(top_builddir)/src/libtracker-sparql-backend/libtracker-sparql-$(TRACKER_API_VERSION).la \ - $(BUILD_LIBS) \ - $(TRACKER_NEEDLE_LIBS) - -tracker_needle_SOURCES = \ - tracker-history.vala \ - tracker-query.vala \ - tracker-result-store.vala \ - tracker-stats.vala \ - tracker-tags-view.vala \ - tracker-utils.vala \ - tracker-needle.vala \ - tracker-view.vala - -@INTLTOOL_DESKTOP_RULE@ - -uidir = $(datadir)/tracker -ui_DATA = tracker-needle.ui - -desktopdir = $(datadir)/applications -desktop_DATA = tracker-needle.desktop - -appdatadir = $(datadir)/appdata -appdata_DATA = tracker-needle.appdata.xml - -BUILT_SOURCES = \ - tracker_needle_vala.stamp - -#Desktop files -%.desktop.in: %.desktop.in.in - @sed -e "s|@VERSION[@]|${VERSION}|" $< > $@ - -#GSettings -gsettings_ENUM_NAMESPACE = org.freedesktop.Tracker -gsettings_ENUM_FILES = $(top_srcdir)/src/libtracker-common/tracker-enums.h - -gsettings_SCHEMAS = $(schemalist) - -schemalist = org.freedesktop.Tracker.Needle.gschema.xml - -@INTLTOOL_XML_NOMERGE_RULE@ - -@GSETTINGS_RULES@ - -# Dist / Clean rules for all data -CLEANFILES = \ - $(desktop_DATA:.desktop=.desktop.in) \ - $(desktop_DATA) \ - $(gsettings_SCHEMAS) - -EXTRA_DIST = \ - $(desktop_DATA:.desktop=.desktop.in.in) \ - $(ui_DATA) \ - $(desktop_DATA) \ - $(appdata_DATA) \ - config.vapi \ - $(gsettings_SCHEMAS:.xml=.xml.in) diff --git a/src/tracker-needle/config.vapi b/src/tracker-needle/config.vapi deleted file mode 100644 index e9b856c25..000000000 --- a/src/tracker-needle/config.vapi +++ /dev/null @@ -1,31 +0,0 @@ -// config.vapi -// -// Copyright (C) 2010 Martyn Russell <martyn@lanedo.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. -// - -[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")] -namespace Config -{ - public const string GETTEXT_PACKAGE; - public const string PACKAGE_NAME; - public const string PACKAGE_VERSION; - public const string APP_PATH; - public const string LOCALEDIR; -} - - diff --git a/src/tracker-needle/icons/16x16/Makefile.am b/src/tracker-needle/icons/16x16/Makefile.am deleted file mode 100644 index 52782da46..000000000 --- a/src/tracker-needle/icons/16x16/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -icondir = $(datadir)/icons/hicolor/16x16/apps -icon_DATA = # Empty - -if HAVE_ARTWORK -icon_DATA += tracker.png -endif - -EXTRA_DIST = $(icon_DATA) diff --git a/src/tracker-needle/icons/16x16/tracker.png b/src/tracker-needle/icons/16x16/tracker.png Binary files differdeleted file mode 100644 index 0048e022b..000000000 --- a/src/tracker-needle/icons/16x16/tracker.png +++ /dev/null diff --git a/src/tracker-needle/icons/22x22/Makefile.am b/src/tracker-needle/icons/22x22/Makefile.am deleted file mode 100644 index 60ba12bf6..000000000 --- a/src/tracker-needle/icons/22x22/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -icondir = $(datadir)/icons/hicolor/22x22/apps -icon_DATA = # Empty - -if HAVE_ARTWORK -icon_DATA += tracker.png -endif - -EXTRA_DIST = $(icon_DATA) diff --git a/src/tracker-needle/icons/22x22/tracker.png b/src/tracker-needle/icons/22x22/tracker.png Binary files differdeleted file mode 100644 index ea038072d..000000000 --- a/src/tracker-needle/icons/22x22/tracker.png +++ /dev/null diff --git a/src/tracker-needle/icons/24x24/Makefile.am b/src/tracker-needle/icons/24x24/Makefile.am deleted file mode 100644 index 573bf12e5..000000000 --- a/src/tracker-needle/icons/24x24/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -icondir = $(datadir)/icons/hicolor/24x24/apps -icon_DATA = # Empty - -if HAVE_ARTWORK -icon_DATA += tracker.png -endif - -EXTRA_DIST = $(icon_DATA) diff --git a/src/tracker-needle/icons/24x24/tracker.png b/src/tracker-needle/icons/24x24/tracker.png Binary files differdeleted file mode 100644 index 4de00ab31..000000000 --- a/src/tracker-needle/icons/24x24/tracker.png +++ /dev/null diff --git a/src/tracker-needle/icons/32x32/Makefile.am b/src/tracker-needle/icons/32x32/Makefile.am deleted file mode 100644 index 19b2311ef..000000000 --- a/src/tracker-needle/icons/32x32/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -icondir = $(datadir)/icons/hicolor/32x32/apps -icon_DATA = # Empty - -if HAVE_ARTWORK -icon_DATA += tracker.png -endif - -EXTRA_DIST = $(icon_DATA) diff --git a/src/tracker-needle/icons/32x32/tracker.png b/src/tracker-needle/icons/32x32/tracker.png Binary files differdeleted file mode 100644 index 96089db9f..000000000 --- a/src/tracker-needle/icons/32x32/tracker.png +++ /dev/null diff --git a/src/tracker-needle/icons/48x48/Makefile.am b/src/tracker-needle/icons/48x48/Makefile.am deleted file mode 100644 index 239df51ab..000000000 --- a/src/tracker-needle/icons/48x48/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -icondir = $(datadir)/icons/hicolor/48x48/apps -icon_DATA = # Empty - -if HAVE_ARTWORK -icon_DATA += tracker.png -endif - -EXTRA_DIST = $(icon_DATA) diff --git a/src/tracker-needle/icons/48x48/tracker.png b/src/tracker-needle/icons/48x48/tracker.png Binary files differdeleted file mode 100644 index 497f2a2a3..000000000 --- a/src/tracker-needle/icons/48x48/tracker.png +++ /dev/null diff --git a/src/tracker-needle/icons/Makefile.am b/src/tracker-needle/icons/Makefile.am deleted file mode 100644 index 2d5974d2c..000000000 --- a/src/tracker-needle/icons/Makefile.am +++ /dev/null @@ -1,14 +0,0 @@ -SUBDIRS = 16x16 22x22 24x24 32x32 48x48 scalable - -gtk_update_icon_cache = gtk-update-icon-cache -f -t $(datadir)/icons/hicolor - -install-data-hook: update-icon-cache -uninstall-hook: update-icon-cache -update-icon-cache: - @-if test -z "$(DESTDIR)"; then \ - echo "Updating Gtk icon cache."; \ - $(gtk_update_icon_cache); \ - else \ - echo "*** Icon cache not updated. After (un)install, run this:"; \ - echo "*** $(gtk_update_icon_cache)"; \ - fi diff --git a/src/tracker-needle/icons/scalable/Makefile.am b/src/tracker-needle/icons/scalable/Makefile.am deleted file mode 100644 index bb3899cfd..000000000 --- a/src/tracker-needle/icons/scalable/Makefile.am +++ /dev/null @@ -1,11 +0,0 @@ -icondir = $(datadir)/icons/hicolor/scalable/apps -icon_DATA = # Empty - -if HAVE_ARTWORK -icon_DATA += tracker.svg -endif - -minericonsdir = $(datadir)/tracker/icons -minericons_DATA = - -EXTRA_DIST = $(icon_DATA) diff --git a/src/tracker-needle/icons/scalable/tracker.svg b/src/tracker-needle/icons/scalable/tracker.svg deleted file mode 100644 index 7655d24ac..000000000 --- a/src/tracker-needle/icons/scalable/tracker.svg +++ /dev/null @@ -1,1347 +0,0 @@ -<?xml version="1.0" encoding="UTF-8" standalone="no"?> -<!-- Created with Inkscape (http://www.inkscape.org/) --> -<svg - xmlns:i="http://ns.adobe.com/AdobeIllustrator/10.0/" - xmlns:dc="http://purl.org/dc/elements/1.1/" - xmlns:cc="http://web.resource.org/cc/" - xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" - xmlns:svg="http://www.w3.org/2000/svg" - xmlns="http://www.w3.org/2000/svg" - xmlns:xlink="http://www.w3.org/1999/xlink" - xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" - xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="48" - height="48" - id="svg2" - sodipodi:version="0.32" - inkscape:version="0.44.1" - version="1.0" - sodipodi:docbase="/home/baze" - sodipodi:docname="tracker.svg" - inkscape:export-filename="/home/baze/tracker.png" - inkscape:export-xdpi="90" - inkscape:export-ydpi="90"> - <defs - id="defs4"> - <radialGradient - r="45" - fy="106.49996" - fx="-25" - cy="106.49996" - cx="-25" - gradientTransform="matrix(3.466166,-6.346783e-2,7.070491e-2,3.695342,32.7241,-321.4409)" - gradientUnits="userSpaceOnUse" - id="radialGradient3293" - xlink:href="#linearGradient3075" - inkscape:collect="always" /> - <radialGradient - r="46" - fy="99.774971" - fx="-24.85253" - cy="99.774971" - cx="-24.85253" - gradientTransform="matrix(0.934777,-0.846006,0.891541,0.985091,-120.2744,-50.59553)" - gradientUnits="userSpaceOnUse" - id="radialGradient3290" - xlink:href="#linearGradient3139" - inkscape:collect="always" /> - <linearGradient - gradientTransform="matrix(1.2,0,0,1.2,-18.8,-66.7005)" - y2="97.761848" - x2="-44.159863" - y1="103.68449" - x1="-39.098888" - gradientUnits="userSpaceOnUse" - id="linearGradient3287" - xlink:href="#linearGradient3149" - inkscape:collect="always" /> - <linearGradient - y2="97.761848" - x2="-44.159863" - y1="103.68449" - x1="-39.098888" - gradientUnits="userSpaceOnUse" - id="linearGradient3283" - xlink:href="#linearGradient3149" - inkscape:collect="always" /> - <radialGradient - r="46" - fy="99.774971" - fx="-24.85253" - cy="99.774971" - cx="-24.85253" - gradientTransform="matrix(0.778981,-0.705005,0.742951,0.820909,-84.56197,13.42081)" - gradientUnits="userSpaceOnUse" - id="radialGradient3281" - xlink:href="#linearGradient3139" - inkscape:collect="always" /> - <radialGradient - r="45" - fy="106.49996" - fx="-25" - cy="106.49996" - cx="-25" - gradientTransform="matrix(2.888472,-5.288986e-2,5.892076e-2,3.079452,42.93675,-212.2837)" - gradientUnits="userSpaceOnUse" - id="radialGradient3279" - xlink:href="#linearGradient3075" - inkscape:collect="always" /> - <radialGradient - r="64.122231" - fy="123.41074" - fx="31.487459" - cy="123.41074" - cx="64.37719" - gradientTransform="matrix(1,0,0,8.747514e-2,0,112.6154)" - gradientUnits="userSpaceOnUse" - id="radialGradient2348" - xlink:href="#linearGradient2345" - inkscape:collect="always" /> - <linearGradient - id="linearGradient2215"> - <stop - style="stop-color:#8e8e8e;stop-opacity:1;" - offset="0" - id="stop2217" /> - <stop - style="stop-color:#f8f8f8;stop-opacity:1;" - offset="1" - id="stop2219" /> - </linearGradient> - <linearGradient - id="linearGradient2221"> - <stop - style="stop-color:#000000;stop-opacity:1;" - offset="0" - id="stop2223" /> - <stop - id="stop2225" - offset="0.40659341" - style="stop-color:#000000;stop-opacity:0.68235294;" /> - <stop - style="stop-color:#000000;stop-opacity:0.48736462;" - offset="0.45329672" - id="stop2227" /> - <stop - id="stop2229" - offset="0.5" - style="stop-color:#000000;stop-opacity:0.36101082;" /> - <stop - style="stop-color:#000000;stop-opacity:0.15162455;" - offset="0.70604396" - id="stop2231" /> - <stop - style="stop-color:#000000;stop-opacity:0;" - offset="1" - id="stop2233" /> - </linearGradient> - <linearGradient - id="linearGradient2235"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop2237" /> - <stop - id="stop2239" - offset="0.42597079" - style="stop-color:#ffffff;stop-opacity:1;" /> - <stop - id="stop2241" - offset="0.5892781" - style="stop-color:#f1f1f1;stop-opacity:1;" /> - <stop - style="stop-color:#eaeaea;stop-opacity:1;" - offset="0.80219781" - id="stop2243" /> - <stop - style="stop-color:#dfdfdf;stop-opacity:1;" - offset="1" - id="stop2245" /> - </linearGradient> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3075" - id="radialGradient1458" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(2.888472,-5.288986e-2,5.892076e-2,3.079452,42.93675,-212.2837)" - cx="-25" - cy="106.49996" - fx="-25" - fy="106.49996" - r="45" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3139" - id="radialGradient1460" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.778981,-0.705005,0.742951,0.820909,-84.56197,13.42081)" - cx="-24.85253" - cy="99.774971" - fx="-24.85253" - fy="99.774971" - r="46" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient3149" - id="linearGradient1462" - gradientUnits="userSpaceOnUse" - x1="-39.098888" - y1="103.68449" - x2="-44.159863" - y2="97.761848" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient2345" - id="radialGradient2250" - cx="64.37719" - cy="123.41074" - fx="31.487459" - fy="123.41074" - r="64.122231" - gradientTransform="matrix(1,0,0,8.747514e-2,0,112.6154)" - gradientUnits="userSpaceOnUse" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient2257" - id="radialGradient1495" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.520175,8.839467e-2,-0.843351,13.788,109.1206,-1545.323)" - cx="42.617531" - cy="120.64188" - fx="42.617531" - fy="120.64188" - r="3.406888" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3311" - id="radialGradient1497" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(6.228741e-2,-3.825032e-4,4.90218e-3,0.798611,68.90433,5.49306)" - cx="95.505852" - cy="59.591507" - fx="95.505852" - fy="59.591507" - r="47.746403" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3225" - id="radialGradient1499" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.297068,-1.880044e-3,7.085819e-4,0.48867,6.806484,-3.45491)" - cx="49.009884" - cy="8.4953117" - fx="47.370888" - fy="6.7701697" - r="3.9750404" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient3217" - id="linearGradient1501" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.29707,0,0,1.29707,6.81152,-10.31269)" - x1="48.914677" - y1="2.9719031" - x2="48.913002" - y2="2.5548496" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3207" - id="radialGradient1503" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.29707,0,0,0.1578,6.81152,-7.300115)" - cx="49.011971" - cy="2.6743078" - fx="49.011971" - fy="2.6743078" - r="1.7246193" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient3235" - id="linearGradient1505" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.297068,-1.880044e-3,1.880044e-3,1.297068,6.796523,-10.3225)" - x1="48.498562" - y1="0.81150496" - x2="48.732723" - y2="2.3657269" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient3251" - id="linearGradient1507" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.28993,0,0,1.29707,7.14915,-10.31269)" - x1="46.051746" - y1="3.0999987" - x2="46.051746" - y2="2.395859" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3273" - id="radialGradient1509" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.860164,0,0,0.1578,24.50481,-7.300115)" - cx="49.011971" - cy="2.6743078" - fx="49.011971" - fy="2.6743078" - r="1.7246193" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient3251" - id="linearGradient1511" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.279856,0,0,1.29707,-133.1341,-10.31269)" - x1="46.051746" - y1="3.0999987" - x2="46.051746" - y2="2.395859" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3259" - id="radialGradient1513" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.853446,0,0,0.1578,-115.9141,-7.300115)" - cx="49.011971" - cy="2.6743078" - fx="49.011971" - fy="2.6743078" - r="1.7246193" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3303" - id="radialGradient1515" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1,0,0,2.608014e-2,0,7.26766)" - cx="34.677639" - cy="7.4622769" - fx="34.677639" - fy="7.4622769" - r="47.595196" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3325" - id="radialGradient1517" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(-1.511766,-6.865741e-3,4.187271e-5,-9.110636e-3,87.10184,7.76835)" - cx="34.677639" - cy="7.4622769" - fx="34.677639" - fy="7.4622769" - r="47.595196" /> - <linearGradient - id="linearGradient3325"> - <stop - id="stop3327" - offset="0" - style="stop-color:#ffffff;stop-opacity:1;" /> - <stop - id="stop3329" - offset="1" - style="stop-color:#ffffff;stop-opacity:0;" /> - </linearGradient> - <linearGradient - id="linearGradient3311"> - <stop - style="stop-color:#2d2d2d;stop-opacity:1;" - offset="0" - id="stop3313" /> - <stop - id="stop3319" - offset="0.5" - style="stop-color:#000000;stop-opacity:1;" /> - <stop - style="stop-color:#000000;stop-opacity:1;" - offset="1" - id="stop3315" /> - </linearGradient> - <linearGradient - id="linearGradient3303"> - <stop - style="stop-color:#ffffff;stop-opacity:0.68345326;" - offset="0" - id="stop3305" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop3307" /> - </linearGradient> - <linearGradient - id="linearGradient3273"> - <stop - style="stop-color:#ffffff;stop-opacity:0.55035973;" - offset="0" - id="stop3275" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop3277" /> - </linearGradient> - <linearGradient - id="linearGradient3259"> - <stop - id="stop3261" - offset="0" - style="stop-color:#ffffff;stop-opacity:0.55035973;" /> - <stop - id="stop3263" - offset="1" - style="stop-color:#000000;stop-opacity:0;" /> - </linearGradient> - <linearGradient - id="linearGradient2280"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop2282" /> - <stop - style="stop-color:#aeaeae;stop-opacity:1;" - offset="1" - id="stop2284" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient3217"> - <stop - style="stop-color:#252525;stop-opacity:1;" - offset="0" - id="stop3219" /> - <stop - style="stop-color:#252525;stop-opacity:0;" - offset="1" - id="stop3221" /> - </linearGradient> - <linearGradient - id="linearGradient3207"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop3209" /> - <stop - style="stop-color:#252525;stop-opacity:0;" - offset="1" - id="stop3211" /> - </linearGradient> - <linearGradient - id="linearGradient2257"> - <stop - style="stop-color:#b4942a;stop-opacity:1;" - offset="0" - id="stop2259" /> - <stop - style="stop-color:#e4dcc9;stop-opacity:1" - offset="1" - id="stop2261" /> - </linearGradient> - <linearGradient - id="linearGradient3235" - inkscape:collect="always"> - <stop - id="stop3237" - offset="0" - style="stop-color:#ffffff;stop-opacity:1;" /> - <stop - id="stop3239" - offset="1" - style="stop-color:#ffffff;stop-opacity:0;" /> - </linearGradient> - <linearGradient - id="linearGradient3251"> - <stop - id="stop3253" - offset="0" - style="stop-color:#000000;stop-opacity:1;" /> - <stop - style="stop-color:#090909;stop-opacity:0.67870039;" - offset="0.7087912" - id="stop14161" /> - <stop - id="stop3255" - offset="1" - style="stop-color:#131313;stop-opacity:0;" /> - </linearGradient> - <foreignObject - requiredExtensions="http://ns.adobe.com/AdobeIllustrator/10.0/" - x="0" - y="0" - width="1" - height="1" - id="foreignObject1939"> - <i:pgfRef - xlink:href="#adobe_illustrator_pgf" /> - </foreignObject> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3291" - id="radialGradient1566" - cx="63.912209" - cy="115.70919" - fx="98.520187" - fy="119.62119" - r="63.912209" - gradientTransform="matrix(1,0,0,0.197802,0,92.82166)" - gradientUnits="userSpaceOnUse" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3291" - id="radialGradient1739" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1,0,0,0.197802,0,92.82166)" - cx="63.912209" - cy="115.7093" - fx="63.912209" - fy="115.7093" - r="63.912209" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3291" - id="radialGradient2096" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1,0,0,0.197802,0,92.82166)" - cx="63.912209" - cy="115.70919" - fx="98.520187" - fy="119.62119" - r="63.912209" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3291" - id="radialGradient2098" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1,0,0,0.197802,0,92.82166)" - cx="63.912209" - cy="115.7093" - fx="63.912209" - fy="115.7093" - r="63.912209" /> - <linearGradient - inkscape:collect="always" - id="linearGradient4171"> - <stop - style="stop-color:#000000;stop-opacity:1;" - offset="0" - id="stop4173" /> - <stop - style="stop-color:#000000;stop-opacity:0;" - offset="1" - id="stop4175" /> - </linearGradient> - <linearGradient - id="linearGradient5176"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop5178" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop5180" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient5142"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop5144" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop5146" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient5111"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop5113" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop5115" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient4206"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop4208" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop4210" /> - </linearGradient> - <linearGradient - id="linearGradient3319"> - <stop - style="stop-color:#000000;stop-opacity:0;" - offset="0" - id="stop3321" /> - <stop - id="stop2287" - offset="0.86263734" - style="stop-color:#000000;stop-opacity:0;" /> - <stop - style="stop-color:#000000;stop-opacity:0.27797833;" - offset="1" - id="stop3323" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient3201"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop3203" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop3205" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient2288"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop2290" /> - <stop - style="stop-color:#ffffff;stop-opacity:0;" - offset="1" - id="stop2292" /> - </linearGradient> - <linearGradient - inkscape:collect="always" - id="linearGradient3291"> - <stop - style="stop-color:#000000;stop-opacity:1;" - offset="0" - id="stop3293" /> - <stop - style="stop-color:#000000;stop-opacity:0;" - offset="1" - id="stop3295" /> - </linearGradient> - <linearGradient - id="linearGradient3225"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop3227" /> - <stop - style="stop-color:#aeaeae;stop-opacity:1;" - offset="1" - id="stop3229" /> - </linearGradient> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3291" - id="radialGradient3297" - cx="63.912209" - cy="115.70919" - fx="98.520187" - fy="119.62119" - r="63.912209" - gradientTransform="matrix(1,0,0,0.197802,0,92.82166)" - gradientUnits="userSpaceOnUse" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3201" - id="radialGradient4208" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1,0,0,0.350763,0,33.62806)" - cx="53.82272" - cy="51.796238" - fx="53.363365" - fy="53.704475" - r="5.2844129" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3201" - id="radialGradient4210" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1,0,0,0.350763,0,33.62806)" - cx="53.82272" - cy="51.796238" - fx="53.363365" - fy="53.704475" - r="5.2844129" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient4206" - id="radialGradient4214" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1,0,0,1.008658,0,-0.322745)" - cx="36.920532" - cy="37.277058" - fx="28.846222" - fy="20.466549" - r="31.704992" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5142" - id="linearGradient4216" - gradientUnits="userSpaceOnUse" - x1="67.70639" - y1="137.9411" - x2="60.432804" - y2="42.427299" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5111" - id="linearGradient4218" - gradientUnits="userSpaceOnUse" - x1="34.841892" - y1="-7.142458" - x2="35.561386" - y2="11.415728" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5111" - id="linearGradient4220" - gradientUnits="userSpaceOnUse" - x1="34.841892" - y1="-7.142458" - x2="35.561386" - y2="11.415728" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5111" - id="linearGradient4222" - gradientUnits="userSpaceOnUse" - x1="34.841892" - y1="-7.142458" - x2="35.561386" - y2="11.415728" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient5176" - id="radialGradient4224" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.743822,4.610586e-7,-4.175093e-7,0.670083,-30.109,9.1749)" - cx="40.478767" - cy="27.809845" - fx="40.478779" - fy="42.86652" - r="30.543081" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5111" - id="linearGradient4226" - gradientUnits="userSpaceOnUse" - x1="34.841892" - y1="-7.142458" - x2="35.561386" - y2="11.415728" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5111" - id="linearGradient4229" - gradientUnits="userSpaceOnUse" - x1="34.841892" - y1="-7.142458" - x2="35.561386" - y2="11.415728" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient5111" - id="linearGradient4231" - gradientUnits="userSpaceOnUse" - x1="34.841892" - y1="-7.142458" - x2="35.561386" - y2="11.415728" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient4171" - id="linearGradient1380" - gradientUnits="userSpaceOnUse" - x1="67.515175" - y1="86.706062" - x2="63.401665" - y2="61.357201" - gradientTransform="matrix(1.004983,0,0,1.005797,-3.514071e-3,-9.765696e-2)" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient3225" - id="linearGradient1395" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(-0.342816,0.414732,0.409438,0.344388,68.74377,42.51885)" - spreadMethod="reflect" - x1="28.071711" - y1="20.204628" - x2="40.198689" - y2="20.20463" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient2288" - id="radialGradient1401" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.599945,-0.725801,7.847448,6.600672,-444.8151,-313.0422)" - cx="32.489605" - cy="69.225014" - fx="29.738691" - fy="69.225014" - r="8.3332367" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient2288" - id="radialGradient1404" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.599945,-0.725801,7.847448,6.600672,-444.8151,-313.0422)" - cx="49.157429" - cy="62.380642" - fx="45.900455" - fy="62.298256" - r="8.3332367" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient3319" - id="radialGradient1412" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.993088,2.250037e-2,-2.180165e-2,0.952313,1.715624,0.815028)" - cx="39.126225" - cy="44.269405" - fx="39.12624" - fy="44.269413" - r="34.469494" /> - <linearGradient - gradientUnits="userSpaceOnUse" - y2="97.761848" - x2="-44.159863" - y1="103.68449" - x1="-39.098888" - id="linearGradient3155" - xlink:href="#linearGradient3149" - inkscape:collect="always" /> - <radialGradient - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(0.778981,-0.705005,0.742951,0.820909,-84.56197,13.42081)" - r="46" - fy="99.774971" - fx="-24.85253" - cy="99.774971" - cx="-24.85253" - id="radialGradient3145" - xlink:href="#linearGradient3139" - inkscape:collect="always" /> - <radialGradient - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(2.888472,-5.288986e-2,5.892076e-2,3.079452,42.93675,-212.2837)" - r="45" - fy="106.49996" - fx="-25" - cy="106.49996" - cx="-25" - id="radialGradient3083" - xlink:href="#linearGradient3075" - inkscape:collect="always" /> - <linearGradient - id="linearGradient3075"> - <stop - id="stop3077" - offset="0" - style="stop-color:#ffffff;stop-opacity:1;" /> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0.42597079" - id="stop3093" /> - <stop - style="stop-color:#f1f1f1;stop-opacity:1;" - offset="0.5892781" - id="stop3085" /> - <stop - id="stop3087" - offset="0.80219781" - style="stop-color:#eaeaea;stop-opacity:1;" /> - <stop - id="stop3079" - offset="1" - style="stop-color:#dfdfdf;stop-opacity:1;" /> - </linearGradient> - <linearGradient - id="linearGradient3139"> - <stop - id="stop3141" - offset="0" - style="stop-color:#000000;stop-opacity:1;" /> - <stop - style="stop-color:#000000;stop-opacity:0.68235294;" - offset="0.40659341" - id="stop3162" /> - <stop - id="stop3164" - offset="0.45329672" - style="stop-color:#000000;stop-opacity:0.48736462;" /> - <stop - style="stop-color:#000000;stop-opacity:0.36101082;" - offset="0.5" - id="stop3158" /> - <stop - id="stop3160" - offset="0.70604396" - style="stop-color:#000000;stop-opacity:0.15162455;" /> - <stop - id="stop3143" - offset="1" - style="stop-color:#000000;stop-opacity:0;" /> - </linearGradient> - <linearGradient - id="linearGradient3149"> - <stop - id="stop3151" - offset="0" - style="stop-color:#8e8e8e;stop-opacity:1;" /> - <stop - id="stop3153" - offset="1" - style="stop-color:#f8f8f8;stop-opacity:1;" /> - </linearGradient> - <linearGradient - id="linearGradient3461"> - <stop - id="stop3463" - offset="0" - style="stop-color:#bbbbbb;stop-opacity:1;" /> - <stop - id="stop3465" - offset="1" - style="stop-color:#bbbbbb;stop-opacity:0;" /> - </linearGradient> - <linearGradient - id="linearGradient3471"> - <stop - id="stop3473" - offset="0" - style="stop-color:#000000;stop-opacity:0.48736462;" /> - <stop - id="stop3475" - offset="1" - style="stop-color:#000000;stop-opacity:0;" /> - </linearGradient> - <linearGradient - id="linearGradient2345" - inkscape:collect="always"> - <stop - id="stop2347" - offset="0" - style="stop-color:#000000;stop-opacity:1;" /> - <stop - id="stop2349" - offset="1" - style="stop-color:#000000;stop-opacity:0;" /> - </linearGradient> - <linearGradient - id="linearGradient4440"> - <stop - id="stop4442" - offset="0" - style="stop-color:#7d7d7d;stop-opacity:1;" /> - <stop - style="stop-color:#b1b1b1;stop-opacity:1.0000000;" - offset="0.50000000" - id="stop4448" /> - <stop - id="stop4444" - offset="1.0000000" - style="stop-color:#686868;stop-opacity:1.0000000;" /> - </linearGradient> - <linearGradient - id="linearGradient4454"> - <stop - id="stop4456" - offset="0.0000000" - style="stop-color:#ce5c00;stop-opacity:0.20784314" /> - <stop - id="stop4458" - offset="1.0000000" - style="stop-color:#f57900;stop-opacity:0.67619050" /> - </linearGradient> - <linearGradient - id="linearGradient4467"> - <stop - id="stop4469" - offset="0" - style="stop-color:#ffffff;stop-opacity:1;" /> - <stop - id="stop4471" - offset="1.0000000" - style="stop-color:#ffffff;stop-opacity:0.24761905;" /> - </linearGradient> - <linearGradient - id="linearGradient4477" - inkscape:collect="always"> - <stop - id="stop4479" - offset="0" - style="stop-color:#000000;stop-opacity:1;" /> - <stop - id="stop4481" - offset="1" - style="stop-color:#000000;stop-opacity:0;" /> - </linearGradient> - <linearGradient - id="linearGradient4487" - inkscape:collect="always"> - <stop - id="stop4489" - offset="0" - style="stop-color:#ffffff;stop-opacity:1;" /> - <stop - id="stop4491" - offset="1" - style="stop-color:#ffffff;stop-opacity:0;" /> - </linearGradient> - <linearGradient - id="linearGradient2366"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop2368" /> - <stop - id="stop2374" - offset="0.50000000" - style="stop-color:#ffffff;stop-opacity:0.21904762;" /> - <stop - style="stop-color:#ffffff;stop-opacity:1.0000000;" - offset="1.0000000" - id="stop2370" /> - </linearGradient> - <linearGradient - id="linearGradient2846"> - <stop - style="stop-color:#8a8a8a;stop-opacity:1.0000000;" - offset="0.0000000" - id="stop2848" /> - <stop - style="stop-color:#484848;stop-opacity:1.0000000;" - offset="1.0000000" - id="stop2850" /> - </linearGradient> - <linearGradient - id="linearGradient2997"> - <stop - id="stop2999" - offset="0" - style="stop-color:#7d7d7d;stop-opacity:1;" /> - <stop - style="stop-color:#b1b1b1;stop-opacity:1.0000000;" - offset="0.50000000" - id="stop3001" /> - <stop - id="stop3003" - offset="1.0000000" - style="stop-color:#686868;stop-opacity:1.0000000;" /> - </linearGradient> - <linearGradient - id="linearGradient2991"> - <stop - id="stop2993" - offset="0.0000000" - style="stop-color:#729fcf;stop-opacity:0.20784314;" /> - <stop - id="stop2995" - offset="1.0000000" - style="stop-color:#729fcf;stop-opacity:0.67619050;" /> - </linearGradient> - <linearGradient - id="linearGradient2985"> - <stop - id="stop2987" - offset="0" - style="stop-color:#ffffff;stop-opacity:1;" /> - <stop - id="stop2989" - offset="1.0000000" - style="stop-color:#ffffff;stop-opacity:0.24761905;" /> - </linearGradient> - <linearGradient - id="linearGradient2965"> - <stop - style="stop-color:#ffffff;stop-opacity:1;" - offset="0" - id="stop2967" /> - <stop - id="stop2969" - offset="0.50000000" - style="stop-color:#ffffff;stop-opacity:0.21904762;" /> - <stop - style="stop-color:#ffffff;stop-opacity:1.0000000;" - offset="1.0000000" - id="stop2971" /> - </linearGradient> - <linearGradient - id="linearGradient2959"> - <stop - style="stop-color:#8a8a8a;stop-opacity:1.0000000;" - offset="0.0000000" - id="stop2961" /> - <stop - style="stop-color:#484848;stop-opacity:1.0000000;" - offset="1.0000000" - id="stop2963" /> - </linearGradient> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient4477" - id="radialGradient3034" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1,0,0,0.237968,0,28.93278)" - cx="24.130018" - cy="37.967922" - fx="24.130018" - fy="37.967922" - r="16.528622" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient2366" - id="linearGradient3040" - gradientUnits="userSpaceOnUse" - x1="18.292673" - y1="13.602121" - x2="17.500893" - y2="25.743469" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient4487" - id="radialGradient3042" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1,0,0,0.237968,0,28.93278)" - cx="24.130018" - cy="37.967922" - fx="24.130018" - fy="37.967922" - r="16.528622" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient4454" - id="radialGradient3044" - gradientUnits="userSpaceOnUse" - cx="18.240929" - cy="21.817987" - fx="18.240929" - fy="21.817987" - r="8.3085051" /> - <radialGradient - inkscape:collect="always" - xlink:href="#linearGradient4467" - id="radialGradient3049" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(2.592963,0,0,2.252104,-24.89514,-18.08455)" - cx="15.414371" - cy="13.078408" - fx="15.414371" - fy="13.078408" - r="6.6562500" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient4440" - id="linearGradient3056" - gradientUnits="userSpaceOnUse" - gradientTransform="matrix(1.334593,0,0,1.291292,-6.809229,-6.604212)" - x1="30.656250" - y1="34.000000" - x2="33.218750" - y2="31.062500" /> - <linearGradient - inkscape:collect="always" - xlink:href="#linearGradient2846" - id="linearGradient3060" - gradientUnits="userSpaceOnUse" - x1="27.366341" - y1="26.580296" - x2="31.335964" - y2="30.557772" - gradientTransform="translate(0.164613,0.856446)" /> - </defs> - <sodipodi:namedview - id="base" - pagecolor="#ffffff" - bordercolor="#666666" - borderopacity="1.0" - gridtolerance="50" - guidetolerance="50" - objecttolerance="10" - inkscape:pageopacity="0.0" - inkscape:pageshadow="2" - inkscape:zoom="31.998886" - inkscape:cx="22.841726" - inkscape:cy="24.537509" - inkscape:document-units="px" - inkscape:current-layer="layer1" - width="48px" - height="48px" - inkscape:window-width="987" - inkscape:window-height="859" - inkscape:window-x="97" - inkscape:window-y="114" - showguides="true" - inkscape:guide-bbox="true" - inkscape:guide-points="false" - inkscape:grid-points="true" - showgrid="true" - gridspacingx="0.5px" - gridspacingy="0.5px"> - <sodipodi:guide - orientation="horizontal" - position="69.953064" - id="guide2827" /> - <sodipodi:guide - orientation="vertical" - position="-33.082496" - id="guide2829" /> - <sodipodi:guide - orientation="vertical" - position="84.852814" - id="guide2831" /> - <sodipodi:guide - orientation="horizontal" - position="-46.214479" - id="guide2835" /> - </sodipodi:namedview> - <metadata - id="metadata7"> - <rdf:RDF> - <cc:Work - rdf:about=""> - <dc:format>image/svg+xml</dc:format> - <dc:type - rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> - </cc:Work> - </rdf:RDF> - </metadata> - <g - inkscape:label="Layer 1" - inkscape:groupmode="layer" - id="layer1"> - <rect - style="opacity:0.57786889;fill:white;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" - id="rect1327" - width="1" - height="0" - x="101.96484" - y="50.58419" /> - <rect - style="opacity:0.57786889;fill:white;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3.63199997;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" - id="rect2306" - width="1" - height="0" - x="-155.40515" - y="7.1223102" /> - <path - sodipodi:nodetypes="ccc" - id="path2318" - d="M -314.34258,-66.093757 L -314.34258,-68.888466 L -314.34258,-66.093757 z " - style="fill:white;fill-opacity:0.75688076;fill-rule:nonzero;stroke:none;stroke-width:0.5;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:4;stroke-opacity:1" /> - <g - style="opacity:0.40163933" - transform="matrix(-0.782995,0,0,0.650879,-2637.201,620.4239)" - id="g4640" /> - <g - id="g4646" - transform="matrix(-0.782995,0,0,0.650879,-2637.201,620.4239)" - style="opacity:0.40163933" /> - <g - id="g4730" - transform="matrix(1,0,0,0.650879,563.7618,627.7517)" - style="opacity:0.40163933" /> - <g - style="opacity:0.40163933" - transform="matrix(1,0,0,0.650879,563.7618,627.7517)" - id="g4748" /> - <path - transform="matrix(1.446431,0,0,1.51999,-10.80992,-16.89523)" - d="M 40.65864 37.967922 A 16.528622 3.9332814 0 1 1 7.6013966,37.967922 A 16.528622 3.9332814 0 1 1 40.65864 37.967922 z" - sodipodi:ry="3.9332814" - sodipodi:rx="16.528622" - sodipodi:cy="37.967922" - sodipodi:cx="24.130018" - id="path4475" - style="opacity:0.17112301;color:black;fill:url(#radialGradient3034);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" - sodipodi:type="arc" /> - <path - style="color:black;fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3060);stroke-width:2.00000095;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" - d="M 18.792182,4.0000008 C 10.653052,4.0000008 4.0473812,10.605672 4.0473812,18.744802 C 4.0473812,26.883932 10.653052,33.489604 18.792182,33.489604 C 22.271737,33.489604 25.343183,32.105211 27.865905,30.086957 C 27.660528,31.093838 27.78787,32.122325 28.622049,32.846882 L 39.586133,42.374292 C 40.819549,43.445621 42.673595,43.305252 43.744923,42.071835 C 44.816251,40.838417 44.675882,38.984373 43.442466,37.913045 L 32.478382,28.385634 C 31.806855,27.802355 30.985504,27.629665 30.172144,27.742912 C 32.158844,25.23049 33.536983,22.194109 33.536983,18.744802 C 33.536983,10.605672 26.931312,4.0000008 18.792182,4.0000008 z M 18.716567,5.2261841 C 26.356026,5.2261841 32.008342,10.015135 32.008342,18.517959 C 32.008342,27.193072 26.191652,31.809734 18.716567,31.809734 C 11.413618,31.809734 5.4247936,26.331642 5.4247936,18.517959 C 5.4247936,10.533852 11.249432,5.226184 18.716567,5.2261841 z " - id="path2844" - sodipodi:nodetypes="csscccscccscczzzz" /> - <path - id="path4430" - d="M 18.767518,3.9368011 C 10.602078,3.9368011 3.9750538,10.563825 3.9750538,18.729265 C 3.9750538,26.894705 10.602078,33.521729 18.767518,33.521729 C 22.258321,33.521729 25.339695,32.132862 27.870573,30.108084 C 27.664532,31.11822 27.792285,32.150031 28.62916,32.87693 L 39.628686,42.435137 C 40.866089,43.509929 42.726128,43.369107 43.800919,42.131702 C 44.87571,40.894298 44.734887,39.03426 43.497484,37.959469 L 32.497959,28.401261 C 31.824261,27.816097 31.000255,27.642848 30.184266,27.756462 C 32.177388,25.235918 33.559982,22.189722 33.559982,18.729265 C 33.559982,10.563825 26.932958,3.9368011 18.767518,3.9368011 z M 18.691659,7.1228703 C 24.972767,7.1228705 30.070477,12.220581 30.070477,18.501689 C 30.070477,24.782797 24.972767,29.880507 18.691659,29.880507 C 12.410551,29.880507 7.3128406,24.782797 7.3128406,18.501689 C 7.3128408,12.220581 12.410551,7.1228703 18.691659,7.1228703 z " - style="color:black;fill:#dcdcdc;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.00000036;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /> - <path - sodipodi:nodetypes="ccccc" - id="path4438" - d="M 39.671617,42.434136 C 39.192945,40.160949 41.068947,37.622714 43.25567,37.645761 C 43.25567,37.645761 32.495303,28.38765 32.495303,28.38765 C 29.550512,28.330944 28.225801,30.660266 28.718489,32.987572 L 39.671617,42.434136 z " - style="color:black;fill:url(#linearGradient3056);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /> - <path - transform="matrix(1.245743,0,0,1.245743,-3.260733,-5.320587)" - d="M 28.549437 18.920233 A 11.048544 11.048544 0 1 1 6.4523487,18.920233 A 11.048544 11.048544 0 1 1 28.549437 18.920233 z" - sodipodi:ry="11.048544" - sodipodi:rx="11.048544" - sodipodi:cy="18.920233" - sodipodi:cx="17.500893" - id="path4450" - style="color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:url(#linearGradient3040);stroke-width:0.8027336;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" - sodipodi:type="arc" /> - <path - sodipodi:type="arc" - style="color:black;fill:url(#radialGradient3042);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" - id="path4485" - sodipodi:cx="24.130018" - sodipodi:cy="37.967922" - sodipodi:rx="16.528622" - sodipodi:ry="3.9332814" - d="M 40.65864 37.967922 A 16.528622 3.9332814 0 1 1 7.6013966,37.967922 A 16.528622 3.9332814 0 1 1 40.65864 37.967922 z" - transform="matrix(0.497764,0,0,0.609621,9.138139,16.47574)" /> - <rect - transform="matrix(0.752986,0.658037,-0.648902,0.760872,0,0)" - ry="1.8879365" - rx="2.1366615" - y="0.67746985" - x="41.054398" - height="4.4404783" - width="19.048445" - id="rect4495" - style="opacity:0.43315507;color:black;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:white;stroke-width:1.00003123;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /> - <path - transform="matrix(1.398614,0,0,1.398614,-6.059725,-7.442512)" - d="M 25.897786 18.478292 A 8.3085051 8.3085051 0 1 1 9.280776,18.478292 A 8.3085051 8.3085051 0 1 1 25.897786 18.478292 z" - sodipodi:ry="8.3085051" - sodipodi:rx="8.3085051" - sodipodi:cy="18.478292" - sodipodi:cx="17.589281" - id="path4452" - style="color:black;fill:url(#radialGradient3044);fill-opacity:1;fill-rule:evenodd;stroke:#ce5c00;stroke-width:0.71499395;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dashoffset:0;stroke-opacity:1;visibility:visible" - sodipodi:type="arc" /> - <path - style="fill:#272c2e;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.98407042px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="M 27.166932,14.788887 C 25.733227,13.44292 20.883226,16.995107 23.033784,19.014059 C 25.184342,21.033011 28.600636,16.134854 27.166932,14.788887 z " - id="path2116" - sodipodi:nodetypes="css" /> - <path - style="fill:#272c2e;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.92405277px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="M 23.925869,25.433801 C 24.573186,26.022493 28.163554,24.011307 27.442852,22.036782 C 26.722156,20.062255 21.98392,23.667724 23.925869,25.433801 z " - id="path2118" - sodipodi:nodetypes="css" /> - <path - style="fill:#272c2e;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.98604864px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="M 21.003845,9.7167316 C 22.487885,11.022282 20.43569,17.078901 18.209632,15.120575 C 15.983573,13.162251 19.519806,8.4111821 21.003845,9.7167316 z " - id="path3032" - sodipodi:nodetypes="css" /> - <path - style="fill:#272c2e;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:0.92799336px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="M 11.656901,15.199887 C 11.023082,14.593518 12.003308,10.096465 13.832909,10.488128 C 15.66251,10.879786 13.558353,17.018991 11.656901,15.199887 z " - id="path3034" - sodipodi:nodetypes="css" /> - <path - style="fill:#272c2e;fill-opacity:1;fill-rule:evenodd;stroke:black;stroke-width:1.03811264px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - d="M 10.974025,18.60242 C 8.430812,22.619158 17.228659,29.979463 20.571676,26.631844 C 21.35606,25.846381 20.807635,25.293693 20.607132,23.247952 C 20.388463,21.016882 21.240785,20.040808 18.58725,19.186273 C 17.241764,16.695215 16.389441,17.671288 14.208696,17.895002 C 12.13379,18.10786 11.570746,17.659961 10.974025,18.60242 z " - id="path2097" - sodipodi:nodetypes="csscss" /> - <path - id="path4462" - d="M 18.321528,8.2531398 C 13.113938,8.2531398 8.8969811,12.470097 8.8969811,17.677687 C 8.8969811,19.181662 9.3172883,20.56546 9.944153,21.82759 C 11.196533,22.289203 12.52691,22.603273 13.93892,22.603273 C 20.109875,22.603273 25.038202,17.741636 25.419026,11.666144 C 23.688062,9.6206128 21.208987,8.2531398 18.321528,8.2531398 z " - style="opacity:0.6011236;color:black;fill:url(#radialGradient3049);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;marker:none;marker-start:none;marker-mid:none;marker-end:none;stroke-miterlimit:10;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible" /> - </g> -</svg> diff --git a/src/tracker-needle/org.freedesktop.Tracker.Needle.gschema.xml.in b/src/tracker-needle/org.freedesktop.Tracker.Needle.gschema.xml.in deleted file mode 100644 index d22b30423..000000000 --- a/src/tracker-needle/org.freedesktop.Tracker.Needle.gschema.xml.in +++ /dev/null @@ -1,19 +0,0 @@ -<?xml version="1.0" encoding="utf-8"?> -<!-- - Author: Kunaal Jain <kunaalus@gmail.com> ---> - -<schemalist> - <schema id="org.freedesktop.Tracker.Needle" path="/org/freedesktop/tracker/needle/" gettext-domain="tracker"> - <key name="default-view" type="i"> - <range min="0" max="2"/> - <default>1</default> - <_summary>Default View</_summary> - <_description> - When 0, default view of tracker-needle will be Icons view. - When 1, default view of tracker-needle will be Categories view. - When 2, default view of tracker-needle will be Files view. - </_description> - </key> - </schema> -</schemalist> diff --git a/src/tracker-needle/tracker-history.vala b/src/tracker-needle/tracker-history.vala deleted file mode 100644 index 888133208..000000000 --- a/src/tracker-needle/tracker-history.vala +++ /dev/null @@ -1,93 +0,0 @@ -// -// Copyright 2010, Martyn Russell <martyn@lanedo.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. -// - -public class Tracker.History { - private KeyFile data; - private string filename; - private string[] history; - - public History () { - debug ("Loading history"); - - data = new KeyFile (); - filename = Path.build_filename (Environment.get_user_data_dir (), "tracker", "tracker-needle.txt", null); - - try { - data.load_from_file (filename, KeyFileFlags.KEEP_COMMENTS | KeyFileFlags.KEEP_TRANSLATIONS); - } catch (KeyFileError e1) { - warning ("Could not load history from file:'%s': %s", filename, e1.message); - return; - } catch (FileError e2) { - if (e2.code == 4) - message ("Creating new history file:'%s'", filename); - else - warning ("Could not load history from file:'%s': %s", filename, e2.message); - return; - } - - if (data.has_group ("History") == false) { - debug (" No history found"); - return; - } - - try { - history = data.get_string_list ("History", "criteria"); - } catch (KeyFileError e1) { - warning ("Could not load history from file:'%s': %s", filename, e1.message); - return; - } - - debug (" Found %d previous search histories", history.length); - - debug (" Done"); - } - - ~History () { - debug ("Saving history"); - - data.set_string_list ("History", "criteria", history); - - try { - string output = data.to_data (); - - FileUtils.set_contents (filename, output, -1); - } catch (GLib.FileError e1) { - warning ("Could not save history to file:'%s': %s", filename, e1.message); - } - - debug (" Done"); - } - - public void add (string criteria) - requires (criteria != null && criteria.length > 0) { - // Don't add the same item more than once - foreach (string check in history) { - if (check == criteria) { - return; - } - } - - history += criteria; - } - - public string[] get () { - return history; - } - -} diff --git a/src/tracker-needle/tracker-needle.appdata.xml b/src/tracker-needle/tracker-needle.appdata.xml deleted file mode 100644 index 58cb2d791..000000000 --- a/src/tracker-needle/tracker-needle.appdata.xml +++ /dev/null @@ -1,24 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright 2014 Martyn Russell <martyn@lanedo.com> --> -<application> - <id type="desktop">tracker-needle.desktop</id> - <metadata_license>CC0-1.0</metadata_license> - <project_license>GPL-2.0+</project_license> - <name>Desktop Search</name> - <summary>Find what you're looking for on this computer</summary> - <description> - <p>Find what you're looking for on this computer by name or - content.</p> - <p>The Desktop Search application is a show case and great - application for searching for your content. You can perform powerful - queries using globbing, AND/OR key words to conjugate hits and - snippets are shown in the resulting hits.</p> - <p>This is the equivalent to Spotlight on Mac, for GNOME.</p> - </description> - <screenshots> - <screenshot type="default" width="707" height="612">https://wiki.gnome.org/Projects/Tracker?action=AttachFile&do=get&target=tracker-needle.png</screenshot> - </screenshots> - <url type="homepage">https://wiki.gnome.org/Projects/Tracker</url> - <updatecontact>tracker-list@gnome.org</updatecontact> - <project_group>GNOME</project_group> -</application> diff --git a/src/tracker-needle/tracker-needle.desktop.in.in b/src/tracker-needle/tracker-needle.desktop.in.in deleted file mode 100644 index d0b31d739..000000000 --- a/src/tracker-needle/tracker-needle.desktop.in.in +++ /dev/null @@ -1,14 +0,0 @@ -[Desktop Entry] -_Name=Desktop Search -_Comment=Find what you’re looking for on this computer by name or content using Tracker -Exec=tracker-needle -Icon=system-search -Terminal=false -Type=Application -Categories=GTK;Utility; -StartupNotify=true -X-GNOME-Bugzilla-Bugzilla=GNOME -X-GNOME-Bugzilla-Product=tracker -X-GNOME-Bugzilla-Component=Tracker Needle -X-GNOME-Bugzilla-Version=@VERSION@ - diff --git a/src/tracker-needle/tracker-needle.ui b/src/tracker-needle/tracker-needle.ui deleted file mode 100644 index 05b68d1ff..000000000 --- a/src/tracker-needle/tracker-needle.ui +++ /dev/null @@ -1,469 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<interface> - <!-- interface-requires gtk+ 3.0 --> - <object class="GtkListStore" id="liststore_search"> - <columns> - <!-- column-name text --> - <column type="gchararray"/> - </columns> - </object> - <object class="GtkWindow" id="window_needle"> - <property name="can_focus">False</property> - <property name="title" translatable="yes">Desktop Search</property> - <property name="default_width">720</property> - <property name="default_height">480</property> - <property name="icon_name">system-search</property> - <child> - <object class="GtkVBox" id="vbox_main"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkToolbar" id="toolbar_main"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkRadioToolButton" id="toolbutton_view_categories"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Display results by category, for example, Music, Videos, Applications, etc. This includes searching the contents of files where applicable.</property> - <property name="use_action_appearance">False</property> - <property name="is_important">True</property> - <property name="use_underline">True</property> - <property name="icon_name">help-faq</property> - <property name="active">True</property> - <property name="group">toolbutton_view_icons</property> - </object> - <packing> - <property name="expand">False</property> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <object class="GtkRadioToolButton" id="toolbutton_view_filelist"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Display results by files found in a list</property> - <property name="use_action_appearance">False</property> - <property name="is_important">True</property> - <property name="use_underline">True</property> - <property name="icon_name">document-open</property> - <property name="active">True</property> - <property name="group">toolbutton_view_icons</property> - </object> - <packing> - <property name="expand">False</property> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <object class="GtkRadioToolButton" id="toolbutton_view_icons"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Display found images</property> - <property name="use_action_appearance">False</property> - <property name="is_important">True</property> - <property name="use_underline">True</property> - <property name="icon_name">emblem-photos</property> - <property name="active">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <object class="GtkSeparatorToolItem" id="separator_secondary"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="expand">False</property> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <object class="GtkRadioToolButton" id="toolbutton_find_in_contents"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Find search criteria inside files</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="stock_id">gtk-find</property> - <property name="active">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <object class="GtkRadioToolButton" id="toolbutton_find_in_titles"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Find search criteria in file titles</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="stock_id">gtk-bold</property> - <property name="group">toolbutton_find_in_contents</property> - </object> - <packing> - <property name="expand">False</property> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <object class="GtkRadioToolButton" id="toolbutton_find_in_tags"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Find search criteria in file tags only (separated by comma)</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="stock_id">gtk-index</property> - <property name="group">toolbutton_find_in_contents</property> - </object> - <packing> - <property name="expand">False</property> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <object class="GtkRadioToolButton" id="toolbutton_find_in_all"> - <property name="can_focus">False</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="stock_id">gtk-select-all</property> - <property name="active">True</property> - <property name="group">toolbutton_find_in_titles</property> - </object> - <packing> - <property name="expand">False</property> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <object class="GtkSeparatorToolItem" id="<separator>"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="expand">False</property> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <object class="GtkToolItem" id="toolitem_search_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="use_action_appearance">False</property> - <property name="is_important">True</property> - <child> - <object class="GtkLabel" id="label_search"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">_Search:</property> - <property name="use_underline">True</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <object class="GtkToolItem" id="toolitem_search_entry"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="use_action_appearance">False</property> - <property name="is_important">True</property> - <child> - <object class="GtkAlignment" id="alignment1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="yscale">0</property> - <property name="left_padding">6</property> - <property name="right_padding">6</property> - <child> - <object class="GtkComboBox" id="combobox_search"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="has_focus">True</property> - <property name="model">liststore_search</property> - <property name="has_entry">True</property> - <property name="entry_text_column">0</property> - <child internal-child="entry"> - <object class="GtkEntry" id="combobox-entry"> - <property name="can_focus">True</property> - <property name="has_focus">True</property> - </object> - </child> - </object> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <object class="GtkToolItem" id="toolcustom_spinner"> - <property name="can_focus">False</property> - <property name="border_width">8</property> - <property name="use_action_appearance">False</property> - </object> - <packing> - <property name="expand">False</property> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <object class="GtkSeparatorToolItem" id="<separator>1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="expand">False</property> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <object class="GtkToggleToolButton" id="toolbutton_show_tags"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Show tagging panel which allows editing tags of selected results</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="icon_name">emblem-favorite</property> - </object> - <packing> - <property name="expand">False</property> - <property name="homogeneous">True</property> - </packing> - </child> - <child> - <object class="GtkToolButton" id="toolbutton_show_stats"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">Show statistics about the data stored</property> - <property name="use_action_appearance">False</property> - <property name="use_underline">True</property> - <property name="stock_id">gtk-info</property> - </object> - <packing> - <property name="expand">False</property> - <property name="homogeneous">True</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkInfoBar" id="info_bar"> - <property name="visible">False</property> - <child internal-child="content_area"> - <object class="GtkBox" id="info_bar_content_area"> - <child> - <object class="GtkLabel" id="info_bar_label"> - <property name="visible">True</property> - <property name="label" translatable="yes"></property> - <property name="wrap">True</property> - </object> - </child> - </object> - </child> - <child internal-child="action_area"> - <object class="GtkBox" id="info_bar_action_area"> - <child> - <object class="GtkButton" id="info_bar_button"> - <property name="label">gtk-close</property> - <property name="visible">True</property> - <property name="use_underline">True</property> - <property name="use_stock">True</property> - </object> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkHPaned" id="hpaned"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="position">500</property> - <child> - <object class="GtkHBox" id="hbox_view"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <placeholder/> - </child> - </object> - <packing> - <property name="resize">True</property> - <property name="shrink">False</property> - </packing> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - </object> - </child> - </object> - <object class="GtkWindow" id="window_tags"> - <property name="can_focus">False</property> - <child> - <object class="GtkVBox" id="vbox_tags"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">2</property> - <child> - <object class="GtkLabel" id="label_tag"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xalign">0</property> - <property name="label" translatable="yes">_Set the tags you want to associate with the %d selected items:</property> - <property name="use_underline">True</property> - <property name="justify">fill</property> - <property name="wrap">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkHBox" id="hbox1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkEntry" id="entry_tag"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="invisible_char">•</property> - <property name="activates_default">True</property> - <property name="width_chars">5</property> - <property name="invisible_char_set">True</property> - <property name="primary_icon_activatable">False</property> - <property name="secondary_icon_activatable">False</property> - <signal name="activate" handler="tracker_tags_view_entry_tag_activate_cb" swapped="no"/> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkHBox" id="hbox2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <child> - <object class="GtkButton" id="button_add"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="can_focus">True</property> - <property name="can_default">True</property> - <property name="has_default">True</property> - <property name="receives_default">True</property> - <property name="tooltip_text" translatable="yes">Add tag</property> - <property name="use_action_appearance">False</property> - <property name="relief">none</property> - <child> - <object class="GtkImage" id="image1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-add</property> - </object> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_remove"> - <property name="visible">True</property> - <property name="sensitive">False</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_text" translatable="yes">Remove selected tag</property> - <property name="use_action_appearance">False</property> - <property name="relief">none</property> - <child> - <object class="GtkImage" id="image2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-remove</property> - </object> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkScrolledWindow" id="scrolledwindow_tags"> - <property name="width_request">200</property> - <property name="height_request">300</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="hscrollbar_policy">never</property> - <property name="shadow_type">in</property> - <child> - <object class="GtkTreeView" id="treeview_tags"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="headers_visible">False</property> - <property name="enable_search">False</property> - <child internal-child="selection"> - <object class="GtkTreeSelection" id="treeview_tags_selection"/> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - </object> - </child> - </object> -</interface> diff --git a/src/tracker-needle/tracker-needle.vala b/src/tracker-needle/tracker-needle.vala deleted file mode 100644 index 4abf8d25f..000000000 --- a/src/tracker-needle/tracker-needle.vala +++ /dev/null @@ -1,867 +0,0 @@ -// -// Copyright 2010, Martyn Russell <martyn@lanedo.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. -// - -using Gtk; -using Atk; - -[CCode (cname = "TRACKER_UI_DIR")] -extern static const string UIDIR; - -[CCode (cname = "SRCDIR")] -extern static const string SRCDIR; - -public class Tracker.Needle { - private GLib.Settings settings_needle = null; - private const string UI_FILE = "tracker-needle.ui"; - private History history; - private Gtk.Window window; - private ToggleToolButton view_categories; - private ToggleToolButton view_filelist; - private ToggleToolButton view_icons; - private SeparatorToolItem separator_secondary; - private ToggleToolButton find_in_contents; - private ToggleToolButton find_in_titles; - private ToggleToolButton find_in_tags; - private ToggleToolButton find_in_all; - private ToolItem search_entry; - private ComboBox search_list; - private Entry search; - private Spinner spinner; - private ToolItem spinner_shell; - private ToggleToolButton show_tags; - private ToolButton show_stats; - private Box view; - private Tracker.View sw_noresults; - private Tracker.View sw_categories; - private Tracker.View sw_filelist; - private Tracker.View sw_icons; - private InfoBar info_bar; - private Label info_bar_label; - private TrackerTagsView tags_view; - private uint last_search_id = 0; - private int size_small = 0; - private int size_medium = 0; - private int size_big = 0; - private uint limit = 500; - private int default_view = 1; - static bool current_find_in_filelist = true; - static bool current_find_in_icons = true; - private Widget current_view; - - private ResultStore categories_model; - private ResultStore files_model; - private ResultStore files_in_tags_model; - private ResultStore files_in_title_model; - private ResultStore images_model; - private ResultStore images_in_title_model; - - private void result_overflow () { - string str = "%s\n<small>%s</small>".printf (_("Search criteria was too generic"), - _("Only the first 500 items will be displayed")); - show_info_message (str, MessageType.INFO); - } - - private void create_models () { - // Categories model - categories_model = new ResultStore (6); - categories_model.limit = limit; - categories_model.result_overflow.connect (result_overflow); - categories_model.add_query (Tracker.Query.Type.APPLICATIONS, - Tracker.Query.Match.FTS, - "?urn", - "tracker:coalesce(nfo:softwareCmdLine(?urn), ?urn)", - "tracker:coalesce(nie:title(?urn), nfo:fileName(?urn))", - "nie:comment(?urn)", - "\"\"", - "\"\""); - - categories_model.add_query (Tracker.Query.Type.IMAGES, - Tracker.Query.Match.FTS, - "?urn", - "nie:url(?urn)", - "tracker:coalesce(nie:title(?urn), nfo:fileName(?urn))", - "fn:string-join((nfo:height(?urn), nfo:width(?urn)), \" x \")", - "nfo:fileSize(?urn)", - "nie:url(?urn)"); - categories_model.add_query (Tracker.Query.Type.MUSIC, - Tracker.Query.Match.FTS_INDIRECT, - "?urn", - "nie:url(?urn)", - "tracker:coalesce(nie:title(?urn), nfo:fileName(?urn))", - "fn:string-join((?performer, ?album), \" - \")", - "nfo:duration(?urn)", - "nie:url(?urn)"); - categories_model.add_query (Tracker.Query.Type.VIDEOS, - Tracker.Query.Match.FTS, - "?urn", - "nie:url(?urn)", - "tracker:coalesce(fts:snippet(?urn),nie:title(?urn), nfo:fileName(?urn))", - "\"\"", - "nfo:duration(?urn)", - "nie:url(?urn)"); - categories_model.add_query (Tracker.Query.Type.DOCUMENTS, - Tracker.Query.Match.FTS_INDIRECT, - "?urn", - "nie:url(?urn)", - "tracker:coalesce(nie:title(?urn), nfo:fileName(?urn))", - "tracker:coalesce(fts:snippet(?urn),nco:fullname(?creator), nco:fullname(?publisher))", - "nfo:pageCount(?urn)", - "nie:url(?urn)"); - categories_model.add_query (Tracker.Query.Type.MAIL, - Tracker.Query.Match.FTS, - "?urn", - "nie:url(?urn)", - "nmo:messageSubject(?urn)", - "tracker:coalesce(fts:snippet(?urn),nco:fullname(?sender), nco:nickname(?sender), nco:emailAddress(?sender))", - "nmo:receivedDate(?urn)", - "fn:concat(\"To: \", tracker:coalesce(nco:fullname(?to), nco:nickname(?to), nco:emailAddress(?to)))"); - categories_model.add_query (Tracker.Query.Type.FOLDERS, - Tracker.Query.Match.FTS, - "?urn", - "nie:url(?urn)", - "tracker:coalesce(fts:snippet(?urn),nie:title(?urn), nfo:fileName(?urn))", - "nie:url(?parent)", - "nfo:fileLastModified(?urn)", - "?tooltip"); - categories_model.add_query (Tracker.Query.Type.BOOKMARKS, - Tracker.Query.Match.FTS, - "?urn", - "nie:url(?bookmark)", - "nie:title(?urn)", - "nie:url(?bookmark)", - "nie:contentLastModified(?urn)", - "nie:url(?bookmark)"); - - // Files model - files_model = new ResultStore (7); - files_model.limit = limit; - files_model.result_overflow.connect (result_overflow); - files_model.add_query (Tracker.Query.Type.ALL, - Tracker.Query.Match.FTS, - "?urn", - "nie:url(?urn)", - "tracker:coalesce(nie:title(?urn), nfo:fileName(?urn))", - "nie:url(?urn)", - "nfo:fileSize(?urn)", - "nfo:fileLastModified(?urn)", - "nie:url(?urn)"); - - files_in_title_model = new ResultStore (7); - files_in_title_model.limit = limit; - files_in_title_model.result_overflow.connect (result_overflow); - files_in_title_model.add_query (Tracker.Query.Type.ALL, - Tracker.Query.Match.TITLES, - "?urn", - "nie:url(?urn)", - "tracker:coalesce(nie:title(?urn), nfo:fileName(?urn))", - "nie:url(?urn)", - "nfo:fileSize(?urn)", - "nfo:fileLastModified(?urn)", - "nie:url(?urn)"); - - files_in_tags_model = new ResultStore(7); - files_in_tags_model.limit = limit; - files_in_tags_model.result_overflow.connect (result_overflow); - files_in_tags_model.add_query (Tracker.Query.Type.ALL, - Tracker.Query.Match.TAGS_ONLY, - "?urn", - "nie:url(?urn)", - "tracker:coalesce(nie:title(?urn), nfo:fileName(?urn))", - "nie:url(?urn)", - "nfo:fileSize(?urn)", - "nfo:fileLastModified(?urn)", - "nie:url(?urn)"); - - // Images model - images_model = new ResultStore (6); - images_model.limit = limit; - images_model.result_overflow.connect (result_overflow); - images_model.icon_size = 128; - images_model.add_query (Tracker.Query.Type.IMAGES, - Tracker.Query.Match.NONE, - "?urn", - "nie:url(?urn)", - "tracker:coalesce(nie:title(?urn), nfo:fileName(?urn))", -// "nie:url(?urn)", - "nfo:fileSize(?urn)", - "nfo:fileLastModified(?urn)", - "nie:url(?urn)"); - - images_in_title_model = new ResultStore (6); - images_in_title_model.limit = limit; - images_in_title_model.result_overflow.connect (result_overflow); - images_in_title_model.icon_size = 128; - images_in_title_model.add_query (Tracker.Query.Type.IMAGES, - Tracker.Query.Match.TITLES, - "?urn", - "nie:url(?urn)", - "tracker:coalesce(nie:title(?urn), nfo:fileName(?urn))", - "nfo:fileSize(?urn)", - "nfo:fileLastModified(?urn)", - "nie:url(?urn)"); - } - - public Needle () { - create_models (); - history = new Tracker.History (); - - // Load Gsettings - settings_needle = new GLib.Settings ("org.freedesktop.Tracker.Needle"); - - settings_needle.changed.connect ((key) => { - debug ("tracker-needle: Key %s changed\n", key); - }); - } - - public void show () { - setup_ui (); - - window.show (); - } - - public void set_search (string[]? args) { - if (args != null) { - string text = ""; - - foreach (string s in args) { - if (text.length > 1) - text += " "; - - text += s; - } - - debug ("Setting search criteria to: '%s'\n", text); - search.set_text (text); - } - } - - private void store_state_changed (GLib.Object object, - ParamSpec p) { - ResultStore store = (ResultStore) object; - - if (store.active) { - spinner_shell.show_all (); - spinner.start (); - } else { - spinner_shell.hide (); - spinner.stop (); - } - } - - private void setup_ui () { - var builder = new Gtk.Builder (); - Button info_bar_button; - Toolbar toolbar; - Paned paned; - - try { - //try load from source tree first. - builder.add_from_file (SRCDIR + UI_FILE); - } catch (GLib.Error e) { - //now the install location - try { - builder.add_from_file (UIDIR + UI_FILE); - } catch (GLib.Error e) { - var msg = new MessageDialog (null, - DialogFlags.MODAL, - MessageType.ERROR, - ButtonsType.CANCEL, - "Failed to load UI file, %s\n", - e.message); - msg.run (); - Gtk.main_quit(); - } - } - - Gtk.icon_size_lookup (Gtk.IconSize.MENU, out size_small, null); - Gtk.icon_size_lookup (Gtk.IconSize.DND, out size_medium, null); - Gtk.icon_size_lookup (Gtk.IconSize.DIALOG, out size_big, null); - - window = builder.get_object ("window_needle") as Gtk.Window; - window.destroy.connect (window_closed); - window.key_press_event.connect (window_key_press_event); - - toolbar = builder.get_object ("toolbar_main") as Toolbar; - toolbar.get_style_context().add_class (STYLE_CLASS_PRIMARY_TOOLBAR); - - info_bar = builder.get_object ("info_bar") as InfoBar; - info_bar_label = builder.get_object ("info_bar_label") as Label; - info_bar_button = builder.get_object ("info_bar_button") as Button; - info_bar_button.clicked.connect (info_bar_closed); - - view_filelist = builder.get_object ("toolbutton_view_filelist") as ToggleToolButton; - view_filelist.toggled.connect (view_toggled); - view_filelist.get_accessible().set_name("View File List"); - view_filelist.get_child().get_accessible().set_name("View File List RadioButton"); - - view_icons = builder.get_object ("toolbutton_view_icons") as ToggleToolButton; - view_icons.toggled.connect (view_toggled); - view_icons.get_accessible().set_name("View Icons"); - view_icons.get_child().get_accessible().set_name("View Icons RadioButton"); - - view_categories = builder.get_object ("toolbutton_view_categories") as ToggleToolButton; - view_categories.toggled.connect (view_toggled); - view_categories.get_accessible().set_name("View Categories"); - view_categories.get_child().get_accessible().set_name("View Categories RadioButton"); - - separator_secondary = builder.get_object ("separator_secondary") as SeparatorToolItem; - - find_in_contents = builder.get_object ("toolbutton_find_in_contents") as ToggleToolButton; - find_in_contents.toggled.connect (find_in_toggled); - find_in_contents.get_accessible().set_name("Find in Contents"); - find_in_contents.get_child().get_accessible().set_name("Find in Contents"); - - find_in_titles = builder.get_object ("toolbutton_find_in_titles") as ToggleToolButton; - find_in_titles.toggled.connect (find_in_toggled); - find_in_titles.get_accessible().set_name("Find in Titles"); - find_in_titles.get_child().get_accessible().set_name("Find in Titles"); - - find_in_tags = builder.get_object ("toolbutton_find_in_tags") as ToggleToolButton; - find_in_tags.toggled.connect (find_in_toggled); - find_in_tags.get_accessible().set_name("Find in Tags"); - find_in_tags.get_child().get_accessible().set_name("Find in Tags"); - - find_in_all = builder.get_object ("toolbutton_find_in_all") as ToggleToolButton; - find_in_all.toggled.connect (find_in_toggled); - find_in_all.get_accessible().set_name("Find in All"); - find_in_all.get_child().get_accessible().set_name("Find in All"); - - search_entry = builder.get_object ("toolitem_search_entry") as ToolItem; - search_entry.get_accessible().set_name("Search Entry"); - - search_list = builder.get_object ("combobox_search") as ComboBox; - search_list.get_accessible().set_name("Search List"); - - search = search_list.get_child () as Entry; - search.changed.connect (search_changed); - search.activate.connect (search_activated); - search.key_press_event.connect (search_key_press_event); - search_history_insert (history.get ()); - - spinner = new Spinner (); - spinner_shell = builder.get_object ("toolcustom_spinner") as ToolItem; - spinner_shell.add (spinner); - - show_tags = builder.get_object ("toolbutton_show_tags") as ToggleToolButton; - show_tags.clicked.connect (show_tags_clicked); - show_tags.get_accessible().set_name("Show Tags"); - show_tags.get_child().get_accessible().set_name("Show Tags"); - - show_stats = builder.get_object ("toolbutton_show_stats") as ToolButton; - show_stats.clicked.connect (show_stats_clicked); - show_stats.get_accessible().set_name("Show Stats"); - show_stats.get_child().get_accessible().set_name("Show Stats"); - - view = builder.get_object ("hbox_view") as Box; - - // Set up views - TreeView treeview; - IconView iconview; - TreeSelection treeselection; - - sw_noresults = new Tracker.View (Tracker.View.Display.NO_RESULTS, null); - view.pack_start (sw_noresults, true, true, 0); - - sw_categories = new Tracker.View (Tracker.View.Display.CATEGORIES, categories_model); - sw_categories.store.notify["active"].connect (store_state_changed); - treeview = (TreeView) sw_categories.get_child (); - treeview.row_activated.connect (view_row_activated); - treeselection = treeview.get_selection (); - treeselection.changed.connect (view_row_selected); - view.pack_start (sw_categories, true, true, 0); - - sw_filelist = new Tracker.View (Tracker.View.Display.FILE_LIST, null); - treeview = (TreeView) sw_filelist.get_child (); - treeview.row_activated.connect (view_row_activated); - treeselection = treeview.get_selection (); - treeselection.changed.connect (view_row_selected); - view.pack_start (sw_filelist, true, true, 0); - - sw_icons = new Tracker.View (Tracker.View.Display.FILE_ICONS, null); - iconview = (IconView) sw_icons.get_child (); - iconview.item_activated.connect (icon_item_activated); - iconview.selection_changed.connect (icon_view_selection_changed); - view.pack_start (sw_icons, true, true, 0); - - // Set up tags widget - paned = builder.get_object ("hpaned") as Paned; - tags_view = new TrackerTagsView (null); - tags_view.hide (); - tags_view.hide_label (); - paned.pack2 (tags_view, false, false); - - //Set up the default view - view_categories.active = false; - view_icons.active = false; - view_filelist.active = false; - - //By default we assume Categories view - default_view = settings_needle.get_int ("default-view"); - - if (default_view == 0) { - view_icons.active = true; - } else if (default_view == 2) { - view_filelist.active = true; - } else { - view_categories.active = true; - } - } - - private bool window_key_press_event (Gtk.Widget widget, Gdk.EventKey event) { - // Add Ctrl+W close window semantics - if (Gdk.ModifierType.CONTROL_MASK in event.state && Gdk.keyval_name (event.keyval) == "w") { - widget.destroy(); - } - - return false; - } - - private bool search_key_press_event (Gtk.Widget widget, Gdk.EventKey event) { - if (Gdk.keyval_name (event.keyval) == "Down" || - Gdk.keyval_name (event.keyval) == "KP_Down") { - var child = ((ScrolledWindow) current_view).get_child (); - - if (child != null) { - child.grab_focus(); - } - } - - return false; - } - - private void search_changed (Editable editable) { - if (last_search_id != 0) { - Source.remove (last_search_id); - } - - last_search_id = Timeout.add_seconds (1, search_run); - } - - private void search_activated (Entry entry) { - if (last_search_id != 0) { - Source.remove (last_search_id); - last_search_id = 0; - } - - search_run (); - } - - private void search_finished (ResultStore? store) { - // Check if we have any results, if we don't change the view - if (store == null || !store.has_results ()) { - sw_noresults.show (); - sw_icons.hide (); - sw_categories.hide (); - sw_filelist.hide (); - } - } - - private TreeIter? search_history_find_or_insert (string criteria, bool? add_to_model = false) { - if (criteria.length < 1) { - return null; - } - - ComboBox combo = search_list as ComboBox; - TreeModel model = combo.get_model (); - string criteria_folded = criteria.casefold (); - - TreeIter iter; - bool valid = model.iter_children (out iter, null); - - while (valid) { - string text; - - model.get (iter, 0, out text, -1); - - string text_folded = text.casefold (); - - if (text_folded == criteria_folded) { - return iter; - } - - valid = model.iter_next (ref iter); - } - - if (add_to_model) { - TreeIter new_iter; - - Gtk.ListStore store = (Gtk.ListStore) model; - store.prepend (out new_iter); - store.set (new_iter, 0, criteria, -1); - - history.add (criteria); - } - - return null; - } - - private void search_history_insert (string[] history) { - foreach (string criteria in history) { - search_history_find_or_insert (criteria, true); - } - } - - private bool search_run () { - last_search_id = 0; - - string str = search.get_text (); - string criteria = str.strip (); - ResultStore store = null; - - if (!show_tags.active) { - if (criteria.length < 3) { - // Allow empty search criteria for finding all - if (!view_icons.active || !find_in_all.active) { - search_finished (store); - return false; - } - } - - search_history_find_or_insert (criteria, true); - } - - // Show correct window - sw_noresults.hide (); - current_view = sw_noresults; - - if (view_icons.active) { - sw_icons.show (); - current_view = sw_icons; - - if (find_in_all.active) { - store = images_model; - } else { - store = images_in_title_model; - } - - sw_icons.store = store; - } else { - sw_icons.hide (); - } - - if (view_categories.active) { - sw_categories.show (); - current_view = sw_categories; - store = categories_model; - } else { - sw_categories.hide (); - } - - if (view_filelist.active) { - sw_filelist.show (); - current_view = sw_filelist; - - if (find_in_tags.active) { - store = files_in_tags_model; - store.search_tags = search_tags(); - debug("Tags to look for: %s", string.joinv("; ", store.search_tags.data)); - } else if (find_in_contents.active) { - store = files_model; - } else { - store = files_in_title_model; - } - - sw_filelist.store = store; - } else { - sw_filelist.hide (); - } - - if (store != null) { - // We can set tags to search by but we don't anymore - // except if user want explecitly search by tags only. - if (!find_in_tags.active) { - store.search_tags = null; - } - store.search_term = search.get_text (); - } - - return false; - } - - private void window_closed() { - // Before exiting save the current view - // By default, we assume categories view - if (view_icons.active) { - settings_needle.set_int ("default-view", 0); - } else if (view_filelist.active) { - settings_needle.set_int ("default-view", 2); - } else { - settings_needle.set_int ("default-view", 1); - } - Gtk.main_quit(); - } - - private void view_toggled () { - if (!view_icons.active && - !view_filelist.active && - !view_categories.active) { - return; - } - - if (view_categories.active || view_filelist.active) { - if (current_find_in_filelist) { - find_in_contents.active = true; - } else { - find_in_titles.active = true; - } - } else if (view_icons.active) { - if (current_find_in_icons) { - find_in_titles.active = true; - } else { - find_in_all.active = true; - } - } - - // Show no results Window when switching - sw_noresults.show (); - sw_icons.hide (); - sw_filelist.hide (); - sw_categories.hide (); - - // Show/Hide secondary widgets - separator_secondary.visible = view_filelist.active || view_icons.active; - find_in_contents.visible = view_filelist.active; - find_in_titles.visible = view_filelist.active || view_icons.active; - find_in_tags.visible = view_filelist.active; - find_in_all.visible = view_icons.active; // only show this in one view - - search_run (); - //current_view = rows; - } - - private void find_in_toggled () { - if (!find_in_contents.active && - !find_in_titles.active && - !find_in_tags.active && - !find_in_all.active) { - return; - } - - if (find_in_contents.active) { - debug ("Find in toggled to 'contents'"); - - if (show_tags.active != true) { - search_entry.sensitive = true; - } - - search_run (); - } else if (find_in_tags.active){ - debug ("Find in toggled to 'tags'"); - - search_entry.sensitive = true; - search_run(); - } else if (find_in_titles.active) { - debug ("Find in toggled to 'titles'"); - - if (show_tags.active != true) { - search_entry.sensitive = true; - } - - search_run (); - } else if (find_in_all.active) { - debug ("Find in toggled to 'all'"); - - // We hide the entry in this case, which is special - search_entry.sensitive = false; - - search_run (); - } - - if (view_filelist.active) { - current_find_in_filelist = find_in_contents.active; - } else if (view_icons.active) { - current_find_in_icons = find_in_titles.active; - } - } - - private void view_row_activated (TreeView view, TreePath path, TreeViewColumn column) { - var model = view.get_model (); - tracker_model_launch_selected (model, path, 1); - } - - private void icon_item_activated (IconView view, TreePath path) { - var model = view.get_model (); - tracker_model_launch_selected (model, path, 1); - } - - private void view_row_selected (TreeSelection selection) { - TreeIter iter; - TreeModel model = null; - debug ("Row selection changed"); - - List<TreePath> rows = selection.get_selected_rows (out model); - List<string> uris = null; - - if (rows == null) { - return; - } - - foreach (TreePath path in rows) { - if (model.get_iter (out iter, path)) { - string uri; - - model.get (iter, 1, out uri, -1); - debug ("--> %s", uri); - - if (uri != null) { - uris.prepend (uri); - } - } - } - - tags_view.set_files (uris); - } - - private void icon_view_selection_changed () { - IconView iconview; - TreeModel model = null; - debug ("Icon selection changed"); - - iconview = (IconView) sw_icons.get_child (); - model = iconview.get_model (); - List<string> uris = null; - - iconview.selected_foreach ((iconview, path) => { - TreeIter iter; - - if (model.get_iter (out iter, path)) { - string uri; - - model.get (iter, 1, out uri, -1); - debug ("--> %s", uri); - - if (uri != null) { - uris.prepend (uri); - } - } - }); - - tags_view.set_files (uris); - } - - private void show_tags_clicked () { - if (show_tags.active) { - debug ("Showing tags"); - tags_view.show (); - //search_entry.sensitive = false; - } else { - debug ("Hiding tags"); - tags_view.hide (); - //search_entry.sensitive = true; - } - - // Re-run search to filter with or without tags - // search_run (); - } - - private void show_stats_clicked () { - debug ("Showing stats dialog"); - Tracker.Stats s = new Tracker.Stats (); - s.show (); - } - - public void show_info_message (string message, - Gtk.MessageType type) { - info_bar.set_message_type (type); - info_bar_label.set_markup (message); - info_bar.show (); - } - - private void info_bar_closed (Button source) { - info_bar.hide (); - } - - private GLib.GenericArray<string> search_tags(){ - GLib.GenericArray<string> tagArray = new GLib.GenericArray<string>(); - - foreach (string tag in search.get_text ().split(",")){ - tagArray.add(tag) ; - } - - return tagArray; - } -} - -static bool print_version = false; -[CCode (array_length = false, array_null_terminated = true)] -static string[] search_criteria = null; - -const OptionEntry[] options = { - { "version", - 'V', - 0, - OptionArg.NONE, - ref print_version, - N_("Print version"), - null }, - { "", // G_OPTION_REMAINING - 0, - 0, - OptionArg.STRING_ARRAY, - ref search_criteria, - N_("[SEARCH-CRITERIA]"), - N_("[SEARCH-CRITERIA]") }, - { null } -}; - -static int main (string[] args) { - OptionContext context = new OptionContext (_("Desktop Search user interface using Tracker")); - - try { - context.set_help_enabled (true); - context.add_main_entries (options, null); - context.add_group (Gtk.get_option_group (true)); - context.parse (ref args); - } catch (Error e) { - printerr (e.message + "\n\n"); - printerr (context.get_help (true, null)); - return 1; - } - - if (print_version) { - string about = ""; - string license = ""; - - about += "Tracker " + Config.PACKAGE_VERSION + "\n"; - - license += "This program is free software and comes without any warranty.\n"; - license += "It is licensed under version 2 or later of the General Public "; - license += "License which can be viewed at:\n"; - license += "\n"; - license += " http://www.gnu.org/licenses/gpl.txt\n"; - - print ("\n" + about + "\n" + license + "\n"); - return 0; - } - - Gtk.init (ref args); - - Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.LOCALEDIR); - Intl.bind_textdomain_codeset (Config.GETTEXT_PACKAGE, "UTF-8"); - Intl.textdomain (Config.GETTEXT_PACKAGE); - - Tracker.Needle n = new Tracker.Needle (); - n.show(); - - n.set_search (search_criteria); - - Gtk.main (); - - return 0; -} diff --git a/src/tracker-needle/tracker-query.vala b/src/tracker-needle/tracker-query.vala deleted file mode 100644 index 0a03e800c..000000000 --- a/src/tracker-needle/tracker-query.vala +++ /dev/null @@ -1,410 +0,0 @@ -// -// Copyright 2010, Martyn Russell <martyn@lanedo.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. -// - -using Tracker.Sparql; - -public class Tracker.Query { - public enum Type { - ALL, - CONTACTS, - APPLICATIONS, - MUSIC, - IMAGES, - VIDEOS, - DOCUMENTS, - MAIL, - CALENDAR, - FOLDERS, - BOOKMARKS - } - - public enum Match { - NONE, - FTS, - FTS_INDIRECT, - TITLES, - TITLES_INDIRECT, - TAGS_ONLY, - TAGS_ONLY_INDIRECT - } - - private string [] match_clauses = { - // NONE (i.e. just show all) - "", - - // FTS - "{ - ?urn fts:match \"%s\" - } UNION { - ?urn nao:hasTag ?tag . - FILTER (fn:contains (fn:lower-case (nao:prefLabel(?tag)), \"%s\")) - }", - - // FTS_INDIRECT (with sub-matching) - "{ - ?match fts:match \"%s\" - } UNION { - ?match nao:hasTag ?tag . - FILTER (fn:contains (fn:lower-case (nao:prefLabel(?tag)), \"%s\")) - }", - - // TITLES - "FILTER (fn:contains (fn:lower-case (nfo:fileName(?urn)), \"%s\"))", - - // TITLES_INDIRECT (with sub-matching) - "FILTER (fn:contains (fn:lower-case (nie:title(?match)), \"%s\"))", - - // TAGS_ONLY (no fts:match, just nao:prefLabel matching, %s is filled in by get_tags_filter() - "?urn nao:hasTag ?tag . - FILTER (nao:prefLabel(?tag) IN (%s))", - - // TAGS_ONLY_INDIRECT (same as TAGS_ONLY for ?match) - "?match nao:hasTag ?tag . - FILTER (nao:prefLabel(?tag) IN (%s))" - }; - - private string [] where_clauses = { - // ALL - "WHERE { - %s . - ?urn nfo:belongsToContainer ?parent ; - tracker:available true . - }", - - // CONTACTS - "", - - // APPLICATIONS - "WHERE { - ?urn a nfo:Software . - %s - }", - - // MUSIC - "WHERE { - { - ?urn nmm:musicAlbum ?match - } UNION { - ?urn nmm:performer ?match - } UNION { - ?urn a nfo:Audio . - ?match a nfo:Audio - FILTER (?urn = ?match) - } - %s . - ?urn nmm:performer [ nmm:artistName ?performer ] ; - nmm:musicAlbum [ nie:title ?album ] ; - nie:url ?tooltip . - }", - - // IMAGES - "WHERE { - ?urn a nfo:Image ; - nie:url ?tooltip . - %s - }", - - // VIDEOS - "WHERE { - ?urn a nfo:Video ; - nie:url ?tooltip . - %s - }", - - // DOCUMENTS - "WHERE { - { - ?urn nco:creator ?match - } UNION { - ?urn nco:publisher ?match - } UNION { - ?urn a nfo:Document . - FILTER (! EXISTS { ?urn a nmo:Email } ) - ?match a nfo:Document - FILTER (?urn = ?match) - } - %s . - ?urn nie:url ?tooltip . - OPTIONAL { - ?urn nco:creator ?creator . - } - OPTIONAL { - ?urn nco:publisher ?publisher . - } - }", - - // MAIL - "WHERE { - ?urn a nmo:Email ; - nmo:from ?sender ; - nmo:to ?to . - %s - }", - - // CALENDAR - "", - - // FOLDERS - "WHERE { - ?urn a nfo:Folder ; - nie:url ?tooltip . - %s - OPTIONAL { - ?urn nfo:belongsToContainer ?parent . - } - }", - - // BOOKMARKS - "WHERE { - ?urn a nfo:Bookmark ; - nfo:bookmarks ?bookmark . - %s - }" - }; - - private string [] sort_clauses = { - // ALL - "DESC(nfo:fileLastModified(?urn)) DESC(nie:contentCreated(?urn)) ASC(nie:title(?urn))", - - // CONTACTS - "ASC(nco:fullname(?urn))", - - // APPLICATIONS - "ASC(nie:title(?urn)) ASC(nie:comment(?urn))", - - // MUSIC - "DESC(nfo:fileLastModified(?urn)) ASC(nie:title(?urn))", - - // IMAGES - "DESC(nfo:fileLastModified(?urn)) ASC(nie:title(?urn))", - - // VIDEOS - "DESC(nfo:fileLastModified(?urn)) ASC(nie:title(?urn))", - - // DOCUMENTS - "DESC(nfo:fileLastModified(?urn)) ASC(nie:title(?urn))", - - // MAIL - "DESC(nmo:receivedDate(?urn)) ASC(nmo:messageSubject(?urn))", - - // CALENDAR - "DESC(nie:contentCreated(?urn))", - - // FOLDERS - "DESC(nfo:fileLastModified(?urn)) ASC(nie:title(?urn))", - - // BOOKMARKS - "DESC(nie:contentLastModified(?urn)) ASC(nie:title(?urn))" - }; - - public string criteria { get; set; } - public uint offset { get; set; } - public uint limit { get; set; } - public string query { get; private set; } - - public GenericArray<string> tags { get; set; } - - private static Sparql.Connection connection; - - public Query () { - try { - connection = Sparql.Connection.get (); - } catch (GLib.Error e) { - warning ("Could not get Sparql connection: %s", e.message); - } - - tags = null; - } - - private string get_tags_filter () { - string filter = ""; - - if (tags != null && tags.length > 0) { - for (int i = 0; i < tags.length; i++) { - string escaped = Tracker.Sparql.escape_string (tags[i]); - - if (filter.length > 1) - filter += ", "; - - filter += "\"%s\"".printf (escaped); - } - } - - return filter; - } - - private bool check_query_and_match_type (Type query_type, Match match_type) { - if (query_type != Type.IMAGES && match_type == Match.NONE) { - critical ("You can not use a non-IMAGES query (%d) with NONE matching", query_type); - return false; - } - - if (query_type == Type.MUSIC && !(match_type == Match.FTS_INDIRECT || - match_type == Match.TITLES_INDIRECT)) { - critical ("You can not use a MUSIC query with match TITLES or FTS, INDIRECT required"); - return false; - } - - if ((query_type != Type.MUSIC && query_type != Type.DOCUMENTS) && - !(match_type == Match.NONE || - match_type == Match.FTS || - match_type == Match.TITLES || - match_type == Match.TAGS_ONLY)) { - critical ("You can not use a non-MUSIC or non-DOCUMENTS query (%d) with INDIRECT matching (%d)", query_type, match_type); - return false; - } - - return true; - } - - public async uint get_count_async (Type query_type, Match match_type, Cancellable? cancellable = null) throws IOError - requires (connection != null) { - Sparql.Cursor cursor = null; - - if (!check_query_and_match_type (query_type, match_type)) { - return 0; - } - - // If we have tags supplied, we ONLY show files from those tags - if (tags != null && tags.length > 0) { - if (match_type == Match.FTS_INDIRECT || - match_type == Match.TITLES_INDIRECT) { - match_type = Match.TAGS_ONLY_INDIRECT; - } else { - match_type = Match.TAGS_ONLY; - } - } - debug ("match_type:%d", match_type); - if (match_type != Match.NONE && - match_type != Match.TAGS_ONLY && - match_type != Match.TAGS_ONLY_INDIRECT && - (criteria == null || criteria.length < 1)) { - warning ("Criteria was NULL or an empty string no query performed"); - return 0; - } - - string match; - - if (match_type == Match.TAGS_ONLY || - match_type == Match.TAGS_ONLY_INDIRECT) { - match = match_clauses[match_type].printf (get_tags_filter ()); - } else { - string criteria_escaped = Tracker.Sparql.escape_string (criteria); - - // FTS queries take 2 arguments for tags and fts:match - if (match_type == Match.FTS || - match_type == Match.FTS_INDIRECT) { - match = match_clauses[match_type].printf (criteria_escaped, criteria_escaped); - } else { - match = match_clauses[match_type].printf (criteria_escaped); - } - } - - query = "SELECT count(?urn)"; - - if (where_clauses[query_type].length > 0) { - query += " " + where_clauses[query_type].printf (match); - } - - if (sort_clauses[query_type].length > 0) { - query += " ORDER BY " + sort_clauses[query_type]; - } - - try { - cursor = yield connection.query_async (query, null); - yield cursor.next_async (); - } catch (GLib.Error e) { - warning ("Could not run Sparql count query: %s", e.message); - } - - return (uint) cursor.get_integer (0); - } - - public async Sparql.Cursor? perform_async (Type query_type, Match match_type, string[] ?args, Cancellable? cancellable = null) throws IOError - requires (connection != null) { - Sparql.Cursor cursor = null; - - if (!check_query_and_match_type (query_type, match_type)) { - return null; - } - - // If we have tags supplied, we ONLY show files from those tags - if (tags != null && tags.length > 0) { - if (match_type == Match.FTS_INDIRECT || - match_type == Match.TITLES_INDIRECT) { - match_type = Match.TAGS_ONLY_INDIRECT; - } else { - match_type = Match.TAGS_ONLY; - } - } - - if (match_type != Match.NONE && - match_type != Match.TAGS_ONLY && - match_type != Match.TAGS_ONLY_INDIRECT && - (criteria == null || criteria.length < 1)) { - warning ("Criteria was NULL or an empty string no query performed"); - return null; - } - - if (limit < 1) { - warning ("Limit was < 1, no query performed"); - return null; - } - - string match; - - if (match_type == Match.TAGS_ONLY || - match_type == Match.TAGS_ONLY_INDIRECT) { - match = match_clauses[match_type].printf (get_tags_filter ()); - } else { - string criteria_escaped = Tracker.Sparql.escape_string (criteria); - - // FTS queries take 2 arguments for tags and fts:match - if (match_type == Match.FTS || - match_type == Match.FTS_INDIRECT) { - match = match_clauses[match_type].printf (criteria_escaped, criteria_escaped); - } else { - match = match_clauses[match_type].printf (criteria_escaped); - } - } - - query = "SELECT " + string.joinv (" ", args); - if (where_clauses[query_type].length > 0) { - query += " " + where_clauses[query_type].printf (match); - } - - if (sort_clauses[query_type].length > 0) { - query += " ORDER BY " + sort_clauses[query_type]; - } - - query += " OFFSET %u LIMIT %u".printf (offset, limit); - - debug ("Running query: '%s'", query); - - try { - cursor = yield connection.query_async (query, null); - } catch (GLib.Error e) { - warning ("Could not run Sparql query: %s", e.message); - } - - debug ("Done"); - - return cursor; - } -} diff --git a/src/tracker-needle/tracker-result-store.vala b/src/tracker-needle/tracker-result-store.vala deleted file mode 100644 index 32192b3c5..000000000 --- a/src/tracker-needle/tracker-result-store.vala +++ /dev/null @@ -1,890 +0,0 @@ -// -// Copyright 2010, Carlos Garnacho <carlos@lanedo.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. -// - -using Gtk; - -public class Tracker.ResultStore : Gtk.TreeModel, GLib.Object { - private GLib.Cancellable cancellable; - - private struct ResultNode { - string [] values; - Gdk.Pixbuf pixbuf; - } - - private class CategoryNode { - public Tracker.Query.Type type; - public QueryData *query; - public ResultNode [] results; - public Gdk.Pixbuf pixbuf; - public int count; - } - - private struct QueryData { - Tracker.Query.Type type; - Tracker.Query.Match match; - string [] args; - } - - private QueryData [] queries; - private GenericArray<CategoryNode> categories; - - private class Operation : GLib.Object { - public CategoryNode node; - public int offset; - } - - private GenericArray<Operation> running_operations; - private GenericArray<Operation> delayed_operations; - - private int n_extra_columns = 2; // Pixbuf and query type - private int n_columns; - private int timestamp; - - public int icon_size { - get; - set; - } - - public uint limit { - get; - set; - } - - public signal void result_overflow (); - - private Operation? find_operation (GenericArray<Operation> array, CategoryNode node, int offset) { - Operation op; - int i; - - for (i = 0; i < array.length; i++) { - op = array[i]; - - if (op.node == node && - op.offset == offset) { - return op; - } - } - - return null; - } - - async void load_operation (Operation op, Cancellable? cancellable) { - Tracker.Query query; - Sparql.Cursor cursor = null; - int i; - - try { - cancellable.set_error_if_cancelled (); - - query = new Tracker.Query (); - query.criteria = _search_term; - query.tags = search_tags; - query.limit = limit; - query.offset = op.offset; - - cursor = yield query.perform_async (op.node.query.type, op.node.query.match, op.node.query.args, cancellable); - - cancellable.set_error_if_cancelled (); - - if (cursor != null) { - for (i = op.offset; i < op.offset + 100; i++) { - ResultNode *result; - TreeIter iter; - TreePath path; - bool b = false; - int j; - - try { - b = yield cursor.next_async (cancellable); - } catch (GLib.Error ge) { - if (!cancellable.is_cancelled ()) { - warning ("Could not fetch row: %s\n", ge.message); - } - } - - if (!b) { - break; - } - - result = &op.node.results[i]; - - for (j = 0; j < n_columns; j++) { - if (j == n_columns - 1) { - // FIXME: Set markup for tooltip column in a nicer way - string s = cursor.get_string (j); - - if (s != null) - result.values[j] = Markup.escape_text (s); - else - result.values[j] = null; - } else { - result.values[j] = cursor.get_string (j); - } - } - - // Emit row-changed - iter = TreeIter (); - iter.stamp = this.timestamp; - iter.user_data = op.node; - iter.user_data2 = result; - iter.user_data3 = i.to_pointer (); - - path = this.get_path (iter); - row_changed (path, iter); - } - } - - running_operations.remove (op); - } catch (GLib.IOError ie) { - if (!cancellable.is_cancelled ()) { - warning ("Could not load items: %s\n", ie.message); - } - return; - } - - if (delayed_operations.length > 0) { - Operation next_to_start; - - // Take last added task from delayed queue and start it - next_to_start = delayed_operations[delayed_operations.length - 1]; - delayed_operations.remove (next_to_start); - running_operations.add (next_to_start); - - load_operation.begin (next_to_start, cancellable); - } else if (running_operations.length == 0) { - // finished processing - this.active = false; - } - } - - private void add_operation (CategoryNode cat, int offset) { - Operation op = new Operation (); - Operation old; - - op.node = cat; - op.offset = offset; - - if (find_operation (running_operations, cat, offset) != null) { - // Operation already running - return; - } - - // If the task is delayed, it will be either pushed - // to the running queue, or reordered to be processed - // next in the delayed queue. - old = find_operation (delayed_operations, cat, offset); - - if (old != null) { - delayed_operations.remove (old); - } - - this.active = true; - - // Running queue is limited to 2 simultaneous queries, - // anything after that will be added to a different queue. - if (running_operations.length < 2) { - running_operations.add (op); - - // Start the operation right away - load_operation.begin (op, cancellable); - } else { - // Reorder the operation if it was already there, else just add - delayed_operations.add (op); - } - } - - async void load_category (QueryData *query_data, Cancellable? cancellable) { - uint count = 0; - - try { - cancellable.set_error_if_cancelled (); - - Tracker.Query query = new Tracker.Query (); - query.criteria = _search_term; - query.tags = search_tags; - - count = yield query.get_count_async (query_data.type, query_data.match, cancellable); - cancellable.set_error_if_cancelled (); - } catch (GLib.IOError ie) { - if (!cancellable.is_cancelled ()) { - warning ("Could not get count: %s\n", ie.message); - } - return; - } - - if (count != 0) { - CategoryNode cat; - ResultNode *res; - int i; - - if (count > limit) { - result_overflow (); - count = limit; - } - - Gtk.TreeIter iter; - Gtk.TreePath path; - - cat = new CategoryNode (); - cat.type = query_data.type; - cat.query = query_data; - cat.results.resize ((int) count); - categories.add (cat); - - iter = TreeIter (); - iter.stamp = this.timestamp; - iter.user_data = cat; - - if (queries.length > 1) { - path = this.get_path (iter); - row_inserted (path, iter); - } - - for (i = 0; i < count; i++) { - res = &cat.results[i]; - res.values = new string[n_columns]; - - iter.user_data2 = res; - iter.user_data3 = i.to_pointer (); - path = this.get_path (iter); - - cat.count++; - row_inserted (path, iter); - } - - if (queries.length > 1) { - iter.user_data2 = null; - iter.user_data3 = null; - path = get_path (iter); - - row_changed (path, iter); - } - } - - if (running_operations.length == 0) { - this.active = false; - } - } - - private void clear_results () { - int j; - - while (categories.length > 0) { - CategoryNode cat = categories[0]; - TreeIter iter; - TreePath path; - - if (cat.results.length == 0) { - continue; - } - - iter = TreeIter (); - iter.stamp = this.timestamp; - iter.user_data = cat; - - for (j = cat.count - 1; j >= 0; j--) { - iter.user_data2 = &cat.results[j]; - iter.user_data3 = j.to_pointer (); - path = get_path (iter); - - row_deleted (path); - cat.count--; - } - - if (queries.length > 1) { - iter.user_data2 = null; - iter.user_data3 = null; - path = get_path (iter); - - row_deleted (path); - } - - categories.remove (cat); - } - } - - private string _search_term; - public string search_term { - get { - return _search_term; - } - set { - int i; - - cancel_search (); - _search_term = value; - - cancellable = new Cancellable (); - - this.active = true; - - categories = new GenericArray<CategoryNode> (); - running_operations = new GenericArray<Operation?> (); - delayed_operations = new GenericArray<Operation?> (); - this.timestamp++; - - for (i = 0; i < queries.length; i++) { - load_category.begin (&queries[i], cancellable); - } - } - } - - public GenericArray<string> search_tags { get; set; } - - public bool active { - get; - private set; - } - - private int find_nth_category_index (CategoryNode? node, int n) { - int i; - - if (node == null) { - // Count from the first one - return n; - } - - for (i = 0; i < categories.length; i++) { - CategoryNode cat; - - cat = categories[i]; - - if (cat == node) { - return i + n; - } - } - - return -1; - } - - private int filled_categories_count () { - int i, n = 0; - - for (i = 0; i < categories.length; i++) { - CategoryNode cat; - - cat = categories[i]; - - if (cat.count > 0) { - n++; - } - } - - return n; - } - - public GLib.Type get_column_type (int index_) { - if (index_ == n_columns) { - return typeof (Gdk.Pixbuf); - } else if (index_ == n_columns + 1) { - return typeof (Tracker.Query.Type); - } else { - return typeof (string); - } - } - - public Gtk.TreeModelFlags get_flags () { - Gtk.TreeModelFlags flags; - - flags = Gtk.TreeModelFlags.ITERS_PERSIST; - - if (queries.length == 1) { - flags |= Gtk.TreeModelFlags.LIST_ONLY; - } - - return flags; - } - - public bool get_iter (out Gtk.TreeIter iter, Gtk.TreePath path) { - unowned int [] indices = path.get_indices (); - CategoryNode cat; - int i = 0; - - iter = TreeIter (); - - if (queries.length > 1) { - if (indices[i] >= categories.length) { - iter.stamp = 0; - return false; - } - - cat = categories[indices[i]]; - i++; - } else { - if (categories.length == 0) { - iter.stamp = 0; - return false; - } - - cat = categories[0]; - } - - iter.stamp = this.timestamp; - iter.user_data = cat; - - if (path.get_depth () == i + 1) { - // it's a result - if (indices[i] >= cat.count) { - iter.stamp = 0; - return false; - } - - iter.user_data2 = &cat.results[indices[i]]; - iter.user_data3 = indices[i].to_pointer (); - } - - return true; - } - - public int get_n_columns () { - return n_columns + n_extra_columns; - } - -#if VALA_0_14 - public Gtk.TreePath? get_path (Gtk.TreeIter iter) { -#else - public Gtk.TreePath get_path (Gtk.TreeIter iter) { -#endif - TreePath path = new TreePath (); - CategoryNode cat; - int i; - - if (queries.length > 1) { - for (i = 0; i < categories.length; i++) { - cat = categories[i]; - - if (cat == iter.user_data) { - path.append_index (i); - break; - } - } - } - - if (iter.user_data2 != null) { - path.append_index ((int) (long) iter.user_data3); - } - - return path; - } - - private async void fetch_thumbnail (TreeIter iter) { - GLib.File file; - GLib.FileInfo info; - ResultNode *result; - string thumb_path; - Gdk.Pixbuf pixbuf = null; - - result = iter.user_data2; - - // Query thumbnail to GIO - file = GLib.File.new_for_uri (result.values[1]); - - try { - info = yield file.query_info_async ("thumbnail::path,standard::icon", - GLib.FileQueryInfoFlags.NONE, - GLib.Priority.DEFAULT, - cancellable); - } catch (GLib.Error ie) { - if (!cancellable.is_cancelled ()) { - warning ("Could not get thumbnail: %s", ie.message); - } - return; - } - - thumb_path = info.get_attribute_byte_string ("thumbnail::path"); - - try { - if (thumb_path != null) { - pixbuf = new Gdk.Pixbuf.from_file_at_size (thumb_path, icon_size, icon_size); - } else { - GLib.Icon icon; - Gtk.IconInfo icon_info; - - icon = (GLib.Icon) info.get_attribute_object ("standard::icon"); - - if (icon == null) { - return; - } - - var theme = IconTheme.get_for_screen (Gdk.Screen.get_default ()); - icon_info = theme.lookup_by_gicon (icon, icon_size, 0); // Gtk.IconLookupFlags.FORCE_SIZE - - if (icon_info == null) { - return; - } - - pixbuf = icon_info.load_icon (); - } - } catch (GLib.Error e) { - warning ("Could not get icon pixbuf: %s\n", e.message); - } - - if (pixbuf != null) { - TreePath path; - - result.pixbuf = pixbuf; - path = get_path (iter); - row_changed (path, iter); - } - } - - public void get_value (Gtk.TreeIter iter, int column, out GLib.Value value) { - CategoryNode cat; - - value = GLib.Value (this.get_column_type (column)); - - if (column >= n_columns + n_extra_columns) { - return; - } - - cat = (CategoryNode) iter.user_data; - - if (column == n_columns + 1) { - // Type column - value.set_enum (cat.type); - return; - } - - if (iter.user_data2 == null) { - if (column == n_columns) { - Gdk.Pixbuf pixbuf; - - pixbuf = cat.pixbuf; - - if (pixbuf == null) { - var theme = IconTheme.get_for_screen (Gdk.Screen.get_default ()); - int size = icon_size; - - switch (cat.type) { - case Tracker.Query.Type.APPLICATIONS: - pixbuf = tracker_pixbuf_new_from_name (theme, "package-x-generic", size); - break; - case Tracker.Query.Type.MUSIC: - pixbuf = tracker_pixbuf_new_from_name (theme, "audio-x-generic", size); - break; - case Tracker.Query.Type.IMAGES: - pixbuf = tracker_pixbuf_new_from_name (theme, "image-x-generic", size); - break; - case Tracker.Query.Type.VIDEOS: - pixbuf = tracker_pixbuf_new_from_name (theme, "video-x-generic", size); - break; - case Tracker.Query.Type.DOCUMENTS: - pixbuf = tracker_pixbuf_new_from_name (theme, "x-office-presentation", size); - break; - case Tracker.Query.Type.MAIL: - pixbuf = tracker_pixbuf_new_from_name (theme, "emblem-mail", size); - break; - case Tracker.Query.Type.FOLDERS: - pixbuf = tracker_pixbuf_new_from_name (theme, "folder", size); - break; - case Tracker.Query.Type.BOOKMARKS: - pixbuf = tracker_pixbuf_new_from_name (theme, "web-browser", size); - break; - } - } - - value.set_object (pixbuf); - } - } else { - ResultNode *result; - int n_node; - - result = iter.user_data2; - n_node = (int) (long) iter.user_data3; - - if (result.values[0] != null) { - if (column == n_columns ) { - if (result.pixbuf != null) { - value.set_object (result.pixbuf); - } else if (queries.length == 1) { - fetch_thumbnail.begin (iter); - } - } else { - value.set_string (result.values[column]); - } - } else { - n_node /= 100; - n_node *= 100; - - add_operation (cat, n_node); - } - } - } - - public bool iter_children (out Gtk.TreeIter iter, Gtk.TreeIter? parent) { - CategoryNode cat; - - iter = TreeIter (); - - if (parent == null) { - if (categories.length == 0) { - iter.stamp = 0; - return false; - } - - if (queries.length > 1) { - int i; - - i = find_nth_category_index (null, 0); - cat = categories[i]; - iter.stamp = this.timestamp; - iter.user_data = cat; - return true; - } else { - iter.stamp = this.timestamp; - iter.user_data = categories[0]; - iter.user_data2 = &cat.results[0]; - iter.user_data3 = 0.to_pointer (); - return true; - } - } - - if (parent.user_data2 != null) { - iter.stamp = 0; - return false; - } - - cat = (CategoryNode) parent.user_data; - - if (cat.results.length <= 0) { - iter.stamp = 0; - return false; - } - - iter.stamp = this.timestamp; - iter.user_data = cat; - iter.user_data2 = &cat.results[0]; - iter.user_data3 = 0.to_pointer (); - - return true; - } - - public bool iter_has_child (Gtk.TreeIter iter) { - if (iter.user_data2 == null) { - CategoryNode cat; - - cat = (CategoryNode) iter.user_data; - return (cat.count > 0); - } - - return false; - } - - public int iter_n_children (Gtk.TreeIter? iter) { - if (iter == null) { - if (queries.length > 1) { - return categories.length - 1; - } else if (categories.length > 0) { - return categories[0].count; - } else { - return -1; - } - } - - if (iter.user_data2 != null) { - // a result doesn't have children - return -1; - } - - CategoryNode cat = (CategoryNode) iter.user_data; - - return cat.count; - } - - public bool iter_next (ref Gtk.TreeIter iter) { - CategoryNode cat; - int i; - - cat = (CategoryNode) iter.user_data; - - if (iter.user_data2 == null) { - i = find_nth_category_index (cat, 1); - - if (i < 0 || i >= categories.length) { - iter.stamp = 0; - return false; - } - - iter.stamp = this.timestamp; - iter.user_data = categories[i]; - - return true; - } else { - // Result node - i = (int) (long) iter.user_data3; - i++; - - if (i >= cat.count) { - iter.stamp = 0; - return false; - } - - iter.user_data2 = &cat.results[i]; - iter.user_data3 = i.to_pointer (); - - return true; - } - } - - public bool iter_nth_child (out Gtk.TreeIter iter, Gtk.TreeIter? parent, int n) { - CategoryNode cat; - - iter = TreeIter (); - - if (parent != null) { - cat = (CategoryNode) parent.user_data; - - if (n >= cat.count) { - iter.stamp = 0; - return false; - } - - iter.stamp = this.timestamp; - iter.user_data = cat; - iter.user_data2 = &cat.results[n]; - iter.user_data3 = n.to_pointer (); - return true; - } else { - int index; - - if (queries.length > 1) { - index = find_nth_category_index (null, n); - - if (index < 0 || index >= categories.length) { - iter.stamp = 0; - return false; - } - } else { - index = 0; - } - - cat = categories[index]; - iter.stamp = this.timestamp; - iter.user_data = cat; - - if (queries.length > 1) { - iter.user_data2 = &cat.results[0]; - iter.user_data3 = 0.to_pointer (); - } - - return true; - } - } - - public bool iter_parent (out Gtk.TreeIter iter, Gtk.TreeIter child) { - iter = TreeIter (); - - if (queries.length > 1 && - child.user_data2 != null) { - // child within a category - iter.stamp = this.timestamp; - iter.user_data = child.user_data; - iter.user_data2 = null; - iter.user_data3 = null; - return true; - } - - iter.stamp = 0; - return false; - } - - public void ref_node (Gtk.TreeIter iter) { - } - - public void unref_node (Gtk.TreeIter iter) { - } - - private void theme_changed (IconTheme theme) { - TreeIter iter; - int i, j; - - iter = TreeIter (); - iter.stamp = this.timestamp; - - for (i = 0; i < categories.length; i++) { - CategoryNode cat = categories[i]; - - iter.user_data = cat; - - for (j = cat.count - 1; j >= 0; j--) { - var result = cat.results[j]; - - iter.user_data2 = &cat.results[j]; - iter.user_data3 = j.to_pointer (); - - if (result.pixbuf != null) { - fetch_thumbnail.begin (iter); - } - } - } - } - - public ResultStore (int _n_columns) { - categories = new GenericArray<CategoryNode> (); - running_operations = new GenericArray<Operation?> (); - delayed_operations = new GenericArray<Operation?> (); - - n_columns = _n_columns; - timestamp = 1; - icon_size = 24; // Default value, overridden by tracker-needle.vala - - var theme = IconTheme.get_for_screen (Gdk.Screen.get_default ()); - theme.changed.connect (theme_changed); - } - - public void add_query (Tracker.Query.Type type, Tracker.Query.Match match, ...) { - var l = va_list (); - string str = null; - string [] args = null; - QueryData query_data; - - do { - str = l.arg (); - - if (str != null) { - args += str; - } - } while (str != null); - - if (args.length != n_columns ) { - warning ("Arguments and number of columns doesn't match"); - return; - } - - query_data = QueryData (); - query_data.type = type; - query_data.match = match; - query_data.args = args; - - queries += query_data; - } - - public bool has_results () { - return filled_categories_count () > 0; - } - - public void cancel_search () { - if (cancellable != null) { - cancellable.cancel (); - cancellable = null; - } - - clear_results (); - } -} diff --git a/src/tracker-needle/tracker-stats.vala b/src/tracker-needle/tracker-stats.vala deleted file mode 100644 index f86714e97..000000000 --- a/src/tracker-needle/tracker-stats.vala +++ /dev/null @@ -1,191 +0,0 @@ -// -// Copyright 2010, Martyn Russell <martyn@lanedo.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. -// - -using Gtk; - -// Added to fix #error for GETTEXT_PACKAGE -private const string b = Config.PACKAGE_NAME; - -[DBus (name = "org.freedesktop.Tracker1.Statistics")] -interface Statistics : DBusProxy { - public abstract string[,] Get () throws DBusError; -} - -public class Tracker.Stats : Dialog { - private Statistics tracker; - - public Stats () { - this.title = "Statistics"; - this.border_width = 12; - this.resizable = false; - - setup_dbus (); - setup_ui (); - } - - private void setup_dbus () { - debug ("Setting up statistics D-Bus connection"); - - try { - tracker = GLib.Bus.get_proxy_sync (BusType.SESSION, - "org.freedesktop.Tracker1", - "/org/freedesktop/Tracker1/Statistics", - DBusProxyFlags.DO_NOT_LOAD_PROPERTIES | DBusProxyFlags.DO_NOT_CONNECT_SIGNALS); - } catch (GLib.IOError e) { - var msg = new MessageDialog (null, - DialogFlags.MODAL, - MessageType.ERROR, - ButtonsType.CANCEL, - "Error connecting to D-Bus session bus, %s", - e.message); - msg.run (); - Gtk.main_quit (); - } - } - - private void setup_ui () { - debug ("Setting up statistics UI"); - - // Spacing between major units - var vbox = this.get_content_area() as Box; - vbox.set_spacing (18); - vbox.set_border_width (0); - - // Label for dialog - var label = new Label (_("The statistics represented here do not reflect their availability, rather the total data stored:")); - label.set_line_wrap (true); - label.set_max_width_chars (50); - label.set_alignment (0.0f, 0.5f); - - // NOTE: We can't use this NEW API because it doesn't work, GTK+ doesn't have a fix yet. - // label.set_halign (Gtk.Align.START); - // label.set_valign (Gtk.Align.CENTER); - // label.set_justify (Gtk.Justification.LEFT); - vbox.pack_start (label, true, true, 0); - - // Size group to line up labels - var sizegroup = new SizeGroup (Gtk.SizeGroupMode.HORIZONTAL); - - try { - var result = tracker.Get (); - - for (int i = 0; i < result.length[0]; i++) { - var key = result[i,0]; - var val = result[i,1]; - string key_used; - - debug ("--> %s = %s", key, val); - - switch (key) { - case "nao:Tag": - key_used = ngettext ("Tag", "Tags", int.parse (val)); - break; - case "nco:Contact": - key_used = ngettext ("Contact", "Contacts", int.parse (val)); - break; - case "nfo:Audio": - key_used = ngettext ("Audio", "Audios", int.parse (val)); - break; - case "nfo:Document": - key_used = ngettext ("Document", "Documents", int.parse (val)); - break; - case "nfo:FileDataObject": - key_used = ngettext ("File", "Files", int.parse (val)); - break; - case "nfo:Folder": - key_used = ngettext ("Folder", "Folders", int.parse (val)); - break; - case "nfo:Image": - key_used = ngettext ("Image", "Images", int.parse (val)); - break; - case "nfo:SoftwareApplication": - key_used = ngettext ("Application", "Applications", int.parse (val)); - break; - case "nfo:Video": - //case "nmm:Video": - key_used = ngettext ("Video", "Videos", int.parse (val)); - break; - case "nmm:MusicAlbum": - key_used = ngettext ("Album", "Albums", int.parse (val)); - break; - case "nmm:MusicPiece": - key_used = ngettext ("Music Track", "Music Tracks", int.parse (val)); - break; - case "nmm:Photo": - key_used = ngettext ("Photo", "Photos", int.parse (val)); - break; - case "nmm:Playlist": - key_used = ngettext ("Playlist", "Playlists", int.parse (val)); - break; - case "nmo:Email": - key_used = ngettext ("Email", "Emails", int.parse (val)); - break; - case "nfo:Bookmark": - key_used = ngettext ("Bookmark", "Bookmarks", int.parse (val)); - break; - - default: - continue; - } - - var box = new Box (Gtk.Orientation.HORIZONTAL, 12); - var label_key = new Label (key_used); - var label_val = new Label (val); - - // NOTE: We can't use this NEW API because it doesn't work, GTK+ doesn't have a fix yet. - // label_key.set_justify (Gtk.Justification.LEFT); - // label_key.set_halign (Gtk.Align.START); - // label_key.set_valign (Gtk.Align.CENTER); - // label_val.set_justify (Gtk.Justification.LEFT); - // label_val.set_halign (Gtk.Align.START); - // label_val.set_valign (Gtk.Align.CENTER); - label_key.set_alignment (0.0f, 0.5f); - label_val.set_alignment (0.0f, 0.5f); - - box.pack_start (label_key, true, true, 0); - box.pack_start (label_val, false, true, 0); - - sizegroup.add_widget (label_key); - - vbox.pack_start (box, true, true, 0); - } - } catch (DBusError e) { - warning ("Could not get Tracker statistics: " + e.message); - } - - // Layout widgets - vbox.set_spacing (10); - - // Add buttons to button area at the bottom - add_button ("_Close", ResponseType.CLOSE); - - // Connect signals - this.response.connect (on_response); - - show_all (); - } - - private void on_response (Dialog source, int response_id) { - switch (response_id) { - case ResponseType.CLOSE: - destroy (); - break; - } - } -} diff --git a/src/tracker-needle/tracker-tags-view.vala b/src/tracker-needle/tracker-tags-view.vala deleted file mode 100644 index b9eb25db7..000000000 --- a/src/tracker-needle/tracker-tags-view.vala +++ /dev/null @@ -1,836 +0,0 @@ -/* - * Copyright (C) 2011, Martyn Russell <martyn@lanedo.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. - */ - -using Gtk; -using Tracker; - -private class TagData { - public TrackerTagsView tv; - public Cancellable cancellable; - public string tag_id; - public TreeIter iter; - public int items; - public bool update; - public bool selected; - - public TagData (string? _tag_id, TreeIter? _iter, bool _update, bool _selected, int _items, TrackerTagsView _tv) { - debug ("Creating tag data"); - - tv = _tv; - cancellable = new Cancellable (); - tag_id = _tag_id; - - if (_iter != null) { - iter = _iter; - } - - items = _items; - update = _update; - selected = _selected; - } - - ~TagData () { - if (cancellable != null) { - cancellable.cancel (); - cancellable = null; - } - } -} - -public class TrackerTagsView : Box { - private Sparql.Connection connection; - private Cancellable cancellable; - - private List<TagData> tag_data_requests; - private List<string> files; - - private Gtk.ListStore store; - - private const string UI_FILE = "tracker-needle.ui"; - - private Box vbox; - private Label label; - private Entry entry; - private Button button_add; - private Button button_remove; - private ScrolledWindow scrolled_window; - private TreeView view; - - enum Col { - SELECTION, - TAG_ID, - TAG_NAME, - TAG_COUNT, - TAG_COUNT_VALUE, - N_COLUMNS - } - - enum Selection { - INCONSISTENT = -1, - FALSE = 0, - TRUE = 1 - } - - public TrackerTagsView (owned List<string>? _files) { - try { - connection = Sparql.Connection.get (); - } catch (GLib.Error e) { - warning ("Could not get Sparql connection: %s", e.message); - } - - files = (owned) _files; - - cancellable = new Cancellable (); - - store = new Gtk.ListStore (Col.N_COLUMNS, - typeof (int), /* Selection type */ - typeof (string), /* Tag ID */ - typeof (string), /* Tag Name */ - typeof (string), /* Tag Count String */ - typeof (int)); /* Tag Count */ - - create_ui (); - } - - ~TrackerTagsView () { - if (cancellable != null) { - cancellable.cancel (); - cancellable = null; - } - - if (files != null) { - foreach (string url in files) { - url = null; - } - - files = null; - } - - if (tag_data_requests != null) { - foreach (TagData td in tag_data_requests) { - td = null; - }; - - tag_data_requests = null; - } - } - - public void hide_label () { - label.hide (); - } - - public void set_files (List<string>? _files) { - if (files != null) { - foreach (string url in files) { - url = null; - } - - files = null; - } - - if (_files != null) { - foreach (string url in _files) { - files.prepend (url); - } - - files.reverse (); - } - - update_for_files (); - } - - private void show_error_dialog (string action, Error e) { - string str = e.message != null ? e.message : _("No error given"); - - var msg = new MessageDialog (null, - DialogFlags.MODAL, - MessageType.ERROR, - ButtonsType.CLOSE, - "%s", - action); - msg.format_secondary_text (str); - msg.response.connect (() => { - msg.destroy (); - }); - - msg.run (); - } - - [CCode (instance_pos = -1)] - public void button_remove_clicked_cb (Button source) { - debug ("Remove clicked"); - - TreeIter iter; - TreeModel model; - - TreeSelection selection = view.get_selection (); - - if (selection.get_selected (out model, out iter)) { - string id; - - model.get (iter, Col.TAG_ID, out id, -1); - - TagData td = new TagData (id, iter, false, true, 1, this); - tag_data_requests.prepend (td); - - remove_tag.begin (td); - } - } - - [CCode (instance_pos = -1)] - public void button_add_clicked_cb (Button source) { - debug ("Add clicked"); - unowned string tag = entry.get_text (); - add_tag.begin (tag); - } - - [CCode (instance_pos = -1)] - public void entry_tag_activated_cb (Entry source) { - debug ("Entry activated"); - ((Widget) button_add).activate (); - } - - [CCode (instance_pos = -1)] - public void entry_tag_changed_cb (Editable source) { - debug ("Entry changed"); - - unowned string tag = entry.get_text (); - TreeIter iter; - - if (find_tag (tag, out iter)) { - ((Widget) button_add).set_sensitive (false); - } else { - ((Widget) button_add).set_sensitive ((tag != null && tag != "")); - } - } - - [CCode (instance_pos = -1)] - public void treeview_tags_cell_toggled_cb (CellRendererToggle source, string path_string) { - debug ("Treeview row cell toggled"); - TreePath path = new TreePath.from_string (path_string); - model_toggle_row.begin (path); - } - - [CCode (instance_pos = -1)] - public void treeview_tags_row_selected_cb (TreeSelection selection) { - debug ("Treeview row selected"); - - TreeIter iter; - TreeModel model; - - if (selection.get_selected (out model, out iter)) { - button_remove.set_sensitive (true); - } else { - button_remove.set_sensitive (false); - } - } - - [CCode (instance_pos = -1)] - public void treeview_tags_row_activated_cb (TreeView source, TreePath path, TreeViewColumn column) { - debug ("Treeview row activated"); - model_toggle_row.begin (path); - } - - [CCode (instance_pos = -1)] - private void treeview_tags_toggle_cell_data_func (Gtk.CellLayout layout, Gtk.CellRenderer cell, Gtk.TreeModel model, Gtk.TreeIter iter) { - int selection; - - model.get (iter, Col.SELECTION, out selection, -1); - ((Gtk.CellRendererToggle) cell).set_active (selection == Selection.TRUE); - ((Gtk.CellRendererToggle) cell).inconsistent = (selection == Selection.INCONSISTENT); - } - - private void create_ui () { - var builder = new Gtk.Builder (); - - try { - debug ("Trying to use UI file:'%s'", SRCDIR + UI_FILE); - builder.add_from_file (SRCDIR + UI_FILE); - } catch (GLib.Error e) { - //now the install location - try { - debug ("Trying to use UI file:'%s'", UIDIR + UI_FILE); - builder.add_from_file (UIDIR + UI_FILE); - } catch (GLib.Error e) { - var msg = new MessageDialog (null, - DialogFlags.MODAL, - MessageType.ERROR, - ButtonsType.CANCEL, - "Failed to load UI file, %s\n", - e.message); - msg.run (); - Gtk.main_quit (); - } - } - - // Get widgets from .ui file - vbox = builder.get_object ("vbox_tags") as Box; - label = builder.get_object ("label_tag") as Label; - entry = builder.get_object ("entry_tag") as Entry; - button_add = builder.get_object ("button_add") as Button; - button_remove = builder.get_object ("button_remove") as Button; - scrolled_window = builder.get_object ("scrolled_window_tags") as ScrolledWindow; - view = builder.get_object ("treeview_tags") as TreeView; - - // Set up signal handlers (didn't work from glade) - ((Editable) entry).changed.connect (entry_tag_changed_cb); - button_add.clicked.connect (button_add_clicked_cb); - button_remove.clicked.connect (button_remove_clicked_cb); - - // Set up treeview - Gtk.TreeViewColumn col; - Gtk.CellRenderer renderer; - - // List column: Tag - renderer = new CellRendererToggle (); - renderer.xpad = 5; - renderer.ypad = 5; - ((CellRendererToggle) renderer).toggled.connect (treeview_tags_cell_toggled_cb); - ((CellRendererToggle) renderer).set_radio (false); - - col = new Gtk.TreeViewColumn (); - col.set_title ("-"); - col.set_resizable (false); - col.set_sizing (Gtk.TreeViewColumnSizing.FIXED); - col.set_fixed_width (25); - col.pack_start (renderer, false); - col.set_cell_data_func (renderer, treeview_tags_toggle_cell_data_func); - view.append_column (col); - - // List column: Name - renderer = new CellRendererText (); - renderer.xpad = 5; - renderer.ypad = 5; - ((CellRendererText) renderer).ellipsize = Pango.EllipsizeMode.END; - ((CellRendererText) renderer).ellipsize_set = true; - - col = new Gtk.TreeViewColumn (); - col.set_title (_("Name")); - col.set_resizable (true); - col.set_sizing (Gtk.TreeViewColumnSizing.AUTOSIZE); - col.set_expand (true); - col.pack_start (renderer, true); - col.add_attribute (renderer, "text", Col.TAG_NAME); - - view.append_column (col); - - // List coumnn: Count - renderer = new CellRendererText (); - renderer.xpad = 5; - renderer.ypad = 5; - - col = new Gtk.TreeViewColumn (); - col.set_title ("-"); - col.set_resizable (false); - col.set_sizing (Gtk.TreeViewColumnSizing.FIXED); - col.set_fixed_width (50); - col.pack_end (renderer, false); - col.add_attribute (renderer, "text", Col.TAG_COUNT); - - view.append_column (col); - - // Selection signals - var selection = view.get_selection (); - selection.changed.connect (treeview_tags_row_selected_cb); - - // Model details - TreeModel model = store as TreeModel; - TreeSortable sortable = model as TreeSortable; - - view.set_model (model); - view.row_activated.connect (treeview_tags_row_activated_cb); - sortable.set_sort_column_id (2, SortType.ASCENDING); - - // Add vbox to this widget's vbox - vbox.unparent (); - base.pack_start (vbox, true, true, 0); - - // Set controls up based on selected file(s) - // NOTE: This can't occur before the view is created - update_for_files (); - - query_tags.begin (); - } - - private void update_for_files () { - if (files != null) { - string str = dngettext (null, - "_Set the tags you want to associate with the %d selected item:", - "_Set the tags you want to associate with the %d selected items:", - files.length ()).printf (files.length ()); - label.set_text_with_mnemonic (str); - vbox.sensitive = true; - } else { - label.set_text (_("No items currently selected")); - vbox.sensitive = false; - } - - query_tags_for_files.begin (); - } - - private async void model_toggle_row (TreePath path) { - TreeModel model; - TreeIter iter; - string id, tag; - int selection; - - model = view.get_model (); - - if (model.get_iter (out iter, path) == false) { - return; - } - - model.get (iter, - Col.SELECTION, out selection, - Col.TAG_ID, out id, - Col.TAG_NAME, out tag, - -1); - - int new_value = selection == Selection.FALSE ? Selection.TRUE : Selection.FALSE; - - string tag_escaped = sparql_get_escaped_string (tag); - string filter = sparql_get_filter_string (null); - string query = null; - - TagData td; - - // NOTE: Was if (selection) ... - if (new_value != Selection.FALSE) { - // NB: ?f is used in filter. - query = "INSERT { - ?urn nao:hasTag ?label - } WHERE { - ?urn nie:url ?f . - ?label nao:prefLabel %s . - %s - }".printf (tag_escaped, filter); - } else { - // NB: ?f is used in filter. - query = "DELETE { - ?urn nao:hasTag ?label - } WHERE { - ?urn nie:url ?f . - ?label nao:prefLabel %s . - %s - }".printf (tag_escaped, filter); - - /* Check if there are any files left with this tag and - * remove tag if not. - */ - td = new TagData (id, iter, false, true, 1, this); - tag_data_requests.prepend (td); - - query_files_for_tag_id.begin (td); - } - - filter = null; - tag_escaped = null; - - if (connection == null) { - warning ("Can't update tags, no SPARQL connection available"); - return; - } - - debug ("Updating tags for uris"); - - entry.set_sensitive (false); - - td = new TagData (id, iter, true, (new_value != Selection.FALSE), 1, this); - tag_data_requests.prepend (td); - - try { - yield connection.update_async (query, Priority.DEFAULT, td.cancellable); - - debug ("Updated tags"); - update_tag_data (td); - - entry.set_text (""); - } catch (GLib.Error e) { - warning ("Could not run Sparql update query: %s", e.message); - show_error_dialog (_("Could not update tags"), e); - } - - tag_data_requests.remove (td); - td = null; - - entry.set_sensitive (true); - } - - private bool find_tag (string tag, out TreeIter iter) { - TreeIter found_iter = { 0 }; - - iter = found_iter; - - if (tag == null || tag == "") { - return false; - } - - TreeModel model = view.get_model (); - bool found = false; - - model.foreach ((model, path, foreach_iter) => { - string foreach_tag; - - model.get (foreach_iter, Col.TAG_NAME, out foreach_tag, -1); - - if (foreach_tag != null && foreach_tag == tag) { - found = true; - found_iter = foreach_iter; - return true; - } - - return false; - }); - - if (found == true) { - iter = found_iter; - return true; - } - - return false; - } - - private async void remove_tag (TagData td) { - if (connection == null) { - warning ("Can't remove tag '%s', no SPARQL connection available", td.tag_id); - tag_data_requests.remove (td); - td = null; - return; - } - - string query = "DELETE { <%s> a rdfs:Resource }".printf (td.tag_id); - - try { - yield connection.update_async (query, Priority.DEFAULT, td.cancellable); - - debug ("Tag removed"); - store.remove (td.iter); - } catch (GLib.Error e) { - warning ("Could not run Sparql update query: %s", e.message); - show_error_dialog (_("Could not remove tag"), e); - } - - tag_data_requests.remove (td); - td = null; - } - - private async void add_tag (string tag) { - string query = null; - - if (connection == null) { - warning ("Can't add tag '%s', no SPARQL connection available", tag); - return; - } - - entry.set_sensitive (false); - - if (files != null && files.length () > 0) { - query = ""; - - string filter = sparql_get_filter_string (null); - string tag_escaped = sparql_get_escaped_string (tag); - - foreach (string url in files) { - query += "INSERT { - _:file a nie:DataObject ; - nie:url '%s' - } WHERE { - OPTIONAL { - ?file a nie:DataObject ; - nie:url '%s' - } . - FILTER (!bound(?file)) - }".printf (url, url); - } - - query += "INSERT { - _:tag a nao:Tag; - nao:prefLabel %s . - } WHERE { - OPTIONAL { - ?tag a nao:Tag ; - nao:prefLabel %s - } . - FILTER (!bound(?tag)) - } - INSERT { - ?urn nao:hasTag ?label - } WHERE { - ?urn nie:url ?f . - ?label nao:prefLabel %s - %s - }".printf (tag_escaped, tag_escaped, tag_escaped, filter); - } else { - string tag_label_escaped = sparql_get_escaped_string (tag); - - query = "INSERT { - _:tag a nao:Tag ; - nao:prefLabel %s . - } WHERE { - OPTIONAL { - ?tag a nao:Tag ; - nao:prefLabel %s - } . - FILTER (!bound(?tag)) - }".printf (tag_label_escaped, tag_label_escaped); - } - - TagData td = new TagData (null, null, false, true, (int) files.length (), this); - tag_data_requests.prepend (td); - - try { - yield connection.update_async (query, Priority.DEFAULT, td.cancellable); - - debug ("Updated tags"); - update_tag_data (td); - - // Only do this on success - entry.set_text (""); - } catch (GLib.Error e) { - warning ("Could not run Sparql update query: %s", e.message); - show_error_dialog (_("Could not update tags"), e); - } - - tag_data_requests.remove (td); - td = null; - - entry.set_sensitive (true); - } - - private void update_tag_data (TagData td) { - unowned string tag = entry.get_text (); - - if (td.update == false) { - TreeIter iter; - - debug ("Setting tag selection state to ON (new)"); - - store.append (out iter); - store.set (iter, - Col.TAG_ID, td.tag_id, - Col.TAG_NAME, tag, - Col.TAG_COUNT, "%d".printf (td.items), - Col.TAG_COUNT_VALUE, td.items, - Col.SELECTION, Selection.TRUE, - -1); - } else if (td.selected == true) { - debug ("Setting tag selection state to ON"); - - store.set (td.iter, Col.SELECTION, Selection.TRUE, -1); - - tag_data_requests.prepend (td); - query_files_for_tag_id.begin (td); - } else { - debug ("Setting tag selection state to FALSE"); - - store.set (td.iter, Col.SELECTION, Selection.FALSE, -1); - - tag_data_requests.prepend (td); - query_files_for_tag_id.begin (td); - } - } - - private void untoggle_all () { - TreeModel model = view.get_model (); - Gtk.ListStore store = (Gtk.ListStore) model; - - model.foreach ((model, path, foreach_iter) => { - store.set (foreach_iter, Col.SELECTION, Selection.FALSE, -1); - return false; - }); - } - - private async void query_tags_for_files () { - untoggle_all (); - - if (files == null) { - return; - } - - // Get tags for files only and make sure we toggle the list - string files_filter = ""; - - foreach (string url in files) { - if (files_filter.length > 0) { - files_filter += ","; - } - - files_filter += "'%s'".printf (url); - } - - string query = "select ?tag nao:prefLabel(?tag) WHERE { ?urn nao:hasTag ?tag . FILTER(nie:url(?urn) IN (%s)) } ORDER BY (?tag)".printf (files_filter); - - debug ("Getting tags for files selected..."); - - try { - Sparql.Cursor cursor = yield connection.query_async (query, null); - - while (yield cursor.next_async ()) { - debug ("Toggling tags..."); - - unowned string id = cursor.get_string (0); - unowned string label = cursor.get_string (1); - - debug (" Enabling tag:'%s', label:'%s'", id, label); - - TreeIter iter; - if (find_tag (label, out iter)) { - store.set (iter, - Col.SELECTION, Selection.TRUE, - -1); - } - } - } catch (GLib.Error e) { - warning ("Could not run Sparql query: %s", e.message); - show_error_dialog (_("Could not retrieve tags for the current selection"), e); - } - } - - private async void query_tags () { - // Get all tags - string query = "SELECT ?urn ?label WHERE { ?urn a nao:Tag ; nao:prefLabel ?label . } ORDER BY ?label"; - - debug ("Clearing tags in store"); - store.clear (); - - try { - Sparql.Cursor cursor = yield connection.query_async (query, null); - - while (yield cursor.next_async ()) { - - debug ("Adding all tags..."); - - unowned string id = cursor.get_string (0); - unowned string label = cursor.get_string (1); - - debug (" Adding tag id:'%s' with label:'%s' to store", id, label); - - TreeIter iter; - store.append (out iter); - - store.set (iter, - Col.TAG_ID, id, - Col.TAG_NAME, label, - Col.SELECTION, Selection.FALSE, - -1); - - TagData td = new TagData (id, iter, false, true, 1, this); - tag_data_requests.prepend (td); - - query_files_for_tag_id.begin (td); - } - } catch (GLib.Error e) { - warning ("Could not run Sparql query: %s", e.message); - show_error_dialog (_("Could not add tag"), e); - } - } - - private async void query_files_for_tag_id (TagData td) { - if (connection == null) { - warning ("Can't query files for tag id '%s', no SPARQL connection available", td.tag_id); - tag_data_requests.remove (td); - td = null; - return; - } - - string query = "SELECT ?url WHERE { ?urn a rdfs:Resource ; nie:url ?url ; nao:hasTag <%s> . }".printf (td.tag_id); - - try { - Sparql.Cursor cursor = yield connection.query_async (query, td.cancellable); - - uint has_tag_in_selection = 0; - uint files_with_tag = 0; - uint files_selected = files.length (); - - while (yield cursor.next_async ()) { - files_with_tag++; - - foreach (string url in files) { - unowned string url_returned = cursor.get_string (0); - - debug ("--> '%s' vs '%s'", url, url_returned); - - if (url_returned == null) { - continue; - } - - if (url_returned == url) { - has_tag_in_selection++; - break; - } - } - } - - debug ("Querying files with tag, in selection:%ld, in total:%ld, selected:%ld", - has_tag_in_selection, files_with_tag, files_selected); - - if (has_tag_in_selection == 0) { - store.set (td.iter, Col.SELECTION, Selection.FALSE, -1); - } else if (files_selected != has_tag_in_selection) { - store.set (td.iter, Col.SELECTION, Selection.INCONSISTENT, -1); - } else { - store.set (td.iter, Col.SELECTION, Selection.TRUE, -1); - } - - string str = "%ld".printf (files_with_tag); - store.set (td.iter, Col.TAG_COUNT, str, Col.TAG_COUNT_VALUE, files_with_tag, -1); - - debug ("Tags for file updated"); - } catch (GLib.Error e) { - warning ("Could not run Sparql query: %s", e.message); - show_error_dialog (_("Could not update tags for file"), e); - } - - tag_data_requests.remove (td); - td = null; - } - - private string sparql_get_filter_string (string? tag) requires (files != null && files.length () > 0) { - string filter = "FILTER ("; - - if (tag != null && tag != "") { - filter += "("; - } - - bool first = true; - - foreach (string url in files) { - if (!first) { - filter += " || "; - } - - filter += "?f = \"%s\"".printf (url); - first = false; - } - - if (tag != null && tag != "") { - filter += ") && ?t = <%s>".printf (tag); - } - - filter += ")"; - - return filter; - } - - private string sparql_get_escaped_string (string str) { - string escaped = Sparql.escape_string (str); - return "\"%s\"".printf (escaped); - } -} - diff --git a/src/tracker-needle/tracker-utils.vala b/src/tracker-needle/tracker-utils.vala deleted file mode 100644 index 54826113e..000000000 --- a/src/tracker-needle/tracker-utils.vala +++ /dev/null @@ -1,238 +0,0 @@ -// -// Copyright 2010, Martyn Russell <martyn@lanedo.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. -// - -using Gtk; - -private const int secs_per_day = 60 * 60 * 24; - -private string? uri_get_selected (TreeModel model, TreePath path, int col) { - TreeIter iter; - model.get_iter (out iter, path); - - weak string uri; - model.get (iter, col, out uri); - - return uri; -} - -private void uri_launch (string uri) { - // Bit of a hack for now if there is no URI scheme, we assume that - // the uri is actually a command line to launch. - if (uri.index_of ("://") < 1) { - var command = uri.split (" "); - debug ("Attempting to spawn_async() '%s'", command[0]); - - Pid child_pid; - string[] argv = new string[1]; - argv[0] = command[0]; - - try { - Process.spawn_async ("/usr/bin", - argv, - null, // environment - SpawnFlags.SEARCH_PATH, - null, // child_setup - out child_pid); - } catch (Error e) { - warning ("Could not launch '%s', %d->%s", command[0], e.code, GLib.strerror (e.code)); - return; - } - - debug ("Launched application with PID:%d", child_pid); - return; - } - - try { - debug ("Attempting to launch application for uri:'%s'", uri); - AppInfo.launch_default_for_uri (uri, null); - } catch (GLib.Error e) { - warning ("Could not launch application: " + e.message); - } -} - -public void tracker_model_launch_selected (TreeModel model, TreePath path, int col) { - string uri = uri_get_selected (model, path, col); - debug ("Selected uri:'%s'", uri); - - uri_launch (uri); -} - -public void tracker_model_launch_selected_parent_dir (TreeModel model, TreePath path, int col) { - string uri = uri_get_selected (model, path, col); - debug ("Selected uri:'%s'", uri); - - File f = File.new_for_uri (uri); - File p = f.get_parent (); - string parent_uri = p.get_uri (); - - debug ("Parent uri:'%s'", parent_uri); - uri_launch (parent_uri); -} - -public string tracker_time_format_from_iso8601 (string s) { - GLib.Time t = GLib.Time (); - t.strptime (s, "%FT%T"); - - var tv_now = GLib.TimeVal (); - tv_now.get_current_time (); - - var tv_then = GLib.TimeVal (); - tv_then.from_iso8601 (s); - - var diff_sec = tv_now.tv_sec - tv_then.tv_sec; - var diff_days = diff_sec / secs_per_day; - var diff_days_abs = diff_days.abs (); - - // stdout.printf ("timeval now:%ld, then:%ld, diff secs:%ld, diff days:%ld, abs: %ld, seconds per day:%d\n", tv_now.tv_sec, tv_then.tv_sec, diff_sec, diff_days, diff_days_abs, secs_per_day); - - // if it's more than a week, use the default date format - if (diff_days_abs > 7) { - /* Translators: This is a strftime(3) date format string, read its man page to fit your locale better */ - /*xgettext:no-c-format*/ - return t.format (_("%x")); - } - - if (diff_days_abs == 0) { - return _("Today"); - } else { - bool future = false; - - if (diff_days < 0) - future = true; - - if (diff_days <= 1) { - if (future) - return _("Tomorrow"); - else - return _("Yesterday"); - } else { - if (future) { - /* Translators: %d is replaced with a number of days. It's always greater than 1 */ - return ngettext ("%ld day from now", "%ld days from now", diff_days_abs).printf (diff_days_abs); - } else { - /* Translators: %d is replaced with a number of days. It's always greater than 1 */ - return ngettext ("%ld day ago", "%ld days ago", diff_days_abs).printf (diff_days_abs); - } - } - } -} - -public string tracker_time_format_from_seconds (string seconds_str) { - double seconds = int.parse (seconds_str); - double total; - int d, h, m, s; - - if (seconds == 0.0) { - return _("Less than one second"); - } - - total = seconds; - s = (int) total % 60; - total /= 60; - m = (int) total % 60; - total /= 60; - h = (int) total % 24; - d = (int) total / 24; - - var output = new StringBuilder (""); - - if (d > 0) { - output.append (" %dd".printf (d)); - } - - if (h > 0) { - output.append (" %.2d".printf (h)); - } - - if (m > 0) { - output.append ("%s%.2d".printf (h > 0 ? ":" : "", m)); - } - - // Always show seconds - output.append ("%s%.2d".printf (m > 0 ? ":" : "0:", s)); - - if (output.len < 1) { - return _("Less than one second"); - } - - string str = output.str; - - return str._chug (); -} - -public Gdk.Pixbuf tracker_pixbuf_new_from_file (IconTheme theme, string filename, int size, bool is_image) { - // Get Icon - var file = File.new_for_uri (filename); - var pixbuf = null as Gdk.Pixbuf; - - if (is_image) { - try { - pixbuf = new Gdk.Pixbuf.from_file_at_size (file.get_path (), size, size); - } catch (GLib.Error e) { - warning ("Error loading icon pixbuf: " + e.message); - } - - if (pixbuf != null) { - return pixbuf; - } - } - - if (file.query_exists (null)) { - try { - var file_info = file.query_info ("standard::icon", - FileQueryInfoFlags.NONE, - null); - - if (file_info != null) { - var icon = file_info.get_icon (); - - try { - if (icon is FileIcon) { - pixbuf = new Gdk.Pixbuf.from_file (((FileIcon) icon).get_file ().get_path ()); - } else if (icon is ThemedIcon) { - pixbuf = theme.load_icon (((ThemedIcon) icon).get_names ()[0], size, Gtk.IconLookupFlags.USE_BUILTIN); - } - } catch (GLib.Error e) { - warning ("Error loading icon pixbuf: " + e.message); - } - } - } catch (GLib.Error e) { - warning ("Error looking up file for pixbuf: " + e.message); - } - } - - if (pixbuf != null) { - return pixbuf; - } - - return tracker_pixbuf_new_from_name (theme, "text-x-generic", size); -} - -public Gdk.Pixbuf tracker_pixbuf_new_from_name (IconTheme theme, string name, int size) { - // Get Icon - var pixbuf = null as Gdk.Pixbuf; - - try { - pixbuf = theme.load_icon (name, size, IconLookupFlags.USE_BUILTIN); - } catch (GLib.Error e) { - warning ("Could not load default icon pixbuf from theme for '%s': %s", name, e.message); - } - - return pixbuf; -} diff --git a/src/tracker-needle/tracker-view.vala b/src/tracker-needle/tracker-view.vala deleted file mode 100644 index 58fa28674..000000000 --- a/src/tracker-needle/tracker-view.vala +++ /dev/null @@ -1,561 +0,0 @@ -// -// Copyright 2010, Martyn Russell <martyn@lanedo.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. -// - -using Gtk; - -public class Tracker.View : ScrolledWindow { - public enum Display { - NO_RESULTS, - CATEGORIES, - FILE_LIST, - FILE_ICONS - } - - public Display display { - get; - private set; - } - - private ResultStore _store; - public ResultStore store { - get { - return _store; - } - set { - if (_store != null) { - _store.row_changed.disconnect (store_row_changed); - } - - _store = value; - - if (_store != null) { - debug ("using store:%p", _store); - _store.row_changed.connect (store_row_changed); - } - - if (display != Display.FILE_ICONS) { - ((TreeView) view).model = _store; - } else { - ((IconView) view).model = _store; - } - } - } - - private Widget view = null; - private Gtk.Menu context_menu; - - private void store_row_changed (TreeModel model, - TreePath path, - TreeIter iter) { - int n_children = model.iter_n_children (iter); - - if (n_children > 0) { - ((TreeView) view).expand_row (path, false); - } - } - - private bool row_selection_func (TreeSelection selection, - TreeModel model, - TreePath path, - bool path_selected) { - if (path.get_depth () == 1) { - // Category row, not selectable - return false; - } - - return true; - } - - public override void unmap () { - if (store != null) { - store.cancel_search (); - } - - base.unmap (); - } - - public View (Display? _display = Display.NO_RESULTS, ResultStore? store) { - set_policy (PolicyType.NEVER, PolicyType.AUTOMATIC); - - display = _display; - - if (store != null) { - _store = store; - store.row_changed.connect (store_row_changed); - debug ("using store:%p", store); - } - - switch (display) { - case Display.NO_RESULTS: - Label l; - - l = new Label (""); - l.set_justify (Justification.CENTER); - - string results = _("No Search Results"); - string help_views = _("Select the view on the toolbar for the content you want, e.g. everything, files or just images"); - string help_search = _("Start to search using the entry box above"); - string markup = @"<big>$results</big>\n\n$help_views\n\n$help_search"; - - l.set_use_markup (true); - l.set_markup (markup); - - view = l; - break; - - case Display.CATEGORIES: - case Display.FILE_LIST: - view = new TreeView (); - break; - - case Display.FILE_ICONS: - view = new IconView (); - break; - } - - if (display == Display.NO_RESULTS) { - add (view); - } else { - add (view); - setup_model (); - setup_menus (); - } - - base.show_all (); - } - - private void setup_model () { - switch (display) { - case Display.FILE_ICONS: { - IconView iv = (IconView) view; - - iv.set_model (store); - iv.set_item_width (128); - iv.set_item_padding (1); - iv.set_row_spacing (2); - iv.set_column_spacing (2); - iv.set_selection_mode (SelectionMode.SINGLE); - iv.set_pixbuf_column (6); - iv.set_text_column (-1); // was 2, -1 is for no text - iv.set_tooltip_column (5); - - break; - } - - case Display.FILE_LIST: { - TreeViewColumn col; - TreeView tv = (TreeView) view; - - tv.set_model (store); - tv.set_tooltip_column (6); - tv.set_rules_hint (false); - tv.set_grid_lines (TreeViewGridLines.VERTICAL); - tv.set_headers_visible (true); - - var renderer1 = new CellRendererPixbuf (); - var renderer2 = new Gtk.CellRendererText (); - - col = new TreeViewColumn (); - col.set_sizing (TreeViewColumnSizing.AUTOSIZE); - col.pack_start (renderer1, false); - col.add_attribute (renderer1, "pixbuf", 7); - renderer1.xpad = 5; - renderer1.ypad = 5; - - col.pack_start (renderer2, true); - renderer2.set_fixed_height_from_font (2); - renderer2.ellipsize = Pango.EllipsizeMode.MIDDLE; - - col.set_title (_("File")); - col.set_resizable (true); - col.set_expand (true); - col.set_cell_data_func (renderer1, background_renderer_func); - col.set_cell_data_func (renderer2, text_renderer_func); - tv.append_column (col); - - var renderer3 = new Gtk.CellRendererText (); - renderer3.set_fixed_height_from_font (2); - col = new TreeViewColumn (); - col.set_sizing (TreeViewColumnSizing.AUTOSIZE); - col.pack_start (renderer3, true); - col.set_title (_("Last Changed")); - col.set_cell_data_func (renderer3, file_date_renderer_func); - tv.append_column (col); - - var renderer4 = new Gtk.CellRendererText (); - renderer4.set_fixed_height_from_font (2); - col = new TreeViewColumn (); - col.set_sizing (TreeViewColumnSizing.AUTOSIZE); - col.pack_start (renderer4, true); - col.set_title (_("Size")); - col.set_cell_data_func (renderer4, file_size_renderer_func); - tv.append_column (col); - - break; - } - - case Display.CATEGORIES: { - TreeViewColumn col; - TreeView tv = (TreeView) view; - TreeSelection selection; - - tv.set_model (store); - tv.set_tooltip_column (5); - tv.set_rules_hint (false); - tv.set_grid_lines (TreeViewGridLines.NONE); - tv.set_headers_visible (false); - tv.set_show_expanders (false); - - selection = tv.get_selection (); - selection.set_select_function (row_selection_func); - - col = new TreeViewColumn (); - col.set_sizing (TreeViewColumnSizing.FIXED); - col.set_expand (true); - - var renderer1 = new CellRendererPixbuf (); - col.pack_start (renderer1, false); - col.add_attribute (renderer1, "pixbuf", 6); - col.set_cell_data_func (renderer1, background_renderer_func); - renderer1.xpad = 5; - renderer1.ypad = 5; - - var renderer2 = new Gtk.CellRendererText (); - col.pack_start (renderer2, true); - col.set_cell_data_func (renderer2, text_renderer_func); - renderer2.set_fixed_height_from_font (2); - renderer2.ellipsize = Pango.EllipsizeMode.MIDDLE; - - //col.set_resizable (true); - //col.set_sizing (TreeViewColumnSizing.AUTOSIZE); - tv.append_column (col); - -// var renderer3 = new Gtk.CellRendererText (); -// col = new TreeViewColumn (); -// col.pack_start (renderer3, true); -// col.add_attribute (renderer3, "text", 3); -// col.set_title (_("Item Detail")); -// col.set_cell_data_func (renderer3, cell_renderer_func); -// tv.append_column (col); - - var renderer4 = new Gtk.CellRendererText (); - renderer4.set_fixed_height_from_font (2); - renderer4.alignment = Pango.Alignment.RIGHT; - renderer4.xalign = 1; - - col = new TreeViewColumn (); - col.set_min_width (80); - col.set_sizing (TreeViewColumnSizing.FIXED); - col.pack_start (renderer4, true); - col.set_cell_data_func (renderer4, category_detail_renderer_func); - tv.append_column (col); - - break; - } - } - } - - private void background_renderer_func (CellLayout cell_layout, - CellRenderer cell, - TreeModel tree_model, - TreeIter iter) { - Gdk.Color color; - Style style; - TreePath path; - - style = view.get_style (); - - color = style.base[StateType.SELECTED]; - int sum_normal = color.red + color.green + color.blue; - color = style.base[StateType.NORMAL]; - int sum_selected = color.red + color.green + color.blue; - color = style.text_aa[StateType.INSENSITIVE]; - - if (sum_normal < sum_selected) { - /* Found a light theme */ - color.red = (color.red + (style.white).red) / 2; - color.green = (color.green + (style.white).green) / 2; - color.blue = (color.blue + (style.white).blue) / 2; - } else { - /* Found a dark theme */ - color.red = (color.red + (style.black).red) / 2; - color.green = (color.green + (style.black).green) / 2; - color.blue = (color.blue + (style.black).blue) / 2; - } - - path = tree_model.get_path (iter); - - // Set odd/even colours - if (path.get_indices()[0] % 2 != 0) { - cell.set ("cell-background-gdk", color); - } else { - cell.set ("cell-background-gdk", null); - } - } - - private void text_renderer_func (CellLayout cell_layout, - CellRenderer cell, - TreeModel tree_model, - TreeIter iter) { - string text, subtext; - string markup = null; - int n_children; - - background_renderer_func (cell_layout, cell, tree_model, iter); - n_children = tree_model.iter_n_children (iter); - - if (n_children > 0) { - // Category row - Tracker.Query.Type type; - string cat = null; - - tree_model.get (iter, 7, out type, -1); - switch (type) { - case Tracker.Query.Type.APPLICATIONS: - cat = _("Applications"); - break; - case Tracker.Query.Type.MUSIC: - cat = _("Music"); - break; - case Tracker.Query.Type.IMAGES: - cat = _("Images"); - break; - case Tracker.Query.Type.VIDEOS: - cat = _("Videos"); - break; - case Tracker.Query.Type.DOCUMENTS: - cat = _("Documents"); - break; - case Tracker.Query.Type.MAIL: - cat = _("Mail"); - break; - case Tracker.Query.Type.FOLDERS: - cat = _("Folders"); - break; - case Tracker.Query.Type.BOOKMARKS: - cat = _("Bookmarks"); - break; - } - - markup = "<b><big>%s</big></b> <small>(%d %s)</small>".printf (cat, n_children, _("Items")); - } else { - // Result row - tree_model.get (iter, 2, out text, 3, out subtext, -1); - - if (text != null) { - markup = Markup.escape_text (text); - - if (subtext != null) { - subtext = subtext.replace ("\n", " "); - markup += "\n<small><span color='grey'>%s</span></small>".printf (Markup.escape_text (subtext)); - } - } else { - markup = "<span color='grey'>%s</span>\n".printf (_("Loading…")); - } - } - - cell.set ("markup", markup); - } - - private void file_size_renderer_func (CellLayout cell_layout, - CellRenderer cell, - TreeModel tree_model, - TreeIter iter) { - string size; - - background_renderer_func (cell_layout, cell, tree_model, iter); - tree_model.get (iter, 4, out size, -1); - - if (size != null) { - size = GLib.format_size (int.parse (size)); - } - - cell.set ("text", size); - } - - private void file_date_renderer_func (CellLayout cell_layout, - CellRenderer cell, - TreeModel tree_model, - TreeIter iter) { - string date; - - background_renderer_func (cell_layout, cell, tree_model, iter); - tree_model.get (iter, 5, out date, -1); - - if (date != null) { - date = tracker_time_format_from_iso8601 (date); - } - - cell.set ("text", date); - } - - private void category_detail_renderer_func (CellLayout cell_layout, - CellRenderer cell, - TreeModel tree_model, - TreeIter iter) { - Tracker.Query.Type category; - string markup = null; - string detail; - - background_renderer_func (cell_layout, cell, tree_model, iter); - tree_model.get (iter, 4, out detail, 7, out category, -1); - - if (detail == null) { - cell.set ("markup", null); - return; - } - - switch (category) { - case Tracker.Query.Type.FOLDERS: - case Tracker.Query.Type.MAIL: - case Tracker.Query.Type.BOOKMARKS: - detail = tracker_time_format_from_iso8601 (detail); - break; - case Tracker.Query.Type.MUSIC: - case Tracker.Query.Type.VIDEOS: - detail = tracker_time_format_from_seconds (detail); - break; - case Tracker.Query.Type.DOCUMENTS: - detail = ngettext ("%d Page", "%d Pages", int.parse (detail)).printf (int.parse (detail)); - break; - case Tracker.Query.Type.IMAGES: - detail = GLib.format_size (int.parse (detail)); - break; - } - - markup = "<span color='grey'><small>%s</small></span>".printf (Markup.escape_text (detail)); - cell.set ("markup", markup); - } - - private void setup_menus () { - // Set up context menu - view.button_press_event.connect (view_button_press_event); - - context_menu = new Gtk.Menu (); - - var item = new Gtk.MenuItem.with_mnemonic (_("_Show Parent Directory")); - item.activate.connect (context_menu_directory_clicked); - context_menu.append (item); - - var separator = new SeparatorMenuItem (); - context_menu.append (separator); - - item = new Gtk.MenuItem.with_mnemonic (_("_Tags…")); - item.activate.connect (context_menu_tags_clicked); - context_menu.append (item); - - context_menu.show_all (); - } - - private bool view_button_press_event (Gtk.Widget widget, Gdk.EventButton event) { - if (event.button == 3) { - if (get_selected_path () != null) { - context_menu.popup (null, null, null, event.button, event.time); - } - } - - return false; - } - - private TreeModel? get_model () { - switch (display) { - case Display.CATEGORIES: - case Display.FILE_LIST: - TreeView v = (TreeView) view; - return v.get_model (); - - case Display.FILE_ICONS: - IconView v = (IconView) view; - return v.get_model (); - default: - break; - } - - return null; - } - - private TreePath? get_selected_path () { - switch (display) { - case Display.CATEGORIES: - case Display.FILE_LIST: - TreeView v = (TreeView) view; - TreeSelection s = v.get_selection (); - List<TreePath> selected = s.get_selected_rows (null); - - return selected.nth_data (0); - - case Display.FILE_ICONS: - IconView v = (IconView) view; - List<TreePath> selected = v.get_selected_items (); - - return selected.nth_data (0); - - default: - break; - } - - return null; - } - - private void context_menu_directory_clicked () { - TreeModel model = get_model (); - TreePath path = get_selected_path (); - - tracker_model_launch_selected_parent_dir (model, path, 1); - } - - private void context_menu_tags_clicked () { - TreeModel model = get_model (); - TreePath path = get_selected_path (); - TreeIter iter; - model.get_iter (out iter, path); - - weak string uri; - model.get (iter, 1, out uri); - - if (uri == null) { - return; - } - - debug ("Showing tags dialog for uri:'%s'", uri); - - // Create dialog and embed vbox. - Dialog dialog = new Dialog.with_buttons (_("Tags"), - (Window) this.get_toplevel (), - DialogFlags.MODAL | DialogFlags.DESTROY_WITH_PARENT, - "_Close", ResponseType.CLOSE, - null); - dialog.set_default_size (400, 300); - dialog.border_width = 12; - dialog.response.connect (() => { - dialog.destroy (); - }); - - List<string> files = null; - files.prepend (uri); - Box vbox = new TrackerTagsView ((owned) files); - - var content = dialog.get_content_area () as Box; - content.pack_start (vbox, true, true, 6); - content.spacing = 10; - - ((Widget) dialog).show_all (); - dialog.run (); - } -} diff --git a/src/tracker-preferences/.gitignore b/src/tracker-preferences/.gitignore deleted file mode 100644 index 4b004ae27..000000000 --- a/src/tracker-preferences/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -tracker-preferences -*.desktop.in diff --git a/src/tracker-preferences/Makefile.am b/src/tracker-preferences/Makefile.am deleted file mode 100644 index 09b32a668..000000000 --- a/src/tracker-preferences/Makefile.am +++ /dev/null @@ -1,50 +0,0 @@ -@INTLTOOL_DESKTOP_RULE@ - -bin_PROGRAMS = tracker-preferences - -desktopdir = $(datadir)/applications -desktop_DATA = tracker-preferences.desktop - -appdatadir = $(datadir)/appdata -appdata_DATA = tracker-preferences.appdata.xml - -pkgdata_DATA = tracker-preferences.ui - -AM_VALAFLAGS = \ - --pkg gtk+-3.0 --pkg gmodule-2.0 --pkg posix \ - $(BUILD_VALAFLAGS) \ - config.vapi \ - tracker-config.vapi - -AM_CPPFLAGS = \ - $(BUILD_VALACFLAGS) \ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - -DTRACKER_UI_DIR=\"$(datadir)/tracker/\" \ - -DLOCALEDIR=\""$(localedir)"\" \ - -DSRCDIR=\"$(abs_srcdir)/\" \ - $(TRACKER_PREFERENCES_CFLAGS) \ - -include config.h - -LDADD = \ - $(top_builddir)/src/libtracker-common/libtracker-common.la \ - $(BUILD_LIBS) \ - $(TRACKER_PREFERENCES_LIBS) - -tracker_preferences_SOURCES = \ - tracker-preferences.vala \ - $(top_srcdir)/src/miners/fs/tracker-config.c - -EXTRA_DIST = \ - $(desktop_DATA:.desktop=.desktop.in.in) \ - $(pkgdata_DATA) \ - $(appdata_DATA) \ - config.vapi \ - tracker-config.vapi - -CLEANFILES = \ - $(desktop_DATA) \ - $(desktop_DATA:.desktop=.desktop.in) - -%.desktop.in: %.desktop.in.in - @sed -e "s|@VERSION[@]|${VERSION}|" $< > $@ diff --git a/src/tracker-preferences/config.vapi b/src/tracker-preferences/config.vapi deleted file mode 100644 index 0f801f594..000000000 --- a/src/tracker-preferences/config.vapi +++ /dev/null @@ -1,29 +0,0 @@ -// config.vapi -// -// Copyright (C) 2011 Martyn Russell <martyn@lanedo.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. -// - -[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")] -namespace Config -{ - public const string GETTEXT_PACKAGE; - public const string PACKAGE_NAME; - public const string PACKAGE_VERSION; - public const string APP_PATH; - public const string LOCALEDIR; -} diff --git a/src/tracker-preferences/tracker-config.vapi b/src/tracker-preferences/tracker-config.vapi deleted file mode 100644 index 3cca1f02e..000000000 --- a/src/tracker-preferences/tracker-config.vapi +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2008-2009, Nokia - * - * 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: Philip Van Hoof <philip@codeminded.be> - */ - -namespace Tracker { - [CCode (cheader_filename = "miners/fs/tracker-config.h")] - public class Config : GLib.Object { - public Config (); - - public int verbosity { get; set; } - public int initial_sleep { get; set; } - public bool enable_monitors { get; set; } - public int throttle { get; set; } - public bool enable_thumbnails { get; set; } - public bool index_on_battery { get; set; } - public bool index_on_battery_first_time { get; set; } - public bool index_removable_devices { get; set; } - public bool index_optical_discs { get; set; } - public bool index_mounted_directories { get; set; } - public int low_disk_space_limit { get; set; } - public int removable_days_threshold { get; set; } - public GLib.SList<string> index_recursive_directories { get; set; } - public GLib.SList<string> index_recursive_directories_unfiltered { get; } - public GLib.SList<string> index_single_directories { get; set; } - public GLib.SList<string> index_single_directories_unfiltered { get; } - public GLib.SList<string> ignored_directories { get; set; } - public GLib.SList<string> ignored_directories_with_content { get; set; } - public GLib.SList<string> ignored_files { get; set; } - public GLib.SList<string> ignored_directory_patterns { get; } - public GLib.SList<string> ignored_file_patterns { get ; } - - public bool save (); - } -} - diff --git a/src/tracker-preferences/tracker-preferences.appdata.xml b/src/tracker-preferences/tracker-preferences.appdata.xml deleted file mode 100644 index 8b66af3a9..000000000 --- a/src/tracker-preferences/tracker-preferences.appdata.xml +++ /dev/null @@ -1,34 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Copyright 2014 Martyn Russell <martyn@lanedo.com> --> -<component type="desktop"> - <id>tracker-preferences.desktop</id> - <metadata_license>CC0-1.0</metadata_license> - <project_license>GPL-2.0+</project_license> - <name>Search and Indexing</name> - <summary>Configure file indexing with Tracker</summary> - <description> - <p>The Desktop Search application (usually separately installed) - finds content which is indexed only. Using this application, you can - quickly configure what data on your system you want indexed or not - indexed. Not only that, you get to control how it is indexed to - ensure indexing does not impede daily use of your computer.</p> - <p>Some of the preferences you can configure using this application - include:</p> - <ul> - <li>What locations you index</li> - <li>When you index (e.g. not on laptop battery)</li> - <li>How you index (e.g. aggressively or in the background)</li> - <li>Black listing files/directories based on globbing pattern matching</li> - <li>Reset the database and reindex your content</li> - </ul> - </description> - <screenshots> - <screenshot type="default" width="642" height="652"> - <image>https://wiki.gnome.org/Projects/Tracker?action=AttachFile&do=get&target=tracker-preferences.png</image> - </screenshot> - </screenshots> - <url type="homepage">https://wiki.gnome.org/Projects/Tracker</url> - <update_contact>tracker-list@gnome.org</update_contact> - <project_group>GNOME</project_group> - <translation type="gettext">tracker</translation> -</component> diff --git a/src/tracker-preferences/tracker-preferences.desktop.in.in b/src/tracker-preferences/tracker-preferences.desktop.in.in deleted file mode 100644 index 0a89b2b10..000000000 --- a/src/tracker-preferences/tracker-preferences.desktop.in.in +++ /dev/null @@ -1,13 +0,0 @@ -[Desktop Entry] -_Name=Search and Indexing -_Comment=Configure file indexing with Tracker -Icon=tracker -Exec=tracker-preferences -Terminal=false -Type=Application -Categories=Settings;X-GNOME-PersonalSettings; -StartupNotify=true -X-GNOME-Bugzilla-Bugzilla=GNOME -X-GNOME-Bugzilla-Product=tracker -X-GNOME-Bugzilla-Component=Tracker Preferences -X-GNOME-Bugzilla-Version=@VERSION@ diff --git a/src/tracker-preferences/tracker-preferences.ui b/src/tracker-preferences/tracker-preferences.ui deleted file mode 100644 index f8302f022..000000000 --- a/src/tracker-preferences/tracker-preferences.ui +++ /dev/null @@ -1,1578 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.18.3 --> -<interface> - <requires lib="gtk+" version="3.12"/> - <object class="GtkAdjustment" id="adjustment_delay"> - <property name="upper">1000</property> - <property name="value">10</property> - <property name="step_increment">1</property> - </object> - <object class="GtkAdjustment" id="adjustment_disk_space_limit"> - <property name="lower">-1</property> - <property name="upper">100</property> - <property name="step_increment">1</property> - <property name="page_increment">10</property> - </object> - <object class="GtkAdjustment" id="adjustment_drop_device_threshold"> - <property name="upper">365</property> - <property name="value">3</property> - <property name="step_increment">1</property> - <property name="page_increment">10</property> - <property name="page_size">10</property> - </object> - <object class="GtkAdjustment" id="adjustment_throttle"> - <property name="upper">20</property> - <property name="step_increment">1</property> - <property name="page_increment">2</property> - </object> - <object class="GtkListStore" id="liststore_ignored_directories"> - <columns> - <!-- column-name Directory --> - <column type="gchararray"/> - </columns> - </object> - <object class="GtkListStore" id="liststore_ignored_directories_with_content"> - <columns> - <!-- column-name Directory --> - <column type="gchararray"/> - </columns> - </object> - <object class="GtkListStore" id="liststore_ignored_files"> - <columns> - <!-- column-name Filename --> - <column type="gchararray"/> - </columns> - </object> - <object class="GtkListStore" id="liststore_index"> - <columns> - <!-- column-name Directory --> - <column type="gchararray"/> - <!-- column-name Recurse --> - <column type="gboolean"/> - </columns> - </object> - <object class="GtkDialog" id="tracker-preferences"> - <property name="width_request">500</property> - <property name="can_focus">False</property> - <property name="border_width">5</property> - <property name="title" translatable="yes">Indexing Preferences</property> - <property name="icon_name">system-search</property> - <property name="type_hint">normal</property> - <signal name="close" handler="gtk_main_quit" swapped="no"/> - <signal name="delete-event" handler="gtk_main_quit" swapped="no"/> - <signal name="response" handler="tracker_preferences_response_cb" swapped="no"/> - <child internal-child="vbox"> - <object class="GtkBox" id="dialog-vbox1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">2</property> - <child internal-child="action_area"> - <object class="GtkButtonBox" id="dialog-action_area1"> - <property name="can_focus">False</property> - <property name="layout_style">end</property> - <child> - <object class="GtkButton" id="button_apply"> - <property name="label">gtk-apply</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_stock">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_close"> - <property name="label">gtk-close</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="use_stock">True</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="pack_type">end</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkNotebook" id="notebook"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="border_width">6</property> - <property name="show_border">False</property> - <child> - <object class="GtkBox" id="vbox_indexing"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="border_width">12</property> - <property name="orientation">vertical</property> - <property name="spacing">18</property> - <child> - <object class="GtkFrame" id="frame_indexing"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label_xalign">0</property> - <property name="shadow_type">none</property> - <child> - <object class="GtkAlignment" id="alignment3"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="top_padding">6</property> - <property name="left_padding">12</property> - <child> - <object class="GtkBox" id="vbox_semantics"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <child> - <object class="GtkCheckButton" id="checkbutton_enable_monitoring"> - <property name="label" translatable="yes">_Monitor file and directory changes</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="has_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="xalign">0</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="tracker_preferences_checkbutton_enable_monitoring_toggled_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="checkbutton_enable_index_on_battery"> - <property name="label" translatable="yes">Enable when running on _battery</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="xalign">0</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="tracker_preferences_checkbutton_enable_index_on_battery_toggled_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="alignment4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkCheckButton" id="checkbutton_enable_index_on_battery_first_time"> - <property name="label" translatable="yes">Enable for _initial data population</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="xalign">0</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="tracker_preferences_checkbutton_enable_index_on_battery_first_time_toggled_cb" swapped="no"/> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="checkbutton_index_removable_media"> - <property name="label" translatable="yes">Include _removable media</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="tooltip_text" translatable="yes">This covers ALL removable media, memory cards, CDs, DVDs, etc.</property> - <property name="use_underline">True</property> - <property name="xalign">0</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="tracker_preferences_checkbutton_index_removable_media_toggled_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">4</property> - </packing> - </child> - <child> - <object class="GtkAlignment" id="alignment8"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="left_padding">12</property> - <child> - <object class="GtkCheckButton" id="checkbutton_index_optical_discs"> - <property name="label" translatable="yes">Include optical di_scs</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="xalign">0</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="tracker_preferences_checkbutton_index_optical_discs_toggled_cb" swapped="no"/> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">5</property> - </packing> - </child> - </object> - </child> - </object> - </child> - <child type="label"> - <object class="GtkLabel" id="label_indexing"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Semantics</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkFrame" id="frame_limitations"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label_xalign">0</property> - <property name="shadow_type">none</property> - <child> - <object class="GtkAlignment" id="alignment7"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="top_padding">6</property> - <property name="left_padding">12</property> - <child> - <object class="GtkBox" id="vbox11"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">18</property> - <child> - <object class="GtkBox" id="vbox12"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="label13"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="tooltip_text" translatable="yes">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. - -This option allows you to make Tracker take a back seat and not eat up too much CPU time if you have other applications more deserving of it.</property> - <property name="label" translatable="yes">Index content in the background:</property> - <property name="use_markup">True</property> - <property name="justify">fill</property> - <property name="wrap">True</property> - <property name="xalign">0</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="vbox7"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <child> - <object class="GtkRadioButton" id="radiobutton_sched_idle_always"> - <property name="label" translatable="yes">O_nly when computer is not being used</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="tooltip_markup" translatable="yes">Indexing content will be <b>much slower</b> but other applications will have priority.</property> - <property name="use_underline">True</property> - <property name="xalign">0</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkRadioButton" id="radiobutton_sched_idle_first_index"> - <property name="label" translatable="yes">_While other applications are running, except for initial data population</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="tooltip_markup" translatable="yes">Indexing content will be <b>much slower</b> but other applications will have priority. This will only be the case on the <b>first index</b> of your content after you start your computer from a new install</property> - <property name="use_underline">True</property> - <property name="xalign">0.5</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <property name="group">radiobutton_sched_idle_always</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkRadioButton" id="radiobutton_sched_idle_never"> - <property name="label" translatable="yes">While _other applications are running</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="tooltip_markup" translatable="yes">Indexing content will be as <b>fast</b> as possible but other applications may suffer and be slower as a result.</property> - <property name="use_underline">True</property> - <property name="xalign">0</property> - <property name="active">True</property> - <property name="draw_indicator">True</property> - <property name="group">radiobutton_sched_idle_always</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="hbox13"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">12</property> - <child> - <object class="GtkLabel" id="label_disk_space_limit"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="ypad">4</property> - <property name="label" translatable="yes">Stop indexing when _disk space is below:</property> - <property name="use_underline">True</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkScale" id="hscale_disk_space_limit"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="adjustment">adjustment_disk_space_limit</property> - <property name="round_digits">0</property> - <property name="digits">0</property> - <property name="value_pos">left</property> - <signal name="format-value" handler="tracker_preferences_hscale_disk_space_limit_format_value_cb" swapped="no"/> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - </child> - <child type="label"> - <object class="GtkLabel" id="label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Limitations</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkFrame" id="frame_garbage_collection"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label_xalign">0</property> - <property name="shadow_type">none</property> - <child> - <object class="GtkAlignment" id="alignment5"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="top_padding">6</property> - <property name="left_padding">12</property> - <child> - <object class="GtkBox" id="vbox9"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <child> - <object class="GtkLabel" id="label_device_drop_threshold"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xpad">3</property> - <property name="ypad">4</property> - <property name="label" translatable="yes">Indexed content from removable devices that have not been inserted for a while, are cleaned up to avoid build up of unused resources.</property> - <property name="use_underline">True</property> - <property name="wrap">True</property> - <property name="max_width_chars">20</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="box1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">12</property> - <child> - <object class="GtkLabel" id="label_device_drop_threshold1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xpad">3</property> - <property name="ypad">4</property> - <property name="label" translatable="yes">Days before deleting removable devices:</property> - <property name="use_underline">True</property> - <property name="xalign">0</property> - <property name="yalign">0</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkScale" id="hscale_drop_device_threshold"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="adjustment">adjustment_drop_device_threshold</property> - <property name="round_digits">0</property> - <property name="digits">0</property> - <property name="value_pos">left</property> - <signal name="format-value" handler="tracker_preferences_hscale_drop_device_threshold_format_value_cb" swapped="no"/> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - </child> - <child type="label"> - <object class="GtkLabel" id="label7"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Garbage Collection</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - </object> - </child> - <child type="tab"> - <object class="GtkLabel" id="label12"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Indexing</property> - </object> - <packing> - <property name="tab_fill">False</property> - </packing> - </child> - <child> - <object class="GtkBox" id="vbox_locations"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="border_width">12</property> - <property name="orientation">vertical</property> - <property name="spacing">18</property> - <child> - <object class="GtkFrame" id="frame_locations"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label_xalign">0</property> - <property name="shadow_type">none</property> - <child> - <object class="GtkAlignment" id="alignment2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="top_padding">6</property> - <property name="left_padding">12</property> - <child> - <object class="GtkBox" id="vbox14"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">18</property> - <child> - <object class="GtkBox" id="vbox5"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="label8"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Special locations such as your <b>Home</b>, <b>Desktop</b> or <b>Documents</b> directory, can be easily toggled below. This will add or remove their real paths from the list underneath. - -If a directory is toggled to <b>Recurse</b>, it means that all sub-directories underneath it will also be indexed. Otherwise, only files immediately in that directory will be indexed.</property> - <property name="use_markup">True</property> - <property name="justify">fill</property> - <property name="wrap">True</property> - <property name="max_width_chars">40</property> - <property name="xalign">0</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="hbox7"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkToggleButton" id="togglebutton_home"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_markup" translatable="yes">Index Home Directory</property> - <property name="relief">none</property> - <signal name="toggled" handler="tracker_preferences_togglebutton_home_toggled_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xpad">1</property> - <property name="ypad">1</property> - <property name="pixel_size">24</property> - <property name="icon_name">user-home</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="togglebutton_desktop"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_markup" translatable="yes">Index Desktop Directory</property> - <property name="relief">none</property> - <signal name="toggled" handler="tracker_preferences_togglebutton_desktop_toggled_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xpad">1</property> - <property name="ypad">1</property> - <property name="pixel_size">24</property> - <property name="icon_name">user-desktop</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="togglebutton_documents"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_markup" translatable="yes">Index Documents Directory</property> - <property name="relief">none</property> - <signal name="toggled" handler="tracker_preferences_togglebutton_documents_toggled_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image11"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xpad">1</property> - <property name="pixel_size">24</property> - <property name="icon_name">folder-documents</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="togglebutton_music"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_markup" translatable="yes">Index Music Directory</property> - <property name="relief">none</property> - <signal name="toggled" handler="tracker_preferences_togglebutton_music_toggled_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image14"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xpad">1</property> - <property name="pixel_size">24</property> - <property name="icon_name">folder-music</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">3</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="togglebutton_pictures"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_markup" translatable="yes">Index Pictures Directory</property> - <property name="relief">none</property> - <signal name="toggled" handler="tracker_preferences_togglebutton_pictures_toggled_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image15"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xpad">1</property> - <property name="pixel_size">24</property> - <property name="icon_name">folder-pictures</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">4</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="togglebutton_videos"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_markup" translatable="yes">Index Videos Directory</property> - <property name="relief">none</property> - <signal name="toggled" handler="tracker_preferences_togglebutton_videos_toggled_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image16"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xpad">1</property> - <property name="pixel_size">24</property> - <property name="icon_name">folder-videos</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">5</property> - </packing> - </child> - <child> - <object class="GtkToggleButton" id="togglebutton_download"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_markup" translatable="yes">Index Download Directory</property> - <property name="relief">none</property> - <signal name="toggled" handler="tracker_preferences_togglebutton_download_toggled_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image17"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="xpad">1</property> - <property name="pixel_size">24</property> - <property name="icon_name">folder-download</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">6</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkBox" id="hbox_duplicate_warning"> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkImage" id="image5"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-dialog-warning</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="label14"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">One or more special locations have the same path. -Those which are the same are disabled!</property> - <property name="justify">fill</property> - <property name="wrap">True</property> - <property name="xalign">0</property> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="vbox3"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <child> - <object class="GtkBox" id="hbox1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkScrolledWindow" id="scrolledwindow1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="shadow_type">in</property> - <child> - <object class="GtkTreeView" id="treeview_index"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="model">liststore_index</property> - <property name="headers_clickable">False</property> - <property name="rules_hint">True</property> - <property name="search_column">0</property> - <child internal-child="selection"> - <object class="GtkTreeSelection" id="treeview-selection1"/> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="vbox23"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">6</property> - <child> - <object class="GtkButton" id="button_index_add"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_markup" translatable="yes">Add directory to be indexed</property> - <signal name="clicked" handler="tracker_preferences_button_index_add_clicked_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image3"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-add</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_index_remove"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_markup" translatable="yes">Remove directory from being indexed</property> - <signal name="clicked" handler="tracker_preferences_button_index_remove_clicked_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-remove</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <placeholder/> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">False</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - </child> - <child type="label"> - <object class="GtkLabel" id="label1"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Where is your content?</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - </object> - <packing> - <property name="position">1</property> - </packing> - </child> - <child type="tab"> - <object class="GtkLabel" id="label2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Locations</property> - </object> - <packing> - <property name="position">1</property> - <property name="tab_fill">False</property> - </packing> - </child> - <child> - <object class="GtkBox" id="vbox_ignored_content"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="border_width">12</property> - <property name="orientation">vertical</property> - <property name="spacing">18</property> - <child> - <object class="GtkFrame" id="frame_ignored_directories"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label_xalign">0</property> - <property name="shadow_type">none</property> - <child> - <object class="GtkAlignment" id="alignment13"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="top_padding">6</property> - <property name="left_padding">12</property> - <child> - <object class="GtkBox" id="hbox2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">12</property> - <property name="homogeneous">True</property> - <child> - <object class="GtkBox" id="vbox_ignored_directories"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="label10"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Glob patterns to ignore:</property> - <property name="xalign">0</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="hbox6"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkScrolledWindow" id="scrolledwindow2"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="shadow_type">in</property> - <child> - <object class="GtkTreeView" id="treeview_ignored_directories"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="model">liststore_ignored_directories</property> - <property name="headers_visible">False</property> - <property name="rules_hint">True</property> - <property name="search_column">0</property> - <child internal-child="selection"> - <object class="GtkTreeSelection" id="treeview-selection2"/> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="vbox25"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">6</property> - <child> - <object class="GtkButton" id="button_ignored_directories_globs_add"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_text" translatable="yes">Opens text entry for glob patterns</property> - <signal name="clicked" handler="tracker_preferences_button_ignored_directories_globs_add_clicked_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image6"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-add</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_ignored_directories_remove"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <signal name="clicked" handler="tracker_preferences_button_ignored_directories_remove_clicked_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image7"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-remove</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_ignored_directories_globs_add1"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="tooltip_text" translatable="yes">Opens the filechooser dialogue</property> - <signal name="clicked" handler="tracker_preferences_button_ignored_directories_add_clicked_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image2"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-directory</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">2</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="vbox_ignored_directories_with_content"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="label5"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">With specific files:</property> - <property name="xalign">0</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="hbox5"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkScrolledWindow" id="scrolledwindow5"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="shadow_type">in</property> - <child> - <object class="GtkTreeView" id="treeview_ignored_directories_with_content"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="model">liststore_ignored_directories_with_content</property> - <property name="headers_visible">False</property> - <property name="rules_hint">True</property> - <property name="search_column">0</property> - <child internal-child="selection"> - <object class="GtkTreeSelection" id="treeview-selection3"/> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="vbox8"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">6</property> - <child> - <object class="GtkButton" id="button_ignored_directories_with_content_add"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <signal name="clicked" handler="tracker_preferences_button_ignored_directories_with_content_add_clicked_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image12"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-add</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_ignored_directories_with_content_remove"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <signal name="clicked" handler="tracker_preferences_button_ignored_directories_with_content_remove_clicked_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image13"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-remove</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <placeholder/> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - </child> - <child type="label"> - <object class="GtkLabel" id="label6"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Directories</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkFrame" id="frame_ignored_files"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label_xalign">0</property> - <property name="shadow_type">none</property> - <child> - <object class="GtkAlignment" id="alignment14"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="top_padding">6</property> - <property name="left_padding">12</property> - <child> - <object class="GtkBox" id="vbox_ignored_files"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">6</property> - <child> - <object class="GtkLabel" id="label11"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Glob patterns to ignore:</property> - <property name="xalign">0</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="hbox3"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">6</property> - <child> - <object class="GtkScrolledWindow" id="scrolledwindow3"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="shadow_type">in</property> - <child> - <object class="GtkTreeView" id="treeview_ignored_files"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="tooltip_text" translatable="yes">Globbing patterns can be used here, for example: “*bar*”. -Most commonly this is used to ignore directories like *~, *.o, *.la, etc</property> - <property name="model">liststore_ignored_files</property> - <property name="headers_visible">False</property> - <property name="headers_clickable">False</property> - <property name="rules_hint">True</property> - <property name="search_column">0</property> - <child internal-child="selection"> - <object class="GtkTreeSelection" id="treeview-selection4"/> - </child> - </object> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkBox" id="vbox6"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">6</property> - <child> - <object class="GtkButton" id="button_ignored_files_add"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <signal name="clicked" handler="tracker_preferences_button_ignored_files_add_clicked_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image8"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-add</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkButton" id="button_ignored_files_remove"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <signal name="clicked" handler="tracker_preferences_button_ignored_files_remove_clicked_cb" swapped="no"/> - <child> - <object class="GtkImage" id="image9"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="stock">gtk-remove</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <placeholder/> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - </object> - </child> - <child type="label"> - <object class="GtkLabel" id="label9"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Files</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="position">2</property> - </packing> - </child> - <child type="tab"> - <object class="GtkLabel" id="label3"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Ignored Content</property> - </object> - <packing> - <property name="position">2</property> - <property name="tab_fill">False</property> - </packing> - </child> - <child> - <object class="GtkBox" id="vbox_control"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="border_width">12</property> - <property name="orientation">vertical</property> - <property name="spacing">18</property> - <child> - <object class="GtkFrame" id="frame_what_is_indexed"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label_xalign">0</property> - <property name="shadow_type">none</property> - <child> - <object class="GtkAlignment" id="alignment9"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="top_padding">6</property> - <property name="left_padding">12</property> - <child> - <object class="GtkBox" id="vbox4"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <property name="spacing">18</property> - <child> - <object class="GtkBox" id="vbox10"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="orientation">vertical</property> - <child> - <object class="GtkCheckButton" id="checkbutton_index_file_content"> - <property name="label" translatable="yes">Index content of _files found</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="xalign">0</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="tracker_preferences_checkbutton_index_file_content_toggled_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkCheckButton" id="checkbutton_index_numbers"> - <property name="label" translatable="yes">Index _numbers</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="use_underline">True</property> - <property name="xalign">0</property> - <property name="draw_indicator">True</property> - <signal name="toggled" handler="tracker_preferences_checkbutton_index_numbers_toggled_cb" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - </object> - </child> - </object> - </child> - <child type="label"> - <object class="GtkLabel" id="label19"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">What is indexed?</property> - <attributes> - <attribute name="weight" value="bold"/> - </attributes> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <placeholder/> - </child> - </object> - <packing> - <property name="position">3</property> - </packing> - </child> - <child type="tab"> - <object class="GtkLabel" id="label16"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="label" translatable="yes">Control</property> - </object> - <packing> - <property name="position">3</property> - <property name="tab_fill">False</property> - </packing> - </child> - </object> - <packing> - <property name="expand">True</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> - <action-widgets> - <action-widget response="-10">button_apply</action-widget> - <action-widget response="-7">button_close</action-widget> - </action-widgets> - </object> -</interface> diff --git a/src/tracker-preferences/tracker-preferences.vala b/src/tracker-preferences/tracker-preferences.vala deleted file mode 100644 index f6bfff007..000000000 --- a/src/tracker-preferences/tracker-preferences.vala +++ /dev/null @@ -1,998 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * Copyright (C) 2009, Nokia - * - * 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. - */ - -using Gtk; -using GLib; -using Tracker; -using Posix; - -[CCode (cname = "TRACKER_UI_DIR")] -extern static const string UIDIR; - -[CCode (cname = "SRCDIR")] -extern static const string SRCDIR; - -public class Tracker.Preferences { - private GLib.Settings settings_fts = null; - private GLib.Settings settings_miner_fs = null; - private GLib.Settings settings_extract = null; - - private bool suggest_restart = false; - - private const string UI_FILE = "tracker-preferences.ui"; - private const string HOME_STRING = "$HOME"; - private string HOME_STRING_EVALUATED; - - private UserDirectory[] ignored_user_directories = null; - - private Window window; - private CheckButton checkbutton_enable_index_on_battery_first_time; - private CheckButton checkbutton_enable_index_on_battery; - private CheckButton checkbutton_enable_monitoring; - private CheckButton checkbutton_index_removable_media; - private CheckButton checkbutton_index_optical_discs; - private Scale hscale_disk_space_limit; - private RadioButton radiobutton_sched_idle_always; - private RadioButton radiobutton_sched_idle_first_index; - private RadioButton radiobutton_sched_idle_never; - private Scale hscale_drop_device_threshold; - private Gtk.ListStore liststore_index; - private Gtk.ListStore liststore_ignored_directories; - private Gtk.ListStore liststore_ignored_files; - private Gtk.ListStore liststore_ignored_directories_with_content; - private TreeView treeview_index; - private TreeView treeview_ignored_directories; - private TreeView treeview_ignored_directories_with_content; - private TreeView treeview_ignored_files; - private TreeViewColumn treeviewcolumn_index1; - private TreeViewColumn treeviewcolumn_index2; - private ToggleButton togglebutton_home; - private ToggleButton togglebutton_desktop; - private ToggleButton togglebutton_documents; - private ToggleButton togglebutton_music; - private ToggleButton togglebutton_pictures; - private ToggleButton togglebutton_videos; - private ToggleButton togglebutton_download; - private CheckButton checkbutton_index_file_content; - private CheckButton checkbutton_index_numbers; - private Box hbox_duplicate_warning; - private Notebook notebook; - - public Preferences () { - debug ("Getting current settings"); - - HOME_STRING_EVALUATED = dir_from_config (HOME_STRING); - - settings_fts = new GLib.Settings ("org.freedesktop.Tracker.FTS"); - /* settings_fts.delay(); */ - - settings_miner_fs = new GLib.Settings ("org.freedesktop.Tracker.Miner.Files"); - /* settings_miner_fs.delay(); */ - - settings_extract = new GLib.Settings ("org.freedesktop.Tracker.Extract"); - /* settings_extract.delay(); */ - - // Change notification for any key in the schema - settings_fts.changed.connect ((key) => { - print ("tracker-fts: Key '%s' changed\n", key); - }); - - settings_miner_fs.changed.connect ((key) => { - print ("tracker-miner-fs: Key '%s' changed\n", key); - }); - - settings_extract.changed.connect ((key) => { - print ("tracker-extract: Key '%s' changed\n", key); - }); - } - - public void setup_ui () { - var builder = new Gtk.Builder (); - - try { - debug ("Trying to use UI file:'%s'", SRCDIR + UI_FILE); - builder.add_from_file (SRCDIR + UI_FILE); - } catch (GLib.Error e) { - //now the install location - try { - debug ("Trying to use UI file:'%s'", UIDIR + UI_FILE); - builder.add_from_file (UIDIR + UI_FILE); - } catch (GLib.Error e) { - var msg = new MessageDialog (null, - DialogFlags.MODAL, - MessageType.ERROR, - ButtonsType.CANCEL, - "Failed to load UI file, %s\n", - e.message); - msg.run (); - Gtk.main_quit(); - } - } - - // Get widgets from .ui file - window = builder.get_object ("tracker-preferences") as Window; - notebook = builder.get_object ("notebook") as Notebook; - - checkbutton_enable_monitoring = builder.get_object ("checkbutton_enable_monitoring") as CheckButton; - checkbutton_enable_index_on_battery = builder.get_object ("checkbutton_enable_index_on_battery") as CheckButton; - checkbutton_enable_index_on_battery_first_time = builder.get_object ("checkbutton_enable_index_on_battery_first_time") as CheckButton; - checkbutton_index_removable_media = builder.get_object ("checkbutton_index_removable_media") as CheckButton; - checkbutton_index_optical_discs = builder.get_object ("checkbutton_index_optical_discs") as CheckButton; - checkbutton_index_optical_discs.set_sensitive (checkbutton_index_removable_media.active); - hscale_disk_space_limit = builder.get_object ("hscale_disk_space_limit") as Scale; - radiobutton_sched_idle_always = builder.get_object ("radiobutton_sched_idle_always") as RadioButton; - radiobutton_sched_idle_first_index = builder.get_object ("radiobutton_sched_idle_first_index") as RadioButton; - radiobutton_sched_idle_never = builder.get_object ("radiobutton_sched_idle_never") as RadioButton; - hscale_drop_device_threshold = builder.get_object ("hscale_drop_device_threshold") as Scale; - togglebutton_home = builder.get_object ("togglebutton_home") as ToggleButton; - togglebutton_desktop = builder.get_object ("togglebutton_desktop") as ToggleButton; - togglebutton_documents = builder.get_object ("togglebutton_documents") as ToggleButton; - togglebutton_music = builder.get_object ("togglebutton_music") as ToggleButton; - togglebutton_pictures = builder.get_object ("togglebutton_pictures") as ToggleButton; - togglebutton_videos = builder.get_object ("togglebutton_videos") as ToggleButton; - togglebutton_download = builder.get_object ("togglebutton_download") as ToggleButton; - checkbutton_index_file_content = builder.get_object ("checkbutton_index_file_content") as CheckButton; - checkbutton_index_numbers = builder.get_object ("checkbutton_index_numbers") as CheckButton; - hbox_duplicate_warning = builder.get_object ("hbox_duplicate_warning") as Box; - - treeview_index = builder.get_object ("treeview_index") as TreeView; - treeviewcolumn_index1 = builder.get_object ("treeviewcolumn_index1") as TreeViewColumn; - treeviewcolumn_index2 = builder.get_object ("treeviewcolumn_index1") as TreeViewColumn; - treeview_ignored_directories = builder.get_object ("treeview_ignored_directories") as TreeView; - treeview_ignored_directories_with_content = builder.get_object ("treeview_ignored_directories_with_content") as TreeView; - treeview_ignored_files = builder.get_object ("treeview_ignored_files") as TreeView; - - treeview_setup (treeview_index, _("Directory"), true, false); - treeview_setup (treeview_ignored_directories, _("Directory"), false, true); - treeview_setup (treeview_ignored_directories_with_content, _("Directory"), false, true); - treeview_setup (treeview_ignored_files, _("File"), false, true); - - liststore_index = builder.get_object ("liststore_index") as Gtk.ListStore; - liststore_index.set_sort_column_id (0, Gtk.SortType.ASCENDING); - liststore_ignored_directories = builder.get_object ("liststore_ignored_directories") as Gtk.ListStore; - liststore_ignored_files = builder.get_object ("liststore_ignored_files") as Gtk.ListStore; - liststore_ignored_directories_with_content = builder.get_object ("liststore_ignored_directories_with_content") as Gtk.ListStore; - - // Set initial values - checkbutton_enable_index_on_battery.active = settings_miner_fs.get_boolean ("index-on-battery"); - checkbutton_enable_index_on_battery_first_time.set_sensitive (!checkbutton_enable_index_on_battery.active); - checkbutton_enable_index_on_battery_first_time.active = settings_miner_fs.get_boolean ("index-on-battery-first-time"); - checkbutton_enable_monitoring.active = settings_miner_fs.get_boolean ("enable-monitors"); - checkbutton_index_removable_media.active = settings_miner_fs.get_boolean ("index-removable-devices"); - checkbutton_index_optical_discs.set_sensitive (checkbutton_index_removable_media.active); - checkbutton_index_optical_discs.active = settings_miner_fs.get_boolean ("index-optical-discs"); - hscale_disk_space_limit.set_value ((double) settings_miner_fs.get_int ("low-disk-space-limit")); - hscale_drop_device_threshold.set_value ((double) settings_miner_fs.get_int ("removable-days-threshold")); - - // What do we do here if extract/miner-fs are different, we - // could use inconsistent states for radiobuttons, but instead - // we're going to just assume miner-fs is the lead here and - // overwrite the extract config with anything we change here. - int sched_idle = settings_miner_fs.get_enum ("sched-idle"); - - if (sched_idle == 0) { - radiobutton_sched_idle_always.active = true; - } else if (sched_idle == 1) { - radiobutton_sched_idle_first_index.active = true; - } else if (sched_idle == 2) { - radiobutton_sched_idle_never.active = true; - } else { - // If broken value set, use default. - radiobutton_sched_idle_first_index.active = true; - } - - // Evaluate any user directories which have same target directory - sanitize_user_dirs (); - - // Populate and toggle user directories - model_populate (liststore_index, settings_miner_fs.get_strv ("index-recursive-directories"), true, true); - model_populate (liststore_index, settings_miner_fs.get_strv ("index-single-directories"), true, false); - model_populate (liststore_ignored_directories, settings_miner_fs.get_strv ("ignored-directories"), false, false); - model_populate (liststore_ignored_files, settings_miner_fs.get_strv ("ignored-files"), false, false); - model_populate (liststore_ignored_directories_with_content, settings_miner_fs.get_strv ("ignored-directories-with-content"), false, false); - - if (ignored_user_directories.length > 0) { - hbox_duplicate_warning.show (); - } else { - hbox_duplicate_warning.hide (); - } - - togglebutton_home.active = model_contains (liststore_index, HOME_STRING_EVALUATED); - togglebutton_desktop.active = model_contains (liststore_index, "&DESKTOP"); - togglebutton_documents.active = model_contains (liststore_index, "&DOCUMENTS"); - togglebutton_music.active = model_contains (liststore_index, "&MUSIC"); - togglebutton_pictures.active = model_contains (liststore_index, "&PICTURES"); - togglebutton_videos.active = model_contains (liststore_index, "&VIDEOS"); - togglebutton_download.active = model_contains (liststore_index, "&DOWNLOAD"); - - checkbutton_index_file_content.active = settings_fts.get_int ("max-words-to-index") > 0; - checkbutton_index_numbers.active = settings_fts.get_boolean ("ignore-numbers") != true; - - // Connect signals - // builder.connect_signals (null); - builder.connect_signals_full (connect_signals); - } - - public void show () { - setup_ui (); - - window.show (); - } - - // This function is used to fix up the parameter ordering for callbacks - // from the .ui file which has the callback names. - [CCode (instance_pos = -1)] - private void connect_signals (Gtk.Builder builder, GLib.Object object, - string signal_name, string handler_name, - GLib.Object? connect_object, - GLib.ConnectFlags flags) { - var module = Module.open (null, ModuleFlags.BIND_LAZY); - void* sym; - - if (!module.symbol (handler_name, out sym)) { - warning ("Symbol not found! %s\n", handler_name); - } else { - Signal.connect (object, signal_name, (GLib.Callback) sym, this); - } - } - - [CCode (instance_pos = -1)] - public void response_cb (Dialog source, int response_id) { - debug ("Got response id %d (apply:%d, close:%d)", response_id, ResponseType.APPLY, ResponseType.CLOSE); - - switch (response_id) { - case ResponseType.APPLY: - debug ("Converting directories for storage"); - - settings_miner_fs.set_strv ("index-single-directories", model_to_strv (liststore_index, true, false)); - settings_miner_fs.set_strv ("index-recursive-directories", model_to_strv (liststore_index, true, true)); - settings_miner_fs.set_strv ("ignored-directories", model_to_strv (liststore_ignored_directories, false, false)); - settings_miner_fs.set_strv ("ignored-files", model_to_strv (liststore_ignored_files, false, false)); - settings_miner_fs.set_strv ("ignored-directories-with-content", model_to_strv (liststore_ignored_directories_with_content, false, false)); - - settings_miner_fs.set_int ("low-disk-space-limit", (int) hscale_disk_space_limit.get_value ()); - settings_miner_fs.set_int ("removable-days-threshold", (int) hscale_drop_device_threshold.get_value ()); - - int sched_idle; - - if (radiobutton_sched_idle_always.active) { - sched_idle = 0; - } else if (radiobutton_sched_idle_first_index.active) { - sched_idle = 1; - } else if (radiobutton_sched_idle_never.active) { - sched_idle = 2; - } else { - assert_not_reached (); - } - - // What do we do here if extract/miner-fs are different, we - // could use inconsistent states for radiobuttons, but instead - // we're going to just assume miner-fs is the lead here and - // overwrite the extract config with anything we change here. - settings_miner_fs.set_enum ("sched-idle", sched_idle); - settings_extract.set_enum ("sched-idle", sched_idle); - - debug ("Saving settings..."); - settings_fts.apply (); - debug (" tracker-fts: Done"); - settings_miner_fs.apply (); - debug (" tracker-miner-fs: Done"); - settings_extract.apply (); - debug (" tracker-extract: Done"); - - if (suggest_restart) { - Dialog dialog = new MessageDialog (window, - DialogFlags.DESTROY_WITH_PARENT, - MessageType.INFO, - ButtonsType.CLOSE, - _("Some of the requested changes will take effect on the next session restart."), - null); - /* Reset this suggestion */ - suggest_restart = false; - dialog.run (); - dialog.destroy (); - } - - return; - - default: - break; - } - - Gtk.main_quit (); - } - - [CCode (instance_pos = -1)] - public void checkbutton_enable_monitoring_toggled_cb (CheckButton source) { - settings_miner_fs.set_boolean ("enable-monitors", source.active); - } - - [CCode (instance_pos = -1)] - public void checkbutton_enable_index_on_battery_toggled_cb (CheckButton source) { - settings_miner_fs.set_boolean ("index-on-battery", source.active); - checkbutton_enable_index_on_battery_first_time.set_sensitive (!source.active); - } - - [CCode (instance_pos = -1)] - public void checkbutton_enable_index_on_battery_first_time_toggled_cb (CheckButton source) { - settings_miner_fs.set_boolean ("index-on-battery-first-time", source.active); - } - - [CCode (instance_pos = -1)] - public void checkbutton_index_removable_media_toggled_cb (CheckButton source) { - settings_miner_fs.set_boolean ("index-removable-devices", source.active); - checkbutton_index_optical_discs.set_sensitive (source.active); - } - - [CCode (instance_pos = -1)] - public void checkbutton_index_optical_discs_toggled_cb (CheckButton source) { - settings_miner_fs.set_boolean ("index-optical-discs", source.active); - } - - [CCode (instance_pos = -1)] - public string hscale_disk_space_limit_format_value_cb (Scale source, double value) { - if (((int) value) == -1) { - /* To translators: This is a feature that is - * disabled for disk space checking. - */ - return _("Disabled"); - } - - return "%d%%".printf ((int) value); - } - - [CCode (instance_pos = -1)] - public string hscale_drop_device_threshold_format_value_cb (Scale source, double value) { - if (((int) value) == 0) { - /* To translators: This is a feature that is - * disabled for removing a device from a - * database cache. - */ - return _("Disabled"); - } - - return "%d".printf ((int) value); - } - - [CCode (instance_pos = -1)] - public void button_index_add_clicked_cb (Button source) { - store_add_dir (liststore_index); - } - - [CCode (instance_pos = -1)] - public void button_index_remove_clicked_cb (Button source) { - store_del_dir (treeview_index); - } - - [CCode (instance_pos = -1)] - public void button_ignored_directories_globs_add_clicked_cb (Button source) { - store_add_value_dialog (liststore_ignored_directories); - } - - [CCode (instance_pos = -1)] - public void button_ignored_directories_add_clicked_cb (Button source) { - store_add_dir (liststore_ignored_directories); - } - - [CCode (instance_pos = -1)] - public void button_ignored_directories_remove_clicked_cb (Button source) { - store_del_dir (treeview_ignored_directories); - } - - [CCode (instance_pos = -1)] - public void button_ignored_directories_with_content_add_clicked_cb (Button source) { - store_add_value_dialog (liststore_ignored_directories_with_content); - } - - [CCode (instance_pos = -1)] - public void button_ignored_directories_with_content_remove_clicked_cb (Button source) { - store_del_dir (treeview_ignored_directories_with_content); - } - - [CCode (instance_pos = -1)] - public void button_ignored_files_add_clicked_cb (Button source) { - store_add_value_dialog (liststore_ignored_files); - } - - [CCode (instance_pos = -1)] - public void button_ignored_files_remove_clicked_cb (Button source) { - store_del_dir (treeview_ignored_files); - } - - private void togglebutton_directory_update_model (ToggleButton source, Gtk.ListStore store, string to_check) { - if (source.active && !model_contains (store, to_check)) { - TreeIter iter; - liststore_index.append (out iter); - var v = Value (typeof (string)); - v.set_string (to_check); - - bool recurse = to_check != HOME_STRING_EVALUATED; - liststore_index.set_value (iter, 0, v); - liststore_index.set_value (iter, 1, recurse); - } - - if (!source.active && model_contains (store, to_check)) { - bool valid; - TreeIter iter; - - valid = store.get_iter_first (out iter); - while (valid) { - Value value; - store.get_value (iter, 0, out value); - if (value.get_string () == to_check) { - store.remove (iter); - valid = store.get_iter_first (out iter); - } else { - valid = store.iter_next (ref iter); - } - } - } - } - - [CCode (instance_pos = -1)] - public void togglebutton_home_toggled_cb (ToggleButton source) { - togglebutton_directory_update_model (source, liststore_index, HOME_STRING_EVALUATED); - } - - [CCode (instance_pos = -1)] - public void togglebutton_desktop_toggled_cb (ToggleButton source) { - togglebutton_directory_update_model (source, liststore_index, Environment.get_user_special_dir (UserDirectory.DESKTOP)); - } - - [CCode (instance_pos = -1)] - public void togglebutton_documents_toggled_cb (ToggleButton source) { - togglebutton_directory_update_model (source, liststore_index, Environment.get_user_special_dir (UserDirectory.DOCUMENTS)); - } - - [CCode (instance_pos = -1)] - public void togglebutton_music_toggled_cb (ToggleButton source) { - togglebutton_directory_update_model (source, liststore_index, Environment.get_user_special_dir (UserDirectory.MUSIC)); - } - - [CCode (instance_pos = -1)] - public void togglebutton_pictures_toggled_cb (ToggleButton source) { - togglebutton_directory_update_model (source, liststore_index, Environment.get_user_special_dir (UserDirectory.PICTURES)); - } - - [CCode (instance_pos = -1)] - public void togglebutton_videos_toggled_cb (ToggleButton source) { - togglebutton_directory_update_model (source, liststore_index, Environment.get_user_special_dir (UserDirectory.VIDEOS)); - } - - [CCode (instance_pos = -1)] - public void togglebutton_download_toggled_cb (ToggleButton source) { - togglebutton_directory_update_model (source, liststore_index, Environment.get_user_special_dir (UserDirectory.DOWNLOAD)); - } - - private void reset_parser () { - string path = Path.build_filename (Environment.get_user_cache_dir (), "tracker", "parser-sha1.txt", null); - FileUtils.unlink (path); - } - - [CCode (instance_pos = -1)] - public void checkbutton_index_file_content_toggled_cb (CheckButton source) { - // FIXME: Should make number configurable, 10000 is the default. - if (source.active) { - settings_fts.reset ("max-words-to-index"); - } else { - settings_fts.set_int ("max-words-to-index", 0); - } - - reset_parser (); - suggest_restart = true; - } - - [CCode (instance_pos = -1)] - public void checkbutton_index_numbers_toggled_cb (CheckButton source) { - settings_fts.set_boolean ("ignore-numbers", !source.active); - reset_parser (); - suggest_restart = true; - } - - private void toggles_update (UserDirectory[] matches, bool active) { - // Check if we need to untoggle a button - foreach (UserDirectory ud in matches) { - switch (ud) { - case UserDirectory.DESKTOP: - togglebutton_desktop.active = active; - break; - case UserDirectory.DOCUMENTS: - togglebutton_documents.active = active; - break; - case UserDirectory.DOWNLOAD: - togglebutton_download.active = active; - break; - case UserDirectory.MUSIC: - togglebutton_music.active = active; - break; - case UserDirectory.PICTURES: - togglebutton_pictures.active = active; - break; - case UserDirectory.VIDEOS: - togglebutton_videos.active = active; - break; - } - } - } - - private void store_add_value_dialog (Gtk.ListStore store) { - Dialog dialog; - Entry entry; - Container content_area; - - dialog = new Dialog.with_buttons (_("Enter value"), - window, - DialogFlags.DESTROY_WITH_PARENT, - _("_Cancel"), ResponseType.CANCEL, - _("_OK"), ResponseType.ACCEPT); - - dialog.set_default_response(ResponseType.ACCEPT); - content_area = (Container) dialog.get_content_area (); - entry = new Entry (); - entry.set_activates_default (true); - entry.show (); - content_area.add (entry); - - if (dialog.run () == ResponseType.ACCEPT) { - string text = entry.get_text (); - - if (text != null && text != "") { - TreeIter iter; - store.append (out iter); - var v = Value (typeof (string)); - v.set_string (text); - store.set_value (iter, 0, v); - } - } - - dialog.destroy (); - } - - private void store_add_dir (Gtk.ListStore store) { - FileChooserDialog dialog = new FileChooserDialog (_("Select directory"), - window, - FileChooserAction.SELECT_FOLDER, - _("_Cancel"), - ResponseType.CANCEL, - _("_OK"), - ResponseType.ACCEPT); - - while (true) { - if (dialog.run () == ResponseType.ACCEPT) { - TreeIter iter; - File f; - - f = dialog.get_file (); - string path = f.get_path (); - - if (model_contains (store, path)) { - MessageDialog md = new MessageDialog (dialog, - DialogFlags.DESTROY_WITH_PARENT, - MessageType.ERROR, - ButtonsType.CLOSE, - _("That directory is already selected as a location to index"), - null); - md.run (); - md.destroy (); - continue; - } - - string dir = f.get_path (); - - // Check which UserDirectorys we match with str - UserDirectory[] matches = dir_match_user_directories (dir); - - // Add to store - store.append (out iter); - var v = Value (typeof (string)); - v.set_string (dir); - store.set_value (iter, 0, v); - - toggles_update (matches, true); - - if (dir == HOME_STRING_EVALUATED) - togglebutton_home.active = true; - - } - - break; - } - - dialog.destroy (); - } - - private void store_del_dir (TreeView view) { - List<TreePath> list; - Gtk.ListStore store; - TreeModel model; - - TreeSelection selection = view.get_selection (); - list = selection.get_selected_rows (out model); - - store = (Gtk.ListStore) model; - - foreach (TreePath path in list) { - TreeIter iter; - - if (!model.get_iter (out iter, path)) { - continue; - } - - Value value; - - model.get_value (iter, 0, out value); - string dir = value.get_string (); - - // Check which UserDirectorys we match with str - UserDirectory[] matches = dir_match_user_directories (dir); - - store.remove (iter); - - // Check if we need to untoggle a button - toggles_update (matches, false); - - if (dir == HOME_STRING_EVALUATED) - togglebutton_home.active = false; - } - } - - private UserDirectory[] dir_match_user_directories (string input) { - UserDirectory[] matches = {}; - int i; - - for (i = 0; i < UserDirectory.N_DIRECTORIES; i++) { - UserDirectory ud = (UserDirectory) i; - unowned string dir = null; - - dir = Environment.get_user_special_dir (ud); - if (input == dir) { - matches += ud; - } - } - - return matches; - } - - private string dir_to_config (string input) { - string output = input; - - if (HOME_STRING_EVALUATED != null && HOME_STRING_EVALUATED == input) { - return HOME_STRING; - } - - for (int i = 0; i < UserDirectory.N_DIRECTORIES; i++) { - UserDirectory ud = (UserDirectory) i; - unowned string dir = null; - - dir = Environment.get_user_special_dir (ud); - if (input == dir) { - // Convert 'G_USER_DIRECTORY_FOO' to '&FOO' - string ud_string = ud.to_string (); - output = "&%s".printf (ud_string.substring (ud_string.last_index_of_char ('_') + 1, -1)); - } - } - - return output; - } - - private string dir_from_config (string input) { - string output = input; - - if (input.has_prefix ("&")) { - unowned string dir = null; - - // Convert '&FOO' to 'G_USER_DIRECTORY_FOO' - string ud_input = "G_USER_DIRECTORY_%s".printf (input.next_char ()); - - for (int i = 0; i < UserDirectory.N_DIRECTORIES && dir == null; i++) { - UserDirectory ud = (UserDirectory) i; - - if (ud_input == ud.to_string ()) { - dir = Environment.get_user_special_dir (ud); - } - } - - // debug ("Found dir '%s' evaluates to '%s'", input, dir); - - if (dir != null) - output = dir; - } else if (input.has_prefix ("$")) { - unowned string env = Environment.get_variable (input.substring (1, -1)); - - // debug ("Found env '%s' (%s) evaluates to '%s'", input, input.substring (1, -1), env); - - if (env != null) - output = env; - } - - return output; - } - - private string[] model_to_strv (Gtk.ListStore model, bool recurse_required, bool recurse_value) { - string[] list = {}; - TreeIter iter; - bool valid; - - for (valid = model.get_iter_first (out iter); - valid; - valid = model.iter_next (ref iter)) { - Value value; - - model.get_value (iter, 0, out value); - - if (recurse_required) { - Value recurse; - - model.get_value (iter, 1, out recurse); - - if (recurse_value != recurse.get_boolean ()) - continue; - } - - // Convert from real value to config values, - // e.g. '$HOME/Desktop' to '&DESKTOP' - string dir = dir_to_config (value.get_string ()); - list += dir; - } - - return list; - } - - public bool model_contains (TreeModel model, string needle) { - TreeIter iter; - string needle_evaluated; - bool valid; - - needle_evaluated = dir_from_config (needle); - - for (valid = model.get_iter_first (out iter); - valid; - valid = model.iter_next (ref iter)) { - Value value; - - model.get_value (iter, 0, out value); - - if (value.get_string () == needle_evaluated) { - return true; - } - } - - return false; - } - - private void model_populate (Gtk.ListStore model, string[] list, bool have_recurse, bool recurse) { - int position = 0; - - foreach (string s in list) { - // Convert any dirs from config to real values - bool ignore = false; - - // Don't insert configs if toggle is not sensitive - foreach (UserDirectory ud in ignored_user_directories) { - string ud_string = ud.to_string (); - string output = "&%s".printf (ud_string.substring (ud_string.last_index_of_char ('_') + 1, -1)); - - if (s == output) { - ignore = true; - break; - } - } - - if (ignore) { - debug ("Ignoring '%s' (duplicates other entries in config)", s); - continue; - } - - string str = dir_from_config (s); - - try { - if (have_recurse) - model.insert_with_values (null, - position++, - 0, - Filename.to_utf8 (str, - -1, - null, - null), - 1, - recurse, - -1); - else - model.insert_with_values (null, - position++, - 0, - Filename.to_utf8 (str, - -1, - null, - null), - -1); - } catch (GLib.ConvertError e) { - print ("Could not convert filename to UTF8: %s", e.message); - } - } - } - - private void treeview_setup (TreeView view, string title, bool show_recurse_column, bool sort) { - TreeViewColumn column; - GLib.List<weak TreeViewColumn> columns = view.get_columns (); - - // Needed to fix glade mess - foreach (TreeViewColumn c in columns) { - view.remove_column (c); - } - - column = new TreeViewColumn.with_attributes (title, - new CellRendererText (), - "text", 0, - null); - column.set_expand (true); - view.append_column (column); - - if (show_recurse_column) { - Gtk.ListStore store = view.get_model () as Gtk.ListStore; - CellRendererToggle cell = new CellRendererToggle (); - - column = new TreeViewColumn.with_attributes (_("Recurse"), - cell, - "active", true, - null); - column.set_expand (false); - view.append_column (column); - - cell.toggled.connect ((toggle, path) => { - var tree_path = new TreePath.from_string (path); - TreeIter iter; - - store.get_iter (out iter, tree_path); - store.set (iter, 1, !toggle.active); - }); - } - - if (sort) { - TreeSortable sortable = view.get_model() as TreeSortable; - sortable.set_sort_column_id (0, SortType.ASCENDING); - } - } - - private void sanitize_user_dirs () { - string[] all_dirs = null; - - all_dirs += HOME_STRING_EVALUATED; - - for (int i = 0; i < UserDirectory.N_DIRECTORIES; i++) { - UserDirectory ud = (UserDirectory) i; - - string dir = Environment.get_user_special_dir (ud); - if (dir == null) { - continue; - } - - foreach (string d in all_dirs) { - if (d == dir) { - debug ("Directory '%s' duplicated in XDG dir %d", d, ud); - - switch (ud) { - case UserDirectory.DESKTOP: - case UserDirectory.DOCUMENTS: - case UserDirectory.DOWNLOAD: - case UserDirectory.MUSIC: - case UserDirectory.PICTURES: - case UserDirectory.VIDEOS: - ignored_user_directories += ud; - break; - - default: - // We don't care about others, we don't - // have toggle buttons for them - break; - } - - break; - } - } - - // Add dir to list of dirs we know about to filter - // out subsequent dirs - all_dirs += dir; - } - - foreach (UserDirectory ud in ignored_user_directories) { - switch (ud) { - case UserDirectory.DESKTOP: - togglebutton_desktop.sensitive = false; - break; - case UserDirectory.DOCUMENTS: - togglebutton_documents.sensitive = false; - break; - case UserDirectory.DOWNLOAD: - togglebutton_download.sensitive = false; - break; - case UserDirectory.MUSIC: - togglebutton_music.sensitive = false; - break; - case UserDirectory.PICTURES: - togglebutton_pictures.sensitive = false; - break; - case UserDirectory.VIDEOS: - togglebutton_videos.sensitive = false; - break; - default: - break; - } - } - } -} - -static bool print_version = false; - -const OptionEntry[] options = { - { "version", - 'V', - 0, - OptionArg.NONE, - ref print_version, - N_("Print version"), - null }, - { null } -}; - -static int main (string[] args) { - OptionContext context = new OptionContext (_("Desktop Search preferences")); - - try { - context.set_help_enabled (true); - context.add_main_entries (options, null); - context.add_group (Gtk.get_option_group (true)); - context.parse (ref args); - } catch (Error e) { - printerr (e.message + "\n\n"); - printerr (context.get_help (true, null)); - return 1; - } - - if (print_version) { - string about = ""; - string license = ""; - - about += "Tracker " + Config.PACKAGE_VERSION + "\n"; - - license += "This program is free software and comes without any warranty.\n"; - license += "It is licensed under version 2 or later of the General Public "; - license += "License which can be viewed at:\n"; - license += "\n"; - license += " http://www.gnu.org/licenses/gpl.txt\n"; - - print ("\n" + about + "\n" + license + "\n"); - return 0; - } - - Gtk.init (ref args); - - Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.LOCALEDIR); - Intl.bind_textdomain_codeset (Config.GETTEXT_PACKAGE, "UTF-8"); - Intl.textdomain (Config.GETTEXT_PACKAGE); - - Tracker.Preferences p = new Tracker.Preferences (); - p.show(); - - Gtk.main (); - - return 0; -} diff --git a/src/tracker-preferences/tracker-status-icon-config.vapi b/src/tracker-preferences/tracker-status-icon-config.vapi deleted file mode 100644 index d2a0ae722..000000000 --- a/src/tracker-preferences/tracker-status-icon-config.vapi +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (C) 2008-2009, Nokia - * - * 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. - */ - -namespace Tracker { - [CCode (cheader_filename = "tracker-status-icon/tracker-icon-config.h")] - public class IconConfig : GLib.Object { - public IconConfig.with_domain (string domain); - - public int visibility { get; set; } - public bool save (); - } -} - 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 b4849c1ff..000000000 --- a/src/tracker-writeback/Makefile.am +++ /dev/null @@ -1,98 +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) \ - $(man_MANS) - -EXTRA_DIST = \ - $(service_DATA:.service=.service.in) \ - $(systemd_user_DATA:.service=.service.in) \ - $(config_DATA) \ - $(gsettings_SCHEMAS:.xml=.xml.in) \ - $(man_MANS) 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/functional-tests/test-apps-data/Makefile.am b/tests/functional-tests/test-apps-data/Makefile.am deleted file mode 100644 index ccdd73079..000000000 --- a/tests/functional-tests/test-apps-data/Makefile.am +++ /dev/null @@ -1,8 +0,0 @@ -appstestdir = $(datadir)/tracker-tests/test-apps-data - -appstest_DATA = \ - test-image-1.jpg \ - test-music-1.mp3 \ - test-video-1.mp4 - -EXTRA_DIST = $(appstest_DATA) diff --git a/tests/functional-tests/test-apps-data/test-image-1.jpg b/tests/functional-tests/test-apps-data/test-image-1.jpg Binary files differdeleted file mode 100644 index f1f917bb5..000000000 --- a/tests/functional-tests/test-apps-data/test-image-1.jpg +++ /dev/null diff --git a/tests/functional-tests/test-apps-data/test-music-1.mp3 b/tests/functional-tests/test-apps-data/test-music-1.mp3 Binary files differdeleted file mode 100644 index bbd4c768d..000000000 --- a/tests/functional-tests/test-apps-data/test-music-1.mp3 +++ /dev/null diff --git a/tests/functional-tests/test-apps-data/test-video-1.mp4 b/tests/functional-tests/test-apps-data/test-video-1.mp4 Binary files differdeleted file mode 100644 index 915e4be13..000000000 --- a/tests/functional-tests/test-apps-data/test-video-1.mp4 +++ /dev/null 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 a19929231..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
\ No newline at end of file diff --git a/tests/functional-tests/test-extraction-data/README b/tests/functional-tests/test-extraction-data/README deleted file mode 100644 index 1a3e21596..000000000 --- a/tests/functional-tests/test-extraction-data/README +++ /dev/null @@ -1,70 +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. -Optionally there can be a "Meego" section, for metadata that should be checked only on that platform. -Adding more platforms is fairly trivial but requires to modify the python code. - -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 4336b0eaa..000000000 --- a/tests/functional-tests/test-extraction-data/audio/Jazz_Audio_OPLs0.expected +++ /dev/null @@ -1,13 +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 - -[Meego] 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 fdb8a54d7..000000000 --- a/tests/functional-tests/test-extraction-data/audio/Makefile.am +++ /dev/null @@ -1,13 +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 87599620f..000000000 --- a/tests/functional-tests/test-extraction-data/audio/audio-test-1.expected +++ /dev/null @@ -1,19 +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 - -[Meego] 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 0ab85f9c4..000000000 --- a/tests/functional-tests/test-extraction-data/audio/audio-test-2.expected +++ /dev/null @@ -1,19 +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 - -[Meego] -nfo_encodedBy=Nokia Music 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 906022c9e..000000000 --- a/tests/functional-tests/test-extraction-data/images/comment-extension-block.expected +++ /dev/null @@ -1,13 +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! - -[Meego] 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 64a11a7a1..000000000 --- a/tests/functional-tests/test-extraction-data/images/test-image-1.expected +++ /dev/null @@ -1,20 +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 - -[Meego] 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 5264068b3..000000000 --- a/tests/functional-tests/test-extraction-data/images/test-image-2.expected +++ /dev/null @@ -1,11 +0,0 @@ -[TestFile] -Filename=test-image-2.png -Bugzilla= -Comment=Basic png example - -[Metadata] -a=nmm:Photo -nfo_width=211 -nfo_height=217 - -[Meego] 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 7aab615a1..000000000 --- a/tests/functional-tests/test-extraction-data/images/test-image-3.expected +++ /dev/null @@ -1,13 +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 - -[Meego] 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 93de5b724..000000000 --- a/tests/functional-tests/test-extraction-data/office/pdf-doc.expected +++ /dev/null @@ -1,9 +0,0 @@ -[TestFile] -Filename=pdf-doc.pdf -Comment=PDF document from the office tools - -[Metadata] - -[Meego] -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 c2a9839ed..000000000 --- a/tests/functional-tests/test-extraction-data/video/184505.expected +++ /dev/null @@ -1,12 +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 - -[Meego] -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 aaa28be77..000000000 --- a/tests/functional-tests/test-extraction-data/video/video-1.expected +++ /dev/null @@ -1,11 +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 - -[Meego] -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 a738c8571..000000000 --- a/tests/functional-tests/test-extraction-data/video/video-2.expected +++ /dev/null @@ -1,11 +0,0 @@ -[TestFile] -Filename=video-2.mov -Bugzilla=NB#181112 -Comment=Produces a Critical in Gstreamer freeing a component. - -[Metadata] -a=nmm:Video - -[Meego] -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/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 bdb4286ea..000000000 --- a/tests/libtracker-extract/Makefile.am +++ /dev/null @@ -1,73 +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 -else -if HAVE_MEEGOTOUCH -test_programs += tracker-encoding -endif -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 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/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 148aedbae..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> - -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_MEEGOTOUCH) - 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); - - tracker_locale_init (); - 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); - tracker_locale_shutdown (); - - 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 4b1cb9c19..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 (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 (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 fce46433e..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; - - 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; -} |