2023-09-17 22:13:42 +03:00
|
|
|
|
package Common.Utils.Validators;
|
2023-10-03 15:07:17 +03:00
|
|
|
|
import Common.Constants.Constants;
|
2023-09-17 22:13:42 +03:00
|
|
|
|
import Common.Global;
|
|
|
|
|
|
import Common.Utils.Utils;
|
|
|
|
|
|
|
|
|
|
|
|
import java.io.InputStreamReader;
|
|
|
|
|
|
import java.util.Vector;
|
|
|
|
|
|
public class ShellParser {
|
|
|
|
|
|
public static ShellParserState state;
|
|
|
|
|
|
public static StringBuilder lineBuilder;
|
|
|
|
|
|
public static String userName;
|
|
|
|
|
|
public static StringBuilder invitationBuilder;
|
|
|
|
|
|
public static char c;
|
|
|
|
|
|
public static char[] buffer = new char[1];
|
|
|
|
|
|
public static Vector<String> lines = new Vector<>();
|
|
|
|
|
|
public static boolean bracketOpened = false;
|
|
|
|
|
|
public static boolean return_active = false;
|
|
|
|
|
|
public static boolean isCommandSymbol() {
|
|
|
|
|
|
int code = c;
|
|
|
|
|
|
return code <= 31 || c == 127;
|
|
|
|
|
|
}
|
|
|
|
|
|
public static void ResetLine() {
|
|
|
|
|
|
invitationBuilder = new StringBuilder();
|
|
|
|
|
|
lineBuilder = new StringBuilder();
|
|
|
|
|
|
bracketOpened = false;
|
|
|
|
|
|
state = ShellParserState.NewLine;
|
|
|
|
|
|
return_active = false;
|
|
|
|
|
|
}
|
|
|
|
|
|
public static boolean isNameCharacter() {
|
|
|
|
|
|
//латиница, цифры,подчеркивания. и -
|
|
|
|
|
|
return String.valueOf(c).matches("[\\w\\-]*") || c == '?';
|
|
|
|
|
|
}
|
|
|
|
|
|
//false наоборот означать что конец строки ЕСТЬ.
|
|
|
|
|
|
public static boolean checkEndLine() {
|
|
|
|
|
|
if (return_active) {
|
|
|
|
|
|
switch (c) {
|
|
|
|
|
|
case '\n':
|
|
|
|
|
|
//ложная тревога. возврат каретки ни на что не влияет.
|
|
|
|
|
|
lines.add(lineBuilder.toString());
|
|
|
|
|
|
ResetLine();
|
|
|
|
|
|
return false;
|
|
|
|
|
|
case '\r':
|
|
|
|
|
|
return false;
|
|
|
|
|
|
default:
|
|
|
|
|
|
//тут был возврат. надо игнорить символ, ибо он уже прочитан.
|
|
|
|
|
|
return_active = false;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
switch (c) {
|
|
|
|
|
|
case '\r':
|
|
|
|
|
|
return_active = true;
|
|
|
|
|
|
return false;
|
|
|
|
|
|
case '\n':
|
|
|
|
|
|
lines.add(lineBuilder.toString());
|
|
|
|
|
|
ResetLine();
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
public static void NewLine() {
|
|
|
|
|
|
if (c == '[') {//приглашение со скобками.
|
|
|
|
|
|
bracketOpened = true;
|
|
|
|
|
|
invitationBuilder.append(c);
|
|
|
|
|
|
state = ShellParserState.UserName;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
if (isNameCharacter()) {
|
|
|
|
|
|
invitationBuilder.append(c);
|
|
|
|
|
|
state = ShellParserState.UserName;
|
|
|
|
|
|
} else
|
|
|
|
|
|
//не буква и не скобка. значит в этой строке приглашения нет.
|
|
|
|
|
|
state = ShellParserState.Skip;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public static void UserName() {
|
|
|
|
|
|
if (c == '@') { //проверить. а тот ли юзернейм.
|
|
|
|
|
|
String test = invitationBuilder.toString();
|
|
|
|
|
|
if (bracketOpened) test = test.substring(1);
|
|
|
|
|
|
test = test.toLowerCase();
|
|
|
|
|
|
state = test.endsWith(userName.toLowerCase()) ? ShellParserState.MachineName : ShellParserState.Skip;
|
|
|
|
|
|
invitationBuilder.append(c);
|
2023-10-03 15:07:17 +03:00
|
|
|
|
} else if (isNameCharacter() || (c == '['))
|
2023-09-17 22:13:42 +03:00
|
|
|
|
invitationBuilder.append(c);
|
|
|
|
|
|
else
|
|
|
|
|
|
state = ShellParserState.Skip;
|
|
|
|
|
|
}
|
|
|
|
|
|
public static void MachineName() {
|
|
|
|
|
|
switch (c) {
|
|
|
|
|
|
case ' ':
|
|
|
|
|
|
case ':':
|
|
|
|
|
|
state = ShellParserState.Path;
|
|
|
|
|
|
invitationBuilder.append(c);
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
if (isNameCharacter())
|
|
|
|
|
|
invitationBuilder.append(c);
|
|
|
|
|
|
else state = ShellParserState.Skip;
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public static void Path() {
|
|
|
|
|
|
switch (c) {
|
|
|
|
|
|
case '$':
|
|
|
|
|
|
case '#':
|
|
|
|
|
|
case '>':
|
|
|
|
|
|
invitationBuilder.append(c);
|
|
|
|
|
|
state = ShellParserState.Space; //приглашение завершено. осталось прочитать пробел после него
|
|
|
|
|
|
break;
|
|
|
|
|
|
case ']':
|
|
|
|
|
|
if (bracketOpened) {
|
|
|
|
|
|
invitationBuilder.append(c);
|
|
|
|
|
|
bracketOpened = false;
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// UI.Info("KEK");
|
|
|
|
|
|
state = ShellParserState.Skip; //непарная скобка, все, привет
|
|
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
|
|
|
|
default:
|
|
|
|
|
|
invitationBuilder.append(c);
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public static void Space() {
|
|
|
|
|
|
if (c == ' ') {
|
|
|
|
|
|
state = ShellParserState.End;
|
|
|
|
|
|
invitationBuilder.append(c);
|
|
|
|
|
|
} else {
|
|
|
|
|
|
state = ShellParserState.Skip;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public static void setUserName(String userName_in) {
|
|
|
|
|
|
userName = userName_in;
|
|
|
|
|
|
}
|
|
|
|
|
|
public static void printChar() {
|
2023-10-03 15:07:17 +03:00
|
|
|
|
if (c != Constants.boop) {
|
|
|
|
|
|
int code = c;
|
|
|
|
|
|
if ((!return_active) || (c == '\n')) {
|
|
|
|
|
|
System.out.print(c == '\r' ? ("\\r") :
|
|
|
|
|
|
(c == '\n' ? "\\n\n" : c));
|
|
|
|
|
|
if (isCommandSymbol())
|
|
|
|
|
|
System.out.print(Utils.RBrackets(code));
|
|
|
|
|
|
}
|
2023-09-17 22:13:42 +03:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
public static void ReadInvitation(InputStreamReader fromServer) {
|
|
|
|
|
|
lines.clear();
|
|
|
|
|
|
ResetLine();
|
|
|
|
|
|
do {
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (fromServer.read(buffer) >= 0) {
|
|
|
|
|
|
c = buffer[0];
|
|
|
|
|
|
printChar();
|
|
|
|
|
|
// if (!isCommandSymbol()) {
|
|
|
|
|
|
if (checkEndLine() && (!isCommandSymbol())) {
|
|
|
|
|
|
lineBuilder.append(c);
|
|
|
|
|
|
switch (state) {
|
|
|
|
|
|
case NewLine:
|
|
|
|
|
|
NewLine();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case UserName:
|
|
|
|
|
|
UserName();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case MachineName:
|
|
|
|
|
|
MachineName();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case Path:
|
|
|
|
|
|
Path();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case Space:
|
|
|
|
|
|
Space();
|
|
|
|
|
|
break;
|
|
|
|
|
|
case Skip:
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2023-10-03 15:07:17 +03:00
|
|
|
|
// System.out.println(Utils.Brackets(state));
|
2023-09-17 22:13:42 +03:00
|
|
|
|
// }
|
|
|
|
|
|
} else
|
|
|
|
|
|
state = ShellParserState.End;
|
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
|
Global.Log.PrintException(ex);
|
|
|
|
|
|
state = ShellParserState.End;
|
|
|
|
|
|
}
|
|
|
|
|
|
} while (!state.equals(ShellParserState.End));
|
|
|
|
|
|
}
|
|
|
|
|
|
public static void ReadLine(InputStreamReader fromServer) {
|
|
|
|
|
|
state = ShellParserState.NewLine;
|
|
|
|
|
|
do {
|
|
|
|
|
|
try {
|
|
|
|
|
|
if (fromServer.read(buffer) >= 0) {
|
|
|
|
|
|
c = buffer[0];
|
|
|
|
|
|
printChar();
|
|
|
|
|
|
switch (c) {
|
|
|
|
|
|
case '\r':
|
|
|
|
|
|
break;
|
|
|
|
|
|
case '\n':
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
} else
|
|
|
|
|
|
state = ShellParserState.End;
|
|
|
|
|
|
} catch (Exception ex) {
|
|
|
|
|
|
Global.Log.PrintException(ex);
|
|
|
|
|
|
state = ShellParserState.End;
|
|
|
|
|
|
}
|
|
|
|
|
|
} while (!state.equals(ShellParserState.End));
|
|
|
|
|
|
}
|
|
|
|
|
|
public static String getCommandResult(InputStreamReader fromServer) {
|
|
|
|
|
|
//если последняя строка ответа - кончается на приглашение, то ничего не делаем.
|
|
|
|
|
|
//если нет. значит ответ кончается на перевод строки. или пуст.
|
|
|
|
|
|
// нужно прочитать еще одно приглашение.
|
|
|
|
|
|
String last_line = "";
|
|
|
|
|
|
String res = "";
|
|
|
|
|
|
boolean no_extra_read = false;
|
|
|
|
|
|
if (lines.size() > 0) {
|
|
|
|
|
|
last_line = lines.lastElement();
|
|
|
|
|
|
if (no_extra_read = last_line.endsWith(invitationBuilder.toString())) {
|
|
|
|
|
|
System.out.println("needs trim");
|
|
|
|
|
|
lines.remove(lines.size() - 1);
|
|
|
|
|
|
//больше ничего не читаем. но. обрезаем ее конец.
|
|
|
|
|
|
last_line = last_line.substring(0, last_line.length() - invitationBuilder.length());
|
|
|
|
|
|
lines.add(last_line);
|
|
|
|
|
|
}
|
|
|
|
|
|
res = String.join("\n", lines);
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!no_extra_read) {
|
|
|
|
|
|
ReadInvitation(fromServer);
|
|
|
|
|
|
}
|
|
|
|
|
|
return res;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|