I have just bought a GPS Tracker, it can send SMS to cellphone just fine. It also supports reporting to a server via GPRS.
I have setup the device to contact my own server on port 8123, it's a FreeBSD server and i have checked that i recieve packets on that port.
I successfully have setup a listener server written in PHP, and i can receive data from the device. But how do i convert the partial HEX data to something usefull (ASCII)?
Example data string:
$$^#T^#E Y'^WÿU210104.000,A,5534.4079,N,01146.2510,E,0.00,,170411,,*10|1.0|72|0000á
Unfortunately i don't know how i can copy-paste the HEX parts
Now how do i get the ID part out? I have tried echo hexdec(mb_substr($data, 4, 7));
The data is following this protocol
From the document:
Command format of GPRS packets are as follows:
From server to tracker:
##\r\n
From tracker to server:
$$\r\n
Note:
Do NOT input ‘’ when writing a command.
All multi-byte data complies with the following sequence: High byte prior to low byte.
The size of a GPRS packet (including data) is about 100 bytes
Item Specification
## 2 bytes. It means the header of packet from server to tracker.
It is in ASCII code (Hex code: 0x40)
$$ 2 bytes. It is the header of packet from tracker to server.
It is in ASCII code (Hex code: 0x24)
L 2 bytes. It means the length of the whole packet including
the header and ending character and it is in hex code
ID 7 bytes, ID must be digit and not over 14 digits, the unused byte
will be stuffed by ‘f’ or ‘0xff’. It is in the format of hex code.
For example, if ID is 13612345678, then it will be shown as
follows: 0x13, 0x61, 0x23, 0x45, 0x67, 0x8f, 0xff.
If all 7 bytes are 0xff, it is a broadcasting command. ID is in hex code
command 2 bytes. The command code is in hex code. Please refer to the
command list below.
data Min 0 byte and max 100 bytes. See Annex 1 for description of ‘data’.
checksum 2 bytes. It indicates CRC-CCITT (default is 0xffff) checksum of
all data (not including CRC itself and the ending character).
It is in hex code.
For example: 24 24 00 11 13 61 23 45 67 8f ff 50 00 05 d8 0d 0a
0x05d8 = CRC-CCITT (24 24 00 11 13 61 23 45 67 8f ff 50 00)
\r\n 2 bytes. It is the ending character and in hex code
(0x0d,0x0a in hex code)
Update
With the answer from Anomie, i was able to piece this together
$arr = unpack('H4length/H14id/H4cmd/H4crc/H4end', mb_substr($data, 2, 11) . mb_substr($data, -4));
var_dump($arr);
This will out put something like
array(5) {
["length"]=>
string(4) "0054"
["id"]=>
string(14) "004512345678ff"
["cmd"]=>
string(4) "9955"
["crc"]=>
string(4) "c97e"
["end"]=>
string(4) "0d0a"
}
It sounds like you are needing to convert binary data to integers or strings. The most straightforward way is to use unpack.
For example, to extract the length you already know you can use
$length_bin = substr($string, 2, 2);
To convert it to an integer, you can use something like
$length = unpack('v', $length_bin); $length = $length[1];
The 'v' code will work for the length and the checksum; if you have a number stored as 4 bytes use 'V', and for the ID you can use 'H*' to get it as a string of hex digits. Other codes are listed in the documentation.
A somewhat less straightforward way is to do the bit manipulation manually, after using unpack with C* to get an array of all the byte values. For example,
$bytes = unpack('C*', $length_bin);
$length = ($bytes[0] << 8) | $bytes[1];
You need to know the format of the messages you are going to receive from the device. You can get this info from the manufacturer. Then, depending on that, you have to create a proper listener in the server side.
I've been working with several devices like that and normally you have to create a process in the server listening to the port with a Socket (or similar). You may have an authentication process also to differentiate between devices (you can have more than one). After that, you simply get the data from the device, you parse it and you store it. Depending on the device you can also send requests or configurations.
Hope this helps
*Edit 26 April:* I have changed the question a bit, thus this seems out of place. Initial question was more on how to read the data from TCP.
I found some great articles on writing a TCP/socket server in PHP (/me slaps PHP around a bit with a large trout)
http://devzone.zend.com/article/1086
http://kevin.vanzonneveld.net/techblog/article/create_daemons_in_php/
Can't wait to get this going :)
Related
I am building an inhouse Invoicing solution for my company. The government requires us to create QR Code fields encoded in Tag-Length-Value (TLV) format.
The TLV encoding shall be as follows:
Tag: the tag value as mentioned above stored in one byte
Length: the length of the byte array resulted from the UTF8 encoding of the field value. The length shall be stored in one byte.
Value: the byte array resulting from the UTF8 encoding of the field value.
In the example they have provided this Base64 Output
AQkxMjM0NTY3ODkCCjEyLzEyLzIwMjADBDEwMDADAzE1MPaIn2Z2jg6VqWvWV6IrZZNzLF7xvZrWXW5xRV5yFY2xFu0ycXOiyqV0k7Wsh6b1IcE2Tfzap1AQAQVsktmsv1FFQ1MxIAAAAGKblFMh9nFRSn8tvftXqo9zRSz2VEAPITSZ3W7UDHKhUx+7yXGijLtJSZGXMOc+jpKwARzDl68GmmRd75NWdOs=
When I decode using
$base64 = "AQkxMjM0NTY3ODkCCjEyLzEyLzIwMjADBDEwMDADAzE1MPaIn2Z2jg6VqWvWV6IrZZNzLF7xvZrWXW5xRV5yFY2xFu0ycXOiyqV0k7Wsh6b1IcE2Tfzap1AQAQVsktmsv1FFQ1MxIAAAAGKblFMh9nFRSn8tvftXqo9zRSz2VEAPITSZ3W7UDHKhUx+7yXGijLtJSZGXMOc+jpKwARzDl68GmmRd75NWdOs=";
echo base64_decode($base64);
The response i get is:
123456789
12/12/20201000150���fv���k�W�+e�s,^��]nqE^r���2qs�ʥt������!�6M�ڧPl�٬�QECS1 b��S!�qQJ-��W��sE,�T#!4��n�r�S��q���II��0�>���×��d]�Vt�
Tag 1: Seller's Name
Tag 2: Vat Registration number
Tag 3: Timestamp of the invoice
Tag 4: Invoice Total
Tag 5: Tax Total
Tag 6: Hash of XML invoice
Tag 7: ECDSA Signature
Tag 8: ECDSA Public Key
Tag 9: ECDSA signature of the cryptographic stamp’s public key
What Am I doing wrong here and what is the right syntax to correct it?
Knowing it's binary data, we can echo it with bin2hex(base64_decode($base64)), and see this:
0109313233343536373839020a31322f31322f323032300304313030300303313530f6889f66768e0e95a96bd657a22b6593732c5ef1bd9ad65d6e71455e72158db116ed327173a2caa57493b5ac87a6f521c1364dfcdaa7501001056c92d9acbf514543533120000000629b945321f671514a7f2dbdfb57aa8f73452cf654400f213499dd6ed40c72a1531fbbc971a28cbb4949919730e73e8e92b0011cc397af069a645def935674eb
For easier viewing, I used the command line tools base64 -d and xxd to get this view:
00000000: 0109 3132 3334 3536 3738 3902 0a31 322f ..123456789..12/
00000010: 3132 2f32 3032 3003 0431 3030 3003 0331 12/2020..1000..1
00000020: 3530 f688 9f66 768e 0e95 a96b d657 a22b 50...fv....k.W.+
00000030: 6593 732c 5ef1 bd9a d65d 6e71 455e 7215 e.s,^....]nqE^r.
00000040: 8db1 16ed 3271 73a2 caa5 7493 b5ac 87a6 ....2qs...t.....
00000050: f521 c136 4dfc daa7 5010 0105 6c92 d9ac .!.6M...P...l...
00000060: bf51 4543 5331 2000 0000 629b 9453 21f6 .QECS1 ...b..S!.
00000070: 7151 4a7f 2dbd fb57 aa8f 7345 2cf6 5440 qQJ.-..W..sE,.T#
00000080: 0f21 3499 dd6e d40c 72a1 531f bbc9 71a2 .!4..n..r.S...q.
00000090: 8cbb 4949 9197 30e7 3e8e 92b0 011c c397 ..II..0.>.......
000000a0: af06 9a64 5def 9356 74eb ...d]..Vt.
You haven't explained what the possible "tag" values are, but I can see the start of that string has a tag of 0x01, a length of 0x09, and the following 9 bytes are ASCII/UTF-8 for 123456789; it then has a tag of 0x02, a length of 0x0a, and the next 10 characters are ASCII/UTF-8 12/12/2020; and so on.
Later, there is a tag of f6 with a length of 88, and some binary data, but without knowing what tag f6 means, I've no reason to suppose that's a problem - maybe it embeds an image, or a stream of compressed data.
For Decode QR Code (Zatca) in PHP
Read QR Code - example base64 code.
Decode the base64 code.
use preg_replace to remove unicode values from the string
And explode to get array
Sample code
$base64 = "AQZSYWZlZXECDTEyMzQ1Njc4OVQxMjUDFDIwMjEtMDctMTJUMTQ6MjU6MDlaBAM3ODYFAjI1";
$decoded = base64_decode($base64);
//print_r($decoded)
//raw data
//\u0001\u0006Rafeeq\u0002\t123456789\u0003\u00142021-07-12T14:25:09Z\u0004\u0003786\u0005\u000225
$result_data = preg_replace('/[\x00-\x1F\x80-\xFF]/', ',', $decoded);
$actula_data = explode(',,', $result_data);
print_r($actula_data);
Output :
["","Rafeeq","123456789T125","2021-07-12T14:25:09Z","786","25"]
Edited:
In the Security Specification it says:
4.2 Structure of the Cryptographic Stamp applied on the QR code
The below specifications of the Cryptographic Stamp required for the QR code are based Annex (2) of the Controls, Requirements, Technical Specifications and
Procedural Rules for Implementing the Provisions of the E-Invoicing Regulation.
The QR code Cryptographic Stamp shall be generated use the same digital certificate used for stamping the electronic invoices. Please refer to section 3 for the
requirements applicable to the management and use of digital certificates used to apply Cryptographic Stamp on electronic invoices.
The Cryptographic Stamp shall be applied on the entire TLV encoding of the QR code fields (from tag 1 to tag 6) then it shall be appended to the TLV structure. The
Cryptographic Stamp consists of two fields as shown in the below table:
I assume the part of the data is a part of the Cryptographic Stamp
The first sequence of audio samples is recorded in JavaScript from the browser in mono, PCM format, 16-bit, and 96,000 Hz. I wrote this audio file as a blob to a server through a JavaScript FormData object using ajax.
These are the raw audio samples. When I retrieved the audio from the web server's directory listing, I received the second sequence of audio samples. It has been downsampled to 48000 Hz and the samples have been altered. What encoder is being used?
Server-side PHP code:
$input = $_FILES['audio']['tmp_name']; //audio blob
$output = $_POST['filename'];
if(move_uploaded_file($input, $output))
exit('Audio file Uploaded');
Client-side JavaScript code:
function send_audio(fn, blob){
var formData = new FormData();
formData.append("filename", fn);
formData.append('audio', blob);
$.ajax({
url:'save_audio.php',
type:'post',
data: formData,
contentType:false,
processData:false,
cache:false,
success: function(data){
console.log("send_audio success!");
console.log(data);
}
});
}
It's not clear whats going on but consider the following:
(1) Try 16-bits not 32-bits per sample (might help).
There is no need to record these audio samples at 32 bits per sample. That means you're using 4 bytes to record one sample value that fits within 2 bytes (16 bits).
Your highest value is 30465 (bytes x77 x01) and the lowest value is -32513 (bytes x80 xFF).
Notice those values fit two bytes? By using 4 bytes you make x00 x00 x77 x01. A waste to store extra00.
Two bytes hold max value of 65535. Or even 32767 if you divide into two parts as +32767 and -32767.
(2) Make sure there is no confusion between encoding of bytes (as hex), and digits (as integers).
Bytes are written as hex inside a file. Your values seem to mess up when converting from integers into hex format. Also 16 bit vs 32 bits for the
Some examples from your numbers compared to 2 bytes (16-bit) hex:
FIRST SEQ: SECOND SEQ:
value | hex | value | hex
100 00 64 612 02 64
553 02 29 41 00 29
203 00 CB -309 FE CB
-409 FE 67 103 00 67
68 00 44 836 03 44
953 03 B9 185 00 B9
154 00 9A -102 FF 9A
-127 FF 81 385 01 81
Notice the value of integer 100 when written as hex (byte values) it becomes byte x64, for some reason a 2 is added in front of that 64 now making it x0264 which converts to integer value of 612.
In the second sequence, where are these extra 02 and FE etc coming from? Why if hex of first seq has a 00, then for the second seq there's something extra now added? Even vice-versa (first = something, then second = something removed to become as 00)?
You need to double check your recording code. Does it add some increasing number to the recorded value?? Because, as you know, 2 is followed by 3 and that pattern is there in your second sequence. Also true that FE is followed by FF (and therefore previous to FE would be FD, FC, FB, FA, etc).
If you still can't explain it then:
Record at 16-bit with 44,100 Hz like the normal way others do it. Then later get complicated if the simple setup works okay. Why 32-bit and 96,000 Hz anyway? Is it a scientific test?
Use a Hex Editor to view your bytes from both sides (saved blob file via JS, against file downloaded via PHP) and compare any changes between the two files.
Show how/what your recording code is doing.
Share the bytes of "I retrieved the audio from the web server" (save as file) for checking.
Maybe someone else can help you. I don't use html forms so maybe there's an encoding option for the POST data type in there too?
i am working on a php-script which encodes given text and hides that in an Image using LSB. But the encoded text is a Byte Array (text encrypted using mcrypt with rijndael-256 and then unpacked with unpack("C*", $encryptedText);) i have tp add the array-size at the beginning of the Array. if i would not do this, reading the Bytes from the Image again would be terrible later on, because the script would not know where to stop reading. I added size Information at the beginning of the Array using These lines of code:
$size = count($byteArray);
array_unshift($byteArray, $size >> 24, ($size & 0xff0000) >> 16, ($size & 0xff00) >> 8, $size & 0xff);
so the size is added in integer Format (4bytes), but now every Image created would have the characteristics that the first hidden Bytes start mostly with Zeros, besause $size is mostly in the range of 60000 or lower. is there any way i can encode size or Change other parts of the program so that it works and the beginning of the bytearry is not nearly the same every time?
Instead of always having the first 4 bytes encoding how long your message is, you can use the last two bits from the first byte to encode how many bytes you need to read for $size. Say, 00 = 1, 01 = 2, 10 = 3 and 11 = 4. For example, if $size is small enough to be expressed with just two bytes, the first few bytes will read as follow:
First byte: xxxxxx01
Second and third bytes: $size
Fourth byte and onward: ByteArray...
You can spice things up further by using a randomised embedding method. You can use a pseudorandom number generator, or chaotic maps, such as the Logistic Map, or Tent Map. The seed or initial condition parameters will be required by the receipt to decipher in what order to read the bytes to extract the message. For example, consider 5 bytes to embed data and 5 numbers generated between 0 and 1.
(0.2843, 0.5643, 0.0904, 0.4308, 0.9866)
Sorting the numbers in ascending order gives you the following order, which you can use to embed your secret:
(3, 1, 4, 2, 5)
How would i check that a file is either jpeg, pdf or tiff? And I mean actually checking, not just from mime type and file extension.
I have access to the raw file data (this check is part of an uploader) and i need to verify that the files are either jpeg, pdf or tiff. I assume I would have to check for some sort of headers in the files but I have no idea what to look for and where to start.
Exif_imagetype is very useful for this: http://us2.php.net/manual/en/function.exif-imagetype.php
It scans the initial bytes of the file to determine the graphic type. It supports a large number of graphic formats (and returns false if it doesn't recognize the format).
You need to implement byte sequence tests.
Here is a guide to checking byte sequences for the most common image formats.
This can be tricky since all files must follow a certain kind of ISO standard with the "magical number" present, which basically is a "header" for the format.
I found this wiki-page about different signatures: http://en.wikipedia.org/wiki/List_of_file_signatures
So in the best case scenario you just need to validate these first bytes.
If you have access to the raw file, you can check the file header for its magic number. This number define the type of file.
to check for image types you can use the exif_imagetype function.
for pdf: you have to open the file and read the first bytes and look if it starts with '%PDF'
$fp = fopen($pdf, 'r');
if(fgets($fp, 4) == '%PDF')
{
... is pdf
}
fclose($fp);
There is no sure fired way to be certain but the first few binary bits of a file are its signature/fingerprint for the file handlers to test. see https://en.wikipedia.org/wiki/List_of_file_signatures
Every file type can vary considerably and some allow for variable / shifting headers, but with a degree of uncertainty (At one time PDF did not mandate the 40 bit signature to be first) we can assume the following hex values sometimes erroneously called "Magic Numbers" as representing the start of each bit stream.
So in general to answer the requested types
FF D8 (ÿØ) would be a Jpeg (EXCEPT JP2000=FF 4F or 00 00) in raw binary or /9j/4 in Base64 format
25 50 44 46 2d (%PDF-) would be the 40 bit signature of a PDF or JVBER in Base64 format
89 50 4E 47 (‰PNG) would be PNG in raw binary or iVBOR in Base64 format
just for good measure here is related older GIF sequence
47 49 46 38 (GIF8) and that's R0lGO as Base64 also we can see the first 8 bits are 01000111 for G
Thus in ALL the above cases just the first "8 bit / byte" would be a very good indicator, no need for Magic strings, but with Zip/###X such as docX pptX cbzX xlsX they ALL have the same Magic Number
50 4B (PK) base64 = UEsDB
Finally the last requested above was Tif(f) which can be two types, Intel or Motorola thus you need to test for
49 49 2A 00 (II* ) base64 = SUkqA
4D 4D 00 2A (MM *) base64 = TU0AK
Can JavaScript string store 100K characters?
I've written a script where a string from PHP is passed to a variable in JavaScript. It works fine when it is cut short to almost ten thousand characters but breaks the script when attempting to pass the entire string whose length is a bit greater than 100K. No errors could be found though. Is there any solution for this as to any way of increasing character limit of JavaScript variable? I'm just a beginner. Would appreciate is some one could find a solution for this.
The ECMAScript Standard ECMA-262 (6th Edition, June 2015) says
6.1.4 The String Type
The String type is the set of all ordered sequences of zero or more 16-bit unsigned integer values ("elements") up to a maximum length of 253-1 elements.
So don't plan on using more than 9,007,199,254,740,991 or about 9 quadrillion characters. Of course, you should be prepared for systems which cannot allocate 18 PB chunks of memory, as this is not required for conforming ECMAScript implementations.
I think the question is asking about the practical limit, not the spec limit. And, no, it is not always the amount of RAM you have. I have x86_64 24GB PC running Linux Mint with x86_64 Firefox and x86_64 Chrome, and the limits I ran into were:
1,073,741,822 limit in Firefox 84
536,870,888 limit in Chrome 87
Any higher and Firefox throws a Uncaught RangeError: repeat count must be less than infinity and not overflow maximum string size, whereas Chrome throws Uncaught RangeError: Invalid string length. Use the following snippet to run a binary search for the max string length in your browser:
for (var startPow2 = 1; startPow2 < 9007199254740992; startPow2 *= 2)
try {" ".repeat(startPow2);} catch(e) {
break;
}
var floor = Math.floor, mask = floor(startPow2 / 2);
while (startPow2 = floor(startPow2 / 2))
try {
" ".repeat(mask + startPow2);
mask += startPow2; // the previous statement succeeded
} catch(e) {}
console.log("The max string length for this browser is " + mask);
There is no theorical limit to JS or PHP on the size of their strings.
I think there are a few possible situations.
Firstly, check that you are not sending your string via HTTP GET. There is a maximum size for GET and i think its dependent on your web server.
Secondly, if you do use POST, check in php.ini for post_max_size and see if it is smaller than the string size you are sending to it as well as your .htacccess file to see if php_value post_max_size is not too small.
Thirdly, check that in php.ini that your memory_limit does not restrict the size of memory that your script can use.
hope this helps.