I don't want to be a bother, and I probably shouldn't be trying to even manipulate a programming language I know nothing about. But the deployment method this presents is too irresistible not to use. Basically urbackup has this script designed to automatically pull a downloader for a specific computer using its WMI %ComputerName% property. The issue I seem to be having is related to JSON not being able to authenticate with server any more after Python 3.4. I honestly know very little about Python, and if it is too complex for me to fix or would require more work than necessary I understand that, I just figured maybe its a simpler error that can be corrected by someone with a bit of know how.
import http.client as http
import json
from urllib.parse import urlparse
from urllib.parse import urlencode
from base64 import b64encode
import hashlib
import socket
import shutil
import os
#############################
# Settings. Please edit.
#############################
#Your server URL
server_url = 'intentionallyremoved.com'
server_basic_username='intentionallyremoved'
server_basic_password='intentionallyremoved'
#user needs following rights
# "settings": "all"
# "status": "some"
# "add_client": "all"
server_username='intentionallyremoved'
server_password='intentionallyremoved'
#############################
# Global script variables.
# Please do not modify.
#############################
session=""
def get_response(action, params):
global server_url;
global server_basic_username;
global server_basic_password;
global session;
headers = {
'Accept': 'application/json',
'Content-Type': 'application/json; charset=UTF-8'
}
if('server_basic_username' in globals() and len(server_basic_username)>0):
userAndPass = b64encode(str.encode(server_basic_username+":"+server_basic_password)).decode("ascii")
headers['Authorization'] = 'Basic %s' % userAndPass
curr_server_url=server_url+"?"+urlencode({"a": action});
if(len(session)>0):
params["ses"]=session
curr_server_url+="&"+urlencode(params);
target = urlparse(curr_server_url)
method = 'GET'
body = ''
if(target.scheme=='http'):
h = http.HTTPConnection(target.hostname, target.port)
elif(target.scheme=='https'):
h = http.HTTPSConnection(target.hostname, target.port)
else:
print('Unkown scheme: '+target.scheme)
raise Exception("Unkown scheme: "+target.scheme)
h.request(
method,
target.path+"?"+target.query,
body,
headers)
return h.getresponse();
def get_json(action, params = {}):
response = get_response(action, params)
if(response.status != 200):
return ""
data = response.readall();
response.close()
return json.loads(data.decode('utf8'))
def download_file(action, outputfn, params):
response = get_response(action, params);
if(response.status!=200):
return False
with open(outputfn, 'wb') as outputf:
shutil.copyfileobj(response, outputf)
return True
def md5(s):
return hashlib.md5(s.encode()).hexdigest()
print("Logging in...")
salt = get_json("salt", {"username": server_username})
if( not ('ses' in salt) ):
print('Username does not exist')
exit(1)
session = salt["ses"];
if( 'salt' in salt ):
password_md5 = md5(salt["rnd"]+md5(salt["salt"]+server_password));
login = get_json("login", { "username": server_username,
"password": password_md5 })
if('success' not in login or not login['success']):
print('Error during login. Password wrong?')
exit(1)
print("Creating client "+socket.gethostname()+"...")
status = get_json("status", { "clientname": socket.gethostname()})
for client in status["client_downloads"]:
if (client["name"] == socket.gethostname()):
print("Downloading Installer...")
if not download_file("download_client", "Client Installer.exe", {"clientid": client["id"]}):
print("Downloading client failed")
exit(1)
print("Sucessfully downloaded client")
os.startfile("Client Installer.exe")
exit(0)
print("Could not find client for download. No permission?")
exit(1)
The error it is outputting looks like this (I've removed applicable server names).
Logging in...
Traceback (most recent call last):
File "\\server\Share\Shortcuts\BackupScript\Script.py", line 110, in <module>
salt = get_json("salt", {"username": server_username})
File "\\server\Share\Shortcuts\BackupScript\Script.py", line 89, in get_json
return json.loads(data.decode('utf8'))
File "C:\Anaconda3\lib\json\__init__.py", line 318, in loads
return _default_decoder.decode(s)
File "C:\Anaconda3\lib\json\decoder.py", line 343, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "C:\Anaconda3\lib\json\decoder.py", line 361, in raw_decode
raise ValueError(errmsg("Expecting value", s, err.value)) from None
ValueError: Expecting value: line 1 column 1 (char 0)
>>>
I've tried using different things talking about using different JSON methods that don't involve the decode variable, and using json.dump instead, but they all seem to lead to different errors because I don't know which parts of the code correspond to the parts of the code I'd be changing. This is really just a quality of life tool, and isn't absolutely necessary. But it would be comforting to simply convert this into an MSI I could deploy instead of having to manually one by one go to each of our (over 100) computers and manually do this. Any help would be appreciated :).
Here is the log in javascript from the back end of the server.
g.login1=function ()
{
var username=I('username').value;
var password=I('password').value;
if( username.length==0 )
{
alert(trans("username_empty"));
I('username').focus();
return false;
}
if( password.length==0 )
{
alert(trans("password_empty"));
I('password').focus();
return false;
}
if(!startLoading()) return false;
new getJSON("salt", "username="+username, login2);
return false;
}
function login2(data)
{
if(data.error==0)
{
alert(trans("user_n_exist"));
stopLoading();
I('username').focus();
return;
}
if(data.ses)
g.session=data.ses;
var username=I('username').value;
var password=I('password').value;
var pwmd5=calcMD5(data.rnd+calcMD5(data.salt+password));
new getJSON("login", "username="+username+"&password="+pwmd5, login3);
}
function login3(data)
{
stopLoading();
if(data.error==2)
{
alert(trans("password_wrong"));
I('password').focus();
return;
}
g.allowed_nav_items = [];
if(data.status!="none")
{
g.allowed_nav_items.push(6);
}
if(data.progress!="none")
{
g.allowed_nav_items.push(5);
}
if(data.browse_backups!="none")
{
g.allowed_nav_items.push(4);
}
if(data.logs!="none")
{
g.allowed_nav_items.push(3);
}
if(data.graph!="none")
{
g.allowed_nav_items.push(2);
}
if(data.settings!="none")
{
g.allowed_nav_items.push(1);
}
build_main_nav();
show_status1();
}
Could you try changing line 86 to read
data = response.read()
I don't know what readall() is but it's not listed in the docs for the HTTPResponse object
Related
I made a python api that I'm trying to get my app to connect to, but for the login function I need to send the username and password but I'm not sure how to do this. This is the python code:
username = data.get('username')
email = data.get('email')
password = data.get('password')
And the Kotlin Code:
private fun sendData(username:String, password:String): Thread {
return Thread {
val url = URL("https://127.0.0.1:5000/login")
val connection = url.openConnection() as HttpsURLConnection
connection.setRequestProperty("username", username)
connection.setRequestProperty("password", password)
if (connection.responseCode == 200) {
val inputSystem = connection.inputStream
println(inputSystem.toString())
Toast.makeText(applicationContext, "It worked", Toast.LENGTH_SHORT).show()
}
else {
var code: String = "ERROR"
Toast.makeText(applicationContext, "NO CONNECTION", Toast.LENGTH_SHORT).show()
}
}
}
The connection is opened but I can get any data across and I haven't tried anything so far as I can't find good documentation on this.
You could, for example, first set up a class to handle your credentials:
class LoginData(
val userID: String,
val pw: String
){
/** Returns a hashmap of the data stored in the class object. */
fun getHashmap(): Map<String,String> {
val params = HashMap<String,String>()
params["username"] = userID
params["password"] = pw
return params
}
/** Obtains a JSONObject of the data stored in the class object. */
fun getJson(): JSONObject {
val params = this.getHashmap()
return JSONObject(params)
}
}
And then, utilising Volley (don't forget to add it to your build gradle: implementation 'com.android.volley:volley:1.2.0'), do something like this:
fun sendData(username: String?, password: String?) {
val url = "https://127.0.0.1:5000/login"
var loginData = LoginData(
userID = username!!,
pw = password!!
)
val queue = Volley.newRequestQueue(this)
val jsonRequest = JsonObjectRequest(
Request.Method.POST,
url,
loginData.getJson(),
Response.Listener {
response -> handleResponse(response)//do something with the response
},
Response.ErrorListener { error -> println("That didn't work: $error")})
queue.add(jsonRequest)
}
with handleResponse() containing your logic to evaluate what comes back from the server:
fun handleResponse(response: JSONObject) {
//your evaluation logic
}
first i taut i have multiple file usig same name but i anable to find the file so, i tried using create new virtual env but i got same error .even i tried to upgrade the package but noting works .
here is my code
import requests
def verify_totp(request_key, totp):
try:
payload = {
"request_key": request_key,
"otp": totp
}
result_string = requests.post4(url=URL_VERIFY_TOTP, json=payload)
if result_string.status_code != 200:
return [ERROR, result_string.text]
result = json.loads(result_string.text)
request_key = result["request_key"]
return [SUCCESS, request_key]
It should be requests.post not requests.post4
Also check your try block and indentation.
def verify_totp(request_key, totp):
# you can avoid the use of a `try except`block if you don't use it
payload = {
"request_key": request_key,
"otp": totp
}
result_string = requests.post(url=URL_VERIFY_TOTP, json=payload)
if result_string.status_code != 200:
return ["ERROR", result_string.text]
result = json.loads(result_string.text)
request_key = result["request_key"]
return ["SUCCESS", request_key]
request_key = "<INSERT YOUR REQUEST KEY HERE>"
totp = "<INSERT YOUR TOTP HERE>"
request_status, request_key = verify_totp(request_key, totp)
print(request_status, request_key)
I'm trying to access a mysql database inside an ios app and I would like to use python to read and write to the database when called from my app.
PHP Code I would like to turn into a python script
I am not sure how to write or read data from my application using mysql-connector.
I believe this is done with the $_POST[a]; but I am not sure how to get the same results using python.
I also have a sample of how I am trying to send data from my app to my database written in swiftui.
'''
import Foundation
import SwiftUI
struct CreateEventButton: View {
#State private var isPresentedEvent = false
#State private var eventid: Int = 0
#State private var eventName: String = ""
#State private var eventDescription: String = ""
#State private var selectedStartTime = Date()
#State private var selectedEndTime = Date()
#Binding var annotationSelected: Bool
func send(_ sender: Any) {
let request = NSMutableURLRequest(url: NSURL(string: "http://YOUR FILE PATH")! as URL)
request.httpMethod = "POST"
let postString = "a=\(self.eventid)&b=\(self.eventName)&=c\(self.eventDescription)&=d\(self.selectedStartTime)&=e\(self.selectedEndTime)"
request.httpBody = postString.data(using: String.Encoding.utf8)
let task = URLSession.shared.dataTask(with: request as URLRequest) {
data, response, error in
if error != nil {
print("error=\(String(describing: error))")
return
}
print("response = \(String(describing: response))")
let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print("responseString = \(String(describing: responseString))")
}
task.resume()
self.eventName = ""
self.eventDescription = ""
self.selectedStartTime = Date()
self.selectedEndTime = Date()
}
var body: some View {
Button(action: {
self.isPresentedEvent.toggle() //trigger modal
}, label: {
Text("Create Event")})
.foregroundColor(.secondary)
.background(Color(.secondarySystemBackground))
.cornerRadius(50.0)
.sheet(isPresented: $isPresentedEvent, content:{
VStack{
TextField("Event Name", text: self.$eventName).padding()
TextField("Event Description", text: self.$eventDescription).padding()
Form {
DatePicker("When your event starts: ", selection: self.$selectedStartTime, in: Date()...)
}
Form {
DatePicker("When your event ends: ", selection: self.$selectedEndTime, in: Date()...)
}
HStack{
Button(action: {
self.isPresentedEvent.toggle()
self.annotationSelected = false
self.eventid += 1
print("Start: \(self.selectedStartTime)")
print("End: \(self.selectedEndTime)")
//send()
}, label: {
Text("Create Event")
})
Button(action: {
self.isPresentedEvent.toggle()
}, label: {
Text("Cancel")
})
}
Text("Create Event Button (Non Functional)").padding()
}
} )
}
}
'''
I am not sure what parameters to put in the sender function created here.
Any insight would be greatly appreciated.
In order to receive POST requests from the SwiiftUI app, you need to run a python webserver like flask.
1. Create a python module (file) something like this:
app.py
from flask import Flask
from flask import make_response
import mysql.connector
from flask import request
server_name = "localhost"
username = "flask"
password = "flask"
dbname = "flask"
# Create and check connection
try:
conn = mysql.connector.connect(
host=server_name,
user=username,
passwd=password,
database=dbname
)
print("Connection OK")
except e:
print("Connection failed: ", e)
mycursor = conn.cursor()
app = Flask(__name__)
#app.route('/', methods=['POST'])
def register():
name = request.form['a']
age = request.form['b']
sql = "INSERT INTO users (name, age) VALUES (%s, %s)"
val = (name, age)
try:
mycursor.execute(sql, val)
conn.commit()
conn.close()
except e:
print("Error: ", e)
return make_response("Success!", 200)
2. Make sure you have the necessary libraries installed:
pip install flask
pip install mysql-connector-python
You need to make sure your MySQL database is up and that you fill in the real credentials for the database in the code. (Default MySQL port = 3306)
3. Start the flask development webserver
export FLASK_APP=app.py # OR set FLASK_APP=app.py (for Windows)
python -m flask run
Your server should start at: http://localhost:5000
Replace: http://YOUR FILE PATH with http://localhost:5000/ in your swift code example and viola!
UPDATE: I tested this and it works. Here is the swiftUI code I generated in postman:
import Foundation
var semaphore = DispatchSemaphore (value: 0)
let parameters = "a=Lance&b=35"
let postData = parameters.data(using: .utf8)
var request = URLRequest(url: URL(string: "http://localhost:5000/")!,timeoutInterval: Double.infinity)
request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
request.httpMethod = "POST"
request.httpBody = postData
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data else {
print(String(describing: error))
return
}
print(String(data: data, encoding: .utf8)!)
semaphore.signal()
}
task.resume()
semaphore.wait()
I'm trying to upload some data from rasberry pi to azure iot hub, I'm facing this problem,Where do I need to set the encoding/charsets?
I've tried data.encode('utf-8') something like that but not working.
Might be someone asked, please help me with this specific code.
I'm following this link.
def generate_sas_token():
expiry=3600
ttl = time.time() + expiry
sign_key = "%s\n%d" % ((quote_plus(URI)), int(ttl))
signature = b64encode(HMAC(b64decode(KEY), sign_key, sha256).digest())
rawtoken = {
'sr' : URI,
'sig': signature,
'se' : str(int(ttl))
}
rawtoken['skn'] = POLICY
return 'SharedAccessSignature ' + urlencode(rawtoken)
def send_message(token, message):
url = 'https://{0}/devices/{1}/messages/events?api-version=2016-11-14'.format(URI, IOT_DEVICE_ID)
headers = {
"Content-Type": "application/json",
"Authorization": token
}
data = json.dumps(message)
print(data)
#data.encode('utf-8')
response = requests.post(url, data=data, headers=headers)
if __name__ == '__main__':
# 2. Generate SAS Token
token = generate_sas_token()
# 3. Send Temperature to IoT Hub
while True:
#temp = read_temp()
message = { "temp": str("12") }
send_message(token, message)
time.sleep(1)
And the error is
Traceback (most recent call last):
File "/home/pi/python/test.py", line 45, in <module>
token = generate_sas_token()
File "/home/pi/python/test.py", line 20, in generate_sas_token
signature = b64encode(HMAC(b64decode(KEY), sign_key, sha256).digest())
File "/usr/lib/python3.5/hmac.py", line 84, in __init__
self.update(msg)
File "/usr/lib/python3.5/hmac.py", line 93, in update
self.inner.update(msg)
TypeError: Unicode-objects must be encoded before hashing
The error tells you must encode before creating your HMAC object. It seems you are decoding it first :
HMAC(b64decode(KEY), sign_key, sha256)
A possible solution could be:
HMAC(b64decode(KEY), sign_key.encode('utf-8'), sha256)
I am trying to replicate the following lines of python code from the https://github.com/joshfraser/robinhood-to-csv repo from GitHub in order to read my transaction history.
orders = robinhood.get_endpoint('orders')
paginated = True
page = 0
while paginated:
for i, order in enumerate(orders['results']):
executions = order['executions']
instrument = robinhood.get_custom_endpoint(order['instrument'])
fields[i + (page * 100)]['symbol'] = instrument['symbol']
for key, value in enumerate(order):
if value != "executions":
fields[i + (page * 100)][value] = order[value]
if order['state'] == "filled":
trade_count += 1
for key, value in enumerate(executions[0]):
fields[i + (page * 100)][value] = executions[0][value]
elif order['state'] == "queued":
queued_count += 1
# paginate
if orders['next'] is not None:
page = page + 1
orders = robinhood.get_custom_endpoint(str(orders['next']))
else:
paginated = False
Where we also have
def get_endpoint(self, endpoint=None):
res = self.session.get(self.endpoints[endpoint])
return json.loads(res.content.decode('utf-8'))
I have thus been working on the following iOS code. I work with this code in an XCode playground so feel free to make one to follow along
import UIKit
import PlaygroundSupport
let LoginEndpoint:String = "https://api.robinhood.com/api-token-auth/"
let LoginRequestData:[String : String] = ["username": "EmailAdress", "password": "Password"]
let OrdersEndpoint:String = "https://api.robinhood.com/orders/"
func httpReq(type: String, url: String, body:[String : String], header:[String : String]) -> ([String : Any]?, Data?, String?){
let url = URL(string: url)
var returnData:([String : Any]?, Data?, String?)? = nil
if let url = url {
var request = NSMutableURLRequest(url: url) as URLRequest
request.httpMethod = type
var postString = ""
for (key, value) in body {
if (postString != "") {
postString += "&"
}
postString += "\(key)=\(value)"
}
request.httpBody = postString.data(using: .utf8)
for (key, value) in header {
request.addValue(value, forHTTPHeaderField: key)
}
let _ = URLSession.shared.dataTask(with: request, completionHandler: {(data, response, error) in
if let data = data {
do {
let jsonSerialized = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any]
returnData = (jsonSerialized, data, nil)
} catch (_) {
returnData = (nil, data, "JSON Parse Erro")
}
} else if let error = error {
returnData = (nil, nil, error.localizedDescription)
}
}).resume()
}
while (returnData == nil) {}
return returnData!
}
let tokenQuery = httpReq(type: "POST", url: LoginEndpoint, body: LoginRequestData, header: [:])
if let token = tokenQuery.0?["token"] {
print("token \(token)")
let historyQuery = httpReq(type: "GET", url: OrdersEndpoint, body: [:], header: ["Authorization": "Token \(token)"])
if let results = historyQuery.0?["results"], let countString = historyQuery.0?["count"] {
}
}
RunLoop.main.run()
PlaygroundPage.current.needsIndefiniteExecution = true
So as you can see I am using the auth token to get to the orders endpoint. I am indeed getting a good response from the orders endpoint but I have no clue how to interpret it.
It would seem from the python code that it is returning an array of JSON objects however I cant figure out how to get to that array in swift. I am not even sure if I am decoding it properly. The funny thing is when you look at the object returned in Playgrounds it would seem XCode knows that there is an array going on. How do I get to it?
Can't really get a good idea of the information being returned by your service, because of the lack of credentials.
However, check out SwiftyJSON. It's a really good library, and is extremely helpful with handling JSON data in Swift. It should solve your JSON handling issues.