AmendHub

Download

jcs

/

subtext

/

zmodem.c

 

(View History)

jcs   zmodem: Fix compilation with ZMODEM_DEBUG enabled Latest amendment: 270 on 2022-11-07

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