Perl - open with relative path Apache - apache

We recently inherited a somewhat legacy perl application and we're working to migrate to a new server as well as setup a sandbox environment so we can start sorting the application out. The issue we're having is the code currently uses some relative paths for the open method. And currently works in their shared hosting environment (we have little access to)
open(HANDLE,"<../relative/path/to/file.txt")
We pulled all of the code, paths, etc. over and for the most part have the application up and running until we run into one of the scripts that does the above, opens a file with a relative path. Then it fails.
If we run the code via the command line, the relative paths work. If we modify the path to be the full path it works both via command line and through Apache (navigating to the page in the browser).
This makes me think there is some module or configuration option we need to set in Apache to allow for the perl scripts to access or use the open command with relative paths?

Relative paths are relative to the process's current work directory, which is not necessarily the same as a the directory containing the program. It fact, it's often / for daemons (and thus their children).
For paths relative to the program's location, use
use FindBin qw( $RealBin );
my $qfn = "$RealBin/relative/path/to/file.txt";
open(my $HANDLE, "<", $qfn)

As mentioned in the comment above. Our final solution was to use:
File::Basename qw( dirname );
chdir(dirname($0));
This allowed us to get the code working while also kept additional code modifications to a minimum.

I was running a script out of cgi-bin and wanted to open a template in htdocs/templates so I did this in my script...
# open the html template
my $filename = sprintf("%s/templates/test.tmplt", $ENV{DOCUMENT_ROOT});
my $template = HTML::Template->new(filename => $filename);

It is bad practice to specify file's path in open with a fixed string unless the path is predefined and never change - as for example with /etc/fstab in linux.
You should change the code to use variable(s) instead.
Define variable at the top of the script -- in feature if you need to change base and path you will know that you find it at the few first lines of the code.
In such situation add temporary in the code something as
use strict;
use warnings;
open( my $fh, '>', 'my_uniq_file.txt')
or die 'Couldn\'t open my_uniq_file.txt';
print $fh 'This directory is default base for path location';
close $fh;
Once you run your script from webserver you should look for the file my_uniq_tile.txt -- it's location will be default base of web server for the file(s) location.
Now adjust variables with file path accordingly.
use strict;
use warnings;
my $dir_project = './project_1/';
my $audio_data = 'audio_data.dat';
my $video_data = 'video_data.dat';
my $descr_data = 'descr_data.dat';
my $qfn = $dir_project . $audio_data;
open(my $fh, '<', $qfn)
or die "Couldn't open $qfn";
while( <$fh> ) {
chomp;
[do something with data]
}
close $fh;

Related

Laravel move url downloaded file to storage clean solution

Problem statement
I am using Laravel Framework 8.83.23
being given an url, a file A gets downloaded using wget to a file system
A brief example just to get an idea:
$cmd = sprintf(
'"%s" --no-check-certificate "%s" -O "%s" 2>&1',
$wgetPath,
$url,
$filePath
);
$ret = exec($cmd, $output, $result_code);
the wget is executed using exec() on a linux file system
file A then needs to be moved to a Storage, let's call it Storage::disk('posters')
I want the Storage facade to handle the file, because, for example, if wget would download the file directly to the storage path using known file system path string, the Storage facade would not be triggered - you no longer can use Storage::fake('posters') in tests, because the file would get downloaded to the same directory, not the fake one
Proposed solution idea
I create a new disk, called Storage::disk('temp')
the wget will download the file to that directory (disc) using string path. The Storage facade will not trigger using code like storage_path(sprintf("app{$DS}temp{$DS}%s.%s", $fname, $extension)); where $DS is directory separator
then, move the file from Storage::disk('temp') to Storage::disk('posters')
working code
Storage::disk('posters')->put(
$fName . '.jpg',
Storage::disk('temp')->get($fName . '.jpg')
);
the code above will use the Storage facade, and therefore, Storage::fake('posters') can be used in tests
Question
is there a cleaner solution you would propose? Creating a new storage disc for temporary files directory does not seem clean to me
I am not sure, whether there is some temporary storage already available for me to use?

PhantomJS -headless browseer

I have to automate a test case in which a list in a particular dashboard is created. We decided to use PhantomJS headless browser. Since I am new to it, I tried creating test myself. Following are the steps I followed just to open the target website.
Created directory phantoms
cd phantoms and installed phantom module using command npm install phantom --save
Created file createlist.js:
createlist.js contents:
var phantom = require('phantom');
var page = require('webpage');
page.open('http://facebook.com', function(status) {
console.log("Status: " + status);
if(status === "success") {
page.render('example.png');
}
phantom.exit();
});
When i execute command node create_list.js, I am getting the following error:
page.open('interact2.responsys.net/interact/jsp/jindex.jsp&#‌​39;, function(st atus) { ^ TypeError: page.open is not a function at Object.<anonymous> (C:\Users\shilshet\New folder\phantom\create_list.js:3 :6) at Module._compile (module.js:413:34)
If I try to execute command like
phantomjs C:/Users/shilshet/New folder/phantom/create_list.js
I am getting this error
bash: phantomjs: command not found
Note: I am using cygwin to execute commands
What I am going wrong? I installed phantomjs module also in the same folder as my node.js.
Could anyone let me know apart from using headless browser, how does one create a profile list in Oracle responsys via REST API call?
While the first answer here should work, it's not the best way to accomplish what you need. The cleaner way to solve your issue is to add the location of your phantomjs executable to your PATH variable defined in a file such as ~/.bash_history.
The file may not be defined, so you may need to create the file, and then add PATH="/path/to/phantomjs/executable"
If you prefer to edit your PATH var via a GUI: Edit PATH variable via Windows GUI
The reason you need to do this, is that your system natively iterates over paths defined in the 'PATH' variable in order to determine where executable files are. Since phantomjs is not included in the PATH variable (nonexistent in the environment), and you try to run 'phantomjs', your system simply does not know which executable to call (or rather it doesn't know it exists)
The reason this is the better approach is:
You don't need to explicitly write out the path of where phantomjs is located every time you want to run it (it's just cleaner looking too)
What happens if you you call phantomjs from multiple files, and the location of where phantomjs is stored changes? If you explicitly typed phantomjs' absolute path everywhere, then you need to change EVERY place you typed it! Nightmare! With this approach, you simply change it in one place; the file that defines your PATH variable
It's pretty conventional to add new file paths to your PATH env variable. You shouldn't clutter it, but it makes sense in this case to add it
For this: "Could anyone let me know apart from using headless browser, how does one create a profile list in Oracle responsys via REST API call?"... I would recommend asking a separate question. I personally don't know, but if you raise the new question, you may get support from someone who does.
Hope this helps! If you need any help whatsoever, let me know.
You mixed up two ways of running PhantomJS.
The more straightforward, more simple way is just launching PhantomJS from command line and giving it the path of a script as an argument. On Windows you would do it like this:
"C:/Users/shilshet/New folder/phantom/phantomjs.exe" "C:/Users/shilshet/New folder/phantom/create_list.js"
Note the quotes here, they're needed because there are spaces in filenames.

How can I read files outside the cgi-bin folder?

I've written a cgi script that processes data that is generated by another program. The problem is that this file is located outside the cgi-bin. How can I make sure that my perl scripts can read this file? I've already tried changing the permissions of this file and I also tried to make a link in the cgi-bin folder but Apache is too smart for that. I guess possible solutions are:
Edit the Apache config file in a way that Apache can read files outside the cgi-bin.
Run the cgi script with a 'portable' webserver. Like you can do with python (python -m http.server [port]). Unfortunately this does not execute the perl cgi scripts.
I'm kind of stuck how to do either one of the solutions.
Your CGI-script could access anything on your OS unless you run the apache under a sort of jail, in this case the your can read anything in the jail. (Of course, if the apache process has permissions to read the file).
e.g the next simple script will print out your password file
use strict;
use warnings;
use CGI;
my $q=CGI->new();
print $q->header();
print qx(cat /etc/passwd);
About the modern perl web-app development, read the following:
PSGI: What is it and what's the fuss about?
plack advent calendar: http://advent.plackperl.org/2009/12/day-1-getting-plack.html (buy the ebook if you can here: http://handbook.plackperl.org )
https://github.com/plack/Plack
Get some modern web-framerowk from CPAN - here are many (maybe too many) - the most known are:
Dancer (Dancer2)
Mojolicious
Poet/Mason
and of course, the big-gun: Catalyst
I personally mostly using
Poet/Mason
Mojolicious
EDIT
In your cgi-bin should exists a script called printenv.pl. Try:
chmod 755 printenv.pl
and point your browser to http://address/cgi-bin/printenv.pl You will get, the apache environment. See, you must know the basics of operating system commands and how the web works to succesfully run an web-application. It is impossible to write down everything in one answer, you need to use google, read answers to other questions here and such.
Also, in the above script, you can change the cat /etc/passwd to any other shell command for testing only what your cgi-script can or can not.
I've solved this problem by using plackup in combination of PSGI.
use CGI::Emulate::PSGI;
use CGI::Compile;
my $sub = CGI::Compile->compile("location/to/script.cgi");
my $app = CGI::Emulate::PSGI->handler($sub);
If you run plackup file.psgi, it sets up a local webserver that runs as the current user. Problem solved.

Executable cgi and image/javascript-files in lighty

I've add/commented out the following lines to my lighttpd.conf:
"mod_cgi"
and
cgi.assign = ( "" => "/var/www/myCgiScript" )
That works as expected... my executable mySite will be called on every request, but the problem is, that I can't open images. For instance, if I do the following:
http://localhost/myImage.png
This will call my executable cgi (mySite) - the same for js-files. Is Is there any chance to handle images as usual?
Thx in advance!
have a look at the documentation for cgi.assign:
http://redmine.lighttpd.net/projects/lighttpd/wiki/Docs:ModCGI#Options
the first argument is a file extension, the second argument is the path to a CGI script to run when a file with that extension is requested. Right now, your config file is saying "for any, or no, extension, run '/var/www/myCgiScript'." You need to specify a set of file extensions for which you want the CGI script to run, and let lighty serve up all other files in the normal manner.

How do I install this service_wrapper for mongrel/rails on my windows server?

I have been given the unpleasant task of installing a Rails 3 app I have written on Windows Server 2008 (definitely not my choice - was promised a linux server but I.T. pulled the rug out at the last minute so please don't suggest a change in environment as a solution).
I followed the instructions on this blog post (with a few minor modifications) and now actually have my app up and running under Windows/IIS (proxying mongrel) after a great deal of frustration. The only thing remaining is to get mongrel running as a service.
Unfortunately the mongrel gem has not been kept up-to-date for Rails 3 and while I can get the app running under mongrel at the command line I am unable to use mongrel_service to get the app running as a service.
The solution to this appears to be to use the service_wrapper project on github which has been mentioned in this previous question. The project is not yet complete but apparently functional but comes without documentation/binaries. I have looked through the source-code and don't really understand what is it/how it works so was wondering if someone can point me in the right direction (or, even better, walk me through how) to get this installed.
So close, yet still so far.....
Alright I have this worked out (with a little help from luislavena himself - thanks).
Download service_wrapper-0.1.0-win32.zip from https://github.com/luislavena/service_wrapper/downloads and extract service_wrapper.exe from bin/. I extracted it to C:\service_wrapper.
Next set up a configuration file. I used the hello example and modified it for my app then placed it in the C:\service_wrapper directory.
; Service section, it will be the only section read by service_wrapper
[service]
; Provide full path to executable to avoid issues when executable path was not
; added to system PATH.
executable = C:\Ruby192\bin\ruby.exe
; Provide there the arguments you will pass to executable from the command line
arguments = C:\railsapp\script\rails s -e production
; Which directory will be used when invoking executable.
; Provide a full path to the directory (not to a file)
directory = C:\railsapp
; Optionally specify a logfile where both STDOUT and STDERR of executable will
; be redirected.
; Please note that full path is also required.
logfile = C:\railsapp\log\service_wrapper.log
Now just create the service with
sc create railsapp binPath= "C:\service_wrapper\service_wrapper.exe C:\service_wrapper\service_wrapper.conf" start= auto
(watch for the spaces after binPath= and start=. It won't work without them)
Then start it with
net start railsapp
And you're home and hosed!
I ought to contribute due to this article. For config of using bundle exec, use the following:
Note that I am setting up rubyCAS! it's a great OpenCAS authentication mechanism!!!
; Service section, it will be the only section read by service_wrapper
[service]
; Provide full path to executable to avoid issues when executable path was not
; added to system PATH.
executable = C:\Ruby\bin\ruby.exe
; Provide there the arguments you will pass to executable from the command line
arguments = D:\rubycas-server bundle exec rackup -s mongrel -p 11011
; Which directory will be used when invoking executable.
; Provide a full path to the directory (not to a file)
directory = D:\rubycas-server
; Optionally specify a logfile where both STDOUT and STDERR of executable will
; be redirected.
; Please note that full path is also required.
logfile = D:\rubycas-server\log\service_wrapper.log