aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Williams <peterw@ximian.com>2001-08-07 03:00:32 +0800
committerPeter Williams <peterw@src.gnome.org>2001-08-07 03:00:32 +0800
commitf789abbd422604206c386199c80fb5eac8e34733 (patch)
treed0a1d734f996e2f4bca6aa58d695d6489b0403b0
parentd701d18f51dbc1501cafba55025a7a74466e16cd (diff)
downloadgsoc2013-evolution-f789abbd422604206c386199c80fb5eac8e34733.tar
gsoc2013-evolution-f789abbd422604206c386199c80fb5eac8e34733.tar.gz
gsoc2013-evolution-f789abbd422604206c386199c80fb5eac8e34733.tar.bz2
gsoc2013-evolution-f789abbd422604206c386199c80fb5eac8e34733.tar.lz
gsoc2013-evolution-f789abbd422604206c386199c80fb5eac8e34733.tar.xz
gsoc2013-evolution-f789abbd422604206c386199c80fb5eac8e34733.tar.zst
gsoc2013-evolution-f789abbd422604206c386199c80fb5eac8e34733.zip
Completely hide the namespace from everything external to the IMAP code,
2001-08-06 Peter Williams <peterw@ximian.com> Completely hide the namespace from everything external to the IMAP code, which Dan W says is the way it should be. * providers/imap/camel-imap-command.c (imap_command_strdup_vprintf): Add a new %F argument, which is like %S but will add the namespace (for folder names). (camel_imap_command): Use %F here. * providers/imap/camel-imap-utils.c (imap_parse_list_response): Changed to strip out the namespec when returning *folder. In order to do this we need to be passed the CamelImapStore. (imap_concat): Move to here from camel-imap-store.c, un-static (imap_namespace_concat): New function, adds the namespace to the folder name, unless it's INBOX. * providers/imap/camel-imap-utils.h: Prototypes. * providers/imap/camel-imap-store.c (imap_connect_online): Extra arg to imap_parse_list_response. (imap_connect_offline): Here too. (get_folder_status): Use %F. (get_folder_online): Here too. (delete_folder): Here too. (create_folder): Here too, and arg to imap_parse_list_response. (parse_list_response_as_folder_info): Arg to i_p_l_r. (get_subscribed_folders_by_hand): Use %F. (get_folders_online): Here too. (get_folder_info_online): Instead of checking for NULL @name, check for name = NULL or "", and set to "" instead of namespace. Pass "" instead of namespace to camel_folder_info_build. (subscribe_folder): Use %F. (unsubscribe_folder): Here too. * providers/imap/camel-imap-folder.c (imap_get_full_name): This now just returns folder->full_name. (do_append): Use %F (do_copy): Here too. svn path=/trunk/; revision=11705
-rw-r--r--camel/ChangeLog40
-rw-r--r--camel/providers/imap/camel-imap-command.c22
-rw-r--r--camel/providers/imap/camel-imap-folder.c25
-rw-r--r--camel/providers/imap/camel-imap-store.c57
-rw-r--r--camel/providers/imap/camel-imap-utils.c44
-rw-r--r--camel/providers/imap/camel-imap-utils.h6
6 files changed, 128 insertions, 66 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog
index 35fc7c8ad4..3bf218d170 100644
--- a/camel/ChangeLog
+++ b/camel/ChangeLog
@@ -1,3 +1,43 @@
+2001-08-06 Peter Williams <peterw@ximian.com>
+
+ Completely hide the namespace from everything external to the IMAP
+ code, which Dan W says is the way it should be.
+
+ * providers/imap/camel-imap-command.c
+ (imap_command_strdup_vprintf): Add a new %F argument, which is like
+ %S but will add the namespace (for folder names).
+ (camel_imap_command): Use %F here.
+
+ * providers/imap/camel-imap-utils.c (imap_parse_list_response):
+ Changed to strip out the namespec when returning *folder. In order
+ to do this we need to be passed the CamelImapStore.
+ (imap_concat): Move to here from camel-imap-store.c, un-static
+ (imap_namespace_concat): New function, adds the namespace to the
+ folder name, unless it's INBOX.
+
+ * providers/imap/camel-imap-utils.h: Prototypes.
+
+ * providers/imap/camel-imap-store.c (imap_connect_online): Extra
+ arg to imap_parse_list_response.
+ (imap_connect_offline): Here too.
+ (get_folder_status): Use %F.
+ (get_folder_online): Here too.
+ (delete_folder): Here too.
+ (create_folder): Here too, and arg to imap_parse_list_response.
+ (parse_list_response_as_folder_info): Arg to i_p_l_r.
+ (get_subscribed_folders_by_hand): Use %F.
+ (get_folders_online): Here too.
+ (get_folder_info_online): Instead of checking for NULL @name, check
+ for name = NULL or "", and set to "" instead of namespace. Pass ""
+ instead of namespace to camel_folder_info_build.
+ (subscribe_folder): Use %F.
+ (unsubscribe_folder): Here too.
+
+ * providers/imap/camel-imap-folder.c (imap_get_full_name): This
+ now just returns folder->full_name.
+ (do_append): Use %F
+ (do_copy): Here too.
+
2001-08-06 Jeffrey Stedfast <fejj@ximian.com>
* camel-pgp-context.c (pgp_verify): Always do --no-auto-key-retrieve.
diff --git a/camel/providers/imap/camel-imap-command.c b/camel/providers/imap/camel-imap-command.c
index 428ecf565d..4c84b47fbb 100644
--- a/camel/providers/imap/camel-imap-command.c
+++ b/camel/providers/imap/camel-imap-command.c
@@ -98,7 +98,7 @@ camel_imap_command (CamelImapStore *store, CamelFolder *folder,
}
store->current_folder = folder;
camel_object_ref (CAMEL_OBJECT (folder));
- cmd = imap_command_strdup_printf (store, "SELECT %S",
+ cmd = imap_command_strdup_printf (store, "SELECT %F",
folder->full_name);
}
@@ -127,11 +127,15 @@ camel_imap_command (CamelImapStore *store, CamelFolder *folder,
* @fmt can include the following %-escapes ONLY:
* %s, %d, %%: as with printf
* %S: an IMAP "string" (quoted string or literal)
+ * %F: an IMAP folder name
*
* %S strings will be passed as literals if the server supports LITERAL+
* and quoted strings otherwise. (%S does not support strings that
* contain newlines.)
*
+ * %F will have the imap store's namespace prepended and then be processed
+ * like %S.
+ *
* On success, the store's command_lock will be locked. It will be
* freed when %CAMEL_IMAP_RESPONSE_TAGGED or %CAMEL_IMAP_RESPONSE_ERROR
* is returned from camel_imap_command_response(). (The lock is
@@ -621,7 +625,6 @@ camel_imap_response_extract_continuation (CamelImapStore *store,
return NULL;
}
-
static char *
imap_command_strdup_vprintf (CamelImapStore *store, const char *fmt,
va_list ap)
@@ -629,7 +632,7 @@ imap_command_strdup_vprintf (CamelImapStore *store, const char *fmt,
GPtrArray *args;
const char *p, *start;
char *out, *op, *string;
- int num, len, i;
+ int num, len, i, arglen;
args = g_ptr_array_new ();
@@ -657,12 +660,16 @@ imap_command_strdup_vprintf (CamelImapStore *store, const char *fmt,
break;
case 'S':
+ case 'F':
string = va_arg (ap, char *);
+ arglen = strlen (string);
+ if (*p == 'F')
+ arglen += strlen (store->namespace) + 1;
g_ptr_array_add (args, string);
if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS)
- len += strlen (string) + 15;
+ len += arglen + 15;
else
- len += strlen (string) * 2;
+ len += arglen * 2;
start = p + 1;
break;
@@ -704,7 +711,10 @@ imap_command_strdup_vprintf (CamelImapStore *store, const char *fmt,
break;
case 'S':
+ case 'F':
string = args->pdata[i++];
+ if (*p == 'F')
+ string = imap_namespace_concat (store, string);
if (store->capabilities & IMAP_CAPABILITY_LITERALPLUS) {
op += sprintf (op, "{%d+}\r\n%s",
strlen (string), string);
@@ -713,6 +723,8 @@ imap_command_strdup_vprintf (CamelImapStore *store, const char *fmt,
op += sprintf (op, "%s", quoted);
g_free (quoted);
}
+ if (*p == 'F')
+ g_free (string);
break;
default:
diff --git a/camel/providers/imap/camel-imap-folder.c b/camel/providers/imap/camel-imap-folder.c
index ba30ac7cc1..054fd7c6a0 100644
--- a/camel/providers/imap/camel-imap-folder.c
+++ b/camel/providers/imap/camel-imap-folder.c
@@ -72,7 +72,6 @@ static void imap_rescan (CamelFolder *folder, int exists, CamelException *ex);
static void imap_refresh_info (CamelFolder *folder, CamelException *ex);
static void imap_sync_online (CamelFolder *folder, CamelException *ex);
static void imap_sync_offline (CamelFolder *folder, CamelException *ex);
-static const char *imap_get_full_name (CamelFolder *folder);
static void imap_expunge_uids_online (CamelFolder *folder, GPtrArray *uids, CamelException *ex);
static void imap_expunge_uids_offline (CamelFolder *folder, GPtrArray *uids, CamelException *ex);
static void imap_expunge_uids_resyncing (CamelFolder *folder, GPtrArray *uids, CamelException *ex);
@@ -114,7 +113,6 @@ camel_imap_folder_class_init (CamelImapFolderClass *camel_imap_folder_class)
disco_folder_class = CAMEL_DISCO_FOLDER_CLASS (camel_type_get_global_classfuncs (camel_disco_folder_get_type ()));
/* virtual method overload */
- camel_folder_class->get_full_name = imap_get_full_name;
camel_folder_class->get_message = imap_get_message;
camel_folder_class->move_messages_to = imap_move_messages_to;
camel_folder_class->search_by_expression = imap_search_by_expression;
@@ -859,25 +857,6 @@ imap_expunge_uids_resyncing (CamelFolder *folder, GPtrArray *uids, CamelExceptio
CAMEL_IMAP_STORE_UNLOCK (store, command_lock);
}
-static const char *
-imap_get_full_name (CamelFolder *folder)
-{
- CamelImapStore *store = CAMEL_IMAP_STORE (folder->parent_store);
- char *name;
- int len;
-
- name = folder->full_name;
- if (store->namespace && *store->namespace) {
- len = strlen (store->namespace);
- if (!strncmp (store->namespace, folder->full_name, len) &&
- strlen (folder->full_name) > len)
- name += len;
- if (*name == store->dir_sep)
- name++;
- }
- return name;
-}
-
static void
imap_append_offline (CamelFolder *folder, CamelMimeMessage *message,
const CamelMessageInfo *info, CamelException *ex)
@@ -944,7 +923,7 @@ do_append (CamelFolder *folder, CamelMimeMessage *message,
camel_object_unref (CAMEL_OBJECT (crlf_filter));
camel_object_unref (CAMEL_OBJECT (memstream));
- response = camel_imap_command (store, NULL, ex, "APPEND %S%s%s {%d}",
+ response = camel_imap_command (store, NULL, ex, "APPEND %F%s%s {%d}",
folder->full_name, flagstr ? " " : "",
flagstr ? flagstr : "", ba->len);
g_free (flagstr);
@@ -1166,7 +1145,7 @@ do_copy (CamelFolder *source, GPtrArray *uids,
char *set;
set = imap_uid_array_to_set (source->summary, uids);
- response = camel_imap_command (store, source, ex, "UID COPY %s %S",
+ response = camel_imap_command (store, source, ex, "UID COPY %s %F",
set, destination->full_name);
if (response && (store->capabilities & IMAP_CAPABILITY_UIDPLUS))
handle_copyuid (response, source, destination);
diff --git a/camel/providers/imap/camel-imap-store.c b/camel/providers/imap/camel-imap-store.c
index 580a889078..4f8571bfae 100644
--- a/camel/providers/imap/camel-imap-store.c
+++ b/camel/providers/imap/camel-imap-store.c
@@ -640,7 +640,7 @@ imap_connect_online (CamelService *service, CamelException *ex)
result = camel_imap_response_extract (store, response, "LIST", NULL);
if (result) {
- imap_parse_list_response (result, NULL, &store->dir_sep, NULL);
+ imap_parse_list_response (store, result, NULL, &store->dir_sep, NULL);
g_free (result);
}
if (!store->dir_sep)
@@ -659,7 +659,7 @@ imap_connect_online (CamelService *service, CamelException *ex)
store->subscribed_folders = g_hash_table_new (g_str_hash, g_str_equal);
for (i = 0; i < response->untagged->len; i++) {
result = response->untagged->pdata[i];
- if (!imap_parse_list_response (result, &flags, NULL, &name))
+ if (!imap_parse_list_response (store, result, &flags, NULL, &name))
continue;
if (flags & (IMAP_LIST_FLAG_MARKED | IMAP_LIST_FLAG_UNMARKED))
store->capabilities |= IMAP_CAPABILITY_useful_lsub;
@@ -729,7 +729,7 @@ imap_connect_offline (CamelService *service, CamelException *ex)
/* Get subscribed folders */
store->subscribed_folders = g_hash_table_new (g_str_hash, g_str_equal);
while (camel_file_util_decode_string (storeinfo, &buf) == 0) {
- if (!imap_parse_list_response (buf, NULL, NULL, &name)) {
+ if (!imap_parse_list_response (store, buf, NULL, NULL, &name)) {
g_free (buf);
continue;
}
@@ -838,7 +838,7 @@ get_folder_status (CamelImapStore *imap_store, const char *folder_name, const ch
/* FIXME: we assume the server is STATUS-capable */
response = camel_imap_command (imap_store, NULL, NULL,
- "STATUS %S (%s)",
+ "STATUS %F (%s)",
folder_name,
type);
@@ -882,18 +882,18 @@ get_folder_online (CamelStore *store, const char *folder_name,
imap_store->current_folder = NULL;
}
response = camel_imap_command (imap_store, NULL, NULL,
- "SELECT %S", folder_name);
+ "SELECT %F", folder_name);
if (!response) {
if (!flags & CAMEL_STORE_FOLDER_CREATE)
return no_such_folder (folder_name, ex);
response = camel_imap_command (imap_store, NULL, ex,
- "CREATE %S", folder_name);
+ "CREATE %F", folder_name);
if (response) {
camel_imap_response_free (imap_store, response);
response = camel_imap_command (imap_store, NULL, NULL,
- "SELECT %S", folder_name);
+ "SELECT %F", folder_name);
}
if (!response) {
CAMEL_IMAP_STORE_UNLOCK (imap_store, command_lock);
@@ -947,18 +947,6 @@ get_folder_offline (CamelStore *store, const char *folder_name,
return new_folder;
}
-static char *
-imap_concat (CamelImapStore *imap_store, const char *prefix, const char *suffix)
-{
- int len;
-
- len = strlen (prefix);
- if (len == 0 || prefix[len - 1] == imap_store->dir_sep)
- return g_strdup_printf ("%s%s", prefix, suffix);
- else
- return g_strdup_printf ("%s%c%s", prefix, imap_store->dir_sep, suffix);
-}
-
static void
delete_folder (CamelStore *store, const char *folder_name, CamelException *ex)
{
@@ -979,7 +967,7 @@ delete_folder (CamelStore *store, const char *folder_name, CamelException *ex)
/* delete the old parent and recreate it */
- response = camel_imap_command (imap_store, NULL, ex, "DELETE %S",
+ response = camel_imap_command (imap_store, NULL, ex, "DELETE %F",
folder_name);
if (response)
camel_imap_response_free (imap_store, response);
@@ -999,12 +987,12 @@ create_folder (CamelStore *store, const char *parent_name,
if (!camel_disco_store_check_online (CAMEL_DISCO_STORE (store), ex))
return NULL;
if (!parent_name)
- parent_name = imap_store->namespace;
+ parent_name = "";
/* check if the parent allows inferiors */
need_convert = FALSE;
- response = camel_imap_command (imap_store, NULL, ex, "LIST \"\" %S",
+ response = camel_imap_command (imap_store, NULL, ex, "LIST \"\" %F",
parent_name);
if (!response) /* whoa, this is bad */
return NULL;
@@ -1013,7 +1001,7 @@ create_folder (CamelStore *store, const char *parent_name,
for (i = 0; i < response->untagged->len; i++) {
resp = response->untagged->pdata[i];
- if (!imap_parse_list_response (resp, &flags, NULL, &thisone))
+ if (!imap_parse_list_response (imap_store, resp, &flags, NULL, &thisone))
continue;
if (strcmp (thisone, parent_name) == 0) {
@@ -1046,7 +1034,7 @@ create_folder (CamelStore *store, const char *parent_name,
/* add the dirsep to the end of parent_name */
name = g_strdup_printf ("%s%c", parent_name, imap_store->dir_sep);
- response = camel_imap_command (imap_store, NULL, ex, "CREATE %S",
+ response = camel_imap_command (imap_store, NULL, ex, "CREATE %F",
name);
g_free (name);
@@ -1060,7 +1048,7 @@ create_folder (CamelStore *store, const char *parent_name,
/* ok now we can create the folder */
full_name = imap_concat (imap_store, parent_name, folder_name);
- response = camel_imap_command (imap_store, NULL, ex, "CREATE %S",
+ response = camel_imap_command (imap_store, NULL, ex, "CREATE %F",
full_name);
if (response) {
camel_imap_response_free (imap_store, response);
@@ -1081,7 +1069,7 @@ parse_list_response_as_folder_info (CamelImapStore *imap_store,
char sep, *dir, *name = NULL;
CamelURL *url;
- if (!imap_parse_list_response (response, &flags, &sep, &dir))
+ if (!imap_parse_list_response (imap_store, response, &flags, &sep, &dir))
return NULL;
if (sep) {
@@ -1136,7 +1124,7 @@ get_subscribed_folders_by_hand (CamelImapStore *imap_store, const char *top,
for (i = 0; i < names->len; i++) {
response = camel_imap_command (imap_store, NULL, ex,
- "LIST \"\" %S",
+ "LIST \"\" %F",
names->pdata[i]);
if (!response) {
g_ptr_array_free (names, TRUE);
@@ -1175,7 +1163,7 @@ get_folders_online (CamelImapStore *imap_store, const char *pattern,
int i;
response = camel_imap_command (imap_store, NULL, ex,
- "%s \"\" %S", lsub ? "LSUB" : "LIST",
+ "%s \"\" %F", lsub ? "LSUB" : "LIST",
pattern);
if (!response)
return;
@@ -1205,9 +1193,9 @@ get_folder_info_online (CamelStore *store, const char *top,
return NULL;
name = top;
- if (!name) {
+ if (!name || name[0] == '\0') {
need_inbox = TRUE;
- name = imap_store->namespace;
+ name = "";
}
folders = g_ptr_array_new ();
@@ -1218,9 +1206,8 @@ get_folder_info_online (CamelStore *store, const char *top,
goto lose;
if (folders->len) {
fi = folders->pdata[0];
- /* note that == is okay; see above */
if (strstr (fi->url, "noselect=yes") &&
- name == imap_store->namespace) {
+ name[0] == '\0') {
camel_folder_info_free (fi);
g_ptr_array_remove_index (folders, 0);
}
@@ -1379,7 +1366,7 @@ get_folder_info_offline (CamelStore *store, const char *top,
fi = NULL;
} else {
g_ptr_array_remove_index_fast (folders, 0);
- fi = camel_folder_info_build (folders, imap_store->namespace,
+ fi = camel_folder_info_build (folders, "",
imap_store->dir_sep, TRUE);
}
@@ -1413,7 +1400,7 @@ subscribe_folder (CamelStore *store, const char *folder_name,
return;
response = camel_imap_command (imap_store, NULL, ex,
- "SUBSCRIBE %S", folder_name);
+ "SUBSCRIBE %F", folder_name);
if (!response)
return;
camel_imap_response_free (imap_store, response);
@@ -1451,7 +1438,7 @@ unsubscribe_folder (CamelStore *store, const char *folder_name,
return;
response = camel_imap_command (imap_store, NULL, ex,
- "UNSUBSCRIBE %S", folder_name);
+ "UNSUBSCRIBE %F", folder_name);
if (!response)
return;
camel_imap_response_free (imap_store, response);
diff --git a/camel/providers/imap/camel-imap-utils.c b/camel/providers/imap/camel-imap-utils.c
index f2909fb6a4..944165aebb 100644
--- a/camel/providers/imap/camel-imap-utils.c
+++ b/camel/providers/imap/camel-imap-utils.c
@@ -27,6 +27,7 @@
#include "camel-imap-utils.h"
#include "camel-imap-summary.h"
+#include "camel-imap-store.h"
#include "camel-folder.h"
#define d(x) x
@@ -47,6 +48,7 @@ imap_next_word (const char *buf)
/**
* imap_parse_list_response:
+ * @store: the IMAP store whose list response we're parsing
* @buf: the LIST or LSUB response
* @flags: a pointer to a variable to store the flags in, or %NULL
* @sep: a pointer to a variable to store the hierarchy separator in, or %NULL
@@ -58,7 +60,7 @@ imap_next_word (const char *buf)
* Return value: whether or not the response was successfully parsed.
**/
gboolean
-imap_parse_list_response (const char *buf, int *flags, char *sep, char **folder)
+imap_parse_list_response (CamelImapStore *store, const char *buf, int *flags, char *sep, char **folder)
{
char *word;
int len;
@@ -114,9 +116,22 @@ imap_parse_list_response (const char *buf, int *flags, char *sep, char **folder)
return FALSE;
if (folder) {
+ char *real_name;
+ int n_len;
+
/* get the folder name */
word = imap_next_word (word);
- *folder = imap_parse_astring (&word, &len);
+ real_name = imap_parse_astring (&word, &len);
+ n_len = strlen (store->namespace);
+ if (!strncmp (real_name, store->namespace, n_len))
+ *folder = g_strdup (real_name + n_len);
+ else if (!g_strcasecmp (real_name, "INBOX")) {
+ *folder = g_strdup (real_name);
+ } else {
+ g_warning ("IMAP folder name \"%s\" does not begin with \"%s\"", real_name, store->namespace);
+ *folder = g_strdup (real_name);
+ }
+ g_free (real_name);
return *folder != NULL;
}
@@ -730,3 +745,28 @@ imap_uid_array_free (GPtrArray *arr)
g_free (arr->pdata[i]);
g_ptr_array_free (arr, TRUE);
}
+
+char *
+imap_concat (CamelImapStore *imap_store, const char *prefix, const char *suffix)
+{
+ int len;
+
+ len = strlen (prefix);
+ if (len == 0 || prefix[len - 1] == imap_store->dir_sep)
+ return g_strdup_printf ("%s%s", prefix, suffix);
+ else
+ return g_strdup_printf ("%s%c%s", prefix, imap_store->dir_sep, suffix);
+}
+
+char *
+imap_namespace_concat (CamelImapStore *store, const char *name)
+{
+ if (!name || *name == '\0')
+ return g_strdup (store->namespace);
+
+ if (!g_strcasecmp (name, "INBOX"))
+ return g_strdup ("INBOX");
+
+ return imap_concat (store, store->namespace, name);
+}
+
diff --git a/camel/providers/imap/camel-imap-utils.h b/camel/providers/imap/camel-imap-utils.h
index a3b4bbdfdc..1d20ffe175 100644
--- a/camel/providers/imap/camel-imap-utils.h
+++ b/camel/providers/imap/camel-imap-utils.h
@@ -29,6 +29,7 @@ extern "C" {
#endif /* __cplusplus }*/
#include "camel-folder-summary.h"
+#include "camel-imap-types.h"
char *imap_next_word (const char *buf);
@@ -36,7 +37,7 @@ char *imap_next_word (const char *buf);
#define IMAP_LIST_FLAG_NOSELECT (1 << 1)
#define IMAP_LIST_FLAG_MARKED (1 << 2)
#define IMAP_LIST_FLAG_UNMARKED (1 << 3)
-gboolean imap_parse_list_response (const char *buf, int *flags, char *sep, char **folder);
+gboolean imap_parse_list_response (CamelImapStore *store, const char *buf, int *flags, char *sep, char **folder);
char *imap_create_flag_list (guint32 flags);
guint32 imap_parse_flag_list (char **flag_list);
@@ -61,6 +62,9 @@ char * imap_uid_array_to_set (CamelFolderSummary *summary, GPtrArray *uids);
GPtrArray *imap_uid_set_to_array (CamelFolderSummary *summary, const char *uids);
void imap_uid_array_free (GPtrArray *arr);
+char *imap_concat (CamelImapStore *imap_store, const char *prefix, const char *suffix);
+char *imap_namespace_concat (CamelImapStore *store, const char *name);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */