package Common.Utils.Validators; import Common.Constants; 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 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); } else if (isNameCharacter() || (c == '[')) 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() { 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)); } } } 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; } } // System.out.println(Utils.Brackets(state)); // } } 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; } }