Seite 1 von 1
Web-GUI bei Drucker umgehen
Verfasst: Mittwoch 6. November 2013, 16:17
von lackschuh
Wir haben hier einen Netzwerkdrucker (
bizhub c284) Für jedes Projekt wird eine Kostenstelle angelegt. Dies erfolgt über das Webinterface indem man gefühlte 700 Klicks machen muss, bis man an der Stelle angekommen ist, wo man die Kostenstelle anlegen kann.
Meine Idee wäre – sofern überhaupt möglich – hier Python einzusetzen. Ich hab mal ein wenig mit Requests gespielt.
Begonnen habe ich bei
http://10.0.2.201/wcd/login.xml nach Anmeldung geht es über
http://10.0.2.201/wcd/login.cgi zu
http://10.0.2.201/wcd/a_authentication_track.xml und so weiter...
Code: Alles auswählen
import urllib
import urllib2
mydata=[('func','PSL_LP1_LOG'),('password','1234567812345678')]
mydata=urllib.urlencode(mydata)
path='http://10.0.2.201/wcd/login.cgi'
req=urllib2.Request(path, mydata)
req.add_header("Accept", "text/html")
page=urllib2.urlopen(req).read()
print page
Spuckt folgendes aus:
Code: Alles auswählen
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<meta http-equiv="Expires" content="0">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<meta http-equiv="Refresh" content="0;URL=./a_system_counter.xml">
<meta http-equiv="Pragma" content="no-cache">
</head>
<body>
<script type="text/javascript"><!--
document.cookie="adm=AS_COU";document.cookie="access=";// --></script>
</body>
</html>
Wäre dies in etwa der richtige Weg? Wenn ja, hätte mir jemand ein paar Tipps, welche Module ich mir noch genauer anschauen muss bzw. ich ich weiter vorzugehen habe?
PS:
Ich hab vor über einer Woche Konica Minolta angeschrieben, ob die eine API hätten/zur Verfügung stellen könnten. Jedoch blieb die Antwort aus.
Re: Web-GUI bei Drucker umgehen
Verfasst: Mittwoch 6. November 2013, 16:47
von BlackJack
@lackschuh: Ich würde eher `mechanize` oder `requests` verwenden.
Re: Web-GUI bei Drucker umgehen
Verfasst: Mittwoch 6. November 2013, 17:15
von Sirius3
@lackschuh: das übliche Vorgehen ist, mit den Entwicklertools Deines Browsers den tatsächlichen Netzwerkverkehr anzuschauen: wie werden welche Formulardaten an welche URL geschickt? Plus den Cookie der die Session-ID speichert.
Re: Web-GUI bei Drucker umgehen
Verfasst: Mittwoch 6. November 2013, 17:36
von lackschuh
Sirius3 hat geschrieben:@lackschuh: das übliche Vorgehen ist, mit den Entwicklertools Deines Browsers den tatsächlichen Netzwerkverkehr anzuschauen: wie werden welche Formulardaten an welche URL geschickt? Plus den Cookie der die Session-ID speichert.
Das hab ich schon gemacht mit Tamper Data. Das Ergebnis ist eine 4000 Zeilen lange XML Datei mit Hunderten von Cookies etc. Da muss ich zuerst mal den Überblick bekommen

Re: Web-GUI bei Drucker umgehen
Verfasst: Donnerstag 7. November 2013, 16:47
von lackschuh
Hallo
Ich bräuchte jetzt doch ein wenig Hilfe. Und zwar bin ich soweit 'vorgedrungen', so dass ich kurz davor bin, ein neues Projekt anzulegen (siehe Bild)
http://10.0.2.201/wcd/a_authentication_track.xml
Aber leider bringt mich dieser Button "Neue Registrierung" um den Verstand. Der Quellcode ist xml und wenn ich mittels "Entwickler-Tool" von Chrome den Button untersuche, dann wird mir folgendes angezeigt:
Code: Alles auswählen
<input type="button" value="Neue Registrierung" id="TrackNewRegist" onclick="html_f.setAu('TrackNew','AA_TRA');html_f.RESET('AA_TRA_Clearnew');html_f.hideHelpWindow();">
Nach dem Drücken des Buttons erscheint eine Eingabemaske. Die URL verändert sich aber nicht...
Wie könnte ich nun weiter vorgehen?
mfg
PS:
Code: Alles auswählen
import requests
payload = {'func': 'PSL_LP1_LOG', 'password': '1234567812345678'}
cookie = {}
r = requests.post('http://10.0.2.201/wcd/login.cgi', data=payload)
r2 = requests.post('http://10.0.2.201/wcd/a_system_counter.xml', cookies=r.cookies)
# print r2.text
r3 = requests.post('http://10.0.2.201/wcd/a_authentication_method.xml', cookies=r.cookies)
# print r3.text
r4 = requests.post('http://10.0.2.201/wcd/a_authentication_track.xml', cookies=r.cookies)
#
print r4.text
Das wäre der letzte Teil, wo die Daten abgeschickt werden:
Code: Alles auswählen
<tdRequest uri="http%3A//10.0.2.201/wcd/a_user.cgi"><tdStartTime>16:05:30.517</tdStartTime>
<tdStartTimeMS>1383750330517</tdStartTimeMS>
<tdElapsedTime>704</tdElapsedTime>
<tdTotalElapsedTime>1226</tdTotalElapsedTime>
<tdStatus>200</tdStatus>
<tdStatusText>OK</tdStatusText><tdRequestMethod>POST</tdRequestMethod>
<tdContentSize>869</tdContentSize>
<tdMimeType>text/xml</tdMimeType>
<tdRequestHeaders>
<tdRequestHeader name="Host">
10.0.2.201</tdRequestHeader>
<tdRequestHeader name="User-Agent">
Mozilla/5.0%20%28Windows%20NT%206.1%3B%20WOW64%3B%20rv%3A25.0%29%20Gecko/20100101%20Firefox/25.0</tdRequestHeader>
<tdRequestHeader name="Accept">
text/html%2Capplication/xhtml+xml%2Capplication/xml%3Bq%3D0.9%2C*/*%3Bq%3D0.8</tdRequestHeader>
<tdRequestHeader name="Accept-Language">
de-de%2Cde%3Bq%3D0.8%2Cen-us%3Bq%3D0.5%2Cen%3Bq%3D0.3</tdRequestHeader>
<tdRequestHeader name="Accept-Encoding">
gzip%2C%20deflate</tdRequestHeader>
<tdRequestHeader name="Referer">
http%3A//10.0.2.201/wcd/a_authentication_track.xml</tdRequestHeader>
<tdRequestHeader name="Cookie">
bv%3DFirefox/25.0%3B%20uatype%3DNN%3B%20selno%3DDe%3B%20lang%3DDe%3B%20favmode%3Dfalse%3B%20vm%3DHtml%3B%20usr%3DS_INF%3B%20access%3D%3B%20param%3D%3B%20wd%3Dn%3B%20help%3Doff%2Coff%2Coff%3B%20adm%3DAA_TRA%3B%20ID%3D503e7c5ac78c9b314d77ecb4abf0989d</tdRequestHeader>
<tdRequestHeader name="Connection">
keep-alive</tdRequestHeader>
</tdRequestHeaders><tdPostHeaders><tdPostHeader name="Content-Type">
application/x-www-form-urlencoded
</tdPostHeader>
<tdPostHeader name="Content-Length">
291
</tdPostHeader>
</tdPostHeaders>
<tdPostElements>
<tdPostElement name="func">
PSL_AA_TRA_TRA
</tdPostElement>
<tdPostElement name="h_token">
aa892267191ef4e4a780536eebc1bd6846bdde1cdc29cab03e47820c01fd8559
</tdPostElement>
<tdPostElement name="AA_TRA_H_NUM">
new
</tdPostElement>
<tdPostElement name="AA_TRA_R_RNM">
Space
</tdPostElement>
<tdPostElement name="AA_TRA_P_UP">
12345678
</tdPostElement>
<tdPostElement name="AA_TRA_P_CMP">
12345678
</tdPostElement>
<tdPostElement name="AA_TRA_T_INF">
Test
</tdPostElement>
<tdPostElement name="AA_TRA_S_ACS">
Off
</tdPostElement>
<tdPostElement name="AA_TRA_S_FCP">
All
</tdPostElement>
<tdPostElement name="AA_TRA_S_FSC">
All
</tdPostElement>
<tdPostElement name="AA_TRA_S_FFA">
All
</tdPostElement>
<tdPostElement name="AA_TRA_S_FPR">
All
</tdPostElement>
<tdPostElement name="AA_TRA_S_FPS">
All
</tdPostElement>
</tdPostElements>
<tdResponseHeaders><tdResponseHeader name="Content-Type">
text/xml
[/size]
Re: Web-GUI bei Drucker umgehen
Verfasst: Donnerstag 7. November 2013, 20:02
von Sirius3
Hallo lackschuh,
letztlich ist es egal, was als Javascript aufgerufen wird, entscheidend ist, was letztlich gepostet wird.
Re: Web-GUI bei Drucker umgehen
Verfasst: Freitag 8. November 2013, 10:08
von lackschuh
Sirius3 hat geschrieben:Hallo lackschuh,
letztlich ist es egal, was als Javascript aufgerufen wird, entscheidend ist, was letztlich gepostet wird.
Morgen Sirius3
Hab da noch ein paar Fragen. Und zwar gibt es da bei den PostData ein Element namens h_token, welches anscheinend dynamisch generiert wird bzw. dessen Wert (siehe unten). Leider weiss ich nicht, was das bedeutet.
Die zweite 'Bildungslücke' ist folgendes. Ich gehe von der URL
http://10.0.2.201/wcd/a_authentication_track.xml aus (da, wo die Daten abgeschickt werden). Die Request URL ist dann
http://10.0.2.201/wcd/a_user.cgi. Wie in etwa müsste dann der POST Request ausschauen?
Code: Alles auswählen
payload2 = {
'func' : 'PSL_AA_TRA_TRA',
'h_token' : 'aa892267191ef4e4a780536eebc1bd6846bdde1cdc29cab03e47820c01fd8559', #???
'AA_TRA_H_NUM' : 'new',
'AA_TRA_R_RNM' : 'Space',
'AA_TRA_P_UP' : '12345678', # Projektnummer
'AA_TRA_P_CMP' : '12345678', # Wiederholung Projektnummer
'AA_TRA_T_INF' : 'Test v2', # Projektname
'AA_TRA_S_ACS' : 'Off',
'AA_TRA_S_FCP' : 'All',
'AA_TRA_S_FSC' : 'All',
'AA_TRA_S_FFA' : 'All',
'AA_TRA_S_FPR' : 'All',
'AA_TRA_S_FPS' : 'All'
}
r4 = requests.post('http://10.0.2.201/wcd/a_authentication_track.xml', data=payload2)
[/size]
Code: Alles auswählen
Request URL:http://10.0.2.201/wcd/a_user.cgi
Request Method:POST
Status Code:200 OK
Request Headersview source
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:de,en-US;q=0.8,en;q=0.6,de-CH;q=0.4,de-AT;q=0.2
Connection:keep-alive
Content-Length:307
Content-Type:application/x-www-form-urlencoded
Cookie:ID_F=4e377857a9ea0bb83f35211eca2a4b49; wd=n; uatype=NN; selno=De; lang=De; param=; usr=ACO; bv=Chrome/30.0.1599.101; help=on,on,on; ID=804dd0f2520453ffee87e73ea5c1a70f; access=; vm=Html; favmode=false; adm=AA_TRA
Host:10.0.2.201
Origin:http://10.0.2.201
Referer:http://10.0.2.201/wcd/a_authentication_track.xml
User-Agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36
Form Dataview sourceview URL encoded
func:PSL_AA_TRA_TRA
h_token:327f59f3db2da665224cc65213fea4b65edd1c68c5adf25d03b1501a22f2cc1d
AA_TRA_H_NUM:new
AA_TRA_R_RNM:Space
AA_TRA_P_UP:1234567812345678
AA_TRA_P_CMP:1234567812345678
AA_TRA_T_INF:Test
AA_TRA_S_ACS:Off
AA_TRA_S_FCP:All
AA_TRA_S_FSC:All
AA_TRA_S_FFA:All
AA_TRA_S_FPR:All
AA_TRA_S_FPS:All
Response Headersview source
Content-Length:869
Content-Type:text/xml
Expires:0
[/size]
Vielen Dank und ein schönes Wochenende

Re: Web-GUI bei Drucker umgehen
Verfasst: Freitag 8. November 2013, 12:53
von Sirius3
Hallo lackschuh,
Du mußt den Request an die Request-URL richten. Woher das Formular stammt ist ja letztlich egal. Steht der 'h_token' schon irgendwo im vom a_authentication_track.xml gesendeten HTML oder wird der per Javascript erzeugt?
Re: Web-GUI bei Drucker umgehen
Verfasst: Freitag 8. November 2013, 13:19
von lackschuh
Der h_token wird nach Aufruf der a_authentication_track.xml geladen/erzeugt:
<Token>cb33a72acbf9d7c7197905ed0dfe55595d0605395b337087f5e8408dd3d7ea8f</Token>
Dann wäre also für mich zuerst der nächste Schritt, mich mit dem Modul xml auseinander zu setzen und ggf. das Element mit getElementsByTagName zubekommen?
EDIT:
Es geht nun

Der Tipp mit dem Token war Gold wert. Das WE ist gerettet. Danke für die Hilfe.
Anbei noch der ganze Code:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
from xml.dom.minidom import parseString
payload = {
'func': 'PSL_LP1_LOG',
'password': '1234567812345678'
}
r = requests.post('http://10.0.2.201/wcd/login.cgi', data=payload)
r2 = requests.post('http://10.0.2.201/wcd/a_system_counter.xml', cookies=r.cookies)
r3 = requests.post('http://10.0.2.201/wcd/a_authentication_method.xml', cookies=r.cookies)
r4 = requests.post('http://10.0.2.201/wcd/a_authentication_track.xml', cookies=r.cookies)
#
print r4.text
token = r4.text
dom = parseString(token)
xmlTag = dom.getElementsByTagName('Token')[0].toxml()
xmlData=xmlTag.replace('<Token>','').replace('</Token>','')
print xmlTag
print xmlData
payload2 = {
'func' : 'PSL_AA_TRA_TRA',
'h_token' : xmlData,
'AA_TRA_H_NUM' : 'new',
'AA_TRA_R_RNM' : 'Space',
'AA_TRA_P_UP' : '123456789', # Projektnummer
'AA_TRA_P_CMP' : '123456789', # Wiederholung Projektnummer
'AA_TRA_T_INF' : 'Test 12345', # Projektname
'AA_TRA_S_ACS' : 'Off',
'AA_TRA_S_FCP' : 'All',
'AA_TRA_S_FSC' : 'All',
'AA_TRA_S_FFA' : 'All',
'AA_TRA_S_FPR' : 'All',
'AA_TRA_S_FPS' : 'All'
}
r5 = requests.post('http://10.0.2.201/wcd/a_user.cgi', data=payload2, cookies=r.cookies)
print r5.text
Re: Web-GUI bei Drucker umgehen
Verfasst: Freitag 8. November 2013, 14:11
von Sirius3
@lackschuh: die Requests für r2 und r3 sind wahrscheinlich überflüssig, da Du mit dem Ergebnis nichts machst. r4 ist dann ein get und kein post. Ich kenn mich mit minidom nicht so aus (ich würde ja ElementTree mit xmlData=dom.findtext('Token') nehmen) aber es gibt sicher eine Methode die direkt den TextContent zurückliefert und die unschönen "replace" überflüssig macht.
Re: Web-GUI bei Drucker umgehen
Verfasst: Freitag 8. November 2013, 14:19
von BlackJack
@lackschuh: Die Rückgabewerte von den `requests`-Aufrufen durchzunummerieren ist unschön. Warum musst Du die denn überhaupt alle aufheben?
Wenn Du ein `requests.Session`-Objekt verwendest, brauchst Du die Cookies nicht manuell verwalten.
Ich würde auch die `ElementTree`-API der DOM-API vorziehen. Und dann dieses hässliche ersetzen auf XML-Quelltext um an einen Wert zu kommen, weglassen.
Re: Web-GUI bei Drucker umgehen
Verfasst: Freitag 8. November 2013, 14:56
von lackschuh
@BlackJack
So besser:
Code: Alles auswählen
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import requests
import xml.etree.ElementTree as ET
payload = {
'func': 'PSL_LP1_LOG',
'password': '1234567812345678'
}
r = requests.post('http://10.0.2.201/wcd/login.cgi', data=payload)
r2 = requests.post('http://10.0.2.201/wcd/a_authentication_track.xml', cookies=r.cookies)
root = ET.fromstring(r2.text)
for i in root.findall('Token'):
xmlData = i.text
payload2 = {
'func' : 'PSL_AA_TRA_TRA',
'h_token' : xmlData,
'AA_TRA_H_NUM' : 'new',
'AA_TRA_R_RNM' : 'Space',
'AA_TRA_P_UP' : '123456789', # Projektnummer
'AA_TRA_P_CMP' : '123456789', # Wiederholung Projektnummer
'AA_TRA_T_INF' : 'Test 123456', # Projektname
'AA_TRA_S_ACS' : 'Off',
'AA_TRA_S_FCP' : 'All',
'AA_TRA_S_FSC' : 'All',
'AA_TRA_S_FFA' : 'All',
'AA_TRA_S_FPR' : 'All',
'AA_TRA_S_FPS' : 'All'
}
r3 = requests.post('http://10.0.2.201/wcd/a_user.cgi', data=payload2, cookies=r.cookies)
print r3.text
#Logout Funktion hinzufüegen
Request 2 und 3 brauch ich nicht. R4 brauch ich für das Token. Das mit den manuell verwalteten Cookies versteh ich nicht ganz...

Re: Web-GUI bei Drucker umgehen
Verfasst: Freitag 8. November 2013, 16:47
von BlackJack
@lackschuh: Hör mal bitte auf Namen zu nummerieren. Im Grunde brauchst Du keines der `response`-Objekte nach der nächsten Anfragen. Nur von der ersten Antwort brauchst Du (noch) die Cookies. Das ist aber kein Grund das ganze Antwort-Objekt aufheben zu müssen. Das gleiche gilt für `payload`.
Mit manuell die Cookies verwalten meine ich das Du manuell, also selbst, mit Code, den Du geschrieben hast, Dich immer wieder um die Cookies bei jeder Anfragen kümmerst. Dafür gibt es `requests.Session`. Einmal erstellen, darüber die Anfragen stellen, nicht selber um Cookies kümmern.
Bei dem XML solltest Du das `content`-Attribut statt des `text` von der Antwort verwenden, denn dieses XML ist kein Text sondern besteht aus Bytes. Das dekodieren erledigt der XML-Parser.
Ungetestet:
Code: Alles auswählen
#!/usr/bin/env python
# coding: utf-8
import requests
import xml.etree.ElementTree as etree
BASE_URL = 'http://10.0.2.201/wcd/'
def main():
with requests.Session() as session:
data = {'func': 'PSL_LP1_LOG', 'password': '1234567812345678'}
session.post(BASE_URL + 'login.cgi', data=data)
response = session.get(BASE_URL + 'a_authentication_track.xml')
token = etree.fromstring(response.content).find('.//Token').text
project_id = '123456789'
project_name = 'Test 123456'
data = {
'func': 'PSL_AA_TRA_TRA',
'h_token': token,
'AA_TRA_H_NUM': 'new',
'AA_TRA_R_RNM': 'Space',
'AA_TRA_P_UP': project_id,
'AA_TRA_P_CMP': project_id,
'AA_TRA_T_INF': project_name,
'AA_TRA_S_ACS': 'Off',
'AA_TRA_S_FCP': 'All',
'AA_TRA_S_FSC': 'All',
'AA_TRA_S_FFA': 'All',
'AA_TRA_S_FPR': 'All',
'AA_TRA_S_FPS': 'All',
}
response = requests.post(BASE_URL + 'a_user.cgi', data=data)
print response.text
# TODO Logout Funktion hinzufügen
if __name__ == '__main__':
main()
Re: Web-GUI bei Drucker umgehen
Verfasst: Montag 11. November 2013, 11:42
von lackschuh
Morgen,
Danke für die Tipps. Hab nun auch das mit requests.Session() begriffen. Ein wenig aufmerksamer in der Doku lesen und man würde
Session Objects
The Session object allows you to persist certain parameters across requests. It also persists cookies across all requests made from the Session instance.
finden
Abschließend hab ich noch ein letztes Problem, welches ich sehr wahrscheinlich auf die unsauberste Art gelöst habe. Und zwar soll eine Meldung erscheinen, falls ein Projekt bereits erstellt wurde:
Code: Alles auswählen
#Fehlermeldung, falls Projekt bereits besteht
try:
token = etree.fromstring(response.content).find('.//ErrorDescription').text
if token == "Don't set Duplicate Password":
print 'ERROR!', 'Project %s existiert bereits!' %project_id
except AttributeError:
print 'Job Done!', project_name, project_id
# Logout
data = {'func': 'PSL_ACO_LGO'}
session.post('http://10.0.2.201/wcd/a_user.cgi', data=data)
zB seht hier im Wiki, dass man generell einen Codeblock nicht in try...except packen soll. Leider fällt mir gerade nichts anders ein...
In mienem Beispielt verhält es sich so, dass, wenn ein Projekt erfolgreich angelegt wurde auch keine Meldung (Don't set Duplicate Password) im Quelltext erscheint und so das Attribut "token" auch kein Wert zugewiesen bekommt, wobei der Attributname sowiso falsch bennant wurde... ggf pw_error oder so bennenen.
mfg
Re: Web-GUI bei Drucker umgehen
Verfasst: Montag 11. November 2013, 12:13
von BlackJack
@lackschuh: Hier könnte man das Ergebnis von dem `find()` an einen Namen binden und auf `None` prüfen. Falls es `None` ist, war alles in Ordnung, ansonsten gab es eine Fehlerbeschreibung im XML. Das sollte man vielleicht auch an den Benutzer melden falls es nicht der erwartete Fehler war. Zusammen mit dem Fehlertext. Ansonsten könnten an der Stelle Fehler verschluckt werden die der Benutzer nie zu gesicht bekommt.
Eventuell macht es auch Sinn eine generelle Funktion oder Methode zum Aufruf von „Funktionen” des Druckers zu schreiben, die wenn eine Fehlerbeschreibung im XML gefunden wird, eine Ausnahme daraus erstellt und auslöst.
Re: Web-GUI bei Drucker umgehen
Verfasst: Montag 11. November 2013, 13:29
von Sirius3
@lackschuh: oder nimm gleich findtext. Das liefert auch None, wenn der Eintrag nicht gefunden wird.