I've a script who gets two parameters from a form: Code (int), Fields (record). In the script, I can assign to Code, say: Code = 1 but if I try, say: Fields.a_field = 1 I get the error:
Error Type: TypeError Error Value: attribute-less object (assign or del)
Do I need some special syntax for that or is it simply not possible (and why)? Regards, Fernando
At 03:12 PM 3/4/2003, Fernando Martins wrote:
I've a script who gets two parameters from a form: Code (int), Fields (record).
Record? Haven't heard of *that* data type...
Fields.a_field = 1
I get the error:
Error Type: TypeError Error Value: attribute-less object (assign or del)
That's because whatever it is you're passing in for the value of Fields doesn't have the attribute you're attempting to assign to. If Fields is a mapping (like REQUEST.form), you may want: Fields['a_field'] = 1 If that's not it, could you provide a bit more info on what's getting passed in for Fields? HTH, Dylan
Error Type: TypeError Error Value: attribute-less object (assign or del)
That's because whatever it is you're passing in for the value of Fields doesn't have the attribute you're attempting to assign to.
It has that attribute but as part of Script (Python) security you cannot assign to it. eg: try this Script (Python) script.title = 'Foo' Not sure that it really provides more security than annoyance, but the idea is you have to call a function or use an API for that object. Cheers -- Andy McKay
On Tue, Mar 04, 2003 at 03:49:33PM -0800, Andy McKay wrote:
It has that attribute but as part of Script (Python) security you cannot assign to it. eg: try this Script (Python)
ahhh ok. so it really is a record. question is, why do you need to modify it in the script anyway? just do foo = Fields.afield and do whatever w/ foo. -- Paul Winkler http://www.slinkp.com
Paul Winkler wrote:
question is, why do you need to modify it in the script anyway? just do foo = Fields.afield and do whatever w/ foo.
I've two forms who pass a similar record to their scripts. Each script does its own processing, "normalising" the record. The record is then passed to another script which does common processing and final storage in a table. Of course, I can pass each field individually to the final script but with a lot of fields it gets ugly. I also can't create classes in a PythonScript, so it's quite limited. Regards, Fernando
Fernando Martins wrote at 2003-3-6 01:32 +0100:
I've two forms who pass a similar record to their scripts. Each script does its own processing, "normalising" the record. The record is then passed to another script which does common processing and final storage in a table.
You can pass dictionaries instead of records. An alternative: "Products.PythonScripts.standard" defines the record factory "Object" (maybe different case, check the source). It returns a writable "record". Dieter
From: Dieter Maurer
Fernando Martins wrote at 2003-3-6 01:32 +0100:
I've two forms who pass a similar record to their scripts. Each script does its own processing, "normalising" the record. The record is then passed to another script which does common processing and final storage in a table.
You can pass dictionaries instead of records.
Yes, but I just needed to modify a maximum of two fields and in a set of 12. It would result in ugly and inefficient code. hmm, unless there's some way to automatically convert an object to a dictionary? (like a list comprehension or dict()) For the record, the obvious solution is to take these two away from this particular record, but a general solution would be better.
An alternative:
"Products.PythonScripts.standard" defines the record factory "Object" (maybe different case, check the source).
It returns a writable "record".
I tried this script: import Products.PythonScripts.standard ObjFields = Products.PythonScripts.standard.Object() ObjFields = Fields ObjFields.a_field = 10 and I got the same error:
Error Type: TypeError Error Value: attribute-less object (assign or del)
Can you spot what's wrong? Thanks, Fernando
Fernando Martins wrote at 2003-3-7 00:04 +0100:
ObjFields = Products.PythonScripts.standard.Object() ObjFields = Fields ObjFields.a_field = 10
and I got the same error:
Error Type: TypeError Error Value: attribute-less object (assign or del)
Sure, as you still work with the same object... After "ObjFields = Fields", "ObjFields contains "Fields" and no longer the newly created "Object()". Dieter
From: Dieter Maurer [mailto:dieter@handshake.de] Fernando Martins wrote at 2003-3-7 00:04 +0100:
ObjFields = Products.PythonScripts.standard.Object() ObjFields = Fields ObjFields.a_field = 10
and I got the same error:
Error Type: TypeError Error Value: attribute-less object (assign or del)
Sure, as you still work with the same object...
After "ObjFields = Fields", "ObjFields contains "Fields" and no longer the newly created "Object()".
Doh! I should have thought about that! So, in Python, Fields is a memory pointer and Fields.a_field is the same as Fields->a_field in C. It seems what I need is shallow copy from the copy module, and I can't in Scripts. Oh well, anyway, I'm now using Evan's patch. Thanks, Fernando
Andy McKay wrote:
It has that attribute but as part of Script (Python) security you cannot assign to it. eg: try this Script (Python)
script.title = 'Foo'
Not sure that it really provides more security than annoyance, but the idea is you have to call a function or use an API for that object.
Thanks for explaining. I suspected it but it didn't seem consistent with the fact that I could modify a literal attribute passed to a PythonScript. I had some hope to just be missing the right syntax to do it. But is there any function to work with the record object?? I don't even know what's its class. Can I add my own functions? Regards, Fernando
Fernando Martins wrote at 2003-3-6 01:32 +0100:
... But is there any function to work with the record object??
You can access its attributes...
I don't even know what's its class.
It is defined in "ZPublisher.HTTPRequest" and its name in "record".
Can I add my own functions?
Sure, when you change the code... Dieter
Thanks for replying, From: Dylan Reinhardt
Fernando Martins wrote:
I've a script who gets two parameters from a form: Code (int), Fields (record).
Record? Haven't heard of *that* data type...
Well, I don't know if it is really a data type. In the zope book it's called parameter conversion, you know, to convert string values from the form to some other Python data type. I was assuming 'record' would convert to some (unknown?) class.
Fields.a_field = 1
I get the error:
Error Type: TypeError Error Value: attribute-less object (assign or del)
That's because whatever it is you're passing in for the value of Fields doesn't have the attribute you're attempting to assign to.
This works ok (in a right-hand side expression): print Fields.a_field
If Fields is a mapping (like REQUEST.form), you may want:
Fields['a_field'] = 1
If that's not it, could you provide a bit more info on what's getting passed in for Fields?
Sure, in the form I've stuff like: <input type="text" name="Fields.Title:record"> <input type="text" name="Fields.Author:record"> etc... I can _use_ expressions like Fields.Title in the Python script but I can't modify it. Cheers, Fernando
On Tue, Mar 04, 2003 at 03:39:48PM -0800, Dylan Reinhardt wrote:
At 03:12 PM 3/4/2003, Fernando Martins wrote:
I've a script who gets two parameters from a form: Code (int), Fields (record).
Record? Haven't heard of *that* data type...
search for it in the "advanced scripting" chapter of the online zope book.
Fields.a_field = 1
I get the error:
Error Type: TypeError Error Value: attribute-less object (assign or del)
That's because whatever it is you're passing in for the value of Fields doesn't have the attribute you're attempting to assign to.
no, then he'd get an AttributeError. but you're right that Fields is probably not what was expected, because the record class defined in HTTPRequest.py will let you assign any attribute. What's in the actual form where it gets a value for Fields? -- Paul Winkler http://www.slinkp.com
At 04:08 PM 3/4/2003, Paul Winkler wrote:
On Tue, Mar 04, 2003 at 03:39:48PM -0800, Dylan Reinhardt wrote:
At 03:12 PM 3/4/2003, Fernando Martins wrote:
I've a script who gets two parameters from a form: Code (int), Fields (record).
Record? Haven't heard of *that* data type...
search for it in the "advanced scripting" chapter of the online zope book.
Aha... still learning something new every day it would seem. :-) Thanks, Dylan
Fernando Martins wrote:
I've a script who gets two parameters from a form: Code (int), Fields (record). ... Fields.a_field = 1
I get the error
I routinely patch Zope so that 'record' instances and the SQL Record subclasses that it generates are writable: (in $ZOPE/lib/python/ZPublisher/HTTPRequest.py) class record: # Allow access to record methods and values from DTML __allow_access_to_unprotected_subobjects__=1 _guarded_writes = 1 (in $ZOPE/lib/python/Shared/DC/ZRDB/Result.py) class r(Record, Implicit, brains, zbrains): 'Result record class' _guarded_writes = 1 I see no reason why 'record' objects shouldn't be mutable like this, but I've never discussed it with anyone. Cheers, Evan @ 4-am
Ah! Here it is ;-) If this patch doesn't go into CVS, I'm willing to submit it to zope labs for you, if you don't mind. Albeit Dieter Maurer's solution is non-intrusive to Zope (after I get it to work) this one makes it transparent for the (script) user ;-) Cheers, Fernando Evan Simpson wrote:
Fernando Martins wrote:
I've a script who gets two parameters from a form: Code (int), Fields (record). ... Fields.a_field = 1
I get the error
I routinely patch Zope so that 'record' instances and the SQL Record subclasses that it generates are writable:
(in $ZOPE/lib/python/ZPublisher/HTTPRequest.py) class record: # Allow access to record methods and values from DTML __allow_access_to_unprotected_subobjects__=1 _guarded_writes = 1
(in $ZOPE/lib/python/Shared/DC/ZRDB/Result.py) class r(Record, Implicit, brains, zbrains): 'Result record class' _guarded_writes = 1
I see no reason why 'record' objects shouldn't be mutable like this, but I've never discussed it with anyone.
Cheers,
Evan @ 4-am
_______________________________________________ Zope maillist - Zope@zope.org http://mail.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope-dev )
With all this discussion on :record flags and :list flags can someone point me to a good reference on the different :flags and how to use them. Or just explain it! :-) On Tue, 2003-03-04 at 17:12, Fernando Martins wrote:
I've a script who gets two parameters from a form: Code (int), Fields (record).
In the script, I can assign to Code, say:
Code = 1
but if I try, say:
Fields.a_field = 1
I get the error:
Error Type: TypeError Error Value: attribute-less object (assign or del)
Do I need some special syntax for that or is it simply not possible (and why)?
Regards, Fernando
_______________________________________________ Zope maillist - Zope@zope.org http://mail.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope-dev ) -- Edward Muller
Interlix - President Web Hosting - PC Service & Support Custom Programming - Network Service & Support Phone: 417-862-0573 Cell: 417-844-2435 Fax: 417-862-0572 http://www.interlix.com
Edward Muller wrote:
With all this discussion on :record flags and :list flags can someone point me to a good reference on the different :flags and how to use them. Or just explain it! :-)
See the Zope book (2.5) chp. 10, section "Passing Parameters to Scripts". It's an easy and quick reading, worthy of your time :-) :flags are used to convert parameters coming from HTML forms, from strings to a python data type. Quite usefull is the possibility to put together several form fields in a list or in an object (record). HTH, Fernando
Edward Muller wrote at 2003-3-6 23:05 -0600:
With all this discussion on :record flags and :list flags can someone point me to a good reference on the different :flags and how to use them. Or just explain it! :-)
There is a HowTo on Zope.org. You find a different presentation in <http://www.dieter.handshake.de/pyprojects/zope/book/chap3.html> Dieter
I really need to site down and read your site and the book specifically. Dieter is the man! On Sat, 2003-03-08 at 07:21, Dieter Maurer wrote:
Edward Muller wrote at 2003-3-6 23:05 -0600:
With all this discussion on :record flags and :list flags can someone point me to a good reference on the different :flags and how to use them. Or just explain it! :-)
There is a HowTo on Zope.org.
You find a different presentation in
<http://www.dieter.handshake.de/pyprojects/zope/book/chap3.html>
Dieter
Hello Folks! good small documentation about this, can be had access in http://www.zope.org/Members/Zen/howto/FormVariableTypes and http://www.zope.org/Members/jpenny/variable_length_forms the difference flags are that record will be created methods and attributes of name field. for example (record)... <input type=text name=person.name:record size=30> you have a method person and an attribute name. for example (records)... <dtml-in "range(item_count)"> <input type=text size=30 name="items.desc:records"> <input type=text size=15 name="items.item:records"> <input type=text size=10 name="items.qty:records"> </dtml-in> The receiving method would be handed a list called 'items' where each listmember is a recordobject with the properties desc, item and qty. You could loop through them like this: <dtml-in items> <dtml-var desc>: <dtml-var item>, <dtml-var qty> </dtml-in> []s Eduardo ----- Original Message ----- From: "Edward Muller" <edwardam@interlix.com> To: "Dieter Maurer" <dieter@handshake.de> Cc: <zope@zope.org> Sent: Saturday, March 08, 2003 3:57 AM Subject: Re: [Zope] assignment to form records
I really need to site down and read your site and the book specifically. Dieter is the man!
On Sat, 2003-03-08 at 07:21, Dieter Maurer wrote:
Edward Muller wrote at 2003-3-6 23:05 -0600:
With all this discussion on :record flags and :list flags can someone point me to a good reference on the different :flags and how to use them. Or just explain it! :-)
There is a HowTo on Zope.org.
You find a different presentation in
<http://www.dieter.handshake.de/pyprojects/zope/book/chap3.html>
Dieter
_______________________________________________ Zope maillist - Zope@zope.org http://mail.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope-dev )
At 03:29 PM 3/8/2003, Eduardo Bastos wrote:
for example (record)... <input type=text name=person.name:record size=30> you have a method person and an attribute name.
for example (records)... <dtml-in "range(item_count)"> <input type=text size=30 name="items.desc:records"> <input type=text size=15 name="items.item:records"> <input type=text size=10 name="items.qty:records"> </dtml-in>
My unsolicited $.02: You may want to think twice about relying on this for a public-facing production system. The first rule of security for a public web site is to validate *all* client input. That includes posted values, *and* field names. Depending on the client to post a form without tweaking the field names is a pretty trusting position to take, IMO. If you're going to validate your data anyway, what's the point of specifying data types at any point prior to validation? Including meaningful field names in your form just gives you one more failure point... it's one more thing you should be validating but most likely aren't, or you wouldn't be using it in the first place. The field name hack is a really neat trick... but it's not something I'd advise depending on for anything important that gets public exposure. FWIW, Dylan
Dylan Reinhardt wrote:
My unsolicited $.02:
You may want to think twice about relying on this for a public-facing production system.
The first rule of security for a public web site is to validate *all* client input. That includes posted values, *and* field names.
Depending on the client to post a form without tweaking the field names is a pretty trusting position to take, IMO. If you're going to validate your data anyway, what's the point of specifying data types at any point prior to validation?
Including meaningful field names in your form just gives you one more failure point... it's one more thing you should be validating but most likely aren't, or you wouldn't be using it in the first place.
The field name hack is a really neat trick... but it's not something I'd advise depending on for anything important that gets public exposure.
Could you elaborate this a little bit? I can't see any problem with using field names which hold data structure information. What you shouldn't do is _rely_ on the types (name:int etc.) for anything important, but using the names to get the data as a record or list etc. doesn't seem dangerous for me. thanks, oliver
At 02:57 AM 3/9/2003, Oliver Bleutgen wrote:
Could you elaborate this a little bit? I can't see any problem with using field names which hold data structure information.
The names themselves aren't a problem... it's the behavior they enable. If you use them in the way they're intended, you are implicitly trusting your clients not to cause any mischief. That might be fine for an intranet message board, but I sure wouldn't recommend it for e-commerce.
What you shouldn't do is _rely_ on the types (name:int etc.) for anything important,
That's my point.
but using the names to get the data as a record or list etc. doesn't seem dangerous for me.
Except that you're passing the client some degree of control over how your data is managed. It sounds like we're agreed that using <input type="text" name="my_num:int"> doesn't mean you can simply assume that whatever conversion the zserver performs must be correct. You should still verify that the value of my_num is an integer... and should do so based on *expecting* an integer, not on what the field name contains. But let's take that one step further to this example: <input type="text" name="person.f_name:string:required"> Two things are wrong here... first is, if you use options like required, default or ignore_empty you're giving the client even more control over how your data validates. How that can be a good idea is beyond me. The second -- somewhat more subtle -- issue is using record notation at all. What are the odds that your record naming scheme maps closely to how this information is structured in your RDBMS? How much more vulnerable do you make yourself to SQL-based attacks if you used this naming technique on anything that passes off data to a SQL query? Are you looping over *everything* you find in given record, or only looking for the attributes you're expecting? I realize that quoting your input with sqlvar takes care of the worst insertion attacks, but that's something I'd consider a last line of defense rather than a primary means of providing security. It's easier not to validate, but that's not a habit I'd recommend for serious projects. I'm only raising issues with field naming to the degree that it's most likely to be used to reduce validation work. Dylan
Hi! i agree with oliver and doesnt seem dangerous for using data structure information in a html page. i checked too types this structures on python scripts and dont have any problems... []s Eduardo
Could you elaborate this a little bit? I can't see any problem with using field names which hold data structure information. What you shouldn't do is _rely_ on the types (name:int etc.) for anything important, but using the names to get the data as a record or list etc. doesn't seem dangerous for me.
All that things like :record and :records do (after reading various docs) is pass a variable names items with the following attributes .desc, .item, .qty. What you do with that variable is then up to you. I don't see how using this functionality is in any way a security hole. I would love a an equivalent :object and :objects flag something like this: <dtml-in "range(item_count)"> <input type=text size=30 name="items.desc:objects:Item"> <input type=text size=15 name="items.item:objects:Item"> <input type=text size=10 name="items.qty:objects:Item"> </dtml-in> Where an 'object' (or objects) is created (Python class is instantiated) and getter and setter methods for .desc, .item and .qty get called with the provided values. For instance the above snippet would create a new object called items, which is an instance of class Item. Class Item would have get_desc, get_item, get_qty, set_desc, set_item, set_qty methods. These would then act as classic getter and setter methods. On Sat, 2003-03-08 at 21:56, Dylan Reinhardt wrote:
At 03:29 PM 3/8/2003, Eduardo Bastos wrote:
for example (record)... <input type=text name=person.name:record size=30> you have a method person and an attribute name.
for example (records)... <dtml-in "range(item_count)"> <input type=text size=30 name="items.desc:records"> <input type=text size=15 name="items.item:records"> <input type=text size=10 name="items.qty:records"> </dtml-in>
My unsolicited $.02:
You may want to think twice about relying on this for a public-facing production system.
The first rule of security for a public web site is to validate *all* client input. That includes posted values, *and* field names.
Depending on the client to post a form without tweaking the field names is a pretty trusting position to take, IMO. If you're going to validate your data anyway, what's the point of specifying data types at any point prior to validation?
Including meaningful field names in your form just gives you one more failure point... it's one more thing you should be validating but most likely aren't, or you wouldn't be using it in the first place.
The field name hack is a really neat trick... but it's not something I'd advise depending on for anything important that gets public exposure.
FWIW,
Dylan
_______________________________________________ Zope maillist - Zope@zope.org http://mail.zope.org/mailman/listinfo/zope ** No cross posts or HTML encoding! ** (Related lists - http://mail.zope.org/mailman/listinfo/zope-announce http://mail.zope.org/mailman/listinfo/zope-dev ) -- Edward Muller
Interlix - President Web Hosting - PC Service & Support Custom Programming - Network Service & Support Phone: 417-862-0573 Cell: 417-844-2435 Fax: 417-862-0572 http://www.interlix.com
At 10:34 PM 3/9/2003, Edward Muller wrote:
All that things like :record and :records do (after reading various docs) is pass a variable names items with the following attributes .desc, .item, .qty. What you do with that variable is then up to you.
Indeed.
I don't see how using this functionality is in any way a security hole.
By itself, it's probably not. But it facilitates insecure coding habits. I already suspect that poor validation is rampant in Zope. One of the classic questions that pops up here from time to time is how you're supposed to capture the "off" value of checkboxes when you only get information on the ones that are checked. This question betrays a deep, dark secret lurking in many web apps: many developers have no idea what fields to expect nor what rules their data can be validated against. Relying on the client to pass along special type & structure codes suggests a similarly high level of uncertainty as to what data is expected and what rules it should be validated against. It's not the feature itself, but the avoidance of validation that gives me concern. But every application has its own requirements and its own environment. Each of us needs to determine what level of paranoia is justified by the specific requirements of each system. Dylan
Edward Muller wrote:
I would love a an equivalent :object and :objects flag something like this:
<dtml-in "range(item_count)"> <input type=text size=30 name="items.desc:objects:Item"> <input type=text size=15 name="items.item:objects:Item"> <input type=text size=10 name="items.qty:objects:Item"> </dtml-in>
Where an 'object' (or objects) is created (Python class is instantiated) and getter and setter methods for .desc, .item and .qty get called with the provided values. For instance the above snippet would create a new object called items, which is an instance of class Item. Class Item would have get_desc, get_item, get_qty, set_desc, set_item, set_qty methods. These would then act as classic getter and setter methods.
It would be nice to see some facilities in this direction. I'm far from fully understanding Zope (I'm at basic ZPT/Scripts/Python level), but maybe something like having a product called Object which allows to specify fields, default values, validation rules and error messages. With an Object called Item one could have validation rules being generated in Javascript (<tal:replace=Item/rules/> ???). When zope receives the form data it would validate the data according to Item specification (fields, rules) and deal with the security concerns pointed by Dylan (missing fields, wrong types). Validation rules could be simple logical expressions (from which Javascript and Python code could be generated) or Python scripts (in this case a Javascript alternative would have to be provided). Of course, then some people would want an UML modeling tool to generate/maintain Objects in Zope. Is this far fetched for Zope? ;-) Regards, Fernando
The Formulator product may help you. <http://www.zope.org/Members/faassen/Formulator> Stefan -- Those who write software only for pay should go hurt some other field. /Erik Naggum/
participants (10)
-
Andy McKay -
Dieter Maurer -
Dylan Reinhardt -
Eduardo Bastos -
Edward Muller -
Evan Simpson -
Fernando Martins -
Oliver Bleutgen -
Paul Winkler -
Stefan H. Holek