~ubuntu-branches/debian/stretch/alpine/stretch

« back to all changes in this revision

Viewing changes to web/src/alpined.d/alpined.c

  • Committer: Bazaar Package Importer
  • Author(s): Asheesh Laroia
  • Date: 2010-10-03 15:31:55 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20101003153155-2exypc96j1e8tw0p
Tags: 2.02-1
* New upstream release, based on re-alpine project
* Updated debian/copyright to reflect this fact
* re-alpine removed the non-free from the tarball, so now
  we do not repack the upstream tarball. (Yay!)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
#if !defined(lint) && !defined(DOS)
2
 
static char rcsid[] = "$Id: alpined.c 1166 2008-08-22 20:41:37Z mikes@u.washington.edu $";
 
2
static char rcsid[] = "$Id: alpined.c 1266 2009-07-14 18:39:12Z hubert@u.washington.edu $";
3
3
#endif
4
4
 
5
5
/* ========================================================================
109
109
 * Maximum number of lines allowed in signatures
110
110
 */
111
111
#define SIG_MAX_LINES           24
112
 
#define SIG_MAX_COLS            132
 
112
#define SIG_MAX_COLS            1024
113
113
 
114
114
 
115
115
/*
139
139
 
140
140
 
141
141
/*
 
142
 * Charset used within alpined and to communicate with alpined
 
143
 * Note: posting-charset still respected
 
144
 */
 
145
#define WP_INTERNAL_CHARSET     "UTF-8"
 
146
 
 
147
 
 
148
/*
142
149
 * Globals referenced throughout pine...
143
150
 */
144
151
struct pine *ps_global;                         /* THE global variable! */
147
154
/*
148
155
 * More global state
149
156
 */
150
 
long       peITop, peICount;
151
 
 
152
 
long       peInputTimeout = PE_INPUT_TIMEOUT;
153
 
long       peAbandonTimeout = 0;
 
157
long       gPeITop, gPeICount;
 
158
 
 
159
long       gPeInputTimeout = PE_INPUT_TIMEOUT;
 
160
long       gPEAbandonTimeout = 0;
 
161
 
154
162
 
155
163
/*
156
164
 * Authorization issues 
294
302
 */
295
303
#define PMC_NONE        0x00
296
304
#define PMC_FORCE_QUAL  0x01
 
305
#define PMC_PRSRV_ATT   0x02
297
306
 
298
307
/*
299
308
 * length of thread info string
334
343
void         peDestroyStream(struct pine *);
335
344
void         pePrepareForAuthException(void);
336
345
char        *peAuthException(void);
 
346
void         peInitVars(struct pine *);
337
347
int          peSelect(Tcl_Interp *, int, Tcl_Obj **, int);
338
348
int          peSelectNumber(Tcl_Interp *, int, Tcl_Obj **, int);
339
349
int          peSelectDate(Tcl_Interp *, int, Tcl_Obj **, int);
387
397
int          peNullWritec(int);
388
398
void         peGetMimeTyping(BODY *, Tcl_Obj **, Tcl_Obj **, Tcl_Obj **, Tcl_Obj **);
389
399
int          peGetFlag(Tcl_Interp *, imapuid_t, int, Tcl_Obj **);
 
400
int          peIsFlagged(MAILSTREAM *, imapuid_t, char *);
390
401
int          peSetFlag(Tcl_Interp *, imapuid_t, int, Tcl_Obj **);
391
402
int          peMsgSelect(Tcl_Interp *, imapuid_t, int, Tcl_Obj **);
392
403
int          peReplyHeaders(Tcl_Interp *, imapuid_t, int, Tcl_Obj **);
414
425
long         peSequenceNumber(imapuid_t);
415
426
int          peMsgCollector(Tcl_Interp *, int, Tcl_Obj **,
416
427
                            int (*)(METAENV *, BODY *, char *, CONTEXT_S **, char *), long);
417
 
int          peMsgCollected(Tcl_Interp  *, MSG_COL_S *, char *);
 
428
int          peMsgCollected(Tcl_Interp  *, MSG_COL_S *, char *, long);
418
429
void         peMsgSetParm(PARAMETER **, char *, char *);
419
430
Tcl_Obj     *peMsgAttachCollector(Tcl_Interp *, BODY *);
420
431
int          peFccAppend(Tcl_Interp *, Tcl_Obj *, char *, int);
462
473
long         peAppendMsg(MAILSTREAM *, void *, char **, char **, STRING **);
463
474
int          remote_pinerc_failure(void);
464
475
char        *peWebAlpinePrefix(void);
 
476
void         peNewMailAnnounce(MAILSTREAM *, long, long);
465
477
int          peMessageNeedPassphrase(Tcl_Interp *, imapuid_t, int, Tcl_Obj **);
466
478
int          peRssReturnFeed(Tcl_Interp *, char *, char *);
467
479
int          peRssPackageFeed(Tcl_Interp *, RSS_FEED_S *);
543
555
 
544
556
    srandom(getpid() + time(0));
545
557
 
546
 
#if     defined(DMALLOC)
547
 
    /* set 'high' flags */
548
 
    dmalloc_debug_setup("debug=0x4f4ed03,log=logfile");
549
 
#endif
550
 
 
551
558
    /*----------------------------------------------------------------------
552
559
           Initialize c-client
553
560
      ----------------------------------------------------------------------*/
570
577
    auth_link (&auth_pla);
571
578
    auth_link (&auth_log);              /* link in the log authenticator */
572
579
    ssl_onceonlyinit ();
 
580
    mail_parameters (NIL,SET_DISABLEPLAINTEXT,(void *) 2);
573
581
 
574
582
#if     PUBCOOKIE
575
583
    /* if REMOTE_USER set, use it as username */
598
606
      ----------------------------------------------------------------------*/
599
607
    pith_opt_remote_pinerc_failure = remote_pinerc_failure;
600
608
    pith_opt_user_agent_prefix = peWebAlpinePrefix;
 
609
    pith_opt_newmail_announce = peNewMailAnnounce;
601
610
 
602
611
    setup_for_index_index_screen();
603
612
 
674
683
 
675
684
                        FD_ZERO(&rfd);
676
685
                        FD_SET(s, &rfd);
677
 
                        tv.tv_sec = (peAbandonTimeout) ? peAbandonTimeout : peInputTimeout;
 
686
                        tv.tv_sec = (gPEAbandonTimeout) ? gPEAbandonTimeout : gPeInputTimeout;
678
687
                        tv.tv_usec = 0;
679
688
                        if((n = select(s+1, &rfd, 0, 0, &tv)) > 0){
680
689
                            socklen_t ll = l;
681
690
 
682
 
                            peAbandonTimeout = 0;
 
691
                            gPEAbandonTimeout = 0;
683
692
 
684
693
                            if((cs = accept(s, (struct sockaddr *) &name, &ll)) == -1){
685
694
                                dprint((SYSDBG_ERR, "accept failure: %s",
1837
1846
                    }
1838
1847
                    return(TCL_OK);
1839
1848
                }
1840
 
                else if(!strcmp(s1, "expungecheck")) {
1841
 
                  /* 
1842
 
                   * Return open folders and how many deleted messages they have
1843
 
                   *
1844
 
                   * return looks something like a list of these:
1845
 
                   * {folder-name number-deleted isinbox isincoming}
1846
 
                   */
1847
 
                    char *type;
1848
 
                    long delete_count;
1849
 
                    Tcl_Obj *resObj;
1850
 
 
1851
 
                    type = Tcl_GetStringFromObj(objv[2], NULL);
1852
 
                    if(!type) return(TCL_ERROR);
1853
 
                    if(strcmp(type, "current") != 0 && strcmp(type, "quit") != 0)
1854
 
                      return(TCL_ERROR);
1855
 
                    if(ps_global->mail_stream != sp_inbox_stream()
1856
 
                       || strcmp(type, "current") == 0){
1857
 
                        delete_count = count_flagged(ps_global->mail_stream, F_DEL);
1858
 
                        resObj = Tcl_NewListObj(0, NULL);
1859
 
                        Tcl_ListObjAppendElement(interp, resObj, 
1860
 
                                 Tcl_NewStringObj(pretty_fn(ps_global->cur_folder), -1));
1861
 
                        Tcl_ListObjAppendElement(interp, resObj, 
1862
 
                                                 Tcl_NewIntObj(delete_count));
1863
 
                        Tcl_ListObjAppendElement(interp, resObj, 
1864
 
                                                 Tcl_NewIntObj((ps_global->mail_stream 
1865
 
                                                            == sp_inbox_stream())
1866
 
                                                               ? 1 : 0));
1867
 
                        Tcl_ListObjAppendElement(interp, resObj, 
1868
 
                            Tcl_NewIntObj((ps_global->context_current->use & CNTXT_INCMNG)
1869
 
                                          ? 1 : 0));
1870
 
                        Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
1871
 
                                                 resObj);
1872
 
                    }
1873
 
                    if(strcmp(type, "quit") == 0){
1874
 
                        delete_count = count_flagged(sp_inbox_stream(), F_DEL);
1875
 
                        resObj = Tcl_NewListObj(0, NULL);
1876
 
                        Tcl_ListObjAppendElement(interp, resObj, 
1877
 
                                                 Tcl_NewStringObj("INBOX", -1));
1878
 
                        Tcl_ListObjAppendElement(interp, resObj, 
1879
 
                                                 Tcl_NewIntObj(delete_count));
1880
 
                        Tcl_ListObjAppendElement(interp, resObj, 
1881
 
                                                 Tcl_NewIntObj(1));
1882
 
                        Tcl_ListObjAppendElement(interp, resObj, 
1883
 
                                                 Tcl_NewIntObj(1));
1884
 
                        Tcl_ListObjAppendElement(interp, 
1885
 
                                                 Tcl_GetObjResult(interp), resObj);
1886
 
                    }
1887
 
                    return(TCL_OK);
1888
 
                }
1889
1849
                else if(!strcmp(s1, "rawsig")){
1890
1850
 
1891
1851
                    if(ps_global->VAR_LITERAL_SIG){
3410
3370
                        /*
3411
3371
                         * write at least one var into nearly empty pinerc
3412
3372
                         * and clear user's var settings. clear global cause
3413
 
                         * they'll get reset in init_vars
 
3373
                         * they'll get reset in peInitVars
3414
3374
                         */
3415
3375
                        for(var = ps_global->vars; var->name != NULL; var++){
3416
3376
                            var->been_written = ((var - ps_global->vars) != V_LAST_VERS_USED);
3426
3386
 
3427
3387
                        write_pinerc(ps_global, Main, WRP_NOUSER | WRP_PRESERV_WRITTEN);
3428
3388
 
3429
 
                        init_vars(ps_global, NULL);
 
3389
                        peInitVars(ps_global);
3430
3390
                        return(TCL_OK);
3431
3391
                    }
3432
3392
                }
4120
4080
                return(TCL_ERROR);
4121
4081
            }
4122
4082
 
4123
 
            dprint((1, "PESession: user: %s\n\tpinerc: %s\n\tpineconf: %s",
4124
 
                       pe_user, pinerc, pineconf ? pineconf : "<none>"));
 
4083
            dprint((SYSDBG_INFO, "session (%s) %s - %s",
 
4084
                    pe_user, pinerc, pineconf ? pineconf : "<none>"));
4125
4085
 
4126
4086
            /* credential cache MUST already be seeded */
4127
4087
 
4143
4103
            fs_give((void **) &pe_user);
4144
4104
            fs_give((void **) &pe_host);
4145
4105
 
4146
 
            return(peCreateStream(interp, ps_global->context_list, "INBOX", TRUE));
 
4106
            return(TCL_OK);
4147
4107
        }
4148
4108
        else if(!strcmp(op, "close")){
4149
4109
            if(ps_global){
4380
4340
                if(Tcl_GetLongFromObj(interp, objv[2], &t) == TCL_OK){
4381
4341
                    /* ten second minimum and max of default */
4382
4342
                    if(t > 0 && t <= PE_INPUT_TIMEOUT){
4383
 
                        peAbandonTimeout = t;
 
4343
                        gPEAbandonTimeout = t;
4384
4344
                        return(TCL_OK);
4385
4345
                    }
4386
4346
                    else
4436
4396
            err = "S/MIME not configured for this server";
4437
4397
#endif /* SMIME */
4438
4398
        }
 
4399
        else if(!strcmp(op, "expungecheck")) {
 
4400
            /* 
 
4401
             * Return open folders and how many deleted messages they have
 
4402
             *
 
4403
             * return looks something like a list of these:
 
4404
             * {folder-name number-deleted isinbox isincoming}
 
4405
             */
 
4406
            char *type;
 
4407
            long delete_count;
 
4408
            Tcl_Obj *resObj;
 
4409
 
 
4410
            if(objc != 3){
 
4411
                err = "PESession: expungecheck <type>";
 
4412
            }
 
4413
            else {
 
4414
                type = Tcl_GetStringFromObj(objv[2], NULL);
 
4415
                if(type && (strcmp(type, "current") == 0 || strcmp(type, "quit") == 0)){
 
4416
 
 
4417
                    if(ps_global->mail_stream != sp_inbox_stream()
 
4418
                       || strcmp(type, "current") == 0){
 
4419
                        delete_count = count_flagged(ps_global->mail_stream, F_DEL);
 
4420
                        resObj = Tcl_NewListObj(0, NULL);
 
4421
                        Tcl_ListObjAppendElement(interp, resObj, 
 
4422
                                                 Tcl_NewStringObj(pretty_fn(ps_global->cur_folder), -1));
 
4423
                        Tcl_ListObjAppendElement(interp, resObj, 
 
4424
                                                 Tcl_NewIntObj(delete_count));
 
4425
                        Tcl_ListObjAppendElement(interp, resObj, 
 
4426
                                                 Tcl_NewIntObj((ps_global->mail_stream 
 
4427
                                                                == sp_inbox_stream())
 
4428
                                                               ? 1 : 0));
 
4429
                        Tcl_ListObjAppendElement(interp, resObj, 
 
4430
                                                 Tcl_NewIntObj((ps_global->context_current->use & CNTXT_INCMNG)
 
4431
                                                               ? 1 : 0));
 
4432
                        Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
 
4433
                                                 resObj);
 
4434
                    }
 
4435
                    if(strcmp(type, "quit") == 0){
 
4436
                        delete_count = count_flagged(sp_inbox_stream(), F_DEL);
 
4437
                        resObj = Tcl_NewListObj(0, NULL);
 
4438
                        Tcl_ListObjAppendElement(interp, resObj, 
 
4439
                                                 Tcl_NewStringObj("INBOX", -1));
 
4440
                        Tcl_ListObjAppendElement(interp, resObj, 
 
4441
                                                 Tcl_NewIntObj(delete_count));
 
4442
                        Tcl_ListObjAppendElement(interp, resObj, 
 
4443
                                                 Tcl_NewIntObj(1));
 
4444
                        Tcl_ListObjAppendElement(interp, resObj, 
 
4445
                                                 Tcl_NewIntObj(1));
 
4446
                        Tcl_ListObjAppendElement(interp, 
 
4447
                                                 Tcl_GetObjResult(interp), resObj);
 
4448
                    }
 
4449
                    return(TCL_OK);
 
4450
                }
 
4451
                else
 
4452
                  err = "PESession: expungecheck unknown type";
 
4453
            }
 
4454
        }
 
4455
        else if(!strcmp(op, "mailcheck")) {
 
4456
            /* 
 
4457
             * CMD: mailcheck
 
4458
             *
 
4459
             * ARGS: reload -- "1" if we're reloading
 
4460
             *       (vs. just checking newmail as a side effect
 
4461
             *        of building a new page)
 
4462
             *
 
4463
             * Return list of folders with new or expunged messages
 
4464
             *
 
4465
             * return looks something like a list of these:
 
4466
             * {new-count newest-uid announcement-msg}
 
4467
             */
 
4468
            int    reload, force = UFU_NONE, rv;
 
4469
            time_t now = time(0);
 
4470
 
 
4471
            if(objc <= 3){
 
4472
                if(objc < 3 || Tcl_GetIntFromObj(interp, objv[2], &reload) == TCL_ERROR)
 
4473
                  reload = 0;
 
4474
 
 
4475
                /* minimum 10 second between IMAP pings */
 
4476
                if(!time_of_last_input() || now - time_of_last_input() > 10){
 
4477
                    force = UFU_FORCE;
 
4478
                    if(!reload)
 
4479
                      peMarkInputTime();
 
4480
                }
 
4481
 
 
4482
                peED.interp = interp;
 
4483
 
 
4484
                /* check for new mail */
 
4485
                new_mail(force, reload ? GoodTime : VeryBadTime, NM_STATUS_MSG);
 
4486
 
 
4487
                if(!reload){                    /* announced */
 
4488
                    zero_new_mail_count();
 
4489
                }
 
4490
 
 
4491
                return(TCL_OK);
 
4492
            }
 
4493
            else
 
4494
              err = "PESession: mailcheck <reload>";
 
4495
        }
4439
4496
    }
4440
4497
 
4441
4498
    Tcl_SetResult(interp, err, TCL_STATIC);
4528
4585
        Tcl_WrongNumArgs(interp, 1, objv, "cmd ?args?");
4529
4586
    }
4530
4587
    else if((op = Tcl_GetStringFromObj(objv[1], NULL)) != NULL){
4531
 
        if(ps_global && ps_global->mail_stream){
 
4588
        if(ps_global){
4532
4589
            if(objc == 2){
4533
4590
                if(!strcmp(op, "current")){
4534
4591
                    CONTEXT_S *cp;
4661
4718
                          break;
4662
4719
                      }
4663
4720
 
4664
 
                    Tcl_SetResult(interp, delim[0] ? delim : "/", TCL_STATIC);
 
4721
                    Tcl_SetResult(interp, delim[0] ? delim : "/", TCL_VOLATILE);
4665
4722
                    return(TCL_OK);
4666
4723
                }
4667
4724
                else
4715
4772
                                     && (mstream = same_stream_and_mailbox(tmp, ps_global->mail_stream)))){
4716
4773
                                    long retflags = 0;
4717
4774
 
 
4775
                                    ps_global->noshow_error = 1;
4718
4776
                                    our_stream = 1;
4719
4777
                                    mstream = context_open(cp, NULL, folder,
4720
4778
                                                           SP_USEPOOL | SP_TEMPUSE| OP_READONLY | OP_SHORTCACHE,
4721
4779
                                                           &retflags);
 
4780
                                    ps_global->noshow_error = 0;
4722
4781
                                }
4723
4782
 
4724
4783
                                count = count_flagged(mstream, flags);
5470
5529
            }
5471
5530
        }
5472
5531
        else
5473
 
          err = "No Mailbox Currently Open";
 
5532
          err = "No User Context Established";
5474
5533
    }
5475
5534
 
5476
5535
    Tcl_SetResult(interp, err, TCL_VOLATILE);
5484
5543
int
5485
5544
PEMailboxCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
5486
5545
{
5487
 
    char *op, errbuf[256], *err = "Unknown PEMailbox request";
 
5546
    char *op, errbuf[256], *err = "Unknown PEMailbox operation";
5488
5547
 
5489
5548
    dprint((5, "PEMailboxCmd"));
5490
5549
 
5492
5551
        Tcl_WrongNumArgs(interp, 1, objv, "cmd ?args?");
5493
5552
    }
5494
5553
    else if((op = Tcl_GetStringFromObj(objv[1], NULL)) != NULL){
5495
 
        if(ps_global && ps_global->mail_stream){
 
5554
        if(!strucmp(op, "open")){
 
5555
            int        i, colid;
 
5556
            char      *folder;
 
5557
            CONTEXT_S *cp;
 
5558
 
 
5559
            peED.uid = 0;               /* forget cached embedded data */
 
5560
 
 
5561
            /*
 
5562
             * CMD: open <context-index> <folder>
 
5563
             *
 
5564
             * 
 
5565
             */
 
5566
            if(objc == 2){
 
5567
                Tcl_SetResult(interp, (!sp_dead_stream(ps_global->mail_stream)) ? "0" : "1", TCL_VOLATILE);
 
5568
                return(TCL_OK);
 
5569
            }
 
5570
 
 
5571
            if(Tcl_GetIntFromObj(interp,objv[2],&colid) != TCL_ERROR){
 
5572
                if((folder = Tcl_GetStringFromObj(objv[objc - 1], NULL)) != NULL) {
 
5573
                    for(i = 0, cp = ps_global->context_list; cp ; i++, cp = cp->next)
 
5574
                      if(i == colid) {
 
5575
                          if(PEMakeFolderString(interp, cp, objc - 3, objv + 3,
 
5576
                                                &folder))
 
5577
                            return TCL_ERROR;
 
5578
                      
 
5579
                          dprint((1, "* PEMailbox open dir=%s folder=%s",cp->dir->ref,folder));
 
5580
                      
 
5581
                          return(peCreateStream(interp, cp, folder, FALSE));
 
5582
                      }
 
5583
 
 
5584
                    err = "open: Unrecognized collection ID";
 
5585
                }
 
5586
                else
 
5587
                  err = "open: Can't read folder";
 
5588
            }
 
5589
            else
 
5590
              err = "open: Can't get collection ID";
 
5591
        }
 
5592
        else if(!strcmp(op, "indexformat")){
 
5593
            /*
 
5594
             * CMD: indexformat
 
5595
             *
 
5596
             * Returns: list of lists where:
 
5597
             *          *  the first element is the name of the
 
5598
             *             field which may be "From", "Subject"
 
5599
             *             "Date" or the emtpy string.
 
5600
             *          *  the second element which is either
 
5601
             *             the percentage width or empty string
 
5602
             */
 
5603
            if(objc == 2)
 
5604
              return(peIndexFormat(interp));
 
5605
        }
 
5606
        else if(ps_global && ps_global->mail_stream){
5496
5607
            if(!strcmp(op, "select")){
5497
5608
                return(peSelect(interp, objc - 2, &((Tcl_Obj **) objv)[2], MN_SLCT));
5498
5609
            }
5502
5613
            else if(!strucmp(op, "apply")){
5503
5614
                return(peApply(interp, objc - 2, &((Tcl_Obj **) objv)[2]));
5504
5615
            }
5505
 
            else if(!strucmp(op, "open")){
5506
 
                    int        i, colid;
5507
 
                    char      *folder;
5508
 
                    CONTEXT_S *cp;
5509
 
 
5510
 
                    peED.uid = 0;               /* forget cached embedded data */
5511
 
 
5512
 
                    /*
5513
 
                     * CMD: open <context-index> <folder>
5514
 
                     *
5515
 
                     * 
5516
 
                     */
5517
 
                    if(objc == 2){
5518
 
                        Tcl_SetResult(interp, (!sp_dead_stream(ps_global->mail_stream)) ? "0" : "1", TCL_VOLATILE);
5519
 
                        return(TCL_OK);
5520
 
                    }
5521
 
 
5522
 
                    if(Tcl_GetIntFromObj(interp,objv[2],&colid) != TCL_ERROR){
5523
 
                        if((folder = Tcl_GetStringFromObj(objv[objc - 1], NULL)) != NULL) {
5524
 
                            for(i = 0, cp = ps_global->context_list; cp ; i++, cp = cp->next)
5525
 
                              if(i == colid) {
5526
 
                                  if(PEMakeFolderString(interp, cp, objc - 3, objv + 3,
5527
 
                                                        &folder))
5528
 
                                    return TCL_ERROR;
5529
 
                      
5530
 
                                  dprint((1, "* PEMailbox open dir=%s folder=%s",cp->dir->ref,folder));
5531
 
                      
5532
 
                                  return(peCreateStream(interp, cp, folder, FALSE));
5533
 
                              }
5534
 
 
5535
 
                            err = "open: Unrecognized collection ID";
5536
 
                        }
5537
 
                        else
5538
 
                          err = "open: Can't read folder";
5539
 
                    }
5540
 
                    else
5541
 
                      err = "open: Can't get collection ID";
5542
 
            }
5543
5616
            else if(!strcmp(op, "expunge")){
5544
5617
                /*
5545
5618
                 * CMD: expunge
5692
5765
 
5693
5766
                            /* set index range for efficiency */
5694
5767
                            if(msgno > 0L && msgno <= mn_get_total(sp_msgmap(ps_global->mail_stream))){
5695
 
                                peITop   = msgno;
5696
 
                                peICount = count;
 
5768
                                gPeITop   = msgno;
 
5769
                                gPeICount = count;
5697
5770
                            }
5698
5771
 
5699
5772
                            if(objc == 4 || Tcl_ListObjGetElements(interp, objv[4], &aObjN, &aObj) == TCL_OK){
5717
5790
                                                            if(!strcmp(s, "statusbits")){
5718
5791
                                                                char *s = peMsgStatBitString(ps_global, ps_global->mail_stream,
5719
5792
                                                                                             sp_msgmap(ps_global->mail_stream), peMessageNumber(uid),
5720
 
                                                                                             peITop, peICount, &fetched);
 
5793
                                                                                             gPeITop, gPeICount, &fetched);
5721
5794
                                                                Tcl_ListObjAppendElement(interp, avObj, Tcl_NewStringObj(s, -1));
5722
5795
                                                            }
5723
5796
                                                            else if(!strcmp(s, "statuslist")){
5724
5797
                                                                Tcl_Obj *nObj = peMsgStatNameList(interp, ps_global, ps_global->mail_stream,
5725
5798
                                                                                                  sp_msgmap(ps_global->mail_stream), peMessageNumber(uid),
5726
 
                                                                                                  peITop, peICount, &fetched);
 
5799
                                                                                                  gPeITop, gPeICount, &fetched);
5727
5800
                                                                Tcl_ListObjAppendElement(interp, avObj, nObj);
5728
5801
                                                            }
5729
5802
                                                            else if(!strcmp(s, "status")){
5876
5949
                    Tcl_SetResult(interp, ps_global->cur_folder, TCL_VOLATILE);
5877
5950
                    return(TCL_OK);
5878
5951
                }
5879
 
                else if(!strcmp(op, "indexformat")){
5880
 
                    /*
5881
 
                     * CMD: indexformat
5882
 
                     *
5883
 
                     * Returns: list of lists where:
5884
 
                     *          *  the first element is the name of the
5885
 
                     *             field which may be "From", "Subject"
5886
 
                     *             "Date" or the emtpy string.
5887
 
                     *          *  the second element which is either
5888
 
                     *             the percentage width or empty string
5889
 
                     */
5890
 
                    return(peIndexFormat(interp));
5891
 
                }
5892
5952
                else if(!strcmp(op, "close")){
5893
5953
                    /*
5894
5954
                     * CMD: close
6074
6134
                    return(TCL_ERROR);
6075
6135
                }
6076
6136
                else if(!strcmp(op, "newmail")){
6077
 
                    int           reload, force = FALSE, rv;
6078
 
                    static time_t last_check = 0;
 
6137
                    int           reload, force = UFU_NONE, rv;
6079
6138
                    time_t        now = time(0);
6080
6139
 
6081
6140
                    /*
6091
6150
                    if(Tcl_GetIntFromObj(interp, objv[2], &reload) == TCL_ERROR)
6092
6151
                      reload = 0;
6093
6152
 
6094
 
                    if(!last_check || now - last_check > 15)
6095
 
                      force = TRUE;
6096
 
 
6097
 
                    last_check = now;
 
6153
                    /* minimum 10 second between IMAP pings */
 
6154
                    if(!time_of_last_input() || now - time_of_last_input() > 10){
 
6155
                        force = UFU_FORCE;
 
6156
                        peMarkInputTime();
 
6157
                    }
6098
6158
 
6099
6159
                    /* check for new mail */
6100
6160
                    new_mail(force, reload ? GoodTime : VeryBadTime, NM_NONE);
6101
 
 
 
6161
                    
6102
6162
                    rv = peNewMailResult(interp);
6103
6163
 
6104
 
                    if(!reload)
6105
 
                      peMarkInputTime();
 
6164
                    if(!reload)                         /* announced */
 
6165
                      zero_new_mail_count();
6106
6166
 
6107
6167
                    return(rv);
6108
6168
                }
6480
6540
            return(TCL_OK);
6481
6541
        }
6482
6542
        else
6483
 
          snprintf(err = errbuf, sizeof(errbuf), "%s: No open mailbox",
6484
 
                  Tcl_GetStringFromObj(objv[0], NULL));
 
6543
          snprintf(err = errbuf, sizeof(errbuf), "%s: %s: No open mailbox",
 
6544
                   Tcl_GetStringFromObj(objv[0], NULL), op);
6485
6545
    }
6486
6546
 
6487
6547
    Tcl_SetResult(interp, err, TCL_VOLATILE);
7103
7163
            }
7104
7164
        }
7105
7165
        else if(objc == 2){
 
7166
            if(!strucmp(subcmd, "count")){
 
7167
                /*
 
7168
                 * Args: flag
 
7169
                 */
 
7170
                char *flagname;
 
7171
                long  n, rawno, count = 0;
 
7172
 
 
7173
                if((flagname = Tcl_GetStringFromObj(objv[1], NULL)) != NULL){
 
7174
                    for(n = 1L; n <= mn_get_total(sp_msgmap(ps_global->mail_stream)); n++){
 
7175
                        rawno = mn_m2raw(sp_msgmap(ps_global->mail_stream), n);
 
7176
                        if(get_lflag(ps_global->mail_stream, NULL, rawno, MN_SLCT)
 
7177
                           && peIsFlagged(ps_global->mail_stream,
 
7178
                                          mail_uid(ps_global->mail_stream, rawno),
 
7179
                                          flagname)){
 
7180
                            count++;
 
7181
                        }
 
7182
                    }
 
7183
                }
 
7184
 
 
7185
                Tcl_SetResult(interp, long2string(count), TCL_VOLATILE);
 
7186
                return(TCL_OK);
 
7187
            }
7106
7188
        }
7107
7189
        else if(objc == 3){
7108
7190
            if(!strucmp(subcmd, "flag")){
7543
7625
                                        Tcl_NewLongObj(n)) != TCL_OK)
7544
7626
              return(TCL_ERROR);
7545
7627
 
7546
 
            /*
7547
 
             * second element is UID of most recent message
7548
 
             */
 
7628
            /* second element is UID of most recent message */
7549
7629
            for(uid = ps_global->mail_stream->nmsgs; uid > 1L; uid--)
7550
7630
              if(!get_lflag(ps_global->mail_stream, NULL, uid, MN_EXLD))
7551
7631
                break;
7576
7656
              return(TCL_ERROR);
7577
7657
        }
7578
7658
 
 
7659
        /* third element is expunge count */
7579
7660
        if(Tcl_ListObjAppendElement(interp,
7580
7661
                                    Tcl_GetObjResult(interp),
7581
7662
                                    Tcl_NewLongObj(sp_expunge_count(ps_global->mail_stream)
9070
9151
int
9071
9152
peGetFlag(Tcl_Interp *interp, imapuid_t uid, int objc, Tcl_Obj **objv)
9072
9153
{
9073
 
    char         *flagname;
9074
 
    long          raw;
9075
 
    int           value = 0;
 
9154
    char *flagname;
 
9155
 
 
9156
    Tcl_SetResult(interp,
 
9157
                  int2string(((flagname = Tcl_GetStringFromObj(objv[0], NULL)) != NULL)
 
9158
                               ? peIsFlagged(ps_global->mail_stream, uid, flagname)
 
9159
                               : 0),
 
9160
                  TCL_VOLATILE);
 
9161
    return(TCL_OK);
 
9162
}
 
9163
 
 
9164
 
 
9165
int
 
9166
peIsFlagged(MAILSTREAM *stream, imapuid_t uid, char *flagname)
 
9167
{
9076
9168
    MESSAGECACHE *mc;
9077
 
 
9078
 
    if((flagname = Tcl_GetStringFromObj(objv[0], NULL)) != NULL){
9079
 
        raw = peSequenceNumber(uid);
9080
 
 
9081
 
        if(!((mc = mail_elt(ps_global->mail_stream, raw))
9082
 
             && mc->valid)){
9083
 
            mail_fetch_flags(ps_global->mail_stream,
9084
 
                             ulong2string(uid), FT_UID);
9085
 
            mc = mail_elt(ps_global->mail_stream, raw);
9086
 
        }
9087
 
 
9088
 
        if(!strucmp(flagname, "deleted")){
9089
 
            value = mc->deleted;
9090
 
        }
9091
 
        else if(!strucmp(flagname, "new")){
9092
 
            value = !mc->seen;
9093
 
        }
9094
 
        else if(!strucmp(flagname, "important")){
9095
 
            value = mc->flagged;
9096
 
        }
9097
 
        else if(!strucmp(flagname, "answered")){
9098
 
            value = mc->answered;
9099
 
        }
9100
 
        else if(!strucmp(flagname, "recent")){
9101
 
            value = mc->recent;
9102
 
        }
 
9169
    long          raw = peSequenceNumber(uid);
 
9170
 
 
9171
    if(!((mc = mail_elt(stream, raw)) && mc->valid)){
 
9172
        mail_fetch_flags(stream, ulong2string(uid), FT_UID);
 
9173
        mc = mail_elt(stream, raw);
9103
9174
    }
9104
9175
 
9105
 
    Tcl_SetResult(interp, int2string(value), TCL_VOLATILE);
9106
 
    return(TCL_OK);
 
9176
    if(!strucmp(flagname, "deleted"))
 
9177
      return(mc->deleted);
 
9178
 
 
9179
    if(!strucmp(flagname, "new"))
 
9180
      return(!mc->seen);
 
9181
 
 
9182
    if(!strucmp(flagname, "important"))
 
9183
      return(mc->flagged);
 
9184
 
 
9185
    if(!strucmp(flagname, "answered"))
 
9186
      return(mc->answered);
 
9187
 
 
9188
    if(!strucmp(flagname, "recent"))
 
9189
      return(mc->recent);
 
9190
 
 
9191
    return(0);
9107
9192
}
9108
9193
 
9109
9194
 
9110
 
 
9111
9195
/*
9112
9196
 * peSetFlag - Set requested flags value to 1 or 0
9113
9197
 *
9218
9302
 
9219
9303
    if((h = build_header_work(ps_global, ps_global->mail_stream,
9220
9304
                              sp_msgmap(ps_global->mail_stream), peMessageNumber(uid),
9221
 
                              peITop, peICount, fetched)) != NULL){
 
9305
                              gPeITop, gPeICount, fetched)) != NULL){
9222
9306
        for(f = h->ifield; f; f = f->next){
9223
9307
 
9224
9308
            if((objField = Tcl_NewListObj(0, NULL)) == NULL)
9321
9405
 
9322
9406
    if((h = build_header_work(ps_global, ps_global->mail_stream,
9323
9407
                              sp_msgmap(ps_global->mail_stream), peMessageNumber(uid),
9324
 
                              peITop, peICount, fetched))
 
9408
                              gPeITop, gPeICount, fetched))
9325
9409
       && h->color_lookup_done
9326
9410
       && h->linecolor){
9327
9411
 
9353
9437
    Tcl_SetResult(interp,
9354
9438
                  peMsgStatBitString(ps_global, ps_global->mail_stream,
9355
9439
                                     sp_msgmap(ps_global->mail_stream), peMessageNumber(uid),
9356
 
                                     peITop, peICount, NULL),
 
9440
                                     gPeITop, gPeICount, NULL),
9357
9441
                  TCL_STATIC);
9358
9442
    return(TCL_OK);
9359
9443
}
10729
10813
 
10730
10814
    pePrepareForAuthException();
10731
10815
 
10732
 
    init_vars(pine_state, NULL);
 
10816
    peInitVars(pine_state);
10733
10817
 
10734
10818
    if(s = peAuthException())
10735
10819
      return(s);
10815
10899
     */
10816
10900
    F_TURN_ON(F_QUELL_IMAP_ENV_CB, pine_state);
10817
10901
    F_TURN_ON(F_SLCTBL_ITEM_NOBOLD, pine_state);
 
10902
    F_TURN_OFF(F_USE_SYSTEM_TRANS, pine_state);
10818
10903
 
10819
10904
    /*
10820
10905
     * Fake screen dimensions for index formatting and
10952
11037
}
10953
11038
 
10954
11039
 
 
11040
void
 
11041
peInitVars(struct pine *ps)
 
11042
{
 
11043
    init_vars(ps, NULL);
 
11044
 
 
11045
    /*
 
11046
     * fix display/keyboard-character-set to utf-8
 
11047
     *
 
11048
     *
 
11049
     */
 
11050
 
 
11051
    if(ps->display_charmap)
 
11052
      fs_give((void **) &ps->display_charmap);
 
11053
 
 
11054
    ps->display_charmap = cpystr(WP_INTERNAL_CHARSET);
 
11055
 
 
11056
    if(ps->keyboard_charmap)
 
11057
      fs_give((void **) &ps->keyboard_charmap);
 
11058
 
 
11059
    ps->keyboard_charmap = cpystr(WP_INTERNAL_CHARSET);
 
11060
 
 
11061
    (void) setup_for_input_output(FALSE, &ps->display_charmap, &ps->keyboard_charmap, &ps->input_cs, NULL);;
 
11062
}
 
11063
 
 
11064
 
 
11065
 
10955
11066
int
10956
11067
peMessageBounce(Tcl_Interp *interp, imapuid_t uid, int objc, Tcl_Obj **objv)
10957
11068
{
12001
12112
 
12002
12113
                    return(rv);
12003
12114
                }
 
12115
                else if(!strcmp(s1, "draft")){
 
12116
                    int rv;
 
12117
 
 
12118
                    if((rv = peMsgCollector(interp, objc - 2, (Tcl_Obj **) &objv[2], peDoPostpone, PMC_PRSRV_ATT)) == TCL_OK)
 
12119
                      Tcl_SetResult(interp, ulong2string(get_last_append_uid()), TCL_VOLATILE);
 
12120
 
 
12121
                    return(rv);
 
12122
                }
12004
12123
                else if(!strcmp(s1, "delete")){
12005
12124
                    if(Tcl_GetLongFromObj(interp, objv[2], &uid) == TCL_OK){
12006
12125
                        MAILSTREAM    *stream;
12126
12245
    for(i = 0; i < nMsg; i++){
12127
12246
        if(Tcl_ListObjGetElements(interp, objMsg[i], &nField, &objField) != TCL_OK){
12128
12247
            err = "";           /* interp's result object has error message */
12129
 
            return(peMsgCollected(interp, &md, err));
 
12248
            return(peMsgCollected(interp, &md, err, flags));
12130
12249
        }
12131
12250
 
12132
12251
        if(nField && (field = Tcl_GetStringFromObj(objField[0], NULL))){
12133
12252
            if(!strcmp(field, "body")){
12134
12253
                if(md.msgtext){
12135
12254
                    err = "Too many bodies";
12136
 
                    return(peMsgCollected(interp, &md, err));
 
12255
                    return(peMsgCollected(interp, &md, err, flags));
12137
12256
                }
12138
12257
                else if((md.msgtext = so_get(CharStar, NULL, EDIT_ACCESS)) != NULL){
12139
12258
                    /* mark storage object as user edited */
12148
12267
                        }
12149
12268
                        else{
12150
12269
                            err = "Value read failure";
12151
 
                            return(peMsgCollected(interp, &md, err));
 
12270
                            return(peMsgCollected(interp, &md, err, flags));
12152
12271
                        }
12153
12272
                    }
12154
12273
                }
12155
12274
                else {
12156
12275
                    err = "Can't acquire body storage";
12157
 
                    return(peMsgCollected(interp, &md, err));
 
12276
                    return(peMsgCollected(interp, &md, err, flags));
12158
12277
                }
12159
12278
            }
12160
12279
            else if(!strucmp(field, "attach")){
12178
12297
                }
12179
12298
                else{
12180
12299
                    strcpy(err = tmp_20k_buf, "Unknown attachment ID");
12181
 
                    return(peMsgCollected(interp, &md, err));
 
12300
                    return(peMsgCollected(interp, &md, err, flags));
12182
12301
                }
12183
12302
            }
12184
12303
            else if(!strucmp(field, "fcc")){
12196
12315
                }
12197
12316
                else {
12198
12317
                    strcpy(err = tmp_20k_buf, "Unrecognized Fcc specification");
12199
 
                    return(peMsgCollected(interp, &md, err));
 
12318
                    return(peMsgCollected(interp, &md, err, flags));
12200
12319
                }
12201
12320
            }
12202
12321
            else if(!strucmp(field, "postoption")){
12213
12332
                        }
12214
12333
                        else{
12215
12334
                            sprintf(err = tmp_20k_buf, "Malformed Post Option: fcc-without-attachments");
12216
 
                            return(peMsgCollected(interp, &md, err));
 
12335
                            return(peMsgCollected(interp, &md, err, flags));
12217
12336
                        }
12218
12337
                    }
12219
12338
                    else if(!strucmp(value, "charset")){
12236
12355
                        }
12237
12356
                        else{
12238
12357
                            err = "Post option read failure";
12239
 
                            return(peMsgCollected(interp, &md, err));
 
12358
                            return(peMsgCollected(interp, &md, err, flags));
12240
12359
                        }
12241
12360
                    }
12242
12361
                    else if(!strucmp(value, "flowed")){
12247
12366
                            }
12248
12367
                            else{
12249
12368
                                err = "Post option read failure";
12250
 
                                return(peMsgCollected(interp, &md, err));
 
12369
                                return(peMsgCollected(interp, &md, err, flags));
12251
12370
                            }
12252
12371
                        }
12253
12372
                    }
12258
12377
                        }
12259
12378
                        else{
12260
12379
                            err = "Post option read failure";
12261
 
                            return(peMsgCollected(interp, &md, err));
 
12380
                            return(peMsgCollected(interp, &md, err, flags));
12262
12381
                        }
12263
12382
                    }
12264
12383
                    else if(!strucmp(value, "priority")){
12283
12402
                        }
12284
12403
                        else{
12285
12404
                            err = "Post option read failure";
12286
 
                            return(peMsgCollected(interp, &md, err));
 
12405
                            return(peMsgCollected(interp, &md, err, flags));
12287
12406
                        }
12288
12407
                    }
12289
12408
                    else{
12290
12409
                        sprintf(err = tmp_20k_buf, "Unknown Post Option: %s", value);
12291
 
                        return(peMsgCollected(interp, &md, err));
 
12410
                        return(peMsgCollected(interp, &md, err, flags));
12292
12411
                    }
12293
12412
                }
12294
12413
                else{
12295
12414
                    sprintf(err = tmp_20k_buf, "Malformed Post Option");
12296
 
                    return(peMsgCollected(interp, &md, err));
 
12415
                    return(peMsgCollected(interp, &md, err, flags));
12297
12416
                }
12298
12417
            }
12299
12418
            else {
12300
12419
                if(nField != 2){
12301
12420
                    sprintf(err = tmp_20k_buf, "Malformed header (%s)", field);
12302
 
                    return(peMsgCollected(interp, &md, err));
 
12421
                    return(peMsgCollected(interp, &md, err, flags));
12303
12422
                }
12304
12423
 
12305
12424
                if((value = Tcl_GetStringFromObj(objField[1], &vl)) != NULL){
12388
12507
                }
12389
12508
                else{
12390
12509
                    err = "Value read failure";
12391
 
                    return(peMsgCollected(interp, &md, err));
 
12510
                    return(peMsgCollected(interp, &md, err, flags));
12392
12511
                }
12393
12512
            }
12394
12513
        }
12395
12514
    }
12396
12515
 
12397
 
    return(peMsgCollected(interp, &md, err));
 
12516
    return(peMsgCollected(interp, &md, err, flags));
12398
12517
}
12399
12518
 
12400
12519
 
12402
12521
 * peMsgCollected - Dispatch collected message data and cleanup
12403
12522
 */
12404
12523
int
12405
 
peMsgCollected(Tcl_Interp *interp, MSG_COL_S *md, char *err) 
 
12524
peMsgCollected(Tcl_Interp *interp, MSG_COL_S *md, char *err, long flags) 
12406
12525
{
12407
 
    int        rv = TCL_OK;
12408
 
    BODY      *body = NULL, *tbp = NULL;
12409
 
    char       errbuf[WP_MAX_POST_ERROR + 1], *charset;
12410
 
    STRLIST_S *lp;
 
12526
    int            rv = TCL_OK, non_ascii = FALSE;
 
12527
    unsigned char  c;
 
12528
    BODY          *body = NULL, *tbp = NULL;
 
12529
    char           errbuf[WP_MAX_POST_ERROR + 1], *charset;
 
12530
    STRLIST_S     *lp;
12411
12531
 
12412
12532
    if(err){
12413
12533
        if(md->msgtext)
12420
12540
        rv = TCL_ERROR;
12421
12541
    }
12422
12542
    else{
12423
 
        /* put stuff to post here */
 
12543
        /* sniff body for possible multipart wrapping to protect encoding */
 
12544
        so_seek(md->msgtext, 0L, 0);
 
12545
 
 
12546
        while(so_readc(&c, md->msgtext))
 
12547
          if(!c || c & 0x80){
 
12548
              non_ascii = TRUE;
 
12549
              break;
 
12550
          }
12424
12551
 
12425
12552
        if(!md->outgoing->from)
12426
12553
          md->outgoing->from = generate_from();
12433
12560
        body = mail_newbody();
12434
12561
 
12435
12562
        /* wire any attachments to body */
12436
 
        if(md->attach){
 
12563
        if(md->attach || (non_ascii && F_OFF(F_COMPOSE_ALWAYS_DOWNGRADE, ps_global))){
12437
12564
            PART          **np;
12438
12565
            PARAMETER **pp;
12439
12566
            COMPATT_S  *a;
12529
12656
 
12530
12657
        /* assign MIME parameters to text body part */
12531
12658
        tbp->type = TYPETEXT;
12532
 
        if(md->html)
12533
 
          tbp->subtype = cpystr("HTML");
 
12659
        if(md->html) tbp->subtype = cpystr("HTML");
12534
12660
 
12535
12661
        tbp->contents.text.data = (void *) md->msgtext;
12536
 
 
12537
 
        /*
12538
 
         * set up text body part's charset
12539
 
         * if it came from compose form as something other
12540
 
         * than UTF-8, toss hands up into air, shrug shoulders.
12541
 
         */
12542
 
        charset = (!md->charset || !strucmp(md->charset, "utf-8")) ? "UTF-8" : "X-UNKNOWN";
12543
 
        peMsgSetParm(&tbp->parameter, "charset", charset);
12544
 
 
12545
 
        /* possibly up/downgrade charset, figure out c-t-e? */
12546
12662
        tbp->encoding = ENCOTHER;
12547
 
        set_mime_type_by_grope(tbp);
12548
 
        set_charset_possibly_to_ascii(tbp, charset);
12549
12663
 
12550
12664
        /* set any text flowed param */
12551
12665
        if(md->flowed)
12573
12687
            }
12574
12688
 
12575
12689
            if(rv == TCL_OK){
12576
 
                peFreeAttach(&peCompAttach);
 
12690
                if((flags & PMC_PRSRV_ATT) == 0)
 
12691
                  peFreeAttach(&peCompAttach);
12577
12692
            }
12578
12693
            else{
12579
12694
                /* maintain pointers to attachments */
13285
13400
 
13286
13401
                            if(completions){
13287
13402
                                for(cp = completions; cp; cp = cp->next)
13288
 
                                  peAppListF(interp, Tcl_GetObjResult(interp), "%s %s",
 
13403
                                  peAppListF(interp, Tcl_GetObjResult(interp), "%s %s %s",
13289
13404
                                             cp->nickname ? cp->nickname : "",
13290
 
                                             cp->full_address ? cp->full_address : "");
 
13405
                                             cp->full_address ? cp->full_address : "",
 
13406
                                             cp->fcc ? cp->fcc : "");
13291
13407
 
13292
13408
                                free_complete_s(&completions);
13293
13409
                            }
15855
15971
}
15856
15972
 
15857
15973
 
 
15974
void peNewMailAnnounce(MAILSTREAM *stream, long n, long t_nm_count){
 
15975
    char      subject[MAILTMPLEN+1], subjtext[MAILTMPLEN+1], from[MAILTMPLEN+1],
 
15976
             *folder = NULL, intro[MAILTMPLEN+1];
 
15977
    long      number;
 
15978
    ENVELOPE *e = NULL;
 
15979
    Tcl_Obj  *resObj;
 
15980
 
 
15981
    if(n && (resObj = Tcl_NewListObj(0, NULL)) != NULL){
 
15982
 
 
15983
        Tcl_ListObjAppendElement(peED.interp, resObj, Tcl_NewLongObj(number = sp_mail_since_cmd(stream)));
 
15984
        Tcl_ListObjAppendElement(peED.interp, resObj, Tcl_NewLongObj(mail_uid(stream, n)));
 
15985
 
 
15986
        if(stream){
 
15987
            e = pine_mail_fetchstructure(stream, n, NULL);
 
15988
 
 
15989
            if(sp_flagged(stream, SP_INBOX))
 
15990
              folder = NULL;
 
15991
            else{
 
15992
                folder = STREAMNAME(stream);
 
15993
                if(folder[0] == '?' && folder[1] == '\0')
 
15994
                  folder = NULL;
 
15995
            }
 
15996
        }
 
15997
 
 
15998
        format_new_mail_msg(folder, number, e, intro, from, subject, subjtext, sizeof(intro));
 
15999
 
 
16000
        snprintf(tmp_20k_buf, SIZEOF_20KBUF, 
 
16001
                 "%s%s%s%.80s%.80s", intro,
 
16002
                 from ? ((number > 1L) ? " Most recent f" : " F") : "",
 
16003
                 from ? "rom " : "",
 
16004
                 from ? from : "",
 
16005
                 subjtext);
 
16006
 
 
16007
        Tcl_ListObjAppendElement(peED.interp, resObj, Tcl_NewStringObj(tmp_20k_buf,-1));
 
16008
 
 
16009
        Tcl_ListObjAppendElement(peED.interp, Tcl_GetObjResult(peED.interp), resObj);
 
16010
    }
 
16011
}
 
16012
 
 
16013
 
15858
16014
/* * * * * * * * * RSS 2.0 Support Routines  * * * * * * * * * * * */
15859
16015
 
15860
16016
/*
15999
16155
{
16000
16156
    char          *scheme = NULL, *loc = NULL, *path = NULL, *parms = NULL, *query = NULL, *frag = NULL;
16001
16157
    char          *buffer = NULL, *bp, *p, *q;
 
16158
    int            ttl = 60;
16002
16159
    unsigned long  port = 0L, buffer_len = 0L;
 
16160
    time_t         theirdate = 0;
16003
16161
    STORE_S       *feed_so = NULL;
16004
16162
    TCPSTREAM     *tcp_stream;
16005
16163
 
16019
16177
                }
16020
16178
            }
16021
16179
 
 
16180
            if(scheme && !strucmp(scheme, "feed")){
 
16181
                fs_give((void **) &scheme);
 
16182
                scheme = cpystr("http");
 
16183
            }
 
16184
 
16022
16185
            mail_parameters(NULL, SET_OPENTIMEOUT, (void *)(long) 5);
16023
16186
            tcp_stream = tcp_open (loc, scheme, port | NET_NOOPENTIMEOUT);
16024
16187
            mail_parameters(NULL, SET_OPENTIMEOUT, (void *)(long) 30);
16031
16194
                         query ? "?" : "", query ? query : "", loc,
16032
16195
                         ALPINE_VERSION, SYSTYPE, get_alpine_revision_string(rev, sizeof(rev)));
16033
16196
 
 
16197
                mail_parameters(NULL, SET_WRITETIMEOUT, (void *)(long) 5);
16034
16198
                mail_parameters(NULL, SET_READTIMEOUT, (void *)(long) 5);
16035
16199
 
16036
16200
                if(tcp_sout(tcp_stream, tmp_20k_buf, strlen(tmp_20k_buf))){
16037
 
                    int ok = 0;
 
16201
                    int ok = 0, chunked = FALSE;
16038
16202
 
16039
16203
                    while((p = tcp_getline(tcp_stream)) != NULL){
16040
16204
                        if(!ok){
16041
16205
                            ok++;
16042
16206
                            if(strucmp(p,"HTTP/1.1 200 OK")){
16043
16207
                                fs_give((void **) &p);
16044
 
                                break;
 
16208
                                break;                  /* bail */
16045
16209
                            }
16046
16210
                        }
16047
 
                        else if(*p == '\0'){
 
16211
                        else if(*p == '\0'){            /* first blank line, start of body  */
 
16212
                            if(buffer || feed_so){
 
16213
                                fs_give((void **) &p);
 
16214
                                break;                  /* bail */
 
16215
                            }
 
16216
 
16048
16217
                            if(buffer_len){
16049
16218
                                buffer = fs_get(buffer_len + 16);
16050
16219
                                if(!tcp_getbuffer(tcp_stream, buffer_len, buffer))
16051
16220
                                  fs_give((void **) &buffer);
16052
16221
 
16053
16222
                                fs_give((void **) &p);
16054
 
                                break;
16055
 
                            }
16056
 
                            else{                       /* no content-length: */
16057
 
                                if((feed_so = so_get(CharStar, NULL, EDIT_ACCESS)) == NULL){
 
16223
                                break;                  /* bail */
 
16224
                            }
 
16225
                            else if((feed_so = so_get(CharStar, NULL, EDIT_ACCESS)) == NULL){
 
16226
                                fs_give((void **) &p);
 
16227
                                break;                  /* bail */
 
16228
                            }
 
16229
                        }
 
16230
                        else if(feed_so){               /* collect body */
 
16231
                            if(chunked){
 
16232
                                int chunk_len = 0, gotbuf;
 
16233
 
 
16234
                                /* first line is chunk size in hex */
 
16235
                                for(q = p; *q && isxdigit((unsigned char) *q); q++)
 
16236
                                  chunk_len = (chunk_len * 16) + XDIGIT2C(*q);
 
16237
 
 
16238
                                if(chunk_len > 0){      /* collect chunk */
 
16239
                                    char *tbuf = fs_get(chunk_len + 16);
 
16240
                                    gotbuf = tcp_getbuffer(tcp_stream, chunk_len, tbuf);
 
16241
                                    if(gotbuf)
 
16242
                                      so_nputs(feed_so, tbuf, chunk_len);
 
16243
 
 
16244
                                    fs_give((void **) &tbuf);
 
16245
 
 
16246
                                    if(!gotbuf){
 
16247
                                        fs_give((void **) &p);
 
16248
                                        break;          /* bail */
 
16249
                                    }
 
16250
                                }
 
16251
 
 
16252
                                /* collect trailing CRLF */
 
16253
                                gotbuf = ((q = tcp_getline(tcp_stream)) != NULL && *q == '\0');
 
16254
                                if(q)
 
16255
                                  fs_give((void **) &q);
 
16256
 
 
16257
                                if(chunk_len == 0 || !gotbuf){
16058
16258
                                    fs_give((void **) &p);
16059
 
                                    break;
 
16259
                                    break;              /* bail */
16060
16260
                                }
16061
16261
                            }
16062
 
                        }
16063
 
                        else if(feed_so){
16064
 
                            so_puts(feed_so, p);
16065
 
                        }
16066
 
                        else{
 
16262
                            else
 
16263
                              so_puts(feed_so, p);
 
16264
                        }
 
16265
                        else{                           /* in header, grok fields */
16067
16266
                            if(q = strchr(p,':')){
16068
16267
                                int l = q - p;
16069
16268
 
16072
16271
                                  q++;
16073
16272
 
16074
16273
                                /* content-length */
16075
 
                                if(l == 14 && !strucmp(p,"content-length")){
 
16274
                                if(l == 4 && !strucmp(p, "date")){
 
16275
                                    theirdate = date_to_local_time_t(q);
 
16276
                                }
 
16277
                                else if(l == 7 && !strucmp(p, "expires")){
 
16278
                                    time_t expires = date_to_local_time_t(q) - ((theirdate > 0) ? theirdate : time(0));
 
16279
 
 
16280
                                    if(expires > 0 && expires < (8 * 60 * 60))
 
16281
                                      ttl = expires;
 
16282
                                }
 
16283
                                else if(l == 12 && !strucmp(p, "content-type")
 
16284
                                        && struncmp(q,"text/xml", 8)
 
16285
                                        && struncmp(q,"application/xhtml+xml", 21)
 
16286
                                        && struncmp(q,"application/rss+xml", 19)
 
16287
                                        && struncmp(q,"application/xml", 15)){
 
16288
                                    fs_give((void **) &p);
 
16289
                                    break;              /* bail */
 
16290
                                }
 
16291
                                else if(l == 13 && !strucmp(p, "cache-control")){
 
16292
                                    if(!struncmp(q,"max-age=",8)){
 
16293
                                        int secs = 0;
 
16294
 
 
16295
                                        for(q += 8; *q && isdigit((unsigned char) *q); q++)
 
16296
                                          secs = ((secs * 10) + (*q - '0'));
 
16297
 
 
16298
                                        if(secs > 0)
 
16299
                                          ttl = secs;
 
16300
                                    }
 
16301
                                }
 
16302
                                else if(l == 14 && !strucmp(p,"content-length")){
16076
16303
                                    while(*q && isdigit((unsigned char) *q))
16077
16304
                                      buffer_len = ((buffer_len * 10) + (*q++ - '0'));
16078
16305
 
16079
 
                                    if(*q)
16080
 
                                      break;
16081
 
                                }
16082
 
                                else if(l == 12 && !strucmp(p, "content-type")
16083
 
                                        && strucmp(q,"text/xml")
16084
 
                                        && strucmp(q,"application/xhtml+xml")
16085
 
                                        && strucmp(q,"application/xml")){
16086
 
                                    break;
16087
 
                                }
16088
 
                                /* SHOULD: if(l == 7 && !strucmp(p, "expires")) */
 
16306
                                    if(*q){
 
16307
                                        fs_give((void **) &p);
 
16308
                                        break;          /* bail */
 
16309
                                    }
 
16310
                                }
 
16311
                                else if(l == 17 && !strucmp(p, "transfer-encoding")){
 
16312
                                    if(!struncmp(q,"chunked", 7)){
 
16313
                                        chunked = TRUE;
 
16314
                                    }
 
16315
                                    else{               /* unknown encoding */
 
16316
                                        fs_give((void **) &p);
 
16317
                                        break;          /* bail */
 
16318
                                    }
 
16319
                                }
16089
16320
                            }
16090
16321
                        }
16091
16322
 
16099
16330
 
16100
16331
                tcp_close(tcp_stream);
16101
16332
                mail_parameters(NULL, SET_READTIMEOUT, (void *)(long) 60);
 
16333
                mail_parameters(NULL, SET_WRITETIMEOUT, (void *)(long) 60);
16102
16334
                peRssComponentFree(&scheme,&loc,&path,&parms,&query,&frag);
16103
16335
 
16104
16336
                if(feed_so){
16106
16338
                    buffer_len = (int) so_tell(feed_so);
16107
16339
                }
16108
16340
 
16109
 
                if(buffer){
 
16341
                if(buffer && buffer_len){
16110
16342
                    RSS_FEED_S *feed;
16111
16343
                    char       *err;
16112
16344
                    STORE_S    *bucket;
16123
16355
                        Tcl_SetResult(interp, "RSS connection failure", TCL_STATIC);
16124
16356
                    }
16125
16357
 
 
16358
                    so_give(&bucket);
 
16359
 
16126
16360
                    if(feed_so)
16127
16361
                      so_give(&feed_so);
 
16362
                    else
 
16363
                      fs_give((void **) &buffer);
16128
16364
 
16129
 
                    so_give(&bucket);
16130
 
                    fs_give((void **) &buffer);
16131
16365
                    return(feed);
16132
16366
                }
16133
16367
                else