summaryrefslogtreecommitdiffabout
path: root/PumpKINDlg.cpp
authorMichael Krelin <hacker@klever.net>2004-07-05 01:53:09 (UTC)
committer Michael Krelin <hacker@klever.net>2004-07-05 01:53:09 (UTC)
commit9938ea772d372ba955b7bc1f1c48a062c3a36f8a (patch) (unidiff)
treea98185df944e3a763f9557aa74bc2837b343f048 /PumpKINDlg.cpp
downloadpumpkin-9938ea772d372ba955b7bc1f1c48a062c3a36f8a.zip
pumpkin-9938ea772d372ba955b7bc1f1c48a062c3a36f8a.tar.gz
pumpkin-9938ea772d372ba955b7bc1f1c48a062c3a36f8a.tar.bz2
initial commit into svn repository
git-svn-id: http://svn.klever.net/kin/pumpkin/trunk@1 fe716a7a-6dde-0310-88d9-d003556173a8
Diffstat (limited to 'PumpKINDlg.cpp') (more/less context) (ignore whitespace changes)
-rw-r--r--PumpKINDlg.cpp1973
1 files changed, 1973 insertions, 0 deletions
diff --git a/PumpKINDlg.cpp b/PumpKINDlg.cpp
new file mode 100644
index 0000000..1e6d03f
--- a/dev/null
+++ b/PumpKINDlg.cpp
@@ -0,0 +1,1973 @@
1// PumpKINDlg.cpp : implementation file
2//
3
4#include "stdafx.h"
5#include "PumpKIN.h"
6#include "PumpKINDlg.h"
7
8#include "PropsServer.h"
9#include "PropsNetwork.h"
10#include "PropsSounds.h"
11#include "ConfirmRRQDlg.h"
12#include "ConfirmWRQDlg.h"
13#include "RequestDlg.h"
14#include "Resolver.h"
15#include "Retrier.h"
16#include "Trayer.h"
17
18#include <io.h>
19
20#ifdef _DEBUG
21#define new DEBUG_NEW
22#undef THIS_FILE
23static char THIS_FILE[] = __FILE__;
24#endif
25
26IMPLEMENT_DYNAMIC(CXferSocket, CAsyncSocket)
27IMPLEMENT_DYNAMIC(CWRQSocket, CXferSocket)
28IMPLEMENT_DYNAMIC(CRRQSocket, CXferSocket)
29
30/////////////////////////////////////////////////////////////////////////////
31// CAboutDlg dialog used for App About
32
33class CAboutDlg : public CDialog
34{
35public:
36 CAboutDlg();
37
38// Dialog Data
39 //{{AFX_DATA(CAboutDlg)
40 enum { IDD = IDD_ABOUTBOX };
41 //}}AFX_DATA
42
43 // ClassWizard generated virtual function overrides
44 //{{AFX_VIRTUAL(CAboutDlg)
45 protected:
46 virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
47 //}}AFX_VIRTUAL
48
49// Implementation
50protected:
51 //{{AFX_MSG(CAboutDlg)
52 afx_msg void OnKlevernet();
53 //}}AFX_MSG
54 DECLARE_MESSAGE_MAP()
55};
56
57CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
58{
59 //{{AFX_DATA_INIT(CAboutDlg)
60 //}}AFX_DATA_INIT
61}
62
63void CAboutDlg::DoDataExchange(CDataExchange* pDX)
64{
65 CDialog::DoDataExchange(pDX);
66 //{{AFX_DATA_MAP(CAboutDlg)
67 //}}AFX_DATA_MAP
68}
69
70BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
71 //{{AFX_MSG_MAP(CAboutDlg)
72 ON_BN_CLICKED(IDC_KLEVERNET, OnKlevernet)
73 //}}AFX_MSG_MAP
74END_MESSAGE_MAP()
75
76/////////////////////////////////////////////////////////////////////////////
77// CPumpKINDlg dialog
78
79CPumpKINDlg::CPumpKINDlg(CWnd* pParent /*=NULL*/)
80 : CDialog(CPumpKINDlg::IDD, pParent)
81{
82 m_ListenPort = 69;
83 m_bTFTPSubdirs = TRUE;
84 m_RRQMode = rrqAlwaysConfirm;
85 m_WRQMode = wrqAlwaysConfirm;
86 m_TFTPTimeOut = CTimeSpan(0,0,0,30);
87 m_RetryTimeOut = CTimeSpan(0,0,0,10);
88 m_LogLength = 100;
89 m_SpeakPort = 69;
90 m_PromptTimeOut=30;
91 m_bShown=TRUE;
92 m_bExiting=FALSE;
93 m_BlockSize=1024;
94 m_bnw.AssignSound("(bang)",IDR_WAVE_RING,CBellsNWhistles::CBang::bangResource);
95 m_bnw.AssignSound("(done)",IDR_WAVE_FINISHED,CBellsNWhistles::CBang::bangResource);
96 m_bnw.AssignSound("(oops)",IDR_WAVE_ABORTED,CBellsNWhistles::CBang::bangResource);
97 m_bnw.AssignSound("(none)",(int)0,CBellsNWhistles::CBang::bangNone);
98 m_bnwRequest="(bang)"; m_bnwSuccess="(done)";
99 m_bnwAbort="(oops)";
100 //{{AFX_DATA_INIT(CPumpKINDlg)
101 //}}AFX_DATA_INIT
102 // Note that LoadIcon does not require a subsequent DestroyIcon in Win32
103 m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
104 m_bmpBack.LoadBitmap(IDB_BACKGROUND);
105 m_bmpBack.GetBitmap(&m_bitmapBack);
106 m_Retrier = new CRetrier(this);
107 ASSERT(m_Retrier);
108 m_Trayer = new CTrayer(this);
109 ASSERT(m_Trayer);
110 LoadSettings();
111}
112
113void CPumpKINDlg::DoDataExchange(CDataExchange* pDX)
114{
115 CDialog::DoDataExchange(pDX);
116 //{{AFX_DATA_MAP(CPumpKINDlg)
117 DDX_Control(pDX, IDC_ABORT, m_AbortCtl);
118 DDX_Control(pDX, IDC_OPTIONS, m_OptionsCtl);
119 DDX_Control(pDX, IDC_LOG, m_Log);
120 DDX_Control(pDX, IDC_CONNECTIONS, m_List);
121 //}}AFX_DATA_MAP
122}
123
124BEGIN_MESSAGE_MAP(CPumpKINDlg, CDialog)
125 //{{AFX_MSG_MAP(CPumpKINDlg)
126 ON_WM_SYSCOMMAND()
127 ON_WM_DESTROY()
128 ON_WM_PAINT()
129 ON_WM_QUERYDRAGICON()
130 ON_WM_CREATE()
131 ON_BN_CLICKED(IDC_OPTIONS, OnOptions)
132 ON_WM_TIMER()
133 ON_BN_CLICKED(IDC_EXIT, OnExit)
134 ON_BN_CLICKED(IDC_PUT, OnPut)
135 ON_BN_CLICKED(IDC_GET, OnGet)
136 ON_NOTIFY(LVN_DELETEALLITEMS, IDC_CONNECTIONS, OnDeleteallitemsConnections)
137 ON_NOTIFY(LVN_DELETEITEM, IDC_CONNECTIONS, OnDeleteitemConnections)
138 ON_NOTIFY(LVN_INSERTITEM, IDC_CONNECTIONS, OnInsertitemConnections)
139 ON_NOTIFY(LVN_ITEMCHANGED, IDC_CONNECTIONS, OnItemchangedConnections)
140 ON_BN_CLICKED(IDC_ABORT, OnAbort)
141 ON_WM_CLOSE()
142 ON_COMMAND(ID_TRAY_SHOWPUMPKINWINDOW, OnTrayShowpumpkinwindow)
143 ON_COMMAND(ID_TRAY_EXIT, OnTrayExit)
144 ON_COMMAND(ID_TRAY_ABOUTPUMPKIN, OnTrayAboutpumpkin)
145 ON_COMMAND(ID_TRAY_FETCHFILE, OnTrayFetchfile)
146 ON_COMMAND(ID_TRAY_HELP, OnTrayHelp)
147 ON_COMMAND(ID_TRAY_OPTIONS, OnTrayOptions)
148 ON_COMMAND(ID_TRAY_SENDFILE, OnTraySendfile)
149 ON_WM_WINDOWPOSCHANGING()
150 ON_LBN_SELCHANGE(IDC_LOG, OnSelchangeLog)
151 ON_COMMAND(ID_TRAY_OPENFILESFOLDER, OnTrayOpenfilesfolder)
152 ON_WM_DROPFILES()
153 ON_BN_CLICKED(ID_HELP, OnHelp)
154 //}}AFX_MSG_MAP
155END_MESSAGE_MAP()
156
157/////////////////////////////////////////////////////////////////////////////
158// CPumpKINDlg message handlers
159
160BOOL CPumpKINDlg::OnInitDialog()
161{
162 CDialog::OnInitDialog();
163
164 // Add "About..." menu item to system menu.
165
166 // IDM_ABOUTBOX must be in the system command range.
167 ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
168 ASSERT(IDM_ABOUTBOX < 0xF000);
169
170 CMenu* pSysMenu = GetSystemMenu(FALSE);
171 CString strAboutMenu;
172 strAboutMenu.LoadString(IDS_ABOUTBOX);
173 if (!strAboutMenu.IsEmpty())
174 {
175 pSysMenu->AppendMenu(MF_SEPARATOR);
176 pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
177 }
178
179 // Set the icon for this dialog. The framework does this automatically
180 // when the application's main window is not a dialog
181 SetIcon(m_hIcon, TRUE); // Set big icon
182 SetIcon(m_hIcon, FALSE); // Set small icon
183
184 VERIFY(m_Retrier->Create(NULL,"PumpKIN-Retrier",WS_CHILD,CRect(0,0,0,0),this,0));
185
186
187 m_Images.Create(16,16,TRUE,2,1);
188 m_iRRQ = m_Images.Add(AfxGetApp()->LoadIcon(IDI_RRQ));
189 m_iWRQ = m_Images.Add(AfxGetApp()->LoadIcon(IDI_WRQ));
190 ASSERT(m_iRRQ>=0);
191 ASSERT(m_iWRQ>=0);
192 m_List.SetImageList(&m_Images,LVSIL_NORMAL);
193 m_List.SetImageList(&m_Images,LVSIL_SMALL);
194 m_List.SetImageList(&m_Images,LVSIL_STATE);
195 m_List.SetTextColor(RGB(255,255,0));// Yellow
196 m_List.SetTextBkColor(RGB(12,167,0));// Green
197 m_List.SetBkColor(RGB(12,167,0));// Green
198CRect listrc;
199 m_List.GetClientRect(&listrc);
200 m_List.InsertColumn(0,"File",LVCFMT_LEFT,listrc.Width()-((listrc.Width()/7)*3+listrc.Width()*2/7),subitemFile);
201 m_List.InsertColumn(1,"type",LVCFMT_CENTER,listrc.Width()/7,subitemType);
202 m_List.InsertColumn(2,"peer",LVCFMT_LEFT,listrc.Width()*2/7,subitemPeer);
203 m_List.InsertColumn(3,"ACK",LVCFMT_RIGHT,listrc.Width()/7,subitemBytes);
204 m_List.InsertColumn(4,"tsize",LVCFMT_RIGHT,listrc.Width()/7,subitemTSize);
205
206 LogLine(IDS_LOG_START);
207
208 SetupButtons();
209
210CRect rc, drc;
211 GetWindowRect(rc);
212 GetDesktopWindow()->GetWindowRect(drc);
213 SetWindowPos(NULL,drc.right-6-rc.Width(),6,0,0,SWP_NOACTIVATE|SWP_NOSIZE|SWP_NOZORDER);
214
215 if(m_bShown)
216 ShowWindow(SW_SHOW);
217 else
218 ShowWindow(SW_HIDE);
219
220 // CG: The following block was added by the ToolTips component.
221 {
222 // Create the ToolTip control.
223 m_tooltip.Create(this);
224 m_tooltip.Activate(TRUE);
225
226 m_tooltip.AddTool(&m_List,IDC_CONNECTIONS);
227 m_tooltip.AddTool(GetDlgItem(IDC_PUT),IDC_PUT);
228 m_tooltip.AddTool(GetDlgItem(IDC_GET),IDC_GET);
229 m_tooltip.AddTool(&m_AbortCtl,IDC_ABORT);
230 m_tooltip.AddTool(GetDlgItem(IDC_OPTIONS),IDC_OPTIONS);
231 m_tooltip.AddTool(GetDlgItem(IDC_EXIT),IDC_EXIT);
232 m_tooltip.AddTool(GetDlgItem(ID_HELP),ID_HELP);
233 m_tooltip.AddTool(GetDlgItem(IDC_LOG),IDC_LOG);
234 }
235 return TRUE; // return TRUE unless you set the focus to a control
236}
237
238void CPumpKINDlg::OnSysCommand(UINT nID, LPARAM lParam)
239{
240 if ((nID & 0xFFF0) == IDM_ABOUTBOX)
241 {
242 CAboutDlg dlgAbout;
243 dlgAbout.DoModal();
244 }
245 else
246 {
247 CDialog::OnSysCommand(nID, lParam);
248 }
249}
250
251void CPumpKINDlg::OnDestroy()
252{
253 SaveSettings();
254
255NOTIFYICONDATA nid;
256 memset(&nid,0,sizeof(nid));
257 nid.cbSize=sizeof(nid);
258 nid.hWnd=m_Trayer->m_hWnd;
259 nid.uID=IDC_TRAYICON;
260 nid.uFlags=0;
261 VERIFY(Shell_NotifyIcon(NIM_DELETE,&nid));
262
263 WinHelp(0L, HELP_QUIT);
264 CDialog::OnDestroy();
265POSITION p = m_LogTimes.GetStartPosition();
266 while(p){
267 CTime *t,*tt;
268 m_LogTimes.GetNextAssoc(p,t,tt);
269 ASSERT(t && tt && t==tt);
270 delete t;
271 }
272 // *** Abort and cleanup transfers
273 m_LogTimes.RemoveAll();
274}
275
276// If you add a minimize button to your dialog, you will need the code below
277// to draw the icon. For MFC applications using the document/view model,
278// this is automatically done for you by the framework.
279
280void CPumpKINDlg::OnPaint()
281{
282 if (IsIconic())
283 {
284 CPaintDC dc(this); // device context for painting
285
286 SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
287
288 // Center icon in client rectangle
289 int cxIcon = GetSystemMetrics(SM_CXICON);
290 int cyIcon = GetSystemMetrics(SM_CYICON);
291 CRect rect;
292 GetClientRect(&rect);
293 int x = (rect.Width() - cxIcon + 1) / 2;
294 int y = (rect.Height() - cyIcon + 1) / 2;
295
296 // Draw the icon
297 dc.DrawIcon(x, y, m_hIcon);
298 }
299 else
300 {
301 CPaintDC pDC(this);
302 CDC bmpDC;
303 bmpDC.CreateCompatibleDC(&pDC);
304 bmpDC.SelectObject(&m_bmpBack);
305 CRect rc;
306 GetClientRect(&rc);
307 for(int x=-m_bitmapBack.bmWidth*2/4;x<rc.Width();x+=m_bitmapBack.bmWidth)
308 for(int y=-m_bitmapBack.bmHeight*2/4;y<rc.Height();y+=m_bitmapBack.bmHeight)
309 pDC.BitBlt(x,y,m_bitmapBack.bmWidth,m_bitmapBack.bmHeight,&bmpDC,0,0,SRCCOPY);
310 bmpDC.DeleteDC();
311 CDialog::OnPaint();
312 }
313}
314
315// The system calls this to obtain the cursor to display while the user drags
316// the minimized window.
317HCURSOR CPumpKINDlg::OnQueryDragIcon()
318{
319 return (HCURSOR) m_hIcon;
320}
321
322int CPumpKINDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
323{
324 if (CDialog::OnCreate(lpCreateStruct) == -1)
325 return -1;
326
327 m_Listener.m_Daddy=this;
328 if(!m_Listener.Create(m_ListenPort,SOCK_DGRAM)){
329 TRACE0("Failed to create socket\n");
330 return -1;
331 }
332
333 if(!m_Trayer->Create(NULL,"PumpKIN TrayIcon",WS_CHILD,CRect(0,0,0,0),this,0)){
334 TRACE0("Failed to create trayer\n");
335 return -1;
336 }
337
338NOTIFYICONDATA nid;
339 memset(&nid,0,sizeof(nid));
340 nid.cbSize=sizeof(nid);
341 nid.hWnd=m_Trayer->m_hWnd;
342 nid.uID=IDC_TRAYICON;
343 nid.uFlags=NIF_MESSAGE|NIF_ICON|NIF_TIP;
344 nid.uCallbackMessage=WM_TRAYICON;
345 nid.hIcon=AfxGetApp()->LoadIcon(IDR_MAINFRAME);
346 // *** Load from resource
347 strcpy(nid.szTip,"PumpKIN");
348 VERIFY(Shell_NotifyIcon(NIM_ADD,&nid));
349
350 return 0;
351}
352
353void CListenSocket::OnReceive(int nErrorCode)
354{
355 ASSERT(m_Daddy);
356 if(nErrorCode){
357 m_Daddy->LogLine(IDS_LOG_LISTENRECEIVEERROR);
358 return;
359 }
360DWORD fionread = 0;
361 VERIFY(IOCtl(FIONREAD,&fionread));// *** Do some checking on the value acquired
362tftp *tftpRQ = tftp::Allocate(fionread);
363 ASSERT(tftpRQ);
364SOCKADDR_IN sin;
365 if(!tftpRQ->Receive(this,fionread,&sin)){
366 m_Daddy->LogLine(IDS_LOG_LISTENACCEPTERROR);
367 delete tftpRQ;
368 return;
369 }
370 #ifndefNDEBUG
371CString tmp;
372 tmp.Format("%u - %s - %u\n",tftpRQ->Opcode(),inet_ntoa(sin.sin_addr),sin.sin_port);
373 TRACE0(tmp);
374#endif
375POSITION p = m_Daddy->m_Xfers.GetStartPosition();
376 while(p){
377 SOCKET key;
378 CXferSocket *sock;
379 m_Daddy->m_Xfers.GetNextAssoc(p,key,sock);
380 ASSERT(sock);
381 if(sock->m_Peer.sin_addr.s_addr==sin.sin_addr.s_addr && sock->m_Peer.sin_port==sin.sin_port){
382 TRACE0("Ignoring request which we are already processing\n");
383 delete tftpRQ;
384 return;
385 }
386 }
387 switch(tftpRQ->Opcode()){
388 case tftp::opRRQ:
389 // Read Request
390 {
391 CString tmp;
392 tmp.Format(IDS_LOG_RRQSERVE,tftpRQ->rqFileName(),tftpRQ->rqType(),inet_ntoa(sin.sin_addr));
393 m_Daddy->LogLine(tmp);
394 CRRQSocket *s = new CRRQSocket(m_Daddy,tftpRQ->rqFileName(),tftpRQ->rqType(),&sin);
395 ASSERT(s);
396 tftpRQ->GetOptions(&s->m_Options);
397 if(!s->Create())
398 s->Destroy(FALSE);
399 }
400 break;
401 case tftp::opWRQ:
402 // Write Request
403 {
404 CString tmp;
405 tmp.Format(IDS_LOG_WRQSERVE,tftpRQ->rqFileName(),tftpRQ->rqType(),inet_ntoa(sin.sin_addr));
406 m_Daddy->LogLine(tmp);
407 CWRQSocket *s = new CWRQSocket(m_Daddy,tftpRQ->rqFileName(),tftpRQ->rqType(),&sin);
408 ASSERT(s);
409 tftpRQ->GetOptions(&s->m_Options);
410 if(!s->Create(NULL,NULL))
411 s->Destroy(FALSE);
412 }
413 break;
414 default:
415 m_Daddy->LogLine(IDS_LOG_LISTENOPCODE);
416 delete tftpRQ;
417 return;
418 }
419 delete tftpRQ;
420}
421
422BOOL tftp::Receive(CAsyncSocket* socket,UINT maxLength,SOCKADDR_IN *sin)
423{
424 ASSERT(socket);
425int saddrLen = sizeof(SOCKADDR_IN);
426 length = sin ?
427 socket->ReceiveFrom(udpBase(),maxLength,(SOCKADDR*)sin,&saddrLen)
428 :
429 socket->Receive(udpBase(),maxLength)
430 ;
431 if(!length)
432 return FALSE;
433 if(length==(tftpLength)SOCKET_ERROR)
434 return FALSE;
435 return TRUE;
436}
437
438UINT tftp::Opcode()
439{
440 return REVERSEBYTES(opcode);
441}
442
443CString tftp::rqFileName()
444{
445 ASSERT(length);
446 ASSERT(Opcode()==opRRQ || Opcode()==opWRQ);
447CString rv;
448 if(memchr(&data.m_RQ.data,0,length-sizeof(opcode)))
449 rv = (LPCTSTR)data.m_RQ.data;
450 return rv;
451}
452
453CString tftp::rqType()
454{
455 ASSERT(length);
456 ASSERT(Opcode()==opRRQ || Opcode()==opWRQ);
457CString rv;
458char *tmp = (char*)memchr(&data.m_RQ.data,0,length-sizeof(opcode));
459 if(tmp++)
460 rv = (LPCTSTR)tmp;
461 return rv;
462}
463
464UINT tftp::GetOptions(tftp::tftpOptions* ops)
465{
466 ASSERT(length);
467 ASSERT(Opcode()==opRRQ || Opcode()==opWRQ || Opcode()==opOACK);
468 ASSERT(ops);
469tftpOptions& o = *ops;
470LPSTR base = (LPSTR)&data.m_RQ.data;
471UINT basePtr = 0;
472 if(Opcode()==opRRQ || Opcode()==opWRQ){
473 base = (LPSTR)memchr(&data.m_RQ.data,0,length-sizeof(opcode));
474 if(!base)
475 return 0;
476 base++;
477 basePtr = (base-(LPSTR)&data.m_RQ.data);
478 base = (LPSTR)memchr(base,0,length-basePtr);
479 if(!base)
480 return 0;
481 base++;
482 basePtr = (base-(LPSTR)&data.m_RQ.data);
483 }
484 ops->RemoveAll();
485UINT rv = 0;
486 while(basePtr<(length-sizeof(opcode))){
487 CString onam = (LPSTR)&data.m_RQ.data[basePtr];
488 basePtr+=onam.GetLength()+1;
489 CString oval = (LPSTR)&data.m_RQ.data[basePtr];
490 basePtr+=oval.GetLength()+1;
491 onam.MakeLower();
492 o[onam]=oval;
493 rv++;
494 }
495 return rv;
496}
497
498tftp::tftp()
499{
500 length=0;
501}
502
503
504void CXferSocket::OnSend(int nErrorCode)
505{
506 if(nErrorCode){
507 ASSERT(m_Daddy);
508 m_Daddy->LogLine(IDS_LOG_XFERSEND);
509 return;
510 }
511 if(!m_Queue.IsEmpty()){
512 tftp *p = m_Queue.GetHead();
513 ASSERT(p);
514 m_Queue.RemoveHead();
515 if(!p->Send(this,&m_Peer)){
516 ASSERT(m_Daddy);
517 m_Daddy->LogLine(IDS_LOG_XFERUDPSEND);
518 }
519 delete p;
520 }
521 DoSelect();
522 if(m_Queue.IsEmpty()){
523 switch(state){
524 case stateDeny:
525 Destroy(FALSE);
526 break;
527 case stateFinish:
528 Destroy(TRUE);
529 break;
530 }
531 }
532}
533
534BOOL tftp::Send(CAsyncSocket *socket,SOCKADDR_IN* saddr)
535{
536 ASSERT(socket);
537int rv = socket->SendTo(udpBase(),length,(SOCKADDR*)saddr,sizeof(SOCKADDR_IN));
538 if(rv!=length)
539 return FALSE;
540 return TRUE;
541}
542
543void CXferSocket::DoSelect()
544{
545 if(m_Peer.sin_addr.s_addr!=INADDR_NONE)
546 AsyncSelect(FD_CLOSE|FD_READ|(m_Queue.IsEmpty()?0:FD_WRITE));
547}
548
549void CXferSocket::OnReceive(int nErrorCode)
550{
551 if(nErrorCode){
552 ASSERT(m_Daddy);
553 m_Daddy->LogLine(IDS_LOG_XFERRECEIVE);
554 return;
555 }
556 ASSERT(m_Daddy);
557DWORD fionread = 0;
558 VERIFY(IOCtl(FIONREAD,&fionread));
559tftp *p = tftp::Allocate(fionread);
560 ASSERT(p);
561SOCKADDR_IN sin;
562 if(!p->Receive(this,fionread,&sin)){
563 m_Daddy->LogLine(IDS_LOG_XFERUDPRECEIVE);
564 delete p;
565 }else
566 if(m_Peer.sin_addr.s_addr==INADDR_NONE){
567 m_Peer.sin_addr=sin.sin_addr;
568 m_Peer.sin_port=sin.sin_port;
569 }
570BOOL alive = TRUE;
571 if(state==stateInit){
572 state=stateXfer;
573 m_Peer.sin_port=sin.sin_port;
574 UpdateList();
575 }
576 if(sin.sin_addr.s_addr!=m_Peer.sin_addr.s_addr || sin.sin_port!=m_Peer.sin_port){
577 m_Daddy->LogLine(IDS_LOG_XFERSOURCETID);
578 // *** Bounce it!
579 }else{
580 alive = OnTFTP(p);
581 }
582 delete p;
583 if(alive){
584 DoSelect();
585 ResetTimeout();
586 }
587}
588
589void CXferSocket::SetPeer(SOCKADDR_IN *sin)
590{
591 ASSERT(sin);
592 memmove(&m_Peer,sin,sizeof(m_Peer));
593}
594
595void CXferSocket::UpdateList()
596{
597 ASSERT(m_Daddy);
598LV_FINDINFO lvf;
599 memset(&lvf,0,sizeof(lvf));
600 lvf.flags=LVFI_PARAM;
601 lvf.lParam=(LPARAM)this;
602int i = m_Daddy->m_List.FindItem(&lvf);
603 if(i<0){
604 ASSERT(IsKindOf(RUNTIME_CLASS(CRRQSocket)) || IsKindOf(RUNTIME_CLASS(CWRQSocket)));
605 i=m_Daddy->m_List.InsertItem(0,m_FileName,IsKindOf(RUNTIME_CLASS(CRRQSocket))?m_Daddy->m_iRRQ:m_Daddy->m_iWRQ);
606 ASSERT(!(i<0));
607 m_Daddy->m_List.SetItemData(i,(DWORD)this);
608 }
609 m_Daddy->m_List.SetItemText(i,CPumpKINDlg::subitemFile,m_FileName);
610 m_Daddy->m_List.SetItemText(i,CPumpKINDlg::subitemType,m_Type);
611 m_Daddy->m_List.SetItemText(i,CPumpKINDlg::subitemPeer,inet_ntoa(m_Peer.sin_addr));
612CString tmp;
613 tmp.Format(IDS_FMT_BYTES,GetACK());
614 m_Daddy->m_List.SetItemText(i,CPumpKINDlg::subitemBytes,tmp);
615 if(m_xferSize>=0){
616 tmp.Format(IDS_FMT_BYTES,m_xferSize);
617 m_Daddy->m_List.SetItemText(i,CPumpKINDlg::subitemTSize,tmp);
618 }
619}
620
621CXferSocket::CXferSocket()
622 : m_wndResolver(NULL), m_Retry(NULL), m_bRetry(FALSE),
623 m_blkSize(512), m_timeOut(30), m_xferSize(-1),
624 m__blkSize(512), m__timeOut(30)
625{
626 m_Daddy=NULL;
627 m_Peer.sin_addr.s_addr=INADDR_NONE;
628 m_Peer.sin_family=AF_INET;
629 state=stateNone;
630}
631
632ULONG CXferSocket::GetACK()
633{
634 return 0;
635}
636
637CXferSocket::CXferSocket(CPumpKINDlg *daddy,LPCTSTR fileName,LPCTSTR type,SOCKADDR_IN* sin)
638 : m_wndResolver(NULL), m_Retry(NULL), m_bRetry(FALSE),
639 m_blkSize(512), m_timeOut(30), m_xferSize(-1),
640 m__blkSize(512), m__timeOut(30)
641{
642 m_Peer.sin_family=AF_INET;
643 state=stateNone;
644 ASSERT(daddy);
645 m_Daddy=daddy;
646 m_timeOut=m__timeOut=m_Daddy->m_TFTPTimeOut.GetTotalSeconds();
647 if(sin){
648 m_Peer.sin_addr.s_addr=sin->sin_addr.s_addr;
649 m_Peer.sin_port=sin->sin_port;
650 }else
651 m_Peer.sin_addr.s_addr=INADDR_NONE;
652 m_FileName=fileName;
653 m_Type=type;
654}
655
656BOOL CRRQSocket::Create(LPCTSTR localFile,LPCTSTR hostName)
657{
658 if(!CAsyncSocket::Create(0,SOCK_DGRAM))
659 return FALSE;
660 ASSERT(m_Daddy);
661 ASSERT(m_Peer.sin_addr.s_addr!=INADDR_NONE || hostName);
662 m_Daddy->m_Xfers[m_hSocket]=this;
663CString lFile = localFile?localFile:m_FileName;
664 TurnSlashes(lFile,TRUE);
665 UpdateList();
666 if(!localFile){// Check only if server
667 if(CheckBadRelativeness(m_FileName)){
668 Deny(tftp::errAccessViolation,IDS_TFTP_ERROR_ACCESS);
669 return TRUE;
670 }
671 switch(m_Daddy->m_RRQMode){
672 case CPumpKINDlg::rrqGiveAll:
673 break;
674 case CPumpKINDlg::rrqAlwaysConfirm:
675 if(ConfirmRequest())
676 break;
677 case CPumpKINDlg::rrqDenyAll:
678 Deny(tftp::errAccessViolation,IDS_TFTP_ERROR_ACCESS);
679 return TRUE;
680 }
681 }
682CString fn = localFile?ApplyRootGently(lFile):ApplyRoot(lFile);
683CFileException e;
684 if(!m_File.Open(fn,CFile::modeRead|CFile::shareDenyWrite,&e)){
685 if(localFile){
686 CString tmp;
687 tmp.Format(IDS_LOG_FAILEDLOCALFILE,fn);
688 m_Daddy->LogLine(tmp);
689 return FALSE;
690 }
691 Deny(&e);
692 return TRUE;
693 }
694 m_xferSize=m_File.GetLength();// *** HANDLE EXCEPTION
695 if(hostName){
696 m_HostName=hostName;
697
698 CString tmp;
699 tmp.Format(IDS_LOG_SENDING,m_FileName,m_HostName);
700 m_Daddy->LogLine(tmp);
701
702 CString inAddr = hostName;
703 int at = inAddr.Find('@');
704 if(at>=0)
705 inAddr=inAddr.Mid(at+1);
706 if((m_Peer.sin_addr.s_addr=inet_addr((LPCTSTR)inAddr))==INADDR_NONE){
707 ASSERT(!m_wndResolver);
708 m_wndResolver = new CResolver(this);
709 ASSERT(m_wndResolver);
710 return m_wndResolver->Resolve();
711 }
712 else
713 OnHostKnown();
714 }else{
715 tftp::tftpOptions o;
716 CString v;
717 if(m_Options.Lookup(tftpoBSize,v)){
718 m__blkSize=atoi(v);
719 if(m__blkSize){
720 m_blkSize=m__blkSize;
721 v.Format("%u",m_blkSize);
722 o[tftpoBSize]=v;
723 }
724 }
725 if(m_Options.Lookup(tftpoTSize,v)){
726 v.Format("%lu",m_xferSize);
727 o[tftpoTSize]=v;
728 }
729 if(m_Options.Lookup(tftpoTOut,v)){
730 m__timeOut=atoi(v);
731 if(m__timeOut){
732 m_timeOut=m__timeOut;
733 v.Format("%u",m_timeOut);
734 o[tftpoTOut]=v;
735 }
736 }
737 state = stateXfer;
738 m_ACK=0;
739 if(o.GetCount()){
740 tftp *p = tftp::Allocate(tftp::tftpOACK::tftpSize(&o));
741 ASSERT(p);
742 p->SetOpcode(tftp::opOACK);
743 p->data.m_OACK.Set(&o);
744 PostTFTP(p,TRUE);
745 }else
746 DoXfer();
747 }
748 return TRUE;
749}
750
751CRRQSocket::CRRQSocket(CPumpKINDlg *daddy,LPCTSTR fileName,LPCTSTR type,SOCKADDR_IN *sin)
752 : CXferSocket(daddy,fileName,type,sin)
753{
754 m_ACK=0;
755 m_LastSlack=0;
756}
757
758UINT tftp::tftpERROR::tftpSize(LPCTSTR msg)
759{
760 return tftpHdrSize-tftpSlackSize+sizeof(tftp::tftpERROR::tftpErrorCode)+strlen(msg)+1;
761}
762
763tftp* tftp::Allocate(UINT tftpSize)
764{
765 ASSERT(tftpSize);
766tftp* rv = (tftp*) new BYTE[tftpSlackSize+tftpSize];
767 ASSERT(rv);
768 rv->length=tftpSize;
769 return rv;
770}
771
772void tftp::errSet(UINT code,LPCTSTR msg)
773{
774 ASSERT(this);
775 ASSERT(length>=data.m_ERROR.tftpSize(msg));
776 strcpy((char*)data.m_ERROR.data,msg);
777 data.m_ERROR.SetCode(code);
778}
779
780void CXferSocket::PostTFTP(tftp* p,BOOL retryable)
781{
782 ASSERT(p);
783 m_Queue.AddTail(p);
784 DoSelect();
785 if(!m_bRetry){
786 if(retryable)
787 SetTry(p);
788 else
789 SetTry();
790 }
791 ResetTimeout();
792}
793
794void CXferSocket::Deny(UINT errCode,UINT errID)
795{
796 PostError(errCode,errID);
797 state=stateDeny;
798}
799
800void CRRQSocket::DoXfer()
801{
802tftp *p = tftp::Allocate(tftp::tftpDATA::tftpSize(m_blkSize));
803 ASSERT(p);
804 p->SetOpcode(tftp::opDATA);
805 TRY{
806 m_File.Seek(m_ACK*m_blkSize,CFile::begin);
807 int bytes = m_File.Read(p->data.m_DATA.data,m_blkSize);
808 p->data.m_DATA.SetBlock(m_ACK+1);
809 p->length=p->length-m_blkSize+bytes;
810 m_LastSlack = m_blkSize-bytes;
811 PostTFTP(p);
812 if(bytes<m_blkSize){
813 state=stateFinish;
814 ASSERT(m_Daddy);
815 CString tmp;
816 tmp.Format(IDS_LOG_XFERRRQFINISHED,(LPCTSTR)m_FileName);
817 m_Daddy->LogLine(tmp);
818 }
819 }CATCH(CFileException,e){
820 Deny(e);
821 }END_CATCH
822}
823
824UINT tftp::tftpDATA::tftpSize(UINT blkSize)
825{
826 return tftpHdrSize-tftpSlackSize+sizeof(tftp::tftpDATA)
827 -sizeof(BYTE)+blkSize;
828}
829
830void CXferSocket::Deny(CFileException* e)
831{
832 PostError(e);
833 state=stateDeny;
834}
835
836void CXferSocket::PostError(UINT errCode,UINT errID)
837{
838CString msg;
839 msg.LoadString(errID);
840 ASSERT(m_Daddy);
841 /*// ***
842CString tmp;
843 tmp.Format(IDS_LOG_SENTTFTPERROR,errCode,(LPCTSTR)msg);
844 m_Daddy->LogLine(tmp);
845 */
846tftp* err = tftp::Allocate(tftp::tftpERROR::tftpSize(msg));
847err->SetOpcode(tftp::opERROR);
848 err->errSet(errCode,msg);
849 PostTFTP(err);
850}
851
852void CXferSocket::PostError(CFileException* e)
853{
854UINT eCode;
855UINT eMsgID;
856 switch(e->m_cause){
857 case CFileException::fileNotFound:
858 eCode=tftp::errNotFound;
859 eMsgID=IDS_TFTP_ERROR_NOTFOUND;
860 break;
861 case CFileException::accessDenied:
862 eCode=tftp::errAccessViolation;
863 eMsgID=IDS_TFTP_ERROR_ACCESS;
864 break;
865 case CFileException::directoryFull:
866 eCode=tftp::errDiskFull;
867 eMsgID=IDS_TFTP_ERROR_DIRFULL;
868 break;
869 case CFileException::sharingViolation:
870 eCode=tftp::errAccessViolation;
871 eMsgID=IDS_TFTP_ERROR_SHARING;
872 break;
873 case CFileException::diskFull:
874 eCode=tftp::errDiskFull;
875 eMsgID=IDS_TFTP_ERROR_DISKFULL;
876 break;
877 default:
878 eCode=tftp::errUndefined;
879 eMsgID=IDS_TFTP_ERROR_UNDEFINED;
880 break;
881 }
882 PostError(eCode,eMsgID);
883}
884
885ULONG CRRQSocket::GetACK(void)
886{
887 return (m_ACK*m_blkSize)-m_LastSlack;
888}
889
890BOOL CRRQSocket::OnTFTP(tftp* p)
891{
892BOOL rv = TRUE;
893 switch(p->Opcode()){
894 case tftp::opOACK:
895 m_ACK=0;
896 ASSERT(state!=stateFinish);
897 {
898 tftp::tftpOptions o;
899 if(p->GetOptions(&o)){
900 CString v;
901 if(o.Lookup(tftpoBSize,v)){
902 m_blkSize=atoi(v);
903 if(!m_blkSize){// *** More sanity checks
904 Deny(tftp::errOption,IDS_TFTP_ERROR_BSIZE);
905 rv = TRUE;
906 break;
907 }
908 }
909 if(o.Lookup(tftpoTOut,v)){
910 m_timeOut=atoi(v);
911 if(!m_timeOut){// *** More sanity checks
912 Deny(tftp::errOption,IDS_TFTP_ERROR_TOUT);
913 rv = TRUE;
914 break;
915 }
916 }
917 if(o.Lookup(tftpoXResume,v)){
918 m_ACK=atoi(v);
919 }
920 }
921 UpdateList();
922 DoXfer();
923 }
924 break;
925 case tftp::opACK:
926 m_ACK=p->data.m_ACK.Block();
927 if(state!=stateFinish){
928 UpdateList();
929 DoXfer();
930 }
931 break;
932 case tftp::opERROR:
933 {
934 ASSERT(m_Daddy);
935 CString tmp;
936 tmp.Format(IDS_LOG_GOTTFTPERROR,p->data.m_ERROR.Code(),(LPCTSTR)p->errMessage());
937 m_Daddy->LogLine(tmp);
938 }
939 Destroy(FALSE);
940 rv = FALSE;
941 break;
942 default:
943 ASSERT(m_Daddy);
944 m_Daddy->LogLine(IDS_LOG_XFEROPCODE);
945 // *** Self destruct maybe??
946 break;
947 }
948 return rv;
949}
950
951BOOL CWRQSocket::OnTFTP(tftp* p)
952{
953 switch(p->Opcode()){
954 case tftp::opOACK:
955 ASSERT(state!=stateFinish);
956 {
957 if(m_bResume)
958 m_ACK=m_File.GetLength()/m_blkSize;
959 else
960 m_ACK=0;
961 tftp::tftpOptions o;
962 if(p->GetOptions(&o)){
963 CString v;
964 if(o.Lookup(tftpoBSize,v)){
965 m_blkSize=atoi(v);
966 if(!m_blkSize){// *** More sanity checks
967 Deny(tftp::errOption,IDS_TFTP_ERROR_BSIZE);
968 return TRUE;
969 }
970 }
971 if(o.Lookup(tftpoTOut,v)){
972 m_timeOut=atoi(v);
973 if(!m_timeOut){// *** More sanity checks
974 Deny(tftp::errOption,IDS_TFTP_ERROR_TOUT);
975 return TRUE;
976 }
977 }
978 if(o.Lookup(tftpoTSize,v)){
979 m_xferSize=atoi(v);
980 }
981 }
982 UpdateList();
983 DoXfer();
984 }
985 break;
986 case tftp::opDATA:
987 {
988 UINTblock = p->data.m_DATA.Block();
989 TRY{
990 m_File.Seek((block-1)*m_blkSize,CFile::begin);
991 int bytes = p->length-sizeof(p->data.m_DATA.block)-(tftpHdrSize-tftpSlackSize);
992 if(bytes){
993 m_File.Write(p->data.m_DATA.data,bytes);
994 // *** Move to the other place where we can do it not that often
995 m_File.SetLength(m_File.GetPosition());
996 }
997 if(bytes<m_blkSize){
998 state=stateFinish;
999 ASSERT(m_Daddy);
1000 CString tmp;
1001 tmp.Format(IDS_LOG_XFERWRQFINISHED,(LPCTSTR)m_FileName);
1002 m_Daddy->LogLine(tmp);
1003 }
1004 m_ACK=block;
1005 m_LastSlack=m_blkSize-bytes;
1006 UpdateList();
1007 DoXfer();
1008 }CATCH(CFileException,e){
1009 Deny(e);
1010 }END_CATCH
1011 }
1012 break;
1013 case tftp::opERROR:
1014 {
1015 ASSERT(m_Daddy);
1016 CString tmp;
1017 tmp.Format(IDS_LOG_GOTTFTPERROR,p->data.m_ERROR.Code(),(LPCTSTR)p->errMessage());
1018 m_Daddy->LogLine(tmp);
1019 }
1020 Destroy(FALSE);
1021 return FALSE;
1022 default:
1023 ASSERT(m_Daddy);
1024 m_Daddy->LogLine(IDS_LOG_XFEROPCODE);
1025 // *** Self destruct maybe??
1026 break;
1027 }
1028 return TRUE;
1029}
1030
1031void tftp::SetOpcode(WORD op)
1032{
1033 opcode = REVERSEBYTES(op);
1034}
1035void tftp::tftpDATA::SetBlock(WORD b)
1036{
1037 block=REVERSEBYTES(b);
1038}
1039WORD tftp::tftpDATA::Block()
1040{
1041 return REVERSEBYTES(block);
1042}
1043WORD tftp::tftpACK::Block()
1044{
1045 return REVERSEBYTES(block);
1046}
1047void tftp::tftpACK::SetBlock(WORD b)
1048{
1049 block = REVERSEBYTES(b);
1050}
1051WORD tftp::tftpERROR::Code()
1052{
1053 return REVERSEBYTES(code);
1054}
1055void tftp::tftpERROR::SetCode(WORD c)
1056{
1057 code = REVERSEBYTES(c);
1058}
1059
1060
1061CString tftp::errMessage()
1062{
1063CString rv;
1064 if(memchr(data.m_ERROR.data,0,length-(tftpHdrSize-tftpSlackSize)-sizeof(data.m_ERROR.code)))
1065 rv = (LPCTSTR)data.m_ERROR.data;
1066 return rv;
1067}
1068
1069void CXferSocket::Destroy(BOOL success)
1070{
1071 if(m_wndResolver){
1072 delete m_wndResolver;
1073 m_wndResolver=NULL;
1074 }
1075 SetTry();
1076 m_Daddy->m_bnw.StartSound(
1077 success
1078 ? m_Daddy->m_bnwSuccess
1079 : m_Daddy->m_bnwAbort
1080 );
1081 if(m_File.m_hFile!=CFile::hFileNull){
1082 TRY{
1083 m_File.Close();
1084 }CATCH(CFileException,e){
1085 TRACE0("Error closing file\n");
1086 }END_CATCH
1087 }
1088 ASSERT(m_Daddy);
1089 m_Daddy->KillTimer(m_hSocket);
1090 m_Daddy->m_Xfers.RemoveKey(m_hSocket);
1091LV_FINDINFO lvf;
1092 memset(&lvf,0,sizeof(lvf));
1093 lvf.flags=LVFI_PARAM;
1094 lvf.lParam=(LPARAM)this;
1095int i = m_Daddy->m_List.FindItem(&lvf);
1096 if(i>=0)
1097 m_Daddy->m_List.DeleteItem(i);
1098 delete this;
1099}
1100
1101void CPumpKINDlg::LogLine(LPCTSTR str)
1102{
1103 ASSERT(m_LogLength);
1104 while(m_Log.GetCount()>m_LogLength && m_Log.GetCount()!=LB_ERR){
1105 CTime *t = (CTime*)m_Log.GetItemData(0);
1106 if(((DWORD)t)!=LB_ERR){
1107 ASSERT(t);
1108 m_LogTimes.RemoveKey(t);
1109 delete t;
1110 }
1111 m_Log.DeleteString(0);
1112 }
1113int i = m_Log.AddString(str);
1114 ASSERT(i!=LB_ERR);
1115CTime *t = new CTime(CTime::GetCurrentTime());
1116 m_Log.SetItemData(i,(DWORD)(m_LogTimes[t]=t));
1117 m_Log.SetCurSel(i);
1118}
1119
1120void CPumpKINDlg::LogLine(UINT msgID)
1121{
1122CString tmp;
1123 tmp.Format(msgID);
1124 LogLine(tmp);
1125}
1126
1127void CXferSocket::TurnSlashes(CString& fn,BOOL bBack)
1128{
1129 ints = fn.Find(bBack?'/':'\\');
1130 while(s>=0){
1131 fn.SetAt(s,bBack?'\\':'/');
1132 s = fn.Find(bBack?'/':'\\');
1133 }
1134}
1135
1136CString CXferSocket::ApplyRoot(LPCTSTR fileName)
1137{
1138 ASSERT(m_Daddy);
1139CString fn = fileName;
1140CString rv = m_Daddy->m_TFTPRoot;
1141 if(rv.IsEmpty())
1142 rv = ".";
1143 if(rv[rv.GetLength()-1]!='\\')
1144 rv+="\\";
1145 while((!fn.IsEmpty()) && fn[0]=='\\')
1146 fn=fn.Mid(1);
1147 rv+=fn;
1148 return rv;
1149}
1150
1151void CPumpKINDlg::OnOptions()
1152{
1153CPropertySheet cps(IDS_TITLE_OPTIONS,this);
1154CPropsServer server;
1155CPropsNetwork network;
1156CPropsSounds sounds;
1157
1158 server.m_RRQMode=m_RRQMode;
1159 server.m_TFTPRoot=m_TFTPRoot;
1160 server.m_TFTPSubdirs=m_bTFTPSubdirs;
1161 server.m_WRQMode=m_WRQMode;
1162 server.m_PromptTimeOut=m_PromptTimeOut;
1163
1164 network.m_ListenPort=m_ListenPort;
1165 network.m_SpeakPort=m_SpeakPort;
1166 network.m_TimeOut=m_TFTPTimeOut.GetTotalSeconds();
1167 network.m_BlockSize=m_BlockSize;
1168
1169 sounds.m_Request = m_bnwRequest;
1170 sounds.m_Success = m_bnwSuccess;
1171 sounds.m_Abort = m_bnwAbort;
1172
1173 cps.AddPage(&server);
1174 cps.AddPage(&network);
1175 cps.AddPage(&sounds);
1176 if(cps.DoModal()==IDOK){
1177 m_RRQMode=server.m_RRQMode;
1178 m_TFTPRoot=server.m_TFTPRoot;
1179 m_bTFTPSubdirs=server.m_TFTPSubdirs;
1180 m_WRQMode=server.m_WRQMode;
1181 m_PromptTimeOut=server.m_PromptTimeOut;
1182
1183 m_ListenPort=network.m_ListenPort;
1184 m_SpeakPort=network.m_SpeakPort;
1185 m_TFTPTimeOut=CTimeSpan(network.m_TimeOut);
1186 m_BlockSize=network.m_BlockSize;
1187
1188 m_bnwRequest = sounds.m_Request;
1189 m_bnwSuccess = sounds.m_Success;
1190 m_bnwAbort = sounds.m_Abort;
1191 }
1192}
1193
1194BOOL CRRQSocket::ConfirmRequest()
1195{
1196CConfirmRRQDlg cd(NULL);
1197 cd.m_Daddy=this;
1198 cd.m_File=m_FileName;
1199 cd.m_Host=inet_ntoa(m_Peer.sin_addr);
1200 if(cd.DoModal()==IDOK)
1201 return TRUE;
1202 return FALSE;
1203}
1204
1205CWRQSocket::CWRQSocket(CPumpKINDlg* daddy,LPCTSTR fileName,LPCTSTR type,SOCKADDR_IN *sin)
1206 : CXferSocket(daddy,fileName,type,sin)
1207{
1208 state=stateNone;
1209 m_ACK=0;
1210 m_LastSlack=0;
1211 m_bResume=FALSE;
1212}
1213
1214BOOL CWRQSocket::Create(LPCTSTR localFile,LPCTSTR hostName)
1215{
1216 if(!CAsyncSocket::Create(0,SOCK_DGRAM))
1217 return FALSE;
1218 ASSERT(m_Daddy);
1219 ASSERT(m_Peer.sin_addr.s_addr!=INADDR_NONE || hostName);
1220 m_Daddy->m_Xfers[m_hSocket]=this;
1221 TurnSlashes(m_FileName,TRUE);
1222 UpdateList();
1223CString fn = localFile?ApplyRootGently(localFile):ApplyRoot(m_FileName);
1224 if(!localFile){// This is an incoming request..
1225 if(CheckBadRelativeness(m_FileName)){
1226 Deny(tftp::errAccessViolation,IDS_TFTP_ERROR_ACCESS);
1227 return TRUE;
1228 }
1229 BOOL exists;
1230 if(!_access((LPCTSTR)fn,0))
1231 m_Rename=exists=TRUE;
1232 else
1233 m_Rename=exists=FALSE;
1234 // *** m_WRQMode only if server transfer
1235 switch(m_Daddy->m_WRQMode){
1236 case CPumpKINDlg::wrqTakeAll:
1237 if(exists){
1238 if(!RenameFile(fn)){
1239 Deny(tftp::errDiskFull,IDS_TFTP_ERROR_FAILEDTORENAME);
1240 return TRUE;
1241 }
1242 }
1243 break;
1244 case CPumpKINDlg::wrqConfirmIfExists:
1245 if(!exists)
1246 break;
1247 case CPumpKINDlg::wrqAlwaysConfirm:
1248 if(exists)
1249 m_bResume=TRUE;
1250 if(ConfirmRequest()){
1251 if(m_Rename){
1252 RenameFile(fn);
1253 if(SaveAs(fn))
1254 break;
1255 }else
1256 break;
1257 }
1258 case CPumpKINDlg::wrqDenyAll:
1259 Deny(tftp::errAccessViolation,IDS_TFTP_ERROR_ACCESS);
1260 return TRUE;
1261 }
1262 }
1263CFileException e;
1264 if(!m_File.Open(
1265 fn,
1266 m_bResume
1267 ?(CFile::modeWrite|CFile::shareDenyWrite)
1268 :(CFile::modeCreate|CFile::modeWrite|CFile::shareDenyWrite),
1269 &e
1270 )){
1271 if(localFile){// Outgoing request
1272 CString tmp;
1273 tmp.Format(IDS_LOG_FAILEDTOOPEN,fn);
1274 m_Daddy->LogLine(tmp);
1275 return FALSE;
1276 }else{
1277 Deny(&e);
1278 return TRUE;
1279 }
1280 }
1281 if(hostName){
1282 m_HostName=hostName;
1283
1284 CString tmp;
1285 tmp.Format(IDS_LOG_REQUESTING,m_FileName,m_HostName);
1286 m_Daddy->LogLine(tmp);
1287
1288 CString inAddr = hostName;
1289 int at = inAddr.Find('@');
1290 if(at>=0)
1291 inAddr=inAddr.Mid(at+1);
1292 if((m_Peer.sin_addr.s_addr=inet_addr((LPCTSTR)inAddr))==INADDR_NONE){
1293 ASSERT(!m_wndResolver);
1294 m_wndResolver = new CResolver(this);
1295 ASSERT(m_wndResolver);
1296 return m_wndResolver->Resolve();
1297 }else{
1298 OnHostKnown();
1299 return TRUE;
1300 }
1301 }
1302CString v;
1303tftp::tftpOptions oack;
1304 if(m_Options.Lookup(tftpoTSize,v)){
1305 m_xferSize=atol(v);
1306 if(!m_xferSize){
1307 Deny(tftp::errOption,IDS_TFTP_ERROR_TSIZE);
1308 return TRUE;
1309 }
1310 }
1311 if(m_Options.Lookup(tftpoBSize,v)){
1312 m_blkSize=atoi(v);
1313 if(!m_blkSize){// *** Do more about sanity check
1314 Deny(tftp::errOption,IDS_TFTP_ERROR_BSIZE);
1315 return TRUE;
1316 }
1317 v.Format("%u",m_blkSize);
1318 oack[tftpoBSize]=v;
1319 }
1320 if(m_Options.Lookup(tftpoTOut,v)){
1321 m_timeOut=atoi(v);
1322 if(!m_timeOut){// *** Do more about sanity check
1323 Deny(tftp::errOption,IDS_TFTP_ERROR_TOUT);
1324 return TRUE;
1325 }
1326 v.Format("%u",m_timeOut);
1327 oack[tftpoTOut]=v;
1328 }
1329 if(m_Options.Lookup(tftpoXResume,v) && m_bResume){
1330 m_ACK=m_File.GetLength()/m_blkSize;
1331 v.Format("%u",m_ACK);
1332 oack[tftpoXResume]=v;
1333 }else
1334 m_ACK=0;
1335 state=stateXfer;
1336 if(oack.GetCount()){
1337 tftp *p = tftp::Allocate(tftp::tftpOACK::tftpSize(&oack));
1338 ASSERT(p);
1339 p->SetOpcode(tftp::opOACK);
1340 p->data.m_OACK.Set(&oack);
1341 PostTFTP(p,TRUE);
1342 }else
1343 DoXfer();
1344 return TRUE;
1345}
1346
1347BOOL CWRQSocket::ConfirmRequest()
1348{
1349CConfirmWRQDlg cd(NULL);
1350 cd.m_Daddy=this;
1351 cd.m_File=m_FileName;
1352 cd.m_Host=inet_ntoa(m_Peer.sin_addr);
1353 switch(cd.DoModal()){
1354 case IDOK:
1355 m_Rename=FALSE;
1356 m_bResume=FALSE;
1357 return TRUE;
1358 case IDC_RENAME:
1359 m_bResume=FALSE;
1360 m_Rename=TRUE;
1361 return TRUE;
1362 case IDC_RESUME:
1363 m_Rename=FALSE;
1364 m_bResume=TRUE;
1365 return TRUE;
1366 case IDCANCEL:
1367 return FALSE;
1368 }
1369 return FALSE;
1370}
1371
1372BOOL CWRQSocket::RenameFile(CString& fn)
1373{
1374CString renamed = fn;
1375 if(fn.IsEmpty())
1376 return FALSE;
1377 if(fn[fn.GetLength()-1]==')'){
1378 int op = fn.ReverseFind('(');
1379 if(op>0 && fn[op-1]==' '){
1380 if(fn.Mid(op+1,fn.GetLength()-op-2).SpanExcluding("0123456789").IsEmpty())
1381 renamed = renamed.Left(op-1);
1382 }
1383 }
1384CString testFN;
1385 for(UINT tmp=0;tmp<32768;tmp++){
1386 testFN.Format("%s (%u)",(LPCTSTR)renamed,tmp);
1387 if(!_access((LPCTSTR)testFN,0))
1388 continue;
1389 fn=testFN;
1390 return TRUE;
1391 }
1392 return FALSE;
1393}
1394
1395BOOL CWRQSocket::SaveAs(CString& fn)
1396{
1397CFileDialog cfd(FALSE,NULL,fn,OFN_EXPLORER|OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT|OFN_PATHMUSTEXIST,NULL,m_Daddy);
1398CString title;
1399 title.LoadString(IDS_RENAME_TITLE);
1400 cfd.m_ofn.lpstrTitle=(LPCTSTR)title;
1401 if(cfd.DoModal()!=IDOK)
1402 return FALSE;
1403 fn = cfd.GetPathName();
1404 return TRUE;
1405}
1406
1407void CWRQSocket::DoXfer()
1408{
1409tftp *p = tftp::Allocate(tftp::tftpACK::tftpSize());
1410 ASSERT(p);
1411 p->SetOpcode(tftp::opACK);
1412 p->data.m_ACK.SetBlock(m_ACK);
1413 TRACE1("WRQ-ACK-%u\n",m_ACK);
1414 PostTFTP(p,TRUE);// *** ??? Hope this is right
1415}
1416
1417UINT tftp::tftpACK::tftpSize()
1418{
1419 return tftpHdrSize-tftpSlackSize+sizeof(tftp::tftpACK);
1420}
1421
1422ULONG CWRQSocket::GetACK()
1423{
1424 return (m_ACK*m_blkSize)-m_LastSlack;
1425}
1426
1427void CXferSocket::ResetTimeout()
1428{
1429 ASSERT(m_Daddy);
1430 m_Daddy->m_Retrier->KillTimer(m_hSocket);
1431 if(m_Retry)
1432 m_Daddy->m_Retrier->SetTimer(m_hSocket,min(60,m_Daddy->m_RetryTimeOut.GetTotalSeconds())*1000,NULL);
1433 if(!m_bRetry){
1434 m_Daddy->KillTimer(m_hSocket);
1435 m_Daddy->SetTimer(m_hSocket,min(60,m_timeOut)*1000,NULL);
1436 }
1437}
1438
1439void CXferSocket::Abort()
1440{
1441 ASSERT(m_Daddy);
1442CString tmp;
1443 tmp.Format(IDS_LOG_XFERABORTED,(LPCTSTR)m_FileName);
1444 m_Daddy->LogLine(tmp);
1445 Destroy(FALSE);
1446}
1447
1448void CPumpKINDlg::OnTimer(UINT nIDEvent)
1449{
1450CXferSocket *socket;
1451 if(m_Xfers.Lookup(nIDEvent,socket)){
1452 CString tmp;
1453 tmp.Format(IDS_LOG_TIMEDOUT,socket->m_FileName);
1454 LogLine(tmp);
1455 socket->Abort();
1456 }else{
1457 TRACE0("Failed to find timed out socket!\n");
1458 }
1459 CDialog::OnTimer(nIDEvent);
1460}
1461
1462void CPumpKINDlg::OnExit()
1463{
1464 if(!m_Xfers.IsEmpty()){
1465 CString title,text;
1466 title.LoadString(IDS_CONFIRMEXIT_TITLE);
1467 text.LoadString(IDS_CONFIRMEXIT_TEXT);
1468 if(MessageBox(text,title,MB_ICONQUESTION|MB_YESNO)!=IDYES)
1469 return;
1470 }
1471 m_bExiting=TRUE;
1472 EndDialog(IDOK);
1473}
1474
1475void CPumpKINDlg::OnPut()
1476{
1477CRequestDlg crd(NULL);
1478 crd.m_Put=TRUE;
1479 crd.m_BSize=m_BlockSize;
1480 if(crd.DoModal()==IDOK){
1481 CRRQSocket *socket = new CRRQSocket(this,crd.m_RemoteFile,crd.m_Type,NULL);
1482 if(crd.m_BSize)
1483 socket->m__blkSize=crd.m_BSize;
1484 if(!socket->Create(crd.m_LocalFile,crd.m_Host))
1485 socket->Destroy();
1486 }
1487}
1488
1489void CPumpKINDlg::OnGet()
1490{
1491CRequestDlg crd(NULL);
1492 crd.m_Put=FALSE;
1493 crd.m_BSize=m_BlockSize;
1494 if(crd.DoModal()==IDOK){
1495 CWRQSocket *socket = new CWRQSocket(this,crd.m_RemoteFile,crd.m_Type,NULL);
1496 if(crd.m_BSize)
1497 socket->m__blkSize=crd.m_BSize;
1498 if(!socket->Create(crd.m_LocalFile,crd.m_Host))
1499 socket->Destroy();
1500 }
1501}
1502
1503void CPumpKINDlg::SetupButtons()
1504{
1505 m_AbortCtl.EnableWindow(m_List.GetSelectedCount()>0);
1506}
1507
1508void CPumpKINDlg::OnDeleteallitemsConnections(NMHDR* pNMHDR, LRESULT* pResult)
1509{
1510 NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
1511 SetupButtons();
1512 *pResult = 0;
1513}
1514
1515void CPumpKINDlg::OnDeleteitemConnections(NMHDR* pNMHDR, LRESULT* pResult)
1516{
1517 NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
1518 SetupButtons();
1519 *pResult = 0;
1520}
1521
1522void CPumpKINDlg::OnInsertitemConnections(NMHDR* pNMHDR, LRESULT* pResult)
1523{
1524 NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
1525 SetupButtons();
1526 *pResult = 0;
1527}
1528
1529void CPumpKINDlg::OnItemchangedConnections(NMHDR* pNMHDR, LRESULT* pResult)
1530{
1531 NM_LISTVIEW* pNMListView = (NM_LISTVIEW*)pNMHDR;
1532 SetupButtons();
1533 *pResult = 0;
1534}
1535
1536void CPumpKINDlg::OnAbort()
1537{
1538 if(!m_List.GetSelectedCount())
1539 return;
1540 intitems = m_List.GetItemCount();
1541 for(int tmp=0;tmp<items;tmp++){
1542 if(!(m_List.GetItemState(tmp,LVIS_SELECTED)&LVIS_SELECTED))
1543 continue;
1544 CXferSocket *xfer = (CXferSocket*) m_List.GetItemData(tmp);
1545 ASSERT(xfer);
1546 xfer->Abort();
1547 }
1548}
1549
1550void CXferSocket::OnFailedToResolve()
1551{
1552 TRACE0("Resolve failed\n");
1553 delete m_wndResolver;
1554 m_wndResolver=NULL;
1555 ASSERT(m_Daddy);
1556CString tmp;
1557 tmp.Format(IDS_LOG_RESOLVEFAILED,m_HostName);
1558 m_Daddy->LogLine(tmp);
1559 Abort();
1560}
1561
1562void CXferSocket::OnResolved()
1563{
1564 delete m_wndResolver;
1565 m_wndResolver=NULL;
1566 TRACE0("Resolved\n");
1567 m_Peer.sin_addr.s_addr = *(DWORD*)(((hostent*)m_ResolveBuff)->h_addr);
1568}
1569
1570void CRRQSocket::OnResolved()
1571{
1572 CXferSocket::OnResolved();
1573 OnHostKnown();
1574}
1575
1576void CRRQSocket::OnHostKnown()
1577{
1578 ASSERT(m_Daddy);
1579 m_Peer.sin_port=htons(m_Daddy->m_SpeakPort);
1580tftp::tftpOptions o;
1581CString v;
1582 ASSERT(m_xferSize>=0);
1583 v.Format("%lu",m_xferSize);
1584 o[tftpoTSize] = v;
1585 ASSERT(m__blkSize);
1586 v.Format("%u",m__blkSize);
1587 o[tftpoBSize] = v;
1588 ASSERT(m__timeOut);
1589 v.Format("%u",m__timeOut);
1590 o[tftpoTOut] = v;
1591 o[tftpoXResume] = "0";
1592 tftp*p = tftp::Allocate(tftp::tftpWRQ::tftpSize(m_FileName,m_Type,&o));
1593 ASSERT(p);
1594 p->SetOpcode(tftp::opWRQ);
1595 p->data.m_WRQ.Set(m_FileName,m_Type,&o);
1596 PostTFTP(p,TRUE);
1597 state=stateInit;
1598 UpdateList();
1599}
1600
1601UINT tftp::tftpRQ::tftpSize(LPCTSTR file,LPCTSTR type,tftp::tftpOptions* ops)
1602{
1603UINT rv = tftpHdrSize-tftpSlackSize+strlen(file)+1+strlen(type)+1;
1604 if(ops){
1605 tftpOptions& o = *ops;
1606 POSITION p = o.GetStartPosition();
1607 while(p){
1608 CString n,v;
1609 o.GetNextAssoc(p,n,v);
1610 rv+=n.GetLength()+1+v.GetLength()+1;
1611 }
1612 }
1613 return rv;
1614}
1615UINT tftp::tftpRRQ::tftpSize(LPCTSTR file,LPCTSTR type,tftp::tftpOptions* ops)
1616{
1617 return tftp::tftpRQ::tftpSize(file,type,ops);
1618}
1619UINT tftp::tftpWRQ::tftpSize(LPCTSTR file,LPCTSTR type,tftp::tftpOptions* ops)
1620{
1621 return tftp::tftpRQ::tftpSize(file,type,ops);
1622}
1623UINT tftp::tftpOACK::tftpSize(tftp::tftpOptions* ops)
1624{
1625UINT rv = tftpHdrSize-tftpSlackSize;
1626 if(ops){
1627 tftpOptions& o = *ops;
1628 POSITION p = o.GetStartPosition();
1629 while(p){
1630 CString n,v;
1631 o.GetNextAssoc(p,n,v);
1632 rv+=n.GetLength()+1+v.GetLength()+1;
1633 }
1634 }
1635 return rv;
1636}
1637void tftp::tftpRQ::Set(LPCTSTR file,LPCTSTR type,tftp::tftpOptions* ops)
1638{
1639 // MAY BE DANGEROUS!
1640UINT ptr = 0;
1641 strcpy((LPTSTR)&data[ptr],file); ptr+=strlen(file)+1;
1642 strcpy((LPTSTR)&data[ptr],type); ptr+=strlen(type)+1;
1643 if(ops){
1644 tftpOptions& o = *ops;
1645 POSITION p = o.GetStartPosition();
1646 while(p){
1647 CString n,v;
1648 o.GetNextAssoc(p,n,v);
1649 strcpy((LPTSTR)&data[ptr],(LPCTSTR)n); ptr+=n.GetLength()+1;
1650 strcpy((LPTSTR)&data[ptr],(LPCTSTR)v); ptr+=v.GetLength()+1;
1651 }
1652 }
1653}
1654void tftp::tftpRRQ::Set(LPCTSTR file,LPCTSTR type,tftp::tftpOptions* ops)
1655{
1656 // MAY BE DANGEROUS!
1657UINT ptr = 0;
1658 strcpy((LPTSTR)&data[ptr],file); ptr+=strlen(file)+1;
1659 strcpy((LPTSTR)&data[ptr],type); ptr+=strlen(type)+1;
1660 if(ops){
1661 tftpOptions& o = *ops;
1662 POSITION p = o.GetStartPosition();
1663 while(p){
1664 CString n,v;
1665 o.GetNextAssoc(p,n,v);
1666 strcpy((LPTSTR)&data[ptr],(LPCTSTR)n); ptr+=n.GetLength()+1;
1667 strcpy((LPTSTR)&data[ptr],(LPCTSTR)v); ptr+=v.GetLength()+1;
1668 }
1669 }
1670}
1671void tftp::tftpWRQ::Set(LPCTSTR file,LPCTSTR type,tftp::tftpOptions* ops)
1672{
1673 // MAY BE DANGEROUS!
1674UINT ptr = 0;
1675 strcpy((LPTSTR)&data[ptr],file); ptr+=strlen(file)+1;
1676 strcpy((LPTSTR)&data[ptr],type); ptr+=strlen(type)+1;
1677 if(ops){
1678 tftpOptions& o = *ops;
1679 POSITION p = o.GetStartPosition();
1680 while(p){
1681 CString n,v;
1682 o.GetNextAssoc(p,n,v);
1683 strcpy((LPTSTR)&data[ptr],(LPCTSTR)n); ptr+=n.GetLength()+1;
1684 strcpy((LPTSTR)&data[ptr],(LPCTSTR)v); ptr+=v.GetLength()+1;
1685 }
1686 }
1687}
1688void tftp::tftpOACK::Set(tftpOptions* ops)
1689{
1690 ASSERT(ops);
1691UINT ptr = 0;
1692tftpOptions& o = *ops;
1693POSITION p = o.GetStartPosition();
1694 while(p){
1695 CString n,v;
1696 o.GetNextAssoc(p,n,v);
1697 strcpy((LPTSTR)&data[ptr],(LPCTSTR)n); ptr+=n.GetLength()+1;
1698 strcpy((LPTSTR)&data[ptr],(LPCTSTR)v); ptr+=v.GetLength()+1;
1699 }
1700}
1701
1702void CWRQSocket::OnResolved()
1703{
1704 CXferSocket::OnResolved();
1705 OnHostKnown();
1706}
1707
1708void CWRQSocket::OnHostKnown()
1709{
1710 ASSERT(m_Daddy);
1711 m_Peer.sin_port=htons(m_Daddy->m_SpeakPort);
1712tftp::tftpOptions o;
1713CString v;
1714 o[tftpoTSize]="0";
1715 if(m__blkSize){
1716 v.Format("%u",m__blkSize);
1717 o[tftpoBSize]=v;
1718 }
1719 if(m__timeOut){
1720 v.Format("%u",m__timeOut);
1721 o[tftpoTOut]=v;
1722 }
1723 tftp*p = tftp::Allocate(tftp::tftpRRQ::tftpSize(m_FileName,m_Type,&o));
1724 ASSERT(p);
1725 p->SetOpcode(tftp::opRRQ);
1726 p->data.m_RRQ.Set(m_FileName,m_Type,&o);
1727 PostTFTP(p,TRUE);
1728 state=stateInit;
1729 UpdateList();
1730}
1731
1732void CPumpKINDlg::OnClose()
1733{
1734 OnTrayShowpumpkinwindow();
1735}
1736
1737void CPumpKINDlg::OnTrayShowpumpkinwindow()
1738{
1739 if(IsWindowVisible()){
1740 m_bShown=FALSE;
1741 ShowWindow(SW_HIDE);
1742 }else{
1743 m_bShown=TRUE;
1744 ShowWindow(SW_SHOW);
1745 SetForegroundWindow();
1746 SetFocus();
1747 }
1748}
1749
1750void CPumpKINDlg::OnTrayExit()
1751{
1752 OnExit();
1753}
1754
1755void CPumpKINDlg::OnTrayAboutpumpkin()
1756{
1757CAboutDlg dlgAbout;
1758 dlgAbout.DoModal();
1759}
1760
1761void CPumpKINDlg::OnTrayFetchfile()
1762{
1763 OnGet();
1764}
1765
1766void CPumpKINDlg::OnTrayHelp()
1767{
1768 OnHelp();
1769}
1770
1771void CPumpKINDlg::OnTrayOptions()
1772{
1773 OnOptions();
1774}
1775
1776void CPumpKINDlg::OnTraySendfile()
1777{
1778 OnPut();
1779}
1780
1781void CPumpKINDlg::LoadSettings()
1782{
1783CWinApp *app = AfxGetApp();
1784 ASSERT(app);
1785 m_bnwRequest=app->GetProfileString("BellsNWhistles","Request",m_bnwRequest);
1786 m_bnwSuccess=app->GetProfileString("BellsNWhistles","Success",m_bnwSuccess);
1787 m_bnwAbort=app->GetProfileString("BellsNWhistles","Abort",m_bnwAbort);
1788 m_bTFTPSubdirs=app->GetProfileInt("TFTPSettings","Subdirs",m_bTFTPSubdirs);
1789 m_ListenPort=app->GetProfileInt("TFTPSettings","ListenPort",m_ListenPort);
1790 m_LogLength=app->GetProfileInt("UISettings","LogLength",m_LogLength);
1791 m_PromptTimeOut=app->GetProfileInt("UISettings","PromptTimeout",m_PromptTimeOut);
1792 m_RRQMode=app->GetProfileInt("TFTPSettings","RRQMode",m_RRQMode);
1793 m_SpeakPort=app->GetProfileInt("TFTPSettings","SpeakPort",m_SpeakPort);
1794 m_TFTPRoot=app->GetProfileString("TFTPSettings","TFTPRoot",m_TFTPRoot);
1795 m_TFTPTimeOut=CTimeSpan(app->GetProfileInt("TFTPSettings","TFTPTimeout",m_TFTPTimeOut.GetTotalSeconds()));
1796 m_BlockSize=app->GetProfileInt("TFTPSettings","TFTPBlockSize",m_BlockSize);
1797 m_RetryTimeOut=CTimeSpan(app->GetProfileInt("TFTPSettings","RetryTimeout",m_RetryTimeOut.GetTotalSeconds()));
1798 m_WRQMode=app->GetProfileInt("TFTPSettings","WRQMode",m_WRQMode);
1799 m_bShown=app->GetProfileInt("UISettings","Visble",m_bShown);
1800 if(m_TFTPRoot.IsEmpty()){
1801 DWORD dL = ::GetCurrentDirectory(0,NULL);
1802 VERIFY(::GetCurrentDirectory(dL,m_TFTPRoot.GetBuffer(dL)));
1803 m_TFTPRoot.ReleaseBuffer();
1804 }
1805 ::SetCurrentDirectory(m_TFTPRoot);
1806}
1807
1808void CPumpKINDlg::SaveSettings()
1809{
1810CWinApp *app = AfxGetApp();
1811 ASSERT(app);
1812 app->WriteProfileString("BellsNWhistles","Request",m_bnwRequest);
1813 app->WriteProfileString("BellsNWhistles","Success",m_bnwSuccess);
1814 app->WriteProfileString("BellsNWhistles","Abort",m_bnwAbort);
1815 app->WriteProfileInt("TFTPSettings","Subdirs",m_bTFTPSubdirs);
1816 app->WriteProfileInt("TFTPSettings","ListenPort",m_ListenPort);
1817 app->WriteProfileInt("UISettings","LogLength",m_LogLength);
1818 app->WriteProfileInt("UISettings","PromptTimeout",m_PromptTimeOut);
1819 app->WriteProfileInt("TFTPSettings","RRQMode",m_RRQMode);
1820 app->WriteProfileInt("TFTPSettings","SpeakPort",m_SpeakPort);
1821 app->WriteProfileString("TFTPSettings","TFTPRoot",m_TFTPRoot);
1822 app->WriteProfileInt("TFTPSettings","TFTPTimeout",m_TFTPTimeOut.GetTotalSeconds());
1823 app->WriteProfileInt("TFTPSettings","TFTPBlockSize",m_BlockSize);
1824 app->WriteProfileInt("TFTPSettings","RetryTimeout",m_RetryTimeOut.GetTotalSeconds());
1825 app->WriteProfileInt("TFTPSettings","WRQMode",m_WRQMode);
1826 app->WriteProfileInt("UISettings","Visble",m_bShown);
1827}
1828
1829void CPumpKINDlg::OnWindowPosChanging(WINDOWPOS FAR* lpwndpos)
1830{
1831 CDialog::OnWindowPosChanging(lpwndpos);
1832 if(!m_bExiting){
1833 if(m_bShown){
1834 lpwndpos->flags&=~SWP_HIDEWINDOW;
1835 lpwndpos->flags|=SWP_SHOWWINDOW;
1836 }else{
1837 lpwndpos->flags&=~SWP_SHOWWINDOW;
1838 lpwndpos->flags|=SWP_HIDEWINDOW;
1839 if(::GetForegroundWindow()==m_hWnd && (m_Trayer && !m_Trayer->m_inMenu))
1840 GetDesktopWindow()->SetForegroundWindow();
1841 }
1842 }
1843}
1844
1845CString CXferSocket::ApplyRootGently(LPCTSTR fn)
1846{
1847CString f = fn;
1848CString rv = f;
1849 if((!f.IsEmpty()) && f[0]!='\\' && f.Find(":")<0 && f.Find("\\")<0)
1850 rv = ApplyRoot(f);
1851 return rv;
1852}
1853
1854BOOL CXferSocket::CheckBadRelativeness(LPCTSTR file)
1855{
1856CString tmp = file;
1857 if(tmp.IsEmpty())
1858 return FALSE;
1859 if(tmp.Find("..")>=0)
1860 return TRUE;
1861 if(tmp.Find(":")>=0)
1862 return TRUE;
1863 if((!m_Daddy->m_bTFTPSubdirs) && m_FileName.Find('\\')>=0)
1864 return TRUE;
1865 return FALSE;
1866}
1867
1868void CAboutDlg::OnKlevernet()
1869{
1870CString url;
1871 url.LoadString(IDS_KLEVERNET_URL);
1872 ShellExecute(::GetDesktopWindow(),"open",url,NULL,NULL,SW_SHOWMAXIMIZED);
1873}
1874
1875BOOL CPumpKINDlg::PreTranslateMessage(MSG* pMsg)
1876{
1877 // CG: The following block was added by the ToolTips component.
1878 {
1879 // Let the ToolTip process this message.
1880 m_tooltip.RelayEvent(pMsg);
1881
1882 return CDialog::PreTranslateMessage(pMsg);
1883 }
1884}
1885
1886void CPumpKINDlg::OnSelchangeLog()
1887{
1888int sel = m_Log.GetCurSel();
1889 if(sel==LB_ERR){
1890 TRACE0("Error retrieving selection\n");
1891 }else{
1892 CTime *t = (CTime*)m_Log.GetItemData(sel);
1893 ASSERT(t);
1894 m_tooltip.UpdateTipText(t->Format(IDS_LOGTIMEFORMAT),&m_Log);
1895 }
1896}
1897
1898void CPumpKINDlg::OnTrayOpenfilesfolder()
1899{
1900 ShellExecute(::GetDesktopWindow(),NULL,m_TFTPRoot,NULL,NULL,SW_SHOWDEFAULT);
1901}
1902
1903void CPumpKINDlg::OnDropFiles(HDROP hDropInfo)
1904{
1905UINT files = ::DragQueryFile(hDropInfo,0xFFFFFFFF,NULL,0);
1906 ASSERT(files);
1907 for(UINT file=0;file<files;file++){
1908 CString theFile;
1909 UINT fileNameLength = ::DragQueryFile(hDropInfo,file,NULL,0);
1910 ASSERT(fileNameLength);
1911 VERIFY(::DragQueryFile(hDropInfo,file,theFile.GetBuffer(fileNameLength+5),fileNameLength+4)<=fileNameLength);
1912 theFile.ReleaseBuffer();
1913 // Send it over!
1914 CRequestDlg crd(NULL);
1915 crd.m_Drop=TRUE;
1916 crd.m_Put=TRUE;
1917 crd.m_BSize=m_BlockSize;
1918 crd.m_LocalFile=theFile;
1919 if(crd.DoModal()==IDOK){
1920 CRRQSocket *socket = new CRRQSocket(this,crd.m_RemoteFile,crd.m_Type,NULL);
1921 if(crd.m_BSize)
1922 socket->m__blkSize=crd.m_BSize;
1923 if(!socket->Create(crd.m_LocalFile,crd.m_Host))
1924 socket->Destroy();
1925 }
1926 }
1927 ::DragFinish(hDropInfo);
1928}
1929
1930void CPumpKINDlg::OnCancel()
1931{
1932 OnClose();
1933}
1934
1935CPumpKINDlg::~CPumpKINDlg()
1936{
1937 delete m_Trayer;
1938 delete m_Retrier;
1939}
1940
1941void CXferSocket::OnRetry()
1942{
1943 if(!m_Retry){
1944 TRACE("Retrying unretriable..\n");
1945 return;
1946 }
1947 TRACE0("Retrying..\n");
1948 m_bRetry=TRUE;
1949 PostTFTP(tftp::Copy(m_Retry));
1950 m_bRetry=FALSE;
1951}
1952
1953tftp* tftp::Copy(tftp *src)
1954{
1955 ASSERT(src);
1956 ASSERT(src->length);
1957tftp* rv = Allocate(src->length);
1958 ASSERT(rv);
1959 memmove(rv,src,tftpSlackSize+src->length);
1960 return rv;
1961}
1962
1963void CXferSocket::SetTry(tftp *p)
1964{
1965 if(m_Retry)
1966 delete m_Retry;
1967 m_Retry=p?tftp::Copy(p):NULL;
1968}
1969
1970void CPumpKINDlg::OnHelp()
1971{
1972 AfxGetApp()->WinHelp(0,HELP_FINDER);
1973}