file path is not retrieved in codeigniter - file

I am creating an invoice on users desired package selection. The pdf file is being created (but it takes some time), while the code checks for the file. The file exists. Here is the address of the file;
C:/wamp/www/proposal/file/invoice/Basic_52_60.pdf
This is the correct path to the file. I am passing this path to the function in another controller as;
redirect('email/email_invoice/'.$file);
When I tested the file path in email_invoice function, it displayed only c:
c:
The slashes in the path are not transferred. I don't know exactly what is the problem.

CodeIgniter considers each segment of the URL a parameter after the controller and method. So you are essentially passing 7 variables to the Email::email_invoice() method.
You could use some sort of encoding to pass it as one variable and then decode it on the other side such as:
$file = base64_encode($file);
redirect('email/email_invoice/' . $file);
Then in Email.php:
public function email_invoice($file) {
$file = base64_decode($file);
}
Or you could pass it as a get parameter:
redirect('email/email_invoice/?file=' . $file);
public function email_invoice() {
$file = $this->input->get('file');
}
The latter requires the $_GET array to be enabled which it is not by default.
UPDATE - Using Flashdata
Based on some of the comments I thought I would update this answer. base64_encode() can result in characters that will break the URL so you would need to use:
$file = urlencode(base64_encode($file));
redirect('email/email_invoice/' . $file);
And on the other side:
public function email_invoice($file) {
$file = urldecode(base64_decode($file));
}
As the OP pointed out $_GET variables can be manipulated leaving you open to directory traversal attacks or other vulnerabilities. Even if done right you would need extra code for security. Encoding can easily be spotted and altered.
File paths probably shouldn't be carried around in the URL. POST data can be manipulated also even if it is less obvious. Security through obscurity is not security at all. A better approach would be to use flashdata.
$this->session->set_flashdata('email_invoice_pdf', $file);
redirect('email/email_invoice/');
Then in your controller:
public function email_invoice() {
$file = $this->session->flashdata('email_invoice_pdf');
}
That's it. The session was used to carry the file path to the next page request, but after that it is gone.

Related

How to read a text file from resources without javaClass

I need to read a text file with readLines() and I've already found this question, but the code in the answers always uses some variation of javaClass; it seems to work only inside a class, while I'm using just a simple Kotlin file with no declared classes. Writing it like this is correct syntax-wise but it looks really ugly and it always returns null, so it must be wrong:
val lines = object {}.javaClass.getResource("file.txt")?.toURI()?.toPath()?.readLines()
Of course I could just specify the raw path like this, but I wonder if there's a better way:
val lines = File("src/main/resources/file.txt").readLines()
Thanks to this answer for providing the correct way to read the file. Currently, reading files from resources without using javaClass or similar constructs doesn't seem to be possible.
// use this if you're inside a class
val lines = this::class.java.getResourceAsStream("file.txt")?.bufferedReader()?.readLines()
// use this otherwise
val lines = object {}.javaClass.getResourceAsStream("file.txt")?.bufferedReader()?.readLines()
According to other similar questions I've found, the second way might also work within a lambda but I haven't tested it. Notice the need for the ?. operator and the lines?.let {} syntax needed from this point onward, because getResourceAsStream() returns null if no resource is found with the given name.
Kotlin doesn't have its own means of getting a resource, so you have to use Java's method Class.getResource. You should not assume that the resource is a file (i.e. don't use toPath) as it could well be an entry in a jar, and not a file on the file system. To read a resource, it is easier to get the resource as an InputStream and then read lines from it:
val lines = this::class.java.getResourceAsStream("file.txt").bufferedReader().readLines()
I'm not sure if my response attempts to answer your exact question, but perhaps you could do something like this:
I'm guessing in the final use case, the file names would be dynamic - Not statically declared. In which case, if you have access to or know the path to the folder, you could do something like this:
// Create an extension function on the String class to retrieve a list of
// files available within a folder. Though I have not added a check here
// to validate this, a condition can be added to assert if the extension
// called is executed on a folder or not
fun String.getFilesInFolder(): Array<out File>? = with(File(this)) { return listFiles() }
// Call the extension function on the String folder path wherever required
fun retrieveFiles(): Array<out File>? = [PATH TO FOLDER].getFilesInFolder()
Once you have a reference to the List<out File> object, you could do something like this:
// Create an extension function to read
fun File.retrieveContent() = readLines()
// You can can further expand this use case to conditionally return
// readLines() or entire file data using a buffered reader or convert file
// content to a Data class through GSON/whatever.
// You can use Generic Constraints
// Refer this article for possibilities
// https://kotlinlang.org/docs/generics.html#generic-constraints
// Then simply call this extension function after retrieving files in the folder.
listOfFiles?.forEach { singleFile -> println(singleFile.retrieveContent()) }
In order to have the same url that work for both Jar or in local, the url (or path) needs to be a relative path from the repository root.
..meaning, the location of your file or folder from your src folder.
could be "/main/resources/your-folder/" or "/client/notes/somefile.md"
The url must be a relative path from the repository root.
it must be "src/main/resources/your-folder/" or "src/client/notes/somefile.md"
Now you get the drill, and luckily for Intellij Idea users, you can get the correct path with a right-click on the folder or file -> copy Path/Reference.. -> Path From Repository Root (this is it)
Last, paste it and do your thing.

File system path for images

I'm writing a custom helper that extends HtmlHelper and overriding the \HtmlHelper::image() method to calculate the image dimensions and add them as HTML attributes. What I have so far works fine for regular pictures:
public function image($path, $options = array()) {
if (!array_key_exists('width', $options) && !array_key_exists('height', $options)) {
$stamp = Configure::read('Asset.timestamp');
Configure::write('Asset.timestamp', false);
$path = $this->assetUrl($path, $options + array('pathPrefix' => Configure::read('App.imageBaseUrl')));
list($width, $height) = #getimagesize(rtrim(WWW_ROOT, '\\/') . $path);
if (!is_null($width)) {
$options['width'] = $width;
}
if (!is_null($height)) {
$options['height'] = $height;
}
Configure::write('Asset.timestamp', $stamp);
}
return parent::image($path, $options);
}
… but has these flaws:
Pictures from plug-ins can't be located on disk (and they should), e.g.:
echo $this->Html->image('/debug_kit/img/cake.icon.png', array('alt' => 'CakePHP'));
… produces this file system path:
…\src\webroot/debug_kit/img/cake.icon.png
… thus getimagesize() fails because actual location is:
…\src\Plugin\DebugKit\webroot\img\cake.icon.png"
External pictures (which should be ignored) go through the full process:
echo $this->Html->image('http://placekitten.com/200/300');
…\src\webroothttp://placekitten.com/200/300
I've been looking for a builtin method to convert a CakePHP picture URL (in any format accepted by \HtmlHelper::image() into a file system path (o something like null when doesn't apply) but I couldn't find any. Native features that need a disk path, such as \Helper::assetTimestamp() are wrapped in tons of non-reusable code.
Is there an elegant solution?
I'd say that there are pretty much only 3 options:
Submit a patch to add asset filesystem path retrieval functionality to the core.
Copy a lot of code from the helper (assetUrl(), webroot(), and assetTimestamp()).
Use web requests for local URLs (ideally combined with caching).
Try using DS rather than using \ or /, they sometime can cause problems with the OS.
DS is directory separator provided by cakephp Short for PHP’s DIRECTORY_SEPARATOR, which is / on Linux and \ on Windows.
Check the doc

Can I use same param name multiple times in the URL for codeigniter-restserver?

http://example.com/api/transfer/transfers/code/456/code/234
When using $this->get('code') on a url like above I expect the REST library to return an array or a list of the codes.
Instead it returns the last one.
Is there a way to return both values in a list, or is there another recommandation for formating the URL.
Thank you
I know it has been long since you posted the question. However it could help other people looking for the same thing.
Assuming that transfer is your controller and transfers is the function, another way to format your url could be:
http://example.com/api/transfer/transfers?code[]=456&code[]=234
This was you perform $this->get('code') you'll get an array back.
If you are creating the url via code then you may use http_build_query(). It handles the necessary escaping. It means it will replace [ for %5B and ] for %5D, in this case.
The code would be like:
$codes = array(456, 234);
$query = http_build_query(array('code' => $data));
$url = 'http://example.com/api/transfer/transfers?' . $query;

Cakephp ghost file

I am facing a curious situation. I am using CakePHP 2.0 (locally), XAMPP and I wanted to add a simple hit counter in my homepage so I added the following code (very very simple)
<?php
$filename = 'hitcount.txt';
$handle = fopen($filename, 'r');
$hits = trim(fgets($handle)) + 1;
fclose($handle);
$handle = fopen($filename, 'w');
fwrite($handle, $hits);
fclose($handle);
echo $hits;
There is a text file named hitcount.txt which contains the number of hits (everytime I visit the page it should increase the number of hits). It works. The problem appeared when I tried to access the hitcount.txt file. It was empty but the echo of $hits returned the exact result! I deleted the file and it still shows me the expected result! I used a different browser, the same. I deleted CakePHP's cache, no change. I used the same piece of code in another page and it did not complain with some error, returning the expected result.
How is it possible for Cakephp to "see" a file that does not exist? Has it anything to do with Apache?
You probably view the file at the wrong location as CakePHP's. My guess is CakePHP's referring to the file at app/webroot/hitcount.txt.
You might want to define a full path for hitcount.txt so you can be sure that you and CakePHP are both referring to the same location.
<?php
$filename = TMP.'hitcount.txt';
This would locate the file at `app/tmp/hitcount.txt'.

drupal 7 file field formatter on custom node for javascript (to set up jQuizMe)

I have set up a module with custom node type (I called jquizme, after the javascript jQuizMe that I really like using). I set up two fields for the javascript files I need to supply to make it work (after the general jQuizMe-2.2.js file you need to add another two javascript files - one for settings and one for the quiz content).
Drupal saves the files as myjavascriptfile.js.txt - I tested them and they still work to make the jQuizMe interface - ok. the problem is, I want to add these files on the node page... the files will be different for each node. how can I access the files for the drupal_add_js() function so they will load the files for the node in question?
I tried setting up custom field formatters, but I don't know how to access the uri for the files of a given node automatically to put in the drupal_add_js() function (I can add a static file and it loads fine ... I did this with hook_node_view ( jquizme_node_view ).
So I just need a way to access the info for the files... how are they linked to each node? I can't find the connection.
As you probably noticed, I am a module writing newbie, and I probably won't understand much related to object oriented programming sorry, haven;t progressed to that level yet), but I am open to any answer. I am sure I left out important info, but this it already getting too long.
I also set up a special page earlier on to just see if I could get jQuizMe to work in Drupal so that is still in the code.
I have tried many answers (last six hours or so... too much to say here), the latest of which is using tokens, but that is not working. Here is what I have so far:
function jquizme_node_view($node, $view_mode, $langcode) {
switch ($node->type) {
case 'jquizme':
$items = field_get_items('node', $node, 'field_myfield', $node->language);
drupal_add_css(drupal_get_path('module', 'jquizme') . '/jQuizMe.css', >array('scope' => 'header'));
drupal_add_js(drupal_get_path('module', 'jquizme') . '/alert.js');
drupal_add_js(drupal_get_path('module', 'jquizme') . '/jQuizMe-2.2.js', >array('scope' => 'header'));
//drupal_add_js($tokens['node']['jquizme_js1_field'], array('scope' => >'header'));
//drupal_add_js($tokens['node']['jquizme_js2'], array('scope' => 'header'));
break;
}
}
Thanks in advance!
Can you try this?
// Let me assume that the field names of your two file fields
// are jquizme_js1_field and jquizme_js2_field for convenience..
function jquizme_node_view($node, $view_mode, $language) {
$items = field_get_items('node', $node, 'jquizme_js1_field');
_jquizme_add_js_from_filefield($items);
$items = field_get_items('node', $node, 'jquizme_js2_field');
_jquizme_add_js_from_filefield($items);
}
// Given the values of a filefield attached to some entity,
// adds them as JS files to the page.
function _jquizme_add_js_from_filefield($items = array()) {
foreach ($items as $item) {
$fid = &$item['fid'];
$file = file_load($fid);
if (!$file) {
continue; // Maybe the file got deleted..
}
$wrapper = file_stream_wrapper_get_instance_by_uri($file->uri);
$path = $wrapper->realpath();
// Ensure that the path exists and that it is a Javascript file..
if (file_exists($path) && preg_match('\.js$', $path)) {
drupal_add_js($path, array('type' => 'file'));
}
}
}

Resources