Friday 22 December 2017

0x47 binary options


Manipulação de dados binários em PHP com pack () e unpack (). Este blogpost foi publicado há mais de dois anos. Isso é muito tempo no mundo do desenvolvimento A história aqui pode não ser relevante, completa ou segura. Código pode não ser completa ou obsoleto, e até mesmo minha visão atual pode ter (completamente) mudou sobre o assunto. Então, por favor, leia mais, mas use-o com cautela. Hoje em dia a maioria de funcionalidade lowlevel como ler ou escrever gráficos são levados em conta bibliotecas de terceiros e thats ok. Sua maneira complicada de fazer as coisas direito e você provavelmente quer se concentrar em outputting ou enviar um PNG em vez de uma construção a partir do zero. Enquanto lendo e escrevendo este tipo de dados binários era normalmente feito em linguagens como C ou mesmo assembler, a maioria das linguagens de alto nível ainda têm esses recursos e sim, até mesmo o PHP Meet pack () e unpack (). A maioria das pessoas nem quer saber sobre como as coisas são feitas internamente e nem quer saber como uma bola de tar é parecida, ou como um arquivo PNG armazena suas paletas de cores. No entanto, se você é como eu, então você é curioso o suficiente e quer saber. Então, hoje eu vou mostrar-lhe como ler um arquivo PNG diretamente do disco e exibir as informações que está escondido atrás da imagem. Mesmo pode dizer-lhe um truque de otimização ou dois, entretanto :-) Primeiras coisas primeiro: pack () e unpack (). Ao lidar com dados binários em PHP, existem 2 funções principais que você não pode viver sem. As funções pack () e unpack () tomam uma seqüência (binária) e as convertem em uma matriz. Ambos trabalham mais ou menos da mesma maneira. Pack () irá armazenar uma matriz de volta para uma estrutura binária, enquanto unpack () fará o oposto. Se você escrever binarystring para um arquivo, seria 8 bytes de comprimento: 4 bytes para o comprimento (uma vez que seu valor de 32 bits), 3 bytes para o ascii aBc, 1 byte para cr e 1 byte para lf Com descompactar você tem que Adicione a chave, pois a saída é uma matriz associativa. Dê uma olhada ao redor no manual php para obter mais informações sobre pack () / unpack (). Formato PNG: O formato binário para arquivos PNG está disponível na internet. Ao visualizar um arquivo PNG em um visualizador ou editor hexadecimal, você verá que os primeiros 8 bytes são sempre os mesmos. O primeiro byte é sempre 0x89. Segundo a 4o byte são as letras PNG (ou em hexadecimal: 0x50 0x4E 0x47) 5º e 6º são os bytes 0x0d e 0x0a, o que representa uma linha DOS terminando em 7º e 8º bytes são 0x1a e 0x0a Então para verificar se um arquivo é Um PNG válido, precisamos fazer o seguinte: abrir o arquivo (como binário) ler os primeiros 8 bytes descompactar os bytes verificar se todas as entradas são o que esperamos abrir o arquivo (como binário): observe o b nas opções do arquivo. Isto irá certificar-se de que o ficheiro é aberto no modo binário. Leia os primeiros 8 bytes: os dados conterão uma string binária. Você não pode realmente lê-lo, então temos que descompactar os dados dele: Isso criaria uma matriz de cabeçalho com a seguinte informação: como você pode ver, a primeira entrada (highbit) é 137, que é o mesmo que 0x89. A assinatura é uma string normal com PNG e outros caracteres devem ser os mesmos que acima. Como exemplo, ele verifica se o highbit é realmente 0x89 e verifica o singnature para PNG. Você deve verificar os outros também .. Após o PNG cabeçalho, você obtém blocos de dados chamados pedaços. Cada pedaço é formatado da mesma maneira: 4 bytes. Comprimento do bloco 4 bytes. Tipo de bloco N bytes. Dados de bloco 4 bytes. Chunk CRC Antes de ler os dados do pedaço, devemos ler o comprimento do pedaço. Então a primeira coisa que fazemos é ler os primeiros 8 bytes (ou 2 dwords na verdade): Agora o número de bytes de dados são conhecidos para que possamos lê-los também: finalmente: lemos o código CRC e adicioná-lo à matriz chunk: Reading Todos os pedaços Ao ler um pedaço, você pode lê-los todos. Dependendo do tipo de pedaço, você pode realmente descompactar os dados e exibir ou usar essa informação também. Otimização Eu disse que estava compartilhando um truque de otimização no começo. Então aqui está: Como você pode ter visto, PNGs têm um monte de pedaços adicionais com eles. Incluindo coisas como a última vez que foi escrito e um monte de pedaços de texto. Uma vez que esses pedaços não são necessários para exibir o PNG corretamente, e eles só ocupam espaço, você poderia escrever um programa que remove esses pedaços do PNG. Especialmente com PNGs pequenos, isso pode economizar até 50 do tamanho do arquivo. Este é um truque que a maioria dos compressores de imagem usará para conseguir imagens de tamanho menor sem alterar até 1 byte na imagem real. Neat huh Os dados binários são tratados de forma diferente dependendo da sua CPU. A maioria das CPUs hoje em dia usa little-endian (intels x86 por exemplo), mas ainda há big-endian cpus lá fora (68000, powerpcs etc). Ao ler uma palavra ou dword a partir de dados binários, certifique-se de saber em que endian os dados são gravados caso contrário você pode acabar com dados incorretos. Especialmente quando você deseja escrever dados binários, certifique-se de pensar em tudo. As coisas podem ficar muito complicadas e miswriting um único byte vai corromper toda a sua imagem. Há um monte de bibliotecas lá fora, que pode fazer essas coisas muito melhor do que você nunca vai. Mas isso não deve impedi-lo para tentar de qualquer maneira :-) basE91 introdução de codificação basE91 é um método avançado para codificar dados binários como caracteres ASCII. É semelhante a UUencode ou base64, mas é mais eficiente. A sobrecarga produzida pelo basE91 depende dos dados de entrada. Ele é no máximo de 23 (versus 33 para base64) e pode variar até 14, o que normalmente ocorre em blocos de 0 bytes. Isso torna o basE91 muito útil para transferir arquivos maiores em conexões binárias inseguras como e-mail ou linhas de terminal. Alfabeto Como o nome sugere, basE91 precisa de 91 caracteres para representar os dados binários codificados em ASCII. A partir dos 94 caracteres ASCII imprimíveis (0x21-0x7E), os três seguintes foram omitidos para construir o alfabeto basE91: A tabela de tradução é composta dos caracteres restantes, como mostrado abaixo. Descriç~ao Pack fornece argumentos em uma seqüência binária de acordo com o formato. A idéia para esta função foi tirada do Perl e todos os códigos de formatação funcionam da mesma forma que no Perl. No entanto, existem alguns códigos de formatação que estão em falta, tais como código de formato Quotuquot Perl039s. Observe que a distinção entre valores assinados e não assinados afeta somente a função unpack (). Onde como function pack () dá o mesmo resultado para os códigos de formato assinados e não assinados. Parâmetros A string de formato consiste em códigos de formato seguidos por um argumento de repetidor opcional. O argumento do repetidor pode ser um valor inteiro ou para repetir até o fim dos dados de entrada. Para a, A, h, H a contagem de repetição especifica quantos caracteres de um argumento de dados são tomados, pois é a posição absoluta onde colocar os dados seguintes, para tudo o resto a contagem de repetição especifica quantos argumentos de dados são consumidos e embalados Na cadeia binária resultante. Os formatos atualmente implementados são: Uma classe auxiliar para converter inteiro em seqüências binárias e vice-versa. Útil para escrever e ler inteiros de / para arquivos ou soquetes. Classe inthelper public static function int8 (i) retorno isint (i). Embalagem (c i). Descompactar (c. I) 1 função estática pública uInt8 (i) return isint (i). Embalagem (C. i). Descompactar (C. i) 1 função pública estática int16 (i) return isint (i). Embalagem (s. I). Desempacotar (s. I) 1 função pública estática uInt16 (i. endianness false) f isint (i). pacote. Descompactar o retorno isarray (i). I 1. I função estática pública int32 (i) return isint (i). Embalagem (I.1). Descompactar (l. I) 1 função estática pública uInt32 (i. Endianness false) f isint (i). pacote. Descompactar o retorno isarray (i). I 1. I public static function int64 (i) retorno isint (i). Embalagem (q.1). Descompactar (q. I) 1 função estática pública uInt64 (i. Endianness false) f isint (i). pacote. Descompactar o retorno isarray (i). I 1. I gt Exemplo de uso: ltphp Header (Content-Type: text / plain) include (inthelper. php) echo inthelper. UInt8 (0x6b). PHPEOL // k eco inthelper. UInt8 (107). PHPEOL // k eco inthelper. UInt8 (x6b). PHPEOL. PHHEOL // 107 inthelper de eco. UInt16 (4101). PHPEOL // x05x10 inthelper de eco. UInt16 (x05x10). PHTOOL // 4101 inthelper de eco. UInt16 (x05x10. Verdadeiro). PHPEOL. PHPEOL // 1296 inthelper de eco. UInt32 (2147483647). PHPEOL // xffxffxffx7f eco inthelper. UInt32 (xffxffxffx7f). PHPEOL. PHPEOL // 2147483647 // Observação: Teste isto com a compilação de 64 bits do PHP echo inthelper. UInt64 (9223372036854775807). PHPEOL // xffxffxffxffxffxffxffx7f echo inthelper. UInt64 (xffxffxffxffxffxffxffx7f). PHPEOL. PHPEOL // 9223372036854775807 Coders exemplo é basicamente uma explicação de bindec () e decbin (), não pack () e unpack (). Heres algum código para converter uma expressão de cadeia binária em seu equivalente de cadeia binária e vice-versa. (Seria ainda mais simples se o pacote / desempacotar oferecido código de formato ab.) Função ltphp bin2bstr (entrada) // Converter uma expressão binária (por exemplo, 100111) em uma cadeia binária if (isstring (entrada)) return null // Sanity check / / Pack em um pacote de retorno de string (H. baseconvert (entrada 2. 16)) função bstr2bin (entrada) // Representação binária de uma seqüência binária if (isstring (entrada)) return null // Verificação de sanidade // Descompactar como um valor de cadeia hexadecimal descompactar (H. entrada) // saída binária baseconvert representação retorno (valor 1, 16. 2) // Retorna string (3) vardump ABC (bin2bstr (01000001 01000010 01000011)) // Retorna string (24) 010000010100001001000011 vardump (bstr2bin (ABC)) gt Mesmo que em um intval 64-bit architecure (6123456789) 6123456789, e sprintf (b, 5.000 milhões) 100101010000001011111001000000000 pacote não vai tratar nada passado para ele como de 64 bits. Se você quer embalar um inteiro de 64-bit: ltphp grande 5000000000 deixou 0xffffffff00000000 direito l 0x00000000ffffffff (big amp esquerda) gtgt 32 r grande amp certo bom pacote (NN l r..) StrReplace urlsafe (array (/), array (. . -), base64encode (bom)) // reconstruir: strReplace unurl (array (-), array (/), urlsafe) base64decode binário (unurl) definir descompactar (N2 tmp) printr (set) conjunto original 1 ltlt... 32 set 2 echo original. Rn gt resulta em: Array (1 gt 1 2 gt 705032704) 5000000000 mas apenas em uma máquina de 64 bits habilitado e PHP distro. Essas duas funções permitem a conversão entre seqüência binária e inteiro assinado com possibilidade de dar o comprimento do bit. Uso: ltphp echo si2bin (- 10. 32) 11111111111111111111111111110110 echo si2bin (10. 32) 00000000000000000000000000001010 echo bin2si (11111111111111111111111111110110. 32) - 10 echo bin2si (00000000000000000000000000001010. 32) 10 // assinado inteiro para si2bin função binária (si bits de 32. ) Se (si gt - pow (2. bits - 1) e si lt pow (2. bits - 1)) if (si gt 0) // positivo ou zero baseconvert (si. Bits bit binlength strlen (bin) se (binlength lt bits) bin strrepeat (0. bits - binlength). Bin else // negativo si - si - pow (2. bits) bin baseconvert (si. 10.2) binlength strlen (bin) se (binlength gt bits) bin strrepeat (1. bits - binlength). Bin retorna bin // binário para assinado integer função bin2si (bin bits 32) se (strlen (bin) bits) se (substr (bin 0. 0) 0) // positivo ou zero si baseconvert (bin. ) Else // negativo si baseconvert (bin 2. 10) si - (pow (2. bits) - si) retorna se gt Isso é como eu usei o pacote para converter base2 para base64 desde baseconvert não suporta base64 As conversões de base não funcionam Para cadeias longas, razão pela qual eu converter 1 byte em um tempo Espero que isso ajude alguém função base2to64 (base2) se (restbits strlen (base2) 8) base2. Strrepeat (0,8-permanece) base64 NULL para (i0iltstrlen (base2) i8) base16. sprintf (02x, bindec (sprintf (08D, substr (base2, i, 8)))) return base64encode (pacote (H, base16)) função base64to2 lista (base 64) (base16) descompactar (H0, base64decode (base64)) base2 NULL para (i0iltstrlen (base16) i) base2. Sprintf (04d, baseconvert (substr (base16, i, 1), 16,2)) return base2 Use igbinary-serialize se você não se importa um pouco sobrecarga. Ou intarray (pela mesma pessoa), se você não se importa usando um pacote ligeiramente experimental que pode ter problemas de compartilhamento de dados entre arquiteturas ordenadas byte / bit diferentes. Eu não acredito que seria muito difícil empurrar uma função serializar e unserialize função lá se você rasgar o código de igbinary para armazenar arrays numéricos com a endianess correta. Olhando igbinaryserialize32 e igbinaryunserialize32 em igbinary. c, deve ser muito fácil copiar essa funcionalidade para intarray. c. Tire o ltlt0 embora, isso é apenas estúpido: P

No comments:

Post a Comment