[PATCH 3/4] Access messages through mail store interface
authorMichal Sojka <sojkam1@fel.cvut.cz>
Thu, 8 Apr 2010 14:42:45 +0000 (16:42 +0200)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:36:32 +0000 (09:36 -0800)
3d/92cc0222a3c3d649b4027d575d6329b1019c63 [new file with mode: 0644]

diff --git a/3d/92cc0222a3c3d649b4027d575d6329b1019c63 b/3d/92cc0222a3c3d649b4027d575d6329b1019c63
new file mode 100644 (file)
index 0000000..b9d2510
--- /dev/null
@@ -0,0 +1,519 @@
+Return-Path: <sojkam1@fel.cvut.cz>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+       by olra.theworths.org (Postfix) with ESMTP id 4EC304196F5\r
+       for <notmuch@notmuchmail.org>; Thu,  8 Apr 2010 07:43:12 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -1.9\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-1.9 tagged_above=-999 required=5\r
+       tests=[BAYES_00=-1.9] autolearn=ham\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+       by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+       with ESMTP id dl2HlPiVMWYm for <notmuch@notmuchmail.org>;\r
+       Thu,  8 Apr 2010 07:43:08 -0700 (PDT)\r
+Received: from max.feld.cvut.cz (max.feld.cvut.cz [147.32.192.36])\r
+       by olra.theworths.org (Postfix) with ESMTP id 834274196F0\r
+       for <notmuch@notmuchmail.org>; Thu,  8 Apr 2010 07:43:07 -0700 (PDT)\r
+Received: from localhost (unknown [192.168.200.4])\r
+       by max.feld.cvut.cz (Postfix) with ESMTP id E5C9719F33D8;\r
+       Thu,  8 Apr 2010 16:43:06 +0200 (CEST)\r
+X-Virus-Scanned: IMAP AMAVIS\r
+Received: from max.feld.cvut.cz ([192.168.200.1])\r
+       by localhost (styx.feld.cvut.cz [192.168.200.4]) (amavisd-new,\r
+       port 10044)\r
+       with ESMTP id 4g-PakWlGmXu; Thu,  8 Apr 2010 16:43:05 +0200 (CEST)\r
+Received: from imap.feld.cvut.cz (imap.feld.cvut.cz [147.32.192.34])\r
+       by max.feld.cvut.cz (Postfix) with ESMTP id 165B519F3404;\r
+       Thu,  8 Apr 2010 16:43:05 +0200 (CEST)\r
+Received: from steelpick.2x.cz (k335-30.felk.cvut.cz [147.32.86.30])\r
+       (Authenticated sender: sojkam1)\r
+       by imap.feld.cvut.cz (Postfix) with ESMTPSA id 12ACF15C062;\r
+       Thu,  8 Apr 2010 16:43:05 +0200 (CEST)\r
+Received: from wsh by steelpick.2x.cz with local (Exim 4.71)\r
+       (envelope-from <sojkam1@fel.cvut.cz>)\r
+       id 1Nzswi-0007cJ-Q0; Thu, 08 Apr 2010 16:43:04 +0200\r
+From: Michal Sojka <sojkam1@fel.cvut.cz>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH 3/4] Access messages through mail store interface\r
+Date: Thu,  8 Apr 2010 16:42:45 +0200\r
+Message-Id: <1270737766-29237-4-git-send-email-sojkam1@fel.cvut.cz>\r
+X-Mailer: git-send-email 1.7.0.2\r
+In-Reply-To: <1270737766-29237-1-git-send-email-sojkam1@fel.cvut.cz>\r
+References: <1270737766-29237-1-git-send-email-sojkam1@fel.cvut.cz>\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+       <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+       <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Thu, 08 Apr 2010 14:43:12 -0000\r
+\r
+This patch modifies notmuch binary to access the messages through mail\r
+store interface, so that non-file based mail stores can also be\r
+implemented.\r
+\r
+The API of notmuch library was changed. Now,\r
+notmuch_message_get_filename() returns relative file name with respect\r
+to the database path. As a result, notmuch show also outputs relative\r
+paths so that MUAs need to be changed.\r
+\r
+Signed-off-by: Michal Sojka <sojkam1@fel.cvut.cz>\r
+---\r
+ lib/database.cc       |   14 +++++++++++---\r
+ lib/index.cc          |    8 ++++++--\r
+ lib/mailstore-files.c |   18 +++++++++++++++++-\r
+ lib/message-file.c    |    8 ++++----\r
+ lib/message.cc        |   33 +++++++++++++++++++++++++--------\r
+ lib/notmuch-private.h |    6 +++---\r
+ lib/notmuch.h         |   16 ++++++++++++++--\r
+ lib/sha1.c            |    6 +-----\r
+ notmuch-client.h      |    2 +-\r
+ notmuch-reply.c       |   10 +++++++++-\r
+ notmuch-show.c        |   14 ++++++++++++--\r
+ show-message.c        |   14 +-------------\r
+ 12 files changed, 104 insertions(+), 45 deletions(-)\r
+\r
+diff --git a/lib/database.cc b/lib/database.cc\r
+index 93c8d0f..bd64ed3 100644\r
+--- a/lib/database.cc\r
++++ b/lib/database.cc\r
+@@ -1374,6 +1374,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
+     notmuch_message_t *message = NULL;\r
+     notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;\r
+     notmuch_private_status_t private_status;\r
++    const char *relative;\r
\r
+     const char *date, *header;\r
+     const char *from, *to, *subject;\r
+@@ -1386,7 +1387,8 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
+     if (ret)\r
+       return ret;\r
\r
+-    message_file = notmuch_message_file_open (filename);\r
++    relative = _notmuch_database_relative_path (notmuch, filename);\r
++    message_file = notmuch_message_file_open (notmuch->mailstore, relative);\r
+     if (message_file == NULL)\r
+       return NOTMUCH_STATUS_FILE_ERROR;\r
\r
+@@ -1438,9 +1440,15 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
+       }\r
\r
+       if (message_id == NULL ) {\r
++          FILE *file;\r
++          char *sha1 = NULL;\r
+           /* No message-id at all, let's generate one by taking a\r
+            * hash over the file's contents. */\r
+-          char *sha1 = notmuch_sha1_of_file (filename);\r
++          file = notmuch_mailstore_open_file (notmuch->mailstore, relative);\r
++          if (file) {\r
++              sha1 = notmuch_sha1_of_file (file);\r
++              fclose (file);\r
++          }\r
\r
+           /* If that failed too, something is really wrong. Give up. */\r
+           if (sha1 == NULL) {\r
+@@ -1483,7 +1491,7 @@ notmuch_database_add_message (notmuch_database_t *notmuch,\r
+           date = notmuch_message_file_get_header (message_file, "date");\r
+           _notmuch_message_set_date (message, date);\r
\r
+-          _notmuch_message_index_file (message, filename);\r
++          _notmuch_message_index_file (message, relative);\r
+       } else {\r
+           ret = NOTMUCH_STATUS_DUPLICATE_MESSAGE_ID;\r
+       }\r
+diff --git a/lib/index.cc b/lib/index.cc\r
+index cf93025..4d8c4dd 100644\r
+--- a/lib/index.cc\r
++++ b/lib/index.cc\r
+@@ -425,15 +425,19 @@ _notmuch_message_index_file (notmuch_message_t *message,\r
+     const char *from, *subject;\r
+     notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;\r
+     static int initialized = 0;\r
++    notmuch_mailstore_t *mailstore;\r
\r
+     if (! initialized) {\r
+       g_mime_init (0);\r
+       initialized = 1;\r
+     }\r
\r
+-    file = fopen (filename, "r");\r
++    mailstore = notmuch_message_get_mailstore(message);\r
++    file = notmuch_mailstore_open_file (mailstore, filename);\r
+     if (! file) {\r
+-      fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno));\r
++      fprintf (stderr, "Error opening %s: %s\n",\r
++               notmuch_message_get_filename (message),\r
++               strerror (errno));\r
+       ret = NOTMUCH_STATUS_FILE_ERROR;\r
+       goto DONE;\r
+     }\r
+diff --git a/lib/mailstore-files.c b/lib/mailstore-files.c\r
+index 8b5e1d5..f2cb8d7 100644\r
+--- a/lib/mailstore-files.c\r
++++ b/lib/mailstore-files.c\r
+@@ -602,11 +602,27 @@ index_new(notmuch_mailstore_t *mailstore, const char* path,\r
+     return ret;\r
+ }\r
\r
++static FILE *\r
++open_file(notmuch_mailstore_t *mailstore, const char *filename)\r
++{\r
++    const char *db_path;\r
++    char *abs_filename;\r
++    FILE *file;\r
++    \r
++    db_path = notmuch_database_get_path(mailstore->notmuch);\r
++    abs_filename = talloc_asprintf(NULL, "%s/%s", db_path, filename);\r
++    if (unlikely(abs_filename == NULL))\r
++      return NULL;\r
++    file = fopen (abs_filename, "r");\r
++    talloc_free(abs_filename);\r
++    return file;\r
++}\r
++\r
+ /* Original notmuch mail store */\r
+ struct _notmuch_mailstore mailstore_files = {\r
+     .type = "files",\r
+     .count_files = count_files,\r
+     .index_new = index_new,\r
+     .sync_tags = NULL,                /* We cannot store tags in this mailstore. */\r
+-    .open_file = NULL,                /* Currently not implemented */\r
++    .open_file = open_file,\r
+ };\r
+diff --git a/lib/message-file.c b/lib/message-file.c\r
+index 0c152a3..13c9f4c 100644\r
+--- a/lib/message-file.c\r
++++ b/lib/message-file.c\r
+@@ -94,7 +94,7 @@ _notmuch_message_file_destructor (notmuch_message_file_t *message)\r
+ /* Create a new notmuch_message_file_t for 'filename' with 'ctx' as\r
+  * the talloc owner. */\r
+ notmuch_message_file_t *\r
+-_notmuch_message_file_open_ctx (void *ctx, const char *filename)\r
++_notmuch_message_file_open_ctx (void *ctx, notmuch_mailstore_t *mailstore, const char *filename)\r
+ {\r
+     notmuch_message_file_t *message;\r
\r
+@@ -104,7 +104,7 @@ _notmuch_message_file_open_ctx (void *ctx, const char *filename)\r
\r
+     talloc_set_destructor (message, _notmuch_message_file_destructor);\r
\r
+-    message->file = fopen (filename, "r");\r
++    message->file = notmuch_mailstore_open_file(mailstore, filename);\r
+     if (message->file == NULL)\r
+       goto FAIL;\r
\r
+@@ -126,9 +126,9 @@ _notmuch_message_file_open_ctx (void *ctx, const char *filename)\r
+ }\r
\r
+ notmuch_message_file_t *\r
+-notmuch_message_file_open (const char *filename)\r
++notmuch_message_file_open (notmuch_mailstore_t *mailstore, const char *filename)\r
+ {\r
+-    return _notmuch_message_file_open_ctx (NULL, filename);\r
++    return _notmuch_message_file_open_ctx (NULL, mailstore, filename);\r
+ }\r
\r
+ void\r
+diff --git a/lib/message.cc b/lib/message.cc\r
+index c32ee7d..c7eff7c 100644\r
+--- a/lib/message.cc\r
++++ b/lib/message.cc\r
+@@ -247,6 +247,7 @@ static void\r
+ _notmuch_message_ensure_message_file (notmuch_message_t *message)\r
+ {\r
+     const char *filename;\r
++    notmuch_mailstore_t *mailstore;\r
\r
+     if (message->message_file)\r
+       return;\r
+@@ -255,7 +256,9 @@ _notmuch_message_ensure_message_file (notmuch_message_t *message)\r
+     if (unlikely (filename == NULL))\r
+       return;\r
\r
+-    message->message_file = _notmuch_message_file_open_ctx (message, filename);\r
++    mailstore = notmuch_message_get_mailstore (message);\r
++\r
++    message->message_file = _notmuch_message_file_open_ctx (message, mailstore, filename);\r
+ }\r
\r
+ const char *\r
+@@ -429,7 +432,7 @@ notmuch_message_get_filename (notmuch_message_t *message)\r
+     int prefix_len = strlen (prefix);\r
+     Xapian::TermIterator i;\r
+     char *colon, *direntry = NULL;\r
+-    const char *db_path, *directory, *basename;\r
++    const char *directory, *basename;\r
+     unsigned int directory_id;\r
+     void *local = talloc_new (message);\r
\r
+@@ -474,18 +477,16 @@ notmuch_message_get_filename (notmuch_message_t *message)\r
\r
+     *colon = '\0';\r
\r
+-    db_path = notmuch_database_get_path (message->notmuch);\r
+-\r
+     directory = _notmuch_database_get_directory_path (local,\r
+                                                     message->notmuch,\r
+                                                     directory_id);\r
\r
+     if (strlen (directory))\r
+-      message->filename = talloc_asprintf (message, "%s/%s/%s",\r
+-                                           db_path, directory, basename);\r
+-    else\r
+       message->filename = talloc_asprintf (message, "%s/%s",\r
+-                                           db_path, basename);\r
++                                           directory, basename);\r
++    else\r
++      message->filename = talloc_asprintf (message, "%s",\r
++                                           basename);\r
+     talloc_free ((void *) directory);\r
\r
+     talloc_free (local);\r
+@@ -493,6 +494,22 @@ notmuch_message_get_filename (notmuch_message_t *message)\r
+     return message->filename;\r
+ }\r
\r
++FILE *\r
++notmuch_message_fopen (notmuch_message_t *message)\r
++{\r
++    const char *filename;\r
++    filename = notmuch_message_get_filename (message);\r
++    return notmuch_mailstore_open_file (message->notmuch->mailstore,\r
++                                      filename);\r
++}\r
++\r
++notmuch_mailstore_t *\r
++notmuch_message_get_mailstore (notmuch_message_t *message)\r
++{\r
++    return message->notmuch->mailstore;\r
++}\r
++\r
++\r
+ notmuch_bool_t\r
+ notmuch_message_get_flag (notmuch_message_t *message,\r
+                         notmuch_message_flag_t flag)\r
+diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h\r
+index d52d84d..bab2090 100644\r
+--- a/lib/notmuch-private.h\r
++++ b/lib/notmuch-private.h\r
+@@ -295,11 +295,11 @@ typedef struct _notmuch_message_file notmuch_message_file_t;\r
+  * Returns NULL if any error occurs.\r
+  */\r
+ notmuch_message_file_t *\r
+-notmuch_message_file_open (const char *filename);\r
++notmuch_message_file_open (notmuch_mailstore_t *mailstore, const char *filename);\r
\r
+ /* Like notmuch_message_file_open but with 'ctx' as the talloc owner. */\r
+ notmuch_message_file_t *\r
+-_notmuch_message_file_open_ctx (void *ctx, const char *filename);\r
++_notmuch_message_file_open_ctx (void *ctx, notmuch_mailstore_t *mailstore, const char *filename);\r
\r
+ /* Close a notmuch message previously opened with notmuch_message_open. */\r
+ void\r
+@@ -402,7 +402,7 @@ char *\r
+ notmuch_sha1_of_string (const char *str);\r
\r
+ char *\r
+-notmuch_sha1_of_file (const char *filename);\r
++notmuch_sha1_of_file (FILE *file);\r
\r
+ /* tags.c */\r
\r
+diff --git a/lib/notmuch.h b/lib/notmuch.h\r
+index 31e47a4..54de0bd 100644\r
+--- a/lib/notmuch.h\r
++++ b/lib/notmuch.h\r
+@@ -739,8 +739,8 @@ notmuch_message_get_replies (notmuch_message_t *message);\r
\r
+ /* Get a filename for the email corresponding to 'message'.\r
+  *\r
+- * The returned filename is an absolute filename, (the initial\r
+- * component will match notmuch_database_get_path() ).\r
++ * The returned filename is an relative filename of the message within\r
++ * the mail store.\r
+  *\r
+  * The returned string belongs to the message so should not be\r
+  * modified or freed by the caller (nor should it be referenced after\r
+@@ -754,6 +754,18 @@ notmuch_message_get_replies (notmuch_message_t *message);\r
+ const char *\r
+ notmuch_message_get_filename (notmuch_message_t *message);\r
\r
++/* Return file handle to read the content of the message.\r
++ *\r
++ * This is a helper function which determines message filename and\r
++ * calls notmuch_mailstore_open_file().\r
++ */\r
++FILE *\r
++notmuch_message_fopen (notmuch_message_t *message);\r
++\r
++/* Get a pointer to the mailstore where the message is stored */\r
++notmuch_mailstore_t *\r
++notmuch_message_get_mailstore (notmuch_message_t *message);\r
++\r
+ /* Message flags */\r
+ typedef enum _notmuch_message_flag {\r
+     NOTMUCH_MESSAGE_FLAG_MATCH,\r
+diff --git a/lib/sha1.c b/lib/sha1.c\r
+index cc48108..a8991b1 100644\r
+--- a/lib/sha1.c\r
++++ b/lib/sha1.c\r
+@@ -74,9 +74,8 @@ notmuch_sha1_of_string (const char *str)\r
+  * file not found, etc.), this function returns NULL.\r
+  */\r
+ char *\r
+-notmuch_sha1_of_file (const char *filename)\r
++notmuch_sha1_of_file (FILE *file)\r
+ {\r
+-    FILE *file;\r
+ #define BLOCK_SIZE 4096\r
+     unsigned char block[BLOCK_SIZE];\r
+     size_t bytes_read;\r
+@@ -84,7 +83,6 @@ notmuch_sha1_of_file (const char *filename)\r
+     unsigned char digest[SHA1_DIGEST_SIZE];\r
+     char *result;\r
\r
+-    file = fopen (filename, "r");\r
+     if (file == NULL)\r
+       return NULL;\r
\r
+@@ -108,8 +106,6 @@ notmuch_sha1_of_file (const char *filename)\r
\r
+     result = _hex_of_sha1_digest (digest);\r
\r
+-    fclose (file);\r
+-\r
+     return result;\r
+ }\r
\r
+diff --git a/notmuch-client.h b/notmuch-client.h\r
+index d8c8df4..728e448 100644\r
+--- a/notmuch-client.h\r
++++ b/notmuch-client.h\r
+@@ -126,7 +126,7 @@ char *\r
+ query_string_from_args (void *ctx, int argc, char *argv[]);\r
\r
+ notmuch_status_t\r
+-show_message_body (const char *filename,\r
++show_message_body (FILE *file,\r
+                  void (*show_part) (GMimeObject *part, int *part_count));\r
\r
+ notmuch_status_t\r
+diff --git a/notmuch-reply.c b/notmuch-reply.c\r
+index 1ec28cd..32d17ef 100644\r
+--- a/notmuch-reply.c\r
++++ b/notmuch-reply.c\r
+@@ -347,6 +347,7 @@ guess_from_received_header (notmuch_config_t *config, notmuch_message_t *message\r
+ static int\r
+ notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_t *query)\r
+ {\r
++    FILE *file;\r
+     GMimeMessage *reply;\r
+     notmuch_messages_t *messages;\r
+     notmuch_message_t *message;\r
+@@ -415,7 +416,14 @@ notmuch_reply_format_default(void *ctx, notmuch_config_t *config, notmuch_query_\r
+               notmuch_message_get_header (message, "date"),\r
+               notmuch_message_get_header (message, "from"));\r
\r
+-      show_message_body (notmuch_message_get_filename (message), reply_part);\r
++      file = notmuch_message_fopen (message);\r
++      if (file) {\r
++          show_message_body (file, reply_part);\r
++          fclose (file);\r
++      } else\r
++          fprintf (stderr, "Error opening %s: %s\n",\r
++                   notmuch_message_get_filename (message),\r
++                   strerror (errno));\r
\r
+       notmuch_message_destroy (message);\r
+     }\r
+diff --git a/notmuch-show.c b/notmuch-show.c\r
+index 6dca672..66fd773 100644\r
+--- a/notmuch-show.c\r
++++ b/notmuch-show.c\r
+@@ -339,6 +339,8 @@ format_part_json (GMimeObject *part, int *part_count)\r
+ static void\r
+ show_message (void *ctx, const show_format_t *format, notmuch_message_t *message, int indent)\r
+ {\r
++    FILE *file;\r
++\r
+     fputs (format->message_start, stdout);\r
+     if (format->message)\r
+       format->message(ctx, message, indent);\r
+@@ -349,8 +351,16 @@ show_message (void *ctx, const show_format_t *format, notmuch_message_t *message\r
+     fputs (format->header_end, stdout);\r
\r
+     fputs (format->body_start, stdout);\r
+-    if (format->part)\r
+-      show_message_body (notmuch_message_get_filename (message), format->part);\r
++    if (format->part) {\r
++      file = notmuch_message_fopen (message);\r
++      if (file) {\r
++          show_message_body (file, format->part);\r
++          fclose (file);\r
++      } else\r
++          fprintf (stderr, "Error opening %s: %s\n",\r
++                   notmuch_message_get_filename (message),\r
++                   strerror (errno));\r
++    }\r
+     fputs (format->body_end, stdout);\r
\r
+     fputs (format->message_end, stdout);\r
+diff --git a/show-message.c b/show-message.c\r
+index b1b61be..79911a7 100644\r
+--- a/show-message.c\r
++++ b/show-message.c\r
+@@ -60,23 +60,15 @@ show_message_part (GMimeObject *part, int *part_count,\r
+ }\r
\r
+ notmuch_status_t\r
+-show_message_body (const char *filename,\r
++show_message_body (FILE *file,\r
+                  void (*show_part) (GMimeObject *part, int *part_count))\r
+ {\r
+     GMimeStream *stream = NULL;\r
+     GMimeParser *parser = NULL;\r
+     GMimeMessage *mime_message = NULL;\r
+     notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;\r
+-    FILE *file = NULL;\r
+     int part_count = 0;\r
\r
+-    file = fopen (filename, "r");\r
+-    if (! file) {\r
+-      fprintf (stderr, "Error opening %s: %s\n", filename, strerror (errno));\r
+-      ret = NOTMUCH_STATUS_FILE_ERROR;\r
+-      goto DONE;\r
+-    }\r
+-\r
+     stream = g_mime_stream_file_new (file);\r
+     g_mime_stream_file_set_owner (GMIME_STREAM_FILE (stream), FALSE);\r
\r
+@@ -87,7 +79,6 @@ show_message_body (const char *filename,\r
+     show_message_part (g_mime_message_get_mime_part (mime_message),\r
+                      &part_count, show_part);\r
\r
+-  DONE:\r
+     if (mime_message)\r
+       g_object_unref (mime_message);\r
\r
+@@ -97,9 +88,6 @@ show_message_body (const char *filename,\r
+     if (stream)\r
+       g_object_unref (stream);\r
\r
+-    if (file)\r
+-      fclose (file);\r
+-\r
+     return ret;\r
+ }\r
\r
+-- \r
+1.7.0.2\r
+\r