34
34
package com .pff ;
35
35
36
36
import java .io .IOException ;
37
- import java .util .Date ;
38
37
import java .util .HashMap ;
39
38
import java .util .Arrays ;
40
39
41
40
/**
42
- * PST DistList contains methods for extracting Addresses from Distribution lists.
41
+ * PST DistList for extracting Addresses from Distribution lists.
43
42
* @author Richard Johnson
44
43
*/
45
44
public class PSTDistList extends PSTMessage {
46
45
47
- PSTDistList (PSTFile theFile , DescriptorIndexNode descriptorIndexNode )
48
- throws PSTException , IOException
49
- {
50
- super (theFile , descriptorIndexNode );
51
- }
52
-
53
- PSTDistList (PSTFile theFile , DescriptorIndexNode folderIndexNode , PSTTableBC table , HashMap <Integer , PSTDescriptorItem > localDescriptorItems )
54
- {
55
- super (theFile , folderIndexNode , table , localDescriptorItems );
56
- }
57
-
58
- private int findNextNullChar (byte [] data , int start ) {
59
- for (; start < data .length ; start += 2 ) {
60
- if (data [start ] == 0 && data [start +1 ] == 0 ) {
61
- break ;
62
- }
63
- }
64
- return start ;
65
- }
46
+ /**
47
+ * constructor.
48
+ * @param theFile pst file
49
+ * @param descriptorIndexNode index of the list
50
+ * @throws PSTException on parsing error
51
+ * @throws IOException on data access error
52
+ */
53
+ PSTDistList (PSTFile theFile , DescriptorIndexNode descriptorIndexNode )
54
+ throws PSTException , IOException {
55
+ super (theFile , descriptorIndexNode );
56
+ }
57
+
58
+ /**
59
+ * Internal constructor for performance.
60
+ * @param theFile pst file
61
+ * @param folderIndexNode index of the list
62
+ * @param table the PSTTableBC this object is represented by
63
+ * @param localDescriptorItems additional external items that represent
64
+ * this object.
65
+ */
66
+ PSTDistList (PSTFile theFile , DescriptorIndexNode folderIndexNode ,
67
+ PSTTableBC table ,
68
+ HashMap <Integer , PSTDescriptorItem > localDescriptorItems ) {
69
+ super (theFile , folderIndexNode , table , localDescriptorItems );
70
+ }
66
71
72
+ /**
73
+ * Find the next two null bytes in an array given start.
74
+ * @param data the array to search
75
+ * @param start the starting index
76
+ * @return position of the next null char
77
+ */
78
+ private int findNextNullChar (byte [] data , int start ) {
79
+ for (; start < data .length ; start += 2 ) {
80
+ if (data [start ] == 0 && data [start + 1 ] == 0 ) {
81
+ break ;
82
+ }
83
+ }
84
+ return start ;
85
+ }
86
+
87
+ /**
88
+ * identifier for one-off entries.
89
+ */
67
90
private byte [] oneOffEntryIdUid = {
68
91
(byte )0x81 , (byte )0x2b , (byte )0x1f , (byte )0xa4 ,
69
92
(byte )0xbe , (byte )0xa3 , (byte )0x10 , (byte )0x19 ,
70
93
(byte )0x9d , (byte )0x6e , (byte )0x00 , (byte )0xdd ,
71
94
(byte )0x01 , (byte )0x0f , (byte )0x54 , (byte )0x02
72
95
};
73
96
74
- private byte [] wrappedEntryIdUid = {
97
+ /**
98
+ * identifier for wrapped entries.
99
+ */
100
+ private byte [] wrappedEntryIdUid = {
75
101
(byte )0xc0 , (byte )0x91 , (byte )0xad , (byte )0xd3 ,
76
102
(byte )0x51 , (byte )0x9d , (byte )0xcf , (byte )0x11 ,
77
103
(byte )0xa4 , (byte )0xa9 , (byte )0x00 , (byte )0xaa ,
78
104
(byte )0x00 , (byte )0x47 , (byte )0xfa , (byte )0xa4
79
105
};
80
106
107
+ /**
108
+ * Inner class to represent distribution list one-off entries.
109
+ */
81
110
public class OneOffEntry {
82
- public String displayName = "" ;
83
- public String addressType = "" ;
84
- public String emailAddress = "" ;
85
- int pos = 0 ;
86
- public String toString () {
87
- return String .format (
88
- "Display Name: %s\n " +
89
- "Address Type: %s\n " +
90
- "Email Address: %s\n " ,
91
- this .displayName ,
92
- this .addressType ,
93
- this .emailAddress );
94
- }
111
+ /** display name. */
112
+ private String displayName = "" ;
113
+ /**
114
+ * @return display name
115
+ * */
116
+ public String getDisplayName () {
117
+ return this .displayName ;
118
+ }
119
+ /** address type (smtp). */
120
+ private String addressType = "" ;
121
+ /**
122
+ * @return address type
123
+ * */
124
+ public String getAddressType () {
125
+ return this .addressType ;
126
+ }
127
+ /** email address. */
128
+ private String emailAddress = "" ;
129
+ /**
130
+ * @return email address.
131
+ * */
132
+ public String getEmailAddress () {
133
+ return this .emailAddress ;
134
+ }
135
+ /** ending position of this object in the data array. */
136
+ private int pos = 0 ;
137
+ /**
138
+ * @return formatted record
139
+ */
140
+ public String toString () {
141
+ return String .format (
142
+ "Display Name: %s\n "
143
+ + "Address Type: %s\n "
144
+ + "Email Address: %s\n " ,
145
+ this .displayName ,
146
+ this .addressType ,
147
+ this .emailAddress );
148
+ }
95
149
}
96
150
151
+ /**
152
+ * Parse a one-off entry from this Distribution List.
153
+ * @param data the item data
154
+ * @param pos the current position in the data.
155
+ * @throws IOException on string reading fail
156
+ * @return the one-off entry
157
+ */
97
158
private OneOffEntry parseOneOffEntry (byte [] data , int pos )
98
- throws IOException
99
- {
100
- int version = ( int ) PSTObject . convertLittleEndianBytesToLong ( data , pos , pos + 2 );
159
+ throws IOException {
160
+ int version = ( int ) PSTObject . convertLittleEndianBytesToLong (
161
+ data , pos , pos + 2 );
101
162
pos += 2 ;
102
163
103
164
// http://msdn.microsoft.com/en-us/library/ee202811(v=exchg.80).aspx
104
- int additionalFlags = (int )PSTObject .convertLittleEndianBytesToLong (data , pos , pos +2 );
165
+ int additionalFlags = (int )PSTObject .convertLittleEndianBytesToLong (
166
+ data , pos , pos + 2 );
105
167
pos += 2 ;
106
168
107
169
int pad = additionalFlags & 0x8000 ;
@@ -116,19 +178,22 @@ private OneOffEntry parseOneOffEntry(byte[] data, int pos)
116
178
117
179
int stringEnd = findNextNullChar (data , pos );
118
180
byte [] displayNameBytes = new byte [stringEnd - pos ];
119
- System .arraycopy (data , pos , displayNameBytes , 0 , displayNameBytes .length );
181
+ System .arraycopy (data , pos , displayNameBytes ,
182
+ 0 , displayNameBytes .length );
120
183
String displayName = new String (displayNameBytes , "UTF-16LE" );
121
184
pos = stringEnd + 2 ;
122
185
123
186
stringEnd = findNextNullChar (data , pos );
124
187
byte [] addressTypeBytes = new byte [stringEnd - pos ];
125
- System .arraycopy (data , pos , addressTypeBytes , 0 , addressTypeBytes .length );
188
+ System .arraycopy (data , pos , addressTypeBytes ,
189
+ 0 , addressTypeBytes .length );
126
190
String addressType = new String (addressTypeBytes , "UTF-16LE" );
127
191
pos = stringEnd + 2 ;
128
192
129
193
stringEnd = findNextNullChar (data , pos );
130
194
byte [] emailAddressBytes = new byte [stringEnd - pos ];
131
- System .arraycopy (data , pos , emailAddressBytes , 0 , emailAddressBytes .length );
195
+ System .arraycopy (data , pos , emailAddressBytes ,
196
+ 0 , emailAddressBytes .length );
132
197
String emailAddress = new String (emailAddressBytes , "UTF-16LE" );
133
198
pos = stringEnd + 2 ;
134
199
@@ -140,22 +205,32 @@ private OneOffEntry parseOneOffEntry(byte[] data, int pos)
140
205
return out ;
141
206
}
142
207
143
- public Object [] getDistributionListMembers ()
144
- throws PSTException , IOException
145
- {
146
- PSTTableBCItem item = this .items .get (pstFile .getNameToIdMapItem (0x8055 , PSTFile .PSETID_Address ));
147
- Object [] out = {};
208
+ /**
209
+ * Get an array of the members in this distribution list.
210
+ * @throws PSTException on corrupted data
211
+ * @throws IOException on bad string reading
212
+ * @return array of entries that can either be PSTDistList.OneOffEntry
213
+ * or a PSTObject, generally PSTContact.
214
+ */
215
+ public Object [] getDistributionListMembers ()
216
+ throws PSTException , IOException {
217
+ PSTTableBCItem item = this .items .get (
218
+ pstFile .getNameToIdMapItem (0x8055 , PSTFile .PSETID_Address ));
219
+ Object [] out = {};
148
220
if (item != null ) {
149
221
int pos = 0 ;
150
- int count = (int )PSTObject .convertLittleEndianBytesToLong (item .data , pos , pos +4 );
151
- out = new Object [count ];
222
+ int count = (int )PSTObject .convertLittleEndianBytesToLong (
223
+ item .data , pos , pos + 4 );
224
+ out = new Object [count ];
152
225
pos += 4 ;
153
- pos = (int )PSTObject .convertLittleEndianBytesToLong (item .data , pos , pos +4 );
226
+ pos = (int )PSTObject .convertLittleEndianBytesToLong (
227
+ item .data , pos , pos + 4 );
154
228
155
- for (int x = 0 ; x < count ; x ++) {
229
+ for (int x = 0 ; x < count ; x ++) {
156
230
// http://msdn.microsoft.com/en-us/library/ee218661(v=exchg.80).aspx
157
231
// http://msdn.microsoft.com/en-us/library/ee200559(v=exchg.80).aspx
158
- int flags = (int )PSTObject .convertLittleEndianBytesToLong (item .data , pos , pos +4 );
232
+ int flags = (int )PSTObject .convertLittleEndianBytesToLong (
233
+ item .data , pos , pos + 4 );
159
234
pos += 4 ;
160
235
161
236
byte [] guid = new byte [16 ];
@@ -168,28 +243,30 @@ public Object[] getDistributionListMembers()
168
243
int entryAddressType = item .data [pos ] & 0x70 >> 4 ;
169
244
boolean isOneOffEntryId = (item .data [pos ] & 0x80 ) > 0 ;
170
245
pos ++;
171
- int wrappedflags = (int )PSTObject .convertLittleEndianBytesToLong (item .data , pos , pos +4 );
172
- pos += 4 ;
246
+ int wrappedflags = (int )PSTObject .convertLittleEndianBytesToLong (
247
+ item .data , pos , pos + 4 );
248
+ pos += 4 ;
173
249
174
- byte [] guid2 = new byte [16 ];
175
- System .arraycopy (item .data , pos , guid , 0 , guid .length );
176
- pos += 16 ;
250
+ byte [] guid2 = new byte [16 ];
251
+ System .arraycopy (item .data , pos , guid , 0 , guid .length );
252
+ pos += 16 ;
177
253
178
- int descriptorIndex = (int )PSTObject .convertLittleEndianBytesToLong (item .data , pos , pos +3 );
179
- pos += 3 ;
254
+ int descriptorIndex = (int )PSTObject .convertLittleEndianBytesToLong (
255
+ item .data , pos , pos + 3 );
256
+ pos += 3 ;
180
257
181
- byte empty = item .data [pos ];
182
- pos ++;
258
+ byte empty = item .data [pos ];
259
+ pos ++;
183
260
184
- out [x ] = PSTObject .detectAndLoadPSTObject (this .pstFile , descriptorIndex );
261
+ out [x ] = PSTObject .detectAndLoadPSTObject (this .pstFile , descriptorIndex );
185
262
186
263
} else if (Arrays .equals (guid , oneOffEntryIdUid )) {
187
264
OneOffEntry entry = parseOneOffEntry (item .data , pos );
188
265
pos = entry .pos ;
189
- out [x ] = entry ;
266
+ out [x ] = entry ;
190
267
}
191
268
}
192
- }
193
- return out ;
194
- }
269
+ }
270
+ return out ;
271
+ }
195
272
}
0 commit comments