Python - Ported AS2 function doesn't work - python

This game uses this encryption to stop people from being able to connect bots easily the function used by the game is:
function djinndecrypt(string, key) {
var crypt = "";
var part = "";
var parts = 0;
var keyGen = key.length;
for(var i = 0; i < string.length; i++) {
var char = string.charAt(i);
var chrNum = string.charCodeAt(i);
var keyChr = key.charAt(parts % key.length);
var keyNum = key.charCodeAt(parts % key.length);
part += char;
if((i+1) % 3 == 0 && i > 0) {
crypt += String.fromCharCode((coreHash.indexOf(part)+2) - keyNum - keyGen);
part = "";
parts++;
}
}
return crypt;
I have attempted to port this to python my code is:
coreHash = "4Qiqc3mpjw2jFLJBaV9ANsWoYDR8ktvZIMeJTfOd1lyH5P7XKxhU6rCbzuE10nS5Ks7rPj1YvnDlbX4m2jI0NkyOL3hHU6FRVduJJoCwfWiABzqSaETMet1pZ89xQc81ieHA0F5EuNnWCwJvMJLQhV3UxPYRB76pbfIy2dcoaT14XkqlZsSzj9KDtrmjO9fjdMPERB12TYzDJrNxc3QajKU0kbvu4F56yHAXWO7tlwni8mZqCSosLVIehJ1pzT1kEsSXAl1O45CdLnRwQeM06ZqxJfJayBN8FWj2prYjuKIhiHU7VbomDPvct935yULcOHNJZsa31DeSlmnPBxJkYbTdAFRotIizv2VpXuf9w0KqQ8Ehjr4MW7Cj164Y1ukWxp9EjOwDPF8rsX5vlZN7QJqfteCATKncUoLVaM16Shy";
def djinndecrypt(string, key):
crypt = ""
part = ""
parts = 0;
keyGen = len(key)
for i in xrange(len(string)):
char = string[i]
chrNum = ord(char)
keyChr = key[parts % len(key)]
keyNum = ord(keyChr)
part += char
if((i + 1) % 3 == 0 and i > 0):
crypt += chr((coreHash.find(part) + 2) - keyNum - keyGen)
part = ""
parts += 1
print crypt
djinndecrypt("zQDHzljoHM6RhuhuhWzQDA5dgOAzQDlbAqkgOA57mM", "69338277581336797325449966279465")
The code ends up raising an exception:
ValueError: chr() arg not in range(256)

chr() only accepts up to 255 as described by the error. You can get more distance using unichr() but that returns Unicode characters instead of ACSII like chr().
However, given that this is supposed to result in an English string, the problem appears to be in the coreHash, as results above 122 [ chr(122) is 'z' ] will be out of alphabetical range.

Related

Python read character

I would like to know how can I read the charaters into a buffer in Python?
In C code, I can easy decralare the buffer character like char buffer[256];:
void read_char(int x, char buffer[], int *flag_stop) {
int i, length;
char character;
i = 0;
bzero(buffer, 256);
do {
if ((length = read(x, &character, 1)) <= 0)
{
*flag_stop = 1;
break;
}
buffer[i] = character;
i++;
}
while(c != 0x0A);
}
But I don't know how to do in Python so the code is something like this:
def read_char(x,buffer,**flag_stop):
i = 0
buffer = np.array([], dtype='S64')
while True:
if os.read(x, character, 1) <= 0:
**flag_stop == 1
break
buffer[i] = str(character)
i=i+1
if(character != 0x0A):
break
I have tried with numpy.chararray but I did not work. Any idea for this problem? thank you very much!
Your main problem is that you want in Python write code exactly like in C.
Python would need something like this
def read_char(x):
flag_stop = False # or 0
i = 0
buffer = np.array([], dtype='S64')
while True:
character = os.read(x, 1)
if not character: # if len(character) < 0
flag_stop = True # or 1
break
buffer[i] = character
i += 1
if character != 0x0A:
break
return buffer, flag_stop
# ---
buffer, flag_stop = read_char(file_handler)
I don't like str() in your code - you may get single byte which is part of mulit-bytes code (like utf-8) and converting to str() can only mess it.

C++ equivalent of python's expandtabs() function?

I need to implement the C++ equivalent of the expandtabs() function. Can someone help me with converting this code to C++?
def expandtabs(string, n):
result = ""
pos = 0
for char in string:
if char == "\t":
# instead of the tab character, append the
# number of spaces to the next tab stop
char = " " * (n - pos % n)
pos = 0
elif char == "\n":
pos = 0
else:
pos += 1
result += char
return result
This is what I have:
std::string ExpandTabs(const std::string &str, int tabsize =4){
std::string ReturnString = str;
std::string result = " ";
int pos = 0;
for(std::string::size_type i = 0; i < ReturnString.size(); ++i) {
if (ReturnString[i] == '\t'){
int spaces = tabsize - pos % tabsize ;
ReturnString.append(" ", spaces);
pos = 0;
}
else{
pos+=1;
}
}
return ReturnString;
You need to build up the string character by character. Currently you assign str to ReturnString at the start of the function and then append whatever spaces you decide are necessary to the end of the string, instead of in place of the tabs.
There are no doubt more idiomatic ways to achieve the same result, but a like for like conversion of the python might look like.
#include <iostream>
#include <string>
std::string expand_tabs(const std::string &str, int tabsize=4)
{
std::string result = "";
int pos = 0;
for(char c: str)
{
if(c == '\t')
{
// append the spaces here.
result.append(tabsize - pos % tabsize, ' ');
pos = 0;
} else
{
result += c;
pos = (c == '\n') ? 0: pos + 1;
}
}
return result;
}
int main()
{
std::cout << expand_tabs("i\tam\ta\tstring\twith\ttabs") << '\n';
std::cout << expand_tabs("1\t2\t3\t4", 2) << '\n';
}
It basically steps through the input forwarding on any non tab characters to the result string, otherwise it adds the correct number of spaces to the result.
Output:
i am a string with tabs
1 2 3 4
A straight translation of the python code is problematic, since char cannot be both a string and a single character, but apart from that it's straightforward:
std::string expandtabs(std::string const&str, std::string::size_type tabsize=8)
{
std::string result;
std::string::size_type pos = 0
result.reserve(str.size()); // avoid re-allocations in case there are no tabs
for(c : str)
switch(c) {
default:
result += c;
++pos;
break;
case '\n':
result += c;
pos = 0;
break;
case '\t':
result.append(tabsize - pos % tabsize,' ');
pos = 0;
}
return result
}

i want to know how to convert decimal to binary

i have a question.
i don't know why my code is wrong
def binary_converter(decimal_number):
i = decimal_number
result = ''
while i >= 0 :
if i % 2 == 0:
result = result + "0"
i = i/2
else :
result = "1"
i = i/2
return result.strip()
it is my code. what is wrong?
There were few little mistakes in your code, olease refer to comments below for details:
def binary_converter(decimal_number):
if decimal_number==0: #corner case
return "0";
i = decimal_number
result = ""
while i>0: # while i >= 0 : //your loop was running indefinitely
if i % 2 == 0:
result = result + "0"
i = i//2 # i= i/2 was doing exact division for eg. 3/2=1.5 but 3//2=1
else :
result = result + "1" # there was a silly mistake here
i = i//2
return result[::-1].strip() # ans should be reversed before converting to integer

Find, replace and print out updated string

I am trying to create a python script that has 10-20 lines of fixed data in a string with 2 special character's that need to be replaced with a different, random string using randomword()
import random, string
def randomword(length):
letters = string.ascii_lowercase
return ''.join(random.choice(letters) for i in range(length))
junk = """
random_string1 = {};
random_string2 = {};
random_string3 = {};
random_string4 = {};
random_string5 = {};
"""
stra = string.replace(junk, '{}', randomword(40))
print (stra)
The two special characters in the string are {}, I would like to iterate through the string to find those characters and replace them with a different random string generated by randomword()
Above is as far as I got, this piece of code replaces all of the occurrences
of {} with a random string, but they have the same values, I would like to have differing values for each {}.
I don't know how to put this into a loop. Any help is appreciated.
use randint(97, 122)
import random
def randomword(length):
s = ""
for _ in range(length):
a = random.randint(97, 122)
s += chr(a)
return s
def replace(original_string, string_to_replace):
result_string = ""
while original_string.find(string_to_replace) >= 0:
pos = original_string.find(string_to_replace)
result_string += original_string[0: pos]
result_string += randomword(40)
next_pos = pos+2
original_string = original_string[next_pos:]
result_string += original_string[:]
return result_string
junk = """
random_string1 = {};
random_string2 = {};
random_string3 = {};
random_string4 = {};
random_string5 = {};
"""
stra = replace(junk, "{}")
print (stra)
Since you are already using the default placeholder for string formatting '{}', you can do:
>>> print(junk.format(*(randomword(40) for _ in range(junk.count('{}')))))
random_string1 = lazbdzezssemtsfknajawriafozpjwizigykvmac;
random_string2 = pxhkyrnjiqsvcivcppqqpbwuocsvbfauygdrwpuj;
random_string3 = ewhrsryjtfwtmulmqfqxzrzvyspiefrddpzrxkvq;
random_string4 = sqiulddoevddtieymjiexnmzezrdayvwigmsmgld;
random_string5 = evscqvrccknkulpkqchodcjlognsnrcxqcsexnrv;
Could use regex:
>>> print(re.sub('{}', lambda _: randomword(40), junk))
random_string1 = emgdidmmghkunqkwdfcnvsffdnfhvqrybhqdfklh;
random_string2 = mgggwchtzpuhntnfxzpsmkarkwnlghcwicnvxmpt;
random_string3 = liemdzegmzfpuozktclxnmfmavjkaxqhrfaldqkn;
random_string4 = ugchyijmsvzmeaiyzyaiudrnnfskzdboukvdwiye;
random_string5 = rfazvtvhygfixielqzbuhlnzvjjtrkhsdetomjri;

Idiomatic way to port C bitfiddling to Python

How would you port the following C code in a Pythonic way (especially the bit fiddling part in Get2, Get3, ...)
switch(mem[pos-1])
{
...
case 0x10: pos+=Get2(&mem[pos+0x02])+0x04; break;
case 0x11: pos+=Get3(&mem[pos+0x0F])+0x12; break;
case 0x16: pos+=Get4(&mem[pos+0x00])+0x04; break;
...
case 0x20: pos+=0x02; break;
}
...
//////////////////////////////////////////////////////////
// Conversion routines to fetch bytes in Big Endian order
//////////////////////////////////////////////////////////
unsigned int Get2(unsigned char *pointer)
{
return (pointer[0] | (pointer[1]<<8));
}
unsigned int Get3(unsigned char *pointer)
{
return (pointer[0] | (pointer[1]<<8) | (pointer[2]<<16));
}
unsigned int Get4(unsigned char *pointer)
{
return (pointer[0] | (pointer[1]<<8) | (pointer[2]<<16) | (pointer[3]<<24));
}
This is what I've got so far:
x = struct.unpack('B', mem[pos-1])[0]
if x == 0x10:
# pos += ???
continue
if x == 0x11:
# pos += ???
continue
if x == 0x16:
# pos += ???
continue
if x == 0x20:
pos += 0x02
continue
If you're just getting one unsigned byte, just do
x = ord(mem[pos - 1])
on Python 2 or
x = mem[pos - 1]
on Python 3.
Instead of select / case, You want a dictionary.
positions = {0x10: do_10, 0x11: do_12, 0x16: do_16}
Where do_10 etc. are functions:
def do_10(pos):
# This actually would need an endianness character
return struct.unpack('H', mem[pos + 0x02])[0] + 0x04
You use it like this:
pos += positions[mem[pos - 1]](pos)
If you want to define the functions right in the dictionary, you can:
positions = {
# This actually would need an endianness character
0x10: (lambda pos: struct.unpack('H', mem[pos + 0x02])[0] + 0x04)
# ...
}
This is a guess, but based on your code, I think this is what you're looking for:
x = struct.unpack('B', mem[pos-1])[0]
if x == 0x10:
pos += 0x04 + struct.unpack('>h' mem[pos+0x04])
elif x == 0x11:
pos += 0x12 + (0x00FFFFFF & struct.unpack('>i' mem[pos+0x0F]))
elif x == 0x16:
pos += 0x04 + struct.unpack('>i' mem[pos])
elif x == 0x20:
pos += 0x02
Your four bit-fiddlers could almost transliterated in python
def bigstr_to_int2(str) :
return (ord(str[0])<<8) | ord(str[1])
Seems to work, but is perhaps not "idiomatic". Ideally, you should try to use the struct.unpack to do the whole thing in bulk, but I can't tell you how to do that, because I don't understand the main function up the top.

Categories