Newer
Older
#include <genwrap.h>
#include <keys.h>
#include "threadwrap.h"
#include "filewrap.h"
#include "syncterm.h"
#include "term.h"
#include "uifcinit.h"
#include "menu.h"
#include "telnet_io.h"
#ifdef WITH_WXWIDGETS
#ifdef GUTS_BUILTIN
#include "gutsz.h"
#endif
#define ANSI_REPLY_BUFSIZE 2048
struct terminal term;
#define TRANSFER_WIN_WIDTH 66
#define TRANSFER_WIN_HEIGHT 18
static char winbuf[(TRANSFER_WIN_WIDTH + 2) * (TRANSFER_WIN_HEIGHT + 1) * 2]; /* Save buffer for transfer window */
static struct text_info trans_ti;
static struct text_info log_ti;
#ifdef WITH_WXWIDGETS
enum html_mode {
HTML_MODE_HIDDEN
,HTML_MODE_RAISED
};
static enum html_mode html_mode=HTML_MODE_HIDDEN;
enum {
HTML_SUPPORT_UNKNOWN
,HTML_NOTSUPPORTED
,HTML_SUPPORTED
};
static int html_supported=HTML_SUPPORT_UNKNOWN;
#if defined(__BORLANDC__)
#pragma argsused
#endif
void mousedrag(unsigned char *scrollback)
{
int key;
struct mouse_event mevent;
unsigned char *screen;
unsigned char *sbuffer;
int pos, startpos,endpos, lines;
int outpos;
char *copybuf;
sbufsize=term.width*2*term.height;
screen=(unsigned char*)alloca(sbufsize);
sbuffer=(unsigned char*)alloca(sbufsize);
gettext(term.x-1,term.y-1,term.x+term.width-2,term.y+term.height-2,screen);
while(1) {
key=getch();
if(key==0 || key==0xff)
key|=getch()<<8;
switch(key) {
case CIO_KEY_MOUSE:
getmouse(&mevent);
startpos=((mevent.starty-1)*term.width)+(mevent.startx-1);
endpos=((mevent.endy-1)*term.width)+(mevent.endx-1);
if(startpos>=term.width*term.height)
startpos=term.width*term.height-1;
if(endpos>=term.width*term.height)
endpos=term.width*term.height-1;
if(endpos<startpos) {
pos=endpos;
endpos=startpos;
startpos=pos;
}
switch(mevent.event) {
case CIOLIB_BUTTON_1_DRAG_MOVE:
memcpy(sbuffer,screen,sbufsize);
for(pos=startpos;pos<=endpos;pos++) {
else
if(((sbuffer[pos*2+1]&0x70)>>4) == (sbuffer[pos*2+1]&0x0F)) {
sbuffer[pos*2+1]|=0x08;
}
}
puttext(term.x-1,term.y-1,term.x+term.width-2,term.y+term.height-2,sbuffer);
break;
default:
lines=abs(mevent.endy-mevent.starty)+1;
copybuf=alloca(endpos-startpos+4+lines*2);
outpos=0;
for(pos=startpos;pos<=endpos;pos++) {
copybuf[outpos++]=screen[pos*2];
if(screen[pos*2]!=' ' && screen[pos*2])
lastchar=outpos;
if((pos+1)%term.width==0) {
#ifdef _WIN32
copybuf[outpos++]='\r';
#endif
copybuf[outpos++]='\n';
}
}
copybuf[outpos]=0;
copytext(copybuf, strlen(copybuf));
puttext(term.x-1,term.y-1,term.x+term.width-2,term.y+term.height-2,screen);
return;
}
break;
default:
puttext(term.x-1,term.y-1,term.x+term.width-2,term.y+term.height-2,screen);
ungetch(key);
return;
}
}
}
void update_status(struct bbslist *bbs, int speed)
char nbuf[LIST_NAME_MAX+10+11+1]; /* Room for "Name (Logging) (115300)" and terminator */
/* SAFE and Logging should me be possible. */
struct text_info txtinfo;
int now;
static int lastupd=0;
static int oldspeed=0;
if(now==lastupd && speed==oldspeed)
oldspeed=speed;
timeon=now - bbs->connected;
gettextinfo(&txtinfo);
oldscroll=_wscroll;
textattr(YELLOW|(BLUE<<4));
/* Move to status line thinger */
window(term.x-1,term.y+term.height-1,term.x+term.width-2,term.y+term.height-1);
gotoxy(1,1);
_wscroll=0;
if(safe_mode)
strcat(nbuf, " (SAFE)");
if(cterm.log)
strcat(nbuf, " (Logging)");
if(speed)
sprintf(strchr(nbuf,0)," (%d)", speed);
if(cterm.doorway_mode)
strcat(nbuf, " (DrWy)");
switch(cio_api.mode) {
case CIOLIB_MODE_CURSES:
case CIOLIB_MODE_CURSES_IBM:
case CIOLIB_MODE_ANSI:
if(timeon>359999)
cprintf(" %-29.29s \263 %-6.6s \263 Connected: Too Long \263 CTRL-S for menu ",nbuf,conn_types[bbs->conn_type]);
cprintf(" %-29.29s \263 %-6.6s \263 Connected: %02d:%02d:%02d \263 CTRL-S for menu ",nbuf,conn_types[bbs->conn_type],timeon/3600,(timeon/60)%60,timeon%60);
break;
default:
if(timeon>359999)
cprintf(" %-30.30s \263 %-6.6s \263 Connected: Too Long \263 ALT-Z for menu ",nbuf,conn_types[bbs->conn_type]);
cprintf(" %-30.30s \263 %-6.6s \263 Connected: %02d:%02d:%02d \263 ALT-Z for menu ",nbuf,conn_types[bbs->conn_type],timeon/3600,(timeon/60)%60,timeon%60);
break;
}
if(wherex()>=80)
clreol();
_wscroll=oldscroll;
textattr(txtinfo.attribute);
window(txtinfo.winleft,txtinfo.wintop,txtinfo.winright,txtinfo.winbottom);
gotoxy(txtinfo.curx,txtinfo.cury);
#if defined(_WIN32) && defined(_DEBUG) && defined(DUMP)
void dump(BYTE* buf, int len)
{
char str[128];
int i,j;
size_t slen=0;
slen=sprintf(str,"RX: ");
for(i=0;i<len;i+=j) {
for(j=0;i+j<len && j<32;j++)
slen+=sprintf(str+slen,"%02X ",buf[i+j]);
OutputDebugString(str);
slen=sprintf(str,"RX: ");
}
}
#endif
/* Zmodem Stuff */
int log_level = LOG_INFO;
enum { ZMODEM_MODE_SEND, ZMODEM_MODE_RECV } zmodem_mode;
static BOOL zmodem_check_abort(void* vp)
zmodem_t* zm = (zmodem_t*)vp;
if(zm!=NULL && kbhit()) {
switch(getch()) {
case ESC:
case CTRL_C:
case CTRL_X:
zm->cancelled=TRUE;
zm->local_abort=TRUE;
break;
}
}
return(zm->cancelled);
extern FILE* log_fp;
extern char *log_levels[];
#if defined(__BORLANDC__)
#pragma argsused
#endif
static int lputs(void* cbdata, int level, const char* str)
#if defined(_WIN32) && defined(_DEBUG) && FALSE
sprintf(msg,"SyncTerm: %s\n",str);
OutputDebugString(msg);
if(log_fp!=NULL && level <= log_level)
fprintf(log_fp,"Xfer %s: %s\n",log_levels[level], str);
if(level > LOG_INFO)
/* Assumes the receive window has been drawn! */
window(log_ti.winleft, log_ti.wintop, log_ti.winright, log_ti.winbottom);
gotoxy(log_ti.curx, log_ti.cury);
switch(level) {
case LOG_DEBUG:
textcolor(LIGHTCYAN);
SAFEPRINTF(msg,"%s\r\n",str);
break;
textcolor(WHITE);
SAFEPRINTF(msg,"%s\r\n",str);
break;
case LOG_NOTICE:
textcolor(YELLOW);
SAFEPRINTF(msg,"%s\r\n",str);
break;
case LOG_WARNING:
textcolor(LIGHTMAGENTA);
SAFEPRINTF(msg,"Warning: %s\r\n",str);
break;
default:
textcolor(LIGHTRED);
SAFEPRINTF(msg,"!ERROR: %s\r\n",str);
break;
}
}
static int lprintf(int level, const char *fmt, ...)
{
char sbuf[1024];
va_list argptr;
va_start(argptr,fmt);
vsnprintf(sbuf,sizeof(sbuf),fmt,argptr);
sbuf[sizeof(sbuf)-1]=0;
va_end(argptr);
return(lputs(NULL,level,sbuf));
}
#if defined(__BORLANDC__)
#pragma argsused
#endif
void zmodem_progress(void* cbdata, uint32_t current_pos)
{
char orig[128];
unsigned cps;
time_t l;
time_t t;
time_t now;
static time_t last_progress;
zmodem_t* zm=(zmodem_t*)cbdata;
zmodem_check_abort(cbdata);
now=time(NULL);
if(now-last_progress>0 || current_pos >= zm->current_file_size) {
hold_update = TRUE;
window(((trans_ti.screenwidth-TRANSFER_WIN_WIDTH)/2)+2
, ((trans_ti.screenheight-TRANSFER_WIN_HEIGHT)/2)+1
, ((trans_ti.screenwidth-TRANSFER_WIN_WIDTH)/2) + TRANSFER_WIN_WIDTH - 2
, ((trans_ti.screenheight-TRANSFER_WIN_HEIGHT)/2)+5);
gotoxy(1,1);
textattr(LIGHTCYAN | (BLUE<<4));
t=now-zm->transfer_start_time;
if(t<=0)
t=1;
if(zm->transfer_start_pos>current_pos)
zm->transfer_start_pos=0;
if((cps=(current_pos-zm->transfer_start_pos)/t)==0)
cps=1; /* cps so far */
l=zm->current_file_size/cps; /* total transfer est time */
l-=t; /* now, it's est time left */
if(l<0) l=0;
cprintf("File (%u of %u): %-.*s"
,zm->current_file_num, zm->total_files, TRANSFER_WIN_WIDTH - 20, zm->current_file_name);
if(zm->transfer_start_pos)
sprintf(orig,"From: %lu ", zm->transfer_start_pos);
else
orig[0]=0;
cprintf("%sByte: %lu of %lu (%lu KB)"
,orig, current_pos, zm->current_file_size, zm->current_file_size/1024);
cprintf("Time: %lu:%02lu ETA: %lu:%02lu Block: %u/CRC-%u %u cps"
,t/60L
,t%60L
,l/60L
,l%60L
,zm->block_size
,zmodem_mode==ZMODEM_MODE_RECV ? (zm->receive_32bit_data ? 32:16) :
(zm->can_fcs_32 && !zm->want_fcs_16) ? 32:16
,cps
);
clreol();
cprintf("%*s%3d%%\r\n", TRANSFER_WIN_WIDTH/2-5, ""
,(long)(((float)current_pos/(float)zm->current_file_size)*100.0));
l = (long)(60*((float)current_pos/(float)zm->current_file_size));
cprintf("[%*.*s%*s]", l, l,
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
"\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1\xb1"
, 60-l, "");
last_progress=now;
hold_update = FALSE;
gotoxy(wherex(), wherey());
hold_update = old_hold;
#if defined(__BORLANDC__)
#pragma argsused
#endif
static int send_byte(void* unused, uchar ch, unsigned timeout /* seconds */)
return(conn_send(&ch,sizeof(ch),timeout*1000)!=1);
#if defined(__BORLANDC__)
#pragma argsused
#endif
static int recv_byte(void* unused, unsigned timeout /* seconds */)
if(conn_recv(&ch, sizeof(ch), timeout*1000))
return(ch);
return(-1);
}
#if defined(__BORLANDC__)
#pragma argsused
#endif
BOOL data_waiting(void* unused, unsigned timeout)
{
return(conn_data_waiting()!=0);
}
void draw_transfer_window(char* title)
char outline[TRANSFER_WIN_WIDTH*2];
char shadow[TRANSFER_WIN_WIDTH*2]; /* Assumes that width*2 > height * 2 */
old_hold = hold_update;
hold_update=TRUE;
gettextinfo(&trans_ti);
top=(trans_ti.screenheight-TRANSFER_WIN_HEIGHT)/2;
left=(trans_ti.screenwidth-TRANSFER_WIN_WIDTH)/2;
gettext(left, top, left + TRANSFER_WIN_WIDTH + 1, top + TRANSFER_WIN_HEIGHT, winbuf);
memset(outline, YELLOW | (BLUE<<4), sizeof(outline));
for(i=2;i < sizeof(outline) - 2; i+=2) {
outline[i] = (char)0xcd; /* Double horizontal line */
outline[0]=(char)0xc9;
outline[sizeof(outline)-2]=(char)0xbb;
puttext(left, top, left + TRANSFER_WIN_WIDTH - 1, top, outline);\
/* Title */
gotoxy(left+4,top);
textattr(YELLOW|(BLUE<<4));
cprintf("\xb5 %*s \xc6",strlen(title),"");
gotoxy(left+6,top);
textattr(WHITE|(BLUE<<4));
cprintf("%s",title);
for(i=2;i < sizeof(outline) - 2; i+=2) {
outline[i] = (char)0xc4; /* Single horizontal line */
outline[0] = (char)0xc7; /* 0xcc */
outline[sizeof(outline)-2]=(char)0xb6; /* 0xb6 */
puttext(left, top+6, left + TRANSFER_WIN_WIDTH - 1, top+6, outline);
for(i=2;i < sizeof(outline) - 2; i+=2) {
outline[i] = (char)0xcd; /* Double horizontal line */
outline[0]=(char)0xc8;
outline[sizeof(outline)-2]=(char)0xbc;
puttext(left, top + TRANSFER_WIN_HEIGHT - 1, left+TRANSFER_WIN_WIDTH - 1, top + TRANSFER_WIN_HEIGHT - 1, outline);
outline[0]=(char)0xba;
outline[sizeof(outline)-2]=(char)0xba;
for(i=2;i < sizeof(outline) - 2; i+=2) {
outline[i] = ' ';
}
for(i=1; i<6; i++) {
puttext(left, top + i, left + TRANSFER_WIN_WIDTH - 1, top+i, outline);
}
/* for(i=3;i < sizeof(outline) - 2; i+=2) { */
/* outline[i] = LIGHTGRAY | (BLACK << 8); */
/* } */
for(i=7; i<TRANSFER_WIN_HEIGHT-1; i++) {
puttext(left, top + i, left + TRANSFER_WIN_WIDTH - 1, top+i, outline);
}
/* Title */
gotoxy(left + TRANSFER_WIN_WIDTH - 20, top + i);
textattr(YELLOW|(BLUE<<4));
cprintf("\xb5 \xc6");
textattr(WHITE|(BLUE<<4));
gotoxy(left + TRANSFER_WIN_WIDTH - 18, top + i);
cprintf("ESC to Abort");
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
/* Shadow */
if(uifc.bclr==BLUE) {
gettext(left + TRANSFER_WIN_WIDTH
, top+1
, left + TRANSFER_WIN_WIDTH + 1
, top + (TRANSFER_WIN_HEIGHT - 1)
, shadow);
for(i=1;i<sizeof(shadow);i+=2)
shadow[i]=DARKGRAY;
puttext(left + TRANSFER_WIN_WIDTH
, top+1
, left + TRANSFER_WIN_WIDTH + 1
, top + (TRANSFER_WIN_HEIGHT - 1)
, shadow);
gettext(left + 2
, top + TRANSFER_WIN_HEIGHT
, left + TRANSFER_WIN_WIDTH + 1
, top + TRANSFER_WIN_HEIGHT
, shadow);
for(i=1;i<sizeof(shadow);i+=2)
shadow[i]=DARKGRAY;
puttext(left + 2
, top + TRANSFER_WIN_HEIGHT
, left + TRANSFER_WIN_WIDTH + 1
, top + TRANSFER_WIN_HEIGHT
, shadow);
}
window(left+2, top + 7, left + TRANSFER_WIN_WIDTH - 3, top + TRANSFER_WIN_HEIGHT - 2);
puttext(
((trans_ti.screenwidth-TRANSFER_WIN_WIDTH)/2)
, ((trans_ti.screenheight-TRANSFER_WIN_HEIGHT)/2)
, ((trans_ti.screenwidth-TRANSFER_WIN_WIDTH)/2) + TRANSFER_WIN_WIDTH + 1
, ((trans_ti.screenheight-TRANSFER_WIN_HEIGHT)/2) + TRANSFER_WIN_HEIGHT
, winbuf);
window(trans_ti.winleft, trans_ti.wintop, trans_ti.winright, trans_ti.winbottom);
gotoxy(trans_ti.curx, trans_ti.cury);
textattr(trans_ti.attribute);
void zmodem_upload(struct bbslist *bbs, FILE *fp, char *path);
void begin_upload(struct bbslist *bbs, BOOL autozm)
char str[MAX_PATH*2+1];
char *opts[3]={
"ZMODEM"
,"ASCII"
,""
};
struct text_info txtinfo;
char *buf;
gettextinfo(&txtinfo);
buf=(char *)alloca(txtinfo.screenheight*txtinfo.screenwidth*2);
gettext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
init_uifc(FALSE, FALSE);
result=filepick(&uifc, "Upload", &fpick, bbs->uldir, NULL, UIFC_FP_ALLOWENTRY);
if(result==-1 || fpick.files<1) {
filepick_free(&fpick);
puttext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
gotoxy(txtinfo.curx, txtinfo.cury);
return;
}
SAFECOPY(path,fpick.selected[0]);
filepick_free(&fpick);
puttext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
if((fp=fopen(path,"rb"))==NULL) {
SAFEPRINTF2(str,"Error %d opening %s for read",errno,path);
uifcmsg("ERROR",str);
puttext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
gotoxy(txtinfo.curx, txtinfo.cury);
return;
}
setvbuf(fp,NULL,_IOFBF,0x10000);
zmodem_upload(bbs, fp, path);
else {
i=0;
uifc.helpbuf="Select Transfer Type";
switch(uifc.list(WIN_MID|WIN_SAV,0,0,0,&i,NULL,"Transfer Type",opts)) {
case 0:
zmodem_upload(bbs, fp, path);
break;
case 1:
}
uifcbail();
puttext(1,1,txtinfo.screenwidth,txtinfo.screenheight,buf);
gotoxy(txtinfo.curx, txtinfo.cury);
#if defined(__BORLANDC__)
#pragma argsused
#endif
static BOOL is_connected(void* unused)
{
return(conn_connected());
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
#ifdef GUTS_BUILTIN
static int guts_lputs(void* cbdata, int level, const char* str)
{
struct GUTS_info *gi=cbdata;
/* ToDo: Do something usefull here. */
/* fprintf(stderr,"%s\n",str); */
return(0);
}
void guts_zmodem_progress(void* cbdata, ulong current_pos)
{
struct GUTS_info *gi=cbdata;
/* ToDo: Do something usefull here. */
return;
}
static int guts_send_byte(void* cbdata, uchar ch, unsigned timeout)
{
int i;
struct GUTS_info *gi=cbdata;
if(!socket_check(gi->oob_socket, NULL, &i, timeout*1000))
return(-1);
if(!i)
return(-1);
if(send(gi->oob_socket,&ch,1,0)==-1)
return(-1);
return(0);
}
static int guts_recv_byte(void* cbdata, unsigned timeout)
{
BOOL data_waiting;
BYTE ch;
struct GUTS_info *gi=cbdata;
if(!socket_check(gi->oob_socket, &data_waiting, NULL, timeout*1000))
return(-1);
if(!data_waiting)
return(-1);
if(recv(gi->oob_socket,&ch,1,0)!=1)
return(-1);
return(ch);
}
static BOOL guts_is_connected(void* cbdata)
{
struct GUTS_info *gi=cbdata;
return socket_check(gi->oob_socket,NULL,NULL,0);
}
BOOL guts_data_waiting(void* cbdata, unsigned timeout)
{
BOOL rd;
struct GUTS_info *gi=cbdata;
if(!socket_check(gi->oob_socket,&rd,NULL,timeout*1000))
return(FALSE);
return(rd);
}
void zmodem_download(struct bbslist *bbs);
void guts_background_download(void *cbdata)
{
struct GUTS_info gi=*(struct GUTS_info *)cbdata;
zmodem_t zm;
ulong bytes_received;
zmodem_mode=ZMODEM_MODE_RECV;
zmodem_init(&zm
,&gi
,guts_lputs, guts_zmodem_progress
,guts_send_byte,guts_recv_byte,guts_is_connected
,NULL /* is_cancelled */
,guts_data_waiting);
/* ToDo: This would be a good time to detach or something. */
zmodem_recv_files(&zm,gi.files[0],&bytes_received);
oob_close(&gi);
}
void guts_background_upload(void *cbdata)
{
struct GUTS_info gi=*(struct GUTS_info *)cbdata;
zmodem_t zm;
ulong fsize;
FILE* fp;
if((fp=fopen(gi.files[0],"rb"))==NULL) {
fprintf(stderr,"Error %d opening %s for read",errno,gi.files[0]);
return;
}
setvbuf(fp,NULL,_IOFBF,0x10000);
zmodem_mode=ZMODEM_MODE_SEND;
zmodem_init(&zm
,&gi
,guts_lputs, guts_zmodem_progress
,guts_send_byte,guts_recv_byte,guts_is_connected
,NULL /* is_cancelled */
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
,guts_data_waiting);
zm.current_file_num = zm.total_files = 1; /* ToDo: support multi-file/batch uploads */
fsize=filelength(fileno(fp));
if(zmodem_send_file(&zm, gi.files[0], fp
,/* ZRQINIT? */TRUE, /* start_time */NULL, /* sent_bytes */ NULL))
zmodem_get_zfin(&zm);
fclose(fp);
oob_close(&gi);
}
void guts_transfer(struct bbslist *bbs)
{
struct GUTS_info gi;
if(safe_mode)
return;
setup_defaults(&gi);
gi.socket=conn_socket;
gi.telnet=bbs->conn_type==CONN_TYPE_TELNET;
gi.server=FALSE;
gi.use_daemon=FALSE;
gi.orig=FALSE;
if(negotiation(&gi)) {
oob_close(&gi);
return;
}
/* Authentication Phase */
if(!gi.inband) {
if(authenticate(&gi)) {
oob_close(&gi);
return;
}
}
if(gi.inband) {
if(gi.direction==UPLOAD)
begin_upload(bbs, TRUE);
zmodem_download(bbs);
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
oob_close(&gi);
}
else {
if(gi.direction==UPLOAD) {
int result;
struct file_pick fpick;
init_uifc(FALSE, FALSE);
result=filepick(&uifc, "Upload", &fpick, bbs->uldir, NULL, UIFC_FP_ALLOWENTRY);
if(result==-1 || fpick.files<1) {
filepick_free(&fpick);
uifcbail();
return;
}
strListPush(&gi.files, fpick.selected[0]);
filepick_free(&fpick);
uifcbail();
_beginthread(guts_background_upload, 0, &gi);
}
else {
strListPush(&gi.files, bbs->dldir);
_beginthread(guts_background_download, 0, &gi);
}
}
return;
}
#endif
{
char linebuf[1024+2]; /* One extra for terminator, one extra for added CR */
char *p;
char ch[2];
int inch;
ch[1]=0;
while(!feof(fp)) {
if(fgets(linebuf, 1025, fp)!=NULL) {
if((p=strrchr(linebuf,'\n'))!=NULL) {
if((p==linebuf && !lastwascr) || (p>linebuf && *(p-1)!='\n')) {
*p='\r';
p++;
*p='\n';
p++;
*p=0;
}
}
if(p!=NULL && p>linebuf) {
if(*(p-1)=='\r')
lastwascr=TRUE;
}
conn_send(linebuf,strlen(linebuf),0);
}
/* Note, during ASCII uploads, do NOT send ANSI responses and don't
* allow speed changes. */
while((inch=recv_byte(NULL, 0))>=0) {
ch[0]=inch;
cterm_write(ch, 1, NULL, 0, NULL);
}
}
fclose(fp);
}
void zmodem_upload(struct bbslist *bbs, FILE *fp, char *path)
{
zmodem_t zm;
ulong fsize;
draw_transfer_window("Zmodem Upload");
zmodem_mode=ZMODEM_MODE_SEND;
conn_binary_mode_on();
zmodem_init(&zm
,/* cbdata */&zm
,lputs, zmodem_progress
,send_byte,recv_byte
,is_connected
,zmodem_check_abort
,data_waiting);
zm.current_file_num = zm.total_files = 1; /* ToDo: support multi-file/batch uploads */
fsize=filelength(fileno(fp));
lprintf(LOG_INFO,"Sending %s (%lu KB) via Zmodem"
,path,fsize/1024);
if(zmodem_send_file(&zm, path, fp
,/* ZRQINIT? */TRUE, /* start_time */NULL, /* sent_bytes */ NULL))
zmodem_get_zfin(&zm);
fclose(fp);
conn_binary_mode_off();
lprintf(LOG_NOTICE,"Hit any key to continue...");
getch();
erase_transfer_window();
}
void zmodem_download(struct bbslist *bbs)
int files_received;
draw_transfer_window("Zmodem Download");
zmodem_mode=ZMODEM_MODE_RECV;
conn_binary_mode_on();
zmodem_init(&zm
,lputs, zmodem_progress
,send_byte,recv_byte
,is_connected
,zmodem_check_abort
,data_waiting);
files_received=zmodem_recv_files(&zm,bbs->dldir,&bytes_received);
if(files_received>1)
lprintf(LOG_INFO,"Received %u files (%lu bytes) successfully", files_received, bytes_received);
conn_binary_mode_off();
lprintf(LOG_NOTICE,"Hit any key to continue...");
getch();
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* X/Y-MODEM stuff */
enum { XMODEM_MODE_SEND, XMODEM_MODE_RECV } xmodem_mode;
uchar block[1024]; /* Block buffer */
ulong block_num; /* Block number */
static BOOL xmodem_check_abort(void* vp)
{
xmodem_t* xm = (xmodem_t*)vp;
if(xm!=NULL && kbhit()) {
switch(getch()) {
case ESC:
case CTRL_C:
case CTRL_X:
xm->cancelled=TRUE;
break;
}
}
return(xm->cancelled);
}
#if defined(__BORLANDC__)
#pragma argsused
#endif
void xmodem_progress(void* cbdata, unsigned block_num, ulong offset, ulong fsize, time_t t)
{
xmodem_check_abort(cbdata);
}
void xmodem_upload(struct bbslist *bbs, FILE *fp, char *path, long mode)
{
xmodem_t xm;
ulong fsize;
xmodem_mode=XMODEM_MODE_SEND;
conn_binary_mode_on();
xmodem_init(&xm
,/* cbdata */&xm
,&mode
,lputs
,xmodem_progress
,send_byte
,recv_byte
,is_connected
,xmodem_check_abort);
xm.total_files = 1; /* ToDo: support multi-file/batch uploads */
fsize=filelength(fileno(fp));
if(mode&XMODEM) {
draw_transfer_window("Xmodem Upload");
lprintf(LOG_INFO,"Sending %s (%lu KB) via Xmodem"
,path,fsize/1024);
}
else if(mode&YMODEM) {
if(mode&GMODE) {
draw_transfer_window("Ymodem-G Upload");
lprintf(LOG_INFO,"Sending %s (%lu KB) via Ymodem-G"
,path,fsize/1024);
}
else {
draw_transfer_window("Ymodem Upload");
lprintf(LOG_INFO,"Sending %s (%lu KB) via Ymodem"
,path,fsize/1024);
}
}
else {
return;
}
if(xmodem_send_file(&xm, path, fp
,/* start_time */NULL, /* sent_bytes */ NULL)) {
if(mode&YMODEM) {
if(xmodem_get_mode(&xm)) {
lprintf(LOG_INFO,"Sending Ymodem termination block");
memset(block,0,128); /* send short block for terminator */
xmodem_put_block(&xm, block, 128 /* block_size */, 0 /* block_num */);
if(!xmodem_get_ack(&xm,6,0)) {
lprintf(LOG_WARNING,"Failed to receive ACK after terminating block");
}
}
}
}
fclose(fp);
conn_binary_mode_off();