remove the now unhidden prefs from the Hidden Preferences section
[claws.git] / tools / fix_date.sh
1 #!/bin/sh
2
3 #  * Copyright 2004 Tristan Chabredier <wwp@claws-mail.org>
4 #  *
5 #  * This file is free software; you can redistribute it and/or modify it
6 #  * under the terms of the GNU General Public License as published by
7 #  * the Free Software Foundation; either version 3 of the License, or
8 #  * (at your option) any later version.
9 #  *
10 #  * This program is distributed in the hope that it will be useful, but
11 #  * WITHOUT ANY WARRANTY; without even the implied warranty of
12 #  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 #  * General Public License for more details.
14 #  *
15 #  * You should have received a copy of the GNU General Public License
16 #  * along with this program; if not, write to the Free Software
17 #  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 #
19 # fix_date.sh           helper script to fix non-standard date or add missing
20 #                                       date header to emails
21
22 # usage: fix_date.sh <filename> [<filename> ..]
23 # It will replace the Date: value w/ the one picked up from more recent
24 # Fetchinfo time header, Received: field.. Otherwise, it will take the file
25 #  modification time (using a RFC 2822-compliant form).
26 # Any already existing X-Original-Date is kept, if missing we're adding it
27 # if the Date: was set (even if set w/ non conform value)
28
29 # TODO: fallback to X-OriginalArrivalTime: ?
30
31 VERSION="0.1.3"
32
33
34 version()
35 {
36         echo "$VERSION"
37         exit 0
38 }
39
40 usage()
41 {
42         echo "usage:"
43         echo "  ${0##*/} [<switches>] <filename> [<filename> ..]"
44         echo "switches:"
45         echo "  -h --help     display this help then exit"
46         echo "  -v --version  display version information then exit"
47         echo "  -d --debug    turn on debug information (be more verbose)"
48         echo "  -f --force    always force (re-)writing of Date: header"
49         echo "  -r --rfc      force re-writing of Date: header when it's not RFC-compliant"
50         echo "  -s --strict   use RFC-strict matching patterns for dates"
51         echo "  --            end of switches (in case a filename starts with a -)"
52         exit $1
53 }
54
55 date_valid()
56 {
57         test $STRICT -eq 1 && \
58                 REGEXP="$DATE_REGEXP_STRICT" || \
59                 REGEXP="$DATE_REGEXP"
60                 
61         echo "$1" | grep -qEim 1 "$REGEXP"
62         DATE_VALID=$?
63 }
64
65 dump_date_fields()
66 {
67         test -z "$X_ORIGINAL_DATE" -a -n "$DATE" && \
68                 echo "X-Original-Date:$DATE" >> "$TMP"
69         echo "Date:$REPLACEMENT_DATE" >> "$TMP"
70 }
71
72
73 # use --force to always (re-)write the Date header
74 # otherwise, the Date header will be written if only it doesn't exist
75 FORCE=0
76 # use --rfc to (re-)write the Date header when it's not RFC-compliant
77 # otherwise, the Date header will be written if only it doesn't exist
78 RFC=0
79 # use --debug to display more information about what's performed
80 DEBUG=0
81 # use --strict to use strict matching patterns for date validation
82 STRICT=0
83 # 0 = valid, always valid until --strict is used, then date_valid overrides this value
84 DATE_VALID=0
85 # max header lines (300 is a reasonable minimum value but 600 has already been encountered, set to 1000 by security)
86 MAX_HEADER_LINES=1000
87
88 while [ -n "$1" ]
89 do
90         case "$1" in
91         -h|--help)              usage 0;;
92         -v|--version)   version;;
93         -f|--force)             FORCE=1;;
94         -d|--debug)             DEBUG=1;;
95         -r|--rfc)               RFC=1;;
96         -s|--strict)    STRICT=1;;
97         --)                             shift
98                                         break;;
99         -*)                             echo "error: unrecognized switch '$1'"
100                                         usage 1;;
101         *)                              break;;
102         esac
103         shift
104 done
105
106 if [ $FORCE -eq 1 -a $RFC -eq 1 ]
107 then
108         echo "error: use either --force or --rfc, but not both at the same time"
109         usage 1
110 fi
111
112 test $# -lt 1 && \
113         usage 1
114
115 TMP="/tmp/${0##*/}.$$.tmp"
116 HEADERS="/tmp/${0##*/}.$$.headers.tmp"
117 BODY="/tmp/${0##*/}.$$.body.tmp"
118
119 DATE_REGEXP='( (Mon|Tue|Wed|Thu|Fri|Sat|Sun),)? [0-9]+ (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) [0-9]+ [0-9]+:[0-9]+:[0-9]+ [+-]?[0-9]+'
120 DATE_REGEXP_STRICT='(Mon|Tue|Wed|Thu|Fri|Sat|Sun), [0-9]+ (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) [0-9]+ [0-9]+:[0-9]+:[0-9]+ [+-]?[0-9]+'
121
122 while [ -n "$1" ]
123 do
124         # skip if file is empty or doesn't exist
125         if [ ! -s "$1" ]
126         then
127                 test $DEBUG -eq 1 && \
128                         echo "$1: no found or empty, skipping"
129                 shift
130                 continue
131         fi
132         SKIP=0
133
134         # split headers and body
135         # find the empty line that separates body (if any) from headers,
136         # work on a temporary dos2unix'ed copy because body might
137         # contain DOS CRLF and grep '^$' won't work
138         head -$MAX_HEADER_LINES "$1" | dos2unix > "$TMP"
139         SEP=`grep -nEm1 "^$" "$TMP" 2>/dev/null | cut -d ':' -f 1`
140         rm -f "$TMP"
141         if [ -z "$SEP" -o "$SEP" = "0" -o $? -ne 0 ]
142         then
143                 cp -f "$1" "$HEADERS"
144                 :> "$BODY"
145                 test $DEBUG -eq 1 && \
146                         echo "$1: no body part could be found before line $MAX_HEADER_LINES"
147         else
148                 sed -n '1,'`expr $SEP - 1`'p' "$1" > "$HEADERS"
149                 sed '1,'`expr $SEP - 1`'d' "$1" > "$BODY"
150         fi
151
152         # work on headers only
153
154         # get the Date and X-Original-Date
155         X_ORIGINAL_DATE=`sed -n '/^X-Original-Date:/,/^[^\t]/p' "$HEADERS" | head -n -1 | cut -d ':' -f 2-`
156         DATE=`sed -n '/^Date:/,/^[^\t]/p' "$HEADERS" | head -n -1 | cut -d ':' -f 2-`
157
158         # work on headers, minus Date and X-Original-Date
159         test -n "$X_ORIGINAL_DATE" && \
160                 sed -i '/^X-Original-Date:/,/^[^\t]/d' "$HEADERS"
161         test -n "$DATE" && \
162                 sed -i '/^Date:/,/^[^\t]/d' "$HEADERS"
163
164         # find a replacement date in Fetchinfo: header
165         FETCH_DATE=`grep -im1 'X-FETCH-TIME: ' "$HEADERS" | cut -d ' ' -f 2-`
166         
167         # or in Received: headers ..
168         test $STRICT -eq 1 && \
169                 REGEXP="$DATE_REGEXP" || \
170                 REGEXP="$DATE_REGEXP_STRICT"
171         RECEIVED_DATE=`sed -n '/^Received:/,/^[^\t]/p' "$HEADERS" | head -n -1 | grep -Eoim 1 "$REGEXP"`
172
173         # .. or from file properties
174         FILE_DATE=`LC_ALL=POSIX LANG=POSIX ls -l --time-style="+%a, %d %b %Y %X %z" "$1" | tr -s ' ' | cut -d ' ' -f 6-11`
175         # we could also use the system date as a possible replacement
176         SYSTEM_DATE="`date -R`"
177
178         # determine which replacement date to use
179         if [ -z "$FETCH_DATE" ]
180         then
181                 if [ -z "$RECEIVED_DATE" ]
182                 then
183                         # don't forget the leading whitespace here
184                         REPLACEMENT_DATE=" $FILE_DATE"
185                         REPLACEMENT="file date"
186 #                       REPLACEMENT_DATE=" $SYSTEM_DATE"
187 #                       REPLACEMENT="system date"
188                 else
189                         REPLACEMENT_DATE="$RECEIVED_DATE"
190                         REPLACEMENT="received date"
191                 fi
192         else
193                 # don't forget the leading whitespace here
194                 REPLACEMENT_DATE=" $FETCH_DATE"
195                 REPLACEMENT="Fetchinfo time header"
196         fi
197
198         # ensure that the original X-Original-Date is kept
199         :> "$TMP"
200         if [ -n "$X_ORIGINAL_DATE" ]
201         then
202                 echo "X-Original-Date:$X_ORIGINAL_DATE" >> "$TMP"
203         fi
204
205         # replace/set the date and write all lines
206         test $RFC -eq 1 && \
207                 date_valid "$DATE"
208         if [ -z "$DATE" ]
209         then
210                 test $DEBUG -eq 1 && \
211                         echo "$1: date not found, using $REPLACEMENT now"
212                 dump_date_fields
213         else
214                 if [ $FORCE -eq 1 ]
215                 then
216                         test $DEBUG -eq 1 && \
217                                 echo "$1: date already found, replacing with $REPLACEMENT"
218                         dump_date_fields
219                 else
220                         if [ $RFC -eq 1 ]
221                         then
222                                 if [ $DATE_VALID -ne 0 ]
223                                 then
224                                         test $DEBUG -eq 1 && \
225                                                 echo "$1: date already found but not RFC-compliant, replacing with $REPLACEMENT"
226                                         dump_date_fields
227                                 else
228                                         test $DEBUG -eq 1 && \
229                                                 echo "$1: date already found and RFC-compliant, skipping"
230                                         SKIP=1
231                                 fi
232                         else
233                                 test $DEBUG -eq 1 && \
234                                         echo "$1: date already found, skipping"
235                                 SKIP=1
236                         fi
237                 fi
238         fi
239
240         if [ $SKIP -eq 0 ]
241         then
242                 # uncomment the following line to backup the original file
243                 #mv -f "$1" "$1.bak"
244
245                 cat "$HEADERS" >> "$TMP"
246                 cat "$BODY" >> "$TMP"
247                 mv -f "$TMP" "$1"
248                 if [ $? -ne 0 ]
249                 then
250                         echo "error while moving '$TMP' to '$1'"
251                         exit 1
252                 fi
253         fi
254         rm -f "$HEADERS" "$BODY" "$TMP" >/dev/null 2>&1
255
256         shift
257 done
258 exit 0