AmendHub

Download

jcs

/

subtext

/

zmodem.c

 

(View History)

jcs   zmodem: Header injection is not needed here Latest amendment: 653 on 2026-09-22

1 /*
2 * Copyright (c) 2022 joshua stein <jcs@jcs.org>
3 *
4 * Copyright (C) 1994-1998 T. Teranishi
5 * (C) 2007- TeraTerm Project
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. The name of the author may not be used to endorse or promote products
18 * derived from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <stdarg.h>
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <time.h>
37
38 #include "crc.h"
39 #include "util.h"
40 #include "zmodem.h"
41
42 /* #define ZMODEM_DEBUG */
43
44 #define ZMODEM_TIMEOUT 20
45
46 #ifdef ZMODEM_DEBUG
47 #include "logger.h"
48 extern struct logger *logger;
49 #endif
50
51 #define LOBYTE(w) ((unsigned char)(((unsigned short)(w)) & 0xff))
52 #define HIBYTE(w) ((unsigned char)((((unsigned short)(w)) >> 8) & 0xff))
53 #define LOWORD(l) ((unsigned short)(l))
54 #define HIWORD(l) ((unsigned short)(((unsigned long)(l) >> 16) & 0xFFFF))
55
56 #define Z_RecvInit 1
57 #define Z_RecvInit2 2
58 #define Z_RecvData 3
59 #define Z_RecvFIN 4
60 #define Z_SendInit 5
61 #define Z_SendInitHdr 6
62 #define Z_SendInitDat 7
63 #define Z_SendFileHdr 8
64 #define Z_SendFileDat 9
65 #define Z_SendDataHdr 10
66 #define Z_SendDataDat 11
67 #define Z_SendDataDat2 12
68 #define Z_SendEOF 13
69 #define Z_SendFIN 14
70 #define Z_SendSkip 15
71 #define Z_Cancel 16
72 #define Z_End 17
73
74 #define Z_PktGetPAD 1
75 #define Z_PktGetDLE 2
76 #define Z_PktHdrFrm 3
77 #define Z_PktGetBin 4
78 #define Z_PktGetHex 5
79 #define Z_PktGetHexEOL 6
80 #define Z_PktGetData 7
81 #define Z_PktGetCRC 8
82
83 #define ZPAD '*'
84 #define ZDLE 0x18
85 #define ZDLEE 0x58
86 #define ZBIN 'A'
87 #define ZHEX 'B'
88 #define ZBIN32 'C'
89
90 #define ZRQINIT 0
91 #define ZRINIT 1
92 #define ZSINIT 2
93 #define ZACK 3
94 #define ZFILE 4
95 #define ZSKIP 5
96 #define ZNAK 6
97 #define ZABORT 7
98 #define ZFIN 8
99 #define ZRPOS 9
100 #define ZDATA 10
101 #define ZEOF 11
102 #define ZFERR 12
103 #define ZCRC 13
104 #define ZCHALLENGE 14
105 #define ZCOMPL 15
106 #define ZCAN 16
107 #define ZFREECNT 17
108 #define ZCOMMAND 18
109 #define ZSTDERR 19
110
111 #define ZCRCE 'h'
112 #define ZCRCG 'i'
113 #define ZCRCQ 'j'
114 #define ZCRCW 'k'
115 #define ZRUB0 'l'
116 #define ZRUB1 'm'
117
118 #define ZF0 3
119 #define ZF1 2
120 #define ZF2 1
121 #define ZF3 0
122 #define ZP0 0
123 #define ZP1 1
124 #define ZP2 2
125 #define ZP3 3
126
127 #define CANFDX 0x01
128 #define CANOVIO 0x02
129 #define CANBRK 0x04
130 #define CANCRY 0x08
131 #define CANLZW 0x10
132 #define CANFC32 0x20
133 #define ESCCTL 0x40
134 #define ESC8 0x80
135
136 #define ZCBIN 1
137 #define ZCNL 2
138
139 #define XON 0x11
140 #define IAC 0xff
141
142 short ZRead1Byte(struct zmodem_session *, unsigned char *);
143 void ZPutHex(struct zmodem_session *, short *, unsigned char);
144 void ZResetTimeout(struct zmodem_session *, short);
145 void ZShHdr(struct zmodem_session *, unsigned char);
146 void ZPutBin(struct zmodem_session *, short *, unsigned char);
147 void ZSbHdr(struct zmodem_session *, unsigned char);
148 void ZStoHdr(struct zmodem_session *, unsigned long);
149 long ZRclHdr(struct zmodem_session *);
150 void ZSendRInit(struct zmodem_session *);
151 void ZSendRQInit(struct zmodem_session *);
152 void ZSendRPOS(struct zmodem_session *);
153 void ZSendACK(struct zmodem_session *);
154 void ZSendNAK(struct zmodem_session *);
155 void ZSendEOF(struct zmodem_session *);
156 void ZSendFIN(struct zmodem_session *);
157 void ZSendSkip(struct zmodem_session *);
158 void ZSendCancel(struct zmodem_session *);
159 void ZSendInitHdr(struct zmodem_session *);
160 void ZSendInitDat(struct zmodem_session *);
161 void ZSendFileHdr(struct zmodem_session *);
162 void ZSendFileDat(struct zmodem_session *);
163 void ZSendDataHdr(struct zmodem_session *);
164 void ZSendDataDat(struct zmodem_session *);
165 bool ZCheckHdr(struct zmodem_session *);
166 void ZParseRInit(struct zmodem_session *);
167 bool ZParseSInit(struct zmodem_session *);
168 void ZParseHdr(struct zmodem_session *);
169 bool ZCreateTemporaryFile(struct zmodem_session *);
170 bool ZParseFile(struct zmodem_session *);
171 bool ZWriteData(struct zmodem_session *);
172 void ZCheckData(struct zmodem_session *);
173
174 #ifdef ZMODEM_DEBUG
175
176 static const char *
177 hdrtype_name(short type)
178 {
179 static const char *s[] = {
180 "ZRQINIT",
181 "ZRINIT",
182 "ZSINIT",
183 "ZACK",
184 "ZFILE",
185 "ZSKIP",
186 "ZNAK",
187 "ZABORT",
188 "ZFIN",
189 "ZRPOS",
190 "ZDATA",
191 "ZEOF",
192 "ZFERR",
193 "ZCRC",
194 "ZCHALLENGE",
195 "ZCOMPL",
196 "ZCAN",
197 "ZFREECNT",
198 "ZCOMMAND",
199 "ZSTDERR",
200 };
201
202 if (type >= ZRQINIT && type <= ZSTDERR)
203 return (s[type]);
204
205 return "";
206 }
207
208 static const char *
209 state_name(struct zmodem_session *zs)
210 {
211 static const char *s[] = {
212 "",
213 "Z_RecvInit",
214 "Z_RecvInit2",
215 "Z_RecvData",
216 "Z_RecvFIN",
217 "Z_SendInit",
218 "Z_SendInitHdr",
219 "Z_SendInitDat",
220 "Z_SendFileHdr",
221 "Z_SendFileDat",
222 "Z_SendDataHdr",
223 "Z_SendDataDat",
224 "Z_SendDataDat2",
225 "Z_SendEOF",
226 "Z_SendFIN",
227 "Z_SendSkip",
228 "Z_Cancel",
229 "Z_End",
230 };
231
232 if (zs->ZState >= Z_RecvInit && zs->ZState <= Z_End)
233 return (s[zs->ZState]);
234
235 return "";
236 }
237
238 #endif /* ZMODEM_DEBUG */
239
240 struct zmodem_session *
241 ZCreateSender(struct session *session, FILE *fp, char *file_name)
242 {
243 struct zmodem_session *zs;
244
245 if (!fp)
246 return NULL;
247
248 zs = xmalloczero(sizeof(struct zmodem_session));
249 if (zs == NULL)
250 return NULL;
251 zs->session = session;
252 zs->file = fp;
253 strlcpy(zs->file_name, file_name, sizeof(zs->file_name));
254
255 fseek(zs->file, 0, SEEK_END);
256 zs->file_size = ftell(zs->file);
257 fseek(zs->file, 0, SEEK_SET);
258
259 zs->BinFlag = true;
260 zs->ZMode = IdZAutoS;
261
262 return zs;
263 }
264
265 struct zmodem_session *
266 ZCreateReceiver(struct session *session, char *path)
267 {
268 struct zmodem_session *zs;
269
270 zs = xmalloczero(sizeof(struct zmodem_session));
271 if (zs == NULL)
272 return NULL;
273 zs->session = session;
274 zs->ZMode = IdZAutoR;
275 zs->upload_file_path = xstrdup(path);
276 if (zs->upload_file_path == NULL) {
277 xfree(&zs);
278 return NULL;
279 }
280
281 return zs;
282 }
283
284 short
285 ZRead1Byte(struct zmodem_session *zs, unsigned char *b)
286 {
287 if (zs->DoIACEscape && zs->LastIAC != 0 && zs->LastIAC != IAC) {
288 *b = zs->LastIAC;
289 zs->LastIAC = 0;
290 return 1;
291 }
292
293 if (session_get_char(zs->session, b) == 0)
294 return 0;
295
296 if (zs->DoIACEscape && zs->LastIAC) {
297 if (*b == IAC) {
298 zs->LastIAC = 0;
299 return 1;
300 }
301
302 /*
303 * The IAC was not escaping an IAC, so return IAC this time and
304 * save the byte we just read for the next iteration.
305 */
306 zs->LastIAC = *b;
307 *b = IAC;
308 return 1;
309 }
310
311 if (zs->DoIACEscape && *b == IAC) {
312 zs->LastIAC = IAC;
313 return 0;
314 }
315
316 /* ignore 0x11, 0x13, 0x81 and 0x83 */
317 if (((*b & 0x7F) == 0x11) || ((*b & 0x7F) == 0x13))
318 return 0;
319
320 return 1;
321 }
322
323 void
324 ZPutHex(struct zmodem_session *zs, short *i, unsigned char b)
325 {
326 if (b <= 0x9f)
327 zs->PktOut[*i] = (b >> 4) + 0x30;
328 else
329 zs->PktOut[*i] = (b >> 4) + 0x57;
330
331 (*i)++;
332
333 if ((b & 0x0F) <= 0x09)
334 zs->PktOut[*i] = (b & 0x0F) + 0x30;
335 else
336 zs->PktOut[*i] = (b & 0x0F) + 0x57;
337
338 (*i)++;
339 }
340
341 void
342 ZResetTimeout(struct zmodem_session *zs, short seconds)
343 {
344 zs->TimeOutAt = Time + seconds;
345 }
346
347 bool
348 ZHaveTimedOut(struct zmodem_session *zs)
349 {
350 if (zs->TimeOutAt && Time >= zs->TimeOutAt)
351 return true;
352
353 return false;
354 }
355
356 void
357 ZShHdr(struct zmodem_session *zs, unsigned char HdrType)
358 {
359 short i;
360
361 zs->PktOut[0] = ZPAD;
362 zs->PktOut[1] = ZPAD;
363 zs->PktOut[2] = ZDLE;
364 zs->PktOut[3] = ZHEX;
365 zs->PktOutCount = 4;
366 ZPutHex(zs, &(zs->PktOutCount), HdrType);
367 zs->CRC = UpdateCRC(HdrType, 0);
368 for (i = 0; i <= 3; i++) {
369 ZPutHex(zs, &(zs->PktOutCount), zs->TxHdr[i]);
370 zs->CRC = UpdateCRC(zs->TxHdr[i], zs->CRC);
371 }
372 ZPutHex(zs, &(zs->PktOutCount), HIBYTE(zs->CRC));
373 ZPutHex(zs, &(zs->PktOutCount), LOBYTE(zs->CRC));
374 zs->PktOut[zs->PktOutCount] = 0x8D;
375 zs->PktOutCount++;
376 zs->PktOut[zs->PktOutCount] = 0x8A;
377 zs->PktOutCount++;
378
379 if ((HdrType != ZFIN) && (HdrType != ZACK)) {
380 zs->PktOut[zs->PktOutCount] = XON;
381 zs->PktOutCount++;
382 }
383
384 zs->PktOutPtr = 0;
385 zs->Sending = true;
386
387 #ifdef ZMODEM_DEBUG
388 logger_printf("[%s] ZShHdr: %s", state_name(zs),
389 hdrtype_name(HdrType));
390 #endif
391 }
392
393 /*
394 * In lrzsz, ZDLE (CAN), DLE, XON, XOFF, CR immediately after @, and these
395 * Characters with MSB are escaped.
396 * It seems that it was the same as lrzsz in Tera Term before, but for some
397 * reason CR is always changed to escape target.
398 *
399 * To avoid problems if you connect to ssh / telnet from the destination
400 * LF and GS are also added to the default escape target.
401 * ssh: ~ immediately after LF or CR is treated as an escape character
402 * telnet: GS is the escape character
403 */
404 void
405 ZPutBin(struct zmodem_session *zs, short *i, unsigned char b)
406 {
407 switch (b) {
408 case 0x0D: // CR
409 case 0x8D: // CR | 0x80
410 if (zs->CtlEsc || ((zs->LastSent & 0x7f) == '@')) {
411 zs->PktOut[*i] = ZDLE;
412 (*i)++;
413 b = b ^ 0x40;
414 }
415 break;
416 case 0x0A: // LF
417 case 0x10: // DLE
418 case 0x11: // XON
419 case 0x13: // XOFF
420 case 0x1d: // GS
421 case ZDLE: // CAN(0x18)
422 case 0x8A: // LF | 0x80
423 case 0x90: // DLE | 0x80
424 case 0x91: // XON | 0x80
425 case 0x93: // XOFF | 0x80
426 case 0x9d: // GS | 0x80
427 zs->PktOut[*i] = ZDLE;
428 (*i)++;
429 b = b ^ 0x40;
430 break;
431 case 0xff:
432 if (zs->DoIACEscape) {
433 zs->PktOut[*i] = 0xff;
434 (*i)++;
435 }
436 /* FALLTHROUGH */
437 default:
438 if (zs->CtlEsc && ((b & 0x60) == 0)) {
439 zs->PktOut[*i] = ZDLE;
440 (*i)++;
441 b = b ^ 0x40;
442 }
443 }
444 zs->LastSent = b;
445 zs->PktOut[*i] = b;
446 (*i)++;
447 }
448
449 void
450 ZSbHdr(struct zmodem_session *zs, unsigned char HdrType)
451 {
452 short i;
453
454 zs->PktOut[0] = ZPAD;
455 zs->PktOut[1] = ZDLE;
456 zs->PktOut[2] = ZBIN;
457 zs->PktOutCount = 3;
458 ZPutBin(zs, &(zs->PktOutCount), HdrType);
459 zs->CRC = UpdateCRC(HdrType, 0);
460 for (i = 0; i <= 3; i++) {
461 ZPutBin(zs, &(zs->PktOutCount), zs->TxHdr[i]);
462 zs->CRC = UpdateCRC(zs->TxHdr[i], zs->CRC);
463 }
464 ZPutBin(zs, &(zs->PktOutCount), HIBYTE(zs->CRC));
465 ZPutBin(zs, &(zs->PktOutCount), LOBYTE(zs->CRC));
466
467 zs->PktOutPtr = 0;
468 zs->Sending = true;
469
470 #ifdef ZMODEM_DEBUG
471 logger_printf("[%s] ZSbHdr: %s", state_name(zs),
472 hdrtype_name(HdrType));
473 #endif
474 }
475
476 void
477 ZStoHdr(struct zmodem_session *zs, unsigned long Pos)
478 {
479 zs->TxHdr[ZP0] = LOBYTE(LOWORD(Pos));
480 zs->TxHdr[ZP1] = HIBYTE(LOWORD(Pos));
481 zs->TxHdr[ZP2] = LOBYTE(HIWORD(Pos));
482 zs->TxHdr[ZP3] = HIBYTE(HIWORD(Pos));
483 }
484
485 long
486 ZRclHdr(struct zmodem_session *zs)
487 {
488 unsigned long l;
489
490 l = (unsigned char)(zs->RxHdr[ZP3]);
491 l = (l << 8) + (unsigned char)(zs->RxHdr[ZP2]);
492 l = (l << 8) + (unsigned char)(zs->RxHdr[ZP1]);
493 return ((l << 8) + (unsigned char)(zs->RxHdr[ZP0]));
494 }
495
496 void
497 ZSendRInit(struct zmodem_session *zs)
498 {
499 zs->Pos = 0;
500 /* we only want this much data thrown at us before we ack it */
501 ZStoHdr(zs, ZMODEM_BLOCK_SIZE * 2);
502 zs->TxHdr[ZF0] = CANFC32 | CANFDX;
503 if (zs->CtlEsc)
504 zs->TxHdr[ZF0] = zs->TxHdr[ZF0] | ESCCTL;
505 ZShHdr(zs, ZRINIT);
506 }
507
508 void
509 ZSendRQInit(struct zmodem_session *zs)
510 {
511 ZStoHdr(zs, 0);
512 ZShHdr(zs, ZRQINIT);
513 }
514
515 void
516 ZSendRPOS(struct zmodem_session *zs)
517 {
518 ZStoHdr(zs, zs->Pos);
519 ZShHdr(zs, ZRPOS);
520 ZResetTimeout(zs, zs->TimeOut);
521 }
522
523 void
524 ZSendACK(struct zmodem_session *zs)
525 {
526 ZStoHdr(zs, 0);
527 ZShHdr(zs, ZACK);
528 ZResetTimeout(zs, zs->TimeOut);
529 }
530
531 void
532 ZSendNAK(struct zmodem_session *zs)
533 {
534 ZStoHdr(zs, 0);
535 ZShHdr(zs, ZNAK);
536 }
537
538 void
539 ZSendEOF(struct zmodem_session *zs)
540 {
541 ZStoHdr(zs, zs->Pos);
542 ZShHdr(zs, ZEOF);
543 zs->ZState = Z_SendEOF;
544 }
545
546 void
547 ZSendFIN(struct zmodem_session *zs)
548 {
549 ZStoHdr(zs, 0);
550 ZShHdr(zs, ZFIN);
551 }
552
553 void
554 ZSendSkip(struct zmodem_session *zs)
555 {
556 ZStoHdr(zs, 0);
557 ZShHdr(zs, ZSKIP);
558 }
559
560 void
561 ZSendCancel(struct zmodem_session *zs)
562 {
563 short i;
564
565 for (i = 0; i <= 7; i++)
566 zs->PktOut[i] = ZDLE;
567 for (i = 8; i <= 17; i++)
568 zs->PktOut[i] = 0x08;
569 zs->PktOutCount = 18;
570 zs->PktOutPtr = 0;
571 zs->Sending = true;
572 zs->ZState = Z_Cancel;
573
574 #ifdef ZMODEM_DEBUG
575 logger_printf("[%s] ZSendCancel", state_name(zs));
576 #endif
577 }
578
579 void
580 ZSendInitHdr(struct zmodem_session *zs)
581 {
582 zs->ZState = Z_SendInitHdr;
583 ZStoHdr(zs, 0);
584 if (zs->CtlEsc)
585 zs->TxHdr[ZF0] = ESCCTL;
586 ZShHdr(zs, ZSINIT);
587 }
588
589 void
590 ZSendInitDat(struct zmodem_session *zs)
591 {
592 zs->CRC = 0;
593 zs->PktOutCount = 0;
594 ZPutBin(zs, &(zs->PktOutCount), 0);
595 zs->CRC = UpdateCRC(0, zs->CRC);
596
597 zs->PktOut[zs->PktOutCount] = ZDLE;
598 zs->PktOutCount++;
599 zs->PktOut[zs->PktOutCount] = ZCRCW;
600 zs->PktOutCount++;
601 zs->CRC = UpdateCRC(ZCRCW, zs->CRC);
602
603 ZPutBin(zs, &(zs->PktOutCount), HIBYTE(zs->CRC));
604 ZPutBin(zs, &(zs->PktOutCount), LOBYTE(zs->CRC));
605
606 zs->PktOutPtr = 0;
607 zs->Sending = true;
608 zs->ZState = Z_SendInitDat;
609
610 #ifdef ZMODEM_DEBUG
611 logger_printf("[%s] ZSendInitDat", state_name(zs));
612 #endif
613 }
614
615 void
616 ZSendFileHdr(struct zmodem_session *zs)
617 {
618 zs->ZState = Z_SendFileHdr;
619 ZStoHdr(zs, 0);
620 if (zs->BinFlag)
621 zs->TxHdr[ZF0] = ZCBIN; /* binary file */
622 else
623 zs->TxHdr[ZF0] = ZCNL; /* text file, convert newline */
624 ZSbHdr(zs, ZFILE);
625
626 #ifdef ZMODEM_DEBUG
627 logger_printf("[%s] ZSendFileHdr: %s", state_name(zs),
628 zs->BinFlag ? "binary" : "text");
629 #endif
630 }
631
632 void
633 ZSendFileDat(struct zmodem_session *zs)
634 {
635 short i, j;
636
637 if (!zs->file) {
638 #ifdef ZMODEM_DEBUG
639 logger_printf("[%s] ZSendFileDat: no file, canceling",
640 state_name(zs));
641 #endif
642 ZSendCancel(zs);
643 return;
644 }
645
646 /* file name */
647 strlcpy((char *)zs->PktOut, zs->file_name, sizeof(zs->PktOut));
648 zs->PktOutCount = strlen((char *)zs->PktOut);
649 zs->CRC = 0;
650 for (i = 0; i < zs->PktOutCount; i++)
651 zs->CRC = UpdateCRC(zs->PktOut[i], zs->CRC);
652 ZPutBin(zs, &(zs->PktOutCount), 0);
653 zs->CRC = UpdateCRC(0, zs->CRC);
654
655 /*
656 * ZFILE fields:
657 * size (dec)
658 * mtime (oct)
659 * mode (oct),
660 * serial (oct)
661 * files remaining (dec)
662 * bytes remaining (dec)
663 */
664 snprintf((char *)zs->PktOut + zs->PktOutCount,
665 sizeof(zs->PktOut) - zs->PktOutCount,
666 "%lu 0 100644 0 0", zs->file_size);
667 j = strlen((char *)zs->PktOut + zs->PktOutCount);
668 for (i = 0; i <= j; i++) {
669 zs->CRC = UpdateCRC(zs->PktOut[zs->PktOutCount], zs->CRC);
670 zs->PktOutCount++;
671 }
672
673 ZPutBin(zs, &(zs->PktOutCount), 0);
674 zs->CRC = UpdateCRC(0, zs->CRC);
675 zs->PktOut[zs->PktOutCount] = ZDLE;
676 zs->PktOutCount++;
677 zs->PktOut[zs->PktOutCount] = ZCRCW;
678 zs->PktOutCount++;
679 zs->CRC = UpdateCRC(ZCRCW, zs->CRC);
680
681 ZPutBin(zs, &(zs->PktOutCount), HIBYTE(zs->CRC));
682 ZPutBin(zs, &(zs->PktOutCount), LOBYTE(zs->CRC));
683
684 zs->PktOutPtr = 0;
685 zs->Sending = true;
686 zs->ZState = Z_SendFileDat;
687
688 fseek(zs->file, 0, SEEK_SET);
689
690 #ifdef ZMODEM_DEBUG
691 logger_printf("[%s] ZSendFileDat: ZFILE: ZF0=%x ZF1=%x "
692 "ZF2=%x file=%s size=%lu", state_name(zs), zs->TxHdr[ZF0],
693 zs->TxHdr[ZF1],zs->TxHdr[ZF2], zs->file_name, zs->file_size);
694 #endif
695 }
696
697 void
698 ZSendDataHdr(struct zmodem_session *zs)
699 {
700 zs->ZState = Z_SendDataHdr;
701 ZStoHdr(zs, zs->Pos);
702 ZSbHdr(zs, ZDATA);
703 }
704
705 void
706 ZSendDataDat(struct zmodem_session *zs)
707 {
708 short c;
709 unsigned char b;
710
711 if (zs->Pos >= zs->file_size) {
712 #ifdef ZMODEM_DEBUG
713 logger_printf("[%s] ZSendDataDat: pos %lu >= file size %lu, EOFing",
714 state_name(zs), zs->Pos, zs->file_size);
715 #endif
716 zs->Pos = zs->file_size;
717 ZSendEOF(zs);
718 fclose(zs->file);
719 zs->file = NULL;
720 return;
721 }
722
723 if (zs->Pos != ftell(zs->file))
724 fseek(zs->file, zs->Pos, SEEK_SET);
725
726 zs->CRC = 0;
727 zs->PktOutCount = 0;
728 do {
729 c = fread(&b, 1, 1, zs->file);
730 if (c > 0) {
731 ZPutBin(zs, &(zs->PktOutCount), b);
732 zs->CRC = UpdateCRC(b, zs->CRC);
733 }
734 } while ((c != 0) && (zs->PktOutCount <= zs->MaxDataLen - 2));
735
736 zs->Pos = ftell(zs->file);
737
738 zs->PktOut[zs->PktOutCount] = ZDLE;
739 zs->PktOutCount++;
740 if (zs->Pos >= zs->file_size)
741 b = ZCRCE;
742 else if ((zs->WinSize >= 0) && (zs->Pos - zs->LastPos > zs->WinSize))
743 b = ZCRCQ;
744 else
745 b = ZCRCG;
746 zs->PktOut[zs->PktOutCount] = b;
747 zs->PktOutCount++;
748 zs->CRC = UpdateCRC(b, zs->CRC);
749
750 ZPutBin(zs, &(zs->PktOutCount), HIBYTE(zs->CRC));
751 ZPutBin(zs, &(zs->PktOutCount), LOBYTE(zs->CRC));
752
753 zs->PktOutPtr = 0;
754 zs->Sending = true;
755 if (b == ZCRCQ)
756 zs->ZState = Z_SendDataDat2; /* wait for response from receiver */
757 else
758 zs->ZState = Z_SendDataDat;
759
760 ZResetTimeout(zs, zs->TimeOut);
761
762 #ifdef ZMODEM_DEBUG
763 logger_printf("[%s] ZSendDataDat: pos=%ld", state_name(zs), zs->Pos);
764 #endif
765 }
766
767 bool
768 ZInit(struct zmodem_session *zs)
769 {
770 zs->CtlEsc = false;
771 zs->MaxDataLen = ZMODEM_BLOCK_SIZE;
772 zs->WinSize = 32767;
773
774 if (zs->ZMode == IdZAutoR)
775 zs->ZMode = IdZReceive;
776 else if (zs->ZMode == IdZAutoS)
777 zs->ZMode = IdZSend;
778
779 zs->PktOutCount = 0;
780 zs->Pos = 0;
781 zs->LastPos = 0;
782 zs->ZPktState = Z_PktGetPAD;
783 zs->Sending = false;
784 zs->LastSent = 0;
785 zs->CanCount = 5;
786
787 if (zs->MaxDataLen <= 0)
788 zs->MaxDataLen = ZMODEM_BLOCK_SIZE;
789 if (zs->MaxDataLen < 64)
790 zs->MaxDataLen = 64;
791 if (zs->MaxDataLen > ZMODEM_BLOCK_SIZE)
792 zs->MaxDataLen = ZMODEM_BLOCK_SIZE;
793
794 zs->TimeOut = ZMODEM_TIMEOUT;
795 ZResetTimeout(zs, zs->TimeOut);
796
797 #ifdef ZMODEM_DEBUG
798 logger_printf("[%s] ZInit: %s", state_name(zs),
799 zs->ZMode == IdZReceive ? "receive" : "send");
800 #endif
801
802 switch (zs->ZMode) {
803 case IdZReceive:
804 zs->ZState = Z_RecvInit;
805 /* give the user extra time to pick a file */
806 ZResetTimeout(zs, zs->TimeOut * 3);
807 ZSendRInit(zs);
808 break;
809 case IdZSend:
810 zs->ZState = Z_SendInit;
811 ZSendRQInit(zs);
812 break;
813 }
814
815 return true;
816 }
817
818 void
819 ZTimeOutProc(struct zmodem_session *zs)
820 {
821 #ifdef ZMODEM_DEBUG
822 logger_printf("[%s] ZTimeOutProc", state_name(zs));
823 #endif
824
825 switch (zs->ZState) {
826 case Z_RecvInit:
827 ZSendRInit(zs);
828 break;
829 case Z_RecvInit2:
830 ZSendACK(zs); /* Ack for ZSINIT */
831 break;
832 case Z_RecvData:
833 ZSendRPOS(zs);
834 break;
835 case Z_RecvFIN:
836 zs->ZState = Z_End;
837 break;
838 }
839 }
840
841 bool
842 ZCheckHdr(struct zmodem_session *zs)
843 {
844 short i;
845 bool ok;
846
847 if (zs->CRC32) {
848 zs->CRC3 = 0xFFFFFFFF;
849 for (i = 0; i <= 8; i++)
850 zs->CRC3 = UpdateCRC32(zs->PktIn[i], zs->CRC3);
851 ok = (zs->CRC3 == 0xDEBB20E3);
852 } else {
853 zs->CRC = 0;
854 for (i = 0; i <= 6; i++)
855 zs->CRC = UpdateCRC(zs->PktIn[i], zs->CRC);
856 ok = (zs->CRC == 0);
857 }
858
859 if (ok) {
860 #ifdef ZMODEM_DEBUG
861 logger_printf("[%s] ZCheckHdr: CRC%s ok", state_name(zs),
862 zs->CRC32 ? "32" : "16");
863 #endif
864 } else {
865 #ifdef ZMODEM_DEBUG
866 if (zs->CRC32)
867 logger_printf("[%s] ZCheckHdr: CRC32 check failed "
868 "(0x%lx != 0xDEBB20E3)", state_name(zs), zs->CRC3);
869 else
870 logger_printf("[%s] ZCheckHdr: CRC16 check failed "
871 "(0x%x != 0x0)", state_name(zs), zs->CRC);
872 #endif
873 switch (zs->ZState) {
874 case Z_RecvInit:
875 ZSendRInit(zs);
876 break;
877 case Z_RecvData:
878 ZSendRPOS(zs);
879 break;
880 }
881 }
882 zs->RxType = zs->PktIn[0];
883 for (i = 1; i <= 4; i++)
884 zs->RxHdr[i - 1] = zs->PktIn[i];
885
886 return ok;
887 }
888
889 void
890 ZParseRInit(struct zmodem_session *zs)
891 {
892 short max;
893
894 if ((zs->ZState != Z_SendInit) && (zs->ZState != Z_SendEOF)) {
895 #ifdef ZMODEM_DEBUG
896 logger_printf("[%s] ZParseRInit: not in Init or EOF",
897 state_name(zs));
898 #endif
899 return;
900 }
901
902 if (!zs->file) {
903 #ifdef ZMODEM_DEBUG
904 logger_printf("[%s] ZParseRInit: no file, FINing",
905 state_name(zs));
906 #endif
907 zs->ZState = Z_SendFIN;
908 ZSendFIN(zs);
909 return;
910 }
911
912 if (zs->CtlEsc) {
913 if ((zs->RxHdr[ZF0] & ESCCTL) == 0) {
914 zs->ZState = Z_SendInitHdr;
915 ZSendInitHdr(zs);
916 return;
917 }
918 } else
919 zs->CtlEsc = (zs->RxHdr[ZF0] & ESCCTL) != 0;
920
921 max = (zs->RxHdr[ZP1] << 8) + zs->RxHdr[ZP0];
922 if (max <= 0)
923 max = ZMODEM_BLOCK_SIZE;
924 if (zs->MaxDataLen > max)
925 zs->MaxDataLen = max;
926
927 #ifdef ZMODEM_DEBUG
928 logger_printf("[%s] ZParseRInit: max data len %d", state_name(zs),
929 zs->MaxDataLen);
930 #endif
931
932 zs->ZState = Z_SendFileHdr;
933 ZSendFileHdr(zs);
934 }
935
936 bool
937 ZParseSInit(struct zmodem_session *zs)
938 {
939 if (zs->ZState != Z_RecvInit) {
940 #ifdef ZMODEM_DEBUG
941 logger_printf("[%s] ZParseSInit: state not RecvInit",
942 state_name(zs));
943 #endif
944 return false;
945 }
946
947 zs->ZState = Z_RecvInit2;
948 zs->CtlEsc = zs->CtlEsc || ((zs->RxHdr[ZF0] & ESCCTL) != 0);
949
950 return true;
951 }
952
953 void
954 ZParseHdr(struct zmodem_session *zs)
955 {
956 #ifdef ZMODEM_DEBUG
957 logger_printf("[%s] ZParseHdr: RxType %s", state_name(zs),
958 hdrtype_name(zs->RxType));
959 #endif
960
961 switch (zs->RxType) {
962 case ZRQINIT:
963 if (zs->ZState == Z_RecvInit)
964 ZSendRInit(zs);
965 break;
966 case ZRINIT:
967 ZParseRInit(zs);
968 break;
969 case ZSINIT:
970 zs->ZPktState = Z_PktGetData;
971 if (zs->ZState == Z_RecvInit)
972 ZResetTimeout(zs, zs->TimeOut);
973 break;
974 case ZACK:
975 switch (zs->ZState) {
976 case Z_SendInitDat:
977 ZSendFileHdr(zs);
978 break;
979 case Z_SendDataDat2:
980 zs->LastPos = ZRclHdr(zs);
981 ZResetTimeout(zs, zs->TimeOut);
982 if (zs->Pos == zs->LastPos)
983 ZSendDataDat(zs);
984 else {
985 zs->Pos = zs->LastPos;
986 ZSendDataHdr(zs);
987 }
988 break;
989 }
990 break;
991 case ZFILE:
992 zs->ZPktState = Z_PktGetData;
993 if ((zs->ZState == Z_RecvInit) || (zs->ZState == Z_RecvInit2)) {
994 zs->BinFlag = (zs->RxHdr[ZF0] != ZCNL);
995 ZResetTimeout(zs, zs->TimeOut);
996 }
997 break;
998 case ZSKIP:
999 if (zs->file) {
1000 fclose(zs->file);
1001 /*
1002 * If you try to send a file that exists on the server
1003 * side, ZParseRInit () will double close, so
1004 * Drop the flag here. (2007.12.20 yutaka)
1005 */
1006 zs->file = NULL;
1007 }
1008 ZStoHdr(zs, 0);
1009 if (zs->CtlEsc)
1010 zs->RxHdr[ZF0] = ESCCTL;
1011 zs->ZState = Z_SendInit;
1012 ZParseRInit(zs);
1013 break;
1014 case ZNAK:
1015 switch (zs->ZState) {
1016 case Z_SendInitHdr:
1017 case Z_SendInitDat:
1018 ZSendInitHdr(zs);
1019 break;
1020 case Z_SendFileHdr:
1021 case Z_SendFileDat:
1022 ZSendFileHdr(zs);
1023 break;
1024 }
1025 break;
1026 case ZABORT:
1027 case ZFERR:
1028 if (zs->ZMode == IdZSend) {
1029 zs->ZState = Z_SendFIN;
1030 ZSendFIN(zs);
1031 }
1032 break;
1033 case ZFIN:
1034 if (zs->ZMode == IdZReceive) {
1035 #if 0
1036 zs->ZState = Z_RecvFIN;
1037 #else
1038 /* we only want to receive one file per session, just end */
1039 zs->ZState = Z_End;
1040 #endif
1041 ZSendFIN(zs);
1042 zs->CanCount = 2;
1043 ZResetTimeout(zs, zs->TimeOut);
1044 } else {
1045 zs->ZState = Z_End;
1046 session_output(zs->session, (const char *)"OO", 2);
1047 }
1048 break;
1049 case ZRPOS:
1050 switch (zs->ZState) {
1051 case Z_SendFileDat:
1052 case Z_SendDataHdr:
1053 case Z_SendDataDat:
1054 case Z_SendDataDat2:
1055 case Z_SendEOF:
1056 if (!zs->file) {
1057 #ifdef ZMODEM_DEBUG
1058 logger_printf("[%s] ZParseHdr: ZRPOS with no file, FINing",
1059 state_name(zs));
1060 #endif
1061 zs->ZState = Z_SendFIN;
1062 ZSendFIN(zs);
1063 break;
1064 }
1065 zs->Pos = ZRclHdr(zs);
1066 zs->LastPos = zs->Pos;
1067 #ifdef ZMODEM_DEBUG
1068 logger_printf("[%s] ZParseHdr: pos=%ld", state_name(zs),
1069 zs->Pos);
1070 #endif
1071 ZSendDataHdr(zs);
1072 break;
1073 }
1074 break;
1075 case ZDATA:
1076 if (zs->Pos != ZRclHdr(zs)) {
1077 ZSendRPOS(zs);
1078 return;
1079 }
1080 ZResetTimeout(zs, zs->TimeOut);
1081 zs->ZPktState = Z_PktGetData;
1082 break;
1083 case ZEOF:
1084 if (zs->Pos != ZRclHdr(zs)) {
1085 #ifdef ZMODEM_DEBUG
1086 logger_printf("[%s] ZParseHdr: ZEOF but pos %ld != received %ld",
1087 state_name(zs), zs->Pos, ZRclHdr(zs));
1088 #endif
1089 ZSendRPOS(zs);
1090 return;
1091 }
1092
1093 if (zs->file) {
1094 #ifdef ZMODEM_DEBUG
1095 logger_printf("[%s] ZParseHdr: finished with file at %ld, "
1096 "closing", state_name(zs), zs->Pos);
1097 #endif
1098 ZSendRPOS(zs);
1099 if (zs->CRRecv) {
1100 zs->CRRecv = false;
1101 fwrite("\r", 1, 1, zs->file);
1102 }
1103 fclose(zs->file);
1104 zs->file = NULL;
1105 }
1106 zs->ZState = Z_RecvInit;
1107 ZSendRInit(zs);
1108 break;
1109 }
1110 zs->Quoted = false;
1111 zs->CRC = 0;
1112 zs->CRC3 = 0xFFFFFFFF;
1113 zs->PktInPtr = 0;
1114 zs->PktInCount = 0;
1115 }
1116
1117 bool
1118 ZCreateTemporaryFile(struct zmodem_session *zs)
1119 {
1120 if (zs->upload_file_path[0] == '\0') {
1121 #ifdef ZMODEM_DEBUG
1122 logger_printf("[%s] ZCreateTemporaryFile: no file path",
1123 state_name(zs));
1124 #endif
1125 return false;
1126 }
1127
1128 zs->file = fopen(zs->upload_file_path, "wb+");
1129 if (zs->file == NULL) {
1130 #ifdef ZMODEM_DEBUG
1131 logger_printf("[%s] ZCreateTemporaryFile: opening %s failed",
1132 state_name(zs), zs->upload_file_path);
1133 #endif
1134 return false;
1135 }
1136
1137 #ifdef ZMODEM_DEBUG
1138 logger_printf("[%s] ZCreateTemporaryFile: %s", state_name(zs),
1139 zs->upload_file_path);
1140 #endif
1141
1142 return true;
1143 }
1144
1145 bool
1146 ZParseFile(struct zmodem_session *zs)
1147 {
1148 unsigned char b;
1149 short i;
1150 char *p, *tfile_name;
1151 unsigned long modtime, file_size;
1152 short mode;
1153 short ret;
1154
1155 if ((zs->ZState != Z_RecvInit) && (zs->ZState != Z_RecvInit2)) {
1156 #ifdef ZMODEM_DEBUG
1157 logger_printf("[%s] ZParseFile: state not RecvInit/2",
1158 state_name(zs));
1159 #endif
1160 return false;
1161 }
1162
1163 zs->CRRecv = false;
1164
1165 /* file name */
1166 zs->PktIn[zs->PktInPtr] = '\0';
1167
1168 /* don't allow paths in file name */
1169 tfile_name = (char *)&zs->PktIn;
1170 i = 0;
1171 while (tfile_name[i] != '\0') {
1172 if (tfile_name[i] == '/') {
1173 tfile_name += i + 1;
1174 i = 0;
1175 }
1176 i++;
1177 }
1178
1179 #ifdef ZMODEM_DEBUG
1180 logger_printf("[%s] ZParseFile: path \"%s\" -> \"%s\"",
1181 state_name(zs), (char *)&zs->PktIn, tfile_name);
1182 #endif
1183
1184 if (tfile_name[0] == '\0')
1185 return false;
1186
1187 strlcpy(zs->file_name, tfile_name, sizeof(zs->file_name));
1188
1189 if (!ZCreateTemporaryFile(zs)) {
1190 zs->file_name[0] = '\0';
1191 return false;
1192 }
1193
1194 /* file size */
1195 i = strlen((char *)zs->PktIn) + 1;
1196 file_size = 0;
1197 do {
1198 b = zs->PktIn[i];
1199 if ((b >= 0x30) && (b <= 0x39))
1200 file_size = (file_size * 10) + b - 0x30;
1201 i++;
1202 } while ((b >= 0x30) && (b <= 0x39));
1203 zs->file_size = file_size;
1204
1205 /* file mtime */
1206 p = (char *)zs->PktIn + i;
1207 zs->file_mtime = 0;
1208 if (*p) {
1209 ret = sscanf(p, "%lo%o", &modtime, &mode);
1210 if (ret >= 1)
1211 zs->file_mtime = modtime;
1212 }
1213
1214 zs->Pos = 0;
1215 fseek(zs->file, 0, SEEK_SET);
1216
1217 zs->ZState = Z_RecvData;
1218 ZStoHdr(zs, 0);
1219
1220 /* set timeout for data */
1221 ZResetTimeout(zs, zs->TimeOut);
1222
1223 return true;
1224 }
1225
1226 bool
1227 ZWriteData(struct zmodem_session *zs)
1228 {
1229 short i;
1230 unsigned char b;
1231
1232 if (zs->ZState != Z_RecvData) {
1233 #ifdef ZMODEM_DEBUG
1234 logger_printf("[%s] ZWriteData: state != RecvData", state_name(zs));
1235 #endif
1236 return false;
1237 }
1238
1239 zs->TimeOutAt = 0;
1240
1241 if (zs->BinFlag)
1242 fwrite(zs->PktIn, zs->PktInPtr, 1, zs->file);
1243 else
1244 for (i = 0; i <= zs->PktInPtr - 1; i++) {
1245 b = zs->PktIn[i];
1246 if ((b == 0x0A) && (!zs->CRRecv))
1247 fwrite("\015", 1, 1, zs->file);
1248 if (zs->CRRecv && (b != 0x0A))
1249 fwrite("\012", 1, 1, zs->file);
1250 zs->CRRecv = b == 0x0D;
1251 fwrite(&b, 1, 1, zs->file);
1252 }
1253
1254 #ifdef ZMODEM_DEBUG
1255 logger_printf("[%s] ZWriteData: wrote %d byte(s) at %ld",
1256 state_name(zs), zs->PktInPtr, zs->Pos);
1257 #endif
1258
1259 zs->Pos += zs->PktInPtr;
1260 fseek(zs->file, zs->Pos, SEEK_SET);
1261 ZStoHdr(zs, zs->Pos);
1262
1263 /* set timeout for data */
1264 ZResetTimeout(zs, zs->TimeOut);
1265
1266 return true;
1267 }
1268
1269 void
1270 ZCheckData(struct zmodem_session *zs)
1271 {
1272 bool ok;
1273
1274 /* check CRC */
1275 if ((zs->CRC32 && zs->CRC3 != 0xDEBB20E3) ||
1276 (!zs->CRC32 && zs->CRC != 0)) {
1277 #ifdef ZMODEM_DEBUG
1278 logger_printf("[%s] ZCheckData: CRC%s failed", state_name(zs),
1279 zs->CRC32 ? "32" : "16");
1280 #endif
1281 switch (zs->ZState) {
1282 case Z_RecvInit:
1283 case Z_RecvInit2:
1284 ZSendNAK(zs);
1285 break;
1286 case Z_RecvData:
1287 ZSendRPOS(zs);
1288 break;
1289 }
1290 zs->ZPktState = Z_PktGetPAD;
1291 return;
1292 }
1293
1294 /* parse data */
1295 switch (zs->RxType) {
1296 case ZSINIT:
1297 ok = ZParseSInit(zs);
1298 break;
1299 case ZFILE:
1300 ok = ZParseFile(zs);
1301 break;
1302 case ZDATA:
1303 ok = ZWriteData(zs);
1304 break;
1305 default:
1306 ok = false;
1307 }
1308
1309 if (!ok) {
1310 #ifdef ZMODEM_DEBUG
1311 logger_printf("[%s] ZCheckData: bad RxType %s, skipping",
1312 state_name(zs), hdrtype_name(zs->RxType));
1313 #endif
1314 zs->ZPktState = Z_PktGetPAD;
1315 zs->ZState = Z_SendSkip;
1316 ZSendSkip(zs);
1317 return;
1318 }
1319
1320 if (zs->RxType == ZFILE)
1321 ZShHdr(zs, ZRPOS);
1322
1323 /* next state */
1324 switch (zs->TERM) {
1325 case ZCRCE:
1326 zs->ZPktState = Z_PktGetPAD;
1327 break;
1328 case ZCRCG:
1329 zs->ZPktState = Z_PktGetData;
1330 break;
1331 case ZCRCQ:
1332 zs->ZPktState = Z_PktGetData;
1333 if (zs->RxType != ZFILE)
1334 ZShHdr(zs, ZACK);
1335 break;
1336 case ZCRCW:
1337 zs->ZPktState = Z_PktGetPAD;
1338 if (zs->RxType != ZFILE)
1339 ZShHdr(zs, ZACK);
1340 break;
1341 default:
1342 zs->ZPktState = Z_PktGetPAD;
1343 }
1344
1345 #ifdef ZMODEM_DEBUG
1346 logger_printf("[%s] ZCheckData: TERM %s", state_name(zs),
1347 hdrtype_name(zs->TERM));
1348 #endif
1349
1350 if (zs->ZPktState == Z_PktGetData) {
1351 zs->Quoted = false;
1352 zs->CRC = 0;
1353 zs->CRC3 = 0xFFFFFFFF;
1354 zs->PktInPtr = 0;
1355 zs->PktInCount = 0;
1356 }
1357 }
1358
1359 bool
1360 ZParse(struct zmodem_session *zs)
1361 {
1362 unsigned char b;
1363 short c;
1364
1365 do {
1366 /* Send packet */
1367 if (zs->Sending) {
1368 c = 1;
1369 while ((c > 0) && (zs->PktOutCount > 0)) {
1370 c = session_output(zs->session,
1371 (const char *)&(zs->PktOut[zs->PktOutPtr]),
1372 zs->PktOutCount);
1373 zs->PktOutPtr = zs->PktOutPtr + c;
1374 zs->PktOutCount = zs->PktOutCount - c;
1375 }
1376 if (zs->PktOutCount <= 0)
1377 zs->Sending = false;
1378 if ((zs->ZMode == IdZReceive) && (zs->PktOutCount > 0))
1379 return true;
1380 }
1381
1382 c = ZRead1Byte(zs, &b);
1383 while (c > 0) {
1384 if (zs->ZState == Z_RecvFIN) {
1385 if (b == 'O')
1386 zs->CanCount--;
1387 if (zs->CanCount <= 0) {
1388 zs->ZState = Z_End;
1389 return false;
1390 }
1391 } else {
1392 switch (b) {
1393 case ZDLE:
1394 zs->CanCount--;
1395 if (zs->CanCount <= 0) {
1396 zs->ZState = Z_End;
1397 return false;
1398 }
1399 break;
1400 default:
1401 zs->CanCount = 5;
1402 }
1403 }
1404
1405 switch (zs->ZPktState) {
1406 case Z_PktGetPAD:
1407 switch (b) {
1408 case ZPAD:
1409 zs->ZPktState = Z_PktGetDLE;
1410 break;
1411 }
1412 break;
1413 case Z_PktGetDLE:
1414 switch (b) {
1415 case ZPAD:
1416 break;
1417 case ZDLE:
1418 zs->ZPktState = Z_PktHdrFrm;
1419 break;
1420 default:
1421 zs->ZPktState = Z_PktGetPAD;
1422 }
1423 break;
1424 case Z_PktHdrFrm: /* Get header format type */
1425 switch (b) {
1426 case ZBIN:
1427 zs->CRC32 = false;
1428 zs->PktInCount = 7;
1429 zs->ZPktState = Z_PktGetBin;
1430 break;
1431 case ZHEX:
1432 zs->HexLo = false;
1433 zs->CRC32 = false;
1434 zs->PktInCount = 7;
1435 zs->ZPktState = Z_PktGetHex;
1436 break;
1437 case ZBIN32:
1438 zs->CRC32 = true;
1439 zs->PktInCount = 9;
1440 zs->ZPktState = Z_PktGetBin;
1441 break;
1442 default:
1443 zs->ZPktState = Z_PktGetPAD;
1444 }
1445 zs->Quoted = false;
1446 zs->PktInPtr = 0;
1447 break;
1448 case Z_PktGetBin:
1449 switch (b) {
1450 case ZDLE:
1451 zs->Quoted = true;
1452 break;
1453 default:
1454 if (zs->Quoted) {
1455 switch (b) {
1456 case ZRUB0:
1457 b = 0x7f;
1458 break;
1459 case ZRUB1:
1460 b = 0xff;
1461 break;
1462 default:
1463 b = b ^ 0x40;
1464 }
1465 zs->Quoted = false;
1466 }
1467
1468 if (zs->PktInPtr >= sizeof(zs->PktIn)) {
1469 zs->ZPktState = Z_PktGetPAD;
1470 break;
1471 }
1472 zs->PktIn[zs->PktInPtr] = b;
1473 zs->PktInPtr++;
1474 zs->PktInCount--;
1475 if (zs->PktInCount == 0) {
1476 zs->ZPktState = Z_PktGetPAD;
1477 if (ZCheckHdr(zs))
1478 ZParseHdr(zs);
1479 }
1480 }
1481 break;
1482 case Z_PktGetHex:
1483 if (b <= '9')
1484 b = b - 0x30;
1485 else if ((b >= 'a') && (b <= 'f'))
1486 b = b - 0x57;
1487 else {
1488 zs->ZPktState = Z_PktGetPAD;
1489 return true;
1490 }
1491
1492 if (zs->HexLo) {
1493 zs->PktIn[zs->PktInPtr] =
1494 zs->PktIn[zs->PktInPtr] + b;
1495 zs->HexLo = false;
1496 zs->PktInPtr++;
1497 zs->PktInCount--;
1498 if (zs->PktInCount <= 0) {
1499 zs->ZPktState = Z_PktGetHexEOL;
1500 zs->PktInCount = 2;
1501 }
1502 } else {
1503 zs->PktIn[zs->PktInPtr] = b << 4;
1504 zs->HexLo = true;
1505 }
1506 break;
1507 case Z_PktGetHexEOL:
1508 zs->PktInCount--;
1509 if (zs->PktInCount <= 0) {
1510 zs->ZPktState = Z_PktGetPAD;
1511 if (ZCheckHdr(zs))
1512 ZParseHdr(zs);
1513 }
1514 break;
1515 case Z_PktGetData:
1516 switch (b) {
1517 case ZDLE:
1518 zs->Quoted = true;
1519 break;
1520 default:
1521 if (zs->Quoted) {
1522 switch (b) {
1523 case ZCRCE:
1524 case ZCRCG:
1525 case ZCRCQ:
1526 case ZCRCW:
1527 zs->TERM = b;
1528 if (zs->CRC32)
1529 zs->PktInCount = 4;
1530 else
1531 zs->PktInCount = 2;
1532 zs->ZPktState = Z_PktGetCRC;
1533 break;
1534 case ZRUB0:
1535 b = 0x7F;
1536 break;
1537 case ZRUB1:
1538 b = 0xFF;
1539 break;
1540 default:
1541 b = b ^ 0x40;
1542 }
1543 zs->Quoted = false;
1544 }
1545
1546 if (zs->CRC32)
1547 zs->CRC3 = UpdateCRC32(b, zs->CRC3);
1548 else
1549 zs->CRC = UpdateCRC(b, zs->CRC);
1550
1551 if (zs->ZPktState == Z_PktGetData) {
1552 if (zs->PktInPtr < ZMODEM_BLOCK_SIZE) {
1553 zs->PktIn[zs->PktInPtr] = b;
1554 zs->PktInPtr++;
1555 } else
1556 zs->ZPktState = Z_PktGetPAD;
1557 }
1558 }
1559 break;
1560 case Z_PktGetCRC:
1561 switch (b) {
1562 case ZDLE:
1563 zs->Quoted = true;
1564 break;
1565 default:
1566 if (zs->Quoted) {
1567 switch (b) {
1568 case ZRUB0:
1569 b = 0x7F;
1570 break;
1571 case ZRUB1:
1572 b = 0xFF;
1573 break;
1574 default:
1575 b = b ^ 0x40;
1576 }
1577 zs->Quoted = false;
1578 }
1579 if (zs->CRC32)
1580 zs->CRC3 = UpdateCRC32(b, zs->CRC3);
1581 else
1582 zs->CRC = UpdateCRC(b, zs->CRC);
1583 zs->PktInCount--;
1584 if (zs->PktInCount <= 0)
1585 ZCheckData(zs);
1586 }
1587 break;
1588 }
1589 c = ZRead1Byte(zs, &b);
1590 }
1591
1592 if (!zs->Sending)
1593 switch (zs->ZState) {
1594 case Z_SendInitHdr:
1595 ZSendInitDat(zs);
1596 break;
1597 case Z_SendFileHdr:
1598 ZSendFileDat(zs);
1599 break;
1600 case Z_SendDataHdr:
1601 case Z_SendDataDat:
1602 ZSendDataDat(zs);
1603 break;
1604 case Z_Cancel:
1605 zs->ZState = Z_End;
1606 break;
1607 }
1608
1609 if (zs->Sending && (zs->PktOutCount > 0))
1610 return true;
1611 } while (zs->Sending);
1612
1613 if (zs->ZState == Z_End)
1614 return false;
1615
1616 return true;
1617 }
1618
1619 void
1620 ZCancel(struct zmodem_session *zs)
1621 {
1622 #ifdef ZMODEM_DEBUG
1623 logger_printf("[%s] ZCancel", state_name(zs));
1624 #endif
1625
1626 ZSendCancel(zs);
1627 }
1628
1629 void
1630 ZDestroy(struct zmodem_session *zs)
1631 {
1632 #ifdef ZMODEM_DEBUG
1633 logger_printf("[%s] ZDestroy", state_name(zs));
1634 #endif
1635
1636 if (zs->file)
1637 fclose(zs->file);
1638 if (zs->upload_file_path)
1639 xfree(&zs->upload_file_path);
1640 xfree(&zs);
1641 }