4 * Copyright (C) 2001 Barnaby Gray <barnaby@beedesign.co.uk>
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "FileTransferClient.h"
25 #include "constants.h"
27 #include "sstream_fix.h"
32 #include <sys/types.h>
40 using std::ostringstream
;
49 * Constructor when receiving an incoming connection
51 FileTransferClient::FileTransferClient(ContactRef self
, MessageHandler
*mh
,
52 ContactTree
*cl
, unsigned int ext_ip
, FileTransferEvent
* ev
)
53 : m_state(WAITING_FOR_INIT
), m_recv(),
54 m_self_contact(self
), m_contact(NULL
), m_contact_list(cl
),
55 m_message_handler(mh
), m_incoming(true), m_local_ext_ip(ext_ip
),
59 m_listenserver
.StartServer();
63 * Constructor for making an outgoing connection
65 FileTransferClient::FileTransferClient(ContactRef self
, ContactRef c
, MessageHandler
*mh
, unsigned int ext_ip
, FileTransferEvent
* ev
)
66 : m_state(NOT_CONNECTED
), m_recv(), m_self_contact(self
),
67 m_contact(c
), m_message_handler(mh
), m_incoming(false), m_local_ext_ip(ext_ip
),
72 m_socket
= new TCPSocket();
73 m_remote_uin
= c
->getUIN();
76 FileTransferClient::~FileTransferClient()
78 if (m_listenserver
.isStarted())
80 SignalRemoveSocket( m_listenserver
.getSocketHandle() );
81 m_listenserver
.Disconnect();
84 if ( m_socket
->getSocketHandle() > -1)
85 SignalRemoveSocket( m_socket
->getSocketHandle() );
89 if (m_fout
.is_open()) m_fout
.close();
90 if (m_fin
.is_open()) m_fin
.close();
93 void FileTransferClient::Init()
100 m_timestamp
= time(NULL
);
101 m_timeout
= 60; // will time out in 60 seconds
104 void FileTransferClient::Connect()
106 m_remote_tcp_version
= m_contact
->getTCPVersion();
107 if (m_remote_tcp_version
>= 7) m_eff_tcp_version
= 7;
108 else if (m_remote_tcp_version
== 6) m_eff_tcp_version
= 6;
109 else throw DisconnectedException("Cannot direct connect to client with too old TCP version");
111 m_socket
->setRemoteIP( m_contact
->getLanIP() );
112 m_socket
->setRemotePort( m_ev
->getPort() );
113 m_socket
->setBlocking(false);
115 SignalAddSocket( m_socket
->getSocketHandle(), SocketEvent::WRITE
);
117 if (m_contact
->getDCCookie() != 0)
118 m_session_id
= m_contact
->getDCCookie();
120 m_session_id
= (unsigned int)(0xffffffff*(rand()/(RAND_MAX
+1.0)));
122 m_state
= WAITING_FOR_INIT_ACK
;
125 void FileTransferClient::FinishNonBlockingConnect()
130 void FileTransferClient::clearoutMessagesPoll()
132 if ((m_state
!= CONNECTED
) &&
133 (time(NULL
) > (m_timestamp
+ m_timeout
)))
137 void FileTransferClient::SendFile() {
138 if (m_state
== CONNECTED
&& m_msgqueue
)
149 else if (m_ev
->getCurrFile() < m_ev
->getTotalFiles())
157 m_ev
->setState(FileTransferEvent::COMPLETE
);
158 SignalLog(LogEvent::INFO
, "FileTransfer is Complete");
159 throw DisconnectedException("FileTransfer is Complete");
164 m_message_handler
->handleUpdateFT(m_ev
);
167 void FileTransferClient::expired()
169 m_ev
->setFinished(false);
170 m_ev
->setDelivered(false);
171 m_ev
->setDirect(true);
172 m_ev
->setState(FileTransferEvent::TIMEOUT
);
173 messageack
.emit(m_ev
);
176 void FileTransferClient::Recv()
180 while ( m_socket
->connected() )
182 if ( !m_socket
->Recv(m_recv
) ) break;
186 catch(SocketException e
)
189 ostr
<< "Failed on recv: " << e
.what();
190 throw DisconnectedException( ostr
.str() );
192 catch(ParseException e
)
195 ostr
<< "Failed parsing: " << e
.what();
196 throw DisconnectedException( ostr
.str() );
200 void FileTransferClient::Parse()
202 if (m_recv
.empty()) return;
204 unsigned short length
;
206 while (!m_recv
.empty())
210 m_recv
.setLittleEndian();
212 if (length
> Incoming_Packet_Limit
) throw ParseException("Received too long incoming packet");
213 if (length
== 0) return;
214 if (m_recv
.remains() < length
) return; // waiting for more of the packet
216 // Optimize??? not create new buffer and copy and erase in old.
218 m_recv
.chopOffBuffer( sb
, length
+2 );
220 if (m_state
!= CONNECTED
)
223 ostr
<< "Received filepacket from " << IPtoString( m_socket
->getRemoteIP() ) << ":" << m_socket
->getRemotePort() << endl
<< sb
;
224 SignalLog(LogEvent::DIRECTPACKET
, ostr
.str());
227 if (m_state
== WAITING_FOR_INIT
)
234 m_state
= WAITING_FOR_INIT_ACK
;
239 connected
.emit(this);
243 else if (m_state
== WAITING_FOR_INIT_ACK
)
250 m_state
= CONNECTED
; // v5 is done handshaking now
252 connected
.emit(this);
257 // Outgoing - next packet should be their INIT
258 m_state
= WAITING_FOR_INIT
;
262 else if (m_state
== WAITING_FOR_INIT2
)
265 // This is a V7 only packet
275 connected
.emit(this);
278 else if (m_state
== CONNECTED
)
286 ostr
<< "Buffer pointer not at end after parsing packet was: 0x" << std::hex
<< sb
.pos()
287 << " should be: 0x" << sb
.size();
288 SignalLog(LogEvent::WARN
, ostr
.str());
295 void FileTransferClient::ConfirmUIN()
297 if ( m_contact_list
->exists(m_remote_uin
) )
299 ContactRef c
= (*m_contact_list
)[ m_remote_uin
];
300 if ( (c
->getExtIP() == m_local_ext_ip
&& c
->getLanIP() == getIP() )
301 /* They are behind the same masquerading box,
302 * and the Lan IP matches
304 || c
->getExtIP() == getIP())
310 // spoofing attempt most likely
312 ostr
<< "Refusing direct connection from someone that claims to be UIN "
313 << m_remote_uin
<< " since their IP " << IPtoString( getIP() ) << " != " << IPtoString( c
->getExtIP() );
314 throw DisconnectedException( ostr
.str() );
320 // don't accept direct connections from contacts not on contact list
321 throw DisconnectedException("Refusing direct connection to contact not on contact list");
325 void FileTransferClient::SendInitPacket()
329 Buffer::marker m1
= b
.getAutoSizeShortMarker();
331 b
<< (unsigned char)0xff; // start byte
332 b
<< (unsigned short)0x0007; // tcp version
333 Buffer::marker m2
= b
.getAutoSizeShortMarker();
336 b
<< (unsigned short)0x0000;
337 b
<< (unsigned int)m_local_server_port
;
339 b
<< m_self_contact
->getUIN();
342 b
<< m_socket
->getLocalIP();
343 b
<< (unsigned char)0x04; // mode
345 b
<< (unsigned int)m_local_server_port
;
348 b
<< (unsigned int)0x00000050; // unknown
349 b
<< (unsigned int)0x00000003; // unknown
350 if (m_eff_tcp_version
== 7)
351 b
<< (unsigned int)0x00000000; // unknown
353 b
.setAutoSizeMarker(m1
);
354 b
.setAutoSizeMarker(m2
);
359 void FileTransferClient::ParseInitPacket(Buffer
&b
)
362 unsigned short length
;
365 unsigned char start_byte
;
367 if (start_byte
!= 0xff) throw ParseException("Init Packet didn't start with 0xff");
369 unsigned short tcp_version
;
371 b
.advance(2); // revision or a length ??
375 m_remote_tcp_version
= tcp_version
;
376 if (tcp_version
<= 5) throw ParseException("Too old client < ICQ99");
377 if (tcp_version
== 6) m_eff_tcp_version
= 6;
378 else m_eff_tcp_version
= 7;
382 if (tcp_version
!= m_remote_tcp_version
)
383 throw ParseException("Client claiming different TCP versions");
386 unsigned int our_uin
;
388 if (our_uin
!= m_self_contact
->getUIN())
389 throw ParseException("Local UIN in Init Packet not same as our Local UIN");
392 // xx xx senders open port
396 unsigned int remote_uin
;
400 m_remote_uin
= remote_uin
;
404 if (m_remote_uin
!= remote_uin
)
405 throw ParseException("Remote UIN in Init Packet for Remote Client not what was expected");
408 // xx xx xx xx senders external IP
409 // xx xx xx xx senders lan IP
414 // xx xx senders port again
418 // xx xx xx xx session id
419 unsigned int session_id
;
423 m_session_id
= session_id
;
427 if (m_session_id
!= session_id
) throw ParseException("Session ID from Remote Client doesn't match the one we sent");
430 // 50 00 00 00 unknown
431 // 03 00 00 00 unknown
434 if (m_eff_tcp_version
== 7)
436 b
.advance(4); // 00 00 00 00 unknown
441 void FileTransferClient::ParseInitAck(Buffer
&b
)
444 unsigned short length
;
446 if (length
!= 4) throw ParseException("Init Ack not as expected");
449 b
>> a
; // should be 0x00000001 really
452 void FileTransferClient::ParseInit2(Buffer
&b
)
455 unsigned short length
;
457 if (length
!= 0x0021)
458 throw ParseException("V7 final handshake packet incorrect length");
463 throw ParseException("Expecting V7 final handshake packet, received something else");
465 unsigned int unknown
;
466 b
>> unknown
// 0x0000000a
467 >> unknown
;// 0x00000001 on genuine connections, otherwise some weird connections which we drop
468 if (unknown
!= 0x00000001) throw DisconnectedException("Ignoring weird direct connection");
469 b
.advance(24); // unknowns
472 void FileTransferClient::SendInit2()
476 Buffer::marker m1
= b
.getAutoSizeShortMarker();
477 b
<< (unsigned char) 0x03 // start byte
478 << (unsigned int) 0x0000000a // unknown
479 << (unsigned int) 0x00000001 // unknown
480 << (unsigned int) (m_incoming
? 0x00000001 : 0x00000000) // unknown
481 << (unsigned int) 0x00000000 // unknown
482 << (unsigned int) 0x00000000; // unknown
485 b
<< (unsigned int) 0x00040001 // unknown
486 << (unsigned int) 0x00000000 // unknown
487 << (unsigned int) 0x00000000; // unknown
491 b
<< (unsigned int) 0x00000000 // unknown
492 << (unsigned int) 0x00000000 // unknown
493 << (unsigned int) 0x00040001; // unknown
495 b
.setAutoSizeMarker(m1
);
499 void FileTransferClient::ParsePacket(Buffer
& b
)
502 unsigned short length
;
511 case 0: ParsePacket0x00(b
);
515 case 1: ParsePacket0x01(b
);
518 case 2: ParsePacket0x02(b
);
519 SendPacket0x03(0,m_ev
->getCurrFile());
521 case 3: ParsePacket0x03(b
);
525 case 5: ParsePacket0x05(b
);
527 case 6: ParsePacket0x06(b
);
530 SignalLog(LogEvent::WARN
, "Received unknown FileTransfer Packet");
534 void FileTransferClient::ParsePacket0x00(Buffer
& b
)
536 unsigned int x1
, t_num_files
, t_size
, speed
;
543 b
.UnpackUint16StringNull(nick
);
545 m_ev
->setTotalSize(t_size
);
546 m_ev
->setTotalFiles(t_num_files
);
547 m_ev
->setCurrFile(0);
548 m_ev
->setSpeed(speed
);
550 m_path
= m_ev
->getSavePath();
553 void FileTransferClient::ParsePacket0x01(Buffer
& b
)
559 b
.UnpackUint16StringNull(nick
);
561 m_ev
->setSpeed(speed
);
564 void FileTransferClient::ParsePacket0x02(Buffer
& b
)
566 unsigned int size
, speed
;
567 string filename
, subdir
;
568 unsigned char file_or_dir
, tmp1
;
571 b
.UnpackUint16StringNull(filename
);
572 b
.UnpackUint16StringNull(subdir
);
583 m_ev
->setCurrFile(m_ev
->getCurrFile()+1);
584 m_ev
->setSpeed(speed
);
586 m_path
= m_ev
->getSavePath();
587 // Add backslash if missing in path
588 if (m_path
.find_last_of('/') != (m_path
.length()-1))
594 while ((pos
= subdir
.find('\\')) != std::string::npos
)
600 // Add backslash if missing in path again
601 if (m_path
.find_last_of('/') != (m_path
.length()-1))
606 if (file_or_dir
== 1)
610 mkdir(m_path
.c_str(), S_IXUSR
|
620 if (m_ev
->getCurrFile() > 1)
622 if (m_fout
.is_open())
628 m_fout
.open(std::string(m_path
+filename
).c_str(), std::ios::out
| std::ios::binary
);
633 << m_path
<< filename
635 m_ev
->setState(FileTransferEvent::ERROR
);
636 m_ev
->setError(ostr
.str());
637 throw DisconnectedException("I/O error");
641 // Notify the Gui that an new file is on it's way..
642 m_message_handler
->handleUpdateFT(m_ev
);
645 void FileTransferClient::ParsePacket0x03(Buffer
& b
)
647 unsigned int npos
, nfiles
, x1
, x2
;
656 m_ev
->setTotalPos(m_ev
->getTotalPos()+npos
);
657 m_ev
->setCurrFile(nfiles
);
659 if (npos
> m_ev
->getSize())
662 ostr
<< "FileTransfer resume request got wrong offset: "
663 << npos
<< " when file only is " << m_ev
->getSize();
664 m_ev
->setState(FileTransferEvent::ERROR
);
665 m_ev
->setError(ostr
.str());
666 throw DisconnectedException("I/O error");
672 ostr
<< "Resuming filetransfer " << npos
<< "/" << m_ev
->getSize();
673 SignalLog(LogEvent::INFO
, ostr
.str());
683 void FileTransferClient::ParsePacket0x05(Buffer
& b
)
688 m_ev
->setSpeed(speed
);
691 void FileTransferClient::ParsePacket0x06(Buffer
& b
)
693 unsigned short length
;
694 length
= b
.remains();
696 m_ev
->setPos(m_ev
->getPos()+length
);
697 m_ev
->setTotalPos(m_ev
->getTotalPos()+length
);
701 b
.Unpack( m_const_buf
, min(length
, (unsigned short)MAX_FileChunk
) );
702 m_fout
.write((const char*)m_const_buf
, std::min(length
, (unsigned short)MAX_FileChunk
) );
703 length
= max(0, length
-(unsigned short)MAX_FileChunk
);
705 m_fout
.flush(); //prob. isn't needed.. but I feel safer ;)
707 if (m_ev
->getTotalPos() >= m_ev
->getTotalSize())
709 m_ev
->setState(FileTransferEvent::COMPLETE
);
710 throw DisconnectedException("FileTransfer is Complete");
714 void FileTransferClient::SendPacket0x00()
717 unsigned int tmp_speed
= m_ev
->getSpeed();
718 unsigned int tmp_tot_nr
= m_ev
->getTotalFiles();
719 unsigned int tmp_tot_size
= m_ev
->getTotalSize();
722 Buffer::marker m1
= b
.getAutoSizeShortMarker();
723 b
<< (unsigned char)0x00;
724 b
<< (unsigned int)0x00000000; //0x00000000 X1
725 b
<< tmp_tot_nr
; //total number of files to send CHANGE!!!!
726 b
<< tmp_tot_size
; //total number of bytes to send CHANGE!!!!
728 b
.PackUint16StringNull(m_self_contact
->getAlias());
729 b
.setAutoSizeMarker(m1
);
734 void FileTransferClient::SendPacket0x01()
737 unsigned int tmp_speed
= m_ev
->getSpeed();
740 Buffer::marker m1
= b
.getAutoSizeShortMarker();
741 b
<< (unsigned char)0x01;
742 b
<< tmp_speed
; //Speed CHANGE!!!!
743 b
.PackUint16StringNull(m_self_contact
->getAlias());
744 b
.setAutoSizeMarker(m1
);
749 void FileTransferClient::SendPacket0x02()
752 string tmp_name
= m_ev
->getFile();
753 unsigned int tmp_size
;
754 unsigned int tmp_speed
= m_ev
->getSpeed();
755 struct stat tmp_stat
;
756 unsigned char file_or_dir
;
758 stat(tmp_name
.c_str(), &tmp_stat
);
759 if (S_ISDIR(tmp_stat
.st_mode
))
766 if (m_base_dir
== NULL
)
768 m_base_dir
= new std::string(tmp_name
.substr(0, tmp_name
.find_last_of('/', tmp_name
.find_last_not_of('/'))+1));
772 else if (S_ISREG(tmp_stat
.st_mode
))
775 tmp_size
= tmp_stat
.st_size
;
778 if (m_base_dir
== NULL
)
780 m_base_dir
= new std::string("");
791 m_fin
.open(tmp_name
.c_str(), std::ios::in
| std::ios::binary
);
799 m_ev
->setState(FileTransferEvent::ERROR
);
800 m_ev
->setError(ostr
.str());
801 throw DisconnectedException("I/O error");
808 ostr
<< "Trying to send unknown file type: "<< tmp_name
;
809 SignalLog(LogEvent::WARN
, ostr
.str());
813 std::string subdir
= "";
815 if (m_base_dir
->length() != 0)
817 tmp_name
.substr(m_base_dir
->length(),
818 tmp_name
.find_last_of('/', tmp_name
.find_last_not_of('/')));
821 while ((pos
= subdir
.find('/')) != std::string::npos
)
824 // Chopping of so just name is sent.
825 pos
= tmp_name
.find_last_of('/');
826 if (pos
== tmp_name
.length()-1)
828 tmp_name
= tmp_name
.substr(0,pos
);
829 pos
= tmp_name
.find_last_of('/');
831 tmp_name
= tmp_name
.substr(pos
+1, tmp_name
.length()-pos
);
833 // Chopping of filename
834 if (m_base_dir
->length() != 0)
835 subdir
= subdir
.substr(0, subdir
.length() - tmp_name
.length() -1);
838 // Remove last backslash from subdir
839 if ((file_or_dir
== 1) &&
840 (subdir
.find_last_of('\\') == (subdir
.length()-1)))
841 subdir
= subdir
.substr(0, subdir
.length() -1);
843 m_ev
->setCurrFile(m_ev
->getCurrFile()+1);
845 m_ev
->setSize(tmp_size
);
849 Buffer::marker m1
= b
.getAutoSizeShortMarker();
850 b
<< (unsigned char)0x02;
852 b
.PackUint16StringNull(tmp_name
); //name of next file.
853 b
.PackUint16StringNull(subdir
); //subdir
855 b
<< (unsigned char)0x00;
856 b
<< (unsigned char)0x00;
857 b
<< (unsigned char)0x00;
858 b
<< (unsigned char)0x00;
860 b
.setAutoSizeMarker(m1
);
865 void FileTransferClient::SendPacket0x03(unsigned int npos
, unsigned int nfiles
)
868 unsigned int speed
= m_ev
->getSpeed();
870 Buffer::marker m1
= b
.getAutoSizeShortMarker();
871 b
<< (unsigned char)0x03;
872 b
<< npos
; //filepos RESUME?
873 b
<< (unsigned int)0x00000000; // X1 Unknown
874 b
<< speed
; //(unsigned int)0x00000064; // speed
877 b
.setAutoSizeMarker(m1
);
882 void FileTransferClient::SendPacket0x05()
887 Buffer::marker m1
= b
.getAutoSizeShortMarker();
889 speed
= m_ev
->getSpeed();
891 b
<< (unsigned char)0x05;
894 b
.setAutoSizeMarker(m1
);
899 void FileTransferClient::SendPacket0x06()
902 unsigned short length
;
904 Buffer::marker m1
= b
.getAutoSizeShortMarker();
908 m_ev
->setState(FileTransferEvent::ERROR
);
909 m_ev
->setError("I/O error while sending data");
910 throw DisconnectedException("I/O error in SendPacket0x06");
913 m_fin
.read((char*)m_const_buf
, 2048);
914 length
= m_fin
.gcount();
916 b
<< (unsigned char)0x06;
918 b
.Pack(m_const_buf
, length
);
919 b
.setAutoSizeMarker(m1
);
921 m_ev
->setPos(m_ev
->getPos()+length
);
922 m_ev
->setTotalPos(m_ev
->getTotalPos()+length
);
927 if (m_ev
->getPos() < m_ev
->getSize())
934 if (m_ev
->getFilesInQueue() == 0)
936 m_ev
->setState(FileTransferEvent::COMPLETE
);
937 SignalLog(LogEvent::INFO
, "FileTransfer is Complete");
938 throw DisconnectedException("FileTransfer is Complete");
943 void FileTransferClient::SendInitAck()
947 Buffer::marker m1
= b
.getAutoSizeShortMarker();
948 b
<< (unsigned int)0x00000001;
949 b
.setAutoSizeMarker(m1
);
953 void FileTransferClient::SendPacketAck(ICQSubType
*icqsubtype
)
958 b
<< (unsigned int)0x00000000 // checksum (filled in by Encrypt)
960 << (unsigned short)0x000e
961 << icqsubtype
->getSeqNum()
962 << (unsigned int)0x00000000
963 << (unsigned int)0x00000000
964 << (unsigned int)0x00000000;
966 icqsubtype
->Output(b
);
972 void FileTransferClient::Send(Buffer
&b
)
978 catch(SocketException e
)
981 ostr
<< "Failed to send: " << e
.what();
982 throw DisconnectedException( ostr
.str() );
986 void FileTransferClient::SendEvent(MessageEvent
*ev
)
988 if (m_state
== CONNECTED
)
990 // send straight away
1000 void FileTransferClient::flush_queue()
1008 unsigned int FileTransferClient::getUIN() const { return m_remote_uin
; }
1010 unsigned int FileTransferClient::getIP() const { return m_socket
->getRemoteIP(); }
1012 unsigned short FileTransferClient::getPort() const { return m_socket
->getRemotePort(); }
1014 unsigned short FileTransferClient::getlistenPort() const { return m_listenserver
.getPort(); }
1016 int FileTransferClient::getfd() const { return m_socket
->getSocketHandle(); }
1018 int FileTransferClient::getlistenfd() { return m_listenserver
.getSocketHandle(); }
1020 TCPSocket
* FileTransferClient::getSocket() const { return m_socket
; }
1022 void FileTransferClient::setSocket()
1024 m_socket
= m_listenserver
.Accept();
1025 SignalLog(LogEvent::INFO
, "Accepting incoming filetransfer");
1028 void FileTransferClient::setContact(ContactRef c
) { m_contact
= c
; }
1030 ContactRef
FileTransferClient::getContact() const { return m_contact
; }
1032 bool FileTransferClient::SetupFileTransfer(FileTransferEvent
*ev
)
1034 struct stat tmp_stat
;
1035 std::string str
= ev
->getDescription();
1036 stat(str
.c_str(), &tmp_stat
);
1037 /* MITZ - what's the idea?!
1038 if (S_ISDIR(tmp_stat.st_mode))
1043 listDirectory(str, size, files, dirs, ev);
1045 ev->setTotalSize(size);
1047 ostr << files << " files in " << dirs << " directories";
1048 ev->setDescription(ostr.str());
1051 else if (S_ISREG(tmp_stat.st_mode))
1054 ev->setTotalSize(tmp_stat.st_size);
1055 // Chopping of so just name is sent.
1056 int pos = str.find_last_of('/');
1057 if (pos == str.length()-1)
1059 str = str.substr(0,pos);
1060 pos = str.find_last_of('/');
1062 str = str.substr(pos+1, str.length()-pos);
1063 ev->setDescription(str);
1071 ev
->setTotalFiles(ev
->getFilesInQueue());
1077 void FileTransferClient::listDirectory(std::string str
, int &size
, int &files
, int &dirs
, FileTransferEvent
*ev
)
1079 struct stat tmp_stat
;
1080 if (str
.length() > 1
1081 && (str
.substr(str
.length()-1, str
.length()) == "."
1082 || str
.substr(str
.length()-2, str
.length()) == ".."))
1085 // Add backslash if missing in path
1086 if (str
.find_last_of('/') != (str
.length()-1))
1090 DIR *dir
= opendir(str
.c_str());
1093 struct dirent
*dent
= readdir(dir
);
1095 std::string tmp_str
;
1097 while (dent
!= NULL
)
1100 tmp_str
+= dent
->d_name
;
1101 stat(tmp_str
.c_str(), &tmp_stat
);
1102 if (S_ISREG(tmp_stat
.st_mode
))
1104 ev
->addFile(tmp_str
);
1105 size
+= tmp_stat
.st_size
;
1108 else if (S_ISDIR(tmp_stat
.st_mode
))
1110 listDirectory(tmp_str
, size
, files
, dirs
, ev
);
1113 dent
= readdir(dir
); //delete on old dent?
1118 FileTransferEvent
* FileTransferClient::getEvent()