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.

136 lines
3.4 KiB

  1. #include <string>
  2. #include <iostream>
  3. #include <memory>
  4. #include <curl/curl.h>
  5. #include "fetchfile.hpp"
  6. #include <boost/filesystem.hpp>
  7. #include <sstream>
  8. //#include <filesystem> // c++17
  9. //namespace fs = std::filesystem;
  10. namespace fs = boost::filesystem;
  11. using namespace std;
  12. Fetchfile::Fetchfile( string basedir ) {
  13. Fetchfile::basedir = basedir;
  14. // test if file exists
  15. string filename = basedir + "fetch.txt";
  16. fs::path p{ filename };
  17. fs::file_status s = fs::status( p );
  18. log << "path "<< p.string() << endl;
  19. log << "is file: "<< fs::is_regular_file( s) << endl;
  20. if (fs::is_regular_file( s)) {
  21. this->exist_fetchfile = true;
  22. // map entries
  23. // from spec: A metadata element MUST consist of a label, a colon, and a value,
  24. // each separated by optional whitespace
  25. // Long values may be continued
  26. // onto the next line by inserting a newline (LF), a carriage return
  27. // (CR), or carriage return plus newline (CRLF) and indenting the next
  28. // line with linear white space (spaces or tabs)
  29. ifstream file;
  30. file.open( filename );
  31. if (file.is_open()) {
  32. string line;
  33. while (getline(file, line)) {
  34. stringstream line_ss ( line );
  35. string url;
  36. string length;
  37. string subfile;
  38. line_ss >> url;
  39. line_ss >> length;
  40. line_ss >> subfile;
  41. fetch_t entry;
  42. entry.url = url;
  43. entry.size = stoi( length );
  44. entry.filename = subfile;
  45. this->entries.push_back( entry );
  46. }
  47. file.close();
  48. }
  49. } else { // no file
  50. this->exist_fetchfile = false;
  51. }
  52. }
  53. bool Fetchfile::fetch( fetch_t fetch ) {
  54. CURL *curl;
  55. CURLcode result;
  56. curl = curl_easy_init();
  57. if (curl != nullptr) {
  58. FILE *fp;
  59. fp = fopen( fetch.filename.c_str(), "wb");
  60. curl_easy_setopt(curl, CURLOPT_URL, fetch.url.c_str());
  61. // FIXME: curl needs a write function if WIN32,
  62. // see https://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html#DESCRIPTION
  63. curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
  64. curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
  65. result = curl_easy_perform(curl);
  66. curl_easy_cleanup(curl);
  67. fclose(fp);
  68. } else {
  69. return false;
  70. }
  71. return true;
  72. }
  73. bool Fetchfile::has_fetchfile() {
  74. return this->exist_fetchfile;
  75. }
  76. list<fetch_t> Fetchfile::get_entries() {
  77. return this->entries;
  78. }
  79. bool Fetchfile::fetch_all_entries() {
  80. bool is_successful = true;
  81. for (auto & entrie : this->entries) {
  82. bool result = this->fetch( entrie );
  83. if (!result) {
  84. is_successful = false;
  85. }
  86. }
  87. return is_successful;
  88. }
  89. bool Fetchfile::validate() {
  90. bool is_valid = true;
  91. if (this->has_fetchfile()) {
  92. // TODO(art1):
  93. }
  94. return is_valid;
  95. }
  96. bool Fetchfile::store( string basedir ) {
  97. fs::path p{ basedir };
  98. fs::file_status s = fs::status( p );
  99. if (! fs::is_directory( s)) {
  100. Fetchfile::log << "directory '" << basedir << "' does not exist" << endl;
  101. return false;
  102. }
  103. string filename = basedir + "fetch.txt";
  104. ofstream fetchfile_txt_file;
  105. fetchfile_txt_file.open( filename );
  106. if (fetchfile_txt_file.is_open()) {
  107. for (auto & entrie : this->entries) {
  108. fetchfile_txt_file << entrie.url << " " << entrie.size << " " << entrie.filename << endl;
  109. }
  110. fetchfile_txt_file.close();
  111. }
  112. return true;
  113. }
  114. void Fetchfile::get_logstream( stringstream & log ) {
  115. log << this->log.rdbuf();
  116. }
  117. void Fetchfile::reset_logstream() {
  118. this->log.str(std::string());
  119. }
  120. // vim: set tabstop=4 softtabstop=0 expandtab shiftwidth=4 smarttab