Odyssey
OFXRequest.prg
1 <?php
2 
3 # NOTE 10/09/12 exposed logic bug -- cu set as 2-factor, app passing in MFA answers, then cu set as legacy: appeared to work except that USERKEY was not returned in OFX output. Some kind of wart related to getting MFA when not expected
4 # Automatic 1-Way OFX as described in OFX 2.1.1 Specification, Section 16
5 #
6 #
7 # APPID : Identifies partner. Use OFXRQ for HomeCU app
8 # APPVER : required according to spec, not used at HomeCU.
9 # ORG : Client Code
10 #
11 # Script supports both SSO access and authenticated access methods.
12 # request will include either USERKEY (indicating SSO)
13 # or USERID/USERPASS (indicating authenticated access)
14 #
15 # USERID : cu:member
16 # USERPASS : password for authenticated account
17 # USERKEY : token for SSO access (replaces both USERID and USERPASS)
18 # CRED2 : Request date, UTC date/time in YYYYmmddHHMISS format
19 # CRED3 : hash # APPID USERID CRED2 hashed with assigned key
20 # DTSTART : Start date, default to 30days past
21 # DTEND : End date, default to today
22 #
23 //require_once('LogSSO.i');
24 
25 // ** SET HOMECU FLAGS
26  $serviceMinimal = true;
27  $serviceShowInfo = false;
28  $serviceLoadMenu = false;
29  $serviceShowMenu = false;
30 
31  // ** INCLUDE MAIN GLOBAL SCRIPT -- Handles security / global variable values
32  // hcuService will be returning a status object: e.g. ["homecuErrors":{[{"message":"message1"}...{"message":"messageN"}}]
33  require_once(dirname(__FILE__) . '/../library/hcuService.i');
34 
35 
36  $inPost = array();
37  $varOk = array(
38  "APPID" => array('filter' => FILTER_SANITIZE_STRING),
39  "DTSTART" => array('filter' => FILTER_SANITIZE_STRING),
40  "DTEND" => array('filter' => FILTER_SANITIZE_STRING),
41  "CRED2" => array('filter' => FILTER_SANITIZE_STRING),
42  "CRED3" => array('filter' => FILTER_SANITIZE_STRING),
43  "USERID" => array('filter' => FILTER_SANITIZE_STRING),
44  "USERPASS" => array('filter' => FILTER_SANITIZE_STRING),
45  "USERKEY" => array('filter' => FILTER_SANITIZE_STRING),
46  "ORG" => array('filter' => FILTER_SANITIZE_STRING),
47  "RQMODE" => array('filter' => FILTER_SANITIZE_STRING),
48  "FACCTID" => array('filter' => FILTER_SANITIZE_STRING),
49  "TACCTID" => array('filter' => FILTER_SANITIZE_STRING),
50  "AMOUNT" => array('filter' => FILTER_SANITIZE_NUMBER_INT),
51  "TRMEMO" => array('filter' => FILTER_SANITIZE_STRING),
52  "PASSTO" => array('filter' => FILTER_SANITIZE_STRING),
53  "PASSWITH" => array('filter' => FILTER_SANITIZE_STRING),
54  "KEYACCTID" => array('filter' => FILTER_SANITIZE_STRING),
55  "IPAYTAG" => array('filter' => FILTER_SANITIZE_STRING),
56  "IPAYINSTITUTION" => array('filter' => FILTER_SANITIZE_STRING),
57  "CFGFLAG" => array('filter' => FILTER_SANITIZE_STRING),
58  "UPDAWARE" => array('filter' => FILTER_SANITIZE_NUMBER_INT),
59  'MFA_' => 'prefix_s'
60  );
61 # CFGFLAG is to be used to capture the session flag settings as used in Fmsg_tx on the desktop. Should be used
62 # currently in TXLIST / TXPOST to control whether or not to query the core for txaccount authority. Not implemented
63 # completely yet, but added to the Load_HB_ENV function and calls
64 
65 HCU_ImportVars( $inPost, "", $varOk );
66 # apptokenkey used only at HCU, not shared. Used to hash / check our token just to be sure it comes back unchanged.
67 $apptokenkey = 'Chahriv8pahvahsa';
68 $encoding='UTF-8';
69 
70 try {
71 # FIX FOR PROD
72 # must be POST method
73 if ($_SERVER['REQUEST_METHOD'] != 'POST')
74  throw new Exception('Unauthorized Method',2010);# post method required
75 
76 switch ($inPost['APPID']) {
77  case "OFXRQ":
78  # iPhone APP
79  $client_source_override = 'APP';
80  # no ip whitelist for iPhone app
81  $appkey = "yuiQu8laLux7bahx";
82  break;
83 
84  case "OFXAA":
85  # Android APP
86  $client_source_override = 'ADA';
87  # no ip whitelist for Android app
88  $appkey = "Gai7Vain2pab5zae";
89  break;
90 
91  default:
92  throw new Exception("Unauthorized ID",2020); # invalid app id
93 }
94 # validate entries
95 # start date optional, must be valid if provided, default 30 days past
96 # end date optional, but must be valid if provided, default today
97 # either USERID/USERPASS or USERKEY is required
98 # USERID HomeCU MEMBER for aggregated access
99 # USERPASS password for aggregated access
100 # USERKEY required if USERID/USERPASS not given; SSO security token
101 # CRED2 required, UTC date in YYYYMMDDHHMI format.
102 # must be within 30 minutes of actual UTC time as shown on HomeCU servers
103 # CRED3 hash required, must match calculated hash
104 #
105 
106 if (empty($inPost['CRED2']) || empty($inPost['ORG']) || empty($inPost['CRED3']) ) {
107  throw new Exception("Invalid Credentials",2030); # Missing values
108 }
109 
110 if (empty($inPost['CRED2'])) {
111  $gmcheck = 0; # force date check to fail
112 } else {
113  # CRED2 is YYYY mm dd HH MI SS
114  # Passed to gmmktime as HH,MI,SS,mm,dd,YYYY
115  $HH = intval(substr($inPost['CRED2'], 8, 2));
116  $MI = intval(substr($inPost['CRED2'], 10, 2));
117  $SS = intval(substr($inPost['CRED2'], 12, 2));
118  $mm = intval(substr($inPost['CRED2'], 4, 2));
119  $dd = intval(substr($inPost['CRED2'], 6, 2));
120  $YYYY = intval(substr($inPost['CRED2'], 0, 4));
121  # convert UTC date/time on request to a (local) timestamp
122  $gmcheck = gmmktime($HH, $MI, $SS, $mm, $dd, $YYYY);
123 }
124 # and get the current timestamp
125 $gmdate = mktime();
126 
127 # FIX FOR PROD
128 # date stretched for testing -- s/b 1800 (30 min)
129 if (empty($inPost['CRED2']) || empty($inPost['ORG']) || empty($inPost['CRED3']) || abs($gmdate - $gmcheck) > 1800) {
130  throw new Exception("Invalid Credentials or Device Date / Time",2030); # Missing values or expired token
131 }
132 $CU = $inPost['ORG'];
133 
134 
135 if (!empty($inPost['USERKEY'])) {
136  # got USERKEY, validate SSO method
137  # for Odyssey, both A=cauth_member and C=current member will be UID values
138  $AUTHMODE = 'SSO';
139 
140  # $mytoken="H=$hash&E=$expires&A=$member";
141  # 11/6/14 to support switch accounts
142  # $mytoken="H=$hash&E=$expires&A=$cauth_member&C=$current_member";
143 
144  $apptokarr = array();
145  parse_str(urldecode($inPost['USERKEY']), $apptokarr);
146 
147  if ($apptokarr['E'] < time()) {
148  throw new Exception("Invalid Credentials (Expired Token) " . __LINE__,15510);
149  }
150 
151  if (is_null($apptokarr['E']) || is_null($apptokarr['A']) || is_null($apptokarr['H'])) {
152  throw new Exception("Invalid Credentials (Partial Token) " . __LINE__,15510);
153  }
154  # if no C= value, assume oldstyle userkey
155  # and set member as A= value so hash works
156  # for odyssey A & C are swapped
157  # A is Uid, C is primary account
158  # Get_History call uses cauth as primary account
159  if (is_null($apptokarr['C'])) {
160  $CAUTH = $apptokarr['A'];
161  } else {
162  $CAUTH = $apptokarr['C'];
163  }
164  $MEMBER = $apptokarr['A'];
165  $EXPIRES = $apptokarr['E'];
166  $hash = MD5($apptokenkey .
167  MD5(join(':', array($apptokenkey, $EXPIRES, $CU, $MEMBER, $CAUTH))));
168  if ($apptokarr['H'] != $hash) {
169  throw new Exception("Invalid Credentials (Corrupted Token) " . __LINE__,15510);
170  }
171 
172 } else {
173  # No USERKEY, default to aggregate AUTH method
174  # for Odyssey, USERID will represent a user_name (login id) value
175  $AUTHMODE = 'MFA';
176  if (empty($inPost['USERID']) || strlen(trim($inPost['USERPASS'])) < 4) {
177  throw new Exception("Invalid Credentials",2040); #MFA missing ID / PASS
178  }
179  $MEMBER = $inPost['USERID'];
180  $CAUTH = $inPost['USERID'];
181  # odyssey shouldn't need this code - this stripped leading zeros from member number for all but the clients listed
182  if (!(preg_match("/\D/", $MEMBER)) && $live && $CU != 'FTCFCU' && $CU != 'UPFCU' && $CU != 'LCSFCU' && $CU != 'CEFCU') {
183  $MEMBER = preg_replace("/^0*/", "", $MEMBER);
184  $CAUTH = $MEMBER;
185  }
186 }
187 
188 
189 if (!empty($MEMBER) && (preg_match("/[\\\`,\"\s;]/", $MEMBER))) {
190  throw new Exception("Invalid Credentials",2041); #Member Bad Characters
191 }
192 # always consider CRED3 as containing ORG:MEMBER, even if USERKEY came in
193 # app always knows CU & Member
194 
195 $hash = hash_hmac('MD5', "${inPost['APPID']}${inPost['ORG']}:${MEMBER}${inPost['CRED2']}", $appkey);
196 #$show = "C member $MEMBER A cauth $CAUTH ${inPost['APPID']}${inPost['ORG']}:${MEMBER}${inPost['CRED2']}";
197 if ($inPost['CRED3'] != $hash) {
198 // $foostring = "Member $MEMBER Cauth $CAUTH\n" . print_r($inPost,true);
199 // $HB_ENV["SYSENV"]["logger"]->info( $foostring );
200  throw new Exception("Authentication Failed",2050); # cred3
201 }
202 if (empty($CU) || empty($MEMBER)) {
203  # shouldn't be able to get here, but just in case ....
204  throw new Exception("Authentication Failed",2004); # missing CU / MEMBER
205 }
206 # set the basics so we can get the rest...
207 $HB_ENV['CU'] = $CU;
208 $HB_ENV['Cu'] = $CU;
209 $HB_ENV['cu'] = $CU;
210 $HB_ENV['AuthMode'] = $AUTHMODE;
211 $cu = $CU;
212  $foostring = "HB_ENV \n" . print_r($HB_ENV,true) . "\n";
213  $HB_ENV["SYSENV"]["logger"]->info( $foostring );
214 
215 // ** First Check HomeBanking Status Online / Offline / database active
216  // * This should set the dbh and HB_ENV value
217  // ** Use the method FROM Mobile
218  Check_HomeCU_Status($dbh, $HB_ENV);
219 
220 
221 $HB_ENV['platform'] = $client_source_override;
222 
223 Load_HB_ENV($dbh, $CU, $MEMBER, $inPost['USERPASS'], $CAUTH, $HB_ENV, $CFGFLAG);
224 # set these things so they are available from the Global scope for
225 # throtlpkt functions
226 $MEMBER=$HB_ENV['Uid'];
227 $Cu = $HB_ENV['Cu'];
228 $Cn = $HB_ENV['Cn'];
229 $CAUTH = $HB_ENV['Cauth'];
230 $Clw = $HB_ENV['livewait'];
231 $Ml = urldecode($HB_ENV['Ml']);
232 
233 $dflt_date = date("Ymd", time() - (30 * 24 * 60 * 60));
234 $dflt_date = date("Ymd", time() - (300 * 24 * 60 * 60));
235 $dflt_end = date("Ymd", time() + (4 * 24 * 60 * 60)); # + 4 days
236 $DTSTART = (empty($inPost['DTSTART']) ? "$dflt_date" : $inPost['DTSTART']);
237 $DTEND = (empty($inPost['DTEND']) ? "$dflt_end" : $inPost['DTEND']);
238 $sqlend = sqlmdy($DTEND);
239 if ("$sqlend" == '')
240  $sqlend = $dflt_end;# won't ever hit now, but left it anyway...
241 
242 $HB_ENV['allowReadonly'] = true;
243 if (!hcu_checkOffline($dbh, $HB_ENV)) {
244  throw new Exception($HB_ENV['offlineblurb'],15520); # CU is marked offline
245  exit;
246 }
247 if ($HB_ENV['Cn'] == "") {
248  throw new Exception('Authentication Failed',2003); # invalid Cn
249 }
250 if ($HB_ENV['Cu'] == "") {
251  throw new Exception('Authentication Failed',2002); # invalid Cu
252 }
253 
254 // Now supporting setting credentials from app,
255 // so 'Last Chance Login' no longer applies if UPDAWARE is set
256 $UPDAWARE = (empty($inPost['UPDAWARE']) ? 0 : 1);
257 if ($UPDAWARE == 0 && ($HB_ENV['Ffchg'] == 'Y' || $HB_ENV['Ffreset'] > 0) && $HB_ENV['Ffremain'] == 1) {
258  throw new Exception('Member Last Chance Login - Please log in through the full Home Banking site to reset security credentials.',15503);
259 }
260 
261 # now that the HB_ENV array is filled, finish authentication if MFA
262 
263 if ($AUTHMODE == "MFA") {
264  # moved this block inside the MFA check -- otherwise
265  # posting updates or asking for more data after logging in with alias
266  # would cause error because USERKEY is always built with Member#
267  #
268  # this block doesn't apply for odyssey - everyone logs in with username
269 // if ($HB_ENV['useralias'] != '' && $MEMBER == $HB_ENV['Cn']) {
270 // $sth = db_query("select hcumbrloginfailed('$Cu','$Cn',$MEM_LOGIN_FAILED_ALIAS)", $dbh);
271 // $p_meta = array('UA' => $_SERVER['HTTP_USER_AGENT']);
272 // $p_hbenv = array('Cu' => $CU, 'Cn' => $Cn, 'user_id' => $HB_ENV['Uid']);
273 // TrackUserLogin($dbh, $p_hbenv, $client_source_override, $MEM_LOGIN_FAILED_ALIAS, $_SERVER['REMOTE_ADDR'], $p_meta);
274 //
275 // throw new Exception('Invalid Account or Username',15507);
276 // }
277  # moved this block inside the MFA check -- otherwise
278  # posting updates or asking for more data on last login
279  # would cause 'locked out' error
280  # failedremain <= 0 - too many failed logins
281  # forceupdate 9 - force pwd change or alias required & forceremain 0
282  # forceupdate 4 - can be set w/need more challenge or empty confidence or force security reset
283  # only lock out if force security resect and forceremain 0
284  # otherwise, flow through and will present security change
285  if ($HB_ENV['failedremain'] <= 0 ||
286  ( ($HB_ENV['forceupdate'] & 9) > 0 && $HB_ENV['Ffremain'] <= 0 ) ||
287  ( ($HB_ENV['forceupdate'] & 4) > 0 && $HB_ENV['Ffreset'] == 2 && $HB_ENV['Ffremain'] <= 0 )) {
288  throw new Exception('Member Account Locked',15502); # locked
289  }
290 
291  # check USERPASS as password
292  if (!(trim($inPost['USERPASS']) > '' && $HB_ENV['password'] == crypt($inPost['USERPASS'], $HB_ENV['password']) && ( preg_match('/^\$1\$/', $HB_ENV['password']) || strlen($inPost['USERPASS']) < 9))) {
293  # password failed
294  $sth = db_query("select hcumbrloginfailed('$CU','{$HB_ENV['Cn']}',16)", $dbh);
295  $p_meta = array('UA' => $_SERVER['HTTP_USER_AGENT']);
296  $p_hbenv = array('Cu' => $CU, 'Cn' => $HB_ENV['Cn'], 'user_id' => $HB_ENV['Uid']);
297  TrackUserLogin($dbh, $p_hbenv, $client_source_override, 16, $_SERVER['REMOTE_ADDR'], $p_meta);
298 
299  throw new Exception("Authentication Failed",15505); # password
300  } else {
301  # password ok, if Force pwd or verify mail, send upd request or fall thru to send data
302  # if not online, set the logtrack parameters to NOT decrement the remaining logins
303  $must = ($HB_ENV['offline'] != 'N' || ($HB_ENV['forceupdate'] & 13) == 0 ? 'N' : 'Y');
304  $tomorrow = date('Y-m-d', mktime(0, 0, 0, date("m"), date("d") + 1, date("Y")));
305  $pchange = ($HB_ENV['offline'] != 'N' ? $tomorrow : $HB_ENV['pwchange']);
306  $adjust = ($must == 'Y' ? 1 : 0);
307 
308  if ($HB_ENV['cver'] == 'L') {
309  # Legacy login method, update login tracker and see if update is requested
310  $sth = db_query("select logtrack('$CU','{$HB_ENV['Cn']}','$must','$pchange','$client_source_override')", $dbh);
311  $p_meta = array('UA' => $_SERVER['HTTP_USER_AGENT']);
312  $p_hbenv = array('Cu' => $CU, 'Cn' => $HB_ENV['Cn'], 'user_id' => $HB_ENV['Uid']);
313  TrackUserLogin($dbh, $p_hbenv, $client_source_override, 0, $_SERVER['REMOTE_ADDR'], $p_meta);
314 
315  # fix the value in HB_ENV
316  $HB_ENV['Ffremain']-=$adjust;
317  if ($HB_ENV['forceupdate'] > 0 && $UPDAWARE == 1 && $HB_ENV['offline'] == 'N') {
318  Send_ReqUpdate($CU, $HB_ENV['Cn'], $HB_ENV['Cauth']);
319  }
320  } else {
321  #print_r($HB_ENV);print_r($drow);#exit;
322  # password ok & 2-factor, send upd request if security reset
323  if (($HB_ENV['forceupdate'] & 4) == 4 && $UPDAWARE == 1 && $HB_ENV['offline'] == 'N') {
324  $sth = db_query("select logtrack('$CU','{$HB_ENV['Cn']}','$must','$pchange','$client_source_override')", $dbh);
325  $p_meta = array('UA' => $_SERVER['HTTP_USER_AGENT']);
326  $p_hbenv = array('Cu' => $CU, 'Cn' => $HB_ENV['Cn'], 'user_id' => $HB_ENV['Uid']);
327  TrackUserLogin($dbh, $p_hbenv, $client_source_override, 0, $_SERVER['REMOTE_ADDR'], $p_meta);
328 
329  # and fix the corresponding value in HB_ENV
330  $HB_ENV['Ffremain']-=$adjust;
331  Send_ReqUpdate($CU, $HB_ENV['Cn'], $HB_ENV['Cauth']);
332  }
333 
334  if (MFA_defined($inPost) > 0) {
335  # if (2-factor & not security reset) & MFA_* exists, we have MFA response, validate answers
336  list($fail, $failreason) = MFA_response($dbh, $HB_ENV, $inPost);
337 
338 
339  if ($fail == 0) {
340  # challenge succeeded, update logtrack and prepare token
341 
342 // $sth = db_query("select logtrack('$CU','{$HB_ENV['Cn']}','$must','$pchange','$client_source_override')", $dbh);
343  $HB_ENV['MFA']['challenge'] = 0; # reset the 'stuck' challenge question
344  $updstat = UpdateMemberLoginTrack($dbh, $HB_ENV['cu'], $MEMBER, $must, $pchange, $client_source_override, $HB_ENV['MFA']);
345  $p_meta = array('UA' => $_SERVER['HTTP_USER_AGENT']);
346  $p_hbenv = array('Cu' => $CU, 'Cn' => $HB_ENV['Cn'], 'user_id' => $HB_ENV['Uid']);
347  TrackUserLogin($dbh, $p_hbenv, $client_source_override, 0, $_SERVER['REMOTE_ADDR'], $p_meta);
348 
349  # and fix the corresponding value in HB_ENV
350  $HB_ENV['Ffremain']-=$adjust;
351 
352  if ($HB_ENV['forceupdate'] > 0 && $UPDAWARE == 1 && $HB_ENV['offline'] == 'N') {
353  Send_ReqUpdate($CU, $HB_ENV['Cn'], $HB_ENV['Cauth']);
354  }
355  } else {
356 // print "Failed $fail because $failreason"; exit;
357  $updstat = UpdateMemberFailedLogin($dbh, $HB_ENV['cu'], $MEMBER, $GLOBALS['MEM_LOGIN_FAILED_QST']);
358  $p_meta = array('UA' => $_SERVER['HTTP_USER_AGENT']);
359  $p_hbenv = array('Cu' => $CU, 'Cn' => $HB_ENV['Cn'], 'user_id' => $HB_ENV['Uid']);
360  TrackUserLogin($dbh, $p_hbenv, $client_source_override, $failreason, $_SERVER['REMOTE_ADDR'], $p_meta);
361 
362  MFA_send_chall($dbh, $HB_ENV, $MC);
363  }
364  } else {
365  # no MFA_, but still 2-factor, send challenge
366  MFA_send_chall($dbh, $HB_ENV, $MC);
367  }
368  }
369  }
370 }
371 apache_note('user_name', "{$CU}:{$HB_ENV['Cn']}");
372 //$apptoken = MakeUserkey($CU, $HB_ENV['Cn'], $HB_ENV['Cauth']);
373 $apptoken = MakeUserkey($CU, $HB_ENV['Uid'], $HB_ENV['Cauth']);
374 
375 $PASSWITH = $inPost['PASSWITH'];
376 switch ($inPost['RQMODE']) {
377  case "IPAYTKN":
378  require_once('ipay.i');
379 
380  $Cu = $HB_ENV['Cu'];
381  //$MasterKey=sha1("${Cu}:3pk4osso");
382 
383  $dbh = db_pconnect();
384  if (!hcu_checkService($dbh, "IPAY")) {
385  $omsg = hcu_checkServiceMsg($dbh, "IPAY");
386  throw new Exception($omsg,2077); # ipay offline
387  }
388 
389  # if IPAYTAG is not provided, default to IPAYAPP
390  # look up cutrusteddetail with key IPAYTAG
391  # to get MOC status, url addresses, institution id, etc.
392 
393  $parray['Cu'] = $Cu;
394  if (!empty($IPAYTAG)) {
395  $parray['trustedid'] = $IPAYTAG;
396  } else {
397  $parray['trustedid'] = "IPAYAPP";
398  $IPAYTAG = "IPAYAPP";
399  }
400  $trusted = cutd_read($dbh, $parray);
401  if ($trusted['status']['Response'] == 'false') {
402  throw new Exception("Bill Pay Service not configured",2076); # no trusted vendor rec
403  }
404 
405  $parms = $trusted['data']["$Cu|$IPAYTAG"];
406  $moc = $parms['moc'];
407  $datemodel = strtolower($parms['datemodel']);
408  if ($moc == 1) {
409  $tokenurl = $parms['moctoken'];
410  $password = $parms['mocpass'];
411  $serviceurl = $parms['mocservice'];
412  } else {
413  $tokenurl = $parms['tokenurl'];
414  $password = $parms['password'];
415  $serviceurl = $parms['serviceurl'];
416  }
417 
418  $parray = array('InstitutionId' => $parms['InstitutionId'], 'password' => $password, 'tokenurl' => $tokenurl);
419  $tokenresp = ipayGetToken($parray);
420  $token = $tokenresp['ipaydata']['token'];
421 
422  $billpay = Get_Billpayid($dbh, $HB_ENV, $IPAYTAG);
423 
424  if (!preg_match('/[^0-]/', $token)) {
425  throw new Exception("Bill Pay Service not available",2075); # get token failed
426  } else {
427  $billpayid = trim($billpay['billpayid']);
428  $ofxcount += countprint("<IPAYTKN>\n<STATUS>\n<CODE>0</CODE>\n");
429  $ofxcount += countprint("<SEVERITY>INFO</SEVERITY>\n</STATUS>\n");
430  $ofxcount += countprint("<GETTOKENRESULT>$token</GETTOKENRESULT>\n");
431  if ("$billpayid" != "" && "$billpayid" !== $HB_ENV['Cn']) {
432  $ofxcount += countprint("<BILLPAYID>$billpayid</BILLPAYID>\n");
433  }
434  $ofxcount += countprint("<INSTITUTIONID>${parms['InstitutionId']}</INSTITUTIONID>\n");
435  if ($moc == 1) {
436  $ofxcount += countprint("<MOCSERVICE>$moc</MOCSERVICE>\n");
437  }
438  if ($datemodel == 'due') {
439  $ofxcount += countprint("<DATEMODEL>DUE</DATEMODEL>\n");
440  } else {
441  $ofxcount += countprint("<DATEMODEL>PROCESS</DATEMODEL>\n");
442  }
443  $ofxcount += countprint("<MOBILESERVICESERVER>$serviceurl</MOBILESERVICESERVER>\n");
444  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
445  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
446  $ofxcount += countprint("</IPAYTKN>\n");
447  exit;
448  }
449  break;
450  case "PASSTHRU":
451 
452  $now = time();
453  $expires = $now + $HB_ENV['SYSENV']['ticket']['expires'];
454 
455  $mycookie = "Ctime=$now&Cu={$HB_ENV['Cu']}&Cn={$HB_ENV['Cn']}&Uid={$HB_ENV['Uid']}&Ce=$expires&Ca=&Cauth={$CAUTH}&Ffchg={$HB_ENV['Ffchg']}&Ffremain={$HB_ENV['Ffremain']}&Fset={$HB_ENV['Fset']}&Fset2=${HB_ENV['Fset2']}&Fset3={$HB_ENV['Fset3']}&Fhdays={$HB_ENV['Fhdays']}&Flite=0&Clw={$HB_ENV['livewait']}&Clu={$HB_ENV['Clu']}&Fplog={$HB_ENV['Fplog']}&Fflog={$HB_ENV['Fflog']}&Fmsg_tx={$HB_ENV['Fmsg_tx']}&Ml={$HB_ENV['Ml']}&Flang=$Flang&Ffreset={$HB_ENV['Ffreset']}";
456 
457  SetTicket($HB_ENV,"", $mycookie);
458 
459  switch ($inPost['PASSTO']) {
460  # seems extra, but this way we can change stuff at homecu
461  # without having to recompile app.
462  case "CKIMAGE":
463  $PSCRIPT = $HB_ENV['homebankingpath'];
464  $PSCRIPT .= "/ImageSOLO.prg";
465  $PSCRIPT .= "?cu=${HB_ENV['Cu']}";
466  break;
467  case "EXTERNAL":
468  $PSCRIPT = urldecode($PASSWITH);
469  if (stripos($PSCRIPT, 'homecu') !== false) {
470  $delim = (strpos($PSCRIPT, '?') === false ? '?' : '&');
471  $PSCRIPT .= "{$delim}vanilla=1";
472  }
473  $PASSWITH = '';
474  break;
475  case "SSO":
476  $PSCRIPT = $HB_ENV['homebankingpath'];
477  $PSCRIPT .= "/hcuConnect";
478  $PSCRIPT .= "?cu=${HB_ENV['Cu']}";
479  # apps request plain vanilla screen, not upgrade-pretty
480  $PSCRIPT .= "&vanilla=1";
481  break;
482  default:
483  $PSCRIPT = $HB_ENV['homebankingpath'];
484  $PSCRIPT .= "/$PASSTO";
485  $PSCRIPT .= "?cu=${HB_ENV['Cu']}";
486  }
487  if (!empty($PASSWITH))
488  $PSCRIPT .= "&" . urldecode($PASSWITH);
489 
490  header("Location: $PSCRIPT");
491  exit;
492 
493  break;
494  case "ESTMT_PDF":
495  # PERKEY is the period key for the desired statement
496  # this could just parse PASSWITH into the environment, but I want to only take the parts I expect -
497  $pass = array();
498  parse_str($PASSWITH, $pass);
499  $stId = $pass['PERKEY'];
500  # if stId is blank throw error
501  # Create_PDF_Statement will be responsible for the output
502  $pdfinfo = Create_PDF_Statement($stId, $HB_ENV, $MC);
503 
504  break;
505 
506  case "NOTICE":
507  #$PASSWITH="NOTICE_TYPE=${TYPE}&NOTICE_ID=${ID}&NOTICE_ACTION=${ACTION}&NOTICE_RESP=${ANSWERID}";
508  # TYPE indicates notice, survey, mktg message, promo etc
509  # ID is the notice id previously sent or 0 if this is a 'get'
510  # ACTION is P for post or V to view/get
511  # ANSWERID (optional) is the chosen response for survey/mktg message
512 # this could just parse PASSWITH into HB_ENV['HCUPOST'], but I want to only take the parts I expect -
513  $pass = array();
514  parse_str($PASSWITH, $pass);
515 
516  switch ($pass['NOTICE_ACTION']) {
517  case 'P':
518  # action P post so set up the HCUPOST array
519  if (!empty($pass['NOTICE_ID']))
520  $HB_ENV['HCUPOST']['notice_id'] = $pass['NOTICE_ID'];
521  if (!empty($pass['NOTICE_TYPE']))
522  $HB_ENV['HCUPOST']['notice_type'] = $pass['NOTICE_TYPE'];
523 
524  $resp_arr = ANS_list($pass);
525  $HB_ENV['HCUPOST']['notice_response'] = array();
526  foreach ($resp_arr as $key => $value) {
527  #print "key $key value $value <br>";
528  $HB_ENV['HCUPOST']['notice_response'][] = $value;
529  }
530 
531  $HB_ENV['HCUPOST']['notice_device'] = 'P';
532  $HB_ENV['HCUPOST']['notice_msg_show'] = 1;
533 
534  $response = Update_NoticeInfo($dbh, $HB_ENV, $MC);
535  # deal with response
536  if (count($response['status']['errors']) > 0) {
537  throw new Exception(implode(" ",$response['status']['errors']),15530); # Update_NoticeInfo
538  } else {
539  $ofxcount += countprint("<NOTICE_RESPONSE>\n<STATUS>\n<CODE>0</CODE>\n");
540  $ofxcount += countprint("<SEVERITY>INFO</SEVERITY>\n</STATUS>\n");
541  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
542  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
543 
544  $ofxcount += countprint("<NOTICE>\n");
545  if (count($response['notice_results'])) {
546  foreach ($response['notice_results'] as $noticekey => $details) {
547  $ofxcount += countprint("<NOTICE_TYPE>{$details['notice_type']}</NOTICE_TYPE>\n");
548  $ofxcount += countprint("<NOTICE_ID>{$details['notice_id']}</NOTICE_ID>\n");
549  $ofxcount += countprint("<NOTICE_POPUP>{$details['notice_popup']}</NOTICE_POPUP>\n");
550  if ($pass['NOTICE_TYPE'] == 'N') {
551  $ofxcount += countprint("<NOTICE_DONOTSHOWTEXT>" . htmlentities($details['notice_donotshowtext'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</NOTICE_DONOTSHOWTEXT>\n");
552  $ofxcount += countprint("<NOTICE_LINKTARGET>{$details['notice_linktarget']}</NOTICE_LINKTARGET>\n");
553  $ofxcount += countprint("<NOTICE_LINKDISPLAY>" . htmlentities($details['notice_linkdisplay'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</NOTICE_LINKDISPLAY>\n");
554  }
555  $ofxcount += countprint("<NOTICE_INTRO>" . htmlentities($details['notice_intro'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</NOTICE_INTRO>\n");
556  $ofxcount += countprint("<NOTICE_TITLE>" . htmlentities($details['notice_title'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</NOTICE_TITLE>\n");
557  $ofxcount += countprint("<NOTICE_TEXT>" . htmlentities(CleanWordQuotes($details['notice_text']), ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</NOTICE_TEXT>\n");
558  $ofxcount += countprint("<NOTICE_ANSWERTYPE>{$details['notice_answertype']}</NOTICE_ANSWERTYPE>\n");
559  $ofxcount += countprint("<NOTICE_ANSWERS>\n");
560  if (count($details['notice_answers'])) {
561  foreach ($details['notice_answers'] as $anskey => $ansdetl) {
562  $ofxcount += countprint("<ANSWER>\n");
563  $ofxcount += countprint("<ANSWER_ID>ANS_{$ansdetl['answer_id']}</ANSWER_ID>\n");
564  $ofxcount += countprint("<ANSWER_TEXT>" . htmlentities(CleanWordQuotes($ansdetl['answer_text']), ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</ANSWER_TEXT>\n");
565  $ofxcount += countprint("<ANSWER_VOTES>{$ansdetl['answer_votes']}</ANSWER_VOTES>\n");
566  $ofxcount += countprint("<ANSWER_PCT>{$ansdetl['answer_pct']}</ANSWER_PCT>\n");
567  $ofxcount += countprint("</ANSWER>\n");
568  }
569  }
570  $ofxcount += countprint("</NOTICE_ANSWERS>\n");
571  }
572  }
573  $ofxcount = + countprint("</NOTICE>\n");
574  $ofxcount = + countprint("</NOTICE_RESPONSE>");
575  }
576  break;
577 
578  case 'V':
579  case 'G': # gather multiple promos plus one survey/message
580  if ($pass['NOTICE_TYPE'] == 'N') {
581  $response = Get_NoticeInfo($dbh, $HB_ENV, $MC, 'P', $pass['NOTICE_ID'], 0);
582  } else {
583  $response = Get_NoticeInfo($dbh, $HB_ENV, $MC, 'P', $pass['NOTICE_TYPE']);
584  }
585  if (count($response['status']['errors']) > 0) {
586  throw new Exception(implode(" ",$response['status']['errors']),15540); # Get_NoticeInfo
587  } else {
588  $ofxcount += countprint("<NOTICE_MESSAGE>\n<STATUS>\n<CODE>0</CODE>\n");
589  $ofxcount += countprint("<SEVERITY>INFO</SEVERITY>\n</STATUS>\n");
590  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
591  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
592 
593  if (count($response['notice'])) {
594  foreach ($response['notice'] as $noticekey => $details) {
595  $ofxcount += countprint("<NOTICE>\n");
596  /*
597  * if no answer list but I have a donotshowtext, send that as an answer
598  */
599  if (!count($details['notice_answers']) && sizeof($details['notice_donotshowtext'])) {
600  $details['notice_answers'][] = array('answer_id' => $details['notice_id'], 'answer_text' => $details['notice_donotshowtext']);
601  $details['notice_answertype'] = 'M';
602  }
603  foreach ($details as $key => $value) {
604  $key = strtoupper($key);
605  switch ($key) {
606  case "NOTICE_ANSWERS":
607  $ofxcount += countprint("<NOTICE_ANSWERS>\n");
608  foreach ($value as $anskey => $ansdetl) {
609  $ofxcount += countprint("<ANSWER>\n");
610  $ofxcount += countprint("<ANSWER_ID>ANS_{$ansdetl['answer_id']}</ANSWER_ID>\n");
611  $ofxcount += countprint("<ANSWER_TEXT>" . htmlentities(CleanWordQuotes($ansdetl['answer_text']), ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</ANSWER_TEXT>\n");
612 
613  $ofxcount += countprint("</ANSWER>\n");
614  }
615  $ofxcount += countprint("</NOTICE_ANSWERS>\n");
616 
617  break;
618  case "NOTICE_TEXT":
619  if ($pass['NOTICE_TYPE'] != 'N') {
620  $ofxcount += countprint("<$key>" . htmlentities(CleanWordQuotes($value), ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
621  }
622  break;
623  /*
624  * ignore these
625  */
626  case "NOTICE_DONOTSHOWTEXT":
627  case "NOTICE_MSG_TX":
628  case "NOTICE_MSG_TX_SHOW":
629  case "NOTICE_MSG_TX_PERM":
630  case "NOTICE_SUPPRESSRESPONSE":
631  case "NOTICE_POSTTARGET":
632  break;
633  case "NOTICE_TYPE":
634  case "NOTICE_ID":
635  case "NOTICE_POPUP":
636  case "NOTICE_ANSWERTYPE":
637  case "NOTICE_LINKTARGET":
638  case "NOTICE_LINKDISPLAY":
639  case "NOTICE_INTRO":
640  case "NOTICE_TITLE":
641  default:
642 
643  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
644  }
645  }
646  $ofxcount += countprint("</NOTICE>");
647  }
648  } else {
649  $ofxcount += countprint("<NOTICE></NOTICE>");
650  }
651 
652  $ofxcount = + countprint("</NOTICE_MESSAGE>");
653  }
654  break;
655 
656  default:
657  # unknown notice_action -- ignore?
658  throw new Exception("Unknown Notice Mode",15550);
659  }
660 
661  break;
662 
663  case "TXLIST":
664  $HB_ENV['allowReadonly'] = false;
665  if (!hcu_checkOffline($dbh, $HB_ENV)) {
666  throw new Exception($HB_ENV['offlineblurb'],15520); # TXLIST cu not online
667  exit;
668  }
669 # OFXRequest will accept CFGFLAG from app, set it in HB_ENV so it passes to TX_list / TX_post
670 # this was to maintain Fmsg_tx session flags w/o html session
671 # but didn't want to limit to ONLY Fmsg_tx - might need others in future
672 # coding ready for test in OFXRequest but not ready in server functions
673 #if cfgflag came in from app, pass it along on TX_list / TX_post call
674 # look for updated setting (of cfgflag? or of Fmsg_tx?) on return
675 # pass updated setting to app so they can return it again?
676 // $HB_ENV['Fmsg_tx'] = ($HB_ENV['Fmsg_tx'] | $HB_ENV['cfgflag']);
677  $txreturn = TX_list($dbh, $HB_ENV);
678  if (count($txreturn['status']['errors']) > 0) {
679  throw new Exception(implode(' ',$txreturn['status']['errors']),15560); # TX_list returns System Unavailable
680  } else {
681  $fc = 0;
682  foreach ($txreturn['acctlist'] as $tx) {
683  if ($tx['from'] == 'Y')
684  $fc++;
685  }
686 
687 # FIX FOR PROD - Error checking, anyone?
688 # send appropriate status if we can't get a list
689 
690  if ($fc == 0) {
691  throw new Exception("No Accounts Available",15570); # TX_list no valid accounts
692  } else {
693  $ofxcount += countprint("<TXLIST>\n<STATUS>\n<CODE>0</CODE>\n");
694  $ofxcount += countprint("<SEVERITY>INFO</SEVERITY>\n</STATUS>\n");
695  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
696  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
697  $ofxcount += countprint("<TRMEMOMAX>${HB_ENV['trmemomaxlen']}</TRMEMOMAX>\n");
698  foreach ($txreturn['acctlist'] as $acctkey => $details) {
699  $ofxcount += countprint("<ACCT>\n<ACCTID>$acctkey</ACCTID>\n");
700  foreach ($details as $key => $value) {
701  $key = strtoupper($key);
702  $ofxcount += countprint("<$key>$value</$key>\n");
703  }
704  $ofxcount += countprint("</ACCT>\n");
705  }
706 
707 # now get the transfer notice, if any
708  $txnotice = Get_NoticeInfo($dbh, $HB_ENV, $MC, 'P', 'transferNotice', 0);
709  $ofxcount += countprint("<NOTICE>\n");
710  if (count($txnotice['notice'])) {
711  foreach ($txnotice['notice'] as $noticekey => $details) {
712  /*
713  * if no answer list but I have a donotshowtext, send that as an answer
714  */
715  if (!count($details['notice_answers']) && sizeof($details['notice_donotshowtext'])) {
716  $details['notice_answers'][] = array('answer_id' => $details['notice_id'], 'answer_text' => $details['notice_donotshowtext']);
717  $details['notice_answertype'] = 'M';
718  }
719  foreach ($details as $key => $value) {
720  $key = strtoupper($key);
721  switch ($key) {
722  case "NOTICE_ANSWERS":
723  $ofxcount += countprint("<NOTICE_ANSWERS>\n");
724  foreach ($value as $anskey => $ansdetl) {
725  $ofxcount += countprint("<ANSWER>\n");
726  $ofxcount += countprint("<ANSWER_ID>ANS_{$ansdetl['answer_id']}</ANSWER_ID>\n");
727 // $ofxcount += countprint("<ANSWER_TEXT>{$ansdetl['answer_text']}</ANSWER_TEXT>\n");
728  $ofxcount += countprint("<ANSWER_TEXT>" . htmlentities(CleanWordQuotes($ansdetl['answer_text']), ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</ANSWER_TEXT>\n");
729 
730  $ofxcount += countprint("</ANSWER>\n");
731  }
732  $ofxcount += countprint("</NOTICE_ANSWERS>\n");
733 
734  break;
735  /*
736  * ignore these
737  */
738  case "NOTICE_INTRO":
739  case "NOTICE_TITLE":
740  case "NOTICE_DONOTSHOWTEXT":
741  case "NOTICE_MSG_TX":
742  case "NOTICE_MSG_TX_SHOW":
743  case "NOTICE_MSG_TX_PERM":
744  case "NOTICE_SUPPRESSRESPONSE":
745  case "NOTICE_POSTTARGET":
746  case "NOTICE_TEXT":
747  break;
748  case "NOTICE_TYPE":
749  case "NOTICE_ID":
750  case "NOTICE_POPUP":
751  case "NOTICE_ANSWERTYPE":
752  case "NOTICE_LINKTARGET":
753  case "NOTICE_LINKDISPLAY":
754  default:
755 
756  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
757  }
758  }
759  }
760  }
761  $ofxcount += countprint("</NOTICE>");
762 
763 //
764 #
765  $ofxcount += countprint("</TXLIST>\n");
766  }
767  }
768  exit;
769  break;
770 
771  case "TXPOST":
772  $HB_ENV['allowReadonly'] = false;
773  if (!hcu_checkOffline($dbh, $HB_ENV)) {
774  throw new Exception($HB_ENV['offlineblurb'],15520); # TXPOST cu not online
775  exit;
776  }
777  # unencode the email for the txpost call
778  $HB_ENV['Ml'] = urldecode($HB_ENV['Ml']);
779 # OFXRequest will accept CFGFLAG from app, set it in HB_ENV so it passes to TX_list / TX_post
780 # this was to maintain Fmsg_tx session flags w/o html session
781 # but didn't want to limit to ONLY Fmsg_tx - might need others in future
782 # coding ready for test in OFXRequest but not ready in server functions
783 #if cfgflag came in from app, pass it along on TX_list / TX_post call
784 # look for updated setting (of cfgflag? or of Fmsg_tx?) on return
785 # pass updated setting to app so they can return it again?
786 // $HB_ENV['Fmsg_tx'] = ($HB_ENV['Fmsg_tx'] | $HB_ENV['cfgflag']);
787 
788  $txreturn = TX_post($MC, $dbh, $HB_ENV, $FACCTID, $TACCTID, $AMOUNT, $TRMEMO);
789  # and put it back
790  $HB_ENV['Ml'] = urlencode($HB_ENV['Ml']);
791 
792  if (count($txreturn['status']['errors']) > 0) {
793  throw new Exception(implode(' ',$txreturn['status']['errors']),15580); # TX_post returns data validation errors
794  } else {
795 
796 # FIX FOR PROD - Error checking, anyone?
797 # send appropriate status if post fails
798 
799  $ofxcount += countprint("<TXPOST>\n<STATUS>\n<CODE>0</CODE>\n");
800  $ofxcount += countprint("<SEVERITY>INFO</SEVERITY>\n</STATUS>\n");
801  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
802  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
803  foreach ($txreturn['txn'] as $key => $value) {
804  $key = strtoupper($key);
805  $ofxcount += countprint("<$key>$value</$key>\n");
806  }
807  $ofxcount += countprint("</TXPOST>\n");
808  }
809  exit;
810  break;
811 
812  case "MEMBERSETTINGS":
813  #$PASSWITH contains
814  // GETALLOWED=1 for Show Allowed Settings
815  // OR
816  // GETSETTINGS=2 for Email
817  // GETSETTINGS=4 for Challenge
818  // GETSETTINGS=8 for UserAlias
819  // GETSETTINGS values can be combined - 10 would get both email & alias
820  #
821  $pass = array();
822  parse_str($PASSWITH, $pass);
823 
824  if ($pass['GETALLOWED'] == '1') {
825  Send_AllowedUpdate($CU, $HB_ENV['Cn'], $HB_ENV['Cauth']);
826  } else {
827  $HB_ENV['requpdate'] = ($pass['GETSETTINGS'] & $HB_ENV['allowupdate']); #limit acceptable values based on cu config
828  if ($HB_ENV['requpdate'] == 0) {
829  throw new Exception('Invalid Settings Request',3125); # unrecognized GETSETTINGS request or not configured
830  } else {
831  Send_ReqUpdate($CU, $HB_ENV['Cn'], $HB_ENV['Cauth']);
832  }
833  }
834  break;
835  case "CHECKALIAS":
836  $pass = array();
837  parse_str($PASSWITH, $pass);
838  $upd_fields['settings_alias']['username'] = $pass['UALIAS'];
839  $upd_fields['settings_alias']['username_confirm'] = $pass['UALIAS'];
840  $upd_fields['settings_alias']['username_required'] = ($HB_ENV['alias'] == 'REQUIRE' ? 'Y' : 'N');
841  $aryUpdate = Validate_Settings($dbh, $HB_ENV, $upd_fields, $MC);
842 
843  if ($aryUpdate['status']['code'] == '000') {
844  Send_ResponseOK($CU, $HB_ENV['Uid'], $HB_ENV['Cauth'], 0, "OK Selected Alias is valid and available"); # Selected Alias is valid and available
845  } else {
846  throw new Exception(implode(' ',$aryUpdate['status']['errors']), 3162); # Selected Alias is not valid or usable
847  }
848  break;
849 
850  case "UPDCRED":
851  #$PASSWITH contains name=value pairs for each credential to be updated
852 # this could just parse PASSWITH into HB_ENV['HCUPOST'], but I want to only take the parts I expect -
853  $pass = array();
854  parse_str($PASSWITH, $pass);
855 
856  if ($pass['ASKLATER'] == 1) {
857  if ($HB_ENV['forceupdate'] > 0 && $HB_ENV['Ffremain'] == 0) {
858  throw new Exception('Requested Updates cannot be deferred',3150); # got 'ask later' response w/0 grace logins remaining
859  } else {
860  Send_ResponseOK($CU, $HB_ENV['Uid'], $HB_ENV['Cauth'], 1, "OK Updates Deferred");
861  }
862  } else {
863  # process updates
864  # start out thinking we won't need a transaction
865  $bolSQLTransaction = false;
866 
867  if (($HB_ENV['allowupdate'] & 4) == 4) {
868  # if challenge stuff allowed and provided, set fields to update,
869  // CQID_*, CQANS_*, CONFWORD, CURPWD
870  if (!empty($pass['CONFWORD'])) {
871  $upd_fields['settings_confidence']['confword'] = $pass['CONFWORD'];
872  }
873  // ** Challenge Questions / Responses
874  // ** loop through the question, just assume they start at 1 and go to the number defined in HB_ENV['cu_chgqst_count']
875  $quest_idx = 1;
876  while (array_key_exists("CQID_{$quest_idx}", $pass)) {
877  $upd_fields['settings_questions'][] = Array('cqid' => $pass["CQID_{$quest_idx}"], 'display' => $pass["CQANS_{$quest_idx}"]);
878  $quest_idx++;
879  }
880  }
881  // if passwd stuff, set fields to update,
882  // NEWPWD, CURPWD
883  if (trim($pass['NEWPWD']) > '') {
884  $upd_fields['settings_password']['newpasswd'] = $pass['NEWPWD'];
885  $upd_fields['settings_password']['confpasswd'] = $pass['NEWPWD'];
886  }
887  // if no error, change pwchange date, clear Ffchange
888  //
889  // if email stuff, set fields to update,
890  // EMAIL, OPTIN
891  if (!empty($pass['EMAIL'])) {
892  $upd_fields['settings_email']['email'] = $pass['EMAIL'];
893  $upd_fields['settings_email']['egenl'] = $pass['OPTIN'];
894  $upd_fields['settings_email']['verify'] = ($HB_ENV['Fverifyml'] == 512 ? 'Y' : 'N');
895  $upd_fields['settings_email']['valid'] = 'Y';
896  }
897  //
898  // if alias stuff allowed/required and provided, set fields to update
899  // UALIAS, CURPWD
900  if (($HB_ENV['allowupdate'] & 8) == 8 && ($pass['UALIAS']) != '') {
901  $upd_fields['settings_alias']['username'] = $pass['UALIAS'];
902  $upd_fields['settings_alias']['username_confirm'] = $pass['UALIAS'];
903  $upd_fields['settings_alias']['username_required'] = ($HB_ENV['alias'] == 'REQUIRE' ? 'Y' : 'N');
904  $bolSQLTransaction = true;
905  }
906  //
907 # start
908  if (trim($pass['NEWPWD']) > '') {
909  $aryUpdate = Validate_PwdRules($dbh, $HB_ENV, $upd_fields, $MC);
910 
911  if ($aryUpdate['status']['code'] != '000') {
912  // return validation errors
913  throw new Exception(implode(' ',$aryUpdate['status']['errors']),3160); # Validate_Settings
914  }
915  }
916  // ** $upd_fields contains the list of fields to update --
917  $aryUpdate = Validate_Settings($dbh, $HB_ENV, $upd_fields, $MC);
918 
919  if ($aryUpdate['status']['code'] != '000') {
920  // return validation errors
921  throw new Exception(implode(' ',$aryUpdate['status']['errors']),3160); # Validate_Settings
922  #print_r($HB_ENV); print_r($upd_fields); exit;
923  } else {
924  // ** UPDATE DATA
925 // send decoded Ml to support emailing member about change
926  $HB_ENV['Ml'] = urldecode($HB_ENV['Ml']);
927  $aryUpdate = Update_Settings($dbh, $HB_ENV, $upd_fields, $bolSQLTransaction, $MC);
928 // and then encode it again since that is how we expect to use it
929  $HB_ENV['Ml'] = urlencode($HB_ENV['Ml']);
930 
931  if ($aryUpdate['status']['code'] != '000') {
932  // return update errors
933  throw new Exception(implode(' ',$aryUpdate['status']['errors']),3170); # Update_Settings
934  } else {
935  // * SUCCESSFUL
936  // return 'OK' status
937  Send_ResponseOK($CU, $HB_ENV['Uid'], $HB_ENV['Cauth'], 1, "OK Updates Successful");
938  }
939  }
940 
941 # end
942  }
943  break;
944  case "MOBLPAY":
945  $parms = array();
946  $parms['Cu'] = $HB_ENV['Cu'];
947  $parms['Cn'] = $HB_ENV['Cn'];
948 
949  $pass = array();
950  parse_str($PASSWITH, $pass);
951  if (!isset($pass['MP_VENDOR'])) {
952  throw new Exception("Missing Mobile Pay parameters",4001);
953  }
954  switch ($pass['MP_VENDOR']) {
955  case 'IPAYMBL':
956  case 'IPAYAPP':
957  case 'IPAYTEST':
958  case 'IPAYJX':
959  if (hcu_checkService($dbh, 'IPAY') !== true) {
960  $omsg = hcu_checkServiceMsg($dbh, "IPAY");
961  throw new Exception("$omsg",999); # MOBLPAY AUTH
962  }
963  if ($pass['MP_VENDOR'] == 'IPAYJX') {
964  require_once('IPAYJX.i');
965  } else {
966  require_once('IPAYMBL.i');
967  }
968  break;
969  case 'CHKFREE':
970  if (hcu_checkService($dbh, 'CHKFREE') !== true) {
971  $omsg = hcu_checkServiceMsg($dbh, "CHKFREE");
972  throw new Exception("$omsg",999); # MOBLPAY AUTH
973  }
974  require_once('CHKFREE.i');
975  break;
976  case 'PSCUPAY_API':
977  if (hcu_checkService($dbh, 'PSCU') !== true) {
978  $omsg = hcu_checkServiceMsg($dbh, "PSCU");
979  throw new Exception("$omsg",999); # MOBLPAY AUTH
980  }
981  require_once('PSCUPAY_API.i');
982  break;
983  case 'MBLPAY_TEST':
984  # HomeCU test stub
985  require_once('MBLPAY_TEST.i');
986  break;
987  default:
988  throw new Exception("Invalid Mobile Pay vendor",4001);
989  break;
990  }
991  $parray['Cu'] = $Cu;
992  $parray['trustedid'] = $pass['MP_VENDOR'];
993  $trusted = cutd_read($dbh, $parray);
994  if ($trusted['status']['Response'] == 'false') {
995  throw new Exception("Bill Pay Service not configured",2076); # no trusted vendor rec
996  }
997  $parms = $trusted['data']["$Cu|{$pass['MP_VENDOR']}"];
998 
999  # set up logging here
1000  $loggingFlag = trim($parms["hcuLogging"]);
1001  if (strlen($loggingFlag) > 0) {
1002 
1003  $enable = $loggingFlag == -1;
1004 
1005  if (!$enable) {
1006  $loggingFlag = str_replace(" ", "", $loggingFlag);
1007  $testArray = explode(",", $loggingFlag);
1008  $enable = in_array($HB_ENV["Cn"], $testArray);
1009  }
1010 
1011  if ($enable) {
1012  // these are used inside the plugin to test if logging and info to log.
1013  $parms["logging"] = "enabled";
1014  $parms["environment"] = array("Cu" => $HB_ENV["Cu"], // credit union
1015  "memberId" => $HB_ENV["Cn"], // member id
1016  "SSOVendor" => $pass['MP_VENDOR'],
1017  "userIP" => $_SERVER['REMOTE_ADDR'], // user's ip address
1018  "dbConn" => $dbh); // database connection
1019  }
1020  }
1021 
1022  $billpay = Get_Billpayid($dbh, $HB_ENV, $pass['MP_VENDOR']);
1023  $parms['BillpayId'] = trim($billpay['billpayid']);
1024  $parms['passwith'] = $pass;
1025  switch ($pass['MP_ACTION']) {
1026  case "MP_AUTH":
1027  $mblpay = bpAuth($parms);
1028  # deal with response
1029 #
1030  if ($mblpay['status']['code'] == '000' && strlen($mblpay["data"]['Token']) > 0) {
1031  # good token, return the response
1032  $ofxcount += countprint("<MBLPAY>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1033  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1034  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1035 
1036  if (is_array($mblpay['data'])) {
1037  $ofxcount += countprint("<MP_AUTH>\n");
1038  foreach ($mblpay['data'] as $key => $value) {
1039 // $key = strtoupper($key);
1040 // $ofxcount += countprint("<$key>$value</$key>\n");
1041  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1042  }
1043  $ofxcount += countprint("</MP_AUTH>\n");
1044  }
1045  $ofxcount += countprint("</MBLPAY>\n");
1046  } else {
1047  // ** If Error messages were included in the array that is returned, then show those errors, if NOT default to feature not set message
1048  // ** Show custom errors here - no MobilePay
1049  $noticesAry = Get_NoticeInfo($dbh, $HB_ENV, $MC, "M", "mblNoMobilePay", true);
1050 
1051  if ($noticesAry["status"]["code"] == "000" && $noticesAry["notice"][0]["notice_id"]) {
1052  $noticeString = $noticesAry["notice"][0]["notice_text"];
1053  } else {
1054  $noticeString = $mblpay['status']['message'];
1055  }
1056 
1057  throw new Exception($noticeString,$mblpay['status']['code']); # MOBLPAY AUTH get token failed
1058  }
1059  break;
1060 
1061  case "MP_TERMS":
1062  $mblpay = bpGetTerms($parms);
1063  # deal with response
1064  if ($mblpay['status']['response'] == 'false') {
1065  throw new Exception($mblpay['status']['message'], $mblpay['status']['code']); # MOBLPAY AUTH
1066  }
1067 
1068  $ofxcount += countprint("<MBLPAY>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1069  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1070  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1071  $ofxcount += countprint("<TOKEN>{$pass['Token']}</TOKEN>\n");
1072 
1073  if (is_array($mblpay['data'])) {
1074  $ofxcount += countprint("<MP_TERMS>\n");
1075  foreach ($mblpay['data'] as $key => $value) {
1076 // $key = strtoupper($key);
1077 // $ofxcount += countprint("<$key>$value</$key>\n");
1078  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1079  }
1080  $ofxcount += countprint("</MP_TERMS>\n");
1081  }
1082  $ofxcount += countprint("</MBLPAY>\n");
1083 
1084 
1085  break;
1086  case "MP_ACCEPT":
1087  $mblpay = bpAcceptTerms($parms);
1088  # deal with response
1089  if ($mblpay['status']['response'] == 'false') {
1090  throw new Exception($mblpay['status']['message'], $mblpay['status']['code']); # MOBLPAY AUTH
1091  }
1092 
1093  $ofxcount += countprint("<MBLPAY>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1094  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1095  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1096  $ofxcount += countprint("<TOKEN>{$pass['Token']}</TOKEN>\n");
1097 
1098  if (is_array($mblpay['data'])) {
1099  $ofxcount += countprint("<MP_ACCEPT>\n");
1100  foreach ($mblpay['data'] as $key => $value) {
1101 // $key = strtoupper($key);
1102 // $ofxcount += countprint("<$key>$value</$key>\n");
1103  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1104  }
1105  $ofxcount += countprint("</MP_ACCEPT>\n");
1106  }
1107  $ofxcount += countprint("</MBLPAY>\n");
1108 
1109 
1110  break;
1111  case "MP_ACCTLIST":
1112  # set Account type for from
1113  # AcctType = Payment | Transfer
1114  # Detailed = 'True' | 'False' (may be missing, false)
1115  $mblfrom = bpSourceAccts($parms);
1116  # determine payment or transfer, set Account type accordingly
1117  $mblpay = bpDestAccts($parms);
1118 
1119  # deal with response
1120  if ($mblfrom['status']['response'] == 'false') {
1121  throw new Exception($mblfrom['status']['message'], $mblfrom['status']['code']); # MOBLPAY SourceAccts
1122  }
1123  if ($mblpay['status']['response'] == 'false') {
1124  throw new Exception($mblpay['status']['message'], $mblpay['status']['code']); # MOBLPAY DestAccts
1125  }
1126 
1127  $ofxcount += countprint("<MBLPAY>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1128  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1129  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1130  $ofxcount += countprint("<TOKEN>{$pass['Token']}</TOKEN>\n");
1131 
1132  if (is_array($mblfrom['data']) || is_array($mblpay['data'])) {
1133  $ofxcount += countprint("<MP_ACCTLIST>\n");
1134 
1135  if (is_array($mblfrom['data'])) {
1136 
1137  $ofxcount += countprint("<SOURCEACCTS>\n");
1138  foreach ($mblfrom['data'] as $akey => $account) {
1139  $ofxcount += countprint("<Account>\n");
1140  foreach ($account as $key => $value) {
1141  if ($key == 'AdditionalInfo') {
1142  $ofxcount += countprint("<AdditionalInfo>\n");
1143  $ofxcount += countprint(htmlentities(http_build_query($value)));
1144  $ofxcount += countprint("\n</AdditionalInfo>\n");
1145  } elseif ($key == 'Name') {
1146  $ofxcount += countprint("<Name>\n");
1147  $ofxcount += countprint(htmlentities($value));
1148  $ofxcount += countprint("\n</Name>\n");
1149  } else {
1150  // $key = strtoupper($key);
1151 // $ofxcount += countprint("<$key>$value</$key>\n");
1152  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1153  }
1154  }
1155  $ofxcount += countprint("</Account>\n");
1156  }
1157  $ofxcount += countprint("</SOURCEACCTS>\n");
1158  }
1159  if (is_array($mblpay['data'])) {
1160  $ofxcount += countprint("<DESTACCTS>\n");
1161  foreach ($mblpay['data'] as $akey => $account) {
1162  $ofxcount += countprint("<Account>\n");
1163  foreach ($account as $key => $value) {
1164  if ($key == 'AdditionalInfo') {
1165  $ofxcount += countprint("<AdditionalInfo>\n");
1166  $ofxcount += countprint(htmlentities(http_build_query($value)));
1167  $ofxcount += countprint("\n</AdditionalInfo>\n");
1168  } elseif ($key == 'Name') {
1169  $ofxcount += countprint("<Name>\n");
1170  $ofxcount += countprint(htmlentities($value));
1171  $ofxcount += countprint("\n</Name>\n");
1172  } else {
1173  // $key = strtoupper($key);
1174 // $ofxcount += countprint("<$key>$value</$key>\n");
1175  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1176  }
1177  }
1178  $ofxcount += countprint("</Account>\n");
1179  }
1180  $ofxcount += countprint("</DESTACCTS>\n");
1181  }
1182  $ofxcount += countprint("</MP_ACCTLIST>\n");
1183  }
1184  $ofxcount += countprint("</MBLPAY>\n");
1185  break;
1186  case "MP_GETPAYMENTDATES":
1187  $mblpay = bpGetPaymentDates($parms);
1188 
1189  # deal with response
1190  if ($mblpay['status']['response'] == 'false') {
1191  throw new Exception($mblpay['status']['message'], $mblpay['status']['code']); # MOBLPAY DATES
1192  }
1193 
1194  $ofxcount += countprint("<MBLPAY>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1195  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1196  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1197  $ofxcount += countprint("<TOKEN>{$pass['Token']}</TOKEN>\n");
1198 
1199  if (is_array($mblpay['data'])) {
1200  $ofxcount += countprint("<MP_GETPAYMENTDATES>\n");
1201  foreach ($mblpay['data'] as $pkey => $paydate) {
1202  switch ($pkey) {
1203  case 'RushOptions':
1204  if (is_array($paydate)) {
1205  $ofxcount += countprint("<RushOptions>\n");
1206  foreach ($paydate as $dateitem) {
1207  if (is_array($dateitem)) {
1208  $ofxcount += countprint("<Option>\n");
1209  foreach ($dateitem as $key => $value) {
1210 // $ofxcount += countprint("<$key>$value</$key>\n");
1211  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1212  }
1213  $ofxcount += countprint("</Option>\n");
1214  }
1215  }
1216  $ofxcount += countprint("</RushOptions>\n");
1217  }
1218  break;
1219  case 'PaymentDates':
1220  if (is_array($paydate)) {
1221  $ofxcount += countprint("<PaymentDates>\n");
1222  foreach ($paydate as $dateitem) {
1223  if (is_array($dateitem)) {
1224  $ofxcount += countprint("<Date>\n");
1225  foreach ($dateitem as $key => $value) {
1226 // $ofxcount += countprint("<$key>$value</$key>\n");
1227  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1228  }
1229  $ofxcount += countprint("</Date>\n");
1230  }
1231  }
1232  $ofxcount += countprint("</PaymentDates>\n");
1233  }
1234  break;
1235  default:
1236  $ofxcount += countprint("<$pkey>$paydate</$pkey>\n");
1237  break;
1238  }
1239  }
1240  $ofxcount += countprint("</MP_GETPAYMENTDATES>\n");
1241  }
1242  $ofxcount += countprint("</MBLPAY>\n");
1243  break;
1244  case "MP_HISTORY":
1245  $mblpay = bpHist($parms);
1246 
1247  # deal with response
1248  if ($mblpay['status']['response'] == 'false') {
1249  throw new Exception($mblpay['status']['message'], $mblpay['status']['code']); # MOBLPAY HIST
1250  }
1251 
1252  $ofxcount += countprint("<MBLPAY>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1253  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1254  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1255  $ofxcount += countprint("<TOKEN>{$pass['Token']}</TOKEN>\n");
1256 
1257  if (is_array($mblpay['data'])) {
1258  $ofxcount += countprint("<MP_HISTORY>\n");
1259  foreach ($mblpay['data'] as $pkey => $payment) {
1260  $ofxcount += countprint("<Payment>\n");
1261  foreach ($payment as $key => $value) {
1262  if ($key == 'AdditionalInfo') {
1263 // $value['miki']="Here & there & everywhere";
1264  $ofxcount += countprint("<AdditionalInfo>\n");
1265 // foreach ($value as $subk => $subv) {
1266 // $ofxcount += countprint("<$subk>$subv</$subk>\n");
1267 // }
1268  $ofxcount += countprint(htmlentities(http_build_query($value)));
1269  $ofxcount += countprint("\n</AdditionalInfo>\n");
1270  } else {
1271 // $key = strtoupper($key);
1272 // $ofxcount += countprint("<$key>$value</$key>\n");
1273  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1274  }
1275  }
1276  $ofxcount += countprint("</Payment>\n");
1277  }
1278  $ofxcount += countprint("</MP_HISTORY>\n");
1279  }
1280 
1281  $ofxcount += countprint("</MBLPAY>\n");
1282  break;
1283  case "MP_GETRUSHOPTIONS":
1284  $mblpay = bpGetRushOptions($parms);
1285 
1286  # deal with response
1287  if ($mblpay['status']['response'] == 'false') {
1288  throw new Exception($mblpay['status']['message'], $mblpay['status']['code']); # MOBLPAY HIST
1289  }
1290 
1291  $ofxcount += countprint("<MBLPAY>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1292  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1293  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1294  $ofxcount += countprint("<TOKEN>{$pass['Token']}</TOKEN>\n");
1295 
1296  if (is_array($mblpay['data'])) {
1297  $ofxcount += countprint("<MP_GETRUSHOPTIONS>\n");
1298  foreach ($mblpay['data'] as $key => $value) {
1299 // $key = strtoupper($key);
1300 // $ofxcount += countprint("<$key>$value</$key>\n");
1301  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1302  }
1303  $ofxcount += countprint("</MP_GETRUSHOPTIONS>\n");
1304  }
1305  $ofxcount += countprint("</MBLPAY>\n");
1306  break;
1307  case "MP_SCHEDULED":
1308  $mblpay = bpSched($parms);
1309 
1310  # deal with response
1311  if ($mblpay['status']['response'] == 'false') {
1312  throw new Exception($mblpay['status']['message'], $mblpay['status']['code']); # MOBLPAY HIST
1313  }
1314 
1315  $ofxcount += countprint("<MBLPAY>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1316  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1317  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1318  $ofxcount += countprint("<TOKEN>{$pass['Token']}</TOKEN>\n");
1319 
1320  if (is_array($mblpay['data'])) {
1321  $ofxcount += countprint("<MP_SCHEDULED>\n");
1322  foreach ($mblpay['data'] as $pkey => $payment) {
1323  $ofxcount += countprint("<Payment>\n");
1324  foreach ($payment as $key => $value) {
1325  if ($key == 'AdditionalInfo') {
1326 // $value['miki']="Here & there & everywhere";
1327  $ofxcount += countprint("<AdditionalInfo>\n");
1328 // foreach ($value as $subk => $subv) {
1329 // $ofxcount += countprint("<$subk>$subv</$subk>\n");
1330 // }
1331  $ofxcount += countprint(htmlentities(http_build_query($value)));
1332  $ofxcount += countprint("\n</AdditionalInfo>\n");
1333  } else {
1334 // $key = strtoupper($key);
1335 // $ofxcount += countprint("<$key>$value</$key>\n");
1336  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1337  }
1338  }
1339  $ofxcount += countprint("</Payment>\n");
1340  }
1341  $ofxcount += countprint("</MP_SCHEDULED>\n");
1342  }
1343  $ofxcount += countprint("</MBLPAY>\n");
1344  break;
1345 
1346  case "MP_PAYMENT":
1347  $mblpay = bpPmtAdd($parms);
1348 
1349  # deal with response
1350  if ($mblpay['status']['response'] == 'false') {
1351  throw new Exception($mblpay['status']['message'], $mblpay['status']['code']); # MOBLPAY HIST
1352  }
1353 
1354  $ofxcount += countprint("<MBLPAY>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1355  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1356  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1357  $ofxcount += countprint("<TOKEN>{$pass['Token']}</TOKEN>\n");
1358 
1359  if (is_array($mblpay['data'])) {
1360  $ofxcount += countprint("<MP_PAYMENT>\n");
1361  foreach ($mblpay['data'] as $key => $value) {
1362 // $key = strtoupper($key);
1363 // $ofxcount += countprint("<$key>$value</$key>\n");
1364  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1365  }
1366  $ofxcount += countprint("</MP_PAYMENT>\n");
1367  }
1368  $ofxcount += countprint("</MBLPAY>\n");
1369  break;
1370 
1371  case "MP_TRANSFER":
1372  $mblpay = bpTrnAdd($parms);
1373 
1374  # deal with response
1375  if ($mblpay['status']['response'] == 'false') {
1376  throw new Exception($mblpay['status']['message'], $mblpay['status']['code']); # MOBLPAY HIST
1377  }
1378 
1379  $ofxcount += countprint("<MBLPAY>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1380  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1381  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1382  $ofxcount += countprint("<TOKEN>{$pass['Token']}</TOKEN>\n");
1383 
1384  if (is_array($mblpay['data'])) {
1385  $ofxcount += countprint("<MP_TRANSFER>\n");
1386  foreach ($mblpay['data'] as $key => $value) {
1387 // $key = strtoupper($key);
1388 // $ofxcount += countprint("<$key>$value</$key>\n");
1389  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1390  }
1391  $ofxcount += countprint("</MP_TRANSFER>\n");
1392  }
1393  $ofxcount += countprint("</MBLPAY>\n");
1394  break;
1395  case "MP_EDITPMT":
1396  $mblpay = bpPmtEdit($parms);
1397 
1398  # deal with response
1399  if ($mblpay['status']['response'] == 'false') {
1400  throw new Exception($mblpay['status']['message'], $mblpay['status']['code']); # MOBLPAY HIST
1401  }
1402 
1403  $ofxcount += countprint("<MBLPAY>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1404  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1405  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1406  $ofxcount += countprint("<TOKEN>{$pass['Token']}</TOKEN>\n");
1407 
1408  if (is_array($mblpay['data'])) {
1409  $ofxcount += countprint("<MP_EDITPMT>\n");
1410  foreach ($mblpay['data'] as $key => $value) {
1411 // $key = strtoupper($key);
1412 // $ofxcount += countprint("<$key>$value</$key>\n");
1413  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1414  }
1415  $ofxcount += countprint("</MP_EDITPMT>\n");
1416  }
1417  $ofxcount += countprint("</MBLPAY>\n");
1418  break;
1419 
1420  case "MP_STOPPMT":
1421  $mblpay = bpPmtStop($parms);
1422 
1423  # deal with response
1424  if ($mblpay['status']['response'] == 'false') {
1425  throw new Exception($mblpay['status']['message'], $mblpay['status']['code']); # MOBLPAY HIST
1426  }
1427 
1428  $ofxcount += countprint("<MBLPAY>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1429  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1430  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1431  $ofxcount += countprint("<TOKEN>{$pass['Token']}</TOKEN>\n");
1432 
1433  if (is_array($mblpay['data'])) {
1434  $ofxcount += countprint("<MP_STOPPMT>\n");
1435  foreach ($mblpay['data'] as $key => $value) {
1436 // $key = strtoupper($key);
1437 // $ofxcount += countprint("<$key>$value</$key>\n");
1438  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1439  }
1440  $ofxcount += countprint("</MP_STOPPMT>\n");
1441  }
1442  $ofxcount += countprint("</MBLPAY>\n");
1443  break;
1444 
1445  default:
1446  # unknown MP_ACTION
1447  throw new Exception("Unknown MOBLPAY Mode",15550);
1448  break;
1449  }
1450  break;
1451  case "MESSAGE":
1452  $pass = array();
1453  parse_str($PASSWITH, $pass);
1454  if (!isset($pass['MSG_SERVICE'])) {
1455  throw new Exception( "Missing Message parameters",4001);
1456  }
1457  $parms = array();
1458  $parms['Cu'] = $HB_ENV['Cu'];
1459  $parms['Cn'] = $HB_ENV['Cn'];
1460  $parms['HCUPOST'] = $pass;
1461 
1462  switch ($pass['MSG_SERVICE']) {
1463  case 'MSGECO':
1464  require_once('msgECO.i');
1465  break;
1466  default:
1467  throw new Exception("Invalid Message Service",4001);
1468  break;
1469  }
1470  switch ($pass['MSG_ACTION']) {
1471  case "READ_MSGS":
1472  $msgResp = msgReadMessages($dbh, $parms);
1473 
1474  # deal with response
1475  if ($msgResp['status']['response'] == 'false') {
1476  throw new Exception($msgResp['status']['message'], $msgResp['status']['code']); # MESSAGE READ_MSGS
1477  }
1478 
1479  $ofxcount += countprint("<MESSAGE>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1480  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1481  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1482 
1483  if (is_array($msgResp['data'])) {
1484  $ofxcount += countprint("<READ_MSGS>\n");
1485  foreach ($msgResp['data'] as $key => $value) {
1486  if (is_array($value)) {
1487  $ofxcount += countprint("<MSG>\n");
1488  foreach ($value as $mkey => $mvalue) {
1489  switch ($mkey) {
1490  case 'subject':
1491  $mvalue = htmlentities($mvalue, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE);
1492  break;
1493  }
1494  $ofxcount += countprint("<$mkey>$mvalue</$mkey>\n");
1495  }
1496  $ofxcount += countprint("</MSG>\n");
1497  } else {
1498 // $ofxcount += countprint("<$key>$value</$key>\n");
1499  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
1500  }
1501  }
1502  $ofxcount += countprint("</READ_MSGS>\n");
1503  }
1504  $ofxcount += countprint("</MESSAGE>\n");
1505  break;
1506 
1507  case "READ_THREAD":
1508  $msgResp = msgReadMessageThread($dbh, $parms);
1509 
1510  # deal with response
1511  if ($msgResp['status']['response'] == 'false') {
1512  throw new Exception($msgResp['status']['message'], $msgResp['status']['code']); # MESSAGE READ_MSGS
1513  }
1514 
1515  $ofxcount += countprint("<MESSAGE>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1516  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1517  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1518 
1519  if (is_array($msgResp['data'])) {
1520  $ofxcount += countprint("<READ_THREAD>\n");
1521  foreach ($msgResp['data'] as $key => $value) {
1522  if (is_array($value)) {
1523  $ofxcount += countprint("<MSG>\n");
1524  foreach ($value as $mkey => $mvalue) {
1525  switch ($mkey) {
1526  case 'subject':
1527  case 'message':
1528  $mvalue = htmlentities($mvalue, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE);
1529  break;
1530  }
1531  $ofxcount += countprint("<$mkey>$mvalue</$mkey>\n");
1532  }
1533  $ofxcount += countprint("</MSG>\n");
1534  } else {
1535  $ofxcount += countprint("<$key>$value</$key>\n");
1536  }
1537  }
1538  $ofxcount += countprint("</READ_THREAD>\n");
1539  }
1540  $ofxcount += countprint("</MESSAGE>\n");
1541  break;
1542 
1543  case "SEND_MSG":
1544  $msgResp = msgSendMessage($dbh, $parms, $MC);
1545 
1546  # deal with response
1547  if ($msgResp['status']['response'] == 'false') {
1548  throw new Exception($msgResp['status']['message'], $msgResp['status']['code']); # MESSAGE READ_MSGS
1549  }
1550 
1551  $ofxcount += countprint("<MESSAGE>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1552  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1553  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1554  $ofxcount += countprint("<SEND_MSG>\n{$msgResp['status']['message']}\n</SEND_MSG>\n");
1555  $ofxcount += countprint("</MESSAGE>\n");
1556  break;
1557  case "DEL_THREAD":
1558  $msgResp = msgDeleteMessageThread($dbh, $parms);
1559 
1560  # deal with response
1561  if ($msgResp['status']['response'] == 'false') {
1562  throw new Exception($msgResp['status']['message'], $msgResp['status']['code']); # MESSAGE READ_MSGS
1563  }
1564 
1565  $ofxcount += countprint("<MESSAGE>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1566  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1567  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1568  $ofxcount += countprint("<DEL_MSG>\n{$msgResp['status']['message']}\n</DEL_MSG>\n");
1569  $ofxcount += countprint("</MESSAGE>\n");
1570  break;
1571  case "CHECK_MSG":
1572  $msgResp = msgCheckForMessages($dbh, $parms);
1573 
1574  # deal with response
1575  if ($msgResp['status']['response'] == 'false') {
1576  throw new Exception($msgResp['status']['message'], $msgResp['status']['code']); # MESSAGE READ_MSGS
1577  }
1578 
1579  $ofxcount += countprint("<MESSAGE>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1580  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1581  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1582 
1583  if (is_array($msgResp['data'])) {
1584 // $ofxcount += countprint("<MSG_RAW>\n" . print_r($msgResp['data'],true) . "</MSG_RAW>\n");
1585  $ofxcount += countprint("<CHECK_MSG>\n");
1586  foreach ($msgResp['data'] as $key => $value) {
1587  $ofxcount += countprint("<$key>$value</$key>\n");
1588  }
1589  $ofxcount += countprint("</CHECK_MSG>\n");
1590  }
1591  $ofxcount += countprint("</MESSAGE>\n");
1592  break;
1593 
1594  default:
1595  # unknown MSG_ACTION
1596  throw new Exception("Unknown MESSAGE Mode",15550);
1597  break;
1598  }
1599  break;
1600 
1601  case "RDCMOBILE":
1602  include('rdcCommon.i'); # HCU functions common to all RDC vendors
1603 
1604 // $rdcparms['Cu'] = $HB_ENV['Cu'];
1605 // $rdcparms['Cn'] = $HB_ENV['Cn'];
1606 
1607  $pass = array();
1608  // note! this is an extra decode for all RDC_ACTION settings other than UPLOAD. Because UPLOAD does an
1609  // extra encode on the app side. Didn't want to disrupt deployed apps, and extra decode is benign since
1610  // none of the other PASSWITH values for RDCMOBILE allow special characters. This will bite us someday...
1611  // but is expedient today.
1612  parse_str(urldecode($PASSWITH), $pass);
1613 
1614  $rdcparms = array();
1615  $rdcparms['chome'] = $HB_ENV['chome'];
1616  $rdcparms['Flang'] = $HB_ENV['Flang'];
1617  $rdcparms['Cu'] = $HB_ENV['Cu'];
1618  $rdcparms['Cn'] = $HB_ENV['Cn'];
1619  $rdcparms['Ml'] = $HB_ENV['Ml'];
1620  $rdcparms['passwith'] = $pass;
1621  # if the app did not send a depositid look for RDCVENDOR
1622  if (!isset($pass['DEPOSITID'])) {
1623  $rdcparms['rdcvendor'] = $pass['RDCVENDOR'];
1624  }
1625 
1626  RDCsession($dbh,$rdcparms);
1627 
1628  switch ("{$rdcparms['rdcvendor']}") {
1629  case "RDCENSENTA":
1630  $verVen = "ENSENTA";
1631  include_once('rdcEnsenta.i');
1632  break;
1633  case "RDCBluepoint":
1634  $verVen = "Bluepoint";
1635  include_once('rdcBluepoint.i');
1636  break;
1637  case "RDCTranzCap":
1638  $verVen = "Catalyst";
1639  include_once('rdcTranzCap.i');
1640  break;
1641  case "RDCVsoft":
1642  $verVen = "VSOFT";
1643  include_once('rdcVSoft.i');
1644  break;
1645  default:
1646 
1647  $verVen = "";
1648  throw new Exception("Missing RDC parameters",4001);
1649  break;
1650  }
1651  if ($verVen != "" && !hcu_checkService($dbh, $verVen)) {
1652  $omsg = hcu_checkServiceMsg($dbh, $verVen);
1653  throw new Exception($omsg,2077); # RDC vendor offline
1654  }
1655  RDCconfig($dbh,$rdcparms);
1656 
1657 
1658  switch ($pass['RDC_ACTION']) {
1659  case "AUTH":
1660 
1661  $rdcsays = RDCauth($dbh, $HB_ENV, $MC, $rdcparms);
1662  # deal with response
1663  if ($rdcsays['status']['response'] == 'false') {
1664  if ($rdcsays['status']['code'] == '110' || $rdcsays['status']['code'] == '111') {
1665  $rcode = '4011';
1666  } else {
1667  $rcode = '4010';
1668  }
1669  throw new Exception($rdcsays['status']['message'],$rcode); # RDC AUTH
1670  } else {
1671  $ofxcount += countprint("<RDC_RESPONSE>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1672  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1673  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1674  $ofxcount += countprint("<DEPOSITID>{$rdcsays['data']['depositid']}</DEPOSITID>\n");
1675  $ofxcount += countprint("<ACCOUNTS>\n");
1676  if (is_array($rdcsays['data']['accounts'])) {
1677  foreach ($rdcsays['data']['accounts'] as $acct => $detl) {
1678  $ofxcount += countprint("<ACCT>\n<ACCTID>$acct</ACCTID>\n");
1679  foreach ($detl as $key => $value) {
1680  $key = strtoupper($key);
1681  $ofxcount += countprint("<$key>$value</$key>\n");
1682  }
1683  $ofxcount += countprint("</ACCT>\n");
1684  }
1685  }
1686  $ofxcount += countprint("</ACCOUNTS>\n");
1687  $ofxcount += countprint("<TERMS>\n");
1688  $ofxcount += countprint("" . htmlentities(CleanWordQuotes("{$rdcsays['data']['terms']}"), ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE));
1689  $ofxcount += countprint("</TERMS>\n");
1690  $ofxcount += countprint("<DEPMESSAGES>\n");
1691  if (is_array($rdcsays['data']['depmessages'])) {
1692  foreach ($rdcsays['data']['depmessages'] as $msg => $detl) {
1693  $ofxcount += countprint("<MSG>\n<MSGID>$msg</MSGID>\n");
1694  foreach ($detl as $key => $value) {
1695  $key = strtoupper($key);
1696  $ofxcount += countprint("<$key>$value</$key>\n");
1697  }
1698  $ofxcount += countprint("</MSG>\n");
1699  }
1700  }
1701  $ofxcount += countprint("</DEPMESSAGES>\n");
1702  $ofxcount += countprint("</RDC_RESPONSE>\n");
1703  }
1704  break;
1705  case "ACCEPT":
1706  if (!isset($pass['DEPOSITID'])) {
1707  throw new Exception("Missing RDC parameters",4001);
1708  } else {
1709  $rdcparms['depositid'] = $pass['DEPOSITID'];
1710  $rdcsays = RDCaccept($dbh, $HB_ENV, $MC, $rdcparms);
1711  # deal with response
1712  if ($rdcsays['status']['response'] == 'false') {
1713  throw new Exception($rdcsays['status']['message'],4020); # RDC ACCEPT
1714  } else {
1715  $ofxcount += countprint("<RDC_RESPONSE>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1716  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1717  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1718  $ofxcount += countprint("<DEPMESSAGES>\n");
1719  if (is_array($rdcsays['data']['depmessages'])) {
1720  foreach ($rdcsays['data']['depmessages'] as $msg => $detl) {
1721  $ofxcount += countprint("<MSG>\n<MSGID>$msg</MSGID>\n");
1722  if (is_array($detl)) {
1723  foreach ($detl as $key => $value) {
1724  $key = strtoupper($key);
1725  $ofxcount += countprint("<$key>$value</$key>\n");
1726  }
1727  }
1728  $ofxcount += countprint("</MSG>\n");
1729  }
1730  }
1731  $ofxcount += countprint("</DEPMESSAGES>\n");
1732  $ofxcount += countprint("</RDC_RESPONSE>\n");
1733  }
1734  }
1735  break;
1736  case "UPLOAD":
1737  if (!isset($pass['DEPOSITID']) || !isset($pass['FB']) || sizeof($_FILES) == 0) {
1738  throw new Exception("Missing RDC parameters",4001);
1739  } else {
1740  $rdcparms['uploads_dir'] = "/home/{$HB_ENV['chome']}/sslforms/RDCImages";
1741  $rdcparms['depositid'] = $pass['DEPOSITID'];
1742  $rdcparms['FB'] = $pass['FB'];
1743  $rdcsays = RDCUploadImage($dbh, $rdcparms);
1744  # deal with response
1745  if ($rdcsays['status']['response'] == 'false') {
1746  throw new Exception($rdcsays['status']['message'],4030); # RDC UPLOAD
1747  } else {
1748  $ofxcount += countprint("<RDC_RESPONSE>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1749  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1750  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1751 // $ofxcount += countprint("<UPLOADED>{$rdcsays['data']['filename']}</UPLOADED>\n");
1752  $ofxcount += countprint("</RDC_RESPONSE>\n");
1753  }
1754  }
1755  break;
1756  case "DEPOSIT":
1757  if (!isset($pass['DEPOSITID']) || !isset($pass['AMOUNT']) || !isset($pass['ACCTID'])) {
1758  throw new Exception("Missing RDC parameters",4001);
1759  } else {
1760  $rdcparms['depositid'] = $pass['DEPOSITID'];
1761  $rdcparms['acctid'] = $pass['ACCTID'];
1762  $rdcparms['amount'] = $pass['AMOUNT'];
1763  $rdcparms['rdcacctid'] = $pass['RDCACCTID'];
1764  $rdcparms['live'] = $HB_ENV['live'];
1765  $rdcparms['Ml'] = $HB_ENV['Ml'];
1766  $rdcparms['Clw'] = $HB_ENV['livewait'];
1767  if ($pass['POSTAWAY'] == 1) {
1768  $rdcparms['POSTAWAY'] = $pass['POSTAWAY'];
1769  }
1770  $rdcsays = RDCdeposit($dbh, $rdcparms);
1771  # deal with response
1772  if ($rdcsays['status']['response'] == 'false') {
1773  throw new Exception($rdcsays['status']['message'],4040); # RDC Deposit
1774  } else {
1775  $ofxcount += countprint("<RDC_RESPONSE>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1776  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1777  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1778  foreach ($rdcsays['data'] as $key => $value) {
1779  if ($key <> 'Risks' && $key <> 'FailReasons' && $key <> 'LocalizedMessageText') {
1780  $key = strtoupper($key);
1781  $ofxcount += countprint("<$key>$value</$key>\n");
1782  }
1783  }
1784  $ofxcount += countprint("<RISKS>\n");
1785  if (is_array($rdcsays['data']['Risks'])) {
1786  foreach ($rdcsays['data']['Risks'] as $msg => $detl) {
1787  $ofxcount += countprint("<MSGTEXT>{$detl['RiskDesc']}</MSGTEXT>\n");
1788  }
1789  }
1790  if (is_array($rdcsays['data']['FailReasons'])) {
1791  foreach ($rdcsays['data']['FailReasons'] as $msg => $detl) {
1792  $ofxcount += countprint("<MSGTEXT>$detl</MSGTEXT>\n");
1793  }
1794  }
1795  if (!empty($rdcsays['data']['LocalizedMessageText'])) {
1796  $ofxcount += countprint("<MSGTEXT>{$rdcsays['data']['LocalizedMessageText']}</MSGTEXT>\n");
1797  }
1798  $ofxcount += countprint("</RISKS>\n");
1799  $ofxcount += countprint("</RDC_RESPONSE>\n");
1800  }
1801  }
1802  break;
1803  case "INFO":
1804  if (!isset($HB_ENV['Cn']) || !isset($pass['DEPOSITID'])) {
1805 // history request needs depositid to get sessionkey --
1806  throw new Exception("Missing RDC parameters",4001);
1807  }
1808  $rdcparms['Cn'] = $HB_ENV['Cn'];
1809  if (isset($pass['DAYS']))
1810  $rdcparms['numberofdays'] = $pass['DAYS'];
1811  if (isset($pass['LIMIT']))
1812  $rdcparms['translimit'] = $pass['LIMIT'];
1813 
1814  /*
1815  * get status list before setting depositid - otherwise we only get status for one rec
1816  */
1817  $depostat = curdc_list($dbh, $rdcparms);
1818 
1819  $rdcparms['depositid'] = $pass['DEPOSITID'];
1820  /*
1821  * but history request needs depositid to get sessionkey --
1822  */
1823  $depohist = RDChistorylist($dbh, $rdcparms);
1824  if ($depostat['status']['response'] == 'false') {
1825  throw new Exception($depostat['status']['message'],4040);
1826  } elseif ($depohist['status']['response'] == 'false') {
1827  throw new Exception($depohist['status']['message'],4040);
1828  } else {
1829 
1830  $histlist = array();
1831  if (is_array($depohist['data']['TransactionList'])) {
1832  foreach ($depohist['data']['TransactionList'] as $key => $value) {
1833  if (!empty($value['ReceiptReferenceNo'])) {
1834  $receiptno = $value['ReceiptReferenceNo'];
1835  foreach ($value as $tag => $tval) {
1836  switch (strtolower($tag)) {
1837  case "transactionid":
1838  case "transactiondttm":
1839  case "receiptreferenceno":
1840  case "submittedamount":
1841  case "currentamount":
1842  case "status":
1843  case "accountnumber":
1844  case "accountholdernumber":
1845  case "transactiontype":
1846  case "acceptedbydescr":
1847  case "statuschgdttm":
1848  case "statusdescr":
1849  case "checknumber":
1850  $histlist[$receiptno][$tag] = $tval;
1851  break;
1852  }
1853  }
1854  }
1855  }
1856  }
1857 
1858  $ofxcount += countprint("<RDC_RESPONSE>\n<STATUS>\n<CODE>0</CODE>\n</STATUS>\n");
1859  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1860  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1861  $ofxcount += countprint("<DEPOSITS>");
1862  foreach ($depostat['data'] as $key => $value) {
1863  $ofxcount += countprint("<DEPOSIT>\n");
1864  foreach ($value as $tag => $tval) {
1865 // if ($value['rdcvendor'] == $depohist['data']['rdcvendor']) {
1866  switch ($tag) {
1867  case "depositid":
1868  case "lastupdate":
1869  case "amount":
1870  case "acctid":
1871  case "status":
1872  $tag = ($tag == 'status' ? "RDCSTATUS" : strtoupper($tag));
1873  $ofxcount += countprint("<$tag>$tval</$tag>\n");
1874  break;
1875  case "vendorinfo":
1876  if ($pass['DEBUG'] == 1)
1877  $ofxcount += countprint("<VENDORINFO>" . print_r($tval, true) . "</VENDORINFO>");
1878  break;
1879  }
1880 // }
1881  }
1882  if (!empty($value['vendorinfo']['TransactionReceiptNumber'])) {
1883  $ofxcount += countprint("<TRANSACTIONRECEIPTNUMBER>{$value['vendorinfo']['TransactionReceiptNumber']}");
1884  $ofxcount += countprint("</TRANSACTIONRECEIPTNUMBER>\n");
1885  $receiptno = $value['vendorinfo']['TransactionReceiptNumber'];
1886  if ($histlist[$receiptno]) {
1887 // $ofxcount += countprint("<RDCINFO>\n");
1888  foreach ($histlist[$receiptno] as $rtag => $rval) {
1889  $rtag = strtoupper($rtag);
1890  $ofxcount += countprint("<$rtag>$rval</$rtag>\n");
1891  }
1892 // $ofxcount += countprint("</RDCINFO>\n");
1893  }
1894  }
1895  $ofxcount += countprint("</DEPOSIT>\n");
1896  }
1897 
1898  $ofxcount += countprint("</DEPOSITS>\n");
1899  $ofxcount += countprint("</RDC_RESPONSE>");
1900  }
1901  break;
1902  default:
1903  # unknown RDC_ACTION
1904  throw new Exception("Unknown RDC Mode",15550);
1905  break;
1906  }
1907  break;
1908  case "ESTMT":
1909  # PASSWITH ES_UPD=1 indicates app supports estmt_flag setting changes
1910  # response set includes terms & notices
1911  # PASSWITH ENROLL=START/STOP updates status, and returned response set
1912  # contains status & enrollment block only
1913  $pass = array();
1914  parse_str($PASSWITH, $pass);
1915 
1916  if (isset($pass['ENROLL'])) {
1917  /*
1918  * set Cu Cn Ml esProcessMode as START/STOP and if STOP, HCUPOST['stop_reason']
1919  * then call Post_CUEStmt to change estatement status
1920  * and Update_NoticeInfo to record
1921  * errors on the Update_NoticeInfo are ignored - small likelihood
1922  * returned message set is STATUS & ENROLLMENT only
1923  */
1924  $HB_ENV['esProcessMode'] = $pass['ENROLL'];
1925  $HB_ENV['HCUPOST']['stop_reason'] = $pass['STOP_REASON'];
1926 
1927  # Post_CUEstmt expects un-encoded $Ml in HB_ENV array
1928  # app stores it encoded, so decode it before calling the function
1929  # and then put it back after so nothing else breaks
1930  $HB_ENV['Ml'] = urldecode($HB_ENV['Ml']);
1931  $response = Post_CUEStmt($dbh, $HB_ENV, $MC);
1932  $HB_ENV['Ml'] = urlencode($HB_ENV['Ml']);
1933  if (count($response['status']['errors']) > 0) {
1934  throw new Exception(implode(' ',$response['status']['errors']),15592); # Post_CUEStmt
1935  } else {
1936  if (intval($pass['NOTICE_ID']) > 0) {
1937  // build up a response to the notice so the member doesn't see again
1938  $HB_ENV["HCUPOST"]["notice_type"] = "C";
1939  $HB_ENV["HCUPOST"]["notice_id"] = intval($pass['NOTICE_ID']);
1940  $HB_ENV["HCUPOST"]["notice_device"] = "P"; // app
1941  $HB_ENV["HCUPOST"]["notice_response"] = array("answer" => 1); // something non-zero but numeric
1942  $HB_ENV["HCUPOST"]["notice_cancel"] = "0";
1943 
1944  $response = Update_NoticeInfo($dbh, $HB_ENV, $MC);
1945  // if (count($response['status']['errors']) > 0) {
1946  // throw new Exception(implode(' ',$response['status']['errors']),15593); # Update_NoticeInfo ES Status change
1947  // }
1948  }
1949 
1950  $response = Get_Estmt($dbh, $HB_ENV, $MC, 1);
1951  }
1952  } else {
1953 
1954  $response = Get_Estmt($dbh, $HB_ENV, $MC);
1955  }
1956  # deal with response
1957  if (count($response['status']['errors']) > 0) {
1958  throw new Exception(implode(' ',$response['status']['errors']),15590); # Get_Estmt
1959  } else {
1960  $ofxcount += countprint("<ESTMT>\n<STATUS>\n<CODE>0</CODE>\n");
1961  $ofxcount += countprint("<SEVERITY>INFO</SEVERITY>\n</STATUS>\n");
1962  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
1963  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
1964 // $ofxcount += countprint("<response>" . print_r($response,true) . "</response>");
1965 
1966  foreach ($response['estmt'] as $key => $value) {
1967  switch (strtolower($key)) {
1968  case "enrolled":
1969  $enrolled = $value;
1970  $key = strtoupper($key);
1971  $ofxcount += countprint("<$key>$value</$key>\n");
1972  break;
1973  case "pdflinks":
1974  $ofxcount += countprint("<PDFLINKS>\n");
1975  if (is_array($value)) {
1976  foreach ($value as $tag => $tval) {
1977  $ofxcount += countprint("<PDFLINK>\n");
1978  foreach ($tval as $tkey => $tkval) {
1979  $tkey = strtoupper($tkey);
1980  $ofxcount += countprint("<$tkey>$tkval</$tkey>\n");
1981  }
1982  $ofxcount += countprint("</PDFLINK>\n");
1983  }
1984  }
1985  $ofxcount += countprint("</PDFLINKS>");
1986  break;
1987  case "toclinks":
1988  $ofxcount += countprint("<TOCLINKS>\n");
1989  if (is_array($value)) {
1990  foreach ($value as $tag => $tval) {
1991  $ofxcount += countprint("<TOCLINK>\n");
1992  foreach ($tval as $tkey => $tkval) {
1993  $tkey = strtoupper($tkey);
1994  $ofxcount += countprint("<$tkey>$tkval</$tkey>\n");
1995  }
1996  $ofxcount += countprint("</TOCLINK>\n");
1997  }
1998  }
1999  $ofxcount += countprint("</TOCLINKS>");
2000  break;
2001  }
2002  }
2003 # add appropriate messages -
2004 // if ES_UPD use Get_NoticeInfo else use hardcoded values
2005 
2006  if (isset($pass['ES_UPD'])) {
2007  # set new ENROLLMENT block
2008  if ($enrolled == "W") {
2009  // give message about waiting for first statement and allow to stop
2010  $termsMsg = $MC->msg('Statement Not Found') . " " . $MC->msg('Statement Missing') . " " . $MC->msg("Statements Stop");
2011  $start = "stop";
2012  $termsName = "esTermsStop";
2013  $termsTitle = $MC->msg("Stop e-Statements");
2014  } else if ($enrolled == "Y") {
2015  $termsMsg = $MC->msg("Statements Stop");
2016  $start = "stop";
2017  $termsName = "esTermsStop";
2018  $termsTitle = $MC->msg("Stop e-Statements");
2019  } else {
2020  $termsMsg = $MC->msg('Account not set for EStatements') . ". " . $MC->msg('Sign up fast');
2021  $start = "start";
2022  $termsName = "esTermsStart";
2023  $termsTitle = $MC->msg("Start e-Statements");
2024  }
2025  $ofxcount += countprint("<ENROLLMENT>\n");
2026  $ofxcount += countprint("<ENROLLED>$enrolled</ENROLLED>\n");
2027  $ofxcount += countprint("<TERMS_TITLE>$termsTitle</TERMS_TITLE>\n");
2028  $ofxcount += countprint("<TERMS_MSG>$termsMsg</TERMS_MSG>\n");
2029  $ofxcount += countprint("<TERMS_BTN>" . $MC->msg('Click Here') . "</TERMS_BTN>\n");
2030 
2031  $response = Get_NoticeInfo($dbh, $HB_ENV, $MC, 'P', $termsName);
2032  // make sure we got the notice
2033  if ($response['status']['code'] != "000" ||
2034  !count($response['notice']) ||
2035  count($response['status']['errors']) > 0 ||
2036  strlen($response['notice'][0]['notice_text']) == 0) {
2037  $response['status']['errors'][] = "Error retrieving Terms of Use";
2038  throw new Exception(implode(' ',$response['status']['errors']),15593); # Get_NoticeInfo estatement terms
2039  } else {
2040  if (count($response['notice'])) {
2041 // $ofxcount += countprint("<TERMS_CALLED>Get_NoticeInfo(\$dbh, \$HB_ENV, \$MC, 'P', $termsName)</TERMS_CALLED>");
2042 // $ofxcount += countprint("<TERMS_RAW>" . print_r($response,true) . "</TERMS_RAW>");
2043  foreach ($response['notice'] as $noticekey => $details) {
2044  $ofxcount += countprint("<TERMS>\n");
2045  /*
2046  * if no answer list but I have a donotshowtext, send that as an answer
2047  */
2048  if (!count($details['notice_answers']) && sizeof($details['notice_donotshowtext'])) {
2049  $details['notice_answers'][] = array('answer_id' => $details['notice_id'], 'answer_text' => $details['notice_donotshowtext']);
2050  $details['notice_answertype'] = 'M';
2051  }
2052  foreach ($details as $key => $value) {
2053  $key = strtoupper($key);
2054  switch ($key) {
2055  case "NOTICE_ANSWERS":
2056  $ofxcount += countprint("<NOTICE_ANSWERS>\n");
2057  foreach ($value as $anskey => $ansdetl) {
2058  $ofxcount += countprint("<ANSWER>\n");
2059  $ofxcount += countprint("<ANSWER_ID>ANS_{$ansdetl['answer_id']}</ANSWER_ID>\n");
2060  $ofxcount += countprint("<ANSWER_TEXT>" . htmlentities(CleanWordQuotes($ansdetl['answer_text']), ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</ANSWER_TEXT>\n");
2061 // $ofxcount += countprint("<ANSWER_TEXT>{$ansdetl['answer_text']}</ANSWER_TEXT>\n");
2062  $ofxcount += countprint("</ANSWER>\n");
2063  }
2064  $ofxcount += countprint("</NOTICE_ANSWERS>\n");
2065 
2066  break;
2067  /*
2068  * ignore these
2069  */
2070  case "NOTICE_INTRO":
2071  case "NOTICE_TITLE":
2072  case "NOTICE_DONOTSHOWTEXT":
2073  case "NOTICE_MSG_TX":
2074  case "NOTICE_MSG_TX_SHOW":
2075  case "NOTICE_MSG_TX_PERM":
2076  case "NOTICE_SUPPRESSRESPONSE":
2077  case "NOTICE_POSTTARGET":
2078  case "NOTICE_TEXT":
2079  break;
2080  case "NOTICE_TYPE":
2081  case "NOTICE_ID":
2082  case "NOTICE_POPUP":
2083  case "NOTICE_ANSWERTYPE":
2084  case "NOTICE_LINKTARGET":
2085  case "NOTICE_LINKDISPLAY":
2086  default:
2087 
2088  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
2089  }
2090  }
2091  $ofxcount += countprint("</TERMS>\n");
2092  }
2093  } else {
2094  $ofxcount += countprint("<TERMS>\n</TERMS>\n");
2095  }
2096  }
2097  $ofxcount += countprint("</ENROLLMENT>\n");
2098  } else {
2099  switch ($response['estmt']['enrolled']) {
2100  case 'Y':
2101  $ofxcount += countprint("<MESSAGES>\n<MESSAGE>\n<MSGHEAD>Discontinuing E-Statement Service</MSGHEAD>
2102  <MSGBODY>Please log in through the full Home Banking site to discontinue E-Statement service</MSGBODY>\n</MESSAGE>\n</MESSAGES>\n");
2103  break;
2104  case 'W':
2105  $ofxcount += countprint("<MESSAGES>\n<MESSAGE>\n<MSGHEAD>" . $MC->msg('Statement Not Found') . "</MSGHEAD>
2106  <MSGBODY>" . $MC->msg('Statement Missing') . "</MSGBODY>\n</MESSAGE>\n</MESSAGES>\n");
2107  break;
2108  case 'N':
2109  default:
2110  $ofxcount += countprint("<MESSAGES>\n<MESSAGE>\n<MSGHEAD>Enrollment Required</MSGHEAD>
2111  <MSGBODY>Please log in through the full Home Banking site to sign up for E-Statements</MSGBODY>\n</MESSAGE>\n</MESSAGES>\n");
2112  break;
2113  }
2114  }
2115 
2116 # now get the estatement notice, if any
2117  $txnotice = Get_NoticeInfo($dbh, $HB_ENV, $MC, 'P', 'esNotice', 0);
2118 
2119  if (count($txnotice['notice'])) {
2120  foreach ($txnotice['notice'] as $noticekey => $details) {
2121  $ofxcount += countprint("<NOTICE>\n");
2122  /*
2123  * if no answer list but I have a donotshowtext, send that as an answer
2124  */
2125  if (!count($details['notice_answers']) && sizeof($details['notice_donotshowtext'])) {
2126  $details['notice_answers'][] = array('answer_id' => $details['notice_id'], 'answer_text' => $details['notice_donotshowtext']);
2127  $details['notice_answertype'] = 'M';
2128  }
2129  foreach ($details as $key => $value) {
2130  $key = strtoupper($key);
2131  switch ($key) {
2132  case "NOTICE_ANSWERS":
2133  $ofxcount += countprint("<NOTICE_ANSWERS>\n");
2134  foreach ($value as $anskey => $ansdetl) {
2135  $ofxcount += countprint("<ANSWER>\n");
2136  $ofxcount += countprint("<ANSWER_ID>ANS_{$ansdetl['answer_id']}</ANSWER_ID>\n");
2137  $ofxcount += countprint("<ANSWER_TEXT>" . htmlentities(CleanWordQuotes($ansdetl['answer_text']), ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</ANSWER_TEXT>\n");
2138 // $ofxcount += countprint("<ANSWER_TEXT>{$ansdetl['answer_text']}</ANSWER_TEXT>\n");
2139  $ofxcount += countprint("</ANSWER>\n");
2140  }
2141  $ofxcount += countprint("</NOTICE_ANSWERS>\n");
2142 
2143  break;
2144  /*
2145  * ignore these
2146  */
2147  case "NOTICE_INTRO":
2148  case "NOTICE_TITLE":
2149  case "NOTICE_DONOTSHOWTEXT":
2150  case "NOTICE_MSG_TX":
2151  case "NOTICE_MSG_TX_SHOW":
2152  case "NOTICE_MSG_TX_PERM":
2153  case "NOTICE_SUPPRESSRESPONSE":
2154  case "NOTICE_POSTTARGET":
2155  case "NOTICE_TEXT":
2156  break;
2157  case "NOTICE_TYPE":
2158  case "NOTICE_ID":
2159  case "NOTICE_POPUP":
2160  case "NOTICE_ANSWERTYPE":
2161  case "NOTICE_LINKTARGET":
2162  case "NOTICE_LINKDISPLAY":
2163  default:
2164 
2165  $ofxcount += countprint("<$key>" . htmlentities($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
2166  }
2167  }
2168  $ofxcount += countprint("</NOTICE>\n");
2169  }
2170  } else {
2171  $ofxcount += countprint("<NOTICE>\n</NOTICE>\n");
2172  }
2173  $ofxcount += countprint("</ESTMT>");
2174  }
2175 
2176  break;
2177  case "GETALERTS":
2178 // $pass = array();
2179 // parse_str($PASSWITH, $pass);
2180 #is cu configured for Alerts?
2181  if (!Check_AlertsEnabled($dbh, $HB_ENV)) {
2182  throw new Exception("Alert feature not configured",3180); # no 'Alert from' email set in admin
2183  }
2184 #list of alert types
2185  $ary_alerttypes = Get_AlertTypes($MC);
2186 #list of cell phone providers
2187  $ary_cellproviders = Get_AlertProviders($dbh);
2188 #cuusers.email and most-recently-used cell number for use as default values when defining a new alert
2189  $ary_dfltmail = Get_AlertDefaultEmail($dbh, $HB_ENV);
2190  $ary_dfltcell = Get_AlertDefaultCell($dbh, $HB_ENV);
2191 #list of members' accounts eligible for each alert type
2192  $ary_acctlist = Get_AlertAccountList($dbh, $HB_ENV);
2193 #list of currently-defined alerts, if any
2194  $ary_alertdetails = Get_AlertsDetailed($dbh, $HB_ENV);
2195 #alerts terms of use document, if any, and a link to display terms of use on demand
2196  $ary_alertterms = Get_NoticeInfo($dbh, $HB_ENV, $MC, 'P', 'alertTerms');
2197 
2198 #a status indicating whether or not the member must accept terms before continuing
2199 #any other alerts messages or notices the member should see
2200 
2201  $ofxcount += countprint("<ALERTSMRY>\n<STATUS>\n<CODE>0</CODE>\n");
2202  $ofxcount += countprint("<SEVERITY>INFO</SEVERITY>\n</STATUS>\n");
2203  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n");
2204  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
2205 
2206  $ofxcount += countprint("<ALERTTYPES>\n");
2207  foreach ($ary_alerttypes as $alertarr) {
2208  $ofxcount += countprint("<ALERTTYPE>\n");
2209  foreach ($alertarr as $key => $value) {
2210  $key = strtoupper($key);
2211  $ofxcount += countprint("<$key>" . htmlspecialchars($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
2212  }
2213  $ofxcount += countprint("</ALERTTYPE>\n");
2214  }
2215  $ofxcount += countprint("</ALERTTYPES>\n");
2216 
2217  $ofxcount += countprint("<CELLPROVIDERS>\n");
2218  foreach ($ary_cellproviders['providers'] as $cellprovider) {
2219  $ofxcount += countprint("<CELLPROVIDER>\n");
2220  foreach ($cellprovider as $key => $value) {
2221  $key = strtoupper($key);
2222  $ofxcount += countprint("<$key>" . htmlspecialchars($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
2223  }
2224  $ofxcount += countprint("</CELLPROVIDER>\n");
2225  }
2226  $ofxcount += countprint("</CELLPROVIDERS>\n");
2227  $ofxcount += countprint("<EMAILDFLT>" . htmlspecialchars($ary_dfltmail['email'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</EMAILDFLT>\n");
2228  $ofxcount += countprint("<CELLDFLT>\n");
2229  foreach ($ary_dfltcell['cell'] as $key => $value) {
2230  $key = strtoupper($key);
2231  $ofxcount += countprint("<$key>" . htmlspecialchars($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
2232  }
2233  $ofxcount += countprint("</CELLDFLT>\n");
2234 
2235  $ofxcount += countprint("<ACCOUNTS>\n");
2236  foreach ($ary_acctlist['accounts'] as $acctarr) {
2237  $ofxcount += countprint("<ACCOUNT>\n");
2238  foreach ($acctarr as $key => $value) {
2239  $key = strtoupper($key);
2240  $ofxcount += countprint("<$key>" . htmlspecialchars($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
2241  }
2242  $ofxcount += countprint("</ACCOUNT>\n");
2243  }
2244  $ofxcount += countprint("</ACCOUNTS>\n");
2245 
2246  $ofxcount += countprint("<ALERTS>\n");
2247  foreach ($ary_alertdetails['alerts'] as $detlarr) {
2248  $ofxcount += countprint("<ALERT>\n");
2249  foreach ($detlarr as $key => $value) {
2250  $key = strtoupper($key);
2251  $ofxcount += countprint("<$key>" . htmlspecialchars($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
2252  }
2253  $ofxcount += countprint("</ALERT>\n");
2254  }
2255  $ofxcount += countprint("</ALERTS>\n");
2256  $ofxcount += countprint("<TERMS>\n");
2257  if (count($ary_alertterms['notice'])) {
2258  foreach ($ary_alertterms['notice'] as $noticekey => $details) {
2259  foreach ($details as $key => $value) {
2260  $key = strtoupper($key);
2261  switch ($key) {
2262  case "NOTICE_ANSWERS":
2263  $ofxcount += countprint("<NOTICE_ANSWERS>\n");
2264  foreach ($value as $anskey => $ansdetl) {
2265  $ofxcount += countprint("<ANSWER>\n");
2266  $ofxcount += countprint("<ANSWER_ID>ANS_{$ansdetl['answer_id']}</ANSWER_ID>\n");
2267  $ofxcount += countprint("<ANSWER_TEXT>" . htmlentities(CleanWordQuotes($ansdetl['answer_text']), ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</ANSWER_TEXT>\n");
2268 // $ofxcount += countprint("<ANSWER_TEXT>{$ansdetl['answer_text']}</ANSWER_TEXT>\n");
2269  $ofxcount += countprint("</ANSWER>\n");
2270  }
2271  $ofxcount += countprint("</NOTICE_ANSWERS>\n");
2272 
2273  break;
2274  /*
2275  * ignore these
2276  */
2277  case "NOTICE_INTRO":
2278  case "NOTICE_TITLE":
2279  case "NOTICE_DONOTSHOWTEXT":
2280  case "NOTICE_MSG_TX":
2281  case "NOTICE_MSG_TX_SHOW":
2282  case "NOTICE_MSG_TX_PERM":
2283  case "NOTICE_SUPPRESSRESPONSE":
2284  case "NOTICE_POSTTARGET":
2285  case "NOTICE_TEXT":
2286  break;
2287  case "NOTICE_TYPE":
2288  case "NOTICE_ID":
2289  case "NOTICE_POPUP":
2290  case "NOTICE_ANSWERTYPE":
2291  case "NOTICE_LINKTARGET":
2292  case "NOTICE_LINKDISPLAY":
2293  default:
2294 
2295  $ofxcount += countprint("<$key>" . htmlspecialchars($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
2296  }
2297  }
2298  }
2299  }
2300  $ofxcount += countprint("</TERMS>");
2301  /*
2302  * if we need to allow for alert disclosure doc, this is how we'd do it
2303  #get alerts notice document, if any, and a link to display notice on demand
2304  */
2305  $ary_alertnotice = Get_NoticeInfo($dbh, $HB_ENV, $MC, 'P', 'alertNotice');
2306 
2307  $ofxcount += countprint("<NOTICE>\n");
2308  if (count($ary_alertnotice['notice'])) {
2309  foreach ($ary_alertnotice['notice'] as $noticekey => $details) {
2310  foreach ($details as $key => $value) {
2311  $key = strtoupper($key);
2312  switch ($key) {
2313  case "NOTICE_ANSWERS":
2314  $ofxcount += countprint("<NOTICE_ANSWERS>\n");
2315  foreach ($value as $anskey => $ansdetl) {
2316  $ofxcount += countprint("<ANSWER>\n");
2317  $ofxcount += countprint("<ANSWER_ID>ANS_{$ansdetl['answer_id']}</ANSWER_ID>\n");
2318  $ofxcount += countprint("<ANSWER_TEXT>" . htmlentities(CleanWordQuotes($ansdetl['answer_text']), ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</ANSWER_TEXT>\n");
2319  $ofxcount += countprint("</ANSWER>\n");
2320  }
2321  $ofxcount += countprint("</NOTICE_ANSWERS>\n");
2322 
2323  break;
2324  // ignore these
2325  case "NOTICE_INTRO":
2326  case "NOTICE_TITLE":
2327  case "NOTICE_DONOTSHOWTEXT":
2328  case "NOTICE_MSG_TX":
2329  case "NOTICE_MSG_TX_SHOW":
2330  case "NOTICE_MSG_TX_PERM":
2331  case "NOTICE_SUPPRESSRESPONSE":
2332  case "NOTICE_POSTTARGET":
2333  case "NOTICE_TEXT":
2334  break;
2335  case "NOTICE_TYPE":
2336  case "NOTICE_ID":
2337  case "NOTICE_POPUP":
2338  case "NOTICE_ANSWERTYPE":
2339  case "NOTICE_LINKTARGET":
2340  case "NOTICE_LINKDISPLAY":
2341  default:
2342 
2343  $ofxcount += countprint("<$key>" . htmlspecialchars($value, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</$key>\n");
2344  }
2345  }
2346  }
2347  }
2348  $ofxcount += countprint("</NOTICE>");
2349 
2350 
2351  $ofxcount += countprint("</ALERTSMRY>\n");
2352  break;
2353 
2354  case "UPDALERT":
2355  $pass = array();
2356  parse_str($PASSWITH, $pass);
2357  $HB_ENV['HCUPOST'] = array(); # start w/ empty array
2358  $HB_ENV['HCUPOST']['type'] = $pass['TYPE'];
2359  $HB_ENV['HCUPOST']['notifymsg'] = $pass['NOTIFYMSG'];
2360  $HB_ENV['HCUPOST']['emailtype'] = $pass['EMAILTYPE'];
2361  $HB_ENV['HCUPOST']['provider_id'] = $pass['PROVIDER_ID'];
2362  $HB_ENV['HCUPOST']['notifyto'] = $pass['NOTIFYTO'];
2363  $HB_ENV['HCUPOST']['id'] = $pass['ALERTID'];
2364  $HB_ENV['HCUPOST']['selacct'] = $pass['SELACCT'];
2365  $HB_ENV['HCUPOST']['inctransdesc'] = $pass['INCTRANSDESC'];
2366 
2367  switch (strtolower($pass['TYPE'])) {
2368  case 'bal':
2369  $HB_ENV['HCUPOST']['notifyamt'] = $pass['NOTIFYAMT'];
2370  $HB_ENV['HCUPOST']['incbal'] = $pass['INCBAL'];
2371  $HB_ENV['HCUPOST']['useavailbal'] = $pass['USEAVAILBAL'];
2372  case 'trans':
2373  $HB_ENV['HCUPOST']['notifydesc'] = $pass['NOTIFYDESC'];
2374  $HB_ENV['HCUPOST']['userange'] = $pass['USERANGE'];
2375  $HB_ENV['HCUPOST']['desc_amtmin'] = $pass['DESC_AMTMIN'];
2376  $HB_ENV['HCUPOST']['desc_amtmax'] = $pass['DESC_AMTMAX'];
2377  $HB_ENV['HCUPOST']['incbal'] = $pass['INCBAL'];
2378  $HB_ENV['HCUPOST']['incamt'] = $pass['INCAMT'];
2379  $HB_ENV['HCUPOST']['transtype'] = $pass['TRANSTYPE'];
2380  case 'check':
2381  $HB_ENV['HCUPOST']['chknum'] = $pass['CHKNUM'];
2382  $HB_ENV['HCUPOST']['incamt'] = $pass['INCAMT'];
2383  case 'loan':
2384  $HB_ENV['HCUPOST']['days_prior'] = $pass['DAYS_PRIOR'];
2385  break;
2386  default:
2387  throw new Exception('Invalid Alert Update Request',3120); # unrecognized Alert type
2388  break;
2389  }
2390  $validalert = Validate_Alert($dbh, $HB_ENV, $MC);
2391  if ($validalert['status']['code'] != '000') {
2392  throw new Exception(implode(' ',$validalert['status']['errors']),3212); # failed Validate_Alert
2393  } else {
2394  $validalert = Update_Alert($dbh, $HB_ENV, $MC);
2395  if ($validalert['status']['code'] != '000') {
2396  throw new Exception(implode(' ',$validalert['status']['errors']),3214); # failed Update_Alert
2397  } else {
2398  Send_ResponseOK($CU, $HB_ENV['Uid'], $HB_ENV['Cauth'], 1, "Alert Update Successful", 2);
2399  }
2400  }
2401  break;
2402  case "DELALERT":
2403  $pass = array();
2404  parse_str($PASSWITH, $pass);
2405  $HB_ENV['HCUPOST'] = array(); # start w/ empty array
2406  $HB_ENV['HCUPOST']['type'] = $pass['TYPE'];
2407  $HB_ENV['HCUPOST']['id'] = $pass['ALERTID'];
2408 
2409  switch (strtolower($pass['TYPE'])) {
2410  case 'bal':
2411  case 'trans':
2412  case 'check':
2413  case 'loan':
2414  break;
2415  default:
2416  throw new Exception('Invalid Alert Delete Request',3216); # unrecognized Alert type
2417  break;
2418  }
2419  $validalert = Delete_Alert($dbh, $HB_ENV, $MC);
2420  if ($validalert['status']['code'] != '000') {
2421  throw new Exception(implode(' ',$validalert['status']['errors']),3218); # failed Delete_Alert
2422  } else {
2423  Send_ResponseOK($CU, $HB_ENV['Uid'], $HB_ENV['Cauth'], 1, "Alert Delete Successful", 2);
2424  }
2425  break;
2426 // case "SWJUMP":
2427 // # re-purpose SWJUMP code to support viewing multiple accounts. Not a credential check,
2428 // # but reset so viewing alternate account works
2429 // $pass = array();
2430 // parse_str($PASSWITH, $pass);
2431 // if (!isset($pass['JUMPTOID'])) {
2432 // send_response('3333', array('Invalid Switch Account Request'), 'ERROR'); # no jumpid
2433 // }
2434 // $swresult = SwitchAccountJumpto($dbh, $HB_ENV, $MC, $pass['JUMPTOID'], 'P');
2435 // if ($swresult['status']['code'] != '000') {
2436 // send_response('3334', array($swresult['status']['message']), 'ERROR'); # failed switch account
2437 // }
2438 // $authjump = array();
2439 // parse_str($swresult['data']['authstring'], $authjump);
2440 // $apptoken = MakeUserkey($CU, $authjump['Cn'], $authjump['Cauth']);
2441 // Load_HB_ENV($dbh, $CU, $authjump['Cn'], '', $authjump['Cauth'], $HB_ENV, $CFGFLAG);
2442 //
2443 //# set these things so they are available from the Global scope for
2444 //# throtlpkt functions
2445 //
2446 // $Cu = $HB_ENV['Cu'];
2447 // $Cn = $HB_ENV['Cn'];
2448 // $Cauth = $HB_ENV['Cauth'];
2449 // $Clw = $HB_ENV['livewait'];
2450 // $Ml = urldecode($HB_ENV['Ml']);
2451 //
2452 // $log = date('Y-m-d H:i:s');
2453 // $tfile = fopen ("/tmp/swJumpLog","a");
2454 // fwrite($tfile,"++++++++++++++++++\n");
2455 // fwrite($tfile,print_r($_REQUEST,true));
2456 // fwrite($tfile,print_r($HB_ENV,true));
2457 // fwrite($tfile,"\n++++++++++++++++++\n");
2458 // fclose ($tfile);
2459 // Send_ResponseOK($CU, $authjump['Cn'], $HB_ENV['Cauth'], 1, "Switch Account Success", 2); # Switch Account jumped successfully
2460  # if we need to push data after the jump,
2461  # skip the Send_ResponseOK above and
2462  # reload the HB_ENV with fresh settings returned in swresult['data']['authstring']
2463  # and remove the break; statement below so it falls through
2464 // break;
2465 # SWJUMP case above relies on falling through to the default to send data. DO NOT insert anything here
2466  default:
2467 # gen OFX
2468 #
2469  if (empty($DTSTART) || !sqlmdy($DTSTART)) {
2470  throw new Exception("Invalid Start Date $DTSTART",2090);
2471  } else {
2472  $sqlstart = sqlmdy($DTSTART);
2473  }
2474  if (!empty($DTEND) && !sqlmdy($DTEND)) {
2475  throw new Exception('Invalid End Date',2090);
2476  }
2477  $HB_ENV['stale'] = 0;
2478  if ($live) {
2479  $cu = $CU;
2480  $Fhdays = $HB_ENV['Fhdays'];
2481  $Fset2 = $HB_ENV['Fset2'];
2482  $Ml = urldecode($HB_ENV['Ml']);
2483 
2484  #require ("throtlpkt.i");
2485  list ($status, $asofdate, $reason) = fetch_packet($CU, $HB_ENV['Cn'], 300);
2486  if ($asofdate == 1) {
2487  throw new Exception('System Unavailable',2061); # couldn't get a packet
2488  $HB_ENV['stale'] = 1;
2489  } else {
2490  $HB_ENV['lastupdate'] = $asofdate;
2491  }
2492  }
2493 
2494  $balances = Get_Balances($dbh, $HB_ENV);
2495 
2496  $expires = mktime(date("H"), date("i"), date("s"), date("m") + 3, date("d"), date("Y"));
2497 
2498  header("Content-Type: application/x-ofx");
2499  header("Content-disposition: inline; filename=\"${CU}_txns.ofx\"");
2500  $now = date('YmdHis');
2501 
2502  $ofxcount = 0;
2503  $ofxcount += countprint('<?xml version="1.0" encoding="' . $encoding . '"?>
2504 <?OFX OFXHEADER="200" VERSION="211" SECURITY="NONE" OLDFILEUID="NONE" NEWFILEUID="NONE"?>
2505 <OFX>
2506 <SIGNONMSGSRSV1>
2507 <SONRS>
2508 <STATUS>
2509 <CODE>0</CODE>
2510 <SEVERITY>INFO</SEVERITY>
2511 </STATUS>
2512 <DTSERVER>' . $now . '</DTSERVER>
2513 <LASTUPDATE>' . $HB_ENV['lastupdate'] . '</LASTUPDATE>
2514 ');
2515  if ($HB_ENV['stale'] == 1)
2516  $ofxcount += countprint("<STALE>YES</STALE>\n");
2517  $ofxcount += countprint("<LANGUAGE>ENG</LANGUAGE>\n");
2518  $ofxcount += countprint("<MEMBER>{$HB_ENV['Uid']}</MEMBER>\n"); # was Cauth for Mammoth
2519  $ofxcount += countprint("<SELECTED_MEMBER>{$HB_ENV['Uid']}</SELECTED_MEMBER>\n");
2520  $ofxcount += countprint("<USERKEY>$apptoken</USERKEY>\n");
2521  $ofxcount += countprint("<TIMEOUT>{$HB_ENV['AppTimeout']}</TIMEOUT>\n");
2522  $ofxcount += countprint("</SONRS>\n");
2523  $ofxcount += countprint("</SIGNONMSGSRSV1>\n");
2524  # no switch accounts in odyssey, but with a little work this might work for viewing multiple accounts
2525 // $switchlist = Get_SwitchAccountList($dbh, $HB_ENV);
2526 // if (count($switchlist['status']['errors']) > 0) {
2527 // throw new Exception(implode(' ',$switchlist['status']['errors']),15592); # Get_SwitchAccountList
2528 // } else {
2529 // $ofxcount += countprint("<SWACCT>\n");
2530 // $ofxcount += countprint("<SWITCHALLOWED>{$switchlist['data']['switchallowed']}</SWITCHALLOWED>\n");
2531 // if (count($switchlist['data']['selectedacct'])) {
2532 // $ofxcount += countprint("<SELECTED_ACCT>\n");
2533 // foreach ($switchlist['data']['selectedacct'] as $key => $value) {
2534 // $key = strtoupper($key);
2535 // $value = htmlspecialchars("$value", ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE);
2536 // $ofxcount += countprint("<$key>$value</$key>\n");
2537 // }
2538 // $ofxcount += countprint("</SELECTED_ACCT>\n");
2539 // }
2540 //// $ofxcount += countprint("<switchlist>" . print_r($switchlist,true) . "</switchlist>");
2541 // if ($switchlist['data']['switchallowed'] && count($switchlist['data']['switchaccounts'])) {
2542 // foreach ($switchlist['data']['switchaccounts'] as $swacct) {
2543 // $ofxcount += countprint("<SWITCHACCT>\n");
2544 // foreach ($swacct as $key => $value) {
2545 // $key = strtoupper($key);
2546 // $value = htmlspecialchars("$value", ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE);
2547 // $ofxcount += countprint("<$key>$value</$key>\n");
2548 // }
2549 // $ofxcount += countprint("</SWITCHACCT>\n");
2550 // }
2551 // }
2552 // $ofxcount += countprint("</SWACCT>\n");
2553 // }
2554  if (count($balances['dp']) && (empty($KEYACCTID) || (!empty($KEYACCTID) && array_key_exists($KEYACCTID, $balances['dp'])))) {
2555  $ofxcount += countprint("<BANKMSGSRSV1>\n");
2556 # for each $balances['dp'] Get_History & print
2557  foreach ($balances['dp'] as $balkey => $balinfo) {
2558  if ((!empty($KEYACCTID)) && $balkey != $KEYACCTID) {
2559  continue;
2560  }
2561  $cert = $balinfo['certnumber'];
2562  $type = $balinfo['accounttype'];
2563  $desc = $balinfo['description'];
2564  $desc = htmlspecialchars("$desc", ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE);
2565  $displaydesc = $balinfo['displaydesc'];
2566  $displaydesc = htmlspecialchars("$displaydesc", ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE);
2567  $type = ("$cert" == "0" ? $type : "${type}_${cert}");
2568  $type = htmlspecialchars(trim($type), ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE);
2569  $ytdinterest = $balinfo['ytdinterest'];
2570  $lastyrinterest = $balinfo['lastyrinterest'];
2571  $holdtotal = $balinfo['holdtotal'];
2572  $pendtotal = $balinfo['pendtotal'];
2573 
2574  switch ($balinfo['deposittype']) {
2575  case "Y":
2576  $acttype = "CHECKING";
2577  $micraccount = $balinfo['micraccount'];
2578  break;
2579  case "C": # Certificates
2580  $acttype = "INVESTMENT";
2581  break;
2582  case "I": # IRA accounts
2583  $acttype = "RETIREMENT";
2584  break;
2585  case "N":
2586  case "S":
2587  $acttype = "SAVINGS";
2588  break;
2589  }
2590 # opening tags for account info
2591 
2592  $ofxcount += countprint("<STMTTRNRS>\n");
2593  $ofxcount += countprint("<TRNUID>0</TRNUID>\n");
2594  $ofxcount += countprint("<STATUS>\n");
2595  $ofxcount += countprint("<CODE>0</CODE>\n");
2596  $ofxcount += countprint("<SEVERITY>INFO</SEVERITY>\n");
2597  $ofxcount += countprint("</STATUS>\n");
2598  $ofxcount += countprint("<STMTRS>\n");
2599  $ofxcount += countprint("<CURDEF>USD</CURDEF>\n");
2600  $ofxcount += countprint("<BANKACCTFROM>\n");
2601  $ofxcount += countprint("<BANKID>" . $HB_ENV['rt'] . "</BANKID>\n");
2602  $ofxcount += countprint("<ACCTID>$type</ACCTID>\n");
2603  $ofxcount += countprint("<ACCTTYPE>$acttype</ACCTTYPE>\n");
2604  $ofxcount += countprint("<DESCRIPTION>$desc</DESCRIPTION>\n");
2605  if ("$displaydesc" > '') {
2606  $ofxcount += countprint("<DISPLAYDESC>$displaydesc</DISPLAYDESC>\n");
2607  }
2608  $ofxcount += countprint("</BANKACCTFROM>\n");
2609 
2610  $history = Get_History($dbh, $HB_ENV, $balkey, $sqlstart, $sqlend);
2611 # opening tags for transaction list
2612  $ofxcount += countprint("<BANKTRANLIST>\n");
2613  $ofxcount += countprint("<DTSTART>${sqlstart}000000</DTSTART>\n");
2614  $ofxcount += countprint("<DTEND>${sqlend}235959</DTEND>\n");
2615 
2616  if (count($history[$balkey])) {
2617  foreach ($history[$balkey] as $tnum => $detl) {
2618 # process the list
2619 
2620  $tranamount = $detl['amount'];
2621  $tranamount = str_replace(",", "", str_replace("$", "", $tranamount));
2622  $tranamount = sprintf("%.2f", $tranamount);
2623  $trbal = $detl['balance'];
2624  $trbal = str_replace(",", "", str_replace("$", "", $trbal));
2625  $trbal = sprintf("%.2f", $trbal);
2626  $check = $detl['checkno'];
2627  $trandesc = $detl['description'];
2628  if ($trandesc < " " && $check != 0) {
2629  $trandesc = "CHK";
2630  }
2631  $trandesc = (preg_replace("/<BR>/", " ", $trandesc));
2632  $trandesc = (preg_replace("/&nbsp;/", " ", $trandesc));
2633  $longdesc = htmlspecialchars($trandesc, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE);
2634  $shortdesc = substr(htmlspecialchars($trandesc, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE), 0, 31);
2635  $shortdesc = preg_replace('/&[^;]*$/', '', $shortdesc);
2636  $shortdesc = (trim($shortdesc) == '' ? '.' : $shortdesc);
2637 
2638  $ofxcount += countprint("<STMTTRN>\n");
2639  if ($tranamount < 0) {
2640  if ($balinfo['deposittype'] == 'Y' and $check != 0) {
2641  $ofxcount += countprint("<TRNTYPE>CHECK</TRNTYPE>\n");
2642  } else {
2643  $ofxcount += countprint("<TRNTYPE>DEBIT</TRNTYPE>\n");
2644  }
2645  } else {
2646  $ofxcount += countprint("<TRNTYPE>CREDIT</TRNTYPE>\n");
2647  }
2648  $ofxcount += countprint("<DTPOSTED>" . $detl['date'] . "</DTPOSTED>\n");
2649 # DTUSER not needed for 211?
2650  $ofxcount += countprint("<DTUSER>" . $detl['date'] . "</DTUSER>\n");
2651  $ofxcount += countprint("<TRNAMT>$tranamount</TRNAMT>\n");
2652  $ofxcount += countprint("<RUNBAL>$trbal</RUNBAL>\n");
2653  $ofxcount += countprint("<FITID>" . $detl['traceno'] . "</FITID>\n");
2654  if ($balinfo['deposittype'] == 'Y' and $check != 0) {
2655  $ofxcount += countprint("<CHECKNUM>$check</CHECKNUM>\n");
2656  if (!empty($detl['ckitem']) && !empty($detl['ckhash'])) {
2657  $ofxcount += countprint("<CKITEM>" . $detl['ckitem'] . "</CKITEM>\n");
2658 // $ofxcount += countprint("<CKITEM>" . urlencode(hcu_encrypturl($detl['ckitem'],$chk_key)) . "</CKITEM>\n");
2659  $ofxcount += countprint("<CKHASH>" . $detl['ckhash'] . "</CKHASH>\n");
2660  }
2661  }
2662  $ofxcount += countprint("<NAME>$shortdesc</NAME>\n");
2663  if (strlen($longdesc) > 0) {
2664  $ofxcount += countprint("<MEMO>$longdesc</MEMO>\n");
2665  }
2666  $ofxcount += countprint("</STMTTRN>\n");
2667  }
2668  }
2669 # closing tags for transaction list
2670 
2671  $ofxcount += countprint("</BANKTRANLIST>\n");
2672  $ofxcount += countprint("<LEDGERBAL>\n");
2673  $ofxcount += countprint("<BALAMT>" . $balinfo['currentbal'] . "</BALAMT>\n");
2674  $ofxcount += countprint("<DTASOF>$now</DTASOF>\n");
2675  $ofxcount += countprint("</LEDGERBAL>\n");
2676  if (($HB_ENV['Fset'] & $CU_SHOWAVAILABLE) == $CU_SHOWAVAILABLE) {
2677  $ofxcount += countprint("<AVAILBAL>\n<BALAMT>" . $balinfo['availablebal'] . "</BALAMT>\n <DTASOF>$now</DTASOF>\n</AVAILBAL>\n");
2678  }
2679 
2680  $ofxcount += countprint("<TXNPENDING>\n");
2681  if ($live == 0) {
2682  $pending = Get_ReqDetails($dbh, $HB_ENV, $balkey);
2683 # Get_ReqDetails returns txdesc already UTF-encoded. Problem?
2684  if (count($pending['acctlist'][$balkey])) {
2685  foreach ($pending['acctlist'][$balkey] as $tnum => $detl) {
2686 # process the list
2687 
2688  $ofxcount += countprint("<REQUEST>\n");
2689  $ofxcount += countprint("<TRACENO>" . $detl['id'] . "</TRACENO>\n");
2690  $ofxcount += countprint("<DTREQUEST>" . $detl['postdate'] . "</DTREQUEST>\n");
2691  $ofxcount += countprint("<TRNAMT>" . $detl['amount'] . "</TRNAMT>\n");
2692  $ofxcount += countprint("<TRNDESC>" . htmlspecialchars($detl['txdesc'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</TRNDESC>\n");
2693  $ofxcount += countprint("</REQUEST>\n");
2694  }
2695  }
2696  }
2697 
2698  if (($HB_ENV['Fset2'] & $CU2_SHOWPEND) == $CU2_SHOWPEND) {
2699  $pending = Get_PendDetails($dbh, $HB_ENV, $balkey);
2700  if (count($pending[$balkey])) {
2701  foreach ($pending[$balkey] as $tnum => $detl) {
2702 # process the list
2703 
2704  $ofxcount += countprint("<ACHWAREHOUSE>\n");
2705  $ofxcount += countprint("<TRACENO>" . $detl['traceno'] . "</TRACENO>\n");
2706  $ofxcount += countprint("<DTREQUEST>" . $detl['postdate'] . "</DTREQUEST>\n");
2707  $ofxcount += countprint("<TRNAMT>" . $detl['amount'] . "</TRNAMT>\n");
2708 // $ofxcount += countprint("<TRNDESC>" . $detl['description'] . "</TRNDESC>\n");
2709  $ofxcount += countprint("<TRNDESC>" . htmlspecialchars($detl['description'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</TRNDESC>\n");
2710  $ofxcount += countprint("</ACHWAREHOUSE>\n");
2711  }
2712  }
2713  }
2714  if (($HB_ENV['Fset2'] & $CU2_SHOWHOLD) == $CU2_SHOWHOLD) {
2715  $pending = Get_HoldDetails($dbh, $HB_ENV, $balkey);
2716  if (count($pending[$balkey])) {
2717  foreach ($pending[$balkey] as $tnum => $detl) {
2718 # process the list
2719 
2720  $ofxcount += countprint("<PREAUTH>\n");
2721  $ofxcount += countprint("<TRACENO>" . $detl['traceno'] . "</TRACENO>\n");
2722  $ofxcount += countprint("<DTREQUEST>" . $detl['postdate'] . "</DTREQUEST>\n");
2723  $ofxcount += countprint("<TRNAMT>" . $detl['amount'] . "</TRNAMT>\n");
2724 // $ofxcount += countprint("<TRNDESC>" . $detl['description'] . "</TRNDESC>\n");
2725  $ofxcount += countprint("<TRNDESC>" . htmlspecialchars($detl['description'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</TRNDESC>\n");
2726  $ofxcount += countprint("</PREAUTH>\n");
2727  }
2728  }
2729  }
2730  $ofxcount += countprint("</TXNPENDING>\n");
2731  $ofxcount += countprint("<EXTRAINFO>\n");
2732  $ofxcount += countprint("<DTASOF>$now</DTASOF>\n");
2733  $ofxcount += countprint("<KEYACCTID>$balkey</KEYACCTID>\n");
2734  $ofxcount += countprint("<YTDINTEREST>$ytdinterest</YTDINTEREST>\n");
2735  $ofxcount += countprint("<LYRINTEREST>$lastyrinterest</LYRINTEREST>\n");
2736  if ($acttype == "CHECKING") {
2737  $ofxcount += countprint("<MICRACCOUNT>$micraccount</MICRACCOUNT>\n");
2738  }
2739  # comment these out until cu_data.i is returning them:
2740 # if (($HB_ENV['Fset2'] & $CU2_SHOWHOLD)== $CU2_SHOWHOLD) {
2741 # $ofxcount += countprint("<HOLDTOTAL>$holdtotal</HOLDTOTAL>\n");
2742 # }
2743 # if (($HB_ENV['Fset2'] & $CU2_SHOWPEND)== $CU2_SHOWPEND) {
2744 # $ofxcount += countprint("<PENDTOTAL>$pendtotal</PENDTOTAL>\n");
2745 # }
2746  #
2747  $ofxcount += countprint("</EXTRAINFO>\n");
2748 # closing tags for account info
2749  $ofxcount += countprint("</STMTRS>\n</STMTTRNRS>\n");
2750  }
2751  $ofxcount += countprint("</BANKMSGSRSV1>\n");
2752  }
2753 #
2754 # If CU2_SPEC18, try to get credit card loans
2755  if (($HB_ENV['Fset2'] & $CU2_SPEC18) == $CU2_SPEC18) {
2756 
2757  if (count($balances['cc']) && (empty($KEYACCTID) || (!empty($KEYACCTID) && array_key_exists($KEYACCTID, $balances['cc'])))) {
2758  $ch_sql = "select ccinfourl from cuadmin where cu='$CU'";
2759  $sth_ch = db_query($ch_sql, $dbh);
2760  list($ccinfo) = db_fetch_array($sth_ch, 0);
2761  $incchist = (trim(strtoupper($ccinfo)) == 'HOMECU' ? 1 : 0);
2762 
2763  $ofxcount += countprint("<CREDITCARDMSGSRSV1>\n");
2764 
2765  foreach ($balances['cc'] as $balkey => $balinfo) {
2766  if ((!empty($KEYACCTID)) && $balkey != $KEYACCTID) {
2767  continue;
2768  }
2769 
2770  $ofxcount += countprint("<CCSTMTTRNRS>\n");
2771 
2772 
2773  $stmntbal = $balinfo['payoff'];
2774  $paymentamount = $balinfo['paymentamount'];
2775  $nextduedate = $balinfo['nextduedate'];
2776  $interestrate = $balinfo['interestrate'];
2777  $creditlimit = $balinfo['creditlimit'];
2778  $ytdinterest = $balinfo['ytdinterest'];
2779  $lastyrinterest = $balinfo['lastyrinterest'];
2780 
2781  $desc = $balinfo['description'];
2782  $desc = htmlspecialchars("$desc", ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE);
2783  $displaydesc = $balinfo['displaydesc'];
2784  $displaydesc = htmlspecialchars("$displaydesc", ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE);
2785  $loan = $balinfo['loan'];
2786  $balance = $balinfo['currentbal'];
2787  $creditlimit = $balinfo['creditlimit'];
2788  $available = $creditlimit - $balance;
2789  $available = ($available < 0 ? "" : $available);
2790 
2791  # open new loan set
2792  $ofxcount += countprint("<CCSTMTRS>\n");
2793  $ofxcount += countprint("<CURDEF>USD</CURDEF>\n");
2794  $ofxcount += countprint("<CCACCTFROM>\n");
2795  $ofxcount += countprint("<ACCTID>$loan</ACCTID>\n");
2796  $ofxcount += countprint("<DESCRIPTION>$desc</DESCRIPTION>\n");
2797  if ("$displaydesc" > '') {
2798  $ofxcount += countprint("<DISPLAYDESC>$displaydesc</DISPLAYDESC>\n");
2799  }
2800  if (trim($balinfo['hisinfo']) > '' && strtolower(trim($balinfo['hisinfo'])) != 'homecu') {
2801  $ofxcount += countprint("<HISTORYURL>" . urlencode($balinfo['hisinfo']) . "</HISTORYURL>\n");
2802  }
2803  $ofxcount += countprint("</CCACCTFROM>\n");
2804  $ofxcount += countprint("<BANKTRANLIST>\n");
2805  $ofxcount += countprint("<DTSTART>${sqlstart}000000</DTSTART>\n");
2806  $ofxcount += countprint("<DTEND>${sqlend}235959</DTEND>\n");
2807 
2808  $cur_avail = (($HB_ENV['Fset2'] & $CU2_CALL_CCAVAIL) == $CU2_CALL_CCAVAIL ?
2809  "Call" : $available);
2810 
2811  if ($incchist) {
2812  $history = Get_History($dbh, $HB_ENV, $balkey, $sqlstart, $sqlend);
2813  if (count($history[$balkey])) {
2814  foreach ($history[$balkey] as $tnum => $detl) {
2815 
2816  $hisbal = $detl['balance'];
2817  $principle = $detl['principal'];
2818  $interest = $detl['interest'];
2819 
2820  if ($principle < 0) {
2821  $trntype = "DEBIT";
2822  } else {
2823  $trntype = "CREDIT";
2824  }
2825 
2826  $totalpay = $detl['totalpay'];
2827  $trdesc = $detl['description'];
2828  $date = $detl['date'];
2829  $traceno = $detl['traceno'];
2830  $longdesc = htmlentities($trdesc, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE);
2831  $shortdesc = substr(htmlentities($trdesc, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE), 0, 31);
2832  $shortdesc = preg_replace('/&[^;]*$/', '', $shortdesc);
2833  $shortdesc = (trim($shortdesc) == '' ? '.' : $shortdesc);
2834 
2835 # transaction data row
2836  $ofxcount += countprint("<STMTTRN>\n");
2837  $ofxcount += countprint("<TRNTYPE>$trntype</TRNTYPE>\n");
2838  $ofxcount += countprint("<DTPOSTED>" . $detl['date'] . "</DTPOSTED>\n");
2839  $ofxcount += countprint("<TRNAMT>$totalpay</TRNAMT>\n");
2840  if (($HB_ENV['Fset'] & $CU_LNBALUNUSABLE) != $CU_LNBALUNUSABLE) {
2841  $ofxcount += countprint("<RUNBAL>$hisbal</RUNBAL>\n");
2842  }
2843  $ofxcount += countprint("<FITID>$traceno</FITID>\n");
2844  if (($HB_ENV['Fset'] & $CU_SHOWLNTXNDESC) == $CU_SHOWLNTXNDESC) {
2845  $ofxcount += countprint("<NAME>$shortdesc</NAME>\n");
2846  $ofxcount += countprint("<MEMO>$longdesc</MEMO>\n");
2847  }
2848  $ofxcount += countprint("</STMTTRN>\n");
2849  }
2850  }
2851  }
2852  $ofxcount += countprint("</BANKTRANLIST>\n");
2853  $ofxcount += countprint("<LEDGERBAL>\n");
2854  $ofxcount += countprint("<BALAMT>$balance</BALAMT>\n");
2855  $ofxcount += countprint("<DTASOF>$now</DTASOF>\n");
2856  $ofxcount += countprint("</LEDGERBAL>\n");
2857  if ($cur_avail > 0) {
2858  $ofxcount += countprint("<AVAILBAL>\n");
2859  $ofxcount += countprint("<BALAMT>$cur_avail</BALAMT>\n");
2860  $ofxcount += countprint("<DTASOF>$now</DTASOF>\n");
2861  $ofxcount += countprint("</AVAILBAL>\n");
2862  }
2863 #
2864  $ofxcount += countprint("<TXNPENDING>\n");
2865  if ($live == 0) {
2866  $pending = Get_ReqDetails($dbh, $HB_ENV, $balkey);
2867 # Get_ReqDetails returns txdesc already UTF-encoded. Problem?
2868  if (count($pending['acctlist'][$balkey])) {
2869  foreach ($pending['acctlist'][$balkey] as $tnum => $detl) {
2870 # process the list
2871 
2872  $ofxcount += countprint("<REQUEST>\n");
2873  $ofxcount += countprint("<TRACENO>" . $detl['id'] . "</TRACENO>\n");
2874  $ofxcount += countprint("<DTREQUEST>" . $detl['postdate'] . "</DTREQUEST>\n");
2875  $ofxcount += countprint("<TRNAMT>" . $detl['amount'] . "</TRNAMT>\n");
2876  $ofxcount += countprint("<TRNDESC>" . htmlspecialchars($detl['txdesc'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</TRNDESC>\n");
2877  $ofxcount += countprint("</REQUEST>\n");
2878  }
2879  }
2880 #
2881  }
2882  if (($HB_ENV['Fset2'] & $CU2_SHOWPEND) == $CU2_SHOWPEND) {
2883  $pending = Get_PendDetails($dbh, $HB_ENV, $balkey);
2884  if (count($pending[$balkey])) {
2885  foreach ($pending[$balkey] as $tnum => $detl) {
2886 # process the list
2887 
2888  $ofxcount += countprint("<ACHWAREHOUSE>\n");
2889  $ofxcount += countprint("<TRACENO>" . $detl['traceno'] . "</TRACENO>\n");
2890  $ofxcount += countprint("<DTREQUEST>" . $detl['postdate'] . "</DTREQUEST>\n");
2891  $ofxcount += countprint("<TRNAMT>" . $detl['amount'] . "</TRNAMT>\n");
2892  $ofxcount += countprint("<TRNDESC>" . htmlspecialchars($detl['description'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</TRNDESC>\n");
2893  $ofxcount += countprint("</ACHWAREHOUSE>\n");
2894  }
2895  }
2896  }
2897  if (($HB_ENV['Fset2'] & $CU2_SHOWHOLD) == $CU2_SHOWHOLD) {
2898  $pending = Get_HoldDetails($dbh, $HB_ENV, $balkey);
2899  if (count($pending[$balkey])) {
2900  foreach ($pending[$balkey] as $tnum => $detl) {
2901 # process the list
2902 
2903  $ofxcount += countprint("<PREAUTH>\n");
2904  $ofxcount += countprint("<TRACENO>" . $detl['traceno'] . "</TRACENO>\n");
2905  $ofxcount += countprint("<DTREQUEST>" . $detl['postdate'] . "</DTREQUEST>\n");
2906  $ofxcount += countprint("<TRNAMT>" . $detl['amount'] . "</TRNAMT>\n");
2907  $ofxcount += countprint("<TRNDESC>" . htmlspecialchars($detl['description'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</TRNDESC>\n");
2908  $ofxcount += countprint("</PREAUTH>\n");
2909  }
2910  }
2911  }
2912  $ofxcount += countprint("</TXNPENDING>\n");
2913  $ofxcount += countprint("<EXTRAINFO>\n");
2914  $ofxcount += countprint("<DTASOF>$now</DTASOF>\n");
2915  $ofxcount += countprint("<KEYACCTID>$balkey</KEYACCTID>\n");
2916  if ($live && ($HB_ENV['Fset2'] & $CU2_SHOWCCSB) == $CU2_SHOWCCSB && ($HB_ENV['Fset2'] & $CU2_CC18NOINFO) != $CU2_CC18NOINFO) {
2917  $ofxcount += countprint("<STMNTBAL>$stmntbal</STMNTBAL>\n");
2918  }
2919  $ofxcount += countprint("<PAYAMOUNT>$paymentamount</PAYAMOUNT>\n");
2920  if (($HB_ENV['Fset'] & $GLOBALS['CU_HIDELOANDATE']) != $GLOBALS['CU_HIDELOANDATE']) {
2921  $ofxcount += countprint("<NEXTDUE>$nextduedate</NEXTDUE>\n");
2922  }
2923  $ofxcount += countprint("<INTERESTRATE>$interestrate</INTERESTRATE>\n");
2924  $ofxcount += countprint("<CREDITLIMIT>$creditlimit</CREDITLIMIT>\n");
2925  $ofxcount += countprint("<YTDINTEREST>$ytdinterest</YTDINTEREST>\n");
2926  $ofxcount += countprint("<LYRINTEREST>$lastyrinterest</LYRINTEREST>\n");
2927  $ofxcount += countprint("</EXTRAINFO>\n");
2928  $ofxcount += countprint("</CCSTMTRS>\n");
2929  $ofxcount += countprint("</CCSTMTTRNRS>\n");
2930  }
2931  $ofxcount += countprint("</CREDITCARDMSGSRSV1>\n");
2932  }
2933  }
2934 
2935 # try to get loans
2936  if (count($balances['ln']) && (empty($KEYACCTID) || (!empty($KEYACCTID) && array_key_exists($KEYACCTID, $balances['ln'])))) {
2937 
2938  $ofxcount += countprint("<LOANMSGSRSV1>\n");
2939 
2940  foreach ($balances['ln'] as $balkey => $balinfo) {
2941  if ((!empty($KEYACCTID)) && $balkey != $KEYACCTID) {
2942  continue;
2943  }
2944 
2945  $ofxcount += countprint("<LOANSTMTTRNRS>\n");
2946 
2947  $balance = $balinfo['currentbal'];
2948  $loan = $balinfo['loan'];
2949  $desc = $balinfo['description'];
2950  $desc = htmlspecialchars("$desc", ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE);
2951  $displaydesc = $balinfo['displaydesc'];
2952  $displaydesc = htmlspecialchars("$displaydesc", ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE);
2953  $payoff = $balinfo['payoff'];
2954  $paymentamount = $balinfo['paymentamount'];
2955  $nextduedate = $balinfo['nextduedate'];
2956  $interestrate = $balinfo['interestrate'];
2957  $creditlimit = $balinfo['creditlimit'];
2958  $ytdinterest = $balinfo['ytdinterest'];
2959  $lastyrinterest = $balinfo['lastyrinterest'];
2960 
2961  # open new loan set
2962  $ofxcount += countprint("<LOANSTMTRS>\n");
2963  $ofxcount += countprint("<CURDEF>USD</CURDEF>\n");
2964  $ofxcount += countprint("<LOANACCTFROM>\n");
2965  $ofxcount += countprint("<LOANACCTID>$loan</LOANACCTID>\n");
2966  $ofxcount += countprint("<LOANACCTTYPE>CONSUMER</LOANACCTTYPE>\n");
2967  $ofxcount += countprint("<DESCRIPTION>$desc</DESCRIPTION>\n");
2968  if ("$displaydesc" > '') {
2969  $ofxcount += countprint("<DISPLAYDESC>$displaydesc</DISPLAYDESC>\n");
2970  }
2971  if (trim($balinfo['hisinfo']) > '' && strtolower(trim($balinfo['hisinfo'])) != 'homecu') {
2972  $ofxcount += countprint("<HISTORYURL>" . urlencode($balinfo['hisinfo']) . "</HISTORYURL>\n");
2973  }
2974  $ofxcount += countprint("</LOANACCTFROM>\n");
2975  $ofxcount += countprint("<LOANTRANLIST>\n");
2976  $ofxcount += countprint("<DTSTART>${sqlstart}000000</DTSTART>\n");
2977  $ofxcount += countprint("<DTEND>${sqlend}235959</DTEND>\n");
2978 
2979  $history = Get_History($dbh, $HB_ENV, $balkey, $sqlstart, $sqlend);
2980  if (count($history[$balkey])) {
2981  foreach ($history[$balkey] as $tnum => $detl) {
2982 
2983  $hisbal = $detl['balance'];
2984  $principle = $detl['principal'];
2985  $interest = $detl['interest'];
2986  $totalpay = $detl['totalpay'];
2987  $traceno = $detl['traceno'];
2988  $trdesc = $detl['description'];
2989 
2990  if ($principle < 0) {
2991  $trntype = "PAYMENT";
2992  } else {
2993  $trntype = "ADVANCE";
2994  }
2995 
2996  $longdesc = htmlentities($trdesc, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE);
2997  $shortdesc = substr(htmlentities($trdesc, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE), 0, 31);
2998  $shortdesc = preg_replace('/&[^;]*$/', '', $shortdesc);
2999  $shortdesc = (trim($shortdesc) == '' ? '.' : $shortdesc);
3000 
3001 # transaction data row
3002  $ofxcount += countprint("<LOANSTMTTRN>\n");
3003  $ofxcount += countprint("<LOANTRNTYPE>$trntype</LOANTRNTYPE>\n");
3004  $ofxcount += countprint("<DTPOSTED>" . $detl['date'] . "</DTPOSTED>\n");
3005  if (($HB_ENV['Fset'] & $CU_SHOWLNTXNSPLIT) == $CU_SHOWLNTXNSPLIT) {
3006  $ofxcount += countprint("<TRNAMT>$totalpay</TRNAMT>\n");
3007  $ofxcount += countprint("<LOANTRNAMT>\n");
3008  $ofxcount += countprint("<PRINAMT>$principle</PRINAMT>\n");
3009  $ofxcount += countprint("<INTAMT>$interest</INTAMT>\n");
3010  $ofxcount += countprint("</LOANTRNAMT>\n");
3011  } else {
3012  $ofxcount += countprint("<TRNAMT>$principle</TRNAMT>\n");
3013  }
3014  if (($HB_ENV['Fset'] & $CU_LNBALUNUSABLE) != $CU_LNBALUNUSABLE) {
3015  $ofxcount += countprint("<RUNBAL>$hisbal</RUNBAL>\n");
3016  }
3017  $ofxcount += countprint("<FITID>$traceno</FITID>\n");
3018  if (($HB_ENV['Fset'] & $CU_SHOWLNTXNDESC) == $CU_SHOWLNTXNDESC) {
3019  $ofxcount += countprint("<NAME>$shortdesc</NAME>\n");
3020  $ofxcount += countprint("<MEMO>$longdesc</MEMO>\n");
3021  }
3022  $ofxcount += countprint("</LOANSTMTTRN>\n");
3023  }
3024  }
3025  $ofxcount += countprint("</LOANTRANLIST>\n");
3026  $ofxcount += countprint("<PRINBAL>\n");
3027  $ofxcount += countprint("<BALAMT>$balance</BALAMT>\n");
3028  $ofxcount += countprint("<DTASOF>$now</DTASOF>\n");
3029  $ofxcount += countprint("</PRINBAL>\n");
3030 
3031  $ofxcount += countprint("<TXNPENDING>\n");
3032  if ($live == 0) {
3033  $pending = Get_ReqDetails($dbh, $HB_ENV, $balkey);
3034 # Get_ReqDetails returns txdesc already UTF-encoded. Problem?
3035  if (count($pending['acctlist'][$balkey])) {
3036  foreach ($pending['acctlist'][$balkey] as $tnum => $detl) {
3037 # process the list
3038 
3039  $ofxcount += countprint("<REQUEST>\n");
3040  $ofxcount += countprint("<TRACENO>" . $detl['id'] . "</TRACENO>\n");
3041  $ofxcount += countprint("<DTREQUEST>" . $detl['postdate'] . "</DTREQUEST>\n");
3042  $ofxcount += countprint("<TRNAMT>" . $detl['amount'] . "</TRNAMT>\n");
3043  $ofxcount += countprint("<TRNDESC>" . htmlspecialchars($detl['txdesc'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</TRNDESC>\n");
3044  $ofxcount += countprint("</REQUEST>\n");
3045  }
3046  }
3047  }
3048 
3049  if (($HB_ENV['Fset2'] & $CU2_SHOWPEND) == $CU2_SHOWPEND) {
3050  $pending = Get_PendDetails($dbh, $HB_ENV, $balkey);
3051  if (count($pending[$balkey])) {
3052  foreach ($pending[$balkey] as $tnum => $detl) {
3053 # process the list
3054 
3055  $ofxcount += countprint("<ACHWAREHOUSE>\n");
3056  $ofxcount += countprint("<TRACENO>" . $detl['traceno'] . "</TRACENO>\n");
3057  $ofxcount += countprint("<DTREQUEST>" . $detl['postdate'] . "</DTREQUEST>\n");
3058  $ofxcount += countprint("<TRNAMT>" . $detl['amount'] . "</TRNAMT>\n");
3059  $ofxcount += countprint("<TRNDESC>" . htmlspecialchars($detl['description'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</TRNDESC>\n");
3060  $ofxcount += countprint("</ACHWAREHOUSE>\n");
3061  }
3062  }
3063  }
3064  if (($HB_ENV['Fset2'] & $CU2_SHOWHOLD) == $CU2_SHOWHOLD) {
3065  $pending = Get_HoldDetails($dbh, $HB_ENV, $balkey);
3066  if (count($pending[$balkey])) {
3067  foreach ($pending[$balkey] as $tnum => $detl) {
3068 # process the list
3069 
3070  $ofxcount += countprint("<PREAUTH>\n");
3071  $ofxcount += countprint("<TRACENO>" . $detl['traceno'] . "</TRACENO>\n");
3072  $ofxcount += countprint("<DTREQUEST>" . $detl['postdate'] . "</DTREQUEST>\n");
3073  $ofxcount += countprint("<TRNAMT>" . $detl['amount'] . "</TRNAMT>\n");
3074  $ofxcount += countprint("<TRNDESC>" . htmlspecialchars($detl['description'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</TRNDESC>\n");
3075  $ofxcount += countprint("</PREAUTH>\n");
3076  }
3077  }
3078  }
3079  $ofxcount += countprint("</TXNPENDING>\n");
3080  $ofxcount += countprint("<EXTRAINFO>\n");
3081  $ofxcount += countprint("<DTASOF>$now</DTASOF>\n");
3082  $ofxcount += countprint("<KEYACCTID>$balkey</KEYACCTID>\n");
3083  $ofxcount += countprint("<PAYOFF>$payoff</PAYOFF>\n");
3084  $ofxcount += countprint("<PAYAMOUNT>$paymentamount</PAYAMOUNT>\n");
3085  if (($HB_ENV['Fset'] & $GLOBALS['CU_HIDELOANDATE']) != $GLOBALS['CU_HIDELOANDATE']) {
3086  $ofxcount += countprint("<NEXTDUE>$nextduedate</NEXTDUE>\n");
3087  }
3088  $ofxcount += countprint("<INTERESTRATE>$interestrate</INTERESTRATE>\n");
3089  $ofxcount += countprint("<CREDITLIMIT>$creditlimit</CREDITLIMIT>\n");
3090  $ofxcount += countprint("<YTDINTEREST>$ytdinterest</YTDINTEREST>\n");
3091  $ofxcount += countprint("<LYRINTEREST>$lastyrinterest</LYRINTEREST>\n");
3092  $ofxcount += countprint("</EXTRAINFO>\n");
3093  $ofxcount += countprint("</LOANSTMTRS>\n");
3094  $ofxcount += countprint("</LOANSTMTTRNRS>\n");
3095  }
3096  $ofxcount += countprint("</LOANMSGSRSV1>\n");
3097  }
3098  $ofxcount += countprint("</OFX>\n");
3099  header("Content-length: $ofxcount");
3100  exit;
3101  break;
3102  }
3103 } catch (Exception $e) {
3104  $code = $e->getCode();
3105  $message = $e->getMessage();
3106 
3107  $ofxcount = 0;
3108  $ofxcount += countprint("<OFXERR>\n<STATUS>\n<CODE>$code</CODE>\n");
3109  $ofxcount += countprint("<SEVERITY>ERROR</SEVERITY>\n</STATUS>\n");
3110 
3111  $ofxcount += countprint("<MESSAGE>\n");
3112  $ofxcount += countprint("<ERR>" . htmlspecialchars($message, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</ERR>\n");
3113  $ofxcount += countprint("<ERRNO>999</ERRNO>\n<ERRSTAT>FAIL</ERRSTAT>\n");
3114  $ofxcount += countprint("</MESSAGE>\n");
3115  $ofxcount += countprint("</OFXERR>\n");
3116 
3117  header("Content-length: $ofxcount");
3118 
3119  exit;
3120 
3121 }
3122 function send_response($code, $message, $severity = "ERROR") {
3123  $ofxcount = 0;
3124  #header("Content-Type: application/x-ofx");
3125  $ofxcount += countprint("<OFXERR>\n<STATUS>\n<CODE>$code</CODE>\n");
3126  $ofxcount += countprint("<SEVERITY>$severity</SEVERITY>\n</STATUS>\n");
3127 
3128  foreach ($message as $err => $details) {
3129  $ofxcount += countprint("<MESSAGE>\n");
3130  $ofxcount += countprint("<ERR>" . htmlspecialchars($details, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</ERR>\n");
3131  $ofxcount += countprint("<ERRNO>999</ERRNO>\n<ERRSTAT>FAIL</ERRSTAT>\n");
3132 // $ofxcount += countprint("<ELIST>" . print_r($message,true) . "</ELIST\n");
3133  $ofxcount += countprint("</MESSAGE>\n");
3134  }
3135  $ofxcount += countprint("</OFXERR>\n");
3136 
3137  header("Content-length: $ofxcount");
3138 
3139  exit;
3140 }
3141 
3142 function sqlmdy($date) {
3143 
3144  if (strtolower($date) == "now" || strtolower($date) == "today") {
3145  $date = date("Y-m-d");
3146  }
3147  # only allow 0-9 and dash(-) or slash (/)
3148  # also allow dot (.) for milliseconds
3149  if (preg_match("/[^0-9\-\/\.]/", $date)) {
3150  return false;
3151  }
3152  if (preg_match("/[-\/]/", $date)) {
3153  list ($yy, $mm, $dd) = preg_split("/[-\/\.]/", $date);
3154  } else {
3155  $yy = substr($date, 0, 4);
3156  $mm = substr($date, 4, 2);
3157  $dd = substr($date, 6, 2);
3158  }
3159  $mm = sprintf("%02d", intval($mm));
3160  $dd = sprintf("%02d", intval($dd));
3161  if (strlen($yy) > 0 && strlen($yy) < 4) {
3162  $yy = ($yy < 70 ? 2000 + $yy : 1900 + $yy);
3163  }
3164  $yy = sprintf("%04d", intval($yy));
3165  if (checkdate($mm, $dd, $yy)) {
3166  return "${yy}${mm}${dd}";
3167  } else {
3168  return false;
3169  }
3170 }
3171 
3172 function countprint($string) {
3173  print $string;
3174  return strlen($string);
3175 }
3176 
3177 function clockwatch($tz, $CU, $MEMBER) {
3178  $localzone = 'US/Mountain';
3179  $tz = ("$tz" == "" ? "US/Mountain" : $tz);
3180  if (strpos("$tz", "/") === false)
3181  $tz = "US/$tz";
3182  global $dbh;
3183  $sqlll = "set time zone '$tz';
3184  select extract(epoch from CURRENT_TIMESTAMP(0)) -
3185  extract(epoch from substring(lastlogin,1,19)::timestamp)::integer
3186  from cuusers
3187  where cu='$CU' and user_name='$MEMBER';";
3188  $sthcl = db_query($sqlll, $dbh);
3189  if ($sthcl) {
3190  list($sincelast) = db_fetch_array($sthcl, 0);
3191  }
3192  $sthcl = db_query("set time zone '$localzone'", $dbh);
3193  return abs($sincelast);
3194 }
3195 
3196 function MFA_send_chall($dbh, $HB_ENV, $MC) {
3197 
3198 # sending all questions regardless of '1 random' setting for cu
3199 # updated 9/12 to recognize '1 random' setting
3200  # use odyssey function
3201  global $encoding;
3202 
3203  $MemberChallengeQuestions_ary=GetChallengeQuestions("CHALLENGE", $dbh, $HB_ENV, $MC, $HB_ENV['Cn']);
3204 
3205  $now = date('YmdHis');
3206  $mfa_resp = '<?xml version="1.0" encoding="' . $encoding . '"?>';
3207  $mfa_resp .="\n";
3208  $mfa_resp .= '<?OFX OFXHEADER="200" VERSION="211" SECURITY="NONE" OLDFILEUID="NONE" NEWFILEUID="NONE"?>';
3209  $mfa_resp .="\n<OFX>
3210 <SIGNONMSGSRSV1>
3211 <SONRS>
3212 <STATUS>
3213 <CODE>3000</CODE>
3214 <SEVERITY>ERROR</SEVERITY>
3215 </STATUS>
3216 <DTSERVER>$now</DTSERVER>
3217 <LANGUAGE>ENG</LANGUAGE>
3218 </SONRS>
3219 <MFACHALLENGETRNRS>
3220 <MFACHALLENGERS>\n";
3221 # force 'What email' as first challenge question
3222  $mfa_resp .= "<MFACHALLENGE>
3223 <MFAPHRASEID>MFA_E</MFAPHRASEID>
3224 <MFAPHRASELABEL>What email address is saved with this account?</MFAPHRASELABEL>
3225 </MFACHALLENGE>\n";
3226 # and now add mfa questions, if any were found
3227  if (count($MemberChallengeQuestions_ary)) {
3228  foreach ((array) $MemberChallengeQuestions_ary as $mfakey => $mfaitem) {
3229 
3230  $mfa_resp .= "<MFACHALLENGE>
3231 <MFAPHRASEID>MFA_{$mfaitem['cqid']}</MFAPHRASEID>
3232 <MFAPHRASELABEL>{$mfaitem['display']}</MFAPHRASELABEL>
3233 </MFACHALLENGE>\n";
3234  }
3235  }
3236  $mfa_resp .= "</MFACHALLENGERS>
3237 </MFACHALLENGETRNRS>
3238 </SIGNONMSGSRSV1>
3239 </OFX>";
3240 
3241  $ofxcount += countprint("$mfa_resp");
3242  header("Content-length: $ofxcount");
3243  exit;
3244 }
3245 
3246 function MFA_response($dbh, $HB_ENV, $inPost) {
3247  $fail = 0;
3248  $failreason = 0;
3249 
3250  $chcount = $HB_ENV['MFA']['mfacount']; # how many questions are in the db?
3251  $mfapost = MFA_resplist($inPost); # get list of MFA variables in the posted request (skips MFA_E)
3252  # update from mammoth - gets id and answers in array using Odyssey format
3253  $mfacount = count($mfapost); # how many MFA_ responses (excluding MFA_E) did we get?
3254  try {
3255  if ($mfacount < $HB_ENV['MFA']['mfacount'] && ($HB_ENV['Fset2'] & $GLOBALS['CU2_RANDOM_CHAL']) == 0) {
3256  # expected challenge questions and there aren't any, so fail
3257  $fail++;
3258  $failreason = $GLOBALS['MEM_LOGIN_FAILED_QST'];
3259  throw new Exception(__LINE__ . 'MFA Failed',$failreason);# expected chall ques and got none
3260  }
3261  # make sure savemail is set in HB_ENV
3262  if (strtolower($inPost['MFA_E']) !== strtolower($HB_ENV['savemail'])) {
3263  $fail++;
3264  $failreason = $GLOBALS['MEM_LOGIN_FAILED_EMAIL'];
3265  throw new Exception(__LINE__ . 'MFA Failed',$failreason);# email mismatch
3266  }
3267  /*
3268  * VALIDATE ANSWERS
3269  * IF savecqid has a value and CU configured for only one answer, then ONLY validate that answer
3270  *
3271  * chcount being greater than one MEANS the aryMfaQuest array contains an 'answers' key, is an array and has at least one value
3272  */
3273  $aryMfaAnswers = $HB_ENV['MFA']['answers']; # stored answers
3274  if (($HB_ENV['Fset2'] & $GLOBALS['CU2_RANDOM_CHAL']) == $GLOBALS['CU2_RANDOM_CHAL'] && $HB_ENV['MFA']['challenge'] > 0) {
3275  // * Set a single key array
3276  $mfaAnswerIdx = Array($HB_ENV['MFA']['challenge']);
3277  } else {
3278  // * Set an array of all the keys in answers
3279  $mfaAnswerIdx = array_keys($aryMfaAnswers);
3280  }
3281 
3282  // ** NOW EVALUATE THE ANSWERS
3283  # for each id in $mfaAnserIdx
3284 
3285  foreach (array_intersect_key($aryMfaAnswers, array_flip($mfaAnswerIdx)) as $qid => $qanswer) {
3286 // print "response - $response - db $qanswer - post " . $inPost["MFA_$qid"] . "<br>";
3287  if (strtolower(trim($qanswer)) != strtolower(trim($inPost["MFA_$qid"]))) {
3288  $fail++;
3289  $failreason = $GLOBALS['MEM_LOGIN_FAILED_QST'];
3290  throw new Exception(__LINE__ . "MFA $qid Failed",$failreason);# chall response mismatch
3291  }
3292  }
3293  } catch (Exception $e) {
3294  # logging handled at point of call - nothing to do here but fall through?
3295  }
3296  return (array($fail, $failreason));
3297 }
3298 
3299 function MFA_resplist($posted) {
3300  # examines the (sanitized!) array of posted values
3301  # returns list of MFA_ excluding MFA_E (email)
3302  $mfalist = array();
3303  foreach (array_keys($posted) as $rkey) {
3304  $m = strpos($rkey, 'MFA_');
3305  if ($m !== FALSE && $m == 0 && $rkey !== 'MFA_E') {
3306  $mfalist[] = array('cqid'=>substr($rkey,4),'cqanswer'=>$posted[$rkey]);
3307  }
3308  }
3309  return ($mfalist);
3310 }
3311 
3312 function MFA_defined($posted) {
3313  # returns a count of MFA_* in (sanitized) array of posted values
3314  $mfa = 0;
3315  foreach (array_keys($posted) as $rkey) {
3316  $m = strpos($rkey, 'MFA_');
3317  if ($m !== FALSE && $m == 0) {
3318  $mfa++;
3319  }
3320  }
3321  return ($mfa);
3322 }
3323 
3324 function ANS_list($arr) {
3325  $anslist = array();
3326  foreach (array_keys($arr) as $rkey) {
3327  $m = strpos($rkey, 'ANS_');
3328  if ($m !== FALSE && $m == 0) {
3329  $anslist[] = substr($rkey, 4);
3330  }
3331  }
3332  return ($anslist);
3333 }
3334 
3335 function Send_ResponseOK($CU, $MEMBER, $CAUTH, $SENDKEY, $MESSAGE, $V = 1) {
3336 # was sending <LASTUPDATE>" . $HB_ENV['lastupdate'] . "</LASTUPDATE>
3337 # but it was always empty as HB_ENV is neither passed in nor global
3338 # so took it out
3339  $now = date('YmdHis');
3340  global $encoding;
3341  if ($V == 1) {
3342  $upd_resp = '<?xml version="1.0" encoding="' . $encoding . '"?>';
3343  $upd_resp .="\n";
3344  $upd_resp .= '<?OFX OFXHEADER="200" VERSION="211" SECURITY="NONE" OLDFILEUID="NONE" NEWFILEUID="NONE"?>';
3345  $upd_resp .="\n<OFX>";
3346  $upd_resp .= "<SIGNONMSGSRSV1>\n<SONRS>";
3347  } else {
3348  $ofxcount += countprint("<OFXPOST>\n");
3349  }
3350  $upd_resp .= "<STATUS>
3351 <CODE>0</CODE>
3352 <SEVERITY>INFO</SEVERITY>
3353 <MESSAGE>
3354 <INFO>$MESSAGE</INFO>
3355 </MESSAGE>
3356 </STATUS>
3357 <DTSERVER>" . $now . "</DTSERVER>
3358 <MEMBER>$MEMBER</MEMBER>";
3359  if ($SENDKEY) {
3360  $apptoken = MakeUserkey($CU, $MEMBER, $CAUTH);
3361  $upd_resp .= "<USERKEY>$apptoken</USERKEY>\n";
3362  }
3363  if ($V == 1) {
3364 
3365  $upd_resp .= "</SONRS>
3366 </SIGNONMSGSRSV1>
3367 </OFX>";
3368  } else {
3369  $upd_resp .= "</OFXPOST>";
3370  }
3371 
3372  $ofxcount += countprint("$upd_resp");
3373  header("Content-length: $ofxcount");
3374  exit;
3375 }
3376 
3377 function Send_AllowedUpdate($CU, $MEMBER, $CAUTH) {
3378  global $dbh;
3379  global $HB_ENV;
3380  global $MC;
3381  global $encoding;
3382 
3383 
3384  $apptoken = MakeUserkey($CU, $MEMBER, $CAUTH);
3385 
3386  $upd_grace = $HB_ENV['Ffremain'];
3387  $upd_wait = ($upd_grace == 0 ? "You must update your credentials now." :
3388  "You must update your credentials within the next $upd_grace login" . ($upd_grace == 1 ? '.' : 's.') );
3389 
3390  $now = date('YmdHis');
3391  $upd_resp = '<?xml version="1.0" encoding="' . $encoding . '"?>';
3392  $upd_resp .="\n";
3393  $upd_resp .= '<?OFX OFXHEADER="200" VERSION="211" SECURITY="NONE" OLDFILEUID="NONE" NEWFILEUID="NONE"?>';
3394  $upd_resp .="\n<OFX>
3395 <SIGNONMSGSRSV1>
3396 <SONRS>
3397 <STATUS>
3398 <CODE>3110</CODE>
3399 <SEVERITY>INFO</SEVERITY>
3400 <SREQ>{$HB_ENV['forceupdate']}</SREQ>
3401 <UREQ>{$HB_ENV['requpdate']}</UREQ>
3402 </STATUS>
3403 <DTSERVER>$now</DTSERVER>
3404 <LANGUAGE>ENG</LANGUAGE>
3405 <MEMBER>{$HB_ENV['Uid']}</MEMBER>
3406 <USERKEY>$apptoken</USERKEY>
3407 </SONRS>
3408 <REQUPDTRNRS>
3409 <REQUPDRS>\n";
3410  if ($HB_ENV['forceupdate'] != 0) {
3411  $upd_resp .= "<UPDCANWAIT>$upd_grace</UPDCANWAIT>
3412  <UPDWAITPHRASE>$upd_wait</UPDWAITPHRASE>\n";
3413  }
3414  $upd_resp .= "<PASSWORD>
3415  <ALLOW>YES</ALLOW>
3416  <REQ>" . (($HB_ENV['forceupdate'] & 1) ? "YES" : "NO") . "</REQ>
3417 </PASSWORD>
3418 <EMAIL>
3419  <ALLOW>YES</ALLOW>
3420  <REQ>" . (($HB_ENV['forceupdate'] & 2) ? "YES" : "NO") . "</REQ>
3421  </EMAIL>
3422 <CHALLENGE>
3423  <ALLOW>" . ($HB_ENV['cver'] == 'F' ? 'YES' : 'NO') . "</ALLOW>
3424  <REQ>" . (($HB_ENV['forceupdate'] & 4) ? "YES" : "NO") . "</REQ>
3425 </CHALLENGE>
3426 <USERALIAS>
3427  <ALLOW>" . ($HB_ENV['alias'] == 'NONE' ? 'NO' : $HB_ENV['alias']) . "</ALLOW>
3428  <REQ>" . (($HB_ENV['forceupdate'] & 8) ? "YES" : "NO") . "</REQ>
3429  </USERALIAS>
3430  </REQUPDRS>
3431 </REQUPDTRNRS>
3432 </SIGNONMSGSRSV1>
3433 </OFX>";
3434 
3435  #header("Content-Type: application/x-ofx");
3436  $ofxcount += countprint("$upd_resp");
3437  header("Content-length: $ofxcount");
3438  exit;
3439 }
3440 
3441 function Send_ReqUpdate($CU, $MEMBER, $CAUTH) {
3442  global $dbh;
3443  global $HB_ENV;
3444  global $MC;
3445  global $encoding;
3446 
3447  $apptoken = MakeUserkey($CU, $MEMBER, $CAUTH);
3448 
3449  $upd_grace = $HB_ENV['Ffremain'];
3450  $upd_wait = ($upd_grace == 0 ? "You must update your credentials now." :
3451  "You must update your credentials within the next $upd_grace login" . ($upd_grace == 1 ? '.' : 's.') );
3452 
3453  $now = date('YmdHis');
3454  $upd_resp = '<?xml version="1.0" encoding="' . $encoding . '"?>';
3455  $upd_resp .="\n";
3456  $upd_resp .= '<?OFX OFXHEADER="200" VERSION="211" SECURITY="NONE" OLDFILEUID="NONE" NEWFILEUID="NONE"?>';
3457  $upd_resp .="\n<OFX>
3458 <SIGNONMSGSRSV1>
3459 <SONRS>
3460 <STATUS>
3461 <CODE>3100</CODE>
3462 <SEVERITY>INFO</SEVERITY>
3463 <SREQ>{$HB_ENV['forceupdate']}</SREQ>
3464 <UREQ>{$HB_ENV['requpdate']}</UREQ>
3465 </STATUS>
3466 <DTSERVER>$now</DTSERVER>
3467 <LANGUAGE>ENG</LANGUAGE>
3468 <MEMBER>{$HB_ENV['Uid']}</MEMBER>
3469 <USERKEY>$apptoken</USERKEY>
3470 </SONRS>
3471 <REQUPDTRNRS>
3472 <REQUPDRS>\n";
3473  if ($HB_ENV['forceupdate'] != 0 && $HB_ENV['requpdate'] == 0) {
3474  $upd_resp .= "<UPDCANWAIT>$upd_grace</UPDCANWAIT>
3475  <UPDWAITPHRASE>$upd_wait</UPDWAITPHRASE>\n";
3476  }
3477  if ((($HB_ENV['forceupdate'] & 4) == 4 && $HB_ENV['requpdate'] == 0) || ($HB_ENV['requpdate'] & 4) == 4) {
3478  # 2-factor and either force reset or not enough questions selected yet
3479  # Security Reset: send master list of challenge questions
3480  $upd_resp .= "<REQUPD>
3481 <UPDPHRASEID>CHALLENGE</UPDPHRASEID>
3482 <UPDCONFLABEL>This confidence word is used to identify and prevent phishing attempts when you access home banking through the web. It is not used in this app, but you are asked to set it now in case you later access your account through the web.</UPDCONFLABEL>
3483 <UPDCONFIDENCE>" . htmlentities($HB_ENV['confidence'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</UPDCONFIDENCE>
3484 <UPDPHRASECOUNT>" . $HB_ENV['cu_chgqst_count'] . "</UPDPHRASECOUNT>\n";
3485  if ($HB_ENV['cu_chgqst_count'] > 0) {
3486  $upd_resp .= "<UPDPHRASELABEL>Please select {$HB_ENV['cu_chgqst_count']} challenge questions.</UPDPHRASELABEL>\n";
3487  $upd_resp .= "<UPDCHOICELIST>\n";
3488  $questlist = GetChallengeQuestions("DISPLAY", $dbh, $HB_ENV);
3489  foreach ($questlist as $QstValue) {
3490  $upd_resp .= "<CHOICEITEM><CQID>{$QstValue['cqid']}</CQID>\n";
3491  $upd_resp .= "<CQTEXT>" . htmlentities($QstValue['display'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</CQTEXT>\n</CHOICEITEM>\n";
3492  }
3493  $upd_resp .= "</UPDCHOICELIST>\n";
3494  if (($HB_ENV['requpdate'] & 4) == 4) {
3495  # 'on-demand' update - send current selected questions/responses
3496  $upd_resp .= "<CURRSELECTED>\n";
3497  foreach ($HB_ENV['MFA']['answers'] as $quest_id => $quest_resp) {
3498  $upd_resp .= "<SELECTEDITEM><CQID>$quest_id</CQID>\n";
3499  $upd_resp .= "<CQRESP>" . htmlentities($quest_resp, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</CQRESP>\n</SELECTEDITEM>\n";
3500  }
3501  $upd_resp .= "</CURRSELECTED>\n";
3502  }
3503  }
3504  $upd_resp .= "</REQUPD>\n";
3505  }
3506  if ((($HB_ENV['forceupdate'] & 1) == 1 && $HB_ENV['requpdate'] == 0) || ($HB_ENV['requpdate'] & 1) == 1) {
3507  # Password
3508  $helpdoc = "pwdRules";
3509  $fragext = (trim($HB_ENV['Flang']) == "en_US" ? "" : "_" . substr($HB_ENV['Flang'], 0, strpos($HB_ENV['Flang'], "_")) );
3510  $helpdoc .= ($fragext > "" && is_readable("/home/{$HB_ENV['chome']}/public_html/{$helpdoc}{$fragext}.html") ? "{$fragext}.html" : ".html");
3511  if (is_readable("/home/{$HB_ENV['chome']}/public_html/$helpdoc")) {
3512  $helpdoc = "https://" . $_SERVER['SERVER_NAME'] . "/fi/{$HB_ENV['chome']}/$helpdoc";
3513  } else {
3514  $helpdoc = "https://" . $_SERVER['SERVER_NAME'] . dirname($_SERVER['PHP_SELF']) . "/$helpdoc";
3515  }
3516 
3517  $pwdRequires = Get_PwdRules($dbh, $HB_ENV);
3518  $upd_resp .= "<REQUPD>
3519 <UPDPHRASEID>PASSWORD</UPDPHRASEID>
3520 <UPDPHRASELABEL>Please select a new password.</UPDPHRASELABEL>
3521 <PWDRULESLINK>" . htmlentities($helpdoc, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</PWDRULESLINK>
3522 <PWDRULESLABEL>I have read the Recommended Password Guidelines</PWDRULESLABEL>
3523 <PWDADVLABEL>Recommended Guidelines</PWDADVLABEL>
3524 <PWDREQUIRES>\n";
3525  foreach ($pwdRequires as $pwdkey => $pwdval) {
3526  $pwdkey = strtoupper($pwdkey);
3527  $upd_resp .= "<$pwdkey>$pwdval</$pwdkey>\n";
3528  }
3529 // if ($pwdRequires['spec'] > 0) {
3530  $pwdSpecChar = Get_PwdSpecialCharacters();
3531  $upd_resp .= "<PWDSPECIALCHARS>" . htmlspecialchars($pwdSpecChar, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</PWDSPECIALCHARS>\n";
3532 // }
3533  $upd_resp .= "</PWDREQUIRES>
3534 </REQUPD>\n";
3535  }
3536  if ((($HB_ENV['forceupdate'] & 6) > 0 && $HB_ENV['requpdate'] == 0) || ($HB_ENV['requpdate'] & 2) == 2) {
3537  # verify email is set or email is empty,
3538  # or we are sending the CHALLENGE set so include email with it (apps treat email as extra challenge question)
3539  $upd_resp .= "<REQUPD>
3540 <UPDPHRASEID>EMAIL</UPDPHRASEID>
3541 <UPDPHRASELABEL>Please provide your email address.</UPDPHRASELABEL>
3542 <CURRENTEMAIL>" . htmlentities($HB_ENV['Ml'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</CURRENTEMAIL>
3543 <CURRENTOPTIN>{$HB_ENV['egenl_flag']}</CURRENTOPTIN>
3544 <OPTIN_PHRASE>" . $MC->msg('Yes Email List') . "</OPTIN_PHRASE>
3545 </REQUPD>\n";
3546  }
3547  if ((($HB_ENV['forceupdate'] & 8) == 8 && $HB_ENV['requpdate'] == 0) || ($HB_ENV['requpdate'] & 8) == 8) {
3548  # user_alias
3549  $maymust = (($HB_ENV['Fset2'] & $GLOBALS['CU2_ALIAS_REQ']) == $GLOBALS['CU2_ALIAS_REQ'] ? 'must' : 'may');
3550  $aliaslabel = $MC->combo_msg('Username Set', 0, '#MAYMUST#', "$maymust");
3551  $upd_resp .= "<REQUPD>
3552 <UPDPHRASEID>USERALIAS</UPDPHRASEID>
3553 <UPDPHRASEREQ>" .
3554  ($HB_ENV['alias'] == 'NONE' ? 'NO' : $HB_ENV['alias']) .
3555  "</UPDPHRASEREQ>
3556 <UPDPHRASELABEL>" . htmlentities($aliaslabel, ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</UPDPHRASELABEL>\n";
3557  if (($HB_ENV['requpdate'] & 8) == 8) {
3558  # 'on-demand' update - send current user alias
3559  $upd_resp .= "<CURRENTALIAS>" . htmlentities($HB_ENV['useralias'], ENT_NOQUOTES | ENT_XML1, 'UTF-8', FALSE) . "</CURRENTALIAS>\n";
3560  }
3561  $upd_resp .= "</REQUPD>\n";
3562  }
3563 
3564  $upd_resp .= "</REQUPDRS>
3565 </REQUPDTRNRS>
3566 </SIGNONMSGSRSV1>
3567 </OFX>";
3568 
3569 
3570  #header("Content-Type: application/x-ofx");
3571  $ofxcount += countprint("$upd_resp");
3572  header("Content-length: $ofxcount");
3573  exit;
3574 }
3575 
3576 function MakeUserkey($CU, $MEMBER, $CAUTH) {
3577  global $apptokenkey;
3578  $appexpires = time() + 900; # 15 minutes
3579  $apphash = MD5($apptokenkey . MD5(join(':', array($apptokenkey, $appexpires, $CU, $MEMBER, $CAUTH))));
3580  # $mytoken="H=$hash&E=$expires&A=$cauth_member&C=$current_member";
3581 
3582  $apptoken = urlencode("H=$apphash&E=$appexpires&A=$MEMBER&C=$CAUTH");
3583  return $apptoken;
3584 }
3585 
3586 function CleanWordQuotes($instring) {
3587  /**
3588  # try to clean up the funky quote characters cut-n-paste from MS Word
3589  * orignal code had the following converions:
3590  * char codes entity codes
3591  * �? 212 & 145 to 8216 curly left single quote
3592  * �? 213 & 146 to 8217 apostrophe, curly right single quote
3593  * ⤽ 210 & 147 to 8220 curly left double quote
3594  * ⤝ 211 & 148 to 8221 curly right double quote
3595  * �? 209 & 151 to 8212 em dash
3596  * �? 208 & 150 to 8211 en dash
3597  * �? 201 & 133 to 8230 ellipsis
3598  *
3599  * replacing with character codes didn't seem to work
3600  * android showed the funky 'a' values above instead of expected char
3601  * maybe due to ISO-8859 vs UTF-8 issues?
3602  * replaced with simple ascii instead, and that appears to work
3603  */
3604  $search = array(
3605  chr(145),
3606  chr(146),
3607  chr(147),
3608  chr(148),
3609  chr(151),
3610  chr(150),
3611  chr(133)
3612  );
3613 
3614  $replace = array(
3615  '\'',
3616  '\'',
3617  '"',
3618  '"',
3619  '-',
3620  '-',
3621  '&#8230;'
3622  );
3623 
3624  $instring = str_replace($search, $replace, $instring);
3625  return $instring;
3626 }
3627 
3628 function Load_HB_ENV($dbh, $CU, $MEMBER, $USERPASS, $CAUTH, &$HB_ENV, $CFGFLAG=0) {
3629  // ** First thing is First Check the username
3630  $username = trim($MEMBER);
3631  $live = $HB_ENV['live'];
3632 
3633  # on first (method MFA) login, MEMBER will have username
3634  # after that, (method SSO) MEMBER will have USERID
3635  # and if using SWJUMP to view alternate account...? Don't know yet
3636 
3637 
3638 
3639  if ($HB_ENV['AuthMode'] == 'MFA') {
3640  # AuthMode=MFA
3641  $qby = "cuuser.user_name ilike '" . prep_save($MEMBER) . "' ";
3642  } elseif ($HB_ENV['AuthMode'] == 'SSO') {
3643  $qby = "cuuser.user_id = $MEMBER ";
3644  } else {
3645  # figure out the SWJUMP
3646  }
3647  if (preg_match("/\D/", $MEMBER) || $HB_ENV['AuthMode'] == 'MFA') {
3648  # username contains non-digits or this is an MFA login
3649  $qby = "cuuser.user_name ilike '" . prep_save($MEMBER) . "' ";
3650  } else {
3651  # SSO login
3652  $qby = "cuuser.user_id = $MEMBER ";
3653  }
3654 
3655 
3656  // ** QUERY THE USER INFORMATION
3657  $sqluser = "SELECT cuuser.user_id as user_id, trim(cuuser.user_name) as user_name, trim(cuuser.passwd) as password, forcechange, forceremain, failedremain,
3658  pwchange, trim(email) as email, egenl_flag, confidence, cuuser.user_id as cuuser_id, cuuser.group_id as cuuser_group_id,
3659  lastlogin, failedlogin, msg_tx, userflags & {$GLOBALS['MEM_FORCE_RESET']}::int4 as mem_force_reset, userflags,
3660  coalesce(challenge_quest_id,0) as challenge_quest_id, trim(cuadmin.rt) as rt,
3661  cuadmin.flagset, cuadmin.flagset2, cuadmin.flagset3, cuadmin.livewait, trim(cuadmin.lastupdate) as lastupdate,
3662  trim(cuadmin.pname) as pname, histdays, gracelimit, trmemomaxlen, mfaquest, primary_account
3663 
3664  FROM {$CU}user as cuuser
3665  JOIN cuadmin on cuadmin.cu = '" . prep_save($CU) . "'
3666  WHERE $qby ";
3667 
3668  $mbr_sth = db_query($sqluser, $dbh);
3669  if (db_num_rows($mbr_sth) == 0) {
3670  $insflag = 1;
3671  } else {
3672  $insflag = 0;
3673  $drow = db_fetch_array($mbr_sth, 0);
3674 // cuuser.user_id as user_id, $saveuid
3675 // trim(cuuser.user_name) as user_name,$saveuser
3676 // trim(cuuser.passwd) as passwd, $savepass
3677 // forcechange, $fchange
3678 // forceremain, $fremain
3679 // failedremain,$failedremain
3680 // pwchange, $pchange
3681 // trim(email) as email, $savemail
3682 // confidence, $saveword
3683 // cuuser.user_id as cuuser_id, $cuuser_id
3684 // cuuser.group_id as cuuser_group_id,$cuuser_group_id
3685 // lastlogin, $llog
3686 // failedlogin, $flog
3687 // msg_tx, $msg_tx
3688 // userflags & {$GLOBALS['MEM_FORCE_RESET']}::int4 as mem_force_reset, $freset
3689 // userflags,$saveuserflags
3690 // coalesce(challenge_quest_id,0) as challenge_quest_id,$savecqid
3691 // cuadmin.flagset, $flagset
3692 // cuadmin.flagset2, $flagset2
3693 // cuadmin.flagset3, $flagset3
3694 // cuadmin.livewait, $livewait
3695 // trim(cuadmin.lastupdate) as lastupdate,$lastupdate
3696 // trim(cuadmin.pname) as pname, $pname
3697 // histdays, $fhdays
3698 // gracelimit, $grace
3699 // trmemomaxlen, $trmemomaxlen
3700 // mfaquest, $dbMfaQuest
3701 // primary_account $userPrimaryAcct
3702 
3703  }
3704 
3705 #If live and MFA login and we have a USERPASS and MEMBER is all digits and (no user record or password == 'NULL PASSWORD')
3706  if ($live && $HB_ENV['AuthMode'] == 'MFA' && trim($USERPASS) > '' && (db_num_rows($mbr_sth) == 0 || $drow['password'] == 'NULL PASSWORD') &&
3707  !(preg_match("/\D/", $MEMBER))) {
3708 # no cuuser record: # try to get user info from the core cu
3709 # run the query again if the fetch was successful
3710 
3711  list ($status, $asofdate, $reason) = fetch_user($CU, $MEMBER, $USERPASS, $insflag);
3712  if ($status == "100" || $status == "101") {
3713  // ** throtlpkt inserted a user record, re-run the query to get it
3714  $mbr_sth = db_query($sqluser, $dbh);
3715  } else {
3716  # didn't get good data - notify HB_ENV
3717  $HB_ENV['core-status'] = $status;
3718  }
3719 # If live and MFA login and we have a USERPASS and MEMBER contains NON-Digits and at least 5 chars and password=NULL PASSWORD and alias is allowed or required
3720 # try to fetch from the core using the primary account from the NULL PASSWORD rec.
3721 
3722  } elseif ($live && $HB_ENV['AuthMode'] == 'MFA' && trim($USERPASS) != '' && $drow['user_name'] != ''
3723  && (preg_match("/^[a-zA-Z][^\\`,\"\s;]*$/", $MEMBER) && strlen($MEMBER) > 5)
3724  && (db_num_rows($mbr_sth) > 0) && $drow['password'] == 'NULL PASSWORD' &&
3725  ( ($drow['flagset2'] & $GLOBALS['CU2_ALIAS_OK']) || ($drow['flagset2'] & $GLOBALS['CU2_ALIAS_REQ']) )
3726  ) {
3727  /*
3728  * for OFXRequest: test for check_alias_format($MEMBER)
3729  * replaced with (preg_match("/^[a-zA-Z][^\\`,\"\s;]*$/", $MEMBER) && strlen($MEMBER) > 5)
3730  * since check_alias_format function is defined in cu_credentials which won't work from the apps
3731  */
3732 
3733  /* FETCH USER FROM CORE USING SAVED MEMBER NUMBER */
3734  # this will need to use primary account instead of $MEMBER?
3735  # OR fetch_user updated to accommodate user_name?
3736  # OR this feature doesn't work this way any more?
3737 
3738  list ($status, $asofdate, $reason) = fetch_user($CU, $drow['primary_account'], $USERPASS, $insflag);
3739  if ($status == "100" || $status == "101") {
3740  // ** throtlpkt inserted a user record, re-run the query to get it
3741  $mbr_sth = db_query($sqluser, $dbh);
3742  } else {
3743  # didn't get good data - notify HB_ENV
3744  $HB_ENV['core-status'] = $status;
3745  }
3746  }
3747 
3748  $drow = db_fetch_array($mbr_sth, 0);
3749 
3750  $HB_ENV['Cu'] = $CU;
3751  $HB_ENV['cu'] = $CU;
3752  $HB_ENV['chome'] = strtolower($CU);
3753 // $HB_ENV['homebankingpath'] = "http://" . $_SERVER['HTTP_HOST'] . dirname($_SERVER['SCRIPT_NAME']);
3754 // $HB_ENV['cuhost'] = array_shift((explode(".", $_SERVER['SERVER_NAME'])));
3755 // $HB_ENV['cupublic'] = "https://" . $_SERVER['HTTP_HOST'] . "/fi/" . $HB_ENV['chome'];
3756 // $HB_ENV['Cn'] = $drow['user_name'];
3757  $HB_ENV['Cn'] = $drow['user_name'];
3758  $HB_ENV['Cauth'] = trim($drow['primary_account']);
3759  # some calls use Uid, some use user_id so set both
3760  $HB_ENV['Uid'] = $drow['user_id'];
3761  $HB_ENV['user_id'] = $drow['user_id'];
3762 // $HB_ENV['useralias'] = $drow['user_alias']; # obsolete use username? or drop?
3763  # some calls use username, some use user_name, so set both
3764  $HB_ENV['username'] = $drow['user_name'];
3765  $HB_ENV['user_name'] = $drow['user_name'];
3766  $HB_ENV['confidence'] = $drow['confidence'];
3767  $HB_ENV['Ml'] = urlencode($drow['email']);
3768  $HB_ENV['savemail'] = $drow['email'];
3769  $HB_ENV['egenl_flag'] = urlencode($drow['egenl_flag']);
3770  $HB_ENV['rt'] = $drow['rt'];
3771  $HB_ENV['tz'] = $drow['tz'];
3772  $HB_ENV['orgname'] = $drow['orgname'];
3773  $HB_ENV['offline'] = (trim($drow['offlinestat']) == '' ? 'N' : $drow['offlinestat']);
3774  $HB_ENV['offlineblurb'] = strip_tags($drow['offlineblurb']);
3775  $HB_ENV['password'] = $drow['password'];
3776  $HB_ENV['userflags'] = $drow['userflags'];
3777  $HB_ENV['failedremain'] = $drow['failedremain'];
3778  $HB_ENV['Ffchg'] = $drow['forcechange'];
3779  $HB_ENV['Ffremain'] = $drow['forceremain'];
3780  $HB_ENV['dbforceremain'] = $drow['forceremain'];
3781  $HB_ENV['Ffreset'] = (is_null($drow['mem_force_reset']) ? 0 : $drow['mem_force_reset']);
3782 // $HB_ENV['Fmsg_tx'] = ($drow['msg_tx'] | $CFGFLAG); # this would add any CFGFLAG passed to msg_tx only
3783  $HB_ENV['Fmsg_tx'] = (is_null($drow['msg_tx']) ? 0 : $drow['msg_tx']);
3784  $HB_ENV['cfgflag'] = $CFGFLAG; # set cfgflag if CFGFLAG if passed
3785  $HB_ENV['Fverifyml'] = ($drow['msg_tx'] & 512);
3786  $HB_ENV['Fhdays'] =(is_null($drow['histdays']) ? 0 : $drow['histdays']);
3787  $HB_ENV['Fset'] = (is_null($drow['flagset']) ? 0 : $drow['flagset']);
3788  $HB_ENV['Fset2'] = (is_null($drow['flagset2']) ? 0 : $drow['flagset2']);
3789  $HB_ENV['Fset3'] = (is_null($drow['flagset3']) ? 0 : $drow['flagset3']);
3790  $HB_ENV['cver'] = $drow['cookie_ver'];
3791  $HB_ENV['trmemomaxlen'] = $drow['trmemomaxlen'];
3792 // $HB_ENV['fetcher'] = $drow['liveserver'];
3793  # mammoth data calls use Clw; odyssey switched to livewait so define both
3794  $HB_ENV['Clw'] = ((is_null($drow['livewait']) || $drow['livewait'] == 0) ? 300 : $drow['livewait']);
3795  $HB_ENV['livewait'] = ((is_null($drow['livewait']) || $drow['livewait'] == 0) ? 300 : $drow['livewait']);
3796  $HB_ENV['lastupdate'] = (empty($drow['lastupdate']) ? "Unknown" : urlencode(trim($drow['lastupdate'])));
3797  $HB_ENV['pwchange'] = (is_null($drow['pwchange']) ? date('Ymd') : $drow['pchange']);
3798  $HB_ENV['employee'] = $drow['employee'];
3799  $HB_ENV['HCUPOST'] = array(); # set empty parameter array
3800  $HB_ENV['cu_chgqst_count'] = intval($drow['min_chlng_qst']);
3801  if ($drow['flagset2'] & $GLOBALS['CU2_ALIAS_REQ']) {
3802  $alias = 'REQUIRE';
3803  } elseif ($drow['flagset2'] & $GLOBALS['CU2_ALIAS_OK']) {
3804  $alias = 'ALLOW';
3805  } else {
3806  $alias = 'NONE';
3807  }
3808  $HB_ENV['alias'] = $alias;
3809 
3810  // * Create the MFA Quest Array (or set empty if Legacy, which shouldn't happen in Odyssey...)
3811  $HB_ENV['MFA'] = ($HB_ENV['cver'] == 'L' ? array() : HCU_JsonDecode($drow['mfaquest']));
3812 
3813  $FORCEUPDATE = 0;
3814  if ($HB_ENV['Ffchg'] == 'Y') {
3815  $FORCEUPDATE += 1; #password
3816  }
3817  if ($HB_ENV['Fverifyml'] == 512 || ($HB_ENV['cver'] == 'F' && $HB_ENV['Ml'] == '')) {
3818  $FORCEUPDATE += 2; # email
3819  }
3820  if ($HB_ENV['cver'] == 'F' &&
3821  ($HB_ENV['Ffreset'] == 2 || $HB_ENV['confidence'] == "" ||
3822  sizeof($HB_ENV['MFA']['answers']) < $HB_ENV['cu_chgqst_count'] )
3823  ) {
3824  $FORCEUPDATE += 4; #challenge questions
3825  }
3826  if ($HB_ENV['alias'] == 'REQUIRE' && $HB_ENV['useralias'] == "") {
3827  $FORCEUPDATE += 8;
3828  }
3829 
3830  $HB_ENV['forceupdate'] = $FORCEUPDATE;
3831  $HB_ENV['allowupdate'] = 3; # password and email update always allowed
3832  $HB_ENV['allowupdate'] += ($HB_ENV['cver'] == 'F' ? 4 : 0);
3833  $HB_ENV['allowupdate'] += ($HB_ENV['alias'] == 'NONE' ? 0 : 8);
3834 #
3835  $HB_ENV['requpdate'] = 0; # assume at first this is not a 'getsettings' request
3836 # eventually this will come from a new column in cuadmin
3837 # but for now....
3838  $HB_ENV['TicketExpires'] = $GLOBALS['TicketExpires'];
3839  $HB_ENV['AppTimeout'] = intval($HB_ENV['SYSENV']['ticket']['expires'] * .8);
3840  $lastlogin = $drow['lastlogin'];
3841  $HB_ENV['Fplog'] = ($lastlogin == 'None' ? '' : (strftime("%D %R", mktime(
3842  substr($lastlogin, 11, 2), substr($lastlogin, 14, 2), substr($lastlogin, 17, 2), substr($lastlogin, 5, 2), substr($lastlogin, 8, 2), substr($lastlogin, 0, 4)))));
3843  $failedlogin = $drow['failedlogin'];
3844  $HB_ENV['Fflog'] = ($failedlogin == 'None' ? '' : (strftime("%D %R", mktime(
3845  substr($failedlogin, 11, 2), substr($failedlogin, 14, 2), substr($failedlogin, 17, 2), substr($failedlogin, 5, 2), substr($failedlogin, 8, 2), substr($failedlogin, 0, 4)))));
3846 
3847  $pname = (empty($drow['pname']) ? "Home Banking" : $drow['pname']);
3848  $HB_ENV['product'] = $pname;
3849  $HB_ENV['secret'] = GetSecretKeyString();
3850 }