Skip to content

Commit

Permalink
Merge pull request #192 from rstudio/fix-uri
Browse files Browse the repository at this point in the history
URI encoding/decoding fixes
  • Loading branch information
wch authored Feb 8, 2019
2 parents 1ca8f15 + 6a72dd9 commit e59dbe8
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 116 deletions.
3 changes: 1 addition & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: httpuv
Type: Package
Title: HTTP and WebSocket Server Library
Version: 1.4.5.9002
Version: 1.4.5.9003
Author: Joe Cheng, Hector Corrada Bravo [ctb], Jeroen Ooms [ctb],
Winston Chang [ctb]
Copyright: RStudio, Inc.; Joyent, Inc.; Nginx Inc.; Igor Sysoev; Niels Provos;
Expand Down Expand Up @@ -35,7 +35,6 @@ Remotes:
r-lib/later
Collate:
'RcppExports.R'
'decode_uri.R'
'httpuv.R'
'server.R'
'static_paths.R'
Expand Down
8 changes: 6 additions & 2 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
httpuv 1.4.5.9002
httpuv 1.4.5.9003
============

* Added support for serving static files from the background I/O thread. Files can now be served from the filesystem without involving the main R thread, which means that these operations won't block or be blocked by code that runs in the main R thread. ([#177](https://github.com/rstudio/httpuv/pull/177))
Expand All @@ -9,7 +9,11 @@ httpuv 1.4.5.9002

* Fixed [#168](https://github.com/rstudio/httpuv/issues/168): A SIGPIPE signal on the httpuv background thread could cause the process to quit. This can happen in some instances when the server is under heavy load. ([#169](https://github.com/rstudio/httpuv/pull/169))

* Fixed [#122](https://github.com/rstudio/httpuv/issues/122): `decodeURI()` and `decodeURIComponent()` previously returned strings encoded with the system's native encoding; they now return UTF-8 encoded strings. ([#185](https://github.com/rstudio/httpuv/pull/185))
* Fixed [#122](https://github.com/rstudio/httpuv/issues/122): `decodeURI()` and `decodeURIComponent()` previously returned strings encoded with the system's native encoding; they now return UTF-8 encoded strings. ([#185](https://github.com/rstudio/httpuv/pull/185), [#192](https://github.com/rstudio/httpuv/pull/192))

* `encodeURI()` and `encodeURIComponent()`, now convert their inputs to UTF-8 before URL-encoding. ([#192](https://github.com/rstudio/httpuv/pull/192))

* `encodeURI()`, `encodeURIComponent()`, `decodeURI()`, and `decodeURIComponent()` now handle `NA`s correctly. ([#192](https://github.com/rstudio/httpuv/pull/192))

* `service()` now executes a single `later` callback, rather than all eligible callbacks. This gives callers more opportunities to perform their own housekeeping when multiple expensive callbacks queue up. ([#176](https://github.com/rstudio/httpuv/pull/176))

Expand Down
30 changes: 16 additions & 14 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
Expand Up @@ -46,30 +46,28 @@ base64encode <- function(x) {
}

#' URI encoding/decoding
#'
#'
#' Encodes/decodes strings using URI encoding/decoding in the same way that web
#' browsers do. The precise behaviors of these functions can be found at
#' developer.mozilla.org:
#' \href{https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI}{encodeURI},
#' \href{https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent}{encodeURIComponent},
#' \href{https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURI}{decodeURI},
#' \href{https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent}{decodeURIComponent}
#'
#'
#' Intended as a faster replacement for \code{\link[utils]{URLencode}} and
#' \code{\link[utils]{URLdecode}}.
#'
#'
#' encodeURI differs from encodeURIComponent in that the former will not encode
#' reserved characters: \code{;,/?:@@&=+$}
#'
#'
#' decodeURI differs from decodeURIComponent in that it will refuse to decode
#' encoded sequences that decode to a reserved character. (If in doubt, use
#' decodeURIComponent.)
#'
#' The only way these functions differ from web browsers is in the encoding of
#' non-ASCII characters. All non-ASCII characters will be escaped byte-by-byte.
#' If conformant non-ASCII behavior is important, ensure that your input vector
#' is UTF-8 encoded before calling encodeURI or encodeURIComponent.
#'
#'
#' For \code{encodeURI} and \code{encodeURIComponent}, input strings will be
#' converted to UTF-8 before URL-encoding.
#'
#' @param value Character vector to be encoded or decoded.
#' @return Encoded or decoded character vector of the same length as the
#' input value. \code{decodeURI} and \code{decodeURIComponent} will return
Expand All @@ -86,12 +84,16 @@ encodeURIComponent <- function(value) {
.Call('_httpuv_encodeURIComponent', PACKAGE = 'httpuv', value)
}

decodeURI_ <- function(value) {
.Call('_httpuv_decodeURI_', PACKAGE = 'httpuv', value)
#' @rdname encodeURI
#' @export
decodeURI <- function(value) {
.Call('_httpuv_decodeURI', PACKAGE = 'httpuv', value)
}

decodeURIComponent_ <- function(value) {
.Call('_httpuv_decodeURIComponent_', PACKAGE = 'httpuv', value)
#' @rdname encodeURI
#' @export
decodeURIComponent <- function(value) {
.Call('_httpuv_decodeURIComponent', PACKAGE = 'httpuv', value)
}

#' Check whether an address is IPv4 or IPv6
Expand Down
15 changes: 0 additions & 15 deletions R/decode_uri.R

This file was deleted.

8 changes: 3 additions & 5 deletions man/encodeURI.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions src/RcppExports-legacy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@

using namespace Rcpp;

std::vector<std::string> decodeURIComponent_(std::vector<std::string> value);
Rcpp::CharacterVector decodeURIComponent(Rcpp::CharacterVector value);
RcppExport SEXP httpuv_decodeURIComponent(SEXP valueSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< std::vector<std::string> >::type value(valueSEXP);
rcpp_result_gen = Rcpp::wrap(decodeURIComponent_(value));
Rcpp::CharacterVector value(valueSEXP);
rcpp_result_gen = Rcpp::wrap(decodeURIComponent(value));
return rcpp_result_gen;
END_RCPP
}
34 changes: 17 additions & 17 deletions src/RcppExports.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,46 +149,46 @@ BEGIN_RCPP
END_RCPP
}
// encodeURI
std::vector<std::string> encodeURI(std::vector<std::string> value);
Rcpp::CharacterVector encodeURI(Rcpp::CharacterVector value);
RcppExport SEXP _httpuv_encodeURI(SEXP valueSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< std::vector<std::string> >::type value(valueSEXP);
Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type value(valueSEXP);
rcpp_result_gen = Rcpp::wrap(encodeURI(value));
return rcpp_result_gen;
END_RCPP
}
// encodeURIComponent
std::vector<std::string> encodeURIComponent(std::vector<std::string> value);
Rcpp::CharacterVector encodeURIComponent(Rcpp::CharacterVector value);
RcppExport SEXP _httpuv_encodeURIComponent(SEXP valueSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< std::vector<std::string> >::type value(valueSEXP);
Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type value(valueSEXP);
rcpp_result_gen = Rcpp::wrap(encodeURIComponent(value));
return rcpp_result_gen;
END_RCPP
}
// decodeURI_
std::vector<std::string> decodeURI_(std::vector<std::string> value);
RcppExport SEXP _httpuv_decodeURI_(SEXP valueSEXP) {
// decodeURI
Rcpp::CharacterVector decodeURI(Rcpp::CharacterVector value);
RcppExport SEXP _httpuv_decodeURI(SEXP valueSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< std::vector<std::string> >::type value(valueSEXP);
rcpp_result_gen = Rcpp::wrap(decodeURI_(value));
Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type value(valueSEXP);
rcpp_result_gen = Rcpp::wrap(decodeURI(value));
return rcpp_result_gen;
END_RCPP
}
// decodeURIComponent_
std::vector<std::string> decodeURIComponent_(std::vector<std::string> value);
RcppExport SEXP _httpuv_decodeURIComponent_(SEXP valueSEXP) {
// decodeURIComponent
Rcpp::CharacterVector decodeURIComponent(Rcpp::CharacterVector value);
RcppExport SEXP _httpuv_decodeURIComponent(SEXP valueSEXP) {
BEGIN_RCPP
Rcpp::RObject rcpp_result_gen;
Rcpp::RNGScope rcpp_rngScope_gen;
Rcpp::traits::input_parameter< std::vector<std::string> >::type value(valueSEXP);
rcpp_result_gen = Rcpp::wrap(decodeURIComponent_(value));
Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type value(valueSEXP);
rcpp_result_gen = Rcpp::wrap(decodeURIComponent(value));
return rcpp_result_gen;
END_RCPP
}
Expand Down Expand Up @@ -251,13 +251,13 @@ static const R_CallMethodDef CallEntries[] = {
{"_httpuv_base64encode", (DL_FUNC) &_httpuv_base64encode, 1},
{"_httpuv_encodeURI", (DL_FUNC) &_httpuv_encodeURI, 1},
{"_httpuv_encodeURIComponent", (DL_FUNC) &_httpuv_encodeURIComponent, 1},
{"_httpuv_decodeURI_", (DL_FUNC) &_httpuv_decodeURI_, 1},
{"_httpuv_decodeURIComponent_", (DL_FUNC) &_httpuv_decodeURIComponent_, 1},
{"_httpuv_decodeURI", (DL_FUNC) &_httpuv_decodeURI, 1},
{"_httpuv_decodeURIComponent", (DL_FUNC) &_httpuv_decodeURIComponent, 1},
{"_httpuv_ipFamily", (DL_FUNC) &_httpuv_ipFamily, 1},
{"_httpuv_invokeCppCallback", (DL_FUNC) &_httpuv_invokeCppCallback, 2},
{"_httpuv_getRNGState", (DL_FUNC) &_httpuv_getRNGState, 0},
{"_httpuv_wsconn_address", (DL_FUNC) &_httpuv_wsconn_address, 1},
{"httpuv_decodeURIComponent", (DL_FUNC) &httpuv_decodeURIComponent, 1},
{"httpuv_decodeURIComponent", (DL_FUNC) &httpuv_decodeURIComponent, 1},
{NULL, NULL, 0}
};

Expand Down
99 changes: 55 additions & 44 deletions src/httpuv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ std::string doEncodeURI(std::string value, bool encodeReserved) {
for (std::string::const_iterator it = value.begin();
it != value.end();
it++) {

if (!needsEscape(*it, encodeReserved)) {
os << *it;
} else {
Expand All @@ -501,60 +501,62 @@ std::string doEncodeURI(std::string value, bool encodeReserved) {
}

//' URI encoding/decoding
//'
//'
//' Encodes/decodes strings using URI encoding/decoding in the same way that web
//' browsers do. The precise behaviors of these functions can be found at
//' developer.mozilla.org:
//' \href{https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI}{encodeURI},
//' \href{https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent}{encodeURIComponent},
//' \href{https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURI}{decodeURI},
//' \href{https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/decodeURIComponent}{decodeURIComponent}
//'
//'
//' Intended as a faster replacement for \code{\link[utils]{URLencode}} and
//' \code{\link[utils]{URLdecode}}.
//'
//'
//' encodeURI differs from encodeURIComponent in that the former will not encode
//' reserved characters: \code{;,/?:@@&=+$}
//'
//'
//' decodeURI differs from decodeURIComponent in that it will refuse to decode
//' encoded sequences that decode to a reserved character. (If in doubt, use
//' decodeURIComponent.)
//'
//' The only way these functions differ from web browsers is in the encoding of
//' non-ASCII characters. All non-ASCII characters will be escaped byte-by-byte.
//' If conformant non-ASCII behavior is important, ensure that your input vector
//' is UTF-8 encoded before calling encodeURI or encodeURIComponent.
//'
//'
//' For \code{encodeURI} and \code{encodeURIComponent}, input strings will be
//' converted to UTF-8 before URL-encoding.
//'
//' @param value Character vector to be encoded or decoded.
//' @return Encoded or decoded character vector of the same length as the
//' input value. \code{decodeURI} and \code{decodeURIComponent} will return
//' strings that are UTF-8 encoded.
//'
//' @export
// [[Rcpp::export]]
std::vector<std::string> encodeURI(std::vector<std::string> value) {
for (std::vector<std::string>::iterator it = value.begin();
it != value.end();
it++) {

*it = doEncodeURI(*it, false);
Rcpp::CharacterVector encodeURI(Rcpp::CharacterVector value) {
Rcpp::CharacterVector out(value.size(), NA_STRING);

for (int i = 0; i < value.size(); i++) {
if (value[i] != NA_STRING) {
const char* s = Rf_translateCharUTF8(value[i]);
s = doEncodeURI(s, false).c_str();
out[i] = Rf_mkCharCE(s, CE_UTF8);
}
}

return value;
return out;
}

//' @rdname encodeURI
//' @export
// [[Rcpp::export]]
std::vector<std::string> encodeURIComponent(std::vector<std::string> value) {
for (std::vector<std::string>::iterator it = value.begin();
it != value.end();
it++) {

*it = doEncodeURI(*it, true);
Rcpp::CharacterVector encodeURIComponent(Rcpp::CharacterVector value) {
Rcpp::CharacterVector out(value.size(), NA_STRING);

for (int i = 0; i < value.size(); i++) {
if (value[i] != NA_STRING) {
const char* s = Rf_translateCharUTF8(value[i]);
s = doEncodeURI(s, true).c_str();
out[i] = Rf_mkCharCE(s, CE_UTF8);
}
}

return value;
return out;
}

int hexToInt(char c) {
Expand Down Expand Up @@ -584,14 +586,14 @@ std::string doDecodeURI(std::string value, bool component) {
for (std::string::const_iterator it = value.begin();
it != value.end();
it++) {

// If there aren't enough characters left for this to be a
// valid escape code, just use the character and move on
if (it > value.end() - 3) {
os << *it;
continue;
}

if (*it == '%') {
char hi = *(++it);
char lo = *(++it);
Expand All @@ -612,32 +614,41 @@ std::string doDecodeURI(std::string value, bool component) {
os << *it;
}
}

return os.str();
}


//' @rdname encodeURI
//' @export
// [[Rcpp::export]]
std::vector<std::string> decodeURI_(std::vector<std::string> value) {
for (std::vector<std::string>::iterator it = value.begin();
it != value.end();
it++) {
Rcpp::CharacterVector decodeURI(Rcpp::CharacterVector value) {
Rcpp::CharacterVector out(value.size(), NA_STRING);

*it = doDecodeURI(*it, false);
for (int i = 0; i < value.size(); i++) {
if (value[i] != NA_STRING) {
const char* s = doDecodeURI(Rcpp::as<std::string>(value[i]), false).c_str();
out[i] = Rf_mkCharCE(s, CE_UTF8);
}
}
return value;

return out;
}

//' @rdname encodeURI
//' @export
// [[Rcpp::export]]
std::vector<std::string> decodeURIComponent_(std::vector<std::string> value) {
for (std::vector<std::string>::iterator it = value.begin();
it != value.end();
it++) {
Rcpp::CharacterVector decodeURIComponent(Rcpp::CharacterVector value) {
Rcpp::CharacterVector out(value.size(), NA_STRING);

*it = doDecodeURI(*it, true);
for (int i = 0; i < value.size(); i++) {
if (value[i] != NA_STRING) {
const char* s = doDecodeURI(Rcpp::as<std::string>(value[i]), true).c_str();
out[i] = Rf_mkCharCE(s, CE_UTF8);
}
}
return value;

return out;
}

//' Check whether an address is IPv4 or IPv6
Expand Down
Loading

0 comments on commit e59dbe8

Please sign in to comment.