├── .github └── workflows │ └── go.yml ├── LICENSE ├── README.md ├── config └── site.json ├── doc ├── baidupage.png └── homepage.png ├── ecmascript ├── ast.go ├── hook.go ├── parser.go ├── parsertest.go ├── token.go └── util.go ├── go.mod ├── go.sum ├── javascript └── hook.js ├── main.go ├── template ├── home.html └── robots.txt └── transform ├── css.go ├── html.go ├── html_test.go └── http.go /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a golang project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go 3 | 4 | name: Go 5 | 6 | on: 7 | push: 8 | branches: [ "master" ] 9 | pull_request: 10 | branches: [ "master" ] 11 | 12 | jobs: 13 | 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v3 18 | 19 | - name: Set up Go 20 | uses: actions/setup-go@v4 21 | with: 22 | go-version: '1.20' 23 | 24 | - name: Build 25 | run: go build -v ./main.go 26 | 27 | - name: Test 28 | run: go test -v ./... 29 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 drawing 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # 简介 3 | 4 | VPN(虚拟专用网络)利用加密通信,在公共网络上建立专用网络的技术,外部网络通过加密认证,访问内网数据。SSL VPN 是解决远程用户访问敏感公司数据最简单最安全的解决技术。利用浏览器内置 SSL 协议,无需安装客户端,便可从外网访问内网应用。 5 | 6 | webtravel 实现通过 SSL 协议访问后端服务的代理技术。其原理如下: 7 | 8 | * 客户端浏览器通过访问代理地址 `https://proxy.com/baidu.com` 9 | * 服务器收到 /baidu.com 的请求时,访问 `baidu.com`,把返回的html数据返回给客户端。 10 | * 从baidu.com返回的html数据包含很多图片,css,js信息,如 `http://www.baidu.com/img/bdlogo.gif`,如果把html不加更改的返回客户端,浏览器就会从`baidu.com/img/bdlogo.gif`获取图片,撇开了 proxy.com,所以服务器端必须修改html,把其中的链接改为 `https://proxy.com/baidu.com/img/bdlogo.gif`。 11 | 12 | 其中除了html中的链接,还包括js,css中的链接,以及客户端js拼接的地址。当然,其中还需要修改http头中的cookie、referer等信息。webtravel 实现了重要逻辑的修改,可访问twitter,webqq等复杂应用。 13 | 14 | # 编译运行 15 | 16 | 下载代码和编译 17 | 18 | ``` 19 | git clone git@github.com:drawing/webtravel.git 20 | 21 | cd webtravel 22 | go build 23 | ``` 24 | 25 | 配置修改 `config/site.json` 26 | 27 | ``` 28 | { 29 | "Protocol" : "http", 30 | "Domain" : "webtravel.fancymore.com", 31 | "AccessPath" : "/access/", 32 | "AccessAddress" : "webtravel.fancymore.com:8080", 33 | 34 | "ListenAddress" : "0.0.0.0:8080" 35 | } 36 | ``` 37 | 38 | * `Domain` 当前程序的域名 39 | * `AccessAddress` 当前运行的域名:端口,如监听80端口,可不写端口 40 | * `ListenAddress` 当前运行程序监听的 IP 和端口 41 | 42 | 43 | 执行程序 44 | ``` 45 | ./webtravel -config ./config/site.json 46 | ``` 47 | 48 | # 使用 49 | 50 | 打开首页 51 | 52 | ![首页](./doc/homepage.png) 53 | 54 | 输入期望访问的地址,如 `www.baidu.com`,点 `Go`,跳转到目标页面 55 | 56 | ![baidu](./doc/baidupage.png) 57 | 58 | 此页面虽然为百度首页,但完全通过 `webtravel` 程序中转,并未直接访问百度资源。 59 | -------------------------------------------------------------------------------- /config/site.json: -------------------------------------------------------------------------------- 1 | { 2 | "Protocol" : "http", 3 | "Domain" : "webtravel.fancymore.com", 4 | "AccessPath" : "/access/", 5 | "AccessAddress" : "webtravel.fancymore.com:8080", 6 | 7 | "ListenAddress" : "0.0.0.0:8080" 8 | } 9 | -------------------------------------------------------------------------------- /doc/baidupage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawing/webtravel/7a5e7af815b6c600906519da510ce78e97f2c7f8/doc/baidupage.png -------------------------------------------------------------------------------- /doc/homepage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/drawing/webtravel/7a5e7af815b6c600906519da510ce78e97f2c7f8/doc/homepage.png -------------------------------------------------------------------------------- /ecmascript/ast.go: -------------------------------------------------------------------------------- 1 | package ecmascript 2 | 3 | import ( 4 | // "log" 5 | "bytes" 6 | "io" 7 | // "fmt" 8 | ) 9 | 10 | type Stmt interface { 11 | stmtNode() 12 | generate(w io.Writer) 13 | } 14 | 15 | type ( 16 | ArrayExpression struct { 17 | elements []Stmt 18 | } 19 | AssignmentExpression struct { 20 | operator []byte 21 | left Stmt 22 | right Stmt 23 | } 24 | BinaryExpression struct { 25 | operator []byte 26 | left Stmt 27 | right Stmt 28 | } 29 | BlockStatement struct { 30 | elements []Stmt 31 | } 32 | BreakStatement struct { 33 | label Stmt 34 | } 35 | CallExpression struct { 36 | callee Stmt 37 | arguments []Stmt 38 | } 39 | CatchClause struct { 40 | param Stmt 41 | body Stmt 42 | } 43 | 44 | ConditionalExpression struct { 45 | expr Stmt 46 | consequent Stmt 47 | alternate Stmt 48 | } 49 | 50 | ContinueStatement struct { 51 | label Stmt 52 | } 53 | DebuggerStatement struct { 54 | } 55 | DoWhileStatement struct { 56 | body Stmt 57 | test Stmt 58 | } 59 | EmptyStatement struct { 60 | } 61 | ExpressionStatement struct { 62 | expr Stmt 63 | brackets bool 64 | } 65 | ForStatement struct { 66 | init Stmt 67 | test Stmt 68 | update Stmt 69 | body Stmt 70 | } 71 | ForInStatement struct { 72 | left Stmt 73 | right Stmt 74 | body Stmt 75 | } 76 | FunctionDeclaration struct { 77 | id Stmt 78 | params []Stmt 79 | body Stmt 80 | } 81 | FunctionExpression struct { 82 | header bool 83 | id Stmt 84 | params []Stmt 85 | defaults string 86 | body Stmt 87 | } 88 | Identifier struct { 89 | value []byte 90 | } 91 | IfStatement struct { 92 | test Stmt 93 | consequent Stmt 94 | alternate Stmt 95 | } 96 | LabeledStatement struct { 97 | expr Stmt 98 | body Stmt 99 | } 100 | Literal struct { 101 | value []byte 102 | } 103 | 104 | MemberExpression struct { 105 | computed bool 106 | object Stmt 107 | property Stmt 108 | } 109 | NewExpression struct { 110 | callee Stmt 111 | args []Stmt 112 | } 113 | ObjectExpression struct { 114 | properties []Stmt 115 | } 116 | PostfixExpression struct { 117 | operator []byte 118 | argument Stmt 119 | } 120 | Program struct { 121 | body []Stmt 122 | } 123 | Property struct { 124 | kind string 125 | key Stmt 126 | value Stmt 127 | } 128 | 129 | ReturnStatement struct { 130 | argument Stmt 131 | } 132 | SequenceExpression struct { 133 | expr []Stmt 134 | } 135 | SwitchCase struct { 136 | test Stmt 137 | consequent []Stmt 138 | } 139 | SwitchStatement struct { 140 | discriminant Stmt 141 | cases []Stmt 142 | } 143 | 144 | ThisExpression struct { 145 | } 146 | ThrowStatement struct { 147 | argument Stmt 148 | } 149 | TryStatement struct { 150 | block Stmt 151 | handers []Stmt 152 | finalizer Stmt 153 | } 154 | UnaryExpression struct { 155 | operator []byte 156 | argument Stmt 157 | prefix bool 158 | } 159 | 160 | VariableDeclaration struct { 161 | kind []byte 162 | declarations []Stmt 163 | semicolon bool 164 | } 165 | VariableDeclarator struct { 166 | id Stmt 167 | init Stmt 168 | } 169 | 170 | WhileStatement struct { 171 | test Stmt 172 | body Stmt 173 | } 174 | WithStatement struct { 175 | object Stmt 176 | body Stmt 177 | } 178 | ) 179 | 180 | type GroupStatement struct { 181 | expr Stmt 182 | } 183 | 184 | func (s *ArrayExpression) stmtNode() {} 185 | func (s *AssignmentExpression) stmtNode() {} 186 | func (s *BinaryExpression) stmtNode() {} 187 | func (s *BlockStatement) stmtNode() {} 188 | func (s *BreakStatement) stmtNode() {} 189 | func (s *CallExpression) stmtNode() {} 190 | func (s *CatchClause) stmtNode() {} 191 | func (s *ConditionalExpression) stmtNode() {} 192 | func (s *ContinueStatement) stmtNode() {} 193 | func (s *DebuggerStatement) stmtNode() {} 194 | func (s *DoWhileStatement) stmtNode() {} 195 | func (s *EmptyStatement) stmtNode() {} 196 | func (s *ExpressionStatement) stmtNode() {} 197 | func (s *ForStatement) stmtNode() {} 198 | func (s *ForInStatement) stmtNode() {} 199 | func (s *FunctionDeclaration) stmtNode() {} 200 | func (s *FunctionExpression) stmtNode() {} 201 | func (s *Identifier) stmtNode() {} 202 | func (s *IfStatement) stmtNode() {} 203 | func (s *LabeledStatement) stmtNode() {} 204 | func (s *Literal) stmtNode() {} 205 | func (s *MemberExpression) stmtNode() {} 206 | func (s *NewExpression) stmtNode() {} 207 | func (s *ObjectExpression) stmtNode() {} 208 | func (s *PostfixExpression) stmtNode() {} 209 | func (s *Program) stmtNode() {} 210 | func (s *Property) stmtNode() {} 211 | func (s *ReturnStatement) stmtNode() {} 212 | func (s *SequenceExpression) stmtNode() {} 213 | func (s *SwitchCase) stmtNode() {} 214 | func (s *SwitchStatement) stmtNode() {} 215 | func (s *ThisExpression) stmtNode() {} 216 | func (s *ThrowStatement) stmtNode() {} 217 | func (s *TryStatement) stmtNode() {} 218 | func (s *UnaryExpression) stmtNode() {} 219 | func (s *VariableDeclaration) stmtNode() {} 220 | func (s *VariableDeclarator) stmtNode() {} 221 | func (s *WhileStatement) stmtNode() {} 222 | func (s *WithStatement) stmtNode() {} 223 | 224 | func (s *GroupStatement) stmtNode() {} 225 | 226 | func (s *ArrayExpression) generate(w io.Writer) { 227 | w.Write([]byte("[")) 228 | for k, v := range s.elements { 229 | if k != 0 { 230 | w.Write([]byte(",")) 231 | } 232 | if v != nil { 233 | v.generate(w) 234 | } 235 | } 236 | w.Write([]byte("]")) 237 | } 238 | 239 | func (s *AssignmentExpression) generate(w io.Writer) { 240 | // fmt.Println("AssignmentExpression", string(s.operator)) 241 | if bytes.Compare(s.operator, []byte("=")) != 0 { 242 | s.left.generate(w) 243 | w.Write(s.operator) 244 | s.right.generate(w) 245 | } else { 246 | b := new(bytes.Buffer) 247 | s.left.generate(b) 248 | 249 | hook_func := assignmentHook(b.Bytes()) 250 | 251 | w.Write(b.Bytes()) 252 | w.Write(s.operator) 253 | 254 | if hook_func != nil { 255 | w.Write(hook_func) 256 | w.Write([]byte("(")) 257 | } 258 | s.right.generate(w) 259 | if hook_func != nil { 260 | w.Write([]byte(")")) 261 | } 262 | } 263 | } 264 | func (s *BinaryExpression) generate(w io.Writer) { 265 | s.left.generate(w) 266 | w.Write([]byte(" ")) 267 | w.Write(s.operator) 268 | w.Write([]byte(" ")) 269 | s.right.generate(w) 270 | } 271 | func (s *BlockStatement) generate(w io.Writer) { 272 | w.Write([]byte("{")) 273 | for _, v := range s.elements { 274 | v.generate(w) 275 | } 276 | w.Write([]byte("}")) 277 | } 278 | func (s *BreakStatement) generate(w io.Writer) { 279 | w.Write([]byte("break ")) 280 | if s.label != nil { 281 | s.label.generate(w) 282 | } 283 | w.Write([]byte(";")) 284 | } 285 | func (s *CallExpression) generate(w io.Writer) { 286 | b := new(bytes.Buffer) 287 | s.callee.generate(b) 288 | bs := b.Bytes() 289 | 290 | replaceFunc, replaceNum, argumentType := calleeHook(bs, len(s.arguments)) 291 | w.Write(bs) 292 | w.Write([]byte("(")) 293 | for k, v := range s.arguments { 294 | if k != 0 { 295 | w.Write([]byte(",")) 296 | } 297 | if replaceFunc != nil && replaceNum == k { 298 | w.Write([]byte(replaceFunc)) 299 | w.Write([]byte("(")) 300 | if argumentType == 0 { 301 | v.generate(w) 302 | } else if argumentType == 1 { 303 | for k1, v1 := range s.arguments { 304 | if k1 != 0 { 305 | w.Write([]byte(",")) 306 | } 307 | v1.generate(w) 308 | } 309 | } 310 | w.Write([]byte(")")) 311 | } else { 312 | v.generate(w) 313 | } 314 | } 315 | w.Write([]byte(")")) 316 | } 317 | func (s *CatchClause) generate(w io.Writer) { 318 | w.Write([]byte("catch(")) 319 | s.param.generate(w) 320 | w.Write([]byte(")")) 321 | s.body.generate(w) 322 | } 323 | func (s *ConditionalExpression) generate(w io.Writer) { 324 | // w.Write([]byte("(")) 325 | s.expr.generate(w) 326 | w.Write([]byte("?")) 327 | s.consequent.generate(w) 328 | w.Write([]byte(":")) 329 | s.alternate.generate(w) 330 | // w.Write([]byte(")")) 331 | } 332 | func (s *ContinueStatement) generate(w io.Writer) { 333 | w.Write([]byte("continue ")) 334 | if s.label != nil { 335 | s.label.generate(w) 336 | } 337 | w.Write([]byte(";")) 338 | } 339 | func (s *DebuggerStatement) generate(w io.Writer) { 340 | w.Write([]byte("debugger;")) 341 | } 342 | func (s *DoWhileStatement) generate(w io.Writer) { 343 | w.Write([]byte("do ")) 344 | s.body.generate(w) 345 | w.Write([]byte(" while(")) 346 | s.test.generate(w) 347 | w.Write([]byte(")")) 348 | } 349 | func (s *EmptyStatement) generate(w io.Writer) { 350 | w.Write([]byte(";")) 351 | } 352 | func (s *ExpressionStatement) generate(w io.Writer) { 353 | if s.brackets { 354 | w.Write([]byte("(")) 355 | } 356 | s.expr.generate(w) 357 | if s.brackets { 358 | w.Write([]byte(")")) 359 | } 360 | w.Write([]byte(";")) 361 | } 362 | func (s *ForStatement) generate(w io.Writer) { 363 | w.Write([]byte("for(")) 364 | if s.init != nil { 365 | s.init.generate(w) 366 | } 367 | w.Write([]byte(";")) 368 | if s.test != nil { 369 | s.test.generate(w) 370 | } 371 | w.Write([]byte(";")) 372 | if s.update != nil { 373 | s.update.generate(w) 374 | } 375 | w.Write([]byte(")")) 376 | s.body.generate(w) 377 | } 378 | func (s *ForInStatement) generate(w io.Writer) { 379 | w.Write([]byte("for(")) 380 | s.left.generate(w) 381 | w.Write([]byte(" in ")) 382 | s.right.generate(w) 383 | w.Write([]byte(")")) 384 | s.body.generate(w) 385 | } 386 | func (s *FunctionDeclaration) generate(w io.Writer) { 387 | w.Write([]byte("function ")) 388 | if s.id != nil { 389 | s.id.generate(w) 390 | } 391 | 392 | w.Write([]byte("(")) 393 | for k, v := range s.params { 394 | if k != 0 { 395 | w.Write([]byte(",")) 396 | } 397 | v.generate(w) 398 | } 399 | w.Write([]byte(")")) 400 | 401 | s.body.generate(w) 402 | } 403 | func (s *FunctionExpression) generate(w io.Writer) { 404 | if s.header { 405 | w.Write([]byte("function ")) 406 | } 407 | 408 | if s.id != nil { 409 | s.id.generate(w) 410 | } 411 | w.Write([]byte("(")) 412 | for k, v := range s.params { 413 | if k != 0 { 414 | w.Write([]byte(",")) 415 | } 416 | v.generate(w) 417 | } 418 | w.Write([]byte(")")) 419 | s.body.generate(w) 420 | } 421 | func (s *Identifier) generate(w io.Writer) { 422 | w.Write(s.value) 423 | } 424 | func (s *IfStatement) generate(w io.Writer) { 425 | w.Write([]byte("if (")) 426 | s.test.generate(w) 427 | w.Write([]byte(")")) 428 | s.consequent.generate(w) 429 | if s.alternate != nil { 430 | w.Write([]byte("else ")) 431 | s.alternate.generate(w) 432 | } 433 | } 434 | func (s *LabeledStatement) generate(w io.Writer) { 435 | s.expr.generate(w) 436 | w.Write([]byte(":")) 437 | if s.body != nil { 438 | s.body.generate(w) 439 | } 440 | } 441 | func (s *Literal) generate(w io.Writer) { 442 | w.Write(s.value) 443 | } 444 | func (s *MemberExpression) generate(w io.Writer) { 445 | b := new(bytes.Buffer) 446 | s.object.generate(b) 447 | if s.computed { 448 | b.Write([]byte("[")) 449 | s.property.generate(b) 450 | b.Write([]byte("]")) 451 | } else { 452 | b.Write([]byte(".")) 453 | s.property.generate(b) 454 | } 455 | 456 | convert_func, present := memberConfigList[b.String()] 457 | if present { 458 | w.Write(convert_func) 459 | w.Write([]byte("(")) 460 | w.Write(b.Bytes()) 461 | w.Write([]byte(")")) 462 | } else { 463 | w.Write(b.Bytes()) 464 | } 465 | } 466 | func (s *NewExpression) generate(w io.Writer) { 467 | w.Write([]byte("new ")) 468 | s.callee.generate(w) 469 | w.Write([]byte("(")) 470 | if s.args != nil { 471 | for k, v := range s.args { 472 | if k != 0 { 473 | w.Write([]byte(",")) 474 | } 475 | v.generate(w) 476 | } 477 | } 478 | w.Write([]byte(")")) 479 | } 480 | func (s *ObjectExpression) generate(w io.Writer) { 481 | w.Write([]byte("{")) 482 | for k, v := range s.properties { 483 | if k != 0 { 484 | w.Write([]byte(",")) 485 | } 486 | v.generate(w) 487 | } 488 | w.Write([]byte("}")) 489 | } 490 | func (s *PostfixExpression) generate(w io.Writer) { 491 | s.argument.generate(w) 492 | w.Write(s.operator) 493 | } 494 | func (s *Program) generate(w io.Writer) { 495 | for _, v := range s.body { 496 | v.generate(w) 497 | } 498 | } 499 | func (s *Property) generate(w io.Writer) { 500 | if s.kind != "init" { 501 | w.Write([]byte(s.kind)) 502 | w.Write([]byte(" ")) 503 | s.key.generate(w) 504 | s.value.generate(w) 505 | } else { 506 | s.key.generate(w) 507 | w.Write([]byte(":")) 508 | s.value.generate(w) 509 | } 510 | } 511 | func (s *ReturnStatement) generate(w io.Writer) { 512 | w.Write([]byte("return ")) 513 | if s.argument != nil { 514 | s.argument.generate(w) 515 | } 516 | w.Write([]byte(";")) 517 | } 518 | func (s *SequenceExpression) generate(w io.Writer) { 519 | for k, v := range s.expr { 520 | if k != 0 { 521 | w.Write([]byte(",")) 522 | } 523 | v.generate(w) 524 | } 525 | } 526 | func (s *SwitchCase) generate(w io.Writer) { 527 | if s.test == nil { 528 | w.Write([]byte("default:")) 529 | } else { 530 | w.Write([]byte("case ")) 531 | s.test.generate(w) 532 | w.Write([]byte(":")) 533 | } 534 | for _, v := range s.consequent { 535 | v.generate(w) 536 | } 537 | 538 | } 539 | func (s *SwitchStatement) generate(w io.Writer) { 540 | w.Write([]byte("switch(")) 541 | s.discriminant.generate(w) 542 | w.Write([]byte("){")) 543 | if s.cases != nil { 544 | for _, v := range s.cases { 545 | v.generate(w) 546 | } 547 | } 548 | w.Write([]byte("}")) 549 | } 550 | func (s *ThisExpression) generate(w io.Writer) { 551 | w.Write([]byte("this")) 552 | } 553 | func (s *ThrowStatement) generate(w io.Writer) { 554 | w.Write([]byte("throw ")) 555 | s.argument.generate(w) 556 | w.Write([]byte(";")) 557 | } 558 | func (s *TryStatement) generate(w io.Writer) { 559 | w.Write([]byte("try")) 560 | s.block.generate(w) 561 | if s.handers != nil { 562 | for _, v := range s.handers { 563 | v.generate(w) 564 | } 565 | } 566 | if s.finalizer != nil { 567 | w.Write([]byte("finally")) 568 | s.finalizer.generate(w) 569 | } 570 | } 571 | func (s *UnaryExpression) generate(w io.Writer) { 572 | w.Write(s.operator) 573 | w.Write([]byte(" ")) 574 | s.argument.generate(w) 575 | } 576 | func (s *VariableDeclaration) generate(w io.Writer) { 577 | w.Write(s.kind) 578 | w.Write([]byte(" ")) 579 | 580 | for k, v := range s.declarations { 581 | if k != 0 { 582 | w.Write([]byte(",")) 583 | } 584 | v.generate(w) 585 | } 586 | if s.semicolon { 587 | w.Write([]byte(";")) 588 | } 589 | } 590 | func (s *VariableDeclarator) generate(w io.Writer) { 591 | s.id.generate(w) 592 | if s.init != nil { 593 | w.Write([]byte("=")) 594 | s.init.generate(w) 595 | } 596 | } 597 | func (s *WhileStatement) generate(w io.Writer) { 598 | w.Write([]byte("while(")) 599 | s.test.generate(w) 600 | w.Write([]byte(")")) 601 | s.body.generate(w) 602 | } 603 | func (s *WithStatement) generate(w io.Writer) { 604 | w.Write([]byte("with(")) 605 | s.object.generate(w) 606 | w.Write([]byte(")")) 607 | s.body.generate(w) 608 | } 609 | 610 | func (s *GroupStatement) generate(w io.Writer) { 611 | w.Write([]byte("(")) 612 | s.expr.generate(w) 613 | w.Write([]byte(")")) 614 | } 615 | -------------------------------------------------------------------------------- /ecmascript/hook.go: -------------------------------------------------------------------------------- 1 | package ecmascript 2 | 3 | import ( 4 | "bytes" 5 | ) 6 | 7 | type calleeConfig struct { 8 | // 0:match 1:suffix 9 | matchType int 10 | matchText []byte 11 | argumentNum int 12 | replaceNum int 13 | replaceFunc []byte 14 | argumentType int 15 | } 16 | 17 | var calleConfigList = []*calleeConfig{ 18 | // facebook.org 19 | &calleeConfig{0, []byte("window.location.replace"), 1, 0, []byte("skip_access_convert_url_0001"), 0}, 20 | &calleeConfig{0, []byte("location.replace"), 1, 0, []byte("skip_access_convert_url_0001"), 0}, 21 | // play.golang.org 22 | &calleeConfig{1, []byte(".pushState"), 3, 2, []byte("skip_access_convert_path_0001"), 0}, 23 | &calleeConfig{1, []byte(".setAttribute"), 2, 1, []byte("skip_access_setAttribute_0001"), 1}, 24 | &calleeConfig{1, []byte(".test"), 1, 0, []byte("skip_access_regex_test_0001"), 0}, 25 | } 26 | 27 | func calleeHook(text []byte, num int) ([]byte, int, int) { 28 | match := false 29 | for _, v := range calleConfigList { 30 | if num != v.argumentNum { 31 | continue 32 | } 33 | if v.matchType == 0 { 34 | if bytes.Equal(text, v.matchText) { 35 | match = true 36 | } 37 | } else if v.matchType == 1 { 38 | if bytes.HasSuffix(text, v.matchText) { 39 | match = true 40 | } 41 | } 42 | if !match { 43 | continue 44 | } 45 | return v.replaceFunc, v.replaceNum, v.argumentType 46 | } 47 | 48 | return nil, 0, 0 49 | } 50 | 51 | var memberConfigList = map[string][]byte{ 52 | "window.location.host": []byte("skip_access_convert_host_0001"), 53 | "window.location.protocol": []byte("skip_access_convert_protocol_0001"), 54 | } 55 | 56 | type assignmentConfig struct { 57 | // 0:match 1:suffix 58 | matchType int 59 | matchText []byte 60 | replaceFunc []byte 61 | } 62 | 63 | var assignmentConfigList = []*assignmentConfig{ 64 | &assignmentConfig{1, []byte(".href"), []byte("skip_access_convert_url_0001")}, 65 | &assignmentConfig{1, []byte(".src"), []byte("skip_access_convert_url_0001")}, 66 | &assignmentConfig{1, []byte(".domain"), []byte("skip_access_convert_domain_0001")}, 67 | &assignmentConfig{1, []byte(".innerHTML"), []byte("skip_access_convert_html_0001")}, 68 | &assignmentConfig{1, []byte(".cookie"), []byte("skip_access_convert_cookie_0001")}, 69 | &assignmentConfig{1, []byte(".outerHTML"), []byte("skip_access_convert_html_0001")}, 70 | } 71 | 72 | func assignmentHook(left []byte) []byte { 73 | var hook []byte = nil 74 | for _, v := range assignmentConfigList { 75 | if v.matchType == 0 { 76 | if bytes.Equal(left, v.matchText) { 77 | hook = v.replaceFunc 78 | } 79 | } else if v.matchType == 1 { 80 | if bytes.HasSuffix(left, v.matchText) { 81 | hook = v.replaceFunc 82 | } 83 | } 84 | if hook != nil { 85 | return hook 86 | } 87 | } 88 | 89 | return nil 90 | } 91 | -------------------------------------------------------------------------------- /ecmascript/parser.go: -------------------------------------------------------------------------------- 1 | package ecmascript 2 | 3 | import ( 4 | "bytes" 5 | "errors" 6 | // "fmt" 7 | ) 8 | 9 | type parser struct { 10 | source []byte 11 | index int 12 | lineNumber int 13 | 14 | strict bool 15 | lookahead Token 16 | lookahead_end_pos int 17 | 18 | state_allowIn bool 19 | state_inFunctionBody bool 20 | state_inSwitch bool 21 | state_inIteration bool 22 | } 23 | 24 | func (p *parser) skipComment() error { 25 | blockComment := false 26 | lineComment := false 27 | 28 | for p.index < len(p.source) { 29 | ch := p.source[p.index] 30 | 31 | if lineComment { 32 | p.index++ 33 | if isLineTerminator(ch) { 34 | lineComment = false 35 | if ch == 13 && p.source[p.index] == 10 { 36 | p.index++ 37 | } 38 | p.lineNumber++ 39 | } 40 | } else if blockComment { 41 | if isLineTerminator(ch) { 42 | if ch == 13 && p.source[p.index+1] == 10 { 43 | p.index++ 44 | } 45 | p.index++ 46 | p.lineNumber++ 47 | if p.index >= len(p.source) { 48 | return errors.New("UnexpectedToken") 49 | } 50 | } else { 51 | ch = p.source[p.index] 52 | p.index++ 53 | if p.index >= len(p.source) { 54 | return errors.New("UnexpectedToken") 55 | } 56 | 57 | if ch == 42 { 58 | ch = p.source[p.index] 59 | if ch == 47 { 60 | p.index++ 61 | blockComment = false 62 | } 63 | } 64 | } 65 | } else if ch == 47 { 66 | ch = p.source[p.index+1] 67 | if ch == 47 { 68 | p.index += 2 69 | lineComment = true 70 | } else if ch == 42 { 71 | p.index += 2 72 | blockComment = true 73 | if p.index >= len(p.source) { 74 | return errors.New("UnexpectedToken") 75 | } 76 | } else { 77 | break 78 | } 79 | } else if isWhiteSpace(ch) { 80 | p.index++ 81 | } else if isLineTerminator(ch) { 82 | p.index++ 83 | if ch == 13 && p.source[p.index] == 10 { 84 | p.index++ 85 | } 86 | p.lineNumber++ 87 | } else { 88 | break 89 | } 90 | } 91 | 92 | return nil 93 | } 94 | 95 | func (p *parser) getIdentifier() ([]byte, error) { 96 | start := p.index 97 | p.index++ 98 | for p.index < len(p.source) { 99 | ch := p.source[p.index] 100 | if ch == 92 { 101 | return p.source[start:p.index], errors.New("EscapeIdentifier Unsupported") 102 | } 103 | if isIdentifierPart(ch) { 104 | p.index++ 105 | } else { 106 | break 107 | } 108 | } 109 | return p.source[start:p.index], nil 110 | } 111 | 112 | func (p *parser) scanIdentifier() (Token, error) { 113 | start := p.index 114 | id, err := p.getIdentifier() 115 | 116 | if err != nil { 117 | return NULLToken, err 118 | } 119 | 120 | sid := string(id) 121 | if len(id) == 1 { 122 | return Token{IdentifierToken, p.source[start:p.index]}, nil 123 | } else if isKeyword(id, p.strict) { 124 | return Token{KeywordToken, p.source[start:p.index]}, nil 125 | } else if sid == "null" { 126 | return Token{NullLiteralToken, p.source[start:p.index]}, nil 127 | } else if sid == "true" || sid == "false" { 128 | return Token{BooleanLiteralToken, p.source[start:p.index]}, nil 129 | } else { 130 | return Token{IdentifierToken, p.source[start:p.index]}, nil 131 | } 132 | return NULLToken, nil 133 | } 134 | 135 | func (p *parser) scanPunctuator() (Token, error) { 136 | start := p.index 137 | code := p.source[start] 138 | switch code { 139 | case 46, 40, 41, 59, 44, 123, 125, 91, 93, 58, 63, 126: 140 | p.index++ 141 | return Token{PunctuatorToken, p.source[start:p.index]}, nil 142 | default: 143 | code2 := p.source[start+1] 144 | if code2 == 61 { 145 | switch code { 146 | case 37, 38, 42, 43, 45, 47, 60, 62, 94, 124: 147 | p.index += 2 148 | return Token{PunctuatorToken, p.source[start:p.index]}, nil 149 | case 33, 61: 150 | p.index += 2 151 | if p.source[p.index] == 61 { 152 | p.index++ 153 | return Token{PunctuatorToken, p.source[start:p.index]}, nil 154 | } 155 | return Token{PunctuatorToken, p.source[start:p.index]}, nil 156 | } 157 | } 158 | } 159 | 160 | ch1 := p.source[p.index] 161 | ch2 := p.source[p.index+1] 162 | ch3 := p.source[p.index+2] 163 | ch4 := p.source[p.index+3] 164 | 165 | if ch1 == '>' && ch2 == '>' && ch3 == '>' { 166 | if ch4 == '=' { 167 | p.index += 4 168 | } else { 169 | p.index += 3 170 | } 171 | return Token{PunctuatorToken, p.source[start:p.index]}, nil 172 | } 173 | 174 | if ch1 == '<' && ch2 == '<' && ch3 == '=' { 175 | p.index += 3 176 | return Token{PunctuatorToken, p.source[start:p.index]}, nil 177 | } 178 | if ch1 == '>' && ch2 == '>' && ch3 == '=' { 179 | p.index += 3 180 | return Token{PunctuatorToken, p.source[start:p.index]}, nil 181 | } 182 | 183 | if ch1 == ch2 && bytes.Contains([]byte("+-<>&|"), []byte{ch1}) { 184 | p.index += 2 185 | return Token{PunctuatorToken, p.source[start:p.index]}, nil 186 | } 187 | if bytes.Contains([]byte("<>=!+-*%&|^/"), []byte{ch1}) { 188 | p.index++ 189 | return Token{PunctuatorToken, p.source[start:p.index]}, nil 190 | } 191 | return NULLToken, errors.New("UnexpectedToken") 192 | } 193 | 194 | func (p *parser) scanNumericLiteral() (Token, error) { 195 | ch := p.source[p.index] 196 | start := p.index 197 | if ch != '.' { 198 | p.index++ 199 | 200 | if ch == '0' { 201 | ch = p.source[p.index] 202 | if ch == 'x' || ch == 'X' { 203 | p.index++ 204 | for p.index < len(p.source) { 205 | if !isHexDigit(p.source[p.index]) { 206 | break 207 | } 208 | p.index++ 209 | } 210 | return Token{NumericLiteralToken, p.source[start:p.index]}, nil 211 | } 212 | if isOctalDigit(ch) { 213 | p.index++ 214 | for p.index < len(p.source) { 215 | if !isOctalDigit(p.source[p.index]) { 216 | break 217 | } 218 | p.index++ 219 | } 220 | return Token{NumericLiteralToken, p.source[start:p.index]}, nil 221 | } 222 | } 223 | 224 | for isDecimalDigit(p.source[p.index]) { 225 | p.index++ 226 | } 227 | ch = p.source[p.index] 228 | } 229 | 230 | if ch == '.' { 231 | p.index++ 232 | for isDecimalDigit(p.source[p.index]) { 233 | p.index++ 234 | } 235 | ch = p.source[p.index] 236 | } 237 | 238 | if ch == 'e' || ch == 'E' { 239 | p.index++ 240 | ch = p.source[p.index] 241 | if ch == '+' || ch == '-' { 242 | p.index++ 243 | } 244 | for isDecimalDigit(p.source[p.index]) { 245 | p.index++ 246 | } 247 | } 248 | 249 | return Token{NumericLiteralToken, p.source[start:p.index]}, nil 250 | } 251 | 252 | func (p *parser) scanStringLiteral() (Token, error) { 253 | quote := p.source[p.index] 254 | if quote != '\'' && quote != '"' { 255 | return NULLToken, errors.New("StringLiteral error") 256 | } 257 | 258 | start := p.index 259 | p.index++ 260 | escape := false 261 | 262 | for p.index < len(p.source) { 263 | ch := p.source[p.index] 264 | p.index++ 265 | 266 | if escape { 267 | escape = false 268 | continue 269 | } 270 | if ch == quote { 271 | break 272 | } 273 | 274 | if ch == '\\' { 275 | escape = true 276 | } 277 | } 278 | 279 | return Token{StringLiteralToken, p.source[start:p.index]}, nil 280 | } 281 | 282 | func (p *parser) scanRegExp() ([]byte, error) { 283 | p.skipComment() 284 | start := p.index 285 | ch := p.source[p.index] 286 | if ch != '/' { 287 | return p.source[start:p.index], errors.New("RegExp Start Error") 288 | } 289 | 290 | p.index++ 291 | 292 | classMarker := false 293 | terminated := false 294 | for p.index < len(p.source) { 295 | ch = p.source[p.index] 296 | p.index++ 297 | if classMarker { 298 | if ch == ']' { 299 | classMarker = false 300 | } 301 | } else { 302 | if ch == '\\' { 303 | ch = p.source[p.index] 304 | p.index++ 305 | if isLineTerminator(ch) { 306 | return p.source[start:p.index], errors.New("UnterminatedRegExp") 307 | } 308 | } else if ch == '/' { 309 | terminated = true 310 | break 311 | } else if ch == '[' { 312 | classMarker = true 313 | } else if isLineTerminator(ch) { 314 | return p.source[start:p.index], errors.New("UnterminatedRegExp") 315 | } 316 | } 317 | } 318 | if !terminated { 319 | return p.source[start:p.index], errors.New("UnterminatedRegExp") 320 | } 321 | 322 | for p.index < len(p.source) { 323 | ch = p.source[p.index] 324 | if !isIdentifierPart(ch) { 325 | break 326 | } 327 | p.index++ 328 | } 329 | p.peek() 330 | return p.source[start:p.index], nil 331 | } 332 | 333 | func isIdentifierName(token Token) bool { 334 | switch token.token_type { 335 | case IdentifierToken, KeywordToken, BooleanLiteralToken, NullLiteralToken: 336 | return true 337 | } 338 | return false 339 | } 340 | 341 | func (p *parser) advance() (Token, error) { 342 | p.skipComment() 343 | 344 | if p.index >= len(p.source) { 345 | return NULLToken, nil 346 | } 347 | 348 | ch := p.source[p.index] 349 | // fmt.Println("aab:", ch) 350 | 351 | if ch == 40 || ch == 41 || ch == 58 { 352 | return p.scanPunctuator() 353 | } 354 | 355 | if ch == 39 || ch == 34 { 356 | return p.scanStringLiteral() 357 | } 358 | 359 | if isIdentifierStart(ch) { 360 | return p.scanIdentifier() 361 | } 362 | 363 | if ch == 46 { 364 | if isDecimalDigit(p.source[p.index+1]) { 365 | return p.scanNumericLiteral() 366 | } 367 | return p.scanPunctuator() 368 | } 369 | 370 | if isDecimalDigit(ch) { 371 | return p.scanNumericLiteral() 372 | } 373 | return p.scanPunctuator() 374 | } 375 | 376 | func (p *parser) lex() (Token, error) { 377 | var err error 378 | token := p.lookahead 379 | token_end_pos := p.lookahead_end_pos 380 | 381 | p.index = p.lookahead_end_pos 382 | p.lookahead, err = p.advance() 383 | if err != nil { 384 | return NULLToken, err 385 | } 386 | 387 | p.lookahead_end_pos = p.index 388 | p.index = token_end_pos 389 | 390 | return token, nil 391 | } 392 | 393 | func (p *parser) peek() error { 394 | var err error 395 | index := p.index 396 | lineNumber := p.lineNumber 397 | p.lookahead, err = p.advance() 398 | if err != nil { 399 | return err 400 | } 401 | 402 | p.lookahead_end_pos = p.index 403 | p.index = index 404 | p.lineNumber = lineNumber 405 | return nil 406 | } 407 | 408 | func (p *parser) peekLineTerminator() bool { 409 | found := false 410 | index := p.index 411 | lineNumber := p.lineNumber 412 | p.skipComment() 413 | if lineNumber != p.lineNumber { 414 | found = true 415 | } 416 | p.index = index 417 | p.lineNumber = lineNumber 418 | 419 | return found 420 | } 421 | 422 | func (p *parser) expect(value string) error { 423 | token, err := p.lex() 424 | 425 | if err != nil { 426 | return err 427 | } 428 | if token.token_type != PunctuatorToken || 429 | value != string(token.token_value) { 430 | return errors.New("expect error") 431 | } 432 | return nil 433 | } 434 | 435 | func (p *parser) expectKeyword(value string) error { 436 | token, err := p.lex() 437 | if err != nil { 438 | return err 439 | } 440 | if token.token_type != KeywordToken || value != string(token.token_value) { 441 | return errors.New("expectKeyword error") 442 | } 443 | return nil 444 | } 445 | 446 | func (p *parser) match(value string) bool { 447 | if p.lookahead.token_type == PunctuatorToken && 448 | value == string(p.lookahead.token_value) { 449 | return true 450 | } 451 | return false 452 | } 453 | 454 | func (p *parser) matchKeyword(value string) bool { 455 | if p.lookahead.token_type == KeywordToken && 456 | value == string(p.lookahead.token_value) { 457 | return true 458 | } 459 | return false 460 | } 461 | 462 | func (p *parser) matchAssign() bool { 463 | if p.lookahead.token_type != PunctuatorToken { 464 | return false 465 | } 466 | switch string(p.lookahead.token_value) { 467 | case "=", "*=", "/=", "%=", "+=", "-=", "<<=", ">>=", ">>>=", "&=", "^=", "|=": 468 | return true 469 | } 470 | return false 471 | } 472 | 473 | func (p *parser) consumeSemicolon() error { 474 | if p.source[p.index] == 59 { 475 | p.lex() 476 | return nil 477 | } 478 | 479 | lineNumber := p.lineNumber 480 | err := p.skipComment() 481 | if err != nil { 482 | return err 483 | } 484 | if lineNumber != p.lineNumber { 485 | return nil 486 | } 487 | 488 | if p.match(";") { 489 | p.lex() 490 | return nil 491 | } 492 | 493 | if p.lookahead.token_type != EOFToken && !p.match("}") { 494 | return errors.New("consumeSemicolon failed") 495 | } 496 | 497 | return nil 498 | } 499 | 500 | func isLeftHandSide(stmt Stmt) bool { 501 | switch stmt.(type) { 502 | case *Identifier, *MemberExpression: 503 | return true 504 | } 505 | return false 506 | } 507 | 508 | func (p *parser) parseArrayInitialiser() (Stmt, error) { 509 | var elements []Stmt 510 | 511 | err := p.expect("[") 512 | if err != nil { 513 | return nil, err 514 | } 515 | 516 | for !p.match("]") { 517 | if p.match(",") { 518 | p.lex() 519 | elements = append(elements, nil) 520 | } else { 521 | elem, err := p.parseAssignmentExpression() 522 | if err != nil { 523 | return nil, err 524 | } 525 | elements = append(elements, elem) 526 | if !p.match("]") { 527 | err = p.expect(",") 528 | if err != nil { 529 | return nil, err 530 | } 531 | } 532 | } 533 | } 534 | 535 | err = p.expect("]") 536 | if err != nil { 537 | return nil, err 538 | } 539 | 540 | return &ArrayExpression{elements: elements}, nil 541 | } 542 | 543 | func (p *parser) parsePropertyFunction(param []Stmt) (Stmt, error) { 544 | previousStrict := p.strict 545 | body, err := p.parseFunctionSourceElements() 546 | if err != nil { 547 | return nil, err 548 | } 549 | p.strict = previousStrict 550 | return &FunctionExpression{header: false, params: param, body: body}, nil 551 | } 552 | 553 | func (p *parser) parseObjectPropertyKey() (Stmt, error) { 554 | token, err := p.lex() 555 | if err != nil { 556 | return nil, err 557 | } 558 | if token.token_type == StringLiteralToken || 559 | token.token_type == NumericLiteralToken { 560 | return &Literal{value: token.token_value}, nil 561 | } 562 | 563 | return &Identifier{value: token.token_value}, nil 564 | } 565 | 566 | func (p *parser) parseObjectProperty() (Stmt, error) { 567 | token := p.lookahead 568 | 569 | if token.token_type == IdentifierToken { 570 | id, err := p.parseObjectPropertyKey() 571 | if err != nil { 572 | return nil, err 573 | } 574 | 575 | if string(token.token_value) == "get" && !p.match(":") { 576 | key, err := p.parseObjectPropertyKey() 577 | if err != nil { 578 | return nil, err 579 | } 580 | err = p.expect("(") 581 | if err != nil { 582 | return nil, err 583 | } 584 | err = p.expect(")") 585 | if err != nil { 586 | return nil, err 587 | } 588 | value, err := p.parsePropertyFunction(nil) 589 | if err != nil { 590 | return nil, err 591 | } 592 | return &Property{"get", key, value}, nil 593 | } 594 | if string(token.token_value) == "set" && !p.match(":") { 595 | key, err := p.parseObjectPropertyKey() 596 | if err != nil { 597 | return nil, err 598 | } 599 | err = p.expect("(") 600 | if err != nil { 601 | return nil, err 602 | } 603 | 604 | token := p.lookahead 605 | if token.token_type != IdentifierToken { 606 | return nil, errors.New("Unexpected") 607 | } 608 | param, err := p.parseVariableIdentifier() 609 | if err != nil { 610 | return nil, err 611 | } 612 | var params []Stmt 613 | params = append(params, param) 614 | 615 | err = p.expect(")") 616 | if err != nil { 617 | return nil, err 618 | } 619 | 620 | value, err := p.parsePropertyFunction(params) 621 | if err != nil { 622 | return nil, err 623 | } 624 | return &Property{"set", key, value}, nil 625 | } 626 | err = p.expect(":") 627 | if err != nil { 628 | return nil, err 629 | } 630 | value, err := p.parseAssignmentExpression() 631 | if err != nil { 632 | return nil, err 633 | } 634 | return &Property{"init", id, value}, nil 635 | } 636 | 637 | if token.token_type == EOFToken || token.token_type == PunctuatorToken { 638 | return nil, errors.New("Unexpected") 639 | } else { 640 | key, err := p.parseObjectPropertyKey() 641 | if err != nil { 642 | return nil, err 643 | } 644 | err = p.expect(":") 645 | if err != nil { 646 | return nil, err 647 | } 648 | value, err := p.parseAssignmentExpression() 649 | if err != nil { 650 | return nil, err 651 | } 652 | return &Property{"init", key, value}, nil 653 | } 654 | 655 | return nil, nil 656 | } 657 | 658 | func (p *parser) parseObjectInitialiser() (Stmt, error) { 659 | err := p.expect("{") 660 | if err != nil { 661 | return nil, err 662 | } 663 | 664 | var properties []Stmt 665 | 666 | for !p.match("}") { 667 | property, err := p.parseObjectProperty() 668 | if err != nil { 669 | return nil, err 670 | } 671 | 672 | properties = append(properties, property) 673 | 674 | if !p.match("}") { 675 | err = p.expect(",") 676 | if err != nil { 677 | return nil, err 678 | } 679 | } 680 | } 681 | 682 | err = p.expect("}") 683 | if err != nil { 684 | return nil, err 685 | } 686 | return &ObjectExpression{properties}, nil 687 | } 688 | 689 | func (p *parser) parseGroupExpression() (Stmt, error) { 690 | err := p.expect("(") 691 | if err != nil { 692 | return nil, err 693 | } 694 | 695 | expr, err := p.parseExpression() 696 | 697 | err = p.expect(")") 698 | if err != nil { 699 | return nil, err 700 | } 701 | 702 | return &GroupStatement{expr}, nil 703 | } 704 | 705 | func (p *parser) parsePrimaryExpression() (Stmt, error) { 706 | token_type := p.lookahead.token_type 707 | 708 | if token_type == IdentifierToken { 709 | token, err := p.lex() 710 | if err != nil { 711 | return nil, err 712 | } 713 | return &Identifier{value: token.token_value}, nil 714 | } 715 | 716 | if token_type == StringLiteralToken || token_type == NumericLiteralToken { 717 | token, err := p.lex() 718 | if err != nil { 719 | return nil, err 720 | } 721 | return &Literal{value: token.token_value}, nil 722 | } 723 | 724 | if token_type == KeywordToken { 725 | if p.matchKeyword("this") { 726 | p.lex() 727 | return &ThisExpression{}, nil 728 | } 729 | 730 | if p.matchKeyword("function") { 731 | return p.parseFunctionExpression() 732 | } 733 | } 734 | 735 | if token_type == BooleanLiteralToken || token_type == NullLiteralToken { 736 | token, err := p.lex() 737 | if err != nil { 738 | return nil, err 739 | } 740 | return &Literal{value: token.token_value}, nil 741 | } 742 | 743 | if p.match("[") { 744 | return p.parseArrayInitialiser() 745 | } 746 | 747 | if p.match("{") { 748 | return p.parseObjectInitialiser() 749 | } 750 | 751 | if p.match("(") { 752 | return p.parseGroupExpression() 753 | } 754 | 755 | if p.match("/") || p.match("/=") { 756 | value, err := p.scanRegExp() 757 | if err != nil { 758 | return nil, err 759 | } 760 | return &Literal{value: value}, nil 761 | } 762 | 763 | return nil, errors.New("Unexpected") 764 | } 765 | 766 | func (p *parser) parseArguments() ([]Stmt, error) { 767 | var args []Stmt 768 | err := p.expect("(") 769 | if err != nil { 770 | return nil, err 771 | } 772 | 773 | if !p.match(")") { 774 | for p.index < len(p.source) { 775 | element, err := p.parseAssignmentExpression() 776 | if err != nil { 777 | return nil, err 778 | } 779 | args = append(args, element) 780 | 781 | if p.match(")") { 782 | break 783 | } 784 | err = p.expect(",") 785 | if err != nil { 786 | return nil, err 787 | } 788 | } 789 | } 790 | 791 | err = p.expect(")") 792 | if err != nil { 793 | return nil, err 794 | } 795 | 796 | return args, nil 797 | } 798 | 799 | func (p *parser) parseNonComputedProperty() (Stmt, error) { 800 | token, err := p.lex() 801 | if err != nil { 802 | return nil, err 803 | } 804 | if !isIdentifierName(token) { 805 | return nil, errors.New("NonComputedProperty failed") 806 | } 807 | return &Identifier{value: token.token_value}, nil 808 | } 809 | 810 | func (p *parser) parseNonComputedMember() (Stmt, error) { 811 | err := p.expect(".") 812 | if err != nil { 813 | return nil, err 814 | } 815 | 816 | return p.parseNonComputedProperty() 817 | } 818 | 819 | func (p *parser) parseComputedMember() (Stmt, error) { 820 | err := p.expect("[") 821 | if err != nil { 822 | return nil, err 823 | } 824 | 825 | expr, err := p.parseExpression() 826 | if err != nil { 827 | return nil, err 828 | } 829 | 830 | err = p.expect("]") 831 | if err != nil { 832 | return nil, err 833 | } 834 | 835 | return expr, nil 836 | } 837 | 838 | func (p *parser) parseNewExpression() (Stmt, error) { 839 | err := p.expectKeyword("new") 840 | if err != nil { 841 | return nil, err 842 | } 843 | 844 | callee, err := p.parseLeftHandSideExpression() 845 | if err != nil { 846 | return nil, err 847 | } 848 | var args []Stmt = nil 849 | if p.match("(") { 850 | args, err = p.parseArguments() 851 | if err != nil { 852 | return nil, err 853 | } 854 | } 855 | return &NewExpression{callee, args}, nil 856 | } 857 | 858 | func (p *parser) parseLeftHandSideExpressionAllowCall() (Stmt, error) { 859 | var expr Stmt 860 | var property Stmt 861 | var err error 862 | 863 | if p.matchKeyword("new") { 864 | expr, err = p.parseNewExpression() 865 | } else { 866 | expr, err = p.parsePrimaryExpression() 867 | } 868 | if err != nil { 869 | return nil, err 870 | } 871 | 872 | for p.match(".") || p.match("[") || p.match("(") { 873 | if p.match("(") { 874 | args, err := p.parseArguments() 875 | if err != nil { 876 | return nil, err 877 | } 878 | expr = &CallExpression{expr, args} 879 | } else if p.match("[") { 880 | property, err = p.parseComputedMember() 881 | if err != nil { 882 | return nil, err 883 | } 884 | expr = &MemberExpression{true, expr, property} 885 | } else { 886 | property, err = p.parseNonComputedMember() 887 | if err != nil { 888 | return nil, err 889 | } 890 | expr = &MemberExpression{false, expr, property} 891 | } 892 | } 893 | 894 | return expr, nil 895 | } 896 | 897 | func (p *parser) parseLeftHandSideExpression() (Stmt, error) { 898 | var expr Stmt 899 | var property Stmt 900 | var err error 901 | 902 | if p.matchKeyword("new") { 903 | expr, err = p.parseNewExpression() 904 | } else { 905 | expr, err = p.parsePrimaryExpression() 906 | } 907 | 908 | if err != nil { 909 | return nil, err 910 | } 911 | 912 | for p.match(".") || p.match("[") { 913 | var computed bool = false 914 | if p.match("[") { 915 | computed = true 916 | property, err = p.parseComputedMember() 917 | } else { 918 | property, err = p.parseNonComputedMember() 919 | } 920 | 921 | if err != nil { 922 | return nil, err 923 | } 924 | 925 | expr = &MemberExpression{computed, expr, property} 926 | } 927 | 928 | return expr, nil 929 | } 930 | 931 | func (p *parser) parsePostfixExpression() (Stmt, error) { 932 | expr, err := p.parseLeftHandSideExpressionAllowCall() 933 | if err != nil { 934 | return nil, err 935 | } 936 | 937 | if p.lookahead.token_type != PunctuatorToken { 938 | return expr, nil 939 | } 940 | 941 | if (p.match("++") || p.match("--")) && !p.peekLineTerminator() { 942 | if !isLeftHandSide(expr) { 943 | return nil, errors.New("1-InvalidLHSInAssignment") 944 | } 945 | 946 | token, err := p.lex() 947 | if err != nil { 948 | return nil, err 949 | } 950 | 951 | return &PostfixExpression{token.token_value, expr}, nil 952 | } 953 | 954 | return expr, nil 955 | } 956 | 957 | func (p *parser) parseUnaryExpression() (Stmt, error) { 958 | if p.lookahead.token_type != PunctuatorToken && 959 | p.lookahead.token_type != KeywordToken { 960 | return p.parsePostfixExpression() 961 | } 962 | 963 | if p.match("++") || p.match("--") { 964 | token, err := p.lex() 965 | if err != nil { 966 | return nil, err 967 | } 968 | 969 | expr, err := p.parseUnaryExpression() 970 | if err != nil { 971 | return nil, err 972 | } 973 | 974 | if !isLeftHandSide(expr) { 975 | return nil, errors.New("2-InvalidLHSInAssignment") 976 | } 977 | 978 | return &UnaryExpression{token.token_value, expr, true}, nil 979 | } 980 | 981 | if p.match("+") || p.match("-") || p.match("~") || p.match("!") { 982 | token, err := p.lex() 983 | if err != nil { 984 | return nil, err 985 | } 986 | 987 | expr, err := p.parseUnaryExpression() 988 | if err != nil { 989 | return nil, err 990 | } 991 | 992 | return &UnaryExpression{token.token_value, expr, false}, nil 993 | } 994 | 995 | if p.matchKeyword("delete") || p.matchKeyword("void") || p.matchKeyword("typeof") { 996 | token, err := p.lex() 997 | if err != nil { 998 | return nil, err 999 | } 1000 | 1001 | expr, err := p.parseUnaryExpression() 1002 | if err != nil { 1003 | return nil, err 1004 | } 1005 | 1006 | return &UnaryExpression{token.token_value, expr, false}, nil 1007 | } 1008 | 1009 | return p.parsePostfixExpression() 1010 | } 1011 | 1012 | func (p *parser) binaryPrecedence(token Token, allowIn bool) int { 1013 | var prec int = 0 1014 | 1015 | if token.token_type != PunctuatorToken && 1016 | token.token_type != KeywordToken { 1017 | return 0 1018 | } 1019 | 1020 | switch string(token.token_value) { 1021 | case "||": 1022 | prec = 1 1023 | case "&&": 1024 | prec = 2 1025 | case "|": 1026 | prec = 3 1027 | case "^": 1028 | prec = 4 1029 | case "&": 1030 | prec = 5 1031 | case "==", "!=", "===", "!==": 1032 | prec = 6 1033 | case "<", ">", "<=", ">=", "instanceof": 1034 | prec = 7 1035 | case "in": 1036 | prec = 0 1037 | if allowIn { 1038 | prec = 7 1039 | } 1040 | case "<<", ">>", ">>>": 1041 | prec = 8 1042 | case "+", "-": 1043 | prec = 9 1044 | case "*", "/", "%": 1045 | prec = 11 1046 | } 1047 | return prec 1048 | } 1049 | 1050 | func (p *parser) parseBinaryExpression() (Stmt, error) { 1051 | previousAllowIn := p.state_allowIn 1052 | p.state_allowIn = true 1053 | 1054 | expr, err := p.parseUnaryExpression() 1055 | if err != nil { 1056 | return nil, err 1057 | } 1058 | 1059 | token := p.lookahead 1060 | // fmt.Println("test:", token.token_type, string(token.token_value)) 1061 | prec := p.binaryPrecedence(token, previousAllowIn) 1062 | // fmt.Println("test2:", prec) 1063 | if prec == 0 { 1064 | return expr, nil 1065 | } 1066 | 1067 | for prec > 0 { 1068 | token, err = p.lex() 1069 | if err != nil { 1070 | return nil, err 1071 | } 1072 | 1073 | right, err := p.parseUnaryExpression() 1074 | if err != nil { 1075 | return nil, err 1076 | } 1077 | expr = &BinaryExpression{token.token_value, expr, right} 1078 | 1079 | prec = p.binaryPrecedence(p.lookahead, previousAllowIn) 1080 | } 1081 | 1082 | p.state_allowIn = previousAllowIn 1083 | 1084 | return expr, nil 1085 | } 1086 | 1087 | // 11.12 Conditional Operator 1088 | func (p *parser) parseConditionalExpression() (Stmt, error) { 1089 | expr, err := p.parseBinaryExpression() 1090 | if err != nil { 1091 | return nil, err 1092 | } 1093 | 1094 | var retExpr Stmt 1095 | // var alternate Stmt 1096 | var consequent Stmt 1097 | 1098 | retExpr = expr 1099 | 1100 | if p.match("?") { 1101 | p.lex() 1102 | previosAllowIn := p.state_allowIn 1103 | p.state_allowIn = true 1104 | consequent, err = p.parseAssignmentExpression() 1105 | if err != nil { 1106 | return nil, err 1107 | } 1108 | p.state_allowIn = previosAllowIn 1109 | err = p.expect(":") 1110 | if err != nil { 1111 | return nil, err 1112 | } 1113 | alternate, err := p.parseAssignmentExpression() 1114 | if err != nil { 1115 | return nil, err 1116 | } 1117 | 1118 | retExpr = &ConditionalExpression{expr: expr, consequent: consequent, alternate: alternate} 1119 | } 1120 | 1121 | return retExpr, nil 1122 | } 1123 | 1124 | func (p *parser) parseAssignmentExpression() (Stmt, error) { 1125 | token := p.lookahead 1126 | 1127 | left, err := p.parseConditionalExpression() 1128 | if err != nil { 1129 | return nil, err 1130 | } 1131 | 1132 | if p.matchAssign() { 1133 | if !isLeftHandSide(left) { 1134 | return nil, errors.New("LeftHandSide error") 1135 | } 1136 | 1137 | token, err = p.lex() 1138 | if err != nil { 1139 | return nil, err 1140 | } 1141 | 1142 | right, err := p.parseAssignmentExpression() 1143 | if err != nil { 1144 | return nil, err 1145 | } 1146 | 1147 | return &AssignmentExpression{token.token_value, left, right}, nil 1148 | } 1149 | 1150 | return left, nil 1151 | } 1152 | 1153 | func (p *parser) parseExpression() (Stmt, error) { 1154 | expr, err := p.parseAssignmentExpression() 1155 | if err != nil { 1156 | return nil, err 1157 | } 1158 | 1159 | if !p.match(",") { 1160 | return expr, nil 1161 | } 1162 | 1163 | var exprlist []Stmt 1164 | exprlist = append(exprlist, expr) 1165 | 1166 | for p.index < len(p.source) { 1167 | if !p.match(",") { 1168 | break 1169 | } 1170 | p.lex() 1171 | 1172 | expr, err = p.parseAssignmentExpression() 1173 | if err != nil { 1174 | return nil, err 1175 | } 1176 | exprlist = append(exprlist, expr) 1177 | } 1178 | 1179 | return &SequenceExpression{expr: exprlist}, nil 1180 | } 1181 | 1182 | func (p *parser) parseStatementList() ([]Stmt, error) { 1183 | var list []Stmt 1184 | 1185 | for p.index < len(p.source) { 1186 | if p.match("}") { 1187 | break 1188 | } 1189 | statement, err := p.parseSourceElement() 1190 | if err != nil { 1191 | return nil, err 1192 | } 1193 | if statement == nil { 1194 | break 1195 | } 1196 | list = append(list, statement) 1197 | } 1198 | return list, nil 1199 | } 1200 | 1201 | func (p *parser) parseBlock() (Stmt, error) { 1202 | err := p.expect("{") 1203 | if err != nil { 1204 | return nil, err 1205 | } 1206 | 1207 | block, err := p.parseStatementList() 1208 | if err != nil { 1209 | return nil, err 1210 | } 1211 | 1212 | err = p.expect("}") 1213 | if err != nil { 1214 | return nil, err 1215 | } 1216 | 1217 | return &BlockStatement{elements: block}, nil 1218 | } 1219 | 1220 | func (p *parser) parseVariableIdentifier() (Stmt, error) { 1221 | token, err := p.lex() 1222 | if err != nil { 1223 | return nil, err 1224 | } 1225 | 1226 | if token.token_type != IdentifierToken { 1227 | return nil, errors.New("Unexpected") 1228 | } 1229 | 1230 | return &Identifier{value: token.token_value}, nil 1231 | } 1232 | 1233 | func (p *parser) parseVariableDeclaration(kind []byte) (Stmt, error) { 1234 | id, err := p.parseVariableIdentifier() 1235 | if err != nil { 1236 | return nil, err 1237 | } 1238 | 1239 | var init Stmt 1240 | 1241 | /*if p.strict && isRestrictedWord(id.value) { 1242 | return nil, errors.New("StrictVarName") 1243 | }*/ 1244 | 1245 | if string(kind) == "const" { 1246 | err := p.expect("=") 1247 | if err != nil { 1248 | return nil, err 1249 | } 1250 | init, err = p.parseAssignmentExpression() 1251 | if err != nil { 1252 | return nil, err 1253 | } 1254 | } else if p.match("=") { 1255 | p.lex() 1256 | init, err = p.parseAssignmentExpression() 1257 | if err != nil { 1258 | return nil, err 1259 | } 1260 | } 1261 | 1262 | return &VariableDeclarator{id: id, init: init}, nil 1263 | } 1264 | 1265 | func (p *parser) parseVariableDeclarationList(kind []byte) ([]Stmt, error) { 1266 | var list []Stmt 1267 | for p.index < len(p.source) { 1268 | stmt, err := p.parseVariableDeclaration(kind) 1269 | if err != nil { 1270 | return nil, err 1271 | } 1272 | list = append(list, stmt) 1273 | 1274 | if p.lookahead.token_type != PunctuatorToken || p.lookahead.token_value[0] != ',' { 1275 | break 1276 | } 1277 | p.lex() 1278 | } 1279 | return list, nil 1280 | } 1281 | 1282 | func (p *parser) parseVariableStatement() (Stmt, error) { 1283 | err := p.expectKeyword("var") 1284 | if err != nil { 1285 | return nil, err 1286 | } 1287 | 1288 | declarations, err := p.parseVariableDeclarationList([]byte("var")) 1289 | if err != nil { 1290 | return nil, err 1291 | } 1292 | 1293 | err = p.consumeSemicolon() 1294 | if err != nil { 1295 | return nil, err 1296 | } 1297 | 1298 | return &VariableDeclaration{[]byte("var"), declarations, true}, nil 1299 | } 1300 | 1301 | func (p *parser) parseConstLetDeclaration(kind []byte) (Stmt, error) { 1302 | err := p.expectKeyword(string(kind)) 1303 | if err != nil { 1304 | return nil, err 1305 | } 1306 | 1307 | declarations, err := p.parseVariableDeclarationList(kind) 1308 | if err != nil { 1309 | return nil, err 1310 | } 1311 | 1312 | err = p.consumeSemicolon() 1313 | if err != nil { 1314 | return nil, err 1315 | } 1316 | 1317 | return &VariableDeclaration{kind, declarations, true}, nil 1318 | } 1319 | 1320 | func (p *parser) parseEmptyStatement() (Stmt, error) { 1321 | err := p.expect(";") 1322 | if err != nil { 1323 | return nil, err 1324 | } 1325 | return &EmptyStatement{}, nil 1326 | } 1327 | 1328 | func (p *parser) parseExpressionStatement() (Stmt, error) { 1329 | expr, err := p.parseExpression() 1330 | if err != nil { 1331 | return nil, err 1332 | } 1333 | p.consumeSemicolon() 1334 | return &ExpressionStatement{expr, true}, nil 1335 | } 1336 | 1337 | func (p *parser) parseIfStatement() (Stmt, error) { 1338 | err := p.expectKeyword("if") 1339 | if err != nil { 1340 | return nil, err 1341 | } 1342 | 1343 | err = p.expect("(") 1344 | if err != nil { 1345 | return nil, err 1346 | } 1347 | 1348 | test, err := p.parseExpression() 1349 | if err != nil { 1350 | return nil, err 1351 | } 1352 | 1353 | err = p.expect(")") 1354 | if err != nil { 1355 | return nil, err 1356 | } 1357 | 1358 | consequent, err := p.parseStatement() 1359 | if err != nil { 1360 | return nil, err 1361 | } 1362 | 1363 | var alternate Stmt 1364 | if p.matchKeyword("else") { 1365 | p.lex() 1366 | alternate, err = p.parseStatement() 1367 | if err != nil { 1368 | return nil, err 1369 | } 1370 | } 1371 | return &IfStatement{test, consequent, alternate}, nil 1372 | } 1373 | 1374 | func (p *parser) parseDoWhileStatement() (Stmt, error) { 1375 | err := p.expectKeyword("do") 1376 | if err != nil { 1377 | return nil, err 1378 | } 1379 | 1380 | oldInIteration := p.state_inIteration 1381 | p.state_inIteration = true 1382 | 1383 | body, err := p.parseStatement() 1384 | if err != nil { 1385 | return nil, err 1386 | } 1387 | 1388 | p.state_inIteration = oldInIteration 1389 | 1390 | err = p.expectKeyword("while") 1391 | if err != nil { 1392 | return nil, err 1393 | } 1394 | 1395 | err = p.expect("(") 1396 | if err != nil { 1397 | return nil, err 1398 | } 1399 | 1400 | test, err := p.parseExpression() 1401 | if err != nil { 1402 | return nil, err 1403 | } 1404 | 1405 | err = p.expect(")") 1406 | if err != nil { 1407 | return nil, err 1408 | } 1409 | 1410 | if p.match(";") { 1411 | p.lex() 1412 | } 1413 | return &DoWhileStatement{body, test}, nil 1414 | } 1415 | 1416 | func (p *parser) parseWhileStatement() (Stmt, error) { 1417 | err := p.expectKeyword("while") 1418 | if err != nil { 1419 | return nil, err 1420 | } 1421 | 1422 | err = p.expect("(") 1423 | if err != nil { 1424 | return nil, err 1425 | } 1426 | 1427 | test, err := p.parseExpression() 1428 | if err != nil { 1429 | return nil, err 1430 | } 1431 | 1432 | err = p.expect(")") 1433 | if err != nil { 1434 | return nil, err 1435 | } 1436 | 1437 | oldInInteration := p.state_inIteration 1438 | p.state_inIteration = true 1439 | 1440 | body, err := p.parseStatement() 1441 | if err != nil { 1442 | return nil, err 1443 | } 1444 | 1445 | p.state_inIteration = oldInInteration 1446 | return &WhileStatement{test, body}, nil 1447 | } 1448 | 1449 | func (p *parser) parseForVariableDeclaration() (Stmt, error) { 1450 | token, err := p.lex() 1451 | if err != nil { 1452 | return nil, err 1453 | } 1454 | 1455 | declarations, err := p.parseVariableDeclarationList([]byte("")) 1456 | if err != nil { 1457 | return nil, err 1458 | } 1459 | 1460 | return &VariableDeclaration{token.token_value, declarations, false}, nil 1461 | } 1462 | 1463 | func (p *parser) parseForStatement() (Stmt, error) { 1464 | err := p.expectKeyword("for") 1465 | if err != nil { 1466 | return nil, err 1467 | } 1468 | 1469 | err = p.expect("(") 1470 | if err != nil { 1471 | return nil, err 1472 | } 1473 | 1474 | var init Stmt 1475 | var left Stmt 1476 | var right Stmt 1477 | if p.match(";") { 1478 | p.lex() 1479 | } else { 1480 | if p.matchKeyword("var") || p.matchKeyword("let") { 1481 | p.state_allowIn = false 1482 | init, err = p.parseForVariableDeclaration() 1483 | p.state_allowIn = true 1484 | 1485 | if /*len(init.declarations) == 1 && */ p.matchKeyword("in") { 1486 | p.lex() 1487 | left = init 1488 | right, err = p.parseExpression() 1489 | if err != nil { 1490 | return nil, err 1491 | } 1492 | } 1493 | } else { 1494 | p.state_allowIn = false 1495 | init, err = p.parseExpression() 1496 | p.state_allowIn = true 1497 | 1498 | if p.matchKeyword("in") { 1499 | if !isLeftHandSide(init) { 1500 | return nil, errors.New("InvalidLHSInForIn") 1501 | } 1502 | 1503 | p.lex() 1504 | left = init 1505 | right, err = p.parseExpression() 1506 | if err != nil { 1507 | return nil, err 1508 | } 1509 | init = nil 1510 | } 1511 | } 1512 | 1513 | if left == nil { 1514 | err = p.expect(";") 1515 | if err != nil { 1516 | return nil, err 1517 | } 1518 | } 1519 | } 1520 | 1521 | var test Stmt 1522 | var update Stmt 1523 | if left == nil { 1524 | if !p.match(";") { 1525 | test, err = p.parseExpression() 1526 | } 1527 | 1528 | err = p.expect(";") 1529 | if err != nil { 1530 | return nil, err 1531 | } 1532 | 1533 | if !p.match(")") { 1534 | update, err = p.parseExpression() 1535 | if err != nil { 1536 | return nil, err 1537 | } 1538 | } 1539 | } 1540 | 1541 | err = p.expect(")") 1542 | if err != nil { 1543 | return nil, err 1544 | } 1545 | 1546 | oldInIteration := p.state_inIteration 1547 | p.state_inIteration = true 1548 | 1549 | body, err := p.parseStatement() 1550 | if err != nil { 1551 | return nil, err 1552 | } 1553 | p.state_inIteration = oldInIteration 1554 | 1555 | if left == nil { 1556 | return &ForStatement{init, test, update, body}, nil 1557 | } 1558 | return &ForInStatement{left, right, body}, nil 1559 | } 1560 | 1561 | func (p *parser) parseContinueStatement() (Stmt, error) { 1562 | err := p.expectKeyword("continue") 1563 | if err != nil { 1564 | return nil, err 1565 | } 1566 | 1567 | if p.source[p.index] == 59 { 1568 | p.lex() 1569 | if !p.state_inIteration { 1570 | return nil, errors.New("IllegalContinue") 1571 | } 1572 | 1573 | return &ContinueStatement{}, nil 1574 | } 1575 | 1576 | if p.peekLineTerminator() { 1577 | if !p.state_inIteration { 1578 | return nil, errors.New("IllegalContinue") 1579 | } 1580 | return &ContinueStatement{}, nil 1581 | } 1582 | 1583 | var label Stmt = nil 1584 | if p.lookahead.token_type == IdentifierToken { 1585 | label, err = p.parseVariableIdentifier() 1586 | if err != nil { 1587 | return nil, err 1588 | } 1589 | } 1590 | 1591 | p.consumeSemicolon() 1592 | 1593 | if label == nil && !p.state_inIteration { 1594 | return nil, errors.New("IllegalContinue") 1595 | } 1596 | return &ContinueStatement{label}, nil 1597 | } 1598 | 1599 | func (p *parser) parseBreakStatement() (Stmt, error) { 1600 | err := p.expectKeyword("break") 1601 | if err != nil { 1602 | return nil, err 1603 | } 1604 | 1605 | if p.source[p.index] == 59 { 1606 | p.lex() 1607 | if !p.state_inIteration && !p.state_inSwitch { 1608 | return nil, errors.New("IllegalBreak") 1609 | } 1610 | 1611 | return &BreakStatement{}, nil 1612 | } 1613 | 1614 | if p.peekLineTerminator() { 1615 | if !p.state_inIteration && !p.state_inSwitch { 1616 | return nil, errors.New("IllegalBreak") 1617 | } 1618 | return &BreakStatement{}, nil 1619 | } 1620 | 1621 | var label Stmt = nil 1622 | if p.lookahead.token_type == IdentifierToken { 1623 | label, err = p.parseVariableIdentifier() 1624 | if err != nil { 1625 | return nil, err 1626 | } 1627 | } 1628 | 1629 | p.consumeSemicolon() 1630 | 1631 | if label == nil && !(p.state_inIteration || p.state_inSwitch) { 1632 | return nil, errors.New("IllegalBreak") 1633 | } 1634 | return &BreakStatement{label}, nil 1635 | } 1636 | 1637 | func (p *parser) parseReturnStatement() (Stmt, error) { 1638 | var argument Stmt 1639 | 1640 | err := p.expectKeyword("return") 1641 | if err != nil { 1642 | return nil, err 1643 | } 1644 | 1645 | if !p.state_inFunctionBody { 1646 | return nil, errors.New("IllegalReturn") 1647 | } 1648 | 1649 | if p.source[p.index] == 32 { 1650 | if isIdentifierStart(p.source[p.index+1]) { 1651 | argument, err = p.parseExpression() 1652 | if err != nil { 1653 | return nil, err 1654 | } 1655 | err = p.consumeSemicolon() 1656 | if err != nil { 1657 | return nil, err 1658 | } 1659 | return &ReturnStatement{argument: argument}, nil 1660 | } 1661 | } 1662 | 1663 | if p.peekLineTerminator() { 1664 | return &ReturnStatement{}, nil 1665 | } 1666 | 1667 | if !p.match(";") { 1668 | if !p.match("}") && p.lookahead.token_type != EOFToken { 1669 | argument, err = p.parseExpression() 1670 | if err != nil { 1671 | return nil, err 1672 | } 1673 | } 1674 | } 1675 | 1676 | err = p.consumeSemicolon() 1677 | if err != nil { 1678 | return nil, err 1679 | } 1680 | 1681 | return &ReturnStatement{argument: argument}, nil 1682 | } 1683 | 1684 | func (p *parser) parseWithStatement() (Stmt, error) { 1685 | if p.strict { 1686 | return nil, errors.New("StrictModeWith") 1687 | } 1688 | 1689 | err := p.expectKeyword("with") 1690 | if err != nil { 1691 | return nil, err 1692 | } 1693 | 1694 | err = p.expect("(") 1695 | if err != nil { 1696 | return nil, err 1697 | } 1698 | 1699 | object, err := p.parseExpression() 1700 | if err != nil { 1701 | return nil, err 1702 | } 1703 | 1704 | err = p.expect(")") 1705 | if err != nil { 1706 | return nil, err 1707 | } 1708 | 1709 | body, err := p.parseStatement() 1710 | if err != nil { 1711 | return nil, err 1712 | } 1713 | return &WithStatement{object: object, body: body}, nil 1714 | } 1715 | 1716 | func (p *parser) parseSwitchCase() (Stmt, error) { 1717 | var test Stmt 1718 | var consequent []Stmt 1719 | if p.matchKeyword("default") { 1720 | p.lex() 1721 | test = nil 1722 | } else { 1723 | err := p.expectKeyword("case") 1724 | if err != nil { 1725 | return nil, err 1726 | } 1727 | test, err = p.parseExpression() 1728 | if err != nil { 1729 | return nil, err 1730 | } 1731 | } 1732 | 1733 | err := p.expect(":") 1734 | if err != nil { 1735 | return nil, err 1736 | } 1737 | 1738 | for p.index < len(p.source) { 1739 | if p.match("}") || p.matchKeyword("default") || p.matchKeyword("case") { 1740 | break 1741 | } 1742 | 1743 | statement, err := p.parseStatement() 1744 | if err != nil { 1745 | return nil, err 1746 | } 1747 | consequent = append(consequent, statement) 1748 | } 1749 | 1750 | return &SwitchCase{test: test, consequent: consequent}, nil 1751 | } 1752 | 1753 | func (p *parser) parseSwitchStatement() (Stmt, error) { 1754 | err := p.expectKeyword("switch") 1755 | if err != nil { 1756 | return nil, err 1757 | } 1758 | 1759 | err = p.expect("(") 1760 | if err != nil { 1761 | return nil, err 1762 | } 1763 | 1764 | discriminant, err := p.parseExpression() 1765 | if err != nil { 1766 | return nil, err 1767 | } 1768 | 1769 | err = p.expect(")") 1770 | if err != nil { 1771 | return nil, err 1772 | } 1773 | 1774 | err = p.expect("{") 1775 | if err != nil { 1776 | return nil, err 1777 | } 1778 | 1779 | if p.match("}") { 1780 | p.lex() 1781 | return &SwitchStatement{discriminant: discriminant}, nil 1782 | } 1783 | 1784 | var cases []Stmt 1785 | 1786 | oldInSwitch := p.state_inSwitch 1787 | p.state_inSwitch = true 1788 | // defaultFound := false 1789 | 1790 | for p.index < len(p.source) { 1791 | if p.match("}") { 1792 | break 1793 | } 1794 | clause, err := p.parseSwitchCase() 1795 | if err != nil { 1796 | return nil, err 1797 | } 1798 | /* 1799 | if clause.test == nil { 1800 | if defaultFound { 1801 | return nil, errors.New("MultipleDefaultsInSwitch") 1802 | } 1803 | defaultFound = true 1804 | } 1805 | */ 1806 | cases = append(cases, clause) 1807 | } 1808 | 1809 | p.state_inSwitch = oldInSwitch 1810 | 1811 | err = p.expect("}") 1812 | if err != nil { 1813 | return nil, err 1814 | } 1815 | 1816 | return &SwitchStatement{discriminant: discriminant, cases: cases}, nil 1817 | } 1818 | 1819 | func (p *parser) parseThrowStatement() (Stmt, error) { 1820 | err := p.expectKeyword("throw") 1821 | if err != nil { 1822 | return nil, err 1823 | } 1824 | 1825 | if p.peekLineTerminator() { 1826 | return nil, errors.New("NewlineAfterThrow") 1827 | } 1828 | 1829 | argument, err := p.parseExpression() 1830 | if err != nil { 1831 | return nil, err 1832 | } 1833 | 1834 | err = p.consumeSemicolon() 1835 | if err != nil { 1836 | return nil, err 1837 | } 1838 | 1839 | return &ThrowStatement{argument}, nil 1840 | } 1841 | 1842 | func (p *parser) parseCatchClause() (Stmt, error) { 1843 | err := p.expectKeyword("catch") 1844 | if err != nil { 1845 | return nil, err 1846 | } 1847 | 1848 | err = p.expect("(") 1849 | if err != nil { 1850 | return nil, err 1851 | } 1852 | 1853 | if p.match(")") { 1854 | return nil, errors.New("CatchClause failed") 1855 | } 1856 | 1857 | param, err := p.parseExpression() 1858 | if err != nil { 1859 | return nil, err 1860 | } 1861 | 1862 | err = p.expect(")") 1863 | if err != nil { 1864 | return nil, err 1865 | } 1866 | 1867 | body, err := p.parseBlock() 1868 | if err != nil { 1869 | return nil, err 1870 | } 1871 | 1872 | return &CatchClause{param: param, body: body}, nil 1873 | } 1874 | 1875 | func (p *parser) parseTryStatement() (Stmt, error) { 1876 | var handlers []Stmt 1877 | var finalizer Stmt 1878 | err := p.expectKeyword("try") 1879 | if err != nil { 1880 | return nil, err 1881 | } 1882 | 1883 | block, err := p.parseBlock() 1884 | if err != nil { 1885 | return nil, err 1886 | } 1887 | 1888 | if p.matchKeyword("catch") { 1889 | stmt, err := p.parseCatchClause() 1890 | if err != nil { 1891 | return nil, err 1892 | } 1893 | handlers = append(handlers, stmt) 1894 | } 1895 | 1896 | if p.matchKeyword("finally") { 1897 | p.lex() 1898 | finalizer, err = p.parseBlock() 1899 | if err != nil { 1900 | return nil, err 1901 | } 1902 | } 1903 | 1904 | return &TryStatement{block: block, handers: handlers, finalizer: finalizer}, nil 1905 | } 1906 | 1907 | func (p *parser) parseDebuggerStatement() (Stmt, error) { 1908 | err := p.expectKeyword("debugger") 1909 | if err != nil { 1910 | return nil, err 1911 | } 1912 | 1913 | err = p.consumeSemicolon() 1914 | if err != nil { 1915 | return nil, err 1916 | } 1917 | 1918 | return &DebuggerStatement{}, nil 1919 | } 1920 | 1921 | func (p *parser) parseStatement() (Stmt, error) { 1922 | token_type := p.lookahead.token_type 1923 | 1924 | if token_type == EOFToken { 1925 | return nil, errors.New("Unexpected") 1926 | } 1927 | 1928 | if token_type == PunctuatorToken { 1929 | switch string(p.lookahead.token_value) { 1930 | case ";": 1931 | return p.parseEmptyStatement() 1932 | case "{": 1933 | return p.parseBlock() 1934 | case "(": 1935 | return p.parseExpressionStatement() 1936 | } 1937 | } 1938 | 1939 | if token_type == KeywordToken { 1940 | switch string(p.lookahead.token_value) { 1941 | case "break": 1942 | return p.parseBreakStatement() 1943 | case "continue": 1944 | return p.parseContinueStatement() 1945 | case "debugger": 1946 | return p.parseDebuggerStatement() 1947 | case "do": 1948 | return p.parseDoWhileStatement() 1949 | case "for": 1950 | return p.parseForStatement() 1951 | case "function": 1952 | return p.parseFunctionDeclaration() 1953 | case "if": 1954 | return p.parseIfStatement() 1955 | case "return": 1956 | return p.parseReturnStatement() 1957 | case "switch": 1958 | return p.parseSwitchStatement() 1959 | case "throw": 1960 | return p.parseThrowStatement() 1961 | case "try": 1962 | return p.parseTryStatement() 1963 | case "var": 1964 | return p.parseVariableStatement() 1965 | case "while": 1966 | return p.parseWhileStatement() 1967 | case "with": 1968 | return p.parseWithStatement() 1969 | } 1970 | } 1971 | 1972 | expr, err := p.parseExpression() 1973 | if err != nil { 1974 | return nil, err 1975 | } 1976 | 1977 | switch expr.(type) { 1978 | case *Identifier: 1979 | if p.match(":") { 1980 | p.lex() 1981 | 1982 | labeledBody, err := p.parseStatement() 1983 | if err != nil { 1984 | return nil, err 1985 | } 1986 | 1987 | return &LabeledStatement{expr: expr, body: labeledBody}, nil 1988 | } 1989 | } 1990 | 1991 | err = p.consumeSemicolon() 1992 | if err != nil { 1993 | return nil, err 1994 | } 1995 | 1996 | return &ExpressionStatement{expr, false}, nil 1997 | } 1998 | 1999 | func (p *parser) parseFunctionSourceElements() (Stmt, error) { 2000 | var sourceElements []Stmt 2001 | err := p.expect("{") 2002 | if err != nil { 2003 | return nil, err 2004 | } 2005 | 2006 | for p.index < len(p.source) { 2007 | if p.lookahead.token_type != StringLiteralToken { 2008 | break 2009 | } 2010 | // token := p.lookahead 2011 | 2012 | sourceElement, err := p.parseSourceElement() 2013 | if err != nil { 2014 | return nil, err 2015 | } 2016 | sourceElements = append(sourceElements, sourceElement) 2017 | 2018 | should_break := false 2019 | switch sourceElement.(type) { 2020 | case *Literal: 2021 | should_break = true 2022 | } 2023 | if should_break { 2024 | break 2025 | } 2026 | 2027 | /*directive := sourceElement.value[1:len(sourceElement.value)-1] 2028 | if types.Compare(directive, []byte("use strict")) == 0 { 2029 | p.strict = true 2030 | }*/ 2031 | } 2032 | 2033 | oldInIteration := p.state_inIteration 2034 | oldInSwitch := p.state_inSwitch 2035 | oldInFunctionBody := p.state_inFunctionBody 2036 | 2037 | p.state_inIteration = false 2038 | p.state_inSwitch = false 2039 | p.state_inFunctionBody = true 2040 | 2041 | for p.index < len(p.source) { 2042 | if p.match("}") { 2043 | break 2044 | } 2045 | sourceElement, err := p.parseSourceElement() 2046 | if err != nil { 2047 | return nil, err 2048 | } 2049 | if sourceElement == nil { 2050 | break 2051 | } 2052 | sourceElements = append(sourceElements, sourceElement) 2053 | } 2054 | 2055 | err = p.expect("}") 2056 | if err != nil { 2057 | return nil, err 2058 | } 2059 | 2060 | p.state_inIteration = oldInIteration 2061 | p.state_inSwitch = oldInSwitch 2062 | p.state_inFunctionBody = oldInFunctionBody 2063 | 2064 | return &BlockStatement{elements: sourceElements}, nil 2065 | } 2066 | 2067 | func (p *parser) parseParams() ([]Stmt, error) { 2068 | var params []Stmt 2069 | 2070 | err := p.expect("(") 2071 | if err != nil { 2072 | return nil, err 2073 | } 2074 | 2075 | if !p.match(")") { 2076 | for p.index < len(p.source) { 2077 | // token := p.lookahead 2078 | param, err := p.parseVariableIdentifier() 2079 | if err != nil { 2080 | return nil, err 2081 | } 2082 | 2083 | params = append(params, param) 2084 | 2085 | if p.match(")") { 2086 | break 2087 | } 2088 | err = p.expect(",") 2089 | if err != nil { 2090 | return nil, err 2091 | } 2092 | } 2093 | } 2094 | 2095 | err = p.expect(")") 2096 | if err != nil { 2097 | return nil, err 2098 | } 2099 | 2100 | return params, nil 2101 | } 2102 | 2103 | func (p *parser) parseFunctionDeclaration() (Stmt, error) { 2104 | err := p.expectKeyword("function") 2105 | if err != nil { 2106 | return nil, err 2107 | } 2108 | 2109 | token := p.lookahead 2110 | 2111 | id, err := p.parseVariableIdentifier() 2112 | if err != nil { 2113 | return nil, err 2114 | } 2115 | if p.strict { 2116 | if isRestrictedWord(token.token_value) { 2117 | return nil, errors.New("strict mode error") 2118 | } 2119 | } 2120 | 2121 | params, err := p.parseParams() 2122 | if err != nil { 2123 | return nil, err 2124 | } 2125 | 2126 | previousStrict := p.strict 2127 | body, err := p.parseFunctionSourceElements() 2128 | if err != nil { 2129 | return nil, err 2130 | } 2131 | p.strict = previousStrict 2132 | 2133 | return &FunctionDeclaration{id: id, params: params, body: body}, nil 2134 | } 2135 | 2136 | func (p *parser) parseFunctionExpression() (Stmt, error) { 2137 | var id Stmt 2138 | err := p.expectKeyword("function") 2139 | if err != nil { 2140 | return nil, err 2141 | } 2142 | 2143 | if !p.match("(") { 2144 | token := p.lookahead 2145 | id, err = p.parseVariableIdentifier() 2146 | if err != nil { 2147 | return nil, err 2148 | } 2149 | if p.strict { 2150 | if isRestrictedWord(token.token_value) { 2151 | return nil, errors.New("strict mode error") 2152 | } 2153 | } 2154 | } 2155 | 2156 | params, err := p.parseParams() 2157 | if err != nil { 2158 | return nil, err 2159 | } 2160 | 2161 | previousStrict := p.strict 2162 | body, err := p.parseFunctionSourceElements() 2163 | if err != nil { 2164 | return nil, err 2165 | } 2166 | p.strict = previousStrict 2167 | 2168 | return &FunctionExpression{header: true, id: id, params: params, body: body}, nil 2169 | } 2170 | 2171 | func (p *parser) parseSourceElement() (Stmt, error) { 2172 | if p.lookahead.token_type == KeywordToken { 2173 | switch string(p.lookahead.token_value) { 2174 | case "const", "let": 2175 | return p.parseConstLetDeclaration(p.lookahead.token_value) 2176 | case "function": 2177 | return p.parseFunctionDeclaration() 2178 | default: 2179 | return p.parseStatement() 2180 | } 2181 | } 2182 | if p.lookahead.token_type != EOFToken { 2183 | return p.parseStatement() 2184 | } 2185 | return nil, nil 2186 | } 2187 | 2188 | func (p *parser) parseSourceElements() ([]Stmt, error) { 2189 | var sourceElements []Stmt 2190 | 2191 | for p.index < len(p.source) { 2192 | token := p.lookahead 2193 | 2194 | if token.token_type != StringLiteralToken { 2195 | break 2196 | } 2197 | 2198 | sourceElement, err := p.parseSourceElement() 2199 | if err != nil { 2200 | return nil, err 2201 | } 2202 | sourceElements = append(sourceElements, sourceElement) 2203 | 2204 | should_break := false 2205 | switch sourceElement.(type) { 2206 | case *Literal: 2207 | should_break = true 2208 | } 2209 | if should_break { 2210 | break 2211 | } 2212 | /* 2213 | directive := sourceElement.value[1:len(sourceElement.value)-1] 2214 | if types.Compare(directive, []byte("use strict")) == 0 { 2215 | p.strict = true 2216 | } 2217 | */ 2218 | } 2219 | 2220 | for p.index < len(p.source) { 2221 | sourceElement, err := p.parseSourceElement() 2222 | if err != nil { 2223 | return nil, err 2224 | } 2225 | if sourceElement == nil { 2226 | break 2227 | } 2228 | sourceElements = append(sourceElements, sourceElement) 2229 | } 2230 | return sourceElements, nil 2231 | } 2232 | 2233 | func (p *parser) parseProgram(source []byte) (Stmt, error) { 2234 | p.index = 0 2235 | p.source = source 2236 | p.strict = false 2237 | p.lineNumber = 0 2238 | 2239 | p.peek() 2240 | 2241 | body, err := p.parseSourceElements() 2242 | if err != nil { 2243 | return nil, err 2244 | } 2245 | 2246 | return &Program{body: body}, nil 2247 | } 2248 | 2249 | type JSTransform struct { 2250 | } 2251 | 2252 | func (t *JSTransform) Process(source []byte) ([]byte, error) { 2253 | var p parser 2254 | 2255 | for i := 0; i < 7; i += 1 { 2256 | source = append(source, '\n') 2257 | } 2258 | 2259 | s, err := p.parseProgram(source) 2260 | if err != nil { 2261 | return source, err 2262 | } 2263 | 2264 | b := new(bytes.Buffer) 2265 | s.generate(b) 2266 | 2267 | return b.Bytes(), nil 2268 | } 2269 | -------------------------------------------------------------------------------- /ecmascript/parsertest.go: -------------------------------------------------------------------------------- 1 | package ecmascript 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "os" 7 | ) 8 | 9 | func ScriptTest() { 10 | buffer, err := ioutil.ReadFile("src/javascript/test.js") 11 | if err != nil { 12 | panic(err) 13 | } 14 | 15 | var p parser 16 | s, err := p.parseProgram([]byte(buffer)) 17 | if err != nil { 18 | panic(err) 19 | } 20 | fmt.Println(s) 21 | 22 | fmt.Println("Begin") 23 | s.generate(os.Stdout) 24 | } 25 | -------------------------------------------------------------------------------- /ecmascript/token.go: -------------------------------------------------------------------------------- 1 | package ecmascript 2 | 3 | const ( 4 | EOFToken = iota 5 | PunctuatorToken 6 | StringLiteralToken 7 | IdentifierToken 8 | KeywordToken 9 | NullLiteralToken 10 | BooleanLiteralToken 11 | NumericLiteralToken 12 | ) 13 | 14 | type Token struct { 15 | token_type int 16 | token_value []byte 17 | } 18 | 19 | var NULLToken Token = Token{EOFToken, []byte("")} 20 | -------------------------------------------------------------------------------- /ecmascript/util.go: -------------------------------------------------------------------------------- 1 | package ecmascript 2 | 3 | func isDecimalDigit(ch byte) bool { 4 | return ch >= '0' && ch <= '9' 5 | } 6 | 7 | func isHexDigit(ch byte) bool { 8 | return (ch >= '0' && ch <= '9') || 9 | (ch >= 'a' && ch <= 'f') || 10 | (ch >= 'A' && ch <= 'F') 11 | } 12 | 13 | func isOctalDigit(ch byte) bool { 14 | return ch >= '0' && ch <= '7' 15 | } 16 | 17 | func isWhiteSpace(ch byte) bool { 18 | return ch == 32 || 19 | ch == 9 || 20 | ch == 0xB || 21 | ch == 0xC || 22 | ch == 0xA0 23 | } 24 | 25 | func isLineTerminator(ch byte) bool { 26 | return ch == 10 || ch == 13 27 | } 28 | 29 | func isIdentifierStart(ch byte) bool { 30 | return ch == 36 || ch == 95 || 31 | (ch >= 65 && ch <= 90) || 32 | (ch >= 97 && ch <= 122) 33 | } 34 | func isIdentifierPart(ch byte) bool { 35 | return ch == 36 || ch == 95 || 36 | (ch >= 65 && ch <= 90) || 37 | (ch >= 97 && ch <= 122) || 38 | (ch >= 48 && ch <= 57) 39 | } 40 | 41 | func isFutureReservedWord(id []byte) bool { 42 | sid := string(id) 43 | if sid == "class" || sid == "enum" || sid == "export" || 44 | sid == "extends" || sid == "import" || sid == "super" { 45 | return true 46 | } 47 | return false 48 | } 49 | 50 | func isStrictModeReservedWord(id []byte) bool { 51 | sid := string(id) 52 | if sid == "implements" || sid == "interface" || sid == "package" || 53 | sid == "private" || sid == "protected" || sid == "public" || 54 | sid == "static" || sid == "yield" || sid == "let" { 55 | return true 56 | } 57 | return false 58 | } 59 | 60 | func isRestrictedWord(id []byte) bool { 61 | sid := string(id) 62 | return sid == "eval" || sid == "arguments" 63 | } 64 | 65 | func isKeyword(id []byte, strict bool) bool { 66 | if strict && isStrictModeReservedWord(id) { 67 | return true 68 | } 69 | sid := string(id) 70 | 71 | switch len(sid) { 72 | case 2: 73 | return sid == "if" || sid == "in" || sid == "do" 74 | case 3: 75 | return sid == "var" || sid == "for" || sid == "new" || 76 | sid == "try" || sid == "let" 77 | case 4: 78 | return sid == "this" || sid == "else" || sid == "case" || 79 | sid == "void" || sid == "with" || sid == "enum" 80 | case 5: 81 | return sid == "while" || sid == "break" || sid == "catch" || 82 | sid == "throw" || sid == "const" || sid == "yield" || 83 | sid == "class" || sid == "super" 84 | case 6: 85 | return sid == "return" || sid == "typeof" || sid == "delete" || 86 | sid == "switch" || sid == "export" || sid == "import" 87 | case 7: 88 | return sid == "default" || sid == "finally" || sid == "extends" 89 | case 8: 90 | return sid == "function" || sid == "continue" || sid == "debugger" 91 | case 10: 92 | return sid == "instanceof" 93 | } 94 | return false 95 | } 96 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module webtravel 2 | 3 | go 1.20 4 | 5 | require github.com/drawing/webtravel v1.0.0 6 | 7 | require golang.org/x/net v0.8.0 // indirect 8 | 9 | replace github.com/drawing/webtravel v1.0.0 => ./ 10 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= 2 | golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= 3 | -------------------------------------------------------------------------------- /javascript/hook.js: -------------------------------------------------------------------------------- 1 | document.domain = "{{.Domain}}" 2 | 3 | if (top.location == self.location) 4 | { 5 | var _gaq = _gaq || []; 6 | _gaq.push(['_setAccount', 'UA-37834254-1']); 7 | _gaq.push(['_trackPageview']); 8 | 9 | (function() { 10 | var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; 11 | ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; 12 | var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); 13 | })(); 14 | } 15 | 16 | function skip_access_convert_url_0001(oldurl) 17 | { 18 | if (typeof(oldurl) != "string") { 19 | return oldurl 20 | } 21 | 22 | newurl = oldurl 23 | 24 | if (oldurl.indexOf("{{.FullURI}}") == 0) { 25 | return newurl 26 | } 27 | if (oldurl.indexOf("{{.RootURI}}") == 0) { 28 | return skip_access_convert_url_0001(oldurl.substring("{{.RootURI}}".length)) 29 | } 30 | 31 | if (document.location.href.indexOf("{{.RootURI}}") == 0) { 32 | temp = document.location.href.substr("{{.RootURI}}".length) 33 | var pos = temp.indexOf("db.") 34 | if (pos != -1) { 35 | temp = temp.substring(0, pos+4) 36 | if (oldurl.indexOf(temp) == 0) { 37 | return skip_access_convert_url_0001(oldurl.substring(temp.length)) 38 | } 39 | } 40 | } 41 | 42 | if (oldurl.indexOf("#") == 0) { 43 | } else if (oldurl.indexOf("about:blank") == 0) { 44 | } else if (oldurl.indexOf("data:") == 0) { 45 | } else if (oldurl.indexOf("file:") == 0) { 46 | } else if (oldurl.indexOf("res:") == 0) { 47 | } else if (oldurl.indexOf("C:") == 0) { 48 | } else if (oldurl.indexOf("javascript:") == 0) { 49 | } 50 | else if (oldurl.indexOf("http://") == 0) { 51 | newurl = oldurl.substr(7) 52 | var pos = newurl.indexOf("/") 53 | host = newurl 54 | path = "/" 55 | if (pos != -1) { 56 | host = newurl.substring(0, pos) 57 | path = newurl.substring(pos) 58 | } 59 | arr = host.split(".") 60 | arr.reverse() 61 | host = arr.join("/") 62 | newurl = "{{.FullURI}}" + host + "/db.a" + path 63 | } 64 | else if (oldurl.indexOf("https://") == 0) { 65 | newurl = oldurl.substr(8) 66 | var pos = newurl.indexOf("/") 67 | host = newurl 68 | path = "/" 69 | if (pos != -1) { 70 | host = newurl.substring(0, pos) 71 | path = newurl.substring(pos) 72 | } 73 | arr = host.split(".") 74 | arr.reverse() 75 | host = arr.join("/") 76 | newurl = "{{.FullURI}}" + host + "/db.b" + path 77 | } 78 | else if (oldurl.indexOf("//") == 0) { 79 | newurl = skip_access_convert_protocol_0001(window.location.protocol) + oldurl 80 | newurl = skip_access_convert_url_0001(newurl) 81 | } 82 | else if (oldurl.indexOf("/") == 0) { 83 | var pos = document.location.href.indexOf("db.") 84 | pos = pos + 4 85 | newurl = document.location.href.substring(0, pos) 86 | newurl = newurl + oldurl 87 | } 88 | else { 89 | var pos = document.location.href.lastIndexOf("/") 90 | if (pos != -1) { 91 | newurl = document.location.href.substring(0, pos+1) + oldurl 92 | } 93 | } 94 | return newurl 95 | } 96 | function skip_access_convert_domain_0001(old_domain) 97 | { 98 | if (typeof(old_domain) != "string") { 99 | return old_domain 100 | } 101 | return "{{.Domain}}" 102 | } 103 | function skip_access_convert_path_0001(oldpath) 104 | { 105 | // alert(oldpath) 106 | if (typeof(oldpath) != "string") { 107 | return oldpath 108 | } 109 | newpath = skip_access_convert_url_0001(oldpath) 110 | pos = newpath.indexOf("://") 111 | if (pos == -1) { 112 | return oldpath 113 | } 114 | newpath = newpath.substr(pos+3) 115 | pos = newpath.indexOf("/") 116 | if (pos == -1) { 117 | return oldpath 118 | } 119 | newpath = newpath.substr(pos) 120 | // alert(newpath) 121 | return newpath 122 | } 123 | 124 | function skip_access_convert_html_0001(html) 125 | { 126 | if (typeof(html) != 'string') 127 | { 128 | return html; 129 | } 130 | 131 | // Extract a base tag 132 | if ((parser = /]+)['"]?(>|\/>|<\/base>)/i.exec(html))) 133 | { 134 | ginf.target.b = parser[1]; // Update base variable for future parsing 135 | if ( ginf.target.b.charAt(ginf.target.b.length-1) != '/' ) // Ensure trailing slash 136 | ginf.target.b += '/'; 137 | html = html.replace(parser[0],''); // Remove from document since we don't want the unproxied URL 138 | } 139 | 140 | // Meta refresh 141 | if (parser = /content=(["'])?([0-9]+)\s*;\s*url=(['"]?)([^"'>]+)\3\1(.*?)(>|\/>)/i.exec(html)) 142 | html = html.replace(parser[0],parser[0].replace(parser[4],skip_access_convert_url_0001(parser[4]))); 143 | 144 | // Proxy an update to URL based attributes 145 | html = html.replace(/\.(action|src|location|href)\s*=\s*([^;}]+)/ig,'.$1=skip_access_convert_url_0001($2)'); 146 | 147 | // Send innerHTML updates through our parser 148 | html = html.replace(/\.innerHTML\s*(\+)?=\s*([^};]+)\s*/ig,'.innerHTML$1=skip_access_convert_html_0001($2)'); 149 | 150 | // Proxy iframe, ensuring the frame flag is added 151 | parser = /]*)\s*src\s*=\s*(["']?)([^"']+)\2/ig; 152 | while (match = parser.exec(html)) 153 | html = html.replace(match[0],'