printer_configuration.cc 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. // Copyright 2016 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "chromeos/printing/printer_configuration.h"
  5. #include "base/containers/fixed_flat_set.h"
  6. #include "base/guid.h"
  7. #include "base/logging.h"
  8. #include "base/notreached.h"
  9. #include "base/strings/string_piece.h"
  10. #include "base/strings/string_util.h"
  11. #include "chromeos/printing/printing_constants.h"
  12. #include "chromeos/printing/uri.h"
  13. #include "net/base/ip_endpoint.h"
  14. #include "third_party/abseil-cpp/absl/types/optional.h"
  15. #include "url/third_party/mozilla/url_parse.h"
  16. #include "url/url_constants.h"
  17. namespace chromeos {
  18. namespace {
  19. std::string ToString(Uri::ParserStatus status) {
  20. switch (status) {
  21. case Uri::ParserStatus::kInvalidPercentEncoding:
  22. return "invalid percent encoding";
  23. case Uri::ParserStatus::kDisallowedASCIICharacter:
  24. return "disallowed ASCII character";
  25. case Uri::ParserStatus::kInvalidUTF8Character:
  26. return "invalid UTF-8 character";
  27. case Uri::ParserStatus::kInvalidScheme:
  28. return "invalid scheme";
  29. case Uri::ParserStatus::kInvalidPortNumber:
  30. return "invalid port number";
  31. case Uri::ParserStatus::kRelativePathsNotAllowed:
  32. return "relative paths not allowed";
  33. case Uri::ParserStatus::kEmptySegmentInPath:
  34. return "empty segment in path";
  35. case Uri::ParserStatus::kEmptyParameterNameInQuery:
  36. return "empty parameter name in query";
  37. case Uri::ParserStatus::kNoErrors:
  38. return "no errors";
  39. }
  40. return "unknown error";
  41. }
  42. } // namespace
  43. std::string ToString(PrinterClass pclass) {
  44. switch (pclass) {
  45. case PrinterClass::kEnterprise:
  46. return "Enterprise";
  47. case PrinterClass::kAutomatic:
  48. return "Automatic";
  49. case PrinterClass::kDiscovered:
  50. return "Discovered";
  51. case PrinterClass::kSaved:
  52. return "Saved";
  53. }
  54. NOTREACHED();
  55. return "";
  56. }
  57. bool IsValidPrinterUri(const Uri& uri, std::string* error_message) {
  58. static constexpr auto kKnownSchemes =
  59. base::MakeFixedFlatSet<base::StringPiece>(
  60. {"http", "https", "ipp", "ipps", "ippusb", "lpd", "socket", "usb"});
  61. static const std::string kPrefix = "Malformed printer URI: ";
  62. if (!kKnownSchemes.contains(uri.GetScheme())) {
  63. if (error_message)
  64. *error_message = kPrefix + "unknown or missing scheme";
  65. return false;
  66. }
  67. // Only printer URIs with the lpd scheme are allowed to have Userinfo.
  68. if (!uri.GetUserinfo().empty() && uri.GetScheme() != "lpd") {
  69. if (error_message)
  70. *error_message = kPrefix + "user info is not allowed for this scheme";
  71. return false;
  72. }
  73. if (uri.GetHost().empty()) {
  74. if (error_message)
  75. *error_message = kPrefix + "missing host";
  76. return false;
  77. }
  78. if (uri.GetScheme() == "ippusb" || uri.GetScheme() == "usb") {
  79. if (uri.GetPort() > -1) {
  80. if (error_message)
  81. *error_message = kPrefix + "port is not allowed for this scheme";
  82. return false;
  83. }
  84. if (uri.GetPath().empty()) {
  85. if (error_message)
  86. *error_message = kPrefix + "path is required for this scheme";
  87. return false;
  88. }
  89. }
  90. if (uri.GetScheme() == "socket" && !uri.GetPath().empty()) {
  91. if (error_message)
  92. *error_message = kPrefix + "path is not allowed for this scheme";
  93. return false;
  94. }
  95. if (!uri.GetFragment().empty()) {
  96. if (error_message)
  97. *error_message = kPrefix + "fragment is not allowed";
  98. return false;
  99. }
  100. return true;
  101. }
  102. bool Printer::PpdReference::IsFilled() const {
  103. return autoconf || !user_supplied_ppd_url.empty() ||
  104. !effective_make_and_model.empty();
  105. }
  106. Printer::Printer() : id_(base::GenerateGUID()), source_(SRC_USER_PREFS) {}
  107. Printer::Printer(const std::string& id) : id_(id), source_(SRC_USER_PREFS) {
  108. if (id_.empty())
  109. id_ = base::GenerateGUID();
  110. }
  111. Printer::Printer(const Printer& other) = default;
  112. Printer& Printer::operator=(const Printer& other) = default;
  113. Printer::~Printer() = default;
  114. bool Printer::SetUri(const Uri& uri, std::string* error_message) {
  115. if (!IsValidPrinterUri(uri, error_message))
  116. return false;
  117. uri_ = uri;
  118. return true;
  119. }
  120. bool Printer::SetUri(const std::string& uri, std::string* error_message) {
  121. Uri parsed_uri(uri);
  122. const Uri::ParserError& parser_status = parsed_uri.GetLastParsingError();
  123. if (parser_status.status == Uri::ParserStatus::kNoErrors)
  124. return SetUri(parsed_uri, error_message);
  125. if (error_message) {
  126. *error_message = "Malformed URI: " + ToString(parser_status.status);
  127. }
  128. return false;
  129. }
  130. bool Printer::IsIppEverywhere() const {
  131. return ppd_reference_.autoconf;
  132. }
  133. net::HostPortPair Printer::GetHostAndPort() const {
  134. if (!HasUri()) {
  135. return net::HostPortPair();
  136. }
  137. return net::HostPortPair(uri_.GetHost(), uri_.GetPort());
  138. }
  139. Uri Printer::ReplaceHostAndPort(const net::IPEndPoint& ip) const {
  140. if (!HasUri()) {
  141. return Uri();
  142. }
  143. const std::string host = ip.ToStringWithoutPort();
  144. if (host.empty()) {
  145. return Uri();
  146. }
  147. Uri uri = uri_;
  148. uri.SetHost(host);
  149. uri.SetPort(ip.port());
  150. return uri;
  151. }
  152. Printer::PrinterProtocol Printer::GetProtocol() const {
  153. if (uri_.GetScheme() == "usb")
  154. return PrinterProtocol::kUsb;
  155. if (uri_.GetScheme() == "ipp")
  156. return PrinterProtocol::kIpp;
  157. if (uri_.GetScheme() == "ipps")
  158. return PrinterProtocol::kIpps;
  159. if (uri_.GetScheme() == "http")
  160. return PrinterProtocol::kHttp;
  161. if (uri_.GetScheme() == "https")
  162. return PrinterProtocol::kHttps;
  163. if (uri_.GetScheme() == "socket")
  164. return PrinterProtocol::kSocket;
  165. if (uri_.GetScheme() == "lpd")
  166. return PrinterProtocol::kLpd;
  167. if (uri_.GetScheme() == "ippusb")
  168. return PrinterProtocol::kIppUsb;
  169. return PrinterProtocol::kUnknown;
  170. }
  171. bool Printer::HasNetworkProtocol() const {
  172. Printer::PrinterProtocol current_protocol = GetProtocol();
  173. switch (current_protocol) {
  174. case PrinterProtocol::kIpp:
  175. case PrinterProtocol::kIpps:
  176. case PrinterProtocol::kHttp:
  177. case PrinterProtocol::kHttps:
  178. case PrinterProtocol::kSocket:
  179. case PrinterProtocol::kLpd:
  180. return true;
  181. default:
  182. return false;
  183. }
  184. }
  185. bool Printer::IsUsbProtocol() const {
  186. Printer::PrinterProtocol current_protocol = GetProtocol();
  187. switch (current_protocol) {
  188. case PrinterProtocol::kUsb:
  189. case PrinterProtocol::kIppUsb:
  190. return true;
  191. default:
  192. return false;
  193. }
  194. }
  195. bool Printer::HasSecureProtocol() const {
  196. Printer::PrinterProtocol current_protocol = GetProtocol();
  197. switch (current_protocol) {
  198. case PrinterProtocol::kUsb:
  199. case PrinterProtocol::kIpps:
  200. case PrinterProtocol::kHttps:
  201. case PrinterProtocol::kIppUsb:
  202. return true;
  203. default:
  204. return false;
  205. }
  206. }
  207. bool Printer::IsZeroconf() const {
  208. return base::EndsWith(uri_.GetHost(), ".local");
  209. }
  210. } // namespace chromeos