Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 package main | 1 package main |
| 2 | 2 |
| 3 import ( | 3 import ( |
| 4 "bytes" | 4 "bytes" |
| 5 "crypto/md5" | 5 "crypto/md5" |
| 6 "database/sql" | 6 "database/sql" |
| 7 "encoding/base64" | 7 "encoding/base64" |
| 8 "encoding/json" | 8 "encoding/json" |
| 9 "flag" | 9 "flag" |
| 10 "fmt" | 10 "fmt" |
| 11 _ "github.com/go-sql-driver/mysql" | 11 _ "github.com/go-sql-driver/mysql" |
| 12 _ "github.com/mattn/go-sqlite3" | 12 _ "github.com/mattn/go-sqlite3" |
| 13 htemplate "html/template" | 13 htemplate "html/template" |
| 14 "io/ioutil" | 14 "io/ioutil" |
| 15 "log" | 15 "log" |
| 16 "net/http" | 16 "net/http" |
| 17 "os" | 17 "os" |
| 18 "os/exec" | 18 "os/exec" |
| 19 "path/filepath" | 19 "path/filepath" |
| 20 "regexp" | 20 "regexp" |
| 21 "strings" | 21 "strings" |
| 22 "text/template" | 22 "text/template" |
| 23 "time" | |
| 23 ) | 24 ) |
| 24 | 25 |
| 25 const ( | 26 const ( |
| 26 RESULT_COMPILE = `c++ -DSK_GAMMA_SRGB -DSK_GAMMA_APPLY_TO_A8 -DSK_SCALAR _TO_FLOAT_EXCLUDED -DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1 -DSK_SUPPORT_GPU=0 -D SK_SUPPORT_OPENCL=0 -DSK_FORCE_DISTANCEFIELD_FONTS=0 -DSK_SCALAR_IS_FLOAT -DSK_C AN_USE_FLOAT -DSK_SAMPLES_FOR_X -DSK_BUILD_FOR_UNIX -DSK_USE_POSIX_THREADS -DSK_ SYSTEM_ZLIB=1 -DSK_DEBUG -DSK_DEVELOPER=1 -I../../src/core -I../../src/images -I ../../tools/flags -I../../include/config -I../../include/core -I../../include/pa thops -I../../include/pipe -I../../include/effects -I../../include/ports -I../.. /src/sfnt -I../../include/utils -I../../src/utils -I../../include/images -g -fno -exceptions -fstrict-aliasing -Wall -Wextra -Winit-self -Wpointer-arith -Wno-unu sed-parameter -Wno-c++11-extensions -Werror -m64 -fno-rtti -Wnon-virtual-dtor -c ../../../cache/%s.cpp -o ../../../cache/%s.o` | 27 RESULT_COMPILE = `c++ -DSK_GAMMA_SRGB -DSK_GAMMA_APPLY_TO_A8 -DSK_SCALAR _TO_FLOAT_EXCLUDED -DSK_ALLOW_STATIC_GLOBAL_INITIALIZERS=1 -DSK_SUPPORT_GPU=0 -D SK_SUPPORT_OPENCL=0 -DSK_FORCE_DISTANCEFIELD_FONTS=0 -DSK_SCALAR_IS_FLOAT -DSK_C AN_USE_FLOAT -DSK_SAMPLES_FOR_X -DSK_BUILD_FOR_UNIX -DSK_USE_POSIX_THREADS -DSK_ SYSTEM_ZLIB=1 -DSK_DEBUG -DSK_DEVELOPER=1 -I../../src/core -I../../src/images -I ../../tools/flags -I../../include/config -I../../include/core -I../../include/pa thops -I../../include/pipe -I../../include/effects -I../../include/ports -I../.. /src/sfnt -I../../include/utils -I../../src/utils -I../../include/images -g -fno -exceptions -fstrict-aliasing -Wall -Wextra -Winit-self -Wpointer-arith -Wno-unu sed-parameter -Wno-c++11-extensions -Werror -m64 -fno-rtti -Wnon-virtual-dtor -c ../../../cache/%s.cpp -o ../../../cache/%s.o` |
| 27 LINK = `c++ -m64 -lstdc++ -lm -o ../../../inout/%s -Wl,--start -group ../../../cache/%s.o obj/experimental/webtry/webtry.main.o obj/gyp/libflag s.a libskia_images.a libskia_core.a libskia_effects.a obj/gyp/libjpeg.a obj/gyp/ libwebp_dec.a obj/gyp/libwebp_demux.a obj/gyp/libwebp_dsp.a obj/gyp/libwebp_enc. a obj/gyp/libwebp_utils.a libskia_utils.a libskia_opts.a libskia_opts_ssse3.a li bskia_ports.a libskia_sfnt.a -Wl,--end-group -lpng -lz -lgif -lpthread -lfontcon fig -ldl -lfreetype` | 28 LINK = `c++ -m64 -lstdc++ -lm -o ../../../inout/%s -Wl,--start -group ../../../cache/%s.o obj/experimental/webtry/webtry.main.o obj/gyp/libflag s.a libskia_images.a libskia_core.a libskia_effects.a obj/gyp/libjpeg.a obj/gyp/ libwebp_dec.a obj/gyp/libwebp_demux.a obj/gyp/libwebp_dsp.a obj/gyp/libwebp_enc. a obj/gyp/libwebp_utils.a libskia_utils.a libskia_opts.a libskia_opts_ssse3.a li bskia_ports.a libskia_sfnt.a -Wl,--end-group -lpng -lz -lgif -lpthread -lfontcon fig -ldl -lfreetype` |
| 28 DEFAULT_SAMPLE = `SkPaint p; | 29 DEFAULT_SAMPLE = `SkPaint p; |
| 29 p.setColor(SK_ColorRED); | 30 p.setColor(SK_ColorRED); |
| 30 p.setAntiAlias(true); | 31 p.setAntiAlias(true); |
| 31 p.setStyle(SkPaint::kStroke_Style); | 32 p.setStyle(SkPaint::kStroke_Style); |
| 32 p.setStrokeWidth(10); | 33 p.setStrokeWidth(10); |
| 33 | 34 |
| 34 canvas->drawLine(20, 20, 100, 100, p); | 35 canvas->drawLine(20, 20, 100, 100, p); |
| 35 ` | 36 ` |
| 36 ) | 37 ) |
| 37 | 38 |
| 38 var ( | 39 var ( |
| 39 // codeTemplate is the cpp code template the user's code is copied into. | 40 // codeTemplate is the cpp code template the user's code is copied into. |
| 40 codeTemplate *template.Template = nil | 41 codeTemplate *template.Template = nil |
| 41 | 42 |
| 42 » // index is the main index.html page we serve. | 43 » // indexTemplate is the main index.html page we serve. |
| 43 » index *htemplate.Template = nil | 44 » indexTemplate *htemplate.Template = nil |
| 45 | |
| 46 » // recentTemplate is a list of recent images. | |
| 47 » recentTemplate *htemplate.Template = nil | |
| 44 | 48 |
| 45 // db is the database, nil if we don't have an SQL database to store dat a into. | 49 // db is the database, nil if we don't have an SQL database to store dat a into. |
| 46 db *sql.DB = nil | 50 db *sql.DB = nil |
| 47 | 51 |
| 48 // directLink is the regex that matches URLs paths that are direct links . | 52 // directLink is the regex that matches URLs paths that are direct links . |
| 49 » directLink = regexp.MustCompile("^c/([a-a0-9]+)$") | 53 » directLink = regexp.MustCompile("^/c/([a-f0-9]+)$") |
| 54 | |
| 55 » // imageLink is the regex that matches URLs paths that are direct links to PNGs. | |
| 56 » imageLink = regexp.MustCompile("^/i/([a-f0-9]+.png)$") | |
| 50 ) | 57 ) |
| 51 | 58 |
| 52 // flags | 59 // flags |
| 53 var ( | 60 var ( |
| 54 useChroot = flag.Bool("use_chroot", false, "Run the compiled code in the schroot jail.") | 61 useChroot = flag.Bool("use_chroot", false, "Run the compiled code in the schroot jail.") |
| 55 port = flag.String("port", ":8000", "HTTP service address (e.g., ': 8000')") | 62 port = flag.String("port", ":8000", "HTTP service address (e.g., ': 8000')") |
| 56 ) | 63 ) |
| 57 | 64 |
| 58 // lineNumbers adds #line numbering to the user's code. | 65 // lineNumbers adds #line numbering to the user's code. |
| 59 func LineNumbers(c string) string { | 66 func LineNumbers(c string) string { |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 74 if err != nil { | 81 if err != nil { |
| 75 log.Fatal(err) | 82 log.Fatal(err) |
| 76 } | 83 } |
| 77 os.Chdir(cwd) | 84 os.Chdir(cwd) |
| 78 | 85 |
| 79 codeTemplate, err = template.ParseFiles(filepath.Join(cwd, "templates/te mplate.cpp")) | 86 codeTemplate, err = template.ParseFiles(filepath.Join(cwd, "templates/te mplate.cpp")) |
| 80 if err != nil { | 87 if err != nil { |
| 81 panic(err) | 88 panic(err) |
| 82 } | 89 } |
| 83 // Convert index.html into a template, which is expanded with the code. | 90 // Convert index.html into a template, which is expanded with the code. |
| 84 » index, err = htemplate.ParseFiles(filepath.Join(cwd, "templates/index.ht ml")) | 91 » indexTemplate, err = htemplate.ParseFiles(filepath.Join(cwd, "templates/ index.html")) |
| 85 if err != nil { | 92 if err != nil { |
| 86 panic(err) | 93 panic(err) |
| 87 } | 94 } |
| 95 | |
| 96 recentTemplate, err = htemplate.ParseFiles(filepath.Join(cwd, "templates /recent.html")) | |
| 97 if err != nil { | |
| 98 panic(err) | |
| 99 } | |
| 88 | 100 |
| 89 // Connect to MySQL server. First, get the password from the metadata se rver. | 101 // Connect to MySQL server. First, get the password from the metadata se rver. |
| 90 // See https://developers.google.com/compute/docs/metadata#custom. | 102 // See https://developers.google.com/compute/docs/metadata#custom. |
| 91 req, err := http.NewRequest("GET", "http://metadata/computeMetadata/v1/i nstance/attributes/password", nil) | 103 req, err := http.NewRequest("GET", "http://metadata/computeMetadata/v1/i nstance/attributes/password", nil) |
| 92 if err != nil { | 104 if err != nil { |
| 93 panic(err) | 105 panic(err) |
| 94 } | 106 } |
| 95 client := http.Client{} | 107 client := http.Client{} |
| 96 req.Header.Add("X-Google-Metadata-Request", "True") | 108 req.Header.Add("X-Google-Metadata-Request", "True") |
| 97 if resp, err := client.Do(req); err == nil { | 109 if resp, err := client.Do(req); err == nil { |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 219 | 231 |
| 220 func writeToDatabase(hash string, code string) { | 232 func writeToDatabase(hash string, code string) { |
| 221 if db == nil { | 233 if db == nil { |
| 222 return | 234 return |
| 223 } | 235 } |
| 224 if _, err := db.Exec("INSERT INTO webtry (code, hash) VALUES(?, ?)", cod e, hash); err != nil { | 236 if _, err := db.Exec("INSERT INTO webtry (code, hash) VALUES(?, ?)", cod e, hash); err != nil { |
| 225 log.Printf("ERROR: Failed to insert code into database: %q\n", e rr) | 237 log.Printf("ERROR: Failed to insert code into database: %q\n", e rr) |
| 226 } | 238 } |
| 227 } | 239 } |
| 228 | 240 |
| 241 func cssHandler(w http.ResponseWriter, r *http.Request) { | |
| 242 http.ServeFile(w, r, "css/webtry.css") | |
| 243 } | |
| 244 | |
| 245 // imageHandler serves up the PNG of a specific try. | |
| 246 func imageHandler(w http.ResponseWriter, r *http.Request) { | |
| 247 log.Printf("Image Handler: %q\n", r.URL.Path) | |
| 248 if r.Method != "GET" { | |
| 249 http.NotFound(w, r) | |
| 250 return | |
| 251 } | |
| 252 match := imageLink.FindStringSubmatch(r.URL.Path) | |
| 253 if len(match) != 2 { | |
| 254 http.NotFound(w, r) | |
| 255 return | |
| 256 } | |
| 257 filename := match[1] | |
| 258 http.ServeFile(w, r, fmt.Sprintf("../../../inout/%s", filename)) | |
|
mtklein
2014/04/14 18:27:53
Doesn't this make you sort of wish the images were
jcgregorio
2014/04/14 18:43:46
Yeah yeah, I'm coming around to that idea :-)
| |
| 259 } | |
| 260 | |
| 261 type Try struct { | |
| 262 Hash string | |
| 263 CreateTS string | |
| 264 } | |
| 265 | |
| 266 type Recent struct { | |
| 267 Tries []Try | |
| 268 } | |
| 269 | |
| 270 // recentHandler shows the last 20 tries. | |
| 271 func recentHandler(w http.ResponseWriter, r *http.Request) { | |
| 272 log.Printf("Recent Handler: %q\n", r.URL.Path) | |
| 273 | |
| 274 var err error | |
| 275 rows, err := db.Query("SELECT create_ts, hash FROM webtry ORDER BY creat e_ts DESC LIMIT 20") | |
| 276 if err != nil { | |
| 277 http.NotFound(w, r) | |
| 278 return | |
| 279 } | |
| 280 recent := []Try{} | |
| 281 for rows.Next() { | |
| 282 var hash string | |
| 283 var create_ts time.Time | |
| 284 if err := rows.Scan(&create_ts, &hash); err != nil { | |
| 285 log.Printf("Error: failed to fetch from database: %q", e rr) | |
| 286 continue | |
| 287 } | |
| 288 recent = append(recent, Try{Hash: hash, CreateTS: create_ts.Form at("2006-02-01")}) | |
|
mtklein
2014/04/14 18:27:53
I've never seen this .Format method before. Cute!
jcgregorio
2014/04/14 18:43:46
Yeah, makes for very readable code.
On 2014/04/14
| |
| 289 } | |
| 290 if err := recentTemplate.Execute(w, Recent{Tries: recent}); err != nil { | |
| 291 log.Printf("ERROR: Failed to expand template: %q\n", err) | |
| 292 } | |
| 293 } | |
| 294 | |
| 229 // mainHandler handles the GET and POST of the main page. | 295 // mainHandler handles the GET and POST of the main page. |
| 230 func mainHandler(w http.ResponseWriter, r *http.Request) { | 296 func mainHandler(w http.ResponseWriter, r *http.Request) { |
| 297 log.Printf("Main Handler: %q\n", r.URL.Path) | |
|
mtklein
2014/04/14 18:27:53
Leftover?
jcgregorio
2014/04/14 18:43:46
Actually useful to have in the logs.
On 2014/04/1
| |
| 231 if r.Method == "GET" { | 298 if r.Method == "GET" { |
| 232 code := DEFAULT_SAMPLE | 299 code := DEFAULT_SAMPLE |
| 233 directLink := regexp.MustCompile("^/c/([a-f0-9]+)$") | |
| 234 match := directLink.FindStringSubmatch(r.URL.Path) | 300 match := directLink.FindStringSubmatch(r.URL.Path) |
| 235 » » if len(match) == 2 { | 301 » » if len(match) == 2 && r.URL.Path != "/" { |
| 236 hash := match[1] | 302 hash := match[1] |
| 237 if db == nil { | 303 if db == nil { |
| 238 http.NotFound(w, r) | 304 http.NotFound(w, r) |
| 239 return | 305 return |
| 240 } | 306 } |
| 241 // Update 'code' with the code found in the database. | 307 // Update 'code' with the code found in the database. |
| 242 if err := db.QueryRow("SELECT code FROM webtry WHERE has h=?", hash).Scan(&code); err != nil { | 308 if err := db.QueryRow("SELECT code FROM webtry WHERE has h=?", hash).Scan(&code); err != nil { |
| 243 http.NotFound(w, r) | 309 http.NotFound(w, r) |
| 244 return | 310 return |
| 245 } | 311 } |
| 246 } | 312 } |
| 247 // Expand the template. | 313 // Expand the template. |
| 248 » » if err := index.Execute(w, userCode{UserCode: code}); err != nil { | 314 » » if err := indexTemplate.Execute(w, userCode{UserCode: code}); er r != nil { |
| 249 log.Printf("ERROR: Failed to expand template: %q\n", err ) | 315 log.Printf("ERROR: Failed to expand template: %q\n", err ) |
| 250 } | 316 } |
| 251 } else if r.Method == "POST" { | 317 } else if r.Method == "POST" { |
| 252 w.Header().Set("Content-Type", "application/json") | 318 w.Header().Set("Content-Type", "application/json") |
| 253 b, err := ioutil.ReadAll(r.Body) | 319 b, err := ioutil.ReadAll(r.Body) |
| 254 if err != nil { | 320 if err != nil { |
| 255 reportError(w, r, err, "Failed to read a request body.") | 321 reportError(w, r, err, "Failed to read a request body.") |
| 256 return | 322 return |
| 257 } | 323 } |
| 258 code := string(b) | 324 code := string(b) |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 305 if err != nil { | 371 if err != nil { |
| 306 reportError(w, r, err, "Failed to serialize a response." ) | 372 reportError(w, r, err, "Failed to serialize a response." ) |
| 307 return | 373 return |
| 308 } | 374 } |
| 309 w.Write(resp) | 375 w.Write(resp) |
| 310 } | 376 } |
| 311 } | 377 } |
| 312 | 378 |
| 313 func main() { | 379 func main() { |
| 314 flag.Parse() | 380 flag.Parse() |
| 315 | 381 » http.HandleFunc("/i/", imageHandler) |
| 382 » http.HandleFunc("/recent/", recentHandler) | |
| 383 » http.HandleFunc("/css/", cssHandler) | |
| 316 http.HandleFunc("/", mainHandler) | 384 http.HandleFunc("/", mainHandler) |
| 317 log.Fatal(http.ListenAndServe(*port, nil)) | 385 log.Fatal(http.ListenAndServe(*port, nil)) |
| 318 } | 386 } |
| OLD | NEW |