C++ Library to handle BagIt structures. BagIt is a standard format to create transfer packages for digital preservation purposes. See https://en.wikipedia.org/wiki/BagIt for details http://andreas-romeyke.de
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

144 lines
4.1 KiB

// Copyright (C) 2018 Andreas Romeyke (art1@andreas-romeyke.de), 2018.
//
// 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 3 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 <https://www.gnu.org/licenses/>.
#include <string>
#include <iostream>
#include <memory>
#include <curl/curl.h>
#include "fetchfile.hpp"
#include <boost/filesystem.hpp>
#include <sstream>
//#include <filesystem> // c++17
//namespace fs = std::filesystem;
namespace fs = boost::filesystem;
// TODO: KLasse statt fetch_t?
using namespace std;
Fetchfile::Fetchfile( string basedir ) {
Fetchfile::basedir = basedir;
// test if file exists
string filename = basedir + "fetch.txt";
fs::path p{ filename };
fs::file_status s = fs::status( p );
log << "path "<< p.string() << endl;
log << "is file: "<< fs::is_regular_file( s) << endl;
if (fs::is_regular_file( s)) {
this->exist_fetchfile = true;
// map entries
// from spec: A metadata element MUST consist of a label, a colon, and a value,
// each separated by optional whitespace
// Long values may be continued
// onto the next line by inserting a newline (LF), a carriage return
// (CR), or carriage return plus newline (CRLF) and indenting the next
// line with linear white space (spaces or tabs)
ifstream file;
file.open( filename );
if (file.is_open()) {
string line;
while (getline(file, line)) {
stringstream line_ss ( line );
string url;
string length;
string subfile;
line_ss >> url;
line_ss >> length;
line_ss >> subfile;
fetch_t entry;
entry.url = url;
entry.size = stoul( length );
entry.filename = subfile;
this->entries.push_back( entry );
}
file.close();
}
} else { // no file
this->exist_fetchfile = false;
}
}
bool Fetchfile::fetch( fetch_t fetch ) {
CURL *curl;
curl = curl_easy_init();
if (curl != nullptr) {
FILE *fp;
fp = fopen( fetch.filename.c_str(), "wb");
curl_easy_setopt(curl, CURLOPT_URL, fetch.url.c_str());
// FIXME: curl needs a write function if WIN32,
// see https://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html#DESCRIPTION
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
CURLcode result = curl_easy_perform(curl);
curl_easy_cleanup(curl);
fclose(fp);
} else {
return false;
}
return true;
}
bool Fetchfile::has_fetchfile() {
return this->exist_fetchfile;
}
list<fetch_t> Fetchfile::get_entries() {
return this->entries;
}
bool Fetchfile::fetch_all_entries() {
bool is_successful = true;
for (auto & entrie : this->entries) {
bool result = this->fetch( entrie );
if (!result) {
is_successful = false;
}
}
return is_successful;
}
bool Fetchfile::validate() {
return true;
}
bool Fetchfile::store( string basedir ) {
fs::path p{ basedir };
fs::file_status s = fs::status( p );
if (! fs::is_directory( s)) {
Fetchfile::log << "directory '" << basedir << "' does not exist" << endl;
return false;
}
string filename = basedir + "fetch.txt";
ofstream fetchfile_txt_file;
fetchfile_txt_file.open( filename );
if (fetchfile_txt_file.is_open()) {
for (auto & entry : this->entries) {
fetchfile_txt_file << entry.url << " " << entry.size << " " << entry.filename << endl;
}
fetchfile_txt_file.close();
}
return true;
}
void Fetchfile::get_logstream( stringstream & log ) {
log << this->log.rdbuf();
}
void Fetchfile::reset_logstream() {
this->log.str(std::string());
}
// vim: set tabstop=4 softtabstop=0 expandtab shiftwidth=4 smarttab