/*************************************************************************** * * * begin : 5 Dec 2003 * * copyright : (C) 2003 by Samokhvalov Anton :) * * * ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "Chm.h" #include using namespace std; using namespace KIO; //#define MYDEBUG #ifdef MYDEBUG #define myWarning qWarning #else #define myWarning( x, ... ) #endif kio_chmProtocol::kio_chmProtocol(const QCString &pool_socket, const QCString &app_socket) : SlaveBase("kio_chmnew", pool_socket, app_socket), d_file( 0 ), d_last_path( "" ) { } kio_chmProtocol::~kio_chmProtocol() { if ( d_file ) { d_file->close(); delete d_file; d_file = 0; } } void kio_chmProtocol::get(const KURL& url ) { myWarning( "get " + url.path() ); QStringList path = QStringList::split( '/', url.path(-1), false ); reconnectIfNeeded( path ); for ( unsigned int i = 0; i < path.count(); i++ ) { if ( path[i].upper().endsWith( ".CHM" ) ) { QString file = "/"; for ( unsigned int j = i + 1; j < path.count() - 1; j++ ) { file += path[j] + "/"; } file += path[ path.count() - 1 ]; myWarning( "getting file " + file ); if ( file.upper().startsWith( "/MS-ITS" ) ) { file = file.right( file.length() - 7 ); myWarning( "redirecting to file " + file ); int pos = file.find( "::/" ); if ( pos == -1 ) { myWarning( "bad url" ); data( QByteArray() ); finished(); return; } QString new_file = file.left( pos ); QString new_url = file.right( file.length() - pos - 3 ); QString dir = "/"; for ( unsigned int j = 0; j < i; j++ ) { dir += path[j] + "/"; } myWarning( "redirection to chm:" + dir + new_file + "/" + new_url ); redirection( "chm:" + dir + new_file + "/" + new_url ); data( QByteArray() ); finished(); return; } if ( !d_file || !d_file->is_open() ) { data( QByteArray() ); finished(); } std::string file_path( (const char*)file.local8Bit() ); if ( d_file->file_exists( file_path ) ) { std::streamsize size = d_file->file_size( file_path ); char* buf = new char[size]; // buf[size] = 0; d_file->read( file_path, buf, size ); // printf( "%s\n", buf ); QByteArray ba; ba.setRawData( buf, size ); data( ba ); ba.resetRawData( buf, size ); data( QByteArray() ); finished(); delete[] buf; } else { myWarning( "trying get nonexisting file" ); data( QByteArray() ); finished(); } return; } } myWarning( "trying get info from hot chm file" ); data( QByteArray() ); finished(); } void kio_chmProtocol::listDir( const KURL& url ) { myWarning( "list dir " + url.path() ); QStringList path = QStringList::split( '/', url.path(-1), false ); reconnectIfNeeded( path ); if ( !d_file || !d_file->is_open() ) { UDSEntry entry; listEntry( entry, true ); finished(); } for ( unsigned int i = 0; i < path.count(); i++ ) { if ( path[i].upper().endsWith( ".CHM" ) ) { QString dir = "/"; QString file = "/"; for ( unsigned int j = 0; j < i; j++ ) { file += path[j] + "/"; } file += path[i]; for ( unsigned int j = i + 1; j < path.count(); j++ ) { dir += path[j] + "/"; } myWarning( "trying read directory " + dir ); std::list< std::string > files; UDSEntry entry; if ( !d_file->readdir( (const char*)dir.local8Bit(), files ) ) { myWarning( "can not read directory " + dir ); listEntry( entry, true ); finished(); } else { for ( std::list< std::string >::const_iterator it = files.begin(); it != files.end(); ++it ) { myWarning( ("file " + *it).c_str() ); const std::string& st = *it; if ( st[ st.length() - 1 ] == '/' ) { myWarning( "creating dir entry " + file + dir + st.c_str() ); createEntry( st.c_str(), true, entry ); listEntry( entry, false ); } else { myWarning( "creating file entry " + file + dir + st.c_str() ); createEntry( st.c_str(), false, entry ); listEntry( entry, false ); } entry.clear(); } listEntry( entry, true ); finished(); } } } } void kio_chmProtocol::stat( const KURL& url ) { myWarning( "stat" + url.path() ); UDSEntry entry; QStringList path = QStringList::split( '/', url.path(-1), false ); reconnectIfNeeded( path ); if ( !d_file || !d_file->is_open() ) { statEntry( entry ); finished(); } if ( path[ path.count() - 1 ].upper().endsWith( ".CHM" ) ) { createEntry( url.path(), true, entry ); statEntry( entry ); finished(); } else { createEntry( url.path(), false, entry ); statEntry( entry ); finished(); } } void kio_chmProtocol::createEntry( const QString& name, bool isDir, UDSEntry& entry ) { UDSAtom atom; atom.m_uds = KIO::UDS_NAME; atom.m_str = name; entry.append( atom ); atom.m_uds = KIO::UDS_FILE_TYPE; atom.m_long = (isDir)?S_IFDIR:S_IFREG; entry.append( atom ); } void kio_chmProtocol::reconnectIfNeeded( const QStringList& path ) { for ( unsigned int i = 0; i < path.count(); i++ ) { if ( path[i].upper().endsWith( ".CHM" ) ) { QString file = "/"; for ( unsigned int j = 0; j < i; j++ ) { file += path[j] + "/"; } file += path[i]; if ( file == d_last_path ) { myWarning( "no reconnection needed" ); return; } myWarning( "reconnecting to file " + file ); d_last_path = file; if ( d_file ) { d_file->close(); delete d_file; d_file = 0; } d_file = new chm::chmfile( (const char*)(file.local8Bit()) ); if ( !d_file->is_open() ) { myWarning( "can not open chm file" ); //TODO return; } myWarning( "done reconnecting" ); } } } extern "C" { int kdemain(int argc, char **argv) { KInstance instance( "kio_chmnew" ); kdDebug(7101) << "*** Starting kio_chmnew " << endl; if (argc != 4) { kdDebug(7101) << "Usage: kio_chmnew protocol domain-socket1 domain-socket2" << endl; exit(-1); } kio_chmProtocol slave(argv[2], argv[3]); slave.dispatchLoop(); kdDebug(7101) << "*** kio_chmnew Done" << endl; return 0; } }