File indexing completed on 2025-01-05 04:26:52

0001 /***************************************************************************
0002  * copyright        : (C) 2008 Ian Monroe <ian@monroe.nu>
0003  *
0004  * This program is free software; you can redistribute it and/or
0005  * modify it under the terms of the GNU General Public License as
0006  * published by the Free Software Foundation; either version 2 of
0007  * the License or (at your option) version 3 or any later version
0008  * accepted by the membership of KDE e.V. (or its successor approved
0009  * by the membership of KDE e.V.), which shall act as a proxy
0010  * defined in Section 14 of version 3 of the license.
0011  *
0012  * This program is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015  * GNU General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU General Public License
0018  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
0019  **************************************************************************/
0020 
0021 //Importer.load( "HttpServer.js" );
0022 
0023 
0024 Importer.loadQtBinding( "qt.core" );
0025 Importer.loadQtBinding( "qt.network" );
0026 
0027 QByteArray.prototype.toString = function()
0028 {
0029    ts = new QTextStream( this, QIODevice.ReadOnly );
0030    return ts.readAll();
0031 }
0032 
0033 function HttpServer()
0034 {
0035   QTcpServer.call( this, null );
0036   var portNumber = 8080;
0037   do {
0038     var connected = this.listen(new QHostAddress( QHostAddress.Any ), portNumber);
0039     portNumber++;
0040   } while( !connected && ((this.serverError() & QAbstractSocket.AddressInUseError) == 0 ) && portNumber < 9000 )
0041   if( !this.isListening() )
0042   {
0043     Amarok.debug( "Unable to open a port for the web server" );
0044     return;
0045   }
0046   Amarok.debug("Web server started at port " + this.serverPort() );
0047   this.newConnection.connect( this, this.newIncomingConnection );
0048   this.registry = new Object();
0049 }
0050 
0051 HttpServer.prototype = new QTcpServer();
0052 
0053 HttpServer.prototype.newIncomingConnection = function()
0054 {
0055   var socket = this.nextPendingConnection();
0056   var request = new QByteArray();
0057   var thisHttp = this;
0058   socket.readyRead.connect( function() {
0059       request.append( socket.readAll() );
0060       var endOfRequest =  request.indexOf("\r\n\r\n");
0061       if( endOfRequest > 0 )
0062       {
0063       try{
0064        request = thisHttp.parseHeader( request, socket, endOfRequest + 4 );
0065        }
0066        catch( error ) {
0067         Amarok.debug( error)
0068        }
0069       }
0070   });
0071 }
0072 
0073 HttpServer.prototype.parseHeader = function( request, socket, endOfRequest )
0074 {
0075     var header = new QHttpRequestHeader( request.left( endOfRequest ).toString() );
0076     if( header.method() == "GET" )
0077     {
0078         this.sendResponse( socket, header.path() ); 
0079         socket.close();
0080     }
0081     return request.mid( endOfRequest );
0082 }
0083 
0084 HttpServer.prototype.sendResponse = function( socket, path )
0085 {
0086    var userResponse = null;
0087    for( var registeredPath in this.registry )
0088    {
0089        Amarok.debug( path.indexOf( registeredPath ) + " for " + registeredPath + " in " + path );
0090        if( path.indexOf( registeredPath ) == 0 )
0091        {
0092            userResponse = this.registry[registeredPath]( path.substring( registeredPath.length )  );
0093            break;
0094        }
0095    }
0096 
0097    Amarok.debug( "respondTo says::" + userResponse + "::");
0098    if( userResponse == null )
0099    {
0100         //var response404 = new QHttpResponseHeader( 404, "Not found", 1, 1 );
0101 //        responseHeader.setStatusLine( 404 );
0102         //responseHeader.setContentType( "text/html" )
0103         content = "HTTP/1.1 404 Not found\n"
0104         content += "Content-Type: text/html\n";
0105         content += "Server: AmarokServer\n\r\n";
0106         content += "<html><head><title>File not found</title></head>\n";
0107         content += "<h1>404 Error</h1>\n"
0108         content += path + " not found.\n\r\n";
0109         //responseHeader.setContentLength( content.length() );
0110         var writeMe = new QByteArray();
0111         //writeMe.append( response404.toString() )
0112         writeMe.append( content )
0113         socket.write( writeMe );
0114         Amarok.debug("response:\n" + writeMe.toString() + " sent.");
0115    }
0116    else
0117    {
0118    try{
0119         content = "HTTP/1.1 200\n"
0120         content += "Content-Type: " + userResponse.mimeType + "\n";
0121         content += "Server: AmarokServer\n\r\n";
0122         var writeMe = new QByteArray();
0123         writeMe.append( content );
0124         writeMe.append( userResponse.content );
0125         socket.write( writeMe );
0126         Amarok.debug("response:\n" + writeMe.toString() + " sent.");
0127     }
0128     catch( e )
0129     {
0130         Amarok.debug( e )
0131     }
0132    }
0133 }
0134 
0135 HttpServer.prototype.register = function( path, responseFn )
0136 {
0137     this.registry[path] = responseFn;
0138     if( path.charAt(0) === "/" )
0139     {
0140         path = path.slice(1);
0141     }
0142 }
0143 
0144 
0145 function fileResponse( path )
0146 {
0147     Amarok.debug( "requesting " + path );
0148     var prefix = "/home/ian/.kde4/share/apps/amarok/scripts/script_console2/webrok/";
0149     if( path === "/" || path === "" )
0150     {
0151         path = "index.js.html";
0152     }
0153     //we need to make sure it doesn't ../ out of the root
0154     url = new QUrl( path );
0155     var fi = new QFileInfo( prefix + url.path() );
0156     if( fi.absoluteFilePath().indexOf( prefix ) == 0 )
0157     {
0158         Amarok.debug( "sending " + fi.absoluteFilePath() );
0159         var file = new QFile( fi.absoluteFilePath() );
0160         if( file.open( QIODevice.ReadOnly ) )
0161         {
0162             var ret = new Object();
0163             if( fi.completeSuffix() == "xml" )
0164             {
0165                 ret.mimeType = "application/xml";
0166             }
0167             else
0168             {
0169                 ret.mimeType = "text/html";
0170             }
0171             ret.content = file.readAll()
0172             return ret;
0173         }
0174         else
0175         {
0176             Amarok.debug("file not found")
0177             return null;
0178         }
0179     }
0180     else
0181     {
0182         Amarok.debug( fi.absoluteFilePath() + " fails security check." );
0183         return null; //send 404 error
0184     }
0185 }
0186 
0187 function testResponse()
0188 {
0189     return "<h3>test</h3>";
0190 }
0191 
0192 function ajaxResponse( pathStr )
0193 {
0194     url = new QUrl( pathStr );
0195     command = url.path();
0196     Amarok.debug( "the command is " + command );
0197     switch( command ) 
0198     {
0199         case "/play":
0200             row = Number( url.queryItemValue( "row" ) );
0201             Amarok.Playlist.playByIndex( row );
0202             Amarok.debug("playing file");
0203             var ret = new Object();
0204             ret.mimeType = "text/plain";
0205             ret.content =  "Playing row " + row;
0206             return ret;
0207         break;
0208         case "/savePlaylist":
0209             Amarok.Playlist.savePlaylist("/home/ian/.kde4/share/apps/amarok/scripts/script_console2/webrok/current.xspf");
0210             var ret = new Object();
0211             ret.mimeType = "text/plain";
0212             ret.content =  "saving playlist"
0213             return ret;        
0214        breakZZz;
0215     }
0216     return null; //404
0217 }
0218 
0219 http = new HttpServer();
0220 http.register( "/ajax", ajaxResponse );
0221 http.register( "/test", testResponse );
0222 http.register( "/", fileResponse );