redirect forms with url values in zend - zend-framework

I have a page of the format www.test.com/policy-info/
which has a form that takes you to another page www.test.com/payment-info.
Now I am redirecting the page from www.test.com/payment-info to www.test.com/policy-info based on the some values obtained from the form. How do I redirect with certain values in the url.
the filename is policy-info.phtml.
Is this the only way to redirect?
$this->redirect(www.test.com/policy-info/index.phhtml&count=2);

You can use this:
$this->_helper->redirector('action', 'controller', 'module', array('param1'=>'value1', 'param2'=>'value2'));
in your case:
$this->_helper->redirector('index', 'policy-info', 'default',array('param1'=>'value1', 'param2'=>'value2'));
I always use $this->_redirect(...) and that works fine:
$this->_redirect('/module/controller/action/param1/value1/param2/value2');

This may be a case where _forward() may be the best choice.
_forward($action, $controller = null, $module = null, array $params = null): perform another action. If called in preDispatch(), the
currently requested action will be skipped in favor of the new one.
Otherwise, after the current action is processed, the action requested
in _forward() will be executed.
also It looks like you may be using named/defined routes, if that is true gotoRoute maybe useful as well Redirector Helper:
$this->_helper->getHelper('Redirector')->gotoRoute(array('param'=>'value'), 'routeName');

Related

Cake PHP pass parameter with form to controller

I don´t know how to securely pass a parameter via form with Cake.
The method I use now is as follows:
$this->Form->create('Post', array('label' => '', 'action' => '', 'url' => 'inseratAngenommen/'.$postId));
In the controller there stands:
function inseratAngenommen($id = null, $bs = null){
//stuff
}
The poblem is that the user can modify the output number of $postId in the browser:
action="/cakephp/posts/inseratAngenommen/149"
For that case I want to pass the parameter invisible in the HTML. Is that possible?
I thought of a method like the Form->PostLink provides. I couldn´t find anything.
Thanks in advance.
It is not possible to send an parameter securely over a website as the data is sent by the user.
Use the validation methods of cakephp to make sure the data is correct.
1] method one: add obscurity: hide the $id into a posted field by:
$this->Form->hidden('id');
$this->Form-field('id'); // even this one will do as cake hides ids by default
2] method two: keep the id on the server for instance in a session
$this->Session->write('current-edited-post-id', $id); // upon form display
$id = $this->Session->read('current-edited-post-id'); // upon form submission
but be warned thou, that method 2 doesn't behave well, if the user opens multiple tabs and operates one session from both of them :(

Symfony2: Redirect to requested path

I want to redirect the user back to the path from which he started the request.
Example:
/profile
/profile/edit
/profile
OR:
/products
/profile/edit
/products
What do I have to set for this redirection mode?
Inside your controller for /profile/edit you can capture the page they came from with $request->headers->get('referer').
If /profile/edit is a page with a single form, I'd probably just add a hidden field that says where the redirect should go.
public function editAction(Request $request)
{
// If you have a POST value coming from the user, it will be used, otherwise
// assume this is the first time they landed on the page and grab the current
// referer. With this method it doesn't matter how many times they submit the form
// you won't accidentally overwrite the referer URL with /profile/edit. That could
// lead to a confusing loop.
$referer = $request->request->get('referer', $request->headers->get('referer'));
if ($formIsSaved)
{
return new RedirectResponse($referer)
}
return array(
// Your template should include a hidden field in the form that returns this.
'referer' => $referer,
);
}
You could pass a redirect path as a GET parameter — say, redirectTo — to the edit page and after the edit process is complete, redirect to that path.
return new RedirectResponse($request->query->get('redirectTo');
You could make it more robust by checking whether or not that parameter is provided, and if it isn't, redirect to some sort of a default path.

zend framework urls and get method

I am developing a website using zend framework.
i have a search form with get method. when the user clicks submit button the query string appears in the url after ? mark. but i want it to be zend like url.
is it possible?
As well as the JS approach you can do a redirect back to the preferred URL you want. I.e. let the form submit via GET, then redirect to the ZF routing style.
This is, however, overkill unless you have a really good reason to want to create neat URLs for your search queries. Generally speaking a search form should send a GET query that can be bookmarked. And there's nothing wrong with ?param=val style parameters in a URL :-)
ZF URLs are a little odd in that they force URL parameters to be part of the main URL. I.e. domain.com/controller/action/param/val/param2/val rather than domain.com/controller/action?param=val&param2=val
This isn't always what you want, but seems to be the way frameworks are going with URL parameters
There is no obvious solution. The form generated by zf will be a standard html one. When submitted from the browser using GET it will result in a request like
/action/specified/in/form?var1=val1&var2=var2
Only solution to get a "zendlike url" (one with / instead of ? or &), would be to hack the form submission using javascript. For example you can listen for onSubmit, abort the submission and instead redirect browser to a translated url. I personally don't believe this solution is worth the added complexity, but it should perform what you're looking for.
After raging against this for a day-and-a-half, and doing my best to figure out the right way to do this fairly simple this, I gave up and did the following. I still can't believe there's not a better way.
The use case that necessitates this is a simple record listing, with a form up top for adding some filters (via GET), maybe some column sorting, and Zend_Paginate thrown in for good measure. I ran into issues using the Url view helper in my pagination partial, but I suspect with even just sorting and a filter-form, Zend_View_Helper_Url would still fall down.
But I digress. My solution was to add a method to my base controller class that merges any raw query-string parameters with the existing zend-style slashy-params, and redirects (but only if necessary). The method can be called in any action that doesn't have to handle POSTs.
Hopefully someone will find this useful. Or even better, find a better way:
/**
* Translate standard URL parameters (?foo=bar&baz=bork) to zend-style
* param (foo/bar/baz/bork). Query-string style
* values override existing route-params.
*/
public function mergeQueryString(){
if ($this->getRequest()->isPost()){
throw new Exception("mergeQueryString only works on GET requests.");
}
$q = $this->getRequest()->getQuery();
$p = $this->getRequest()->getParams();
if (empty($q)) {
//there's nothing to do.
return;
}
$action = $p['action'];
$controller = $p['controller'];
$module = $p['module'];
unset($p['action'],$p['controller'],$p['module']);
$params = array_merge($p,$q);
$this->_helper->getHelper('Redirector')
->setCode(301)
->gotoSimple(
$action,
$controller,
$module,
$params);
}

Zend_Test - Setting redirect in Controller Plugin for PHPUnit

I have been trying to use PHPUnit to test an application. I have it all working, but cannot test redirects.
My redirects are occurring inside an Acl Controller Plugin, not inside an Action in a Controller.
I have changed them to use the suggested format of
$r = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
$r->gotoSimple("index", "index", "default");
But this fails in the tests, the response body is empty and I get errors like
Zend_Dom_Exception: Cannot query; no document registered
If I then change the test so that the dispatch method does not result in gotoSimple() being called then the test runs correctly.
How am I supposed to do a redirect in my application so that it runs correctly with Zend_Test's response object?
The Zend docs cover this in about two lines, which I have tried and it fails.
Thanks.
To test that redirect has occurred, you need to add
$this->assertRedirectTo( 'index' );
after running $this->dispatch();
You cannot query the response body, since it's empty in case of redirect (that's where your exception comes from).
You can always check what the response actually looks like with
print_r( $this->getResponse() );
Make sure, your actions return anything after redirections, because Zend_Test_PHPUnit disables redirects, so the code after redirect is executed as well.
$r = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
$r->gotoSimple("index", "index", "default");
return;
or
$r = Zend_Controller_Action_HelperBroker::getStaticHelper('redirector');
return $r->gotoSimple("index", "index", "default");
To test the redirect itself, you may use assertRedirect* assertions.
Read the above manual, because there are important notes about action hooks.

How do I use and debug WWW::Mechanize?

I am very new to Perl and i am learning on the fly while i try to automate some projects for work. So far its has been a lot of fun.
I am working on generating a report for a customer. I can get this report from a web page i can access.
First i will need to fill a form with my user name, password and choose a server from a drop down list, and log in.
Second i need to click a link for the report section.
Third a need to fill a form to create the report.
Here is what i wrote so far:
my $mech = WWW::Mechanize->new();
my $url = 'http://X.X.X.X/Console/login/login.aspx';
$mech->get( $url );
$mech->submit_form(
form_number => 1,
fields =>{
'ctl00$ctl00$cphVeriCentre$cphLogin$txtUser' => 'someone',
'ctl00$ctl00$cphVeriCentre$cphLogin$txtPW' => '12345',
'ctl00$ctl00$cphVeriCentre$cphLogin$ddlServers' => 'Live',
button => 'Sign-In'
},
);
die unless ($mech->success);
$mech->dump_forms();
I dont understand why, but, after this i look at the what dump outputs and i see the code for the first login page, while i belive i should have reached the next page after my successful login.
Could there be something with a cookie that can effect me and the login attempt?
Anythings else i am doing wrong?
Appreciate you help,
Yaniv
This is several months after the fact, but I resolved the same issue based on a similar questions I asked. See Is it possible to automate postback from the client side? for more info.
I used Python's Mechanize instead or Perl, but the same principle applies.
Summarizing my earlier response:
ASP.NET pages need a hidden parameter called __EVENTTARGET in the form, which won't exist when you use mechanize normally.
When visited by a normal user, there is a __doPostBack('foo') function on these pages that gives the relevant value to __EVENTTARGET via a javascript onclick event on each of the links, but since mechanize doesn't use javascript you'll need to set these values yourself.
The python solution is below, but it shouldn't be too tough to adapt it to perl.
def add_event_target(form, target):
#Creates a new __EVENTTARGET control and adds the value specified
#.NET doesn't generate this in mechanize for some reason -- suspect maybe is
#normally generated by javascript or some useragent thing?
form.new_control('hidden','__EVENTTARGET',attrs = dict(name='__EVENTTARGET'))
form.set_all_readonly(False)
form["__EVENTTARGET"] = target
You can only mechanize stuff that you know. Before you write any more code, I suggest you use a tool like Firebug and inspect what is happening in your browser when you do this manually.
Of course there might be cookies that are used. Or maybe your forgot a hidden form parameter? Only you can tell.
EDIT:
WWW::Mechanize should take care of cookies without any further intervention.
You should always check whether the methods you called were successful. Does the first get() work?
It might be useful to take a look at the server logs to see what is actually requested and what HTTP status code is sent as a response.
If you are on Windows, use Fiddler to see what data is being sent when you perform this process manually, and then use Fiddler to compare it to the data captured when performed by your script.
In my experience, a web debugging proxy like Fiddler is more useful than Firebug when inspecting form posts.
I have found it very helpful to use Wireshark utility when writing web automation with WWW::Mechanize. It will help you in few ways:
Enable you realize whether your HTTP request was successful or not.
See the reason of failure on HTTP level.
Trace the exact data which you pass to the server and see what you receive back.
Just set an HTTP filter for the network traffic and start your Perl script.
The very short gist of aspx pages it that they hold all of the local session information within a couple of variables prefixed by "__" in the general aspxform. Usually this is a top level form and all form elements will be part of it, but I guess that can vary by implementation.
For the particular implementation I was dealing with I needed to worry about 2 of these state variables, specifically:
__VIEWSTATE
__EVENTVALIDATION.
Your goal is to make sure that these variables are submitted into the form you are submitting, since they might be part of that main form aspxform that I mentioned above, and you are probably submitting a different form than that.
When a browser loads up an aspx page a piece of javascript passes this session information along within the asp server/client interaction, but of course we don't have that luxury with perl mechanize, so you will need to manually post these yourself by adding the elements to the current form using mechanize.
In the case that I just solved I basically did this:
my $browser = WWW::Mechanize->new( );
# fetch the login page to get the initial session variables
my $login_page = 'http://www.example.com/login.aspx';
$response = $browser->get( $login_page);
# very short way to find the fields so you can add them to your post
$viewstate = ($browser->find_all_inputs( type => 'hidden', name => '__VIEWSTATE' ))[0]->value;
$validation = ($browser->find_all_inputs( type => 'hidden', name => '__EVENTVALIDATION' ))[0]->value;
# post back the formdata you need along with the session variables
$browser->post( $login_page, [ username => 'user', password => 'password, __VIEWSTATE => $viewstate, __EVENTVALIDATION => $validation ]);
# finally get back the content and make sure it looks right
print $response->content();