On 26 août, 12:01, k4rlchen <h...@gws.ms> wrote:
> Thanks Łukasz,
>
> unfortunatly, the application is in use for 10 years and delivered to > 300
> mobile computers.
> A change of application would mean a big scale operation.
>
> I was not 100% correct describing the matter. The values are not passed via
> url but in a form input field.

If the form's method is GET (which seems to be the case according to
your first post), the values ARE actually passed via the url. And
there's indeed a W3C recommandation that ';' should be treated as
equivalent to '&' in querystring, which doesn't contradict the URIs
rfc that clearly states that ';' is a reserved character in a query
string.

FWIW, if the form's method is POST, the values are encoded in the POST
request's body. Since the default encoding is application/x-www-form-
urlencoded (pretty self-explanatory I think). The alternative is
multipart/form-data, but I don't know if this change much here...

Also and FWIW, the CorrectWay(tm) to pass multiple values for a same
name in a query string is to use as many 'name=XXX' as values, ie : "/
foo?bar=1&bar=2&bar=3".

If I understand correctly, the client app is not a generic browser but
your own specific mobile app ? if yes, I strongly suggest you fix it
ASAP (next release or so), and warn your customers that they'll have
to upgrade sooner or later.

But anyway...

> The old cgi uses cgi.FieldStorage() , which works with this.

Django uses either cgi.parse_qsl or mod_python.utils.parse_qsl,
depending on mod_python's availability.

>>> from cgi import parse_qsl
>>> parse_qsl("asdf=1;2;3;4;")
[('asdf', '1')]
>>> parse_qsl("asdf=1;2;3;4;", True)
[('asdf', '1'), ('2', ''), ('3', ''), ('4', '')]
>>> parse_qsl("asdf=1;2;3;4;", True, True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/cgi.py", line 192, in parse_qsl
    return urlparse.parse_qsl(qs, keep_blank_values, strict_parsing)
  File "/usr/lib/python2.6/urlparse.py", line 343, in parse_qsl
    raise ValueError, "bad query field: %r" % (name_value,)
ValueError: bad query field: '2'
>>>


> Any posibility to use a regular expression to replace the semicolon before
> the QueryDict is created?.

Depending on how your django application is deployed, you may try&use
a rewrite rule (Apache) - not tested - or a WSGI Middeleware (not
tested neither). But all you can do this way (with a simple,
maintainable regexp at least) is to replace a reserved char by a non-
reserved one, insetad of turning a badly written querystring into a
well-formed one.

My own solution would be to just monkeypatch
django.http.QueryDict.__init__ to do the replacement before the
querystring is parsed, ie:

# myapp.models.py
# NB : put this in a models files to make sure it's executed as soon
as possible

from django import http
from urllib import urlencode

def _fix_qs(qs):
   query = list()
   parts = qs.split('&')
   for part in parts:
      try:
          k, v = part.split("=")
      except ValueError:
          parts.append((part, ""))
      else:
          if ";" in v:
              args = v.split(";")
              for arg in args:
                  query.append((k, arg))
          else:
              query.append((k, v))
    return urlencode(query)


def _patch_qd_init(init_func):
   def _patched_init(self, query_string, mutable=False,
encoding=None):
         if ";" in query_string:
             query_string = _fix_qs(query_string)
         init_func(self, query_string, mutable, encoding)
   return _patched_init

http.QueryDict.__dict__['__init__'] =
_patch_qd_init(http.QueryDict.__dict__['__init__'])


NB : not tested neither, so very probably broken one way or another -
but at least you get the idea.

HTH
B.


HTH


-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To post to this group, send email to django-us...@googlegroups.com.
To unsubscribe from this group, send email to 
django-users+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/django-users?hl=en.

Reply via email to