1#' Safely interpolate strings
2#'
3#' `glue_safe()` and `glue_data_safe()` differ from [glue()] and [glue_data()]
4#' in that the safe versions only look up symbols from an environment using
5#' [get()]. They do not execute any R code. This makes them suitable for use
6#' with untrusted input, such as inputs in a Shiny application, where using the
7#' normal functions would allow an attacker to execute arbitrary code.
8#' @inheritParams glue
9#' @export
10#' @examples
11#' "1 + 1" <- 5
12#' # glue actually executes the code
13#' glue("{1 + 1}")
14#'
15#' # glue_safe just looks up the value
16#' glue_safe("{1 + 1}")
17#'
18#' rm("1 + 1")
19glue_safe <- function(..., .envir = parent.frame()) {
20  glue(..., .envir = .envir, .transformer = get_transformer)
21}
22
23#' @rdname glue_safe
24#' @export
25glue_data_safe <- function(.x, ..., .envir = parent.frame()) {
26  glue_data(.x, ..., .envir = .envir, .transformer = get_transformer)
27}
28
29get_transformer <- function(text, envir) {
30  if (!exists(text, envir = envir)) {
31    stop("object '", text, "' not found", call. = FALSE)
32  } else {
33    get(text, envir = envir)
34  }
35}
36