tmailfs: support for UTF-8 searches - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit 6541f1798bb775b2a00c64af2b8d3f296a3d6f40
 (DIR) parent 1889a2578366ca17b4fee0b0641b4db183efd383
 (HTM) Author: Akshat Kumar <seed@mail.nanosouffle.net>
       Date:   Fri,  6 Sep 2013 16:09:29 -0400
       
       mailfs: support for UTF-8 searches
       
       UTF-8 searches with the SEARCH command must
       be conducted in two steps: the first sends
       tthe SEARCH command with the length of the
       UTF-8 encoded string and the second sends
       tthe literal search term. The searches need
       tto not be quoted.
       
       R=rsc, david.ducolombier, rsc, 0intro
       CC=plan9port.codebot
       https://codereview.appspot.com/13244043
       
       Diffstat:
         M src/cmd/upas/nfs/imap.c             |      55 +++++++++++++++++++++++++------
       
       1 file changed, 45 insertions(+), 10 deletions(-)
       ---
 (DIR) diff --git a/src/cmd/upas/nfs/imap.c b/src/cmd/upas/nfs/imap.c
       t@@ -34,6 +34,8 @@ struct Imap
                /* SEARCH results */
                uint                *uid;
                uint                nuid;
       +
       +        uint                reply;
        };
        
        static struct {
       t@@ -66,10 +68,11 @@ static int                getbox(Imap*, Box*);
        static int                getboxes(Imap*);
        static char*        gsub(char*, char*, char*);
        static int                imapcmd(Imap*, Box*, char*, ...);
       +static Sx*                imapcmdsxlit(Imap*, Box*, char*, ...);
        static Sx*                imapcmdsx(Imap*, Box*, char*, ...);
        static Sx*                imapcmdsx0(Imap*, char*, ...);
       -static Sx*                imapvcmdsx(Imap*, Box*, char*, va_list);
       -static Sx*                imapvcmdsx0(Imap*, char*, va_list);
       +static Sx*                imapvcmdsx(Imap*, Box*, char*, va_list, int);
       +static Sx*                imapvcmdsx0(Imap*, char*, va_list, int);
        static int                imapdial(char*, int);
        static int                imaplogin(Imap*);
        static int                imapquote(Fmt*);
       t@@ -338,7 +341,7 @@ imaprefreshthread(void *v)
         * Run a single command and return the Sx.  Does NOT redial.
         */
        static Sx*
       -imapvcmdsx0(Imap *z, char *fmt, va_list arg)
       +imapvcmdsx0(Imap *z, char *fmt, va_list arg, int dotag)
        {
                char *s;
                Fmt f;
       t@@ -353,7 +356,8 @@ imapvcmdsx0(Imap *z, char *fmt, va_list arg)
        
                prefix = strlen(tag)+1;
                fmtstrinit(&f);
       -        fmtprint(&f, "%s ", tag);
       +        if(dotag)
       +                fmtprint(&f, "%s ", tag);
                fmtvprint(&f, fmt, arg);
                fmtprint(&f, "\r\n");
                s = fmtstrflush(&f);
       t@@ -379,7 +383,7 @@ imapcmdsx0(Imap *z, char *fmt, ...)
                Sx *sx;
                
                va_start(arg, fmt);
       -        sx = imapvcmdsx0(z, fmt, arg);
       +        sx = imapvcmdsx0(z, fmt, arg, 1);
                va_end(arg);
                return sx;
        }
       t@@ -388,7 +392,7 @@ imapcmdsx0(Imap *z, char *fmt, ...)
         * Run a single command on box b.  Does redial.
         */
        static Sx*
       -imapvcmdsx(Imap *z, Box *b, char *fmt, va_list arg)
       +imapvcmdsx(Imap *z, Box *b, char *fmt, va_list arg, int dotag)
        {
                int tries;
                Sx *sx;
       t@@ -419,7 +423,7 @@ reconnect:
                        freesx(sx);
                }
        
       -        if((sx=imapvcmdsx0(z, fmt, arg)) == nil){
       +        if((sx=imapvcmdsx0(z, fmt, arg, dotag)) == nil){
                        if(tries++ == 0 && (z->fd < 0 || !z->connected))
                                goto reconnect;
                        return nil;
       t@@ -434,7 +438,7 @@ imapcmd(Imap *z, Box *b, char *fmt, ...)
                va_list arg;
        
                va_start(arg, fmt);
       -        sx = imapvcmdsx(z, b, fmt, arg);
       +        sx = imapvcmdsx(z, b, fmt, arg, 1);
                va_end(arg);
                if(sx == nil)
                        return -1;
       t@@ -454,7 +458,19 @@ imapcmdsx(Imap *z, Box *b, char *fmt, ...)
                va_list arg;
        
                va_start(arg, fmt);
       -        sx = imapvcmdsx(z, b, fmt, arg);
       +        sx = imapvcmdsx(z, b, fmt, arg, 1);
       +        va_end(arg);
       +        return sx;
       +}
       +
       +static Sx*
       +imapcmdsxlit(Imap *z, Box *b, char *fmt, ...)
       +{
       +        Sx *sx;
       +        va_list arg;
       +
       +        va_start(arg, fmt);
       +        sx = imapvcmdsx(z, b, fmt, arg, 0);
                va_end(arg);
                return sx;
        }
       t@@ -469,6 +485,10 @@ imapwaitsx(Imap *z)
                                fprint(2, "<| %#$\n", sx);
                        if(sx->nsx >= 1 && sx->sx[0]->type == SxAtom && cistrcmp(sx->sx[0]->data, tag) == 0)
                                return sx;
       +                if(sx->nsx >= 1 && sx->sx[0]->type == SxAtom && cistrcmp(sx->sx[0]->data, "+") == 0){
       +                        z->reply = 1;
       +                        return sx;
       +                }
                        if(sx->nsx >= 1 && sx->sx[0]->type == SxAtom && strcmp(sx->sx[0]->data, "*") == 0)
                                unexpected(z, sx);
                        if(sx->type == SxList && sx->nsx == 0){
       t@@ -651,17 +671,32 @@ imapsearchbox(Imap *z, Box *b, char *search, Msg ***mm)
                int i, nuid;
                Msg **m;
                int nm;
       +        Sx *sx;
        
                qlock(&z->lk);
       -        if(imapcmd(z, b, "UID SEARCH CHARSET UTF-8 TEXT %Z", search) < 0){
       +        sx = imapcmdsx(z, b, "UID SEARCH CHARSET UTF-8 TEXT {%d}", strlen(search));
       +        freesx(sx);
       +        if(!z->reply){
       +                qunlock(&z->lk);
       +                return -1;
       +        }
       +        if((sx = imapcmdsxlit(z, b, "%s", search)) == nil){
       +                qunlock(&z->lk);
       +                return -1;
       +        }
       +        if(sx->nsx < 2 || !isatom(sx->sx[1], "OK")){
       +                werrstr("%$", sx);
       +                freesx(sx);
                        qunlock(&z->lk);
                        return -1;
                }
       +        freesx(sx);
        
                uid = z->uid;
                nuid = z->nuid;
                z->uid = nil;
                z->nuid = 0;
       +        z->reply = 0;
                qunlock(&z->lk);
        
                m = emalloc(nuid*sizeof m[0]);