├── .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 | 
53 |
54 | 输入期望访问的地址,如 `www.baidu.com`,点 `Go`,跳转到目标页面
55 |
56 | 
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 = /