351
401
int peDetach(Tcl_Interp *, imapuid_t, int, Tcl_Obj **);
352
402
int peAttachInfo(Tcl_Interp *, imapuid_t, int, Tcl_Obj **);
353
403
int peSaveDefault(Tcl_Interp *, imapuid_t, int, Tcl_Obj **);
404
int peSaveWork(Tcl_Interp *, imapuid_t, int, Tcl_Obj **, long);
354
405
int peSave(Tcl_Interp *, imapuid_t, int, Tcl_Obj **);
406
int peCopy(Tcl_Interp *, imapuid_t, int, Tcl_Obj **);
407
int peMove(Tcl_Interp *, imapuid_t, int, Tcl_Obj **);
355
408
int peGotoDefault(Tcl_Interp *, imapuid_t, Tcl_Obj **);
356
409
int peTakeaddr(Tcl_Interp *, imapuid_t, int, Tcl_Obj **);
410
int peTakeFrom(Tcl_Interp *, imapuid_t, int, Tcl_Obj **);
411
int peAddSuggestedContactInfo(Tcl_Interp *, Tcl_Obj *, ADDRESS *);
357
412
int peReplyQuote(Tcl_Interp *, imapuid_t, int, Tcl_Obj **);
358
413
long peMessageNumber(imapuid_t);
359
414
long peSequenceNumber(imapuid_t);
360
415
int peMsgCollector(Tcl_Interp *, int, Tcl_Obj **,
361
int (*)(METAENV *, BODY *, char *, CONTEXT_S **, char *));
416
int (*)(METAENV *, BODY *, char *, CONTEXT_S **, char *), long);
362
417
int peMsgCollected(Tcl_Interp *, MSG_COL_S *, char *);
363
418
void peMsgSetParm(PARAMETER **, char *, char *);
364
419
Tcl_Obj *peMsgAttachCollector(Tcl_Interp *, BODY *);
4558
4738
err = "PEFolder: unread: Can't read collection ID";
4740
else if(objc == 5 && !strcmp(op, "empty")){
4744
* Returns: number of expunge messages
4746
* Arguments: <colnum> <folder> <what>
4747
* where <what> is either <uid>, 'selected', or 'all'
4750
MAILSTREAM *stream = NULL;
4753
int colid, i, our_stream = 0;
4754
long uid, raw, count = 0L;
4755
char *errstr = NULL, *what, *folder, *p, tmp[MAILTMPLEN];
4757
if(Tcl_GetIntFromObj(interp,objv[2],&colid) != TCL_ERROR){
4758
for(i = 0, cp = ps_global->context_list; cp ; i++, cp = cp->next)
4759
if(i == colid) break;
4763
if((folder = Tcl_GetStringFromObj(objv[3], NULL)) != NULL){
4764
if((what = Tcl_GetStringFromObj(objv[4], NULL)) != NULL){
4766
if(!((context_allowed(context_apply(tmp, cp, folder, sizeof(tmp)))
4767
&& (stream = same_stream_and_mailbox(tmp, ps_global->mail_stream)))
4768
|| (stream = same_stream_and_mailbox(tmp, sp_inbox_stream())))){
4772
stream = context_open(cp, NULL, folder, SP_USEPOOL | SP_TEMPUSE | OP_SHORTCACHE, &retflags);
4776
msgmap = sp_msgmap(stream);
4778
if(!strucmp(what, "all")){
4779
if(mn_get_total(msgmap)){
4780
agg_select_all(stream, msgmap, NULL, 1);
4781
errstr = peApplyFlag(stream, msgmap, 'd', 0, &count);
4783
(void) cmd_expunge_work(stream, msgmap);
4787
/* little complicated since we don't display deleted state and
4788
* don't want to expunge what's not intended.
4789
* remember what's deleted and restore state on the ones left
4790
* when we're done. shouldn't happen much.
4791
* NOTE: "uid" is NOT a UID in this loop
4793
for(uid = 1L; uid <= mn_get_total(msgmap); uid++){
4794
raw = mn_m2raw(msgmap, uid);
4795
if(!get_lflag(stream, msgmap, uid, MN_EXLD)
4796
&& (mc = mail_elt(stream, raw)) != NULL
4798
set_lflag(stream, msgmap, uid, MN_STMP, 1);
4799
mail_flag(stream, long2string(raw), "\\DELETED", 0L);
4802
set_lflag(stream, msgmap, uid, MN_STMP, 0);
4805
if(!strucmp(what,"selected")){
4806
if(any_lflagged(msgmap, MN_SLCT)){
4807
if(!(errstr = peApplyFlag(stream, msgmap, 'd', 0, &count)))
4808
(void) cmd_expunge_work(stream, msgmap);
4815
for(p = what; *p; p++)
4816
if(isdigit((unsigned char) *p)){
4817
uid = (uid * 10) + (*p - '0');
4820
errstr = "Invalid uid value";
4825
/* uid is a UID here */
4826
mail_flag(stream, long2string(uid), "\\DELETED", ST_SET | ST_UID);
4827
(void) cmd_expunge_work(stream, msgmap);
4832
/* restore deleted on what didn't get expunged */
4833
for(uid = 1L; uid <= mn_get_total(msgmap); uid++){
4834
raw = mn_m2raw(msgmap, uid);
4835
if(get_lflag(stream, msgmap, uid, MN_STMP)){
4836
set_lflag(stream, msgmap, uid, MN_STMP, 0);
4837
mail_flag(stream, long2string(raw), "\\DELETED", ST_SET);
4843
pine_mail_close(stream);
4846
errstr = "no stream";
4849
errstr = "Cannot get which ";
4852
errstr = "Cannot get folder";
4855
errstr = "Invalid collection";
4858
Tcl_SetResult(interp, errstr, TCL_VOLATILE);
4862
Tcl_SetResult(interp, long2string(count), TCL_VOLATILE);
4560
4865
else if(!strcmp(op, "export")){
4905
5212
return(TCL_OK);
4907
5214
else if(!strucmp(op, "create")){
4910
folder = Tcl_GetStringFromObj(objv[objc - 1], NULL);
4912
Tcl_SetResult(interp, "PEFolder create: Can't read folder", TCL_VOLATILE);
4916
if(PEFolderChange(interp, cp, objc - 4, objv + 3) == TCL_ERROR)
4919
ps_global->c_client_error[0] = ps_global->last_error[0] = '\0';
4922
if(!context_create(cp, NULL, folder)){
4924
Tcl_SetResult(interp, AUTH_FAILURE_STRING, TCL_VOLATILE);
4927
Tcl_SetResult(interp,
4928
(ps_global->last_error[0])
4929
? ps_global->last_error
4930
: (ps_global->c_client_error[0])
4931
? ps_global->c_client_error
4932
: "Unable to create folder",
5217
folder = Tcl_GetStringFromObj(objv[objc - 1], NULL);
5219
Tcl_SetResult(interp, "PEFolder create: Can't read folder", TCL_VOLATILE);
5223
if(PEFolderChange(interp, cp, objc - 4, objv + 3) == TCL_ERROR)
5226
ps_global->c_client_error[0] = ps_global->last_error[0] = '\0';
5227
pePrepareForAuthException();
5229
if(!context_create(cp, NULL, folder)){
5230
if((aes = peAuthException()) != NULL){
5231
Tcl_SetResult(interp, aes, TCL_VOLATILE);
5234
Tcl_SetResult(interp,
5235
(ps_global->last_error[0])
5236
? ps_global->last_error
5237
: (ps_global->c_client_error[0])
5238
? ps_global->c_client_error
5239
: "Unable to create folder",
5243
reset_context_folders(cp);
5247
Tcl_SetResult(interp, "OK", TCL_STATIC);
4935
5248
reset_context_folders(cp);
4938
Tcl_SetResult(interp, "OK", TCL_STATIC);
4939
reset_context_folders(cp);
4942
5251
else if(!strucmp(op, "delete")){
4944
MAILSTREAM *strm = NULL;
4946
folder = Tcl_GetStringFromObj(objv[objc - 1], NULL);
4948
Tcl_SetResult(interp, "PEFolder delete: Can't read folder", TCL_VOLATILE);
4952
if(PEFolderChange(interp, cp, objc - 4, objv + 3) == TCL_ERROR)
4955
ps_global->c_client_error[0] = ps_global->last_error[0] = '\0';
4959
/* close open folder, then delete */
4960
if((strm = context_already_open_stream(cp,folder,AOS_NONE)) != NULL
4961
&& strm == ps_global->mail_stream){
4962
do_broach_folder(ps_global->inbox_name,
4963
ps_global->context_list, NULL, DB_INBOXWOCNTXT);
4966
if(!context_delete(cp, NULL, folder)){
4968
Tcl_SetResult(interp, AUTH_FAILURE_STRING, TCL_VOLATILE);
5252
int fi, readonly, close_opened = 0;
5253
char *folder, *fnamep, *target = NULL, *aes;
5254
MAILSTREAM *del_stream = NULL, *strm = NULL;
5256
PINERC_S *prc = NULL;
5259
folder = Tcl_GetStringFromObj(objv[objc - 1], NULL);
5261
Tcl_SetResult(interp, "PEFolder delete: Can't read folder", TCL_VOLATILE);
5265
if(PEFolderChange(interp, cp, objc - 4, objv + 3) == TCL_ERROR)
5268
/* so we can check for folder's various properties */
5269
build_folder_list(NULL, cp, folder, NULL, BFL_NONE);
5271
ps_global->c_client_error[0] = ps_global->last_error[0] = '\0';
5273
pePrepareForAuthException();
5275
/* close open folder, then delete */
5277
if((fi = folder_index(folder, cp, FI_FOLDER)) < 0
5278
|| (fp = folder_entry(fi, FOLDERS(cp))) == NULL){
5279
Tcl_SetResult(interp, "Cannot find folder to delete", TCL_STATIC);
5280
reset_context_folders(cp);
5284
if(!((cp->use & CNTXT_INCMNG) && fp->name
5285
&& check_for_move_mbox(fp->name, NULL, 0, &target))){
5289
dprint((4, "=== delete_folder(%s) ===\n", folder ? folder : "?"));
5291
ew = config_containing_inc_fldr(fp);
5292
if(ps_global->restricted)
4971
Tcl_SetResult(interp,
4972
(ps_global->last_error[0])
4973
? ps_global->last_error
4974
: (ps_global->c_client_error[0])
4975
? ps_global->c_client_error
4976
: "Unable to delete folder",
5297
prc = ps_global->prc;
5300
prc = ps_global->post_prc;
5306
readonly = prc ? prc->readonly : 1;
5309
if(prc && prc->quit_to_edit && (cp->use & CNTXT_INCMNG)){
5310
Tcl_SetResult(interp, "Must Exit Alpine to Change Configuration", TCL_STATIC);
5311
reset_context_folders(cp);
5315
if(cp == ps_global->context_list
5316
&& !(cp->dir && cp->dir->ref)
5317
&& strucmp(folder, ps_global->inbox_name) == 0){
5318
Tcl_SetResult(interp, "Cannot delete special folder", TCL_STATIC);
5319
reset_context_folders(cp);
5322
else if(readonly && (cp->use & CNTXT_INCMNG)){
5323
Tcl_SetResult(interp, "Folder not in editable config file", TCL_STATIC);
5324
reset_context_folders(cp);
5328
&& (strm=context_already_open_stream(cp,fp->name,AOS_NONE)))
5331
&& (strm=context_already_open_stream(NULL,target,AOS_NONE)))){
5332
if(strm == ps_global->mail_stream)
5335
else if(fp->isdir || fp->isdual){ /* NO DELETE if directory isn't EMPTY */
5336
FDIR_S *fdirp = next_folder_dir(cp,folder,TRUE,NULL);
5341
else if(fp->hasnochildren)
5344
ret = folder_total(fdirp->folders) > 0;
5345
free_fdir(&fdirp, 1);
5349
Tcl_SetResult(interp, "Cannot delete non-empty directory", TCL_STATIC);
5350
reset_context_folders(cp);
5355
* Folder by the same name exist, so delete both...
5357
Tcl_SetResult(interp, "Cannot delete: folder is also a directory", TCL_STATIC);
5358
reset_context_folders(cp);
5364
if(cp->use & CNTXT_INCMNG){
5365
Tcl_SetResult(interp, "Cannot delete incoming folder", TCL_STATIC);
5366
reset_context_folders(cp);
5370
dprint((2,"deleting \"%s\" (%s) in context \"%s\"\n",
5371
fp->name ? fp->name : "?",
5372
fp->nickname ? fp->nickname : "",
5373
cp->context ? cp->context : "?"));
5376
* Close it, NULL the pointer, and let do_broach_folder fixup
5379
pine_mail_actually_close(strm);
5381
do_broach_folder(ps_global->inbox_name,
5382
ps_global->context_list,
5383
NULL, DB_INBOXWOCNTXT);
5388
* Use fp->name since "folder" may be a nickname...
5390
if(ps_global->mail_stream
5391
&& context_same_stream(cp, fp->name, ps_global->mail_stream))
5392
del_stream = ps_global->mail_stream;
5396
if(!context_delete(cp, del_stream, fnamep)){
5397
if((aes = peAuthException()) != NULL){
5398
Tcl_SetResult(interp, aes, TCL_VOLATILE);
5401
Tcl_SetResult(interp,
5402
(ps_global->last_error[0])
5403
? ps_global->last_error
5404
: (ps_global->c_client_error[0])
5405
? ps_global->c_client_error
5406
: "Unable to delete folder",
5410
reset_context_folders(cp);
5415
Tcl_SetResult(interp, "OK", TCL_STATIC);
4979
5416
reset_context_folders(cp);
4982
Tcl_SetResult(interp, "OK", TCL_STATIC);
4983
reset_context_folders(cp);
4987
5420
* must be at least 5 arguments for the next set of commands
5147
5583
Tcl_SetResult(interp, ps_global->last_error, TCL_VOLATILE);
5148
5584
return(TCL_OK);
5586
else if(!strcmp(op, "trashdeleted")){
5590
* Returns: OK after moving deleted messages to Trash and expunging
5596
char *streamstr = NULL, tmp[MAILTMPLEN];
5597
long n, tomove = 0L;
5599
if(objc == 3) streamstr = Tcl_GetStringFromObj(objv[2], NULL);
5601
|| (streamstr && (strcmp(streamstr, "current") == 0))){
5602
stream = ps_global->mail_stream;
5603
msgmap = sp_msgmap(stream);
5605
else if(streamstr && (strcmp(streamstr, "inbox") == 0)){
5606
stream = sp_inbox_stream();
5607
msgmap = sp_msgmap(stream);
5609
else return(TCL_ERROR);
5611
ps_global->last_error[0] = '\0';
5612
if(IS_NEWS(stream) && stream->rdonly){
5613
msgno_exclude_deleted(stream, msgmap);
5614
clear_index_cache(sp_inbox_stream(), 0);
5617
* This is kind of surprising at first. For most sort
5618
* orders, if the whole set is sorted, then any subset
5619
* is also sorted. Not so for OrderedSubject sort.
5620
* If you exclude the first message of a subject group
5621
* then you change the date that group is to be sorted on.
5623
if(mn_get_sort(msgmap) == SortSubject2)
5624
refresh_sort(ps_global->mail_stream, msgmap, FALSE);
5627
if(!(cp = default_save_context(ps_global->context_list)))
5628
cp = ps_global->context_list;
5630
/* copy to trash if we're not in trash */
5631
if(ps_global->VAR_TRASH_FOLDER
5632
&& ps_global->VAR_TRASH_FOLDER[0]
5633
&& context_allowed(context_apply(tmp, cp, ps_global->VAR_TRASH_FOLDER, sizeof(tmp)))
5634
&& !same_stream_and_mailbox(tmp, stream)){
5636
/* save real selected set, and */
5637
for(n = 1L; n <= mn_get_total(msgmap); n++){
5638
set_lflag(stream, msgmap, n, MN_STMP, get_lflag(stream, msgmap, n, MN_SLCT));
5639
/* select deleted */
5640
if(!get_lflag(stream, msgmap, n, MN_EXLD)
5641
&& (mc = mail_elt(stream, mn_m2raw(msgmap,n))) != NULL && mc->deleted){
5643
set_lflag(stream, msgmap, n, MN_SLCT, 1);
5646
set_lflag(stream, msgmap, n, MN_SLCT, 0);
5649
if(tomove && pseudo_selected(stream, msgmap)){
5651
/* save delted to Trash */
5652
n = save(ps_global, stream,
5653
cp, ps_global->VAR_TRASH_FOLDER,
5654
msgmap, SV_FOR_FILT | SV_FIX_DELS);
5656
/* then remove them */
5658
(void) cmd_expunge_work(stream, msgmap);
5661
restore_selected(msgmap);
5664
/* restore selected set */
5665
for(n = 1L; n <= mn_get_total(msgmap); n++)
5666
set_lflag(stream, msgmap, n, MN_SLCT,
5667
get_lflag(stream, msgmap, n, MN_STMP));
5671
Tcl_SetResult(interp, ps_global->last_error, TCL_VOLATILE);
5150
5674
else if(!strcmp(op, "nextvector")){
5151
5675
long msgno, count, countdown;
5152
5676
int i, aObjN = 0;
5412
5948
else if(!strcmp(op, "zoom")){
5413
5949
Tcl_SetResult(interp,
5414
long2string((any_lflagged(ps_global->msgmap, MN_HIDE) > 0L)
5415
? any_lflagged(ps_global->msgmap, MN_SLCT) : 0L),
5950
long2string((any_lflagged(sp_msgmap(ps_global->mail_stream), MN_HIDE) > 0L)
5951
? any_lflagged(sp_msgmap(ps_global->mail_stream), MN_SLCT) : 0L),
5955
else if(!strcmp(op, "focus")){
5956
Tcl_SetResult(interp,
5957
long2string((any_lflagged(sp_msgmap(ps_global->mail_stream), MN_HIDE) > 0L)
5958
? any_lflagged(sp_msgmap(ps_global->mail_stream), MN_SRCH) : 0L),
5417
5960
return(TCL_OK);
5419
5962
else if(!strcmp(op, "first")){
5420
if(any_lflagged(ps_global->msgmap, MN_HIDE)){
5963
if(any_lflagged(sp_msgmap(ps_global->mail_stream), MN_HIDE)){
5423
5966
for(n = 1L; n <= mn_get_total(sp_msgmap(ps_global->mail_stream)); n++)
5424
if(!get_lflag(ps_global->mail_stream, ps_global->msgmap, n, MN_HIDE)){
5967
if(!get_lflag(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), n, MN_HIDE)){
5425
5968
Tcl_SetResult(interp, long2string(n), TCL_VOLATILE);
5426
5969
return(TCL_OK);
5429
unzoom_index(ps_global, ps_global->mail_stream, ps_global->msgmap);
5972
unzoom_index(ps_global, ps_global->mail_stream, sp_msgmap(ps_global->mail_stream));
5433
5976
Tcl_SetResult(interp, int2string(1), TCL_VOLATILE);
5434
5977
return(TCL_OK);
5979
else if(!strucmp(op, "current")){
5981
unsigned long u = 0;
5988
* Returns: list of current msg {<sequence> <uid>}
5991
if(mn_total_cur(sp_msgmap(ps_global->mail_stream)) <= 0
5992
|| ((n = mn_get_cur(sp_msgmap(ps_global->mail_stream))) > 0
5993
&& (u = mail_uid(ps_global->mail_stream, mn_m2raw(sp_msgmap(ps_global->mail_stream), n))) > 0)){
5994
Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), Tcl_NewStringObj(long2string(n), -1));
5995
Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), Tcl_NewStringObj(ulong2string(u), -1));
5999
err = "Cannot get current";
5436
6001
else if(!strcmp(op, "last")){
5437
if(any_lflagged(ps_global->msgmap, MN_HIDE)){
6002
if(any_lflagged(sp_msgmap(ps_global->mail_stream), MN_HIDE)){
5440
6005
for(n = mn_get_total(sp_msgmap(ps_global->mail_stream)); n > 0L; n--)
5441
if(!get_lflag(ps_global->mail_stream, ps_global->msgmap, n, MN_HIDE)){
6006
if(!get_lflag(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), n, MN_HIDE)){
5442
6007
Tcl_SetResult(interp, long2string(n), TCL_VOLATILE);
5443
6008
return(TCL_OK);
5617
6182
if(Tcl_GetIntFromObj(interp, objv[2], &newstate) != TCL_ERROR){
5618
6183
if(newstate > 0){
5619
if(any_lflagged(ps_global->msgmap, MN_HIDE) != (mn_get_total(sp_msgmap(ps_global->mail_stream)) - (n = any_lflagged(ps_global->msgmap, MN_SLCT)))){
5620
zoom_index(ps_global, ps_global->mail_stream, ps_global->msgmap);
6184
if(any_lflagged(sp_msgmap(ps_global->mail_stream), MN_HIDE) != (mn_get_total(sp_msgmap(ps_global->mail_stream)) - (n = any_lflagged(sp_msgmap(ps_global->mail_stream), MN_SLCT)))){
6185
zoom_index(ps_global, ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), MN_SLCT);
5625
if(any_lflagged(ps_global->msgmap, MN_HIDE))
5626
unzoom_index(ps_global, ps_global->mail_stream, ps_global->msgmap);
6190
if(any_lflagged(sp_msgmap(ps_global->mail_stream), MN_HIDE))
6191
unzoom_index(ps_global, ps_global->mail_stream, sp_msgmap(ps_global->mail_stream));
6195
Tcl_SetResult(interp, long2string(zoomed), TCL_VOLATILE);
6198
else if(!strcmp(op, "focus")){
6200
long n, zoomed = 0L;
6205
* Set/clear HID bits of non MN_SRCH messages as requested.
6206
* PEMailbox [first | last | next] are senstive to MN_HIDE flag
6208
* ARGS: newstate - 1 or 0
6210
* Returns: count of zoomed messages
6213
if(Tcl_GetIntFromObj(interp, objv[2], &newstate) != TCL_ERROR){
6215
if(any_lflagged(sp_msgmap(ps_global->mail_stream), MN_HIDE) != (mn_get_total(sp_msgmap(ps_global->mail_stream)) - (n = any_lflagged(sp_msgmap(ps_global->mail_stream), MN_SRCH))))
6216
zoom_index(ps_global, ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), MN_SRCH);
6221
if(any_lflagged(sp_msgmap(ps_global->mail_stream), MN_HIDE))
6222
unzoom_index(ps_global, ps_global->mail_stream, sp_msgmap(ps_global->mail_stream));
5948
return(peSelectError(interp, subcmd));
5950
agg_select_all(ps_global->mail_stream, ps_global->msgmap, NULL, 1);
6551
if(matchflag & MN_SLCT){
6553
return(peSelectError(interp, subcmd));
6555
agg_select_all(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), NULL, 1);
6557
else if(matchflag & MN_SRCH){
6558
for(n = 1L; n <= ps_global->mail_stream->nmsgs; n++)
6559
set_lflag(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), n, matchflag, 1);
5951
6562
Tcl_SetResult(interp, "All", TCL_VOLATILE);
5953
6564
else if(!strucmp(subcmd, "none")){
5960
return(peSelectError(interp, subcmd));
5962
agg_select_all(ps_global->mail_stream, ps_global->msgmap, &n, 0);
6570
if(matchflag & MN_SLCT){
6572
return(peSelectError(interp, subcmd));
6574
agg_select_all(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), &n, 0);
6576
else if(matchflag & MN_SRCH){
6577
for(n = 1L; n <= ps_global->mail_stream->nmsgs; n++)
6578
set_lflag(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), n, matchflag, 0);
5963
6581
Tcl_SetResult(interp, long2string(n), TCL_VOLATILE);
6583
else if(!strucmp(subcmd, "searched")){
6587
for(n = 1L, i = 0; n <= ps_global->mail_stream->nmsgs; n++)
6588
if(get_lflag(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), n, MN_SRCH)){
6590
set_lflag(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), n, MN_SLCT, 1);
6593
Tcl_SetResult(interp, long2string(i), TCL_VOLATILE);
6595
else if(!strucmp(subcmd, "unsearched")){
6599
for(n = 1L, i = 0; n <= ps_global->mail_stream->nmsgs; n++)
6600
if(get_lflag(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), n, MN_SRCH)){
6602
set_lflag(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), n, MN_SLCT, 0);
6605
Tcl_SetResult(interp, long2string(i), TCL_VOLATILE);
5966
6608
if(!strucmp(subcmd, "narrow"))
5974
6616
return(peSelectError(interp, "missing subcommand"));
5976
6618
if(!strucmp(subcmd, "num")){
5978
* Args: [broad | narrow] firstnumber lastnumber
5981
long first = 0L, last = 0L, n;
5984
if(Tcl_GetLongFromObj(interp, objv[2], &first) == TCL_OK
5985
&& Tcl_GetLongFromObj(interp, objv[3], &last) == TCL_OK){
5986
if(last && last < first){
5992
if(first >= 1L && first <= mn_get_total(sp_msgmap(ps_global->mail_stream))){
5994
if(last >= 1L && last <= mn_get_total(sp_msgmap(ps_global->mail_stream))){
5995
for(n = first; n <= last; n++)
5996
mm_searched(ps_global->mail_stream,
5997
mn_m2raw(ps_global->msgmap, n));
6000
return(peSelectError(interp, "last out of range"));
6003
mm_searched(ps_global->mail_stream,
6004
mn_m2raw(ps_global->msgmap, first));
6008
return(peSelectError(interp, "first out of range"));
6011
return(peSelectError(interp, "can't read first/last"));
6014
return(peSelectError(interp, "num first last"));
6619
if((i = peSelectNumber(interp, objc - 2, &objv[2], matchflag)) != TCL_OK)
6016
6622
else if(!strucmp(subcmd, "date")){
6018
* Args: [broad | narrow]
6019
* tense - "on", "since", "before"
6020
* year - 4 digit year
6021
* month - abbreviated month "jan", "feb"...
6025
char *tense, *year, *month, *day, buf[256];
6028
if((tense = peSelValTense(objv[2])) != NULL){
6029
if((year = peSelValYear(objv[3])) != NULL){
6030
if((month = peSelValMonth(objv[4])) != NULL){
6031
if((day = peSelValDay(objv[5])) != NULL){
6032
snprintf(buf, sizeof(buf), "%s %s-%s-%s",
6033
tense, day, month, year);
6034
mail_search_full(ps_global->mail_stream, NULL,
6036
SE_NOPREFETCH | SE_FREE);
6039
return(peSelectError(interp, "<with valid day>"));
6042
return(peSelectError(interp, "<with valid month>"));
6045
return(peSelectError(interp, "<with valid year>"));
6048
return(peSelectError(interp, "<with valid tense>"));
6051
return(peSelectError(interp, "date tense year monthabbrev daynum"));
6623
if((i = peSelectDate(interp, objc - 2, &objv[2], matchflag)) != TCL_OK)
6053
6626
else if(!strucmp(subcmd, "text")){
6055
* Args: [broad | narrow]
6057
* field - to from cc recip partic subj any
6058
* text - free text search string
6064
if((not = peSelValCase(objv[2])) >= 0){
6065
if((field = peSelValField(objv[3])) != '\0'){
6066
if((text = Tcl_GetStringFromObj(objv[4], NULL))
6067
&& strlen(text) < 1024){
6068
/* BUG: fix charset not to be NULL below */
6069
if(agg_text_select(ps_global->mail_stream,
6071
field, not, 0, text, NULL, NULL))
6072
/* BUG: plug in "charset" above? */
6073
return(peSelectError(interp, "programmer botch"));
6076
return(peSelectError(interp, "<with search string < 1024>"));
6079
return(peSelectError(interp, "<with valid field>"));
6082
return(peSelectError(interp, "<with valid case>"));
6085
return(peSelectError(interp, "text case field text"));
6627
if((i = peSelectText(interp, objc - 2, &objv[2], matchflag)) != TCL_OK)
6087
6630
else if(!strucmp(subcmd, "status")){
6089
* Args: [broad | narrow]
6091
* status - imp new ans del
6098
if((not = peSelValCase(objv[2])) >= 0){
6099
if((flag = peSelValFlag(objv[3])) != '\0'){
6100
if(agg_flag_select(ps_global->mail_stream, not, flag, NULL))
6101
return(peSelectError(interp, "programmer botch"));
6631
if((i = peSelectStatus(interp, objc - 2, &objv[2], matchflag)) != TCL_OK)
6634
else if(!strucmp(subcmd, "compound")){
6636
int nSearchList, nSearch;
6637
Tcl_Obj **oSearchList, **oSearch;
6639
/* BUG: should set up one SEARCHPGM to fit criteria and issue single search */
6641
if(Tcl_ListObjGetElements(interp, objv[2], &nSearchList, &oSearchList) == TCL_OK){
6642
for(i = 0; i < nSearchList; i++){
6643
if(Tcl_ListObjGetElements(interp, oSearchList[i], &nSearch, &oSearch) == TCL_OK){
6644
if((s = Tcl_GetStringFromObj(oSearch[0], NULL)) != NULL){
6645
if(!strucmp(s,"date")){
6646
if((n = peSelectDate(interp, nSearch - 1, &oSearch[1], matchflag)) != TCL_OK)
6649
else if(!strucmp(s,"text")){
6650
if((n = peSelectText(interp, nSearch - 1, &oSearch[1], matchflag)) != TCL_OK)
6653
else if(!strucmp(s,"status")){
6654
if((n = peSelectStatus(interp, nSearch - 1, &oSearch[1], matchflag)) != TCL_OK)
6658
return(peSelectError(interp, "unknown compound search"));
6660
/* logical AND the results */
6661
mm_search_count = 0L;
6662
for(n = 1L; n <= ps_global->mail_stream->nmsgs; n++)
6663
if((mc = mail_elt(ps_global->mail_stream, n)) != NULL){
6664
if(mc->searched && mc->spare7)
6667
mc->searched = mc->spare7 = 0;
6671
return(peSelectError(interp, "malformed compound search"));
6104
return(peSelectError(interp, "<with valid flag>"));
6674
return(peSelectError(interp, "malformed compound search"));
6107
return(peSelectError(interp, "<with valid case>"));
6110
return(peSelectError(interp, "status focus case flag"));
6678
return(peSelectError(interp, "malformed compound search"));
6113
6681
return(peSelectError(interp, "cmd cmdargs"));
6136
6704
for(i = 1L, msgno = 0L; i <= mn_get_total(sp_msgmap(ps_global->mail_stream)); i++)
6138
6706
/* turning OFF selectedness if the "searched" bit isn't lit. */
6139
if(get_lflag(ps_global->mail_stream, ps_global->msgmap, i, MN_SLCT)){
6707
if(get_lflag(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), i, matchflag)){
6140
6708
if(!mail_elt(ps_global->mail_stream,
6141
mn_m2raw(ps_global->msgmap, i))->searched){
6709
mn_m2raw(sp_msgmap(ps_global->mail_stream), i))->searched){
6143
set_lflag(ps_global->mail_stream, ps_global->msgmap, i, MN_SLCT, 0);
6711
set_lflag(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), i, matchflag, 0);
6145
set_lflag(ps_global->mail_stream, ps_global->msgmap, i, MN_HIDE, 1);
6713
set_lflag(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), i, MN_HIDE, 1);
6147
else if(msgno < mn_get_cur(ps_global->msgmap))
6715
else if(msgno < mn_get_cur(sp_msgmap(ps_global->mail_stream)))
6151
else if(mail_elt(ps_global->mail_stream,mn_m2raw(ps_global->msgmap,i))->searched){
6719
else if(mail_elt(ps_global->mail_stream,mn_m2raw(sp_msgmap(ps_global->mail_stream),i))->searched){
6152
6720
/* turn ON selectedness if "searched" bit is lit. */
6153
if(!get_lflag(ps_global->mail_stream, ps_global->msgmap, i, MN_SLCT)){
6721
if(!get_lflag(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), i, matchflag)){
6155
set_lflag(ps_global->mail_stream, ps_global->msgmap, i, MN_SLCT, 1);
6723
set_lflag(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), i, matchflag, 1);
6157
set_lflag(ps_global->mail_stream, ps_global->msgmap, i, MN_HIDE, 0);
6725
set_lflag(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream), i, MN_HIDE, 0);
6161
6729
/* if we're zoomed and the current message was unselected */
6162
6730
if(narrow && msgno
6163
&& get_lflag(ps_global->mail_stream,ps_global->msgmap,mn_get_cur(ps_global->msgmap),MN_HIDE))
6164
mn_reset_cur(ps_global->msgmap, msgno);
6731
&& get_lflag(ps_global->mail_stream,sp_msgmap(ps_global->mail_stream),mn_get_cur(sp_msgmap(ps_global->mail_stream)),MN_HIDE))
6732
mn_reset_cur(sp_msgmap(ps_global->mail_stream), msgno);
6167
6735
Tcl_SetResult(interp, long2string(diff), TCL_VOLATILE);
6174
6742
return(TCL_ERROR);
6746
peSelectNumber(Tcl_Interp *interp, int objc, Tcl_Obj **objv, int matchflag)
6749
* Args: [broad | narrow] firstnumber lastnumber
6752
long first = 0L, last = 0L, n;
6755
if(Tcl_GetLongFromObj(interp, objv[0], &first) == TCL_OK
6756
&& Tcl_GetLongFromObj(interp, objv[1], &last) == TCL_OK){
6757
if(last && last < first){
6763
if(first >= 1L && first <= mn_get_total(sp_msgmap(ps_global->mail_stream))){
6765
if(last >= 1L && last <= mn_get_total(sp_msgmap(ps_global->mail_stream))){
6766
for(n = first; n <= last; n++)
6767
mm_searched(ps_global->mail_stream,
6768
mn_m2raw(sp_msgmap(ps_global->mail_stream), n));
6771
return(peSelectError(interp, "last out of range"));
6774
mm_searched(ps_global->mail_stream,
6775
mn_m2raw(sp_msgmap(ps_global->mail_stream), first));
6779
return(peSelectError(interp, "first out of range"));
6782
return(peSelectError(interp, "can't read first/last"));
6785
return(peSelectError(interp, "num first last"));
6791
peSelectDate(Tcl_Interp *interp, int objc, Tcl_Obj **objv, int matchflag)
6794
* Args: [broad | narrow]
6795
* tense - "on", "since", "before"
6796
* year - 4 digit year
6797
* month - abbreviated month "jan", "feb"...
6801
char *tense, *year, *month, *day, buf[256];
6804
if((tense = peSelValTense(objv[0])) != NULL){
6805
if((year = peSelValYear(objv[1])) != NULL){
6806
if((month = peSelValMonth(objv[2])) != NULL){
6807
if((day = peSelValDay(objv[3])) != NULL){
6808
snprintf(buf, sizeof(buf), "%s %s-%s-%s", tense, day, month, year);
6809
pine_mail_search_full(ps_global->mail_stream, NULL,
6811
SE_NOPREFETCH | SE_FREE);
6814
return(peSelectError(interp, "<with valid day>"));
6817
return(peSelectError(interp, "<with valid month>"));
6820
return(peSelectError(interp, "<with valid year>"));
6823
return(peSelectError(interp, "<with valid tense>"));
6826
return(peSelectError(interp, "date tense year monthabbrev daynum"));
6832
peSelectText(Tcl_Interp *interp, int objc, Tcl_Obj **objv, int matchflag)
6835
* Args: [broad | narrow]
6837
* field - to from cc recip partic subj any
6838
* text - free text search string
6844
if((not = peSelValCase(objv[0])) >= 0){
6845
if((field = peSelValField(objv[1])) != '\0'){
6846
if((text = Tcl_GetStringFromObj(objv[2], NULL))
6847
&& strlen(text) < 1024){
6848
/* BUG: fix charset not to be NULL below */
6849
if(agg_text_select(ps_global->mail_stream,
6850
sp_msgmap(ps_global->mail_stream),
6851
field, not, 0, text, NULL, NULL))
6852
/* BUG: plug in "charset" above? */
6853
return(peSelectError(interp, "programmer botch"));
6856
return(peSelectError(interp, "<with search string < 1024>"));
6859
return(peSelectError(interp, "<with valid field>"));
6862
return(peSelectError(interp, "<with valid case>"));
6865
return(peSelectError(interp, "text case field text"));
6871
peSelectStatus(Tcl_Interp *interp, int objc, Tcl_Obj **objv, int matchflag)
6874
* Args: [broad | narrow]
6876
* status - imp new ans del
6882
if((not = peSelValCase(objv[0])) >= 0){
6883
if((flag = peSelValFlag(objv[1])) != '\0'){
6884
if(agg_flag_select(ps_global->mail_stream, not, flag, NULL))
6885
return(peSelectError(interp, "programmer botch"));
6888
return(peSelectError(interp, "<with valid flag>"));
6891
return(peSelectError(interp, "<with valid case>"));
6894
return(peSelectError(interp, "status focus case flag"));
6179
6900
peSelValTense(Tcl_Obj *objp)
6408
7136
* folder - imp new ans del
6415
if(Tcl_GetIntFromObj(interp, objv[1], &colid) != TCL_ERROR){
6417
for(i = 0, cp = ps_global->context_list; cp ; i++, cp = cp->next)
6419
if((folder = Tcl_GetStringFromObj(objv[2], NULL)) != NULL){
6420
if(pseudo_selected(ps_global->msgmap)){
6422
del = (!READONLY_FOLDER(ps_global->mail_stream)
6423
&& F_OFF(F_SAVE_WONT_DELETE, ps_global));
6424
i = save(ps_global, ps_global->mail_stream,
6425
cp, folder, ps_global->msgmap, del);
6427
err = (i == mn_total_cur(ps_global->msgmap)) ? NULL : "problem saving";
6429
restore_selected(ps_global->msgmap);
6431
return(peApplyError(interp, err));
6433
Tcl_SetResult(interp, long2string(i), TCL_VOLATILE);
6437
return(peApplyError(interp, "can't select"));
6440
return(peApplyError(interp, "no folder name"));
6443
return(peApplyError(interp, "bad colid"));
6446
return(peApplyError(interp, "invalid case"));
7139
int colid, flgs = 0, i;
7143
if(Tcl_GetIntFromObj(interp, objv[1], &colid) != TCL_ERROR){
7145
for(i = 0, cp = ps_global->context_list; cp ; i++, cp = cp->next)
7147
if((folder = Tcl_GetStringFromObj(objv[2], NULL)) != NULL){
7148
if(pseudo_selected(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream))){
7150
if(!READONLY_FOLDER(ps_global->mail_stream)
7151
&& F_OFF(F_SAVE_WONT_DELETE, ps_global))
7154
if(colid == 0 && !strucmp(folder, "inbox"))
7155
flgs |= SV_INBOXWOCNTXT;
7157
i = save(ps_global, ps_global->mail_stream,
7158
cp, folder, sp_msgmap(ps_global->mail_stream), flgs);
7160
err = (i == mn_total_cur(sp_msgmap(ps_global->mail_stream))) ? NULL : "problem saving";
7162
restore_selected(sp_msgmap(ps_global->mail_stream));
7164
return(peApplyError(interp, err));
7166
Tcl_SetResult(interp, long2string(i), TCL_VOLATILE);
7170
return(peApplyError(interp, "can't select"));
7173
return(peApplyError(interp, "no folder name"));
7176
return(peApplyError(interp, "bad colid"));
7179
return(peApplyError(interp, "invalid case"));
7181
else if(!strucmp(subcmd, "copy")){
7184
* folder - imp new ans del
7187
int colid, flgs = 0, i;
7191
if(Tcl_GetIntFromObj(interp, objv[1], &colid) != TCL_ERROR){
7193
for(i = 0, cp = ps_global->context_list; cp ; i++, cp = cp->next)
7195
if((folder = Tcl_GetStringFromObj(objv[2], NULL)) != NULL){
7196
if(pseudo_selected(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream))){
7198
if(colid == 0 && !strucmp(folder, "inbox"))
7199
flgs |= SV_INBOXWOCNTXT;
7201
i = save(ps_global, ps_global->mail_stream,
7202
cp, folder, sp_msgmap(ps_global->mail_stream), flgs);
7204
err = (i == mn_total_cur(sp_msgmap(ps_global->mail_stream))) ? NULL : "problem copying";
7206
restore_selected(sp_msgmap(ps_global->mail_stream));
7208
return(peApplyError(interp, err));
7210
Tcl_SetResult(interp, long2string(i), TCL_VOLATILE);
7214
return(peApplyError(interp, "can't select"));
7217
return(peApplyError(interp, "no folder name"));
7220
return(peApplyError(interp, "bad colid"));
7223
return(peApplyError(interp, "invalid case"));
7225
else if(!strucmp(subcmd, "move")){
7228
* folder - imp new ans del
7231
int colid, flgs = 0, i;
7235
if(Tcl_GetIntFromObj(interp, objv[1], &colid) != TCL_ERROR){
7237
for(i = 0, cp = ps_global->context_list; cp ; i++, cp = cp->next)
7239
if((folder = Tcl_GetStringFromObj(objv[2], NULL)) != NULL){
7240
if(pseudo_selected(ps_global->mail_stream, sp_msgmap(ps_global->mail_stream))){
7244
if(colid == 0 && !strucmp(folder, "inbox"))
7245
flgs |= SV_INBOXWOCNTXT;
7247
i = save(ps_global, ps_global->mail_stream,
7248
cp, folder, sp_msgmap(ps_global->mail_stream), flgs);
7250
err = (i == mn_total_cur(sp_msgmap(ps_global->mail_stream))) ? NULL : "problem moving";
7252
restore_selected(sp_msgmap(ps_global->mail_stream));
7254
return(peApplyError(interp, err));
7256
Tcl_SetResult(interp, long2string(i), TCL_VOLATILE);
7260
return(peApplyError(interp, "can't select"));
7263
return(peApplyError(interp, "no folder name"));
7266
return(peApplyError(interp, "bad colid"));
7269
return(peApplyError(interp, "invalid case"));
7271
else if(!strucmp(subcmd, "spam")){
7276
char *spamaddr, *spamsubj = NULL;
7279
if((spamaddr = Tcl_GetStringFromObj(objv[1], NULL))
7280
&& (spamsubj = Tcl_GetStringFromObj(objv[2], NULL))){
7281
for(n = 1L; n <= mn_get_total(sp_msgmap(ps_global->mail_stream)); n++){
7282
rawno = mn_m2raw(sp_msgmap(ps_global->mail_stream), n);
7283
if(get_lflag(ps_global->mail_stream, NULL, rawno, MN_SLCT)){
7284
char errbuf[WP_MAX_POST_ERROR + 1], *rs = NULL;
7286
if((rs = peSendSpamReport(rawno, spamaddr, spamsubj, errbuf)) != NULL){
7287
Tcl_SetResult(interp, rs, TCL_VOLATILE);
7294
Tcl_SetResult(interp, "OK", TCL_VOLATILE);
6822
7739
{"attachinfo", 1, {{4, peAttachInfo}}},
6823
7740
{"savedefault", 1, {{3, peSaveDefault}}},
6824
7741
{"save", 1, {{5, peSave}}},
7742
{"copy", 1, {{5, peCopy}}},
7743
{"move", 1, {{5, peMove}}},
6825
7744
{"takeaddr", 1, {{3, peTakeaddr}}},
7745
{"takefrom", 1, {{3, peTakeFrom}}},
6826
7746
{"replyquote", 1, {{3, peReplyQuote}}},
6827
7747
{"bounce", 2, {{4, peMessageBounce},{5, peMessageBounce}}},
6828
{"spam", 2, {{4, peMessageSpam}, {5, peMessageSpam}}},
6829
{"trash", 2, {{4, peMessageTrash}, {5, peMessageTrash}}},
7748
{"spam", 1, {{5, peMessageSpamNotice}}},
7749
{"needpasswd", 1, {{3, peMessageNeedPassphrase}}},
9121
peSave(Tcl_Interp *interp, imapuid_t uid, int objc, Tcl_Obj **objv)
10089
peSaveWork(Tcl_Interp *interp, imapuid_t uid, int objc, Tcl_Obj **objv, long sflags)
10091
int flgs = 0, i, colid;
9124
10092
char *folder, *err = NULL;
9125
10093
CONTEXT_S *cp;
9127
10095
if(Tcl_GetIntFromObj(interp, objv[0], &colid) != TCL_ERROR){
9128
10096
if((folder = Tcl_GetStringFromObj(objv[1], NULL)) != NULL){
9129
mn_set_cur(ps_global->msgmap, peMessageNumber(uid));
10097
mn_set_cur(sp_msgmap(ps_global->mail_stream), peMessageNumber(uid));
9130
10098
for(i = 0, cp = ps_global->context_list; cp ; i++, cp = cp->next)
9132
if(!READONLY_FOLDER(ps_global->mail_stream)
9133
&& F_OFF(F_SAVE_WONT_DELETE, ps_global))
9136
i = save(ps_global, ps_global->mail_stream,
9137
cp, folder, ps_global->msgmap, flgs);
9139
if(i == mn_total_cur(ps_global->msgmap)){
9140
if(mn_total_cur(ps_global->msgmap) <= 1L){
9141
if(ps_global->context_list->next
9142
&& context_isambig(folder)){
9143
char *tag = (cp->nickname && strlen(cp->nickname)) ? cp->nickname : (cp->label && strlen(cp->label)) ? cp->label : "Folders";
9144
snprintf(tmp_20k_buf, SIZEOF_20KBUF,
9145
"Message %s copied to \"%.15s%s\" in <%.15s%s>",
9146
long2string(mn_get_cur(ps_global->msgmap)), folder,
9147
(strlen(folder) > 15) ? "..." : "",
9149
(strlen(tag) > 15) ? "..." : "");
9152
snprintf(tmp_20k_buf, SIZEOF_20KBUF,
9153
"Message %s copied to folder \"%.27s%s\"",
9154
long2string(mn_get_cur(ps_global->msgmap)), folder,
9155
(strlen(folder) > 27) ? "..." : "");
9158
snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s messages saved",
9159
comatose(mn_total_cur(ps_global->msgmap)));
9161
if(flgs & SV_DELETE){
9162
strncat(tmp_20k_buf, " and deleted", SIZEOF_20KBUF-strlen(tmp_20k_buf)-1);
9163
tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
9166
q_status_message(SM_ORDER, 0, 3, tmp_20k_buf);
9170
err = ps_global->last_error;
10103
if(!READONLY_FOLDER(ps_global->mail_stream)
10104
&& (sflags & PSW_COPY) != PSW_COPY
10105
&& ((sflags & PSW_MOVE) == PSW_MOVE || F_OFF(F_SAVE_WONT_DELETE, ps_global)))
10108
if(colid == 0 && !strucmp(folder, "inbox"))
10109
flgs |= SV_INBOXWOCNTXT;
10111
if(sflags & (PSW_COPY | PSW_MOVE))
10112
flgs |= SV_FIX_DELS;
10114
i = save(ps_global, ps_global->mail_stream,
10115
cp, folder, sp_msgmap(ps_global->mail_stream), flgs);
10117
if(i == mn_total_cur(sp_msgmap(ps_global->mail_stream))){
10118
if(mn_total_cur(sp_msgmap(ps_global->mail_stream)) <= 1L){
10119
if(ps_global->context_list->next
10120
&& context_isambig(folder)){
10121
char *tag = (cp->nickname && strlen(cp->nickname)) ? cp->nickname : (cp->label && strlen(cp->label)) ? cp->label : "Folders";
10122
snprintf(tmp_20k_buf, SIZEOF_20KBUF,
10123
"Message %s %s to \"%.15s%s\" in <%.15s%s>",
10124
long2string(mn_get_cur(sp_msgmap(ps_global->mail_stream))),
10125
(sflags & PSW_MOVE) ? "moved" : "copied",
10127
(strlen(folder) > 15) ? "..." : "",
10129
(strlen(tag) > 15) ? "..." : "");
10132
snprintf(tmp_20k_buf, SIZEOF_20KBUF,
10133
"Message %s %s to folder \"%.27s%s\"",
10134
long2string(mn_get_cur(sp_msgmap(ps_global->mail_stream))),
10135
(sflags & PSW_MOVE) ? "moved" : "copied",
10137
(strlen(folder) > 27) ? "..." : "");
10140
/* with mn_set_cur above, this *should not* happen */
10141
Tcl_SetResult(interp, "TOO MANY MESSAGES COPIED", TCL_VOLATILE);
10145
if(sflags == PSW_NONE && (flgs & SV_DELETE)){
10146
strncat(tmp_20k_buf, " and deleted", SIZEOF_20KBUF-strlen(tmp_20k_buf)-1);
10147
tmp_20k_buf[SIZEOF_20KBUF-1] = '\0';
10150
q_status_message(SM_ORDER, 0, 3, tmp_20k_buf);
10154
err = ps_global->last_error;
9174
10157
err = "open: Unrecognized collection ID";
9183
10166
return(TCL_ERROR);
10170
* peSave - Save message with given UID in current folder to
10171
* specified collection/folder
10173
* Params: argv[0] == destination context number
10174
* argv[1] == testination foldername
10176
* NOTE: just a wrapper around peSaveWork
10179
peSave(Tcl_Interp *interp, imapuid_t uid, int objc, Tcl_Obj **objv)
10181
return(peSaveWork(interp, uid, objc, objv, PSW_NONE));
10186
* peCopy - Copy message with given UID in current folder to
10187
* specified collection/folder
10189
* Params: argv[0] == destination context number
10190
* argv[1] == testination foldername
10192
* NOTE: just a wrapper around peSaveWork that makes sure
10193
* delete-on-save is NOT set
10196
peCopy(Tcl_Interp *interp, imapuid_t uid, int objc, Tcl_Obj **objv)
10198
return(peSaveWork(interp, uid, objc, objv, PSW_COPY));
10203
* peMove - Move message with given UID in current folder to
10204
* specified collection/folder
10206
* Params: argv[0] == destination context number
10207
* argv[1] == testination foldername
10209
* NOTE: just a wrapper around peSaveWork that makes sure
10210
* delete-on-save IS set so it can be expunged
10213
peMove(Tcl_Interp *interp, imapuid_t uid, int objc, Tcl_Obj **objv)
10215
return(peSaveWork(interp, uid, objc, objv, PSW_MOVE));
9188
10220
* peGotoDefault - Default Goto command file name for the given message
9991
11056
static char *fakedomain = "@";
9992
11057
void *msgtext;
9995
rawno = peSequenceNumber(uid);
9997
if(objc > 0 && objv[0] && (to = Tcl_GetStringFromObj(objv[0], NULL)) && strlen(to)){
9998
if((env = mail_fetchstructure(ps_global->mail_stream, rawno, NULL)) == NULL){
9999
Tcl_SetResult(interp, ps_global->last_error, TCL_VOLATILE);
10003
/* empty subject gets "spam" subject */
10004
if(!(objc == 2 && objv[1]
10005
&& (subj = Tcl_GetStringFromObj(objv[1], NULL)) != NULL
10007
subj = env->subject;
10009
/*---- New Body to start with ----*/
10010
body = mail_newbody();
10011
body->type = TYPEMULTIPART;
10013
/*---- The TEXT part/body ----*/
10014
body->nested.part = mail_newbody_part();
10015
body->nested.part->body.type = TYPETEXT;
10017
if((msgtext = (void *)so_get(CharStar, NULL, EDIT_ACCESS)) == NULL){
10018
pine_free_body(&body);
10019
Tcl_SetResult(interp, "peMessageSpam: Can't allocate text", TCL_VOLATILE);
10023
sprintf(tmp_20k_buf,
10024
"The attached message is being reported to <%s> as Spam\n",
10026
so_puts((STORE_S *) msgtext, tmp_20k_buf);
10027
body->nested.part->body.contents.text.data = msgtext;
10030
/*---- Attach the raw message ----*/
10031
if(forward_mime_msg(ps_global->mail_stream, rawno, NULL, env,
10032
&(body->nested.part->next), msgtext)){
10033
outgoing = mail_newenvelope();
10034
metaenv = pine_new_env(outgoing, NULL, NULL, custom = peCustomHdrs());
10037
pine_free_body(&body);
10038
Tcl_SetResult(interp, "peMessageSpam: Can't generate forwarded message", TCL_VOLATILE);
10042
/* rfc822_parse_adrlist feels free to destroy input so copy */
10043
tmp_a_string = cpystr(to);
10044
rfc822_parse_adrlist(&outgoing->to, tmp_a_string,
10045
(F_ON(F_COMPOSE_REJECTS_UNQUAL, ps_global))
10046
? fakedomain : ps_global->maildomain);
10047
fs_give((void **) &tmp_a_string);
10049
outgoing->from = generate_from();
10050
outgoing->subject = cpystr(subj);
10051
outgoing->return_path = rfc822_cpy_adr(outgoing->from);
10052
outgoing->message_id = generate_message_id();
10054
rfc822_date(tmp_20k_buf);
10055
outgoing->date = (unsigned char *) cpystr(tmp_20k_buf);
10057
/* NO FCC for Spam Reporting */
10059
if(peDoPost(metaenv, body, NULL, NULL, errbuf) != TCL_OK)
10062
pine_free_body(&body);
10064
pine_free_env(&metaenv);
10067
free_customs(custom);
10069
mail_free_envelope(&outgoing);
10070
pine_free_body(&body);
10075
Tcl_SetResult(interp, (errstr) ? errstr : "OK", TCL_VOLATILE);
10076
return(errstr ? TCL_ERROR : TCL_OK);
10081
peMessageTrash(Tcl_Interp *interp, imapuid_t uid, int objc, Tcl_Obj **objv)
10083
Tcl_SetResult(interp, "OK", TCL_VOLATILE);
11060
if((env = mail_fetchstructure(ps_global->mail_stream, rawno, NULL)) == NULL){
11061
return(ps_global->last_error);
11064
/* empty subject gets "spam" subject */
11065
if(!(subj && *subj))
11066
subj = env->subject;
11068
/*---- New Body to start with ----*/
11069
body = mail_newbody();
11070
body->type = TYPEMULTIPART;
11072
/*---- The TEXT part/body ----*/
11073
body->nested.part = mail_newbody_part();
11074
body->nested.part->body.type = TYPETEXT;
11076
if((msgtext = (void *)so_get(CharStar, NULL, EDIT_ACCESS)) == NULL){
11077
pine_free_body(&body);
11078
return("peSendSpamReport: Can't allocate text");
11081
sprintf(tmp_20k_buf,
11082
"The attached message is being reported to <%s> as Spam\n",
11084
so_puts((STORE_S *) msgtext, tmp_20k_buf);
11085
body->nested.part->body.contents.text.data = msgtext;
11088
/*---- Attach the raw message ----*/
11089
if(forward_mime_msg(ps_global->mail_stream, rawno, NULL, env,
11090
&(body->nested.part->next), msgtext)){
11091
outgoing = mail_newenvelope();
11092
metaenv = pine_new_env(outgoing, NULL, NULL, custom = peCustomHdrs());
11095
pine_free_body(&body);
11096
return("peSendSpamReport: Can't generate forwarded message");
11099
/* rfc822_parse_adrlist feels free to destroy input so copy */
11100
tmp_a_string = cpystr(to);
11101
rfc822_parse_adrlist(&outgoing->to, tmp_a_string,
11102
(F_ON(F_COMPOSE_REJECTS_UNQUAL, ps_global))
11103
? fakedomain : ps_global->maildomain);
11104
fs_give((void **) &tmp_a_string);
11106
outgoing->from = generate_from();
11107
outgoing->subject = cpystr(subj);
11108
outgoing->return_path = rfc822_cpy_adr(outgoing->from);
11109
outgoing->message_id = generate_message_id();
11111
rfc822_date(tmp_20k_buf);
11112
outgoing->date = (unsigned char *) cpystr(tmp_20k_buf);
11114
/* NO FCC for Spam Reporting */
11116
if(peDoPost(metaenv, body, NULL, NULL, errbuf) != TCL_OK)
11119
pine_free_body(&body);
11121
pine_free_env(&metaenv);
11124
free_customs(custom);
11126
mail_free_envelope(&outgoing);
11127
pine_free_body(&body);
10233
11282
Tcl_SetResult(interp, tmp_20k_buf, TCL_VOLATILE);
10234
11283
return(TCL_OK);
11285
else if(!strcmp(s1, "attachments")){
11287
Tcl_Obj *objAttach;
11289
for(p = peCompAttach; p; p = p->next)
11291
objAttach = Tcl_NewListObj(0, NULL);
11294
Tcl_ListObjAppendElement(interp, objAttach, Tcl_NewStringObj(p->id,-1));
11297
Tcl_ListObjAppendElement(interp, objAttach, Tcl_NewStringObj(p->l.f.remote,-1));
11300
Tcl_ListObjAppendElement(interp, objAttach, Tcl_NewLongObj(p->l.f.size));
11303
snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/%s", p->l.f.type, p->l.f.subtype);
11304
Tcl_ListObjAppendElement(interp, objAttach, Tcl_NewStringObj(tmp_20k_buf,-1));
11306
/* append to list */
11307
Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), objAttach);
11312
objAttach = Tcl_NewListObj(0, NULL);
11315
Tcl_ListObjAppendElement(interp, objAttach, Tcl_NewStringObj(p->id,-1));
11318
if((name = get_filename_parameter(NULL, 0, p->l.b.body, NULL)) != NULL){
11319
Tcl_ListObjAppendElement(interp, objAttach, Tcl_NewStringObj(name, -1));
11320
fs_give((void **) &name);
11323
Tcl_ListObjAppendElement(interp, objAttach, Tcl_NewStringObj("Unknown", -1));
11326
Tcl_ListObjAppendElement(interp, objAttach,
11327
Tcl_NewLongObj((p->l.b.body->encoding == ENCBASE64)
11328
? ((p->l.b.body->size.bytes * 3)/4)
11329
: p->l.b.body->size.bytes));
11332
snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s/%s",
11333
body_type_names(p->l.b.body->type),
11334
p->l.b.body->subtype ? p->l.b.body->subtype : "Unknown");
11335
Tcl_ListObjAppendElement(interp, objAttach, Tcl_NewStringObj(tmp_20k_buf, -1));
11337
Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), objAttach);
10237
11343
else if(objc == 3){
10238
11344
if(!strcmp(s1, "unattach")){
10633
11736
char *s1 = Tcl_GetStringFromObj(objv[1], NULL);
10637
if(!strcmp(s1, "any")){
10638
MAILSTREAM *stream;
10640
if(postponed_stream(&stream, ps_global->VAR_POSTPONED_FOLDER, "Postponed", 0) && stream){
10641
Tcl_SetResult(interp, "1", TCL_STATIC);
10643
if(stream != ps_global->mail_stream)
10644
pine_mail_close(stream);
10647
Tcl_SetResult(interp, "0", TCL_STATIC);
10651
else if(!strcmp(s1, "count")){
10652
MAILSTREAM *stream;
10654
if(postponed_stream(&stream, ps_global->VAR_POSTPONED_FOLDER, "Postponed", 0) && stream){
10655
Tcl_SetResult(interp, Tcl_NewLongObj(stream->nmsgs), TCL_STATIC);
10657
if(stream != ps_global->mail_stream)
10658
pine_mail_close(stream);
10661
Tcl_SetResult(interp, "-1", TCL_STATIC);
10665
else if(!strcmp(s1, "list")){
10666
MAILSTREAM *stream;
10668
Tcl_Obj *objEnv = NULL, *objEnvList;
11739
if(!strcmp(s1, "extract")){
11740
if(Tcl_GetLongFromObj(interp, objv[2], &uid) == TCL_OK){
11741
Tcl_Obj *objHdr = NULL, *objBod = NULL, *objAttach = NULL, *objOpts = NULL;
11742
MAILSTREAM *stream;
11744
ENVELOPE *env = NULL;
11745
PINEFIELD *custom = NULL, *cp;
11746
REPLY_S *reply = NULL;
11747
ACTION_S *role = NULL;
10671
if(postponed_stream(&stream, ps_global->VAR_POSTPONED_FOLDER, "Postponed", 0) && stream){
10672
if(!stream->nmsgs){
10673
(void) redraft_cleanup(&stream, FALSE, REDRAFT_PPND);
10674
Tcl_SetResult(interp, "", TCL_STATIC);
10678
objEnvList = Tcl_NewListObj(0, NULL);
10680
for(n = 1; n <= stream->nmsgs; n++){
10681
if((env = pine_mail_fetchstructure(stream, n, NULL)) != NULL){
10682
objEnv = Tcl_NewListObj(0, NULL);
10684
peAppListF(interp, objEnv, "%s%s", "uid",
10685
ulong2string(mail_uid(stream, n)));
10687
peAppListF(interp, objEnv, "%s%a", "to", env->to);
10689
date_str((char *)env->date, iSDate, 1, tmp_20k_buf, SIZEOF_20KBUF, 0);
10691
peAppListF(interp, objEnv, "%s%s", "date", tmp_20k_buf);
10693
peAppListF(interp, objEnv, "%s%s", "subj",
10694
rfc1522_decode_to_utf8((unsigned char *) tmp_20k_buf,
10695
SIZEOF_20KBUF, env->subject));
10697
Tcl_ListObjAppendElement(interp, objEnvList, objEnv);
11751
char *fcc = NULL, *lcc = NULL;
11752
unsigned flags = REDRAFT_DEL | REDRAFT_PPND;
11754
if(objc > 3){ /* optional flags */
11756
Tcl_Obj **objFlags;
11759
Tcl_ListObjGetElements(interp, objv[3], &nFlags, &objFlags);
11760
for(i = 0; i < nFlags; i++){
11761
if((flagstr = Tcl_GetStringFromObj(objFlags[i], NULL)) == NULL){
11765
if(!strucmp(flagstr, "html"))
11766
flags |= REDRAFT_HTML;
10701
Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), objEnvList);
10703
Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
10704
Tcl_NewStringObj("utf-8", -1));
10706
if(stream != ps_global->mail_stream)
10707
pine_mail_close(stream);
10713
else if(objc == 3){
10714
if(!strcmp(s1, "extract")){
10715
if(Tcl_GetLongFromObj(interp, objv[2], &uid) == TCL_OK){
10716
Tcl_Obj *objHdr = NULL, *objBod = NULL, *objAttach = NULL, *objOpts = NULL;
10717
MAILSTREAM *stream;
10719
ENVELOPE *env = NULL;
10720
PINEFIELD *custom = NULL, *cp;
10721
REPLY_S *reply = NULL;
10722
ACTION_S *role = NULL;
10728
if(postponed_stream(&stream, ps_global->VAR_POSTPONED_FOLDER, "Postponed", 0) && stream){
10729
if((so = so_get(CharStar, NULL, EDIT_ACCESS)) != NULL){
10730
if(((n = mail_msgno(stream, uid)) > 0L
10731
&& redraft_work(&stream, n, &env, &b, &fcc, &lcc, &reply,
10732
NULL, &custom, &role, /* should role be NULL? */
10733
REDRAFT_DEL | REDRAFT_PPND, so))){
11769
/* BUG: should probably complain if argc > 4 */
11772
&& postponed_stream(&stream, ps_global->VAR_POSTPONED_FOLDER, "Postponed", 0)
11774
if((so = so_get(CharStar, NULL, EDIT_ACCESS)) != NULL){
11775
if((n = mail_msgno(stream, uid)) > 0L){
11776
if(redraft_work(&stream, n, &env, &b, &fcc, &lcc, &reply,
11777
NULL, &custom, &role, /* should role be NULL? */
10734
11779
char *charset = NULL;
10736
11781
/* prepare to package up for caller */
10737
11782
objHdr = Tcl_NewListObj(0, NULL);
10739
11784
/* determine body part's charset */
10740
if((charset = rfc2231_get_param(b->parameter,"charset",NULL,NULL)) != NULL){
11785
if((charset = parameter_val(b->parameter,"charset")) != NULL){
10741
11786
objOpts = Tcl_NewListObj(0, NULL);
10742
11787
peAppListF(interp, objOpts, "%s%s", "charset", charset);
10743
11788
fs_give((void **) &charset);
11791
/* body part's MIME subtype */
11792
if(b->subtype && strucmp(b->subtype,"plain")){
11794
objOpts = Tcl_NewListObj(0, NULL);
11796
peAppListF(interp, objOpts, "%s%s", "subtype", b->subtype);
10746
11799
peAppListF(interp, objHdr, "%s%a", "from",
10747
role && role->from ? role->from : env->from);
11800
role && role->from ? role->from : env->from);
10748
11801
peAppListF(interp, objHdr, "%s%a", "to", env->to);
10749
11802
peAppListF(interp, objHdr, "%s%a", "cc", env->cc);
10750
11803
peAppListF(interp, objHdr, "%s%a", "bcc", env->bcc);
10837
11890
pine_free_body(&b);
10838
11891
free_action(&role);
11893
/* if Drafts got whacked, open INBOX */
11894
if(!ps_global->mail_stream)
11895
do_broach_folder(ps_global->inbox_name,
11896
ps_global->context_list,
11897
NULL, DB_INBOXWOCNTXT);
10840
11899
return(TCL_OK);
10843
11902
so_give(&so);
10846
err = "No internal storage";
10848
/* redraft_work cleaned up the "stream" */
10851
err = "No Postponed stream";
10854
err = "Malformed extract request";
10856
else if(!strcmp(s1, "append")){
10857
return(peMsgCollector(interp, objc - 2, (Tcl_Obj **) &objv[2], peDoPostpone));
11905
err = "Unknown UID";
11908
err = "No internal storage";
11910
/* redraft_work cleaned up the "stream" */
11913
err = "No Postponed stream";
11916
err = "Malformed extract request";
11918
else if(objc == 2){
11919
if(!strcmp(s1, "any")){
11920
MAILSTREAM *stream;
11922
if(postponed_stream(&stream, ps_global->VAR_POSTPONED_FOLDER, "Postponed", 0) && stream){
11923
Tcl_SetResult(interp, "1", TCL_STATIC);
11925
if(stream != ps_global->mail_stream)
11926
pine_mail_close(stream);
11929
Tcl_SetResult(interp, "0", TCL_STATIC);
11933
else if(!strcmp(s1, "count")){
11934
MAILSTREAM *stream;
11936
if(postponed_stream(&stream, ps_global->VAR_POSTPONED_FOLDER, "Postponed", 0) && stream){
11937
Tcl_SetResult(interp, long2string(stream->nmsgs), TCL_STATIC);
11939
if(stream != ps_global->mail_stream)
11940
pine_mail_close(stream);
11943
Tcl_SetResult(interp, "-1", TCL_STATIC);
11947
else if(!strcmp(s1, "list")){
11948
MAILSTREAM *stream;
11950
Tcl_Obj *objEnv = NULL, *objEnvList;
11953
if(postponed_stream(&stream, ps_global->VAR_POSTPONED_FOLDER, "Postponed", 0) && stream){
11954
if(!stream->nmsgs){
11955
(void) redraft_cleanup(&stream, FALSE, REDRAFT_PPND);
11956
Tcl_SetResult(interp, "", TCL_STATIC);
11960
objEnvList = Tcl_NewListObj(0, NULL);
11962
for(n = 1; n <= stream->nmsgs; n++){
11963
if((env = pine_mail_fetchstructure(stream, n, NULL)) != NULL){
11964
objEnv = Tcl_NewListObj(0, NULL);
11966
peAppListF(interp, objEnv, "%s%s", "uid",
11967
ulong2string(mail_uid(stream, n)));
11969
peAppListF(interp, objEnv, "%s%a", "to", env->to);
11971
date_str((char *)env->date, iSDate, 1, tmp_20k_buf, SIZEOF_20KBUF, 0);
11973
peAppListF(interp, objEnv, "%s%s", "date", tmp_20k_buf);
11975
peAppListF(interp, objEnv, "%s%s", "subj",
11976
rfc1522_decode_to_utf8((unsigned char *) tmp_20k_buf,
11977
SIZEOF_20KBUF, env->subject));
11979
Tcl_ListObjAppendElement(interp, objEnvList, objEnv);
11983
Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), objEnvList);
11985
Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp),
11986
Tcl_NewStringObj("utf-8", -1));
11988
if(stream != ps_global->mail_stream)
11989
pine_mail_close(stream);
11995
else if(objc == 3){
11996
if(!strcmp(s1, "append")){
11999
if((rv = peMsgCollector(interp, objc - 2, (Tcl_Obj **) &objv[2], peDoPostpone, PMC_NONE)) == TCL_OK)
12000
Tcl_SetResult(interp, ulong2string(get_last_append_uid()), TCL_VOLATILE);
12004
else if(!strcmp(s1, "delete")){
12005
if(Tcl_GetLongFromObj(interp, objv[2], &uid) == TCL_OK){
12006
MAILSTREAM *stream;
12009
if(postponed_stream(&stream, ps_global->VAR_POSTPONED_FOLDER, "Postponed", 0) && stream){
12010
if((rawno = mail_msgno(stream, uid)) > 0L){
12011
mail_flag(stream, long2string(rawno), "\\DELETED", ST_SET);
12012
ps_global->expunge_in_progress = 1;
12013
mail_expunge(stream);
12014
ps_global->expunge_in_progress = 0;
12015
if(stream != ps_global->mail_stream)
12016
pine_mail_actually_close(stream);
12021
err = "PEPostpone delete: UID no longer exists";
12024
err = "PEPostpone delete: No Postponed stream";
12027
err = "PEPostpone delete: No uid provided";
14796
* peTakeFrom - Take only From Address
14799
peTakeFrom(Tcl_Interp *interp, imapuid_t uid, int objc, Tcl_Obj **objv)
14808
* Return value will be of the form:
14810
* { "line to print",
14811
* {"personal", "mailbox", "host"} # addr
14812
* {"nick", "fullname", "fcc", "comment"} # suggested
14817
* The two list items will be empty if that line is
14818
* just informational.
14822
if((env = pine_mail_fetchstructure(ps_global->mail_stream,
14823
rawno = peSequenceNumber(uid),
14825
/* append the address information */
14826
for(ap = env->from; ap; ap = ap->next){
14827
objItem = Tcl_NewListObj(0, NULL);
14828
/* append EMPTY "line to print" */
14829
if(Tcl_ListObjAppendElement(interp, objItem, Tcl_NewStringObj("",-1)) != TCL_OK)
14832
/* append address info */
14833
peAppListF(interp, objItem, "%s%s%s",
14834
ap->personal ? (char *) rfc1522_decode_to_utf8((unsigned char *) tmp_20k_buf, SIZEOF_20KBUF, ap->personal) : "",
14835
ap->mailbox ? ap->mailbox : "",
14836
ap->host ? ap->host : "");
14838
/* append suggested info */
14839
peAddSuggestedContactInfo(interp, objItem, ap);
14841
if(Tcl_ListObjAppendElement(interp, Tcl_GetObjResult(interp), objItem) != TCL_OK)
14848
err = ps_global->last_error;
14851
err = "Invalid UID";
14858
peAddSuggestedContactInfo(Tcl_Interp *interp, Tcl_Obj *lobjp, ADDRESS *addr)
14860
char *nick = NULL, *full = NULL, *fcc = NULL, *comment = NULL;
14862
get_contactinfo_from_addr(addr, &nick, &full, &fcc, &comment);
14864
peAppListF(interp, lobjp, "%s%s%s%s",
14868
comment ? comment : "");
14871
fs_give((void **) &nick);
14874
fs_give((void **) &full);
14877
fs_give((void **) &fcc);
14880
fs_give((void **) &comment);
13577
14884
/* * * * * * * * * Status message ring management * * * * * * * * * * * * */
14540
15848
return(TRUE);
15852
peWebAlpinePrefix(void)
15858
/* * * * * * * * * RSS 2.0 Support Routines * * * * * * * * * * * */
15861
* PERssCmd - RSS TCL interface
15864
PERssCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
15868
dprint((2, "PERssCmd"));
15871
Tcl_WrongNumArgs(interp, 1, objv, "cmd ?args?");
15874
s1 = Tcl_GetStringFromObj(objv[1], NULL);
15877
if(!strcmp(s1, "news")){
15878
return(peRssReturnFeed(interp, "news", ps_global->VAR_RSS_NEWS));
15880
else if(!strcmp(s1, "weather")){
15881
return(peRssReturnFeed(interp, "weather", ps_global->VAR_RSS_WEATHER));
15885
Tcl_SetResult(interp, "Unknown PERss command", TCL_STATIC);
15890
* peRssReturnFeed - fetch feed contents and package Tcl response
15893
peRssReturnFeed(Tcl_Interp *interp, char *type, char *link)
15896
char *errstr = "UNKNOWN";
15899
ps_global->c_client_error[0] = '\0';
15901
if((feed = peRssFeed(interp, type, link)) != NULL)
15902
return(peRssPackageFeed(interp, feed));
15904
if(ps_global->mm_log_error)
15905
errstr = ps_global->c_client_error;
15908
errstr = "missing setting";
15910
snprintf(tmp_20k_buf, SIZEOF_20KBUF, "%s feed fail: %s", type, errstr);
15911
Tcl_SetResult(interp, tmp_20k_buf, TCL_VOLATILE);
15916
* peRssPackageFeed - build a list of feed item elements
15918
* LIST ORDER: {title} {link} {description} {image}
15921
peRssPackageFeed(Tcl_Interp *interp, RSS_FEED_S *feed)
15925
for(item = feed->items; item; item = item->next)
15926
if(peAppListF(interp, Tcl_GetObjResult(interp), "%s %s %s %s",
15927
(item->title && *item->title)? item->title : "Feed Provided No Title",
15928
item->link ? item->link : "",
15929
item->description ? item->description : "",
15930
feed->image ? feed->image : "") != TCL_OK)
15938
* peRssFeed - return cached feed struct or fetch a new one
15941
peRssFeed(Tcl_Interp *interp, char *type, char *link)
15943
int i, cache_l, cp_ref;
15944
time_t now = time(0);
15945
RSS_FEED_S *feed = NULL;
15946
RSS_CACHE_S *cache, *cp;
15947
static RSS_CACHE_S news_cache[RSS_NEWS_CACHE_SIZE], weather_cache[RSS_WEATHER_CACHE_SIZE];
15949
if(!strucmp(type,"news")){
15950
cache = &news_cache[0];
15951
cache_l = RSS_NEWS_CACHE_SIZE;
15954
cache = &weather_cache[0];
15955
cache_l = RSS_WEATHER_CACHE_SIZE;
15958
/* search/purge cache */
15959
for(i = 0; i < cache_l; i++)
15961
if(now > cache[i].stale){
15962
peRssClearCacheEntry(&cache[i]);
15964
else if(!strcmp(link, cache[i].link)){
15965
cache[i].referenced++;
15966
return(cache[i].feed); /* HIT! */
15970
if((feed = peRssFetch(interp, link)) != NULL){
15971
/* find cache slot, and insert feed into cache */
15972
for(i = 0, cp_ref = 0; i < cache_l; i++)
15973
if(!cache[i].feed){
15977
else if(cache[i].referenced >= cp_ref)
15981
cp = &cache[0]; /* failsafe */
15983
peRssClearCacheEntry(cp); /* make sure */
15985
cp->link = cpystr(link);
15987
cp->referenced = 0;
15988
cp->stale = now + (((feed->ttl > 0) ? feed->ttl : 60) * 60);
15995
* peRssFetch - follow the provided link an return the resulting struct
15998
peRssFetch(Tcl_Interp *interp, char *link)
16000
char *scheme = NULL, *loc = NULL, *path = NULL, *parms = NULL, *query = NULL, *frag = NULL;
16001
char *buffer = NULL, *bp, *p, *q;
16002
unsigned long port = 0L, buffer_len = 0L;
16003
STORE_S *feed_so = NULL;
16004
TCPSTREAM *tcp_stream;
16008
rfc1808_tokens(link, &scheme, &loc, &path, &parms, &query, &frag);
16009
if(scheme && loc && path){
16010
if((p = strchr(loc,':')) != NULL){
16012
while(*p && isdigit((unsigned char) *p))
16013
port = ((port * 10) + (*p++ - '0'));
16016
Tcl_SetResult(interp, "Bad RSS port number", TCL_STATIC);
16017
peRssComponentFree(&scheme,&loc,&path,&parms,&query,&frag);
16022
mail_parameters(NULL, SET_OPENTIMEOUT, (void *)(long) 5);
16023
tcp_stream = tcp_open (loc, scheme, port | NET_NOOPENTIMEOUT);
16024
mail_parameters(NULL, SET_OPENTIMEOUT, (void *)(long) 30);
16026
if(tcp_stream != NULL){
16029
snprintf(tmp_20k_buf, SIZEOF_20KBUF, "GET /%s%s%s%s%s HTTP/1.1\r\nHost: %s\r\nAccept: application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8\r\nAccept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7\r\nUser-Agent: Web-Alpine/%s (%s %s)\r\n\r\n",
16030
path, parms ? ":" : "", parms ? parms : "",
16031
query ? "?" : "", query ? query : "", loc,
16032
ALPINE_VERSION, SYSTYPE, get_alpine_revision_string(rev, sizeof(rev)));
16034
mail_parameters(NULL, SET_READTIMEOUT, (void *)(long) 5);
16036
if(tcp_sout(tcp_stream, tmp_20k_buf, strlen(tmp_20k_buf))){
16039
while((p = tcp_getline(tcp_stream)) != NULL){
16042
if(strucmp(p,"HTTP/1.1 200 OK")){
16043
fs_give((void **) &p);
16047
else if(*p == '\0'){
16049
buffer = fs_get(buffer_len + 16);
16050
if(!tcp_getbuffer(tcp_stream, buffer_len, buffer))
16051
fs_give((void **) &buffer);
16053
fs_give((void **) &p);
16056
else{ /* no content-length: */
16057
if((feed_so = so_get(CharStar, NULL, EDIT_ACCESS)) == NULL){
16058
fs_give((void **) &p);
16064
so_puts(feed_so, p);
16067
if(q = strchr(p,':')){
16071
while(isspace((unsigned char ) *q))
16074
/* content-length */
16075
if(l == 14 && !strucmp(p,"content-length")){
16076
while(*q && isdigit((unsigned char) *q))
16077
buffer_len = ((buffer_len * 10) + (*q++ - '0'));
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")){
16088
/* SHOULD: if(l == 7 && !strucmp(p, "expires")) */
16092
fs_give((void **) &p);
16096
Tcl_SetResult(interp, "RSS send failure", TCL_STATIC);
16097
peRssComponentFree(&scheme,&loc,&path,&parms,&query,&frag);
16100
tcp_close(tcp_stream);
16101
mail_parameters(NULL, SET_READTIMEOUT, (void *)(long) 60);
16102
peRssComponentFree(&scheme,&loc,&path,&parms,&query,&frag);
16105
buffer = (char *) so_text(feed_so);
16106
buffer_len = (int) so_tell(feed_so);
16115
/* grok response */
16116
bucket = so_get(CharStar, NULL, EDIT_ACCESS);
16117
gf_set_readc(&gc, buffer, buffer_len, CharStar, 0);
16118
gf_set_so_writec(&pc, bucket);
16120
gf_link_filter(gf_html2plain, gf_html2plain_rss_opt(&feed,0));
16121
if((err = gf_pipe(gc, pc)) != NULL){
16122
gf_html2plain_rss_free(&feed);
16123
Tcl_SetResult(interp, "RSS connection failure", TCL_STATIC);
16130
fs_give((void **) &buffer);
16134
Tcl_SetResult(interp, "RSS response error", TCL_STATIC);
16137
Tcl_SetResult(interp, "RSS connection failure", TCL_STATIC);
16140
Tcl_SetResult(interp, "RSS feed missing scheme", TCL_STATIC);
16143
Tcl_SetResult(interp, "No RSS Feed Defined", TCL_STATIC);
16150
peRssComponentFree(char **scheme,char **loc,char **path,char **parms,char **query,char **frag)
16152
if(scheme) fs_give((void **) scheme);
16153
if(loc) fs_give((void **) loc);
16154
if(path) fs_give((void **) path);
16155
if(parms) fs_give((void **) parms);
16156
if(query) fs_give((void **) query);
16157
if(frag) fs_give((void **) frag);
16161
peRssClearCacheEntry(RSS_CACHE_S *entry)
16165
fs_give((void **) &entry->link);
16167
gf_html2plain_rss_free(&entry->feed);
16168
memset(entry, 0, sizeof(RSS_CACHE_S));