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