From 4346eae92cf9821348f15ff3bfdd1313f3db67ac Mon Sep 17 00:00:00 2001 From: Timothy Prepscius Date: Thu, 1 Aug 2013 13:05:35 -0400 Subject: [PATCH] moves around some files adds the apache-7 --- ext/.gitignore | 1 + ext/apache-tomcat | 1 + java/core/.gitignore | 1 + java/core/lib | 1 + java/core/src/core/server/srp/db/UserDb.java | 479 ++++++++++++++++++ .../src/core/server/srp/db/sql/Catalog.java | 51 ++ .../src/core/server/srp/db/sql/create_tables | 55 ++ .../src/core/server/srp/db/sql/create_user | 1 + .../core/server/srp/db/sql/delete_user.sql | 24 + .../srp/db/sql/expunge_deleted_user.sql | 9 + .../server/srp/db/sql/get_deleted_user.sql | 7 + .../db/sql/get_deleted_user_mail_block.sql | 8 + .../core/server/srp/db/sql/get_last_failure | 8 + java/core/src/core/server/srp/db/sql/get_user | 6 + .../core/server/srp/db/sql/get_user_key_block | 8 + .../server/srp/db/sql/get_user_mail_block | 8 + .../src/core/server/srp/db/sql/mark_failure | 8 + .../core/server/srp/db/sql/room_for_new_user | 4 + .../core/server/srp/db/sql/set_user_key_block | 1 + .../server/srp/db/sql/set_user_mail_block | 1 + .../org/timepedia/exporter/client/Export.java | 9 + .../timepedia/exporter/client/Exportable.java | 10 + .../timepedia/exporter/client/NoExport.java | 10 + 23 files changed, 711 insertions(+) create mode 100644 ext/.gitignore create mode 120000 ext/apache-tomcat create mode 100644 java/core/.gitignore create mode 120000 java/core/lib create mode 100644 java/core/src/core/server/srp/db/UserDb.java create mode 100644 java/core/src/core/server/srp/db/sql/Catalog.java create mode 100644 java/core/src/core/server/srp/db/sql/create_tables create mode 100644 java/core/src/core/server/srp/db/sql/create_user create mode 100644 java/core/src/core/server/srp/db/sql/delete_user.sql create mode 100644 java/core/src/core/server/srp/db/sql/expunge_deleted_user.sql create mode 100644 java/core/src/core/server/srp/db/sql/get_deleted_user.sql create mode 100644 java/core/src/core/server/srp/db/sql/get_deleted_user_mail_block.sql create mode 100644 java/core/src/core/server/srp/db/sql/get_last_failure create mode 100644 java/core/src/core/server/srp/db/sql/get_user create mode 100644 java/core/src/core/server/srp/db/sql/get_user_key_block create mode 100644 java/core/src/core/server/srp/db/sql/get_user_mail_block create mode 100644 java/core/src/core/server/srp/db/sql/mark_failure create mode 100644 java/core/src/core/server/srp/db/sql/room_for_new_user create mode 100644 java/core/src/core/server/srp/db/sql/set_user_key_block create mode 100644 java/core/src/core/server/srp/db/sql/set_user_mail_block create mode 100644 java/core/src/org/timepedia/exporter/client/Export.java create mode 100644 java/core/src/org/timepedia/exporter/client/Exportable.java create mode 100644 java/core/src/org/timepedia/exporter/client/NoExport.java diff --git a/ext/.gitignore b/ext/.gitignore new file mode 100644 index 0000000..28ab4ff --- /dev/null +++ b/ext/.gitignore @@ -0,0 +1 @@ +apache-tomcat-7.0.37/ diff --git a/ext/apache-tomcat b/ext/apache-tomcat new file mode 120000 index 0000000..58b360d --- /dev/null +++ b/ext/apache-tomcat @@ -0,0 +1 @@ +apache-tomcat-7.0.37 \ No newline at end of file diff --git a/java/core/.gitignore b/java/core/.gitignore new file mode 100644 index 0000000..e660fd9 --- /dev/null +++ b/java/core/.gitignore @@ -0,0 +1 @@ +bin/ diff --git a/java/core/lib b/java/core/lib new file mode 120000 index 0000000..dc598c5 --- /dev/null +++ b/java/core/lib @@ -0,0 +1 @@ +../lib \ No newline at end of file diff --git a/java/core/src/core/server/srp/db/UserDb.java b/java/core/src/core/server/srp/db/UserDb.java new file mode 100644 index 0000000..97feee8 --- /dev/null +++ b/java/core/src/core/server/srp/db/UserDb.java @@ -0,0 +1,479 @@ +/** + * Author: Timothy Prepscius + * License: GPLv3 Affero + keep my name in the code! + */ + +package core.server.srp.db; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.SecureRandom; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Timestamp; +import java.util.Date; + +import core.exceptions.CryptoException; +import core.exceptions.PublicMessageException; +import core.exceptions.UserExistsException; +import core.server.srp.db.sql.Catalog; +import core.util.LogOut; +import core.util.Pair; +import core.util.Passwords; +import core.util.Strings; +import core.util.Triple; +import core.util.Base64; + +public abstract class UserDb +{ + static LogOut log = new LogOut(UserDb.class); + + SecureRandom random = new SecureRandom(); + Catalog catalog; + + protected UserDb (Catalog catalog) + { + this.catalog = catalog; + } + + public void testCreateUser (String version, String userName) throws Exception + { + checkRoomForNewUser(); + testIllegalUserName(userName); + + if (getUser(userName)!=null) + throw new UserExistsException(); + } + + public void checkRoomForNewUser () throws Exception + { + Connection connection = openConnection(); + + try + { + PreparedStatement statement = connection.prepareStatement (catalog.getSingle(catalog.ROOM_FOR_NEW_USER)); + ResultSet results = statement.executeQuery(); + if (results.next()) + { + boolean hasRoom = results.getBoolean("room"); + if (hasRoom) + return; + } + + throw new PublicMessageException("No room for new users"); + } + finally + { + closeConnection(connection); + } + + } + + public Integer getUserId (String userName) throws IOException, SQLException + { + return getUser(userName).first; + } + + public void createUser(String version, String userName, byte[] v, byte[] s) throws Exception + { + checkRoomForNewUser(); + testIllegalUserName(userName); + + if (getUser(userName)!=null) + throw new UserExistsException(); + + Connection connection = openConnection(); + + try + { + PreparedStatement statement = connection.prepareStatement (catalog.getSingle(catalog.CREATE_USER)); + statement.setString(1, version); + statement.setString(2, userName); + statement.setString(3, Base64.encode(v)); + statement.setString(4, Base64.encode(s)); + log(statement); + + statement.executeUpdate(); + } + finally + { + closeConnection(connection); + } + } + + + public Pair > getUser (String userName) throws IOException, SQLException + { + Connection connection = openConnection(); + + Pair> result = null; + + try + { + PreparedStatement statement = connection.prepareStatement (catalog.getSingle(catalog.GET_USER)); + statement.setString(1, userName); + log(statement); + + ResultSet results = statement.executeQuery(); + if (results.next()) + { + result = + new Pair >( + results.getInt("id"), + new Triple ( + results.getString("version"), + Base64.decode(results.getString("v")), + Base64.decode(results.getString("s")) + ) + ); + } + } + finally + { + closeConnection(connection); + } + + return result; + } + + public Triple getVVS (String userName) throws IOException, SQLException + { + Triple vvs = getUser(userName).second; + return + new Triple( + vvs.first, + new BigInteger (vvs.second), + new BigInteger (vvs.third) + ); + } + + protected byte[] setMailBlock (String userName, byte[] block) throws IOException, SQLException + { + Integer id = getUser(userName).first; + + Connection connection = openConnection(); + + byte[] result = null; + + try + { + PreparedStatement statement = connection.prepareStatement (catalog.getSingle(catalog.SET_USER_MAIL_BLOCK)); + statement.setInt(1, id); + statement.setString (2, Base64.encode(block)); + log(statement); + + statement.executeUpdate(); + } + finally + { + closeConnection(connection); + } + + return result; + } + + abstract public byte[] setBlock (String userName, byte[] block) throws IOException, SQLException, CryptoException; + abstract public byte[] getBlock (String userName) throws IOException, SQLException, CryptoException; + + protected byte[] setKeyBlock (String userName, byte[] block) throws IOException, SQLException + { + Integer id = getUser(userName).first; + + Connection connection = openConnection(); + + byte[] result = null; + + try + { + PreparedStatement statement = connection.prepareStatement (catalog.getSingle(catalog.SET_USER_KEY_BLOCK)); + statement.setInt(1, id); + statement.setString (2, Base64.encode(block)); + log(statement); + + statement.executeUpdate(); + } + finally + { + closeConnection(connection); + } + + return result; + } + + protected byte[] getMailBlock (String userName) throws IOException, SQLException + { + Connection connection = openConnection(); + + byte[] result = null; + + try + { + PreparedStatement statement = connection.prepareStatement (catalog.getSingle(catalog.GET_USER_MAIL_BLOCK)); + statement.setString(1, userName); + log(statement); + + ResultSet results = statement.executeQuery(); + if (results.next()) + result = Base64.decode(results.getString("block")); + } + finally + { + closeConnection(connection); + } + + return result; + } + + public byte[] getDeletedMailBlock(String userName) throws IOException, SQLException + { + Connection connection = openConnection(); + + byte[] result = null; + + try + { + PreparedStatement statement = connection.prepareStatement (catalog.getSingle(catalog.GET_DELETED_USER_MAIL_BLOCK)); + statement.setString(1, userName); + log(statement); + + ResultSet results = statement.executeQuery(); + if (results.next()) + result = Base64.decode(results.getString("block")); + } + finally + { + closeConnection(connection); + } + + return result; + } + + public String getDeletedUser() throws IOException, SQLException + { + Connection connection = openConnection(); + + String result = null; + + try + { + PreparedStatement statement = connection.prepareStatement (catalog.getSingle(catalog.GET_DELETED_USER)); + log(statement); + + ResultSet results = statement.executeQuery(); + if (results.next()) + result = results.getString("name"); + } + finally + { + closeConnection(connection); + } + + return result; + } + + protected byte[] getKeyBlock (String userName) throws IOException, SQLException + { + Connection connection = openConnection(); + + byte[] result = null; + + try + { + PreparedStatement statement = connection.prepareStatement (catalog.getSingle(catalog.GET_USER_KEY_BLOCK)); + statement.setString(1, userName); + log(statement); + + ResultSet results = statement.executeQuery(); + if (results.next()) + result = Base64.decode(results.getString("block")); + } + finally + { + closeConnection(connection); + } + + return result; + } + + public void ensureTables() throws SQLException, IOException + { + Connection connection = openConnection(); + try + { + for (String sql : catalog.getMulti(catalog.CREATE_TABLES)) + { + PreparedStatement statement = connection.prepareStatement (sql); + log(statement); + statement.executeUpdate(); + } + } + finally + { + closeConnection(connection); + } + } + + public void rateLimitFailure (String userName) throws SQLException, IOException + { + Connection connection = openConnection(); + try + { + PreparedStatement statement = connection.prepareStatement (catalog.getSingle(catalog.GET_LAST_FAILURE)); + statement.setString(1, userName); + log(statement); + + ResultSet rs = statement.executeQuery(); + if (rs.next()) + { + Timestamp timeStamp = rs.getTimestamp("mark"); + Date now = new Date(); + + if (now.getTime() - timeStamp.getTime() < catalog.FAILURE_TIMEOUT_SECONDS * 1000) + throw new PublicMessageException ("Too many failures, try again later."); + } + } + finally + { + closeConnection(connection); + } + } + + public void markFailure (String userName) throws SQLException, IOException + { + Connection connection = openConnection(); + try + { + PreparedStatement statement = connection.prepareStatement (catalog.getSingle(catalog.MARK_FAILURE)); + statement.setString(1, userName); + statement.executeUpdate(); + } + finally + { + closeConnection(connection); + } + + } + + public void deleteUser(String userName) throws IOException, SQLException + { + Connection connection = openConnection(); + try + { + String[] texts = catalog.getMulti(catalog.DELETE); + for (String text : texts) + { + PreparedStatement statement = connection.prepareStatement (text); + statement.setString(1, userName); + + log(statement); + statement.executeUpdate(); + } + } + finally + { + closeConnection(connection); + } + } + + public void expungeUser(String userName) throws IOException, SQLException + { + Connection connection = openConnection(); + try + { + String[] texts = catalog.getMulti(catalog.EXPUNGE); + for (String text : texts) + { + PreparedStatement statement = connection.prepareStatement (text); + statement.setString(1, userName); + statement.executeUpdate(); + } + } + finally + { + closeConnection(connection); + } + } + + public Connection openConnection () throws IOException, SQLException + { + log.debug("Connecting to", catalog.CONNECTION_STRING); + return DriverManager.getConnection(catalog.CONNECTION_STRING, catalog.USER, Passwords.getPasswordFor(catalog.USER)); + } + + public void closeConnection (Connection connection) + { + try + { + if (connection != null) + connection.close(); + } + catch (Exception e) + { + e.printStackTrace(); + } + + } + public void log (Statement sql) + { + System.out.println (sql); + } + + protected void testIllegalUserName(String userName) throws Exception + { + // http://www.ietf.org/rfc/rfc2142.txt + final String[] illegalStartsWith = { + "info", + "marketing", + "sales", + "support", + + "abuse", + "noc", + "security", + + "postmaster", + "hostmaster", + "usenet", + "news", + "webmaster", + "www", + "uucp", + "ftp", + + "admin", + "system", + "root", + "test", + "root", + "hostma", + "web", + "post", + "mail", + }; + + final String[] illegalParts = { + "postmaster", + "webmaster", + "root", + "admin", + "system", + }; + + String username = userName.toLowerCase(); + for (String illegal : illegalParts) + { + if (username.indexOf(illegal) != -1) + throw new Exception("Illegal username"); + } + + for (String illegal : illegalStartsWith) + { + if (username.startsWith(illegal)) + throw new Exception("Illegal username"); + } + } +} diff --git a/java/core/src/core/server/srp/db/sql/Catalog.java b/java/core/src/core/server/srp/db/sql/Catalog.java new file mode 100644 index 0000000..7e4a9cd --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/Catalog.java @@ -0,0 +1,51 @@ +/** + * Author: Timothy Prepscius + * License: GPLv3 Affero + keep my name in the code! + */ + +package core.server.srp.db.sql; + +import java.io.IOException; +import java.sql.SQLException; + +import core.constants.ConstantsServer; +import core.util.Passwords; +import core.util.SqlCatalog; +import core.util.Streams; + + +public final class Catalog extends SqlCatalog +{ + public String CONNECTION_STRING = ConstantsServer.DBCONNECTION_PREFIX + "mail"; + public String USER = "mail"; + + public int FAILURE_TIMEOUT_SECONDS = 60; + + public final String + CREATE_TABLES = "create_tables", + CREATE_USER = "create_user", + GET_USER = "get_user", + GET_USER_MAIL_BLOCK = "get_user_mail_block", + SET_USER_MAIL_BLOCK = "set_user_mail_block", + GET_USER_KEY_BLOCK = "get_user_key_block", + SET_USER_KEY_BLOCK = "set_user_key_block", + GET_LAST_FAILURE = "get_last_failure", + MARK_FAILURE = "mark_failure", + + DELETE = "delete_user.sql", + EXPUNGE = "expunge_deleted_user.sql", + GET_DELETED_USER = "get_deleted_user.sql", + GET_DELETED_USER_MAIL_BLOCK = "get_deleted_user_mail_block.sql", + + ROOM_FOR_NEW_USER = "room_for_new_user"; + + public Catalog () + { + + } + + public String getPassword () throws IOException + { + return Passwords.getPasswordFor(USER); + } +} diff --git a/java/core/src/core/server/srp/db/sql/create_tables b/java/core/src/core/server/srp/db/sql/create_tables new file mode 100644 index 0000000..ecd8894 --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/create_tables @@ -0,0 +1,55 @@ +CREATE TABLE IF NOT EXISTS registry ( + k VARCHAR(50), + v VARCHAR(255), + mark TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (k) +); + +INSERT IGNORE INTO registry (k,v) VALUES ("max_users", "1000"); + +CREATE TABLE IF NOT EXISTS user ( + version VARCHAR(50), + id INTEGER AUTO_INCREMENT, + name VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '', + v TEXT, + s TEXT, + mark TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (name), + UNIQUE KEY (id) +); + +CREATE TABLE IF NOT EXISTS mail_block ( + user_id INTEGER, + block TEXT, + mark TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (user_id) +); + +CREATE TABLE IF NOT EXISTS key_block ( + user_id INTEGER, + block TEXT, + mark TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (user_id) +); + +CREATE TABLE IF NOT EXISTS failure ( + user_id INTEGER, + mark TIMESTAMP, + PRIMARY KEY (user_id) +); + +CREATE TABLE IF NOT EXISTS deleted_user ( + version VARCHAR(50), + id INTEGER AUTO_INCREMENT, + name VARCHAR(255) COLLATE utf8_general_ci NOT NULL DEFAULT '', + v TEXT, + s TEXT, + mark TIMESTAMP NULL DEFAULT NULL, + deleted TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (id) +); + +CREATE TABLE IF NOT EXISTS deleted_mail_block LIKE mail_block; +CREATE TABLE IF NOT EXISTS deleted_key_block LIKE key_block; +DROP TABLE IF EXISTS metadata; + \ No newline at end of file diff --git a/java/core/src/core/server/srp/db/sql/create_user b/java/core/src/core/server/srp/db/sql/create_user new file mode 100644 index 0000000..65db5c4 --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/create_user @@ -0,0 +1 @@ +INSERT INTO user (version, name, v, s) VALUES (?, ?, ?, ?) \ No newline at end of file diff --git a/java/core/src/core/server/srp/db/sql/delete_user.sql b/java/core/src/core/server/srp/db/sql/delete_user.sql new file mode 100644 index 0000000..6e4c106 --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/delete_user.sql @@ -0,0 +1,24 @@ +REPLACE INTO deleted_mail_block + SELECT mail_block.* + FROM mail_block, user + WHERE user.name=? AND mail_block.user_id = user.id; + +REPLACE INTO deleted_key_block + SELECT key_block.* + FROM key_block, user + WHERE user.name=? AND key_block.user_id = user.id; + +REPLACE INTO deleted_user(version, id, name, v, s, mark) + SELECT version, id, name, v, s, mark + FROM user + WHERE user.name=?; + +DELETE mail_block.* + FROM mail_block, user + WHERE user.name=? AND mail_block.user_id = user.id; + +DELETE key_block.* + FROM key_block, user + WHERE user.name=? AND key_block.user_id = user.id; + +DELETE FROM user WHERE user.name=? \ No newline at end of file diff --git a/java/core/src/core/server/srp/db/sql/expunge_deleted_user.sql b/java/core/src/core/server/srp/db/sql/expunge_deleted_user.sql new file mode 100644 index 0000000..9231dae --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/expunge_deleted_user.sql @@ -0,0 +1,9 @@ +DELETE deleted_mail_block.* + FROM deleted_mail_block, deleted_user + WHERE deleted_user.name=? AND deleted_mail_block.user_id = deleted_user.id; + +DELETE deleted_key_block.* + FROM deleted_key_block, deleted_user + WHERE deleted_user.name=? AND deleted_key_block.user_id = deleted_user.id; + +DELETE FROM deleted_user WHERE deleted_user.name=? \ No newline at end of file diff --git a/java/core/src/core/server/srp/db/sql/get_deleted_user.sql b/java/core/src/core/server/srp/db/sql/get_deleted_user.sql new file mode 100644 index 0000000..3dac938 --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/get_deleted_user.sql @@ -0,0 +1,7 @@ +select + * +from + deleted_user +order by + deleted +limit 1 \ No newline at end of file diff --git a/java/core/src/core/server/srp/db/sql/get_deleted_user_mail_block.sql b/java/core/src/core/server/srp/db/sql/get_deleted_user_mail_block.sql new file mode 100644 index 0000000..222f5b7 --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/get_deleted_user_mail_block.sql @@ -0,0 +1,8 @@ +SELECT + deleted_mail_block.* +FROM + deleted_user, + deleted_mail_block +WHERE + deleted_mail_block.user_id = deleted_user.id AND + deleted_user.name = ? \ No newline at end of file diff --git a/java/core/src/core/server/srp/db/sql/get_last_failure b/java/core/src/core/server/srp/db/sql/get_last_failure new file mode 100644 index 0000000..34f1ae7 --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/get_last_failure @@ -0,0 +1,8 @@ +SELECT + failure.mark +FROM + user, + failure +WHERE + user.name = ? AND + failure.user_id = user.id \ No newline at end of file diff --git a/java/core/src/core/server/srp/db/sql/get_user b/java/core/src/core/server/srp/db/sql/get_user new file mode 100644 index 0000000..90c2ac7 --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/get_user @@ -0,0 +1,6 @@ +SELECT + * +FROM + user +WHERE + user.name = ? diff --git a/java/core/src/core/server/srp/db/sql/get_user_key_block b/java/core/src/core/server/srp/db/sql/get_user_key_block new file mode 100644 index 0000000..99494fc --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/get_user_key_block @@ -0,0 +1,8 @@ +SELECT + key_block.* +FROM + user, + key_block +WHERE + key_block.user_id = user.id AND + user.name = ? \ No newline at end of file diff --git a/java/core/src/core/server/srp/db/sql/get_user_mail_block b/java/core/src/core/server/srp/db/sql/get_user_mail_block new file mode 100644 index 0000000..a37c5bd --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/get_user_mail_block @@ -0,0 +1,8 @@ +SELECT + mail_block.* +FROM + user, + mail_block +WHERE + mail_block.user_id = user.id AND + user.name = ? \ No newline at end of file diff --git a/java/core/src/core/server/srp/db/sql/mark_failure b/java/core/src/core/server/srp/db/sql/mark_failure new file mode 100644 index 0000000..baebf51 --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/mark_failure @@ -0,0 +1,8 @@ +REPLACE INTO failure (user_id, mark) +SELECT + id as user_id, + now() as mark +FROM + user +WHERE + name = ? \ No newline at end of file diff --git a/java/core/src/core/server/srp/db/sql/room_for_new_user b/java/core/src/core/server/srp/db/sql/room_for_new_user new file mode 100644 index 0000000..c72a6b4 --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/room_for_new_user @@ -0,0 +1,4 @@ +select + count(*) < (select convert(v, unsigned integer) from registry where k="max_users") as room +from + user \ No newline at end of file diff --git a/java/core/src/core/server/srp/db/sql/set_user_key_block b/java/core/src/core/server/srp/db/sql/set_user_key_block new file mode 100644 index 0000000..4f8e6e8 --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/set_user_key_block @@ -0,0 +1 @@ +REPLACE INTO key_block (user_id, block) VALUES (?, ?) \ No newline at end of file diff --git a/java/core/src/core/server/srp/db/sql/set_user_mail_block b/java/core/src/core/server/srp/db/sql/set_user_mail_block new file mode 100644 index 0000000..3bcd3ab --- /dev/null +++ b/java/core/src/core/server/srp/db/sql/set_user_mail_block @@ -0,0 +1 @@ +REPLACE INTO mail_block (user_id, block) VALUES (?, ?) \ No newline at end of file diff --git a/java/core/src/org/timepedia/exporter/client/Export.java b/java/core/src/org/timepedia/exporter/client/Export.java new file mode 100644 index 0000000..54e27c2 --- /dev/null +++ b/java/core/src/org/timepedia/exporter/client/Export.java @@ -0,0 +1,9 @@ +/** + * Author: Timothy Prepscius + * License: GPLv3 Affero + keep my name in the code! + */ +package org.timepedia.exporter.client; + +public @interface Export +{ +} diff --git a/java/core/src/org/timepedia/exporter/client/Exportable.java b/java/core/src/org/timepedia/exporter/client/Exportable.java new file mode 100644 index 0000000..656688d --- /dev/null +++ b/java/core/src/org/timepedia/exporter/client/Exportable.java @@ -0,0 +1,10 @@ +/** + * Author: Timothy Prepscius + * License: GPLv3 Affero + keep my name in the code! + */ +package org.timepedia.exporter.client; + +public interface Exportable +{ + +} diff --git a/java/core/src/org/timepedia/exporter/client/NoExport.java b/java/core/src/org/timepedia/exporter/client/NoExport.java new file mode 100644 index 0000000..935dd87 --- /dev/null +++ b/java/core/src/org/timepedia/exporter/client/NoExport.java @@ -0,0 +1,10 @@ +/** + * Author: Timothy Prepscius + * License: GPLv3 Affero + keep my name in the code! + */ +package org.timepedia.exporter.client; + +public @interface NoExport +{ + +}