PHP: Extract fdf fields as an array from a PDF - php

i want to extract the available fields as an array from a fillable pdf.
an array like: array('firstname','secondname','address');
i do not need the values for those fields, if they are filled.
what is easiest way to do that using PHP?

under online documentation for "fdf_next_field_name" the following example is given that you can modify to store the field names into an array
<?php
$fdf = fdf_open($HTTP_FDF_DATA);
for ($field = fdf_next_field_name($fdf); $field != ""; $field = fdf_next_field_name($fdf, $field)) {
echo "field: $field\n";
}
?>

I upvoted Murray's answer because her was in ernest and I am pretty sure that he is right pre php 5.3
Sadly, pecl fdf is no more.
Thankfully, one "noah" made a comment on the php documentation with a preg_match_all regex solution to the problem. Included here with slight modifications for clarity. Long live noah.
function parse($text_from_file) {
if (!preg_match_all("/<<\s*\/V([^>]*)>>/x",$text_from_file,$out,PREG_SET_ORDER))
return;
for ($i=0;$i<count($out);$i++) {
$pattern = "<<.*/V\s*(.*)\s*/T\s*(.*)\s*>>";
$thing = $out[$i][2];
if (eregi($pattern,$out[$i][0],$regs)) {
$key = $regs[2];
$val = $regs[1];
$key = preg_replace("/^\s*\(/","",$key);
$key = preg_replace("/\)$/","",$key);
$key = preg_replace("/\\\/","",$key);
$val = preg_replace("/^\s*\(/","",$val);
$val = preg_replace("/\)$/","",$val);
$matches[$key] = $val;
}
}
return $matches;
}
I expect that someone will get fedup with the lack of true fdf support in php and fix this.
Since we are all probably after the same basic workflow if you are reading this question, then you should know that the basic workflow that I am following is:
download normal pdf form.
use libreoffice to make it a pdf form with named fields.
use pdftk to turn it into a fdf file
use this function to figure out what values the form needs.
populate a flat php array with the correct variables defined (from db/whatever)
use pdf_forge to create a new fdf with the values pre-filled
use pdftk again to create a new pdf from fdf+original-pdf with the variables (from db/whatever)
profit
HTH
-FT

If you control the pdf and just want the keys, the following will work. Uses php, no other libraries (good if you host doesn't have them).
Set the pdf submit button to html and set the page to the address where your php code will run.
$q_string = file_get_contents("php://input");
parse_str($q_string , $pdf_array);
$pdfkeys = array_keys($pdf_array);
The html query string, from the pdf file, is put into the variable $q_string. It is then parsed into an array called $pdf_array. $pdf_array holds all of the keys and values. Then array_keys() is used to put all the keys into $pdfkeys as you wanted.
I had come here looking how to read pdf values to put into a db, and finally after some more poking around came up with the above. Hopefully meets some people's needs. xfdf can also work, but you will need to parse as xml then -- this was simpler for me.

I get a normal post from PDFs submitting to my server, but not in the $_POST array. You just have to parse it from php://input:
$allVars = file_get_contents("php://input");
parse_str($allVars, $myPost);
foreach($myPost as $key => $value) {
$allKeys[] = $key;
}

Related

how to loop through a text file in php to find a specific line of text

I have made a program that lets you enter the username and password then it stores it in a text file and when i want to login i want to make it so it loops through the text file that has the usr/pass in to find if you entered your credentials in correctly. I'm not sure how to do this. please can somebody help
Example text.txt file:
$ cat text.txt
text1|answer1
text2|answer2
text3|answer3
Example code:
cat test2.php
<?php
$text="text1";
$file="text.txt";
$f = fopen($file, 'r');
while($data = fgets($f))
{
$ar_data=explode('|',$data);
if($ar_data[0]==$text) {
echo "looking for: ".$ar_data[1]."\n";
}
}
Example usage:
$ php test2.php
looking for: answer1
The text fileis not a good way for verify user credentials. You should try sql database. sqlite3 for example.
You can just hard code them in an array:
$passwords = ['someuser' => 'password'];
If you really want to store them in a file, so you can change them (for example) without editing the code, One way is to use something like this:
$passwords = ['someuser' => 'password'];
file_put_contents('passwords.php', '<?php return '.var_export($passwords,true).';');
This will create a file with something this in it (white space not withstanding):
<?php return array('someuser' => 'password');
Then when you need to import it into code you can simply use
$passwords = require 'passwords.php';
Which will put the contents of that file into that variable. Then you can check them really easily like so:
$passwords = require 'passwords.php';
if(isset($passwords[$user]) && $passwords[$user] == $password){
//do something when logged in
}
You can also modify the array and then save it:
$passwords = require 'passwords.php';
$passwords['someuser'] = $new_password;
file_put_contents('passwords.php', '<?php return '.var_export($passwords,true).';');
Of course you can even edit the passwords manually in the file. Sort of like a config file.
As I mentioned in the comments, it's better to use the DB, encryption and what not but as you said
this is only for me and someone else
As long as you don't have any third party data, and your ok with the security implications of this, then you can probably squeak by with the above.
To explain it:
Var Export converts arrays to valid PHP code, but in a string format. Then if we add the PHP open tag <?php, the return call return and the ending ; to it and save it in a PHP file, we now have a valid PHP file with dynamic passwords saved in it as an array.
When you have such a file that returns an array, you can inject that into a variable just by setting it like I showed above. Then it's a simple matter of checking to see if everything matches up.
Performance wise your offloading most of the penalty of this to saving the file, importing an array like this is very fast as is the key lookup. Much faster then iterating though a file and trying to parse the data from it.
You'll have to get the paths and filenames right and all that Jazz, but it should be pretty strait forward.

Writing values to INI file

I'm trying to store multiple data and then at the end go a head and push the data into the new .ini file. I found solutions which works but I want to get all the data first and then update the file at the end but the solutions i found updates the file straight away!
A solution I liked and worked is located: https://stackoverflow.com/a/36997282/6613233
I am trying to allow it gather information and then push it to the file at the end. My own attempt at this is below but i keep getting array array in my ini file.
Code:
$fbsettingsDB = parse_ini_file("location.ini", true);
$fbsettingsDB["id"]["value"] = $_POST['fbconfigid'];
$fbsettingsDB["location"]["value"] = $_POST['fbconfigcty'];
file_put_contents('location.ini', implode("\n", $fbsettingsDB));
The above is how I want to collect data. I have a bunch of code which goes in and out of statements, I want it to go ahead.. Assign the values required and at the very end go ahead and put the contents in the file like shown above.
Using the referred code i would then have to do:
config_set("location.ini", "id", "value", $_POST['fbconfigid']);
config_set("location.ini", "location", "value", $_POST['something']);
config_set("location.ini", "result", "value", $_POST['somethingelse']);
Which overwrites the file every time which in my opinion is just crazy! Overkill for my idea, there is obviously some way that can suit my needs so i can just call the function once after making a list of edit/changes and then when i call the function it grabs all my changed data and saves the file the way i want it!
I'll try to explain first why your code doesn't work, compared to the other.
Your inifile-array is build up of a nested array, $array[section][item] = value. The first dimension has the section names. The second dimension is the name of the items in the sections. So $fbsettingsDB["location"] contains an array of items, of which "value" is one.
Implode doesn't check if the array is nested. It just takes the first dimension (the sections) and tries to treat their values as a string. Since those values are actually arrays of items, PHP just converts that to the text 'array'.
Apart from that, you can't just implode the whole array. Section names should be enclosed in square brackets, so there is a little more work to do in that regard too.
If you check the solution in the answer you referred to, you'll see that it contains a loop which takes care of the first layer, the sections.
The array of items of each section is converted separately with implode, which is then prefixed by the section name in square brackets, and the whole lot is appended to the end result.
So, your intention here: You don't want to set a value and write it back to file at once, but update multiple values and only write the end result to disk. Well, fortunately the function doesn't have to be atomic. It already performs three separate actions: loading from disk, modifying the data, and serializing it back to disk. Let's see if those can be isolated in separate functions:
Read the data. Well, hardly worth to make a function, but it may make your application somewhat more consistent if you use the same naming et cetera in a collection of related functions.
Note: I just wrote these from scratch. No PHP at hand to test, so they might contain minor syntactical errors.
So here it is:
// Loads ini file data
function config_read($config_file) {
return parse_ini_file($config_file, true);
}
Setting the config in the loaded data. Again, hardly worth to have a function, but it adds readability and hides how exactly the ini file data is built up, so you don't have to worry about implementation details when using it. Note that the array is passed by reference. The array you specify is updated. The function doesn't return a value.
// Update a setting in loaded inifile data
function config_set(&$config_data, $section, $key, $value) {
$config_data[$section][$key] = $value;
}
Then writing it:
// Serializes inifile config data back to disk.
function config_write($config_data, $config_file) {
$new_content = '';
foreach ($config_data as $section => $section_content) {
$section_content = array_map(function($value, $key) {
return "$key=$value";
}, array_values($section_content), array_keys($section_content));
$section_content = implode("\n", $section_content);
$new_content .= "[$section]\n$section_content\n";
}
file_put_contents($config_file, $new_content);
}
Note that so far I didn't modify any of the code. I just wrapped it in separate functions. If you like, you could even call those functions in another function, so you still got the shorthand to write everything to disk at once. You'll have the original functionality, but without having duplicate code:
// Short-hand function for updating a single config value in a file.
function config_set_file($config_file, $section, $key, $value) {
$config_data = config_read($config_file);
config_set($config_data, $section, $key, $value)
config_write($config_file, $section, $key, $value);
}
So, now you got this collection of functions, you can decide which to use based on the situation. If you just want to update a single value, you might as well write this:
config_set_file("location.ini", "id", "value", $_POST['fbconfigid']);
But if you have multiple configs to set, you can do this:
// Load
$config_data = config_read("location.ini");
// Set multiple values
config_set($config_data, "id", "value", $_POST['fbconfigid']);
config_set($config_data, "location", "value", $_POST['something']);
config_set($config_data, "result", "value", $_POST['somethingelse']);
// Save
config_write($config_data, $config_file);
I can imagine you can add other shorthands, like config_set_array_file, which you could call like this.. I'll leave the implementation of this one to you for exercise. ;)
array_config_set_file($config_file, array(
"id" => $_POST['fbconfigid'],
"location" => $_POST['something'],
"result" => $_POST['somethingelse']));
And after that, you can poor all this into an IniFile class to make it even nicer. :)

PHP - Use a URL Key to get data from a separate file not normally index

I'm not a PHP dev and I have little experience with it. I ask for your forgiveness and assistance.
Here's my problem:
I have a script and I need to be able to append a 'key' (I don't know what else to call it) like:
http://my-web-address.com/packages.php?key=secret
When this key is present, I need to run the code responsible for extracting the data from a .json file in a separate directory. (Normally, the code wouldn't index this directory. It should only indexes it when the key is present in the URL.)
I believe this code to be the foreach section in the link above.
I'm having a hard time explaining this in a way that makes sense, so I guess it's easier to show you what I mean.
I know it should be easy; at first I thought I could simply do it with something like this:
if ($key == "secret") {
$document['packages'][] = getPackageData("secretdirectory/secret.json");
}
But alas, simply appending that didn't make it work.
Any ideas?
As Ron Dadon said, but with a slight modification:
sanitize($value) {
// Sanitize the key - see below
return $value;
}
$key = sanitize($_GET['key']);
if ($key == "secret") {
$document['packages'][] = getPackageData("secretdirectory/secret.json");
}
However you should sanitize that input, as anyone can change the key. Here are some resources on that:
Clean & Safe string in PHP
Remove all special characters from a string
The ultimate clean/secure function
You need to use the GET array:
if ($_GET['key'] == "secret") {
$document['packages'][] = getPackageData("secretdirectory/secret.json");
}

PHP - make $_FILES filenames safe

I have an form that contains an "attachments" field, allowing a user to add multiple attachments. Each attachment is then uploaded but before doing so, each file name is made safe using the following function.
function safeFile($file) {
$lower = strtolower($file);
$trim = rtrim($lower, '.');
$regex = array('#[^A-Za-z0-9\.\_\- ]#');
return trim(preg_replace($regex, '', $trim));
}
So far so good.
I'm then json encoding the file names to store in the database. using the following:
json_decode($_FILES['attachment']['name']);
This outputs the following in the database:
["FILE.jpg", "OTHER.jpg"]
This works, however I'm also trying to call the safeFile() function so that the same action is applied before inserting into the database as it does when uploaded.
I tried using the following which did not work.
json_encode( safeFile($_FILES['add_attachment']['name']) );
To get around this, thinking logically, would I have to create a foreach loop, then making each individual file name safe, then return an array?
Could someone please shove me in the right direction?
You don't need a foreach loop
You need to use array_map() like this
array_map("safeFile", $_FILES['add_attachment']['name']);
Also, what I think you need to be using is json_encode() not json_decode

How to make a zipped download with files that exist in a database?

I want to make some kind of user panel for my users - after they will update the info on the panel it will make a new row for them in the database with an original source code which i build but with the edited fields they made.
Example:
UserName: [_______]
PageID: [_______]
They fill it in and the when they press update it will automatically insert the data to a pre-made code to a new field in the table.
<?php
$username = ? (whats the best way to insert UserName textarea value in here?)
$pageid = ? (whats the best way to insert UserName textarea value in here?)
?>
Now that was the first question: whats the best way to insert UserName textarea value in here?
The Second question is how to Auto Encrypt this on insert (I don't care about the way it will be encrypted, even if it will not be IonCube encrypted it will be fine)
And the last and the most important question is how to make an automatic function that when they will press "Update" will automatically make files from the SQL field and prompt them to download the zipped files with their files (I don't want to store any of those files on my server because they may interrupt one with the other cause there may be 100 users doing this action at the same time)
Guys trust me i has been looking for this answers all over the net and didn't found a thing.. (I found EVERYTHING i need except this stuff).
Thanks for future assistance guys!
Best Regards, Rico S.
1) The best way to do it is by using some sort of formatting like
Put you template like this
$template = "whats the best way to insert %%UserName%% %%textarea%% value in here.";
And then create an array with like
$trans = array ("%%UserName%%" => $username, "%%textarea%% => $textarea);
Then use php's strtr function to convert it
$data_to_store = strtr($template, $trans);
2) You can find a lot of encryption and decryption algorithms and php classes for doing that check out PHP Classes.
3) You could try this. But i am not 100% sure if its works properly.
Use PHP's ZipArchive Directory
And then load the content's into a string
then
<?php
header('Content-Disposition: attachment; filename="downloaded.pdf"');
$zip = new ZipArchive;
$res = $zip->open('php://stdout', ZipArchive::CREATE);
if ($res === TRUE) {
$zip->addFromString('file.txt', $content_populated_from_db);
$zip->close();
echo 'ok';
} else {
echo 'failed';
}
exit;
?>
I hope this works, If it didn't try changing the flags of ZipArchive::open. And if it didn't work then also. In that case let me know, with you code and i might be able to help you. As of this point, i havn't tried it.

Categories