blob: 3aa057facecd287de214edd162239afecfe17fd7 [file] [log] [blame]
/**
* Copyright 2010 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
// Author: jmarantz@google.com (Joshua Marantz)
#include "net/instaweb/util/public/url_multipart_encoder.h"
#include "net/instaweb/util/public/message_handler.h"
namespace {
// Ultimately these will be encoded by the URL Escaper so we want to
// stay within legal URL space so we don't blow up. We'll have to
// see how we like this aesthetically. We want to stay within legal
// filename space as well so the filenames don't look too ugly.
const char kEscape = '='; // Nice if this is filename-legal
const char kEscapedEscape[] = "==";
const char kSeparator = '+';
const char kEscapedSeparator[] = "=+";
} // namespace
namespace net_instaweb {
std::string UrlMultipartEncoder::Encode() const {
std::string encoding;
for (int i = 0, n = urls_.size(); i <n; ++i) {
if (i != 0) {
encoding += kSeparator;
}
const std::string& url = urls_[i];
for (int c = 0, nc = url.size(); c < nc; ++c) {
char ch = url[c];
if (ch == kEscape) {
encoding += kEscapedEscape;
} else if (ch == kSeparator) {
encoding += kEscapedSeparator;
} else {
encoding += ch;
}
}
}
return encoding;
}
bool UrlMultipartEncoder::Decode(const StringPiece& encoding,
MessageHandler* handler) {
urls_.clear();
std::string url;
bool append_last = false;
for (int c = 0, nc = encoding.size(); c < nc; ++c) {
char ch = encoding[c];
if (ch == kSeparator) {
urls_.push_back(url);
url.clear();
append_last = true;
// ensure that a "a+b+" results in 3 urls with the last one empty.
} else {
if (ch == kEscape) {
++c;
if (c == nc) {
handler->Message(kError,
"Invalid encoding: escape at end of string %s",
encoding.as_string().c_str());
return false;
}
ch = encoding[c];
if ((ch != kEscape) && (ch != kSeparator)) {
handler->Message(kError,
"Invalid character `%c', after escape `%c' in %s",
ch, kEscape, encoding.as_string().c_str());
return false;
}
}
url += ch;
}
}
if (append_last || !url.empty()) {
urls_.push_back(url);
}
return true;
}
} // namespace net_instaweb