Develop and Download Open Source Software

Browse Subversion Repository

Contents of /trunk/teraterm/teraterm/filesys_log.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 7291 - (show annotations) (download) (as text)
Fri Nov 30 16:28:38 2018 UTC (5 years, 4 months ago) by zmatsuo
Original Path: trunk/teraterm/teraterm/filesys.cpp
File MIME type: text/x-c++src
File size: 47008 byte(s)
extern "C" 削除
1 /*
2 * Copyright (C) 1994-1998 T. Teranishi
3 * (C) 2005-2018 TeraTerm Project
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 */
29
30 /* TERATERM.EXE, file transfer routines */
31 #include "stdafx.h"
32 #include "teraterm.h"
33 #include "tttypes.h"
34 #include "ttftypes.h"
35 #include "tt_res.h"
36 #include "ftdlg.h"
37 #include "protodlg.h"
38 #include "ttwinman.h"
39 #include "commlib.h"
40 #include "ttcommon.h"
41 #include "ttdde.h"
42 #include "ttlib.h"
43 #include "helpid.h"
44 #include "dlglib.h"
45 #include "vtterm.h"
46 #include "win16api.h"
47
48 #include "filesys.h"
49 #include "ftlib.h"
50
51 #include "buffer.h"
52
53 #include <io.h>
54 #include <process.h>
55
56 #define FS_BRACKET_NONE 0
57 #define FS_BRACKET_START 1
58 #define FS_BRACKET_END 2
59
60 PFileVar LogVar = NULL;
61 PFileVar SendVar = NULL;
62 PFileVar FileVar = NULL;
63 static PCHAR ProtoVar = NULL;
64 static int ProtoId;
65
66 static BYTE LogLast = 0;
67 BOOL FileLog = FALSE;
68 BOOL BinLog = FALSE;
69 BOOL DDELog = FALSE;
70 static BOOL FileRetrySend, FileRetryEcho, FileCRSend, FileReadEOF, BinaryMode;
71 static BYTE FileByte;
72
73 #define FILE_SEND_BUF_SIZE 8192
74 struct FileSendHandler {
75 CHAR buf[FILE_SEND_BUF_SIZE];
76 int pos;
77 int end;
78 };
79 static struct FileSendHandler FileSendHandler;
80 static int FileDlgRefresh;
81
82 static int FileBracketMode = FS_BRACKET_NONE;
83 static int FileBracketPtr = 0;
84 static char BracketStartStr[] = "\033[200~";
85 static char BracketEndStr[] = "\033[201~";
86
87 static BOOL FSend = FALSE;
88
89 HWND HWndLog = NULL; //steven add
90
91 static HMODULE HTTFILE = NULL;
92 static int TTFILECount = 0;
93
94 PGetSetupFname GetSetupFname;
95 PGetTransFname GetTransFname;
96 PGetMultiFname GetMultiFname;
97 PGetGetFname GetGetFname;
98 PSetFileVar SetFileVar;
99 PGetXFname GetXFname;
100 PProtoInit ProtoInit;
101 PProtoParse ProtoParse;
102 PProtoTimeOutProc ProtoTimeOutProc;
103 PProtoCancel ProtoCancel;
104 PTTFILESetUILanguageFile TTFILESetUILanguageFile;
105 PTTFILESetFileSendFilter TTFILESetFileSendFilter;
106
107 #define IdGetSetupFname 1
108 #define IdGetTransFname 2
109 #define IdGetMultiFname 3
110 #define IdGetGetFname 4
111 #define IdSetFileVar 5
112 #define IdGetXFname 6
113
114 #define IdProtoInit 7
115 #define IdProtoParse 8
116 #define IdProtoTimeOutProc 9
117 #define IdProtoCancel 10
118
119 #define IdTTFILESetUILanguageFile 11
120 #define IdTTFILESetFileSendFilter 12
121
122 /*
123 Line Head flag for timestamping
124 2007.05.24 Gentaro
125 */
126 enum enumLineEnd {
127 Line_Other = 0,
128 Line_LineHead = 1,
129 Line_FileHead = 2,
130 };
131
132 enum enumLineEnd eLineEnd = Line_LineHead;
133
134
135 // �x�����������p�X���b�h�����b�Z�[�W
136 #define WM_DPC_LOGTHREAD_SEND (WM_APP + 1)
137
138 static void CloseFileSync(PFileVar ptr);
139
140
141 BOOL LoadTTFILE()
142 {
143 BOOL Err;
144
145 if (HTTFILE != NULL)
146 {
147 TTFILECount++;
148 return TRUE;
149 }
150 else
151 TTFILECount = 0;
152
153 HTTFILE = LoadHomeDLL("TTPFILE.DLL");
154 if (HTTFILE == NULL)
155 return FALSE;
156
157 Err = FALSE;
158
159 GetSetupFname = (PGetSetupFname)GetProcAddress(HTTFILE,
160 MAKEINTRESOURCE(IdGetSetupFname));
161 if (GetSetupFname==NULL)
162 Err = TRUE;
163
164 GetTransFname = (PGetTransFname)GetProcAddress(HTTFILE,
165 MAKEINTRESOURCE(IdGetTransFname));
166 if (GetTransFname==NULL)
167 Err = TRUE;
168
169 GetMultiFname = (PGetMultiFname)GetProcAddress(HTTFILE,
170 MAKEINTRESOURCE(IdGetMultiFname));
171 if (GetMultiFname==NULL)
172 Err = TRUE;
173
174 GetGetFname = (PGetGetFname)GetProcAddress(HTTFILE,
175 MAKEINTRESOURCE(IdGetGetFname));
176 if (GetGetFname==NULL)
177 Err = TRUE;
178
179 SetFileVar = (PSetFileVar)GetProcAddress(HTTFILE,
180 MAKEINTRESOURCE(IdSetFileVar));
181 if (SetFileVar==NULL)
182 Err = TRUE;
183
184 GetXFname = (PGetXFname)GetProcAddress(HTTFILE,
185 MAKEINTRESOURCE(IdGetXFname));
186 if (GetXFname==NULL)
187 Err = TRUE;
188
189 ProtoInit = (PProtoInit)GetProcAddress(HTTFILE,
190 MAKEINTRESOURCE(IdProtoInit));
191 if (ProtoInit==NULL)
192 Err = TRUE;
193
194 ProtoParse = (PProtoParse)GetProcAddress(HTTFILE,
195 MAKEINTRESOURCE(IdProtoParse));
196 if (ProtoParse==NULL)
197 Err = TRUE;
198
199 ProtoTimeOutProc = (PProtoTimeOutProc)GetProcAddress(HTTFILE,
200 MAKEINTRESOURCE(IdProtoTimeOutProc));
201 if (ProtoTimeOutProc==NULL)
202 Err = TRUE;
203
204 ProtoCancel = (PProtoCancel)GetProcAddress(HTTFILE,
205 MAKEINTRESOURCE(IdProtoCancel));
206 if (ProtoCancel==NULL)
207 Err = TRUE;
208
209 TTFILESetUILanguageFile = (PTTFILESetUILanguageFile)GetProcAddress(HTTFILE,
210 MAKEINTRESOURCE(IdTTFILESetUILanguageFile));
211 if (TTFILESetUILanguageFile==NULL) {
212 Err = TRUE;
213 }
214 else {
215 TTFILESetUILanguageFile(ts.UILanguageFile);
216 }
217
218 TTFILESetFileSendFilter = (PTTFILESetFileSendFilter)GetProcAddress(HTTFILE,
219 MAKEINTRESOURCE(IdTTFILESetFileSendFilter));
220 if (TTFILESetFileSendFilter==NULL) {
221 Err = TRUE;
222 }
223 else {
224 TTFILESetFileSendFilter(ts.FileSendFilter);
225 }
226
227 if (Err)
228 {
229 FreeLibrary(HTTFILE);
230 HTTFILE = NULL;
231 return FALSE;
232 }
233 else {
234 TTFILECount = 1;
235 return TRUE;
236 }
237 }
238
239 BOOL FreeTTFILE()
240 {
241 if (TTFILECount==0)
242 return FALSE;
243 TTFILECount--;
244 if (TTFILECount>0)
245 return TRUE;
246 if (HTTFILE!=NULL)
247 {
248 FreeLibrary(HTTFILE);
249 HTTFILE = NULL;
250 }
251 return TRUE;
252 }
253
254 static PFileTransDlg FLogDlg = NULL;
255 static PFileTransDlg SendDlg = NULL;
256 static PProtoDlg PtDlg = NULL;
257
258 BOOL OpenFTDlg(PFileVar fv)
259 {
260 PFileTransDlg FTDlg;
261 HWND HFTDlg;
262 char uimsg[MAX_UIMSG];
263
264 FTDlg = new CFileTransDlg();
265
266 fv->StartTime = 0;
267 fv->ProgStat = 0;
268
269 if (fv->OpId != OpLog) {
270 fv->HideDialog = ts.FTHideDialog;
271 }
272
273 if (FTDlg!=NULL)
274 {
275 FTDlg->Create(fv, &cv, &ts);
276 FTDlg->RefreshNum();
277 if (fv->OpId == OpLog) {
278 HWndLog = FTDlg->m_hWnd; // steven add
279 }
280 }
281
282 if (fv->OpId==OpLog)
283 FLogDlg = FTDlg; /* Log */
284 else
285 SendDlg = FTDlg; /* File send */
286
287 HFTDlg=FTDlg->GetSafeHwnd();
288
289 GetDlgItemText(HFTDlg, IDC_TRANS_FILENAME, uimsg, sizeof(uimsg));
290 get_lang_msg("DLG_FILETRANS_FILENAME", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
291 SetDlgItemText(HFTDlg, IDC_TRANS_FILENAME, ts.UIMsg);
292 GetDlgItemText(HFTDlg, IDC_FULLPATH_LABEL, uimsg, sizeof(uimsg));
293 get_lang_msg("DLG_FILETRANS_FULLPATH", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
294 SetDlgItemText(HFTDlg, IDC_FULLPATH_LABEL, ts.UIMsg);
295 GetDlgItemText(HFTDlg, IDC_TRANS_TRANS, uimsg, sizeof(uimsg));
296 get_lang_msg("DLG_FILETRANS_TRNAS", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
297 SetDlgItemText(HFTDlg, IDC_TRANS_TRANS, ts.UIMsg);
298 GetDlgItemText(HFTDlg, IDC_TRANS_ELAPSED, uimsg, sizeof(uimsg));
299 get_lang_msg("DLG_FILETRANS_ELAPSED", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
300 SetDlgItemText(HFTDlg, IDC_TRANS_ELAPSED, ts.UIMsg);
301 GetDlgItemText(HFTDlg, IDCANCEL, uimsg, sizeof(uimsg));
302 get_lang_msg("DLG_FILETRANS_CLOSE", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
303 SetDlgItemText(HFTDlg, IDCANCEL, ts.UIMsg);
304 GetDlgItemText(HFTDlg, IDC_TRANSPAUSESTART, uimsg, sizeof(uimsg));
305 get_lang_msg("DLG_FILETRANS_PAUSE", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
306 SetDlgItemText(HFTDlg, IDC_TRANSPAUSESTART, ts.UIMsg);
307 GetDlgItemText(HFTDlg, IDC_TRANSHELP, uimsg, sizeof(uimsg));
308 get_lang_msg("BTN_HELP", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
309 SetDlgItemText(HFTDlg, IDC_TRANSHELP, ts.UIMsg);
310
311 fv->StartTime = GetTickCount();
312 if (fv->OpId == OpSendFile) {
313 InitDlgProgress(HFTDlg, IDC_TRANSPROGRESS, &fv->ProgStat);
314 ShowWindow(GetDlgItem(HFTDlg, IDC_TRANS_ELAPSED), SW_SHOW);
315 }
316
317 return (FTDlg!=NULL);
318 }
319
320 void ShowFTDlg(WORD OpId)
321 {
322 if (OpId == OpLog) {
323 if (FLogDlg != NULL) {
324 FLogDlg->ShowWindow(SW_SHOWNORMAL);
325 SetForegroundWindow(FLogDlg->GetSafeHwnd());
326 }
327 }
328 else {
329 if (SendDlg != NULL) {
330 SendDlg->ShowWindow(SW_SHOWNORMAL);
331 SetForegroundWindow(SendDlg->GetSafeHwnd());
332 }
333 }
334 }
335
336 BOOL NewFileVar(PFileVar *fv)
337 {
338 if ((*fv)==NULL)
339 {
340 *fv = (PFileVar)malloc(sizeof(TFileVar));
341 if ((*fv)!=NULL)
342 {
343 memset(*fv, 0, sizeof(TFileVar));
344 strncpy_s((*fv)->FullName, sizeof((*fv)->FullName),ts.FileDir, _TRUNCATE);
345 AppendSlash((*fv)->FullName,sizeof((*fv)->FullName));
346 (*fv)->DirLen = strlen((*fv)->FullName);
347 (*fv)->FileOpen = FALSE;
348 (*fv)->OverWrite = ((ts.FTFlag & FT_RENAME) == 0);
349 (*fv)->HMainWin = HVTWin;
350 (*fv)->Success = FALSE;
351 (*fv)->NoMsg = FALSE;
352 (*fv)->HideDialog = FALSE;
353 }
354 }
355
356 return ((*fv)!=NULL);
357 }
358
359 void FreeFileVar(PFileVar *fv)
360 {
361 if ((*fv)!=NULL)
362 {
363 CloseFileSync(*fv);
364 //if ((*fv)->FileOpen) _lclose((*fv)->FileHandle);
365 if ((*fv)->FnStrMemHandle>0)
366 {
367 GlobalUnlock((*fv)->FnStrMemHandle);
368 GlobalFree((*fv)->FnStrMemHandle);
369 }
370 free(*fv);
371 *fv = NULL;
372 }
373 }
374
375 // &h ���z�X�g�����u�� (2007.5.14)
376 // &p ��TCP�|�[�g�������u�� (2009.6.12)
377 void ConvertLogname(char *c, int destlen)
378 {
379 char buf[MAXPATHLEN], buf2[MAXPATHLEN], *p = c;
380 char tmphost[1024];
381 char tmpuser[256+1];
382 DWORD len_user = sizeof(tmpuser);
383
384 memset(buf, 0, sizeof(buf));
385
386 while(*p != '\0') {
387 if (*p == '&' && *(p+1) != '\0') {
388 switch (*(p+1)) {
389 case 'h':
390 if (cv.Open) {
391 if (cv.PortType == IdTCPIP) {
392 // �z�X�g����IPv6�A�h���X�����A�t�@�C�������g�p�����������������������A
393 // �]�v�����������������B
394 // (2013.3.9 yutaka)
395 strncpy_s(tmphost, sizeof(tmphost), ts.HostName, _TRUNCATE);
396 //strncpy_s(tmphost, sizeof(tmphost), "2001:0db8:bd05:01d2:288a:1fc0:0001:10ee", _TRUNCATE);
397 replaceInvalidFileNameChar(tmphost, '_');
398 strncat_s(buf,sizeof(buf), tmphost, _TRUNCATE);
399 }
400 else if (cv.PortType == IdSerial) {
401 strncpy_s(buf2,sizeof(buf2),buf,_TRUNCATE);
402 _snprintf_s(buf, sizeof(buf), _TRUNCATE, "%sCOM%d", buf2, ts.ComPort);
403 }
404 }
405 break;
406 case 'p':
407 if (cv.Open) {
408 if (cv.PortType == IdTCPIP) {
409 char port[6];
410 _snprintf_s(port, sizeof(port), _TRUNCATE, "%d", ts.TCPPort);
411 strncat_s(buf,sizeof(buf),port,_TRUNCATE);
412 }
413 }
414 break;
415 case 'u':
416 if (GetUserName(tmpuser, &len_user) != 0) {
417 strncat_s(buf,sizeof(buf),tmpuser,_TRUNCATE);
418 }
419 break;
420 default:
421 strncpy_s(buf2,sizeof(buf2),p,2);
422 strncat_s(buf,sizeof(buf),buf2,_TRUNCATE);
423 }
424 p++;
425 }
426 else {
427 strncpy_s(buf2,sizeof(buf2),p,1);
428 strncat_s(buf,sizeof(buf),buf2,_TRUNCATE);
429 }
430 p++;
431 }
432 strncpy_s(c, destlen, buf, _TRUNCATE);
433 }
434
435 void FixLogOption()
436 {
437 if (ts.LogBinary) {
438 ts.LogTypePlainText = false;
439 ts.LogTimestamp = false;
440 }
441 }
442
443
444 // �X���b�h���I�����t�@�C�����N���[�Y
445 static void CloseFileSync(PFileVar ptr)
446 {
447 BOOL ret;
448 DWORD code;
449
450 if (!ptr->FileOpen)
451 return;
452
453 if (ptr->LogThread != (HANDLE)-1) {
454 // �X���b�h���I������
455 ret = PostThreadMessage(ptr->LogThreadId, WM_QUIT, 0, 0);
456 if (ret != 0) {
457 // �X���b�h�L���[���G���L���[���������������������������s���B
458 WaitForSingleObject(ptr->LogThread, INFINITE);
459 }
460 else {
461 code = GetLastError();
462 }
463 CloseHandle(ptr->LogThread);
464 ptr->LogThread = (HANDLE)-1;
465 }
466 CloseHandle((HANDLE)ptr->FileHandle);
467 }
468
469 // �x�����������p�X���b�h
470 static unsigned _stdcall DeferredLogWriteThread(void *arg)
471 {
472 MSG msg;
473 PFileVar fv = (PFileVar)arg;
474 PCHAR buf;
475 DWORD buflen;
476 DWORD wrote;
477
478 PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
479
480 // �X���b�h�L���[���������I�������������X���b�h�����������m�����B
481 if (fv->LogThreadEvent != NULL) {
482 SetEvent(fv->LogThreadEvent);
483 }
484
485 while (GetMessage(&msg, NULL, 0, 0) > 0) {
486 switch (msg.message) {
487 case WM_DPC_LOGTHREAD_SEND:
488 buf = (PCHAR)msg.wParam;
489 buflen = (DWORD)msg.lParam;
490 WriteFile((HANDLE)LogVar->FileHandle, buf, buflen, &wrote, NULL);
491 free(buf); // ����������������
492 break;
493
494 case WM_QUIT:
495 goto end;
496 break;
497 }
498 }
499
500 end:
501 _endthreadex(0);
502 return (0);
503 }
504
505
506 BOOL LogStart()
507 {
508 LONG Option;
509 char *logdir;
510 unsigned tid;
511 DWORD ofs, size, written_size;
512 char buf[512];
513 const char *crlf = "\r\n";
514 DWORD crlf_len = 2;
515
516 if ((FileLog) || (BinLog)) return FALSE;
517
518 if (! LoadTTFILE()) return FALSE;
519 if (! NewFileVar(&LogVar))
520 {
521 FreeTTFILE();
522 return FALSE;
523 }
524 LogVar->OpId = OpLog;
525
526 if (strlen(ts.LogDefaultPath) > 0) {
527 logdir = ts.LogDefaultPath;
528 }
529 else if (strlen(ts.FileDir) > 0) {
530 logdir = ts.FileDir;
531 }
532 else {
533 logdir = ts.HomeDir;
534 }
535
536 if (strlen(&(LogVar->FullName[LogVar->DirLen]))==0) {
537 Option = 0;
538 if (ts.LogBinary) {
539 Option |= LOGDLG_BINARY;
540 }
541 if (ts.Append) {
542 Option |= LOGDLG_APPEND;
543 }
544 if (ts.LogTypePlainText) {
545 Option |= LOGDLG_PLAINTEXT;
546 }
547 if (ts.LogTimestamp) {
548 Option |= LOGDLG_TIMESTAMP;
549 }
550 if (ts.LogHideDialog) {
551 Option |= LOGDLG_HIDEDIALOG;
552 }
553 if (ts.LogAllBuffIncludedInFirst) {
554 Option |= LOGDLG_INCSCRBUFF;
555 }
556
557 switch (ts.LogTimestampType) {
558 case TIMESTAMP_LOCAL:
559 // nothing to do
560 break;
561 case TIMESTAMP_UTC:
562 Option |= LOGDLG_UTC;
563 break;
564 case TIMESTAMP_ELAPSED_LOGSTART:
565 Option |= LOGDLG_ELAPSED;
566 break;
567 case TIMESTAMP_ELAPSED_CONNECTED:
568 Option |= LOGDLG_ELAPSED | LOGDLG_ELAPSEDCON;
569 break;
570 default:
571 // not reached
572 break;
573 }
574
575 // ���O���f�t�H���g�t�@�C���������� (2006.8.28 maya)
576 strncat_s(LogVar->FullName, sizeof(LogVar->FullName), ts.LogDefaultName, _TRUNCATE);
577 ParseStrftimeFileName(LogVar->FullName, sizeof(LogVar->FullName));
578 ConvertLogname(LogVar->FullName, sizeof(LogVar->FullName));
579
580 strncpy_s(LogVar->LogDefaultPath, sizeof(LogVar->LogDefaultPath), ts.LogDefaultPath, _TRUNCATE);
581 if (! (*GetTransFname)(LogVar, logdir, GTF_LOG, &Option)) {
582 FreeFileVar(&LogVar);
583 FreeTTFILE();
584 return FALSE;
585 }
586
587 ts.LogBinary = CheckFlag(Option, LOGDLG_BINARY);
588 CheckFlag(Option, LOGDLG_BINARY);
589 ts.Append =
590 CheckFlag(Option, LOGDLG_APPEND);
591 ts.LogTypePlainText =
592 CheckFlag(Option, LOGDLG_PLAINTEXT);
593 ts.LogTimestamp =
594 CheckFlag(Option, LOGDLG_TIMESTAMP);
595 ts.LogHideDialog =
596 CheckFlag(Option, LOGDLG_HIDEDIALOG);
597 ts.LogAllBuffIncludedInFirst =
598 CheckFlag(Option, LOGDLG_INCSCRBUFF);
599
600 if (Option & LOGDLG_ELAPSED) {
601 // �o������
602 if (Option & LOGDLG_ELAPSEDCON) {
603 ts.LogTimestampType = TIMESTAMP_ELAPSED_CONNECTED;
604 }
605 else {
606 ts.LogTimestampType = TIMESTAMP_ELAPSED_LOGSTART;
607 }
608 }
609 else {
610 // �����`��
611 if (Option & LOGDLG_UTC) {
612 ts.LogTimestampType = TIMESTAMP_UTC;
613 }
614 else {
615 ts.LogTimestampType = TIMESTAMP_LOCAL;
616 }
617 }
618 }
619 else {
620 // LogVar->DirLen = 0 ��������������
621 // �t���p�X�E�����p�X������ LogVar->FullName �������������K�v������
622 char FileName[MAX_PATH];
623
624 // �t���p�X��
625 strncpy_s(FileName, sizeof(FileName), LogVar->FullName, _TRUNCATE);
626 ConvFName(logdir, FileName, sizeof(FileName), "", LogVar->FullName, sizeof(LogVar->FullName));
627
628 ParseStrftimeFileName(LogVar->FullName, sizeof(LogVar->FullName));
629 ConvertLogname(LogVar->FullName, sizeof(LogVar->FullName));
630
631 (*SetFileVar)(LogVar);
632
633 FixLogOption();
634 }
635
636 if (ts.LogBinary > 0)
637 {
638 BinLog = TRUE;
639 FileLog = FALSE;
640 if (! CreateBinBuf())
641 {
642 FileTransEnd(OpLog);
643 return FALSE;
644 }
645 }
646 else {
647 BinLog = FALSE;
648 FileLog = TRUE;
649 if (! CreateLogBuf())
650 {
651 FileTransEnd(OpLog);
652 return FALSE;
653 }
654 }
655 cv.LStart = cv.LogPtr;
656 cv.LCount = 0;
657 if (ts.LogHideDialog)
658 LogVar->HideDialog = 1;
659
660 HelpId = HlpFileLog;
661 /* 2007.05.24 Gentaro */
662 eLineEnd = Line_LineHead;
663
664 if (ts.Append > 0)
665 {
666 int dwShareMode = FILE_SHARE_READ;
667 if (!ts.LogLockExclusive) {
668 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
669 }
670 LogVar->FileHandle = CreateFile(LogVar->FullName, GENERIC_WRITE, dwShareMode, NULL,
671 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
672 if (LogVar->FileHandle != INVALID_HANDLE_VALUE){
673 SetFilePointer(LogVar->FileHandle, 0, NULL, FILE_END);
674 /* 2007.05.24 Gentaro
675 If log file already exists,
676 a newline is inserted before the first timestamp.
677 */
678 eLineEnd = Line_FileHead;
679 }
680 }
681 else {
682 int dwShareMode = FILE_SHARE_READ;
683 if (!ts.LogLockExclusive) {
684 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
685 }
686 LogVar->FileHandle = CreateFile(LogVar->FullName, GENERIC_WRITE, dwShareMode, NULL,
687 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
688 }
689 LogVar->FileOpen = (LogVar->FileHandle != INVALID_HANDLE_VALUE);
690 if (! LogVar->FileOpen)
691 {
692 char msg[128];
693
694 // �t�@�C���I�[�v���G���[�������b�Z�[�W�\�������������B(2008.7.9 yutaka)
695 if (LogVar->NoMsg == FALSE) {
696 _snprintf_s(msg, sizeof(msg), _TRUNCATE, "Can not create a `%s' file. (%d)", LogVar->FullName, GetLastError());
697 MessageBox(NULL, msg, "Tera Term: File open error", MB_OK | MB_ICONERROR);
698 }
699
700 FileTransEnd(OpLog);
701 return FALSE;
702 }
703 LogVar->ByteCount = 0;
704
705 // Log rotate configuration
706 LogVar->RotateMode = ts.LogRotate;
707 LogVar->RotateSize = ts.LogRotateSize;
708 LogVar->RotateStep = ts.LogRotateStep;
709
710 // Log rotate���L���������A�����t�@�C���T�C�Y�����������B
711 // �������t�@�C�������������T�C�Y�����[�e�[�g�������������C���B
712 // (2016.4.9 yutaka)
713 if (LogVar->RotateMode != ROTATE_NONE) {
714 size = GetFileSize((HANDLE)LogVar->FileHandle, NULL);
715 if (size != -1)
716 LogVar->ByteCount = size;
717 }
718
719 if (! OpenFTDlg(LogVar)) {
720 FileTransEnd(OpLog);
721 return FALSE;
722 }
723
724 // �x�����������p�X���b�h���N�����B
725 // (2013.4.19 yutaka)
726 // DeferredLogWriteThread �X���b�h���N�������A�X���b�h�L���[�����������������O���A
727 // ���O�t�@�C�����N���[�Y(CloseFileSync)���s���������A�G���L���[�����s���A�f�b�h���b�N
728 // �����������������C�������B
729 // �X���b�h�����������s�������A���O�����C�x���g�I�u�W�F�N�g���g�����A�X���b�h�L���[��
730 // ���������������������������������B���O�t���C�x���g�I�u�W�F�N�g���g���������A
731 // �V�X�e��(Windows OS)�������j�[�N�����O�������K�v�������B
732 // (2016.9.23 yutaka)
733 LogVar->LogThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
734 LogVar->LogThread = (HANDLE)_beginthreadex(NULL, 0, DeferredLogWriteThread, LogVar, 0, &tid);
735 LogVar->LogThreadId = tid;
736 if (LogVar->LogThreadEvent != NULL) {
737 WaitForSingleObject(LogVar->LogThreadEvent, INFINITE);
738 CloseHandle(LogVar->LogThreadEvent);
739 }
740
741 // �����o�b�t�@�������f�[�^�������������o���������A
742 // ���O�������J�n�����B
743 // (2013.9.29 yutaka)
744 if (ts.LogAllBuffIncludedInFirst) {
745 for (ofs = 0 ; ; ofs++ ) {
746 // 1�����s�����������B���������������A�G�X�P�[�v�V�[�P���X�������������B
747 size = BuffGetAnyLineData(ofs, buf, sizeof(buf));
748 if (size == -1)
749 break;
750
751 #if 0
752 if (ts.DeferredLogWriteMode) { // �x����������
753 char *pbuf = (char *)malloc(size + 2);
754 memcpy(pbuf, buf, size);
755 pbuf[size] = '\r';
756 pbuf[size+1] = '\n';
757 Sleep(1); // �X���b�h�L���[�����������������A�R���e�L�X�g�X�C�b�`�������B
758 PostThreadMessage(LogVar->LogThreadId, WM_DPC_LOGTHREAD_SEND, (WPARAM)pbuf, size + 2);
759 } else { // �������B�l�b�g���[�N�o�R�����x���B
760 #endif
761 WriteFile((HANDLE)LogVar->FileHandle, buf, size, &written_size, NULL);
762 WriteFile((HANDLE)LogVar->FileHandle, crlf, crlf_len, &written_size, NULL);
763 #if 0
764 }
765 #endif
766 }
767 }
768
769 return TRUE;
770 }
771
772 void LogPut1(BYTE b)
773 {
774 LogLast = b;
775 cv.LogBuf[cv.LogPtr] = b;
776 cv.LogPtr++;
777 if (cv.LogPtr>=InBuffSize)
778 cv.LogPtr = cv.LogPtr-InBuffSize;
779
780 if (FileLog)
781 {
782 if (cv.LCount>=InBuffSize)
783 {
784 cv.LCount = InBuffSize;
785 cv.LStart = cv.LogPtr;
786 }
787 else
788 cv.LCount++;
789 }
790 else
791 cv.LCount = 0;
792
793 if (DDELog)
794 {
795 if (cv.DCount>=InBuffSize)
796 {
797 cv.DCount = InBuffSize;
798 cv.DStart = cv.LogPtr;
799 }
800 else
801 cv.DCount++;
802 }
803 else {
804 cv.DCount = 0;
805 // ���O���������}�N�����X�g�[���������������C���B
806 // ���O�����������x�}�N�����~�������A�o�b�t�@���C���f�b�N�X�������������������A
807 // ���x�}�N�������������������f�[�^�������������������B
808 // �}�N�������~���������������C���f�b�N�X�����������������������B
809 // (2006.12.26 yutaka)
810 cv.DStart = cv.LogPtr;
811 }
812 }
813
814 void Log1Byte(BYTE b)
815 {
816 if (b==0x0d)
817 {
818 LogLast = b;
819 return;
820 }
821 if ((b==0x0a) && (LogLast==0x0d))
822 LogPut1(0x0d);
823 LogPut1(b);
824 }
825
826 static BOOL Get1(PCHAR Buf, int *Start, int *Count, PBYTE b)
827 {
828 if (*Count<=0) return FALSE;
829 *b = Buf[*Start];
830 (*Start)++;
831 if (*Start>=InBuffSize)
832 *Start = *Start-InBuffSize;
833 (*Count)--;
834 return TRUE;
835 }
836
837
838
839 static CRITICAL_SECTION g_filelog_lock; /* ���b�N�p���� */
840
841 void logfile_lock_initialize(void)
842 {
843 InitializeCriticalSection(&g_filelog_lock);
844 }
845
846 static inline void logfile_lock(void)
847 {
848 EnterCriticalSection(&g_filelog_lock);
849 }
850
851 static inline void logfile_unlock(void)
852 {
853 LeaveCriticalSection(&g_filelog_lock);
854 }
855
856 // �R�����g�����O����������
857 void CommentLogToFile(char *buf, int size)
858 {
859 DWORD wrote;
860
861 if (LogVar == NULL || !LogVar->FileOpen) {
862 char uimsg[MAX_UIMSG];
863 get_lang_msg("MSG_ERROR", uimsg, sizeof(uimsg), "ERROR", ts.UILanguageFile);
864 get_lang_msg("MSG_COMMENT_LOG_OPEN_ERROR", ts.UIMsg, sizeof(ts.UIMsg),
865 "It is not opened by the log file yet.", ts.UILanguageFile);
866 ::MessageBox(NULL, ts.UIMsg, uimsg, MB_OK|MB_ICONEXCLAMATION);
867 return;
868 }
869
870 logfile_lock();
871 WriteFile((HANDLE)LogVar->FileHandle, buf, size, &wrote, NULL);
872 WriteFile((HANDLE)LogVar->FileHandle, "\r\n", 2, &wrote, NULL); // ���s
873 /* Set Line End Flag
874 2007.05.24 Gentaro
875 */
876 eLineEnd = Line_LineHead;
877 logfile_unlock();
878 }
879
880 // ���O�����[�e�[�g�����B
881 // (2013.3.21 yutaka)
882 static void LogRotate(void)
883 {
884 int loopmax = 10000; // XXX
885 char filename[1024];
886 char newfile[1024], oldfile[1024];
887 int i, k;
888 int dwShareMode = FILE_SHARE_READ;
889 unsigned tid;
890
891 if (! LogVar->FileOpen) return;
892
893 if (LogVar->RotateMode == ROTATE_NONE)
894 return;
895
896 if (LogVar->RotateMode == ROTATE_SIZE) {
897 if (LogVar->ByteCount <= LogVar->RotateSize)
898 return;
899 //OutputDebugPrintf("%s: mode %d size %ld\n", __FUNCTION__, LogVar->RotateMode, LogVar->ByteCount);
900 } else {
901 return;
902 }
903
904 logfile_lock();
905 // ���O�T�C�Y���������������B
906 LogVar->ByteCount = 0;
907
908 // �������������t�@�C�����N���[�Y�����A�������t�@�C�����I�[�v�������B
909 CloseFileSync(LogVar);
910 //_lclose(LogVar->FileHandle);
911
912 // �������[�e�[�V�������X�e�b�v�����w����������
913 if (LogVar->RotateStep > 0)
914 loopmax = LogVar->RotateStep;
915
916 for (i = 1 ; i <= loopmax ; i++) {
917 _snprintf_s(filename, sizeof(filename), _TRUNCATE, "%s.%d", LogVar->FullName, i);
918 if (_access_s(filename, 0) != 0)
919 break;
920 }
921 if (i > loopmax) {
922 // �������������������������A�������t�@�C�������p�������B
923 i = loopmax;
924 }
925
926 // ���t�@�C�������l�[���B
927 for (k = i-1 ; k >= 0 ; k--) {
928 if (k == 0)
929 strncpy_s(oldfile, sizeof(oldfile), LogVar->FullName, _TRUNCATE);
930 else
931 _snprintf_s(oldfile, sizeof(oldfile), _TRUNCATE, "%s.%d", LogVar->FullName, k);
932 _snprintf_s(newfile, sizeof(newfile), _TRUNCATE, "%s.%d", LogVar->FullName, k+1);
933 remove(newfile);
934 if (rename(oldfile, newfile) != 0) {
935 OutputDebugPrintf("%s: rename %d\n", __FUNCTION__, errno);
936 }
937 }
938
939 // ���I�[�v��
940 if (!ts.LogLockExclusive) {
941 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
942 }
943 LogVar->FileHandle = CreateFile(LogVar->FullName, GENERIC_WRITE, dwShareMode, NULL,
944 CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
945
946 // �x�����������p�X���b�h���N�����B
947 // (2013.4.19 yutaka)
948 // DeferredLogWriteThread �X���b�h���N�������A�X���b�h�L���[�����������������O���A
949 // ���O�t�@�C�����N���[�Y(CloseFileSync)���s���������A�G���L���[�����s���A�f�b�h���b�N
950 // �����������������C�������B
951 // �X���b�h�����������s�������A���O�����C�x���g�I�u�W�F�N�g���g�����A�X���b�h�L���[��
952 // ���������������������������������B���O�t���C�x���g�I�u�W�F�N�g���g���������A
953 // �V�X�e��(Windows OS)�������j�[�N�����O�������K�v�������B
954 // (2016.9.26 yutaka)
955 LogVar->LogThreadEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
956 LogVar->LogThread = (HANDLE)_beginthreadex(NULL, 0, DeferredLogWriteThread, LogVar, 0, &tid);
957 LogVar->LogThreadId = tid;
958 if (LogVar->LogThreadEvent != NULL) {
959 WaitForSingleObject(LogVar->LogThreadEvent, INFINITE);
960 CloseHandle(LogVar->LogThreadEvent);
961 }
962
963 logfile_unlock();
964
965 }
966
967 void LogToFile()
968 {
969 PCHAR Buf;
970 int Start, Count;
971 BYTE b;
972 PCHAR WriteBuf;
973 DWORD WriteBufMax, WriteBufLen;
974 CHAR tmp[128];
975 DWORD wrote;
976
977 if (! LogVar->FileOpen) return;
978 if (FileLog)
979 {
980 Buf = cv.LogBuf;
981 Start = cv.LStart;
982 Count = cv.LCount;
983 }
984 else if (BinLog)
985 {
986 Buf = cv.BinBuf;
987 Start = cv.BStart;
988 Count = cv.BCount;
989 }
990 else
991 return;
992
993 if (Buf==NULL) return;
994 if (Count==0) return;
995
996 // ���b�N������(2004.8.6 yutaka)
997 logfile_lock();
998
999 if (ts.DeferredLogWriteMode) {
1000 WriteBufMax = 8192;
1001 WriteBufLen = 0;
1002 WriteBuf = (PCHAR)malloc(WriteBufMax);
1003 while (Get1(Buf,&Start,&Count,&b)) {
1004 if (((cv.FilePause & OpLog)==0) && (! cv.ProtoFlag))
1005 {
1006 tmp[0] = 0;
1007 if ( ts.LogTimestamp && eLineEnd ) {
1008 char *strtime = NULL;
1009
1010 switch (ts.LogTimestampType) {
1011 case TIMESTAMP_LOCAL:
1012 strtime = mctimelocal(ts.LogTimestampFormat, FALSE);
1013 break;
1014 case TIMESTAMP_UTC:
1015 strtime = mctimelocal(ts.LogTimestampFormat, TRUE);
1016 break;
1017 case TIMESTAMP_ELAPSED_LOGSTART:
1018 strtime = strelapsed(LogVar->StartTime);
1019 break;
1020 case TIMESTAMP_ELAPSED_CONNECTED:
1021 strtime = strelapsed(cv.ConnectedTime);
1022 break;
1023 }
1024
1025 /* 2007.05.24 Gentaro */
1026 if( eLineEnd == Line_FileHead ){
1027 strncat_s(tmp, sizeof(tmp), "\r\n", _TRUNCATE);
1028 }
1029 strncat_s(tmp, sizeof(tmp), "[", _TRUNCATE);
1030 strncat_s(tmp, sizeof(tmp), strtime, _TRUNCATE);
1031 strncat_s(tmp, sizeof(tmp), "] ", _TRUNCATE);
1032 }
1033
1034 /* 2007.05.24 Gentaro */
1035 if( b == 0x0a ){
1036 eLineEnd = Line_LineHead; /* set endmark*/
1037 }
1038 else {
1039 eLineEnd = Line_Other; /* clear endmark*/
1040 }
1041
1042 if (WriteBufLen >= (WriteBufMax*4/5)) {
1043 WriteBufMax *= 2;
1044 WriteBuf = (PCHAR)realloc(WriteBuf, WriteBufMax);
1045 }
1046 memcpy(&WriteBuf[WriteBufLen], tmp, strlen(tmp));
1047 WriteBufLen += strlen(tmp);
1048 WriteBuf[WriteBufLen++] = b;
1049
1050 (LogVar->ByteCount)++;
1051 }
1052 }
1053
1054 PostThreadMessage(LogVar->LogThreadId, WM_DPC_LOGTHREAD_SEND, (WPARAM)WriteBuf, WriteBufLen);
1055
1056 } else {
1057
1058 while (Get1(Buf,&Start,&Count,&b))
1059 {
1060 if (((cv.FilePause & OpLog)==0) && (! cv.ProtoFlag))
1061 {
1062 if ( ts.LogTimestamp && eLineEnd ) {
1063 char *strtime = NULL;
1064
1065 switch (ts.LogTimestampType) {
1066 case TIMESTAMP_LOCAL:
1067 strtime = mctimelocal(ts.LogTimestampFormat, FALSE);
1068 break;
1069 case TIMESTAMP_UTC:
1070 strtime = mctimelocal(ts.LogTimestampFormat, TRUE);
1071 break;
1072 case TIMESTAMP_ELAPSED_LOGSTART:
1073 strtime = strelapsed(LogVar->StartTime);
1074 break;
1075 case TIMESTAMP_ELAPSED_CONNECTED:
1076 strtime = strelapsed(cv.ConnectedTime);
1077 break;
1078 }
1079 WriteFile((HANDLE)LogVar->FileHandle, "[", 1, &wrote, NULL);
1080 WriteFile((HANDLE)LogVar->FileHandle, strtime, strlen(strtime), &wrote, NULL);
1081 WriteFile((HANDLE)LogVar->FileHandle, "] ", 2, &wrote, NULL);
1082 }
1083
1084 /* 2007.05.24 Gentaro */
1085 if( b == 0x0a ){
1086 eLineEnd = Line_LineHead; /* set endmark*/
1087 }
1088 else {
1089 eLineEnd = Line_Other; /* clear endmark*/
1090 }
1091
1092 WriteFile((HANDLE)LogVar->FileHandle, (PCHAR)&b, 1, &wrote, NULL);
1093 (LogVar->ByteCount)++;
1094 }
1095 }
1096
1097 }
1098
1099 logfile_unlock();
1100
1101 if (FileLog)
1102 {
1103 cv.LStart = Start;
1104 cv.LCount = Count;
1105 }
1106 else {
1107 cv.BStart = Start;
1108 cv.BCount = Count;
1109 }
1110 if (((cv.FilePause & OpLog) !=0) || cv.ProtoFlag) return;
1111 if (FLogDlg!=NULL)
1112 FLogDlg->RefreshNum();
1113
1114 // ���O�E���[�e�[�g
1115 LogRotate();
1116
1117 }
1118
1119 BOOL CreateLogBuf()
1120 {
1121 if (cv.HLogBuf==NULL)
1122 {
1123 cv.HLogBuf = GlobalAlloc(GMEM_MOVEABLE,InBuffSize);
1124 cv.LogBuf = NULL;
1125 cv.LogPtr = 0;
1126 cv.LStart = 0;
1127 cv.LCount = 0;
1128 cv.DStart = 0;
1129 cv.DCount = 0;
1130 }
1131 return (cv.HLogBuf!=NULL);
1132 }
1133
1134 void FreeLogBuf()
1135 {
1136 if ((cv.HLogBuf==NULL) || FileLog || DDELog)
1137 return;
1138 if (cv.LogBuf!=NULL)
1139 GlobalUnlock(cv.HLogBuf);
1140 GlobalFree(cv.HLogBuf);
1141 cv.HLogBuf = NULL;
1142 cv.LogBuf = NULL;
1143 cv.LogPtr = 0;
1144 cv.LStart = 0;
1145 cv.LCount = 0;
1146 cv.DStart = 0;
1147 cv.DCount = 0;
1148 }
1149
1150 BOOL CreateBinBuf()
1151 {
1152 if (cv.HBinBuf==NULL)
1153 {
1154 cv.HBinBuf = GlobalAlloc(GMEM_MOVEABLE,InBuffSize);
1155 cv.BinBuf = NULL;
1156 cv.BinPtr = 0;
1157 cv.BStart = 0;
1158 cv.BCount = 0;
1159 }
1160 return (cv.HBinBuf!=NULL);
1161 }
1162
1163 void FreeBinBuf()
1164 {
1165 if ((cv.HBinBuf==NULL) || BinLog)
1166 return;
1167 if (cv.BinBuf!=NULL)
1168 GlobalUnlock(cv.HBinBuf);
1169 GlobalFree(cv.HBinBuf);
1170 cv.HBinBuf = NULL;
1171 cv.BinBuf = NULL;
1172 cv.BinPtr = 0;
1173 cv.BStart = 0;
1174 cv.BCount = 0;
1175 }
1176
1177 void FileSendStart()
1178 {
1179 LONG Option = 0;
1180
1181 if (! cv.Ready || FSend) return;
1182 if (cv.ProtoFlag)
1183 {
1184 FreeFileVar(&SendVar);
1185 return;
1186 }
1187
1188 if (! LoadTTFILE())
1189 return;
1190 if (! NewFileVar(&SendVar))
1191 {
1192 FreeTTFILE();
1193 return;
1194 }
1195 SendVar->OpId = OpSendFile;
1196
1197 FSend = TRUE;
1198
1199 if (strlen(&(SendVar->FullName[SendVar->DirLen]))==0) {
1200 if (ts.TransBin)
1201 Option |= LOGDLG_BINARY;
1202 SendVar->FullName[0] = 0;
1203 if (! (*GetTransFname)(SendVar, ts.FileDir, GTF_SEND, &Option)) {
1204 FileTransEnd(OpSendFile);
1205 return;
1206 }
1207 ts.TransBin = CheckFlag(Option, LOGDLG_BINARY);
1208 }
1209 else
1210 (*SetFileVar)(SendVar);
1211
1212 SendVar->FileHandle = CreateFile(SendVar->FullName, GENERIC_READ, FILE_SHARE_READ, NULL,
1213 OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
1214 SendVar->FileOpen = (SendVar->FileHandle != INVALID_HANDLE_VALUE);
1215 if (! SendVar->FileOpen)
1216 {
1217 FileTransEnd(OpSendFile);
1218 return;
1219 }
1220 SendVar->ByteCount = 0;
1221 SendVar->FileSize = GetFSize(SendVar->FullName);
1222
1223 TalkStatus = IdTalkFile;
1224 FileRetrySend = FALSE;
1225 FileRetryEcho = FALSE;
1226 FileCRSend = FALSE;
1227 FileReadEOF = FALSE;
1228 FileSendHandler.pos = 0;
1229 FileSendHandler.end = 0;
1230 FileDlgRefresh = 0;
1231
1232 if (BracketedPasteMode()) {
1233 FileBracketMode = FS_BRACKET_START;
1234 FileBracketPtr = 0;
1235 BinaryMode = TRUE;
1236 }
1237 else {
1238 FileBracketMode = FS_BRACKET_NONE;
1239 BinaryMode = ts.TransBin;
1240 }
1241
1242 if (! OpenFTDlg(SendVar))
1243 FileTransEnd(OpSendFile);
1244 }
1245
1246 void FileTransEnd(WORD OpId)
1247 /* OpId = 0: close Log and FileSend
1248 OpLog: close Log
1249 OpSendFile: close FileSend */
1250 {
1251 if (((OpId==0) || (OpId==OpLog)) && (FileLog || BinLog))
1252 {
1253 FileLog = FALSE;
1254 BinLog = FALSE;
1255 if (FLogDlg!=NULL)
1256 {
1257 FLogDlg->DestroyWindow();
1258 FLogDlg = NULL;
1259 HWndLog = NULL; // steven add
1260 }
1261 FreeFileVar(&LogVar);
1262 FreeLogBuf();
1263 FreeBinBuf();
1264 FreeTTFILE();
1265 }
1266
1267 if (((OpId==0) || (OpId==OpSendFile)) && FSend)
1268 {
1269 FSend = FALSE;
1270 TalkStatus = IdTalkKeyb;
1271 if (SendDlg!=NULL)
1272 {
1273 SendDlg->DestroyWindow();
1274 SendDlg = NULL;
1275 }
1276 FreeFileVar(&SendVar);
1277 FreeTTFILE();
1278 }
1279
1280 EndDdeCmnd(0);
1281 }
1282
1283 int FSOut1(BYTE b)
1284 {
1285 if (BinaryMode)
1286 return CommBinaryOut(&cv,(PCHAR)&b,1);
1287 else if ((b>=0x20) || (b==0x09) || (b==0x0A) || (b==0x0D))
1288 return CommTextOut(&cv,(PCHAR)&b,1);
1289 else
1290 return 1;
1291 }
1292
1293 int FSEcho1(BYTE b)
1294 {
1295 if (BinaryMode)
1296 return CommBinaryEcho(&cv,(PCHAR)&b,1);
1297 else
1298 return CommTextEcho(&cv,(PCHAR)&b,1);
1299 }
1300
1301 // �������������������������g��
1302 // - BinaryMode == true
1303 // - FileBracketMode == false
1304 // - cv.TelFlag == false
1305 // - ts.LocalEcho == 0
1306 void FileSendBinayBoost()
1307 {
1308 WORD c, fc;
1309 LONG BCOld;
1310 DWORD read_bytes;
1311
1312 if ((SendDlg == NULL) ||
1313 ((cv.FilePause & OpSendFile) != 0))
1314 return;
1315
1316 BCOld = SendVar->ByteCount;
1317
1318 if (FileRetrySend)
1319 {
1320 c = CommRawOut(&cv, &(FileSendHandler.buf[FileSendHandler.pos]),
1321 FileSendHandler.end - FileSendHandler.pos);
1322 FileSendHandler.pos += c;
1323 FileRetrySend = (FileSendHandler.end != FileSendHandler.pos);
1324 if (FileRetrySend)
1325 return;
1326 }
1327
1328 do {
1329 if (FileSendHandler.pos == FileSendHandler.end) {
1330 ReadFile((HANDLE)SendVar->FileHandle, &(FileSendHandler.buf[0]), sizeof(FileSendHandler.buf), &read_bytes, NULL);
1331 fc = LOWORD(read_bytes);
1332 FileSendHandler.pos = 0;
1333 FileSendHandler.end = fc;
1334 } else {
1335 fc = FileSendHandler.end - FileSendHandler.end;
1336 }
1337
1338 if (fc != 0)
1339 {
1340 c = CommRawOut(&cv, &(FileSendHandler.buf[FileSendHandler.pos]),
1341 FileSendHandler.end - FileSendHandler.pos);
1342 FileSendHandler.pos += c;
1343 FileRetrySend = (FileSendHandler.end != FileSendHandler.pos);
1344 SendVar->ByteCount = SendVar->ByteCount + c;
1345 if (FileRetrySend)
1346 {
1347 if (SendVar->ByteCount != BCOld)
1348 SendDlg->RefreshNum();
1349 return;
1350 }
1351 }
1352 FileDlgRefresh = SendVar->ByteCount;
1353 SendDlg->RefreshNum();
1354 BCOld = SendVar->ByteCount;
1355 if (fc != 0)
1356 return;
1357 } while (fc != 0);
1358
1359 FileTransEnd(OpSendFile);
1360 }
1361
1362 void FileSend()
1363 {
1364 WORD c, fc;
1365 LONG BCOld;
1366 DWORD read_bytes;
1367
1368 if (cv.PortType == IdSerial && ts.FileSendHighSpeedMode &&
1369 BinaryMode && !FileBracketMode && !cv.TelFlag &&
1370 (ts.LocalEcho == 0) && (ts.Baud >= 115200)) {
1371 return FileSendBinayBoost();
1372 }
1373
1374 if ((SendDlg==NULL) ||
1375 ((cv.FilePause & OpSendFile) !=0))
1376 return;
1377
1378 BCOld = SendVar->ByteCount;
1379
1380 if (FileRetrySend)
1381 {
1382 FileRetryEcho = (ts.LocalEcho>0);
1383 c = FSOut1(FileByte);
1384 FileRetrySend = (c==0);
1385 if (FileRetrySend)
1386 return;
1387 }
1388
1389 if (FileRetryEcho)
1390 {
1391 c = FSEcho1(FileByte);
1392 FileRetryEcho = (c==0);
1393 if (FileRetryEcho)
1394 return;
1395 }
1396
1397 do {
1398 if (FileBracketMode == FS_BRACKET_START) {
1399 FileByte = BracketStartStr[FileBracketPtr++];
1400 fc = 1;
1401
1402 if (FileBracketPtr >= sizeof(BracketStartStr) - 1) {
1403 FileBracketMode = FS_BRACKET_END;
1404 FileBracketPtr = 0;
1405 BinaryMode = ts.TransBin;
1406 }
1407 }
1408 else if (! FileReadEOF) {
1409 ReadFile((HANDLE)SendVar->FileHandle, &FileByte, 1, &read_bytes, NULL);
1410 fc = LOWORD(read_bytes);
1411 SendVar->ByteCount = SendVar->ByteCount + fc;
1412
1413 if (FileCRSend && (fc==1) && (FileByte==0x0A)) {
1414 ReadFile((HANDLE)SendVar->FileHandle, &FileByte, 1, &read_bytes, NULL);
1415 fc = LOWORD(read_bytes);
1416 SendVar->ByteCount = SendVar->ByteCount + fc;
1417 }
1418 }
1419 else {
1420 fc = 0;
1421 }
1422
1423 if (fc == 0 && FileBracketMode == FS_BRACKET_END) {
1424 FileReadEOF = TRUE;
1425 FileByte = BracketEndStr[FileBracketPtr++];
1426 fc = 1;
1427 BinaryMode = TRUE;
1428
1429 if (FileBracketPtr >= sizeof(BracketEndStr) - 1) {
1430 FileBracketMode = FS_BRACKET_NONE;
1431 FileBracketPtr = 0;
1432 }
1433 }
1434
1435
1436 if (fc!=0)
1437 {
1438 c = FSOut1(FileByte);
1439 FileCRSend = (ts.TransBin==0) && (FileByte==0x0D);
1440 FileRetrySend = (c==0);
1441 if (FileRetrySend)
1442 {
1443 if (SendVar->ByteCount != BCOld)
1444 SendDlg->RefreshNum();
1445 return;
1446 }
1447 if (ts.LocalEcho>0)
1448 {
1449 c = FSEcho1(FileByte);
1450 FileRetryEcho = (c==0);
1451 if (FileRetryEcho)
1452 return;
1453 }
1454 }
1455 if ((fc==0) || ((SendVar->ByteCount % 100 == 0) && (FileBracketPtr == 0))) {
1456 SendDlg->RefreshNum();
1457 BCOld = SendVar->ByteCount;
1458 if (fc!=0)
1459 return;
1460 }
1461 } while (fc!=0);
1462
1463 FileTransEnd(OpSendFile);
1464 }
1465
1466 void FLogChangeButton(BOOL Pause)
1467 {
1468 if (FLogDlg!=NULL)
1469 FLogDlg->ChangeButton(Pause);
1470 }
1471
1472 void FLogRefreshNum()
1473 {
1474 if (FLogDlg!=NULL)
1475 FLogDlg->RefreshNum();
1476 }
1477
1478 BOOL OpenProtoDlg(PFileVar fv, int IdProto, int Mode, WORD Opt1, WORD Opt2)
1479 {
1480 int vsize;
1481 PProtoDlg pd;
1482 HWND Hpd;
1483 char uimsg[MAX_UIMSG];
1484
1485 ProtoId = IdProto;
1486
1487 switch (ProtoId) {
1488 case PROTO_KMT:
1489 vsize = sizeof(TKmtVar);
1490 break;
1491 case PROTO_XM:
1492 vsize = sizeof(TXVar);
1493 break;
1494 case PROTO_YM:
1495 vsize = sizeof(TYVar);
1496 break;
1497 case PROTO_ZM:
1498 vsize = sizeof(TZVar);
1499 break;
1500 case PROTO_BP:
1501 vsize = sizeof(TBPVar);
1502 break;
1503 case PROTO_QV:
1504 vsize = sizeof(TQVVar);
1505 break;
1506 }
1507 ProtoVar = (PCHAR)malloc(vsize);
1508 if (ProtoVar==NULL)
1509 return FALSE;
1510
1511 switch (ProtoId) {
1512 case PROTO_KMT:
1513 ((PKmtVar)ProtoVar)->KmtMode = Mode;
1514 break;
1515 case PROTO_XM:
1516 ((PXVar)ProtoVar)->XMode = Mode;
1517 ((PXVar)ProtoVar)->XOpt = Opt1;
1518 ((PXVar)ProtoVar)->TextFlag = 1 - (Opt2 & 1);
1519 break;
1520 case PROTO_YM:
1521 ((PYVar)ProtoVar)->YMode = Mode;
1522 ((PYVar)ProtoVar)->YOpt = Opt1;
1523 break;
1524 case PROTO_ZM:
1525 ((PZVar)ProtoVar)->BinFlag = (Opt1 & 1) != 0;
1526 ((PZVar)ProtoVar)->ZMode = Mode;
1527 break;
1528 case PROTO_BP:
1529 ((PBPVar)ProtoVar)->BPMode = Mode;
1530 break;
1531 case PROTO_QV:
1532 ((PQVVar)ProtoVar)->QVMode = Mode;
1533 break;
1534 }
1535
1536 pd = new CProtoDlg();
1537 if (pd==NULL)
1538 {
1539 free(ProtoVar);
1540 ProtoVar = NULL;
1541 return FALSE;
1542 }
1543 pd->Create(fv,&ts);
1544
1545 Hpd=pd->GetSafeHwnd();
1546
1547 GetDlgItemText(Hpd, IDC_PROT_FILENAME, uimsg, sizeof(uimsg));
1548 get_lang_msg("DLG_PROT_FILENAME", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
1549 SetDlgItemText(Hpd, IDC_PROT_FILENAME, ts.UIMsg);
1550 GetDlgItemText(Hpd, IDC_PROT_PROT, uimsg, sizeof(uimsg));
1551 get_lang_msg("DLG_PROT_PROTO", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
1552 SetDlgItemText(Hpd, IDC_PROT_PROT, ts.UIMsg);
1553 GetDlgItemText(Hpd, IDC_PROT_PACKET, uimsg, sizeof(uimsg));
1554 get_lang_msg("DLG_PROT_PACKET", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
1555 SetDlgItemText(Hpd, IDC_PROT_PACKET, ts.UIMsg);
1556 GetDlgItemText(Hpd, IDC_PROT_TRANS, uimsg, sizeof(uimsg));
1557 get_lang_msg("DLG_PROT_TRANS", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
1558 SetDlgItemText(Hpd, IDC_PROT_TRANS, ts.UIMsg);
1559 GetDlgItemText(Hpd, IDC_PROT_ELAPSED, uimsg, sizeof(uimsg));
1560 get_lang_msg("DLG_PROT_ELAPSED", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
1561 SetDlgItemText(Hpd, IDC_PROT_ELAPSED, ts.UIMsg);
1562 GetDlgItemText(Hpd, IDCANCEL, uimsg, sizeof(uimsg));
1563 get_lang_msg("BTN_CANCEL", ts.UIMsg, sizeof(ts.UIMsg), uimsg, ts.UILanguageFile);
1564 SetDlgItemText(Hpd, IDCANCEL, ts.UIMsg);
1565
1566 (*ProtoInit)(ProtoId,FileVar,ProtoVar,&cv,&ts);
1567
1568 PtDlg = pd;
1569 return TRUE;
1570 }
1571
1572 void CloseProtoDlg()
1573 {
1574 if (PtDlg!=NULL)
1575 {
1576 PtDlg->DestroyWindow();
1577 PtDlg = NULL;
1578
1579 ::KillTimer(FileVar->HMainWin,IdProtoTimer);
1580 if ((ProtoId==PROTO_QV) &&
1581 (((PQVVar)ProtoVar)->QVMode==IdQVSend))
1582 CommTextOut(&cv,"\015",1);
1583 if (FileVar->LogFlag)
1584 CloseHandle(FileVar->LogFile);
1585 FileVar->LogFile = 0;
1586 if (ProtoVar!=NULL)
1587 {
1588 free(ProtoVar);
1589 ProtoVar = NULL;
1590 }
1591 }
1592 }
1593
1594 BOOL ProtoStart()
1595 {
1596 if (cv.ProtoFlag)
1597 return FALSE;
1598 if (FSend)
1599 {
1600 FreeFileVar(&FileVar);
1601 return FALSE;
1602 }
1603
1604 if (! LoadTTFILE())
1605 return FALSE;
1606 NewFileVar(&FileVar);
1607
1608 if (FileVar==NULL)
1609 {
1610 FreeTTFILE();
1611 return FALSE;
1612 }
1613 cv.ProtoFlag = TRUE;
1614 return TRUE;
1615 }
1616
1617 void ProtoEnd()
1618 {
1619 if (! cv.ProtoFlag)
1620 return;
1621 cv.ProtoFlag = FALSE;
1622
1623 /* Enable transmit delay (serial port) */
1624 cv.DelayFlag = TRUE;
1625 TalkStatus = IdTalkKeyb;
1626
1627 CloseProtoDlg();
1628
1629 if ((FileVar!=NULL) && FileVar->Success)
1630 EndDdeCmnd(1);
1631 else
1632 EndDdeCmnd(0);
1633
1634 FreeTTFILE();
1635 FreeFileVar(&FileVar);
1636 }
1637
1638 int ProtoDlgParse()
1639 {
1640 int P;
1641
1642 P = ActiveWin;
1643 if (PtDlg==NULL)
1644 return P;
1645
1646 if ((*ProtoParse)(ProtoId,FileVar,ProtoVar,&cv))
1647 P = 0; /* continue */
1648 else {
1649 CommSend(&cv);
1650 ProtoEnd();
1651 }
1652 return P;
1653 }
1654
1655 void ProtoDlgTimeOut()
1656 {
1657 if (PtDlg!=NULL)
1658 (*ProtoTimeOutProc)(ProtoId,FileVar,ProtoVar,&cv);
1659 }
1660
1661 void ProtoDlgCancel()
1662 {
1663 if ((PtDlg!=NULL) &&
1664 (*ProtoCancel)(ProtoId,FileVar,ProtoVar,&cv))
1665 ProtoEnd();
1666 }
1667
1668 void KermitStart(int mode)
1669 {
1670 WORD w;
1671
1672 if (! ProtoStart())
1673 return;
1674
1675 switch (mode) {
1676 case IdKmtSend:
1677 FileVar->OpId = OpKmtSend;
1678 if (strlen(&(FileVar->FullName[FileVar->DirLen]))==0)
1679 {
1680 if (! (*GetMultiFname)(FileVar,ts.FileDir,GMF_KERMIT,&w) ||
1681 (FileVar->NumFname==0))
1682 {
1683 ProtoEnd();
1684 return;
1685 }
1686 }
1687 else
1688 (*SetFileVar)(FileVar);
1689 break;
1690 case IdKmtReceive:
1691 FileVar->OpId = OpKmtRcv;
1692 break;
1693 case IdKmtGet:
1694 FileVar->OpId = OpKmtSend;
1695 if (strlen(&(FileVar->FullName[FileVar->DirLen]))==0)
1696 {
1697 if (! (*GetGetFname)(FileVar->HMainWin,FileVar) ||
1698 (strlen(FileVar->FullName)==0))
1699 {
1700 ProtoEnd();
1701 return;
1702 }
1703 }
1704 else
1705 (*SetFileVar)(FileVar);
1706 break;
1707 case IdKmtFinish:
1708 FileVar->OpId = OpKmtFin;
1709 break;
1710 default:
1711 ProtoEnd();
1712 return;
1713 }
1714 TalkStatus = IdTalkQuiet;
1715
1716 /* disable transmit delay (serial port) */
1717 cv.DelayFlag = FALSE;
1718
1719 if (! OpenProtoDlg(FileVar,PROTO_KMT,mode,0,0))
1720 ProtoEnd();
1721 }
1722
1723 void XMODEMStart(int mode)
1724 {
1725 LONG Option;
1726 int tmp;
1727
1728 if (! ProtoStart())
1729 return;
1730
1731 if (mode==IdXReceive)
1732 FileVar->OpId = OpXRcv;
1733 else
1734 FileVar->OpId = OpXSend;
1735
1736 if (strlen(&(FileVar->FullName[FileVar->DirLen]))==0)
1737 {
1738 Option = MAKELONG(ts.XmodemBin,ts.XmodemOpt);
1739 if (! (*GetXFname)(FileVar->HMainWin,
1740 mode==IdXReceive,&Option,FileVar,ts.FileDir))
1741 {
1742 ProtoEnd();
1743 return;
1744 }
1745 tmp = HIWORD(Option);
1746 if (mode == IdXReceive) {
1747 if (IsXoptCRC(tmp)) {
1748 if (IsXopt1k(ts.XmodemOpt)) {
1749 ts.XmodemOpt = Xopt1kCRC;
1750 }
1751 else {
1752 ts.XmodemOpt = XoptCRC;
1753 }
1754 }
1755 else {
1756 if (IsXopt1k(ts.XmodemOpt)) {
1757 ts.XmodemOpt = Xopt1kCksum;
1758 }
1759 else {
1760 ts.XmodemOpt = XoptCheck;
1761 }
1762 }
1763 ts.XmodemBin = LOWORD(Option);
1764 }
1765 else {
1766 if (IsXopt1k(tmp)) {
1767 if (IsXoptCRC(ts.XmodemOpt)) {
1768 ts.XmodemOpt = Xopt1kCRC;
1769 }
1770 else {
1771 ts.XmodemOpt = Xopt1kCksum;
1772 }
1773 }
1774 else {
1775 if (IsXoptCRC(ts.XmodemOpt)) {
1776 ts.XmodemOpt = XoptCRC;
1777 }
1778 else {
1779 ts.XmodemOpt = XoptCheck;
1780 }
1781 }
1782 }
1783 }
1784 else
1785 (*SetFileVar)(FileVar);
1786
1787 if (mode==IdXReceive)
1788 FileVar->FileHandle = _lcreat(FileVar->FullName,0);
1789 else
1790 FileVar->FileHandle = _lopen(FileVar->FullName,OF_READ);
1791
1792 FileVar->FileOpen = FileVar->FileHandle != INVALID_HANDLE_VALUE;
1793 if (! FileVar->FileOpen)
1794 {
1795 ProtoEnd();
1796 return;
1797 }
1798 TalkStatus = IdTalkQuiet;
1799
1800 /* disable transmit delay (serial port) */
1801 cv.DelayFlag = FALSE;
1802
1803 if (! OpenProtoDlg(FileVar,PROTO_XM,mode,
1804 ts.XmodemOpt,ts.XmodemBin))
1805 ProtoEnd();
1806 }
1807
1808 void YMODEMStart(int mode)
1809 {
1810 WORD Opt;
1811
1812 if (! ProtoStart())
1813 return;
1814
1815 if (mode==IdYSend)
1816 {
1817 // �t�@�C���]�������I�v�V������"Yopt1K"�����������B
1818 // TODO: "Yopt1K", "YoptG", "YoptSingle"�������������������AIDD_FOPT���g�������K�v�����B
1819 Opt = Yopt1K;
1820 FileVar->OpId = OpYSend;
1821 if (strlen(&(FileVar->FullName[FileVar->DirLen]))==0)
1822 {
1823 if (! (*GetMultiFname)(FileVar,ts.FileDir,GMF_Y,&Opt) ||
1824 (FileVar->NumFname==0))
1825 {
1826 ProtoEnd();
1827 return;
1828 }
1829 //ts.XmodemBin = Opt;
1830 }
1831 else
1832 (*SetFileVar)(FileVar);
1833 }
1834 else {
1835 FileVar->OpId = OpYRcv;
1836 // �t�@�C���]�������I�v�V������"Yopt1K"�����������B
1837 Opt = Yopt1K;
1838 (*SetFileVar)(FileVar);
1839 }
1840
1841 TalkStatus = IdTalkQuiet;
1842
1843 /* disable transmit delay (serial port) */
1844 cv.DelayFlag = FALSE;
1845
1846 if (! OpenProtoDlg(FileVar,PROTO_YM,mode,Opt,0))
1847 ProtoEnd();
1848 }
1849
1850 void ZMODEMStart(int mode)
1851 {
1852 WORD Opt;
1853
1854 if (! ProtoStart())
1855 return;
1856
1857 if (mode == IdZSend || mode == IdZAutoS)
1858 {
1859 Opt = ts.XmodemBin;
1860 FileVar->OpId = OpZSend;
1861 if (strlen(&(FileVar->FullName[FileVar->DirLen]))==0)
1862 {
1863 if (! (*GetMultiFname)(FileVar,ts.FileDir,GMF_Z,&Opt) ||
1864 (FileVar->NumFname==0))
1865 {
1866 if (mode == IdZAutoS) {
1867 CommRawOut(&cv, "\030\030\030\030\030\030\030\030\b\b\b\b\b\b\b\b\b\b", 18);
1868 }
1869 ProtoEnd();
1870 return;
1871 }
1872 ts.XmodemBin = Opt;
1873 }
1874 else
1875 (*SetFileVar)(FileVar);
1876 }
1877 else /* IdZReceive or IdZAutoR */
1878 FileVar->OpId = OpZRcv;
1879
1880 TalkStatus = IdTalkQuiet;
1881
1882 /* disable transmit delay (serial port) */
1883 cv.DelayFlag = FALSE;
1884
1885 if (! OpenProtoDlg(FileVar,PROTO_ZM,mode,Opt,0))
1886 ProtoEnd();
1887 }
1888
1889 void BPStart(int mode)
1890 {
1891 LONG Option = 0;
1892
1893 if (! ProtoStart())
1894 return;
1895 if (mode==IdBPSend)
1896 {
1897 FileVar->OpId = OpBPSend;
1898 if (strlen(&(FileVar->FullName[FileVar->DirLen]))==0)
1899 {
1900 FileVar->FullName[0] = 0;
1901 if (! (*GetTransFname)(FileVar, ts.FileDir, GTF_BP, &Option))
1902 {
1903 ProtoEnd();
1904 return;
1905 }
1906 }
1907 else
1908 (*SetFileVar)(FileVar);
1909 }
1910 else /* IdBPReceive or IdBPAuto */
1911 FileVar->OpId = OpBPRcv;
1912
1913 TalkStatus = IdTalkQuiet;
1914
1915 /* disable transmit delay (serial port) */
1916 cv.DelayFlag = FALSE;
1917
1918 if (! OpenProtoDlg(FileVar,PROTO_BP,mode,0,0))
1919 ProtoEnd();
1920 }
1921
1922 void QVStart(int mode)
1923 {
1924 WORD W;
1925
1926 if (! ProtoStart())
1927 return;
1928
1929 if (mode==IdQVSend)
1930 {
1931 FileVar->OpId = OpQVSend;
1932 if (strlen(&(FileVar->FullName[FileVar->DirLen]))==0)
1933 {
1934 if (! (*GetMultiFname)(FileVar,ts.FileDir,GMF_QV, &W) ||
1935 (FileVar->NumFname==0))
1936 {
1937 ProtoEnd();
1938 return;
1939 }
1940 }
1941 else
1942 (*SetFileVar)(FileVar);
1943 }
1944 else
1945 FileVar->OpId = OpQVRcv;
1946
1947 TalkStatus = IdTalkQuiet;
1948
1949 /* disable transmit delay (serial port) */
1950 cv.DelayFlag = FALSE;
1951
1952 if (! OpenProtoDlg(FileVar,PROTO_QV,mode,0,0))
1953 ProtoEnd();
1954 }

Back to OSDN">Back to OSDN
ViewVC Help
Powered by ViewVC 1.1.26