Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - _TTFH_3500

#1
Hola, tengo un archivo que fue comprimido con zlib y estoy tratando de averiguar el método que fue utilizado para comprimirlo.

Este archivo en particular usa un nivel 9 de compresión, y por lo que pude descifrar la entrada se divide en bloques de 8KiB, y se hace Z_SYNC_FLUSH luego de comprimir cada bloque, pero cada 8 bloques el algoritmo parece hacer otra cosa.

Este es el código que escribí para descomprimir y comprimir el archivo.
Para descomprimir funciona bien, pero solo comprime correctamente los primeros 7 bloques del archivo.
Código (python) [Seleccionar]
import sys
import zlib

# python3 zlib-flate.py -d output.bin input.bin
# python3 zlib-flate.py -9 input.bin output_test.bin

def usage():
print("Usage:")
print(f"python3 {sys.argv[0]} -[1-9,d] input.bin output.bin")
exit()

def main():
argc = len(sys.argv)
if argc != 4:
usage()
try:
if sys.argv[1] == "-d":
# Decompress file
with open(sys.argv[2], "rb") as input_file, open(sys.argv[3], "wb") as output_file:
data = input_file.read()
comp_obj = zlib.decompressobj()
data_plain = comp_obj.decompress(data)
output_file.write(data_plain)
else:
# Compress file
level = -int(sys.argv[1])
if level < 1 or level > 9:
print("Invalid compression level")
with open(sys.argv[2], "rb") as input_file, open(sys.argv[3], "wb") as output_file, open("output.bin", "rb") as test_file:
comp_obj = zlib.compressobj(level)
data = input_file.read(8 * 1024) # Read block of 8KiB
i = 1
while data != b"":
data_zip = comp_obj.compress(data)
data_zip += comp_obj.flush(zlib.Z_SYNC_FLUSH)

# Check if compressed data differs
lenght = len(data_zip)
data_test = test_file.read(lenght)
if data_zip == data_test:
print(f"Block #{i}: correctly compressed")
else:
print(f"Block #{i}: invalid data")
exit()

output_file.write(data_zip)
data = input_file.read(8 * 1024)
i = i + 1
print("File compressed correctly!")
except (IOError, ValueError) as error:
print("Invalid parameters")

main()


Archivo comprimido con zlib:
https://mega.nz/file/8a5C1SyQ#xqy9nCycTrWfrnwuvWa39xd128s9huSFuf8kOr6kK8Q

#2
Siempre quise hacer un programa que dado un numero lo imprima como texto, por ejemplo 132 -> ciento treinta y dos, pero nunca me puse, hasta hoy que vi gramáticas de cláusulas definidas en programación lógica y en poco más de media hora salió.
Los casos más difíciles de hacer fueron por ejemplo 16 (dieciséis), 21 (veintiuno) que son una única palabra y 1002 (mil dos) que no es "un mil dos" o "uno mil dos".
Como no chequeo que el resto sea distinto de cero pueden generarse casos como "40 -> cuarenta y cero" o "41 -> cuarenta y cero y uno, cuarenta y cero... y cero y uno" que son quitados con el operador cut (!).
Les dejo acá el código y algunos ejemplos.
17 diecisiete
29 veintinueve
547 quinientos cuarenta y siete
1234 mil doscientos treinta y cuatro
3597426 tres millones quinientos noventa y siete mil cuatrocientos veintiséis
742258963 setecientos cuarenta y dos millones doscientos cincuenta y ocho mil novecientos sesenta y tres
100000000000 cien mil millones
999999999999 novecientos noventa y nueve mil novecientos noventa y nueve millones novecientos noventa y nueve mil novecientos noventa y nueve
1000000000000 un billon
31000 treinta y uno mil*
* Y aquí encontré un bug, debería decir treinta y un mil

Código (bash) [Seleccionar]

% Imprime un numero como texto
print_number(N) :- numero(N, L, []), !, atomic_list_concat(L, ' ', A), writeln(A).

% Crea una lista [0..N]
create_list(N, L) :- findall(X, between(0, N, X), L).

% Imprime los numeros entre 0 y N
print_numbers(N) :- create_list(N, L), print_aux(L).
print_aux([]).
print_aux([X|L]) :- print_number(X), print_aux(L).

% Convierte un numero en una lista de palabras
% ej: numero(132, L, []) -> [ciento, treinta, y, dos].
numero(0) --> [cero].
numero(1) --> [uno].
numero(2) --> [dos].
numero(3) --> [tres].
numero(4) --> [cuatro].
numero(5) --> [cinco].
numero(6) --> [seis].
numero(7) --> [siete].
numero(8) --> [ocho].
numero(9) --> [nueve].

numero(10) --> [dies].
numero(11) --> [once].
numero(12) --> [doce].
numero(13) --> [trece].
numero(14) --> [catorce].
numero(15) --> [quince].

numero(20) --> [veinte].
numero(30) --> [treinta].
numero(40) --> [cuarenta].
numero(50) --> [cincuenta].
numero(60) --> [sesenta].
numero(70) --> [setenta].
numero(80) --> [ochenta].
numero(90) --> [noventa].
numero(100) --> [cien].

% Convertir numeros entre 16 y 19
numero(N) --> {N > 15, N < 20, U is N mod 10, numero(U, X, []), atomic_list_concat([dieci|X], S)}, [S].
% Convertir numeros entre 21 y 29
numero(N) --> {N > 20, N < 30, U is N mod 10, numero(U, X, []), atomic_list_concat([veinti|X], S)}, [S].
% Convertir numeros entre 31 y 99
numero(N) --> {N > 30, N < 100, D is N - (N mod 10), U is N mod 10}, numero(D), [y], numero(U).

numero(200) --> [doscientos].
numero(300) --> [trescientos].
numero(400) --> [cuatrocientos].
numero(500) --> [quinientos].
numero(600) --> [seiscientos].
numero(700) --> [setecientos].
numero(800) --> [ochocientos].
numero(900) --> [novecientos].
numero(1000) --> [mil].

% Convertir numeros entre 101 y 199
numero(N) --> {N > 100, N < 200, D is N mod 100}, [ciento], numero(D).
% Convertir numeros entre 201 y 999
numero(N) --> {N > 200, N < 1000, C is N - (N mod 100), D is N mod 100}, numero(C), numero(D).

% Convertir numeros entre 1001 y 1999
numero(N) --> {N > 1000, N < 2000, D is N mod 1000}, [mil], numero(D).
% Convertir numeros entre 2000 y 999 000 que terminan en 000, ej: 7000
numero(N) --> {N >= 2000, N =< 999000, C is N div 1000, D is N mod 1000, D = 0}, numero(C), [mil].
% Convertir numeros entre 2001 y 999 999
numero(N) --> {N > 2000, N < 1000000, C is N div 1000, D is N mod 1000}, numero(C), [mil], numero(D).

numero(1000000) --> [un, millon].

% Convertir numeros entre 1 000 001 y 1 999 999
numero(N) --> {N > 1000000, N < 2000000, D is N mod 1000000}, [un, millon], numero(D).
% Convertir numeros entre 2 000 000 y 999 999 000 000 que terminan en 000 000, ej: 7 000 000
numero(N) --> {N >= 2000000, N =< 999999000000, C is N div 1000000, D is N mod 1000000, D = 0}, numero(C), [millones].
% Convertir numeros entre 2000001 y 999 999 999 999
numero(N) --> {N > 2000000, N < 1000000000000, C is N div 1000000, D is N mod 1000000}, numero(C), [millones], numero(D).

numero(1000000000000) --> [un, billon].


Para ejecutar instalan SWI-Prolog
Guardan el código como "numtext.pl"
Abren cmd en el directorio donde guardaron el archivo
> swipl numtext.pl
?- print_number(N). # donde N es el número a mostrar
#3
Ok, encontre el error, las imagenes no terminan con un salto de linea. Primero se envia un HTTP request con el tamaño del archivo y luego los datos del archivo.

Código (cpp) [Seleccionar]
void* pushData(void* args) {
sockets* src_dst = (sockets*)args;
int src = src_dst->source;
int dst = src_dst->dest;
char* data = new char[1048576];
while (true) {
strcpy(data, "");
int msg_size = recv(src, data, 1048576, 0);
if (msg_size > 0) {
printf("%d->%d Reenviando %d bytes\n", src, dst, msg_size);
send(dst, data, msg_size, 0);
}
}
delete (sockets*)args;
delete[] data;
close(src);
close(dst);
return NULL;
}
#4
Programación C/C++ / Ayuda con HTML Proxy en C
11 Febrero 2020, 17:39 PM
Supongamos que tengo una página web en un servidor Apache corriendo en 192.168.1.1:80 y quiero acceder a él desde 127.0.0.1:8080 (las ip y puertos son solo de ejemplo).

El siguiente programa me muestra la página pero las imágenes no cargan, tampoco puedo hacer login. No se que es lo que tengo mal.

Código (cpp) [Seleccionar]
// g++ -Wall -Werror tcp_proxy.cpp -o tcp_proxy -lpthread -lws2_32

#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <winsock2.h>
#include <ws2tcpip.h>

#define Localhost "127.0.0.1"
#define ProxyPort 8080
#define HTTP_Server "192.168.1.1"
#define HTTP_Port "80"

#define MaxUsersQueue 10
#define MaxMsgSize 2048

struct sockets {
int source;
int dest;
};

void* conectarProxy(void*);
void* pushData(void*);

int main(int argc, char* argv[]) {
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);

int proxy_socket = socket(AF_INET, SOCK_STREAM, 0);

sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = inet_addr(Localhost);
if (argc < 2)
server_addr.sin_port = htons(ProxyPort);
else // Usar puerto pasado desde la terminal
server_addr.sin_port = htons(atoi(argv[1]));

int server_addr_size = sizeof(server_addr);
bind(proxy_socket, (sockaddr*) &server_addr, server_addr_size);

listen(proxy_socket, MaxUsersQueue);

while (true) {
sockaddr_in client_addr;
int client_addr_size = sizeof(client_addr);
int socket_client = accept(proxy_socket, (sockaddr*) &client_addr, &client_addr_size);

pthread_t hilo_conectarProxy;
pthread_create(&hilo_conectarProxy, NULL, conectarProxy, &socket_client);
}
close(proxy_socket);
return 0;
}

void* conectarProxy(void* sc_param) {
int socket_client = *((int*)sc_param);

int httpServerSock = socket(AF_INET, SOCK_STREAM, 0);
addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
addrinfo* res;
getaddrinfo(HTTP_Server, HTTP_Port, &hints, &res);
connect(httpServerSock, res->ai_addr, res->ai_addrlen);
freeaddrinfo(res);

sockets* cliente_proxy = new sockets{socket_client, httpServerSock};
pthread_t hilo_cliente_proxy;
pthread_create(&hilo_cliente_proxy, NULL, pushData, cliente_proxy);

sockets* proxy_cliente = new sockets{httpServerSock, socket_client};
pthread_t hilo_proxy_cliente;
pthread_create(&hilo_proxy_cliente, NULL, pushData, proxy_cliente);

pthread_join(hilo_cliente_proxy, NULL);
pthread_join(hilo_proxy_cliente, NULL);
return NULL;
}

void* pushData(void* args) {
sockets* src_dst = (sockets*)args;
int src = src_dst->source;
int dst = src_dst->dest;
char* data = new char[MaxMsgSize];
char buffer[MaxMsgSize];
while (true) {
strcpy(data, "");
strcpy(buffer, "");
int msg_size = 0;
do {
msg_size += recv(src, buffer, MaxMsgSize, 0);
if (msg_size == 0) break;
if (msg_size == -1) break;
printf("%d->%d Recibido: %d bytes\n", src, dst, msg_size);
strcat(data, buffer);
} while (strchr(data, '\n') == NULL);
if (msg_size == -1) break;
int sent_msg_size = send(dst, data, msg_size, 0);
printf("%d->%d Enviado: %d bytes\n", src, dst, msg_size);
if (sent_msg_size == -1) break;
}
delete (sockets*)args;
delete[] data;
close(src);
close(dst);
return NULL;
}
#5
Hola, ANSI X9.23 es una forma bastante sensilla de padding, simplemente agrega ceros y la cantidad de ceros que agregaste hasta completar un multiplo del tamanio del bloque.

CitarIn ANSI X9.23, between 1 and 8 bytes are always added as padding. The block is padded with zeros and the last byte of the block is set to the number of bytes added.
Example: In the following example the block size is 8 bytes, and padding is required for 4 bytes (in hexadecimal format)

... | DD DD DD DD DD DD DD DD | DD DD DD DD 00 00 00 04 |


En cuanto al algoritmo de cifrado puedes inventar uno basado en AES con un tamanio de clave distinto.
#6
Hardware / Re: pregunta sobre procesadores???
7 Julio 2019, 23:52 PM
Depende de la laptop, en el 99.9% de los casos el socket es BGA (Ball Grid Array) y esta soldado a la placa base por lo que es practicamente imposible de cambiar el procesador.
Salvo en algunas excepciones el socket es PGA (Pin Grid Array) o LGA (Land Grid Array) y si es posible cambiarlo de igual forma que en las PC de escritorio.
Para saber el tipo de socket si tienes un procesador Intel vas a ark.intel.com buscas el modelo de procesador y si en Sockets Soportados dice algo que contenga BGA (ej: FCBGA1356) es porque esta soldado.
#7
Puedes usar guion bajo siempre que no este al comienzo o hallan dos seguidos.
MAL:
int _numero;
int un__numero;
int __ARRAY_
BIEN:
int un_numero;
int esto_es_una_variable;
int estoTambien;

C++ implementa los siguientes metodos... a veces, no estoy seguro de cuando, depende de si una clase hereda de otra, es virtual o virtual pura, usa un template, etc. Igual no importa mucho, si lo usas y te da error al compilar entonces no esta definido y tienes que implementarlo vos, si te da error en la ejecucion quizas lo implemento y no hace lo que quieres y tienes que redefinirlo*.

Código (cpp) [Seleccionar]

class array {
private:
  int inicio, tamanio;
  int* datos;
public:
  // Constructor por defecto (sin parametros):
  array();
  // Constructor por copia
  array(const array&);
  // Constructor por movimiento
  array(array&&);
  // Operador de asignacion
  array operator=(const array&);
  // Operador de asignacion por movimiento
  array& operator=(array&&);
  // Destructor
  ~array();

  // NO implementa otros constructores
  array(int, int, int*);
  // NO implementa la comparacion
  bool operator==(const array&);
  bool operator<=(const array&);
};


*
Código (cpp) [Seleccionar]

// Lo que hace por defecto
array::array(const array& arr) {
  start = arr.start;
  size = arr.size;
  data = arr.data;
}

// Lo que tu quieres que haga
array::array(const array& arr) {
  start = arr.start;
  size = arr.size;
  data = new int[size];
  for (int32_t i = 0; i < size; i++)
    data[i] = arr.data[i];
}


#8
C++ crea de forma implicita un contructor por defecto (sin parametros) y sobrecarga el operando de asignacion en el caso de que la clase sea bastante trivial, es decir implementa lo siguiente a partir de tu codigo:

Código (cpp) [Seleccionar]

class s {
private:
int x;
public:
s() { x = 0}
s(int x1) { x = x1; }
s operator=(int x1) { x = x1; return *this; }
void p() const { std::cout << x; }
int getx() const { return x; }
};


La linea s t = 6; en el main llama al constructor por defecto s() y pone x = 0, luego llama s.operator=(6) y pone x = 6

Otra cosa que no tiene que ver con tu pregunta, NUNCA pongas uno o dos guion bajo al principio del nombre de una variable en C++, esos nombres estan reservados para las librerias del lenguaje y es una mala practica de programacion que deriva de los lenguajes no case-sensitive como Visual Basic donde para diferenciar User y user escribes _user.

Citar"Don't overlegislate naming, but do use a consistent naming convention: There are only two must-dos: a) never use "underhanded names," ones that begin with an underscore or that contain a double underscore;" (p2 , C++ Coding Standards, Herb Sutter and Andrei Alexandrescu)

#9
Como crear conjunto a partir de lista de tuplas por clave?
Por ejemplo tengo la siguiente lista de tuplas
Código (python) [Seleccionar]
x = [('El', 'auto'), ('el', 'auto'), ('un', 'auto'), ('algun', 'auto'), ('Los', 'camiones'),  ('UN', 'auto')]

Y quiero obtener la siguiente:
Código (python) [Seleccionar]
y =  [('el', 'auto'), ('Los', 'camiones')]
En lugar de "el" podria estar cualquiera de los determinantes usados anteriormente.

He intentado usar set() pero no se como hacer para que tome solo el segundo parametro para crear el conjunto.

He implementado el siguiente codigo pero es muy ineficiente, basicamente busca todas las ocurrencias para quedarse con una sola.

Código (python) [Seleccionar]

    nombres = [('El', 'auto'), ('el', 'auto'), ('un', 'auto'), ('El', 'camion')]
    pares = []
    palabras = list(set(x[1] for x in nombres))
    for i in range(0, len(palabras)):
        j = [det[0] for det in nombres if det[1] == palabras[i]]
        pares = pares + [(j[0], palabras[i])]
    print(pares)
#10
Código (cpp) [Seleccionar]
#include <random>
#include <cstdio>
#include <stdexcept>

class Vehiculo {
public:
  virtual ~Vehiculo() { }; // Clase abstracta
};

class Automovil : public Vehiculo {
public:
  int matricula = 4409;
};

class Bicicleta : public Vehiculo {
public:
  int cambios = 18;
};

void MostrarAtrb(const Vehiculo& vehiculo) {
  try {
    const Automovil& car = dynamic_cast<const Automovil&>(vehiculo);
    printf("Es un Automovil con matricula: %d\n", car.matricula);
  } catch(std::bad_cast &e) {
    printf("Error %s\n", e.what());
  }
  try {
    const Bicicleta& bici = dynamic_cast<const Bicicleta&>(vehiculo);
    printf("Es una Bicicleta con %d cambios\n", bici.cambios);
  } catch(std::bad_cast &e) {
    printf("Error %s\n", e.what());
  }
}

int main() {
  Vehiculo vehiculo;
  if (rand() % 2 == 0)
    vehiculo = Automovil();
  else
    vehiculo = Bicicleta();
  MostrarAtrb(vehiculo); // Como se de que tipo se creo el objeto???
  return 0;
}


Ambas conversiones de tipo dan error.