diff --git a/Makefile b/Makefile index e7ce487..575f0fa 100644 --- a/Makefile +++ b/Makefile @@ -50,12 +50,6 @@ KAZ_SRC = $(patsubst %, $(CPP_DIR)/%.cpp, $(KAZ_MOD)) KAZ_OBJ = $(patsubst %, $(OBJ_DIR)/%.o, $(KAZ_MOD)) KAZ_OUT = $(patsubst %, $(OUT_DIR)/%, $(KAZ_PRG)) -JIR_PRG = jirafeauAPI -JIR_MOD = jirafeauAPI SizeArg kazDebug kazMisc -JIR_SRC = $(patsubst %, $(CPP_DIR)/%.cpp, $(JIR_MOD)) -JIR_OBJ = $(patsubst %, $(OBJ_DIR)/%.o, $(JIR_MOD)) -JIR_OUT = $(patsubst %, $(OUT_DIR)/%, $(JIR_PRG)) - ## FLAGS ############################### #DFLAGS = -O2 -DDISABLE_LOG @@ -71,18 +65,13 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/*/%.cpp $(CC) $< $(IFLAGS) -cpp -c -o $@ ## ENTRIES ############################# -all: init eMailShrinker jirafeauAPI doc +all: init eMailShrinker doc eMailShrinker: $(KAZ_OUT) $(KAZ_OUT): $(KAZ_OBJ) $(CC) $(KAZ_OBJ) $(IFLAGS) -cpp -L$(LIB_DIR) $(LFLAGS) -o $@ -jirafeauAPI: $(JIR_OUT) - -$(JIR_OUT): $(JIR_OBJ) - $(CC) $(JIR_OBJ) $(IFLAGS) -cpp -L$(LIB_DIR) $(LFLAGS) -o $@ - doc: doxygen src/Doxyfile diff --git a/README.md b/README.md index 7dae8b3..0cea90b 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,6 @@ depollueur/ │   ├── Attachment.cpp │   ├── eMailShrinker.cpp │   ├── EmbeddedData.cpp - │   ├── jirafeauAPI.cpp │   ├── kazDebug.cpp │   ├── kazMisc.cpp │   ├── MainAttachment.cpp diff --git a/src/bash/checkAltered.sh b/src/bash/checkAltered.sh new file mode 100755 index 0000000..b1d677d --- /dev/null +++ b/src/bash/checkAltered.sh @@ -0,0 +1,78 @@ +#!/bin/bash +########################################################################## +# 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. # +########################################################################## + +PRG=$(basename $0) + +usage () { + echo "Usage: ${PRG} logDir" + exit 1 +} + +BOLD='\e[1m' +RED='\e[0;31m' +GREEN='\e[0;32m' +YELLOW='\e[0;33m' +BLUE='\e[0;34m' +MAGENTA='\e[0;35m' +CYAN='\e[0;36m' +NC='\e[0m' # No Color +NL=' +' +[ "$#" -eq 1 ] || usage +logDir=$(realpath "$1") + +######################################## +# recherche des binaires +cd $(dirname $0) +eMailShrinker="$(realpath "./eMailShrinker")" +[ -x "${eMailShrinker}" ] || eMailShrinker="$(realpath "../../build/out/eMailShrinker")" +[ -x "${eMailShrinker}" ] || ( echo "${RED}eMailShrinker not found${NC}" ; exit) + + +cd "${logDir}" +for i in in.*.orig; +do + clear + echo -e " ${GREEN}${BOLD}${i//.orig}${NC}\n" + "${eMailShrinker}" -l ${i} + echo -e "\n ####################\n" + "${eMailShrinker}" -l ${i//.orig}.altered + echo -en "\n(q = quit / y = rm / default = continue)? " + read rep + case "${rep}" in + "q" ) break;; + "y") rm ${i} ${i//.orig}.altered + esac +done diff --git a/src/bash/checkShrinker.sh b/src/bash/checkShrinker.sh new file mode 100755 index 0000000..8ee010e --- /dev/null +++ b/src/bash/checkShrinker.sh @@ -0,0 +1,77 @@ +#!/bin/bash +########################################################################## +# 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. # +########################################################################## + +PRG=$(basename $0) +FILTER_TEST="$(realpath "$(dirname $0)/filterTest.sh")" + +ATTACH_MODE="FOOTER" + +usage () { + echo "Usage: ${PRG} {NONE|FOOTER|ATTACHMENT|BOTH} mbox..." + exit 1 +} + +######################################## +BOLD='\e[1m' +RED='\e[0;31m' +GREEN='\e[0;32m' +YELLOW='\e[0;33m' +BLUE='\e[0;34m' +MAGENTA='\e[0;35m' +CYAN='\e[0;36m' +NC='\e[0m' # No Color +NL=' +' + +######################################## +[ "$#" -lt 2 ] && usage + +ATTACH_MODE="$1"; shift + +case "${ATTACH_MODE}" in + ""|NONE|FOOTER|ATTACHMENT|BOTH);; + *) usage;; +esac + +for mbox in $*; do + clear + echo -e " ${GREEN}${BOLD}${mbox}${NC}\n" + "${FILTER_TEST}" -s -m "${ATTACH_MODE}" "${mbox}" + echo -en "\n(q = quit / default = continue)? " + read rep + case "${rep}" in + "q" ) break;; + esac +done diff --git a/src/bash/filter.sh b/src/bash/filter.sh index 0790fa8..6d54c6e 100755 --- a/src/bash/filter.sh +++ b/src/bash/filter.sh @@ -38,9 +38,8 @@ # - installer l'utilitaire dos2unix # - le contenu de INSPECT_DIR doit être accessible en écriture pour le # proriétaire du script -# - shrinkEMail et jirafeau.sh doivent être accessible en execution pour -# le roriétaire du script -# - il faut que root fasse avant : +# - shrinkEMail doit être accessible en execution pour le proriétaire +# - comme le programme n'a pas de privigèle, il faut que root fasse avant : # mkdir -p "${DIR_LOG}/pb/" ; chmod a+rwx "${DIR_LOG}/pb/" ########################################################################## @@ -63,7 +62,6 @@ MAILS=/tmp/FILTER MAX_KEEP_IN_MAIL=5ki MAX_UPLOAD_SIZE=1Gi SHRINK_CMD=/home/filter/eMailShrinker -JIRAFEAU_CMD=/home/filter/jirafeauAPI JIRAFEAU_URL=https://depot.${DOMAINNAME:-"kaz.bzh"} JIRAFEAU_LOCAL=http://depot MD5_CMD=/usr/bin/md5sum @@ -80,20 +78,20 @@ KEEP_FAILED=true DEBUG=true #################### FONCTIONS ############################################ -BOLD='[1m' -RED='[0;31m' -GREEN='[0;32m' -YELLOW='[0;33m' -BLUE='[0;34m' -MAGENTA='[0;35m' -CYAN='[0;36m' -NC='[0m' # No Color +BOLD='\e[1m' +RED='\e[0;31m' +GREEN='\e[0;32m' +YELLOW='\e[0;33m' +BLUE='\e[0;34m' +MAGENTA='\e[0;35m' +CYAN='\e[0;36m' +NC='\e[0m' # No Color NL=' ' #--------------------- Fichier de LOG ------------------- LOG_FIC () { - echo "${BLUE}$(date +%d-%m-%Y-%H-%M-%S)${NC} : $*" >> "${TMP_LOG}" + echo -e "${BLUE}$(date +%d-%m-%Y-%H-%M-%S)${NC} : $*" >> "${TMP_LOG}" } quitFilter () { @@ -124,11 +122,11 @@ curlJirafeauSend () { # $4: name # $5: password - type=$3 - [ -z "${type}" ] && type="text/plain" - LOG_FIC " - curl -X POST -F \"time=$1\" -F \"key=$5\" -F \"file=@$2;type=${type};filename=\\\"$4\\\"\" \"${JIRAFEAU_LOCAL}/a.php\"" + type="type=$3;" + [ -z "$3" -o "$3" = "/" ] && type="" + LOG_FIC " - curl -X POST -F \"time=$1\" -F \"key=$5\" -F \"file=@$2;${type}filename=\\\"$4\\\"\" \"${JIRAFEAU_LOCAL}/a.php\"" for num in {1..2}; do - OUTPUT=$(curl -X POST -F "time=$1" -F "key=$5" -F "file=@$2;type=${type};filename=\"$4\"" "${JIRAFEAU_LOCAL}/a.php") + OUTPUT=$(curl -X POST -F "time=$1" -F "key=$5" -F "file=@$2;${type}filename=\"$4\"" "${JIRAFEAU_LOCAL}/a.php") read JIR_TOKEN <<< "${OUTPUT}" case "${JIR_TOKEN}" in "" | no | *Error* | \<* ) @@ -151,7 +149,7 @@ function check_skip_domains() { local domain="${email##*@}" # Utiliser grep pour vérifier si le domaine est dans la liste des domaines à sauter - if echo "$SKIP_DOMAINS" | grep -q -w "$domain"; then + if echo "${SKIP_DOMAINS}" | grep -q -w "${domain}"; then echo "yes" return fi @@ -162,7 +160,7 @@ function check_skip_domains() { } #################### MAIN ################################################# -echo "${NL}${BLUE}$(date +%d-%m-%Y-%H-%M-%S)${NC} : ${GREEN}######################################## filter start (log in ${TMP_LOG})${NC}" >> "${FIC_LOG}" +echo -e "${NL}${BLUE}$(date +%d-%m-%Y-%H-%M-%S)${NC} : ${GREEN}######################################## filter start (log in ${TMP_LOG})${NC}" >> "${FIC_LOG}" LOG_FIC "${GREEN}######################################## ${TMP_LOG} ${NC}" if ! mkdir -p "${MAILS}"; then diff --git a/src/bash/filterTest.sh b/src/bash/filterTest.sh index 6761bb8..d515e08 100755 --- a/src/bash/filterTest.sh +++ b/src/bash/filterTest.sh @@ -36,22 +36,21 @@ PRG=$(basename $0) ATTACH_MODE="FOOTER" - -BOLD='' -RED='' -GREEN='' -YELLOW='' -BLUE='' -MAGENTA='' -CYAN='' -NC='' # No Color +export SIMULATE="" + +BOLD='\e[1m' +RED='\e[0;31m' +GREEN='\e[0;32m' +YELLOW='\e[0;33m' +BLUE='\e[0;34m' +MAGENTA='\e[0;35m' +CYAN='\e[0;36m' +NC='\e[0m' # No Color NL=' ' - -TTY=$(tty) ######################################## LOG () { - echo "$1" >> "${TTY}" + echo -e "$1" 1>&2 } usage () { @@ -64,6 +63,7 @@ while : ; do -h*) usage;; -v*) "${eMailShrinker}" -v; exit;; -g) DEBUG="-g"; shift;; + -s) SIMULATE="echo"; shift;; -m) shift; ATTACH_MODE="$1"; shift;; *) break;; esac @@ -83,11 +83,11 @@ mbox=$(realpath "$1") cd $(dirname $0) eMailShrinker="$(realpath "./eMailShrinker")" [ -x "${eMailShrinker}" ] || eMailShrinker="$(realpath "../../build/out/eMailShrinker")" -[ -x "${eMailShrinker}" ] || ( echo "${RED}eMailShrinker not found${NC}" ; exit) +[ -x "${eMailShrinker}" ] || ( echo -e "${RED}eMailShrinker not found${NC}" ; exit) ######################################## dos2unix "${mbox}" -DOMAINNAME="$(cat domainname)" +[ -z "${SIMULATE}" ] && DOMAINNAME="$(cat domainname)" JIRAFEAU_URL="https://depot.${DOMAINNAME}" JIRAFEAU_LOCAL="${JIRAFEAU_URL}" @@ -99,8 +99,7 @@ curlJirafeauUpdate () { # $1: periode # $2: jirafeauItemRef - curl -X POST -d "u=$1" -d "h=$2" "${JIRAFEAU_LOCAL}/a.php" - #"${jirafeauAPI}" -f "${JIRAFEAU_LOCAL}" -t "$1" update "$2" + [ -z "${SIMULATE}" ] && curl -X POST -d "u=$1" -d "h=$2" "${JIRAFEAU_LOCAL}/a.php" } curlJirafeauSend () { @@ -110,11 +109,14 @@ curlJirafeauSend () { # $4: name # $5: password - type=$3 - [ -z "${type}" ] && type="text/plain" - LOG "curl -X POST -F \"time=$1\" -F \"key=$5\" -F \"file=@$2;type=${type};filename=\\\"$4\\\"\" \"${JIRAFEAU_LOCAL}/a.php\"" - curl -X POST -F "time=$1" -F "key=$5" -F "file=@$2;type=${type};filename=\"$4\"" "${JIRAFEAU_LOCAL}/a.php" || exit 1 - #"${jirafeauAPI}" -f "${JIRAFEAU_LOCAL}" -t "$1" -s "1Gi" -c "${type}" -n "$4" send "$2" "$5" + if [ -n "${SIMULATE}" ]; then + echo -e "TokenXXX\nCodeX" + return + fi + type="type=$3;" + [ -z "$3" -o "$3" = "/" ] && type="" + LOG "curl -X POST -F \"time=$1\" -F \"key=$5\" -F \"file=@$2;${type}filename=\\\"$4\\\"\" \"${JIRAFEAU_LOCAL}/a.php\"" + curl -X POST -F "time=$1" -F "key=$5" -F "file=@$2;${type}filename=\"$4\"" "${JIRAFEAU_LOCAL}/a.php" || exit 1 } ######################################## @@ -126,19 +128,18 @@ echo -e "time: $(date "+%Y-%m-%d-%H:%M:%S")\nid: $(date +%s)" > "${TMP_DIR}/arch ######################################## # affichage de la structure de départ -LOG " - ${BLUE}mbox: ${mbox}${NC}" +LOG " - ${BLUE}mbox: ${mbox}${NC}${YELLOW}" "${eMailShrinker}" -l "${mbox}" -LOG +LOG "${NC}" ######################################## # recherche des prolongations des délais de grace -"${eMailShrinker}" ${DEBUG} -u "${mbox}" > "${TMP_DIR}/url-to-refresh.txt" 2>> "${TTY}" +"${eMailShrinker}" ${DEBUG} -u "${mbox}" > "${TMP_DIR}/url-to-refresh.txt" cat "${TMP_DIR}/url-to-refresh.txt" | grep "${JIRAFEAU_URL}" | while read REMOTE_LINK; do REMOTE_REF=$(echo "${REMOTE_LINK}" | sed -e 's/.*h=\([^&]*\).*/\1/' -e 's/.*http.*//') [ -z "${REMOTE_REF}" ] && continue LOG " - ${BLUE}update ${REMOTE_REF}${NC}" - curlJirafeauUpdate "month" "${REMOTE_REF}" 2>> "${TTY}" - LOG + curlJirafeauUpdate "month" "${REMOTE_REF}" echo "old: ${REMOTE_REF} ${REMOTE_KEY}" >> "${TMP_DIR}/archive-content.txt" done @@ -167,7 +168,7 @@ cat "${TMP_DIR}/PJ-name.txt" | { LOG " - ${BLUE}find ${ATTACH_NAME} / (${ATTACH_CONTENT_TYPE}) / ${ATTACH_MEDIA} ${NC}" PASSWORD=$(apg -n 1 -m 12 -M cln) PASSWORD_MD5=$(echo -n ${PASSWORD} | ${MD5_CMD} | cut -d \ -f 1) - curlJirafeauSend "month" "${ATTACH_MEDIA}" "${ATTACH_CONTENT_TYPE}" "${ATTACH_NAME}" "${PASSWORD}" 2>> "${TTY}" > "${TMP_DIR}/one.txt" + curlJirafeauSend "month" "${ATTACH_MEDIA}" "${ATTACH_CONTENT_TYPE}" "${ATTACH_NAME}" "${PASSWORD}" > "${TMP_DIR}/one.txt" cat "${TMP_DIR}/one.txt" | { read JIR_TOKEN @@ -175,7 +176,7 @@ cat "${TMP_DIR}/PJ-name.txt" | { case "${JIR_TOKEN}" in "" | no | *Error* | \<* ) LOG " - ${RED}can't upload ${ATTACH_MEDIA} <${JIR_TOKEN}> <${JIR_CODE}>${NC}" - cat "${TMP_DIR}/one.txt" >> "${TTY}" + cat "${TMP_DIR}/one.txt" >&2 echo "url:" exit 1 ;; @@ -191,7 +192,7 @@ cat "${TMP_DIR}/PJ-name.txt" | { if [ "${NB_ATTACH}" -gt 1 ]; then PASSWORD=$(apg -n 1 -m 12 -M cln) PASSWORD_MD5=$(echo -n ${PASSWORD} | ${MD5_CMD} | cut -d \ -f 1) - curlJirafeauSend "month" "${TMP_DIR}/archive-content.txt" "text/kaz_email_archive" "archive_content" "${PASSWORD}" 2>> "${TTY}" > "${TMP_DIR}/one.txt" || exit 1 + curlJirafeauSend "month" "${TMP_DIR}/archive-content.txt" "text/kaz_email_archive" "archive_content" "${PASSWORD}" > "${TMP_DIR}/one.txt" || exit 1 cat "${TMP_DIR}/one.txt" | { read JIR_TOKEN read JIR_CODE @@ -221,12 +222,12 @@ LOG " - ${GREEN}ATTACH_MODE: ${ATTACH_MODE}${NC}" ######################################## # substitution des pièces jointes par les codes fournis par jirafeau -cat "${TMP_DIR}/PJ-Keys.txt" | "${eMailShrinker}" ${DEBUG} ${ATTACH_MODE} -s "5ki" "${mbox}" "${TMP_DIR}/new-mbox" 2>> "${TTY}" || exit 1 +cat "${TMP_DIR}/PJ-Keys.txt" | "${eMailShrinker}" ${DEBUG} ${ATTACH_MODE} -s "5ki" "${mbox}" "${TMP_DIR}/new-mbox" || exit 1 ######################################## # affichage de la structure à la fin -LOG " - ${BLUE}new-mbox:${NC}" -"${eMailShrinker}" -l "${TMP_DIR}/new-mbox" 2>> "${TTY}" || exit 1 +LOG " - ${BLUE}new-mbox:${NC}${YELLOW}" +"${eMailShrinker}" -l "${TMP_DIR}/new-mbox" || ( LOG "${NC}" ; exit 1) -echo -e "\nresul in ${TMP_DIR}/new-mbox" +echo -e "\n${NC}${GREEN}${BOLD}resul in ${TMP_DIR}/new-mbox${NC}" exit 0 diff --git a/src/cpp/Attachment.cpp b/src/cpp/Attachment.cpp index d8db6c2..57c4ce7 100644 --- a/src/cpp/Attachment.cpp +++ b/src/cpp/Attachment.cpp @@ -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 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 &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 ()) diff --git a/src/cpp/MainAttachment.cpp b/src/cpp/MainAttachment.cpp index 4637dd8..d8278e7 100644 --- a/src/cpp/MainAttachment.cpp +++ b/src/cpp/MainAttachment.cpp @@ -160,14 +160,13 @@ kaz::operator >> (istream &in, AttachMode &attachMode) { // ================================================================================ const string kaz::headerTypeLabels[] = { - "Same", "Multi", "MainPlain", "AttachHtml" + "Same", "Mixed", "MainPlain" }; const map 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 " - 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 &liOne) { // html text => "
  • name" - 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 { text/plainOKmute multimute multi empty mailmute plainmute multimute html - */ +*/ 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 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::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 (); } diff --git a/src/cpp/eMailShrinker.cpp b/src/cpp/eMailShrinker.cpp index c84f0ea..9f01c76 100644 --- a/src/cpp/eMailShrinker.cpp +++ b/src/cpp/eMailShrinker.cpp @@ -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 @@ -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 diff --git a/src/cpp/jirafeauAPI.cpp b/src/cpp/jirafeauAPI.cpp deleted file mode 100644 index ec52de8..0000000 --- a/src/cpp/jirafeauAPI.cpp +++ /dev/null @@ -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 -#include -#include -#include -#include -#include - -#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 > (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 (&contentType)->default_value (contentType), "content-type of the sended file") - ("attachName,n", value (&attachName)->default_value (attachName), "force attachment name") - ("minimumAvailability,t", value (&minimumAvailability)->default_value (minimumAvailability), "minimum period of available download") - ("maxUploadSize,s", value (&maxUploadSize)->default_value (maxUploadSize), "maximum upload size") - ("file server registery,f", value (&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 (&proxy)->default_value (proxy), "set proxy (proxy-host.org:8080)") - ("uploadPage,u", value (&uploadPage)->default_value (uploadPage), "upload page") - ("updatePage,v", value (&updatePage)->default_value (updatePage), "update page") - ; - - options_description cmd ("All options"); - cmd.add (mainDescription).add (hide).add_options () - (inputFileC, value > (), "input") - ; - positional_options_description p; - p.add (inputFileC, -1); - variables_map vm; - basic_parsed_options 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 var = vm[inputFileC].as > (); - int nbArgs = vm[inputFileC].as > ().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; -} - -// ================================================================================ diff --git a/src/cpp/kazMisc.cpp b/src/cpp/kazMisc.cpp index 03f17a0..1e09ba5 100644 --- a/src/cpp/kazMisc.cpp +++ b/src/cpp/kazMisc.cpp @@ -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 &subst) { - DEF_LOG ("kaz::replaceAll", "str: " << str); + DEF_LOG ("kazMisc::replaceAll", "str: " << str.substr (0, 100) << "..."); for (map::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 &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 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) << "..."); } // ================================================================================ diff --git a/src/include/MainAttachment.hpp b/src/include/MainAttachment.hpp index edc95c4..74d4781 100644 --- a/src/include/MainAttachment.hpp +++ b/src/include/MainAttachment.hpp @@ -51,7 +51,7 @@ namespace kaz { ostream &operator << (ostream &out, const AttachMode &attachMode); istream &operator >> (istream &in, AttachMode &attachMode); - enum HeaderType { SAME, MULTI, MAIN_PLAIN, ATTACH_HTML }; + enum HeaderType { SAME, MIXED, MAIN_PLAIN }; extern const string headerTypeLabels[]; extern const map headerTypeMap; ostream &operator << (ostream &out, const HeaderType &headerType); @@ -105,6 +105,14 @@ namespace kaz { vector allMarkedPtrs; /*! previous links find in mbox */ map previousLinks; + /*! boundary if a mixed section is added including previous and next "--" */ + string addedBoundary; + /*! size of added boundary before the last "--" */ + streamoff addedBoundaryMiddleSize; + /*! moved conten-type headers */ + string movedContentType; + + /*! add link only if no significant value already exist. Trust the values from html.*/ void addPrevious (const string &href, const string &name, const bool &trust = false); diff --git a/src/include/kazMisc.hpp b/src/include/kazMisc.hpp index 03ca6a4..112cd17 100644 --- a/src/include/kazMisc.hpp +++ b/src/include/kazMisc.hpp @@ -100,7 +100,7 @@ namespace kaz { inline bool isQuotedPrintable (const char &c) { return - c == ' ' || c == '\t' || (c >= 33 && c <= 126 && c != '=' && c != '.'); + c == ' ' || (c >= 33 && c <= 126 && c != '=' && c != '.'); // '.' is available in rfc2184 but it avoid to check '.' alone in a line :-) } diff --git a/src/mainpage.md b/src/mainpage.md index de42aec..e644860 100644 --- a/src/mainpage.md +++ b/src/mainpage.md @@ -16,11 +16,10 @@ Dans le cas où l'on souhaite signer ses messages, il faut au préalable dépose -Main Programmes: +Main Programme: * [eMailShrinker](eMailShrinker_8cpp.html) - * [jirafeauAPI](jirafeauAPI_8cpp.html) Main classes: * [MainAttachment](classkaz_1_1MainAttachment.html) * [Attachment](classkaz_1_1Attachment.html) - \ No newline at end of file + diff --git a/structures.odt b/structures.odt new file mode 100644 index 0000000..f4e003b Binary files /dev/null and b/structures.odt differ