kerryzhang 5 years ago
parent
commit
7ec86f4b60
4 changed files with 158 additions and 32 deletions
  1. 16 27
      README.md
  2. 60 3
      jrebelhandler.go
  3. 33 1
      main.go
  4. 49 1
      uuid.go

+ 16 - 27
README.md

@@ -1,28 +1,17 @@
+# Jrebel 激活服务器 By GoLang
+- [参考Java版本:https://gitee.com/gsls200808/JrebelLicenseServerforJava](https://gitee.com/gsls200808/JrebelLicenseServerforJava)
 
-
-
-```json
-{
-    "serverVersion": "3.2.4",
-    "serverProtocolVersion": "1.1",
-    "serverGuid": "a1b4aea8-b031-4302-b602-670a990272cb",
-    "groupType": "managed",
-    "id": 1,
-    "licenseType": 1,
-    "evaluationLicense": false,
-    "signature": "OJE9wGg2xncSb+VgnYT+9HGCFaLOk28tneMFhCbpVMKoC/Iq4LuaDKPirBjG4o394/UjCDGgTBpIrzcXNPdVxVr8PnQzpy7ZSToGO8wv/KIWZT9/ba7bDbA8/RZ4B37YkCeXhjaixpmoyz/CIZMnei4q7oWR7DYUOlOcEWDQhiY=",
-    "serverRandomness": "H2ulzLlh7E0=",
-    "seatPoolType": "standalone",
-    "statusCode": "SUCCESS",
-    "offline": false,
-    "validFrom": null,
-    "validUntil": null,
-    "company": "Administrator",
-    "orderId": "",
-    "zeroIds": [
-        
-    ],
-    "licenseValidFrom": 1490544001000,
-    "licenseValidUntil": 1691839999000
-}
-```
+## Win编译
+```shell
+SET CGO_ENABLED=0
+SET GOOS=linux
+SET GOARCH=amd64
+go build ./
+```
+- GOOS
+    - linux
+    - windows
+    - darwin : 苹果系统
+- GOARCH:
+    - amd64 : 64位
+    - 386:  : 32位

+ 60 - 3
jrebelhandler.go

@@ -19,7 +19,12 @@ func indexHandler(w http.ResponseWriter, r *http.Request) {
 	loggingRequest("indexHandler", r)
 	w.Header().Set("content-type", "text/html; charset=utf-8")
 	w.WriteHeader(200)
-	_, _ = fmt.Fprintf(w, "")
+	html := `<h1>Hello,This is a Jrebel & JetBrains License Server!</h1>
+<p>License Server started at http://localhost:%d
+<p>JetBrains Activation address was: <span style='color:red'>http://localhost:%d/
+<p>JRebel 7.1 and earlier version Activation address was: <span style='color:red'>http://localhost:%d/{tokenname}</span>, with any email."
+<p>JRebel 2018.1 and later version Activation address was: http://localhost:%d/{guid}(eg:<span style='color:red'> http://localhost:%d/%s </span>), with any email.`
+	_, _ = fmt.Fprintf(w, html, serverPort, serverPort, serverPort, serverPort, serverPort, newUUIDV4String())
 }
 
 func jrebelLeasesHandler(w http.ResponseWriter, r *http.Request) {
@@ -131,12 +136,64 @@ func pingHandler(w http.ResponseWriter, r *http.Request) {
 
 func obtainTicketHandler(w http.ResponseWriter, r *http.Request) {
 	w.Header().Add("content-type", "application/json; charset=utf-8")
-	w.WriteHeader(200)
+
+	parameter, err := getHttpBodyParameter(r)
+	if err != nil {
+		responseError(w, err, 403)
+		return
+	}
+	salt := parameter.Get("salt")
+	username := parameter.Get("userName")
+	prolongationPeriod := "607875500"
+	if salt == "" || username == "" {
+		w.WriteHeader(403)
+		_, _ = fmt.Fprintln(w)
+	} else {
+		w.WriteHeader(200)
+		xmlContent := "<ObtainTicketResponse><message></message><prolongationPeriod>" + prolongationPeriod + "</prolongationPeriod><responseCode>OK</responseCode><salt>" + salt + "</salt><ticketId>1</ticketId><ticketProperties>licensee=" + username + "\tlicenseType=0\t</ticketProperties></ObtainTicketResponse>"
+		signature, err := signWithMd5([]byte(xmlContent))
+		if err != nil {
+			w.WriteHeader(403)
+			_, _ = fmt.Fprintf(w, "%s\n", err)
+		} else {
+			body := "<!-- " + hex.EncodeToString(signature) + " -->\n" + xmlContent
+			w.WriteHeader(200)
+			_, _ = fmt.Fprintf(w, "%s\n", body)
+		}
+	}
 
 }
 func releaseTicketHandler(w http.ResponseWriter, r *http.Request) {
-	fmt.Fprintf(w, "Hello there!\n")
+	w.Header().Add("content-type", "text/html; charset=utf-8")
+	parameter, err := getHttpBodyParameter(r)
+	if err != nil {
+		responseError(w, err, 403)
+		return
+	}
+	salt := parameter.Get("salt")
+	if salt == "" {
+		w.WriteHeader(403)
+		_, _ = fmt.Fprintln(w)
+	} else {
+		xmlContent := "<ReleaseTicketResponse><message></message><responseCode>OK</responseCode><salt>" + salt + "</salt></ReleaseTicketResponse>"
+		signature, err := signWithMd5([]byte(xmlContent))
+		if err != nil {
+			w.WriteHeader(403)
+			_, _ = fmt.Fprintf(w, "%s\n", err)
+		} else {
+			body := "<!-- " + hex.EncodeToString(signature) + " -->\n" + xmlContent
+			w.WriteHeader(200)
+			_, _ = fmt.Fprintf(w, "%s\n", body)
+		}
+	}
+
 }
+
+func responseError(w http.ResponseWriter, err error, code int) {
+	w.WriteHeader(403)
+	_, _ = fmt.Fprintf(w, "%s\n", err)
+}
+
 func response(w http.ResponseWriter, resp interface{}) {
 	bodyData, err := json.Marshal(&resp)
 	if err != nil {

+ 33 - 1
main.go

@@ -1,10 +1,40 @@
 package main
 
 import (
+	"fmt"
 	"net/http"
+	"os"
+	"strconv"
+	"strings"
 )
 
+var serverPort = 12345
+
 func main() {
+	if len(os.Args) > 1 {
+		for k, v := range os.Args {
+			if k == 0 {
+				continue
+			}
+			arg := strings.TrimSpace(v)
+			hasPortL := strings.HasPrefix(arg, "--port=")
+			hasPortS := strings.HasPrefix(arg, "-p=")
+			if hasPortL {
+				i, err := strconv.ParseInt(strings.ReplaceAll(arg, "--port=", ""), 10, 32)
+				if err == nil {
+					serverPort = int(i)
+					break
+				}
+			}
+			if hasPortS {
+				i, err := strconv.ParseInt(strings.ReplaceAll(arg, "-p=", ""), 10, 32)
+				if err == nil {
+					serverPort = int(i)
+					break
+				}
+			}
+		}
+	}
 
 	http.HandleFunc("/", indexHandler)
 	http.HandleFunc("/jrebel/leases", jrebelLeasesHandler)
@@ -16,5 +46,7 @@ func main() {
 	http.HandleFunc("/rpc/obtainTicket.action", obtainTicketHandler)
 	http.HandleFunc("/rpc/releaseTicket.action", releaseTicketHandler)
 
-	_ = http.ListenAndServe(":12345", nil)
+	fmt.Printf("start server with port = %d\n", serverPort)
+
+	_ = http.ListenAndServe(":"+strconv.Itoa(serverPort), nil)
 }

+ 49 - 1
uuid.go

@@ -1,5 +1,53 @@
 package main
 
-func getHex(len int64) {
+import (
+	"fmt"
+	"math/rand"
+	"strconv"
+)
+
+// 随机生成UUID 的V4版本
+func newUUIDV4String() (uuid string) {
+	randBytes := newUuidV4()
+	return _uuidToString(randBytes)
+}
+
+func newUuidV4() (randBytes [16]byte) {
+	for k := range randBytes {
+		randBytes[k] = byte(rand.Int() & 0xFF)
+	}
+	randBytes[6] &= 0xFF
+	randBytes[6] |= 0x40
+	randBytes[8] &= 0x3F
+	randBytes[8] |= 0x80
+	return randBytes
+}
+func _uuidToString(data [16]byte) (uuid string) {
+	var msb, lsb int64
+	msb = 0
+	lsb = 0
+	for i := 0; i < 8; i++ {
+		msb = (msb << 8) | int64(data[i]&0xff)
+	}
+	for i := 8; i < 16; i++ {
+		lsb = (lsb << 8) | int64(data[i]&0xff)
+	}
+	uuid = _digits(msb>>32, 8) + "-" +
+		_digits(msb>>16, 4) + "-" +
+		_digits(msb, 4) + "-" +
+		_digits(lsb>>48, 4) + "-" +
+		_digits(lsb, 12)
+	return
+}
+
+func _digits(val int64, digits int) (hex string) {
+	i := uint(digits * 4)
+	var hi uint
+	hi = 1 << i
+	res := int64(hi) | val&int64(hi-1)
+	format := "%0" + strconv.Itoa(digits) + "x"
+	hex = fmt.Sprintf(format, res)
+	hex = hex[1:]
+	return
 
 }