1# SHELL_FUNCTIONS.SH 2# 3# Author: "Garen Erdoisa" <scamper@trisk.com> 4# Licence: GNU GPL 5# Last update: 8/14/2011 6# 7# This code is written on behalf of the SpamBouncer project 8# and as such is donated by the Author to the SpamBouncer 9# project. 10# 11# Synopsis: 12# This is a /bin/sh functions file intended to be loaded 13# into the current environemt of "functions/mimeparts.sh" 14# which is a SpamBouncer /bin/sh script that uses these functions 15# for parsing MIME Version 1.0 encoded email. 16# This script is designed specifically for use inside SpamBouncer's 17# unique procmail recipes. It is not intended for general use or for 18# use with any other program or set of programs, and would require major 19# modifications to make it work outside of that environment. 20 21# FUNCTION SPLITPARTS() 22# expecting base filename to split into mime parts as the first command line argument. 23# expecting a part designation as the 2nd command line argument. 24function splitparts(){ 25 ${CAT} $1 |\ 26 ${SED} -ne "$3p" |\ 27 ${SED} -e '2,$!d;$d' >$1_$2 28 29 ${CAT} $1 |\ 30 ${SED} -ne "$3p" |\ 31 ${SED} -e '2,$!d;$d' |\ 32 ${FORMAIL} -cX "Content-" |\ 33 ${SED} -e "${SPACES_TABS_TO_SPACES}" |\ 34 ${SED} -e '$s/.*/&\n/' >$1_$2.header 35 36 ${CAT} $1 |\ 37 ${SED} -ne "$3p" |\ 38 ${SED} -e '2,$!d;$d' |\ 39 ${FORMAIL} -I "" >$1_$2.body 40} 41 42# FUNCTION GREPLOCALPARTS() 43# expecting filename in $1 and boundary tag in $2 for input 44function greplocalparts() 45{ 46 # Save the boundary tag to a file for a later fgrep 47 # using the string in the file. I had to do it this way 48 # because fgrep misinterprets strings begining with one or two -'s when 49 # they appear on the command line as command line arguments 50 # to fgrep, while if they are in a file, fgrep uses them as 51 # a pattern to match against. Boundary strings always begining with -- 52 # in the mime message body. 53 ${ECHO} "$2" >${1}.boundary 54 55 # Replace any regexp meta characters in the boundary string 56 # in the pattern space only with a regexp . wildcard char. 57 # This is so sed or sh do not misinterpret the chars as 58 # /bin/sh or sed regexp meta characters. 59 # The numbers are octal. 60 # 042 " shell open/close quoted text 61 # 044 $ end of line anchor also shell meta in some cases 62 # 052 * sed match zero or more of preceeding character 63 # 054 ' forward single quote 64 # 057 / sed open/close pattern space. 65 # 133 [ regexp char list open also shell meta 66 # 134 \ sed escape the next char. 67 # 135 ] regexp char list close also shell meta 68 # 136 ^ begining of line anchor 69 # 140 ` back quote shell execute sub command 70 # 71 # All of the above are replaced with this in the pattern space. 72 # 056 . sed wild card match a single char (used to replace all of these in the pattern space) 73 74 LOCSTR=`${ECHO} "${2}" |${TR} "\042\044\052\054\057\133\134\135\136\140" "\056"` 75 76 # Use the modified boundary string with the wildcards to find the 77 # starting and ending line numbers of mime parts. 78 # 79 # We are prepending the line numbers to indicate exactly where in the part 80 # the boundary string was found. Trailing whitespaces are allowd. 81 # The two greps at the end, confirm that the strings found 82 # using this method are valid by comparing them back against the 83 # unmodified boundary string. 84 LOCALPARTS=` 85 ${CAT} $1 |\ 86 ${SED} -ne "/^--${LOCSTR}\(--\)\?\([ ]\{1,\}\)\?$/=;//p" |\ 87 ${SED} -e 's/$/;/' |\ 88 ${TR} -d '\012\015' |\ 89 ${SED} -e 's/\([0-9]\{1,\}\)\(;\)\(--\)/\1:\3/g;s/;/\n/g' |\ 90 ${GREP} -Faf ${1}.boundary |\ 91 ${EGREP} "^[0-9]+:--.+(--)?[ ]+?$" 92 ` 93} 94 95# FUNCTION GETLINEPAIRS() 96# expects a grep of the file with line numbers in front of boundary indicators as quoted input. 97# ie: 98# 3:--__Boundary 99# 9:--__Boundary 100# 130:--__Boundary 101# 824:--__Boundary-- 102# It will reformat the above into: 103# "3,9 9,130 130,824" 104function getlinepairs() 105{ 106# echo "function getlinepairs" 107LOCALLINEPAIRS=` 108 ${ECHO} "$1" |\ 109 ${SED} -ne ' 110 # Begin surgery on preceeding pattern space from the Grep results: 111 # 112 # Address line one only of the preceeding pattern space 113 # replace the line number from the grep with the line number 114 # followed by a comma 115 1s/^\([0-9]\{1,\}\):\(.\{1,\}\)$/\1,/p 116 117 # Next we have to duplicate some of the line numbers so 118 # we can end up with pairs. The end of one part becomes 119 # the defacto begining of the next part in a multi part 120 # message. 121 # 122 # Address line one to end of preceeding pattern space 123 # replace first match where P is the match with P;\nP, 124 # drop the 2nd match entirely. 125 1,$s/^\([0-9]\{1,\}\):\(.\{1,\}\)$/\1;\n\1,/p 126 ' |\ 127 ${SED} -e ' 128 # continued surgery on preceeding pattern space 129 # Delete the last line of the preceeding pattern space. 130 # we dont need it. 131 $d 132 133 # the tr following this strips out end of line characters 134 # in the preceeding pattern space, putting everything back 135 # just on one line so that we can seperate the lines again 136 # where the semi-colons were edited in. 137 ' |\ 138 ${TR} -d '\012\015' |\ 139 ${SED} -e ' 140 # continued surgery on preceeding pattern space 141 # globally replace all semi-colons with <space>, then strip 142 # any trailing space from the pattern space. 143 # This makes rows with pairs of line numbers seperated by a comma 144 # this format is sutable for use in sed to address just those 145 # lines in the main message body. 146 # The pairs of line numbers reference the begining and ending 147 # lines of each part of the mime boundary we are considering 148 # in the message body only. Line 1 being the first line of 149 # the message body after the headers. 150 s/;/ /g 151 s/ $// 152 '` 153} 154 155# FUNCTION DBECHO() 156# Conditional echo. 157# first parameter is a number that indicates if we should print the message 158# or not. If that number is greater than or equal to the current SBLOGLEVEL 159# then we do, otherwise skip it. 160function dbecho() 161{ 162 LEVEL="$1" 163 if [ ${LEVEL} -le ${SBLOGLEVEL} ] && [ -f ${LOGFILE} ]; then 164 shift 165 SBLOGPREFIX="`${DATE} '+%b %d %H:%M:%S'` ${HOST} SpamBouncer[${SBPID}]:" 166 MESSAGE="${SBLOGPREFIX} $*" 167 if [ "${SBLOGFILE}" = "INTERNAL" ]; then 168 ${ECHO} "${MESSAGE}" 169 elif [ -f ${SBLOGFILE} ]; then 170 ${ECHO} "${MESSAGE}" >>${SBLOGFILE} 171 fi 172 fi 173} 174