agent-bypass 2.11.6 → 2.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,8 @@
1
- """argparse 极简兼容层(iSH 上省 ~1.8s import 成本)。
2
- 覆盖三工具用到的子集:位置参数、--opt 值、type、default、choices、
3
- store_true、subparsers(dest)、parse_args、error、-h。
4
- 不支持:前缀缩写、nargs、metavar、互斥组等(三工具未用)。"""
1
+ """argparse 极简兼容层(iSH 上省 ~1.8s import 成本,全部工具共用)。
2
+ 覆盖子集:位置参数(含 nargs='?')、--opt 值、--opt=value、type、default、
3
+ choices、store_true、action='append'、required、dest、set_defaults、
4
+ subparsers(dest)、parse_args、error、-h。
5
+ 不支持:前缀缩写、metavar、互斥组、nargs 其他取值等(全部工具未用)。"""
5
6
  import sys
6
7
 
7
8
 
@@ -20,22 +21,32 @@ class ArgumentParser:
20
21
  self._opts = []
21
22
  self._sub_dest = None
22
23
  self._sub_parsers = {}
24
+ self._defaults = {}
23
25
 
24
26
  def add_argument(self, *names, **kw):
25
- flag = kw.get('action') == 'store_true'
27
+ action = kw.get('action')
28
+ flag = action == 'store_true'
29
+ append = action == 'append'
30
+ optpos = kw.get('nargs') == '?'
26
31
  if len(names) == 1 and not names[0].startswith('-'):
27
- o = dict(dest=names[0], flags=None, pos=True, is_flag=False,
32
+ o = dict(dest=kw.get('dest') or names[0], flags=None, pos=True,
33
+ is_flag=False, append=False, required=False, optpos=optpos,
28
34
  type=kw.get('type', str), default=kw.get('default'),
29
35
  choices=kw.get('choices'), help=kw.get('help', ''))
30
36
  else:
31
37
  longs = [n for n in names if n.startswith('--')]
32
- dest = (longs[0] if longs else names[0]).lstrip('-').replace('-', '_')
38
+ dest = kw.get('dest') or ((longs[0] if longs else names[0])
39
+ .lstrip('-').replace('-', '_'))
33
40
  o = dict(dest=dest, flags=list(names), pos=False, is_flag=flag,
34
- type=kw.get('type', str),
35
- default=kw.get('default', False if flag else None),
41
+ append=append, required=bool(kw.get('required')),
42
+ optpos=False, type=kw.get('type', str),
43
+ default=kw.get('default', [] if append else (False if flag else None)),
36
44
  choices=kw.get('choices'), help=kw.get('help', ''))
37
45
  self._opts.append(o)
38
46
 
47
+ def set_defaults(self, **kw):
48
+ self._defaults.update(kw)
49
+
39
50
  def add_subparsers(self, dest=None, **kw):
40
51
  self._sub_dest = dest or 'cmd'
41
52
  holder = self
@@ -46,11 +57,14 @@ class ArgumentParser:
46
57
  holder._sub_parsers[name] = p
47
58
  return p
48
59
  return _Sub()
60
+
49
61
  def parse_args(self, argv=None):
50
62
  argv = list(sys.argv[1:] if argv is None else argv)
51
63
  if self._sub_parsers:
64
+ ns = _NS()
65
+ for k, v in self._defaults.items():
66
+ setattr(ns, k, v)
52
67
  if not argv:
53
- ns = _NS()
54
68
  setattr(ns, self._sub_dest, None)
55
69
  return ns
56
70
  for i, t in enumerate(argv):
@@ -71,6 +85,8 @@ class ArgumentParser:
71
85
  ns = _NS()
72
86
  for o in self._opts:
73
87
  setattr(ns, o['dest'], o['default'])
88
+ for k, v in self._defaults.items():
89
+ setattr(ns, k, v)
74
90
  pos_order = [o for o in self._opts if o['pos']]
75
91
  pos_idx = 0
76
92
  i = 0
@@ -80,16 +96,20 @@ class ArgumentParser:
80
96
  self.print_help()
81
97
  raise SystemExit(0)
82
98
  if t.startswith('-') and t != '-':
83
- o = self._find(t)
99
+ tkey, teq, tval = t.partition('=')
100
+ o = self._find(tkey if teq else t)
84
101
  if o is None:
85
102
  self.error('unrecognized arguments: %s' % t)
86
103
  if o['is_flag']:
87
104
  setattr(ns, o['dest'], True)
88
105
  i += 1
106
+ elif teq:
107
+ self._setval(ns, o, self._conv(o, tval, tkey))
108
+ i += 1
89
109
  else:
90
110
  if i + 1 >= len(argv):
91
111
  self.error('argument %s: expected one argument' % t)
92
- setattr(ns, o['dest'], self._conv(o, argv[i + 1], t))
112
+ self._setval(ns, o, self._conv(o, argv[i + 1], t))
93
113
  i += 2
94
114
  else:
95
115
  if pos_idx >= len(pos_order):
@@ -99,15 +119,30 @@ class ArgumentParser:
99
119
  pos_idx += 1
100
120
  i += 1
101
121
  for o in pos_order[pos_idx:]:
102
- if o['default'] is None:
122
+ if o['default'] is None and not o['optpos']:
103
123
  self.error('the following arguments are required: %s' % o['dest'])
124
+ for o in self._opts:
125
+ if o['required'] and getattr(ns, o['dest']) is None:
126
+ fl = ', '.join(o['flags'] or [o['dest']])
127
+ self.error('the following arguments are required: %s' % fl)
104
128
  return ns
105
129
 
130
+ def _setval(self, ns, o, v):
131
+ if o['append']:
132
+ cur = getattr(ns, o['dest'])
133
+ if not isinstance(cur, list):
134
+ cur = []
135
+ setattr(ns, o['dest'], cur)
136
+ cur.append(v)
137
+ else:
138
+ setattr(ns, o['dest'], v)
139
+
106
140
  def _find(self, flag):
107
141
  for o in self._opts:
108
142
  if o['flags'] and flag in o['flags']:
109
143
  return o
110
144
  return None
145
+
111
146
  def _conv(self, o, raw, shown):
112
147
  if o['type'] is not str:
113
148
  try:
@@ -131,7 +166,9 @@ class ArgumentParser:
131
166
  w('\noptions:\n')
132
167
  for o in self._opts:
133
168
  if o['flags']:
134
- w(' %s %s\n' % (', '.join(o['flags']), o['help']))
169
+ meta = ' {%s}' % ', '.join(map(str, o['choices'])) if o['choices'] else ''
170
+ req = ' (required)' if o.get('required') else ''
171
+ w(' %s%s%s %s\n' % (', '.join(o['flags']), meta, req, o['help']))
135
172
  else:
136
173
  w(' %s %s\n' % (o['dest'], o['help']))
137
174
  if self._sub_parsers:
@@ -153,6 +190,21 @@ if __name__ == '__main__':
153
190
  d.add_argument('-w', '--workers', type=int, default=8, help='并发')
154
191
  d.add_argument('--dot', action='store_true', help='DoT')
155
192
  d.add_argument('--via', choices=['udp', 'dot'], default='udp', help='通道')
156
- ns = ap.parse_args()
157
- print('cmd=%s target=%s workers=%r dot=%r via=%s' % (
158
- ns.cmd, ns.target, ns.workers, ns.dot, ns.via))
193
+ a = sub.add_parser('add', help='add test')
194
+ a.add_argument('--type', required=True, choices=['a', 'b'], help='类型')
195
+ a.add_argument('--lib', action='append', default=[], help='重复项')
196
+ a.add_argument('--from', dest='source', default='', help='dest 改名')
197
+ a.add_argument('tgt', nargs='?', help='可选位置')
198
+ a.set_defaults(func='F')
199
+ ns = ap.parse_args(['add', '--type=a', '--lib', 'x', '--lib=y', '--from', 'src'])
200
+ assert (ns.cmd, ns.type, ns.lib, ns.source, ns.tgt, ns.func) == \
201
+ ('add', 'a', ['x', 'y'], 'src', None, 'F'), vars(ns)
202
+ ns2 = ap.parse_args(['dns', 'example.com', '-w', '4', '--dot'])
203
+ assert (ns2.cmd, ns2.target, ns2.workers, ns2.dot, ns2.via) == \
204
+ ('dns', 'example.com', 4, True, 'udp'), vars(ns2)
205
+ try:
206
+ ap.parse_args(['add'])
207
+ raise AssertionError('required 未触发')
208
+ except SystemExit as e:
209
+ assert e.code == 2
210
+ print('argsmini self-test OK')
@@ -13,7 +13,8 @@
13
13
  2. NVD 官方,最全
14
14
  3. GitHub 相关 PoC 仓库
15
15
  """
16
- import argparse, json, ssl, sys, urllib.parse
16
+ import argsmini as argparse
17
+ import json, ssl, sys, urllib.parse
17
18
  import urllib.request, urllib.error
18
19
 
19
20
  CTX = ssl.create_default_context()
@@ -63,12 +64,12 @@ def from_circl(kw, limit):
63
64
  return []
64
65
 
65
66
 
66
- def from_nvd(kw, limit, retries=2):
67
+ def from_nvd(kw, limit, retries=1):
67
68
  u = ("https://services.nvd.nist.gov/rest/json/cves/2.0?"
68
69
  f"keywordSearch={urllib.parse.quote(kw)}&resultsPerPage={limit}")
69
70
  d = {}
70
71
  for _ in range(retries + 1):
71
- d = get(u, timeout=60)
72
+ d = get(u, timeout=30)
72
73
  if "_error" not in d and "vulnerabilities" in d:
73
74
  break
74
75
  if "_error" in d or "vulnerabilities" not in d:
@@ -136,16 +137,17 @@ def main():
136
137
  if src not in results:
137
138
  continue
138
139
  i += 1
140
+ tgt = sys.stderr if a.json else sys.stdout # JSON 模式诊断走 stderr,防数据错位
139
141
  print(f"\n{'='*60}\n[{i}] {labels[src]} — {a.keyword}\n{'='*60}",
140
- file=sys.stderr)
142
+ file=tgt)
141
143
  rows = results[src]
142
144
  if not rows:
143
- print(" (无结果 / 源不可用)", file=sys.stderr)
145
+ print(" (无结果 / 源不可用)", file=tgt)
144
146
  for c in rows:
145
147
  if a.json:
146
148
  print(json.dumps({"source": src, **c}, ensure_ascii=False))
147
149
  elif src == "github":
148
- print(f"★{c['stars']:<5} {c['repo']}\n {c['desc']}\n {c['url']}")
150
+ print(f"★{c.get('stars', 0):<5} {c.get('repo', '?')}\n {c.get('desc', '')}\n {c.get('url', '')}")
149
151
  else:
150
152
  print(f"{c['cve']} CVSS={c['cvss']} {c['published']}\n {c['summary']}")
151
153
  for r in c["refs"][:2]:
package/scripts/deck.py CHANGED
@@ -19,7 +19,8 @@
19
19
  python3 deck.py clear
20
20
  python3 deck.py next-round
21
21
  """
22
- import argparse, json, os
22
+ import argsmini as argparse
23
+ import json, os
23
24
  from datetime import datetime, timezone, timedelta
24
25
 
25
26
  BASE = os.path.dirname(os.path.abspath(__file__))
@@ -20,7 +20,8 @@
20
20
  # 只提取不查 CVE
21
21
  python3 depscan.py https://target.com --no-cve
22
22
  """
23
- import argparse, json, re, ssl, sys, urllib.parse
23
+ import argsmini as argparse
24
+ import json, re, ssl, sys, urllib.parse
24
25
  import urllib.request, urllib.error
25
26
 
26
27
  CTX = ssl.create_default_context()