summaryrefslogtreecommitdiff
path: root/src/terminal/internal/fqterm_zmodem.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/terminal/internal/fqterm_zmodem.h')
-rw-r--r--src/terminal/internal/fqterm_zmodem.h623
1 files changed, 623 insertions, 0 deletions
diff --git a/src/terminal/internal/fqterm_zmodem.h b/src/terminal/internal/fqterm_zmodem.h
new file mode 100644
index 0000000..bd1f4f4
--- /dev/null
+++ b/src/terminal/internal/fqterm_zmodem.h
@@ -0,0 +1,623 @@
+/***************************************************************************
+ * fqterm, a terminal emulator for both BBS and *nix. *
+ * Copyright (C) 2008 fqterm development group. *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. *
+ ***************************************************************************/
+
+#ifndef FQTERM_ZMODEM_H
+#define FQTERM_ZMODEM_H
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <errno.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <QByteArray>
+#include <QObject>
+#include <QTimer>
+#include <QFile>
+#include <QStringList>
+
+namespace FQTerm {
+
+/* PARAMETERS
+ *
+ * The following #defines control the behavior of the Zmodem
+ * package. Note that these may be replaced with variables
+ * if you like. For example, "#define DoInitRZ" may be replaced
+ * with "extern int DoInitRz" to use a global variable, or with
+ * "#define DoInitRZ (info->doInitRz)" to use a variable you
+ * add to the ZModem structure.
+ *
+ * It is assumed that the compiler is good enough to optimize
+ * "if( 0 )" and "if( 1 )" cases. If not, you may wish to modify
+ * the source code to use #ifdef instead.
+ */
+
+#define DoInitRZ 1 /* send initial "rz\r" when transmitting */
+#define AllowCommand 0 /* allow remote end to execute commands */
+#define SendSample 1 /* sender can sample reverse channel */
+#define SendAttn 1 /* sender can be interrupted with Attn signal */
+#define ResponseTime 10 /* reasonable response time for sender to
+ * respond to requests from receiver */
+#define SerialNo 1 /* receiver serial # */
+#define MaxNoise 64 /* max "noise" characters before transmission
+ * pauses */
+#define MaxErrs 30 /* Max receive errors before cancel */
+#define AlwaysSinit 1 /* always send ZSINIT header, even if not
+ * needed, this makes protocol more robust */
+
+#define SendOnly 0 /* compiles smaller version for send only */
+#define RcvOnly 0 /* compiles smaller version for receive only */
+
+enum enum_InputState {
+ Idle, Padding, Inhdr, Indata, Finish, Ysend, Yrcv
+};
+enum enum_Protocol {
+ XMODEM, YMODEM, ZMODEM
+};
+enum enum_Streaming {
+ Full, StrWindow, SlidingWindow, Segmented
+};
+enum enum_transferstate {
+ notransfer, transferstart, transferstop
+};
+
+
+/* Internal State */
+
+typedef enum zmstate {
+ /* receive */
+ RStart, /* sent RINIT, waiting for ZFILE or SINIT */
+ RSinitWait, /* got SINIT, waiting for data */
+ RFileName, /* got ZFILE, waiting for filename & info */
+ RCrc, /* got filename, want crc too */
+ RFile, /* got filename, ready to read */
+ RData, /* reading data */
+ RDataErr, /* encountered error, ignoring input */
+ RFinish, /* sent ZFIN, waiting for 'OO' */
+
+ /* transmit */
+ TStart, /* waiting for INIT frame from other end */
+ TInit, /* received INIT, sent INIT, waiting for ZACK */
+ FileWait, /* sent file header, waiting for ZRPOS */
+ CrcWait, /* sent file crc, waiting for ZRPOS */
+ Sending, /* sending data subpackets, ready for int */
+ SendWait, /* waiting for ZACK */
+ SendDone, /* file finished, need to send EOF */
+ SendEof, /* sent EOF, waiting for ZACK */
+ TFinish, /* sent ZFIN, waiting for ZFIN */
+
+ /* general */
+ CommandData, /* waiting for command data */
+ CommandWait, /* waiting for command to execute */
+ StderrData, /* waiting for stderr data */
+ Done,
+
+ /* x/ymodem transmit */
+ YTStart, /* waiting for 'G', 'C' or NAK */
+ YTFile, /* sent filename, waiting for ACK */
+ YTDataWait, /* ready to send data, waiting for 'C' */
+ YTData, /* sent data, waiting for ACK */
+ YTEOF, /* sent eof, waiting for ACK */
+ YTFin, /* sent null filename, waiting for ACK */
+
+ /* x/ymodem receive */
+ YRStart, /* sent 'C', waiting for filename */
+ YRDataWait, /* received filename, waiting for data */
+ YRData, /* receiving filename or data */
+ YREOF /* received first EOT, waiting for 2nd */
+
+} ZMState;
+
+
+
+
+typedef struct {
+ int ifd; /* input fd, for use by caller's routines */
+ int ofd; /* output fd, for use by caller's routines */
+ FILE *file; /* file being transfered */
+ int zrinitflags; /* receiver capabilities, see below */
+ int zsinitflags; /* sender capabilities, see below */
+ char *attn; /* attention string, see below */
+ int timeout; /* timeout value, in seconds */
+ int bufsize; /* receive buffer size, bytes */
+ int packetsize; /* preferred transmit packet size */
+ int windowsize; /* max window size */
+
+ /* file attributes: read-only */
+
+ int filesRem, bytesRem;
+ uchar f0, f1, f2, f3; /* file flags */
+ int len, mode, fileType; /* file flags */
+ ulong date; /* file date */
+
+ /* From here down, internal to Zmodem package */
+
+ ZMState state; /* protocol internal state */
+ char *filename; /* filename */
+ char *rfilename; /* remote filename */
+ int crc32; /* use 32-bit crc */
+ int pktLen; /* length of this packet */
+ int DataType; /* input data type */
+ int PacketType; /* type of this packet */
+ int rcvlen;
+ int chrCount; /* chars received in current header/buffer */
+ int crcCount; /* crc characters remaining at end of buffer */
+ int canCount; /* how many CAN chars received? */
+ int noiseCount; /* how many noise chars received? */
+ int errorFlush; /* ignore incoming data because of error */
+ uchar *buffer; /* data buffer */
+ ulong offset; /* file offset */
+ ulong lastOffset; /* last acknowledged offset */
+ ulong zrposOffset; /* last offset specified w/zrpos */
+ int ylen, bufp; /* len,location of last Ymodem packet */
+ int fileEof; /* file eof reached */
+ int packetCount; /* # packets received */
+ int errCount; /* how many data errors? */
+ int timeoutCount; /* how many times timed out? */
+ int windowCount; /* how much data sent in current window */
+ int atSign; /* last char was '@' */
+ int lastCR; /* last char was CR */
+ int escCtrl; /* other end requests ctrl chars be escaped */
+ int escHibit; /* other end requests hi bit be escaped */
+ int escape; /* next character is escaped */
+ int interrupt; /* received attention signal */
+ int waitflag; /* next send should wait */
+ /* parser state */
+ // enum enum_InputState {Idle, Padding, Inhdr, Indata, Finish, Ysend, Yrcv} InputState ;
+ enum_InputState InputState;
+ // enum enum_Protocol {XMODEM, YMODEM, ZMODEM} Protocol ;
+ enum_Protocol Protocol;
+ uchar hdrData[9]; /* header type and data */
+ uchar fileFlags[4]; /* file xfer flags */
+ ulong crc; /* crc of incoming header/data */
+ // enum enum_Streaming {Full, StrWindow, SlidingWindow, Segmented} Streaming ;
+ enum_Streaming Streaming;
+} ZModem;
+
+
+
+/* ZRINIT flags. Describe receiver capabilities */
+
+#define CANFDX 1 /* Rx is Full duplex */
+#define CANOVIO 2 /* Rx can overlap I/O */
+#define CANBRK 4 /* Rx can send a break */
+#define CANCRY 010 /* Rx can decrypt */
+#define CANLZW 020 /* Rx can uncompress */
+#define CANFC32 040 /* Rx can use 32-bit crc */
+#define ESCCTL 0100 /* Rx needs control chars escaped */
+#define ESC8 0200 /* Rx needs 8th bit escaped. */
+
+/* ZSINIT flags. Describe sender capabilities */
+
+#define TESCCTL 0100 /* Tx needs control chars escaped */
+#define TESC8 0200 /* Tx needs 8th bit escaped. */
+
+
+/* ZFILE transfer flags */
+
+/* F0 */
+#define ZCBIN 1 /* binary transfer */
+#define ZCNL 2 /* convert NL to local eol convention */
+#define ZCRESUM 3 /* resume interrupted file xfer, or append to a
+ growing file. */
+
+/* F1 */
+#define ZMNEWL 1 /* transfer if source newer or longer */
+#define ZMCRC 2 /* transfer if different CRC or length */
+#define ZMAPND 3 /* append to existing file, if any */
+#define ZMCLOB 4 /* replace existing file */
+#define ZMNEW 5 /* transfer if source is newer */
+#define ZMDIFF 6 /* transfer if dates or lengths different */
+#define ZMPROT 7 /* protect: transfer only if dest doesn't exist */
+#define ZMCHNG 8 /* change filename if destination exists */
+#define ZMMASK 037 /* mask for above. */
+#define ZMSKNOLOC 0200 /* skip if not present at Rx end */
+
+/* F2 */
+#define ZTLZW 1 /* lzw compression */
+#define ZTRLE 3 /* run-length encoding */
+
+/* F3 */
+#define ZCANVHDR 1 /* variable headers ok */
+#define ZRWOVR 4 /* byte position for receive window override/256 */
+#define ZXSPARS 64 /* encoding for sparse file ops. */
+
+
+
+/* ATTN string special characters. All other characters sent verbose */
+
+#define ATTNBRK '\335' /* send break signal */
+#define ATTNPSE '\336' /* pause for one second */
+
+/* error code definitions [O] means link still open */
+
+#define ZmDone -1 /* done */
+#define ZmErrInt -2 /* internal error */
+#define ZmErrSys -3 /* system error, see errno */
+#define ZmErrNotOpen -4 /* communication channel not open */
+#define ZmErrCantOpen -5 /* can't open file, see errno [O] */
+#define ZmFileTooLong -6 /* remote filename too long [O] */
+#define ZmFileCantWrite -7 /* could not write file, see errno */
+#define ZmDataErr -8 /* too many data errors */
+#define ZmErrInitTo -10 /* transmitter failed to respond to init req. */
+#define ZmErrSequence -11 /* packet received out of sequence */
+#define ZmErrCancel -12 /* cancelled by remote end */
+#define ZmErrRcvTo -13 /* remote receiver timed out during transfer */
+#define ZmErrSndTo -14 /* remote sender timed out during transfer */
+#define ZmErrCmdTo -15 /* remote command timed out */
+
+
+
+/* ZModem character definitions */
+
+#define ZDLE 030 /* zmodem escape is CAN */
+#define ZPAD '*' /* pad */
+#define ZBIN 'A' /* introduces 16-bit crc binary header */
+#define ZHEX 'B' /* introduces 16-bit crc hex header */
+#define ZBIN32 'C' /* introduces 32-bit crc binary header */
+#define ZBINR32 'D' /* introduces RLE packed binary frame w/32-bit crc */
+#define ZVBIN 'a' /* alternate ZBIN */
+#define ZVHEX 'b' /* alternate ZHEX */
+#define ZVBIN32 'c' /* alternate ZBIN32 */
+#define ZVBINR32 'd' /* alternate ZBINR32 */
+#define ZRESC 0177 /* RLE flag/escape character */
+
+
+
+/* ZModem header type codes */
+
+#define ZRQINIT 0 /* request receive init */
+#define ZRINIT 1 /* receive init */
+#define ZSINIT 2 /* send init sequence, define Attn */
+#define ZACK 3 /* ACK */
+#define ZFILE 4 /* file name, from sender */
+#define ZSKIP 5 /* skip file command, from receiver */
+#define ZNAK 6 /* last packet was garbled */
+#define ZABORT 7 /* abort */
+#define ZFIN 8 /* finish session */
+#define ZRPOS 9 /* resume file from this position, from receiver */
+#define ZDATA 10 /* data packets to follow, from sender */
+#define ZEOF 11 /* end of file, from sender */
+#define ZFERR 12 /* fatal i/o error, from receiver */
+#define ZCRC 13 /* request for file crc, from receiver */
+#define ZCHALLENGE 14 /* "send this number back to me", from receiver */
+#define ZCOMPL 15 /* request is complete */
+#define ZCAN 16 /* other end cancelled with CAN-CAN-CAN-CAN-CAN */
+#define ZFREECNT 17 /* request for free bytes on filesystem */
+#define ZCOMMAND 18 /* command, from sending program */
+#define ZSTDERR 19 /* output this message to stderr */
+
+
+/* ZDLE escape sequences */
+
+
+#define ZCRCE 'h' /* CRC next, frame ends, header follows */
+#define ZCRCG 'i' /* CRC next, frame continues nonstop */
+#define ZCRCQ 'j' /* CRC next, send ZACK, frame continues nonstop */
+#define ZCRCW 'k' /* CRC next, send ZACK, frame ends */
+#define ZRUB0 'l' /* translate to 0177 */
+#define ZRUB1 'm' /* translate to 0377 */
+
+
+/* ascii definitions */
+
+#define SOH 1 /* ^A */
+#define STX 2 /* ^B */
+#define EOT 4 /* ^D */
+#define ACK 6 /* ^F */
+#define DLE 16 /* ^P */
+#define XON 17 /* ^Q */
+#define XOFF 19 /* ^S */
+#define NAK 21 /* ^U */
+#define SYN 22 /* ^V */
+#define CAN 24 /* ^X */
+
+
+/* state table entry. There is one row of the table per
+ * possible state. Each row is a row of all reasonable
+ * inputs for this state. The entries are sorted so that
+ * the most common inputs occur first, to reduce search time
+ * Unexpected input is reported and ignored, as it might be
+ * caused by echo or something.
+ *
+ * Extra ZRINIT headers are the receiver trying to resync.
+ */
+class FQTermConfig;
+
+class FQTermZmodem;
+
+class FQTermTelnet;
+
+class FQTermFileDialog;
+
+typedef int(FQTermZmodem:: *ActionFunc)(ZModem*);
+
+typedef struct {
+ int type; /* frame type */
+ // int (*func)(ZModem *) ; /* transition function */
+ ActionFunc func;
+ int IFlush; /* flag: flush input first */
+ int OFlush; /* flag: flush output first */
+ ZMState newstate; /* new state. May be overridden by func */
+} StateTable;
+
+//class FQTermTelnet;
+
+class FQTermZmodem: public QObject {
+ Q_OBJECT;
+ public:
+ FQTermZmodem(FQTermConfig *config, FQTermTelnet *netinterface, int type, int serverEncoding);
+ ~FQTermZmodem();
+
+ /* zmodem-supplied functions: */
+ int ZmodemTInit(ZModem *info);
+ int ZmodemTFile(char *file, char *rmtname, uint f0, uint f1, uint f2, uint f3,
+ int filesRem, int bytesRem, ZModem *info);
+ int ZmodemTFinish(ZModem *info);
+ int ZmodemAbort(ZModem *info);
+ int ZmodemRInit(ZModem *info);
+ int ZmodemRcv(uchar *str, int len, ZModem *info, int &consumed_bytes);
+ int ZmodemAttention(ZModem *info);
+
+ int ZmodemReset(ZModem *info);
+
+ int YmodemTInit(ZModem *info);
+ int XmodemTInit(ZModem *info);
+ int YmodemRInit(ZModem *info);
+ int XmodemRInit(ZModem *info);
+
+ ulong FileCrc(char *name);
+ const char *sname(ZModem*);
+ const char *sname2(ZMState);
+
+ /* caller-supplied functions: */
+ int ZXmitChr(uchar c, ZModem *info);
+ int ZXmitStr(const uchar *str, int len, ZModem *info);
+ void ZIFlush(ZModem *info);
+ void ZOFlush(ZModem *info);
+ int ZAttn(ZModem *info);
+ void ZStatus(int type, int value, const char *status);
+ FILE *ZOpenFile(char *name, ulong crc, ZModem *info);
+
+ int ZWriteFile(uchar *buffer, int len, FILE *, ZModem*);
+ int ZCloseFile(ZModem *info);
+ void ZFlowControl(int onoff, ZModem *info);
+
+ /* end caller-supplied functions */
+
+ int ZXmitHdr(int type, int format, const uchar data[4], ZModem *info);
+ int ZXmitHdrHex(int type, const uchar data[4], ZModem *info);
+ int ZXmitHdrBin(int type, const uchar data[4], ZModem *info);
+ int ZXmitHdrBin32(int type, const uchar data[4], ZModem *info);
+ uchar *putZdle(uchar *ptr, uchar c, ZModem *info);
+ uchar *putHex(uchar *ptr, uchar c);
+
+ uchar *ZEnc4(ulong n);
+ ulong ZDec4(const uchar buf[4]);
+
+ int YrcvChar(char c, register ZModem *info);
+ int YrcvTimeout(register ZModem *info);
+ void ZIdleStr(uchar *buffer, int len, ZModem *info);
+
+ /* LEXICAL BOX: handle characters received from remote end.
+ * These may be header, data or noise.
+ *
+ * This section is a finite state machine for parsing headers
+ * and reading input data. The info->chrCount field is effectively
+ * the state variable.
+ */
+
+ int FinishChar(char c, register ZModem *info);
+ int DataChar(uchar c, register ZModem *info);
+ int HdrChar(uchar c, register ZModem *info);
+ int IdleChar(uchar c, register ZModem *info);
+
+ int YsendChar(char c, ZModem *info);
+
+ int ZPF(ZModem *info);
+ int Ignore(ZModem *info);
+ int AnswerChallenge(register ZModem *info);
+ int GotAbort(register ZModem *info);
+ int GotCancel(ZModem *info);
+ int GotCommand(ZModem *info);
+ int GotStderr(register ZModem *info);
+ int RetDone(ZModem *info);
+ int GotCommandData(register ZModem *info, int crcGood);
+ int GotStderrData(register ZModem *info, int crcGood);
+
+ int GotFileName(ZModem *info, int crcGood);
+ int ResendCrcReq(ZModem *info);
+ int GotSinitData(ZModem *info, int crcGood);
+ int ResendRpos(ZModem *info);
+ int GotFileData(ZModem *info, int crcGood);
+ int SendRinit(ZModem *info);
+
+ int GotSinit(ZModem *info);
+ int GotFile(ZModem *info);
+ int GotFin(ZModem *info);
+ int GotData(ZModem *info);
+ int GotEof(ZModem *info);
+ int GotFreecnt(ZModem *info);
+ int GotFileCrc(ZModem *info);
+
+ int GotRinit(ZModem*);
+ int SendZSInit(ZModem*);
+ int SendFileCrc(ZModem*);
+ int GotSendAck(ZModem*);
+ int GotSendDoneAck(ZModem*);
+ int GotSendNak(ZModem*);
+ int GotSendWaitAck(ZModem*);
+ int SkipFile(ZModem*);
+ int GotSendPos(ZModem*);
+
+ int requestFile(ZModem *info, ulong crc);
+ void parseFileName(ZModem *info, char *fileinfo);
+ int fileError(ZModem *info, int type, int data);
+
+ int ProcessPacket(ZModem *info);
+ int rejectPacket(ZModem *info);
+ int acceptPacket(ZModem *info);
+
+ int calcCrc(uchar *str, int len);
+
+ char *strdup(const char *str);
+
+ int SendMoreFileData(ZModem *info);
+
+ uint rcvHex(uint i, char c);
+
+ int ZDataReceived(register ZModem *info, int crcGood);
+ int dataSetup(register ZModem *info);
+ int ZProtocol(register ZModem *info);
+
+ int ZXmitData(int, int, uchar, uchar *data, ZModem*);
+ int YXmitData(uchar *, int, ZModem*);
+
+ int YSendFilename(ZModem*);
+ int YSendData(ZModem*);
+ int YSendFin(ZModem*);
+
+ int sendFilename(ZModem*);
+ int SendFileData(ZModem*);
+ int ResendEof(ZModem*);
+
+ int OverAndOut(ZModem*);
+
+ int startFileData(ZModem *info);
+
+ void zmodemlog(const char *fmt, ...);
+
+ // interface function
+ // all not completed
+ void transferTimeOut(void*);
+ void upload(char*);
+ void uploadNext(char*);
+ void transferFinish();
+ void xferCancel();
+
+ /* data received from remote, pass it to Zmodem funcs */
+ void transferSendData(char *, int);
+ void TransferCancel();
+
+#if 1
+ static StateTable RStartOps[];
+ static StateTable RSinitWaitOps[];
+ static StateTable RFileNameOps[];
+ static StateTable RCrcOps[];
+ static StateTable RFileOps[];
+ static StateTable RDataOps[];
+ static StateTable RFinishOps[];
+
+
+ static StateTable TStartOps[];
+ static StateTable TInitOps[];
+ static StateTable FileWaitOps[];
+ static StateTable CrcWaitOps[];
+ static StateTable SendingOps[];
+ static StateTable SendDoneOps[];
+ static StateTable SendWaitOps[];
+ static StateTable SendEofOps[];
+ static StateTable TFinishOps[];
+
+ static StateTable CommandDataOps[];
+ static StateTable CommandWaitOps[];
+ static StateTable StderrDataOps[];
+ static StateTable DoneOps[];
+
+ static StateTable *tables[];
+ static const char *hdrnames[];
+#endif
+
+#if 0
+ StateTable RStartOps[];
+ StateTable RSinitWaitOps[];
+ StateTable RFileNameOps[];
+ StateTable RCrcOps[];
+ StateTable RFileOps[];
+ StateTable RDataOps[];
+ StateTable RFinishOps[];
+
+
+ StateTable TStartOps[];
+ StateTable TInitOps[];
+ StateTable FileWaitOps[];
+ StateTable CrcWaitOps[];
+ StateTable SendingOps[];
+ StateTable SendDoneOps[];
+ StateTable SendWaitOps[];
+ StateTable SendEofOps[];
+ StateTable TFinishOps[];
+
+ StateTable CommandDataOps[];
+ StateTable CommandWaitOps[];
+ StateTable StderrDataOps[];
+ StateTable DoneOps[];
+
+ StateTable *tables[];
+ char *hdrnames[];
+#endif
+ FQTermTelnet *telnet_;
+ FQTermConfig *config_;
+ // Dialog
+ // QDialog *zmodemDialog, uploadListDialog;
+
+ bool sending;
+
+ enum_transferstate transferstate;
+
+ ZModem info;
+
+ // connection type, e.g. telnet or ssh , 0=telnet, 1=ssh
+
+ int connectionType;
+
+ // Timer
+ QTimer *zmodemTimer;
+
+ //log file
+ FILE *zmodemlogfile;
+
+ int zerrno;
+ uchar lastPullByte;
+
+ QStringList strFileList;
+ QStringList::Iterator itFile;
+
+ int serverEncodingID;
+
+ QString lastDownloadedFilename_;
+
+ // end Member
+ signals:
+ void ZmodemState(int, int, const char *);
+
+ public slots:
+ void zmodemCancel();
+ int ZmodemTimeout();
+};
+
+} // namespace FQTerm
+
+#endif // FQTERM_ZMODEM_H