Help parsing resources.arsc? - php

I'm trying to parse the resources contained in a resources.arsc file as discussed in this question. I know the androidmanifest.xml file identifies resources located in the .arsc file. I have successfully managed to parse the header of the .arsc file, I can't figure out how to parse the resources themselves.
Can somebody please help me figure out how to parse the resources contained in an .arsc file?
My parsing code so far:
<?php
$doc = fopen('resources.arsc', 'r+');
for($i=1;$i<10;$i++){
$res[$i] = _unpack('V', fread($doc, 4));
}
for ($i = 0, $j = $res[6]; $i <= $j; $i++) {
$word = fread($doc, 4);
$stroffs[] = _unpack('V', $word);
}
$strings = array();
$curroffs = 0;
foreach($stroffs as $offs){
//read length
$len = _unpack('v', fread($doc, 2));
//read string
if($len>0){
$str = fread($doc, $len*2);
}else{
$str = '';
}
//null
$wd = fread($doc, 2);
//utf-16le
$strings[] = mb_convert_encoding($str, 'gbk', 'UTF-16LE');
//curr offset
$curroffs += ($len+1)*2 + 2;
}
$tpos = ftell($doc);
read_doc_past_sentinel($doc);
//fseek($doc, $tpos + $tpos % 4);
$i = 0;
$xmls = $strings;
print_r($xmls);
//------------------------------------
//and then...somebody konw format or continue parse?
//------------------------------------
function read_doc_past_sentinel(&$doc){
$pos = ftell($doc);
$count= 0;
while($word = fread($doc, 4)){
if(_unpack('V', $word)==-1)break;
}
$n = 1;
if ($count < $n){
while($word = peek_doc($doc, 4)){
if(_unpack('V', $word) != -1)break;
fread($doc, 4);
$n++;
if(isset($count) && $count >= $n)break;
}
echo 'skip '.$n.' chars<br />';
}
}
function peek_doc(&$doc, $size){
$data = fread($doc, $size);
fseek($doc, ftell($doc)-$size);
return $data;
}
function _unpack($m, $b){
//if(!$b)return '';
$res = unpack($m, $b);
return $res[1];
}
?>

This is a fairly complicated binary file. You will need way more code than that to parse it. :)
My suggestion would be to use the same code that the platform does -- that is the ResTable and related classes found here:
frameworks/base/include/utils/ResourceTypes.h
frameworks/base/libs/utils/ResourceTypes.cpp
Note that ResourceTypes.h also has definitions for the complete structure of the resource table (which the classes there use to parse it).
You may also just be able to use the aapt tool. This has a number of options for parsing resource-related data out of an .apk:
aapt d[ump] [--values] WHAT file.{apk} [asset [asset ...]]
badging Print the label and icon for the app declared in APK.
permissions Print the permissions from the APK.
resources Print the resource table from the APK.
configurations Print the configurations in the APK.
xmltree Print the compiled xmls in the given assets.
xmlstrings Print the strings of the given compiled xml assets.
If there is some other data you want not available with those commands, consider modifying the tool code in frameworks/base/tools/aapt to add stuff to parse out what you want. This tool is using ResTable to parse the resources.

Related

Format text file for the LOAD DATA INFILE command

I'm working in a company where I have this project to create a web application based on the products my company is making.
There is an inside server which contains all the data from my company. What I have to do is parse the data the oracle server is retrieving. It is retrieving .lst files which can be easily translated to .csv using Excel or some php packages.
I successfully imported the Clients table into my MySQL database using the LOAD DATA INFILE command. But I'm running some issues when I want to parse the Articles table.
The columns/values aren't necessarily separated by semi-colons. To parse the data I'll have to say for example :
The first 6 characters are the Article ID
The next 35 characters are the description of the article
and so on...
Is there a way I could achieve this when using the LOAD DATA INFILE command, or should I format the file correctly using PHP then use this command and if so what could be the best approach?
Thanks guys, I hope I made myself clear since english isn't my primary language. :P
Edit : those are rows.
51016 51016 BOITE ORANGINA 33cls CASHS "24" 040430024000330 0000000000 1 01000000550009000 000000NNNNNN caisse 0000003750000000000001230
51019 51019 BOITE OASIS ORANGE CASHS "24" 33cl 040430024000330 0000000000 1 01000000550009000 000000NNNNNN caisse 0000003670000000000001230
The first line is getting parsed correctly while the second isnt.The double quote after 24 is being put into the next column. I just wanted to know if it was possible to do something about it, like deleting the double quotes.
A previous developer created an application to manage the articles, clients from the company. Unfortunately he cannot help me anymore but here is a ligne that describe a row.
import_a;Code_article;6;designation;35;designation2;35;Code_famille;2;Code_sousfamille;4;unite_condition;3;contenance;6/1000;Champ_vide;2;degre;4/10;champ_vide_6;6;Code_emballage;4;Champ_vide2;8;validite;1;Champ_vide3;7;code_tva;2;taux_tva;9/100;poids;6/1000;champ_vide4;19;montant_droits;6/1000;valide;1;rupture;1;edit_tarif;1;pre_commande;1;gratuit_autorise;1;trans_port;1;Champ_libre;1;caisse;15;prix_revient;9/100;stock;6/1;Champ_vide5;5;code_fournisseur;11/1
import_a => It's the filename you can just ignore that.
Then you have the name of the column followed by the number of characters. For example Code_articles is composed of 6 characters and so on.
You can also just ignore the duplicate ID Key at the beginning. But in total there should be 31 columns.
You can use this perl script to start your testing. The most important thing is the adjust the $def line according to your real data, until your get the correct result.
#!/usr/bin/perl
$input_file = "/tmp/a.lst";
$output_file = "/tmp/a.csv";
$testing = 1; #testing, print out directly first 100 lines
# we are using tab (#9) for the output csv file
$delim ="\t";
# output column header
$output_header = 1;
$defs= "import_a;Code_article;6;Code_article2;6;designation;29;designation2;35;Code_famille;2;Code_sousfamille;4;unite_condition;3;contenance;6/1000;Champ_vide;2;degre;4/10;champ_vide_6;6;Code_emballage;4;Champ_vide2;8;validite;1;Champ_vide3;7;code_tva;2;taux_tva;9/100;poids;6/1000;champ_vide4;19;montant_droits;6/1000;valide;1;rupture;1;edit_tarif;1;pre_commande;1;gratuit_autorise;1;trans_port;1;Champ_libre;1;caisse;15;prix_revient;9/100;stock;6/1;Champ_vide5;5;code_fournisseur;11/1";
my #input_fields, #input_fieldwidths, #input_fieldwidth_max, $input_field_no =0;
#defs= split(";",$defs);
$total_defs=$#defs;
$total_cols = 0;
$total_width = 0;
for($x=0; $x<$total_defs /2; $x++)
{
push(#input_fields, $defs[$x*2+1]);
$width = $defs[$x*2+2];
if($width=~/(.*)\/(.*)/){
$mw= $1;
$xw= $2;
}
else{
$mw = $width;
$xw= 0;
}
$total_width += $mw;
push(#input_field_widths,$mw);
push(#input_field_widths_max, $xw);
$total_cols ++;
}
if($testing){
for($x=1; $x<$total_cols; $x++)
{
print "$input_fields[$x]: $input_field_widths[$x]\n";
}
}
open(INPUT, $input_file) || die "Can not open input file";
open(OUTPUT, ">$output_file" ) || die "Can not open output file";
# this is the csv head
if($output_header){
print OUTPUT "$input_fields[0]";
for($x=1; $x<$total_cols; $x++)
{
print OUTPUT "\t$input_fields[$x]";
}
print OUTPUT "\n";
}
$lines=0;
foreach $l (<INPUT>)
{
chop($l);
$pos =0;
for($f=0; $f < $total_cols; $f++)
{
$val = substr($l, $pos, $input_field_widths[$f]);
print OUTPUT $delim if($pos);
print $delim if($pos && $testing);
print OUTPUT $val;
print $val if($testing);
$pos += $input_field_widths[$f];
}
print OUTPUT "\n";
print "\n" if($testing);
$lines++;
if($testing && $lines>100) { last;};
}
print $lines , " lines transformed\n";
close(INPUT);
close(OUTPUT);
Edit: for a comma separated quoted csv format:
#!/usr/bin/perl
$input_file = "/tmp/a.lst";
$output_file = "/tmp/a.csv";
# we are using tab (#9) for the output csv file
$delim =";";
$testing = 1; #testing, print out directly first 10 lines
$quote ="'";
# output column header
$output_header = 1;
$defs= "import_a;Code_article;6;Code_article2;6;designation;29;designation2;35;Code_famille;2;Code_sousfamille;4;unite_condition;3;contenance;6/1000;Champ_vide;2;degre;4/10;champ_vide_6;6;Code_emballage;4;Champ_vide2;8;validite;1;Champ_vide3;7;code_tva;2;taux_tva;9/100;poids;6/1000;champ_vide4;19;montant_droits;6/1000;valide;1;rupture;1;edit_tarif;1;pre_commande;1;gratuit_autorise;1;trans_port;1;Champ_libre;1;caisse;15;prix_revient;9/100;stock;6/1;Champ_vide5;5;code_fournisseur;11/1";
my #input_fields, #input_fieldwidths, #input_fieldwidth_max, $input_field_no =0;
#defs= split(";",$defs);
$total_defs=$#defs;
$total_cols = 0;
$total_width = 0;
for($x=0; $x<$total_defs /2; $x++)
{
push(#input_fields, $defs[$x*2+1]);
$width = $defs[$x*2+2];
if($width=~/(.*)\/(.*)/){
$mw= $1;
$xw= $2;
}
else{
$mw = $width;
$xw= 0;
}
$total_width += $mw;
push(#input_field_widths,$mw);
push(#input_field_widths_max, $xw);
$total_cols ++;
}
if($testing){
for($x=0; $x<$total_cols; $x++)
{
print "$input_fields[$x]: $input_field_widths[$x]\n";
}
}
open(INPUT, $input_file) || die "Can not open input file";
open(OUTPUT, ">$output_file" ) || die "Can not open output file";
# this is the csv head
if($output_header){
print OUTPUT "$input_fields[0]";
for($x=1; $x<$total_cols; $x++)
{
print OUTPUT "\t$input_fields[$x]";
}
print OUTPUT "\n";
}
$lines=0;
foreach $l (<INPUT>)
{
chop($l);
$pos =0;
for($f=0; $f < $total_cols; $f++)
{
$val = substr($l, $pos, $input_field_widths[$f]);
print OUTPUT $delim if($pos);
#print $delim if($pos && $testing);
print OUTPUT $quote, $val, $quote;
if($testing){
print $input_fields[$f] , "=", $val, "\n";
}
$pos += $input_field_widths[$f];
}
print OUTPUT "\n";
print "\n" if($testing);
$lines++;
if($testing && $lines>0) { last;};
}
print $lines , " lines transformed\n";
close(INPUT);
close(OUTPUT);

Huge operation in PHP

I am converting a Java program into PHP for a webpage, the only problem is that I am using a free web hosting service (000Webhost) and it does not let me make time limit changes. The program compiles data from (currently, 66, however, more are possible) different webpages, and puts the data into a table. I can provide code, though, I am by no means a PHP scripter, so that may be the source of my problems. Can someone help me figure out my issues?
<?php
$html = file_get_contents("http://www.someURL.com");
$newString = explode("data = [", $html);
$sOne = explode("]", $newString[1]);
$names = explode(", ", $sOne[0]);
$urls = array();
foreach($names as $name) {
$chars = str_split($name);
foreach ($chars as $ch) {
if (!ctype_alnum($ch) && $ch != '-' && $ch != '_' && $ch != ' ') {
$name = trim(str_replace($ch, ' ', $name));
}
}
$urls[count($urls)] = 'http://www.someURL.com/' .str_replace(' ', '_', $name);
}
echo count($urls);
for ($i = 0; $i < count($urls); $i++) {
$url = $urls[$i];
$html = #file($url);
if (strpos($html, "404 - Page not found") === false) {
echo $i;
flush(); #ob_flush();
}
}
echo '<br>';
echo '<br>';
?>
The echos in there are a debug, telling me how many pages I need to process, and how many I actually have processed.
Thanks.
you can run you php processing in a local host, WAMP, LAMP , XAMP etc, and then change your php time limit to 0 (unlimited) , fill the local DB in all the data you just saved and then move the local db to the production db

export .po file into .csv

I am looking for a simple way to create an excel or CSV file from a .po localization file.
I couldn't find any via Google, so i'm thinking of writing it myself in PHP.
The PO file has such structure
msgid "Titre"
msgstr "Titre"
So i guess i need my PHP script to parse the .po file looking for "the first bit of text between comma after each occurrence of the keyword msgstr".
I assume that's the job for a regex, so i tried that, but it does not return anything:
$po_file = '/path/to/messages.po';
if(!is_file($po_file)){
die("you got the filepath wrong dude.");
}
$str = file_get_contents($po_file);
// find all occurences of msgstr "SOMETHING"
preg_match('#^msgstr "([^/]+)"#i', $str, $matches);
$msgstr = $matches[1];
var_dump($msgstr);
There is a nice pear library. File_Gettext
If you look at the source File/Gettext/PO.php you see the regex pattern that you'll need:
$matched = preg_match_all('/msgid\s+((?:".*(?<!\\\\)"\s*)+)\s+' .
'msgstr\s+((?:".*(?<!\\\\)"\s*)+)/',
$contents, $matches);
for ($i = 0; $i < $matched; $i++) {
$msgid = substr(rtrim($matches[1][$i]), 1, -1);
$msgstr = substr(rtrim($matches[2][$i]), 1, -1);
$this->strings[parent::prepare($msgid)] = parent::prepare($msgstr);
}
Or just use the pear lib:
include 'File/Gettext/PO.php';
$po = new File_Gettext_PO();
$po->load($poFile);
$poArray = $po->toArray();
foreach ($poArray['strings'] as $msgid => $msgstr) {
// write your csv as you like...
}
After search on Google and i've found this code to extract comment msgid, msgstr. It works!
$contents = file_get_contents("file.po");
$regex = '/^#\s*(.+?)\nmsgid "(.+?)"\nmsgstr "(.+?)"/m';
$matched = preg_match_all($regex, $contents, $matches );
$array = NULL;
for ($i = 0; $i < $matched; $i++) {
$array[] = array('comment' => $matches[1][$i],
'msgid' => $matches[2][$i],
'msgstr' => $matches[3][$i]
);
}
print_r($array);

Create dynamic sitemap from text file using php

I have to create a dynamic site map for a uni assignment using PHP.
I have saved the names of the links in a text file called "sitemap.txt". These names are the names of the pages minus their extensions and I am supposed to use this content to generate a link. The content looks like this:
Index,Services,Contact Us,Register,Login,Class Manager
My code is below:
<?php
$fp = fopen("sitemap.txt", "r");
echo '<p class="smallerText">';
while(!feof($fp))
{
$line = fgets($fp);
$array = explode(",", $line);
}
fclose($fp);
$num_elements = count($array);
$list = '<ul class="servicesList" name="sitemap">';
for($count = 0; $count < $num_elements; $count++)
{
$list .= "<li>$array[$count]</li>";
}
$list .= "</ul>";
echo "$list";
?>
So basically I have been able to print the contents of the file to the page without any issues. But I need to convert the static text into links.
Can anyone suggest a way? I was thinking using regex or string matching but I'm not sure how.
I am not sure what you are asking, but if it's creating link out of those names, can't you just ....
$YourDomain="http://mydomain.com/";
$ext=".php";
for($count = 0; $count < $num_elements; $count++)
{
$list .= "<li>$array[$count]</li>";
}

how to scan a LAN for live hosts using PHP and SNMP?

I would like to have a quick script listing all active hosts in a LAN, and I am a bit lost. From other posts I figured that this can be done most effectively by polling the DHCP server (in my case a Lancom router) using SNMP.
However, I am not familiar with the SNMP commands in PHP. Is snmpwalk() the correct function? Can I get snmpwalk() or any other php function to return an array that contains a list of all live hosts?
Finding live hosts
The best way to be sure you get all live hosts is with a ping sweep of the subnet, using a tool like nmap. Since Windows hosts don't respond to pings by default, it also includes a brief TCP port scan as well. The syntax from the linux CLI is nmap -sP 192.0.2.0/24 (substitute your subnet instead of 192.0.2.0/24).
SNMP query
I don't think SNMP will really solve your problem, but I will include what I can to assist... When you use the PHP SNMP Extension, you first need to know the OID for the table with the correct information. The LANCOM-1711-MIB is one possibility, but it's hard to know for sure; you should contact LANCOM support if you don't know which SNMP OID to poll.
Let's just go on the assumption that staDhcpLanIpadd (OID: 1.3.6.1.4.1.2356.500.2.1712.1.32.21.1.2) is the OID you need. At this point, you would snmpwalk the router using SNMPv2c and the SNMP community you configured on it. Presumably, this OID gives you the list of DHCP addresses issued; however, that doesn't mean they are live at the time you poll the router (someone could have unplugged the cable, or turned them off).
So I wrote a script that probes the Lancom router and pulls out the DHCP/BOOTP table. It may be used for all those who need to monitor such routers, and therefore I am sharing it. It also outputs a nice HTML table; the function BetterTable() can be used on any 2D array.
You will need to set IP, userid, and pwd (first three variables) in order to use the script on your router.
<?php
$router_ip = '';
$username = '';
$password = '';
$port = 23;
$timeout = 10;
$connection = fsockopen($router_ip, $port, $errno, $errstr, $timeout);
if(!$connection){
echo "Connection failed\n";
exit();
} else {
fputs($connection, "$username\r\n");
fputs($connection, "$password\r\n");
fputs($connection, "cd setup/dhcp/dhcp-table \r\n");
fputs($connection, "dir \r\n");
fputs($connection, " ");
$j = 0;
while ($j < 16) {
fgets($connection);
$j++;
}
stream_set_timeout($connection, 2);
$timeoutCount = 0;
$content ='';
$DhcpArray = '';
(int) $index =0;
$DhcpFile = "C:\IP-Symcon\webfront\user\images\LancomDhcp.txt";
$fh = fopen($DhcpFile, 'w') or die("can't open file");
//$DhcpArray[0] = array ('IP-Address', 'MAC-Address', 'Timeout', 'Hostname', 'Type', 'LAN-Ifc', 'Ethernet-Port', 'VLAN-ID', 'Network-Name');
while (!feof($connection)){
$content = fgets($connection);
$content = str_replace("\r", '', $content);
$content = str_replace("\n", "", $content);
$lineArray = explode(' ', $content);
if (isValidIp($lineArray [0]))
{
$DhcpArray[$index]['IP-Address'] = substr ($content, 0,17);
$DhcpArray[$index]['MAC-Address'] = substr ($content, 17,32-18);
$DhcpArray[$index]['Timeout'] = substr ($content, 31,41-32);
$DhcpArray[$index]['Hostname'] = substr ($content, 40,108-41);
$DhcpArray[$index]['Type'] = substr ($content, 107,125-108);
$DhcpArray[$index]['LAN-Ifc'] = substr ($content, 124,137-125);
$DhcpArray[$index]['Ethernet-Port'] = substr ($content, 136,152-137);
$DhcpArray[$index]['VLAN-ID'] = substr ($content, 151,161-152);
$DhcpArray[$index]['Network-Name'] = substr ($content, 160);
fwrite($fh, $content);
$index +=1;
}
# If the router say "press space for more", send space char:
if (preg_match('/MORE/', $content) ){ // IF current line contain --More-- expression,
fputs ($connection, " "); // sending space char for next part of output.
} # The "more" controlling part complated.
$info = stream_get_meta_data($connection);
if ($info['timed_out']) { // If timeout of connection info has got a value, the router not returning a output.
$timeoutCount++; // We want to count, how many times repeating.
}
if ($timeoutCount >2){ // If repeating more than 2 times,
break; // the connection terminating..
}
}
$content = substr($content,410);
BetterTable($DhcpArray);
fclose($fh);
}
echo "End.\r\n";
//--------------------------------------------------------------------
function isValidIp($ip)
{/* PCRE Pattern written by Junaid Atari */
return !preg_match ( '/^([1-9]\d|1\d{0,2}|2[0-5]{2})\.('.
'(0|1?\d{0,2}|2[0-5]{2})\.){2}(0|1?'.
'\d{0,2}|2[0-5]{2})(\:\d{2,4})?$/',
(string) $ip )
? false
: true;
}
//--------------------------------------------------------------
function BetterTable($twoDimArray)
{
$i = 0;
echo "<table>
<table class='BetterTable' border='1'>";
echo "<tr>";
echo '<td>Line #
</td>';
foreach ($twoDimArray[0] as $fieldName => $fieldValue)
{
echo '<td>'.$fieldName. '</td>';
}echo '</tr>';
$i = 0;
foreach ($twoDimArray as $rowName => $rowValue)
{
if ($i%2 == 0)
Echo "<tr bgcolor=\"#d0d0d0\" >";
else
Echo "<tr bgcolor=\"#eeeeee\">";
$fields = count($twoDimArray[$i]);
$y = 0;
echo '<td>'.$i. '</td>';
foreach ($rowValue as $fieldName => $fieldValue)
{
echo '<td>'.$fieldValue. '</td>';
$y = $y + 1;
}
echo '</tr>';
$i = $i + 1;
}
echo '</table>';
}
?>

Categories