mirror of
https://github.com/moparisthebest/mailiverse
synced 2024-11-24 17:42:16 -05:00
adds another cut of the pgp key ring, adds first cut of internal store so test-setups don't need to use S3
This commit is contained in:
parent
f2e97bec7f
commit
08b39c1af7
@ -92,5 +92,15 @@ You are screwed. Totally screwed. Make backups to a safe place of the mysql se
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
* How should I have done the code to avoid all that nasty call back stuff
|
||||||
|
|
||||||
|
I'm thinking that I should have done a master dispatcher.
|
||||||
|
I should have done all http requests sync not async.
|
||||||
|
And had like 20 threads to do request on and computation.
|
||||||
|
|
||||||
|
Instead of creating all of these callback chains, I should have just dispatched to one of the workers.
|
||||||
|
|
||||||
|
|
||||||
|
* The StoreEnable and CreateBucket should happen behind the scenes.
|
||||||
|
The results should be encrypted with a user supplied key
|
||||||
|
also, CreateBucket could be hacked.
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
if [ -z "$1" ]; then echo "Must supply prod or dev"; exit 0; fi
|
|
||||||
|
|
||||||
V=`date "+%Y%m%d_%H%M%S"`
|
V=`date "+%Y%m%d_%H%M%S"`
|
||||||
M=$1
|
M=prod
|
||||||
|
|
||||||
rsync -avL --delete ../web/WebContent/ www/
|
rsync -avL --delete ../web/WebContent/ www/
|
||||||
rsync -avL --delete ../gwt/war/mailiverse_gwt/ www/mailiverse_gwt/
|
rsync -avL --delete ../gwt/war/mailiverse_gwt/ www/mailiverse_gwt/
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#./server-shutdown tunnel
|
#./server-shutdown tunnel
|
||||||
|
|
||||||
./server-deploy tomcat
|
./server-deploy tomcat
|
||||||
#./server-deploy james
|
#./server-deploy james
|
||||||
./server-deploy postfix
|
./server-deploy postfix-user
|
||||||
./server-deploy mail-user
|
./server-deploy mail-user
|
||||||
./server-deploy mail-key
|
./server-deploy mail-key
|
||||||
./server-deploy tools
|
./server-deploy tools
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
./dev-server-deploy tomcat
|
./dev-server-deploy tomcat
|
||||||
#./dev-server-deploy james
|
#./dev-server-deploy james
|
||||||
./dev-server-deploy postfix
|
./dev-server-deploy postfix-user
|
||||||
./dev-server-deploy mail-user
|
./dev-server-deploy mail-user
|
||||||
./dev-server-deploy mail-key
|
./dev-server-deploy mail-key
|
||||||
./dev-server-deploy tools
|
./dev-server-deploy tools
|
||||||
|
@ -33,8 +33,10 @@ inet_interfaces = all
|
|||||||
inet_protocols = all
|
inet_protocols = all
|
||||||
|
|
||||||
javapipe_destination_recipient_limit = 1
|
javapipe_destination_recipient_limit = 1
|
||||||
virtual_mailbox_domains = hash:/etc/postfix/virtual_domains
|
virtual_mailbox_domains = hash:/etc/postfix/config/virtual_domains
|
||||||
virtual_mailbox_maps = mysql:/etc/postfix/virtual_mailbox_maps.cf
|
virtual_mailbox_maps = mysql:/etc/postfix/config/virtual_mailbox_maps.cf
|
||||||
virtual_transport = javapipe
|
virtual_transport = javapipe
|
||||||
|
|
||||||
|
|
||||||
|
smtp_sasl_auth_enable = yes
|
||||||
|
smtp_sasl_password_maps = mysql:/etc/postfix/config/sasl_password.cf
|
||||||
|
16
deploy/postfix-user/config/sasl_password.cf
Normal file
16
deploy/postfix-user/config/sasl_password.cf
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#
|
||||||
|
# mysql config file for local(8) aliases(5) lookups
|
||||||
|
#
|
||||||
|
|
||||||
|
# The user name and password to log into the mysql server.
|
||||||
|
hosts = 127.0.0.1
|
||||||
|
user = postfix
|
||||||
|
password = postfix
|
||||||
|
|
||||||
|
# The database name on the servers.
|
||||||
|
dbname = postfix
|
||||||
|
|
||||||
|
# For Postfix 2.2 and later The SQL query template.
|
||||||
|
# See mysql_table(5) for details.
|
||||||
|
query = SELECT password FROM user WHERE name='%s'
|
||||||
|
|
1
deploy/postfix-user/resources/passwords/store
Symbolic link
1
deploy/postfix-user/resources/passwords/store
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../passwords/store
|
1
deploy/tomcat/resources/passwords/store
Symbolic link
1
deploy/tomcat/resources/passwords/store
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../passwords/store
|
@ -1,3 +1,7 @@
|
|||||||
|
pushd ~/tomcat/webapps
|
||||||
|
rm -rf Mailiverse
|
||||||
|
popd
|
||||||
|
|
||||||
cd ~/tomcat/bin
|
cd ~/tomcat/bin
|
||||||
|
|
||||||
./shutdown.sh
|
./shutdown.sh
|
||||||
|
1
gwt/src/core/connector/mv/ClientInfoMvStore.java
Symbolic link
1
gwt/src/core/connector/mv/ClientInfoMvStore.java
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../java/core/src/core/connector/mv/ClientInfoMvStore.java
|
1
gwt/src/core/connector/mv/async
Symbolic link
1
gwt/src/core/connector/mv/async
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../java/core/src/core/connector/mv/async
|
1
gwt/src/core/constants/ConstantsMvStore.java
Symbolic link
1
gwt/src/core/constants/ConstantsMvStore.java
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../java/core/src/core/constants/ConstantsMvStore.java
|
@ -5,7 +5,7 @@ import app.service.Main;
|
|||||||
|
|
||||||
public class HttpDelegateFactory
|
public class HttpDelegateFactory
|
||||||
{
|
{
|
||||||
static HttpDelegate create ()
|
static public HttpDelegate create ()
|
||||||
{
|
{
|
||||||
return new JSHttpDelegate(Main.delegate);
|
return new JSHttpDelegate(Main.delegate);
|
||||||
}
|
}
|
||||||
|
1
gwt/src/mail/client/model/PublicKey.java
Symbolic link
1
gwt/src/mail/client/model/PublicKey.java
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../java/core/src/mail/client/model/PublicKey.java
|
1
gwt/src/mail/client/model/PublicKeyRing.java
Symbolic link
1
gwt/src/mail/client/model/PublicKeyRing.java
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../../java/core/src/mail/client/model/PublicKeyRing.java
|
@ -1 +1 @@
|
|||||||
ubuntu
|
root
|
||||||
|
@ -6,6 +6,7 @@ MAIL_PASSWORD=`cat ../passwords/mail`
|
|||||||
MAIL_EXTRA_PASSWORD=`cat ../passwords/mail_extra`
|
MAIL_EXTRA_PASSWORD=`cat ../passwords/mail_extra`
|
||||||
JAMES_PASSWORD=`cat ../passwords/james`
|
JAMES_PASSWORD=`cat ../passwords/james`
|
||||||
CAPTCHA_PASSWORD=`cat ../passwords/captcha`
|
CAPTCHA_PASSWORD=`cat ../passwords/captcha`
|
||||||
|
STORE_PASSWORD=`cat ../passwords/store`
|
||||||
|
|
||||||
M_HOST=$1
|
M_HOST=$1
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ sed \
|
|||||||
-e ''s/MAIL_EXTRA_PASSWORD/$MAIL_EXTRA_PASSWORD/'' \
|
-e ''s/MAIL_EXTRA_PASSWORD/$MAIL_EXTRA_PASSWORD/'' \
|
||||||
-e ''s/JAMES_PASSWORD/$JAMES_PASSWORD/'' \
|
-e ''s/JAMES_PASSWORD/$JAMES_PASSWORD/'' \
|
||||||
-e ''s/CAPTCHA_PASSWORD/$CAPTCHA_PASSWORD/'' \
|
-e ''s/CAPTCHA_PASSWORD/$CAPTCHA_PASSWORD/'' \
|
||||||
|
-e ''s/STORE_PASSWORD/$STORE_PASSWORD/'' \
|
||||||
setup-mysql.sql.template > setup-mysql.sql \
|
setup-mysql.sql.template > setup-mysql.sql \
|
||||||
`
|
`
|
||||||
|
|
||||||
|
@ -1,17 +1,20 @@
|
|||||||
CREATE DATABASE mail DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
|
CREATE DATABASE mail DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
|
||||||
CREATE DATABASE mail_extra DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
|
CREATE DATABASE mail_extra DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
|
||||||
CREATE DATABASE captcha DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
|
CREATE DATABASE captcha DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
|
||||||
|
CREATE DATABASE store DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
|
||||||
CREATE DATABASE postfix DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
|
CREATE DATABASE postfix DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
|
||||||
CREATE DATABASE james CHARACTER SET utf8;
|
CREATE DATABASE james CHARACTER SET utf8;
|
||||||
|
|
||||||
CREATE USER 'mail'@'localhost' IDENTIFIED BY 'MAIL_PASSWORD';
|
CREATE USER 'mail'@'localhost' IDENTIFIED BY 'MAIL_PASSWORD';
|
||||||
CREATE USER 'mail_extra'@'localhost' IDENTIFIED BY 'MAIL_EXTRA_PASSWORD';
|
CREATE USER 'mail_extra'@'localhost' IDENTIFIED BY 'MAIL_EXTRA_PASSWORD';
|
||||||
CREATE USER 'captcha'@'localhost' IDENTIFIED BY 'CAPTCHA_PASSWORD';
|
CREATE USER 'captcha'@'localhost' IDENTIFIED BY 'CAPTCHA_PASSWORD';
|
||||||
|
CREATE USER 'store'@'localhost' IDENTIFIED BY 'STORE_PASSWORD';
|
||||||
CREATE USER 'james'@'localhost' IDENTIFIED BY 'JAMES_PASSWORD';
|
CREATE USER 'james'@'localhost' IDENTIFIED BY 'JAMES_PASSWORD';
|
||||||
CREATE USER 'postfix'@'localhost' IDENTIFIED BY 'postfix';
|
CREATE USER 'postfix'@'localhost' IDENTIFIED BY 'postfix';
|
||||||
|
|
||||||
GRANT ALL PRIVILEGES ON mail.* TO 'mail'@'localhost';
|
GRANT ALL PRIVILEGES ON mail.* TO 'mail'@'localhost';
|
||||||
GRANT ALL PRIVILEGES ON mail_extra.* TO 'mail_extra'@'localhost';
|
GRANT ALL PRIVILEGES ON mail_extra.* TO 'mail_extra'@'localhost';
|
||||||
GRANT ALL PRIVILEGES ON captcha.* TO 'captcha'@'localhost';
|
GRANT ALL PRIVILEGES ON captcha.* TO 'captcha'@'localhost';
|
||||||
|
GRANT ALL PRIVILEGES ON store.* TO 'store'@'localhost';
|
||||||
GRANT ALL PRIVILEGES ON james.* TO 'james'@'localhost';
|
GRANT ALL PRIVILEGES ON james.* TO 'james'@'localhost';
|
||||||
GRANT ALL PRIVILEGES ON postfix.* TO 'postfix'@'localhost';
|
GRANT ALL PRIVILEGES ON postfix.* TO 'postfix'@'localhost';
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
set -x
|
set -x
|
||||||
|
|
||||||
|
apt-get update
|
||||||
echo "1" | apt-get install postfix postfix-mysql postfix-pcre --yes
|
echo "1" | apt-get install postfix postfix-mysql postfix-pcre --yes
|
||||||
|
apt-get install sasl2-bin --yes
|
||||||
|
|
||||||
cp sudoers.d-postfix-user /etc/sudoers.d/postfix-user
|
cp sudoers.d-postfix-user /etc/sudoers.d/postfix-user
|
||||||
chmod 0440 /etc/sudoers.d/postfix-user
|
chmod 0440 /etc/sudoers.d/postfix-user
|
||||||
@ -11,7 +13,6 @@ rm master.cf
|
|||||||
|
|
||||||
ln -fs /home/postfix-user/config/main.cf
|
ln -fs /home/postfix-user/config/main.cf
|
||||||
ln -fs /home/postfix-user/config/master.cf
|
ln -fs /home/postfix-user/config/master.cf
|
||||||
#ln -fs /home/postfix-user/config/virtual_domains.pcre
|
ln -fs /home/postfix-user/config
|
||||||
ln -fs /home/postfix-user/config/virtual_domains
|
|
||||||
ln -fs /home/postfix-user/config/virtual_mailbox_maps.cf
|
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@ import core.callback.Callback;
|
|||||||
import core.callback.CallbackChain;
|
import core.callback.CallbackChain;
|
||||||
import core.callback.CallbackDefault;
|
import core.callback.CallbackDefault;
|
||||||
import core.callback.CallbackWithVariables;
|
import core.callback.CallbackWithVariables;
|
||||||
|
import core.constants.ConstantsMvStore;
|
||||||
import core.constants.ConstantsS3;
|
import core.constants.ConstantsS3;
|
||||||
import core.constants.ConstantsEnvironmentKeys;
|
import core.constants.ConstantsEnvironmentKeys;
|
||||||
import core.constants.ConstantsClient;
|
import core.constants.ConstantsClient;
|
||||||
@ -125,7 +126,7 @@ public class JSSignUp implements Exportable, SRPClientListener
|
|||||||
}
|
}
|
||||||
|
|
||||||
static class SignUpInfo {
|
static class SignUpInfo {
|
||||||
public static enum Storage { Mailiverse, Dropbox };
|
public static enum Storage { S3, Mailiverse, Dropbox };
|
||||||
|
|
||||||
String name, password, captchaToken;
|
String name, password, captchaToken;
|
||||||
Environment serverEnvironment, clientEnvironment, completeEnvironment;
|
Environment serverEnvironment, clientEnvironment, completeEnvironment;
|
||||||
@ -145,6 +146,8 @@ public class JSSignUp implements Exportable, SRPClientListener
|
|||||||
String awsWriteAccessKey, awsWriteSecretKey;
|
String awsWriteAccessKey, awsWriteSecretKey;
|
||||||
String awsReadWriteAccessKey, awsReadWriteSecretKey;
|
String awsReadWriteAccessKey, awsReadWriteSecretKey;
|
||||||
|
|
||||||
|
String mvAccessKey, mvSecretKey;
|
||||||
|
|
||||||
String smtpPassword;
|
String smtpPassword;
|
||||||
byte[] rsaPublicKey;
|
byte[] rsaPublicKey;
|
||||||
byte[] rsaPrivateKey;
|
byte[] rsaPrivateKey;
|
||||||
@ -180,10 +183,15 @@ public class JSSignUp implements Exportable, SRPClientListener
|
|||||||
this.dropboxAuthSecret = authSecret;
|
this.dropboxAuthSecret = authSecret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void initializeStorageMailiverse (String storageRegion)
|
void initializeStorageS3 (String storageRegion)
|
||||||
|
{
|
||||||
|
this.storage = Storage.S3;
|
||||||
|
this.storageRegion = storageRegion;
|
||||||
|
}
|
||||||
|
|
||||||
|
void initializeStorageMailiverse ()
|
||||||
{
|
{
|
||||||
this.storage = Storage.Mailiverse;
|
this.storage = Storage.Mailiverse;
|
||||||
this.storageRegion = storageRegion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDropboxInfo (String userToken, String userSecret)
|
public void setDropboxInfo (String userToken, String userSecret)
|
||||||
@ -205,6 +213,13 @@ public class JSSignUp implements Exportable, SRPClientListener
|
|||||||
this.awsReadWriteSecretKey = awsReadWriteSecretKey;
|
this.awsReadWriteSecretKey = awsReadWriteSecretKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setMailiverseInfo (String mvAccessKey, String mvSecretKey)
|
||||||
|
{
|
||||||
|
this.mvAccessKey = mvAccessKey;
|
||||||
|
this.mvSecretKey = mvSecretKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void calculateRSA (Callback callback) throws NoSuchAlgorithmException
|
public void calculateRSA (Callback callback) throws NoSuchAlgorithmException
|
||||||
{
|
{
|
||||||
new CryptorRSAFactory().generate(2048, new CallbackDefault() {
|
new CryptorRSAFactory().generate(2048, new CallbackDefault() {
|
||||||
@ -347,13 +362,65 @@ public class JSSignUp implements Exportable, SRPClientListener
|
|||||||
completeEnvironment.addChildEnvironment(ConstantsEnvironmentKeys.CLIENT_ENVIRONMENT, clientEnvironment);
|
completeEnvironment.addChildEnvironment(ConstantsEnvironmentKeys.CLIENT_ENVIRONMENT, clientEnvironment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void calculateEnvironmentMailiverse ()
|
||||||
|
{
|
||||||
|
String handler = ConstantsStorage.HANDLER_MV;
|
||||||
|
String prefix = handler + "/";
|
||||||
|
|
||||||
|
serverEnvironment = new Environment();
|
||||||
|
serverEnvironment.put(ConstantsEnvironmentKeys.CONFIGURATION_VERSION, ConstantsVersion.CONFIGURATION);
|
||||||
|
serverEnvironment.put(ConstantsEnvironmentKeys.HANDLER, handler);
|
||||||
|
serverEnvironment.put(ConstantsEnvironmentKeys.SMTP_PASSWORD, smtpPassword);
|
||||||
|
serverEnvironment.put(prefix + ConstantsMvStore.AccessKeyId, mvAccessKey);
|
||||||
|
serverEnvironment.put(prefix + ConstantsMvStore.SecretKey, mvSecretKey);
|
||||||
|
serverEnvironment.put(
|
||||||
|
ConstantsEnvironmentKeys.PUBLIC_ENCRYPTION_KEY,
|
||||||
|
Base64.encode(rsaPublicKey)
|
||||||
|
);
|
||||||
|
serverEnvironment.put(
|
||||||
|
ConstantsEnvironmentKeys.PGP_PUBLIC_KEY,
|
||||||
|
Base64.encode(pgpPublicKey)
|
||||||
|
);
|
||||||
|
|
||||||
|
clientEnvironment = new Environment();
|
||||||
|
clientEnvironment.put(ConstantsEnvironmentKeys.CONFIGURATION_VERSION, ConstantsVersion.CONFIGURATION);
|
||||||
|
clientEnvironment.put(ConstantsEnvironmentKeys.HANDLER, handler);
|
||||||
|
clientEnvironment.put(ConstantsEnvironmentKeys.SMTP_PASSWORD, smtpPassword);
|
||||||
|
clientEnvironment.put(prefix + ConstantsMvStore.AccessKeyId, mvAccessKey);
|
||||||
|
clientEnvironment.put(prefix + ConstantsMvStore.SecretKey, mvSecretKey);
|
||||||
|
clientEnvironment.put(
|
||||||
|
ConstantsEnvironmentKeys.PUBLIC_ENCRYPTION_KEY,
|
||||||
|
Base64.encode(rsaPublicKey)
|
||||||
|
);
|
||||||
|
clientEnvironment.put(
|
||||||
|
ConstantsEnvironmentKeys.PRIVATE_DECRYPTION_KEY,
|
||||||
|
Base64.encode(rsaPrivateKey)
|
||||||
|
);
|
||||||
|
clientEnvironment.put(
|
||||||
|
ConstantsEnvironmentKeys.PGP_PUBLIC_KEY,
|
||||||
|
Base64.encode(pgpPublicKey)
|
||||||
|
);
|
||||||
|
clientEnvironment.put(
|
||||||
|
ConstantsEnvironmentKeys.PGP_PRIVATE_KEY,
|
||||||
|
Base64.encode(pgpPrivateKey)
|
||||||
|
);
|
||||||
|
|
||||||
|
completeEnvironment = new Environment();
|
||||||
|
completeEnvironment.put(ConstantsEnvironmentKeys.CONFIGURATION_VERSION, ConstantsVersion.CONFIGURATION);
|
||||||
|
completeEnvironment.addChildEnvironment(ConstantsEnvironmentKeys.SERVER_ENVIRONMENT, serverEnvironment);
|
||||||
|
completeEnvironment.addChildEnvironment(ConstantsEnvironmentKeys.CLIENT_ENVIRONMENT, clientEnvironment);
|
||||||
|
}
|
||||||
|
|
||||||
public void calculateEnvironment ()
|
public void calculateEnvironment ()
|
||||||
{
|
{
|
||||||
if (storage == Storage.Dropbox)
|
if (storage == Storage.Dropbox)
|
||||||
calculateEnvironmentDropbox();
|
calculateEnvironmentDropbox();
|
||||||
else
|
else
|
||||||
if (storage == Storage.Mailiverse)
|
if (storage == Storage.S3)
|
||||||
calculateEnvironmentAWS();
|
calculateEnvironmentAWS();
|
||||||
|
else
|
||||||
|
if (storage == Storage.Mailiverse)
|
||||||
|
calculateEnvironmentMailiverse();
|
||||||
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -376,8 +443,11 @@ public class JSSignUp implements Exportable, SRPClientListener
|
|||||||
if (storage.equals("dropbox"))
|
if (storage.equals("dropbox"))
|
||||||
info.intializeStorageDropbox(ConstantsClient.DROPBOX_APPKEY, ConstantsClient.DROPBOX_APPSECRET, dropboxUserKey, dropboxUserSecret);
|
info.intializeStorageDropbox(ConstantsClient.DROPBOX_APPKEY, ConstantsClient.DROPBOX_APPSECRET, dropboxUserKey, dropboxUserSecret);
|
||||||
else
|
else
|
||||||
|
if (storage.equals("s3"))
|
||||||
|
info.initializeStorageS3(JSON_.getString(JSON_.parse(storageInfo), "region"));
|
||||||
|
else
|
||||||
if (storage.equals("mailiverse"))
|
if (storage.equals("mailiverse"))
|
||||||
info.initializeStorageMailiverse(JSON_.getString(JSON_.parse(storageInfo), "region"));
|
info.initializeStorageMailiverse();
|
||||||
|
|
||||||
CallbackChain signUpChain = new CallbackChain();
|
CallbackChain signUpChain = new CallbackChain();
|
||||||
|
|
||||||
@ -489,6 +559,9 @@ public class JSSignUp implements Exportable, SRPClientListener
|
|||||||
|
|
||||||
protected void signUp_step_requestAccess (SignUpInfo info, Callback callback)
|
protected void signUp_step_requestAccess (SignUpInfo info, Callback callback)
|
||||||
{
|
{
|
||||||
|
if (info.storage == SignUpInfo.Storage.S3)
|
||||||
|
signUp_step_requestS3Bucket(info, callback);
|
||||||
|
else
|
||||||
if (info.storage == SignUpInfo.Storage.Mailiverse)
|
if (info.storage == SignUpInfo.Storage.Mailiverse)
|
||||||
signUp_step_requestMailiverseBucket(info, callback);
|
signUp_step_requestMailiverseBucket(info, callback);
|
||||||
else
|
else
|
||||||
@ -496,9 +569,9 @@ public class JSSignUp implements Exportable, SRPClientListener
|
|||||||
signUp_step_requestDropboxAccessToken(info, callback);
|
signUp_step_requestDropboxAccessToken(info, callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void signUp_step_requestMailiverseBucket (SignUpInfo info, Callback callback)
|
protected void signUp_step_requestS3Bucket (SignUpInfo info, Callback callback)
|
||||||
{
|
{
|
||||||
log.debug("signUp_step_requestMailiverseBucket");
|
log.debug("signUp_step_requestS3Bucket");
|
||||||
|
|
||||||
String url =
|
String url =
|
||||||
ConstantsClient.WEB_SERVER_TOMCAT + "CreateBucket" +
|
ConstantsClient.WEB_SERVER_TOMCAT + "CreateBucket" +
|
||||||
@ -509,7 +582,7 @@ public class JSSignUp implements Exportable, SRPClientListener
|
|||||||
new CallbackDefault(info) {
|
new CallbackDefault(info) {
|
||||||
public void onSuccess(Object... arguments)
|
public void onSuccess(Object... arguments)
|
||||||
{
|
{
|
||||||
log.debug("signUp_step_requestMailiverseBucket callback");
|
log.debug("signUp_step_requestS3Bucket callback");
|
||||||
SignUpInfo info = V(0);
|
SignUpInfo info = V(0);
|
||||||
String response = (String)arguments[0];
|
String response = (String)arguments[0];
|
||||||
String awsBucketName=null, awsBucketRegion=null,
|
String awsBucketName=null, awsBucketRegion=null,
|
||||||
@ -549,6 +622,45 @@ public class JSSignUp implements Exportable, SRPClientListener
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void signUp_step_requestMailiverseBucket (SignUpInfo info, Callback callback)
|
||||||
|
{
|
||||||
|
log.debug("signUp_step_requestMailiverseBucket");
|
||||||
|
|
||||||
|
String url =
|
||||||
|
ConstantsClient.WEB_SERVER_TOMCAT + "StoreEnable" +
|
||||||
|
"?email=" + info.name + "&captcha=" + info.captchaToken;
|
||||||
|
|
||||||
|
JSHttpDelegate http = new JSHttpDelegate(main.delegate);
|
||||||
|
http.execute(HttpDelegate.GET, url, null, false, false, null,
|
||||||
|
new CallbackDefault(info) {
|
||||||
|
public void onSuccess(Object... arguments)
|
||||||
|
{
|
||||||
|
log.debug("signUp_step_requestMailiverseBucket callback");
|
||||||
|
SignUpInfo info = V(0);
|
||||||
|
String response = (String)arguments[0];
|
||||||
|
String mvAccessKey=null, mvSecretKey=null;
|
||||||
|
|
||||||
|
String[] parts = response.split("&");
|
||||||
|
for (String part : parts)
|
||||||
|
{
|
||||||
|
String[] keyValue = part.split("!");
|
||||||
|
String key = keyValue[0];
|
||||||
|
String value = keyValue[1];
|
||||||
|
|
||||||
|
if (key.equalsIgnoreCase(ConstantsMvStore.AccessKeyId))
|
||||||
|
mvAccessKey = value;
|
||||||
|
else
|
||||||
|
if (key.equalsIgnoreCase(ConstantsMvStore.SecretKey))
|
||||||
|
mvSecretKey = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
info.setMailiverseInfo(mvAccessKey, mvSecretKey);
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}.setReturn(callback)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
protected void signUp_step_requestDropboxAccessToken (SignUpInfo info, Callback callback)
|
protected void signUp_step_requestDropboxAccessToken (SignUpInfo info, Callback callback)
|
||||||
{
|
{
|
||||||
log.debug("signUp_step_requestAccessToken");
|
log.debug("signUp_step_requestAccessToken");
|
||||||
|
@ -79,4 +79,16 @@ public class CallbackSync
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void checkException () throws Exception
|
||||||
|
{
|
||||||
|
if (results != null && results.length > 0)
|
||||||
|
{
|
||||||
|
if (results[0] instanceof Exception)
|
||||||
|
{
|
||||||
|
Exception e = (Exception)results[0];
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
33
java/core/src/core/connector/mv/ClientInfoMvStore.java
Normal file
33
java/core/src/core/connector/mv/ClientInfoMvStore.java
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
package core.connector.mv;
|
||||||
|
|
||||||
|
import core.constants.ConstantsClient;
|
||||||
|
import core.constants.ConstantsMvStore;
|
||||||
|
import core.util.Environment;
|
||||||
|
|
||||||
|
public class ClientInfoMvStore
|
||||||
|
{
|
||||||
|
private String accessId;
|
||||||
|
private String secretKey;
|
||||||
|
|
||||||
|
public ClientInfoMvStore (Environment e)
|
||||||
|
{
|
||||||
|
accessId = e.checkGet(ConstantsMvStore.AccessKeyId);
|
||||||
|
secretKey = e.checkGet(ConstantsMvStore.SecretKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBucketEndpoint ()
|
||||||
|
{
|
||||||
|
return ConstantsClient.SERVER_TOMCAT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAccessId()
|
||||||
|
{
|
||||||
|
return accessId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSecretKey()
|
||||||
|
{
|
||||||
|
return secretKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
346
java/core/src/core/connector/mv/async/ConnectorMvStore.java
Normal file
346
java/core/src/core/connector/mv/async/ConnectorMvStore.java
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
package core.connector.mv.async;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import core.callback.Callback;
|
||||||
|
import core.callback.CallbackDefault;
|
||||||
|
import core.callback.CallbackWithVariables;
|
||||||
|
import core.connector.FileInfo;
|
||||||
|
import core.connector.async.AsyncStoreConnectorHelper;
|
||||||
|
import core.connector.mv.ClientInfoMvStore;
|
||||||
|
import core.connector.s3.async.S3Connector;
|
||||||
|
import core.crypt.HashSha256;
|
||||||
|
import core.crypt.HmacSha1;
|
||||||
|
import core.util.Base64;
|
||||||
|
import core.util.DateFormat;
|
||||||
|
import core.util.FastRandom;
|
||||||
|
import core.util.HttpDelegate;
|
||||||
|
import core.util.JSON_;
|
||||||
|
import core.util.LogNull;
|
||||||
|
import core.util.Strings;
|
||||||
|
import core.util.XML;
|
||||||
|
|
||||||
|
public class ConnectorMvStore extends AsyncStoreConnectorHelper
|
||||||
|
{
|
||||||
|
static LogNull log = new LogNull(S3Connector.class);
|
||||||
|
final int LOCK_INTERVAL = 10 * 1000;
|
||||||
|
|
||||||
|
ClientInfoMvStore info;
|
||||||
|
HttpDelegate httpDelegate;
|
||||||
|
|
||||||
|
HmacSha1 mac;
|
||||||
|
static FastRandom fastRandom = new FastRandom();
|
||||||
|
|
||||||
|
protected String createUrlPrefix ()
|
||||||
|
{
|
||||||
|
return "https://" + info.getBucketEndpoint() + "/";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String createRandomPostfix ()
|
||||||
|
{
|
||||||
|
return "random=" + fastRandom.nextLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method converts AWSSecretKey into crypto instance.
|
||||||
|
protected void setKey(String secretKey) throws Exception
|
||||||
|
{
|
||||||
|
mac = new HmacSha1(Base64.decode(secretKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method creates S3 signature for a given String.
|
||||||
|
protected String sign(String data) throws Exception
|
||||||
|
{
|
||||||
|
// Signed String must be BASE64 encoded.
|
||||||
|
byte[] signBytes = mac.mac(Strings.toBytes(data));
|
||||||
|
String signature = Base64.encode(signBytes);
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String format(String format, Date date)
|
||||||
|
{
|
||||||
|
DateFormat df = new DateFormat(format);
|
||||||
|
String dateString = df.format(date, 0) + " GMT";
|
||||||
|
return dateString;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String[][] makeHeaders (String keyId, String method, String contentMD5, String contentType, int contentLength, Date date, String resource) throws Exception
|
||||||
|
{
|
||||||
|
String fmt = "EEE, dd MMM yyyy HH:mm:ss";
|
||||||
|
String dateString = format(fmt, date);
|
||||||
|
|
||||||
|
// Generate signature
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
buf.append(method).append("\n");
|
||||||
|
buf.append(contentMD5).append("\n");
|
||||||
|
buf.append(contentType).append("\n");
|
||||||
|
buf.append("\n"); // empty real date header
|
||||||
|
buf.append(dateString).append("\n");
|
||||||
|
buf.append(resource);
|
||||||
|
|
||||||
|
log.debug("Signing:{" + buf.toString() + "}");
|
||||||
|
String signature = sign(buf.toString());
|
||||||
|
|
||||||
|
String[][] headers;
|
||||||
|
if (method.equals("PUT"))
|
||||||
|
{
|
||||||
|
headers = new String[][] {
|
||||||
|
{"X-Mv-Date" , dateString },
|
||||||
|
{"Content-Type", contentType },
|
||||||
|
{"Content-Length", ""+contentLength },
|
||||||
|
{"Authorization", "MV " + keyId + ":" + signature }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
headers = new String[][] {
|
||||||
|
{"X-Mv-Date" , dateString },
|
||||||
|
{"Authorization", "MV " + keyId + ":" + signature }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConnectorMvStore(ClientInfoMvStore clientInfo, HttpDelegate httpDelegate) throws Exception
|
||||||
|
{
|
||||||
|
this.info = clientInfo;
|
||||||
|
this.httpDelegate = httpDelegate;
|
||||||
|
|
||||||
|
setKey (info.getSecretKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
long toVersionFromString (String s) throws Exception
|
||||||
|
{
|
||||||
|
HashSha256 hash = new HashSha256();
|
||||||
|
byte[] result = hash.hash(Strings.toBytes(s));
|
||||||
|
|
||||||
|
long l =
|
||||||
|
((long)result[0]) |
|
||||||
|
((long)result[1] << 8) |
|
||||||
|
((long)result[2] << 16) |
|
||||||
|
((long)result[3] << 24);
|
||||||
|
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void listDirectoryFinished (List<FileInfo> files, Callback callback, String path, Object... arguments)
|
||||||
|
{
|
||||||
|
log.debug("listDirectoryFinished");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
if (arguments[0] instanceof Exception)
|
||||||
|
throw (Exception)arguments[0];
|
||||||
|
|
||||||
|
String result = (String)arguments[0];
|
||||||
|
log.trace(result);
|
||||||
|
|
||||||
|
DateFormat dateTimeFormat = new DateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z' Z");
|
||||||
|
|
||||||
|
Object doc = JSON_.parse(result);
|
||||||
|
Object nodes = JSON_.getArray(doc, "contents");
|
||||||
|
for (int i=0; i<JSON_.size(nodes); ++i)
|
||||||
|
{
|
||||||
|
Object currentNode = JSON_.get(nodes, i);
|
||||||
|
|
||||||
|
String keyNode = JSON_.getString(currentNode, "path");
|
||||||
|
String etagNode = JSON_.getString(currentNode, "version");
|
||||||
|
long sizeNode = JSON_.getInt(currentNode, "size");
|
||||||
|
String lastModifiedNode = JSON_.getString(currentNode, "date");
|
||||||
|
|
||||||
|
log.trace(keyNode, etagNode, sizeNode, lastModifiedNode);
|
||||||
|
|
||||||
|
String fullPath = keyNode;
|
||||||
|
String relativePath = fullPath.substring(path.length());
|
||||||
|
|
||||||
|
FileInfo fi = new FileInfo(
|
||||||
|
fullPath,
|
||||||
|
relativePath,
|
||||||
|
sizeNode,
|
||||||
|
dateTimeFormat.parse(lastModifiedNode),
|
||||||
|
etagNode
|
||||||
|
);
|
||||||
|
|
||||||
|
files.add(fi);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (JSON_.getBoolean(doc, "isTruncated"))
|
||||||
|
{
|
||||||
|
log.debug("results were truncated, requesting more...");
|
||||||
|
listIterative(files, path, callback);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log.debug("results were complete, invoking callback");
|
||||||
|
|
||||||
|
Collections.sort(files, new FileInfo.SortByDateAscending());
|
||||||
|
for (FileInfo i : files)
|
||||||
|
log.trace ("path: ", i.path, " date:", i.date);
|
||||||
|
|
||||||
|
callback.invoke(files);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
|
callback.invoke(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void list(String path, Callback callback)
|
||||||
|
{
|
||||||
|
listIterative(new ArrayList<FileInfo>(), path, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void listIterative(List<FileInfo> files, String path, Callback callback)
|
||||||
|
{
|
||||||
|
log.debug("listDirectory",path);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String url =
|
||||||
|
createUrlPrefix() +
|
||||||
|
"StoreList?Resource=" + path + "&max-keys=1000" +
|
||||||
|
(!files.isEmpty() ? ("&marker=" + files.get(files.size()-1).path) : "") +
|
||||||
|
"&" + createRandomPostfix();
|
||||||
|
|
||||||
|
log.debug(url);
|
||||||
|
|
||||||
|
String[][] headers = makeHeaders (
|
||||||
|
info.getAccessId(), "GET", "", "", 0, new Date(), path
|
||||||
|
);
|
||||||
|
|
||||||
|
httpDelegate.execute (HttpDelegate.GET, url, headers, false, false, null,
|
||||||
|
new CallbackWithVariables(files, callback, path) {
|
||||||
|
@Override
|
||||||
|
public void invoke(Object... arguments)
|
||||||
|
{
|
||||||
|
List<FileInfo> files = V(0);
|
||||||
|
Callback callback = V(1);
|
||||||
|
String path = V(2);
|
||||||
|
listDirectoryFinished(files, callback, path, arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
e.printStackTrace();
|
||||||
|
|
||||||
|
callback.invoke(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createDirectory(String path, Callback callback)
|
||||||
|
{
|
||||||
|
log.debug("createDirectory",path);
|
||||||
|
callback.invoke(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void get(String path, Callback callback)
|
||||||
|
{
|
||||||
|
log.debug("get",path);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String url =
|
||||||
|
createUrlPrefix() +
|
||||||
|
"StoreGet?Resource=" + path +
|
||||||
|
"&" + createRandomPostfix();
|
||||||
|
|
||||||
|
log.debug(url);
|
||||||
|
|
||||||
|
String[][] headers = makeHeaders (
|
||||||
|
info.getAccessId(), "GET", "", "", 0, new Date(), path
|
||||||
|
);
|
||||||
|
|
||||||
|
httpDelegate.execute(HttpDelegate.GET, url, headers, false, true, null, grabVersion_(true).setReturn(callback));
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
callback.invoke(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Callback grabVersion_(boolean includeResponseData)
|
||||||
|
{
|
||||||
|
return new CallbackDefault(includeResponseData) {
|
||||||
|
public void onSuccess(Object... arguments) throws Exception {
|
||||||
|
|
||||||
|
boolean includeResponseData = (Boolean)V(0);
|
||||||
|
String[][] headers = (String[][])arguments[1];
|
||||||
|
|
||||||
|
for (String[] pair : headers)
|
||||||
|
{
|
||||||
|
if (pair[0].equals("Version"))
|
||||||
|
{
|
||||||
|
if (includeResponseData)
|
||||||
|
next(arguments[0], pair[1]);
|
||||||
|
else
|
||||||
|
next(pair[1]);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("No ETag Response header");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(String path, byte[] contents, Callback callback)
|
||||||
|
{
|
||||||
|
log.debug("put",path);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String url =
|
||||||
|
createUrlPrefix() +
|
||||||
|
"StorePut?Resource=" + path +
|
||||||
|
"&" + createRandomPostfix();
|
||||||
|
|
||||||
|
log.debug(url);
|
||||||
|
|
||||||
|
String[][] headers = makeHeaders (
|
||||||
|
info.getAccessId(), "PUT", "", "application/octet-stream", contents.length, new Date(), path
|
||||||
|
);
|
||||||
|
|
||||||
|
httpDelegate.execute(HttpDelegate.PUT, url, headers, true, false, contents, grabVersion_(false).setReturn(callback));
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
callback.invoke(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(String path, Callback callback)
|
||||||
|
{
|
||||||
|
log.debug("delete",path);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String url =
|
||||||
|
createUrlPrefix() +
|
||||||
|
"StoreDelete?Resource=" + path +
|
||||||
|
"&" + createRandomPostfix();
|
||||||
|
|
||||||
|
log.debug(url);
|
||||||
|
|
||||||
|
String[][] headers = makeHeaders (
|
||||||
|
info.getAccessId(), "DELETE", "", "", 0, new Date(), path
|
||||||
|
);
|
||||||
|
|
||||||
|
httpDelegate.execute(HttpDelegate.DELETE, url, headers, true, false, null, callback);
|
||||||
|
}
|
||||||
|
catch (Throwable e)
|
||||||
|
{
|
||||||
|
callback.invoke(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
137
java/core/src/core/connector/mv/sync/ConnectorMvStore.java
Normal file
137
java/core/src/core/connector/mv/sync/ConnectorMvStore.java
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
package core.connector.mv.sync;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import core.callback.CallbackSync;
|
||||||
|
import core.connector.ConnectorException;
|
||||||
|
import core.connector.FileInfo;
|
||||||
|
import core.connector.mv.ClientInfoMvStore;
|
||||||
|
import core.connector.sync.StoreConnector;
|
||||||
|
import core.util.HttpDelegateFactory;
|
||||||
|
|
||||||
|
public class ConnectorMvStore implements StoreConnector
|
||||||
|
{
|
||||||
|
private ClientInfoMvStore clientInfo;
|
||||||
|
private core.connector.mv.async.ConnectorMvStore connector;
|
||||||
|
|
||||||
|
public ConnectorMvStore (ClientInfoMvStore clientInfo) throws Exception
|
||||||
|
{
|
||||||
|
this.clientInfo = clientInfo;
|
||||||
|
this.connector = new core.connector.mv.async.ConnectorMvStore(clientInfo, HttpDelegateFactory.create());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void open() throws ConnectorException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws ConnectorException
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<FileInfo> listDirectory(String path) throws ConnectorException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CallbackSync sync = new CallbackSync(connector.list_(path)).invoke();
|
||||||
|
return sync.<List<FileInfo>>export();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new ConnectorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void createDirectory(String path) throws ConnectorException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CallbackSync sync = new CallbackSync(connector.createDirectory_(path)).invoke();
|
||||||
|
sync.checkException();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new ConnectorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] get(String path) throws ConnectorException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CallbackSync sync = new CallbackSync(connector.get_(path)).invoke();
|
||||||
|
return sync.<byte[]>export();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new ConnectorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] get(String path, long size) throws ConnectorException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CallbackSync sync = new CallbackSync(connector.get_(path)).invoke();
|
||||||
|
return sync.<byte[]>export();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new ConnectorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(String path, byte[] contents) throws ConnectorException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CallbackSync sync = new CallbackSync(connector.put_(path, contents)).invoke();
|
||||||
|
sync.checkException();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new ConnectorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void move(String from, String to) throws ConnectorException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CallbackSync sync = new CallbackSync(connector.move_(from, to)).invoke();
|
||||||
|
sync.checkException();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new ConnectorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delete(String path) throws ConnectorException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CallbackSync sync = new CallbackSync(connector.delete_(path)).invoke();
|
||||||
|
sync.checkException();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new ConnectorException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean ensureDirectories(String... folders)
|
||||||
|
{
|
||||||
|
CallbackSync sync = new CallbackSync(connector.ensureDirectories_(folders)).invoke();
|
||||||
|
return sync.<Boolean>exportNoException();
|
||||||
|
}
|
||||||
|
}
|
8
java/core/src/core/constants/ConstantsMvStore.java
Normal file
8
java/core/src/core/constants/ConstantsMvStore.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package core.constants;
|
||||||
|
|
||||||
|
public class ConstantsMvStore
|
||||||
|
{
|
||||||
|
public static final String AccessKeyId = "AccessKeyId";
|
||||||
|
public static final String SecretKey = "SecretKey";
|
||||||
|
|
||||||
|
}
|
@ -4,7 +4,8 @@ public class ConstantsStorage
|
|||||||
{
|
{
|
||||||
public final static String
|
public final static String
|
||||||
HANDLER_DROPBOX = "DB",
|
HANDLER_DROPBOX = "DB",
|
||||||
HANDLER_S3 = "S3";
|
HANDLER_S3 = "S3",
|
||||||
|
HANDLER_MV = "MV";
|
||||||
|
|
||||||
public final static String
|
public final static String
|
||||||
IN = "In",
|
IN = "In",
|
||||||
@ -28,4 +29,5 @@ public class ConstantsStorage
|
|||||||
|
|
||||||
public static final int MAIL_CHECK_LOCK_TIME_SECONDS = 120;
|
public static final int MAIL_CHECK_LOCK_TIME_SECONDS = 120;
|
||||||
public static final int MAIL_CHECK_LOCK_TIME_ALLOWED_BEFORE_RELOCK_SECONDS = 60;
|
public static final int MAIL_CHECK_LOCK_TIME_ALLOWED_BEFORE_RELOCK_SECONDS = 60;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
9
java/core/src/core/util/HttpDelegateFactory.java
Normal file
9
java/core/src/core/util/HttpDelegateFactory.java
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
package core.util;
|
||||||
|
|
||||||
|
public class HttpDelegateFactory
|
||||||
|
{
|
||||||
|
static public HttpDelegate create ()
|
||||||
|
{
|
||||||
|
return new HttpDelegateJava();
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,20 @@ import java.util.ArrayList;
|
|||||||
|
|
||||||
public class SqlCatalog
|
public class SqlCatalog
|
||||||
{
|
{
|
||||||
|
static LogOut log = new LogOut(SqlCatalog.class);
|
||||||
|
public SqlCatalog ()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Class.forName("com.mysql.jdbc.Driver");
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.exception(e);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public String getSingle (String name) throws IOException
|
public String getSingle (String name) throws IOException
|
||||||
{
|
{
|
||||||
return Streams.readFullyString(getClass().getResourceAsStream(name), "UTF-8");
|
return Streams.readFullyString(getClass().getResourceAsStream(name), "UTF-8");
|
||||||
|
@ -36,6 +36,8 @@ import mail.client.model.Model;
|
|||||||
import mail.client.model.ModelFactory;
|
import mail.client.model.ModelFactory;
|
||||||
import mail.client.model.Mail;
|
import mail.client.model.Mail;
|
||||||
import mail.client.model.ModelSerializer;
|
import mail.client.model.ModelSerializer;
|
||||||
|
import mail.client.model.PublicKey;
|
||||||
|
import mail.client.model.PublicKeyRing;
|
||||||
import mail.client.model.Settings;
|
import mail.client.model.Settings;
|
||||||
|
|
||||||
public class CacheManager extends Servent<Master>
|
public class CacheManager extends Servent<Master>
|
||||||
@ -46,6 +48,9 @@ public class CacheManager extends Servent<Master>
|
|||||||
IndexedCache cacheMail;
|
IndexedCache cacheMail;
|
||||||
IndexedCache cacheConversation;
|
IndexedCache cacheConversation;
|
||||||
IndexedCache cacheFolder;
|
IndexedCache cacheFolder;
|
||||||
|
IndexedCache cacheKeys;
|
||||||
|
|
||||||
|
PublicKeyRing keyRing;
|
||||||
Settings settings;
|
Settings settings;
|
||||||
|
|
||||||
boolean isCaching = false;
|
boolean isCaching = false;
|
||||||
@ -84,6 +89,10 @@ public class CacheManager extends Servent<Master>
|
|||||||
this.settings.setId(Constants.SETTINGS_ID);
|
this.settings.setId(Constants.SETTINGS_ID);
|
||||||
this.masterCache.link(settings);
|
this.masterCache.link(settings);
|
||||||
|
|
||||||
|
this.keyRing = new PublicKeyRing(this);
|
||||||
|
this.keyRing.setId(Constants.KEYRING_ID);
|
||||||
|
this.masterCache.link(keyRing);
|
||||||
|
|
||||||
ItemSerializer itemSerializer = new ModelSerializer(json);
|
ItemSerializer itemSerializer = new ModelSerializer(json);
|
||||||
|
|
||||||
this.cacheMail = new IndexedCache(
|
this.cacheMail = new IndexedCache(
|
||||||
@ -104,11 +113,17 @@ public class CacheManager extends Servent<Master>
|
|||||||
this.cacheFolder.setId(Constants.FOLDER_ID);
|
this.cacheFolder.setId(Constants.FOLDER_ID);
|
||||||
masterCache.link(cacheFolder);
|
masterCache.link(cacheFolder);
|
||||||
|
|
||||||
|
this.cacheKeys = new IndexedCache(
|
||||||
|
new ItemCacheFactory ("K", library, itemFactory, itemSerializer)
|
||||||
|
);
|
||||||
|
this.cacheKeys.setId(Constants.KEY_ID);
|
||||||
|
masterCache.link(cacheKeys);
|
||||||
|
|
||||||
//-------------------------------------------------------------
|
//-------------------------------------------------------------
|
||||||
|
|
||||||
Callback countDown =
|
Callback countDown =
|
||||||
new CountDown(
|
new CountDown(
|
||||||
4,
|
5,
|
||||||
getMaster().getEventPropagator().signal_(Events.Initialize_IndexedCacheLoadComplete)
|
getMaster().getEventPropagator().signal_(Events.Initialize_IndexedCacheLoadComplete)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -117,6 +132,7 @@ public class CacheManager extends Servent<Master>
|
|||||||
cacheMail.apply(new Split(countDown));
|
cacheMail.apply(new Split(countDown));
|
||||||
cacheConversation.apply(new Split(countDown));
|
cacheConversation.apply(new Split(countDown));
|
||||||
cacheFolder.apply(new Split(countDown));
|
cacheFolder.apply(new Split(countDown));
|
||||||
|
cacheKeys.apply(new Split(countDown));
|
||||||
|
|
||||||
//-------------------------------------------------------------
|
//-------------------------------------------------------------
|
||||||
|
|
||||||
@ -143,6 +159,7 @@ public class CacheManager extends Servent<Master>
|
|||||||
cacheMail.markCreate();
|
cacheMail.markCreate();
|
||||||
cacheConversation.markCreate();
|
cacheConversation.markCreate();
|
||||||
cacheFolder.markCreate();
|
cacheFolder.markCreate();
|
||||||
|
cacheKeys.markCreate();
|
||||||
masterCache.markCreate();
|
masterCache.markCreate();
|
||||||
|
|
||||||
settings.markCreate();
|
settings.markCreate();
|
||||||
@ -261,6 +278,16 @@ public class CacheManager extends Servent<Master>
|
|||||||
cacheFolder.put(f);
|
cacheFolder.put(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void putKey(PublicKey k)
|
||||||
|
{
|
||||||
|
cacheKeys.put(k);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PublicKey getKey (ID id)
|
||||||
|
{
|
||||||
|
return (PublicKey)cacheKeys.getAndAcquire(Type.PublicKey, id);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isFullyCached ()
|
public boolean isFullyCached ()
|
||||||
{
|
{
|
||||||
return (!library.hasDirtyChildren() && !masterCache.hasDirtyChildren());
|
return (!library.hasDirtyChildren() && !masterCache.hasDirtyChildren());
|
||||||
|
@ -13,6 +13,8 @@ import core.connector.async.AsyncStoreConnectorBase64;
|
|||||||
import core.connector.async.AsyncStoreConnectorEncrypted;
|
import core.connector.async.AsyncStoreConnectorEncrypted;
|
||||||
import core.connector.dropbox.ClientInfoDropbox;
|
import core.connector.dropbox.ClientInfoDropbox;
|
||||||
import core.connector.dropbox.async.ConnectorDropbox;
|
import core.connector.dropbox.async.ConnectorDropbox;
|
||||||
|
import core.connector.mv.ClientInfoMvStore;
|
||||||
|
import core.connector.mv.async.ConnectorMvStore;
|
||||||
import core.connector.s3.ClientInfoS3;
|
import core.connector.s3.ClientInfoS3;
|
||||||
import core.connector.s3.async.S3Connector;
|
import core.connector.s3.async.S3Connector;
|
||||||
import core.constants.ConstantsEnvironmentKeys;
|
import core.constants.ConstantsEnvironmentKeys;
|
||||||
@ -82,6 +84,13 @@ public class Client
|
|||||||
connector = new S3Connector(clientInfo, httpDelegate);
|
connector = new S3Connector(clientInfo, httpDelegate);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
if (handler.equals(ConstantsStorage.HANDLER_MV))
|
||||||
|
{
|
||||||
|
Environment mvEnvironment = mailBoxEnvironment.childEnvironment(handler);
|
||||||
|
ClientInfoMvStore clientInfo = new ClientInfoMvStore(mvEnvironment);
|
||||||
|
connector = new ConnectorMvStore(clientInfo, httpDelegate);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
throw new Exception ("Unknown handler");
|
throw new Exception ("Unknown handler");
|
||||||
}
|
}
|
||||||
|
@ -26,5 +26,7 @@ public class Constants
|
|||||||
SETTINGS_ID = ID.fromLong(1),
|
SETTINGS_ID = ID.fromLong(1),
|
||||||
MAIL_ID = ID.fromLong(2),
|
MAIL_ID = ID.fromLong(2),
|
||||||
CONVERSATION_ID = ID.fromLong(3),
|
CONVERSATION_ID = ID.fromLong(3),
|
||||||
FOLDER_ID = ID.fromLong(4);
|
FOLDER_ID = ID.fromLong(4),
|
||||||
|
KEYRING_ID = ID.fromLong(5),
|
||||||
|
KEY_ID = ID.fromLong(6);
|
||||||
}
|
}
|
||||||
|
43
java/core/src/mail/client/cache/JSON.java
vendored
43
java/core/src/mail/client/cache/JSON.java
vendored
@ -26,6 +26,8 @@ import mail.client.model.FolderSet;
|
|||||||
import mail.client.model.Header;
|
import mail.client.model.Header;
|
||||||
import mail.client.model.Identity;
|
import mail.client.model.Identity;
|
||||||
import mail.client.model.Mail;
|
import mail.client.model.Mail;
|
||||||
|
import mail.client.model.PublicKey;
|
||||||
|
import mail.client.model.PublicKeyRing;
|
||||||
import mail.client.model.Recipients;
|
import mail.client.model.Recipients;
|
||||||
import mail.client.model.Settings;
|
import mail.client.model.Settings;
|
||||||
import mail.client.model.TransportState;
|
import mail.client.model.TransportState;
|
||||||
@ -573,4 +575,45 @@ public class JSON extends Servent<Master>
|
|||||||
|
|
||||||
return o;
|
return o;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void fromJSON(PublicKey item, Object parse) throws JSONException
|
||||||
|
{
|
||||||
|
item.setEmail(JSON_.getString(parse, "email"));
|
||||||
|
item.setPublicKey(JSON_.getString(parse, "publicKey"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object toJSON(PublicKey item) throws JSONException
|
||||||
|
{
|
||||||
|
Object o = JSON_.newObject();
|
||||||
|
JSON_.put(o, "email", item.toString());
|
||||||
|
JSON_.put(o, "publicKey", item.getPublicKey());
|
||||||
|
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void fromJSON(PublicKeyRing item, Object a) throws JSONException
|
||||||
|
{
|
||||||
|
for (int i=0; i<JSON_.size(a); ++i) // reverse it
|
||||||
|
{
|
||||||
|
Object iNs = JSON_.getObject(a, i);
|
||||||
|
item.addPublicKeyFromCache(
|
||||||
|
toID(JSON_.getString(iNs,"id")),
|
||||||
|
toIdentity(JSON_.getString(iNs, "identity"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object toJSON(PublicKeyRing item) throws JSONException
|
||||||
|
{
|
||||||
|
Object a = JSON_.newArray();
|
||||||
|
for (Pair<ID,Identity> iNs : item.getPublicKeys())
|
||||||
|
{
|
||||||
|
Object o = JSON_.newObject();
|
||||||
|
JSON_.put(o, "id", toJSON(iNs.first));
|
||||||
|
JSON_.put(o, "identity", toJSON(iNs.second));
|
||||||
|
}
|
||||||
|
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
4
java/core/src/mail/client/cache/Type.java
vendored
4
java/core/src/mail/client/cache/Type.java
vendored
@ -13,5 +13,7 @@ public enum Type {
|
|||||||
FolderFilterSet,
|
FolderFilterSet,
|
||||||
FolderMaster,
|
FolderMaster,
|
||||||
Index,
|
Index,
|
||||||
Settings
|
Settings,
|
||||||
|
PublicKeyRing,
|
||||||
|
PublicKey,
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,6 @@ public class Identity implements Serializable, Exportable
|
|||||||
String name;
|
String name;
|
||||||
String email;
|
String email;
|
||||||
boolean isPrimary = false;
|
boolean isPrimary = false;
|
||||||
String publicKey;
|
|
||||||
|
|
||||||
protected Identity ()
|
protected Identity ()
|
||||||
{
|
{
|
||||||
@ -169,19 +168,4 @@ public class Identity implements Serializable, Exportable
|
|||||||
this.email = identity.email;
|
this.email = identity.email;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPublicKey (String publicKey)
|
|
||||||
{
|
|
||||||
this.publicKey = publicKey;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasPublicKey()
|
|
||||||
{
|
|
||||||
return publicKey != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getPublicKey()
|
|
||||||
{
|
|
||||||
return publicKey;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,7 @@ public class Mail extends Model
|
|||||||
this.attachments = attachments;
|
this.attachments = attachments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
public boolean isPresendEncryptable()
|
public boolean isPresendEncryptable()
|
||||||
{
|
{
|
||||||
for (Identity i : getHeader().getRecipients().getAll())
|
for (Identity i : getHeader().getRecipients().getAll())
|
||||||
@ -191,4 +192,5 @@ public class Mail extends Model
|
|||||||
Base64.encode(aes.encrypt(Strings.toBytes(JSON_.asString(container))))
|
Base64.encode(aes.encrypt(Strings.toBytes(JSON_.asString(container))))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,8 @@ public class ModelSerializer implements ItemSerializer
|
|||||||
return Strings.toBytes(json.toJSON((Folder)item).toString());
|
return Strings.toBytes(json.toJSON((Folder)item).toString());
|
||||||
if (item instanceof Settings)
|
if (item instanceof Settings)
|
||||||
return Strings.toBytes(json.toJSON((Settings)item).toString());
|
return Strings.toBytes(json.toJSON((Settings)item).toString());
|
||||||
|
if (item instanceof PublicKey)
|
||||||
|
return Strings.toBytes(json.toJSON((PublicKey)item).toString());
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -58,6 +60,8 @@ public class ModelSerializer implements ItemSerializer
|
|||||||
json.fromJSON((Folder)item, JSON_.parse(Strings.toString(bytes)));
|
json.fromJSON((Folder)item, JSON_.parse(Strings.toString(bytes)));
|
||||||
if (item instanceof Settings)
|
if (item instanceof Settings)
|
||||||
json.fromJSON((Settings)item, JSON_.parse(Strings.toString(bytes)));
|
json.fromJSON((Settings)item, JSON_.parse(Strings.toString(bytes)));
|
||||||
|
if (item instanceof PublicKey)
|
||||||
|
json.fromJSON((PublicKey)item, JSON_.parse(Strings.toString(bytes)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
35
java/core/src/mail/client/model/PublicKey.java
Normal file
35
java/core/src/mail/client/model/PublicKey.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package mail.client.model;
|
||||||
|
|
||||||
|
import mail.client.CacheManager;
|
||||||
|
|
||||||
|
public class PublicKey extends Model
|
||||||
|
{
|
||||||
|
String email;
|
||||||
|
String publicKey;
|
||||||
|
|
||||||
|
public PublicKey(CacheManager manager)
|
||||||
|
{
|
||||||
|
super(manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail (String email)
|
||||||
|
{
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail (String email)
|
||||||
|
{
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPublicKey (String publicKey)
|
||||||
|
{
|
||||||
|
this.publicKey = publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPublicKey ()
|
||||||
|
{
|
||||||
|
return publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
34
java/core/src/mail/client/model/PublicKeyRing.java
Normal file
34
java/core/src/mail/client/model/PublicKeyRing.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package mail.client.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import core.util.Pair;
|
||||||
|
import mail.client.CacheManager;
|
||||||
|
import mail.client.cache.ID;
|
||||||
|
|
||||||
|
public class PublicKeyRing extends Model
|
||||||
|
{
|
||||||
|
List<Pair<ID, Identity>> ring;
|
||||||
|
|
||||||
|
public PublicKeyRing(CacheManager manager)
|
||||||
|
{
|
||||||
|
super(manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPublicKeyFromCache(ID id, Identity identity)
|
||||||
|
{
|
||||||
|
ring.add(Pair.create(id, identity));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPublicKey(ID id, Identity identity)
|
||||||
|
{
|
||||||
|
ring.add(Pair.create(id, identity));
|
||||||
|
markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Pair<ID,Identity>> getPublicKeys()
|
||||||
|
{
|
||||||
|
return ring;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
32
java/core/src/mail/server/handler/MailetHandlerMvStore.java
Normal file
32
java/core/src/mail/server/handler/MailetHandlerMvStore.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* Author: Timothy Prepscius
|
||||||
|
* License: GPLv3 Affero + keep my name in the code!
|
||||||
|
*/
|
||||||
|
package mail.server.handler;
|
||||||
|
|
||||||
|
|
||||||
|
import core.connector.mv.ClientInfoMvStore;
|
||||||
|
import core.connector.mv.sync.ConnectorMvStore;
|
||||||
|
import core.connector.sync.EncryptedStoreConnector;
|
||||||
|
import core.connector.sync.StoreConnector;
|
||||||
|
import core.constants.ConstantsStorage;
|
||||||
|
import core.crypt.CryptorRSAAES;
|
||||||
|
import core.crypt.CryptorRSAFactoryEnvironment;
|
||||||
|
import core.util.Environment;
|
||||||
|
import core.util.LogOut;
|
||||||
|
|
||||||
|
|
||||||
|
public class MailetHandlerMvStore extends MailetHandlerDefault
|
||||||
|
{
|
||||||
|
static LogOut log = new LogOut(MailetHandlerMvStore.class);
|
||||||
|
|
||||||
|
public StoreConnector createConnector (Environment e) throws Exception
|
||||||
|
{
|
||||||
|
log.debug("createConnector");
|
||||||
|
|
||||||
|
return new EncryptedStoreConnector(
|
||||||
|
new CryptorRSAAES(CryptorRSAFactoryEnvironment.create(e)),
|
||||||
|
new ConnectorMvStore(new ClientInfoMvStore(e.childEnvironment(ConstantsStorage.HANDLER_MV)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -49,6 +49,9 @@ public class UserInformationFactory
|
|||||||
else
|
else
|
||||||
if (handlerName.equals(ConstantsStorage.HANDLER_DROPBOX))
|
if (handlerName.equals(ConstantsStorage.HANDLER_DROPBOX))
|
||||||
mailetHandler = new MailetHandlerDropbox();
|
mailetHandler = new MailetHandlerDropbox();
|
||||||
|
else
|
||||||
|
if (handlerName.equals(ConstantsStorage.HANDLER_MV))
|
||||||
|
mailetHandler = new MailetHandlerMvStore();
|
||||||
else
|
else
|
||||||
throw new Exception("Unknown handler");
|
throw new Exception("Unknown handler");
|
||||||
|
|
||||||
|
13
java/core/src/store/server/ConstantsMvServer.java
Normal file
13
java/core/src/store/server/ConstantsMvServer.java
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package store.server;
|
||||||
|
|
||||||
|
public class ConstantsMvServer {
|
||||||
|
|
||||||
|
public static final String
|
||||||
|
HEADER_DATE = "X-Mv-Date",
|
||||||
|
HEADER_CONTENT_TYPE = "Content-Type",
|
||||||
|
HEADER_CONTENT_LENGTH = "Content-Length",
|
||||||
|
HEADER_AUTHORIZATION = "Authorization",
|
||||||
|
|
||||||
|
PARAMETER_RESOURCE = "Resource";
|
||||||
|
|
||||||
|
}
|
64
java/core/src/store/server/StoreServer.java
Normal file
64
java/core/src/store/server/StoreServer.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
package store.server;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import store.server.db.DbStore;
|
||||||
|
import core.connector.FileInfo;
|
||||||
|
import core.util.Pair;
|
||||||
|
|
||||||
|
public class StoreServer
|
||||||
|
{
|
||||||
|
DbStore store;
|
||||||
|
|
||||||
|
public StoreServer () throws Exception
|
||||||
|
{
|
||||||
|
store = new DbStore();
|
||||||
|
store.ensureTables();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<String,String> newKeyPair (String userName) throws Exception
|
||||||
|
{
|
||||||
|
Pair<String, String> v = StoreUtils.createKeyIdAndSecretKey();
|
||||||
|
DbStore store = new DbStore();
|
||||||
|
int userId = store.getUserId(userName);
|
||||||
|
store.addUserKeyPair(userId, v.first, v.second);
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void newUser (String userName) throws Exception
|
||||||
|
{
|
||||||
|
store.addUser(userName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<String,String> newUserWithKeyPair (String userName) throws Exception
|
||||||
|
{
|
||||||
|
newUser (userName);
|
||||||
|
return newKeyPair(userName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String putKeyValue (String keyId, String key, byte[] value) throws Exception
|
||||||
|
{
|
||||||
|
return store.putKeyValue(store.getUserIdAndSecretKey(keyId).first, key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<String, byte[]> getKeyValue (String keyId, String key) throws Exception
|
||||||
|
{
|
||||||
|
return store.getKeyValue(store.getUserIdAndSecretKey(keyId).first, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeKeyValue (String keyId, String key) throws Exception
|
||||||
|
{
|
||||||
|
store.removeKeyValue (store.getUserIdAndSecretKey(keyId).first, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeUser (String name) throws Exception
|
||||||
|
{
|
||||||
|
store.removeUser (name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FileInfo> listKeys (String keyId, String key) throws Exception
|
||||||
|
{
|
||||||
|
return store.listKeys(store.getUserIdAndSecretKey(keyId).first, key);
|
||||||
|
}
|
||||||
|
}
|
142
java/core/src/store/server/StoreUtils.java
Normal file
142
java/core/src/store/server/StoreUtils.java
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
package store.server;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import store.server.db.DbStore;
|
||||||
|
|
||||||
|
import core.crypt.HmacSha1;
|
||||||
|
import core.util.Base64;
|
||||||
|
import core.util.LogOut;
|
||||||
|
import core.util.Pair;
|
||||||
|
import core.util.SecureRandom;
|
||||||
|
import core.util.Strings;
|
||||||
|
|
||||||
|
public class StoreUtils
|
||||||
|
{
|
||||||
|
static LogOut log = new LogOut(StoreUtils.class);
|
||||||
|
|
||||||
|
// This method creates S3 signature for a given String.
|
||||||
|
static protected String sign(HmacSha1 mac, String data) throws Exception
|
||||||
|
{
|
||||||
|
// Signed String must be BASE64 encoded.
|
||||||
|
byte[] signBytes = mac.mac(Strings.toBytes(data));
|
||||||
|
String signature = Base64.encode(signBytes);
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
static public Pair<String, String> createKeyIdAndSecretKey ()
|
||||||
|
{
|
||||||
|
byte[] keyId = new byte[32];
|
||||||
|
byte[] secretKey = new byte[32];
|
||||||
|
SecureRandom random = new SecureRandom();
|
||||||
|
random.nextBytes(keyId);
|
||||||
|
random.nextBytes(secretKey);
|
||||||
|
|
||||||
|
return Pair.create(Base64.encode(keyId), Base64.encode(secretKey));
|
||||||
|
}
|
||||||
|
|
||||||
|
static public void verifySignature (String data, String keyId, String signature) throws Exception
|
||||||
|
{
|
||||||
|
DbStore dbStore = new DbStore();
|
||||||
|
Pair<Integer, String> userIdAndSecretKey = dbStore.getUserIdAndSecretKey(keyId);
|
||||||
|
|
||||||
|
log.debug ("verifySignature", data, userIdAndSecretKey.second);
|
||||||
|
|
||||||
|
HmacSha1 userMac = new HmacSha1(Base64.decode(userIdAndSecretKey.second));
|
||||||
|
String correctSignature = sign(userMac, data);
|
||||||
|
|
||||||
|
if (!correctSignature.equals(signature))
|
||||||
|
throw new Exception ("Signature mismatch");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* returns the keyId of the user
|
||||||
|
*
|
||||||
|
* @param action
|
||||||
|
* @param headers
|
||||||
|
* @param resource
|
||||||
|
* @param content
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
static public String verifyUser (String action, Map<String,String> headers, String resource, byte[] content) throws Exception
|
||||||
|
{
|
||||||
|
String method = action;
|
||||||
|
String dateString = headers.get(ConstantsMvServer.HEADER_DATE);
|
||||||
|
String contentType = headers.get(ConstantsMvServer.HEADER_CONTENT_TYPE);
|
||||||
|
String contentLength = headers.get(ConstantsMvServer.HEADER_CONTENT_LENGTH);
|
||||||
|
|
||||||
|
if (contentLength != null)
|
||||||
|
if (Integer.parseInt(contentLength) != content.length)
|
||||||
|
throw new Exception ("Length mismatch");
|
||||||
|
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
buf.append(method).append("\n");
|
||||||
|
buf.append("").append("\n");
|
||||||
|
buf.append(contentType != null ? contentType : "").append("\n");
|
||||||
|
buf.append("\n"); // empty real date header
|
||||||
|
buf.append(dateString).append("\n");
|
||||||
|
buf.append(resource);
|
||||||
|
|
||||||
|
String[] authorizationParts = headers.get(ConstantsMvServer.HEADER_AUTHORIZATION).split(":");
|
||||||
|
String keyId = authorizationParts[0].split(" ")[1];
|
||||||
|
String signature = authorizationParts[1];
|
||||||
|
|
||||||
|
verifySignature (buf.toString(), keyId, signature);
|
||||||
|
|
||||||
|
return keyId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
public byte[] getFile (String userPath) throws Exception
|
||||||
|
{
|
||||||
|
FileInputStream f = new FileInputStream(ConstantsMvServer.PATH + userPath);
|
||||||
|
byte[] result = Streams.readFullyBytes(f);
|
||||||
|
f.close();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putFile (String userPath, byte[] bytes) throws Exception
|
||||||
|
{
|
||||||
|
FileOutputStream f = new FileOutputStream (ConstantsMvServer.PATH + userPath);
|
||||||
|
f.write(bytes);
|
||||||
|
f.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<File> listFiles(File dir, List<File> files)
|
||||||
|
{
|
||||||
|
if (!dir.isDirectory())
|
||||||
|
{
|
||||||
|
files.add(dir);
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (File file : dir.listFiles())
|
||||||
|
listFiles(file, files);
|
||||||
|
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FileInfo> listKeys (String userPath)
|
||||||
|
{
|
||||||
|
List<File> files = listFiles (new File (ConstantsMvServer.PATH + userPath), new ArrayList<File>());
|
||||||
|
|
||||||
|
List<FileInfo> fileInfos = new ArrayList<FileInfo>();
|
||||||
|
for (File file : files)
|
||||||
|
{
|
||||||
|
FileInfo info = new FileInfo(
|
||||||
|
file.getPath(),
|
||||||
|
file.getPath(),
|
||||||
|
file.length(),
|
||||||
|
new Date(file.lastModified()),
|
||||||
|
"" + file.lastModified()
|
||||||
|
);
|
||||||
|
|
||||||
|
fileInfos.add(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileInfos;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
304
java/core/src/store/server/db/DbStore.java
Normal file
304
java/core/src/store/server/db/DbStore.java
Normal file
@ -0,0 +1,304 @@
|
|||||||
|
package store.server.db;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
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.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import core.connector.FileInfo;
|
||||||
|
import core.util.Base64;
|
||||||
|
import core.util.FastRandom;
|
||||||
|
import core.util.LogOut;
|
||||||
|
import core.util.Pair;
|
||||||
|
import core.util.Passwords;
|
||||||
|
import store.server.db.sql.Catalog;
|
||||||
|
|
||||||
|
public class DbStore
|
||||||
|
{
|
||||||
|
FastRandom random = new FastRandom();
|
||||||
|
LogOut log = new LogOut(DbStore.class);
|
||||||
|
Catalog catalog = new Catalog();
|
||||||
|
|
||||||
|
public void ensureTables() throws Exception
|
||||||
|
{
|
||||||
|
Connection connection = openConnection();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (String sql : catalog.getMulti(Catalog.ENSURE_TABLES))
|
||||||
|
{
|
||||||
|
PreparedStatement statement = connection.prepareStatement (sql);
|
||||||
|
log(statement);
|
||||||
|
statement.executeUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
closeConnection(connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String putKeyValue (int userId, String key, byte[] value) throws Exception
|
||||||
|
{
|
||||||
|
Connection connection = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connection = openConnection();
|
||||||
|
String sql = catalog.getSingle(Catalog.PUT_KEY_VALUE);
|
||||||
|
PreparedStatement statement = connection.prepareStatement(sql);
|
||||||
|
statement.setInt(1, userId);
|
||||||
|
statement.setString(2, key);
|
||||||
|
statement.setBytes(3, value);
|
||||||
|
|
||||||
|
byte[] randomBytes = new byte[16];
|
||||||
|
random.nextBytes(randomBytes);
|
||||||
|
String randomB64 = Base64.encode(randomBytes);
|
||||||
|
|
||||||
|
statement.setString(4, randomB64);
|
||||||
|
statement.execute();
|
||||||
|
|
||||||
|
return randomB64;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
closeConnection (connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<String, byte[]> getKeyValue (int userId, String key) throws Exception
|
||||||
|
{
|
||||||
|
Connection connection = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connection = openConnection();
|
||||||
|
String sql = catalog.getSingle(Catalog.GET_KEY_VALUE);
|
||||||
|
PreparedStatement statement = connection.prepareStatement(sql);
|
||||||
|
statement.setInt(1, userId);
|
||||||
|
statement.setString(2, key);
|
||||||
|
|
||||||
|
ResultSet results = statement.executeQuery();
|
||||||
|
if (results.next())
|
||||||
|
{
|
||||||
|
return Pair.create(results.getString("version"), results.getBytes("v"));
|
||||||
|
}
|
||||||
|
|
||||||
|
results.close();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
closeConnection (connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("Unknown key");
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FileInfo> listKeys (int userId, String key) throws Exception
|
||||||
|
{
|
||||||
|
Connection connection = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connection = openConnection();
|
||||||
|
String sql = catalog.getSingle(Catalog.LIST_KEY_VALUES);
|
||||||
|
PreparedStatement statement = connection.prepareStatement(sql);
|
||||||
|
statement.setInt(1, userId);
|
||||||
|
statement.setString(2, key);
|
||||||
|
|
||||||
|
List<FileInfo> retval = new ArrayList<FileInfo>();
|
||||||
|
ResultSet results = statement.executeQuery();
|
||||||
|
while (results.next())
|
||||||
|
{
|
||||||
|
String path = results.getString("k");
|
||||||
|
int size = results.getInt("size");
|
||||||
|
Date date = results.getTimestamp("mark");
|
||||||
|
String version = results.getString("version");
|
||||||
|
|
||||||
|
FileInfo fileInfo = new FileInfo(path, path.substring(key.length()), size, date, version);
|
||||||
|
retval.add(fileInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
results.close();
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
closeConnection (connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<Integer, String> getUserIdAndSecretKey (String keyId) throws Exception
|
||||||
|
{
|
||||||
|
Connection connection = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connection = openConnection();
|
||||||
|
String sql = catalog.getSingle(Catalog.GET_USER_ID_AND_SECRET_KEY);
|
||||||
|
PreparedStatement statement = connection.prepareStatement(sql);
|
||||||
|
statement.setString(1, keyId);
|
||||||
|
|
||||||
|
ResultSet results = statement.executeQuery();
|
||||||
|
if (results.next())
|
||||||
|
{
|
||||||
|
return Pair.create(results.getInt("user_id"), results.getString("secret_key"));
|
||||||
|
}
|
||||||
|
|
||||||
|
results.close();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
closeConnection (connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("Unknown KeyId");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addUser (String userName) throws Exception
|
||||||
|
{
|
||||||
|
Connection connection = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connection = openConnection();
|
||||||
|
String sql = catalog.getSingle(Catalog.ADD_USER);
|
||||||
|
PreparedStatement statement = connection.prepareStatement(sql);
|
||||||
|
statement.setString(1, userName);
|
||||||
|
|
||||||
|
statement.execute();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
closeConnection (connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeUser (String userName) throws Exception
|
||||||
|
{
|
||||||
|
Connection connection = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connection = openConnection();
|
||||||
|
String[] sqls = catalog.getMulti(Catalog.REMOVE_USER);
|
||||||
|
|
||||||
|
boolean first = true;
|
||||||
|
for (String sql : sqls)
|
||||||
|
{
|
||||||
|
PreparedStatement statement = connection.prepareStatement(sql);
|
||||||
|
if (first)
|
||||||
|
statement.setString(1, userName);
|
||||||
|
|
||||||
|
statement.execute();
|
||||||
|
first = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
closeConnection (connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeKeyValue(int userId, String key) throws Exception
|
||||||
|
{
|
||||||
|
Connection connection = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connection = openConnection();
|
||||||
|
String sql = catalog.getSingle(Catalog.REMOVE_KEY_VALUE);
|
||||||
|
PreparedStatement statement = connection.prepareStatement(sql);
|
||||||
|
statement.setInt(1, userId);
|
||||||
|
statement.setString(2, key);
|
||||||
|
|
||||||
|
statement.execute();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
closeConnection (connection);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUserId(String userName) throws Exception
|
||||||
|
{
|
||||||
|
Connection connection = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connection = openConnection();
|
||||||
|
String sql = catalog.getSingle(Catalog.GET_USER_ID);
|
||||||
|
PreparedStatement statement = connection.prepareStatement(sql);
|
||||||
|
statement.setString(1, userName);
|
||||||
|
|
||||||
|
ResultSet results = statement.executeQuery();
|
||||||
|
if (results.next())
|
||||||
|
{
|
||||||
|
return results.getInt("user_id");
|
||||||
|
}
|
||||||
|
|
||||||
|
results.close();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
closeConnection (connection);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new Exception("Unknown user name");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void addUserKeyPair (int userId, String keyId, String secretKey) throws Exception
|
||||||
|
{
|
||||||
|
Connection connection = null;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
connection = openConnection();
|
||||||
|
String sql = catalog.getSingle(Catalog.ADD_USER_KEY_PAIR);
|
||||||
|
PreparedStatement statement = connection.prepareStatement(sql);
|
||||||
|
statement.setInt(1, userId);
|
||||||
|
statement.setString(2, keyId);
|
||||||
|
statement.setString(3, secretKey);
|
||||||
|
|
||||||
|
statement.execute();
|
||||||
|
}
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
log.debug (sql);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
java/core/src/store/server/db/sql/Catalog.java
Normal file
28
java/core/src/store/server/db/sql/Catalog.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/**
|
||||||
|
* Author: Timothy Prepscius
|
||||||
|
* License: GPLv3 Affero + keep my name in the code!
|
||||||
|
*/
|
||||||
|
package store.server.db.sql;
|
||||||
|
|
||||||
|
import core.constants.ConstantsServer;
|
||||||
|
import core.util.SqlCatalog;
|
||||||
|
|
||||||
|
public class Catalog extends SqlCatalog
|
||||||
|
{
|
||||||
|
public static final String
|
||||||
|
ENSURE_TABLES = "ensure_tables.sql",
|
||||||
|
|
||||||
|
ADD_USER = "add_user.sql",
|
||||||
|
ADD_USER_KEY_PAIR = "add_user_key_pair.sql",
|
||||||
|
GET_USER_ID = "get_user_id.sql",
|
||||||
|
REMOVE_USER = "remove_user.sql",
|
||||||
|
GET_USER_ID_AND_SECRET_KEY = "get_user_id_and_secret_key.sql",
|
||||||
|
|
||||||
|
LIST_KEY_VALUES = "list_keys.sql",
|
||||||
|
REMOVE_KEY_VALUE = "remove_key_value.sql",
|
||||||
|
PUT_KEY_VALUE = "put_key_value.sql",
|
||||||
|
GET_KEY_VALUE = "get_key_value.sql";
|
||||||
|
|
||||||
|
public String CONNECTION_STRING = ConstantsServer.DBCONNECTION_PREFIX + "store";
|
||||||
|
public String USER = "store";
|
||||||
|
}
|
1
java/core/src/store/server/db/sql/add_user.sql
Normal file
1
java/core/src/store/server/db/sql/add_user.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
INSERT INTO users (name) VALUES (?)
|
1
java/core/src/store/server/db/sql/add_user_key_pair.sql
Normal file
1
java/core/src/store/server/db/sql/add_user_key_pair.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
INSERT INTO key_pairs (user_id, key_id, secret_key) VALUES (?,?,?);
|
24
java/core/src/store/server/db/sql/ensure_tables.sql
Normal file
24
java/core/src/store/server/db/sql/ensure_tables.sql
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
user_id INTEGER AUTO_INCREMENT NOT NULL,
|
||||||
|
PRIMARY KEY (user_id),
|
||||||
|
KEY (name)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS key_pairs (
|
||||||
|
user_id INTEGER NOT NULL,
|
||||||
|
key_id VARCHAR(255) NOT NULL,
|
||||||
|
secret_key VARCHAR(255) NOT NULL,
|
||||||
|
mark TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
PRIMARY KEY (user_id, key_id),
|
||||||
|
KEY (key_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS key_values (
|
||||||
|
user_id INTEGER NOT NULL,
|
||||||
|
k VARCHAR(2048),
|
||||||
|
v LONGBLOB,
|
||||||
|
mark TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
version VARCHAR(255) NOT NULL,
|
||||||
|
PRIMARY KEY (user_id, k(128))
|
||||||
|
);
|
1
java/core/src/store/server/db/sql/get_key_value.sql
Normal file
1
java/core/src/store/server/db/sql/get_key_value.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
SELECT version, v FROM key_values WHERE user_id = ? AND k = ?
|
1
java/core/src/store/server/db/sql/get_user_id.sql
Normal file
1
java/core/src/store/server/db/sql/get_user_id.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
SELECT user_id FROM users WHERE name = ?
|
@ -0,0 +1 @@
|
|||||||
|
SELECT user_id, secret_key FROM key_pairs WHERE key_id = ?
|
13
java/core/src/store/server/db/sql/list_keys.sql
Normal file
13
java/core/src/store/server/db/sql/list_keys.sql
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# this is really lame and I know it
|
||||||
|
# but I need to avoid the LIKE clause, until I have time to figure out
|
||||||
|
# where the function is for proper mysql escaping.
|
||||||
|
|
||||||
|
SELECT
|
||||||
|
k,
|
||||||
|
mark,
|
||||||
|
version,
|
||||||
|
LENGTH(v) as size
|
||||||
|
FROM
|
||||||
|
key_values
|
||||||
|
WHERE
|
||||||
|
user_id = ? AND LOCATE(?,k)=1
|
1
java/core/src/store/server/db/sql/put_key_value.sql
Normal file
1
java/core/src/store/server/db/sql/put_key_value.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
REPLACE INTO key_values (user_id,k,v,version) VALUES (?,?,?,?)
|
1
java/core/src/store/server/db/sql/remove_key_value.sql
Normal file
1
java/core/src/store/server/db/sql/remove_key_value.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
DELETE FROM key_value WHERE user_id = ? AND k = ?
|
0
java/core/src/store/server/db/sql/remove_user.sql
Normal file
0
java/core/src/store/server/db/sql/remove_user.sql
Normal file
1
java/webserver/src/core/constants/ConstantsMvStore.java
Symbolic link
1
java/webserver/src/core/constants/ConstantsMvStore.java
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../../../core/src/core/constants/ConstantsMvStore.java
|
105
java/webserver/src/mail/web/StoreEnable.java
Normal file
105
java/webserver/src/mail/web/StoreEnable.java
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package mail.web;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import core.constants.ConstantsMvStore;
|
||||||
|
import core.server.captcha.Captcha;
|
||||||
|
import core.util.LogOut;
|
||||||
|
import core.util.Pair;
|
||||||
|
import core.util.Strings;
|
||||||
|
|
||||||
|
import store.server.StoreServer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Servlet implementation class StoreEnable
|
||||||
|
*/
|
||||||
|
@WebServlet("/StoreEnable")
|
||||||
|
public class StoreEnable extends HttpServlet
|
||||||
|
{
|
||||||
|
static LogOut log = new LogOut(StoreEnable.class);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
StoreServer store;
|
||||||
|
Captcha captcha;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HttpServlet#HttpServlet()
|
||||||
|
*/
|
||||||
|
public StoreEnable() throws Exception
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
store = new StoreServer();
|
||||||
|
captcha = new Captcha();
|
||||||
|
captcha.ensureTables();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.exception(e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doCors(HttpServletResponse response)
|
||||||
|
{
|
||||||
|
response.setHeader("Access-Control-Allow-Origin", ConstantsWeb.WEB_SERVER_URL);
|
||||||
|
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
||||||
|
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
|
||||||
|
*/
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
doCors(response);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String email = request.getParameter("email");
|
||||||
|
String captchaToken = request.getParameter("captcha");
|
||||||
|
|
||||||
|
log.debug("email",email, "captchaToken",captchaToken);
|
||||||
|
|
||||||
|
captcha.useToken(captchaToken, Captcha.CreateBucket);
|
||||||
|
Pair<String,String> result = store.newUserWithKeyPair(email);
|
||||||
|
|
||||||
|
ArrayList<String> keyValues = new ArrayList<String>();
|
||||||
|
keyValues.add(ConstantsMvStore.AccessKeyId + "!" + result.first);
|
||||||
|
keyValues.add(ConstantsMvStore.SecretKey + "!" + result.second);
|
||||||
|
|
||||||
|
response.getWriter().write(Strings.concat(keyValues, "&"));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.exception(e);
|
||||||
|
throw new ServletException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
|
||||||
|
*/
|
||||||
|
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
doGet(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doOptions (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
doCors(response);
|
||||||
|
super.doOptions(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
88
java/webserver/src/mail/web/StoreGet.java
Normal file
88
java/webserver/src/mail/web/StoreGet.java
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package mail.web;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import store.server.ConstantsMvServer;
|
||||||
|
import store.server.StoreServer;
|
||||||
|
|
||||||
|
import core.util.Base64;
|
||||||
|
import core.util.HttpDelegate;
|
||||||
|
import core.util.LogOut;
|
||||||
|
import core.util.Pair;
|
||||||
|
import core.util.Streams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Servlet implementation class StoreGet
|
||||||
|
*/
|
||||||
|
@WebServlet("/StoreGet")
|
||||||
|
public class StoreGet extends HttpServlet
|
||||||
|
{
|
||||||
|
static LogOut log = new LogOut(StoreGet.class);
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
StoreServer store;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HttpServlet#HttpServlet()
|
||||||
|
*/
|
||||||
|
public StoreGet() throws Exception
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
store = new StoreServer();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.exception(e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doCors(HttpServletResponse response)
|
||||||
|
{
|
||||||
|
response.setHeader("Access-Control-Allow-Origin", ConstantsWeb.WEB_SERVER_URL);
|
||||||
|
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
||||||
|
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doRequest (String action, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
doCors(response);
|
||||||
|
|
||||||
|
String resource = request.getParameter(ConstantsMvServer.PARAMETER_RESOURCE);
|
||||||
|
String keyId = StoreWebUtils.verifyUser(action, request, resource, null);
|
||||||
|
|
||||||
|
Pair<String, byte[]> versionAndData = store.getKeyValue(keyId, resource);
|
||||||
|
response.setHeader("Version", versionAndData.first);
|
||||||
|
response.getOutputStream().write(versionAndData.second);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.exception(e);
|
||||||
|
throw new ServletException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
|
||||||
|
*/
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
doRequest(HttpDelegate.GET, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doOptions (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
doCors(response);
|
||||||
|
super.doOptions(request, response);
|
||||||
|
}
|
||||||
|
}
|
83
java/webserver/src/mail/web/StoreList.java
Normal file
83
java/webserver/src/mail/web/StoreList.java
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package mail.web;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import store.server.ConstantsMvServer;
|
||||||
|
import store.server.StoreServer;
|
||||||
|
import core.util.HttpDelegate;
|
||||||
|
import core.util.LogOut;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Servlet implementation class StoreList
|
||||||
|
*/
|
||||||
|
@WebServlet("/StoreList")
|
||||||
|
public class StoreList extends HttpServlet {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
static LogOut log = new LogOut(StoreList.class);
|
||||||
|
StoreServer store;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HttpServlet#HttpServlet()
|
||||||
|
*/
|
||||||
|
public StoreList() throws Exception
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
store = new StoreServer();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.exception(e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doCors(HttpServletResponse response)
|
||||||
|
{
|
||||||
|
response.setHeader("Access-Control-Allow-Origin", ConstantsWeb.WEB_SERVER_URL);
|
||||||
|
response.setHeader("Access-Control-Allow-Methods", "GET, OPTIONS");
|
||||||
|
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doRequest (String action, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
doCors(response);
|
||||||
|
|
||||||
|
String resource = request.getParameter(ConstantsMvServer.PARAMETER_RESOURCE);
|
||||||
|
String keyId = StoreWebUtils.verifyUser(action, request, resource, null);
|
||||||
|
|
||||||
|
String json = StoreWebUtils.transformFileInfoListToJson(store.listKeys(keyId, resource));
|
||||||
|
response.getOutputStream().write(json.getBytes("UTF-8"));
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.exception(e);
|
||||||
|
throw new ServletException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
|
||||||
|
*/
|
||||||
|
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
doRequest(HttpDelegate.GET, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doOptions (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
doCors(response);
|
||||||
|
super.doOptions(request, response);
|
||||||
|
}
|
||||||
|
}
|
85
java/webserver/src/mail/web/StorePut.java
Normal file
85
java/webserver/src/mail/web/StorePut.java
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package mail.web;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.annotation.WebServlet;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
import store.server.ConstantsMvServer;
|
||||||
|
import store.server.StoreServer;
|
||||||
|
import core.util.HttpDelegate;
|
||||||
|
import core.util.LogOut;
|
||||||
|
import core.util.Streams;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Servlet implementation class StorePut
|
||||||
|
*/
|
||||||
|
@WebServlet("/StorePut")
|
||||||
|
public class StorePut extends HttpServlet {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
static LogOut log = new LogOut(StorePut.class);
|
||||||
|
StoreServer store;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HttpServlet#HttpServlet()
|
||||||
|
*/
|
||||||
|
public StorePut() throws Exception
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
store = new StoreServer();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.exception(e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doCors(HttpServletResponse response)
|
||||||
|
{
|
||||||
|
response.setHeader("Access-Control-Allow-Origin", ConstantsWeb.WEB_SERVER_URL);
|
||||||
|
response.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS");
|
||||||
|
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doRequest (String action, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
doCors(response);
|
||||||
|
|
||||||
|
byte[] content = Streams.readFullyBytes(request.getInputStream());
|
||||||
|
String resource = request.getParameter(ConstantsMvServer.PARAMETER_RESOURCE);
|
||||||
|
String keyId = StoreWebUtils.verifyUser(action, request, resource, content);
|
||||||
|
|
||||||
|
String version = store.putKeyValue(keyId, resource, content);
|
||||||
|
response.setHeader("Version", version);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
log.exception(e);
|
||||||
|
throw new ServletException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
|
||||||
|
*/
|
||||||
|
protected void doPut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
doRequest(HttpDelegate.PUT, request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doOptions (HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
|
||||||
|
{
|
||||||
|
doCors(response);
|
||||||
|
super.doOptions(request, response);
|
||||||
|
}
|
||||||
|
}
|
67
java/webserver/src/mail/web/StoreWebUtils.java
Normal file
67
java/webserver/src/mail/web/StoreWebUtils.java
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package mail.web;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import core.connector.FileInfo;
|
||||||
|
import core.util.DateFormat;
|
||||||
|
import core.util.LogOut;
|
||||||
|
|
||||||
|
import store.server.ConstantsMvServer;
|
||||||
|
import store.server.StoreUtils;
|
||||||
|
|
||||||
|
public class StoreWebUtils
|
||||||
|
{
|
||||||
|
static LogOut log = new LogOut(StoreWebUtils.class);
|
||||||
|
|
||||||
|
public static String verifyUser (String action, HttpServletRequest request, String resource, byte[] content) throws Exception
|
||||||
|
{
|
||||||
|
String possibleHeaders[] = {
|
||||||
|
ConstantsMvServer.HEADER_DATE,
|
||||||
|
ConstantsMvServer.HEADER_CONTENT_TYPE,
|
||||||
|
ConstantsMvServer.HEADER_CONTENT_LENGTH,
|
||||||
|
ConstantsMvServer.HEADER_AUTHORIZATION
|
||||||
|
};
|
||||||
|
|
||||||
|
Map<String, String> headers = new HashMap<String,String>();
|
||||||
|
for (String possibleHeader : possibleHeaders)
|
||||||
|
{
|
||||||
|
String value = request.getHeader(possibleHeader);
|
||||||
|
if (value != null)
|
||||||
|
headers.put(possibleHeader, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return StoreUtils.verifyUser(action, headers, resource, content);
|
||||||
|
}
|
||||||
|
|
||||||
|
static public String transformFileInfoListToJson (List<FileInfo> fileInfos) throws Exception
|
||||||
|
{
|
||||||
|
DateFormat dateTimeFormat = new DateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z GMT'");
|
||||||
|
|
||||||
|
JSONArray a = new JSONArray();
|
||||||
|
for (FileInfo fileInfo : fileInfos)
|
||||||
|
{
|
||||||
|
JSONObject o = new JSONObject();
|
||||||
|
o.put("path", fileInfo.path);
|
||||||
|
o.put("size", fileInfo.size);
|
||||||
|
o.put("version", fileInfo.version);
|
||||||
|
o.put("date", dateTimeFormat.format(fileInfo.date));
|
||||||
|
|
||||||
|
log.debug ("converted date", fileInfo.date, "to", o.get("date"));
|
||||||
|
|
||||||
|
a.put(o);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject r = new JSONObject();
|
||||||
|
r.put("contents", a);
|
||||||
|
r.put("isTruncated", false);
|
||||||
|
|
||||||
|
return r.toString();
|
||||||
|
}
|
||||||
|
}
|
1
java/webserver/src/store
Symbolic link
1
java/webserver/src/store
Symbolic link
@ -0,0 +1 @@
|
|||||||
|
../../core/src/store
|
@ -8,4 +8,6 @@ openssl pkcs12 -in store.p12 -nocerts -out store.key
|
|||||||
openssl rsa -in store.key -out final.key
|
openssl rsa -in store.key -out final.key
|
||||||
|
|
||||||
rm final.crt
|
rm final.crt
|
||||||
cat authority-response/* >> final.crt
|
cat authority-response/server.crt >> final.crt
|
||||||
|
cat authority-response/PositiveSSLCA2.crt >> final.crt
|
||||||
|
cat authority-response/AddTrustExternalCARoot.crt >> final.crt
|
||||||
|
@ -4,5 +4,6 @@ echo `./make-single-password` > mail
|
|||||||
echo `./make-single-password` > mail-pbe
|
echo `./make-single-password` > mail-pbe
|
||||||
echo `./make-single-password` > mail_extra
|
echo `./make-single-password` > mail_extra
|
||||||
echo `./make-single-password` > push-certificate
|
echo `./make-single-password` > push-certificate
|
||||||
|
echo `./make-single-password` > store
|
||||||
|
|
||||||
|
|
||||||
|
1
passwords/store
Normal file
1
passwords/store
Normal file
@ -0,0 +1 @@
|
|||||||
|
PASSWORD FOR STORE DB USER
|
@ -154,4 +154,4 @@ mDispatch = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
$(document).ready(setTimeout(function() { mDispatch.startWorker(); }, 250));
|
// $(document).ready(setTimeout(function() { mDispatch.startWorker(); }, 250));
|
||||||
|
@ -103,7 +103,7 @@ var mDelegateCommon =
|
|||||||
log("finishing url ", url, " ", this.status);
|
log("finishing url ", url, " ", this.status);
|
||||||
|
|
||||||
var getResponseHeadersHack = function(xhr) {
|
var getResponseHeadersHack = function(xhr) {
|
||||||
var headers = ['ETag','Content-Type', 'x-dropbox-metadata'];
|
var headers = ['ETag','Content-Type', 'x-dropbox-metadata', 'Version'];
|
||||||
var result = [];
|
var result = [];
|
||||||
for (var i=0; i<headers.length; ++i)
|
for (var i=0; i<headers.length; ++i)
|
||||||
{
|
{
|
||||||
|
@ -172,25 +172,27 @@
|
|||||||
<td class="right-side">
|
<td class="right-side">
|
||||||
<div class="inner-td">
|
<div class="inner-td">
|
||||||
I want to use the storage provider:<br/>
|
I want to use the storage provider:<br/>
|
||||||
<label class="checkbox inline"><input name="storage" type="radio" onchange="mSignUp.onStorageChange();" value="mailiverse" checked>Mailiverse</label>
|
<br/>
|
||||||
<label class="checkbox inline"><input name="storage" type="radio" onchange="mSignUp.onStorageChange();" value="dropbox">Dropbox</label>
|
<label class="checkbox inline"><input name="storage" type="radio" onchange="mSignUp.onStorageChange();" value="mailiverse" checked>Mailiverse</label><br/>
|
||||||
|
<label class="checkbox inline"><input name="storage" type="radio" onchange="mSignUp.onStorageChange();" value="s3">Mailiverse (S3 Backed)</label><br>
|
||||||
|
<label class="checkbox inline"><input name="storage" type="radio" onchange="mSignUp.onStorageChange();" value="dropbox">Dropbox</label><br/>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
<tr id="storage_mailiverse" class="storage-option">
|
<tr id="storage_s3" class="storage-option" style="display:none">
|
||||||
<td class="left-side">
|
<td class="left-side">
|
||||||
<div class="inner-td">
|
<div class="inner-td">
|
||||||
<h4>Mailiverse storage</h4>
|
<h4>Mailiverse S3 backed storage</h4>
|
||||||
We provide infinite mail storage.
|
We provide infinite mail storage.
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="right-side">
|
<td class="right-side">
|
||||||
<div class="inner-td">
|
<div class="inner-td">
|
||||||
Mailiverse storage is simple, no hassle. We take care of everything.<br/>
|
Mailiverse S3 backed storage is simple, no hassle. We take care of everything.<br/>
|
||||||
<br/>
|
<br/>
|
||||||
Pick the region you are closest to most of the time.<br/>
|
Pick the region you are closest to most of the time.<br/>
|
||||||
<select id="storage_mailiverse_region">
|
<select id="storage_s3_region">
|
||||||
<option value="US_Standard" selected="selected">US Standard</option>
|
<option value="US_Standard" selected="selected">US Standard</option>
|
||||||
<option value="US_West">US-West (Northern California)</option>
|
<option value="US_West">US-West (Northern California)</option>
|
||||||
<option value="US_West_2">US-West-2 (Oregon)</option>
|
<option value="US_West_2">US-West-2 (Oregon)</option>
|
||||||
@ -204,6 +206,20 @@
|
|||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
|
||||||
|
<tr id="storage_mailiverse" class="storage-option">
|
||||||
|
<td class="left-side">
|
||||||
|
<div class="inner-td">
|
||||||
|
<h4>Mailiverse storage</h4>
|
||||||
|
We provide infinite mail storage. This storage is backed by our local db.
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="right-side">
|
||||||
|
<div class="inner-td">
|
||||||
|
Mailiverse storage is simple, no hassle. We take care of everything.<br/>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<tr id="storage_dropbox" class="storage-option" style="display:none">
|
<tr id="storage_dropbox" class="storage-option" style="display:none">
|
||||||
<td class="left-side">
|
<td class="left-side">
|
||||||
<div class="inner-td">
|
<div class="inner-td">
|
||||||
|
@ -20,7 +20,7 @@ mSignUp = {
|
|||||||
|
|
||||||
onStorageChange: function()
|
onStorageChange: function()
|
||||||
{
|
{
|
||||||
var possible = [ 'mailiverse', 'dropbox' ];
|
var possible = [ 's3', 'mailiverse', 'dropbox' ];
|
||||||
var value = $('input[name=storage]:checked').val();
|
var value = $('input[name=storage]:checked').val();
|
||||||
$('#storage_' + value).show();
|
$('#storage_' + value).show();
|
||||||
|
|
||||||
@ -35,6 +35,11 @@ mSignUp = {
|
|||||||
mSignUp.validate['storageAuthorized'] = true;
|
mSignUp.validate['storageAuthorized'] = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
if (value == 's3')
|
||||||
|
{
|
||||||
|
mSignUp.validate['storageAuthorized'] = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
mSignUp.validate['storageAuthorized'] = false;
|
mSignUp.validate['storageAuthorized'] = false;
|
||||||
mSignUp.manualTestDropboxAlreadyAuthorized();
|
mSignUp.manualTestDropboxAlreadyAuthorized();
|
||||||
@ -296,8 +301,8 @@ mSignUp = {
|
|||||||
$('#_mSignUpExecute').show();
|
$('#_mSignUpExecute').show();
|
||||||
|
|
||||||
var storageInfo = {};
|
var storageInfo = {};
|
||||||
if (mSignUp.storage == "mailiverse")
|
if (mSignUp.storage == "s3")
|
||||||
storageInfo = { region: $('#storage_mailiverse_region').val() };
|
storageInfo = { region: $('#storage_s3_region').val() };
|
||||||
|
|
||||||
var signUpDelegate = {
|
var signUpDelegate = {
|
||||||
progress: function(x) {
|
progress: function(x) {
|
||||||
|
Loading…
Reference in New Issue
Block a user