Pārlūkot izejas kodu

paste: render HTML version if visitor is browser

Peter Cai 1 gadu atpakaļ
vecāks
revīzija
9e92c1d826
Parakstījis: Peter Cai <[email protected]> GPG atslēgas ID: 71F5FB4E4F3FD54F
6 mainītis faili ar 108 papildinājumiem un 5 dzēšanām
  1. 1
    0
      Cargo.lock
  2. 1
    0
      backend/Cargo.toml
  3. 1
    0
      backend/src/main.rs
  4. 18
    5
      backend/src/paste.rs
  5. 20
    0
      backend/src/util.rs
  6. 67
    0
      template/code.html

+ 1
- 0
Cargo.lock Parādīt failu

@@ -112,6 +112,7 @@ dependencies = [
112 112
  "byteorder 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
113 113
  "bytes 0.4.9 (registry+https://github.com/rust-lang/crates.io-index)",
114 114
  "futures 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
115
+ "htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
115 116
  "rand 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
116 117
  "serde 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",
117 118
  "serde_derive 1.0.70 (registry+https://github.com/rust-lang/crates.io-index)",

+ 1
- 0
backend/Cargo.toml Parādīt failu

@@ -9,6 +9,7 @@ actix-web = "0.7"
9 9
 bytes = "0.4"
10 10
 byteorder = "1.2"
11 11
 futures = "0.1"
12
+htmlescape = "0.3"
12 13
 rand = "0.5"
13 14
 serde = "1.0"
14 15
 serde_derive = "1.0"

+ 1
- 0
backend/src/main.rs Parādīt failu

@@ -2,6 +2,7 @@ extern crate actix;
2 2
 extern crate actix_web;
3 3
 extern crate bytes;
4 4
 extern crate byteorder;
5
+extern crate htmlescape;
5 6
 extern crate rand;
6 7
 extern crate futures;
7 8
 extern crate serde;

+ 18
- 5
backend/src/paste.rs Parādīt failu

@@ -1,9 +1,10 @@
1
-use actix_web::{http, App, AsyncResponder, Responder, HttpMessage, HttpRequest};
1
+use actix_web::{http, App, AsyncResponder, Responder, HttpMessage, HttpRequest, HttpResponse};
2 2
 use actix_web::error::{ErrorNotFound, ErrorInternalServerError};
3 3
 use app::{AngryError, AngryAppState};
4 4
 use bytes::Bytes;
5 5
 use futures::Future;
6 6
 use futures::future::{self, Either};
7
+use htmlescape;
7 8
 use util;
8 9
 
9 10
 pub fn setup_routes(app: App<AngryAppState>) -> App<AngryAppState> {
@@ -53,8 +54,10 @@ fn paste(req: &HttpRequest<AngryAppState>) -> impl Responder {
53 54
 }
54 55
 
55 56
 fn show_paste(req: &HttpRequest<AngryAppState>) -> impl Responder {
56
-    // TODO: Show rendered version of the paste (i.e. add a HTML frame for highlighting etc.)
57
-    // if the viewer is a browser
57
+    let ua = req.headers().get(http::header::USER_AGENT)
58
+        .and_then(|r| {
59
+            r.to_str().ok()
60
+        }).unwrap_or("").to_owned();
58 61
     let id = req.match_info().get("id").unwrap().to_owned();
59 62
     let state = req.state().clone();
60 63
     let db = state.get_db();
@@ -63,9 +66,19 @@ fn show_paste(req: &HttpRequest<AngryAppState>) -> impl Responder {
63 66
             println!("{:?}", e);
64 67
             ErrorInternalServerError(e)
65 68
         })
66
-        .and_then(|p| {
69
+        .and_then(move |p| {
67 70
             if p != "" {
68
-                Ok(p)
71
+                let mut resp = HttpResponse::Ok();
72
+                if util::ua_is_browser(&ua) {
73
+                    // Show a rendered HTML for GUI browsers
74
+                    resp.header(http::header::CONTENT_TYPE, "text/html");
75
+                    Ok(resp.body(
76
+                        include_str!("../../template/code.html")
77
+                            .replace("{{code}}", &htmlescape::encode_minimal(&p))))
78
+                } else {
79
+                    resp.header(http::header::CONTENT_TYPE, "text/plain");
80
+                    Ok(resp.body(p))
81
+                }
69 82
             } else {
70 83
                 Err(ErrorNotFound("Paste data not recorded"))
71 84
             }

+ 20
- 0
backend/src/util.rs Parādīt failu

@@ -20,4 +20,24 @@ pub fn rand_str(len: usize) -> String {
20 20
  */
21 21
 pub fn conn_scheme_host_port(info: &ConnectionInfo) -> String {
22 22
     format!("{}://{}", info.scheme(), info.host())
23
+}
24
+
25
+/*
26
+ * Return true if the user agent is considered a browser
27
+ */
28
+const BROWSER_AGENTS: &[&str] = &[
29
+    "chrome",
30
+    "msie",
31
+    "trident",
32
+    "firefox",
33
+    "safari",
34
+];
35
+pub fn ua_is_browser(ua: &str) -> bool {
36
+    let ua = ua.to_lowercase();
37
+    for ba in BROWSER_AGENTS {
38
+        if ua.contains(ba) {
39
+            return true;
40
+        }
41
+    }
42
+    return false;
23 43
 }

+ 67
- 0
template/code.html Parādīt failu

@@ -0,0 +1,67 @@
1
+<!DOCTYPE html>
2
+<html lang="en">
3
+  <head>
4
+    <meta charset="utf-8">
5
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
+    <meta name="viewport" content="width=device-width, initial-scale=1">
7
+    <title>Angry.Im - Paste</title>
8
+
9
+    <!-- Bootstrap -->
10
+    <link href="https://cdn.css.net/files/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" rel="stylesheet">
11
+    <!-- Hightlight.js -->
12
+    <link href="https://cdn.css.net/files/highlight.js/9.9.0/styles/zenburn.min.css" rel="stylesheet">
13
+    <style>
14
+      pre {
15
+        border-radius: 5px;
16
+        font-size: 1em;
17
+      }
18
+    </style>
19
+  </head>
20
+  <body>
21
+    <div class="container">
22
+      <div class="card card-outline-info text-center">
23
+        <div class="card-block">
24
+          <pre class="text-left"><code id="code">{{code}}</code></pre>
25
+        </div>
26
+      </div>
27
+    </div>
28
+    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
29
+    <script src="https://cdn.css.net/files/jquery/1.12.4/jquery.min.js"></script>
30
+    <!-- Include all compiled plugins (below), or include individual files as needed -->
31
+    <script src="https://cdn.css.net/files/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js"></script>
32
+    <!-- Hightlight.js -->
33
+    <script src="https://cdn.css.net/files/highlight.js/9.9.0/highlight.min.js"></script>
34
+    <script>
35
+      var code = ""
36
+      $(document).ready(function() {
37
+          code = $("#code").text()
38
+          var lang = getParameterByName('lang')
39
+          if (lang != null && lang != "") {
40
+              toggleLanguage(lang)
41
+          } else {
42
+              hljs.initHighlighting()
43
+          }
44
+      })
45
+      function getParameterByName(name, url) {
46
+          if (!url) {
47
+              url = window.location.href;
48
+          }
49
+          name = name.replace(/[\[\]]/g, "\\$&");
50
+          var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
51
+          results = regex.exec(url);
52
+          if (!results) return null;
53
+          if (!results[2]) return '';
54
+          return decodeURIComponent(results[2].replace(/\+/g, " "));
55
+      }
56
+      function toggleLanguage(lang) {
57
+          $('#code').removeClass()
58
+          $('#code').addClass(lang)
59
+          $('#code').text(code)
60
+          // Add language
61
+          $.getScript('https://cdn.css.net/files/highlight.js/9.9.0/languages/' + lang + '.min.js', function () {
62
+              hljs.initHighlighting()
63
+          })
64
+      }
65
+    </script>
66
+  </body>
67
+</html>

Notiek ielāde…
Atcelt
Saglabāt