form_urlencoded.rs 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Copyright 2013-2014 Simon Sapin.
  2. //
  3. // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
  4. // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
  5. // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
  6. // option. This file may not be copied, modified, or distributed
  7. // except according to those terms.
  8. use std::str;
  9. use encoding;
  10. use encoding::EncodingRef;
  11. use encoding::all::UTF_8;
  12. use encoding::label::encoding_from_whatwg_label;
  13. use super::{percent_encode_byte, percent_decode};
  14. pub fn parse_form_urlencoded(input: &str,
  15. encoding_override: Option<EncodingRef>,
  16. use_charset: bool,
  17. mut isindex: bool)
  18. -> ~[(~str, ~str)] {
  19. let mut encoding_override = encoding_override.unwrap_or(UTF_8 as EncodingRef);
  20. let mut pairs = ~[];
  21. for string in input.split('&') {
  22. if string.len() > 0 {
  23. let (name, value) = match string.find('=') {
  24. Some(position) => (string.slice_to(position), string.slice_from(position + 1)),
  25. None => if isindex { ("", string) } else { (string, "") }
  26. };
  27. let name = name.replace("+", " ");
  28. let value = value.replace("+", " ");
  29. if use_charset && name.as_slice() == "_charset_" {
  30. match encoding_from_whatwg_label(value) {
  31. Some(encoding) => encoding_override = encoding,
  32. None => (),
  33. }
  34. }
  35. pairs.push((name, value));
  36. }
  37. isindex = false;
  38. }
  39. #[inline]
  40. fn decode(input: &~str, encoding_override: EncodingRef) -> ~str {
  41. let bytes = percent_decode(input.as_bytes());
  42. encoding_override.decode(bytes, encoding::DecodeReplace).unwrap()
  43. }
  44. for pair in pairs.mut_iter() {
  45. let new_pair = {
  46. let &(ref name, ref value) = pair;
  47. (decode(name, encoding_override), decode(value, encoding_override))
  48. };
  49. *pair = new_pair;
  50. }
  51. pairs
  52. }
  53. pub fn serialize_form_urlencoded(pairs: ~[(~str, ~str)],
  54. encoding_override: Option<EncodingRef>)
  55. -> ~str {
  56. #[inline]
  57. fn byte_serialize(input: &str, output: &mut ~str,
  58. encoding_override: Option<EncodingRef>) {
  59. let keep_alive;
  60. let input = match encoding_override {
  61. None => input.as_bytes(), // "Encode" to UTF-8
  62. Some(encoding) => {
  63. keep_alive = encoding.encode(input, encoding::EncodeNcrEscape).unwrap();
  64. keep_alive.as_slice()
  65. }
  66. };
  67. for byte in input.iter() {
  68. match *byte {
  69. 0x20 => output.push_str("+"),
  70. 0x2A | 0x2D | 0x2E | 0x30 .. 0x39 | 0x41 .. 0x5A | 0x5F | 0x61 .. 0x7A
  71. => unsafe { str::raw::push_byte(output, *byte) },
  72. _ => percent_encode_byte(*byte, output),
  73. }
  74. }
  75. }
  76. let mut output = ~"";
  77. for &(ref name, ref value) in pairs.iter() {
  78. if output.len() > 0 {
  79. output.push_str("&");
  80. byte_serialize(name.as_slice(), &mut output, encoding_override);
  81. output.push_str("=");
  82. byte_serialize(value.as_slice(), &mut output, encoding_override);
  83. }
  84. }
  85. output
  86. }