Weird behavior when doing POST by PyCurl - python

I have a simple code to post data to a remote server:
def main():
headers = {}
headers['Content-Type'] = 'application/json'
target_url = r'the_url'
data = {"bodyTextPlain": "O estimulante concorrente dos azulzinhos\r\nConhe\u00e7a a nova tend\u00eancia em estimulante masculino e feminino\r\n\r\nEste estimulante ficou conhecido por seus efeitos similares as p\u00edlulas\r\nazuis,\r\ndestacando-se por n\u00e3o possuir contraindica\u00e7\u00e3o ou efeito colateral.\r\n\r\nSucesso de vendas e principal concorrente natural dos azulzinhos,\r\nsua f\u00f3rmula \u00e9 totalmente natural e livre de qu\u00edmicos.\r\n\r\nPossuindo registro no Minist\u00e9rio da Sa\u00fade (ANVISA) e atestado de\r\nautenticidade.\r\n\r\nSaiba mais http://www5.somenteagora.com.br/maca\r\nAdquirindo 3 frascos voc\u00ea ganha +1 de brinde. Somente esta semana!\r\n\r\n\r\n\r\n\r\nPare de receber\r\nhttp://www5.somenteagora.com.br/app/sair/3056321/1\r\n\r\n"}
buffer = StringIO()
curl = pycurl.Curl()
curl.setopt(curl.URL, target_url)
curl.setopt(pycurl.HTTPHEADER, ['%s: %s' % (k, v) for k, v in headers.items()])
# this line causes the problem
curl.setopt(curl.POSTFIELDS, json.dumps(data))
curl.setopt(pycurl.SSL_VERIFYPEER, False)
curl.setopt(pycurl.SSL_VERIFYHOST, False)
curl.setopt(pycurl.WRITEFUNCTION, buffer.write)
curl.perform()
response = buffer.getvalue()
print curl.getinfo(pycurl.HTTP_CODE)
print response
The remote server has errors parsing the json string I send:
500
{
"status" : "Error",
"message" : "Unexpected IOException (of type java.io.CharConversionException): Invalid UTF-32 character 0x3081a901(above 10ffff) at char #7, byte #31)"
}
However if I save the post data from json.dumps to a variable and then do post:
#curl.setopt(curl.POSTFIELDS, json.dumps(data))
data_s = json.dumps(data)
curl.setopt(curl.POSTFIELDS, data_s)
Then there is no error:
200
Is there any difference between these two cases?
Thanks.

This is a marvelously subtle question. The answer lies in this warning in the documentation for Curl.setopt_string(option, value):
Warning: No checking is performed that option does, in fact, expect a string value. Using this method incorrectly can crash the program and may lead to a security vulnerability. Furthermore, it is on the application to ensure that the value object does not get garbage collected while libcurl is using it. libcurl copies most string options but not all; one option whose value is not copied by libcurl is CURLOPT_POSTFIELDS.
When you use a variable, this creates a reference to the string so it doesn't get garbage collected. When you inline the expression, the string is deallocated before libcurl finishes using it, with unpredictable results.
To avoid having to worry about the lifetime of your objects, you can use CURLOPT_COPYPOSTFIELDS instead.

Related

Problem with cryptography.fernet: decrypt my code with a wrong key

I was working with fernet to encrypt. In the tests I founded that if I change the last character of the key, fernet it is able to dencrypt.
For example if the key is ZwvCXUGvnG0RvkhNszIQsQOqz8yaKjUSJpxraDVsxd4= and i type ZwvCXUGvnG0RvkhNszIQsQOqz8yaKjUSJpxraDVsxd5= instead, the program dencrypt my code. I founded this error bc i was lazy to copy a whole new key, so i decided to only change the last character. This happen with every consecuent character in the last one character of the key.
If anyone could help me i would be very thankfull
This is my code
from cryptography.fernet import Fernet
text1="""Find me and follow me through corridors, refectories and files
You must follow, leave this academic factory
You'll find me in the matinée, the dark of the matinée
It's better in the matinée, the dark of the matinée is mine
Yes, it's mine"""
def crearLLave():
key=Fernet.generate_key()
print(key.decode())
return Fernet(key)
def crearLLaveManual(llave):
try:
return Fernet(llave)
except:
again=bytes(input("Formato incorrecto "), "ascii")
return crearLLaveManual(again)
def encriptarTexto(cadena, llave):
return llave.encrypt(str.encode(cadena))
def desencriptarTexto(cadena_encriptada, llave):
try:
return llave.decrypt(cadena_encriptada).decode()
except:
cadena=bytes(input("La cámara de los secretos no se abrirá, intente de nuevo: "),"ascii")
return desencriptarTexto(cadena_encriptada, crearLLaveManual(cadena))
llave=crearLLave()
texto_encriptado=encriptarTexto(text1, llave)
print("La cadena encriptada es: ",texto_encriptado.decode())
cadenaLlave=bytes(input("Escriba la llave para desencriptar el texto: "), "ascii")
llaveManual=crearLLaveManual(cadenaLlave)
print("El texto desencriptado es: ",desencriptarTexto(texto_encriptado, llaveManual))
Console Message:
lIX2AfP-cyFRNgYgFRf3Sy3uKQ4Hrr4Lvrn12wFGo30=
La cadena encriptada es: gAAAAABjg7kdWTCIRjIrIAFk2fQg-znc1zRdrc7VaTkjcKZL1RZ2jmCjvf6NlzQ-39yxh0BMXY0FkrBTN0Ky51HiGy9cxmlbpZ7_Jwp6wml2DsMkCWf7h49EYLN8hjtpzFoiTUy7coguSXgFDBVVyucAUhgcn1EzleHJ_pKlDsyw6EnNLVBqUkmI8WYOY5NwEfCKx3UUlvV3dYDZqjeVqMX90CaAueUMtgDvcVP77tkngK7U2jfneH85bxBo8LJooenFnVeqNxwc70a8vY-GmOihnbDyAOT-GYwmLMssMP5QYDWNBnnTEmMSm4Dt-OHCvOYRyie82T6Art6PK5miinVsjsvkXpd6g343tmNSg34XMbMqgTIILXB7t6gZqdfnpUNUJ6vLfQvM4s4bYSltEEgTSIwrMUUUbA==
Escriba la llave para desencriptar el texto: lIX2AfP-cyFRNgYgFRf3Sy3uKQ4Hrr4Lvrn12wFGo31=
El texto desencriptado es: Find me and follow me through corridors, refectories and files
You must follow, leave this academic factory
You'll find me in the matinée, the dark of the matinée
It's better in the matinée, the dark of the matinée is mine
Yes, it's mine

Random (incorrect) comma appears in JSON with very large request from Flask

Im trying to send a json from Flask to NodeJS and respond a pdf. The json contains data necessary for making receipts used by the walking collector and its basic structure looks like this:
{"list":[{"user":"user1","month":"11/2020"},{"user":"user1","month":"12/2020"}],qid:"query_id"}
This works well but only if the json is small enough (about 500 elements in the inner list ) if i were to pass a bit more elements (like 600/700) it will break with the following:
SyntaxError: Unexpected token , in JSON at position 98224
After a trip to JSONLint found out the culprit in the list:
{ "NOMBRE": "JUAN ", "NROSOCIO": 2706, "DIRECCION": "fake_street 587 ", "RECARGO": 0, "IMPORTE": 50, "PERIODO": "12/2020", "BARCODE": "027061220201000050.0", "COBRADOR", : "1" }
The problem its the random , before : in COBRADOR but i dont know why its (consistently) there
Things i tried
Replacing all the data with static values
Not putting the "COBRADOR" element in the json (the comma still apears)
Transforming the buffer to string before parsing in Node
Python code for generating the json
for socio in db.session.query(socios).filter(socios.COBRADOR == cobrador).all():
mes = int(mesi)
año = int(añoi)
for i in range(meses):
barcode = cuponificador(str(socio.NROSOCIO),5)+cuponificador(str(mes),2)+str(año)+str(socio.COBRADOR)+cuponificador(str(importe),8)
periodo = str(mes)+"/"+str(año)
ret.append(({"NOMBRE":socio.NOMBRE,"NROSOCIO":socio.NROSOCIO,"DIRECCION":socio.DIRECCION,"RECARGO":ceil(float(recargo)),"IMPORTE":ceil(float(importe)),"PERIODO":periodo,"BARCODE":barcode,"COBRADOR":cobrador}))
mes = mes + 1
if (mes == 13):
mes = 1
año = año + 1
req = requests.post("http://localhost:3000/", json= ({"list":ret,"tipo":"socios"}))
NodeJs code
const server = http.createServer((req, res) => {
let data = []
req.on('data', chunk => {
data.push(chunk)
})
req.on('end', () => {
console.log("LLego pedido")
console.log(data.toString('utf8'))
jason = JSON.parse(data.toString('utf8')) //here breaks
//jason = JSON.parse(data) //also tried this
cupones = jason.list
tipo = jason.tipo
make(cupones, tipo).then(function() {
var file = fs.createReadStream('./document.pdf');
file.on('open', function () {
var stat = fs.statSync('./document.pdf');
res.statusCode = 200;
res.setHeader('Content-Length', stat.size);
res.setHeader('Content-Type', 'application/pdf');
file.pipe(res);
});
})
})});
Why are those commas coming up and how do it stop it?

ARP request without reply raw sockets python

I'm trying to get a arp reply after send ARP request but the reply is not comming.
I had a look to wireshark for the results and i think he does the broadcast to the network, but no reply show up...
In results of wireshark the MAC addr of sender and receiver is do not correspond to the real MAC addr, im bealive i'm not packing this right but i dont understand why.
need help...
#!/usr/bin/env python3
import struct
import socket
raw = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0806))
raw.bind(("wlp3s0", socket.htons(0x0806)))
mac_local = b"ff:ff:ff:ff:ff:ff" # mac de quem envia request
ip_local = "192.168.1.7" # ip de quem envia request
mac_dest = b"00:00:00:00:00:00" # mac de quem recebe request
ip_dest = "192.168.1.2" # ip de quem recebe request
# Ethernet Header
protocol = 0x0806 # 0x0806 protocol to ARP
ethernet_header = struct.pack("!6s6sH", mac_dest, mac_local, protocol)
# ARP header
type_hardware = 1
type_protocol = 0x0800 # IPV4
size_addr_hardware = 6 # Refere ao tamanho do endereço do MAC que é
48 bits == 6 bytes
size_addr_protocol = 4 # Refere ao tamanho do endereço do ipv4 que é
32 bits == 4 bytes
operation = 1 # 1 = request / 2 = Reply
source_ip = socket.inet_aton(ip_local)
dest_ip = socket.inet_aton(ip_dest)
arp_addr = struct.pack("!HHBBH6s4s6s4s", type_hardware, type_protocol,
size_addr_hardware, size_addr_protocol, operation,
mac_local, source_ip, mac_dest, dest_ip)
pkt = ethernet_header + arp_addr
cont = 0
while cont < 6:
raw.send(pkt)
cont +=1
enter image description here
enter image description here
mac_dest and mac_local are definitely not right. You've just created a byte string with the ASCII value. Each of those is 17 bytes long. And you're just taking the first 6 of those 17 bytes for each of the addresses.
They should be something like this instead:
mac_dest = b'\x00\x00\x00\x00\x00\x00'
mac_local = b'\xff\xff\xff\xff\xff\xff'
Check that the length of the byte string before the struct.pack call is exactly six bytes.
Also, not sure what you're trying to do, but I doubt it makes sense to use the all-zero hardware address as a destination address. Pretty sure no one will receive that as it would be a unicast to an address that no one has. The opposite might be helpful (send to the broadcast address from all-zero) -- I think that's standard for ARP probes.
I'm somehow confused about the accepted answer.
Is MAC 00:00:00: 00:00:00 not a valid MAC from XEROX?
https://hwaddress.com/company/xerox-corporation/
When I see ARP-request captured with e.g wireshark
then mac adresses in requests are always like
MAC_DST: FF:FF:FF:FF:FF:FF //mac broadcast
MAC_SRC: MAC-address of requester
the mac adresses in reply would then be
MAC_DST: MAC-adress of requester
MAC_SRC: MAC-address of replier

how to deal with strange chars in selenium? 'utf8' codec can't decode byte 0xc3 in position 0:

im trying to send keys with spanish accents in selenium, what im doing is sending strings via a array with various entrys, here is the line where it get stucks.
["Electrodomésticos", "Otros electrodomésticos", ["sensorhumo.jpg"], "Sensor de humo inalámbrico independiente.", "-Frecuencia: 433Mhz. -Codigo de trabajo: 2262. -Alacance inalámbrico: 80 mts con línea de vista. ", "59000", "x", "x", "x", "x", "x", "x"],
when i send this part:
"-Frecuencia: 433Mhz. -Codigo de trabajo: 2262. -Alacance inalámbrico: 80 mts con línea de vista. "
to this code:
descripcion=".//*[#id='field-description']"
descripciontext=str(array3[i][x])
x=x+1
descripcionelement = wait.until(lambda driver: driver.find_element_by_xpath(descripcion))
descripcionelement.send_keys(descripciontext)
it throws this message:
UnicodeDecodeError: 'utf8' codec can't decode byte 0xc3 in position 0:
unexpected end of data
it only works if i remove the accents from this part and i tried using decode.
I've stumbled with this error myself, when I was trying to send something like 'España' in a select option inside a form.
The accepted answer is right, the best approach is to send values in unicode.
I'll leave here a short easy code, that transforms the value that is sent, either str or unicode, in a transparent way
def _convert(param):
if isinstance(param, str):
return param.decode('utf-8')
else:
return param
# both examples will work
parameter = 'España'
driver_element.send_keys(_convert(parameter))
unicode_parameter = u'España'
driver_element.send_keys(_convert(parameter))
To handle unicode in selenium-sendkeys, unicode casting is needed, to convert bytes into unicode use one of the ways-
descripciontext = "-Frecuencia: 433Mhz. -Codigo de trabajo: 2262.
-Alacance inalámbrico: 80 mts con línea de vista."
Unicode (by manual): descripciontext = u"-Frecuencia: 433Mhz. -Codigo de trabajo: 2262. -Alacance inalámbrico: 80 mts con línea de vista."
Or
Unicode (by automatic decoding): descripciontext = unicode(descripciontext.decode("iso-8859-4"))
Now use send_keys
descripcionelement.send_keys(descripciontext)

Using asyncio to read the output of a serial port

I have been doing some port-reading for work, and I need to know if I should use asyncIO to read the data that comes in from this port.
Here's some details about the way in which the system is constructed.
Multiple sensors are being read at the same time and might produce output that goes in at the same time. (all data comes in through a probee ZU10 connected to a usb port) All data must be timestamped as soon as it comes in.
The data is supposed to be processed and then sent to a django webapp through a REST API.
The thing Is, it's really important not to lose any data, I'm asking about this because I believe there must be an easier way to do this than the one I'm thinking of.
The way I want the data to come in is through an asyncronous process that takes in the data into a queue and timestamps it, this way there is no way in which loss of data is present, and timestamping may be no more than a few fractions of a second off, which is not a problem.
If anyone has got any ideas I would be thankful for them
Here's the code I'm using to open the port, take the data in and what I've got so far on the actually reading the meaningful data.
Here's the reading part:
import serial #for port opening
import sys #for exceptions
#
#configure the serial connections (the parameters differs on the device you are connecting to)
class Serializer:
def __init__(self, port, baudrate=9600, timeout=.1):
self.port = serial.Serial(port = port, baudrate=baudrate,
timeout=timeout, writeTimeout=timeout)
def open(self):
''' Abre Puerto Serial'''
self.port.open()
def close(self):
''' Cierra Puerto Serial'''
self.port.close()
def send(self, msg):
''' envía mensaje a dispositivo serial'''
self.port.write(msg)
def recv(self):
''' lee salidas del dispositivo serial '''
return self.port.readline()
PORT = '/dev/ttyUSB0' #Esto puede necesitar cambiarse
# test main class made for testing
def main():
test_port = Serializer(port = PORT)
while True:
print(test_port.recv())
if __name__ == "__main__":
main()
And a bit of what I'm going to be using to filter out the meaningful reads (bear with it, it might be full of awful errors and maybe a terrible RegEx):
import re
from Lector import ChecaPuertos
from Lector import entrada
patterns = [r'^{5}[0-9],2[0-9a-fA-F] $'] #pattern list
class IterPat:
def __init__(self, lect, pat = patterns):
self.pat = pat # lista de patrones posibles para sensores
self.lect = lect # lectura siendo analizada
self.patLen = len(pat) #Largo de patrones
def __iter__(self):
self.iteracion = 0 #crea la variable a iterar.
def __next__(self):
'''
Primero revisa si ya pasamos por todas las iteraciones posibles
luego revisa si la iteración es la que pensabamos, de ser así regresa una
tupla con el patrón correspondiente, y la lectura
de otra forma para el valor de ser mostrado
'''
pattern = re.compile(self.pat[self.iteracion])
comp = pattern.match(self.lect)
if comp == True:
re_value = (self.pattern, self.lect)
return re_value
else:
self.iteración += 1
def main():
puerto = ChecaPuertos.serial_ports()
serial = entrada.Serializer(port = puerto[0])
if serial != open:
serial.open()
while True:
iter = IterPat()
#This is incomplete right here.
I am using asyncio to read/write a serial port with pyserial. I am having my device on the other end of the serial connection write a single byte when it is ready to receive a payload. Asyncio watches for that byte then sends the payload. It looks something like this:
serial_f = serial.Serial(port=dev, baudrate=BAUDRATE, timeout=2)
def write_serial():
status = serial_f.read(1)
serial_f.write(buffer)
loop = asyncio.get_event_loop()
loop.add_reader(serial_f.fileno(), write_serial)

Categories