1 /* UserPrefValuesNative.cpp
2  *
3  * Copyright (C) 2021 by RStudio, PBC
4  *
5  * Unless you have received this program directly from RStudio pursuant
6  * to the terms of a commercial license agreement with RStudio, then
7  * this program is licensed to you under the terms of version 3 of the
8  * GNU Affero General Public License. This program is distributed WITHOUT
9  * ANY EXPRESS OR IMPLIED WARRANTY, INCLUDING THOSE OF NON-INFRINGEMENT,
10  * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Please refer to the
11  * AGPL (http://www.gnu.org/licenses/agpl-3.0.txt) for more details.
12  *
13  */
14 
15 #include <session/prefs/UserPrefs.hpp>
16 #include <session/prefs/UserState.hpp>
17 
18 #include <boost/algorithm/string.hpp>
19 
20 #include <core/json/JsonRpc.hpp>
21 
22 #include <r/RExec.hpp>
23 
24 using namespace rstudio::core;
25 
26 namespace rstudio {
27 namespace session {
28 namespace prefs {
29 namespace {
30 
setCRANReposOption(const std::string & url,const std::string & secondary)31 void setCRANReposOption(const std::string& url, const std::string& secondary)
32 {
33    if (!url.empty())
34    {
35       Error error = r::exec::RFunction(".rs.setCRANReposFromSettings",
36                                        url, secondary).call();
37       if (error)
38          LOG_ERROR(error);
39    }
40 }
41 
42 } // anonymous namespace
43 
lineEndings()44 string_utils::LineEnding UserPrefValuesNative::lineEndings()
45 {
46    std::string pref(lineEndingConversion());
47 
48    if (pref == kLineEndingConversionNative)
49       return string_utils::LineEndingNative;
50    else if (pref == kLineEndingConversionPosix)
51       return string_utils::LineEndingPosix;
52    else if (pref == kLineEndingConversionWindows)
53       return string_utils::LineEndingWindows;
54    else if (pref == kLineEndingConversionPassthrough)
55       return string_utils::LineEndingPassthrough;
56 
57    return string_utils::LineEndingNative;
58 }
59 
getCRANMirror()60 CRANMirror UserPrefValuesNative::getCRANMirror()
61 {
62    // get the settings
63    struct CRANMirror mirror;
64    json::readObject(cranMirror(),
65          kCranMirrorUrl, mirror.url,
66          kCranMirrorName, mirror.name,
67          kCranMirrorHost, mirror.host,
68          kCranMirrorSecondary, mirror.secondary,
69          kCranMirrorCountry, mirror.country);
70 
71    // upgrade 1.2 preview builds
72    std::vector<std::string> parts;
73    boost::split(parts, mirror.url, boost::is_any_of("|"));
74    if (parts.size() >= 2)
75    {
76       mirror.secondary = mirror.url;
77       mirror.url = parts.at(1);
78    }
79 
80    // re-map cran.rstudio.org to cran.rstudio.com
81    if (boost::algorithm::starts_with(mirror.url, "http://cran.rstudio.org"))
82       mirror.url = "http://cran.rstudio.com/";
83 
84    // remap url without trailing slash
85    if (!mirror.url.empty() && !boost::algorithm::ends_with(mirror.url, "/"))
86       mirror.url += "/";
87 
88    return mirror;
89 }
90 
91 
setCRANMirror(const struct CRANMirror & mirror,bool update)92 core::Error UserPrefValuesNative::setCRANMirror(const struct CRANMirror& mirror,
93       bool update)
94 {
95    json::Object obj;
96    obj[kCranMirrorName] = mirror.name;
97    obj[kCranMirrorHost] = mirror.host;
98    obj[kCranMirrorUrl] = mirror.url;
99    obj[kCranMirrorSecondary] = mirror.secondary;
100    obj[kCranMirrorCountry] = mirror.country;
101 
102    // only set the underlying option if it's not empty (some
103    // evidence exists that this is possible, it doesn't appear to
104    // be possible in the current code however previous releases
105    // may have let this in)
106    if (!mirror.url.empty() && update)
107       setCRANReposOption(mirror.url, mirror.secondary);
108 
109    return setCranMirror(obj);
110 }
111 
defaultTerminalShellValue()112 console_process::TerminalShell::ShellType UserPrefValuesNative::defaultTerminalShellValue()
113 {
114    using ShellType = console_process::TerminalShell::ShellType;
115 #ifdef WIN32
116    ShellType type = console_process::TerminalShell::shellTypeFromString(windowsTerminalShell());
117 #else
118    ShellType type = console_process::TerminalShell::shellTypeFromString(posixTerminalShell());
119 #endif
120 
121    // map obsolete 32-bit shell types to their 64-bit equivalents
122    if (type == console_process::TerminalShell::ShellType::Cmd32)
123       type = console_process::TerminalShell::ShellType::Cmd64;
124    else if (type == console_process::TerminalShell::ShellType::PS32)
125       type = console_process::TerminalShell::ShellType::PS64;
126 
127    return static_cast<console_process::TerminalShell::ShellType>(type);
128 }
129 
130 }
131 }
132 }
133