Validating Uploaded Files Server Side - php

I have some CSV files that I need uploaded to a site I'm writing in CodeIgniter.
I need to validate the CSV to make sure they contain various info, column counts match up and stuff like that.
Does CI have any sort of plugin to make this easy?

After the file is uploaded, open it and use fgetcsv to go through it line by line.
http://us3.php.net/manual/en/function.fgetcsv.php
It creates an array (in that link, the array in the first example is called $data), if you are looking for column count, you can find it with sizeof($data). If you need specific column content or types, you can use a wide variety of regex to figure it out. Say column 3 has to be an email address:
$column_size = 8;
while($data=fgetcsv($p))
{
if ( sizeof($data) < $column_size )
{
// handle wrong column count error here
}
if ( !is_email($data[2] ) // is_email is a fictional function
{
// handle error here
}
// other checks...
}
I don't know if there is a CI plugin for it, but it probably couldn't make it much easier anyway.

Related

Storing multiple artist info from API into file (PHP)

I really need help. I'm using an API to gather artist information depending on the artist name ($artist_name = $_GET['artistname']).
I need to add the API results into an array and store it into a file (NOT a database). This file will be ever growing as more and more artist entries are added to it.
Once I have an array in the file, I need to be able to read it and parse it. That way I can display the information without repeatedly using the API.
I have figured out how to add an array to a file with one entry, but how can I add more keys into the same array?
This is what I'm using now...
//ARRAY
$artist_info_location_array = array($artist_name => $location_entry);
//FILE
$artist_location_file = get_template_directory()."/Database/Artists/info-location.json";
//GET ARRAY FILE
$get_location_array[] = json_decode(file_get_contents($artist_location_file), true);
if (is_array($get_location_array)) {
if (!array_key_exists($artist_name, $get_location_array)) {
file_put_contents($artist_location_file, json_encode($artist_info_location_array));
}
}
It prints this to the file:
{"Imagine Dragons":"Las Vegas, NV, US"}
That's cool, but I need to be able to add more artists to this SAME ARRAY. So the result should look like this with another artist added:
{"Imagine Dragons":"Las Vegas, NV, US", "Adele":"London, UK"}
That shows Imagine Dragons and Adele both added to the same array.
Can someone help me "append" or add extra keys and values to the same array as they are added to the file?
Thanks.
EDIT 1 (In response to Martin):
I have a panel on the side of the page in question. This panel will show relevant information about the artist that has been searched for. Let's say you search for the artist "Adele". $artist_name would = Adele.
Lets say I'd like to store all artist locations, I would use the example I posted to store each artist location in the file called info-location.json ($artist_location_file).
So every time an artist page is loaded, the artist name and location would be added to the array in the file.
If my example doesn't make any sense, please show me an example on how to add multiple entries into ONE ARRAY. I am using an API and would like to cache this information to use instead of requesting the API on each load.
Hope this makes sense. :)
I might be misunderstanding your question, but if you just want to read in a json file, add an associative array key to it if it does not exist and then put it back into the json file why dont you do something like this:
if (is_array($get_location_array)) {
if (!array_key_exists($artist_name, $get_location_array)) {
$get_location_array[$artist_name] = $location;
file_put_contents($artist_location_file, json_encode($artist_info_location_array));
}
}
file_put_contents will overwrite an existing file (pretty sure). But your best option is to use a database. If you can't do that, then I suggest to prevent writing to the file while you are doing this I suggest you use fopen, flock, and fwrite and then fclose

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 can I make this PHP code more efficient? (Editing a line in a CSV file)

This code works, but I just hacked it together with my limited knowledge of PHP and I'm sure there's a more elegant and efficient way to go about it. If you'd be so kind as to point out how I can improve, that would be great!
So I have a CSV file, structured like so:
Code Class Value Status Date Created Date Redeemed
========================================================================
a51f3g45 gold 50 valid 2012-08-20
4f6a2984 silver 200 redeemed 2012-08-23 2012-08-27
gf3eb54b gold 150 valid 2012-08-30
etc...
The user fills out a form to change the Class, Value, and Status fields of a given line. I cobbled together the following code to replace the old values with the new ones:
$file = 'codes.csv';
$old_csv_string = file_get_contents($file);
preg_match('/('.$_POST['code'].',.*,.*,.*,.*,.*)\n/',$old_csv_string,$matches);
$old_row = $matches[1];
preg_match('/'.$_POST['code'].',(.*,.*,.*),.*,.*\n/',$old_csv_string,$matches_part);
$old_row_part = $matches_part[1];
$new_row_part = $_POST['class'].",".$_POST['value'].",".$_POST['status'];
$new_row = str_replace($old_row_part,$new_row_part,$old_row);
$new_csv_string = str_replace($old_row,$new_row,$old_csv_string);
file_put_contents($file,$new_csv_string);
So can I do better than 10 lines of code? Any advice would be greatly appreciated :)
Note: I tried using fgetcsv, but I couldn't figure out how to find the unique code within a 2D array, then replace its siblings.
Why are you doing this ?
I think you should store the data in a SQL table.
Each time user update data, do it in the table.
If you want the CSV to be downloadable at any moment. Use a .htaccess to redirect your.csv to csv_generator.php only if your.csv does not exist.
csv_generator.php will regenerate the whole csv if it does not exist, save it on hard drive for later use, and send it with correct mime/type in header (so it's transparent for user). User don't see he is requesting a php page.
Then you need to delete the csv on hard drive each time someone update the data (so it will be regenerated on next request)
I think this is the way to have an always ready to download csv online.
Do you know google doc does this ? Users can change data in a spreadsheet wich is available to download as a csv from a url (you need to publish this spreadsheet as a csv file).
Try using split like that for each line:
list($code, $class, $value, $status, $created, $redeemed) = split(",", $line, 6) ;
Thus you will have each field in separate variable.
Of course you need to take care of the first row in case you don't want to copy header.

Vaildate a Zip code against a list

I want to have a form on my intranet site... basically we are a home improvement company and have a list of bad area codes that we do not do business in ... IE list of bad zips 19020 19021 etc are bad so if they are I want it to return with a popup which says bad area ... if it is not on the list I want it to say Good Area
You haven't given too much information, so what follows is a very general solution. One way to approach this is to have two maps called badZips and goodZips:
var badZips = {
"19020": true,
"19021": true
...
};
var goodZips = {
"90210": true,
...
};
Then in your form-validation function, you can do:
if(badZips[zip]) {
alert("You entered a bad zip code");
}
else if(goodZips[zip]) {
alert("You entered a good zip code");
}
else {
alert("That zip code is not recognized");
}
Actually creating the maps depends on how your webapp is set up. How do you store the zips - is it in the database? Or have you hardcoded it?
Using apache, install geoIP. Echo their zipcode into a javascript function, which compares to a black-list you created.
http://www.maxmind.com/app/ip-location
Your functional requirements are pretty simple but you didn't really mention what setup you have. Do you want this functionality to happen on a form? What are you going to code with? Do you have a database? Based on the tags you've used I'll just assume that you don't have a database.
Basically you can have a list of area codes and a flag for each to indicate if it's a bad or a good code. You can keep this list in a multi-dimensional array in PHP as static data (http://www.webcheatsheet.com/PHP/multidimensional_arrays.php).
So it might look something like:
<?php
$areaCodes = array( array('aCode'='19020','aFlag'=>true),
array('aCode'='19021','aFlag'=>true),
array('aCode'='19022','aFlag'=>false)
);
?>
When you need an area code to be validated, just do a search in the array and check the flag to see if it's a good code or a bad code.
Store the zip codes in an array, then check if the given zip is in the array.
<?php
$BadZip = array("19020", "19021");
if (in_array($Zip, $BadZip))
{
echo "Bad Zip code!";
}
?>
If in_array returns true, then the zip code is in the list of bad zips.
Alternatively you could use the same method with a list of good zips.

How can I write this Drupal snippet more efficiently?

I'm working on a patch to submit to the Registration Code module for Drupal. In short, is there a more efficient way to write the code below?
if (module_exists('regcode_voucher')) {
$cnfg = variable_get('regcode_voucher_display', array('regform' => 'regform'));
if (empty($cnfg['regform'])) {
return;
}
}
It seems like I should be able to reduce it to one if statement with && combining two conditions, but I haven't found the syntax or the necessary php array function that would allow me to do that.
In case some context helps, the regcode_voucher sub-module allows users to enter their registration code on the user edit page. On our sites, after a "beta" period, we want to simplify the registration form by removing the registration code field; but we'd like users to still be able to enter the code on their account edit page. The code above is part of a patch that allows the regcode's hook_user changes to be bypassed.
Code looks like good, what efficient do you want? Little changes may be:
if (module_exists('regcode_voucher')) {
$cnfg = variable_get('regcode_voucher_display', null);
if ($cnfg) {
// do your actions
}
}
And I don't recommend to merge if..., code should be clear and simpler to understand. If you merge these for optimizing, you win "tiny" milliseconds for real-live processors, but lost your clean code.
Why are you returning an array from variable_get if the variable is not found? variable_get will always return a string or a serialized array (that needs to be unserialized). If I'm missing something, you can use array_key_exists('regcode', variable_get(...)) to check for the array key.
This should work... note returning "false" from variable_get as a default if the variable is not found, which will cause the if conditions to not match. I personally find this more readable than nested if statements (for 3+ conditions I'd nest, though).
if( module_exists('regcode_voucher') && variable_get('regcode_voucher_display', false) ) {
// stuff
}

Categories