bug-uploaded files base64 decodieren

Deutschsprachiges Forum für Diskussionen und Fragen zu MantisBT

Moderators: Developer, Contributor

Post Reply
mikes222

bug-uploaded files base64 decodieren

Post by mikes222 »

Ich versuche gerade, in Mantis SUPA (http://sourceforge.net/projects/supa/) zu integrieren. Mit SUPA kann man Screenshots aus der Zwischenablage direkt nach Mantis hochladen. Also nur noch Alt-Druck, Button "paste image from clipboard" und "upload" drücken.

Wegen eines "Bugs" kann dieses Modul allerdings die Datei nur base64-codiert hochsenden zum Server.

Der Post-Request sieht so aus:

Code: Select all

...
--AaB03x764031 
Content-Disposition: form-data; name="file"; filename="screenshot15.png" 
Content-Type: image/png 
Content-Transfer-Encoding: base64 

iVBORw0KGgoAAAANSUhEUgAAA2gAAAP0CAIAAABQ0IhSAACAAElEQVR42uydB1wUx9//+T/P80ti
...
Das empfangende Modul für den Upload ist bug_file_add.php

Wo im Sourcecode von Mantis kann ich die Datei am besten wieder decodieren?
und wie erkenne ich, ob die Datei normal oder base64-kodiert gesendet wurde?
... oder anders gefragt, wie kann ich auf das Content-Transfer-Encoding vom file-Abschnitt zugreifen?

Bin für jede Hilfe dankbar und stelle gerne den Sourcecode hier zur Verfügung, wenns denn mal funktioniert.
mikes222

Re: bug-uploaded files base64 decodieren

Post by mikes222 »

Nun ja, mit einem Hack habe ich es geschafft. Beim Uploaden des images stelle ich den Content-Type auf "image/base64png" und ändere ihn auf der Serverseite wieder.

in core/file_api.php in der methode file_add()

Code: Select all

        $t_file_size = filesize( $t_tmp_file );
        if( 0 == $t_file_size ) {
                trigger_error( ERROR_FILE_NO_UPLOAD_FAILURE, ERROR );
        }

// Start base64 decoding
if ($c_file_type == 'image/base64png') {
  $c_file_type = 'image/png';
  $handle = fopen( $t_tmp_file, 'rb' );
  $contents = fread( $handle, $t_file_size );
  fclose($handle);

  $contents = base64_decode($contents);

  $handle = fopen( $t_tmp_file, 'w' );
  fwrite($handle, $contents);
  fclose($handle);
  $t_file_size = strlen( $contents );
}
// End base64 decoding
Weiters muß noch bug_file_upload_inc.php geändert werden. Hier wird der Clientseitige Teil reinprogrammiert:

Code: Select all

<form method="post" enctype="multipart/form-data" name="myform" action="bug_file_add.php">
<?php echo form_security_field( 'bug_file_add' ) ?>

<table class="width100" cellspacing="1">
<tr>
        <td class="form-title" colspan="2">
<?php
                collapse_icon( 'upload_form' );
                echo lang_get( 'upload_file' ) ?>
        </td>
</tr>
<tr class="row-1">
        <td class="category" width="15%">
                <?php echo lang_get( 'select_file' ) ?><br />
                <?php echo '<span class="small">(' . lang_get( 'max_file_size' ) . ': ' . number_format( $t_max_file_size/1000 ) . 'k)</span>'?>
        </td>
        <td width="35%">
                <input type="hidden" name="bug_id" value="<?php echo $f_bug_id ?>" />
                <input type="hidden" name="max_file_size" value="<?php echo $t_max_file_size ?>" />
                <input name="file" id="upload" type="file" size="40" />
                <input type="submit" class="button" value="<?php echo lang_get( 'upload_file_button' ) ?>" />
        </td>
    <td width="50%">

        </div>
            <input type="button" onclick="return pasteScreenshot();" value="Einf&uuml;gen"/>
            <input type="button" onclick="return uploadScreenshot();" value="Upload"/>
            <input type="button" onclick="document.getElementById( 'SupaApplet' ).clear(); return false;" value="L&ouml;schen"/>
            <div>
                Dateiname:
                <input value="screenshot1" name="otherparam" id="param"/>
            </div>
            <div style="border: 1px solid">
                <applet id="SupaApplet" width="200" height="200" code="de.christophlinder.supa.SupaApplet" archive="Supa.jar"/>
            </div>

        <script type="text/javascript">
                        <!--
                        function pasteScreenshot()
                        {
                                // Call the paste() method of the applet.
                                // This will paste the image from the clipboard into the applet :)
                                try
                                {
                                        var applet = document.getElementById( "SupaApplet" );
                                        if( !applet.pasteFromClipboard )
                                        {
                                                throw "SupaApplet is not loaded (yet)";
                                        }
                                        var err = applet.pasteFromClipboard();
                                        switch( err )
                                        {
                                                case 0:
                                                /* no error */
                                                break;
                                                case 1:
                                                alert( "Unknown Error" );
                                                break;
                                                case 2:
                                                alert( "Empty clipboard" );
                                                break;
                                                case 3:
                                                alert( "Clipboard content not supported. Only image data is supported." );
                                                break;
                                                case 4:
                                                alert( "Clipboard in use by another application. Please try again in a few seconds." );
                                                break;
                                                default:
                                                alert( "Unknown error code: "+err );
                                        }
                                }
                                        catch( e )
                                        {
                                                alert(e);
                                                throw e;
                                        }
                                        return false;
                        }
                        function uploadScreenshot()
                        {
                                // Get the base64 encoded data from the applet and POST it via an AJAX
                                // request. See the included Supa.js for details
                                var s = new supa();
                                var applet = document.getElementById( "SupaApplet" );
                                try
                                {
                                        var result = s.ajax_post(
                                        applet, // applet reference
                                        "bug_file_add.php", // call this url
                                        "file", // this is the name of the POSTed file-element
                                        document.getElementById('param').value, // this is the filename of the POSTed file excluding extension
                                        {
                                                form: document.forms["myform"]
                                        } // elements of this form will get POSTed, too
                                        );

                                        if( result.match( "Operation successful" ) )
                                        {
                                                document.close();
                                                document.open();
                                                document.write(result);
                                                document.close();
                                                //window.open( result );
                                        }
                                        else
                                        {
                                                alert( result );
                                        }
                                }
                                catch( ex )
                                {
                                        if( ex == "no_data_found" )
                                        {
                                                alert( "Please paste an image first" );
                                        }
                                        else
                                        {
                                                alert( ex );
                                        }
                                }
                                return false; // prevent changing the page
                        }
                //-->
        </script>
    </td>
</tr>
</table>
</form>
Zuletzt noch die Supa.js, damit der Screenshot so hochgeladen wird, daß auch Mantis glücklich ist:

Code: Select all

function supa() {
this.ajax_post = function( supaApplet,
actionUrl,
fieldname_filename,
filename,
otherParams )
{
// sanity checks
if( !fieldname_filename || fieldname_filename == "" ) {
throw "Developer Error: fieldname_filename not set or empty";
}
if( !filename || filename == "" ) {
throw "Filename required";
}
if( !supaApplet.getEncodedString ) {
throw "SupaApplet is not loaded (yet)";
}
// get bytes from the applet
supaApplet.setImageCodec('png');
//supaApplet.setEncoding('null');
supaApplet.setEncoding('base64');
var bytes = supaApplet.getEncodedString();
//var bytes = supaApplet.getBytes();
if( !bytes || bytes.length == 0 ) {
// we're optimistic: any exception means: there's no data :)
throw "no_data_found";
}
//alert( "bytes: "+bytes.length );
// some constants for the request body
//FIXME: make sure boundaryString is not part of bytes or the form values
var boundaryString = 'AaB03x'+ parseInt(Math.random()*9999999,10);
var boundary = '--'+boundaryString;
var cr= '\r\n';
filename=filename + ".png";
// build request body
var body = '';
body += boundary + cr;
// add "normal" form values
if( otherParams && otherParams.form ) {
        for( var i = 0; i < otherParams.form.elements.length; ++i ) {
                var elem = otherParams.form.elements[i];
                if( elem.name && elem.name != 'file') {
                        //alert( elem.name );
                        //FIXME: is this the correct encoding?
                        body += "Content-disposition: form-data; name=\""+escape(elem.name)+"\";" + cr;
                        body += cr;
                        body += encodeURI(elem.value) + cr;
                        body += boundary + cr;
                }
        }
}
if( otherParams && otherParams.params ) {
for( var key in otherParams.params ) {
body += "Content-disposition: form-data; name=\""+escape(key)+"\";" + cr;
body += cr;
body += encodeURI(otherParams.params[key]) + cr;
body += boundary + cr;
}
}
// add the screenshot as a file
//FIXME: is this the correct encoding?
body += "Content-Disposition: form-data; name=\""+escape(fieldname_filename)+"\"; filename=\""+encodeURI(filename)+"\"" + cr;
//body += "Content-Type: application/octet-stream" + cr;
//body += "Content-Type: image/png" + cr;
body += "Content-Type: image/base64png" + cr;
body += "Content-Transfer-Encoding: base64" + cr;
body += cr;
body += bytes;
body += cr;
// last boundary, no extra cr here!
body += boundary + "--" + cr;
// finally, the Ajax request
var isAsync = false;
var xrequest = new XMLHttpRequest();
xrequest.open( "POST", actionUrl, isAsync );
// set request headers
xrequest.setRequestHeader( "Content-Type", "multipart/form-data; boundary="+boundaryString );
xrequest.setRequestHeader( "Content-length", body.length );
xrequest.setRequestHeader( "Connection", "close" );
xrequest.send( body );
return xrequest.responseText;
}

hoffe, das hilft eventuellen Nachahmern.
chlw
Posts: 1
Joined: 24 Apr 2012, 17:43

Re: bug-uploaded files base64 decodieren

Post by chlw »

Hallo mikes222

Danke für den Post, ist ja schon 'ne Weile her...
Habe das versucht mit einer Mantis BT Version 1.2.10, aber kein Glück :(

Hast Du vielleicht eine Idee, wie das gehen könnte? Es fehlt wohl nicht viel, aber ich weiss z.B. nicht, wo die *.jar und die das *.js hin muss, und auf der Erfassungsseite (bug_report_page.php) bekomme ich auch keine zusätzliche Tabellenzeile, die das Einfügen des Screenshots ermöglichen würde.

Any help or hints are very much appreciated... :wink:

Gruss

chlw
Post Reply