| 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/binary" | 8 "encoding/binary" |
| 9 "encoding/json" | 9 "encoding/json" |
| 10 "flag" | 10 "flag" |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 72 // db is the database, nil if we don't have an SQL database to store dat
a into. | 72 // db is the database, nil if we don't have an SQL database to store dat
a into. |
| 73 db *sql.DB = nil | 73 db *sql.DB = nil |
| 74 | 74 |
| 75 // directLink is the regex that matches URLs paths that are direct links
. | 75 // directLink is the regex that matches URLs paths that are direct links
. |
| 76 directLink = regexp.MustCompile("^/c/([a-f0-9]+)$") | 76 directLink = regexp.MustCompile("^/c/([a-f0-9]+)$") |
| 77 | 77 |
| 78 // iframeLink is the regex that matches URLs paths that are links to ifr
ames. | 78 // iframeLink is the regex that matches URLs paths that are links to ifr
ames. |
| 79 iframeLink = regexp.MustCompile("^/iframe/([a-f0-9]+)$") | 79 iframeLink = regexp.MustCompile("^/iframe/([a-f0-9]+)$") |
| 80 | 80 |
| 81 // imageLink is the regex that matches URLs paths that are direct links
to PNGs. | 81 // imageLink is the regex that matches URLs paths that are direct links
to PNGs. |
| 82 » imageLink = regexp.MustCompile("^/i/([a-z0-9-]+.png)$") | 82 » imageLink = regexp.MustCompile("^/i/([a-z0-9-_]+.png)$") |
| 83 | 83 |
| 84 // tryInfoLink is the regex that matches URLs paths that are direct link
s to data about a single try. | 84 // tryInfoLink is the regex that matches URLs paths that are direct link
s to data about a single try. |
| 85 tryInfoLink = regexp.MustCompile("^/json/([a-f0-9]+)$") | 85 tryInfoLink = regexp.MustCompile("^/json/([a-f0-9]+)$") |
| 86 | 86 |
| 87 // workspaceLink is the regex that matches URLs paths for workspaces. | 87 // workspaceLink is the regex that matches URLs paths for workspaces. |
| 88 workspaceLink = regexp.MustCompile("^/w/([a-z0-9-]+)$") | 88 workspaceLink = regexp.MustCompile("^/w/([a-z0-9-]+)$") |
| 89 | 89 |
| 90 // errorRE is ther regex that matches compiler errors and extracts the l
ine / column information. | 90 // errorRE is ther regex that matches compiler errors and extracts the l
ine / column information. |
| 91 errorRE = regexp.MustCompile("^.*.cpp:(\\d+):(\\d+):\\s*(.*)") | 91 errorRE = regexp.MustCompile("^.*.cpp:(\\d+):(\\d+):\\s*(.*)") |
| 92 | 92 |
| (...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 400 | 400 |
| 401 // expandGyp produces the GYP file needed to build the code | 401 // expandGyp produces the GYP file needed to build the code |
| 402 func expandGyp(hash string) error { | 402 func expandGyp(hash string) error { |
| 403 return writeTemplate(fmt.Sprintf("../../../cache/%s.gyp", hash), gypTemp
late, struct{ Hash string }{hash}) | 403 return writeTemplate(fmt.Sprintf("../../../cache/%s.gyp", hash), gypTemp
late, struct{ Hash string }{hash}) |
| 404 } | 404 } |
| 405 | 405 |
| 406 // response is serialized to JSON as a response to POSTs. | 406 // response is serialized to JSON as a response to POSTs. |
| 407 type response struct { | 407 type response struct { |
| 408 Message string `json:"message"` | 408 Message string `json:"message"` |
| 409 CompileErrors []compileError `json:"compileErrors"` | 409 CompileErrors []compileError `json:"compileErrors"` |
| 410 » Img string `json:"img"` | 410 » RasterImg string `json:"rasterImg"` |
| 411 » GPUImg string `json:"gpuImg"` |
| 411 Hash string `json:"hash"` | 412 Hash string `json:"hash"` |
| 412 } | 413 } |
| 413 | 414 |
| 414 // doCmd executes the given command line string; the command being | 415 // doCmd executes the given command line string; the command being |
| 415 // run is expected to not care what its current working directory is. | 416 // run is expected to not care what its current working directory is. |
| 416 // Returns the stdout and stderr. | 417 // Returns the stdout and stderr. |
| 417 func doCmd(commandLine string) (string, error) { | 418 func doCmd(commandLine string) (string, error) { |
| 418 glog.Infof("Command: %q\n", commandLine) | 419 glog.Infof("Command: %q\n", commandLine) |
| 419 programAndArgs := strings.SplitN(commandLine, " ", 2) | 420 programAndArgs := strings.SplitN(commandLine, " ", 2) |
| 420 program := programAndArgs[0] | 421 program := programAndArgs[0] |
| (...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 717 } | 718 } |
| 718 } | 719 } |
| 719 return false | 720 return false |
| 720 } | 721 } |
| 721 | 722 |
| 722 type TryRequest struct { | 723 type TryRequest struct { |
| 723 Code string `json:"code"` | 724 Code string `json:"code"` |
| 724 Width int `json:"width"` | 725 Width int `json:"width"` |
| 725 Height int `json:"height"` | 726 Height int `json:"height"` |
| 726 GPU bool `json:"gpu"` | 727 GPU bool `json:"gpu"` |
| 728 Raster bool `json:"raster"` |
| 729 PDF bool `json:"pdf"` |
| 727 Name string `json:"name"` // Optional name of the workspace the code
is in. | 730 Name string `json:"name"` // Optional name of the workspace the code
is in. |
| 728 Source int `json:"source"` // ID of the source image, 0 if none. | 731 Source int `json:"source"` // ID of the source image, 0 if none. |
| 729 } | 732 } |
| 730 | 733 |
| 731 // iframeHandler handles the GET and POST of the main page. | 734 // iframeHandler handles the GET and POST of the main page. |
| 732 func iframeHandler(w http.ResponseWriter, r *http.Request) { | 735 func iframeHandler(w http.ResponseWriter, r *http.Request) { |
| 733 glog.Infof("IFrame Handler: %q\n", r.URL.Path) | 736 glog.Infof("IFrame Handler: %q\n", r.URL.Path) |
| 734 if r.Method != "GET" { | 737 if r.Method != "GET" { |
| 735 http.NotFound(w, r) | 738 http.NotFound(w, r) |
| 736 return | 739 return |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 851 if n == MAX_TRY_SIZE { | 854 if n == MAX_TRY_SIZE { |
| 852 err := fmt.Errorf("Code length equal to, or exceeded, %d
", MAX_TRY_SIZE) | 855 err := fmt.Errorf("Code length equal to, or exceeded, %d
", MAX_TRY_SIZE) |
| 853 reportTryError(w, r, err, "Code too large.", "") | 856 reportTryError(w, r, err, "Code too large.", "") |
| 854 return | 857 return |
| 855 } | 858 } |
| 856 request := TryRequest{} | 859 request := TryRequest{} |
| 857 if err := json.Unmarshal(buf.Bytes(), &request); err != nil { | 860 if err := json.Unmarshal(buf.Bytes(), &request); err != nil { |
| 858 reportTryError(w, r, err, "Coulnd't decode JSON.", "") | 861 reportTryError(w, r, err, "Coulnd't decode JSON.", "") |
| 859 return | 862 return |
| 860 } | 863 } |
| 864 if !(request.GPU || request.Raster || request.PDF) { |
| 865 reportTryError(w, r, nil, "No run configuration supplied
...", "") |
| 866 return |
| 867 } |
| 861 if hasPreProcessor(request.Code) { | 868 if hasPreProcessor(request.Code) { |
| 862 err := fmt.Errorf("Found preprocessor macro in code.") | 869 err := fmt.Errorf("Found preprocessor macro in code.") |
| 863 reportTryError(w, r, err, "Preprocessor macros aren't al
lowed.", "") | 870 reportTryError(w, r, err, "Preprocessor macros aren't al
lowed.", "") |
| 864 return | 871 return |
| 865 } | 872 } |
| 866 hash, err := expandCode(LineNumbers(request.Code), request.Sourc
e, request.Width, request.Height) | 873 hash, err := expandCode(LineNumbers(request.Code), request.Sourc
e, request.Width, request.Height) |
| 867 if err != nil { | 874 if err != nil { |
| 868 reportTryError(w, r, err, "Failed to write the code to c
ompile.", hash) | 875 reportTryError(w, r, err, "Failed to write the code to c
ompile.", hash) |
| 869 return | 876 return |
| 870 } | 877 } |
| 871 writeToDatabase(hash, request.Code, request.Name, request.Source
, request.Width, request.Height) | 878 writeToDatabase(hash, request.Code, request.Name, request.Source
, request.Width, request.Height) |
| 872 err = expandGyp(hash) | 879 err = expandGyp(hash) |
| 873 if err != nil { | 880 if err != nil { |
| 874 reportTryError(w, r, err, "Failed to write the gyp file.
", hash) | 881 reportTryError(w, r, err, "Failed to write the gyp file.
", hash) |
| 875 return | 882 return |
| 876 } | 883 } |
| 877 cmd := fmt.Sprintf("scripts/fiddle_wrapper %s --width %d --heigh
t %d", hash, request.Width, request.Height) | 884 cmd := fmt.Sprintf("scripts/fiddle_wrapper %s --width %d --heigh
t %d", hash, request.Width, request.Height) |
| 885 if request.Raster { |
| 886 cmd += " --raster" |
| 887 } |
| 878 if request.GPU { | 888 if request.GPU { |
| 879 cmd += " --gpu" | 889 cmd += " --gpu" |
| 880 } | 890 } |
| 891 if request.PDF { |
| 892 cmd += " --pdf" |
| 893 } |
| 881 if *useChroot { | 894 if *useChroot { |
| 882 cmd = "schroot -c webtry --directory=/ -- /skia_build/sk
ia/experimental/webtry/" + cmd | 895 cmd = "schroot -c webtry --directory=/ -- /skia_build/sk
ia/experimental/webtry/" + cmd |
| 883 } | 896 } |
| 884 if request.Source > 0 { | 897 if request.Source > 0 { |
| 885 cmd += fmt.Sprintf(" --source image-%d.png", request.Sou
rce) | 898 cmd += fmt.Sprintf(" --source image-%d.png", request.Sou
rce) |
| 886 } | 899 } |
| 887 | 900 |
| 888 message, err := doCmd(cmd) | 901 message, err := doCmd(cmd) |
| 889 | 902 |
| 890 outputLines := strings.Split(message, "\n") | 903 outputLines := strings.Split(message, "\n") |
| (...skipping 22 matching lines...) Expand all Loading... |
| 913 | 926 |
| 914 if err != nil { | 927 if err != nil { |
| 915 if len(errorLines) > 0 { | 928 if len(errorLines) > 0 { |
| 916 reportCompileError(w, r, errorLines, hash) | 929 reportCompileError(w, r, errorLines, hash) |
| 917 } else { | 930 } else { |
| 918 reportTryError(w, r, err, "Failed to run the cod
e:\n"+message, hash) | 931 reportTryError(w, r, err, "Failed to run the cod
e:\n"+message, hash) |
| 919 } | 932 } |
| 920 return | 933 return |
| 921 } | 934 } |
| 922 | 935 |
| 923 png, err := ioutil.ReadFile("../../../inout/" + hash + ".png") | |
| 924 if err != nil { | |
| 925 reportTryError(w, r, err, "Failed to open the generated
PNG.", hash) | |
| 926 return | |
| 927 } | |
| 928 | |
| 929 m := response{ | 936 m := response{ |
| 930 Img: base64.StdEncoding.EncodeToString([]byte(png)), | |
| 931 Hash: hash, | 937 Hash: hash, |
| 932 } | 938 } |
| 939 |
| 940 if request.Raster { |
| 941 png, err := ioutil.ReadFile("../../../inout/" + hash + "
_raster.png") |
| 942 if err != nil { |
| 943 reportTryError(w, r, err, "Failed to open the ra
ster-generated PNG.", hash) |
| 944 return |
| 945 } |
| 946 |
| 947 m.RasterImg = base64.StdEncoding.EncodeToString([]byte(p
ng)) |
| 948 } |
| 949 |
| 950 if request.GPU { |
| 951 png, err := ioutil.ReadFile("../../../inout/" + hash + "
_GPU.png") |
| 952 if err != nil { |
| 953 reportTryError(w, r, err, "Failed to open the GP
U-generated PNG.", hash) |
| 954 return |
| 955 } |
| 956 |
| 957 m.GPUImg = base64.StdEncoding.EncodeToString([]byte(png)
) |
| 958 } |
| 959 |
| 933 resp, err := json.Marshal(m) | 960 resp, err := json.Marshal(m) |
| 934 if err != nil { | 961 if err != nil { |
| 935 reportTryError(w, r, err, "Failed to serialize a respons
e.", hash) | 962 reportTryError(w, r, err, "Failed to serialize a respons
e.", hash) |
| 936 return | 963 return |
| 937 } | 964 } |
| 938 w.Header().Set("Content-Type", "application/json") | 965 w.Header().Set("Content-Type", "application/json") |
| 939 w.Write(resp) | 966 w.Write(resp) |
| 940 } | 967 } |
| 941 } | 968 } |
| 942 | 969 |
| 943 func main() { | 970 func main() { |
| 944 flag.Parse() | 971 flag.Parse() |
| 945 Init() | 972 Init() |
| 946 http.HandleFunc("/i/", autogzip.HandleFunc(imageHandler)) | 973 http.HandleFunc("/i/", autogzip.HandleFunc(imageHandler)) |
| 947 http.HandleFunc("/w/", autogzip.HandleFunc(workspaceHandler)) | 974 http.HandleFunc("/w/", autogzip.HandleFunc(workspaceHandler)) |
| 948 http.HandleFunc("/recent/", autogzip.HandleFunc(recentHandler)) | 975 http.HandleFunc("/recent/", autogzip.HandleFunc(recentHandler)) |
| 949 http.HandleFunc("/iframe/", autogzip.HandleFunc(iframeHandler)) | 976 http.HandleFunc("/iframe/", autogzip.HandleFunc(iframeHandler)) |
| 950 http.HandleFunc("/json/", autogzip.HandleFunc(tryInfoHandler)) | 977 http.HandleFunc("/json/", autogzip.HandleFunc(tryInfoHandler)) |
| 951 http.HandleFunc("/sources/", autogzip.HandleFunc(sourcesHandler)) | 978 http.HandleFunc("/sources/", autogzip.HandleFunc(sourcesHandler)) |
| 952 | 979 |
| 953 // Resources are served directly | 980 // Resources are served directly |
| 954 // TODO add support for caching/etags/gzip | 981 // TODO add support for caching/etags/gzip |
| 955 http.Handle("/res/", autogzip.Handle(http.FileServer(http.Dir("./")))) | 982 http.Handle("/res/", autogzip.Handle(http.FileServer(http.Dir("./")))) |
| 956 | 983 |
| 957 // TODO Break out /c/ as it's own handler. | 984 // TODO Break out /c/ as it's own handler. |
| 958 http.HandleFunc("/", autogzip.HandleFunc(mainHandler)) | 985 http.HandleFunc("/", autogzip.HandleFunc(mainHandler)) |
| 959 glog.Fatal(http.ListenAndServe(*port, nil)) | 986 glog.Fatal(http.ListenAndServe(*port, nil)) |
| 960 } | 987 } |
| OLD | NEW |