Html Upload mit Python-CGI - korrupte files

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
plip
User
Beiträge: 3
Registriert: Montag 17. Februar 2014, 06:28

Servus,

ich versuche gerade nach einem Beispiel aus dem Netz einen File-Upload per
Python-CGI zu implementieren (momentan noch lokal). Der Transfer läuft durch und das Script
meldet einen erfolgreichen Upload - nur leider sind die Files (z.B.
jpeg-Bilder) danach viel kleiner und lassen sich nicht öffnen.

Server:

Code: Alles auswählen

import http.server
PORT = 8080
handler = http.server.CGIHTTPRequestHandler
httpd = http.server.HTTPServer(("", PORT), handler)
print("serving at port", PORT)
httpd.serve_forever()
Upload-Form:

Code: Alles auswählen

<div>
<form enctype="multipart/form-data" action="cgi-bin/upload.py" method="post">
    <p>File: <input type="file" name="file"></p>
      <input type="submit" value=" Start Upload ">
</form>
<div>
CGI:

Code: Alles auswählen

#!C:\Python33\python.exe 
#!/usr/bin/env python
import cgi, os
import cgitb; cgitb.enable()

try: # Windows needs stdio set for binary mode.
    import msvcrt
    msvcrt.setmode (0, os.O_BINARY) # stdin  = 0
    msvcrt.setmode (1, os.O_BINARY) # stdout = 1
except ImportError:
    pass

form = cgi.FieldStorage()

# A nested FieldStorage instance holds the file
fileitem = form['file']

# Test if the file was uploaded
if fileitem.filename:
   try:
      fn = os.path.basename(fileitem.filename)
      oFile = open('files\\' + fn, 'wb')
      data = fileitem.value
      oFile.write(data)
      oFile.close()
      message = '\nThe file "' + fn + '" was uploaded successfully'
   except Exception as e:
      message = 'Error wrting file "' + fn +'" : ' + str(e)   
else:
   message = 'No file was uploaded'
   
print("""\
Content-Type: text/html\n
<html><body>
<p>%s</p>
</body></html>
""" % (message,))
Schon der Aufruf

Code: Alles auswählen

fileitem.file.read()
liefert einen String, der viel kleiner ist als die Datei (etwa 40K von 3M, Größe jedes Mal ein bisschen anders).
Hat jemand eine Idee?
Rigoletto
User
Beiträge: 28
Registriert: Freitag 14. Februar 2014, 21:05

Passiert da bei allen Filetypen, text und binär?
Was ist wenn die Datei nur 10kb hat, fehlt dann auch was?

Ich glaub bei post ist die upload größe auf max. 32 oder 64 kb beschränkt und du musst auf get wecchseln.
Benutzeravatar
/me
User
Beiträge: 3555
Registriert: Donnerstag 25. Juni 2009, 14:40
Wohnort: Bonn

Rigoletto hat geschrieben:Ich glaub bei post ist die upload größe auf max. 32 oder 64 kb beschränkt und du musst auf get wecchseln.
Die erlaubte Größe ist nur durch den Server beschränkt und nicht durch die HTTP-Spezifikation.
Rigoletto
User
Beiträge: 28
Registriert: Freitag 14. Februar 2014, 21:05

Die erlaubte Größe ist nur durch den Server beschränkt und nicht durch die HTTP-Spezifikation.
Richtig, aber bei "POST" afaik schiebt der Browser die Daten über die URL an den Server, und die browser haben da eine Größenbegrenzung.
Rigoletto
User
Beiträge: 28
Registriert: Freitag 14. Februar 2014, 21:05

Aber probier mal die Größe manuell hochzusetzen:

Code: Alles auswählen

<input type="hidden" name="MAX_FILE_SIZE" value="1024000" />
BlackJack

@Rigoletto: Bei POST sind die Daten gerade *nicht* in der URL kodiert. Und dieser <input>-Hack dürfte nicht funktionieren, das wäre nämlich eine Lücke die kein vernünftiger Admin zulassen würde das der Client einfach so Beschränkungen aushebeln kann die der Admin vorgibt.
Rigoletto
User
Beiträge: 28
Registriert: Freitag 14. Februar 2014, 21:05

BlackJack hat geschrieben:@Rigoletto: Bei POST sind die Daten gerade *nicht* in der URL kodiert. Und dieser <input>-Hack dürfte nicht funktionieren, das wäre nämlich eine Lücke die kein vernünftiger Admin zulassen würde das der Client einfach so Beschränkungen aushebeln kann die der Admin vorgibt.
Ja, stimmt, POST codiert nicht in der url, sofern nutzt er richtig POST.
Aber das <input> ist kein hack sondern der Browser verhindert von vornherein das ich 10MByte Daten uploade wenn der Server auf 5MByte begrenzt ist, und ich das in der html angebe. Sonst lade ich umsonst 5MByte hoch und bekomme erst dann den abbruch vom server. Den Server interessiert die angabe nicht, nur den browser.
BlackJack

@Rigoletto: Das ist eine PHP-Umgebungsvariable, also für den Server, und das funktioniert nur wenn die Felddaten einfach so in die Umgebung übernommen werden, was eine Sicherheitslücke ist und deshalb von keinem ernstzunehmenden Admin mehr erlaubt wird. Das ist also komplett sinnfrei denn bei Python über CGI hat das gar keinen Effekt.
plip
User
Beiträge: 3
Registriert: Montag 17. Februar 2014, 06:28

Ich hab jetzt mal ein 660K großes xml-File probiert. Angekommen sind 43K, die sind aber Ordnung...
Kann das eventuell auch mit dem Python-Server/Handler zusammenhängen. Hab schon überlegt es probehalber mal mit P2 statt P3 zu versuchen, weil die Beispiele alle in P2-Syntax waren. Oder ich versuchs mal auf meinem Raspberry-Pi mit lighttpd...
plip
User
Beiträge: 3
Registriert: Montag 17. Februar 2014, 06:28

Mit dem RPI funktionierts. Außerdem ist die Übertragung viel schneller als beim localhost, was etwas seltsam ist, oder?
Rigoletto
User
Beiträge: 28
Registriert: Freitag 14. Februar 2014, 21:05

BlackJack hat geschrieben:@Rigoletto: Das ist eine PHP-Umgebungsvariable, also für den Server, und das funktioniert nur wenn die Felddaten einfach so in die Umgebung übernommen werden, was eine Sicherheitslücke ist und deshalb von keinem ernstzunehmenden Admin mehr erlaubt wird. Das ist also komplett sinnfrei denn bei Python über CGI hat das gar keinen Effekt.
Nicht nur, der Browser hat auch angaben die er verifiziert: http://www.tizag.com/htmlT/htmlupload.php
BlackJack

@Rigoletto: Das ist Unsinn, dem Browser ist dieses Feld vollkommen egal ausser das er es zum Server überträgt, und dort ist es wie gesagt, wenn überhaupt auch nur für PHP von Interesse. Entgegen der Angabe auf der Webseite ist die Angabe auch in Bytes und nicht in Kilobytes.

Diese Falschinformation scheint von der PHP-Dokumentation in die Netzwelt gesetzt worden zu sein. Hier der entsprechende Bug-Report: https://bugs.php.net/bug.php?id=40387
Rigoletto
User
Beiträge: 28
Registriert: Freitag 14. Februar 2014, 21:05

BlackJack hat geschrieben:@Rigoletto: Das ist Unsinn, dem Browser ist dieses Feld vollkommen egal ausser das er es zum Server überträgt, und dort ist es wie gesagt, wenn überhaupt auch nur für PHP von Interesse. Entgegen der Angabe auf der Webseite ist die Angabe auch in Bytes und nicht in Kilobytes.

Diese Falschinformation scheint von der PHP-Dokumentation in die Netzwelt gesetzt worden zu sein. Hier der entsprechende Bug-Report: https://bugs.php.net/bug.php?id=40387
Hier nochmal in deutsch: http://de.selfhtml.org/html/formulare/d ... definieren
Und ich kann selber sagen das diese Angabe funktioniert, da selbst benutzt. Das hat mit PHP auch nichts zu tun, der Browser checkt das Feld genauso wie eine size-angabe bei einem normalem Texteingabefeld.

added: Ok, es ist nicht der Browser der es checkt sondern javascript.
BlackJack

@Rigoletto: Das steht ja auch ganz deutlich in dem von Dir verlinkten Abschnitt bei Erläuterungen, zweiter Absatz:
http://de.selfhtml.org/html/formulare/datei_upload.htm#definieren hat geschrieben:Das Attribut maxlength wurde in HTML 3.2 definiert als Hinweis an den Browser, nur Dateien bis zu einer Bytegröße dieser Angabe zur Auswahl zuzulassen. In HTML 4.01 wird auf diese Funktion nicht mehr eingegangen. Uns ist auch kein Browser bekannt, der diese Angabe in irgendeiner Weise einschränkend umsetzt.
Ausserdem bist Du hier mal eben so von einem <input>-Feld mit einem bestimmten Namen zu einem Attribut im Datei-<input>-Feld mit einem anderen Wert gesprungen.
Antworten