12
12
import argparse
13
13
import binascii
14
14
15
- from typing import Any , Optional , Sequence , cast
15
+ from typing import Any , Iterable , List , Optional , Sequence , cast
16
16
17
17
try :
18
18
from sender import broadcast_packet
39
39
pkg_customize ,
40
40
)
41
41
42
+
42
43
class ModeOptionalAction (argparse .Action ):
43
44
"""
44
45
Custom action for handling optional arguments in argparse.
@@ -87,11 +88,223 @@ def format_usage(self) -> str:
87
88
return " | " .join (self .option_strings )
88
89
89
90
91
+ class MaxWidthHelpFormatter (argparse .RawTextHelpFormatter ):
92
+ """
93
+ *Replace some methods with Python 3.13 versions for better display*
94
+
95
+ Custom help formatter that formats the usage and actions in a more readable way.
96
+
97
+ It ensures that the usage line does not exceed a specified width.
98
+ """
99
+
100
+ def __init__ (self , prog : str , indent_increment : int = 2 , max_help_position : int = 24 , width : int = 80 ) -> None :
101
+ super ().__init__ (prog , indent_increment , max_help_position , width )
102
+
103
+ def _format_usage (
104
+ self ,
105
+ usage : Optional [str ],
106
+ actions : Iterable [argparse .Action ],
107
+ groups : Iterable [argparse ._MutuallyExclusiveGroup ],
108
+ prefix : Optional [str ],
109
+ ) -> str :
110
+ if prefix is None :
111
+ prefix = "usage: "
112
+
113
+ if usage is not None :
114
+ usage = usage % dict (prog = self ._prog )
115
+ elif usage is None and not actions :
116
+ usage = "%(prog)s" % dict (prog = self ._prog )
117
+ elif usage is None :
118
+ prog = "%(prog)s" % dict (prog = self ._prog )
119
+
120
+ optionals = []
121
+ positionals = []
122
+ for action in actions :
123
+ if action .option_strings :
124
+ optionals .append (action )
125
+ else :
126
+ positionals .append (action )
127
+
128
+ format = self ._format_actions_usage
129
+ action_usage = format (optionals + positionals , groups )
130
+ usage = " " .join ([s for s in [prog , action_usage ] if s ])
131
+
132
+ text_width = self ._width - self ._current_indent
133
+ if len (prefix ) + len (usage ) > text_width :
134
+ opt_parts = self ._get_actions_usage_parts (optionals , groups )
135
+ pos_parts = self ._get_actions_usage_parts (positionals , groups )
136
+
137
+ def get_lines (parts , indent , prefix = None ):
138
+ lines = []
139
+ line = []
140
+ indent_length = len (indent )
141
+ if prefix is not None :
142
+ line_len = len (prefix ) - 1
143
+ else :
144
+ line_len = indent_length - 1
145
+ for part in parts :
146
+ if line_len + 1 + len (part ) > text_width and line :
147
+ lines .append (indent + " " .join (line ))
148
+ line = []
149
+ line_len = indent_length - 1
150
+ line .append (part )
151
+ line_len += len (part ) + 1
152
+ if line :
153
+ lines .append (indent + " " .join (line ))
154
+ if prefix is not None :
155
+ lines [0 ] = lines [0 ][indent_length :]
156
+ return lines
157
+
158
+ if len (prefix ) + len (prog ) <= 0.75 * text_width :
159
+ indent = " " * (len (prefix ) + len (prog ) + 1 )
160
+ if opt_parts :
161
+ lines = get_lines ([prog ] + opt_parts , indent , prefix )
162
+ lines .extend (get_lines (pos_parts , indent ))
163
+ elif pos_parts :
164
+ lines = get_lines ([prog ] + pos_parts , indent , prefix )
165
+ else :
166
+ lines = [prog ]
167
+
168
+ else :
169
+ indent = " " * len (prefix )
170
+ parts = opt_parts + pos_parts
171
+ lines = get_lines (parts , indent )
172
+ if len (lines ) > 1 :
173
+ lines = []
174
+ lines .extend (get_lines (opt_parts , indent ))
175
+ lines .extend (get_lines (pos_parts , indent ))
176
+ lines = [prog ] + lines
177
+
178
+ usage = "\n " .join (lines )
179
+
180
+ return "%s%s\n \n " % (prefix , usage )
181
+
182
+ def _format_actions_usage (
183
+ self ,
184
+ actions : Iterable [argparse .Action ],
185
+ groups : Iterable [argparse ._MutuallyExclusiveGroup ],
186
+ ) -> str :
187
+ return " " .join (self ._get_actions_usage_parts (list (actions ), groups ))
188
+
189
+ def _get_actions_usage_parts (
190
+ self ,
191
+ actions : Sequence [argparse .Action ],
192
+ groups : Iterable [argparse ._MutuallyExclusiveGroup ],
193
+ ) -> List [str ]:
194
+
195
+ group_actions = set ()
196
+ inserts = {}
197
+ for group in groups :
198
+ if not group ._group_actions :
199
+ raise ValueError (f"empty group { group } " )
200
+
201
+ if all (action .help is argparse .SUPPRESS for action in group ._group_actions ):
202
+ continue
203
+
204
+ try :
205
+ start = actions .index (group ._group_actions [0 ])
206
+ except ValueError :
207
+ continue
208
+ else :
209
+ end = start + len (group ._group_actions )
210
+ if actions [start :end ] == group ._group_actions :
211
+ group_actions .update (group ._group_actions )
212
+ inserts [start , end ] = group
213
+
214
+ parts = []
215
+ for action in actions :
216
+ if action .help is argparse .SUPPRESS :
217
+ part = None
218
+ elif not action .option_strings :
219
+ default = self ._get_default_metavar_for_positional (action )
220
+ part = self ._format_args (action , default )
221
+ if action in group_actions :
222
+ if part [0 ] == "[" and part [- 1 ] == "]" :
223
+ part = part [1 :- 1 ]
224
+ else :
225
+ option_string = action .option_strings [0 ]
226
+ if action .nargs == 0 :
227
+ try :
228
+ part = action .format_usage ()
229
+ except AttributeError :
230
+ part = action .option_strings [0 ]
231
+ else :
232
+ default = self ._get_default_metavar_for_optional (action )
233
+ args_string = self ._format_args (action , default )
234
+ part = "%s %s" % (option_string , args_string )
235
+ if not action .required and action not in group_actions :
236
+ part = "[%s]" % part
237
+
238
+ parts .append (part )
239
+
240
+ inserted_separators_indices = set ()
241
+ for start , end in sorted (inserts , reverse = True ):
242
+ group = inserts [start , end ]
243
+ group_parts = [item for item in parts [start :end ] if item is not None ]
244
+ group_size = len (group_parts )
245
+ if group .required :
246
+ open , close = "()" if group_size > 1 else ("" , "" )
247
+ else :
248
+ open , close = "[]"
249
+ group_parts [0 ] = open + group_parts [0 ]
250
+ group_parts [- 1 ] = group_parts [- 1 ] + close
251
+ for i , part in enumerate (group_parts [:- 1 ], start = start ):
252
+ if i not in inserted_separators_indices :
253
+ parts [i ] = part + " |"
254
+ inserted_separators_indices .add (i )
255
+ parts [start + group_size - 1 ] = group_parts [- 1 ]
256
+ for i in range (start + group_size , end ):
257
+ parts [i ] = None
258
+
259
+ return [item for item in parts if item is not None ]
260
+
261
+ def _format_action_invocation (self , action : argparse .Action ) -> str :
262
+ if not action .option_strings :
263
+ default = self ._get_default_metavar_for_positional (action )
264
+ return " " .join (self ._metavar_formatter (action , default )(1 ))
265
+ else :
266
+ if action .nargs == 0 :
267
+ return ", " .join (action .option_strings )
268
+ else :
269
+ default = self ._get_default_metavar_for_optional (action )
270
+ args_string = self ._format_args (action , default )
271
+ return ", " .join (action .option_strings ) + " " + args_string
272
+
273
+ def _format_args (self , action : argparse .Action , default_metavar : str ) -> str :
274
+ get_metavar = self ._metavar_formatter (action , default_metavar )
275
+ if action .nargs is None :
276
+ result = "%s" % get_metavar (1 )
277
+ elif action .nargs == argparse .OPTIONAL :
278
+ result = "[%s]" % get_metavar (1 )
279
+ elif action .nargs == argparse .ZERO_OR_MORE :
280
+ metavar = get_metavar (1 )
281
+ if len (metavar ) == 2 :
282
+ result = "[%s [%s ...]]" % metavar
283
+ else :
284
+ result = "[%s ...]" % metavar
285
+ elif action .nargs == argparse .ONE_OR_MORE :
286
+ result = "%s [%s ...]" % get_metavar (2 )
287
+ elif action .nargs == argparse .REMAINDER :
288
+ result = "..."
289
+ elif action .nargs == argparse .PARSER :
290
+ result = "%s ..." % get_metavar (1 )
291
+ elif action .nargs == argparse .SUPPRESS :
292
+ result = ""
293
+ else :
294
+ action .nargs = cast (int , action .nargs )
295
+ try :
296
+ formats = ["%s" for _ in range (action .nargs )]
297
+ except TypeError :
298
+ raise ValueError ("invalid nargs value" ) from None
299
+ result = " " .join (formats ) % get_metavar (action .nargs )
300
+ return result
301
+
302
+
90
303
if __name__ == "__main__" :
91
304
parser = argparse .ArgumentParser (
92
- description = "Jiyu Attack Script" ,
93
- epilog = "Github Repositories: https://github.com/weilycoder/Jiyu_udp_attack/tree/main/ \n \n "
94
- "Example usage:\n "
305
+ description = "Jiyu Attack Script\n \n "
306
+ "Github Repositories: https://github.com/weilycoder/Jiyu_udp_attack/tree/main/ \n " ,
307
+ epilog = "Example usage:\n "
95
308
' python Jiyu_udp_attack -t 192.168.106.100 -m "Hello World"\n '
96
309
" python Jiyu_udp_attack -t 192.168.106.104 -w https://www.github.com\n "
97
310
' python Jiyu_udp_attack -t 192.168.106.0/24 -f 192.168.106.2 -c "del *.log" -i 1000\n '
@@ -107,7 +320,7 @@ def format_usage(self) -> str:
107
320
' python Jiyu_udp_attack -t 192.168.106.100 --pkg ":{0.int.little_4}" 1024\n '
108
321
' python Jiyu_udp_attack -t 192.168.106.100 --pkg ":{0}{1.size_800}" 4d hello\n '
109
322
" python Jiyu_udp_attack -t 192.168.106.100 --pkg test.txt 1024 hello\n " ,
110
- formatter_class = argparse . RawTextHelpFormatter ,
323
+ formatter_class = MaxWidthHelpFormatter ,
111
324
)
112
325
network_config_group = parser .add_argument_group (
113
326
"Network Configuration" , "Specify the network configuration for the attack."
0 commit comments