[PATCH 1/9] lib: read "property" terms from messages.
[notmuch-archives.git] / 6b / 9c4722829ffc7c2f6b56a0b0c39c2ef035dc6b
1 Return-Path: <thomas@schwinge.name>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id 11F1E431FB6\r
6         for <notmuch@notmuchmail.org>; Sun,  9 Jan 2011 23:35:47 -0800 (PST)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: 0\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=0 tagged_above=-999 required=5\r
12         tests=[RCVD_IN_DNSWL_NONE=-0.0001] autolearn=disabled\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id qWS-+TegsXGd for <notmuch@notmuchmail.org>;\r
16         Sun,  9 Jan 2011 23:35:43 -0800 (PST)\r
17 X-Greylist: delayed 3699 seconds by postgrey-1.32 at olra;\r
18         Sun, 09 Jan 2011 23:35:42 PST\r
19 Received: from smtprelay02.ispgateway.de (smtprelay02.ispgateway.de\r
20         [80.67.18.14])\r
21         by olra.theworths.org (Postfix) with ESMTP id 99719431FB5\r
22         for <notmuch@notmuchmail.org>; Sun,  9 Jan 2011 23:35:42 -0800 (PST)\r
23 Received: from [87.180.81.26] (helo=stokes.schwinge.homeip.net)\r
24         by smtprelay02.ispgateway.de with esmtpa (Exim 4.68)\r
25         (envelope-from <thomas@schwinge.name>) id 1Pc0nY-0006F7-PV\r
26         for notmuch@notmuchmail.org; Sun, 09 Jan 2011 20:19:29 +0100\r
27 Received: (qmail 23501 invoked from network); 9 Jan 2011 19:19:20 -0000\r
28 Received: from kepler.schwinge.homeip.net (192.168.111.7)\r
29         by stokes.schwinge.homeip.net with QMQP; 9 Jan 2011 19:19:20 -0000\r
30 Received: (nullmailer pid 27483 invoked by uid 1000);\r
31         Sun, 09 Jan 2011 19:19:19 -0000\r
32 From: Thomas Schwinge <thomas@schwinge.name>\r
33 To: notmuch@notmuchmail.org\r
34 Subject: Hallo!, and hooray!, and some first work, too\r
35 User-Agent: Notmuch/0.5-33-g665f77b (http://notmuchmail.org) Emacs/23.2.1\r
36         (i486-pc-linux-gnu)\r
37 Date: Sun, 09 Jan 2011 20:19:15 +0100\r
38 Message-ID: <87tyhhvqa4.fsf@kepler.schwinge.homeip.net>\r
39 MIME-Version: 1.0\r
40 Content-Type: multipart/signed; boundary="=-=-=";\r
41         micalg=pgp-sha1; protocol="application/pgp-signature"\r
42 X-Df-Sender: thomas@schwinge.name\r
43 X-BeenThere: notmuch@notmuchmail.org\r
44 X-Mailman-Version: 2.1.13\r
45 Precedence: list\r
46 List-Id: "Use and development of the notmuch mail system."\r
47         <notmuch.notmuchmail.org>\r
48 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
49         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
50 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
51 List-Post: <mailto:notmuch@notmuchmail.org>\r
52 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
53 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
54         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
55 X-List-Received-Date: Mon, 10 Jan 2011 07:35:47 -0000\r
56 \r
57 --=-=-=\r
58 Content-Type: text/plain; charset=utf-8\r
59 Content-Transfer-Encoding: quoted-printable\r
60 \r
61 Hallo!\r
62 \r
63 After having read about it in ..., in ..., (don't know anymore), and then\r
64 again over at LWN, I have had the plan to try (or rather: directly switch\r
65 to) notmuch like half a year ago, or longer.  I eventually was brave\r
66 enough to begin that process in the last days of 2010.  I'm still with\r
67 you, as you can see.  Hooray!  :-)\r
68 \r
69 As I said on IRC already: there are, of course, still some rough edges,\r
70 but what else should I expect from such a young project.\r
71 \r
72 \r
73 I'm currently using getmail, then maildrop which invokes notmuch-deliver\r
74 for getting my emails into both maildir storage, and making them known to\r
75 notmuch.  In that process I can apply tags at will (based on List-Id: /\r
76 Mailing-List: headers, mostly, but also for possibly-spam, and so on),\r
77 and then use a script that operates on these to further massage them.\r
78 Thus, I don't really have a need for ``notmuch new'' anymore, and\r
79 notmuch-deliver is sort of an atomic / integrated ``put into maildir and\r
80 add tags'' tool for me.  I will post more details on my setup (or rather:\r
81 directly put it into the wiki), as soon as all this settles down some\r
82 more.\r
83 \r
84 I have not yet switched all my email channels to notmuch, but will do so\r
85 soon, I think.\r
86 \r
87 Likewise, there are some topics I'd like to discuss.  I'll also begin to\r
88 plow through notmuch's mailing list archive, and will gladly accept\r
89 id:xxx pointers that answer / discuss the questions I'll be sending.\r
90 \r
91 \r
92 I poked at notmuch-deliver's code two weeks ago already (Ali, beware,\r
93 there'll be some few further patches coming), and in the last hours, I\r
94 finally had a look at notmuch.h and some of the source code.  Here is a\r
95 diff containing some comments, or to-do items.  Not all are fully fledged\r
96 (I have neither been using talloc, nor Xapian before), but perhaps\r
97 someone nevertheless feels like commenting on them.  In general I can\r
98 say, that the notmuch code makes a solid impression.  :-)\r
99 \r
100 \r
101 diff --git a/emacs/notmuch-maildir-fcc.el b/emacs/notmuch-maildir-fcc.el\r
102 index 3f1c124..0d7017c 100644\r
103 =2D-- a/emacs/notmuch-maildir-fcc.el\r
104 +++ b/emacs/notmuch-maildir-fcc.el\r
105 @@ -16,6 +16,14 @@\r
106  ;; To use this as the fcc handler for message-mode,\r
107  ;; customize the notmuch-fcc-dirs variable\r
108 =20\r
109 +;; TODO.  A bunch of maildir code is not specific to fcc handling and shou=\r
110 ld be\r
111 +;; factored out.\r
112 +\r
113 +;; TODO.  In fact, apart from using notmuch-database-path (which should\r
114 +;; probably be message-directory instead, anyways?), this whole unit is not\r
115 +;; specific to notmuch, and should perhaps be integrated into Emacs'\r
116 +;; message.el -- or is there even anything in Gnus that can directly be us=\r
117 ed?\r
118 +\r
119  (eval-when-compile (require 'cl))\r
120  (require 'message)\r
121 =20\r
122 @@ -73,7 +81,7 @@ yet when sending a mail."\r
123  (defun notmuch-fcc-header-setup ()\r
124    "Add an Fcc header to the current message buffer.\r
125 =20\r
126 =2DCan be added to `message-send-hook' and will set the Fcc header\r
127 +Is by default added to `message-header-setup-hook' and will set the Fcc he=\r
128 ader\r
129  based on the values of `notmuch-fcc-dirs'. An existing Fcc header\r
130  will NOT be removed or replaced."\r
131 =20\r
132 @@ -163,7 +171,7 @@ will NOT be removed or replaced."\r
133          (make-directory (concat path "/new/") t)\r
134          (make-directory (concat path "/tmp/") t))\r
135         ((file-regular-p path)\r
136 =2D      (error "%s is a file. Can't creat maildir." path))\r
137 +        (error "%s is a file. Can't create maildir." path))\r
138         (t\r
139          (error "I don't know how to create a maildir here"))))\r
140 =20\r
141 @@ -173,6 +181,8 @@ if successful, nil if not."\r
142    (let ((msg-id (notmuch-maildir-fcc-make-uniq-maildir-id)))\r
143      (while (file-exists-p (concat destdir "/tmp/" msg-id))\r
144        (setq msg-id (notmuch-maildir-fcc-make-uniq-maildir-id)))\r
145 +;; TODO.  Race.  Should instead (try to) open (create) the file exclusivel=\r
146 y,\r
147 +;; until that succeeds.\r
148      (cond ((notmuch-maildir-fcc-dir-is-maildir-p destdir)\r
149            (write-file (concat destdir "/tmp/" msg-id))\r
150            msg-id)\r
151 diff --git a/lib/database.cc b/lib/database.cc\r
152 index 7a00917..b08c429 100644\r
153 =2D-- a/lib/database.cc\r
154 +++ b/lib/database.cc\r
155 @@ -551,7 +551,10 @@ notmuch_database_create (const char *path)\r
156 =20\r
157      notmuch =3D notmuch_database_open (path,\r
158                                      NOTMUCH_DATABASE_MODE_READ_WRITE);\r
159 +    /* XXX: should check 'notmuch'.  */\r
160 +\r
161      notmuch_database_upgrade (notmuch, NULL, NULL);\r
162 +    /* XXX: should check return value.  */\r
163 =20\r
164    DONE:\r
165      if (notmuch_path)\r
166 @@ -760,18 +763,6 @@ handle_sigalrm (unused (int signal))\r
167      do_progress_notify =3D 1;\r
168  }\r
169 =20\r
170 =2D/* Upgrade the current database.\r
171 =2D *\r
172 =2D * After opening a database in read-write mode, the client should\r
173 =2D * check if an upgrade is needed (notmuch_database_needs_upgrade) and\r
174 =2D * if so, upgrade with this function before making any modifications.\r
175 =2D *\r
176 =2D * The optional progress_notify callback can be used by the caller to\r
177 =2D * provide progress indication to the user. If non-NULL it will be\r
178 =2D * called periodically with 'count' as the number of messages upgraded\r
179 =2D * so far and 'total' the overall number of messages that will be\r
180 =2D * converted.\r
181 =2D */\r
182  notmuch_status_t\r
183  notmuch_database_upgrade (notmuch_database_t *notmuch,\r
184                           void (*progress_notify) (void *closure,\r
185 @@ -1012,6 +1003,7 @@ _notmuch_database_get_directory_db_path (const char *=\r
186 path)\r
187   * is an empty string, then both directory and basename will be\r
188   * returned as NULL.\r
189   */\r
190 +/* XXX: isn't there a standard libc function that can be used?  */\r
191  notmuch_status_t\r
192  _notmuch_database_split_path (void *ctx,\r
193                               const char *path,\r
194 @@ -1141,6 +1133,7 @@ _notmuch_database_filename_to_direntry (void *ctx,\r
195         return status;\r
196 =20\r
197      *direntry =3D talloc_asprintf (ctx, "%u:%s", directory_id, basename);\r
198 +    /* XXX: *direntry !=3D NULL?  */\r
199 =20\r
200      return NOTMUCH_STATUS_SUCCESS;\r
201  }\r
202 @@ -1168,6 +1161,9 @@ _notmuch_database_relative_path (notmuch_database_t *=\r
203 notmuch,\r
204         while (*relative =3D=3D '/' && *(relative+1) =3D=3D '/')\r
205             relative++;\r
206 =20\r
207 +        /* XXX: canonicalize paths (symlinks, `x/./y, `x/../y') before\r
208 +           comparing?  */\r
209 +\r
210         if (strncmp (relative, db_path, db_path_len) =3D=3D 0)\r
211         {\r
212             relative +=3D db_path_len;\r
213 @@ -1601,6 +1597,8 @@ notmuch_database_add_message (notmuch_database_t *not=\r
214 much,\r
215 =20\r
216             /* If a message ID is too long, substitute its sha1 instead. */\r
217             if (message_id && strlen (message_id) > NOTMUCH_MESSAGE_ID_MAX) {\r
218 +              /* XXX: How to distinguish this one later on (or don't we ha=\r
219 ve\r
220 +                 to?) from the message-id (possibly) generated below?  */\r
221                 char *compressed =3D _message_id_compressed (message_file,\r
222                                                            message_id);\r
223                 talloc_free (message_id);\r
224 @@ -1619,6 +1617,8 @@ notmuch_database_add_message (notmuch_database_t *not=\r
225 much,\r
226                 goto DONE;\r
227             }\r
228 =20\r
229 +            /* XXX: How to distinguish this one later on (or don't we have=\r
230  to?)\r
231 +               from the message-id (possibly) generated above?  */\r
232             message_id =3D talloc_asprintf (message_file,\r
233                                           "notmuch-sha1-%s", sha1);\r
234             free (sha1);\r
235 @@ -1641,6 +1641,7 @@ notmuch_database_add_message (notmuch_database_t *not=\r
236 much,\r
237         }\r
238 =20\r
239         _notmuch_message_add_filename (message, filename);\r
240 +        /* XXX: check return value.  */\r
241 =20\r
242         /* Is this a newly created message object? */\r
243         if (private_status =3D=3D NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND) {\r
244 @@ -1655,6 +1656,7 @@ notmuch_database_add_message (notmuch_database_t *not=\r
245 much,\r
246             _notmuch_message_set_date (message, date);\r
247 =20\r
248             _notmuch_message_index_file (message, filename);\r
249 +            /* XXX: check return value.  */\r
250         } else {\r
251             ret =3D NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;\r
252         }\r
253 @@ -1735,11 +1737,15 @@ notmuch_database_remove_message (notmuch_database_t=\r
254  *notmuch,\r
255                 status =3D NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;\r
256             }\r
257         }\r
258 +=20=20=20=20=20=20=20=20\r
259 +        /* XXX: talloc_free (term); */\r
260      } catch (const Xapian::Error &error) {\r
261         fprintf (stderr, "Error: A Xapian exception occurred removing message: %s=\r
262 \n",\r
263                  error.get_msg().c_str());\r
264         notmuch->exception_reported =3D TRUE;\r
265         status =3D NOTMUCH_STATUS_XAPIAN_EXCEPTION;\r
266 +\r
267 +        /* XXX: (conditionally) talloc_free (term); */\r
268      }\r
269 =20\r
270      talloc_free (local);\r
271 diff --git a/lib/directory.cc b/lib/directory.cc\r
272 index 946be4f..925b1da 100644\r
273 =2D-- a/lib/directory.cc\r
274 +++ b/lib/directory.cc\r
275 @@ -140,6 +140,7 @@ _notmuch_directory_create (notmuch_database_t *notmuch,\r
276             char *term =3D talloc_asprintf (local, "%s%s",\r
277                                           _find_prefix ("directory"), db_path);\r
278             directory->doc.add_term (term, 0);\r
279 +            /* XXX?: talloc_free (term); */\r
280 =20\r
281             directory->doc.set_data (path);\r
282 =20\r
283 @@ -152,6 +153,7 @@ _notmuch_directory_create (notmuch_database_t *notmuch,\r
284                                         _find_prefix ("directory-direntry"),\r
285                                         parent_id, basename);\r
286                 directory->doc.add_term (term, 0);\r
287 +                /* XXX?: talloc_free (term); */\r
288             }\r
289 =20\r
290             directory->doc.add_value (NOTMUCH_VALUE_TIMESTAMP,\r
291 diff --git a/lib/message.cc b/lib/message.cc\r
292 index adcd07d..cf4e36a 100644\r
293 =2D-- a/lib/message.cc\r
294 +++ b/lib/message.cc\r
295 @@ -187,13 +187,14 @@ _notmuch_message_create (const void *talloc_owner,\r
296   *     There is already a document with message ID 'message_id' in the\r
297   *     database. The returned message can be used to query/modify the\r
298   *     document.\r
299 + *\r
300   *   NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND:\r
301   *\r
302   *     No document with 'message_id' exists in the database. The\r
303   *     returned message contains a newly created document (not yet\r
304   *     added to the database) and a document ID that is known not to\r
305   *     exist in the database. The caller can modify the message, and a\r
306 =2D *     call to _notmuch_message_sync will add * the document to the\r
307 + *     call to _notmuch_message_sync will add the document to the\r
308   *     database.\r
309   *\r
310   * If an error occurs, this function will return NULL and *status\r
311 @@ -449,8 +450,10 @@ _notmuch_message_add_filename (notmuch_message_t *mess=\r
312 age,\r
313      status =3D _notmuch_database_filename_to_direntry (local,\r
314                                                      message->notmuch,\r
315                                                      filename, &direntry);\r
316 =2D    if (status)\r
317 +    if (status) {\r
318 +        /* XXX: talloc_free (local); */\r
319         return status;\r
320 +    }\r
321 =20\r
322      _notmuch_message_add_term (message, "file-direntry", direntry);\r
323 =20\r
324 @@ -717,6 +720,7 @@ _notmuch_message_close (notmuch_message_t *message)\r
325   *\r
326   * This change will not be reflected in the database until the next\r
327   * call to _notmuch_message_sync. */\r
328 +/* XXX: basically nowehere this function's return value is checked.  */\r
329  notmuch_private_status_t\r
330  _notmuch_message_add_term (notmuch_message_t *message,\r
331                            const char *prefix_name,\r
332 @@ -730,9 +734,12 @@ _notmuch_message_add_term (notmuch_message_t *message,\r
333 =20\r
334      term =3D talloc_asprintf (message, "%s%s",\r
335                             _find_prefix (prefix_name), value);\r
336 +    /* XXX: term !=3D NULL?  */\r
337 =20\r
338 =2D    if (strlen (term) > NOTMUCH_TERM_MAX)\r
339 +    if (strlen (term) > NOTMUCH_TERM_MAX) {\r
340 +        /* XXX: talloc_free (term); */\r
341         return NOTMUCH_PRIVATE_STATUS_TERM_TOO_LONG;\r
342 +    }\r
343 =20\r
344      message->doc.add_term (term, 0);\r
345 =20\r
346 @@ -820,6 +827,7 @@ notmuch_message_add_tag (notmuch_message_t *message, co=\r
347 nst char *tag)\r
348      if (strlen (tag) > NOTMUCH_TAG_MAX)\r
349         return NOTMUCH_STATUS_TAG_TOO_LONG;\r
350 =20\r
351 +    /* XXX: what if tag is already present -- added again?  */\r
352      private_status =3D _notmuch_message_add_term (message, "tag", tag);\r
353      if (private_status) {\r
354         INTERNAL_ERROR ("_notmuch_message_add_term return unexpected value: %d\n",\r
355 diff --git a/lib/notmuch.h b/lib/notmuch.h\r
356 index e508309..ffc7f8f 100644\r
357 =2D-- a/lib/notmuch.h\r
358 +++ b/lib/notmuch.h\r
359 @@ -810,6 +810,7 @@ notmuch_message_set_flag (notmuch_message_t *message,\r
360   * For the original textual representation of the Date header from the\r
361   * message call notmuch_message_get_header() with a header value of\r
362   * "date". */\r
363 +/* XXX: what if Date: was missing?  */\r
364  time_t\r
365  notmuch_message_get_date  (notmuch_message_t *message);\r
366 =20\r
367 @@ -866,6 +867,8 @@ notmuch_message_get_tags (notmuch_message_t *message);\r
368 =20\r
369  /* Add a tag to the given message.\r
370   *\r
371 + * XXX: which are valid characters for a tag?\r
372 + *\r
373   * Return value:\r
374   *\r
375   * NOTMUCH_STATUS_SUCCESS: Tag successfully added to message\r
376 @@ -1112,7 +1115,7 @@ notmuch_tags_destroy (notmuch_tags_t *tags);\r
377   *\r
378   *   o Read the mtime of a directory from the filesystem\r
379   *\r
380 =2D *   o Call add_message for all mail files in the directory\r
381 + *   o Call notmuch_database_add_message for all mail files in the directo=\r
382 ry\r
383   *\r
384   *   o Call notmuch_directory_set_mtime with the mtime read from the\r
385   *     filesystem.\r
386 @@ -1157,7 +1160,7 @@ notmuch_directory_get_mtime (notmuch_directory_t *dir=\r
387 ectory);\r
388  notmuch_filenames_t *\r
389  notmuch_directory_get_child_files (notmuch_directory_t *directory);\r
390 =20\r
391 =2D/* Get a notmuch_filenams_t iterator listing all the filenames of\r
392 +/* Get a notmuch_filenames_t iterator listing all the filenames of\r
393   * sub-directories in the database within the given directory.\r
394   *\r
395   * The returned filenames will be the basename-entries only (not\r
396 diff --git a/notmuch-new.c b/notmuch-new.c\r
397 index cdf8513..74a09bf 100644\r
398 =2D-- a/notmuch-new.c\r
399 +++ b/notmuch-new.c\r
400 @@ -784,6 +784,7 @@ notmuch_new_command (void *ctx, int argc, char *argv[])\r
401             gettimeofday (&add_files_state.tv_start, NULL);\r
402             notmuch_database_upgrade (notmuch, upgrade_print_progress,\r
403                                       &add_files_state);\r
404 +            /* XXX: should check return value.  */\r
405             printf ("Your notmuch database has now been upgraded to database form=\r
406 at version %u.\n",\r
407                     notmuch_database_get_version (notmuch));\r
408         }\r
409 diff --git a/notmuch-restore.c b/notmuch-restore.c\r
410 index f095f64..2c607c3 100644\r
411 =2D-- a/notmuch-restore.c\r
412 +++ b/notmuch-restore.c\r
413 @@ -115,7 +115,10 @@ notmuch_restore_command (unused (void *ctx), int argc,=\r
414  char *argv[])\r
415         }\r
416 =20\r
417         notmuch_message_freeze (message);\r
418 +        /* XXX: check return value.  */\r
419 +\r
420         notmuch_message_remove_all_tags (message);\r
421 +        /* XXX: check return value.  */\r
422 =20\r
423         next =3D file_tags;\r
424         while (next) {\r
425 @@ -133,6 +136,7 @@ notmuch_restore_command (unused (void *ctx), int argc, =\r
426 char *argv[])\r
427         }\r
428 =20\r
429         notmuch_message_thaw (message);\r
430 +        /* XXX: check return value.  */\r
431 =20\r
432         if (synchronize_flags)\r
433             notmuch_message_tags_to_maildir_flags (message);\r
434 diff --git a/notmuch-tag.c b/notmuch-tag.c\r
435 index 60e21e0..3b7a00c 100644\r
436 =2D-- a/notmuch-tag.c\r
437 +++ b/notmuch-tag.c\r
438 @@ -120,6 +120,7 @@ notmuch_tag_command (void *ctx, unused (int argc), unus=\r
439 ed (char *argv[]))\r
440         message =3D notmuch_messages_get (messages);\r
441 =20\r
442         notmuch_message_freeze (message);\r
443 +        /* XXX: check return value.  */\r
444 =20\r
445         for (i =3D 0; i < remove_tags_count; i++)\r
446             notmuch_message_remove_tag (message,\r
447 @@ -129,6 +130,7 @@ notmuch_tag_command (void *ctx, unused (int argc), unus=\r
448 ed (char *argv[]))\r
449             notmuch_message_add_tag (message, argv[add_tags[i]] + 1);\r
450 =20\r
451         notmuch_message_thaw (message);\r
452 +        /* XXX: check return value.  */\r
453 =20\r
454         if (synchronize_flags)\r
455             notmuch_message_tags_to_maildir_flags (message);\r
456 \r
457 \r
458 Gr=C3=BC=C3=9Fe,\r
459  Thomas\r
460 \r
461 --=-=-=\r
462 Content-Type: application/pgp-signature\r
463 \r
464 -----BEGIN PGP SIGNATURE-----\r
465 Version: GnuPG v1.4.10 (GNU/Linux)\r
466 \r
467 iEYEARECAAYFAk0qCjMACgkQFaWaPJ2HwAoDHACfXoIIZMdiDTC88w7Mu78Ks/r6\r
468 1rcAnA/LXMFwJOFF5bNSY9NzmM5OMZ+X\r
469 =qHIc\r
470 -----END PGP SIGNATURE-----\r
471 --=-=-=--\r