This commit is contained in:
2023-10-29 17:03:58 +01:00
parent c2656fd377
commit 6afbaf1fb2
15 changed files with 359 additions and 461 deletions

View File

@ -125,7 +125,7 @@ Attachment::removeSection (string &content, const string &beginTag, const string
// ================================================================================
string
Attachment::getSection (const string &content, const string &beginTag, const string &endTag) {
DEF_LOG ("Attachment::getSection", "beginTag: " << beginTag << " endTag: " << endTag << " content: " << content);
DEF_LOG ("Attachment::getSection", "beginTag: " << beginTag << " endTag: " << endTag << " content: " << content.substr (0, 100) << "...");
vector<string> list;
getSection (content, beginTag, endTag, list);
size_t sum (0);
@ -142,18 +142,17 @@ Attachment::getSection (const string &content, const string &beginTag, const str
// ================================================================================
void
Attachment::getSection (const string &content, const string &beginTag, const string &endTag, vector<string> &result) {
DEF_LOG ("Attachment::getSection", "beginTag: " << beginTag << " endTag: " << endTag << " content: " << content);
DEF_LOG ("Attachment::getSection", "beginTag: " << beginTag << " endTag: " << endTag << " content: " << content.substr (0, 100) << "...");
for (string::size_type startPos (0);
(startPos = caseInsensitiveFind (content, beginTag, startPos)) != string::npos;
) {
LOG (beginTag << ": " << startPos);
string::size_type stopPos = caseInsensitiveFind (content, endTag, startPos);
LOG_BUG (stopPos == string::npos, break, "eMailShrinker: bug A3: " << endTag << " not found! at: " << startPos);
// LOG_BUG (stopPos == string::npos, break, "eMailShrinker: bug A3: " << endTag << " not found! at: " << startPos << endl << content);
LOG_BUG (stopPos == string::npos, break, "eMailShrinker: bug A3: " << endTag << " not found! at: " << startPos << endl << content.substr (0, 100) << "...");
LOG ("start: " << startPos << " stop: " << stopPos);
LOG_BUG (startPos == stopPos, /**/, "eMailShrinker: bug A4: " << endTag << " without " << beginTag << " at: " << startPos);
LOG_BUG (startPos == stopPos, /* */, "eMailShrinker: bug A4: " << endTag << " without " << beginTag << " at: " << startPos);
if (startPos != stopPos) {
startPos += beginTag.length ();
result.push_back (content.substr (startPos, stopPos-startPos));
@ -317,7 +316,7 @@ Attachment::readMime (ifstream &mbox, streamoff &curPos) {
if (line[0] == ' ' || line[0] == '\t') {
if (lastVar.empty ()) {
LOG_BUG (true, /**/, "eMailShrinker: bug A5: not compliant MIME. pos: " << (curPos - (line.length () + 1)) << " line: " << line);
LOG_BUG (true, /* */, "eMailShrinker: bug A5: not compliant MIME. pos: " << (curPos - (line.length () + 1)) << " line: " << line);
} else {
LOG ("add line to var: " << line);
env.find (lastVar)->second += cleanString (line);
@ -500,7 +499,7 @@ Attachment::getContent (ifstream &mbox) const {
// ================================================================================
void
Attachment::println (ofstream &outbox, string content) const {
DEF_LOG ("Attachment::println", "content: " << content);
DEF_LOG ("Attachment::println", "content: " << content.substr (0, 100) << "...");
if (isBase64Encoding ())
base64Encode (content);
if (isQuotedPrintableEnconding ())

View File

@ -160,14 +160,13 @@ kaz::operator >> (istream &in, AttachMode &attachMode) {
// ================================================================================
const string
kaz::headerTypeLabels[] = {
"Same", "Multi", "MainPlain", "AttachHtml"
"Same", "Mixed", "MainPlain"
};
const map<string, HeaderType>
kaz::headerTypeMap = boost::assign::map_list_of
("same", SAME)
("multi", MULTI)
("mixed", MIXED)
("mainplain", MAIN_PLAIN)
("attachhtml", ATTACH_HTML)
;
ostream &
kaz::operator << (ostream &out, const HeaderType &headerType) {
@ -254,7 +253,7 @@ MainAttachment::addLink (string &plain, string &html, const string &url, const s
// ================================================================================
void
MainAttachment::getDisclaim (string &plain, string &html) const {
DEF_LOG ("Attachment::getDisclaim", "");
DEF_LOG ("MainAttachment::getDisclaim", "");
plain = html = "";
int linkCount (0);
@ -310,7 +309,7 @@ MainAttachment::getDisclaim (string &plain, string &html) const {
// ================================================================================
void
MainAttachment::addPrevious (const string &href, const string &name, const bool &trust) {
DEF_LOG ("Attachment::addPrevious", "href: " << href << " name: " << name);
DEF_LOG ("MainAttachment::addPrevious", "href: " << href << " name: " << name);
const string oldVal = previousLinks [href];
if (name.empty ())
return;
@ -324,7 +323,7 @@ MainAttachment::addPrevious (const string &href, const string &name, const bool
void
MainAttachment::extractLinks (const string &extractedPlainKAZ) {
// plain text => "* name <url>"
DEF_LOG ("Attachment::extractedPlainKAZ", "extractedPlainKAZ: " << extractedPlainKAZ);
DEF_LOG ("MainAttachment::extractedPlainKAZ", "extractedPlainKAZ: " << extractedPlainKAZ);
for (string::size_type startPos (0);
(startPos = extractedPlainKAZ.find ("http", startPos)) != string::npos;
) {
@ -369,7 +368,7 @@ MainAttachment::extractLinks (const string &extractedPlainKAZ) {
void
MainAttachment::extractLinks (const vector<string> &liOne) {
// html text => "<li ...><a href="url">name</a>"
DEF_LOG ("Attachment::extractedPlainKAZ", "liOne.size: " << liOne.size ());
DEF_LOG ("MainAttachment::extractedPlainKAZ", "liOne.size: " << liOne.size ());
for (const string &one : liOne) {
if (caseInsensitiveFind (one, CLASS_ONE) == string::npos)
continue;
@ -463,38 +462,60 @@ MainAttachment::removePreviousArchive () {
// ================================================================================
void MainAttachment::rewriteHeaders (ifstream &mbox, ofstream &outbox, const HeaderType &headerType) {
DEF_LOG ("MainAttachment::rewriteHeaders", "headerType: " << headerType);
if (SAME == headerType) {
switch (headerType) {
case SAME:
copy (mbox, outbox, 0, contentPos);
return;
case MAIN_PLAIN:
break;
case MIXED:
if (boost::iequals (getContentType (), "multipart/mixed")) {
copy (mbox, outbox, 0, contentPos);
return;
}
break;
}
string mime (getMime (mbox));
mime.insert (0, "\n");
string::size_type startPos = (0);
for (string token : {string ("content-transfer-encoding"), Attachment::contentTypeToken}) {
startPos = caseInsensitiveFind (mime, token);
for (string::size_type stopPos (startPos);
// remove previous content-type at begin of ligne (after a "\n")
for (string token : {string ("content-transfer-encoding"),
Attachment::contentTypeToken}) {
LOG ("token:" << token);
startPos = caseInsensitiveFind (mime, string ("\n")+token);
if (startPos == string::npos)
continue;
for (string::size_type stopPos (startPos+1);
(stopPos = mime.find ("\n", stopPos)) != string::npos;
) {
if (string (" \t").find (mime [stopPos+1]) == string::npos) {
// not wrap after
movedContentType += mime.substr (startPos+1, stopPos-startPos);
mime.erase (startPos, stopPos-startPos);
break;
}
// merge wrap lines
// find next endl
++stopPos;
}
}
string contentType (KAZ_EMPTY_TEXT_PLAIN);
switch (headerType) {
case SAME: /* no way */;
case SAME: /* no way */ break;
case MAIN_PLAIN: contentType = KAZ_EMPTY_TEXT_PLAIN; break;
case ATTACH_HTML: contentType = KAZ_ATTACHMENT_TEXT_HTML; break;
case MULTI:
boundary = "__KAZ__"+boundaryGen (40);
contentType = "Content-Type: multipart/mixed; boundary=\""+boundary+"\"";
boundary = "--"+boundary+"--";
boundaryMiddleSize = boundary.length () - 2;
case MIXED:
addedBoundary = "__KAZ__"+boundaryGen (40);
contentType = "Content-Type: multipart/mixed; boundary=\""+addedBoundary+"\"\n";
addedBoundary = "--"+addedBoundary+"--";
addedBoundaryMiddleSize = addedBoundary.length () - 2;
}
// skip '\n'
++startPos;
if (startPos >= mime.length ())
startPos = mime.length ()-1;
startPos = mime.length () - 1;
mime.insert (startPos, contentType);
outbox << mime << flush;
outbox << mime.substr (1) << endl << flush;
}
// ================================================================================
@ -641,12 +662,12 @@ MainAttachment::extract (ifstream &mbox, const SizeArg &minSize) const {
<tr><th>text/plain</th><td>OK</td><td>mute multi</td><td>mute multi</td></tr>
<tr><th>empty mail</th><td>mute plain</td><td>mute multi</td><td>mute html</td></tr>
</table>
*/
*/
void
MainAttachment::substitute (ifstream &mbox, ofstream &outbox, const SizeArg &minSize, AttachMode attachMode) {
DEF_LOG ("MainAttachment::substitute", "minSize: " << minSize << " AttachMode: " << attachMode);
// preparation
// setup
extractPreviousKAZ (mbox);
removePreviousArchive ();
map<const string, const string> translateHtml;
@ -676,28 +697,35 @@ MainAttachment::substitute (ifstream &mbox, ofstream &outbox, const SizeArg &min
string plainDisclaim, htmlDisclaim;
getDisclaim (plainDisclaim, htmlDisclaim);
LOG_BUG (plainDisclaim.empty () ^ htmlDisclaim.empty (), /* */,
"eMailShrinker: bug M8: not empty disclaim. (plainDisclaim: " << plainDisclaim.size () << " htmlDisclaim: " << htmlDisclaim.size () << ")");
if (plainDisclaim.empty ()) {
// no change
cerr << "eMailShrinker: original email inchanged" << endl;
copy (mbox, outbox, 0, endPos);
return;
}
if (boost::iequals (getContentType (), "multipart/report")) {
// no change
cerr << "eMailShrinker: repport email inchange" << endl;
copy (mbox, outbox, 0, endPos);
return;
}
HeaderType headerType (SAME);
// copy email
if (!boundary.size () && plainDisclaim.size ())
switch (attachMode) {
case NONE: LOG_BUG (true, /* */, "eMailShrinker: bug M12: nothing to do"); break;
case FOOTER: headerType = (emptyEMail ? MAIN_PLAIN : SAME); break;
case BOTH: headerType = MULTI; break;
case ATTACHMENT: headerType = ATTACH_HTML; break;
}
switch (attachMode) {
case NONE: LOG_BUG (true, /* */, "eMailShrinker: bug M12: nothing to do"); break;
case FOOTER: headerType = (emptyEMail && !boundary.size ()) ? MAIN_PLAIN : SAME; break;
case BOTH: headerType = MIXED; break;
case ATTACHMENT: headerType = MIXED; break;
}
rewriteHeaders (mbox, outbox, headerType);
streamoff curPos = contentPos;
if (MAIN_PLAIN == headerType) {
LOG ("Replace old content with plain");
string content (plainDisclaim);
base64Encode (content);
outbox << content << endl;
outbox.flush ();
return;
}
if (ATTACH_HTML == headerType) {
LOG ("Replace old content with html");
LOG ("Replace old content with plain");
string content (plainDisclaim);
base64Encode (content);
outbox << content << endl;
@ -705,29 +733,38 @@ MainAttachment::substitute (ifstream &mbox, ofstream &outbox, const SizeArg &min
return;
}
if (plainDisclaim.size () && emptyEMail && (attachMode & FOOTER)) {
// // XXX => MIXED
// if (ATTACH_HTML == headerType) {
// LOG ("Replace old content with html");
// string content (plainDisclaim);
// base64Encode (content);
// outbox << content << endl;
// outbox.flush ();
// return;
// }
if (emptyEMail && (attachMode & FOOTER)) {
// case : multi
LOG ("Force main text");
cerr << "eMailShrinker: force main text" << endl;
string content (plainDisclaim);
base64Encode (content);
outbox << boundary.substr (0, boundary.length () -2) << endl
outbox << boundary.substr (0, boundaryMiddleSize) << endl
<< KAZ_EMPTY_TEXT_PLAIN << endl
<< content << endl;
outbox.flush ();
}
if (MULTI == headerType) {
if (movedContentType.size ()) {
LOG ("New boundary");
map<string, string>::const_iterator it (env.find (contentTypeToken));
LOG_BUG (it == env.end (), /* */, "eMailShrinker: bug M13: no content-type");
outbox << boundary.substr (0, boundary.length () -2) << endl
<< Attachment::contentTypeToken << ": " << it->second << endl;
outbox << addedBoundary.substr (0, addedBoundaryMiddleSize) << endl
<< movedContentType << endl;
}
for (Attachment *attachP : allMarkedPtrs) {
copy (mbox, outbox, curPos, attachP->beginInParent);
LOG_BUG (attachP->toUpdate && attachP->toExtract, /**/, "eMailShrinker: bug M5: update and extract. pos: " << attachP->beginPos);
outbox << endl; // force end MIME section
LOG_BUG (attachP->toUpdate && attachP->toExtract, /* */, "eMailShrinker: bug M5: update and extract. pos: " << attachP->beginPos);
if (attachP->isSigned) {
LOG ("don't change signed content");
@ -742,8 +779,8 @@ MainAttachment::substitute (ifstream &mbox, ofstream &outbox, const SizeArg &min
bool isHtml = textProp == HTML;
bool isDisclaimer = attachP->toDisclaim;
LOG_BUG (isPlain && isHtml, /**/, "eMailShrinker: bug M6: plain and html: " << attachP->getContentType ());
LOG_BUG (! (isPlain || isHtml), /**/, "eMailShrinker: bug M7: not plain or html: " << attachP->getContentType ());
LOG_BUG (isPlain && isHtml, /* */, "eMailShrinker: bug M6: plain and html: " << attachP->getContentType ());
LOG_BUG (! (isPlain || isHtml), /* */, "eMailShrinker: bug M7: not plain or html: " << attachP->getContentType ());
LOG ("toUpdate: isPlain: " << isPlain << " isHtml: " << isHtml << " isDisclaimer: " << isDisclaimer);
if (attachP != this)
copy (mbox, outbox, attachP->beginInParent, attachP->contentPos);
@ -806,25 +843,31 @@ MainAttachment::substitute (ifstream &mbox, ofstream &outbox, const SizeArg &min
curPos = attachP->endPos;
}
if (plainDisclaim.size () && (attachMode & ATTACHMENT)) {
if (subAttachements.size ()) {
streamoff lastPos = subAttachements.back ().endPos;
copy (mbox, outbox, curPos, lastPos);
curPos = lastPos;
}
if (attachMode & ATTACHMENT) {
LOG ("Add kaz attachment");
if (movedContentType.size ()) {
copy (mbox, outbox, curPos, endPos);
outbox << addedBoundary.substr (0, addedBoundaryMiddleSize) << endl
<< KAZ_ATTACHMENT_TEXT_HTML << endl;
} else
outbox << boundary.substr (0, boundaryMiddleSize) << endl
<< KAZ_ATTACHMENT_TEXT_HTML << endl;
cerr << "eMailShrinker: force attachment" << endl;
if (subAttachements.size ()) {
streamoff lastPos = subAttachements.back ().endPos;
copy (mbox, outbox, curPos, lastPos);
curPos = lastPos;
}
string content (KAZ_HTML_CONTENT+htmlDisclaim+BODY_END+HTML_END);
base64Encode (content);
outbox << boundary.substr (0, boundary.length () -2) << endl
<< KAZ_ATTACHMENT_TEXT_HTML << endl
<< content << endl;
outbox << content << endl;
outbox.flush ();
}
copy (mbox, outbox, curPos, endPos);
if (MULTI == headerType)
outbox << boundary.substr (0, boundary.length ()) << endl;
if (!movedContentType.size ())
copy (mbox, outbox, curPos, endPos);
else
outbox << addedBoundary << endl;
outbox.close ();
}

View File

@ -33,8 +33,8 @@
////////////////////////////////////////////////////////////////////////////
#include "version.hpp"
const std::string kaz::LAST_VERSION_NUM ("2.17");
const std::string kaz::LAST_VERSION_DATE ("2023-04-23");
const std::string kaz::LAST_VERSION_NUM ("2.18");
const std::string kaz::LAST_VERSION_DATE ("2023-10-29");
const std::string kaz::LAST_VERSION (LAST_VERSION_NUM+" "+LAST_VERSION_DATE+" eMailShrinker");
#include <iostream>
@ -202,9 +202,11 @@ main (int argc, char** argv) {
attachment.markSignificant (minAttachSize, mbox);
mbox.close ();
if (listFlag)
if (listFlag) {
// debug
cerr << attachment;
return 0;
}
if (updateListFlag) {
// case update

View File

@ -1,294 +0,0 @@
////////////////////////////////////////////////////////////////////////////
// Copyright KAZ 2021 //
// //
// contact (at) kaz.bzh //
// //
// This software is a filter to shrink email by attachment extraction. //
// //
// This software is governed by the CeCILL-B license under French law and //
// abiding by the rules of distribution of free software. You can use, //
// modify and/or redistribute the software under the terms of the //
// CeCILL-B license as circulated by CEA, CNRS and INRIA at the following //
// URL "http://www.cecill.info". //
// //
// As a counterpart to the access to the source code and rights to copy, //
// modify and redistribute granted by the license, users are provided //
// only with a limited warranty and the software's author, the holder of //
// the economic rights, and the successive licensors have only limited //
// liability. //
// //
// In this respect, the user's attention is drawn to the risks associated //
// with loading, using, modifying and/or developing or reproducing the //
// software by the user in light of its specific status of free software, //
// that may mean that it is complicated to manipulate, and that also //
// therefore means that it is reserved for developers and experienced //
// professionals having in-depth computer knowledge. Users are therefore //
// encouraged to load and test the software's suitability as regards //
// their requirements in conditions enabling the security of their //
// systems and/or data to be ensured and, more generally, to use and //
// operate it in the same conditions as regards security. //
// //
// The fact that you are presently reading this means that you have had //
// knowledge of the CeCILL-B license and that you accept its terms. //
////////////////////////////////////////////////////////////////////////////
#define LAST_VERSION "1.1 2022-10-30 jirafeauAPI"
#include <iostream>
#include <string>
#include <curl/curl.h>
#include <chrono>
#include <boost/program_options.hpp>
#include <boost/filesystem.hpp>
#include "kazDebug.hpp"
#include "kazMisc.hpp"
#include "SizeArg.hpp"
using namespace std;
using namespace boost;
using namespace boost::program_options;
using namespace kaz;
namespace bfs = boost::filesystem;
// ================================================================================
static options_description mainDescription ("Main options", getCols ());
static options_description hide ("Hidded options", getCols ());
static char *prog = NULL;
// ================================================================================
void
usage (const string &msg = "", const bool &hidden = false) {
if (!msg.empty ()) {
cout << msg << endl;
exit (1);
}
cout << endl
<< "Usage: " << endl
<< " A) " << prog << " [-s size] [-t period] [-c content-type] [-n attachName] [-f server] send file [password] > url,delCode" << endl
<< " B) " << prog << " [-t period] [-f server] update ref > dealine" << endl
<< endl << " store ficle" << endl << endl
<< " A: send file (options : s, t)" << endl
<< " B: update deadline (options : t) " << endl
<< endl << mainDescription
<< endl;
if (hidden)
cout << hide << endl;
exit (0);
}
void
version () {
cout << LAST_VERSION << " KAZ team production (https://kaz.bzh/)" << endl;
exit (0);
}
static auto startPrg = std::chrono::high_resolution_clock::now ();
void
showTime (string msg) {
using namespace std::chrono;
static auto stopPrg = high_resolution_clock::now ();
cerr << msg << " done in " << ns2string (duration_cast<duration<double> > (stopPrg-startPrg).count ()) << endl;
}
// ================================================================================
static size_t
WriteCallback (void *contents, size_t size, size_t nmemb, void *userp) {
((std::string*) userp)->append ((char*) contents, size * nmemb);
return size * nmemb;
}
// ================================================================================
static const string inputFile = "input-file";
static const char *const inputFileC = inputFile.c_str ();
int
main (int argc, char** argv) {
// uncomment next line in case of debug parse options
// Log::debug = true;
DEF_LOG ("main:", "");
prog = argv [0];
bool
debugFlag (false),
helpFlag (false),
versionFlag (false),
useTheForceLuke (false);
enum JirCmd { SEND, UPDATE } jirCmd;
string
inputFileName,
password,
contentType,
attachName,
urlBase ("http://file.kaz.bzh"),
uploadPage ("/a.php"),
updatePage ("/a.php"),
minimumAvailability ("month"),
proxy;
SizeArg maxUploadSize ("100 Mi");
try {
mainDescription.add_options ()
("help,h", bool_switch (&helpFlag), "produce this help message")
("version,v", bool_switch (&versionFlag), "display version information")
("contentType,c", value<string> (&contentType)->default_value (contentType), "content-type of the sended file")
("attachName,n", value<string> (&attachName)->default_value (attachName), "force attachment name")
("minimumAvailability,t", value<string> (&minimumAvailability)->default_value (minimumAvailability), "minimum period of available download")
("maxUploadSize,s", value<SizeArg> (&maxUploadSize)->default_value (maxUploadSize), "maximum upload size")
("file server registery,f", value<string> (&urlBase)->default_value (urlBase), "server where file are temporary stored")
;
hide.add_options ()
("useTheForceLuke", bool_switch (&useTheForceLuke), "display hidded options")
("debug,g", bool_switch (&debugFlag), "debug mode")
("proxy,p", value<string> (&proxy)->default_value (proxy), "set proxy (proxy-host.org:8080)")
("uploadPage,u", value<string> (&uploadPage)->default_value (uploadPage), "upload page")
("updatePage,v", value<string> (&updatePage)->default_value (updatePage), "update page")
;
options_description cmd ("All options");
cmd.add (mainDescription).add (hide).add_options ()
(inputFileC, value<vector<string> > (), "input")
;
positional_options_description p;
p.add (inputFileC, -1);
variables_map vm;
basic_parsed_options<char> parsed = command_line_parser (argc, argv).options (cmd).positional (p).run ();
store (parsed, vm);
notify (vm);
if (debugFlag) {
#ifdef DISABLE_LOG
cerr << "No debug option available (was compiled with -DDISABLE_LOG)" << endl;
#endif
}
Log::debug = debugFlag;
if (useTheForceLuke)
usage ("", true);
if (versionFlag)
version ();
if (helpFlag)
usage ();
if (vm.count (inputFileC)) {
vector<string> var = vm[inputFileC].as<vector<string> > ();
int nbArgs = vm[inputFileC].as<vector<string> > ().size ();
if (!nbArgs)
usage ("No command");
if (var [0].compare ("send") == 0)
jirCmd = SEND;
else if (var [0].compare ("update") == 0)
jirCmd = UPDATE;
else
usage ("Unknown command ("+var [0]+")");
if (nbArgs < 2)
usage ("no input file");
inputFileName = var [1];
if (nbArgs == 3)
password = var [2];
if (nbArgs > 3)
usage ("Too much arguments");
}
} catch (std::exception &e) {
cerr << "error: " << e.what() << endl;
usage ();
return 1;
} catch (...) {
cerr << "Exception of unknown type!" << endl;
return 1;
}
if (inputFileName.empty ())
usage ("no input");
CURL *easyhandle = curl_easy_init ();
if (! easyhandle) {
cerr << "no curl" << endl;
return 1;
}
string readBuffer;
if (proxy.length ())
curl_easy_setopt(easyhandle, CURLOPT_PROXY, proxy.c_str ());
curl_easy_setopt (easyhandle, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt (easyhandle, CURLOPT_WRITEDATA, &readBuffer);
curl_mime *multipart = curl_mime_init (easyhandle);
curl_mimepart *part = nullptr;
switch (jirCmd) {
case SEND: {
LOG ("SEND: " << (urlBase+uploadPage));
curl_easy_setopt (easyhandle, CURLOPT_URL, (urlBase+uploadPage).c_str ());
LOG ("maxUploadSize: " << maxUploadSize);
long uploadsize = (size_t) maxUploadSize;
curl_easy_setopt (easyhandle, CURLOPT_INFILESIZE, uploadsize);
LOG ("time: " << minimumAvailability);
part = curl_mime_addpart (multipart);
curl_mime_name (part, "time");
curl_mime_data (part, minimumAvailability.c_str (), CURL_ZERO_TERMINATED);
if (password.size ()) {
LOG ("key: " << password);
part = curl_mime_addpart (multipart);
curl_mime_name (part, "key");
curl_mime_data (part, password.c_str (), CURL_ZERO_TERMINATED);
}
LOG ("inputFileName: " << bfs::path (inputFileName).filename ());
part = curl_mime_addpart (multipart);
curl_mime_name (part, "file");
if (contentType.length ()) {
LOG ("contentType: " << contentType);
curl_mime_type (part, contentType.c_str ());
}
if (attachName.empty ()) {
attachName = bfs::path (inputFileName).filename ().c_str ();
LOG ("attachName: " << attachName);
}
curl_mime_filename (part, attachName.c_str ());
FILE *fp = fopen (inputFileName.c_str (), "r");
fseek (fp, 0L, SEEK_END);
long int fsize (ftell (fp));
fseek (fp, 0L, SEEK_SET);
curl_mime_data_cb (part, fsize,
(curl_read_callback) fread,
(curl_seek_callback) fseek,
NULL, //(curl_seek_callback) fclose,
fp);
}
break;
case UPDATE: {
LOG ("UPDATE: " << (urlBase+updatePage));
curl_easy_setopt (easyhandle, CURLOPT_URL, (urlBase+updatePage).c_str ());
LOG ("h: " << inputFileName);
part = curl_mime_addpart (multipart);
curl_mime_name (part, "h");
curl_mime_data (part, inputFileName.c_str (), CURL_ZERO_TERMINATED);
LOG ("u: " << minimumAvailability);
part = curl_mime_addpart (multipart);
curl_mime_name (part, "u");
curl_mime_data (part, minimumAvailability.c_str (), CURL_ZERO_TERMINATED);
}
break;
}
curl_easy_setopt (easyhandle, CURLOPT_MIMEPOST, multipart);
CURLcode res (curl_easy_perform (easyhandle));
curl_easy_cleanup (easyhandle);
cout << readBuffer << endl;
showTime ("Upload");
if (res != CURLE_OK)
cerr << prog << " failed: " << curl_easy_strerror (res) << endl;
return 0;
}
// ================================================================================

View File

@ -105,7 +105,7 @@ kaz::ns2string (const double &delta) {
// ================================================================================
void
kaz::replaceAll (string& str, const string &from, const string &to) {
DEF_LOG ("kaz::replaceAll", "form: " << from << " to: " << to);
DEF_LOG ("kazMisc::replaceAll", "form: " << from << " to: " << to);
if (str.empty () || from.empty ())
return;
for (string::size_type startPos (0);
@ -116,7 +116,7 @@ kaz::replaceAll (string& str, const string &from, const string &to) {
void
kaz::replaceAll (string& str, const map<const string, const string> &subst) {
DEF_LOG ("kaz::replaceAll", "str: " << str);
DEF_LOG ("kazMisc::replaceAll", "str: " << str.substr (0, 100) << "...");
for (map<const string, const string>::const_iterator it = subst.begin (); it != subst.end (); ++it)
replaceAll (str, it->first, it->second);
}
@ -124,16 +124,16 @@ kaz::replaceAll (string& str, const map<const string, const string> &subst) {
// ================================================================================
void
kaz::toLower (string &content) {
DEF_LOG ("kaz::toLower", "content: " << content);
DEF_LOG ("kazMisc::toLower", "content: " << content.substr (0, 100) << "...");
static locale loc;
for (string::size_type i = 0; i < content.length (); ++i)
content [i] = tolower (content[i], loc);
LOG ("content: " << content);
LOG ("content: " << content.substr (0, 100) << "...");
}
const string &
kaz::toUpperIfNeed (const string &src, string &tmp) {
DEF_LOG ("kaz::toUpperIfNeed", "src: " << src);
DEF_LOG ("kazMisc::toUpperIfNeed", "src: " << src);
for (string::const_iterator it = src.begin (); it != src.end (); ++it)
if (*it != toupper (*it)) {
tmp.reserve ();
@ -151,7 +151,7 @@ caseInsensitiveCharCompare (char a, char b) {
string::size_type
kaz::caseInsensitiveFind (const string& s, const string& pattern, const string::size_type &pos) {
DEF_LOG ("kaz::caseInsensitiveFind", "pattern: " << pattern << " pos: " << pos << " s: " << s);
DEF_LOG ("kazMisc::caseInsensitiveFind", "pattern: " << pattern << " pos: " << pos << " s: " << s.substr (0, 100) << "...");
string tmp;
const string &upperPattern (toUpperIfNeed (pattern, tmp));
LOG ("pattern: " << upperPattern);
@ -164,7 +164,7 @@ kaz::caseInsensitiveFind (const string& s, const string& pattern, const string::
string::size_type
kaz::caseInsensitiveRFind (const string& s, const string& pattern, const string::size_type &pos) {
DEF_LOG ("kaz::caseInsensitiveRFind", "pattern: " << pattern << " pos: " << pos << " s: " << s);
DEF_LOG ("kazMisc::caseInsensitiveRFind", "pattern: " << pattern << " pos: " << pos << " s: " << s.substr (0, 100) << "...");
string tmp;
const string &upperPattern (toUpperIfNeed (pattern, tmp));
LOG ("pattern: " << upperPattern);
@ -192,7 +192,7 @@ kaz::boundaryGen (const int &size) {
template<char delim>
void
kaz::quotedDecode (string &content) {
DEF_LOG ("kaz::quotedDecode", "delim: " << delim << " content: " << content);
DEF_LOG ("kazMisc::quotedDecode", "delim: " << delim << " content: " << content.substr (0, 100) << "...");
string::size_type len (content.length ());
if (!len)
return;
@ -206,25 +206,24 @@ kaz::quotedDecode (string &content) {
continue;
}
if (p+1 < content.end () && *(p+1) == '\n') {
LOG_BUG (q == content.begin (), ++p;continue, "kazMisc::quotedDecode bug: bad quoted-printable format. (start with '=', delim: " << int (delim) << " content: " << content << ")");
LOG_BUG (q == content.begin (), ++p;continue, "kazMisc::quotedDecode bug: bad quoted-printable format. (start with '=', delim: " << int (delim) << " content: " << content.substr (0, 100) << "...)");
++p;
--q;
continue;
}
LOG_BUG (p+3 > content.end () || !isxdigit (p[1]) || !isxdigit (p[2]), return, "kazMisc::quotedDecode bug: bad quoted-printable format. (delim: " << int (delim) << " content: " << content << ")");
LOG_BUG (p+3 > content.end () || !isxdigit (p[1]) || !isxdigit (p[2]), return, "kazMisc::quotedDecode bug: bad quoted-printable format. (delim: " << int (delim) << " p:" << content.substr (p-content.begin (), 3) << " content: " << content.substr (0, 100) << "... len: " << len << ")");
*q = (char) ((getHexaVal (p[1]) << 4) + getHexaVal (p[2]));
p += 2;
}
content.resize (q-content.begin ());
LOG ("content: " << content);
LOG ("content: " << content.substr (0, 100) << "...");
}
// ================================================================================
void
kaz::quotedEncode (string &content) {
DEF_LOG ("kaz::quotedDecode", "content: " << content);
DEF_LOG ("kazMisc::quotedDecode", "content: " << content.substr (0, 100) << "...");
string::size_type nbQuoted (0);
for (string::const_iterator it = content.begin (); it != content.end (); ++it)
if (isQuotedPrintable (*it))
@ -267,13 +266,13 @@ kaz::quotedEncode (string &content) {
++cols;
}
content.swap (result);
LOG ("content: " << content);
LOG ("content: " << content.substr (0, 100) << "...");
}
// ================================================================================
void
kaz::base64Decode (string &content) {
DEF_LOG ("kaz::base64Decode", "content: " << content);
DEF_LOG ("kazMisc::base64Decode", "content: " << content.substr (0, 100) << "...");
string::size_type len (content.length ());
if (!len)
return;
@ -294,7 +293,7 @@ kaz::base64Decode (string &content) {
if (!isBase64 (c)) {
content.resize (lastOK-content.begin ());
LOG ("kazMisc::base64Decode bug: bad base64 format. (content: " << content << ")");
LOG ("kazMisc::base64Decode bug: bad base64 format. (content: " << content.substr (0, 100) << "...)");
return;
}
buff [idx] = getBase64Val (c);
@ -317,13 +316,13 @@ kaz::base64Decode (string &content) {
}
}
content.resize (q-content.begin ());
LOG ("content: " << content);
LOG ("content: " << content.substr (0, 100) << "...");
}
// ================================================================================
void
kaz::base64Encode (string &content) {
DEF_LOG ("kaz::base64Encode", "content: " << content);
DEF_LOG ("kazMisc::base64Encode", "content: " << content.substr (0, 100) << "...");
string::size_type length (content.length ());
std::string result;
result.reserve ((length + 2) / 3 * 4 + length / MAX_QUOTED_PRINTABLE_SIZE + 1);
@ -353,13 +352,13 @@ kaz::base64Encode (string &content) {
}
}
content = result;
LOG ("content: " << content);
LOG ("content: " << content.substr (0, 100) << "...");
}
// ================================================================================
void
kaz::iso2utf (string &content) {
DEF_LOG ("kaz::iso2utf", "content: " << content);
DEF_LOG ("kazMisc::iso2utf", "content: " << content.substr (0, 100) << "...");
string::size_type len (content.length ());
if (!len)
return;
@ -385,14 +384,14 @@ kaz::iso2utf (string &content) {
if (p == q)
break;
}
LOG ("content: " << content);
LOG ("content: " << content.substr (0, 100) << "...");
}
// ================================================================================
void
kaz::encodedWordDecode (string &content) {
// rfc2047
DEF_LOG ("kaz::encodedWordDecode", "content: " << content);
DEF_LOG ("kazMisc::encodedWordDecode", "content: " << content.substr (0, 100) << "...");
string::size_type charsetPos = content.find ("=?");
if (charsetPos == string::npos)
return;
@ -436,29 +435,29 @@ kaz::encodedWordDecode (string &content) {
pos = m.position () + m.str ().length ();
}
content = result + content.substr (pos);
LOG ("content: " << content);
LOG ("content: " << content.substr (0, 100) << "...");
}
// ================================================================================
void
kaz::charsetValueDecode (string &content) {
// rfc2184
DEF_LOG ("kaz::charsetValueDecode", "content: " << content);
DEF_LOG ("kazMisc::charsetValueDecode", "content: " << content.substr (0, 100) << "...");
string::size_type langPos = content.find ("'");
LOG_BUG (langPos == string::npos, return, "kazMisc::charsetValueDecode bug: no '. (content: " << content << ")");
LOG_BUG (langPos == string::npos, return, "kazMisc::charsetValueDecode bug: no '. (content: " << content.substr (0, 100) << "...)");
string::size_type contentPos = content.find ("'", langPos+1);
LOG_BUG (contentPos == string::npos, return, "kazMisc::charsetValueDecode bug: no double '. (content: " << content << ")");
LOG_BUG (contentPos == string::npos, return, "kazMisc::charsetValueDecode bug: no double '. (content: " << content.substr (0, 100) << "...)");
string tmp (content.substr (contentPos+1));
quotedDecode<'%'> (tmp);
LOG ("tmp: " << tmp);
LOG ("tmp: " << tmp.substr (0, 100) << "...");
string charset (content.substr (0, langPos));
toLower (charset);
if (! caseInsensitiveFind (charset, "ISO"))
iso2utf (tmp);
content = tmp;
LOG ("content: " << content);
LOG ("content: " << content.substr (0, 100) << "...");
}
// ================================================================================