1 //=============================================================================
2 //
3 //   File : DccCanvasWindow.cpp
4 //   Creation date : Sun Jul 29 07 2001 20:23:13 by Szymon Stefanek
5 //
6 //   This file is part of the KVIrc IRC client distribution
7 //   Copyright (C) 2001-2010 Szymon Stefanek (pragma at kvirc dot net)
8 //
9 //   This program is FREE software. You can redistribute it and/or
10 //   modify it under the terms of the GNU General Public License
11 //   as published by the Free Software Foundation; either version 2
12 //   of the License, or (at your option) any later version.
13 //
14 //   This program is distributed in the HOPE that it will be USEFUL,
15 //   but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 //   See the GNU General Public License for more details.
18 //
19 //   You should have received a copy of the GNU General Public License
20 //   along with this program. If not, write to the Free Software Foundation,
21 //   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 //
23 //=============================================================================
24 
25 #define QT_MODULE_CANVAS
26 
27 #include "DccCanvasWindow.h"
28 
29 #ifdef COMPILE_DCC_CANVAS
30 
31 #include "DccDialog.h"
32 #include "DccMarshal.h"
33 #include "canvaswidget.h"
34 
35 #define _KVI_DEBUG_CHECK_RANGE_
36 #include "kvi_debug.h"
37 #include "KviOptions.h"
38 #include "KviInput.h"
39 #include "KviIrcView.h"
40 #include "KviIconManager.h"
41 #include "KviLocale.h"
42 #include "KviError.h"
43 #include "kvi_out.h"
44 #include "KviNetUtils.h"
45 #include "KviConsoleWindow.h"
46 #include "KviMainWindow.h"
47 #include "KviMemory.h"
48 #include "KviThread.h"
49 #include "KviIrcSocket.h"
50 #include "kvi_settings.h"
51 #include "KviIrcConnection.h"
52 
53 #include <QSplitter>
54 
55 extern DccBroker * g_pDccBroker;
56 
DccCanvasWindow(DccDescriptor * dcc,const char * name)57 DccCanvasWindow::DccCanvasWindow(DccDescriptor * dcc, const char * name)
58     : DccWindow(KVI_WINDOW_TYPE_DCCCANVAS, name, dcc)
59 {
60 	m_pSplitter = new QSplitter(QSplitter::Vertical, this, "splitter");
61 
62 	m_pCanvas = new DccCanvasWidget(m_pSplitter);
63 
64 	m_pIrcView = new KviIrcView(m_pSplitter, this);
65 	m_pInput = new KviInput(this);
66 
67 	//	setFocusHandler(m_pInput,this);
68 
69 	m_pMarshal = new DccMarshal(this);
70 	connect(m_pMarshal, SIGNAL(error(int)), this, SLOT(handleMarshalError(int)));
71 	connect(m_pMarshal, SIGNAL(connected()), this, SLOT(connected()));
72 
73 	if(!(m_pDescriptor->bActive))
74 	{
75 		// PASSIVE CONNECTION
76 		output(KVI_OUT_DCCMSG, __tr2qs_ctx("Attempting a passive DCC CANVAS connection", "dcc"));
77 		int ret = m_pMarshal->dccListen(dcc->szListenIp, dcc->szListenPort, m_pDescriptor->bDoTimeout);
78 		if(ret != KviError_success)
79 			handleMarshalError(ret);
80 		else
81 		{
82 
83 			output(KVI_OUT_DCCMSG, __tr2qs_ctx("Listening on interface %Q port %Q", "dcc"),
84 			    &(m_pMarshal->localIp()), &(m_pMarshal->localPort()));
85 
86 			if(dcc->bSendRequest)
87 			{
88 				QString ip = !dcc->szFakeIp.isEmpty() ? dcc->szFakeIp : dcc->szListenIp;
89 				QString port = !dcc->szFakePort.isEmpty() ? dcc->szFakePort.toUtf8().data() : m_pMarshal->localPort();
90 				//#warning "OPTION FOR SENDING 127.0.0.1 and so on (not an unsigned number)"
91 				struct in_addr a;
92 				if(kvi_stringIpToBinaryIp(ip.toUtf8().data(), &a))
93 					ip.setNum(htonl(a.s_addr));
94 				dcc->console()->connection()->sendFmtData("PRIVMSG %s :%cDCC CANVAS chat %Q %Q%c",
95 				    dcc->console()->connection()->encodeText(dcc->szNick.toUtf8().data()).data(),
96 				    0x01, &ip,
97 				    &port,
98 				    0x01);
99 				output(KVI_OUT_DCCMSG, __tr2qs_ctx("Sent DCC CANVAS request to %Q, waiting for the remote client to connect...", "dcc"),
100 				    &(dcc->szNick));
101 			}
102 			else
103 				outputNoFmt(KVI_OUT_DCCMSG, __tr2qs_ctx("DCC CANVAS request not sent: awaiting manual connections", "dcc"));
104 		}
105 	}
106 	else
107 	{
108 		// ACTIVE CONNECTION
109 		outputNoFmt(KVI_OUT_DCCMSG, __tr2qs_ctx("Attempting an active DCC CANVAS connection", "dcc"));
110 		int ret = m_pMarshal->dccConnect(dcc->szIp.toUtf8().data(), dcc->szPort.toUtf8().data(), m_pDescriptor->bDoTimeout);
111 		if(ret != KviError_success)
112 			handleMarshalError(ret);
113 		else
114 			output(KVI_OUT_DCCMSG, __tr2qs_ctx("Contacting host %Q on port %Q", "dcc"), &(dcc->szIp), &(dcc->szPort));
115 	}
116 
117 	//	m_pSlaveThread = nullptr;
118 }
119 
~DccCanvasWindow()120 DccCanvasWindow::~DccCanvasWindow()
121 {
122 	g_pDccBroker->unregisterDccWindow(this);
123 	//	if(m_pSlaveThread)
124 	//	{
125 	//		m_pSlaveThread->terminate();
126 	//		delete m_pSlaveThread;
127 	//		m_pSlaveThread = nullptr;
128 	//	}
129 	KviThreadManager::killPendingEvents(this);
130 	//	delete m_pDescriptor;
131 	//	delete m_pMarshal;
132 }
133 
target()134 const QString & DccCanvasWindow::target()
135 {
136 	// This may change on the fly...
137 	m_szTarget.sprintf("%s@%s:%s",
138 	    m_pDescriptor->szNick.toUtf8().data(), m_pDescriptor->szIp.toUtf8().data(), m_pDescriptor->szPort.toUtf8().data());
139 	return m_szTarget;
140 }
141 
fillCaptionBuffers()142 void DccCanvasWindow::fillCaptionBuffers()
143 {
144 	KviCString tmp(KviCString::Format, "DCC Canvas %s@%s:%s",
145 	    m_pDescriptor->szNick.toUtf8().data(), m_pDescriptor->szIp.toUtf8().data(), m_pDescriptor->szPort.toUtf8().data());
146 
147 	m_szPlainTextCaption = tmp;
148 
149 	m_szHtmlActiveCaption.sprintf("<font color=\"%s\"><b>%s</b></font>",
150 	    KVI_OPTION_COLOR(KviOption_colorCaptionTextActive).name().ascii(), tmp.ptr());
151 	m_szHtmlInactiveCaption.sprintf("<font color=\"%s\"><b>%s</b></font>",
152 	    KVI_OPTION_COLOR(KviOption_colorCaptionTextInactive).name().ascii(), tmp.ptr());
153 }
154 
myIconPtr()155 QPixmap * DccCanvasWindow::myIconPtr()
156 {
157 	return g_pIconManager->getSmallIcon(KviIconManager::Canvas);
158 }
159 
getBaseLogFileName(KviCString & buffer)160 void DccCanvasWindow::getBaseLogFileName(KviCString & buffer)
161 {
162 	buffer.sprintf("%s_%s_%s", m_pDescriptor->szNick.toUtf8().data(), m_pDescriptor->szIp.toUtf8().data(), m_pDescriptor->szPort.toUtf8().data());
163 }
164 
ownMessage(const QString & text,bool bUserFeedback)165 void DccCanvasWindow::ownMessage(const QString & text, bool bUserFeedback)
166 {
167 	KviCString buf(KviCString::Format, "%s\r\n", text);
168 	//	m_pSlaveThread->sendRawData(buf.ptr(),buf.len());
169 
170 	if(bUserFeedback)
171 		m_pFrm->firstConsole()->outputPrivmsg(this, KVI_OUT_OWNPRIVMSG,
172 		    m_pDescriptor->szLocalNick.toUtf8().data(), m_pDescriptor->szLocalUser.toUtf8().data(),
173 		    m_pDescriptor->szLocalHost.toUtf8().data(), text);
174 }
175 
ownAction(const QString & text)176 void DccCanvasWindow::ownAction(const QString & text)
177 {
178 	KviCString buf(KviCString::Format, "%cACTION %s%c\r\n", text);
179 	//	m_pSlaveThread->sendRawData(buf.ptr(),buf.len());
180 	output(KVI_OUT_OWNACTION, "%Q %s", &(m_pDescriptor->szLocalNick), text);
181 }
182 
event(QEvent * e)183 bool DccCanvasWindow::event(QEvent * e)
184 {
185 	//	if(e->type() == KVI_THREAD_EVENT)
186 	//	{
187 	//		switch(((KviThreadEvent *)e)->id())
188 	//		{
189 	//			case KVI_DCC_THREAD_EVENT_ERROR:
190 	//			{
191 	//				int * err = ((KviThreadDataEvent<int> *)e)->getData();
192 	//				output(KVI_OUT_DCCERROR,__tr("ERROR: %s"),kvi_getErrorString(*err));
193 	//				delete err;
194 	//				return true;
195 	//			}
196 	//			break;
197 	//			case KVI_DCC_THREAD_EVENT_DATA:
198 	//			{
199 	//				KviCString * d = ((KviThreadDataEvent<KviCString> *)e)->getData();
200 	//				if(d->firstCharIs(0x01))
201 	//				{
202 	//					d->cutLeft(1);
203 	//					if(d->lastCharIs(0x01))d->cutRight(1);
204 	//					if(kvi_strEqualCIN("ACTION",d->ptr(),6))d->cutLeft(6);
205 	//					d->stripLeftWhiteSpace();
206 	//					output(KVI_OUT_ACTION,"%s %s",m_pDescriptor->szNick.ptr(),d->ptr());
207 	//				} else {
208 	//
209 	//#ifdef COMPILE_CRYPT_SUPPORT
210 	//					if(KviCryptSessionInfo * cinf = cryptSessionInfo())
211 	//					{
212 	//						if(cinf->bDoDecrypt)
213 	//						{
214 	//							if(cinf->pEngine->isCryptographicEngine() && (*(d->ptr()) == KVI_TEXT_CRYPT))
215 	//							{
216 	//								KviCString decryptedStuff;
217 	//								if(cinf->pEngine->decrypt(d->ptr() + 1,decryptedStuff))
218 	//								{
219 	//									m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_DCCCHATMSGCRYPTED,
220 	//										m_pDescriptor->szNick.ptr(),m_pDescriptor->szUser.ptr(),
221 	//										m_pDescriptor->szHost.ptr(),decryptedStuff.ptr());
222 	//								} else {
223 	//									output(KVI_OUT_SYSTEMERROR,
224 	//										__tr("The following message looks like an encrypted one, but the crypting engine failed to decode it: %s"),
225 	//										cinf->pEngine->lastError());
226 	//									m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_DCCCHATMSG,
227 	//										m_pDescriptor->szNick.ptr(),m_pDescriptor->szUser.ptr(),
228 	//										m_pDescriptor->szHost.ptr(),d->ptr() + 1);
229 	//								}
230 	//								delete d;
231 	//								return true;
232 	//							} else {
233 	//								if(!(cinf->pEngine->isCryptographicEngine()))
234 	//								{
235 	//									KviCString decryptedStuff;
236 	//									if(cinf->pEngine->decrypt(d->ptr(),decryptedStuff))
237 	//									{
238 	//										m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_DCCCHATMSG,
239 	//											m_pDescriptor->szNick.ptr(),m_pDescriptor->szUser.ptr(),
240 	//											m_pDescriptor->szHost.ptr(),decryptedStuff.ptr());
241 	//										delete d;
242 	//										return true;
243 	//									} else {
244 	//										output(KVI_OUT_SYSTEMERROR,
245 	//											__tr("The following message looks like an encrypted one, but the crypting engine failed to decode it: %s"),
246 	//											cinf->pEngine->lastError());
247 	//									}
248 	//								}
249 	//							}
250 	//						}
251 	//					}
252 	//#endif
253 	//					m_pFrm->firstConsole()->outputPrivmsg(this,KVI_OUT_DCCCHATMSG,
254 	//						m_pDescriptor->szNick.ptr(),m_pDescriptor->szUser.ptr(),
255 	//						m_pDescriptor->szHost.ptr(),d->ptr());
256 	//				}
257 	//				delete d;
258 	//				return true;
259 	//			}
260 	//			break;
261 	//		}
262 	//	}
263 	return KviWindow::event(e);
264 }
265 
resizeEvent(QResizeEvent * e)266 void DccCanvasWindow::resizeEvent(QResizeEvent * e)
267 {
268 	int hght = m_pInput->heightHint();
269 	//	int hght2 = m_pTopSplitter->sizeHint().height();
270 	//	m_pTopSplitter->setGeometry(0,0,width(),hght2);
271 	m_pSplitter->setGeometry(0, 0, width(), height() - hght);
272 	m_pInput->setGeometry(0, height() - hght, width(), hght);
273 }
274 
sizeHint() const275 QSize DccCanvasWindow::sizeHint() const
276 {
277 	QSize ret(m_pIrcView->sizeHint().width(),
278 	    m_pIrcView->sizeHint().height() + m_pInput->heightHint());
279 	return ret;
280 }
281 
handleMarshalError(int err)282 void DccCanvasWindow::handleMarshalError(int err)
283 {
284 	QString sss = KviError::getDescription(err);
285 	output(KVI_OUT_DCCERROR, __tr2qs_ctx("DCC failed: %Q", "dcc"), &sss);
286 }
287 
connected()288 void DccCanvasWindow::connected()
289 {
290 	output(KVI_OUT_DCCMSG, __tr2qs_ctx("Connected to %Q:%Q", "dcc"),
291 	    &(m_pMarshal->remoteIp()), &(m_pMarshal->remotePort()));
292 	output(KVI_OUT_DCCMSG, __tr2qs_ctx("Local end is %Q:%Q", "dcc"),
293 	    &(m_pMarshal->localIp()), &(m_pMarshal->localPort()));
294 	if(!(m_pDescriptor->bActive))
295 	{
296 		// PASSIVE CONNECTION...Find out the remote end
297 		m_pDescriptor->szIp = m_pMarshal->remoteIp();
298 		m_pDescriptor->szPort = m_pMarshal->remotePort();
299 		m_pDescriptor->szHost = m_pMarshal->remoteIp();
300 	}
301 	updateCaption();
302 	//	m_pSlaveThread = new KviDccCanvasThread(this,m_pMarshal->releaseSocket());
303 	//	m_pSlaveThread->start();
304 }
305 
306 #endif
307