summaryrefslogtreecommitdiffstats
path: root/src/utils
diff options
context:
space:
mode:
authorMichal Kubecek <mkubecek@suse.cz>2015-04-13 09:21:39 +0200
committerMichal Kubecek <mkubecek@suse.cz>2015-04-13 09:21:39 +0200
commite2bc6f4153813cc570ae814c8ddb74628009b488 (patch)
treea40b171be1d859c2232ccc94f758010f9ae54d3c /src/utils
downloadtwinkle-e2bc6f4153813cc570ae814c8ddb74628009b488.tar
twinkle-e2bc6f4153813cc570ae814c8ddb74628009b488.tar.gz
twinkle-e2bc6f4153813cc570ae814c8ddb74628009b488.tar.lz
twinkle-e2bc6f4153813cc570ae814c8ddb74628009b488.tar.xz
twinkle-e2bc6f4153813cc570ae814c8ddb74628009b488.zip
initial checkin
Check in contents of upstream 1.4.2 tarball, exclude generated files.
Diffstat (limited to 'src/utils')
-rw-r--r--src/utils/Makefile.am11
-rw-r--r--src/utils/file_utils.cpp128
-rw-r--r--src/utils/file_utils.h82
-rw-r--r--src/utils/mime_database.cpp104
-rw-r--r--src/utils/mime_database.h90
-rw-r--r--src/utils/record_file.h158
-rw-r--r--src/utils/record_file.hpp178
7 files changed, 751 insertions, 0 deletions
diff --git a/src/utils/Makefile.am b/src/utils/Makefile.am
new file mode 100644
index 0000000..e4d8fb5
--- /dev/null
+++ b/src/utils/Makefile.am
@@ -0,0 +1,11 @@
+AM_CPPFLAGS = -Wall $(XML2_CFLAGS) -I$(top_srcdir)/src
+
+noinst_LIBRARIES = libutils.a
+
+libutils_a_SOURCES =\
+ file_utils.cpp\
+ mime_database.cpp\
+ file_utils.h\
+ mime_database.h\
+ record_file.h\
+ record_file.hpp
diff --git a/src/utils/file_utils.cpp b/src/utils/file_utils.cpp
new file mode 100644
index 0000000..e3734c1
--- /dev/null
+++ b/src/utils/file_utils.cpp
@@ -0,0 +1,128 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "file_utils.h"
+#include "util.h"
+
+#include <fstream>
+#include <string>
+#include <vector>
+#include <cerrno>
+#include <cstdlib>
+#include <unistd.h>
+
+using namespace std;
+using namespace utils;
+
+bool utils::filecopy(const string &from, const string &to) {
+ ifstream from_file(from.c_str());
+ if (!from_file) {
+ return false;
+ }
+
+ ofstream to_file(to.c_str());
+ if (!to_file) {
+ return false;
+ }
+
+ to_file << from_file.rdbuf();
+
+ if (!to_file.good() || !from_file.good()) {
+ return false;
+ }
+
+ return true;
+}
+
+string utils::strip_path_from_filename(const string &filename) {
+ vector<string> v = split_on_last(filename, PATH_SEPARATOR);
+ return v.back();
+}
+
+string utils::get_path_from_filename(const string &filename) {
+ vector<string> v = split_on_last(filename, PATH_SEPARATOR);
+
+ if (v.size() == 1) {
+ // There is no path.
+ return "";
+ }
+
+ return v.front();
+}
+
+string utils::get_extension_from_filename(const string &filename) {
+ vector<string> v = split_on_last(filename, '.');
+
+ if (v.size() == 1) {
+ // There is no file extension.
+ return "";
+ } else {
+ return v.back();
+ }
+}
+
+string utils::apply_glob_to_filename(const string &filename, const string &glob) {
+ string name = strip_path_from_filename(filename);
+ string path = get_path_from_filename(filename);
+ string new_name = glob;
+
+ string::size_type idx = new_name.find('*');
+
+ if (idx == string::npos)
+ {
+ // The glob expression does not contain a wild card to replace.
+ return filename;
+ }
+
+ new_name.replace(new_name.begin() + idx, new_name.begin() + idx + 1, name);
+
+ string new_filename = path;
+ if (!new_filename.empty()) {
+ new_filename += PATH_SEPARATOR;
+ }
+ new_filename += new_name;
+
+ return new_filename;
+}
+
+string get_working_dir(void) {
+ size_t buf_size = 1024;
+ char *buf = (char*)malloc(buf_size);
+ char *dir = NULL;
+
+ while (true) {
+ if ((dir = getcwd(buf, buf_size)) != NULL) break;
+ if (errno != ERANGE) break;
+
+ // The buffer is too small.
+ // Avoid eternal looping.
+ if (buf_size > 8192) break;
+
+ // Increase the buffer size
+ free(buf);
+ buf_size *= 2;
+ buf = (char*)malloc(buf_size);
+ }
+
+ string result;
+ if (dir) result = dir;
+
+ free(buf);
+
+ return result;
+}
diff --git a/src/utils/file_utils.h b/src/utils/file_utils.h
new file mode 100644
index 0000000..a6e97a1
--- /dev/null
+++ b/src/utils/file_utils.h
@@ -0,0 +1,82 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/**
+ * @file
+ * File utilities
+ */
+
+#ifndef _FILE_UTILS_H
+#define _FILE_UTILS_H
+
+#include <string>
+
+using namespace std;
+
+namespace utils {
+
+/** Separator to split parts in a file path. */
+#define PATH_SEPARATOR '/'
+
+/**
+ * Copy a file.
+ * @param from [in] Absolute path of file to copy.
+ * @param to [in] Absolute path of destination file.
+ * @return true if copy succeeded, otherwise false.
+ */
+bool filecopy(const string &from, const string &to);
+
+/**
+ * Strip the path to a file from an absolute file name.
+ * @return The remaining file name without the full path.
+ */
+string strip_path_from_filename(const string &filename);
+
+/**
+ * Get path to a file from an absolute file name.
+ * @return The path name.
+ */
+string get_path_from_filename(const string &filename);
+
+/**
+ * Get the extension from a file name.
+ * @return The extension (without the initial dot).
+ * @return Empty string if the file name does not have an extension.
+ */
+string get_extension_from_filename(const string &filename);
+
+/**
+ * Apply a glob expression to a filename.
+ * E.g. /tmp/twinkle with glob *.txt gives /tmp/twinkle.txt
+ * /tmp/twinkle with README* give /tmp/READMEtwinkle.txt
+ * @param filename [in] The filename.
+ * @param glob [in] The glob expression to apply.
+ * @return The modified filename.
+ */
+string apply_glob_to_filename(const string &filename, const string &glob);
+
+/**
+ * Get the absolute path of the current working directory.
+ * @return The absolute path of the current working directory.
+ * @return Empty string if the current working directory cannot be determined.
+ */
+string get_working_dir(void);
+
+}; // namespace
+
+#endif
diff --git a/src/utils/mime_database.cpp b/src/utils/mime_database.cpp
new file mode 100644
index 0000000..ff8248e
--- /dev/null
+++ b/src/utils/mime_database.cpp
@@ -0,0 +1,104 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include "mime_database.h"
+
+#include <cassert>
+
+#include "log.h"
+#include "sys_settings.h"
+
+using namespace utils;
+
+//////////////////////////
+// class t_mime_db_record
+//////////////////////////
+
+bool t_mime_db_record::create_file_record(vector<string> &v) const {
+ // The mime database is read only. So this function should
+ // never be called.
+ assert(false);
+ return false;
+}
+
+bool t_mime_db_record::populate_from_file_record(const vector<string> &v) {
+ // Check number of fields
+ if (v.size() != 2) return false;
+
+ mimetype = v[0];
+ file_glob = v[1];
+
+ return true;
+}
+
+//////////////////////////
+// class t_mime_database
+//////////////////////////
+
+t_mime_database::t_mime_database() {
+ set_separator(':');
+ set_filename(sys_config->get_mime_shared_database());
+
+ mime_magic_ = magic_open(MAGIC_MIME | MAGIC_ERROR);
+ if (mime_magic_ == (magic_t)NULL) {
+ log_file->write_report("Failed to open magic number database",
+ "t_mime_database::t_mime_database", LOG_NORMAL, LOG_WARNING);
+
+ return;
+ }
+
+ magic_load(mime_magic_, NULL);
+}
+
+t_mime_database::~t_mime_database() {
+ magic_close(mime_magic_);
+}
+
+void t_mime_database::add_record(const t_mime_db_record &record) {
+ map_mime2glob_.insert(make_pair(record.mimetype, record.file_glob));
+}
+
+string t_mime_database::get_glob(const string &mimetype) const {
+ map<string, string>::const_iterator it = map_mime2glob_.find(mimetype);
+
+ if (it != map_mime2glob_.end()) {
+ return it->second;
+ }
+
+ return "";
+}
+
+string t_mime_database::get_mimetype(const string &filename) const {
+ const char *mime_desc = magic_file(mime_magic_, filename.c_str());
+
+ if (!mime_desc) return "";
+
+ // Sometimes the magic libary adds additional info to the
+ // returned mime type. Strip this info.
+ string mime_type(mime_desc);
+ string::size_type end_of_mime = mime_type.find_first_not_of(
+ "abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQSTUVWXYZ"
+ "0123456789-.!%*_+`'~/");
+
+ if (end_of_mime != string::npos) {
+ mime_type = mime_type.substr(0, end_of_mime);
+ }
+
+ return mime_type;
+}
diff --git a/src/utils/mime_database.h b/src/utils/mime_database.h
new file mode 100644
index 0000000..fcf6444
--- /dev/null
+++ b/src/utils/mime_database.h
@@ -0,0 +1,90 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/**
+ * @file
+ * Mime database
+ * Conversion between mime types, file content and file extensions.
+ */
+
+#ifndef _MIME_DATABASE_H
+#define _MIME_DATABASE_H
+
+#include <map>
+#include <string>
+#include <magic.h>
+
+#include "record_file.h"
+
+using namespace std;
+
+namespace utils {
+
+/** Record from the mime database. */
+class t_mime_db_record : public utils::t_record {
+public:
+ string mimetype; /**< Mimetype, e.g. text/plain */
+ string file_glob; /**< File glob expression */
+
+ virtual bool create_file_record(vector<string> &v) const;
+ virtual bool populate_from_file_record(const vector<string> &v);
+};
+
+/**
+ * The mime database.
+ * The default location for the mime database is /usr/share/mime/globs
+ */
+class t_mime_database : public utils::t_record_file<t_mime_db_record> {
+private:
+ /** Mapping between mimetypes and file globs. */
+ map<string, string> map_mime2glob_;
+
+ /** Handle on the magic number database. */
+ magic_t mime_magic_;
+
+protected:
+ virtual void add_record(const t_mime_db_record &record);
+
+public:
+ /** Constructor */
+ t_mime_database();
+
+ /** Destructor */
+ ~t_mime_database();
+
+ /**
+ * Get a glob expression for a mimetype.
+ * @param mimetype [in] The mimetype.
+ * @return Glob expression associated with the mimetype. Empty string
+ * if no glob expression can be found.
+ */
+ string get_glob(const string &mimetype) const;
+
+ /**
+ * Get the mimetype of a file.
+ * @param filename [in] Name of the file.
+ * @return The mimetype or empty string if no mimetype can be determined.
+ */
+ string get_mimetype(const string &filename) const;
+};
+
+}; // namespace
+
+extern utils::t_mime_database *mime_database;
+
+#endif
diff --git a/src/utils/record_file.h b/src/utils/record_file.h
new file mode 100644
index 0000000..6108ea0
--- /dev/null
+++ b/src/utils/record_file.h
@@ -0,0 +1,158 @@
+/*
+ Copyright (C) 2005-2009 Michel de Boer <michel@twinklephone.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/**
+ * @file
+ * File to store data records.
+ */
+
+#ifndef _RECORD_FILE_H
+#define _RECORD_FILE_H
+
+#include <list>
+#include <string>
+#include <vector>
+#include <cstdlib>
+#include <sys/stat.h>
+#include <iostream>
+#include <fstream>
+
+#include "translator.h"
+#include "util.h"
+#include "threads/mutex.h"
+
+
+using namespace std;
+
+namespace utils {
+
+/** A single record in a file. */
+class t_record {
+public:
+ virtual ~t_record() {};
+
+ /**
+ * Create a record to write to a file.
+ * @param v [out] Vector of fields of record.
+ * @return true, if record is succesfully created.
+ * @return false, otherwise.
+ */
+ virtual bool create_file_record(vector<string> &v) const = 0;
+
+ /**
+ * Populate from a file record.
+ * @param v [in] Vector containing the fields of the record.
+ * @return true, if record is succesfully populated.
+ * @return false, if file record could not be parsed.
+ */
+ virtual bool populate_from_file_record(const vector<string> &v) = 0;
+};
+
+/**
+ * A file containing records with a fixed number of fields.
+ * @param R Subclass of @ref t_record
+ */
+template< class R >
+class t_record_file {
+private:
+ /** Separator to separate fields in a file record. */
+ char field_separator;
+
+ /** Header string to write as comment at start of file. */
+ string header;
+
+ /** Name of the file containing the records. */
+ string filename;
+
+ /**
+ * Split a record into separate fields.
+ * @param record [in] A complete record.
+ * @param v [out] Vector of fields.
+ */
+ void split_record(const string &record, vector<string> &v) const;
+
+ /**
+ * Join fields of a record into a string.
+ * Separator and comment symbols will be escaped.
+ * @param v [in] Vector of fields.
+ * @return Joined fields.
+ */
+ string join_fields(const vector<string> &v) const;
+
+protected:
+ /** Mutex to protect concurrent access/ */
+ mutable t_recursive_mutex mtx_records;
+
+ /** Records in the file. */
+ list<R> records;
+
+ /**
+ * Add a record to the file.
+ * @param record [in] Record to add.
+ */
+ virtual void add_record(const R &record);
+
+public:
+ /** Constructor. */
+ t_record_file();
+
+ /** Constructor. */
+ t_record_file(const string &_header, char _field_separator, const string &_filename);
+
+ /** Destructor. */
+ virtual ~t_record_file() {};
+
+ /** @name Setters */
+ //@{
+ void set_header(const string &_header);
+ void set_separator(char _separator);
+ void set_filename(const string &_filename);
+ //@}
+
+ /** @name Getters */
+ //@{
+ list<R> *get_records();
+ //@}
+
+ /**
+ * Load records from file.
+ * @param error_msg [out] Error message on failure return.
+ * @return true, if file was read succesfully.
+ * @return false, if it fails. error_msg is an error to be given to
+ * the user.
+ */
+ virtual bool load(string &error_msg);
+
+ /**
+ * Save records to file.
+ * @param error_msg [out] Error message on failure return.
+ * @return true, if file was saved succesfully.
+ * @return false, if it fails. error_msg is an error to be given to
+ * the user.
+ */
+ virtual bool save(string &error_msg) const;
+
+ typedef typename list<R>::const_iterator record_const_iterator;
+ typedef typename list<R>::iterator record_iterator;
+};
+
+#include "record_file.hpp"
+
+}; // namespace
+
+#endif
diff --git a/src/utils/record_file.hpp b/src/utils/record_file.hpp
new file mode 100644
index 0000000..43281d6
--- /dev/null
+++ b/src/utils/record_file.hpp
@@ -0,0 +1,178 @@
+/*
+ Copyright (C) 2005-2007 Michel de Boer <michel@twinklephone.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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#define COMMENT_SYMBOL '#'
+
+template< class R >
+void t_record_file<R>::split_record(const string &record, vector<string> &v) const {
+ v = split_escaped(record, field_separator);
+
+ for (vector<string>::iterator it = v.begin(); it != v.end(); ++it) {
+ *it = unescape(*it);
+ }
+}
+
+template< class R >
+string t_record_file<R>::join_fields(const vector<string> &v) const {
+ string s;
+
+ for (vector<string>::const_iterator it = v.begin(); it != v.end(); ++it) {
+ if (it != v.begin()) s += field_separator;
+
+ // Escape comment symbol.
+ if (!it->empty() && it->at(0) == COMMENT_SYMBOL) s += '\\';
+
+ s += escape(*it, field_separator);
+ }
+
+ return s;
+}
+
+template< class R >
+void t_record_file<R>::add_record(const R &record) {
+ records.push_back(record);
+}
+
+template< class R >
+t_record_file<R>::t_record_file(): field_separator('|')
+{}
+
+template< class R >
+t_record_file<R>::t_record_file(const string &_header, char _field_separator,
+ const string &_filename) :
+ header(_header),
+ field_separator(_field_separator),
+ filename(_filename)
+{}
+
+template< class R >
+void t_record_file<R>::set_header(const string &_header) {
+ header = _header;
+}
+
+template< class R >
+void t_record_file<R>::set_separator(char _separator) {
+ field_separator = _separator;
+}
+
+template< class R >
+void t_record_file<R>::set_filename(const string &_filename) {
+ filename = _filename;
+}
+
+template< class R >
+list<R> *t_record_file<R>::get_records() {
+ return &records;
+}
+
+template< class R >
+bool t_record_file<R>::load(string &error_msg) {
+ struct stat stat_buf;
+
+ mtx_records.lock();
+
+ records.clear();
+
+ // Check if file exists
+ if (filename.empty() || stat(filename.c_str(), &stat_buf) != 0) {
+ // There is no file.
+ mtx_records.unlock();
+ return true;
+ }
+
+ // Open call ile
+ ifstream file(filename.c_str());
+ if (!file) {
+ error_msg = TRANSLATE("Cannot open file for reading: %1");
+ error_msg = replace_first(error_msg, "%1", filename);
+ mtx_records.unlock();
+ return false;
+ }
+
+ // Read and parse history file.
+ while (!file.eof()) {
+ string line;
+
+ getline(file, line);
+
+ // Check if read operation succeeded
+ if (!file.good() && !file.eof()) {
+ error_msg = TRANSLATE("File system error while reading file %1 .");
+ error_msg = replace_first(error_msg, "%1", filename);
+ mtx_records.unlock();
+ return false;
+ }
+
+ line = trim(line);
+
+ // Skip empty lines
+ if (line.size() == 0) continue;
+
+ // Skip comment lines
+ if (line[0] == COMMENT_SYMBOL) continue;
+
+ // Add record. Skip records that cannot be parsed.
+ R record;
+ vector<string> v;
+ split_record(line, v);
+ if (record.populate_from_file_record(v)) {
+ add_record(record);
+ }
+ }
+
+ mtx_records.unlock();
+ return true;
+}
+
+template< class R >
+bool t_record_file<R>::save(string &error_msg) const {
+ if (filename.empty()) return false;
+
+ mtx_records.lock();
+
+ // Open file
+ ofstream file(filename.c_str());
+ if (!file) {
+ error_msg = TRANSLATE("Cannot open file for writing: %1");
+ error_msg = replace_first(error_msg, "%1", filename);
+ mtx_records.unlock();
+ return false;
+ }
+
+ // Write file header
+ file << "# " << header << endl;
+
+ // Write records
+ for (record_const_iterator i = records.begin(); i != records.end(); ++i) {
+ vector<string> v;
+ if (i->create_file_record(v)) {
+ file << join_fields(v);
+ file << endl;
+ }
+ }
+
+ mtx_records.unlock();
+
+ if (!file.good()) {
+ error_msg = TRANSLATE("File system error while writing file %1 .");
+ error_msg = replace_first(error_msg, "%1", filename);
+ return false;
+ }
+
+ return true;
+}