From a651e8ef73884efbe750efb857df0b83ac5278db Mon Sep 17 00:00:00 2001 From: akwizgran <michael@briarproject.org> Date: Sat, 2 Mar 2013 04:45:02 +0000 Subject: [PATCH] Removed subject line from wire format, added content type. --- .../res/drawable-hdpi/content_attachment.png | Bin 0 -> 1502 bytes .../res/drawable-mdpi/content_attachment.png | Bin 0 -> 1318 bytes .../res/drawable-xhdpi/content_attachment.png | Bin 0 -> 1717 bytes .../android/messages/ConversationAdapter.java | 7 ++ .../messages/ConversationListActivity.java | 14 +-- .../sf/briar/api/db/GroupMessageHeader.java | 8 +- .../net/sf/briar/api/db/MessageHeader.java | 12 ++- .../sf/briar/api/db/PrivateMessageHeader.java | 8 +- .../net/sf/briar/api/messaging/Message.java | 9 +- .../briar/api/messaging/MessageFactory.java | 14 +-- .../api/messaging/MessagingConstants.java | 3 + .../api/messaging/UnverifiedMessage.java | 20 +++- .../sf/briar/db/DatabaseComponentImpl.java | 2 +- .../src/net/sf/briar/db/JdbcDatabase.java | 101 ++++++++++-------- .../briar/messaging/MessageFactoryImpl.java | 47 +++++--- .../net/sf/briar/messaging/MessageImpl.java | 11 +- .../net/sf/briar/messaging/MessageReader.java | 26 ++++- .../briar/messaging/MessageVerifierImpl.java | 5 +- .../net/sf/briar/ProtocolIntegrationTest.java | 10 +- briar-tests/src/net/sf/briar/TestMessage.java | 17 ++- .../sf/briar/db/DatabaseComponentTest.java | 11 +- .../src/net/sf/briar/db/H2DatabaseTest.java | 50 ++++----- .../net/sf/briar/messaging/ConstantsTest.java | 9 +- .../SimplexMessagingIntegrationTest.java | 4 +- 24 files changed, 239 insertions(+), 149 deletions(-) create mode 100644 briar-android/res/drawable-hdpi/content_attachment.png create mode 100644 briar-android/res/drawable-mdpi/content_attachment.png create mode 100644 briar-android/res/drawable-xhdpi/content_attachment.png diff --git a/briar-android/res/drawable-hdpi/content_attachment.png b/briar-android/res/drawable-hdpi/content_attachment.png new file mode 100644 index 0000000000000000000000000000000000000000..53b963d54106ff032f364ac815f513ab91e9bd23 GIT binary patch literal 1502 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%qp275hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8<fR&VF+bTgE72zA8;GAESs$i;Tpqp%9W~g9hqGxDg zU}<8hqhMrUXrOOsq;FuZYiM9)YHnp<r~m~@K--E^(yW49+@N*=dA3R!B_#z``ugSN z<$C4Ddih1^`i7R4mih)p`bI{&Koz>hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83 zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s0<RzFwUtj!6b93RUi%Wu15$?rmaB)aw zL8^XGYH@yPQ8F;%(v(3~6<9eJr6!i-7lq{K=fFZSAS1sdzc?emK*2fKRL@YsH!(Rg z4<rKC;p=PVnO9trn3tUD>0+w{G(#^lGsVip(#+J-%-Ge`$-u?X(ACh=#L&{!#L3yw z&D7A`#K{n**Cju>G&eP`1g19yq1O$kUQlAlEdbi=l3J8mmYU*Ll%J~r_Ow+dZnrq& zG!Lpb1-DyVaO%|uIz}H9wMbD769T3m5EGtofgE_!Pt60S_ab1zZklm1hJk@8z|+Ms zq~g|_nfJYe6D5wDn@33qp7c5r8OY`-?&=$|=Y^KOSZs>;-6y`{u{Y!|_traf1if*~ z-=(q3bFWNC*Oac8IUAI;lcwaYo4b#{hJQ~_aarHHErvC6KMc0*eZJ@X_u9I-8#kmz zE)3hYEuecgR{*1y1M3O~(FIH)4M5J>%^6?WPo`}8wOBeqAcjrdQMt~c<)GaShW7`y z{dHBFyi)hThB5;-wga42a+wbvo~q+4klw@ezSgxtjM-mRVF3@<1LhxRzV~j}T(XbZ zhRy!qrg+BhywA-Kn*6xZA~HQ#p8f6v#vdGBaZHaM@crN}N@#jDSE^yj^~!*i#`ja# zTe{uaqT|t={y=C4pV(fO80O_KuSknOKPuN4!ceMsUHssrW`>QS8@Q_uu-Y^2ir8}h zVAttooNg<RnA~2ydFu46E7usUCmn76x~5S={6FLV*t}bZr)inbpY%@5;kf3mn(HUG zOf%j8hvUb=Jv~<>N^;%arM>QP(Cyw>;cv(lUB~jK;G<-L;2P^S8|O~romcRH#rCSU z&K+%=HKp5%{23ql%oD#~DmWqex<{eY_kYVdLMja64|u!X33izHINEQU{2k`?ve%YM zwkjqEv453F-0xMmzVQE_M757LJ5DB=oyz<nR%3e2<N6H7&1=N96`n7y;WcLZ-Ci}r zcuw`fM=zO`MU;2`KdX3VT4B*wi}+`m;(dQivS#pXc>X|9B2BwnI#)kqGy5&404Aq7 z%#(dqMnBN9IR3gx?4jv}Ifs}1=SM^$Bt{EzSpNtoFf6ujpE0+)JOWhWdb;|#taD0e F0st!fBvt?b literal 0 HcmV?d00001 diff --git a/briar-android/res/drawable-mdpi/content_attachment.png b/briar-android/res/drawable-mdpi/content_attachment.png new file mode 100644 index 0000000000000000000000000000000000000000..38ff9f853ce781299b92b471da4cb9d587100a66 GIT binary patch literal 1318 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdz$r9IylHmNblJdl&R0hYC{G?O` z&)mfH)S%SFl*+=BsWuD@%qp275hW46K32*3xq68pHF_1f1wh>l3^w)^1&PVosU-?Y zsp*+{wo31J?^jaDOtDo8H}y5}EpSfF$n>ZxN)4{^3rViZPPR-@vbR&PsjvbXkegbP zs8ErclUHn2VXFi-*9yo63F|8<fR&VF+bTgE72zA8;GAESs$i;Tpqp%9W~g9hqGxDg zU}<8hqhMrUXrOOsq;FuZYiM9)YHnp<r~m~@K--E^(yW49+@N*=dA3R!B_#z``ugSN z<$C4Ddih1^`i7R4mih)p`bI{&Koz>hm3bwJ6}oxF$}kgLQj3#|G7CyF^YauyCMG83 zmzLNn0bL65LT&-v*t}wBFaZNhzap_f-%!s0<RzFwUtj!6b93RUi%Wu15$?rmaB)aw zL8^XGYH@yPQ8F;%(v(3~6<9eJr6!i-7lq{K=fFZSAS1sdzc?emK*2fKRL@YsH!(Rg z4<rKC;p=PVnO9trn3tUD>0+w{G(#^lGsVip(#+J-%*4pl$-u?X(ACh=#L&{!#L3yw z&D7A`#K{n**Cju>G&eP`1g19ytk==R#nRCXr(RHE$SnZc?2=lPS(cjOR+OKs0QR(1 zCT_PF;4}}aHwCL(!2U4AsaGH97=2LGB1JV!2$+6AOnAZta^OinH4m8Hi+~B6BSroX z0|Vm>PZ!6Kid%1{oz->;6glv`cfI3g1y{|V5huEi>P*=>RVlm7>)Ido8@D4*AG_qX zM#n{Py_(6U0GFR$X+2Iom37<Ct$tl9o!>L7wfa?faen^0-*=18@3cMsd5?#svXo|V z1fzBW>l%lp|CJ|ty!d?f0{_~8SD`N*`1%sh$Dc2~`<|(BdcU*&m4A&5^0lA#<tDSK zNF_?$N?_-E7^-qlQQ!KP=9SN)0lJT^Bw92pnv^Fy*!DQE>l~~~xab$D;p2AYv~j`G zvn$V@IcQ*Wpfq5C_oX^6=|<M}1fEq+Tt^b*pKaZ#qmsyQ%a@5)V0zL=rrm+{yBbA* zaNLZQJX{mgXP9r*WU{BDc0<?VAntUf2Q5=FE*-O7byI=$xmqK)#l)=8qdzo0TWWe- zmE<-m>w3fBU$%bJCa!X|#x-;HzWVPOF~w3ed(y%@+gioNZhapmw>{VtAiYXQ=P=8e zLwa|za%X6LV*1t69ALgsZ1$vofh+$-a9-cDYPRGKeK!TAx09xA%lUb9=5NUW*56?t n6n}^2u&!wk{qdbCo{5Jcry!0&X=_|DsO0i=^>bP0l+XkK9d6U< literal 0 HcmV?d00001 diff --git a/briar-android/res/drawable-xhdpi/content_attachment.png b/briar-android/res/drawable-xhdpi/content_attachment.png new file mode 100644 index 0000000000000000000000000000000000000000..1cffb3fbf2f1149821435933ea6a236ff2663ed5 GIT binary patch literal 1717 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=k|nMYCBgY=CFO}lsSJ)O`AMk? zp1FzXsX?iUDV2pMQ*9U+m{l@EB1$5BeXNr6bM+EIYV;~{3xK*A7;Nk-3KEmEQ%e+* zQqwc@Y?a>c-mj#PnPRIHZt82`Ti~3Uk?B!Ylp0*+7m{3+ootz+WN)WnQ(*-(AUCxn zQK2F?C$HG5!d3}vt`(3C64qBz04piUwpD^SD#ABF!8yMuRl!uxKsVXI%uvD1M9<K~ zz|zE0N5ROz&_LhNNZ-I**U-Sq)ZEIzPyq^*fVLH-q*(>IxIyg#@@$ndN=gc>^!3Zj z%k|2Q_413-^$jg8E%gnI^o@*kfhu&1EAvVcD|GXUm0>2hq!uR^WfqiV=I1GZOiWD5 zFD<cE0=g99h1>$Tv3bSNU;+l1ennz|zM-B0$V)JVzP|XC=H|jx7ncO3BHWAB;Np<V zf>iyW)Z+ZoqGVvir744~DzI`cN=+=uFAB-e&w+(vKt_H^esM;Afr4|esh**NZ(?$0 z9!LbN!`Ii!Gq1QLF)umQ)5TT^Xog;9W{Q=GrJ1RvnX#j(lYxt&p{t>#iJ_&diIcOV zo2j9>iIX8ruS<S%X>Mv>2~2MaLa!4}y`aR9TL84#CABECEH%ZgC_h&L>}jh^+-|YJ zX&zK>3U0Sp;?%1Tbc{YIYLTKECIn1BASOKF0y*%cpPC0u??u3b%`?qzFEGETd%8G= zRNQ(q!#i6zP@>H^xo2ya$Hgk=Jy*E07IFu(WM5gky*0t{&W<as+=Y+N7Y1&WKG@1F z-c_-1m%)~b+dBfKrv^D*c8gA)EP0>*UZdmeGnSc;C103-xWMLD^vvdS>^Vt&p2KH~ z_SuLoU<zsA3SiW7U|qq0g>&Nh=iX!MnSVRV-<Y;(>yHQ472I(RpYAhv9erdUe=5pH zq1%q}Tf<b9-0->IEgABf%hj&=tlRuRYyLiVCckOR{%|JOS06MD@c0!J#Bw63{eY$c ze_b<Q0OR}vJg!TW<~oYMU^I1m!TO;$^Wvn2#}8Ci6g7!H5UgPG5}CAYb@M}g{#@RO zv;Xaz<hL>HIw;w;+kdt4gTk)vU-}<J{;*7!n7jLcqurJZAr1bMr4Py+ziS$?r{!+o zvxH^7rcTc)*pAKWkxW*XSi%x{+9LRx$APGVhDv>-eGR|azCKZ6t;ps39Msg{;nbM9 zt69@9`4+3ofv{V`k6oK<-Y@^CwOFlS4&UX3Y1txXH?A;n{*`f#IOZeabK`vHqFEnT z1wM>y648+CiFR#D6U@BC_B<kH(l_C|I#Vpg7D@Mg=d67bReJCLl(TLbT4J9fn|Xt; zC@sD}r)1BMxoccQ@BL@LZD!%kX&W=)O0&7I8jnSt{!vkhWvShFp9RGf$?rax`Ht~b zjm7z!QoXDpJF0ITXFd7yh2!KyVw+ycJ^LTzyw2j5>a!g$q^yrwyq<V9QsKdLtv@>K z3zRv9_p>ZsU_4DMlHG-W<z(vvg3Fpp1#8ZKEARQ;SbXNKo4Ssn-I)%_2m9{0%C7hv zp~L^=oYV27+20vwA1K{0Z~p$K*$+w&`R1hG|0~b5Ct~(z4TpE1H=q2?Fj-vb)59X2 z)Mq=-$~<+s%&oI!+OcM*)%q?^qPHKY+-BAP^??BE6j{0Y*F7grhSeYW(tE*KudHMF z>J=+;(z;7j6;^$jS;l?B;Jx~dS8O+5)!gfN@8PiFMsxVJqCHQ3+g@vk%d6S;L9?Y# sX~C`)@)xf^!j&K)Nwwi=$zQ<)2K8#|<Q1=rB|sI4r>mdKI;Vst0E}vobpQYW literal 0 HcmV?d00001 diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationAdapter.java b/briar-android/src/net/sf/briar/android/messages/ConversationAdapter.java index 67c6c629b7..31fdd1dcc8 100644 --- a/briar-android/src/net/sf/briar/android/messages/ConversationAdapter.java +++ b/briar-android/src/net/sf/briar/android/messages/ConversationAdapter.java @@ -45,6 +45,13 @@ implements OnItemClickListener { else star.setImageResource(R.drawable.rating_not_important); layout.addView(star); + if(!item.getContentType().equals("text/plain")) { + ImageView attachment = new ImageView(ctx); + attachment.setPadding(0, 5, 5, 5); + attachment.setImageResource(R.drawable.content_attachment); + layout.addView(attachment); + } + TextView subject = new TextView(ctx); // Give me all the unused width subject.setLayoutParams(new LayoutParams(WRAP_CONTENT, WRAP_CONTENT, diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java b/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java index f09c7dabed..b54a41827e 100644 --- a/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java +++ b/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java @@ -112,21 +112,21 @@ implements OnClickListener, DatabaseListener { ContactId contactId = db.addContact("Carol"); // Insert some fake messages to and from the contact Message m = messageFactory.createPrivateMessage(null, - "First message's subject is short", - "First message's body".getBytes("UTF-8")); + "text/plain", + "First message is short".getBytes("UTF-8")); db.addLocalPrivateMessage(m, contactId); db.setReadFlag(m.getId(), true); db.setStarredFlag(m.getId(), true); Thread.sleep(1000); m = messageFactory.createPrivateMessage(m.getId(), - "Second message's subject is also short", - "Second message's body".getBytes("UTF-8")); + "image/jpeg", new byte[1000]); db.receiveMessage(contactId, m); Thread.sleep(1000); m = messageFactory.createPrivateMessage(m.getId(), - "Third message's subject is quite long to test" - + " line wrapping and exciting stuff like that", - "Third message's body".getBytes("UTF-8")); + "text/plain", + ("Third message is quite long to test line" + + " wrapping and subject line extraction and" + + " all that fun stuff").getBytes("UTF-8")); db.addLocalPrivateMessage(m, contactId); db.setReadFlag(m.getId(), true); } diff --git a/briar-api/src/net/sf/briar/api/db/GroupMessageHeader.java b/briar-api/src/net/sf/briar/api/db/GroupMessageHeader.java index af8add02b3..543f34a939 100644 --- a/briar-api/src/net/sf/briar/api/db/GroupMessageHeader.java +++ b/briar-api/src/net/sf/briar/api/db/GroupMessageHeader.java @@ -9,10 +9,10 @@ public class GroupMessageHeader extends MessageHeader { private final GroupId groupId; private final Author author; - public GroupMessageHeader(MessageId id, MessageId parent, String subject, - long timestamp, boolean read, boolean starred, GroupId groupId, - Author author) { - super(id, parent, subject, timestamp, read, starred); + public GroupMessageHeader(MessageId id, MessageId parent, + String contentType, String subject, long timestamp, boolean read, + boolean starred, GroupId groupId, Author author) { + super(id, parent, contentType, subject, timestamp, read, starred); this.groupId = groupId; this.author = author; } diff --git a/briar-api/src/net/sf/briar/api/db/MessageHeader.java b/briar-api/src/net/sf/briar/api/db/MessageHeader.java index b1f11d1bd5..2cbab3f51c 100644 --- a/briar-api/src/net/sf/briar/api/db/MessageHeader.java +++ b/briar-api/src/net/sf/briar/api/db/MessageHeader.java @@ -5,14 +5,15 @@ import net.sf.briar.api.messaging.MessageId; public abstract class MessageHeader { private final MessageId id, parent; - private final String subject; + private final String contentType, subject; private final long timestamp; private final boolean read, starred; - protected MessageHeader(MessageId id, MessageId parent, String subject, - long timestamp, boolean read, boolean starred) { + protected MessageHeader(MessageId id, MessageId parent, String contentType, + String subject, long timestamp, boolean read, boolean starred) { this.id = id; this.parent = parent; + this.contentType = contentType; this.subject = subject; this.timestamp = timestamp; this.read = read; @@ -32,6 +33,11 @@ public abstract class MessageHeader { return parent; } + /** Returns the message's content type. */ + public String getContentType() { + return contentType; + } + /** Returns the message's subject line. */ public String getSubject() { return subject; diff --git a/briar-api/src/net/sf/briar/api/db/PrivateMessageHeader.java b/briar-api/src/net/sf/briar/api/db/PrivateMessageHeader.java index 900c2cb2a9..af55211c66 100644 --- a/briar-api/src/net/sf/briar/api/db/PrivateMessageHeader.java +++ b/briar-api/src/net/sf/briar/api/db/PrivateMessageHeader.java @@ -8,10 +8,10 @@ public class PrivateMessageHeader extends MessageHeader { private final ContactId contactId; private final boolean incoming; - public PrivateMessageHeader(MessageId id, MessageId parent, String subject, - long timestamp, boolean read, boolean starred, ContactId contactId, - boolean incoming) { - super(id, parent, subject, timestamp, read, starred); + public PrivateMessageHeader(MessageId id, MessageId parent, + String contentType, String subject, long timestamp, boolean read, + boolean starred, ContactId contactId, boolean incoming) { + super(id, parent, contentType, subject, timestamp, read, starred); this.contactId = contactId; this.incoming = incoming; } diff --git a/briar-api/src/net/sf/briar/api/messaging/Message.java b/briar-api/src/net/sf/briar/api/messaging/Message.java index f2aac57fba..b48d54cc06 100644 --- a/briar-api/src/net/sf/briar/api/messaging/Message.java +++ b/briar-api/src/net/sf/briar/api/messaging/Message.java @@ -23,7 +23,14 @@ public interface Message { */ Author getAuthor(); - /** Returns the message's subject line. */ + /** Returns the message's content type. */ + String getContentType(); + + /** + * Returns the message's subject line, which is created from the first 50 + * bytes of the message body if the content type is text/plain, or is the + * empty string otherwise. + */ String getSubject(); /** Returns the timestamp created by the message's {@link Author}. */ diff --git a/briar-api/src/net/sf/briar/api/messaging/MessageFactory.java b/briar-api/src/net/sf/briar/api/messaging/MessageFactory.java index 25dee5e10c..ade4acda4e 100644 --- a/briar-api/src/net/sf/briar/api/messaging/MessageFactory.java +++ b/briar-api/src/net/sf/briar/api/messaging/MessageFactory.java @@ -7,27 +7,27 @@ import java.security.PrivateKey; public interface MessageFactory { /** Creates a private message. */ - Message createPrivateMessage(MessageId parent, String subject, byte[] body) - throws IOException, GeneralSecurityException; + Message createPrivateMessage(MessageId parent, String contentType, + byte[] body) throws IOException, GeneralSecurityException; /** Creates an anonymous message to an unrestricted group. */ Message createAnonymousGroupMessage(MessageId parent, Group group, - String subject, byte[] body) throws IOException, + String contentType, byte[] body) throws IOException, GeneralSecurityException; /** Creates an anonymous message to a restricted group. */ Message createAnonymousGroupMessage(MessageId parent, Group group, - PrivateKey groupKey, String subject, byte[] body) + PrivateKey groupKey, String contentType, byte[] body) throws IOException, GeneralSecurityException; /** Creates a pseudonymous message to an unrestricted group. */ Message createPseudonymousMessage(MessageId parent, Group group, - Author author, PrivateKey authorKey, String subject, byte[] body) - throws IOException, GeneralSecurityException; + Author author, PrivateKey authorKey, String contentType, + byte[] body) throws IOException, GeneralSecurityException; /** Creates a pseudonymous message to a restricted group. */ Message createPseudonymousMessage(MessageId parent, Group group, PrivateKey groupKey, Author author, PrivateKey authorKey, - String subject, byte[] body) throws IOException, + String contentType, byte[] body) throws IOException, GeneralSecurityException; } diff --git a/briar-api/src/net/sf/briar/api/messaging/MessagingConstants.java b/briar-api/src/net/sf/briar/api/messaging/MessagingConstants.java index 5f3f93ac28..4ddcedf2c5 100644 --- a/briar-api/src/net/sf/briar/api/messaging/MessagingConstants.java +++ b/briar-api/src/net/sf/briar/api/messaging/MessagingConstants.java @@ -36,6 +36,9 @@ public interface MessagingConstants { */ int MAX_BODY_LENGTH = MAX_PACKET_LENGTH - 1024; + /** The maximum length of a message's content type in UTF-8 bytes. */ + int MAX_CONTENT_TYPE_LENGTH = 50; + /** The maximum length of a message's subject line in UTF-8 bytes. */ int MAX_SUBJECT_LENGTH = 100; diff --git a/briar-api/src/net/sf/briar/api/messaging/UnverifiedMessage.java b/briar-api/src/net/sf/briar/api/messaging/UnverifiedMessage.java index cf1fcf2ce4..83c81e5555 100644 --- a/briar-api/src/net/sf/briar/api/messaging/UnverifiedMessage.java +++ b/briar-api/src/net/sf/briar/api/messaging/UnverifiedMessage.java @@ -6,18 +6,19 @@ public class UnverifiedMessage { private final MessageId parent; private final Group group; private final Author author; - private final String subject; + private final String contentType, subject; private final long timestamp; private final byte[] raw, authorSig, groupSig; private final int bodyStart, bodyLength, signedByAuthor, signedByGroup; public UnverifiedMessage(MessageId parent, Group group, Author author, - String subject, long timestamp, byte[] raw, byte[] authorSig, - byte[] groupSig, int bodyStart, int bodyLength, int signedByAuthor, - int signedByGroup) { + String contentType, String subject, long timestamp, byte[] raw, + byte[] authorSig, byte[] groupSig, int bodyStart, int bodyLength, + int signedByAuthor, int signedByGroup) { this.parent = parent; this.group = group; this.author = author; + this.contentType = contentType; this.subject = subject; this.timestamp = timestamp; this.raw = raw; @@ -53,7 +54,16 @@ public class UnverifiedMessage { return author; } - /** Returns the message's subject line. */ + /** Returns the message's content type. */ + public String getContentType() { + return contentType; + } + + /** + * Returns the message's subject line, which is created from the first 50 + * bytes of the message body if the content type is text/plain, or is the + * empty string otherwise. + */ public String getSubject() { return subject; } diff --git a/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java b/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java index 299f52bd4e..888acb4642 100644 --- a/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java +++ b/briar-core/src/net/sf/briar/db/DatabaseComponentImpl.java @@ -472,7 +472,7 @@ DatabaseCleaner.Callback { if(m.getGroup() != null) throw new IllegalArgumentException(); if(m.getAuthor() != null) throw new IllegalArgumentException(); if(!db.addPrivateMessage(txn, m, c)) return false; - db.addStatus(txn, c, m.getId(), !incoming); + db.addStatus(txn, c, m.getId(), incoming); // Count the bytes stored synchronized(spaceLock) { bytesStoredSinceLastCheck += m.getSerialised().length; diff --git a/briar-core/src/net/sf/briar/db/JdbcDatabase.java b/briar-core/src/net/sf/briar/db/JdbcDatabase.java index 45ec3fd7f3..4836072a9e 100644 --- a/briar-core/src/net/sf/briar/db/JdbcDatabase.java +++ b/briar-core/src/net/sf/briar/db/JdbcDatabase.java @@ -125,6 +125,7 @@ abstract class JdbcDatabase implements Database<Connection> { + " authorId HASH," // Null for private/anon messages + " authorName VARCHAR," // Null for private/anon messages + " authorKey VARCHAR," // Null for private/anon messages + + " contentType VARCHAR NOT NULL," + " subject VARCHAR NOT NULL," + " timestamp BIGINT NOT NULL," + " length INT NOT NULL," @@ -633,10 +634,10 @@ abstract class JdbcDatabase implements Database<Connection> { PreparedStatement ps = null; try { String sql = "INSERT INTO messages (messageId, parentId, groupId," - + " authorId, authorName, authorKey, subject, timestamp," - + " length, bodyStart, bodyLength, raw, sendability, read," - + " starred)" - + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ZERO()," + + " authorId, authorName, authorKey, contentType, subject," + + " timestamp, length, bodyStart, bodyLength, raw," + + " sendability, read, starred)" + + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ZERO()," + " FALSE, FALSE)"; ps = txn.prepareStatement(sql); ps.setBytes(1, m.getId().getBytes()); @@ -653,13 +654,14 @@ abstract class JdbcDatabase implements Database<Connection> { ps.setString(5, a.getName()); ps.setBytes(6, a.getPublicKey()); } - ps.setString(7, m.getSubject()); - ps.setLong(8, m.getTimestamp()); + ps.setString(7, m.getContentType()); + ps.setString(8, m.getSubject()); + ps.setLong(9, m.getTimestamp()); byte[] raw = m.getSerialised(); - ps.setInt(9, raw.length); - ps.setInt(10, m.getBodyStart()); - ps.setInt(11, m.getBodyLength()); - ps.setBytes(12, raw); + ps.setInt(10, raw.length); + ps.setInt(11, m.getBodyStart()); + ps.setInt(12, m.getBodyLength()); + ps.setBytes(13, raw); int affected = ps.executeUpdate(); if(affected != 1) throw new DbStateException(); ps.close(); @@ -707,22 +709,23 @@ abstract class JdbcDatabase implements Database<Connection> { if(containsMessage(txn, m.getId())) return false; PreparedStatement ps = null; try { - String sql = "INSERT INTO messages (messageId, parentId, subject," - + " timestamp, length, bodyStart, bodyLength, raw," - + " contactId, read, starred)" - + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, FALSE, FALSE)"; + String sql = "INSERT INTO messages (messageId, parentId," + + " contentType, subject, timestamp, length, bodyStart," + + " bodyLength, raw, contactId, read, starred)" + + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, FALSE, FALSE)"; ps = txn.prepareStatement(sql); ps.setBytes(1, m.getId().getBytes()); if(m.getParent() == null) ps.setNull(2, BINARY); else ps.setBytes(2, m.getParent().getBytes()); - ps.setString(3, m.getSubject()); - ps.setLong(4, m.getTimestamp()); + ps.setString(3, m.getContentType()); + ps.setString(4, m.getSubject()); + ps.setLong(5, m.getTimestamp()); byte[] raw = m.getSerialised(); - ps.setInt(5, raw.length); - ps.setInt(6, m.getBodyStart()); - ps.setInt(7, m.getBodyLength()); - ps.setBytes(8, raw); - ps.setInt(9, c.getInt()); + ps.setInt(6, raw.length); + ps.setInt(7, m.getBodyStart()); + ps.setInt(8, m.getBodyLength()); + ps.setBytes(9, raw); + ps.setInt(10, c.getInt()); int affected = ps.executeUpdate(); if(affected != 1) throw new DbStateException(); ps.close(); @@ -1226,7 +1229,8 @@ abstract class JdbcDatabase implements Database<Connection> { ResultSet rs = null; try { String sql = "SELECT messageId, parentId, authorId, authorName," - + " authorKey, subject, timestamp, read, starred" + + " authorKey, contentType, subject, timestamp, read," + + " starred" + " FROM messages" + " WHERE groupId = ?"; ps = txn.prepareStatement(sql); @@ -1246,12 +1250,13 @@ abstract class JdbcDatabase implements Database<Connection> { byte[] authorKey = rs.getBytes(5); author = new Author(authorId, authorName, authorKey); } - String subject = rs.getString(6); - long timestamp = rs.getLong(7); - boolean read = rs.getBoolean(8); - boolean starred = rs.getBoolean(9); - headers.add(new GroupMessageHeader(id, parent, subject, - timestamp, read, starred, g, author)); + String contentType = rs.getString(6); + String subject = rs.getString(7); + long timestamp = rs.getLong(8); + boolean read = rs.getBoolean(9); + boolean starred = rs.getBoolean(10); + headers.add(new GroupMessageHeader(id, parent, contentType, + subject, timestamp, read, starred, g, author)); } rs.close(); ps.close(); @@ -1268,8 +1273,8 @@ abstract class JdbcDatabase implements Database<Connection> { PreparedStatement ps = null; ResultSet rs = null; try { - String sql = "SELECT m.messageId, parentId, subject, timestamp," - + " m.contactId, read, starred, seen" + String sql = "SELECT m.messageId, parentId, contentType, subject," + + " timestamp, m.contactId, read, starred, seen" + " FROM messages AS m" + " JOIN statuses AS s" + " ON m.messageId = s.messageId" @@ -1283,14 +1288,15 @@ abstract class JdbcDatabase implements Database<Connection> { MessageId id = new MessageId(rs.getBytes(1)); byte[] b = rs.getBytes(2); MessageId parent = b == null ? null : new MessageId(b); - String subject = rs.getString(3); - long timestamp = rs.getLong(4); - ContactId contactId = new ContactId(rs.getInt(5)); - boolean read = rs.getBoolean(6); - boolean starred = rs.getBoolean(7); - boolean seen = rs.getBoolean(8); - headers.add(new PrivateMessageHeader(id, parent, subject, - timestamp, read, starred, contactId, !seen)); + String contentType = rs.getString(3); + String subject = rs.getString(4); + long timestamp = rs.getLong(5); + ContactId contactId = new ContactId(rs.getInt(6)); + boolean read = rs.getBoolean(7); + boolean starred = rs.getBoolean(8); + boolean seen = rs.getBoolean(9); + headers.add(new PrivateMessageHeader(id, parent, contentType, + subject, timestamp, read, starred, contactId, seen)); } rs.close(); ps.close(); @@ -1307,8 +1313,8 @@ abstract class JdbcDatabase implements Database<Connection> { PreparedStatement ps = null; ResultSet rs = null; try { - String sql = "SELECT m.messageId, parentId, subject, timestamp," - + " read, starred, seen" + String sql = "SELECT m.messageId, parentId, contentType, subject," + + " timestamp, read, starred, seen" + " FROM messages AS m" + " JOIN statuses AS s" + " ON m.messageId = s.messageId" @@ -1323,13 +1329,14 @@ abstract class JdbcDatabase implements Database<Connection> { MessageId id = new MessageId(rs.getBytes(1)); byte[] b = rs.getBytes(2); MessageId parent = b == null ? null : new MessageId(b); - String subject = rs.getString(3); - long timestamp = rs.getLong(4); - boolean read = rs.getBoolean(5); - boolean starred = rs.getBoolean(6); - boolean seen = rs.getBoolean(7); - headers.add(new PrivateMessageHeader(id, parent, subject, - timestamp, read, starred, c, !seen)); + String contentType = rs.getString(3); + String subject = rs.getString(4); + long timestamp = rs.getLong(5); + boolean read = rs.getBoolean(6); + boolean starred = rs.getBoolean(7); + boolean seen = rs.getBoolean(8); + headers.add(new PrivateMessageHeader(id, parent, contentType, + subject, timestamp, read, starred, c, seen)); } rs.close(); ps.close(); diff --git a/briar-core/src/net/sf/briar/messaging/MessageFactoryImpl.java b/briar-core/src/net/sf/briar/messaging/MessageFactoryImpl.java index 43d5f0f4b9..bf329c80c4 100644 --- a/briar-core/src/net/sf/briar/messaging/MessageFactoryImpl.java +++ b/briar-core/src/net/sf/briar/messaging/MessageFactoryImpl.java @@ -1,6 +1,7 @@ package net.sf.briar.messaging; import static net.sf.briar.api.messaging.MessagingConstants.MAX_BODY_LENGTH; +import static net.sf.briar.api.messaging.MessagingConstants.MAX_CONTENT_TYPE_LENGTH; import static net.sf.briar.api.messaging.MessagingConstants.MAX_PACKET_LENGTH; import static net.sf.briar.api.messaging.MessagingConstants.MAX_SIGNATURE_LENGTH; import static net.sf.briar.api.messaging.MessagingConstants.MAX_SUBJECT_LENGTH; @@ -11,6 +12,9 @@ import static net.sf.briar.api.messaging.Types.MESSAGE; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; import java.security.GeneralSecurityException; import java.security.PrivateKey; import java.security.SecureRandom; @@ -40,6 +44,7 @@ class MessageFactoryImpl implements MessageFactory { private final MessageDigest messageDigest; private final WriterFactory writerFactory; private final Clock clock; + private final CharsetDecoder decoder; @Inject MessageFactoryImpl(CryptoComponent crypto, WriterFactory writerFactory, @@ -50,44 +55,46 @@ class MessageFactoryImpl implements MessageFactory { messageDigest = crypto.getMessageDigest(); this.writerFactory = writerFactory; this.clock = clock; + decoder = Charset.forName("UTF-8").newDecoder(); } - public Message createPrivateMessage(MessageId parent, String subject, + public Message createPrivateMessage(MessageId parent, String contentType, byte[] body) throws IOException, GeneralSecurityException { - return createMessage(parent, null, null, null, null, subject, body); + return createMessage(parent, null, null, null, null, contentType, body); } public Message createAnonymousGroupMessage(MessageId parent, Group group, - String subject, byte[] body) throws IOException, + String contentType, byte[] body) throws IOException, GeneralSecurityException { - return createMessage(parent, group, null, null, null, subject, body); + return createMessage(parent, group, null, null, null, contentType, + body); } public Message createAnonymousGroupMessage(MessageId parent, Group group, - PrivateKey groupKey, String subject, byte[] body) + PrivateKey groupKey, String contentType, byte[] body) throws IOException, GeneralSecurityException { - return createMessage(parent, group, groupKey, null, null, subject, + return createMessage(parent, group, groupKey, null, null, contentType, body); } public Message createPseudonymousMessage(MessageId parent, Group group, - Author author, PrivateKey authorKey, String subject, byte[] body) + Author author, PrivateKey authorKey, String contentType, byte[] body) throws IOException, GeneralSecurityException { - return createMessage(parent, group, null, author, authorKey, subject, - body); + return createMessage(parent, group, null, author, authorKey, + contentType, body); } public Message createPseudonymousMessage(MessageId parent, Group group, PrivateKey groupKey, Author author, PrivateKey authorKey, - String subject, byte[] body) throws IOException, + String contentType, byte[] body) throws IOException, GeneralSecurityException { return createMessage(parent, group, groupKey, author, authorKey, - subject, body); + contentType, body); } private Message createMessage(MessageId parent, Group group, PrivateKey groupKey, Author author, PrivateKey authorKey, - String subject, byte[] body) throws IOException, + String contentType, byte[] body) throws IOException, GeneralSecurityException { // Validate the arguments if((author == null) != (authorKey == null)) @@ -95,7 +102,7 @@ class MessageFactoryImpl implements MessageFactory { if((group == null || group.getPublicKey() == null) != (groupKey == null)) throw new IllegalArgumentException(); - if(subject.getBytes("UTF-8").length > MAX_SUBJECT_LENGTH) + if(contentType.getBytes("UTF-8").length > MAX_CONTENT_TYPE_LENGTH) throw new IllegalArgumentException(); if(body.length > MAX_BODY_LENGTH) throw new IllegalArgumentException(); @@ -127,7 +134,7 @@ class MessageFactoryImpl implements MessageFactory { else writeGroup(w, group); if(author == null) w.writeNull(); else writeAuthor(w, author); - w.writeString(subject); + w.writeString(contentType); long timestamp = clock.currentTimeMillis(); w.writeInt64(timestamp); byte[] salt = new byte[SALT_LENGTH]; @@ -158,7 +165,17 @@ class MessageFactoryImpl implements MessageFactory { // Hash the message, including the signatures, to get the message ID w.removeConsumer(digestingConsumer); MessageId id = new MessageId(messageDigest.digest()); - return new MessageImpl(id, parent, group, author, subject, + // If the content type is text/plain, extract a subject line + String subject; + if(contentType.equals("text/plain")) { + byte[] start = new byte[Math.min(MAX_SUBJECT_LENGTH, body.length)]; + System.arraycopy(body, 0, start, 0, start.length); + decoder.reset(); + subject = decoder.decode(ByteBuffer.wrap(start)).toString(); + } else { + subject = ""; + } + return new MessageImpl(id, parent, group, author, contentType, subject, timestamp, out.toByteArray(), bodyStart, body.length); } diff --git a/briar-core/src/net/sf/briar/messaging/MessageImpl.java b/briar-core/src/net/sf/briar/messaging/MessageImpl.java index 3472613223..4ff50f3102 100644 --- a/briar-core/src/net/sf/briar/messaging/MessageImpl.java +++ b/briar-core/src/net/sf/briar/messaging/MessageImpl.java @@ -12,14 +12,14 @@ class MessageImpl implements Message { private final MessageId id, parent; private final Group group; private final Author author; - private final String subject; + private final String contentType, subject; private final long timestamp; private final byte[] raw; private final int bodyStart, bodyLength; public MessageImpl(MessageId id, MessageId parent, Group group, - Author author, String subject, long timestamp, byte[] raw, - int bodyStart, int bodyLength) { + Author author, String contentType, String subject, long timestamp, + byte[] raw, int bodyStart, int bodyLength) { if(bodyStart + bodyLength > raw.length) throw new IllegalArgumentException(); if(bodyLength > MAX_BODY_LENGTH) @@ -28,6 +28,7 @@ class MessageImpl implements Message { this.parent = parent; this.group = group; this.author = author; + this.contentType = contentType; this.subject = subject; this.timestamp = timestamp; this.raw = raw; @@ -51,6 +52,10 @@ class MessageImpl implements Message { return author; } + public String getContentType() { + return contentType; + } + public String getSubject() { return subject; } diff --git a/briar-core/src/net/sf/briar/messaging/MessageReader.java b/briar-core/src/net/sf/briar/messaging/MessageReader.java index 0345b70c6e..de0bf74ac5 100644 --- a/briar-core/src/net/sf/briar/messaging/MessageReader.java +++ b/briar-core/src/net/sf/briar/messaging/MessageReader.java @@ -1,6 +1,7 @@ package net.sf.briar.messaging; import static net.sf.briar.api.messaging.MessagingConstants.MAX_BODY_LENGTH; +import static net.sf.briar.api.messaging.MessagingConstants.MAX_CONTENT_TYPE_LENGTH; import static net.sf.briar.api.messaging.MessagingConstants.MAX_PACKET_LENGTH; import static net.sf.briar.api.messaging.MessagingConstants.MAX_SIGNATURE_LENGTH; import static net.sf.briar.api.messaging.MessagingConstants.MAX_SUBJECT_LENGTH; @@ -8,6 +9,9 @@ import static net.sf.briar.api.messaging.MessagingConstants.SALT_LENGTH; import static net.sf.briar.api.messaging.Types.MESSAGE; import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.CharsetDecoder; import net.sf.briar.api.FormatException; import net.sf.briar.api.messaging.Author; @@ -24,11 +28,13 @@ class MessageReader implements StructReader<UnverifiedMessage> { private final StructReader<Group> groupReader; private final StructReader<Author> authorReader; + private final CharsetDecoder decoder; MessageReader(StructReader<Group> groupReader, StructReader<Author> authorReader) { this.groupReader = groupReader; this.authorReader = authorReader; + decoder = Charset.forName("UTF-8").newDecoder(); } public UnverifiedMessage readStruct(Reader r) throws IOException { @@ -55,8 +61,8 @@ class MessageReader implements StructReader<UnverifiedMessage> { Author author = null; if(r.hasNull()) r.readNull(); else author = authorReader.readStruct(r); - // Read the subject - String subject = r.readString(MAX_SUBJECT_LENGTH); + // Read the content type + String contentType = r.readString(MAX_CONTENT_TYPE_LENGTH); // Read the timestamp long timestamp = r.readInt64(); if(timestamp < 0) throw new FormatException(); @@ -65,6 +71,16 @@ class MessageReader implements StructReader<UnverifiedMessage> { if(salt.length < SALT_LENGTH) throw new FormatException(); // Read the message body byte[] body = r.readBytes(MAX_BODY_LENGTH); + // If the content type is text/plain, extract a subject line + String subject; + if(contentType.equals("text/plain")) { + byte[] start = new byte[Math.min(MAX_SUBJECT_LENGTH, body.length)]; + System.arraycopy(body, 0, start, 0, start.length); + decoder.reset(); + subject = decoder.decode(ByteBuffer.wrap(start)).toString(); + } else { + subject = ""; + } // Record the offset of the body within the message int bodyStart = (int) counting.getCount() - body.length; // Record the length of the data covered by the author's signature @@ -83,8 +99,8 @@ class MessageReader implements StructReader<UnverifiedMessage> { r.removeConsumer(counting); r.removeConsumer(copying); byte[] raw = copying.getCopy(); - return new UnverifiedMessage(parent, group, author, subject, timestamp, - raw, authorSig, groupSig, bodyStart, body.length, - signedByAuthor, signedByGroup); + return new UnverifiedMessage(parent, group, author, contentType, + subject, timestamp, raw, authorSig, groupSig, bodyStart, + body.length, signedByAuthor, signedByGroup); } } diff --git a/briar-core/src/net/sf/briar/messaging/MessageVerifierImpl.java b/briar-core/src/net/sf/briar/messaging/MessageVerifierImpl.java index e1dc4896e7..22abc26555 100644 --- a/briar-core/src/net/sf/briar/messaging/MessageVerifierImpl.java +++ b/briar-core/src/net/sf/briar/messaging/MessageVerifierImpl.java @@ -53,7 +53,8 @@ class MessageVerifierImpl implements MessageVerifier { if(!signature.verify(m.getGroupSignature())) throw new GeneralSecurityException(); } - return new MessageImpl(id, m.getParent(), group, author, m.getSubject(), - m.getTimestamp(), raw, m.getBodyStart(), m.getBodyLength()); + return new MessageImpl(id, m.getParent(), group, author, + m.getContentType(), m.getSubject(), m.getTimestamp(), raw, + m.getBodyStart(), m.getBodyLength()); } } diff --git a/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java b/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java index 18aff79214..e838923c98 100644 --- a/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java +++ b/briar-tests/src/net/sf/briar/ProtocolIntegrationTest.java @@ -70,7 +70,7 @@ public class ProtocolIntegrationTest extends BriarTestCase { private final Group group, group1; private final Message message, message1, message2, message3; private final String authorName = "Alice"; - private final String subject = "Hello"; + private final String contentType = "text/plain"; private final String messageBody = "Hello world"; private final Collection<MessageId> messageIds; private final TransportId transportId; @@ -107,16 +107,16 @@ public class ProtocolIntegrationTest extends BriarTestCase { // Create two messages to each group: one anonymous, one pseudonymous MessageFactory messageFactory = i.getInstance(MessageFactory.class); message = messageFactory.createAnonymousGroupMessage(null, group, - subject, messageBody.getBytes("UTF-8")); + contentType, messageBody.getBytes("UTF-8")); message1 = messageFactory.createAnonymousGroupMessage(null, group1, - groupKeyPair.getPrivate(), subject, + groupKeyPair.getPrivate(), contentType, messageBody.getBytes("UTF-8")); message2 = messageFactory.createPseudonymousMessage(null, group, - author, authorKeyPair.getPrivate(), subject, + author, authorKeyPair.getPrivate(), contentType, messageBody.getBytes("UTF-8")); message3 = messageFactory.createPseudonymousMessage(null, group1, groupKeyPair.getPrivate(), author, authorKeyPair.getPrivate(), - subject, messageBody.getBytes("UTF-8")); + contentType, messageBody.getBytes("UTF-8")); messageIds = Arrays.asList(message.getId(), message1.getId(), message2.getId(), message3.getId()); // Create some transport properties diff --git a/briar-tests/src/net/sf/briar/TestMessage.java b/briar-tests/src/net/sf/briar/TestMessage.java index 0c4ae532a9..9a8283505e 100644 --- a/briar-tests/src/net/sf/briar/TestMessage.java +++ b/briar-tests/src/net/sf/briar/TestMessage.java @@ -13,23 +13,26 @@ public class TestMessage implements Message { private final MessageId id, parent; private final Group group; private final Author author; - private final String subject; + private final String contentType, subject; private final long timestamp; private final byte[] raw; private final int bodyStart, bodyLength; public TestMessage(MessageId id, MessageId parent, Group group, - Author author, String subject, long timestamp, byte[] raw) { - this(id, parent, group, author, subject, timestamp, raw, 0, raw.length); + Author author, String contentType, String subject, long timestamp, + byte[] raw) { + this(id, parent, group, author, contentType, subject, timestamp, raw, 0, + raw.length); } public TestMessage(MessageId id, MessageId parent, Group group, - Author author, String subject, long timestamp, byte[] raw, - int bodyStart, int bodyLength) { + Author author, String contentType, String subject, long timestamp, + byte[] raw, int bodyStart, int bodyLength) { this.id = id; this.parent = parent; this.group = group; this.author = author; + this.contentType = contentType; this.subject = subject; this.timestamp = timestamp; this.raw = raw; @@ -53,6 +56,10 @@ public class TestMessage implements Message { return author; } + public String getContentType() { + return contentType; + } + public String getSubject() { return subject; } diff --git a/briar-tests/src/net/sf/briar/db/DatabaseComponentTest.java b/briar-tests/src/net/sf/briar/db/DatabaseComponentTest.java index 1cf9044ffa..72958c9de3 100644 --- a/briar-tests/src/net/sf/briar/db/DatabaseComponentTest.java +++ b/briar-tests/src/net/sf/briar/db/DatabaseComponentTest.java @@ -59,7 +59,7 @@ public abstract class DatabaseComponentTest extends BriarTestCase { protected final AuthorId authorId; protected final Author author; protected final MessageId messageId, messageId1; - protected final String subject; + protected final String contentType, subject; protected final long timestamp; protected final int size; protected final byte[] raw; @@ -80,14 +80,15 @@ public abstract class DatabaseComponentTest extends BriarTestCase { author = new Author(authorId, "Alice", new byte[60]); messageId = new MessageId(TestUtils.getRandomId()); messageId1 = new MessageId(TestUtils.getRandomId()); + contentType = "text/plain"; subject = "Foo"; timestamp = System.currentTimeMillis(); size = 1234; raw = new byte[size]; - message = new TestMessage(messageId, null, group, author, subject, - timestamp, raw); - privateMessage = new TestMessage(messageId, null, null, null, subject, - timestamp, raw); + message = new TestMessage(messageId, null, group, author, contentType, + subject, timestamp, raw); + privateMessage = new TestMessage(messageId, null, null, null, + contentType, subject, timestamp, raw); transportId = new TransportId(TestUtils.getRandomId()); transportProperties = new TransportProperties(Collections.singletonMap( "foo", "bar")); diff --git a/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java b/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java index ec00dd3f61..3126208083 100644 --- a/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java +++ b/briar-tests/src/net/sf/briar/db/H2DatabaseTest.java @@ -56,7 +56,7 @@ public class H2DatabaseTest extends BriarTestCase { private final AuthorId authorId; private final Author author; private final MessageId messageId, messageId1; - private final String subject; + private final String contentType, subject; private final long timestamp; private final int size; private final byte[] raw; @@ -73,15 +73,16 @@ public class H2DatabaseTest extends BriarTestCase { author = new Author(authorId, "Alice", new byte[60]); messageId = new MessageId(TestUtils.getRandomId()); messageId1 = new MessageId(TestUtils.getRandomId()); + contentType = "text/plain"; subject = "Foo"; timestamp = System.currentTimeMillis(); size = 1234; raw = new byte[size]; random.nextBytes(raw); - message = new TestMessage(messageId, null, group, author, subject, - timestamp, raw); - privateMessage = new TestMessage(messageId1, null, null, null, + message = new TestMessage(messageId, null, group, author, contentType, subject, timestamp, raw); + privateMessage = new TestMessage(messageId1, null, null, null, + contentType, subject, timestamp, raw); transportId = new TransportId(TestUtils.getRandomId()); contactId = new ContactId(1); contactName = "Alice"; @@ -552,7 +553,7 @@ public class H2DatabaseTest extends BriarTestCase { Author author1 = new Author(authorId1, "Bob", new byte[60]); MessageId messageId1 = new MessageId(TestUtils.getRandomId()); Message message1 = new TestMessage(messageId1, null, group, author1, - subject, timestamp, raw); + contentType, subject, timestamp, raw); Database<Connection> db = open(false); Connection txn = db.startTransaction(); @@ -584,12 +585,12 @@ public class H2DatabaseTest extends BriarTestCase { GroupId groupId1 = new GroupId(TestUtils.getRandomId()); Group group1 = new Group(groupId1, "Group name", null); Message child1 = new TestMessage(childId1, messageId, group, author, - subject, timestamp, raw); + contentType, subject, timestamp, raw); Message child2 = new TestMessage(childId2, messageId, group, author, - subject, timestamp, raw); + contentType, subject, timestamp, raw); // The third child is in a different group Message child3 = new TestMessage(childId3, messageId, group1, author, - subject, timestamp, raw); + contentType, subject, timestamp, raw); Database<Connection> db = open(false); Connection txn = db.startTransaction(); @@ -620,7 +621,7 @@ public class H2DatabaseTest extends BriarTestCase { public void testGetOldMessages() throws Exception { MessageId messageId1 = new MessageId(TestUtils.getRandomId()); Message message1 = new TestMessage(messageId1, null, group, author, - subject, timestamp + 1000, raw); + contentType, subject, timestamp + 1000, raw); Database<Connection> db = open(false); Connection txn = db.startTransaction(); @@ -651,7 +652,7 @@ public class H2DatabaseTest extends BriarTestCase { byte[] largeBody = new byte[ONE_MEGABYTE]; for(int i = 0; i < largeBody.length; i++) largeBody[i] = (byte) i; Message message1 = new TestMessage(messageId, null, group, author, - subject, timestamp, largeBody); + contentType, subject, timestamp, largeBody); Database<Connection> db = open(false); // Sanity check: there should be enough space on disk for this test @@ -1130,8 +1131,8 @@ public class H2DatabaseTest extends BriarTestCase { // A message with no parent should return null MessageId childId = new MessageId(TestUtils.getRandomId()); - Message child = new TestMessage(childId, null, group, null, subject, - timestamp, raw); + Message child = new TestMessage(childId, null, group, null, contentType, + subject, timestamp, raw); db.addGroupMessage(txn, child); assertTrue(db.containsMessage(txn, childId)); assertNull(db.getGroupMessageParent(txn, childId)); @@ -1152,7 +1153,7 @@ public class H2DatabaseTest extends BriarTestCase { MessageId childId = new MessageId(TestUtils.getRandomId()); MessageId parentId = new MessageId(TestUtils.getRandomId()); Message child = new TestMessage(childId, parentId, group, null, - subject, timestamp, raw); + contentType, subject, timestamp, raw); db.addGroupMessage(txn, child); assertTrue(db.containsMessage(txn, childId)); assertFalse(db.containsMessage(txn, parentId)); @@ -1178,9 +1179,9 @@ public class H2DatabaseTest extends BriarTestCase { MessageId childId = new MessageId(TestUtils.getRandomId()); MessageId parentId = new MessageId(TestUtils.getRandomId()); Message child = new TestMessage(childId, parentId, group, null, - subject, timestamp, raw); + contentType, subject, timestamp, raw); Message parent = new TestMessage(parentId, null, group1, null, - subject, timestamp, raw); + contentType, subject, timestamp, raw); db.addGroupMessage(txn, child); db.addGroupMessage(txn, parent); assertTrue(db.containsMessage(txn, childId)); @@ -1203,7 +1204,7 @@ public class H2DatabaseTest extends BriarTestCase { // A message with a private parent should return null MessageId childId = new MessageId(TestUtils.getRandomId()); Message child = new TestMessage(childId, messageId1, group, null, - subject, timestamp, raw); + contentType, subject, timestamp, raw); db.addGroupMessage(txn, child); db.addPrivateMessage(txn, privateMessage, contactId); assertTrue(db.containsMessage(txn, childId)); @@ -1227,9 +1228,9 @@ public class H2DatabaseTest extends BriarTestCase { MessageId childId = new MessageId(TestUtils.getRandomId()); MessageId parentId = new MessageId(TestUtils.getRandomId()); Message child = new TestMessage(childId, parentId, group, null, - subject, timestamp, raw); - Message parent = new TestMessage(parentId, null, group, null, subject, - timestamp, raw); + contentType, subject, timestamp, raw); + Message parent = new TestMessage(parentId, null, group, null, + contentType, subject, timestamp, raw); db.addGroupMessage(txn, child); db.addGroupMessage(txn, parent); assertTrue(db.containsMessage(txn, childId)); @@ -1252,9 +1253,9 @@ public class H2DatabaseTest extends BriarTestCase { // Store a couple of messages int bodyLength = raw.length - 20; Message message1 = new TestMessage(messageId, null, group, null, - subject, timestamp, raw, 5, bodyLength); + contentType, subject, timestamp, raw, 5, bodyLength); Message privateMessage1 = new TestMessage(messageId1, null, null, - null, subject, timestamp, raw, 10, bodyLength); + null, contentType, subject, timestamp, raw, 10, bodyLength); db.addGroupMessage(txn, message1); db.addPrivateMessage(txn, privateMessage1, contactId); @@ -1294,7 +1295,7 @@ public class H2DatabaseTest extends BriarTestCase { MessageId parentId = new MessageId(TestUtils.getRandomId()); long timestamp1 = System.currentTimeMillis(); Message message1 = new TestMessage(messageId1, parentId, group, author, - subject, timestamp1, raw); + contentType, subject, timestamp1, raw); db.addGroupMessage(txn, message1); // Mark one of the messages read assertFalse(db.setReadFlag(txn, messageId, true)); @@ -1352,6 +1353,7 @@ public class H2DatabaseTest extends BriarTestCase { assertEquals(m.getGroup().getId(), h.getGroupId()); if(m.getAuthor() == null) assertNull(h.getAuthor()); else assertEquals(m.getAuthor(), h.getAuthor()); + assertEquals(m.getContentType(), h.getContentType()); assertEquals(m.getSubject(), h.getSubject()); assertEquals(m.getTimestamp(), h.getTimestamp()); } @@ -1423,13 +1425,13 @@ public class H2DatabaseTest extends BriarTestCase { db.addGroupMessage(txn, message); MessageId messageId1 = new MessageId(TestUtils.getRandomId()); Message message1 = new TestMessage(messageId1, null, group, author, - subject, timestamp, raw); + contentType, subject, timestamp, raw); db.addGroupMessage(txn, message1); // Store one message in the second group MessageId messageId2 = new MessageId(TestUtils.getRandomId()); Message message2 = new TestMessage(messageId2, null, group1, author, - subject, timestamp, raw); + contentType, subject, timestamp, raw); db.addGroupMessage(txn, message2); // Mark one of the messages in the first group read diff --git a/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java b/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java index f715b6f2c9..76e4d6ccab 100644 --- a/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java +++ b/briar-tests/src/net/sf/briar/messaging/ConstantsTest.java @@ -8,7 +8,7 @@ import static net.sf.briar.api.messaging.MessagingConstants.MAX_PROPERTIES_PER_T import static net.sf.briar.api.messaging.MessagingConstants.MAX_PROPERTY_LENGTH; import static net.sf.briar.api.messaging.MessagingConstants.MAX_PUBLIC_KEY_LENGTH; import static net.sf.briar.api.messaging.MessagingConstants.MAX_SIGNATURE_LENGTH; -import static net.sf.briar.api.messaging.MessagingConstants.MAX_SUBJECT_LENGTH; +import static net.sf.briar.api.messaging.MessagingConstants.MAX_CONTENT_TYPE_LENGTH; import static net.sf.briar.api.messaging.MessagingConstants.MAX_SUBSCRIPTIONS; import java.io.ByteArrayOutputStream; @@ -123,15 +123,16 @@ public class ConstantsTest extends BriarTestCase { crypto.generateSignatureKeyPair().getPrivate(); PrivateKey authorPrivate = crypto.generateSignatureKeyPair().getPrivate(); - String subject = createRandomString(MAX_SUBJECT_LENGTH); + String contentType = createRandomString(MAX_CONTENT_TYPE_LENGTH); byte[] body = new byte[MAX_BODY_LENGTH]; Message message = messageFactory.createPseudonymousMessage(parent, - group, groupPrivate, author, authorPrivate, subject, body); + group, groupPrivate, author, authorPrivate, contentType, body); // Check the size of the serialised message int length = message.getSerialised().length; assertTrue(length > UniqueId.LENGTH + MAX_GROUP_NAME_LENGTH + MAX_PUBLIC_KEY_LENGTH + MAX_AUTHOR_NAME_LENGTH - + MAX_PUBLIC_KEY_LENGTH + MAX_BODY_LENGTH); + + MAX_PUBLIC_KEY_LENGTH + MAX_CONTENT_TYPE_LENGTH + + MAX_BODY_LENGTH); assertTrue(length <= MAX_PACKET_LENGTH); } diff --git a/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java b/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java index 1257c0eccd..105518b8f5 100644 --- a/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java +++ b/briar-tests/src/net/sf/briar/messaging/simplex/SimplexMessagingIntegrationTest.java @@ -112,10 +112,10 @@ public class SimplexMessagingIntegrationTest extends BriarTestCase { db.addEndpoint(ep); km.endpointAdded(ep, initialSecret.clone()); // Send Bob a message - String subject = "Hello"; + String contentType = "text/plain"; byte[] body = "Hi Bob!".getBytes("UTF-8"); MessageFactory messageFactory = alice.getInstance(MessageFactory.class); - Message message = messageFactory.createPrivateMessage(null, subject, + Message message = messageFactory.createPrivateMessage(null, contentType, body); db.addLocalPrivateMessage(message, contactId); // Create an outgoing simplex connection -- GitLab