diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..00a51af --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# These are explicitly windows files and should use crlf +*.bat text eol=crlf + diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0ed93fd --- /dev/null +++ b/.gitignore @@ -0,0 +1,51 @@ +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build + +### Gradle template +/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Cache of project +.gradletasknamecache + +# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 +# gradle/wrapper/gradle-wrapper.properties + +### Java template +# Compiled class file +*.class + +# Log file +*.log + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* + +### JetBrains template +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +.idea/ +*.iml +*.ipr +*.iws + +# IntelliJ +out/ diff --git a/build.gradle.kts b/build.gradle.kts new file mode 100644 index 0000000..d76ce5f --- /dev/null +++ b/build.gradle.kts @@ -0,0 +1,31 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java project to get you started. + * For more details take a look at the Java Quickstart chapter in the Gradle + * User Manual available at https://docs.gradle.org/6.0.1/userguide/tutorial_java_projects.html + */ + +plugins { + // Apply the java plugin to add support for Java + java + + // Apply the application plugin to add support for building a CLI application. + application +} + +repositories { + // Use jcenter for resolving dependencies. + // You can declare any Maven/Ivy/file repository here. + jcenter() +} + +dependencies { + // Use JUnit test framework + testImplementation("junit:junit:4.12") +} + +application { + // Define the main class for the application. + mainClassName = "midaef.web.file.server.Main" +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..cc4fdc2 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..9492014 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..2fe81a7 --- /dev/null +++ b/gradlew @@ -0,0 +1,183 @@ +#!/usr/bin/env sh + +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +## +## Gradle start up script for UN*X +## +############################################################################## + +# Attempt to set APP_HOME +# Resolve links: $0 may be a link +PRG="$0" +# Need this for relative symlinks. +while [ -h "$PRG" ] ; do + ls=`ls -ld "$PRG"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + PRG="$link" + else + PRG=`dirname "$PRG"`"/$link" + fi +done +SAVED="`pwd`" +cd "`dirname \"$PRG\"`/" >/dev/null +APP_HOME="`pwd -P`" +cd "$SAVED" >/dev/null + +APP_NAME="Gradle" +APP_BASE_NAME=`basename "$0"` + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD="maximum" + +warn () { + echo "$*" +} + +die () { + echo + echo "$*" + echo + exit 1 +} + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "`uname`" in + CYGWIN* ) + cygwin=true + ;; + Darwin* ) + darwin=true + ;; + MINGW* ) + msys=true + ;; + NONSTOP* ) + nonstop=true + ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD="$JAVA_HOME/jre/sh/java" + else + JAVACMD="$JAVA_HOME/bin/java" + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD="java" + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then + MAX_FD_LIMIT=`ulimit -H -n` + if [ $? -eq 0 ] ; then + if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then + MAX_FD="$MAX_FD_LIMIT" + fi + ulimit -n $MAX_FD + if [ $? -ne 0 ] ; then + warn "Could not set maximum file descriptor limit: $MAX_FD" + fi + else + warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" + fi +fi + +# For Darwin, add options to specify how the application appears in the dock +if $darwin; then + GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" +fi + +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then + APP_HOME=`cygpath --path --mixed "$APP_HOME"` + CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` + + # We build the pattern for arguments to be converted via cygpath + ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` + SEP="" + for dir in $ROOTDIRSRAW ; do + ROOTDIRS="$ROOTDIRS$SEP$dir" + SEP="|" + done + OURCYGPATTERN="(^($ROOTDIRS))" + # Add a user-defined pattern to the cygpath arguments + if [ "$GRADLE_CYGPATTERN" != "" ] ; then + OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" + fi + # Now convert the arguments - kludge to limit ourselves to /bin/sh + i=0 + for arg in "$@" ; do + CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` + CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option + + if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition + eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` + else + eval `echo args$i`="\"$arg\"" + fi + i=`expr $i + 1` + done + case $i in + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + esac +fi + +# Escape application args +save () { + for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done + echo " " +} +APP_ARGS=`save "$@"` + +# Collect all arguments for the java command, following the shell quoting and substitution rules +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..9618d8d --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,100 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto init + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto init + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:init +@rem Get command-line arguments, handling Windows variants + +if not "%OS%" == "Windows_NT" goto win9xME_args + +:win9xME_args +@rem Slurp the command line arguments. +set CMD_LINE_ARGS= +set _SKIP=2 + +:win9xME_args_slurp +if "x%~1" == "x" goto execute + +set CMD_LINE_ARGS=%* + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle.kts b/settings.gradle.kts new file mode 100644 index 0000000..11368fe --- /dev/null +++ b/settings.gradle.kts @@ -0,0 +1,10 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * + * Detailed information about configuring a multi-project build in Gradle can be found + * in the user manual at https://docs.gradle.org/6.0.1/userguide/multi_project_builds.html + */ + +rootProject.name = "web_file_server" diff --git a/src/com/nameless/Main.java b/src/com/nameless/Main.java deleted file mode 100644 index 713da3a..0000000 --- a/src/com/nameless/Main.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.nameless; - -import java.util.Scanner; - -/** - * This program can be use for your home PC or server. - * Web file server give you the ability to have permanent access to files on your computer. - * The author of this program does not call for its use as malicious software. - * Anyway the author does not bear any responsibility! - * - * @author Mikhailov Danil(midaef). - */ - -/** - * This class is Main and it's do instance server class. - */ - -public class Main { - - private static Integer port; - private static String password; - - public Main() { - settingsServer(); - new Server(port, password); - } - - public static void main(String[] args) { - new Main(); - } - - private static void settingsServer() { - System.out.println("Web file server v1.0"); - System.out.println("GitHub: https://github.com/midaef/web_file_server"); - System.out.print("Configure your server\nPort: "); - port = new Scanner(System.in).nextInt(); - System.out.print("Password: "); - password = new Scanner(System.in).nextLine(); - } - -} diff --git a/src/com/nameless/Page.java b/src/com/nameless/Page.java deleted file mode 100644 index 5ad37d9..0000000 --- a/src/com/nameless/Page.java +++ /dev/null @@ -1,197 +0,0 @@ -package com.nameless; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Base64; - -/** - * This program can be use for your home PC or server. - * Web file server give you the ability to have permanent access to files on your computer. - * The author of this program does not call for its use as malicious software. - * Anyway the author does not bear any responsibility! - * - * @author Mikhailov Danil(midaef). - */ - -/** - * This class use for create any page. - */ - -public class Page { - - private ArrayList dirList = new ArrayList<>(); - private String index = ""; - private File dir; - - public Page() {} - - public String createIndexPage(String directory, Boolean isMainDirectory) { - index = readFile("index.html"); - getEmptyDirectory(directory); - addButtonToPage(isMainDirectory); - addDirectoryToPage(directory); - clearDirectoryList(); - return index; - } - - private void addDirectoryToPage(String directory) { - for (int i = 0; i < dirList.size(); i++) { - index = index.replace("&file&", - "&download&&size&&icon&" + - dirList.get(i) + "&file&").replace("&title&", getUserName()) - .replace("&path&", "

" + "Your directory: " + directory + "

"); - setDownloadLink(directory, i); - setSize(directory, i); - setIcon(directory, i); - } - index = index.replace("&file&", ""); - } - - private void setDownloadLink(String directory, int count) { - dir = new File(directory + "/" + dirList.get(count)); - if (dir.isFile()) { - index = index.replace("&download&", ""); - } else { - index = index.replace("&download&", ""); - } - } - - public void clearDirectoryList() {dirList.clear();} - - private void setIcon(String directory, int count) { - dir = new File(directory + "/" + dirList.get(count)); - if (dir.isDirectory()) { - index = index.replace("&icon&", - ""); - } else { - index = index.replace("&icon&", - ""); - } - } - - private void setSize(String directory, int count) { - dir = new File(directory + "/" + dirList.get(count)); - if (dir.isFile()) { - index = index.replace("&size&", "" + dir.length() / 1024 + " KB"); - } else { - index = index.replace("&size&", ""); - } - } - - private void getEmptyDirectory(String directory) { - if (dirList.isEmpty()) { - index = index.replace("&file&", "Directory is empty") - .replace("&path&", "

" + directory + "

") - .replace("&title&", getUserName()); - } - } - - private void addButtonToPage(Boolean isMainDirectory) { - if (!isMainDirectory) { - index = index.replace("&back-link&", "Parent directory") - .replace("&back-link-src&", readFile("back_link_icon.txt")); - } - else index = index.replace("&back-link&", "").replace("&back-link-src&", ""); - } - - public String readFile(String fileName) { - String txt = ""; - try { - File file = new File(fileName); - FileReader fileReader = new FileReader(file); - BufferedReader bufferedReader = new BufferedReader(fileReader); - String line; - while((line = bufferedReader.readLine()) != null) { - txt += line + "\n"; - } - bufferedReader.close(); - } catch (Exception e) { - e.printStackTrace(); - } - return txt; - } - - public String createPageNotFound() { - String page = readFile("404.html").replace("&cat&", readFile("cat.txt")); - return page; - } - - public String createErrorPage() { - String page = readFile("error.html").replace("&cat&", readFile("cat.txt")); - return page; - } - - private String getUserName() { - return System.getProperty("user.name"); - } - - public String getFormatFile(String directoryName) { - String[] formatList = {".txt", ".xml", ".log", ".bat", ".cmd", ".py", ".acp", ".acpx", ".cfg", ".css", ".js", - ".html", ".htm", ".php", ".xhtml", ".c", ".cpp", ".cs", ".h", ".sh", ".java", ".swift", ".vb", ".ini", - ".png", ".jpg", ".gif", ".bmp"}; - for (String format : formatList) { - if (directoryName.endsWith(format)) { - return format; - } - } - return ""; - } - - public String openFile(String format, String directoryLink) { - String[] imageFormat = {".png", ".jpg", ".gif", ".bmp"}; - String[] textFormat = {".txt", ".xml", ".log", ".bat", ".cmd", ".py", ".acp", ".acpx", ".cfg", ".css", ".js", - ".html", ".htm", ".php", ".xhtml", ".c", ".cpp", ".cs", ".h", ".sh", ".java", ".swift", ".vb", ".ini"}; - for (String text : textFormat) { - if (format.equals(text)) return readFile(directoryLink); - } - for (String image : imageFormat) { - if (format.equals(image)) { - String dataImage = openImage(directoryLink, format); - String base64 = dataImage.split(":img:")[1]; - Integer width = Integer.parseInt(dataImage.split(":img:")[0].split("/")[0]) / 4; - Integer height = Integer.parseInt(dataImage.split(":img:")[0].split("/")[1]) / 4; - String src = "data:" + "image/" + - format.replace(".", "") + ";" + "base64," + base64; - return readFile("img.html").replace("&src&", src) - .replace("&width&", width.toString()).replace("&height&", height.toString()); - } - } - return ""; - } - - private String openImage(String directoryLink, String format) { - try { - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - BufferedImage bufferedImage = ImageIO.read(new File(directoryLink)); - ImageIO.write(bufferedImage, format.replace(".", "") , outputStream); - Integer width = bufferedImage.getWidth(); - Integer height = bufferedImage.getHeight(); - return width + "/" + height + ":img:" + Base64.getEncoder().encodeToString(outputStream.toByteArray()); - } catch (IOException e) { - return createErrorPage(); - } - } - - public String getMainDir(String directory) { - String OS = System.getProperty("os.name"); - String userName = getUserName(); - if (OS.startsWith("Mac")) dir = new File("/Users/" + userName + "/" + directory); - else dir = new File("C:\\Users\\" + userName + "/" + directory); - if (!getFormatFile(directory).isEmpty()) return dir.getPath(); - for (File file : dir.listFiles()) { - if (!file.getName().startsWith(".") && !dirList.contains(file.getName()) - && !file.getName().startsWith("ntuser") && !file.getName().startsWith("NTUSER")) { - dirList.add(file.getName()); - } - } - return dir.getPath(); - } - -} \ No newline at end of file diff --git a/src/com/nameless/Server.java b/src/com/nameless/Server.java deleted file mode 100644 index 22b2cf2..0000000 --- a/src/com/nameless/Server.java +++ /dev/null @@ -1,207 +0,0 @@ -package com.nameless; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintStream; -import java.math.BigInteger; -import java.net.InetAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.security.MessageDigest; -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Date; -import java.util.HashMap; - - -/** - * This program can be use for your home PC or server. - * Web file server give you the ability to have permanent access to files on your computer. - * The author of this program does not call for its use as malicious software. - * Anyway the author does not bear any responsibility! - * - * @author Mikhailov Danil(midaef). - */ - -/** - * This class use for start web file server. - * It's server can get request from browser and send to client. - * 1. If you want to start the server in your PC - * 2. You should to set-up the port in your router's settings. - * 3. Start program and set port and password. - * 4. Next, in the browser, connect in the format "localhost:port" or "ip:port". - * 5. Input password and any login. - * By the way, when you set-up port, you have to check port is not busy - */ - -public class Server { - - private Boolean shutdown = false; - private Page page = new Page(); - private Integer port; - private String password; - private HashMap users = new HashMap<>(); - - public Server(Integer port, String password) { - this.port = port; - this.password = password; - start(); - } - - private void start() { - try { - InetAddress address = InetAddress.getByName("::"); - ServerSocket serverSocket = new ServerSocket(port, 50, address); - System.out.println("[SERVER STARTED]-[" + getNowDate() + "]"); - while (!shutdown) { - try (Socket socket = serverSocket.accept()) { - BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); - String line = reader.readLine(); - String clientIP = getClientIP(socket); - if (line != null) { - String token = createToken(clientIP, reader); - Boolean isLogin = login(line, token); - if (isLogin) { - line = line.split("\n")[0].replace(" HTTP/1.1", ""); - String request = parser(line); - sendRequest(socket, request); - } else sendRequest(socket, page.readFile("login.html")); - } - } catch (Exception e) {e.printStackTrace();} - } - } catch (Exception e) {e.printStackTrace();} - System.out.println("[Server stopped]-" + "[" + getNowDate() + "]"); - } - - private String createToken(String clientIP, BufferedReader reader) { - try { - String userAgent = ""; - for (int i = 0; i < 7; i++) { - userAgent = reader.readLine(); - if (userAgent.startsWith("User-Agent: ")) { - break; - } - } - userAgent = userAgent + clientIP; - if (userAgent.startsWith("User-Agent: ")) { - MessageDigest m = MessageDigest.getInstance("MD5"); - m.reset(); - m.update(userAgent.getBytes("utf-8")); - String token = new BigInteger(1, m.digest()).toString(16); - while (token.length() < 32) { - token = "0" + token; - } - return token; - } - } catch (Exception e) {e.printStackTrace();} - return ""; - } - - private String getPasswordAndLogin(String line) { - String req[] = line.split("="); - String data = req[req.length-1].replace("/ HTTP/1.1", ""); - return data; - } - - private Boolean login(String line, String token) { - if (!users.containsKey(token)) { - if (line.contains("entry=")) { - String req = getPasswordAndLogin(line); - if (req.split("/")[1].equals(password)) { - users.put(token, req.split("/")[0]); - return true; - } else return false; - } else return false; - } - return true; - } - - private String getClientIP(Socket socket) { - return socket.getInetAddress().toString(); - } - - private String parser(String line) { - String directoryLink = ""; - if (line.contains("dir=") && !line.contains("download=")) { - String directoryName = splitRequest(line, "dir="); - try { - directoryLink = page.getMainDir(directoryName); - } catch (Exception e) { - return page.createErrorPage(); - } - if (!page.getFormatFile(directoryName).isEmpty()) { - return page.openFile(page.getFormatFile(directoryName), directoryLink); - } - String index = page.createIndexPage(directoryLink, false); - return index; - } else if (line.contains("download=")) { - String filePath = splitRequest(line, "dir=").replace("download=", "") - .replace("//", ""); - String path = page.getMainDir("") + "/" + filePath; - page.clearDirectoryList(); - if (filePath.contains("/")) { - String[] data = filePath.split("/"); - return path + "&" + data[data.length-1] + "&" + new File(path).length() + "&keyword=download"; - } - return path + "&" + filePath + "&" + new File(path).length() + "&keyword=download"; - } else if (line.equals("GET /") || line.contains("entry")) { - String directory = page.getMainDir(""); - return page.createIndexPage(directory, true); - } - return page.createPageNotFound(); - } - - private String splitRequest(String line, String type) { - String[] request = line.split("\\?"); - String directoryName = ""; - for (String str : request) { - directoryName += "/" + str.replace(type, "").replace("GET /", "") - .replace("%20", " "); - } - String[] data = {}; - if (directoryName.contains(password + "//")) data = directoryName.split("//"); - else if (data.length == 0) return directoryName; - return data[data.length-1]; - } - - private byte[] getBytes(String path) { - byte[] fileInArray = new byte[(int)new File(path).length()]; - try { - FileInputStream f = new FileInputStream(path); - f.read(fileInArray); - return fileInArray; - } catch (Exception e) {e.printStackTrace();} - return fileInArray; - } - - private void sendRequest(Socket socket, String req) { - try { - String httpResponse = "HTTP/1.1 200 OK\r\n"; - OutputStream outputStream = socket.getOutputStream(); - PrintStream ps = new PrintStream(outputStream); - if (req.contains("keyword=download")) { - String data[] = req.split("&"); - byte[] fileInArray = getBytes(data[0]); - ps.printf(httpResponse); - ps.print("Content-Disposition: form-data; name=\"myFile\"; filename=\"" + data[1] + "\"\r\n"); - ps.printf("Content-Type: text/plain; charset=utf-8\r\n\r\n"); - outputStream.write(fileInArray); - } else { - httpResponse+="\r\n" + req; - socket.getOutputStream().write(httpResponse.getBytes("UTF-8")); - } - } catch (Exception e) {e.printStackTrace();} - } - - private String getNowDate() { - Date now = new Date(); - LocalDateTime nowDate = LocalDateTime.now(); - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); - String formatDateTime = nowDate.format(formatter); - return formatDateTime; - } - -} diff --git a/src/main/java/midaef/web/file/server/Main.java b/src/main/java/midaef/web/file/server/Main.java new file mode 100644 index 0000000..8115cae --- /dev/null +++ b/src/main/java/midaef/web/file/server/Main.java @@ -0,0 +1,43 @@ +package midaef.web.file.server; + +import java.util.Scanner; + +/** + * This program can be use for your home PC or server. + * Web file server give you the ability to have permanent access to files on your computer. + * The author of this program does not call for its use as malicious software. + * Anyway the author does not bear any responsibility! + * + * @author Mikhailov Danil(midaef). + */ + +/** + * This class is Main and it's do instance server class. + */ + +public class Main { + + private static Integer port; + private static String password; + + public Main() { + settingsServer(); + new Server(port, password); + } + + public static void main(String[] args) { + new Main(); + } + + private static void settingsServer() { + System.out.println("Web file server v1.0"); + System.out.println("GitHub: https://github.com/midaef/web_file_server"); + System.out.print("Configure your server\nPort: "); +// port = new Scanner(System.in).nextInt(); + System.out.print("Password: "); +// password = new Scanner(System.in).nextLine(); + port = 8888; + password = "password"; + } + +} diff --git a/src/main/java/midaef/web/file/server/Page.java b/src/main/java/midaef/web/file/server/Page.java new file mode 100644 index 0000000..b5829d7 --- /dev/null +++ b/src/main/java/midaef/web/file/server/Page.java @@ -0,0 +1,213 @@ +package midaef.web.file.server; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Base64; + +/** + * This program can be use for your home PC or server. + * Web file server give you the ability to have permanent access to files on your computer. + * The author of this program does not call for its use as malicious software. + * Anyway the author does not bear any responsibility! + * + * @author Mikhailov Danil(midaef). + */ + +/** + * This class use for create any page. + */ + +public class Page { + + private ArrayList dirList = new ArrayList<>(); + private String index = ""; + private File dir; + + public Page() { + } + + public String createIndexPage(String directory, Boolean isMainDirectory) { + index = readFile("index.html"); + getEmptyDirectory(directory); + addButtonToPage(isMainDirectory); + addDirectoryToPage(directory); + clearDirectoryList(); + return index; + } + + private void addDirectoryToPage(String directory) { + for (int i = 0; i < dirList.size(); i++) { + index = index.replace("&file&", + "&download&&size&&icon&" + + dirList.get(i) + "&file&").replace("&title&", getUserName()) + .replace("&path&", "

" + "Your directory: " + directory + "

"); + setDownloadLink(directory, i); + setSize(directory, i); + setIcon(directory, i); + } + index = index.replace("&file&", ""); + } + + private void setDownloadLink(String directory, int count) { + dir = new File(directory + "/" + dirList.get(count)); + if (dir.isFile()) { + index = index.replace("&download&", ""); + } else { + index = index.replace("&download&", ""); + } + } + + public void clearDirectoryList() { + dirList.clear(); + } + + private void setIcon(String directory, int count) { + dir = new File(directory + "/" + dirList.get(count)); + if (dir.isDirectory()) { + index = index.replace("&icon&", + ""); + } else { + index = index.replace("&icon&", + ""); + } + } + + private void setSize(String directory, int count) { + dir = new File(directory + "/" + dirList.get(count)); + if (dir.isFile()) { + index = index.replace("&size&", "" + dir.length() / 1024 + " KB"); + } else { + index = index.replace("&size&", ""); + } + } + + private void getEmptyDirectory(String directory) { + if (dirList.isEmpty()) { + index = index.replace("&file&", "Directory is empty") + .replace("&path&", "

" + directory + "

") + .replace("&title&", getUserName()); + } + } + + private void addButtonToPage(Boolean isMainDirectory) { + if (!isMainDirectory) { + index = index.replace("&back-link&", "Parent directory") + .replace("&back-link-src&", readFile("back_link_icon.txt")); + } else index = index.replace("&back-link&", "").replace("&back-link-src&", ""); + } + + public String readFile(String fileName) { + String txt = ""; + try { + InputStreamReader inputStreamReader; + if (Files.exists(Paths.get(fileName))) { + File file = new File(fileName); + inputStreamReader = new FileReader(file); + } else { + inputStreamReader = new InputStreamReader(getClass().getClassLoader().getResourceAsStream(fileName)); + } + BufferedReader bufferedReader = new BufferedReader(inputStreamReader); + String line; + while ((line = bufferedReader.readLine()) != null) { + txt += line + "\n"; + } + bufferedReader.close(); + } catch (Exception e) { + e.printStackTrace(); + } + return txt; + } + + public String createPageNotFound() { + String page = readFile("404.html").replace("&cat&", readFile("cat.txt")); + return page; + } + + public String createErrorPage() { + String page = readFile("error.html").replace("&cat&", readFile("cat.txt")); + return page; + } + + private String getUserName() { + return System.getProperty("user.name"); + } + + public String getFormatFile(String directoryName) { + String[] formatList = {".txt", ".xml", ".log", ".bat", ".cmd", ".py", ".acp", ".acpx", ".cfg", ".css", ".js", + ".html", ".htm", ".php", ".xhtml", ".c", ".cpp", ".cs", ".h", ".sh", ".java", ".swift", ".vb", ".ini", + ".png", ".jpg", ".gif", ".bmp"}; + for (String format : formatList) { + if (directoryName.endsWith(format)) { + return format; + } + } + return ""; + } + + public String openFile(String format, String directoryLink) { + String[] imageFormat = {".png", ".jpg", ".gif", ".bmp"}; + String[] textFormat = {".txt", ".xml", ".log", ".bat", ".cmd", ".py", ".acp", ".acpx", ".cfg", ".css", ".js", + ".html", ".htm", ".php", ".xhtml", ".c", ".cpp", ".cs", ".h", ".sh", ".java", ".swift", ".vb", ".ini"}; + for (String text : textFormat) { + if (format.equals(text)) return readFile(directoryLink); + } + for (String image : imageFormat) { + if (format.equals(image)) { + String dataImage = openImage(directoryLink, format); + String base64 = dataImage.split(":img:")[1]; + Integer width = Integer.parseInt(dataImage.split(":img:")[0].split("/")[0]) / 4; + Integer height = Integer.parseInt(dataImage.split(":img:")[0].split("/")[1]) / 4; + String src = "data:" + "image/" + + format.replace(".", "") + ";" + "base64," + base64; + return readFile("img.html").replace("&src&", src) + .replace("&width&", width.toString()).replace("&height&", height.toString()); + } + } + return ""; + } + + private String openImage(String directoryLink, String format) { + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + BufferedImage bufferedImage = ImageIO.read(new File(directoryLink)); + ImageIO.write(bufferedImage, format.replace(".", ""), outputStream); + Integer width = bufferedImage.getWidth(); + Integer height = bufferedImage.getHeight(); + return width + "/" + height + ":img:" + Base64.getEncoder().encodeToString(outputStream.toByteArray()); + } catch (IOException e) { + return createErrorPage(); + } + } + + public String getMainDir(String directory) { + String OS = System.getProperty("os.name"); + String userName = getUserName(); + if (OS.startsWith("Mac")) { + dir = new File("/Users/" + userName + "/" + directory); + } else { + dir = new File("C:\\Users\\" + userName + "/" + directory); + } + if (!getFormatFile(directory).isEmpty()) { + return dir.getPath(); + } + for (File file : dir.listFiles()) { + if (!file.getName().startsWith(".") && !dirList.contains(file.getName()) + && !file.getName().startsWith("ntuser") && !file.getName().startsWith("NTUSER")) { + dirList.add(file.getName()); + } + } + return dir.getPath(); + } + +} diff --git a/src/main/java/midaef/web/file/server/Server.java b/src/main/java/midaef/web/file/server/Server.java new file mode 100644 index 0000000..ff0667e --- /dev/null +++ b/src/main/java/midaef/web/file/server/Server.java @@ -0,0 +1,77 @@ +package midaef.web.file.server; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintStream; +import java.math.BigInteger; +import java.net.InetAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.security.MessageDigest; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Date; +import java.util.HashMap; + + +/** + * This program can be use for your home PC or server. + * Web file server give you the ability to have permanent access to files on your computer. + * The author of this program does not call for its use as malicious software. + * Anyway the author does not bear any responsibility! + * + * @author Mikhailov Danil(midaef). + */ + +/** + * This class use for start web file server. + * It's server can get request from browser and send to client. + * 1. If you want to start the server in your PC + * 2. You should to set-up the port in your router's settings. + * 3. Start program and set port and password. + * 4. Next, in the browser, connect in the format "localhost:port" or "ip:port". + * 5. Input password and any login. + * By the way, when you set-up port, you have to check port is not busy + */ + +public class Server { + private Boolean shutdown = false; + private Integer port; + private String password; + + public Server(Integer port, String password) { + this.port = port; + this.password = password; + start(); + } + + private void start() { + try { + InetAddress address = InetAddress.getByName("::"); + ServerSocket serverSocket = new ServerSocket(port); + System.out.println("[SERVER STARTED]-[" + getNowDate() + "]"); + while (!shutdown) { + try { + Socket socket = serverSocket.accept(); + new Session(socket, password).start(); + } catch (Exception e) { + e.printStackTrace(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + System.out.println("[Server stopped]-" + "[" + getNowDate() + "]"); + } + + private String getNowDate() { + Date now = new Date(); + LocalDateTime nowDate = LocalDateTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); + String formatDateTime = nowDate.format(formatter); + return formatDateTime; + } +} diff --git a/src/main/java/midaef/web/file/server/Session.java b/src/main/java/midaef/web/file/server/Session.java new file mode 100644 index 0000000..f612765 --- /dev/null +++ b/src/main/java/midaef/web/file/server/Session.java @@ -0,0 +1,187 @@ +package midaef.web.file.server; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.PrintStream; +import java.math.BigInteger; +import java.net.Socket; +import java.security.MessageDigest; +import java.util.HashMap; + +public class Session extends Thread { + private final Socket socket; + private final String password; + private Page page = new Page(); + private HashMap users = new HashMap<>(); + + public Session(Socket socket, String password) { + this.socket = socket; + this.password = password; + } + + @Override + public void run() { + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); + String line = null; + line = reader.readLine(); + String clientIP = getClientIP(socket); + if (line != null) { + String token = createToken(clientIP, reader); + Boolean isLogin = login(line, token); + if (isLogin) { + line = line.split("\n")[0].replace(" HTTP/1.1", ""); + String request = parser(line); + sendRequest(socket, request); + } else { + sendRequest(socket, page.readFile("login.html")); + } + } + } catch (IOException e) { + e.printStackTrace(); + } finally { + try { + socket.close(); + } catch (IOException e) { + // ignore + } + } + } + + private String getClientIP(Socket socket) { + return socket.getInetAddress().toString(); + } + + private String createToken(String clientIP, BufferedReader reader) { + try { + String userAgent = ""; + for (int i = 0; i < 7; i++) { + userAgent = reader.readLine(); + if (userAgent.startsWith("User-Agent: ")) { + break; + } + } + userAgent = userAgent + clientIP; + if (userAgent.startsWith("User-Agent: ")) { + MessageDigest m = MessageDigest.getInstance("MD5"); + m.reset(); + m.update(userAgent.getBytes("utf-8")); + String token = new BigInteger(1, m.digest()).toString(16); + while (token.length() < 32) { + token = "0" + token; + } + return token; + } + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } + + private String parser(String line) { + String directoryLink = ""; + if (line.contains("dir=") && !line.contains("download=")) { + String directoryName = splitRequest(line, "dir="); + try { + directoryLink = page.getMainDir(directoryName); + } catch (Exception e) { + return page.createErrorPage(); + } + if (!page.getFormatFile(directoryName).isEmpty()) { + return page.openFile(page.getFormatFile(directoryName), directoryLink); + } + String index = page.createIndexPage(directoryLink, false); + return index; + } else if (line.contains("download=")) { + String filePath = splitRequest(line, "dir=").replace("download=", "") + .replace("//", ""); + String path = page.getMainDir("") + "/" + filePath; + page.clearDirectoryList(); + if (filePath.contains("/")) { + String[] data = filePath.split("/"); + return path + "&" + data[data.length - 1] + "&" + new File(path).length() + "&keyword=download"; + } + return path + "&" + filePath + "&" + new File(path).length() + "&keyword=download"; + } else if (line.equals("GET /") || line.contains("entry")) { + String directory = page.getMainDir(""); + return page.createIndexPage(directory, true); + } + return page.createPageNotFound(); + } + + private void sendRequest(Socket socket, String req) { + try { + String httpResponse = "HTTP/1.1 200 OK\r\n"; + OutputStream outputStream = socket.getOutputStream(); + PrintStream ps = new PrintStream(outputStream); + if (req.contains("keyword=download")) { + String data[] = req.split("&"); + byte[] fileInArray = getBytes(data[0]); + ps.printf(httpResponse); + ps.print("Content-Disposition: form-data; name=\"myFile\"; filename=\"" + data[1] + "\"\r\n"); + ps.printf("Content-Type: text/plain; charset=utf-8\r\n\r\n"); + outputStream.write(fileInArray); + } else { + httpResponse += "\r\n" + req; + socket.getOutputStream().write(httpResponse.getBytes("UTF-8")); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + + private String getPasswordAndLogin(String line) { + String req[] = line.split("="); + String data = req[req.length - 1].replace("/ HTTP/1.1", ""); + return data; + } + + private String splitRequest(String line, String type) { + String[] request = line.split("\\?"); + String directoryName = ""; + for (String str : request) { + directoryName += "/" + str.replace(type, "").replace("GET /", "") + .replace("%20", " "); + } + String[] data = {}; + if (directoryName.contains(password + "//")) { + data = directoryName.split("//"); + } else { + if (data.length == 0) return directoryName; + } + return data[data.length - 1]; + } + + private Boolean login(String line, String token) { + if (!users.containsKey(token)) { + if (line.contains("entry=")) { + String req = getPasswordAndLogin(line); + if (req.split("/")[1].equals(password)) { + users.put(token, req.split("/")[0]); + return true; + } else { + return false; + } + } else { + return false; + } + } + return true; + } + + private byte[] getBytes(String path) { + byte[] fileInArray = new byte[(int) new File(path).length()]; + try { + FileInputStream f = new FileInputStream(path); + f.read(fileInArray); + return fileInArray; + } catch (Exception e) { + e.printStackTrace(); + } + return fileInArray; + } +} diff --git a/404.html b/src/main/resources/404.html similarity index 100% rename from 404.html rename to src/main/resources/404.html diff --git a/back_link_icon.txt b/src/main/resources/back_link_icon.txt similarity index 100% rename from back_link_icon.txt rename to src/main/resources/back_link_icon.txt diff --git a/cat.txt b/src/main/resources/cat.txt similarity index 100% rename from cat.txt rename to src/main/resources/cat.txt diff --git a/download_icon.txt b/src/main/resources/download_icon.txt similarity index 100% rename from download_icon.txt rename to src/main/resources/download_icon.txt diff --git a/error.html b/src/main/resources/error.html similarity index 100% rename from error.html rename to src/main/resources/error.html diff --git a/file_icon.txt b/src/main/resources/file_icon.txt similarity index 100% rename from file_icon.txt rename to src/main/resources/file_icon.txt diff --git a/folder_icon.txt b/src/main/resources/folder_icon.txt similarity index 100% rename from folder_icon.txt rename to src/main/resources/folder_icon.txt diff --git a/img.html b/src/main/resources/img.html similarity index 100% rename from img.html rename to src/main/resources/img.html diff --git a/index.html b/src/main/resources/index.html similarity index 100% rename from index.html rename to src/main/resources/index.html diff --git a/login.html b/src/main/resources/login.html similarity index 100% rename from login.html rename to src/main/resources/login.html