Python using urllib to authenticate to a webpage - python

I have read the other posts on this, but my situation is a bit unique I think. I am trying to use python to read my grades off of the school's home access center website, but I think there is something peculiar in the way they have it programmed, here is the code that I am using:
import urllib
def WebLogin(password):
params = urllib.urlencode(
{'txtLogin': username,
'txtPassword': password })
f = urllib.urlopen("http://home.tamdistrict.org/homeaccess/Student/Assignments.aspx", params)
if "The following errors occurred while attempting to log in:" in f.read():
print "Login failed."
print f.read()
else:
print "Correct!"
print f.read()
It always prints "Correct" no matter what I enter for the username and password. Each f.read() returns only a blank line. I am really stuck here, thanks for all of your help!

urlopen returns a file-like object. In particular, you can only call read() once (with no arguments -- you can read in chunks by passing a size to read, but ya) -- subsequent calls to read() will return None because you've exhausted it (and unlike regular file objects, there is no seek method). You should store the result in a variable.
content = f.read()
if "The following errors occurred while attempting to log in:" in content:
print "Login failed."
print content
else:
print "Correct!"
print content

Related

How to convert suds object to xml string

This is a duplicate to this question:
How to convert suds object to xml
But the question has not been answered: "totxt" is not an attribute on the Client class.
Unfortunately I lack of reputation to add comments. So I ask again:
Is there a way to convert a suds object to its xml?
I ask this because I already have a system that consumes wsdl files and sends data to a webservice. But now the customers want to alternatively store the XML as files (to import them later manually). So all I need are 2 methods for writing data: One writes to a webservice (implemented and tested), the other (not implemented yet) writes to files.
If only I could make something like this:
xml_as_string = My_suds_object.to_xml()
The following code is just an example and does not run. And it's not elegant. Doesn't matter. I hope you get the idea what I want to achieve:
I have the function "write_customer_obj_webservice" that works. Now I want to write the function "write_customer_obj_xml_file".
import suds
def get_customer_obj():
wsdl_url = r'file:C:/somepathhere/Customer.wsdl'
service_url = r'http://someiphere/Customer'
c = suds.client.Client(wsdl_url, location=service_url)
customer = c.factory.create("ns0:CustomerType")
return customer
def write_customer_obj_webservice(customer):
wsdl_url = r'file:C:/somepathhere/Customer.wsdl'
service_url = r'http://someiphere/Customer'
c = suds.client.Client(wsdl_url, location=service_url)
response = c.service.save(someparameters, None, None, customer)
return response
def write_customer_obj_xml_file(customer):
output_filename = r'C\temp\testxml'
# The following line is the problem. "to_xml" does not exist and I can't find a way to do it.
xml = customer.to_xml()
fo = open(output_filename, 'a')
try:
fo.write(xml)
except:
raise
else:
response = 'All ok'
finally:
fo.close()
return response
# Get the customer object always from the wsdl.
customer = get_customer_obj()
# Since customer is an object, setting it's attributes is very easy. There are very complex objects in this system.
customer.name = "Doe J."
customer.age = 42
# Write the new customer to a webservice or store it in a file for later proccessing
if later_processing:
response = write_customer_obj_xml_file(customer)
else:
response = write_customer_obj_webservice(customer)
I found a way that works for me. The trick is to create the Client with the option "nosend=True".
In the documentation it says:
nosend - Create the soap envelope but don't send. When specified, method invocation returns a RequestContext instead of sending it.
The RequestContext object has the attribute envelope. This is the XML as string.
Some pseudo code to illustrate:
c = suds.client.Client(url, nosend=True)
customer = c.factory.create("ns0:CustomerType")
customer.name = "Doe J."
customer.age = 42
response = c.service.save(someparameters, None, None, customer)
print response.envelope # This prints the XML string that would have been sent.
You have some issues in write_customer_obj_xml_file function:
Fix bad path:
output_filename = r'C:\temp\test.xml'
The following line is the problem. "to_xml" does not exist and I can't find a way to do it.
What's the type of customer? type(customer)?
xml = customer.to_xml() # to be continued...
Why mode='a'? ('a' => append, 'w' => create + write)
Use a with statement (file context manager).
with open(output_filename, 'w') as fo:
fo.write(xml)
Don't need to return a response string: use an exception manager. The exception to catch can be EnvironmentError.
Analyse
The following call:
customer = c.factory.create("ns0:CustomerType")
Construct a CustomerType on the fly, and return a CustomerType instance customer.
I think you can introspect your customer object, try the following:
vars(customer) # display the object attributes
help(customer) # display an extensive help about your instance
Another way is to try the WSDL URLs by hands, and see the XML results.
You may obtain the full description of your CustomerType object.
And then?
Then, with the attributes list, you can create your own XML. Use an XML template and fill it with the object attributes.
You may also found the magic function (to_xml) which do the job for you. But, not sure the XML format matches your need.
client = Client(url)
client.factory.create('somename')
# The last XML request by client
client.last_sent()
# The last XML response from Web Service
client.last_received()

Module urllib.request not getting data

I am trying to test this demo program from lynda using Python 3. I am using Pycharm as my IDE. I already added and installed the request package, but when I run the program, it runs cleanly and shows a message "Process finished with exit code 0", but does not show any output from print statement. Where am I going wrong ?
import urllib.request # instead of urllib2 like in Python 2.7
import json
def printResults(data):
# Use the json module to load the string data into a dictionary
theJSON = json.loads(data)
# now we can access the contents of the JSON like any other Python object
if "title" in theJSON["metadata"]:
print(theJSON["metadata"]["title"])
# output the number of events, plus the magnitude and each event name
count = theJSON["metadata"]["count"];
print(str(count) + " events recorded")
# for each event, print the place where it occurred
for i in theJSON["features"]:
print(i["properties"]["place"])
# print the events that only have a magnitude greater than 4
for i in theJSON["features"]:
if i["properties"]["mag"] >= 4.0:
print("%2.1f" % i["properties"]["mag"], i["properties"]["place"])
# print only the events where at least 1 person reported feeling something
print("Events that were felt:")
for i in theJSON["features"]:
feltReports = i["properties"]["felt"]
if feltReports != None:
if feltReports > 0:
print("%2.1f" % i["properties"]["mag"], i["properties"]["place"], " reported " + str(feltReports) + " times")
# Open the URL and read the data
urlData = "http://earthquake.usgs.gov/earthquakes/feed/v1.0/summary/2.5_day.geojson"
webUrl = urllib.request.urlopen(urlData)
print(webUrl.getcode())
if webUrl.getcode() == 200:
data = webUrl.read()
data = data.decode("utf-8") # in Python 3.x we need to explicitly decode the response to a string
# print out our customized results
printResults(data)
else:
print("Received an error from server, cannot retrieve results " + str(webUrl.getcode()))
Not sure if you left this out on purpose, but this script isn't actually executing any code beyond the imports and function definition. Assuming you didn't leave it out on purpose, you would need the following at the end of your file.
if __name__ == '__main__':
data = "" # your data
printResults(data)
The check on __name__ equaling "__main__" is just so your code is only executing when the file is explicitly run. To always run your printResults(data) function when the file is accessed (like, say, if its imported into another module) you could just call it at the bottom of your file like so:
data = "" # your data
printResults(data)
I had to restart the IDE after installing the module. I just realized and tried it now with "Run as Admin". Strangely seems to work now.But not sure if it was a temp error, since even without restart, it was able to detect the module and its methods.
Your comments re: having to restart your IDE makes me think that pycharm might not automatically detect newly installed python packages. This SO answer seems to offer a solution.
SO answer

I need a super-duper simple CGI Python photo upload

I've looked through tons of answers but the truth is, I only know super basic python and I really need help. I don't know the os module or anything like that and I can't use PHP (not that I know it anyway, but it's not permitted) and I need something so easy that I can understand it.
Basically, I need a CGI upload (I don't need the HTML form, I've got that much down) that will take the photo and save it. That's it. I don't need any fancy place for it to save, I just need the file to be properly uploaded from the form.
I've got various versions of this function and I can't get them working because I don't understand them so PLEASE HELP!!!
import cgi
def savefile (filename, photodoc):
form=cgi.FieldStorage()
name=form[filename]
period=name.split(.)
if period[1]=="jpeg" or period[1]=="jpg" or period[1]=="png":
idk what to do
else:
make an error message
This cgi program will "take the photo and save it. That's it."
#!/usr/bin/python2.7
import cgi
field=cgi.FieldStorage()['fieldname']
open(field.filename, 'wb').write(field.value)
Among the things it doesn't do are error checking and security checking, and specifying in what directory the files should be saved.
Duplicate question but here's what you need:
Depending if windows or linux, first set to binary mode:
try:
import msvcrt
msvcrt.setmode (0, os.O_BINARY)
msvcrt.setmode (1, os.O_BINARY)
except ImportError:
pass
Then:
form = cgi.FieldStorage()
name = form[filename]
period = name.split('.') #You need the quotes around the period
if period[1]=='jpeg' or period[1] == 'jpg' or period[1] =='png':
if upload.filename:
name = os.path.basename(upload.filename)
out = open(YOUR_FILEPATH_HERE + name, 'wb', 1000)
message = "The file '" + name + "' was uploaded successfully"
while True:
packet = upload.file.read(1000)
if not packet:
break
out.write(packet)
out.close()
else:
print 'Error'
Some sources:
How to use Python/CGI for file uploading
http://code.activestate.com/recipes/273844-minimal-http-upload-cgi/

cgi URL forwarding with "Location" header - only partial forwarding?

Greetings all,
I have a python CGI script which using
print "Location: [nextfilename]"
print
After "forwarding" (the reason for the quotes there is apparent in a second), I see the HTML of the page to which it has forwarded fine, but all images, etc. are not showing. The address bar still shows the cgi script as the current location, not the HTML file itself. If I go to the HTML file directly, it displays fine.
Basically, the CGI script, which is stored in the cgi-bin, whereas the HTML files are not, is trying to render images with relational links that are broken.
How do I actually forward to the next page, not just render the next page through the cgi script?
I have gone through the script with a fine-toothed comb to make sure that i wasn't actually using a print htmlDoc command anywhere that would be interrupting and screwing this up.
Sections of Code that are Applicable:
def get_nextStepName():
"""Generates a random filename."""
nextStepBuilder = ["../htdocs/bcc/"]
fileLength = random.randrange(10)+5
for i in range(fileLength):
j = random.choice(varLists.ALPHANUM)
nextStepBuilder.append(j)
nextStepName = ""
for char in nextStepBuilder:
nextStepName += char
nextStepName += ".html"
return nextStepName
def make_step2(user, password, email, headerContent, mainContent, sideSetup, sideContent, footerContent):
"""Creates the next step of user registration and logs valid data to a pickle for later confirmation."""
nextStepName = get_nextStepName()
mainContent = "<h1>Step Two: The Nitty Gritty</h1>"
mainContent += "<p>User Name: %s </p>" % (user)
mainContent += """\
[HTML CODE GOES HERE]
"""
htmlDoc = htmlGlue.glue(headerContent, mainContent, sideSetup, sideContent, footerContent)
f = open(nextStepName, "w")
f.write(htmlDoc)
f.close()
nextStepName = nextStepName[9:] #truncates the ../htdocs part of the filename to fix a relational link issue when redirecting
gotoNext(nextStepName)
def gotoNext(filename):
nextLocation = "Location:"
nextLocation += filename
print(nextLocation)
print
Any thoughts? Thanks a ton. CGI is new to me.
You need to send a 30X Status header as well. See RFC 2616 for details.

Python newbie - Input strings, return a value to a web page

I've got a program I would like to use to input a password and one or multiple strings from a web page. The program takes the strings and outputs them to a time-datestamped text file, but only if the password matches the set MD5 hash.
The problems I'm having here are that
I don't know how to get this code on the web. I have a server, but is it as easy as throwing pytext.py onto my server?
I don't know how to write a form for the input to this script and how to get the HTML to work with this program. If possible, it would be nice to make it a multi-line input box... but it's not necessary.
I want to return a value to a web page to let the user know if the password authenticated successfully or failed.
dtest
import sys
import time
import getopt
import hashlib
h = hashlib.new('md5')
var = sys.argv[1]
print "Password: ", var
h.update(var)
print h.hexdigest()
trial = h.hexdigest()
check = "86fe2288ac154c500983a8b89dbcf288"
if trial == check:
print "Password success"
time_stamp = time.strftime('%Y-%m-%d_%H-%M-%S', (time.localtime(time.time())))
strFile = "txt_" + str(time_stamp) + ".txt"
print "File created: txt_" + str(time_stamp) + ".txt"
#print 'The command line arguments are:'
#for i in sys.argv:
#print i
text_file = open(strFile, "w")
text_file.write(str(time_stamp) + "\n")
for i in range(2, len(sys.argv)):
text_file.write(sys.argv[i] + "\n")
#print 'Debug to file:', sys.argv[i]
text_file.close()
else:
print "Password failure"
You'll need to read up on mod_python (if you're using Apache) and the Python CGI module.
Take a look at django. It's an excellent web framework that can accomplish exactly what you are asking. It also has an authentication module that handles password hashing and logins for you.

Categories