"Fossies" - the Fresh Open Source Software Archive

Member "evolution-mapi-3.46.1/src/libexchangemapi/e-mapi-fast-transfer.c" (2 Dec 2022, 17108 Bytes) of package /linux/misc/evolution-mapi-3.46.1.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "e-mapi-fast-transfer.c" see the Fossies "Dox" file reference documentation.

    1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
    2 /*
    3  * This program is free software; you can redistribute it and/or
    4  * modify it under the terms of the GNU Lesser General Public
    5  * License as published by the Free Software Foundation; either
    6  * version 2 of the License, or (at your option) version 3.
    7  *
    8  * This program is distributed in the hope that it will be useful,
    9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   11  * Lesser General Public License for more details.
   12  *
   13  * You should have received a copy of the GNU Lesser General Public
   14  * License along with the program; if not, see <http://www.gnu.org/licenses/>
   15  *
   16  *
   17  * Authors:
   18  *    Milan Crha <mcrha@redhat.com>
   19  *
   20  * Copyright (C) 2011 Red Hat, Inc. (www.redhat.com)
   21  *
   22  */
   23 
   24 #include "evolution-mapi-config.h"
   25 
   26 #include "e-mapi-connection.h"
   27 #include "e-mapi-debug.h"
   28 
   29 #include "e-mapi-fast-transfer.h"
   30 
   31 #ifndef HAVE_FAST_TRANSFER_TAGS_2_1
   32 #define StartMessage PidTagStartMessage
   33 #define EndMessage PidTagEndMessage
   34 #define StartRecip PidTagStartRecip
   35 #define EndToRecip PidTagEndToRecip
   36 #define NewAttach PidTagNewAttach
   37 #define EndAttach PidTagEndAttach
   38 #define StartEmbed PidTagStartEmbed
   39 #define EndEmbed PidTagEndEmbed
   40 #endif
   41 
   42 struct _EMapiFXParserClosure;
   43 typedef struct _EMapiFXParserClosure EMapiFXParserClosure;
   44 
   45 struct _EMapiFXParserClosure {
   46     EMapiConnection *conn;
   47     TALLOC_CTX *mem_ctx;
   48     TransferObjectCB cb;
   49     gpointer cb_user_data;
   50     GCancellable *cancellable;
   51     GError **perror;
   52 
   53     uint32_t next_proptag_is_nameid;
   54     uint32_t next_nameid_proptag;
   55     guint32 object_index;
   56     guint32 objects_total;
   57 
   58     /* in what section it is now */
   59     uint32_t marker;
   60     /* where to store read properties */
   61     struct mapi_SPropValue_array *current_properties;
   62     TALLOC_CTX *current_streamed_mem_ctx;
   63     EMapiStreamedProp **current_streamed_properties;
   64     guint32 *current_streamed_properties_count;
   65     
   66     /* what object is currently read (can be embeded object or the below object */
   67     EMapiObject *current_object;
   68 
   69     /* main object properties */
   70     EMapiObject *object;
   71 };
   72 
   73 static void
   74 e_mapi_object_finish_read (EMapiObject *object)
   75 {
   76     EMapiRecipient *rprev, *rtail, *rnext;
   77     EMapiAttachment *aprev, *atail, *anext;
   78 
   79     if (!object)
   80         return;
   81 
   82     /* reverse order of recipients and attachments */
   83     rprev = NULL;
   84     for (rtail = object->recipients; rtail; rtail = rnext) {
   85         rnext = rtail->next;
   86         rtail->next = rprev;
   87         rprev = rtail;
   88     }
   89     object->recipients = rprev;
   90 
   91     aprev = NULL;
   92     for (atail = object->attachments; atail; atail = anext) {
   93         anext = atail->next;
   94         atail->next = aprev;
   95         aprev = atail;
   96     }
   97     object->attachments = aprev;
   98 }
   99 
  100 static gboolean
  101 process_parsed_object (EMapiFXParserClosure *data)
  102 {
  103     g_return_val_if_fail (data != NULL, FALSE);
  104     g_return_val_if_fail (data->conn != NULL, FALSE);
  105     g_return_val_if_fail (data->cb != NULL, FALSE);
  106     g_return_val_if_fail (data->object != NULL, FALSE);
  107 
  108     return data->cb (data->conn, data->mem_ctx, data->object, data->object_index, data->objects_total, data->cb_user_data, data->cancellable, data->perror);
  109 }
  110 
  111 static enum MAPISTATUS
  112 parse_marker_cb (uint32_t marker, void *closure)
  113 {
  114     EMapiFXParserClosure *data = closure;
  115     gboolean stop = FALSE;
  116 
  117     /* g_print ("\tMarker: %s (0x%08x)\n", get_proptag_name (marker), marker); */
  118     switch (marker) {
  119         case StartMessage:
  120             if (data->object) {
  121                 g_debug ("%s: StartMessage: out of order, previous object not finished yet", G_STRFUNC);
  122                 e_mapi_object_finish_read (data->object);
  123                 stop = !process_parsed_object (data);
  124                 e_mapi_object_free (data->object);
  125                 data->object = NULL;
  126                 data->current_object = NULL;
  127                 data->current_properties = NULL;
  128                 data->current_streamed_mem_ctx = NULL;
  129                 data->current_streamed_properties = NULL;
  130                 data->current_streamed_properties_count = NULL;
  131             }
  132 
  133             if (stop)
  134                 return MAPI_E_USER_CANCEL;
  135 
  136             /* new object parsing */
  137             data->object_index++;
  138             data->object = e_mapi_object_new (data->mem_ctx);
  139             data->current_object = data->object;
  140             data->current_properties = &data->object->properties;
  141             data->current_streamed_mem_ctx = data->object;
  142             data->current_streamed_properties = &data->object->streamed_properties;
  143             data->current_streamed_properties_count = &data->object->streamed_properties_count;
  144             data->marker = marker;
  145             break;
  146         case EndMessage:
  147             if (!data->object) {
  148                 g_debug ("%s: EndMessage no object started", G_STRFUNC);
  149             } else {
  150                 e_mapi_object_finish_read (data->object);
  151                 stop = !process_parsed_object (data);
  152 
  153                 e_mapi_object_free (data->object);
  154                 data->object = NULL;
  155                 data->current_object = NULL;
  156                 data->current_properties = NULL;
  157                 data->current_streamed_mem_ctx = NULL;
  158                 data->current_streamed_properties = NULL;
  159                 data->current_streamed_properties_count = NULL;
  160 
  161                 if (stop)
  162                     return MAPI_E_USER_CANCEL;
  163             }
  164             data->marker = 0;
  165             break;
  166         case StartRecip:
  167             if (!data->current_object) {
  168                 g_debug ("%s: StartRecip no object started", G_STRFUNC);
  169             } else {
  170                 EMapiRecipient *recipient;
  171 
  172                 recipient = e_mapi_recipient_new (data->mem_ctx);
  173 
  174                 /* they are stored in reverse order, but reverted before passing to a caller */
  175                 recipient->next = data->current_object->recipients;
  176                 data->current_object->recipients = recipient;
  177 
  178                 data->current_properties = &recipient->properties;
  179                 data->current_streamed_mem_ctx = NULL;
  180                 data->current_streamed_properties = NULL;
  181                 data->current_streamed_properties_count = NULL;
  182             }
  183             data->marker = marker;
  184             break;
  185         case EndToRecip:
  186             data->current_properties = NULL;
  187             data->current_streamed_mem_ctx = NULL;
  188             data->current_streamed_properties = NULL;
  189             data->current_streamed_properties_count = NULL;
  190             data->marker = 0;
  191             break;
  192         case NewAttach:
  193             if (!data->current_object) {
  194                 g_debug ("%s: NewAttach no object started", G_STRFUNC);
  195             } else {
  196                 EMapiAttachment *attachment;
  197 
  198                 attachment = e_mapi_attachment_new (data->mem_ctx);
  199 
  200                 /* they are stored in reverse order, but reverted before passing to a caller */
  201                 attachment->next = data->current_object->attachments;
  202                 data->current_object->attachments = attachment;
  203 
  204                 data->current_properties = &attachment->properties;
  205                 data->current_streamed_mem_ctx = attachment;
  206                 data->current_streamed_properties = &attachment->streamed_properties;
  207                 data->current_streamed_properties_count = &attachment->streamed_properties_count;
  208             }
  209             data->marker = marker;
  210             break;
  211         case EndAttach:
  212             data->current_properties = NULL;
  213             data->current_streamed_mem_ctx = NULL;
  214             data->current_streamed_properties = NULL;
  215             data->current_streamed_properties_count = NULL;
  216             data->marker = 0;
  217             break;
  218         case StartEmbed:
  219             if (!data->current_object) {
  220                 g_debug ("%s: StartEmbed no object started", G_STRFUNC);
  221             } else if (!data->current_object->attachments) {
  222                 g_debug ("%s: StartEmbed no attachment started", G_STRFUNC);
  223             } else if (data->current_object->attachments->embedded_object) {
  224                 g_debug ("%s: StartEmbed attachment has embedded object already", G_STRFUNC);
  225             } else {
  226                 EMapiObject *object;
  227 
  228                 object = e_mapi_object_new (data->mem_ctx);
  229 
  230                 object->parent = data->current_object;
  231                 data->current_object->attachments->embedded_object = object;
  232                 data->current_object = object;
  233                 data->current_properties = &object->properties;
  234                 data->current_streamed_mem_ctx = object;
  235                 data->current_streamed_properties = &object->streamed_properties;
  236                 data->current_streamed_properties_count = &object->streamed_properties_count;
  237             }
  238             data->marker = marker;
  239             break;
  240         case EndEmbed:
  241             if (!data->current_object) {
  242                 g_debug ("%s: EndEmbed no object started", G_STRFUNC);
  243             } else if (!data->current_object->parent) {
  244                 g_debug ("%s: EndEmbed no parent object", G_STRFUNC);
  245             } else {
  246                 e_mapi_object_finish_read (data->current_object);
  247                 data->current_object = data->current_object->parent;
  248                 data->current_properties = NULL;
  249                 data->current_streamed_mem_ctx = NULL;
  250                 data->current_streamed_properties = NULL;
  251                 data->current_streamed_properties_count = NULL;
  252             }
  253             data->marker = 0;
  254             break;
  255         default:
  256             data->marker = marker;
  257             break;
  258     }
  259 
  260     return MAPI_E_SUCCESS;
  261 }
  262 
  263 static enum MAPISTATUS
  264 parse_delprop_cb (uint32_t proptag, void *closure)
  265 {
  266     return MAPI_E_SUCCESS;
  267 }
  268 
  269 static enum MAPISTATUS
  270 parse_namedprop_cb (uint32_t proptag, struct MAPINAMEID nameid, void *closure)
  271 {
  272     /* the next property is a named property, but cannot make it proptag, thus left it for later */
  273     EMapiFXParserClosure *data = closure;
  274     uint32_t lid = MAPI_E_RESERVED;
  275     char *guid;
  276 
  277     guid = GUID_string (data->mem_ctx, &(nameid.lpguid));
  278 
  279     if (nameid.ulKind == MNID_ID) {
  280         if (mapi_nameid_lid_lookup_canonical (nameid.kind.lid, guid, &lid) != MAPI_E_SUCCESS)
  281             lid = MAPI_E_RESERVED;
  282     } else if (nameid.ulKind == MNID_STRING) {
  283         if (mapi_nameid_string_lookup_canonical (nameid.kind.lpwstr.Name, guid, &lid) != MAPI_E_SUCCESS)
  284             lid = MAPI_E_RESERVED;
  285     }
  286 
  287     talloc_free (guid);
  288 
  289     if (lid != MAPI_E_RESERVED && (lid & 0xFFFF) == (proptag & 0xFFFF)) {
  290         data->next_proptag_is_nameid = proptag;
  291         data->next_nameid_proptag = lid;
  292     }
  293 
  294     return MAPI_E_SUCCESS;
  295 }
  296 
  297 static enum MAPISTATUS
  298 parse_property_cb (struct SPropValue prop, void *closure)
  299 {
  300     EMapiFXParserClosure *data = closure;
  301 
  302     if (data->next_proptag_is_nameid == prop.ulPropTag) {
  303         prop.ulPropTag = data->next_nameid_proptag;
  304     }
  305 
  306     data->next_proptag_is_nameid = MAPI_E_RESERVED;
  307     data->next_nameid_proptag = MAPI_E_RESERVED;
  308 
  309     if (!data->current_properties) {
  310         if (data->marker)
  311             g_debug ("%s: Property received out of order under marker %s", G_STRFUNC, get_proptag_name (data->marker));
  312         return MAPI_E_SUCCESS;
  313     }
  314 
  315     switch (prop.ulPropTag & 0xFFFF) {
  316         case PT_BINARY:
  317             if (data->current_streamed_properties && data->current_streamed_properties_count &&
  318                 prop.value.bin.cb > 65535) {
  319                 guint32 index;
  320 
  321                 (*data->current_streamed_properties) = talloc_realloc (data->current_streamed_mem_ctx,
  322                     (*data->current_streamed_properties),
  323                     EMapiStreamedProp,
  324                     (*data->current_streamed_properties_count) + 1);
  325                 index = (*data->current_streamed_properties_count);
  326                 (*data->current_streamed_properties_count)++;
  327                 (*data->current_streamed_properties)[index].proptag = prop.ulPropTag;
  328                 (*data->current_streamed_properties)[index].cb = prop.value.bin.cb;
  329                 (*data->current_streamed_properties)[index].lpb = prop.value.bin.lpb;
  330                 break;
  331             } else if (prop.value.bin.cb > 65535) {
  332                 g_debug ("%s: PT_BINARY property 0x%X larger than 64KB (%d), will be truncated", G_STRFUNC, prop.ulPropTag, prop.value.bin.cb);
  333             }
  334             /* falls through */
  335         case PT_BOOLEAN:
  336         case PT_I2:
  337         case PT_LONG:
  338         case PT_DOUBLE:
  339         case PT_I8:
  340         case PT_STRING8:
  341         case PT_UNICODE:
  342         case PT_SYSTIME:
  343         case PT_ERROR:
  344         case PT_CLSID:
  345         case PT_SVREID:
  346         case PT_MV_STRING8:
  347         case PT_MV_UNICODE:
  348         case PT_MV_BINARY:
  349         case PT_MV_LONG:
  350             data->current_properties->cValues++;
  351             data->current_properties->lpProps = talloc_realloc (data->mem_ctx,
  352                                         data->current_properties->lpProps,
  353                                         struct mapi_SPropValue,
  354                                         data->current_properties->cValues + 1);
  355             cast_mapi_SPropValue (data->mem_ctx, &data->current_properties->lpProps[data->current_properties->cValues - 1], &prop);
  356             data->current_properties->lpProps[data->current_properties->cValues].ulPropTag = 0;
  357             break;
  358         default:
  359             /* skip all of other type */
  360             break;
  361     }
  362 
  363     return MAPI_E_SUCCESS;
  364 }
  365 
  366 static enum MAPISTATUS
  367 e_mapi_fast_transfer_internal (EMapiConnection *conn,
  368                    TALLOC_CTX *mem_ctx,
  369                    TransferObjectCB cb,
  370                    gpointer cb_user_data,
  371                    gint objects_total,
  372                    gboolean expect_start_message,
  373                    mapi_object_t *fasttransfer_ctx,
  374                    GCancellable *cancellable,
  375                    GError **perror)
  376 {
  377     enum MAPISTATUS ms;
  378     enum TransferStatus transferStatus;
  379     uint16_t stepCount = -1, totalCount = -1;
  380     struct fx_parser_context *parser;
  381     EMapiFXParserClosure data = { 0 };
  382 
  383     data.conn = conn;
  384     data.mem_ctx = talloc_new (mem_ctx);
  385     data.cb = cb;
  386     data.cb_user_data = cb_user_data;
  387     data.cancellable = cancellable;
  388     data.perror = perror;
  389 
  390     data.next_proptag_is_nameid = MAPI_E_RESERVED;
  391     data.next_nameid_proptag = MAPI_E_RESERVED;
  392     data.object_index = 0;
  393     data.objects_total = objects_total;
  394     data.marker = 0;
  395     data.current_properties = NULL;
  396     data.current_streamed_mem_ctx = NULL;
  397     data.current_streamed_properties = NULL;
  398     data.current_streamed_properties_count = NULL;
  399     data.current_object = NULL;
  400     data.object = NULL;
  401 
  402     if (!expect_start_message) {
  403         data.object_index++;
  404         data.object = e_mapi_object_new (data.mem_ctx);
  405         data.current_object = data.object;
  406         data.current_properties = &data.object->properties;
  407         data.current_streamed_mem_ctx = data.object;
  408         data.current_streamed_properties = &data.object->streamed_properties;
  409         data.current_streamed_properties_count = &data.object->streamed_properties_count;
  410         data.marker = StartMessage;
  411     }
  412         
  413     parser = fxparser_init (data.mem_ctx, &data);
  414     fxparser_set_marker_callback (parser, parse_marker_cb);
  415     fxparser_set_delprop_callback (parser, parse_delprop_cb);
  416     fxparser_set_namedprop_callback (parser, parse_namedprop_cb);
  417     fxparser_set_property_callback (parser, parse_property_cb);
  418 
  419     do {
  420         DATA_BLOB transferdata;
  421 
  422         transferdata.data = NULL;
  423 
  424         ms = FXGetBuffer (fasttransfer_ctx, 0, &transferStatus, &stepCount, &totalCount, &transferdata);
  425         if (ms != MAPI_E_SUCCESS)
  426             break;
  427 
  428         ms = fxparser_parse (parser, &transferdata);
  429         talloc_free (transferdata.data);
  430         if (ms != MAPI_E_SUCCESS)
  431             break;
  432 
  433         if (g_cancellable_is_cancelled (cancellable)) {
  434             ms = MAPI_E_USER_CANCEL;
  435             break;
  436         }
  437     } while ((transferStatus == TransferStatus_Partial) || (transferStatus == TransferStatus_NoRoom));
  438 
  439     if (data.object) {
  440         e_mapi_object_finish_read (data.object);
  441         if (ms == MAPI_E_SUCCESS && !process_parsed_object (&data))
  442             ms = MAPI_E_USER_CANCEL;
  443 
  444         e_mapi_object_free (data.object);
  445     }
  446 
  447     talloc_free (parser);
  448     talloc_free (data.mem_ctx);
  449 
  450     return ms;
  451 }
  452 
  453 enum MAPISTATUS
  454 e_mapi_fast_transfer_objects (EMapiConnection *conn,
  455                   TALLOC_CTX *mem_ctx,
  456                   mapi_object_t *obj_folder,
  457                   mapi_id_array_t *ids,
  458                   TransferObjectCB cb,
  459                   gpointer cb_user_data,
  460                   GCancellable *cancellable,
  461                   GError **perror)
  462 {
  463     enum MAPISTATUS ms;
  464     mapi_object_t fasttransfer_ctx;
  465 
  466     mapi_object_init (&fasttransfer_ctx);
  467 
  468     ms = FXCopyMessages (obj_folder, ids, FastTransferCopyMessage_BestBody, FastTransfer_Unicode, &fasttransfer_ctx);
  469     if (ms == MAPI_E_SUCCESS)
  470         ms = e_mapi_fast_transfer_internal (conn, mem_ctx, cb, cb_user_data, ids->count, TRUE, &fasttransfer_ctx, cancellable, perror);
  471 
  472     mapi_object_release (&fasttransfer_ctx);
  473 
  474     if (perror && !*perror && ms != MAPI_E_SUCCESS)
  475         make_mapi_error (perror, G_STRFUNC, ms);
  476 
  477     return ms;
  478 }
  479 
  480 enum MAPISTATUS
  481 e_mapi_fast_transfer_object (EMapiConnection *conn,
  482                  TALLOC_CTX *mem_ctx,
  483                  mapi_object_t *object,
  484                  guint32 transfer_flags, /* bit or of EMapiFastTransferFlags */
  485                  TransferObjectCB cb,
  486                  gpointer cb_user_data,
  487                  GCancellable *cancellable,
  488                  GError **perror)
  489 {
  490     enum MAPISTATUS ms;
  491     mapi_object_t fasttransfer_ctx;
  492     struct SPropTagArray *excludes = NULL;
  493 
  494     mapi_object_init (&fasttransfer_ctx);
  495 
  496     #define add(x)  {                       \
  497         if (!excludes)                      \
  498             excludes = set_SPropTagArray (mem_ctx, 0x1, x); \
  499         else                            \
  500             SPropTagArray_add (mem_ctx, excludes, x);   \
  501     }
  502 
  503     if (!(transfer_flags & E_MAPI_FAST_TRANSFER_FLAG_ATTACHMENTS))
  504         add (PidTagMessageAttachments);
  505     if (!(transfer_flags & E_MAPI_FAST_TRANSFER_FLAG_RECIPIENTS))
  506         add (PidTagMessageRecipients);
  507 
  508     #undef add
  509 
  510     if (!excludes)
  511         excludes = talloc_zero (mem_ctx, struct SPropTagArray);
  512 
  513     ms = FXCopyTo (object, 0, FastTransferCopyTo_BestBody, FastTransfer_Unicode, excludes, &fasttransfer_ctx);
  514     if (ms == MAPI_E_SUCCESS)
  515         ms = e_mapi_fast_transfer_internal (conn, mem_ctx, cb, cb_user_data, 1, FALSE, &fasttransfer_ctx, cancellable, perror);
  516 
  517     mapi_object_release (&fasttransfer_ctx);
  518     talloc_free (excludes);
  519 
  520     if (perror && !*perror && ms != MAPI_E_SUCCESS)
  521         make_mapi_error (perror, G_STRFUNC, ms);
  522 
  523     return ms;
  524 }
  525 
  526 enum MAPISTATUS
  527 e_mapi_fast_transfer_properties (EMapiConnection *conn,
  528                  TALLOC_CTX *mem_ctx,
  529                  mapi_object_t *object,
  530                  struct SPropTagArray *tags,
  531                  TransferObjectCB cb,
  532                  gpointer cb_user_data,
  533                  GCancellable *cancellable,
  534                  GError **perror)
  535 {
  536     enum MAPISTATUS ms;
  537     mapi_object_t fasttransfer_ctx;
  538 
  539     g_return_val_if_fail (tags != NULL, MAPI_E_INVALID_PARAMETER);
  540     g_return_val_if_fail (tags->cValues > 0, MAPI_E_INVALID_PARAMETER);
  541 
  542     mapi_object_init (&fasttransfer_ctx);
  543 
  544     ms = FXCopyProperties (object, 0, 0, FastTransfer_Unicode, tags, &fasttransfer_ctx);
  545     if (ms == MAPI_E_SUCCESS)
  546         ms = e_mapi_fast_transfer_internal (conn, mem_ctx, cb, cb_user_data, 1, FALSE, &fasttransfer_ctx, cancellable, perror);
  547 
  548     mapi_object_release (&fasttransfer_ctx);
  549 
  550     if (perror && !*perror && ms != MAPI_E_SUCCESS)
  551         make_mapi_error (perror, G_STRFUNC, ms);
  552 
  553     return ms;
  554 }