Convert encryption/decryption function from Python to PHP - encryption

I have this Python script to encrypt/decrypt URLs:
# -*- coding: utf-8 -*-
import base64
from operator import itemgetter
class cryptUrl:
def __init__(self):
self.key = 'secret'
def encode(self, str):
enc = []
for i in range(len(str)):
key_c = self.key[i % len(self.key)]
enc_c = chr((ord(str[i]) + ord(key_c)) % 256)
enc.append(enc_c)
return base64.urlsafe_b64encode("".join(enc))
def decode(self, str):
dec = []
str = base64.urlsafe_b64decode(str)
for i in range(len(str)):
key_c = self.key[i % len(self.key)]
dec_c = chr((256 + ord(str[i]) - ord(key_c)) % 256)
dec.append(dec_c)
return "".join(dec)
url = "http://google.com";
print cryptUrl().encode(url.decode('utf-8'))
This works fine. For example the above url is converted to 29nX4p-joszS4czg2JPG4dI= and the decryption brings it back to the URL.
Now i want to convert this to a PHP function. So far encryption is working fine....but decryption is not....and i dont know why.....so far i got this:
function base64_url_encode($input) {
return strtr(base64_encode($input), '+/=', '-_');
}
function base64_url_decode($input) {
return strtr(base64_decode($input), '-_', '+/=');
}
function encode ($str)
{
$key = 'secret';
$enc = array();
for ($i;$i<strlen($str);$i++){
$key_c = $key[$i % strlen($key)];
$enc_c = chr((ord($str[$i]) + ord($key_c)) % 256);
$enc[] = $enc_c;
}
return base64_url_encode(implode($enc));
}
function decode ($str)
{
$key = 'secret';
$dec = array();
$str = base64_url_decode($str);
for ($i;$i<strlen($str);$i++){
$key_c = $key[$i % strlen($key)];
$dec_c = chr((256 + ord($str[$i]) + ord($key_c)) % 256);
$dec[] = $dec_c;
}
return implode($dec);
}
$str = '29nX4p-joszS4czg2JPG4dI=';
echo decode($str);
Now the above decoding prints out : N>:Tý\&™åª—Væ which is not http://google.com :p
Like i said encoding function works though.
Why isnt the decoding working ? What am i missing ?
Btw i cant use any other encoding/decoding function. I have a list of URLs encoded with python and i want to move the whole system to a PHP based site....so i need to decode those URLs with a PHP function instead of python.
(Use this page to execute Python: http://www.compileonline.com/execute_python_online.php)

Double check the syntax of strtr().
I'd suggest you using in in the following way:
strtr(
base64_encode($input),
array(
'+' => '-',
'/' => '_',
'=' => YOUR_REPLACE_CHARACTER
)
)
Make sure you have YOUR_REPLACE_CHARACTER!
Also, I'm sure you'll handle the reverse function, where you need to simply flip the values of the replace array.

Related

OCR using microsoft cognitive

What if i only want to process image from disk for reading text from it and storing them in text file.
As it is working for both json and data. i want to do work with data only. How to do that?
from __future__ import print_function
import time
import requests
import cv2
import operator
import numpy as np
# Import library to display results
import matplotlib.pyplot as plt
%matplotlib inline
_url = 'https://api.projectoxford.ai/vision/v1/analyses'
_key = 'd784ea882edd4feaa373dc5a80fa87e8'
_maxNumRetries = 10
def processRequest( json, data, headers, params ):
"""
Helper function to process the request to Project Oxford
Parameters:
json: Used when processing images from its URL. See API Documentation
data: Used when processing image read from disk. See API Documentation
headers: Used to pass the key information and the data type request
"""
retries = 0
result = None
while True:
response = requests.request( 'post', _url, json = json, data = data, headers = headers, params = params )
if response.status_code == 429:
print( "Message: %s" % ( response.json()['error']['message'] ) )
if retries <= _maxNumRetries:
time.sleep(1)
retries += 1
continue
else:
print( 'Error: failed after retrying!' )
break
elif response.status_code == 200 or response.status_code == 201:
if 'content-length' in response.headers and int(response.headers['content-length']) == 0:
result = None
elif 'content-type' in response.headers and isinstance(response.headers['content-type'], str):
if 'application/json' in response.headers['content-type'].lower():
result = response.json() if response.content else None
elif 'image' in response.headers['content-type'].lower():
result = response.content
else:
print( "Error code: %d" % ( response.status_code ) )
print( "Message: %s" % ( response.json()['error']['message'] ) )
break
return result
def renderResultOnImage( result, img ):
"""Display the obtained results onto the input image"""
R = int(result['color']['accentColor'][:2],16)
G = int(result['color']['accentColor'][2:4],16)
B = int(result['color']['accentColor'][4:],16)
cv2.rectangle( img,(0,0), (img.shape[1], img.shape[0]), color = (R,G,B), thickness = 25 )
if 'categories' in result:
categoryName = sorted(result['categories'], key=lambda x: x['score'])[0]['name']
cv2.putText( img, categoryName, (30,70), cv2.FONT_HERSHEY_SIMPLEX, 2, (255,0,0), 3 )
pathToFileInDisk = r'test.jpg'
with open( pathToFileInDisk, 'rb' ) as f:
data = f.read()
# Computer Vision parameters
params = { 'visualFeatures' : 'Color,Categories'}
headers = dict()
headers['Ocp-Apim-Subscription-Key'] = _key
headers['Content-Type'] = 'application/octet-stream'
json = None
result = processRequest( json, data, headers, params )
if result is not None:
# Load the original image, fetched from the URL
data8uint = np.fromstring( data, np.uint8 ) # Convert string to an unsigned int array
img = cv2.cvtColor( cv2.imdecode( data8uint, cv2.IMREAD_COLOR ), cv2.COLOR_BGR2RGB )
renderResultOnImage( result, img )
ig, ax = plt.subplots(figsize=(15, 20))
ax.imshow( img )
It's showing sytax error at %matplot inline
I gather you copied your Python code from somewhere, and there are a number of issues with it:
Your syntax error is stemming from the fact that %matplotlib is valid syntax for iPython, not plain Python.
Based on your problem description, IIUC, you've no need for any plotting code, so you might as well drop matplotlib (and cv2 and numpy, for that matter).
Your API URL is wrong: you want https://api.projectoxford.ai/vision/v1.0/ocr.
The code you'll want will be basically like this:
import json
import requests
import urllib
headers = {
# Request headers
'Content-Type': 'application/json',
'Ocp-Apim-Subscription-Key': 'YOUR_KEY_HERE',
}
params = urllib.urlencode({
# Request parameters
'language': 'unk',
'detectOrientation ': 'true',
})
body = {"url":"YOUR_URL_HERE"}
response = requests.post("https://api.projectoxford.ai/vision/v1.0/ocr?%s" % params, json=body, headers=headers)
result = response.json()
for region in result['regions']:
for line in region['lines']:
for word in line['words']:
print word['text']
Get more details about the response JSON on the API page, if you want, for instance, to arrange the text differently.
You forgot to redact your API key, so you'll probably want to generate a new one via the subscriptions page.

How can I read/decrypt the encrypted_value column in the chrome sqlite database using powershell?

I'm trying to read the contents of a cookie (to use for authentication in a script), but the value is stored as some sort of encrypted value in the chrome sqlite database. Is there any way to decrypt this using powershell?
Right now I can read the value out of the database using a script like this:
[string]$sqlite_library_path = "C:\Path\To\System.Data.SQLite.dll"
[string]$db_data_source = "C:\Users\$env:USERNAME\AppData\Local\Google\Chrome\User Data\Default\Cookies"
[string]$db_query = "SELECT * FROM cookies WHERE name='cookiename' AND host_key='servername'"
[void][System.Reflection.Assembly]::LoadFrom($sqlite_library_path)
$db_dataset = New-Object System.Data.DataSet
$db_data_adapter = New-Object System.Data.SQLite.SQLiteDataAdapter($db_query,"Data Source=$db_data_source")
[void]$db_data_adapter.Fill($db_dataset)
$db_dataset.Tables[0].encrypted_value
The problem is that the encryped value that is returned is unusable. How can I convert this into a usable value?
Adapted to Powershell from this answer: Encrypted cookies in Chrome
# Load System.Security assembly
Add-Type -AssemblyName System.Security
# Decrypt cookie
$ByteArr = [System.Security.Cryptography.ProtectedData]::Unprotect(
$db_dataset.Tables[0].encrypted_value,
$null,
[System.Security.Cryptography.DataProtectionScope]::CurrentUser
)
# Convert to string
$DecryptedCookie = [System.Text.Encoding]::ASCII.GetString($ByteArr)
I also advise you to change the way you getting the path to the cookies DB, because it's unreliable. In fact, it doesn't works on my machine, because, I've renamed user, but profile folder still keeps it's old name. Use Environment.GetFolderPath method instead:
# Get Cookies DB path
[string]$db_data_source = Join-Path -Path [Environment]::GetFolderPath('LocalApplicationData') -ChildPath 'Google\Chrome\User Data\Default\Cookies'
For those who don't have/want a SQLite assembly, you can use the sqlite command.
Here's a working 1-line example for Bash on MSYS2 (spread over multiple lines for readability).
Fill in the '' blanks in the SQL query as needed.
sqlite3 "${LOCALAPPDATA}\\Google\\Chrome\\User Data\\Default\\Cookies" \
".mode quote" \
"SELECT encrypted_value FROM cookies WHERE host_key = '' AND name = '' AND path = '/'"|\
powershell -command 'function main() {
$newline = [System.Text.Encoding]::ASCII.GetBytes(([char]10).ToString());
$stdout = [System.Console]::OpenStandardOutput();
try {
for ($n = 0; ($s = [System.Console]::In.ReadLine()) -ne $null; ++$n) {
if ($n) { $stdout.Write($newline, 0, $newline.Length); }
$s = [System.Text.RegularExpressions.Regex]::Match($s,
"^X" + [char]39 + "(.*)" + [char]39 + "$").Groups[1].Value;
$b = [byte[]]::new($s.Length / 2);
For ($i=0; $i -lt $s.Length; $i += 2) {
$b[$i / 2] = [System.Convert]::ToByte($s.Substring($i, 2), 16);
}
Add-Type -AssemblyName System.Security;
$output = [System.Security.Cryptography.ProtectedData]::Unprotect($b, $null,
[System.Security.Cryptography.DataProtectionScope]::CurrentUser);
$stdout.Write($output, 0, $output.Length);
}
} finally {
$stdout.Close();
}
}
main'

Log4perl category as log file name

I'm sure I'm being dim and missing the obvious but is there a simple way of using the current category as the filename in a config file without resorting to a subroutine call?
So that in the following one could use ${category}.log instead of repeating bin.nh.tpp in the filename line
log4perl.logger.**bin.nh.tpp**=INFO, BIN_NH_TPP_LOGFILE
log4perl.appender.BIN_NH_TPP_LOGFILE=Log::Log4perl::Appender::File
log4perl.appender.BIN_NH_TPP_LOGFILE.filename=${LOGS}/nh/**bin.nh.tpp**.log
log4perl.appender.BIN_NH_TPP_LOGFILE.mode=append
log4perl.appender.BIN_NH_TPP_LOGFILE.layout=PatternLayout
log4perl.appender.BIN_NH_TPP_LOGFILE.layout.ConversionPattern=[%d] %F{1} %L %c - %m%n
It's somewhat more involved than a subroutine, I'm afraid. Subroutines in l4p conf files allow for including variables known at conf file parsing time, e.g. the time/date or a user id. You can't modify log time behavior that way.
The easiest way I can think of right now to accomplish what you want is a custom appender like
package FileByCategoryAppender;
use warnings;
use strict;
use base qw( Log::Log4perl::Appender::File );
sub new {
my( $class, %options ) = #_;
$options{filename } = "no-category.log";
my $self = $class->SUPER::new( %options );
bless $self, $class;
}
sub log {
my( $self, %params ) = #_;
my $category = $params{ log4p_category };
$self->SUPER::file_switch( $category . ".log" );
$self->SUPER::log( %params );
}
1;
and then use it in your script like
use strict;
use warnings;
use Log::Log4perl qw( get_logger );
my $conf = q(
log4perl.category = WARN, Logfile
log4perl.appender.Logfile = FileByCategoryAppender
log4perl.appender.Logfile.create_at_logtime = 1
log4perl.appender.Logfile.layout = \
Log::Log4perl::Layout::PatternLayout
log4perl.appender.Logfile.layout.ConversionPattern = %d %F{1} %L> %m %n
);
Log::Log4perl::init(\$conf);
my $logger = get_logger("Bar::Twix");
$logger->error("twix error");
$logger = get_logger("Bar::Mars");
$logger->error("mars error");
which will result in two log files being created at log time:
# Bar.Mars.log
2012/11/18 11:12:12 t 21> mars error
and
# Bar.Twix.log
2012/11/18 11:12:12 t 21> twix error

Base64 encoded output differs from as3crypto and pycrypto encryption libraries

I'm trying to use symmetric encryption to pass data from actionscript 3 (client) to python (server).
The libraries I'm using are as3crypto and pycrypto, I'm not sure if I'm using these libraries correctly.
Actionscript 3:
private function testOnInit():void {
var t_toEnc:String = 'testtest';
var t_byAry:ByteArray = Hex.toArray( Hex.fromString( t_toEnc ) );
var t_key:ByteArray = Hex.toArray( Hex.fromString( 'Thisisthekey' ) );
var t_cbc:CBCMode = new CBCMode( new BlowFishKey( t_key ), new NullPad );
var t_enc:String;
t_cbc.IV = Hex.toArray( '30313233' );
t_cbc.encrypt( t_byAry );
t_enc = Base64.encodeByteArray( t_byAry );
dbg( 'b64 encrypted string ' + t_enc ); //this is just a debugging function we use in our code.
}
This is the base64 encoded output of the function above.
xvVqLzV5TU4=
Now, using the same key, initialization vector, and algorithm from the pycrypto library gives me different output.
Python:
from Crypto.Cipher import Blowfish
B = Blowfish.new( 'Thisisthekey', Blowfish.MODE_CBC, '30313233' )
S = 'testtest'
X = B.encrypt( S )
import base64
Y = base64.b64encode( X )
print Y
I82NQEkSHhE=
I'm pretty sure that I'm doing something wrong with the encryption process because I can base64 encode 'testtest' on both libraries and receive the same output.
Actionscript 3:
var b:ByteArray = new ByteArray();
b.writeUTFBytes( 'testtest' );
dbg( Base64.encodeByteArray( b ) );
Yields...
dGVzdHRlc3Q=
Python:
>>> T = 'testtest'
>>> print base64.b64encode( T )
Yields
dGVzdHRlc3Q=
Could someone please encrypt and base64encode the same string with the same IV in either python or actionscript, so I know which library is actually producing the correct output?
The problem might be in padding. ActionScript uses no padding, but Py doesn't show what padding it uses. So, it can be the reason. Try another padding (PKCS#5 for instance) with actionscript.

How can I encode xml files to xfdl (base64-gzip)?

Before reading anything else, please take time to read the original thread.
Overview: a .xfdl file is a gzipped .xml file which has then been encoded in base64. I wish to de-encode the .xfdl into xml which I can then modify and then re-encode back into a .xfdl file.
xfdl > xml.gz > xml > xml.gz > xfdl
I have been able to take a .xfdl file and de-encode it from base64 using uudeview:
uudeview -i yourform.xfdl
Then decommpressed it using gunzip
gunzip -S "" < UNKNOWN.001 > yourform-unpacked.xml
The xml produced is 100% readable and looks wonderful. Without modifying the xml then, i should be able to re-compress it using gzip:
gzip yourform-unpacked.xml
Then re-encoded in base-64:
base64 -e yourform-unpacked.xml.gz yourform_reencoded.xfdl
If my thinking is correct, the original file and the re-encoded file should be equal. If I put yourform.xfdl and yourform_reencoded.xfdl into beyond compare, however, they do not match up. Also, the original file can be viewed in an http://www.grants.gov/help/download_software.jsp#pureedge">.xfdl viewer. The viewer says that the re-encoded xfdl is unreadable.
I have also tried uuenview to re-encode in base64, it also produces the same results. Any help would be appreciated.
As far as I know you cannot find the compression level of an already compressed file. When you are compressing the file you can specify the compression level with -# where the # is from 1 to 9 (1 being the fastest compression and 9 being the most compressed file). In practice you should never compare a compressed file with one that has been extracted and recompressed, slight variations can easily crop up. In your case I would compare the base64 encoded versions instead of the gzip'd versions.
Check these out:
http://www.ourada.org/blog/archives/375
http://www.ourada.org/blog/archives/390
They are in Python, not Ruby, but that should get you pretty close.
And the algorithm is actually for files with header 'application/x-xfdl;content-encoding="asc-gzip"' rather than 'application/vnd.xfdl; content-encoding="base64-gzip"'
But the good news is that PureEdge (aka IBM Lotus Forms) will open that format with no problem.
Then to top it off, here's a base64-gzip decode (in Python) so you can make the full round-trip:
with open(filename, 'r') as f:
header = f.readline()
if header == 'application/vnd.xfdl; content-encoding="base64-gzip"\n':
decoded = b''
for line in f:
decoded += base64.b64decode(line.encode("ISO-8859-1"))
xml = zlib.decompress(decoded, zlib.MAX_WBITS + 16)
I did this in Java with the help of the Base64 class from http://iharder.net/base64.
I've been working on an application to do form manipulation in Java. I decode the file, create an DOM document from the XML then write it back to file.
My code in Java to read the file looks like this:
public XFDLDocument(String inputFile)
throws IOException,
ParserConfigurationException,
SAXException
{
fileLocation = inputFile;
try{
//create file object
File f = new File(inputFile);
if(!f.exists()) {
throw new IOException("Specified File could not be found!");
}
//open file stream from file
FileInputStream fis = new FileInputStream(inputFile);
//Skip past the MIME header
fis.skip(FILE_HEADER_BLOCK.length());
//Decompress from base 64
Base64.InputStream bis = new Base64.InputStream(fis,
Base64.DECODE);
//UnZIP the resulting stream
GZIPInputStream gis = new GZIPInputStream(bis);
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
doc = db.parse(gis);
gis.close();
bis.close();
fis.close();
}
catch (ParserConfigurationException pce) {
throw new ParserConfigurationException("Error parsing XFDL from file.");
}
catch (SAXException saxe) {
throw new SAXException("Error parsing XFDL into XML Document.");
}
}
My code in java looks like this to write the file to disk:
/**
* Saves the current document to the specified location
* #param destination Desired destination for the file.
* #param asXML True if output needs should be as un-encoded XML not Base64/GZIP
* #throws IOException File cannot be created at specified location
* #throws TransformerConfigurationExample
* #throws TransformerException
*/
public void saveFile(String destination, boolean asXML)
throws IOException,
TransformerConfigurationException,
TransformerException
{
BufferedWriter bf = new BufferedWriter(new FileWriter(destination));
bf.write(FILE_HEADER_BLOCK);
bf.newLine();
bf.flush();
bf.close();
OutputStream outStream;
if(!asXML) {
outStream = new GZIPOutputStream(
new Base64.OutputStream(
new FileOutputStream(destination, true)));
} else {
outStream = new FileOutputStream(destination, true);
}
Transformer t = TransformerFactory.newInstance().newTransformer();
t.transform(new DOMSource(doc), new StreamResult(outStream));
outStream.flush();
outStream.close();
}
Hope that helps.
I've been working on something like that and this should work for php. You must have a writable tmp folder and the php file be named example.php!
<?php
function gzdecode($data) {
$len = strlen($data);
if ($len < 18 || strcmp(substr($data,0,2),"\x1f\x8b")) {
echo "FILE NOT GZIP FORMAT";
return null; // Not GZIP format (See RFC 1952)
}
$method = ord(substr($data,2,1)); // Compression method
$flags = ord(substr($data,3,1)); // Flags
if ($flags & 31 != $flags) {
// Reserved bits are set -- NOT ALLOWED by RFC 1952
echo "RESERVED BITS ARE SET. VERY BAD";
return null;
}
// NOTE: $mtime may be negative (PHP integer limitations)
$mtime = unpack("V", substr($data,4,4));
$mtime = $mtime[1];
$xfl = substr($data,8,1);
$os = substr($data,8,1);
$headerlen = 10;
$extralen = 0;
$extra = "";
if ($flags & 4) {
// 2-byte length prefixed EXTRA data in header
if ($len - $headerlen - 2 < 8) {
return false; // Invalid format
echo "INVALID FORMAT";
}
$extralen = unpack("v",substr($data,8,2));
$extralen = $extralen[1];
if ($len - $headerlen - 2 - $extralen < 8) {
return false; // Invalid format
echo "INVALID FORMAT";
}
$extra = substr($data,10,$extralen);
$headerlen += 2 + $extralen;
}
$filenamelen = 0;
$filename = "";
if ($flags & 8) {
// C-style string file NAME data in header
if ($len - $headerlen - 1 < 8) {
return false; // Invalid format
echo "INVALID FORMAT";
}
$filenamelen = strpos(substr($data,8+$extralen),chr(0));
if ($filenamelen === false || $len - $headerlen - $filenamelen - 1 < 8) {
return false; // Invalid format
echo "INVALID FORMAT";
}
$filename = substr($data,$headerlen,$filenamelen);
$headerlen += $filenamelen + 1;
}
$commentlen = 0;
$comment = "";
if ($flags & 16) {
// C-style string COMMENT data in header
if ($len - $headerlen - 1 < 8) {
return false; // Invalid format
echo "INVALID FORMAT";
}
$commentlen = strpos(substr($data,8+$extralen+$filenamelen),chr(0));
if ($commentlen === false || $len - $headerlen - $commentlen - 1 < 8) {
return false; // Invalid header format
echo "INVALID FORMAT";
}
$comment = substr($data,$headerlen,$commentlen);
$headerlen += $commentlen + 1;
}
$headercrc = "";
if ($flags & 1) {
// 2-bytes (lowest order) of CRC32 on header present
if ($len - $headerlen - 2 < 8) {
return false; // Invalid format
echo "INVALID FORMAT";
}
$calccrc = crc32(substr($data,0,$headerlen)) & 0xffff;
$headercrc = unpack("v", substr($data,$headerlen,2));
$headercrc = $headercrc[1];
if ($headercrc != $calccrc) {
echo "BAD CRC";
return false; // Bad header CRC
}
$headerlen += 2;
}
// GZIP FOOTER - These be negative due to PHP's limitations
$datacrc = unpack("V",substr($data,-8,4));
$datacrc = $datacrc[1];
$isize = unpack("V",substr($data,-4));
$isize = $isize[1];
// Perform the decompression:
$bodylen = $len-$headerlen-8;
if ($bodylen < 1) {
// This should never happen - IMPLEMENTATION BUG!
echo "BIG OOPS";
return null;
}
$body = substr($data,$headerlen,$bodylen);
$data = "";
if ($bodylen > 0) {
switch ($method) {
case 8:
// Currently the only supported compression method:
$data = gzinflate($body);
break;
default:
// Unknown compression method
echo "UNKNOWN COMPRESSION METHOD";
return false;
}
} else {
// I'm not sure if zero-byte body content is allowed.
// Allow it for now... Do nothing...
echo "ITS EMPTY";
}
// Verifiy decompressed size and CRC32:
// NOTE: This may fail with large data sizes depending on how
// PHP's integer limitations affect strlen() since $isize
// may be negative for large sizes.
if ($isize != strlen($data) || crc32($data) != $datacrc) {
// Bad format! Length or CRC doesn't match!
echo "LENGTH OR CRC DO NOT MATCH";
return false;
}
return $data;
}
echo "<html><head></head><body>";
if (empty($_REQUEST['upload'])) {
echo <<<_END
<form enctype="multipart/form-data" action="example.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="100000" />
<table>
<th>
<input name="uploadedfile" type="file" />
</th>
<tr>
<td><input type="submit" name="upload" value="Convert File" /></td>
</tr>
</table>
</form>
_END;
}
if (!empty($_REQUEST['upload'])) {
$file = "tmp/" . $_FILES['uploadedfile']['name'];
$orgfile = $_FILES['uploadedfile']['name'];
$name = str_replace(".xfdl", "", $orgfile);
$convertedfile = "tmp/" . $name . ".xml";
$compressedfile = "tmp/" . $name . ".gz";
$finalfile = "tmp/" . $name . "new.xfdl";
$target_path = "tmp/";
$target_path = $target_path . basename($_FILES['uploadedfile']['name']);
if (move_uploaded_file($_FILES['uploadedfile']['tmp_name'], $target_path)) {
} else {
echo "There was an error uploading the file, please try again!";
}
$firstline = "application/vnd.xfdl; content-encoding=\"base64-gzip\"\n";
$data = file($file);
$data = array_slice($data, 1);
$raw = implode($data);
$decoded = base64_decode($raw);
$decompressed = gzdecode($decoded);
$compressed = gzencode($decompressed);
$encoded = base64_encode($compressed);
$decoded2 = base64_decode($encoded);
$decompressed2 = gzdecode($decoded2);
$header = bin2hex(substr($decoded, 0, 10));
$tail = bin2hex(substr($decoded, -8));
$header2 = bin2hex(substr($compressed, 0, 10));
$tail2 = bin2hex(substr($compressed, -8));
$header3 = bin2hex(substr($decoded2, 0, 10));
$tail3 = bin2hex(substr($decoded2, -8));
$filehandle = fopen($compressedfile, 'w');
fwrite($filehandle, $decoded);
fclose($filehandle);
$filehandle = fopen($convertedfile, 'w');
fwrite($filehandle, $decompressed);
fclose($filehandle);
$filehandle = fopen($finalfile, 'w');
fwrite($filehandle, $firstline);
fwrite($filehandle, $encoded);
fclose($filehandle);
echo "<center>";
echo "<table style='text-align:center' >";
echo "<tr><th>Stage 1</th>";
echo "<th>Stage 2</th>";
echo "<th>Stage 3</th></tr>";
echo "<tr><td>RAW DATA -></td><td>DECODED DATA -></td><td>UNCOMPRESSED DATA -></td></tr>";
echo "<tr><td>LENGTH: ".strlen($raw)."</td>";
echo "<td>LENGTH: ".strlen($decoded)."</td>";
echo "<td>LENGTH: ".strlen($decompressed)."</td></tr>";
echo "<tr><td><a href='tmp/".$orgfile."'/>ORIGINAL</a></td><td>GZIP HEADER:".$header."</td><td><a href='".$convertedfile."'/>XML CONVERTED</a></td></tr>";
echo "<tr><td></td><td>GZIP TAIL:".$tail."</td><td></td></tr>";
echo "<tr><td><textarea cols='30' rows='20'>" . $raw . "</textarea></td>";
echo "<td><textarea cols='30' rows='20'>" . $decoded . "</textarea></td>";
echo "<td><textarea cols='30' rows='20'>" . $decompressed . "</textarea></td></tr>";
echo "<tr><th>Stage 6</th>";
echo "<th>Stage 5</th>";
echo "<th>Stage 4</th></tr>";
echo "<tr><td>ENCODED DATA <-</td><td>COMPRESSED DATA <-</td><td>UNCOMPRESSED DATA <-</td></tr>";
echo "<tr><td>LENGTH: ".strlen($encoded)."</td>";
echo "<td>LENGTH: ".strlen($compressed)."</td>";
echo "<td>LENGTH: ".strlen($decompressed)."</td></tr>";
echo "<tr><td></td><td>GZIP HEADER:".$header2."</td><td></td></tr>";
echo "<tr><td></td><td>GZIP TAIL:".$tail2."</td><td></td></tr>";
echo "<tr><td><a href='".$finalfile."'/>FINAL FILE</a></td><td><a href='".$compressedfile."'/>RE-COMPRESSED FILE</a></td><td></td></tr>";
echo "<tr><td><textarea cols='30' rows='20'>" . $encoded . "</textarea></td>";
echo "<td><textarea cols='30' rows='20'>" . $compressed . "</textarea></td>";
echo "<td><textarea cols='30' rows='20'>" . $decompressed . "</textarea></td></tr>";
echo "</table>";
echo "</center>";
}
echo "</body></html>";
?>
You'll need to put the following line at the beginning of the XFDL file:
application/vnd.xfdl; content-encoding="base64-gzip"
After you've generated the base64-encoded file, open it in a text editor and paste the line above on the first line. Ensure that the base64'ed block starts at the beginning of the second line.
Save it and try it in the Viewer! If it still does not work, it may be that the changes that were made to the XML made it non-compliant in some manner. In this case, after the XML has been modified, but before it has been gzipped and base64 encoded, save it with an .xfdl file extension and try opening it with the Viewer tool. The viewer should be able to parse and display the uncompressed / unencoded file if it is in a valid XFDL format.
Different implementations of the gzip algorithm will always produce slightly different but still correct files, also the compression level of the original file may be different then what you are running it at.
gzip will put the filename in the header of file, so that a gzipped file vary in length depending on the filename of the uncompressed file.
If gzip acts on a stream, the filename is omitted and the file is a bit shorter, so the following should work:
gzip yourform-unpacked.xml.gz
Then re-encoded in base-64:
base64 -e yourform-unpacked.xml.gz yourform_reencoded.xfdl
maybe this will produce a file of the same length
Interesting, I'll give it a shot. The variations aren't slight, however. The newly encoded file is longer and when comparing the binary of the before and after, the data hardly matches up at all.
Before (the first three lines)
H4sIAAAAAAAAC+19eZOiyNb3/34K3r4RT/WEU40ssvTtrhuIuKK44Bo3YoJdFAFZ3D79C6hVVhUq
dsnUVN/qmIkSOLlwlt/JPCfJ/PGf9dwAlorj6pb58wv0LfcFUEzJknVT+/ml2uXuCSJP3kNf/vOQ
+TEsFVkgoDfdn18mnmd/B8HVavWt5TsKI2vKN8magyENiH3Lf9kRfpd817PmF+jpiOhQRFZcXTMV
After (the first three lines):
H4sICJ/YnEgAAzEyNDQ2LTExNjk2NzUueGZkbC54bWwA7D1pU+JK19/9FV2+H5wpByEhJMRH
uRUgCMom4DBYt2oqkAZyDQlmQZ1f/3YSNqGzKT3oDH6RdE4vOXuf08vFP88TFcygYSq6dnlM
naWOAdQGuqxoo8vjSruRyGYzfII6/id3dPGjVKwCBK+Zl8djy5qeJ5NPT09nTduAojyCZwN9
As you can see H4SI match up, then after that it's pandemonium.

Resources