"Fossies" - the Fresh Open Source Software Archive

Member "citadel/modules/imap/imap_metadata.c" (5 Jun 2021, 8068 Bytes) of package /linux/www/citadel.tar.gz:


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 "imap_metadata.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 8.24_vs_9.01.

    1 /*
    2  * IMAP METADATA extension
    3  *
    4  * This is an implementation of the Bynari variant of the METADATA extension.
    5  *
    6  * Copyright (c) 2007-2017 by the citadel.org team
    7  *
    8  * This program is open source software; you can redistribute it and/or modify
    9  * it under the terms of the GNU General Public License as published by
   10  * the Free Software Foundation; either version 3 of the License, or
   11  * (at your option) any later version.
   12  *
   13  * This program is distributed in the hope that it will be useful,
   14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
   15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   16  * GNU General Public License for more details.
   17  *
   18  * You should have received a copy of the GNU General Public License
   19  * along with this program; if not, write to the Free Software
   20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   21  */
   22 
   23 
   24 #include "sysdep.h"
   25 #include <stdlib.h>
   26 #include <unistd.h>
   27 #include <stdio.h>
   28 #include <fcntl.h>
   29 #include <signal.h>
   30 #include <pwd.h>
   31 #include <errno.h>
   32 #include <sys/types.h>
   33 #include <time.h>
   34 #include <sys/wait.h>
   35 #include <ctype.h>
   36 #include <string.h>
   37 #include <limits.h>
   38 #include <libcitadel.h>
   39 #include "citadel.h"
   40 #include "server.h"
   41 #include "sysdep_decls.h"
   42 #include "citserver.h"
   43 #include "support.h"
   44 #include "config.h"
   45 #include "user_ops.h"
   46 #include "database.h"
   47 #include "msgbase.h"
   48 #include "internet_addressing.h"
   49 #include "serv_imap.h"
   50 #include "imap_tools.h"
   51 #include "imap_fetch.h"
   52 #include "imap_misc.h"
   53 #include "genstamp.h"
   54 
   55 #include "ctdl_module.h"
   56 
   57 /*
   58  * Implements the SETMETADATA command.
   59  *
   60  * Again, the only thing we're interested in setting here is the folder type.
   61  *
   62  * Attempting to set anything else calls a stub which fools the client into
   63  * thinking that there is no remaining space available to store annotations.
   64  */
   65 void imap_setmetadata(int num_parms, ConstStr *Params) {
   66     char roomname[ROOMNAMELEN];
   67     char savedroom[ROOMNAMELEN];
   68     int msgs, new;
   69     int ret;
   70     int setting_user_value = 0;
   71     char set_value[32];
   72     int set_view = VIEW_BBS;
   73     visit vbuf;
   74 
   75     if (num_parms != 6) {
   76         IReply("BAD usage error");
   77         return;
   78     }
   79 
   80     /*
   81      * Don't allow other types of metadata to be set
   82      */
   83     if (strcasecmp(Params[3].Key, "/vendor/kolab/folder-type")) {
   84         IReply("NO [METADATA TOOMANY] SETMETADATA failed");
   85         return;
   86     }
   87 
   88     if (!strcasecmp(Params[4].Key, "(value.shared")) {
   89         setting_user_value = 0;             /* global view */
   90     }
   91     else if (!strcasecmp(Params[4].Key, "(value.priv")) {
   92         setting_user_value = 1;             /* per-user view */
   93     }
   94     else {
   95         IReply("NO [METADATA TOOMANY] SETMETADATA failed");
   96         return;
   97     }
   98 
   99     /*
  100      * Extract the folder type without any parentheses.  Then learn
  101      * the Citadel view type based on the supplied folder type.
  102      */
  103     extract_token(set_value, Params[5].Key, 0, ')', sizeof set_value);
  104     if (!strncasecmp(set_value, "mail", 4)) {
  105         set_view = VIEW_MAILBOX;
  106     }
  107     else if (!strncasecmp(set_value, "event", 5)) {
  108         set_view = VIEW_CALENDAR;
  109     }
  110     else if (!strncasecmp(set_value, "contact", 7)) {
  111         set_view = VIEW_ADDRESSBOOK;
  112     }
  113     else if (!strncasecmp(set_value, "journal", 7)) {
  114         set_view = VIEW_JOURNAL;
  115     }
  116     else if (!strncasecmp(set_value, "note", 4)) {
  117         set_view = VIEW_NOTES;
  118     }
  119     else if (!strncasecmp(set_value, "task", 4)) {
  120         set_view = VIEW_TASKS;
  121     }
  122     else {
  123         set_view = VIEW_MAILBOX;
  124     }
  125 
  126     ret = imap_grabroom(roomname, Params[2].Key, 1);
  127     if (ret != 0) {
  128         IReply("NO Invalid mailbox name or access denied");
  129         return;
  130     }
  131 
  132     /*
  133      * CtdlUserGoto() formally takes us to the desired room.  (If another
  134      * folder is selected, save its name so we can return there!!!!!)
  135      */
  136     if (IMAP->selected) {
  137         strcpy(savedroom, CC->room.QRname);
  138     }
  139     CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
  140 
  141     /*
  142      * Always set the per-user view to the requested one.
  143      */
  144     CtdlGetRelationship(&vbuf, &CC->user, &CC->room);
  145     vbuf.v_view = set_view;
  146     CtdlSetRelationship(&vbuf, &CC->user, &CC->room);
  147 
  148     /* If this is a "value.priv" set operation, we're done. */
  149 
  150     if (setting_user_value)
  151     {
  152         IReply("OK SETANNOTATION complete");
  153     }
  154 
  155     /* If this is a "value.shared" set operation, we are allowed to perform it
  156      * under certain conditions.
  157      */
  158     else if (   (is_room_aide())                    /* aide or room aide */
  159         ||  (   (CC->room.QRflags & QR_MAILBOX)
  160             &&  (CC->user.usernum == atol(CC->room.QRname)) /* mailbox owner */
  161             )
  162         ||  (msgs == 0)     /* hack: if room is empty, assume we just created it */
  163     ) {
  164         CtdlGetRoomLock(&CC->room, CC->room.QRname);
  165         CC->room.QRdefaultview = set_view;
  166         CtdlPutRoomLock(&CC->room);
  167         IReply("OK SETANNOTATION complete");
  168     }
  169 
  170     /* If we got to this point, we don't have permission to set the default view. */
  171     else {
  172         IReply("NO [METADATA TOOMANY] SETMETADATA failed");
  173     }
  174 
  175     /*
  176      * If a different folder was previously selected, return there now.
  177      */
  178     if ( (IMAP->selected) && (strcasecmp(roomname, savedroom)) ) {
  179         CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
  180     }
  181     return;
  182 }
  183 
  184 
  185 /*
  186  * Implements the GETMETADATA command.
  187  *
  188  * Regardless of what the client asked for, we are going to supply them with
  189  * the folder type.  It's the only metadata we have anyway.
  190  */
  191 void imap_getmetadata(int num_parms, ConstStr *Params) {
  192     char roomname[ROOMNAMELEN];
  193     char savedroom[ROOMNAMELEN];
  194     int msgs, new;
  195     int ret;
  196     int found = 0;
  197 
  198 /* this doesn't work if you have rooms/floors with spaces. 
  199    we need this for the bynari connector.
  200     if (num_parms > 5) {
  201         IReply("BAD usage error");
  202         return;
  203     }
  204 */
  205     ret = imap_grabroom(roomname, Params[2].Key, 1);
  206     if (ret != 0) {
  207         IReply("NO Invalid mailbox name or access denied");
  208         return;
  209     }
  210 
  211     /*
  212      * CtdlUserGoto() formally takes us to the desired room.  (If another
  213      * folder is selected, save its name so we can return there!!!!!)
  214      */
  215     if (IMAP->selected) {
  216         strcpy(savedroom, CC->room.QRname);
  217     }
  218     CtdlUserGoto(roomname, 0, 0, &msgs, &new, NULL, NULL);
  219 
  220     IAPuts("* METADATA ");
  221     IPutCParamStr(2);
  222     IAPuts(" \"/vendor/kolab/folder-type\" (\"value.shared\" \"");
  223 
  224     /* If it's one of our hard-coded default rooms, we know what to do... */
  225 
  226     if (CC->room.QRname[10] == '.')
  227     {
  228         if (!strcasecmp(&CC->room.QRname[11], MAILROOM)) {
  229             found = 1;
  230             IAPuts("mail.inbox");
  231         }
  232         else if (!strcasecmp(&CC->room.QRname[11], SENTITEMS)) {
  233             found = 1;
  234             IAPuts("mail.sentitems");
  235         }
  236         else if (!strcasecmp(&CC->room.QRname[11], USERDRAFTROOM)) {
  237             found = 1;
  238             IAPuts("mail.drafts");
  239         }
  240         else if (!strcasecmp(&CC->room.QRname[11], USERCALENDARROOM)) {
  241             found = 1;
  242             IAPuts("event.default");
  243         }
  244         else if (!strcasecmp(&CC->room.QRname[11], USERCONTACTSROOM)) {
  245             found = 1;
  246             IAPuts("contact.default");
  247         }
  248         else if (!strcasecmp(&CC->room.QRname[11], USERNOTESROOM)) {
  249             found = 1;
  250             IAPuts("note.default");
  251         }
  252         else if (!strcasecmp(&CC->room.QRname[11], USERTASKSROOM)) {
  253             found = 1;
  254             IAPuts("task.default");
  255         }
  256     }
  257 
  258     /* Otherwise, use the view for this room to determine the type of data.
  259      * We are going with the default view rather than the user's view, because
  260      * the default view almost always defines the actual contents, while the
  261      * user's view might only make changes to presentation.  It also saves us
  262      * an extra database access because we don't need to load the visit record.
  263      */
  264     if (!found)
  265     {
  266         if (CC->room.QRdefaultview == VIEW_CALENDAR) {
  267             IAPuts("event");
  268         }
  269         else if (CC->room.QRdefaultview == VIEW_ADDRESSBOOK) {
  270             IAPuts("contact");
  271         }
  272         else if (CC->room.QRdefaultview == VIEW_TASKS) {
  273             IAPuts("task");
  274         }
  275         else if (CC->room.QRdefaultview == VIEW_NOTES) {
  276             IAPuts("note");
  277         }
  278         else if (CC->room.QRdefaultview == VIEW_JOURNAL) {
  279             IAPuts("journal");
  280         }
  281     }
  282     /* If none of the above conditions were met, consider it an ordinary mailbox. */
  283 
  284     if (!found) {
  285         IAPuts("mail");
  286     }
  287 
  288     /* "mail.outbox" and "junkemail" are not implemented. */
  289 
  290     IAPuts("\")\r\n");
  291 
  292     /*
  293      * If a different folder was previously selected, return there now.
  294      */
  295     if ( (IMAP->selected) && (strcasecmp(roomname, savedroom)) ) {
  296         CtdlUserGoto(savedroom, 0, 0, &msgs, &new, NULL, NULL);
  297     }
  298 
  299     IReply("OK GETMETADATA complete");
  300     return;
  301 }
  302