diff options
author | Michal Kubecek <mkubecek@suse.cz> | 2015-04-13 09:21:39 +0200 |
---|---|---|
committer | Michal Kubecek <mkubecek@suse.cz> | 2015-04-13 09:21:39 +0200 |
commit | e2bc6f4153813cc570ae814c8ddb74628009b488 (patch) | |
tree | a40b171be1d859c2232ccc94f758010f9ae54d3c /src/utils | |
download | twinkle-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.am | 11 | ||||
-rw-r--r-- | src/utils/file_utils.cpp | 128 | ||||
-rw-r--r-- | src/utils/file_utils.h | 82 | ||||
-rw-r--r-- | src/utils/mime_database.cpp | 104 | ||||
-rw-r--r-- | src/utils/mime_database.h | 90 | ||||
-rw-r--r-- | src/utils/record_file.h | 158 | ||||
-rw-r--r-- | src/utils/record_file.hpp | 178 |
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; +} |