1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
| import ( "fmt" "io" "log" "math/rand" "mime/multipart" "net/http" "os" "os/exec" "path/filepath" "strconv" "strings" "time" ) var blacklistChars = []rune{'<', '>', '"', '\'', '\\', '?', '*', '{', '}', '\t', '\n', '\r'} func main() { // 设置路由 http.HandleFunc("/gojava", compileJava) http.HandleFunc("/testExecYourJarOnServer", testExecYourJarOnServer) // 设置静态文件服务器 fs := http.FileServer(http.Dir(".")) http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // 检查请求的路径是否需要被禁止访问 if isForbiddenPath(r.URL.Path) { http.Error(w, "Forbidden", http.StatusForbidden) return } // 否则,继续处理其他请求 fs.ServeHTTP(w, r) })) // 启动服务器 log.Println("Server started on :80") log.Fatal(http.ListenAndServe(":80", nil)) } func isForbiddenPath(path string) bool { // 检查路径是否为某个特定文件或文件夹的路径 // 这里可以根据你的需求进行设置 forbiddenPaths := []string{ "/main.go", "/upload/", } // 检查请求的路径是否与禁止访问的路径匹配 for _, forbiddenPath := range forbiddenPaths { if strings.HasPrefix(path, forbiddenPath) { return true } } return false } func isFilenameBlacklisted(filename string) bool { for _, char := range filename { for _, blackChar := range blacklistChars { if char == blackChar { return true } } } return false } // compileJava 处理上传并编译Java文件的请求 func compileJava(w http.ResponseWriter, r *http.Request) { // 检查请求方法是否为POST if r.Method != http.MethodPost { http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) return } // 解析multipart/form-data格式的表单数据 err := r.ParseMultipartForm(10 << 20) // 设置最大文件大小为10MB if err != nil { http.Error(w, "Error parsing form", http.StatusInternalServerError) return } // 从表单中获取上传的文件 file, handler, err := r.FormFile("file") if err != nil { http.Error(w, "Error retrieving file", http.StatusBadRequest) return } defer file.Close() if isFilenameBlacklisted(handler.Filename) { http.Error(w, "Invalid filename: contains blacklisted character", http.StatusBadRequest) return } // 检查文件扩展名是否为.java if !strings.HasSuffix(handler.Filename, ".java") { http.Error(w, "Invalid file format, please select a .java file", http.StatusBadRequest) return } // 保存上传的文件至./upload文件夹 err = saveFile(file, "./upload/"+handler.Filename) if err != nil { http.Error(w, "Error saving file", http.StatusInternalServerError) return } // 生成随机文件名 rand.Seed(time.Now().UnixNano()) randomName := strconv.FormatInt(rand.Int63(), 16) + ".jar" // 编译Java文件 cmd := "javac ./upload/" + handler.Filename compileCmd := exec.Command("sh", "-c", cmd) //compileCmd := exec.Command("javac", "./upload/"+handler.Filename) compileOutput, err := compileCmd.CombinedOutput() if err != nil { http.Error(w, "Error compiling Java file: "+string(compileOutput), http.StatusInternalServerError) return } // 将编译后的.class文件打包成.jar文件 fileNameWithoutExtension := strings.TrimSuffix(handler.Filename, filepath.Ext(handler.Filename)) jarCmd := exec.Command("jar", "cvfe", "./final/"+randomName, fileNameWithoutExtension, "-C", "./upload", strings.TrimSuffix(handler.Filename, ".java")+".class") jarOutput, err := jarCmd.CombinedOutput() if err != nil { http.Error(w, "Error creating JAR file: "+string(jarOutput), http.StatusInternalServerError) return } // 返回编译后的.jar文件的下载链接 fmt.Fprintf(w, "/final/%s", randomName) } // saveFile 保存上传的文件 func saveFile(file multipart.File, filePath string) error { // 创建目标文件 f, err := os.Create(filePath) if err != nil { return err } defer f.Close() // 将上传的文件内容复制到目标文件中 _, err = io.Copy(f, file) if err != nil { return err } return nil } func testExecYourJarOnServer(w http.ResponseWriter, r *http.Request) { jarFile := "./final/" + r.URL.Query().Get("jar") // 检查是否存在指定的.jar文件 if !strings.HasSuffix(jarFile, ".jar") { http.Error(w, "Invalid jar file format", http.StatusBadRequest) return } if _, err := os.Stat(jarFile); os.IsNotExist(err) { http.Error(w, "Jar file not found", http.StatusNotFound) return } // 执行.jar文件 cmd := exec.Command("java", "-jar", jarFile) output, err := cmd.CombinedOutput() if err != nil { http.Error(w, "Error running jar file: "+string(output), http.StatusInternalServerError) return } // 输出结果 w.Header().Set("Content-Type", "text/plain") w.Write(output) }
|