From 5e0dcee64b602007f93d3756437ed595fbbf1a06 Mon Sep 17 00:00:00 2001 From: thetric Date: Thu, 4 Jan 2018 19:23:11 +0100 Subject: feat: remove ftp server a ftp server is out of scope of a diagram creation tool BREAKING CHANGE: plantuml doesn't provide a ftp server anymore --- src/net/sourceforge/plantuml/Option.java | 12 - src/net/sourceforge/plantuml/Run.java | 13 - src/net/sourceforge/plantuml/ftp/FtpConnexion.java | 212 ------------- src/net/sourceforge/plantuml/ftp/FtpLoop.java | 333 --------------------- src/net/sourceforge/plantuml/ftp/FtpServer.java | 128 -------- 5 files changed, 698 deletions(-) delete mode 100644 src/net/sourceforge/plantuml/ftp/FtpConnexion.java delete mode 100644 src/net/sourceforge/plantuml/ftp/FtpLoop.java delete mode 100644 src/net/sourceforge/plantuml/ftp/FtpServer.java diff --git a/src/net/sourceforge/plantuml/Option.java b/src/net/sourceforge/plantuml/Option.java index 3e93a38..9270f59 100644 --- a/src/net/sourceforge/plantuml/Option.java +++ b/src/net/sourceforge/plantuml/Option.java @@ -77,7 +77,6 @@ public class Option { private boolean splash = false; private boolean textProgressBar = false; private int nbThreads = 0; - private int ftpPort = -1; private boolean hideMetadata = false; private boolean checkMetadata = false; private int stdrpt = 0; @@ -359,13 +358,6 @@ public class Option { if (nb.matches("\\d+")) { this.imageIndex = Integer.parseInt(nb); } - } else if (StringUtils.goLowerCase(s).startsWith("-ftp")) { - final int x = s.indexOf(':'); - if (x == -1) { - this.ftpPort = 4242; - } else { - this.ftpPort = Integer.parseInt(s.substring(x + 1)); - } } else if (s.startsWith("-c")) { s = s.substring(2); config.add(StringUtils.eventuallyRemoveStartingAndEndingDoubleQuote(s)); @@ -386,10 +378,6 @@ public class Option { return new StdrptNull(); } - public int getFtpPort() { - return ftpPort; - } - private void addInConfig(final FileReader source) throws IOException { BufferedReader br = null; try { diff --git a/src/net/sourceforge/plantuml/Run.java b/src/net/sourceforge/plantuml/Run.java index 9715273..08735e0 100644 --- a/src/net/sourceforge/plantuml/Run.java +++ b/src/net/sourceforge/plantuml/Run.java @@ -61,7 +61,6 @@ import net.sourceforge.plantuml.code.Transcoder; import net.sourceforge.plantuml.code.TranscoderUtil; import net.sourceforge.plantuml.command.UmlDiagramFactory; import net.sourceforge.plantuml.descdiagram.DescriptionDiagramFactory; -import net.sourceforge.plantuml.ftp.FtpServer; import net.sourceforge.plantuml.objectdiagram.ObjectDiagramFactory; import net.sourceforge.plantuml.png.MetadataTag; import net.sourceforge.plantuml.preproc.Stdlib; @@ -135,11 +134,6 @@ public class Run { return; } - if (option.getFtpPort() != -1) { - goFtp(option); - return; - } - forceOpenJdkResourceLoad(); if (option.getPreprocessorOutputMode() == OptionPreprocOutputMode.CYPHER) { cypher = new LanguageDescriptor().getCypher(); @@ -316,13 +310,6 @@ public class Run { return sb.toString(); } - private static void goFtp(Option option) throws IOException { - final int ftpPort = option.getFtpPort(); - System.err.println("ftpPort=" + ftpPort); - final FtpServer ftpServer = new FtpServer(ftpPort, option.getFileFormatOption().getFileFormat()); - ftpServer.go(); - } - public static void printFonts() { final Font fonts[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getAllFonts(); for (Font f : fonts) { diff --git a/src/net/sourceforge/plantuml/ftp/FtpConnexion.java b/src/net/sourceforge/plantuml/ftp/FtpConnexion.java deleted file mode 100644 index 25d236c..0000000 --- a/src/net/sourceforge/plantuml/ftp/FtpConnexion.java +++ /dev/null @@ -1,212 +0,0 @@ -/* ======================================================================== - * PlantUML : a free UML diagram generator - * ======================================================================== - * - * (C) Copyright 2009-2020, Arnaud Roques - * - * Project Info: http://plantuml.com - * - * If you like this project or if you find it useful, you can support us at: - * - * http://plantuml.com/patreon (only 1$ per month!) - * http://plantuml.com/paypal - * - * This file is part of PlantUML. - * - * PlantUML is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * PlantUML distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - * License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - * - * Original Author: Arnaud Roques - * - * - */ -package net.sourceforge.plantuml.ftp; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import net.sourceforge.plantuml.BlockUml; -import net.sourceforge.plantuml.FileFormat; -import net.sourceforge.plantuml.FileFormatOption; -import net.sourceforge.plantuml.SourceStringReader; -import net.sourceforge.plantuml.core.DiagramDescription; - -public class FtpConnexion { - - private final String user; - private final Map incoming = new HashMap(); - private final Map outgoing = new HashMap(); - private final Set futureOutgoing = new HashSet(); - - private FileFormat fileFormat; - - public FtpConnexion(String user, FileFormat defaultfileFormat) { - this.user = user; - this.fileFormat = defaultfileFormat; - } - - public synchronized void addIncoming(String fileName, String data) { - if (fileName.startsWith("/")) { - throw new IllegalArgumentException(); - } - incoming.put(fileName, data); - } - - public synchronized void futureOutgoing(String fileName) { - outgoing.remove(fileName); - futureOutgoing.add(fileName); - } - - public synchronized Collection getFiles() { - final List result = new ArrayList(incoming.keySet()); - result.addAll(outgoing.keySet()); - result.addAll(futureOutgoing); - return Collections.unmodifiableCollection(result); - } - - public synchronized boolean willExist(String fileName) { - if (incoming.containsKey(fileName)) { - return true; - } - if (outgoing.containsKey(fileName)) { - return true; - } - if (futureOutgoing.contains(fileName)) { - return true; - } - return false; - } - - public synchronized boolean doesExist(String fileName) { - if (incoming.containsKey(fileName)) { - return true; - } - if (outgoing.containsKey(fileName)) { - return true; - } - return false; - } - - public synchronized byte[] getData(String fileName) throws InterruptedException { - if (fileName.startsWith("/")) { - throw new IllegalArgumentException(); - } - final String data = incoming.get(fileName); - if (data != null) { - return data.getBytes(); - } - // do { - // if (willExist(fileName) == false) { - // return null; - // } - final byte data2[] = outgoing.get(fileName); - if (data2 == null) { - return new byte[1]; - } - // if (data2 != null) { - return data2; - // } - // Thread.sleep(200L); - // } while (true); - } - - public synchronized int getSize(String fileName) { - if (fileName.startsWith("/")) { - throw new IllegalArgumentException(); - } - final String data = incoming.get(fileName); - if (data != null) { - return data.length(); - } - final byte data2[] = outgoing.get(fileName); - if (data2 != null) { - return data2.length; - } - return 0; - } - - public void processImage(String fileName) throws IOException { - if (fileName.startsWith("/")) { - throw new IllegalArgumentException(); - } - final String pngFileName = getFutureFileName(fileName); - boolean done = false; - try { - final SourceStringReader sourceStringReader = new SourceStringReader(incoming.get(fileName)); - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - final FileFormat format = getFileFormat(); - final DiagramDescription desc = sourceStringReader.generateDiagramDescription(new FileFormatOption(format)); - final List blocks = sourceStringReader.getBlocks(); - if (blocks.size() > 0) { - blocks.get(0).getDiagram().exportDiagram(baos, 0, new FileFormatOption(format)); - } - final String errorFileName = pngFileName.substring(0, pngFileName.length() - 4) + ".err"; - synchronized (this) { - outgoing.remove(pngFileName); - futureOutgoing.remove(pngFileName); - outgoing.remove(errorFileName); - if (desc != null && desc.getDescription() != null) { - outgoing.put(pngFileName, baos.toByteArray()); - done = true; - if (desc.getDescription().startsWith("(Error)")) { - final ByteArrayOutputStream errBaos = new ByteArrayOutputStream(); - sourceStringReader.outputImage(errBaos, new FileFormatOption(FileFormat.ATXT)); - errBaos.close(); - outgoing.put(errorFileName, errBaos.toByteArray()); - } - } - } - } finally { - if (done == false) { - outgoing.put(pngFileName, new byte[0]); - } - } - } - - public String getFutureFileName(String fileName) { - return getFileFormat().changeName(fileName, 0); - } - - private FileFormat getFileFormat() { - return fileFormat; - } - - public synchronized void delete(String fileName) { - if (fileName.contains("*")) { - incoming.clear(); - outgoing.clear(); - futureOutgoing.clear(); - } else { - incoming.remove(fileName); - outgoing.remove(fileName); - futureOutgoing.add(fileName); - } - } - - public void setFileFormat(FileFormat fileFormat) { - this.fileFormat = fileFormat; - - } - -} diff --git a/src/net/sourceforge/plantuml/ftp/FtpLoop.java b/src/net/sourceforge/plantuml/ftp/FtpLoop.java deleted file mode 100644 index a1d90a5..0000000 --- a/src/net/sourceforge/plantuml/ftp/FtpLoop.java +++ /dev/null @@ -1,333 +0,0 @@ -/* ======================================================================== - * PlantUML : a free UML diagram generator - * ======================================================================== - * - * (C) Copyright 2009-2020, Arnaud Roques - * - * Project Info: http://plantuml.com - * - * If you like this project or if you find it useful, you can support us at: - * - * http://plantuml.com/patreon (only 1$ per month!) - * http://plantuml.com/paypal - * - * This file is part of PlantUML. - * - * PlantUML is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * PlantUML distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - * License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - * - * Original Author: Arnaud Roques - * - * - */ -package net.sourceforge.plantuml.ftp; - -// server - -// FtpServer.java -import java.io.BufferedReader; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.PrintWriter; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.UnknownHostException; -import java.util.Collection; -import java.util.StringTokenizer; - -import net.sourceforge.plantuml.FileFormat; -import net.sourceforge.plantuml.FileUtils; -import net.sourceforge.plantuml.StringUtils; - -class FtpLoop implements Runnable { - enum Mode { - ACTIF, PASSIF - }; - - final private Socket incoming; - final private FtpServer ftpServer; - final private BufferedReader br; - final private PrintWriter pw; - - private FtpConnexion connexion; - private String ipClient = null; - private int port = -1; - private Mode mode; - - public FtpLoop(Socket socket, FtpServer ftpServer) throws IOException { - this.incoming = socket; - this.ftpServer = ftpServer; - this.br = new BufferedReader(new InputStreamReader(incoming.getInputStream(), ftpServer.getCharset())); - this.pw = new PrintWriter(incoming.getOutputStream(), true); - } - - // http://www.ncftp.com/libncftp/doc/ftp_overview.html - // http://www.nsftools.com/tips/RawFTP.htm - // http://www.commentcamarche.net/contents/internet/ftp.php3 - // http://en.wikipedia.org/wiki/List_of_FTP_server_return_codes - // http://www.freefire.org/articles/ftpexample.php - // http://forum.hardware.fr/hfr/Programmation/VB-VBA-VBS/transfert-sujet_59989_1.htm - // http://www.excel-downloads.com/forum/104130-telechargement-ftp-via-vba.html - // http://www.pcreview.co.uk/forums/ftp-vba-macro-t949945.html - private void runInternal() throws IOException, InterruptedException { - localLog("Starting Loop"); - myOut("220 PlantUML"); - while (true) { - final String s = br.readLine(); - localLog("s=" + s); - if (s == null) { - pw.close(); - br.close(); - return; - } - final boolean finish = manage(s); - if (finish) { - return; - } - } - } - - private boolean manage(final String cmd) throws UnknownHostException, IOException, InterruptedException { - final String upper = StringUtils.goUpperCase(cmd); - if (upper.startsWith("USER")) { - myOut("331 Password required"); - final String user = cmd.substring("USER ".length()); - connexion = ftpServer.getFtpConnexion(user); - } else if (upper.startsWith("PASS")) { - myOut("230 Logged in."); - } else if (upper.startsWith("PWD")) { - // myOut("/"); - // myOut("200 OK /"); - myOut("257 \"/\" is current directory."); - } else if (upper.startsWith("CWD")) { - final String dir = cmd.substring("CWD ".length()); - myOut("250 \"" + dir + "\" is new working directory.."); - } else if (upper.startsWith("TYPE")) { - myOut("200 Command okay."); - // localLog("type=" + s); - } else if (upper.startsWith("PORT")) { - mode = Mode.ACTIF; - final StringTokenizer st = new StringTokenizer(cmd, " ,"); - st.nextToken(); - ipClient = st.nextToken() + "." + st.nextToken() + "." + st.nextToken() + "." + st.nextToken(); - port = Integer.parseInt(st.nextToken()) * 256 + Integer.parseInt(st.nextToken()); - // localLog("ipClient=" + ipClient); - // localLog("port=" + port); - - myOut("200 Command okay."); - } else if (upper.startsWith("LIST")) { - if (mode == Mode.ACTIF) { - listActif(); - } else { - listPassif(); - } - } else if (upper.startsWith("STOR")) { - if (mode == Mode.ACTIF) { - storActif(cmd); - } else { - storPassif(cmd); - } - } else if (upper.startsWith("PASV")) { - mode = Mode.PASSIF; - port = ftpServer.getFreePort(); - final int p1 = port / 256; - final int p2 = port % 256; - assert port == p1 * 256 + p2; - localLog("adr=" + incoming.getInetAddress().getHostAddress()); - final String ipServer = ftpServer.getIpServer(); - localLog("server=" + ipServer); - myOut("227 Entering Passive Mode (" + ipServer.replace('.', ',') + "," + p1 + "," + p2 + ")."); - ipClient = ipServer; - } else if (upper.startsWith("RETR")) { - if (mode == Mode.ACTIF) { - retrActif(cmd); - } else { - retrPassif(cmd); - } - } else if (upper.startsWith("DELE")) { - final String file = cmd.substring("DELE ".length()); - connexion.delete(file); - myOut("200 Command okay."); - } else if (upper.startsWith("QUIT")) { - myOut("221 Goodbye."); - return true; - } else if (upper.startsWith("SYST")) { - myOut("215 UNIX Type: L8."); - } else { - myOut("502 Command not implemented."); - } - return false; - } - - private void localLog(String s) { - } - - private void retr(final String fileName, Socket soc) throws UnknownHostException, IOException, InterruptedException { - final OutputStream os = soc.getOutputStream(); - final byte[] data = connexion.getData(fileName); - - if (data != null) { - os.write(data); - } - os.flush(); - os.close(); - soc.close(); - myOut("226 Transfer complete."); - } - - private void retrPassif(final String s) throws UnknownHostException, IOException, InterruptedException { - String fileName = s.substring("STOR ".length()); - fileName = removeStartingsSlash(fileName); - if (connexion.willExist(fileName) == false) { - myOut("550 No such file."); - return; - } - myOut("150 Opening"); - waitForMe(fileName); - final ServerSocket ss = new ServerSocket(port); - final Socket incoming = ss.accept(); - retr(fileName, incoming); - ss.close(); - } - - private void waitForMe(String fileName) throws InterruptedException { - do { - if (connexion.doesExist(fileName)) { - return; - } - Thread.sleep(200L); - } while (true); - } - - private void retrActif(final String s) throws UnknownHostException, IOException, InterruptedException { - String fileName = s.substring("STOR ".length()); - fileName = removeStartingsSlash(fileName); - if (connexion.willExist(fileName) == false) { - myOut("550 No such file."); - return; - } - myOut("150 Opening"); - waitForMe(fileName); - final Socket soc = new Socket(ipClient, port); - retr(fileName, soc); - } - - private void storActif(final String s) throws IOException { - final String fileName = removeStartingsSlash(s.substring("STOR ".length())); - myOut("150 FILE: " + fileName); - final Socket soc = new Socket(ipClient, port); - stor(fileName, soc); - } - - private void storPassif(final String s) throws IOException { - final String fileName = removeStartingsSlash(s.substring("STOR ".length())); - myOut("150 FILE: " + fileName); - final ServerSocket ss = new ServerSocket(port); - final Socket incoming = ss.accept(); - stor(fileName, incoming); - ss.close(); - } - - private String removeStartingsSlash(String fileName) { - while (fileName.startsWith("/")) { - fileName = fileName.substring(1); - } - return fileName; - } - - private void stor(String fileName, Socket socket) throws UnknownHostException, IOException { - final InputStream is = socket.getInputStream(); - final ByteArrayOutputStream baos = new ByteArrayOutputStream(); - FileUtils.copyToStream(is, baos); - - myOut("226 Transfer complete."); - - if ("png".equalsIgnoreCase(fileName)) { - connexion.setFileFormat(FileFormat.PNG); - } else if ("svg".equalsIgnoreCase(fileName)) { - connexion.setFileFormat(FileFormat.SVG); - } else if ("eps".equalsIgnoreCase(fileName)) { - connexion.setFileFormat(FileFormat.EPS); - } - - if (fileName.length() > 3) { - final String data = new String(baos.toByteArray(), ftpServer.getCharset()); - final String pngFileName = connexion.getFutureFileName(fileName); - connexion.futureOutgoing(pngFileName); - connexion.addIncoming(fileName, data); - - ftpServer.processImage(connexion, fileName); - } - } - - private void listActif() throws UnknownHostException, IOException { - myOut("150 Opening ASCII mode data"); - final Socket soc = new Socket(ipClient, port); - list(soc); - } - - private void listPassif() throws UnknownHostException, IOException { - myOut("150 Opening ASCII mode data"); - final ServerSocket ss = new ServerSocket(port); - final Socket incoming = ss.accept(); - list(incoming); - ss.close(); - } - - private void list(final Socket soc) throws IOException { - final PrintWriter listing = new PrintWriter(soc.getOutputStream(), true); - final Collection files = connexion.getFiles(); - if (files.size() > 0) { - int total = 0; - for (String n : files) { - total += (connexion.getSize(n) + 511) / 512; - } - listing.println("total " + total); - // localLog(total); - for (String n : files) { - final String ls = String.format("%10s %4d %-8s %-8s %8d %3s %2s %5s %s", "-rw-rw-r--", 1, "plantuml", - "plantuml", connexion.getSize(n), "Sep", 28, 2006, n); - listing.println(ls); - // localLog(ls); - } - } - listing.flush(); - listing.close(); - soc.close(); - myOut("226 Listing completed."); - } - - private void myOut(String s) { - if (s.indexOf('\t') != -1) { - throw new IllegalArgumentException(); - } - pw.println(s); - pw.flush(); - } - - public void run() { - try { - runInternal(); - } catch (Throwable t) { - t.printStackTrace(); - } - - } - -} diff --git a/src/net/sourceforge/plantuml/ftp/FtpServer.java b/src/net/sourceforge/plantuml/ftp/FtpServer.java deleted file mode 100644 index 53354f6..0000000 --- a/src/net/sourceforge/plantuml/ftp/FtpServer.java +++ /dev/null @@ -1,128 +0,0 @@ -/* ======================================================================== - * PlantUML : a free UML diagram generator - * ======================================================================== - * - * (C) Copyright 2009-2020, Arnaud Roques - * - * Project Info: http://plantuml.com - * - * If you like this project or if you find it useful, you can support us at: - * - * http://plantuml.com/patreon (only 1$ per month!) - * http://plantuml.com/paypal - * - * This file is part of PlantUML. - * - * PlantUML is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * PlantUML distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public - * License for more details. - * - * You should have received a copy of the GNU General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA. - * - * - * Original Author: Arnaud Roques - * - * - */ -package net.sourceforge.plantuml.ftp; - -// server - -// FtpServer.java -import java.io.IOException; -import java.net.ServerSocket; -import java.net.Socket; -import java.util.Map; -import java.util.TreeMap; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import net.sourceforge.plantuml.FileFormat; - -public class FtpServer { - - private final Map datas = new TreeMap(); - private final ExecutorService exeImage = Executors.newFixedThreadPool(2); - private final String charset = "UTF-8"; - - private final int listenPort; - - private int portFree = 10042; - private String ip; - private final FileFormat defaultfileFormat; - - public FtpServer(int listenPort, FileFormat defaultfileFormat) { - this.listenPort = listenPort; - this.defaultfileFormat = defaultfileFormat == null ? FileFormat.PNG : defaultfileFormat; - } - - public synchronized int getFreePort() { - portFree++; - // Log.println("port=" + portFree); - return portFree; - } - - public void go() throws IOException { - final ServerSocket s = new ServerSocket(listenPort); - final ExecutorService exe = Executors.newCachedThreadPool(); - while (true) { - final Socket incoming = s.accept(); - ip = incoming.getLocalAddress().getHostAddress(); - System.out.println("New Client Connected from " + incoming.getInetAddress().getHostName() + "... "); - exe.submit(new FtpLoop(incoming, this)); - } - } - - public String getIpServer() { - return ip; - } - - public synchronized FtpConnexion getFtpConnexion(String user) { - if (user == null) { - throw new IllegalArgumentException(); - } - FtpConnexion data = datas.get(user); - if (data == null) { - data = new FtpConnexion(user, defaultfileFormat); - datas.put(user, data); - } - return data; - } - - public static void main(String[] args) throws IOException { - System.out.println("****************************** ************************************************** "); - System.out.println("****************************** FTP SERVER***********************************"); - - System.out.println("****************************** ************************************************** "); - System.out.println("Server Started..."); - System.out.println("Waiting for connections..."); - System.out.println(" "); - new FtpServer(4242, FileFormat.PNG).go(); - } - - public void processImage(final FtpConnexion connexion, final String name) { - exeImage.submit(new Runnable() { - public void run() { - try { - connexion.processImage(name); - } catch (IOException e) { - e.printStackTrace(); - } - } - }); - } - - public final String getCharset() { - return charset; - } - -} -- cgit v1.2.3