AmendHub

Download

jcs

/

subtext

/

zmodem.c

 

(View History)

jcs   zmodem: Set ZP0 to something in ZRINIT Latest amendment: 502 on 2023-05-01

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 - 1; 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 || zs->ZMode == IdZAutoS) {
775 if (zs->ZMode == IdZAutoR) {
776 zs->ZMode = IdZReceive;
777 session_output(zs->session, (const char *)'0', 1);
778 } else {
779 zs->ZMode = IdZSend;
780 session_output(zs->session, (const char *)'1', 1);
781 }
782 session_output(zs->session, (const char *)'0', 1);
783 session_output(zs->session, (const char *)'B', 1);
784 session_output(zs->session, (const char *)ZDLE, 1);
785 session_output(zs->session, (const char *)ZPAD, 1);
786 }
787
788 zs->PktOutCount = 0;
789 zs->Pos = 0;
790 zs->LastPos = 0;
791 zs->ZPktState = Z_PktGetPAD;
792 zs->Sending = false;
793 zs->LastSent = 0;
794 zs->CanCount = 5;
795
796 if (zs->MaxDataLen <= 0)
797 zs->MaxDataLen = ZMODEM_BLOCK_SIZE;
798 if (zs->MaxDataLen < 64)
799 zs->MaxDataLen = 64;
800 if (zs->MaxDataLen > ZMODEM_BLOCK_SIZE)
801 zs->MaxDataLen = ZMODEM_BLOCK_SIZE;
802
803 zs->TimeOut = ZMODEM_TIMEOUT;
804 ZResetTimeout(zs, zs->TimeOut);
805
806 #ifdef ZMODEM_DEBUG
807 logger_printf("[%s] ZInit: %s", state_name(zs),
808 zs->ZMode == IdZReceive ? "receive" : "send");
809 #endif
810
811 switch (zs->ZMode) {
812 case IdZReceive:
813 zs->ZState = Z_RecvInit;
814 /* give the user extra time to pick a file */
815 ZResetTimeout(zs, zs->TimeOut * 3);
816 ZSendRInit(zs);
817 break;
818 case IdZSend:
819 zs->ZState = Z_SendInit;
820 ZSendRQInit(zs);
821 break;
822 }
823
824 return true;
825 }
826
827 void
828 ZTimeOutProc(struct zmodem_session *zs)
829 {
830 #ifdef ZMODEM_DEBUG
831 logger_printf("[%s] ZTimeOutProc", state_name(zs));
832 #endif
833
834 switch (zs->ZState) {
835 case Z_RecvInit:
836 ZSendRInit(zs);
837 break;
838 case Z_RecvInit2:
839 ZSendACK(zs); /* Ack for ZSINIT */
840 break;
841 case Z_RecvData:
842 ZSendRPOS(zs);
843 break;
844 case Z_RecvFIN:
845 zs->ZState = Z_End;
846 break;
847 }
848 }
849
850 bool
851 ZCheckHdr(struct zmodem_session *zs)
852 {
853 short i;
854 bool ok;
855
856 if (zs->CRC32) {
857 zs->CRC3 = 0xFFFFFFFF;
858 for (i = 0; i <= 8; i++)
859 zs->CRC3 = UpdateCRC32(zs->PktIn[i], zs->CRC3);
860 ok = (zs->CRC3 == 0xDEBB20E3);
861 } else {
862 zs->CRC = 0;
863 for (i = 0; i <= 6; i++)
864 zs->CRC = UpdateCRC(zs->PktIn[i], zs->CRC);
865 ok = (zs->CRC == 0);
866 }
867
868 if (ok) {
869 #ifdef ZMODEM_DEBUG
870 logger_printf("[%s] ZCheckHdr: CRC%s ok", state_name(zs),
871 zs->CRC32 ? "32" : "16");
872 #endif
873 } else {
874 #ifdef ZMODEM_DEBUG
875 if (zs->CRC32)
876 logger_printf("[%s] ZCheckHdr: CRC32 check failed "
877 "(0x%lx != 0xDEBB20E3)", state_name(zs), zs->CRC3);
878 else
879 logger_printf("[%s] ZCheckHdr: CRC16 check failed "
880 "(0x%x != 0x0)", state_name(zs), zs->CRC);
881 #endif
882 switch (zs->ZState) {
883 case Z_RecvInit:
884 ZSendRInit(zs);
885 break;
886 case Z_RecvData:
887 ZSendRPOS(zs);
888 break;
889 }
890 }
891 zs->RxType = zs->PktIn[0];
892 for (i = 1; i <= 4; i++)
893 zs->RxHdr[i - 1] = zs->PktIn[i];
894
895 return ok;
896 }
897
898 void
899 ZParseRInit(struct zmodem_session *zs)
900 {
901 short max;
902
903 if ((zs->ZState != Z_SendInit) && (zs->ZState != Z_SendEOF)) {
904 #ifdef ZMODEM_DEBUG
905 logger_printf("[%s] ZParseRInit: not in Init or EOF",
906 state_name(zs));
907 #endif
908 return;
909 }
910
911 if (!zs->file) {
912 #ifdef ZMODEM_DEBUG
913 logger_printf("[%s] ZParseRInit: no file, FINing",
914 state_name(zs));
915 #endif
916 zs->ZState = Z_SendFIN;
917 ZSendFIN(zs);
918 return;
919 }
920
921 if (zs->CtlEsc) {
922 if ((zs->RxHdr[ZF0] & ESCCTL) == 0) {
923 zs->ZState = Z_SendInitHdr;
924 ZSendInitHdr(zs);
925 return;
926 }
927 } else
928 zs->CtlEsc = (zs->RxHdr[ZF0] & ESCCTL) != 0;
929
930 max = (zs->RxHdr[ZP1] << 8) + zs->RxHdr[ZP0];
931 if (max <= 0)
932 max = ZMODEM_BLOCK_SIZE;
933 if (zs->MaxDataLen > max)
934 zs->MaxDataLen = max;
935
936 #ifdef ZMODEM_DEBUG
937 logger_printf("[%s] ZParseRInit: max data len %d", state_name(zs),
938 zs->MaxDataLen);
939 #endif
940
941 zs->ZState = Z_SendFileHdr;
942 ZSendFileHdr(zs);
943 }
944
945 bool
946 ZParseSInit(struct zmodem_session *zs)
947 {
948 if (zs->ZState != Z_RecvInit) {
949 #ifdef ZMODEM_DEBUG
950 logger_printf("[%s] ZParseSInit: state not RecvInit",
951 state_name(zs));
952 #endif
953 return false;
954 }
955
956 zs->ZState = Z_RecvInit2;
957 zs->CtlEsc = zs->CtlEsc || ((zs->RxHdr[ZF0] & ESCCTL) != 0);
958
959 return true;
960 }
961
962 void
963 ZParseHdr(struct zmodem_session *zs)
964 {
965 #ifdef ZMODEM_DEBUG
966 logger_printf("[%s] ZParseHdr: RxType %s", state_name(zs),
967 hdrtype_name(zs->RxType));
968 #endif
969
970 switch (zs->RxType) {
971 case ZRQINIT:
972 if (zs->ZState == Z_RecvInit)
973 ZSendRInit(zs);
974 break;
975 case ZRINIT:
976 ZParseRInit(zs);
977 break;
978 case ZSINIT:
979 zs->ZPktState = Z_PktGetData;
980 if (zs->ZState == Z_RecvInit)
981 ZResetTimeout(zs, zs->TimeOut);
982 break;
983 case ZACK:
984 switch (zs->ZState) {
985 case Z_SendInitDat:
986 ZSendFileHdr(zs);
987 break;
988 case Z_SendDataDat2:
989 zs->LastPos = ZRclHdr(zs);
990 ZResetTimeout(zs, zs->TimeOut);
991 if (zs->Pos == zs->LastPos)
992 ZSendDataDat(zs);
993 else {
994 zs->Pos = zs->LastPos;
995 ZSendDataHdr(zs);
996 }
997 break;
998 }
999 break;
1000 case ZFILE:
1001 zs->ZPktState = Z_PktGetData;
1002 if ((zs->ZState == Z_RecvInit) || (zs->ZState == Z_RecvInit2)) {
1003 zs->BinFlag = (zs->RxHdr[ZF0] != ZCNL);
1004 ZResetTimeout(zs, zs->TimeOut);
1005 }
1006 break;
1007 case ZSKIP:
1008 if (zs->file) {
1009 fclose(zs->file);
1010 /*
1011 * If you try to send a file that exists on the server
1012 * side, ZParseRInit () will double close, so
1013 * Drop the flag here. (2007.12.20 yutaka)
1014 */
1015 zs->file = NULL;
1016 }
1017 ZStoHdr(zs, 0);
1018 if (zs->CtlEsc)
1019 zs->RxHdr[ZF0] = ESCCTL;
1020 zs->ZState = Z_SendInit;
1021 ZParseRInit(zs);
1022 break;
1023 case ZNAK:
1024 switch (zs->ZState) {
1025 case Z_SendInitHdr:
1026 case Z_SendInitDat:
1027 ZSendInitHdr(zs);
1028 break;
1029 case Z_SendFileHdr:
1030 case Z_SendFileDat:
1031 ZSendFileHdr(zs);
1032 break;
1033 }
1034 break;
1035 case ZABORT:
1036 case ZFERR:
1037 if (zs->ZMode == IdZSend) {
1038 zs->ZState = Z_SendFIN;
1039 ZSendFIN(zs);
1040 }
1041 break;
1042 case ZFIN:
1043 if (zs->ZMode == IdZReceive) {
1044 #if 0
1045 zs->ZState = Z_RecvFIN;
1046 #else
1047 /* we only want to receive one file per session, just end */
1048 zs->ZState = Z_End;
1049 #endif
1050 ZSendFIN(zs);
1051 zs->CanCount = 2;
1052 ZResetTimeout(zs, zs->TimeOut);
1053 } else {
1054 zs->ZState = Z_End;
1055 session_output(zs->session, (const char *)"OO", 2);
1056 }
1057 break;
1058 case ZRPOS:
1059 switch (zs->ZState) {
1060 case Z_SendFileDat:
1061 case Z_SendDataHdr:
1062 case Z_SendDataDat:
1063 case Z_SendDataDat2:
1064 case Z_SendEOF:
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 zs->PktIn[zs->PktInPtr] = b;
1469 zs->PktInPtr++;
1470 zs->PktInCount--;
1471 if (zs->PktInCount == 0) {
1472 zs->ZPktState = Z_PktGetPAD;
1473 if (ZCheckHdr(zs))
1474 ZParseHdr(zs);
1475 }
1476 }
1477 break;
1478 case Z_PktGetHex:
1479 if (b <= '9')
1480 b = b - 0x30;
1481 else if ((b >= 'a') && (b <= 'f'))
1482 b = b - 0x57;
1483 else {
1484 zs->ZPktState = Z_PktGetPAD;
1485 return true;
1486 }
1487
1488 if (zs->HexLo) {
1489 zs->PktIn[zs->PktInPtr] =
1490 zs->PktIn[zs->PktInPtr] + b;
1491 zs->HexLo = false;
1492 zs->PktInPtr++;
1493 zs->PktInCount--;
1494 if (zs->PktInCount <= 0) {
1495 zs->ZPktState = Z_PktGetHexEOL;
1496 zs->PktInCount = 2;
1497 }
1498 } else {
1499 zs->PktIn[zs->PktInPtr] = b << 4;
1500 zs->HexLo = true;
1501 }
1502 break;
1503 case Z_PktGetHexEOL:
1504 zs->PktInCount--;
1505 if (zs->PktInCount <= 0) {
1506 zs->ZPktState = Z_PktGetPAD;
1507 if (ZCheckHdr(zs))
1508 ZParseHdr(zs);
1509 }
1510 break;
1511 case Z_PktGetData:
1512 switch (b) {
1513 case ZDLE:
1514 zs->Quoted = true;
1515 break;
1516 default:
1517 if (zs->Quoted) {
1518 switch (b) {
1519 case ZCRCE:
1520 case ZCRCG:
1521 case ZCRCQ:
1522 case ZCRCW:
1523 zs->TERM = b;
1524 if (zs->CRC32)
1525 zs->PktInCount = 4;
1526 else
1527 zs->PktInCount = 2;
1528 zs->ZPktState = Z_PktGetCRC;
1529 break;
1530 case ZRUB0:
1531 b = 0x7F;
1532 break;
1533 case ZRUB1:
1534 b = 0xFF;
1535 break;
1536 default:
1537 b = b ^ 0x40;
1538 }
1539 zs->Quoted = false;
1540 }
1541
1542 if (zs->CRC32)
1543 zs->CRC3 = UpdateCRC32(b, zs->CRC3);
1544 else
1545 zs->CRC = UpdateCRC(b, zs->CRC);
1546
1547 if (zs->ZPktState == Z_PktGetData) {
1548 if (zs->PktInPtr < ZMODEM_BLOCK_SIZE) {
1549 zs->PktIn[zs->PktInPtr] = b;
1550 zs->PktInPtr++;
1551 } else
1552 zs->ZPktState = Z_PktGetPAD;
1553 }
1554 }
1555 break;
1556 case Z_PktGetCRC:
1557 switch (b) {
1558 case ZDLE:
1559 zs->Quoted = true;
1560 break;
1561 default:
1562 if (zs->Quoted) {
1563 switch (b) {
1564 case ZRUB0:
1565 b = 0x7F;
1566 break;
1567 case ZRUB1:
1568 b = 0xFF;
1569 break;
1570 default:
1571 b = b ^ 0x40;
1572 }
1573 zs->Quoted = false;
1574 }
1575 if (zs->CRC32)
1576 zs->CRC3 = UpdateCRC32(b, zs->CRC3);
1577 else
1578 zs->CRC = UpdateCRC(b, zs->CRC);
1579 zs->PktInCount--;
1580 if (zs->PktInCount <= 0)
1581 ZCheckData(zs);
1582 }
1583 break;
1584 }
1585 c = ZRead1Byte(zs, &b);
1586 }
1587
1588 if (!zs->Sending)
1589 switch (zs->ZState) {
1590 case Z_SendInitHdr:
1591 ZSendInitDat(zs);
1592 break;
1593 case Z_SendFileHdr:
1594 ZSendFileDat(zs);
1595 break;
1596 case Z_SendDataHdr:
1597 case Z_SendDataDat:
1598 ZSendDataDat(zs);
1599 break;
1600 case Z_Cancel:
1601 zs->ZState = Z_End;
1602 break;
1603 }
1604
1605 if (zs->Sending && (zs->PktOutCount > 0))
1606 return true;
1607 } while (zs->Sending);
1608
1609 if (zs->ZState == Z_End)
1610 return false;
1611
1612 return true;
1613 }
1614
1615 void
1616 ZCancel(struct zmodem_session *zs)
1617 {
1618 #ifdef ZMODEM_DEBUG
1619 logger_printf("[%s] ZCancel", state_name(zs));
1620 #endif
1621
1622 ZSendCancel(zs);
1623 }
1624
1625 void
1626 ZDestroy(struct zmodem_session *zs)
1627 {
1628 #ifdef ZMODEM_DEBUG
1629 logger_printf("[%s] ZDestroy", state_name(zs));
1630 #endif
1631
1632 if (zs->file)
1633 fclose(zs->file);
1634 if (zs->upload_file_path)
1635 xfree(&zs->upload_file_path);
1636 xfree(&zs);
1637 }