m2u-upass-core / src / my / com / upass / maybank / MaybankFacadeImpl.java @ 56:c05a77f786c8
History | View | Annotate | Download (12.5 KB)
1 | 30:aec0089bb43e | hadi | package my.com.upass.maybank; |
---|---|---|---|
2 | |||
3 | 50:4121579eae5e | hadi | import java.text.ParseException; |
4 | 40:29d3fc38fdee | hadi | import java.util.ArrayList; |
5 | import java.util.Arrays; |
||
6 | 55:275e8875e7c0 | hadi | import java.util.Date; |
7 | 51:74be74b4d46a | hadi | import java.util.HashMap; |
8 | 40:29d3fc38fdee | hadi | import java.util.LinkedList; |
9 | import java.util.List; |
||
10 | import java.util.Map; |
||
11 | |||
12 | 51:74be74b4d46a | hadi | import javax.jws.WebParam; |
13 | import javax.jws.WebResult; |
||
14 | 30:aec0089bb43e | hadi | import javax.jws.WebService; |
15 | |||
16 | 40:29d3fc38fdee | hadi | import my.com.upass.MinimalConstants; |
17 | 33:9d5b4aece71c | hadi | import my.com.upass.UPassControllerV2; |
18 | 40:29d3fc38fdee | hadi | import my.com.upass.UPassException; |
19 | 46:8f67d8567943 | hadi | import my.com.upass.generic.hibernate.GenericDAOHibernate; |
20 | import my.com.upass.generic.hibernate.HibernateUtils; |
||
21 | 37:848f67a9b39c | hadi | import my.com.upass.maybank.entities.IbccUser; |
22 | 40:29d3fc38fdee | hadi | import my.com.upass.maybank.entities.Im2uUser; |
23 | import my.com.upass.maybank.entities.M2uUser; |
||
24 | import my.com.upass.maybank.entities.StockUser; |
||
25 | import my.com.upass.maybank.entities.TicketingUser; |
||
26 | import my.com.upass.maybank.entities.UserProfile; |
||
27 | 42:d32be3a379fb | hadi | import my.com.upass.pojo.ClientApp; |
28 | 37:848f67a9b39c | hadi | import my.com.upass.pojo.MinimalUserBean; |
29 | 40:29d3fc38fdee | hadi | import my.com.upass.pojo.UserAppAccess; |
30 | 52:7d9b71dd008a | hadi | import my.com.upass.util.MapElement; |
31 | import my.com.upass.util.MapWrapper; |
||
32 | 30:aec0089bb43e | hadi | |
33 | 40:29d3fc38fdee | hadi | import org.apache.log4j.Logger; |
34 | import org.hibernate.Session; |
||
35 | 30:aec0089bb43e | hadi | |
36 | 43:78b1d801d083 | hadi | /**
|
37 | * @author Hadi
|
||
38 | *
|
||
39 | */
|
||
40 | 32:d43f37e77545 | hadi | @WebService(
|
41 | serviceName = "MaybankFacade",
|
||
42 | endpointInterface = "my.com.upass.maybank.MaybankFacade")
|
||
43 | //
|
||
44 | public class MaybankFacadeImpl |
||
45 | extends MinimalMaybankFacadeImpl
|
||
46 | implements MaybankFacade {
|
||
47 | 30:aec0089bb43e | hadi | |
48 | 40:29d3fc38fdee | hadi | private static final Logger LOGGER = Logger.getLogger(MaybankFacadeImpl.class); |
49 | |||
50 | 33:9d5b4aece71c | hadi | private final UPassControllerV2 upcV2; |
51 | |||
52 | 40:29d3fc38fdee | hadi | //
|
53 | |||
54 | 33:9d5b4aece71c | hadi | public MaybankFacadeImpl() {
|
55 | upcV2 = new UPassControllerV2();
|
||
56 | } |
||
57 | |||
58 | @Override
|
||
59 | 55:275e8875e7c0 | hadi | public int newIbccAdminUser( |
60 | 39:e450611bea1f | hadi | String appAccessId, String hashedSecretKey, |
61 | 34:420c5039e742 | hadi | String username, String hashedPassword) { |
62 | 39:e450611bea1f | hadi | |
63 | 51:74be74b4d46a | hadi | final IbccUser ibccUser = new IbccUser(); |
64 | 40:29d3fc38fdee | hadi | // ibccUser.setPanCc(panCc);
|
65 | |||
66 | 51:74be74b4d46a | hadi | final MinimalUserBean minUser = new MinimalUserBean(); |
67 | 40:29d3fc38fdee | hadi | minUser.setUsername(username); |
68 | 51:74be74b4d46a | hadi | |
69 | 40:29d3fc38fdee | hadi | minUser.setHashedPassword(hashedPassword); |
70 | ibccUser.setMinUser(minUser); |
||
71 | |||
72 | return newAdminUser(appAccessId, hashedSecretKey, ibccUser);
|
||
73 | 30:aec0089bb43e | hadi | } |
74 | |||
75 | 51:74be74b4d46a | hadi | @Override
|
76 | 55:275e8875e7c0 | hadi | public int newIbccPublicUser( |
77 | 37:848f67a9b39c | hadi | String appAccessId, String hashedSecretKey, |
78 | String username, String hashedPassword, String panCc) { |
||
79 | |||
80 | 51:74be74b4d46a | hadi | final IbccUser ibccUser = new IbccUser(); |
81 | 37:848f67a9b39c | hadi | ibccUser.setPanCc(panCc); |
82 | |||
83 | 51:74be74b4d46a | hadi | final MinimalUserBean minUser = new MinimalUserBean(); |
84 | 37:848f67a9b39c | hadi | minUser.setUsername(username); |
85 | minUser.setHashedPassword(hashedPassword); |
||
86 | ibccUser.setMinUser(minUser); |
||
87 | |||
88 | return newUser(appAccessId, hashedSecretKey, ibccUser);
|
||
89 | } |
||
90 | |||
91 | 51:74be74b4d46a | hadi | @Override
|
92 | 55:275e8875e7c0 | hadi | public int newOnlineStockUser( |
93 | String appAccessId, String hashedSecretKey, |
||
94 | String username, String hashedPassword, String idNo) { |
||
95 | |||
96 | StockUser stockUser = new StockUser();
|
||
97 | stockUser.setIdNo(idNo); |
||
98 | |||
99 | MinimalUserBean minUser = new MinimalUserBean();
|
||
100 | minUser.setUsername(username); |
||
101 | minUser.setHashedPassword(hashedPassword); |
||
102 | stockUser.setMinUser(minUser); |
||
103 | |||
104 | return newUser(appAccessId, hashedSecretKey, stockUser);
|
||
105 | } |
||
106 | |||
107 | @Override
|
||
108 | public int newIm2uUser( |
||
109 | String appAccessId, String hashedSecretKey, |
||
110 | String username, String hashedPassword, |
||
111 | String wsFlag, String wsIdentCode, String wsMySgId, Date wsRegTimeStamp) { |
||
112 | |||
113 | Im2uUser im2uUser = new Im2uUser();
|
||
114 | im2uUser.setWsFlag(wsFlag); |
||
115 | im2uUser.setWsIdentCode(wsIdentCode); |
||
116 | im2uUser.setWsMySgId(wsMySgId); |
||
117 | im2uUser.setWsRegTimeStamp(wsRegTimeStamp); |
||
118 | |||
119 | MinimalUserBean minUser = new MinimalUserBean();
|
||
120 | minUser.setUsername(username); |
||
121 | minUser.setHashedPassword(hashedPassword); |
||
122 | im2uUser.setMinUser(minUser); |
||
123 | |||
124 | return newUser(appAccessId, hashedSecretKey, im2uUser);
|
||
125 | } |
||
126 | |||
127 | @Override
|
||
128 | 51:74be74b4d46a | hadi | public int newTicketingUser( |
129 | 52:7d9b71dd008a | hadi | String appAccessId, String hashedSecretKey, |
130 | String username, String hashedPassword, |
||
131 | 51:74be74b4d46a | hadi | String fullName, String firstName, String lastName, String payeeCode) { |
132 | |||
133 | final TicketingUser ticketingUser = new TicketingUser(); |
||
134 | ticketingUser.setFullName(fullName); |
||
135 | ticketingUser.setFirstName(firstName); |
||
136 | ticketingUser.setLastName(lastName); |
||
137 | ticketingUser.setPayeeCode(payeeCode); |
||
138 | 52:7d9b71dd008a | hadi | |
139 | 51:74be74b4d46a | hadi | final MinimalUserBean minUser = new MinimalUserBean(); |
140 | minUser.setUsername(username); |
||
141 | minUser.setHashedPassword(hashedPassword); |
||
142 | ticketingUser.setMinUser(minUser); |
||
143 | 52:7d9b71dd008a | hadi | |
144 | 51:74be74b4d46a | hadi | return newUser(appAccessId, hashedSecretKey, ticketingUser);
|
145 | } |
||
146 | 52:7d9b71dd008a | hadi | |
147 | 43:78b1d801d083 | hadi | /**
|
148 | * @deprecated
|
||
149 | * @see #lookupUsername(String, String, String)
|
||
150 | */
|
||
151 | @Override
|
||
152 | public Response lookupUsername_internal(
|
||
153 | String appAccessId, String hashedSecretKey, String username) { |
||
154 | |||
155 | throw new java.lang.UnsupportedOperationException(); |
||
156 | } |
||
157 | |||
158 | 33:9d5b4aece71c | hadi | @Override
|
159 | 39:e450611bea1f | hadi | public ResponseElement lookupUsername(
|
160 | 40:29d3fc38fdee | hadi | String appAccessId, String hashedSecretKey, String username) { |
161 | 39:e450611bea1f | hadi | |
162 | final Response response = super.lookupUsername_internal(appAccessId, hashedSecretKey, username); |
||
163 | return new ResponseElement(response); |
||
164 | } |
||
165 | |||
166 | 43:78b1d801d083 | hadi | /**
|
167 | * @deprecated
|
||
168 | * @see #lookupPublicUsername(String, String, String)
|
||
169 | */
|
||
170 | 40:29d3fc38fdee | hadi | @Override
|
171 | 43:78b1d801d083 | hadi | public Response lookupPublicUsername_internal(
|
172 | 40:29d3fc38fdee | hadi | String appAccessId, String hashedSecretKey, String username) { |
173 | |||
174 | 42:d32be3a379fb | hadi | throw new java.lang.UnsupportedOperationException(); |
175 | 40:29d3fc38fdee | hadi | } |
176 | |||
177 | 39:e450611bea1f | hadi | @Override
|
178 | 42:d32be3a379fb | hadi | public ResponseElement lookupPublicUsername(
|
179 | 40:29d3fc38fdee | hadi | String appAccessId, String hashedSecretKey, String username) { |
180 | 39:e450611bea1f | hadi | |
181 | 42:d32be3a379fb | hadi | final Response response = super.lookupPublicUsername_internal(appAccessId, hashedSecretKey, username); |
182 | return new ResponseElement(response); |
||
183 | } |
||
184 | |||
185 | 43:78b1d801d083 | hadi | /**
|
186 | * @deprecated
|
||
187 | * @see #lookupPan1(String, String, String)
|
||
188 | */
|
||
189 | 42:d32be3a379fb | hadi | @Override
|
190 | public Response lookupPan1_internal(
|
||
191 | String appAccessId, String hashedSecretKey, String pan1) { |
||
192 | |||
193 | throw new java.lang.UnsupportedOperationException(); |
||
194 | } |
||
195 | |||
196 | @Override
|
||
197 | public ResponseElement lookupPan1(
|
||
198 | String appAccessId, String hashedSecretKey, String pan1) { |
||
199 | |||
200 | final Response response = super.lookupPan1_internal(appAccessId, hashedSecretKey, pan1); |
||
201 | return new ResponseElement(response); |
||
202 | } |
||
203 | |||
204 | 43:78b1d801d083 | hadi | /**
|
205 | * @deprecated
|
||
206 | * @see #lookupPan2(String, String, String)
|
||
207 | */
|
||
208 | 42:d32be3a379fb | hadi | @Override
|
209 | public Response lookupPan2_internal(
|
||
210 | String appAccessId, String hashedSecretKey, String pan1) { |
||
211 | |||
212 | throw new java.lang.UnsupportedOperationException(); |
||
213 | } |
||
214 | |||
215 | @Override
|
||
216 | public ResponseElement lookupPan2(
|
||
217 | String appAccessId, String hashedSecretKey, String pan2) { |
||
218 | |||
219 | final Response response = super.lookupPan2_internal(appAccessId, hashedSecretKey, pan2); |
||
220 | return new ResponseElement(response); |
||
221 | } |
||
222 | |||
223 | 43:78b1d801d083 | hadi | /**
|
224 | * @deprecated
|
||
225 | * @see #lookupPanCc(String, String, String)
|
||
226 | */
|
||
227 | 42:d32be3a379fb | hadi | @Override
|
228 | public Response lookupPanCc_internal(
|
||
229 | String appAccessId, String hashedSecretKey, String panCc) { |
||
230 | |||
231 | throw new java.lang.UnsupportedOperationException(); |
||
232 | } |
||
233 | |||
234 | @Override
|
||
235 | public ResponseElement lookupPanCc(
|
||
236 | String appAccessId, String hashedSecretKey, String panCc) { |
||
237 | |||
238 | final Response response = super.lookupPanCc_internal(appAccessId, hashedSecretKey, panCc); |
||
239 | return new ResponseElement(response); |
||
240 | 30:aec0089bb43e | hadi | } |
241 | |||
242 | 33:9d5b4aece71c | hadi | @Override
|
243 | 34:420c5039e742 | hadi | public int deleteUser( |
244 | 39:e450611bea1f | hadi | String appAccessId, String hashedSecretKey, |
245 | 34:420c5039e742 | hadi | String username) {
|
246 | 39:e450611bea1f | hadi | |
247 | 43:78b1d801d083 | hadi | int rc = MinimalConstants.ERR_UNKNOWN;
|
248 | Session session = null;
|
||
249 | try {
|
||
250 | session = HibernateUtils.currentSession(); |
||
251 | session.beginTransaction(); |
||
252 | |||
253 | 44:7a7fb8fcfd6e | hadi | rc = upcV2.deleteUserWithTheProfile(appAccessId, hashedSecretKey, username, session); |
254 | |||
255 | if (rc == MinimalConstants.ERR_SUCCESS)
|
||
256 | session.getTransaction().commit(); |
||
257 | else
|
||
258 | GenericDAOHibernate.rollbackTransactionIfAny(session); |
||
259 | |||
260 | } catch (UPassException e) {
|
||
261 | rc = e.getErrorCode(); |
||
262 | e.printStackTrace(); |
||
263 | GenericDAOHibernate.rollbackTransactionIfAny(session); |
||
264 | 43:78b1d801d083 | hadi | |
265 | } catch (Exception e) { |
||
266 | LOGGER.error(e, e); |
||
267 | GenericDAOHibernate.rollbackTransactionIfAny(session); |
||
268 | |||
269 | } finally {
|
||
270 | GenericDAOHibernate.closeSessionIfAny(session); |
||
271 | } |
||
272 | return rc;
|
||
273 | 30:aec0089bb43e | hadi | } |
274 | |||
275 | 33:9d5b4aece71c | hadi | @Override
|
276 | 40:29d3fc38fdee | hadi | public ResponseListElement searchUserByFilter(
|
277 | 52:7d9b71dd008a | hadi | String appAccessId, String hashedSecretKey, MapWrapper searchFilter) { |
278 | 39:e450611bea1f | hadi | |
279 | 40:29d3fc38fdee | hadi | ResponseListElement res = new ResponseListElement();
|
280 | 52:7d9b71dd008a | hadi | final List<MapWrapper> items = new LinkedList<MapWrapper>(); |
281 | 40:29d3fc38fdee | hadi | |
282 | Session session = null;
|
||
283 | try {
|
||
284 | session = HibernateUtils.currentSession(); |
||
285 | 42:d32be3a379fb | hadi | |
286 | 40:29d3fc38fdee | hadi | List<UserProfile> examples = new ArrayList<UserProfile>(5); |
287 | for (Class<? extends UserProfile> clazz : Arrays.asList( |
||
288 | IbccUser.class, Im2uUser.class, M2uUser.class, StockUser.class, TicketingUser.class)) { |
||
289 | |||
290 | final UserProfile example = clazz.newInstance();
|
||
291 | 52:7d9b71dd008a | hadi | example.mapToProperties(searchFilter.getMap()); |
292 | 40:29d3fc38fdee | hadi | examples.add(example); |
293 | } |
||
294 | 42:d32be3a379fb | hadi | List<UserProfile> profiles = upcV2.listProfilesByExamples(
|
295 | appAccessId, hashedSecretKey, examples, session); |
||
296 | |||
297 | 40:29d3fc38fdee | hadi | for (UserProfile profile : profiles)
|
298 | 52:7d9b71dd008a | hadi | items.add(new MapWrapper(profile.propertiesToMap()));
|
299 | 40:29d3fc38fdee | hadi | |
300 | res.setItems(items); |
||
301 | res.setCode(MinimalConstants.ERR_SUCCESS); |
||
302 | |||
303 | } catch (UPassException e) {
|
||
304 | LOGGER.info(e, e); |
||
305 | res.setCode(e.getErrorCode()); |
||
306 | |||
307 | 50:4121579eae5e | hadi | } catch (ParseException e) { |
308 | LOGGER.error(e, e); |
||
309 | res.setCode(MinimalConstants.ERR_INVALID_INPUT); |
||
310 | |||
311 | 40:29d3fc38fdee | hadi | } catch (Exception e) { |
312 | LOGGER.error(e, e); |
||
313 | res.setCode(MinimalConstants.ERR_UNKNOWN); |
||
314 | |||
315 | } finally {
|
||
316 | GenericDAOHibernate.closeSessionIfAny(session); |
||
317 | } |
||
318 | return res;
|
||
319 | 39:e450611bea1f | hadi | } |
320 | |||
321 | @Override
|
||
322 | public int changeIdNo( |
||
323 | String appAccessId, String hashedSecretKey, |
||
324 | String username, String idNo) { |
||
325 | |||
326 | 40:29d3fc38fdee | hadi | Session session = null;
|
327 | try {
|
||
328 | session = HibernateUtils.currentSession(); |
||
329 | session.beginTransaction(); |
||
330 | |||
331 | UserProfile profile = upcV2.findProfile( |
||
332 | 42:d32be3a379fb | hadi | appAccessId, hashedSecretKey, username, ClientApp.APP_ID_ONLINE_STOCK, session); |
333 | 40:29d3fc38fdee | hadi | |
334 | if (profile instanceof StockUser) { |
||
335 | StockUser stockUser = (StockUser) profile; |
||
336 | stockUser.setIdNo(idNo); |
||
337 | |||
338 | int rc = upcV2.updateProfileShallowly(
|
||
339 | appAccessId, hashedSecretKey, stockUser, session); |
||
340 | |||
341 | 44:7a7fb8fcfd6e | hadi | if (rc == MinimalConstants.ERR_SUCCESS)
|
342 | session.getTransaction().commit(); |
||
343 | else
|
||
344 | GenericDAOHibernate.rollbackTransactionIfAny(session); |
||
345 | |||
346 | 40:29d3fc38fdee | hadi | return rc;
|
347 | |||
348 | } else {
|
||
349 | GenericDAOHibernate.rollbackTransactionIfAny(session); |
||
350 | 42:d32be3a379fb | hadi | return MinimalConstants.ERR_INVALID_INPUT;
|
351 | 40:29d3fc38fdee | hadi | } |
352 | } catch (UPassException e) {
|
||
353 | LOGGER.info(e, e); |
||
354 | GenericDAOHibernate.rollbackTransactionIfAny(session); |
||
355 | return e.getErrorCode();
|
||
356 | |||
357 | } catch (Exception e) { |
||
358 | LOGGER.error(e, e); |
||
359 | GenericDAOHibernate.rollbackTransactionIfAny(session); |
||
360 | return MinimalConstants.ERR_UNKNOWN;
|
||
361 | |||
362 | } finally {
|
||
363 | GenericDAOHibernate.closeSessionIfAny(session); |
||
364 | } |
||
365 | } |
||
366 | |||
367 | 51:74be74b4d46a | hadi | @Override
|
368 | public CountResponseElement getFailedLoginsCount(
|
||
369 | String appAccessId, String hashedSecretKey, String username) { |
||
370 | |||
371 | CountResponse response = super.getFailedLoginsCount(appAccessId, hashedSecretKey, username);
|
||
372 | return new CountResponseElement(response); |
||
373 | } |
||
374 | |||
375 | @Override
|
||
376 | 53:7f6572116251 | hadi | public int updateIm2uUser( |
377 | 51:74be74b4d46a | hadi | String appAccessId, String hashedSecretKey, |
378 | 52:7d9b71dd008a | hadi | String username, MapWrapper attributes) {
|
379 | 51:74be74b4d46a | hadi | |
380 | Session session = null;
|
||
381 | try {
|
||
382 | session = HibernateUtils.currentSession(); |
||
383 | session.beginTransaction(); |
||
384 | |||
385 | UserProfile profile = upcV2.findProfile( |
||
386 | 53:7f6572116251 | hadi | appAccessId, hashedSecretKey, username, ClientApp.APP_ID_IM2U, session); |
387 | 51:74be74b4d46a | hadi | |
388 | if (profile != null) { |
||
389 | 52:7d9b71dd008a | hadi | final Map<String, String> tempMap = new HashMap<String, String>(); |
390 | 51:74be74b4d46a | hadi | tempMap.putAll(profile.propertiesToMap()); |
391 | |||
392 | 52:7d9b71dd008a | hadi | final Map<String, String> attributesMap = attributes.getMap(); |
393 | attributesMap.remove("username");
|
||
394 | tempMap.putAll(attributesMap); |
||
395 | 51:74be74b4d46a | hadi | |
396 | profile.mapToProperties(tempMap); |
||
397 | |||
398 | int rc = upcV2.updateProfileShallowly(
|
||
399 | appAccessId, hashedSecretKey, profile, session); |
||
400 | |||
401 | if (rc == MinimalConstants.ERR_SUCCESS) {
|
||
402 | session.getTransaction().commit(); |
||
403 | |||
404 | } else {
|
||
405 | LOGGER.warn("Unable to update user profile.");
|
||
406 | GenericDAOHibernate.rollbackTransactionIfAny(session); |
||
407 | } |
||
408 | return rc;
|
||
409 | |||
410 | } else {
|
||
411 | GenericDAOHibernate.rollbackTransactionIfAny(session); |
||
412 | return MinimalConstants.ERR_INVALID_INPUT;
|
||
413 | } |
||
414 | } catch (UPassException e) {
|
||
415 | LOGGER.info(e, e); |
||
416 | GenericDAOHibernate.rollbackTransactionIfAny(session); |
||
417 | return e.getErrorCode();
|
||
418 | |||
419 | } catch (Exception e) { |
||
420 | LOGGER.error(e, e); |
||
421 | GenericDAOHibernate.rollbackTransactionIfAny(session); |
||
422 | return MinimalConstants.ERR_UNKNOWN;
|
||
423 | |||
424 | } finally {
|
||
425 | GenericDAOHibernate.closeSessionIfAny(session); |
||
426 | } |
||
427 | } |
||
428 | |||
429 | 40:29d3fc38fdee | hadi | // Helper methods
|
430 | |||
431 | protected int newAdminUser( |
||
432 | String appAccessId, String hashedSecretKey, UserProfile profile) { |
||
433 | |||
434 | int rc = MinimalConstants.ERR_UNKNOWN;
|
||
435 | Session session = null;
|
||
436 | try {
|
||
437 | session = HibernateUtils.currentSession(); |
||
438 | session.beginTransaction(); |
||
439 | |||
440 | rc = upcV2.addUser( |
||
441 | appAccessId, hashedSecretKey, profile.getMinUser(), UserAppAccess.TYPE_ADMIN, session); |
||
442 | |||
443 | if (rc == MinimalConstants.ERR_SUCCESS) {
|
||
444 | rc = upcV2.updateProfileShallowly(appAccessId, hashedSecretKey, profile, session); |
||
445 | |||
446 | 44:7a7fb8fcfd6e | hadi | if (rc == MinimalConstants.ERR_SUCCESS)
|
447 | session.getTransaction().commit(); |
||
448 | else
|
||
449 | GenericDAOHibernate.rollbackTransactionIfAny(session); |
||
450 | 40:29d3fc38fdee | hadi | |
451 | } else
|
||
452 | GenericDAOHibernate.rollbackTransactionIfAny(session); |
||
453 | |||
454 | } catch (Exception e) { |
||
455 | GenericDAOHibernate.rollbackTransactionIfAny(session); |
||
456 | LOGGER.error(e, e); |
||
457 | |||
458 | } finally {
|
||
459 | GenericDAOHibernate.closeSessionIfAny(session); |
||
460 | } |
||
461 | return rc;
|
||
462 | 30:aec0089bb43e | hadi | } |
463 | } |