├── .gitattributes ├── .gitignore ├── LICENSE.txt ├── LICENSE_ALv2.txt ├── LICENSE_BOL.txt ├── LICENSE_GNU_AGPLv3.txt ├── LICENSE_GNU_APL.txt ├── README.txt ├── client.inc ├── client.php ├── client ├── aero.css ├── aqua.css ├── flat.css ├── icon.ico ├── icon.png ├── light.css ├── luna.css ├── modern.css ├── precious.css ├── rule.css ├── spartan.css ├── standard.css ├── template.html └── template.js ├── common.inc ├── common ├── fi.xml ├── ofx.xml └── pdf.dat ├── cryptojs.js ├── encoding.js ├── index.php ├── index.txt ├── log └── .gitkeep ├── php.ini ├── php_mac.ini ├── server.inc ├── server.php ├── server ├── auwallet.inc ├── benefit401k.inc ├── btmu.inc ├── chocom.inc ├── dccard.inc ├── esaifu.inc ├── jaccscard.inc ├── jist.inc ├── jpbank.inc ├── kabucom.inc ├── mhbk.inc ├── mobilesuica.inc ├── mufgcard.inc ├── nanaco.inc ├── netbk.inc ├── nrkn.inc ├── osaifuponta.inc ├── rakutensec.inc ├── saisoncard.inc ├── sbisec.inc ├── smbc.inc ├── smbccard.inc ├── smcprepaide.inc ├── surugavisacard.inc ├── viewcard.inc └── waon.inc └── start_php.bat /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | 19 | *.bat eol=crlf 20 | *.ini eol=crlf 21 | *.xml eol=crlf 22 | *.dat eol=crlf 23 | 24 | *.inc linguist-language=PHP 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Project ignored files 2 | log/*.log 3 | 4 | # Windows image file caches 5 | Thumbs.db 6 | ehthumbs.db 7 | 8 | # Folder config file 9 | Desktop.ini 10 | 11 | # Recycle Bin used on file shares 12 | $RECYCLE.BIN/ 13 | 14 | # Windows Installer files 15 | *.cab 16 | *.msi 17 | *.msm 18 | *.msp 19 | 20 | # Windows shortcuts 21 | *.lnk 22 | 23 | # ========================= 24 | # Operating System Files 25 | # ========================= 26 | 27 | # OSX 28 | # ========================= 29 | 30 | .DS_Store 31 | .AppleDouble 32 | .LSOverride 33 | 34 | # Thumbnails 35 | ._* 36 | 37 | # Files that might appear on external disk 38 | .Spotlight-V100 39 | .Trashes 40 | 41 | # Directories potentially created on remote AFP share 42 | .AppleDB 43 | .AppleDesktop 44 | Network Trash Folder 45 | Temporary Items 46 | .apdisk 47 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | マネーサウンドは、GNU AFFERO GENERAL PUBLIC LICENSE Version 3、および 2 | Beatrek Origin Licenseのデュアルライセンスに基づき提供いたします。 3 | 4 | ライセンスの詳細については、./LICENSE_GNU_AGPLv3.txt、および./LICENSE_BOL.txtを 5 | ご参照ください。 6 | 7 | 8 | ./server.*, ./server/*.*: 9 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 10 | 上記ファイルは、GNU AFFERO GENERAL PUBLIC LICENSE Version 3、および 11 | Beatrek Origin Licenseのデュアルライセンスに基づき提供いたします。 12 | 13 | ライセンスの詳細については、./LICENSE_GNU_AGPLv3.txt、および./LICENSE_BOL.txtを 14 | ご参照ください。 15 | 16 | 17 | ./client.*, ./client/*.*: 18 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 19 | 上記ファイルは、Apache License Version 2.0、およびBeatrek Origin Licenseの 20 | デュアルライセンスに基づき提供いたします。 21 | 22 | ライセンスの詳細については、./LICENSE_ALv2.txt、および./LICENSE_BOL.txtをご参照 23 | ください。 24 | 25 | 26 | ./common.*, ./common/*.*, ./index.*, ./README.txt, ./php*.ini, ./start_php.bat: 27 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 28 | 上記ファイルは、GNU All-Permissive License、およびBeatrek Origin Licenseの 29 | デュアルライセンスに基づき提供いたします。 30 | 31 | ライセンスの詳細については、./LICENSE_GNU_APL.txt、および./LICENSE_BOL.txtを 32 | ご参照ください。 33 | 34 | 35 | ./cryptojs.js: 36 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 37 | (c) 2009-2013 by Jeff Mott. All rights reserved. 38 | 39 | Redistribution and use in source and binary forms, with or without 40 | modification, are permitted provided that the following conditions 41 | are met: 42 | 43 | * Redistributions of source code must retain the above copyright 44 | notice, this list of conditions, and the following disclaimer. 45 | * Redistributions in binary form must reproduce the above copyright 46 | notice, this list of conditions, and the following disclaimer in 47 | the documentation or other materials provided with the distribution. 48 | * Neither the name CryptoJS nor the names of its contributors 49 | may be used to endorse or promote products derived from this software 50 | without specific prior written permission. 51 | 52 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 53 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 54 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 55 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 56 | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 57 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 58 | TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 59 | PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 60 | LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 61 | NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 62 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 63 | 64 | 65 | ./encoding.js: 66 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 67 | The MIT License (MIT) 68 | 69 | Copyright (c) 2013-2015 polygon planet 70 | 71 | Permission is hereby granted, free of charge, to any person obtaining a copy 72 | of this software and associated documentation files (the "Software"), to deal 73 | in the Software without restriction, including without limitation the rights 74 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 75 | copies of the Software, and to permit persons to whom the Software is 76 | furnished to do so, subject to the following conditions: 77 | 78 | The above copyright notice and this permission notice shall be included in 79 | all copies or substantial portions of the Software. 80 | 81 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 82 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 83 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 84 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 85 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 86 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 87 | THE SOFTWARE. 88 | 89 | -------------------------------------------------------------------------------- /LICENSE_ALv2.txt: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /LICENSE_BOL.txt: -------------------------------------------------------------------------------- 1 | Beatrek Origin License 2 | 3 | (準拠法) 4 | 本ライセンスの解釈、および適用は、日本国法に準拠するものとします。 5 | 6 | (著作権) 7 | 本ライセンスが適用されるソースコードの著作権は、特に記載のない限り、 8 | 著作者であるアウター・ガイ事務所に帰属するものであり、日本国著作権法、 9 | 国際条約、およびその他の法律によって保護されています。 10 | 明示的に付与されていないすべての権利は、著作者により留保されています。 11 | 12 | (適用の除外) 13 | 本ライセンスが適用されるソースコードのうち、アウター・ガイ事務所以外の 14 | 者が著作者であるソースコード部分については、本ライセンスが適用されない 15 | ものとします。 16 | 17 | (使用、および利用の制限) 18 | 本ライセンスが適用されるソースコードは、著作者が何らの制約を受ける 19 | ことなく、著作者の自己の技術を他に転用する目的で、現状有姿のまま 20 | 供するものであり、お客様が事前に著作者の文書による許諾を得た場合を 21 | 除き、かかる目的、あるいはその他法律によって明示的に認められる範囲を 22 | 超えて、かかるソースコードを、いかなる方法によっても使用、および利用 23 | することはできません。 24 | 25 | (免責) 26 | 著作者は、本ライセンスが適用されるソースコードに関して、明示的、 27 | あるいは黙示的を問わず、一切保証しません。 28 | 著作者は、本ライセンスが適用されるソースコードの使用、または 29 | 使用不能により生じたあらゆる損失および損害について、著作者が予見し、 30 | または予見し得た場合を含め、いかなる場合も一切責任を負わないものと 31 | します。 32 | 33 | -------------------------------------------------------------------------------- /LICENSE_GNU_APL.txt: -------------------------------------------------------------------------------- 1 | GNU All-Permissive License 2 | 3 | Copying and distribution of this file, with or without modification, 4 | are permitted in any medium without royalty provided the copyright 5 | notice and this notice are preserved. This file is offered as-is, 6 | without any warranty. 7 | 8 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | マネーサウンド:OFX/CSV/PDF出力対応のアカウントアグリゲーションサービス 2 | 3 | マネーサウンドは、対応金融機関の口座情報一覧を取得するアカウントアグリゲーションサービスです。取得した明細データは、OFX/CSV対応ソフト・サービスに取り込めるほか、PDFでの保存や、口座一覧の印刷にも対応しています。 4 | 5 | マネーサウンドを実行するには、PHPバージョン5.4以降が必要です。 6 | 7 | ソースコード(GitHub) 8 | https://github.com/outerguy/moneysound 9 | 10 | プロジェクトサイト(Beatrek) 11 | https://www.beatrek.com/home/moneysound.htm 12 | 13 | Beatrek OFX仕様書(Beatrek) 14 | https://www.beatrek.com/home/ofxspec.htm 15 | 16 | -------------------------------------------------------------------------------- /client.inc: -------------------------------------------------------------------------------- 1 | 18 | -------------------------------------------------------------------------------- /client.php: -------------------------------------------------------------------------------- 1 | [\w\W]*<\/OFX>[\r\n]+?/", "", $ofx)), "\"\r\n") . "\\r\\n"; 23 | 24 | // PDFを文字列形式に変換する 25 | $pdftext = addcslashes($pdf, "\"\r\n"); 26 | 27 | // XMLファイルに定義されている金融機関をJSON形式に変換する 28 | $fis = get_fi_settings(); 29 | $filist = trim(json_encode($fis, JSON_UNESCAPED_UNICODE + JSON_UNESCAPED_SLASHES)); 30 | 31 | // 埋め込み文字列を置換する 32 | $js = str_replace(array("", "", "", "", "", "\"\"", "\"\""), array(ENV_PRODUCT_CLIENT_VERSION, ENV_PRODUCT_VERSION, ENV_PRODUCT_FAMILY, $ofxhead, $pdftext, $filist, (ENV_BOOL_DEBUG == true? "true": "false")), $js); 33 | 34 | // レスポンスを返す 35 | header(get_http_status(ENV_NUM_STATUS_SUCCESS)); 36 | header("Cache-Control: no-cache"); 37 | header("Pragma: no-cache"); 38 | header("Content-Type: text/javascript; charset=UTF-8"); 39 | header("Content-Length: " . strlen($js)); 40 | echo $js; 41 | 42 | ?> 43 | -------------------------------------------------------------------------------- /client/aero.css: -------------------------------------------------------------------------------- 1 | @media screen { 2 | * { 3 | font-family: "Meiryo UI", "メイリオ", "Meiryo", sans-serif; 4 | } 5 | body { 6 | color: #000000; 7 | background: #FFFFFF; 8 | font-size: 85%; 9 | } 10 | hr, h1 { 11 | display: none; 12 | } 13 | header.bg, nav.bg, section.bg, footer.bg { 14 | filter: blur(2px); 15 | -webkit-filter: blur(2px); 16 | } 17 | nav { 18 | margin: 20px 0px 20px 0px; 19 | } 20 | aside { 21 | color: inherit; 22 | background: #CCCCCC; 23 | background: rgba(204, 204, 204, 0.5); 24 | } 25 | footer { 26 | margin: 20px 0px 0px 0px; 27 | } 28 | form#modal { 29 | border: solid 1px #000000; 30 | border-radius: 7px 7px 6px 6px; 31 | padding: 0px; 32 | box-shadow: 3px 3px 30px 0px rgba(0, 0, 0, 0.9); 33 | color: inherit; 34 | background: transparent; 35 | background: transparent linear-gradient(to bottom, rgba(204, 204, 204, 0.8), rgba(153, 153, 153, 0.6) 30px, rgba(255, 255, 255, 0.8) 40%, rgba(153, 153, 153, 0.6) 40%, rgba(153, 153, 153, 0.8)); 36 | } 37 | h3#modalhead { 38 | padding: 5px 10px 5px 10px; 39 | margin: 0px; 40 | color: #000000; 41 | background: transparent; 42 | text-shadow: 0px 0px 10px #EEEEEE, -5px 0px 5px #EEEEEE, 5px 0px 5px #EEEEEE; 43 | text-align: left; 44 | text-indent: 0px; 45 | font-size: 95%; 46 | font-weight: normal; 47 | line-height: 140%; 48 | letter-spacing: 0px; 49 | } 50 | div#modalbody { 51 | border: solid #666666; 52 | border-width: 1px 1px 0px 1px; 53 | padding: 10px; 54 | margin: 0px 5px 0px 5px; 55 | color: inherit; 56 | background: #FFFFFF; 57 | } 58 | div#modalfoot { 59 | border: solid #666666; 60 | border-width: 0px 1px 1px 1px; 61 | padding: 0px 10px 10px 10px; 62 | margin: 0px 5px 5px 5px; 63 | color: inherit; 64 | background: #FFFFFF; 65 | } 66 | table { 67 | border: solid 1px #999999; 68 | padding: 0px; 69 | margin: 0px auto 0px auto; 70 | } 71 | thead, tfoot { 72 | color: #000000; 73 | background: #EEEEEE; 74 | } 75 | tbody { 76 | color: inherit; 77 | background: #FFFFFF; 78 | } 79 | tbody.pending { 80 | color: inherit; 81 | background: #00CC33; 82 | } 83 | tbody.ready { 84 | color: #888888; 85 | background: #FFFFFF; 86 | } 87 | tbody.error { 88 | color: #FF0000; 89 | background: #FFFFFF; 90 | } 91 | caption { 92 | border: solid #333333; 93 | border-width: 1px 1px 0px 1px; 94 | border-radius: 7px 7px 0px 0px; 95 | padding: 5px 10px 5px 10px; 96 | color: #FFFFFF; 97 | background: #666666; 98 | background: #666666 linear-gradient(to bottom, #777777, #444444 50%, #222222 50%, #111111); 99 | font-size: 85%; 100 | font-weight: bold; 101 | line-height: 150%; 102 | } 103 | th, td { 104 | border: solid #999999; 105 | border-width: 1px 0px 1px 0px; 106 | } 107 | th { 108 | font-weight: normal; 109 | } 110 | td.fi { 111 | max-width: 120px; 112 | } 113 | td.accttype { 114 | max-width: 240px; 115 | } 116 | td.balance { 117 | max-width: 120px; 118 | } 119 | a:link, a:visited { 120 | color: #0000FF; 121 | background: transparent; 122 | text-decoration: underline; 123 | } 124 | a:hover, a:active { 125 | color: #FF0000; 126 | background: transparent; 127 | } 128 | input[type="button"], input[type="submit"], input[type="reset"] { 129 | border: solid 1px #666666; 130 | border-radius: 4px; 131 | padding: 4px 9px 4px 9px; 132 | margin: 0px; 133 | color: #000000; 134 | background: #DDDDDD; 135 | background: #DDDDDD linear-gradient(to bottom, #EEEEEE 50%, #DDDDDD 50%); 136 | text-decoration: none; 137 | font-weight: normal; 138 | } 139 | input[type="button"]:hover, input[type="submit"]:hover, input[type="reset"]:hover { 140 | border: solid 1px #3377AA; 141 | background: #AADDEE; 142 | background: #AADDEE linear-gradient(to bottom, #DDEEFF 50%, #AADDEE 50%); 143 | } 144 | input[type="button"]:active, input[type="submit"]:active, input[type="reset"]:active { 145 | border: solid 1px #336688; 146 | background: #DDDDDD; 147 | background: #DDDDDD linear-gradient(to bottom, #D7E7F7 50%, #66BBDD 60%); 148 | } 149 | input[type="button"]:disabled, input[type="submit"]:disabled, input[type="reset"]:disabled { 150 | border: solid 1px #AAAAAA; 151 | color: #888888; 152 | background: #EEEEEE; 153 | } 154 | input[type="button"] + input[type="button"], input[type="submit"] + input[type="reset"] { 155 | margin: 0px 0px 0px 5px; 156 | } 157 | input, select { 158 | font-size: 105%; 159 | } 160 | } 161 | -------------------------------------------------------------------------------- /client/aqua.css: -------------------------------------------------------------------------------- 1 | @media screen { 2 | * { 3 | font-family: "ヒラギノ角ゴ ProN W3", "Hiragino Kaku Gothic ProN", "IPAexゴシック", "IPA Pゴシック", "IPAPGothic", "Meiryo UI", "メイリオ", "Meiryo", sans-serif; 4 | } 5 | body { 6 | color: #222222; 7 | background: #1A294A; 8 | background: #1A294A linear-gradient(to right, #1A294A, #2C6E94, #1A294A); 9 | background-attachment: fixed; 10 | font-size: 80%; 11 | } 12 | hr { 13 | display: none; 14 | } 15 | header.bg, nav.bg, section.bg, footer.bg { 16 | filter: blur(1px); 17 | -webkit-filter: blur(1px); 18 | } 19 | header { 20 | display: none; 21 | } 22 | nav { 23 | margin: 20px 0px 20px 0px; 24 | } 25 | footer { 26 | margin: 20px 0px 0px 0px; 27 | } 28 | footer ul li a:link, footer ul li a:visited, footer ul li a:hover { 29 | border: solid 1px #939393; 30 | border-radius: 4px; 31 | padding: 3px 12px 3px 12px; 32 | margin: 0px -3px 0px -3px; 33 | box-shadow: 0px 0px 1px 0px #CECECE; 34 | color: #222222; 35 | background: #ECECEC; 36 | background: #ECECEC linear-gradient(to bottom, #FFFFFF 25%, #F5F5F5 50%, #ECECEC 50%, #ECECEC 75%, #F3F3F3 100%); 37 | text-decoration: none; 38 | text-shadow: 0px 0px 1px #222222; 39 | font-size: 90%; 40 | font-weight: normal; 41 | line-height: 175%; 42 | } 43 | footer ul li a:active { 44 | border: solid 1px #5B60B0; 45 | color: inherit; 46 | background: #A4D3FF; 47 | background: #A4D3FF linear-gradient(to bottom, #E4FAFF 5%, #D5ECFF 5%, #A4D3FF 50%, #88C7FA 50%, #D5F9FF 100%); 48 | } 49 | aside { 50 | color: inherit; 51 | background: #CCCCCC; 52 | background: rgba(0, 0, 0, 0.5); 53 | } 54 | form#modal { 55 | border: solid 1px #000000; 56 | padding: 0px; 57 | box-shadow: 0px 0px 15px 0px rgba(0, 0, 0, 0.5); 58 | color: inherit; 59 | background: #CCCCCC; 60 | background: #CCCCCC linear-gradient(to bottom, #F1F1F1, #BBBBBB 24px); 61 | } 62 | h3#modalhead { 63 | padding: 6px; 64 | margin: 0px; 65 | color: #000000; 66 | background: transparent; 67 | text-shadow: 0px 0px 1px #222222, 1px 1px 1px #FFFFFF; 68 | text-align: center; 69 | text-indent: 0px; 70 | font-weight: normal; 71 | font-size: 100%; 72 | line-height: 100%; 73 | letter-spacing: 0px; 74 | } 75 | div#modalbody { 76 | border: solid #696969; 77 | border-width: 1px 0px 0px 0px; 78 | padding: 10px; 79 | margin: 0px 0px 0px 0px; 80 | background: #EDEDED; 81 | } 82 | div#modalfoot { 83 | padding: 0px 10px 10px 10px; 84 | margin: 0px 0px 0px 0px; 85 | color: inherit; 86 | background: #EDEDED; 87 | } 88 | table { 89 | border: solid 1px #CECECE; 90 | padding: 0px; 91 | margin: 0px auto 0px auto; 92 | } 93 | thead, tfoot { 94 | color: #000000; 95 | background: #ECECEC; 96 | background: #ECECEC linear-gradient(to bottom, #FFFFFF 25%, #F5F5F5 50%, #ECECEC 50%, #ECECEC 75%, #F3F3F3 100%); 97 | text-shadow: 0px 0px 1px #222222; 98 | } 99 | tbody { 100 | color: inherit; 101 | background: #FFFFFF; 102 | } 103 | table tbody:nth-child(odd), table#detail tbody tr:nth-child(odd) { 104 | color: inherit; 105 | background: #F2F5FA; 106 | } 107 | tbody.pending tr { 108 | color: #FFFFFF; 109 | background: #2B6DDE; 110 | } 111 | tbody.pending td a:link, tbody.pending td a:hover, tbody.pending td a:visited, tbody.pending td a:active { 112 | color: #FFFFFF; 113 | background: transparent; 114 | } 115 | tbody.ready tr { 116 | color: #888888; 117 | background: transparent; 118 | } 119 | tbody.error tr { 120 | color: #FF0000; 121 | background: transparent; 122 | } 123 | caption { 124 | border: solid #CECECE; 125 | border-width: 1px 1px 0px 1px; 126 | padding: 12px; 127 | color: #000000; 128 | background: #DDDDDD linear-gradient(to bottom, #F8F8F8 1%, #EFEFEF 1%, #CCCCCC 99%); 129 | font-size: 85%; 130 | font-weight: bold; 131 | text-align: left; 132 | text-shadow: 0px 0px 1px #222222, 1px 1px 1px #FFFFFF; 133 | } 134 | thead, tfoot { 135 | border: solid #CECECE; 136 | border-width: 1px 0px 1px 0px; 137 | } 138 | th { 139 | font-weight: normal; 140 | } 141 | td.fi { 142 | max-width: 128px; 143 | } 144 | td.accttype { 145 | max-width: 384px; 146 | } 147 | a:link, a:visited, a:hover { 148 | color: #222222; 149 | background: transparent; 150 | text-decoration: underline; 151 | } 152 | a:active { 153 | color: #2B6DDE; 154 | background: transparent; 155 | } 156 | input[type="button"], input[type="button"]:hover, input[type="submit"], input[type="submit"]:hover, input[type="reset"], input[type="reset"]:hover { 157 | border: solid 1px #939393; 158 | border-radius: 4px; 159 | padding: 0px 12px 0px 12px; 160 | margin: 0px; 161 | box-shadow: 0px 0px 1px 0px #CECECE; 162 | color: #222222; 163 | background: #ECECEC; 164 | background: #ECECEC linear-gradient(to bottom, #FFFFFF 25%, #F5F5F5 50%, #ECECEC 50%, #ECECEC 75%, #F3F3F3 100%); 165 | text-decoration: none; 166 | text-shadow: 0px 0px 1px #222222; 167 | font-size: 90%; 168 | font-weight: normal; 169 | line-height: 175%; 170 | } 171 | input[type="button"]:active, input[type="submit"]:active, input[type="reset"]:active { 172 | border: solid 1px #5B60B0; 173 | background: #A4D3FF; 174 | background: #A4D3FF linear-gradient(to bottom, #E4FAFF 5%, #D5ECFF 5%, #A4D3FF 50%, #88C7FA 50%, #D5F9FF 100%); 175 | } 176 | input[type="button"]:disabled, input[type="submit"]:disabled, input[type="reset"]:disabled { 177 | border: solid 1px #AAAAAA; 178 | color: #888888; 179 | background: #EEEEEE; 180 | } 181 | input[type="button"] + input[type="button"], input[type="submit"] + input[type="reset"] { 182 | margin: 0px 0px 0px 5px; 183 | } 184 | input, select { 185 | font-size: 95%; 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /client/flat.css: -------------------------------------------------------------------------------- 1 | @media screen { 2 | * { 3 | font-family: "ヒラギノ角ゴ ProN W3", "Hiragino Kaku Gothic ProN", "IPAexゴシック", "IPA Pゴシック", "IPAPGothic", "Meiryo UI", "メイリオ", "Meiryo", sans-serif; 4 | } 5 | body { 6 | color: #000000; 7 | background: #EFA09B; 8 | background: #EFA09B linear-gradient(to right, #D8B99A, #EFA09B, #A87190); 9 | background-attachment: fixed; 10 | font-size: 80%; 11 | } 12 | body > p { 13 | margin: 60px 0px -40px 0px; 14 | } 15 | hr { 16 | display: none; 17 | } 18 | header.bg, nav.bg, section.bg, footer.bg { 19 | filter: blur(8px); 20 | -webkit-filter: blur(8px); 21 | } 22 | header { 23 | display: none; 24 | } 25 | nav { 26 | margin: 0px 0px 60px 0px; 27 | } 28 | nav p { 29 | position: fixed; 30 | top: 0px; 31 | left: 0px; 32 | padding: 0px 0px 0px 10px; 33 | margin: 0px; 34 | width: 100%; 35 | height: 22px; 36 | color: inherit; 37 | background: #FBFCFB; 38 | box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.4); 39 | text-align: left; 40 | } 41 | aside { 42 | color: inherit; 43 | background: #7F7F7F; 44 | background: rgba(0, 0, 0, 0.3); 45 | } 46 | footer { 47 | margin: 20px 0px 0px 0px; 48 | } 49 | form#modal { 50 | border: 0px; 51 | border-radius: 4px; 52 | padding: 0px; 53 | box-shadow: 0px 25px 50px 0px rgba(0, 0, 0, 0.4); 54 | color: inherit; 55 | background: #DADADA linear-gradient(to bottom, #F4F4F4 1px, #E5E5E5 1px, #CFCFCF 28px); 56 | font-size: 95%; 57 | } 58 | h3#modalhead { 59 | padding: 6px; 60 | margin: 0px; 61 | color: #404040; 62 | background: transparent; 63 | text-align: center; 64 | font-weight: normal; 65 | line-height: 100%; 66 | } 67 | div#modalbody { 68 | border: solid #B0B0B0; 69 | border-width: 1px 0px 0px 0px; 70 | padding: 10px; 71 | margin: 0px 0px 0px 0px; 72 | color: inherit; 73 | background: #ECECEC; 74 | } 75 | div#modalfoot { 76 | border: 0px; 77 | border-radius: 0px 0px 4px 4px; 78 | padding: 0px 10px 10px 10px; 79 | margin: 0px 0px 0px 0px; 80 | color: inherit; 81 | background: #ECECEC; 82 | } 83 | table { 84 | border: 0px; 85 | padding: 0px; 86 | margin: 0px auto 0px auto; 87 | font-size: 95%; 88 | } 89 | thead, tfoot { 90 | color: #585858; 91 | background: #F0F0F0; 92 | background: rgba(245, 245, 245, 0.8); 93 | text-shadow: 0px 0px 0px #404040; 94 | } 95 | tbody { 96 | color: inherit; 97 | background: #FFFFFF; 98 | background: rgba(255, 255, 255, 0.8); 99 | } 100 | tbody.pending tr { 101 | color: #FFFFFF; 102 | background: #167CFC; 103 | } 104 | tbody.pending td a:link, tbody.pending td a:hover, tbody.pending td a:visited, tbody.pending td a:active { 105 | color: #FFFFFF; 106 | background: transparent; 107 | } 108 | tbody.ready tr { 109 | color: #BCBCBC; 110 | background: transparent; 111 | } 112 | tbody.error tr { 113 | color: #FF0000; 114 | background: transparent; 115 | } 116 | caption { 117 | border: solid #DBDBDB; 118 | border-width: 0px 0px 1px 0px; 119 | border-radius: 4px 4px 0px 0px; 120 | padding: 10px; 121 | color: #404040; 122 | background: #F6F6F6 linear-gradient(to bottom, #FBFBFB 1px, #F6F6F6 1px); 123 | font-size: 95%; 124 | font-weight: normal; 125 | text-align: center; 126 | } 127 | th { 128 | font-weight: normal; 129 | } 130 | td.fi { 131 | max-width: 128px; 132 | } 133 | td.accttype { 134 | max-width: 384px; 135 | } 136 | a:link, a:visited, a:hover { 137 | color: #000000; 138 | background: transparent; 139 | text-decoration: underline; 140 | } 141 | a:active { 142 | color: #167CFC; 143 | background: transparent; 144 | } 145 | input[type="button"], input[type="button"]:hover, input[type="submit"], input[type="submit"]:hover, input[type="reset"], input[type="reset"]:hover { 146 | border: solid 1px #C2C2C2; 147 | border-radius: 4px; 148 | padding: 0px 10px 0px 10px; 149 | margin: 0px; 150 | color: #404040; 151 | background: #FFFFFF; 152 | text-decoration: none; 153 | text-shadow: 0px 0px 0px #202020; 154 | font-size: 100%; 155 | font-weight: normal; 156 | line-height: 175%; 157 | } 158 | input[type="button"]:active, input[type="button"]:focus, input[type="submit"]:active, input[type="submit"]:focus, input[type="reset"]:active, input[type="reset"]:focus { 159 | border: solid 1px #3383FB; 160 | color: #FFFFFF; 161 | background: #A4D3FF; 162 | background: #A4D3FF linear-gradient(to bottom, #4EADFF, #0092FF, #0075FF); 163 | text-shadow: 0px 0px 0px #FFFFFF; 164 | } 165 | input[type="button"]:disabled, input[type="submit"]:disabled, input[type="reset"]:disabled { 166 | border: solid 1px #D7D7D7; 167 | color: #B8B8B8; 168 | background: #F5F5F5; 169 | } 170 | input[type="button"] + input[type="button"], input[type="submit"] + input[type="reset"] { 171 | margin: 0px 0px 0px 4px; 172 | } 173 | input, select { 174 | font-size: 100%; 175 | } 176 | nav input[type="button"], nav input[type="button"]:hover, nav input[type="button"]:active, nav input[type="button"]:focus, nav input[type="button"]:disabled { 177 | border: 0px; 178 | border-radius: 0px; 179 | margin: 0px; 180 | color: #474747; 181 | background: transparent; 182 | text-shadow: 0px 0px 0px #272727; 183 | font-size: 110%; 184 | line-height: 22px; 185 | cursor: default; 186 | } 187 | nav input[type="button"]:disabled { 188 | display: none; 189 | } 190 | nav input[type="button"]:active { 191 | color: #FFFFFF; 192 | background: #0662D9; 193 | text-shadow: 0px 0px 0px #FFFFFF; 194 | } 195 | nav input[type="button"] + input[type="button"] { 196 | margin: 0px; 197 | } 198 | } 199 | -------------------------------------------------------------------------------- /client/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outerguy/moneysound/fc8d6f8ce19b7fd79aa418d2de4dd193bfaced7b/client/icon.ico -------------------------------------------------------------------------------- /client/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outerguy/moneysound/fc8d6f8ce19b7fd79aa418d2de4dd193bfaced7b/client/icon.png -------------------------------------------------------------------------------- /client/light.css: -------------------------------------------------------------------------------- 1 | @media screen { 2 | * { 3 | font-family: "Takao Pゴシック", "TakaoPGothic", "IPAexゴシック", "IPA Pゴシック", "IPAPGothic", "MS Pゴシック", "MS PGothic", sans-serif; 4 | } 5 | body { 6 | color: #4C4C4C; 7 | background: #481415; 8 | background: #481415 linear-gradient(to right, #481415 20%, #723D3E 40%, #723D3E 60%, #481415 80%); 9 | background-attachment: fixed; 10 | } 11 | hr { 12 | border-top: solid 1px #D3D0CD; 13 | border-right: 0px; 14 | border-bottom: solid 1px #FAF9F9; 15 | border-left: 0px; 16 | } 17 | header.bg, nav.bg, section.bg, footer.bg { 18 | filter: blur(3px); 19 | -webkit-filter: blur(3px); 20 | } 21 | header { 22 | display: none; 23 | } 24 | nav, footer { 25 | margin: 20px 0px 20px 0px; 26 | } 27 | aside { 28 | color: inherit; 29 | background: #481415; 30 | background: rgba(72, 20, 21, 0.4); 31 | } 32 | form#modal { 33 | border: 0px; 34 | border-radius: 7px 7px 0px 0px; 35 | padding: 0px; 36 | color: inherit; 37 | background: #4D4C47; 38 | background: #4D4C47 linear-gradient(to bottom, #5D5B54 1px, #4D4C47 1px, #3C3B37 25px); 39 | box-shadow: 0px 10px 20px #000000; 40 | } 41 | h3#modalhead { 42 | padding: 5px 5px 5px 12px; 43 | margin: 0px; 44 | color: #DFDBD2; 45 | background: transparent; 46 | text-shadow: 0px 0px 2px #000000; 47 | text-align: left; 48 | font-size: 105%; 49 | font-weight: bold; 50 | line-height: 120%; 51 | } 52 | div#modalbody { 53 | padding: 12px; 54 | font-size: 100%; 55 | color: inherit; 56 | background: #F2F1F0; 57 | } 58 | div#modalfoot { 59 | padding: 0px 12px 12px 12px; 60 | color: inherit; 61 | background: #F2F1F0; 62 | } 63 | table { 64 | border: solid 1px #CECBC8; 65 | padding: 0px; 66 | margin: 0px auto 0px auto; 67 | color: inherit; 68 | background: #FFFFFF; 69 | } 70 | thead, tfoot { 71 | color: #666666; 72 | background: #EEEEEE; 73 | background: #EEEEEE linear-gradient(to bottom, #FDFDFD, #EAE9E7); 74 | } 75 | tbody.pending { 76 | color: #FFFFFF; 77 | background: #F07746; 78 | } 79 | tbody.ready { 80 | color: #ADA9A5; 81 | background: transparent; 82 | } 83 | tbody.error { 84 | color: #F07746; 85 | background: transparent; 86 | } 87 | thead th.fi, thead th.accttype, thead th.balance, thead th.timestamp, tbody td.fi, tbody td.accttype, tbody td.balance, tbody td.timestamp, tfoot th { 88 | font-size: 100%; 89 | } 90 | tbody.pending td a:link, tbody.pending td a:hover, tbody.pending td a:visited, tbody.pending td a:active { 91 | color: #FFFFFF; 92 | background: transparent; 93 | } 94 | caption { 95 | padding: 4px 6px 4px 6px; 96 | margin: 0px 0px 6px 0px; 97 | color: #DFDBD2; 98 | background: #555555; 99 | background: #555555 linear-gradient(to bottom, #626055, #403F3A); 100 | text-shadow: 0px 0px 2px #000000; 101 | text-align: left; 102 | font-size: 105%; 103 | font-weight: bold; 104 | line-height: 110%; 105 | box-shadow: 0px 3px 6px #000000; 106 | } 107 | th, td { 108 | border: solid #CECBC8; 109 | border-width: 1px 0px 1px 0px; 110 | padding: 1px 3px 1px 3px; 111 | } 112 | th { 113 | font-weight: bold; 114 | } 115 | td.fi { 116 | max-width: 125px; 117 | } 118 | td.accttype { 119 | max-width: 200px; 120 | } 121 | td.timestamp { 122 | max-width: 100px; 123 | } 124 | a:link, a:visited { 125 | color: #F07746; 126 | background: transparent; 127 | text-decoration: underline; 128 | } 129 | a:hover, a:active { 130 | color: #FF4012; 131 | background: transparent; 132 | } 133 | input[type="button"], input[type="submit"], input[type="reset"] { 134 | border: solid 1px #B7B7B7; 135 | border-radius: 5px / 4px; 136 | padding: 5px; 137 | margin: 3px 0px 3px 0px; 138 | color: #4C4C4C; 139 | background: #F2F1F0; 140 | background: #F2F1F0 linear-gradient(to bottom, #FFFFFF, #ECECEA 95%, #EFEEED 100%); 141 | font-size: 100%; 142 | line-height: 110%; 143 | text-decoration: none; 144 | } 145 | input[type="button"]:hover, input[type="submit"]:hover, input[type="reset"]:hover { 146 | color: inerit; 147 | background: #FFFFFF; 148 | background: #FFFFFF linear-gradient(to bottom, #FFFFFF 50%, #F1F1F1); 149 | box-shadow: 0px 0px 2px 0px #B7B7B7; 150 | } 151 | input[type="button"]:active, input[type="submit"]:active, input[type="reset"]:active { 152 | border: solid 1px #DD7C55; 153 | color: inerit; 154 | background: #DADADA; 155 | background: #DADADA linear-gradient(to bottom, #E9E8E6, #F3F3F2 5%, #DDDBD9); 156 | box-shadow: 0px 0px 2px 0px #DD7C55; 157 | } 158 | input[type="button"]:disabled, input[type="submit"]:disabled, input[type="reset"]:disabled { 159 | border: solid 1px #D2D2D2; 160 | color: #95918C; 161 | background: #EBEBEB; 162 | } 163 | input[type="button"] + input[type="button"], input[type="submit"] + input[type="reset"] { 164 | margin: 0px 0px 0px 5px; 165 | } 166 | input, select { 167 | font-size: 110%; 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /client/luna.css: -------------------------------------------------------------------------------- 1 | @media screen { 2 | * { 3 | font-family: "MS UI Gothic", "MS Pゴシック", "MS PGothic", sans-serif; 4 | } 5 | body { 6 | margin: 0px 0px 20px 0px; 7 | color: #000000; 8 | background: #ECE9D8; 9 | } 10 | hr { 11 | border-top: solid 1px #ACA899; 12 | border-right: 0px; 13 | border-bottom: solid 1px #FFFFFF; 14 | border-left: 0px; 15 | } 16 | h1 { 17 | padding: 10px; 18 | margin: 0px; 19 | font-size: 95%; 20 | text-align: center; 21 | text-indent: 2px; 22 | letter-spacing: 2px; 23 | line-height: 100%; 24 | color: inherit; 25 | background: #FFFFFF; 26 | } 27 | header { 28 | border: solid #ACA899; 29 | border-width: 0px 0px 1px 0px; 30 | } 31 | nav { 32 | border: solid #FFFFFF; 33 | border-width: 1px 0px 0px 0px; 34 | padding: 0px 0px 0px 0px; 35 | margin: 0px; 36 | } 37 | footer { 38 | margin: 10px 0px 0px 0px; 39 | } 40 | footer ul li a { 41 | font-size: 85%; 42 | } 43 | aside { 44 | color: inherit; 45 | background: #000000; 46 | background: rgba(0, 0, 0, 0.5); 47 | } 48 | form#modal { 49 | border: solid #0022CC; 50 | border-width: 1px; 51 | border-radius: 8px 8px 0px 0px; 52 | padding: 0px; 53 | box-shadow: 0px 0px 10px 0px #666666; 54 | color: inherit; 55 | background: #0055EE; 56 | background: #0055EE linear-gradient(to bottom, #3399FF, #0055EE 4px, #0055EE 16px, #0077FF 24px, #0044CC 28px); 57 | } 58 | h3#modalhead { 59 | padding: 7px 5px 7px 5px; 60 | margin: 0px; 61 | color: #FFFFFF; 62 | background: transparent; 63 | text-shadow: 1px 1px 1px #001188; 64 | text-align: left; 65 | text-indent: 2px; 66 | font-weight: bold; 67 | font-size: 85%; 68 | line-height: 120%; 69 | letter-spacing: 2px; 70 | } 71 | div#modalbody { 72 | border: solid #0022CC; 73 | border-width: 1px 0px 0px 0px; 74 | padding: 7px; 75 | margin: 0px 2px 0px 2px; 76 | color: inherit; 77 | background: #ECE9D8; 78 | font-size: 95%; 79 | line-height: 110%; 80 | } 81 | div#modalfoot { 82 | padding: 0px 7px 7px 7px; 83 | margin: 0px 2px 2px 2px; 84 | color: inherit; 85 | background: #ECE9D8; 86 | } 87 | table { 88 | border: solid 1px #99BBEE; 89 | border-spacing: 0px; 90 | padding: 0px; 91 | margin: 0px auto 0px auto; 92 | } 93 | thead, tfoot { 94 | color: #002266; 95 | background: #DDEEFF; 96 | } 97 | tbody { 98 | color: inherit; 99 | background: #FFFFFF; 100 | } 101 | tbody.pending { 102 | color: #FFFFFF; 103 | background: #3366BB; 104 | } 105 | tbody.ready { 106 | color: #888888; 107 | background: #EEEEEE; 108 | } 109 | tbody.error { 110 | color: #FF0000; 111 | background: #FFEEEE; 112 | } 113 | thead th.fi, thead th.accttype, thead th.balance, thead th.timestamp, tbody td.fi, tbody td.accttype, tbody td.balance, tbody td.timestamp, tfoot th { 114 | font-size: 85%; 115 | } 116 | tbody.pending td a:link, tbody.pending td a:hover, tbody.pending td a:visited, tbody.pending td a:active { 117 | color: #FFFFFF; 118 | background: transparent; 119 | } 120 | caption { 121 | border: solid #9999AA; 122 | border-width: 1px 1px 0px 1px; 123 | border-radius: 8px 8px 0px 0px; 124 | padding: 7px 10px 7px 10px; 125 | color: #000000; 126 | background: #EEE7DD; 127 | background: #EEE7DD linear-gradient(to bottom, #FFFFFF, #DDD7CC); 128 | font-size: 100%; 129 | font-weight: normal; 130 | line-height: 100%; 131 | text-indent: 2px; 132 | letter-spacing: 2px; 133 | text-shadow: 1px 1px 1px #FFFFFF; 134 | } 135 | th, td { 136 | border: solid #99BBEE; 137 | border-width: 1px 0px 1px 0px; 138 | } 139 | th { 140 | font-weight: bold; 141 | } 142 | td.fi { 143 | max-width: 128px; 144 | } 145 | td.accttype { 146 | max-width: 192px; 147 | } 148 | a:link, a:visited { 149 | color: #0000FF; 150 | background: transparent; 151 | text-decoration: underline; 152 | } 153 | a:hover, a:active { 154 | color: #FF0000; 155 | background: transparent; 156 | } 157 | input[type="button"], input[type="submit"], input[type="reset"] { 158 | border: solid 1px #666666; 159 | border-radius: 4px; 160 | padding: 2px 10px 2px 10px; 161 | margin: 0px; 162 | color: #000000; 163 | background: #EEE7DD; 164 | background: #EEE7DD linear-gradient(to bottom, #FFFFFF, #DDD7CC); 165 | box-shadow: 0px 0px 1px 0px #FFFFFF; 166 | text-decoration: none; 167 | font-weight: normal; 168 | } 169 | input[type="button"]:hover, input[type="submit"]:hover, input[type="reset"]:hover { 170 | border: solid 2px #FFAA33; 171 | padding: 1px 9px 1px 9px; 172 | box-shadow: 0px 0px 0px 1px #003366; 173 | } 174 | input[type="button"]:active, input[type="submit"]:active, input[type="reset"]:active { 175 | border: solid 1px #003366; 176 | padding: 2px 10px 2px 10px; 177 | box-shadow: 0px 0px 1px 0px #003366; 178 | color: inherit; 179 | background: #E2E1DA; 180 | } 181 | input[type="button"]:disabled, input[type="submit"]:disabled, input[type="reset"]:disabled { 182 | border: solid 1px #AAAAAA; 183 | padding: 2px 10px 2px 10px; 184 | color: #AAAA99; 185 | background: #F7F7EE; 186 | box-shadow: 0px 0px 1px 0px #FFFFFF; 187 | } 188 | input[type="button"] + input[type="button"], input[type="submit"] + input[type="reset"] { 189 | margin: 0px 0px 0px 2px; 190 | } 191 | } 192 | -------------------------------------------------------------------------------- /client/modern.css: -------------------------------------------------------------------------------- 1 | @media screen { 2 | * { 3 | font-family: "Meiryo UI", "メイリオ", "Meiryo", sans-serif; 4 | } 5 | body { 6 | margin: 0px 0px 40px 0px; 7 | color: #000000; 8 | background: #1D1D1D; 9 | font-size: 95%; 10 | } 11 | hr { 12 | display: none; 13 | } 14 | header h1 { 15 | padding: 30px; 16 | margin: 0px; 17 | color: #FFFFFF; 18 | background: transparent; 19 | font-size: 200%; 20 | font-weight: normal; 21 | line-height: 100%; 22 | text-align: left; 23 | } 24 | footer ul li a { 25 | margin: 0px 0.2em 0px 0.2em; 26 | } 27 | footer ul li a:link, footer ul li a:visited { 28 | color: #FFFFFF; 29 | background: transparent; 30 | } 31 | footer ul li a:hover, footer ul li a:active { 32 | color: #CC3333; 33 | background: transparent; 34 | } 35 | aside { 36 | color: inherit; 37 | background: #CCCCCC; 38 | background: rgba(0, 0, 0, 0.5); 39 | } 40 | footer { 41 | margin: 30px 0px 0px 0px; 42 | } 43 | nav, section { 44 | color: inherit; 45 | background: #1D1D1D; 46 | background: #1D1D1D linear-gradient(to right, #92009B 20%, #1D1D1D 20%, #1D1D1D 21%, #008F00 21%, #008F00 31%, #1D1D1D 31%, #1D1D1D 32%, #0099AB 32%, #0099AB 72%, #1D1D1D 72%, #1D1D1D 73%, #FFDA46 73%, #FFDA46 93%, #1D1D1D 93%); 47 | } 48 | nav { 49 | padding: 10px 0px 0px 0px; 50 | margin: 0px 0px -20px 0px; 51 | } 52 | section { 53 | padding: 20px 0px 30px 0px; 54 | margin: 0px; 55 | } 56 | form#modal { 57 | border: solid 1px #6699CC; 58 | padding: 0px; 59 | box-shadow: 0px 0px 5px 0px rgba(0, 0, 0, 0.3); 60 | color: inherit; 61 | background: #66AAFF; 62 | } 63 | h3#modalhead { 64 | padding: 5px; 65 | margin: 0px; 66 | color: #000000; 67 | background: transparent; 68 | text-align: center; 69 | text-indent: 0px; 70 | font-weight: normal; 71 | font-size: 100%; 72 | line-height: 140%; 73 | letter-spacing: 0px; 74 | } 75 | div#modalbody { 76 | border: solid #6699CC; 77 | border-width: 1px 1px 0px 1px; 78 | padding: 10px; 79 | margin: 0px 5px 0px 5px; 80 | color: inherit; 81 | background: #FFFFFF; 82 | font-size: 90%; 83 | line-height: 130%; 84 | } 85 | div#modalfoot { 86 | border: solid #6699CC; 87 | border-width: 0px 1px 1px 1px; 88 | padding: 0px 10px 10px 10px; 89 | margin: 0px 5px 5px 5px; 90 | color: inherit; 91 | background: #FFFFFF; 92 | } 93 | table { 94 | border: solid 1px #C6CFD5; 95 | padding: 0px; 96 | margin: 0px auto 0px auto; 97 | } 98 | thead, tfoot { 99 | color: #2B4C66; 100 | background: #ECF0F1; 101 | } 102 | tbody { 103 | color: #2B4C66; 104 | background: #FFFFFF; 105 | } 106 | tbody.pending { 107 | color: inherit; 108 | background: #CDDBE1; 109 | } 110 | tbody.ready { 111 | color: #95A5B2; 112 | background: #FFFFFF; 113 | } 114 | tbody.error { 115 | color: #CC1122; 116 | background: #FFFFFF; 117 | } 118 | caption { 119 | border: 0px; 120 | padding: 0px; 121 | color: #FFFFFF; 122 | background: transparent; 123 | font-size: 125%; 124 | font-weight: bold; 125 | line-height: 150%; 126 | text-align: left; 127 | } 128 | th, td { 129 | border: solid #C6CFD5; 130 | border-width: 1px 0px 1px 0px; 131 | } 132 | th { 133 | font-weight: bold; 134 | } 135 | a:link, a:visited { 136 | color: #3333CC; 137 | background: transparent; 138 | text-decoration: underline; 139 | } 140 | a:hover, a:active { 141 | color: #CC3333; 142 | background: transparent; 143 | } 144 | input[type="button"], input[type="submit"], input[type="reset"] { 145 | border: solid 1px #AAAAAA; 146 | padding: 1px 11px 1px 11px; 147 | margin: 1px 0px 1px 0px; 148 | color: #000000; 149 | background: #F0F0F0; 150 | background: #F0F0F0 linear-gradient(to bottom, #F0F0F0, #E7E7E7); 151 | text-decoration: none; 152 | font-weight: normal; 153 | } 154 | input[type="button"]:hover, input[type="submit"]:hover, input[type="reset"]:hover { 155 | border: solid 1px #77AAEE; 156 | color: inherit; 157 | background: #F0F7FF; 158 | background: #F0F7FF linear-gradient(to bottom, #F0F7FF, #DDEEFF); 159 | } 160 | input[type="button"]:active, input[type="submit"]:active, input[type="reset"]:active { 161 | border: solid 1px #5599DD; 162 | color: inherit; 163 | background: #DDEEFF; 164 | background: #DDEEFF linear-gradient(to bottom, #DDEEFF, #CCDDFF); 165 | } 166 | input[type="button"]:disabled, input[type="submit"]:disabled, input[type="reset"]:disabled { 167 | border: solid 1px #D9D9D9; 168 | color: #838383; 169 | background: #EFEFEF; 170 | } 171 | input[type="button"]:focus, input[type="submit"]:focus, input[type="reset"]:focus { 172 | border: solid 1px #5599DD; 173 | } 174 | input[type="button"] + input[type="button"], input[type="submit"] + input[type="reset"] { 175 | margin: 0px 0px 0px 5px; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /client/precious.css: -------------------------------------------------------------------------------- 1 | @media screen { 2 | * { 3 | font-family: "メイリオ", "Meiryo", sans-serif; 4 | } 5 | body { 6 | margin: 0px 0px 40px 0px; 7 | color: #000000; 8 | background: #CC9933; 9 | background: #CC9933 linear-gradient(to bottom, #CC9933, #996600 40px, #CC9933 200px) center top no-repeat; 10 | } 11 | hr { 12 | display: none; 13 | } 14 | header h1 { 15 | color: #663300; 16 | background: transparent; 17 | font-size: 180%; 18 | text-align: center; 19 | text-shadow: 0px -2px 2px #FFFF99; 20 | line-height: 150%; 21 | } 22 | nav { 23 | margin: 0px 0px 20px 0px; 24 | } 25 | aside { 26 | color: inherit; 27 | background: #000000; 28 | background: rgba(0, 0, 0, 0.5); 29 | } 30 | footer { 31 | margin: 20px 0px 0px 0px; 32 | } 33 | form#modal { 34 | border: solid 2px #996633; 35 | border-radius: 10px 10px 0px 0px; 36 | padding: 0px; 37 | box-shadow: 0px 0px 10px 0px #666666; 38 | color: inherit; 39 | background: #DDAA77; 40 | background: #DDAA77 linear-gradient(to bottom, #FFFFCC, #996633 15px, #CC9966 25px, #FFFFCC 30px); 41 | } 42 | h3#modalhead { 43 | border: solid #996633; 44 | border-width: 0px 0px 2px 0px; 45 | padding: 8px 10px 5px 10px; 46 | margin: 0px; 47 | color: #663300; 48 | background: transparent; 49 | text-shadow: 0px -2px 2px #FFFFCC; 50 | text-align: center; 51 | text-indent: 2px; 52 | font-weight: bold; 53 | font-size: 100%; 54 | line-height: 100%; 55 | letter-spacing: 2px; 56 | } 57 | div#modalbody { 58 | padding: 15px; 59 | color: inherit; 60 | background: #FFFFFF; 61 | line-height: 175%; 62 | font-size: 95%; 63 | letter-spacing: 1px; 64 | } 65 | div#modalfoot { 66 | padding: 0px 15px 15px 15px; 67 | color: inherit; 68 | background: #FFFFFF; 69 | } 70 | table { 71 | border: solid 2px #996600; 72 | padding: 0px; 73 | margin: 0px auto 0px auto; 74 | } 75 | thead, tfoot { 76 | color: #333333; 77 | background: #DDDDDD; 78 | background: #DDDDDD linear-gradient(to bottom, #FFFFFF, #CCCCCC 50%, #FFFFFF); 79 | text-shadow: 0px -2px 2px #FFFFFF; 80 | } 81 | tbody { 82 | color: #996600; 83 | background: #FFFFFF; 84 | text-shadow: 0px -1px 2px #FFFF99; 85 | } 86 | tbody td.control .btn { 87 | opacity: 0.5; 88 | } 89 | tbody:hover td.control .btn { 90 | opacity: 1; 91 | } 92 | tbody.pending, tbody.pending td a:link, tbody.pending td a:hover, tbody.pending td a:visited, tbody.pending td a:active { 93 | color: #FFFFFF; 94 | background: #996600; 95 | } 96 | tbody.ready { 97 | color: #999999; 98 | background: #FFFFFF; 99 | } 100 | tbody.error { 101 | color: #CC3333; 102 | background: #FFFFFF; 103 | } 104 | caption { 105 | border: solid #996600; 106 | border-width: 2px 2px 0px 2px; 107 | border-radius: 10px 10px 0px 0px; 108 | padding: 5px 10px 5px 10px; 109 | color: #663300; 110 | background: #DDAA44; 111 | background: #DDAA44 linear-gradient(to bottom, #FFFF99, #996600 50%, #CC9933 75%, #CCCC66); 112 | text-shadow: 0px -2px 2px #FFFF99; 113 | font-size: 85%; 114 | font-weight: bold; 115 | line-height: 150%; 116 | text-indent: 2px; 117 | letter-spacing: 2px; 118 | } 119 | th, td { 120 | border: solid #CC9933; 121 | border-width: 1px 0px 1px 0px; 122 | } 123 | th { 124 | font-weight: normal; 125 | } 126 | a:link, a:visited { 127 | color: #996600; 128 | background: transparent; 129 | text-decoration: underline; 130 | } 131 | a:hover { 132 | color: #CC3333; 133 | background: transparent; 134 | } 135 | a:active { 136 | color: #660000; 137 | background: transparent; 138 | } 139 | input[type="button"], input[type="submit"], input[type="reset"] { 140 | border: 0px; 141 | border-radius: 5px; 142 | padding: 3px 9px 3px 9px; 143 | color: #333333; 144 | background: #AAAAAA; 145 | background: #AAAAAA linear-gradient(to bottom, #FFFFFF, #666666 50%, #999999 75%, #CCCCCC); 146 | text-shadow: 0px -2px 2px #FFFFFF; 147 | box-shadow: 0px 0px 0px 2px #666666; 148 | text-decoration: none; 149 | font-weight: bold; 150 | text-indent: 2px; 151 | letter-spacing: 2px; 152 | } 153 | input[type="button"]:hover, input[type="submit"]:hover, input[type="reset"]:hover { 154 | color: #663300; 155 | background: #DDAA44; 156 | background: #DDAA44 linear-gradient(to bottom, #FFFF99, #996600 50%, #CC9933 75%, #CCCC66); 157 | text-shadow: 0px -2px 2px #FFFF99; 158 | box-shadow: 0px 0px 0px 2px #996600; 159 | } 160 | input[type="button"]:active, input[type="submit"]:active, input[type="reset"]:active { 161 | color: #663300; 162 | background: #DDAA77; 163 | background: #DDAA77 linear-gradient(to bottom, #FFFFCC, #996633 50%, #CC9966 75%, #FFFFCC); 164 | text-shadow: 0px -2px 2px #FFFFCC; 165 | box-shadow: 0px 0px 0px 2px #996633; 166 | } 167 | input[type="button"]:disabled, input[type="submit"]:disabled, input[type="reset"]:disabled { 168 | color: #999999; 169 | background: #CCCCCC; 170 | background: #CCCCCC linear-gradient(to bottom, #FFFFFF, #CCCCCC 50%, #DDDDDD 75%, #EEEEEE); 171 | text-shadow: 0px 2px 2px #FFFFFF; 172 | box-shadow: 0px 0px 0px 2px #999999; 173 | } 174 | input[type="button"] + input[type="button"], input[type="submit"] + input[type="reset"] { 175 | margin: 0px 0px 0px 6px; 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /client/rule.css: -------------------------------------------------------------------------------- 1 | body { 2 | position: static; 3 | border: 0px; 4 | padding: 0px; 5 | margin: 0px; 6 | width: 100%; 7 | overflow-x: hidden; 8 | overflow-y: scroll; 9 | font-size: 85%; 10 | z-index: 1; 11 | } 12 | header, caption, footer { 13 | cursor: default; 14 | } 15 | header, nav, section, footer, article { 16 | display: block; 17 | } 18 | aside { 19 | position: fixed; 20 | top: 0px; 21 | left: 0px; 22 | width: 100%; 23 | height: 100%; 24 | z-index: 2; 25 | } 26 | nav p, footer ul { 27 | text-align: center; 28 | } 29 | footer ul { 30 | border: 0px; 31 | padding: 0px; 32 | margin: 0px; 33 | } 34 | footer li { 35 | display: inline; 36 | border: 0px; 37 | padding: 0px 0.25em 0px 0.25em; 38 | margin: 0px; 39 | } 40 | section h2, footer h2 { 41 | display: none; 42 | } 43 | code { 44 | font-family: monospace; 45 | } 46 | pre { 47 | word-wrap: break-word; 48 | } 49 | a { 50 | cursor: pointer; 51 | } 52 | a img { 53 | border: 0px; 54 | padding: 0px; 55 | margin: 0px; 56 | } 57 | table { 58 | border-collapse: collapse; 59 | border-spacing: 0px; 60 | empty-cells: show; 61 | caption-side: top; 62 | word-wrap: break-word; 63 | } 64 | thead, tfoot { 65 | line-height: 200%; 66 | } 67 | tbody { 68 | line-height: 120%; 69 | } 70 | th, td { 71 | border: 0px; 72 | padding: 2px; 73 | margin: 0px; 74 | text-indent: 1px; 75 | letter-spacing: 1px; 76 | } 77 | td.fi, td.accttype, th.control, td.control { 78 | text-align: left; 79 | } 80 | td.balance { 81 | text-align: right; 82 | } 83 | td.status, td.timestamp { 84 | text-align: center; 85 | } 86 | td a { 87 | cursor: help; 88 | } 89 | p#debug { 90 | border: 0px; 91 | padding: 0.5em; 92 | margin: 0px; 93 | color: #FFFFFF; 94 | background: #FF0000; 95 | text-align: center; 96 | } 97 | form#modal { 98 | position: fixed; 99 | top: 0px; 100 | left: 0px; 101 | z-index: 3; 102 | white-space: nowrap; 103 | } 104 | form#modal p { 105 | border: 0px; 106 | padding: 0px; 107 | margin: 0px; 108 | } 109 | h3#modalhead, div#modalbody, div#modalfoot { 110 | cursor: default; 111 | } 112 | div#modalbody { 113 | max-width: 640px; 114 | max-height: 360px; 115 | overflow: hidden; 116 | } 117 | div#modalbody p.label { 118 | border: 0px; 119 | padding: 10px 0px 0px 0px; 120 | margin: 0px; 121 | font-size: 90%; 122 | font-weight: bold; 123 | } 124 | div#modalbody p.label:first-child { 125 | border: 0px; 126 | padding: 0px; 127 | margin: 0px; 128 | } 129 | div#modalbody p.label:after { 130 | content: ":"; 131 | } 132 | div#modalfoot { 133 | text-align: right; 134 | } 135 | div#help { 136 | margin: 0px; 137 | max-height: 192px; 138 | overflow: auto; 139 | } 140 | div#help h2, div#help h3, div#help ul, div#help ul li { 141 | max-width: 480px; 142 | } 143 | div#help h2 { 144 | border: 0px; 145 | padding: 0px; 146 | margin: 0px 0px 1em 0px; 147 | font-size: 100%; 148 | } 149 | div#help h3 { 150 | border: 0px; 151 | padding: 0px; 152 | margin: 1em 0px 0px 0px; 153 | font-size: 100%; 154 | } 155 | div#help h3:after { 156 | content: ":"; 157 | } 158 | div#help ul { 159 | border: 0px; 160 | padding: 0px; 161 | margin: 0px 0px 0px 2em; 162 | font-size: 100%; 163 | } 164 | div#details { 165 | min-height: 192px; 166 | max-height: 192px; 167 | overflow-x: hidden; 168 | overflow-y: scroll; 169 | border: 0px; 170 | padding: 0px; 171 | margin: 10px 0px 0px 0px; 172 | } 173 | table#detail { 174 | table-layout: fixed; 175 | width: 512px; 176 | } 177 | table#detail th.dt { 178 | width: 64px; 179 | } 180 | table#detail th.note { 181 | width: 328px; 182 | } 183 | table#detail th.amt { 184 | width: 120px; 185 | } 186 | table#detail td.dt { 187 | text-align: center; 188 | } 189 | table#detail td.note { 190 | text-align: left; 191 | } 192 | table#detail td.amt { 193 | text-align: right; 194 | } 195 | table#detail td { 196 | overflow: hidden; 197 | text-overflow: ellipsis; 198 | } 199 | .pending, .pending input[type="button"]:disabled { 200 | cursor: wait; 201 | } 202 | input[type="button"], input[type="submit"], input[type="reset"] { 203 | font-size: 85%; 204 | cursor: pointer; 205 | line-height: 150%; 206 | /* iOSのボタンサイズを補正する */ 207 | -webkit-appearance: none; 208 | } 209 | input[type="button"]:disabled, input[type="submit"]:disabled, input[type="reset"]:disabled { 210 | cursor: default; 211 | } 212 | /* Firefoxのボタンサイズを補正する */ 213 | input[type="button"]::-moz-focus-inner, input[type="submit"]::-moz-focus-inner, input[type="reset"]::-moz-focus-inner { 214 | border-width: 1px; 215 | padding: 0px; 216 | margin: -1px; 217 | } 218 | input[type="text"], input[type="password"], input[type="email"], input[type="tel"], input[type="file"], select { 219 | width: 320px; 220 | } 221 | .al { 222 | text-align: left; 223 | } 224 | .ac { 225 | text-align: center; 226 | } 227 | .ar { 228 | text-align: right; 229 | } 230 | .none { 231 | display: none; 232 | } 233 | @media print { 234 | * { 235 | font-family: sans-serif; 236 | } 237 | body { 238 | color: #000000; 239 | background: #FFFFFF; 240 | } 241 | header { 242 | display: block; 243 | } 244 | nav, footer { 245 | display: none; 246 | } 247 | h1 { 248 | border: 0px; 249 | padding: 0px; 250 | margin: 0px; 251 | font-size: 150%; 252 | text-align: left; 253 | letter-spacing: 0px; 254 | } 255 | table { 256 | width: 100%; 257 | border: solid #000000; 258 | border-width: 4px 0px 0px 0px; 259 | padding: 0px; 260 | margin: 0px; 261 | } 262 | thead tr, tfoot tr { 263 | border: solid #000000; 264 | border-width: 1px 0px 1px 0px; 265 | padding: 0px; 266 | margin: 0px; 267 | } 268 | thead tr th, tfoot tr th { 269 | border: 0px; 270 | padding: 0.5em 0.25em 0.5em 0.25em; 271 | margin: 0px; 272 | font-weight: normal; 273 | } 274 | tbody:nth-child(odd) { 275 | color: inherit; 276 | background: #FFFFFF; 277 | } 278 | tbody:nth-child(even) { 279 | color: inherit; 280 | background: #CCEEFF; 281 | } 282 | th.control, td.control { 283 | display: none; 284 | } 285 | td.fi, td.accttype, td.balance, td.timestamp { 286 | max-width: inherit; 287 | } 288 | caption { 289 | border: 0px; 290 | padding: 0px 0px 1em 0px; 291 | margin: 0px; 292 | font-size: 100%; 293 | text-align: left; 294 | } 295 | p#debug { 296 | display: none; 297 | } 298 | a { 299 | color: #000000; 300 | background: transparent; 301 | text-decoration: none 302 | } 303 | } 304 | -------------------------------------------------------------------------------- /client/spartan.css: -------------------------------------------------------------------------------- 1 | @media screen { 2 | * { 3 | font-family: "Yu Gothic UI", "游ゴシック", "Meiryo UI", "メイリオ", "Meiryo", sans-serif; 4 | } 5 | body { 6 | color: #000000; 7 | background: #FFFFFF; 8 | font-size: 80%; 9 | } 10 | hr { 11 | display: none; 12 | } 13 | header { 14 | height: 32px; 15 | color: inherit; 16 | background: #CCCCCC; 17 | } 18 | header h1 { 19 | display: inline-block; 20 | border: 0px; 21 | padding: 0px 8px 0px 8px; 22 | margin: 0px; 23 | color: inherit; 24 | background: #F2F2F2; 25 | font-size: 100%; 26 | font-weight: normal; 27 | line-height: 32px; 28 | text-align: left; 29 | } 30 | footer { 31 | line-height: 44px; 32 | } 33 | footer ul li a { 34 | border: 0px; 35 | padding: 0px; 36 | margin: 0px 0.2em 0px 0.2em; 37 | } 38 | aside { 39 | color: inherit; 40 | background: #F2F2F2; 41 | background: rgba(0, 0, 0, 0.05); 42 | } 43 | nav { 44 | border: solid #CCCCCC; 45 | border-width: 0px 0px 1px 0px; 46 | padding: 0px; 47 | margin: 0px; 48 | color: inherit; 49 | background: #F2F2F2; 50 | } 51 | nav p { 52 | border: 0px; 53 | padding: 0px; 54 | margin: 0px; 55 | line-height: 44px; 56 | text-align: left; 57 | } 58 | section { 59 | color: inherit; 60 | background: #FFFFFF; 61 | } 62 | form#modal { 63 | border: solid 1px #A4A4A4; 64 | padding: 0px; 65 | margin: 0px; 66 | box-shadow: 0px 0px 16px 0px rgba(0, 0, 0, 0.3); 67 | color: inherit; 68 | background: #FFFFFF; 69 | } 70 | h3#modalhead { 71 | border: solid #DADBDC; 72 | border-width: 0px 0px 1px 0px; 73 | padding: 5px; 74 | margin: 0px; 75 | color: inherit; 76 | background: transparent; 77 | text-align: left; 78 | text-indent: 0px; 79 | font-weight: normal; 80 | font-size: 100%; 81 | line-height: 140%; 82 | letter-spacing: 0px; 83 | } 84 | div#modalbody { 85 | border: 0px; 86 | padding: 10px; 87 | margin: 0px; 88 | color: inherit; 89 | background: #FFFFFF; 90 | font-size: 120%; 91 | line-height: 120%; 92 | } 93 | div#modalfoot { 94 | border: 0px; 95 | padding: 0px; 96 | margin: 0px 10px 10px 10px; 97 | color: inherit; 98 | background: #FFFFFF; 99 | } 100 | table { 101 | border: solid 1px #CCCCCC; 102 | padding: 0px; 103 | margin: 0px auto 0px auto; 104 | } 105 | tbody { 106 | color: inherit; 107 | background: #FFFFFF; 108 | } 109 | tbody.pending { 110 | color: inherit; 111 | background: #91C1E7; 112 | } 113 | tbody.ready { 114 | color: #B2B2B2; 115 | background: #F2F2F2; 116 | } 117 | tbody.error { 118 | color: #FD2121; 119 | background: #F2F2F2; 120 | } 121 | caption { 122 | border: 0px; 123 | padding: 0px 8px 0px 8px; 124 | margin: 0px; 125 | color: inherit; 126 | background: #FFFFFF; 127 | font-size: 150%; 128 | line-height: 64px; 129 | text-align: left; 130 | } 131 | th, td { 132 | border: solid #CCCCCC; 133 | border-width: 1px 0px 1px 0px; 134 | padding: 0px; 135 | margin: 0px; 136 | line-height: 170%; 137 | } 138 | .fi { 139 | max-width: 90px; 140 | } 141 | .accttype { 142 | max-width: 170px; 143 | } 144 | .timestamp { 145 | max-width: 40px; 146 | } 147 | .fi, .accttype, .balance, .timestamp { 148 | padding: 0px 4px 0px 4px; 149 | } 150 | th { 151 | color: inherit; 152 | background: #E6E6E6; 153 | font-weight: bold; 154 | } 155 | a:link, a:visited { 156 | color: #0078D7; 157 | background: transparent; 158 | text-decoration: none; 159 | } 160 | a:hover { 161 | color: #0068AF; 162 | background: transparent; 163 | } 164 | a:active { 165 | color: #00456B; 166 | background: transparent; 167 | } 168 | input[type="button"], input[type="submit"], input[type="reset"] { 169 | min-width: 44px; 170 | border: 0px; 171 | padding: 0px 8px 0px 8px; 172 | margin: 0px; 173 | color: #000000; 174 | background: transparent; 175 | text-decoration: none; 176 | font-size: 100%; 177 | font-weight: normal; 178 | line-height: 45px; 179 | } 180 | input[type="button"]:hover, input[type="button"]:active, input[type="submit"]:hover, input[type="submit"]:active, input[type="reset"]:hover, input[type="reset"]:active { 181 | border: 0px; 182 | color: #000000; 183 | background: #DADADA; 184 | } 185 | input[type="button"]:disabled, input[type="submit"]:disabled, input[type="reset"]:disabled { 186 | border: 0px; 187 | color: #B2B2B2; 188 | background: transparent; 189 | } 190 | div#modalbody th, div#modalbody td { 191 | font-size: 85%; 192 | } 193 | div#modalbody input { 194 | font-size: 100%; 195 | } 196 | div#modalbody select { 197 | font-size: 100%; 198 | line-height: 170%; 199 | } 200 | div#modalbody p.label { 201 | font-weight: normal; 202 | line-height: 170%; 203 | } 204 | div#modalbody p.label:after { 205 | content: ""; 206 | } 207 | div#modalfoot input[type="submit"], div#modalfoot input[type="reset"] { 208 | border: solid 2px #CCCCCC; 209 | padding: 0px 8px 0px 8px; 210 | margin: 0px; 211 | font-size: 120%; 212 | line-height: 170%; 213 | color: #000000; 214 | background: #CCCCCC; 215 | } 216 | div#modalfoot input[type="submit"]:hover, div#modalfoot input[type="reset"]:hover { 217 | border: solid 2px #7A7A7A; 218 | color: inherit; 219 | background: #CCCCCC; 220 | } 221 | div#modalfoot input[type="submit"]:active, div#modalfoot input[type="reset"]:active { 222 | border: solid 2px #999999; 223 | color: inherit; 224 | background: #999999; 225 | } 226 | div#modalfoot input[type="submit"] + input[type="reset"] { 227 | margin: 0px 0px 0px 10px; 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /client/standard.css: -------------------------------------------------------------------------------- 1 | @media screen { 2 | * { 3 | font-family: sans-serif; 4 | } 5 | body { 6 | color: #000000; 7 | background: #FFFFFF; 8 | background: #FFFFFF linear-gradient(to right, #EEEEEE, #FFFFFF 25%, #FFFFFF 75%, #EEEEEE); 9 | } 10 | header { 11 | display: none; 12 | } 13 | nav, footer { 14 | margin: 10px 0px 10px 0px; 15 | } 16 | footer ul li a { 17 | font-size: 90%; 18 | } 19 | aside { 20 | color: inherit; 21 | background: #CCCCCC; 22 | background: rgba(204, 204, 204, 0.5); 23 | } 24 | form#modal { 25 | border: solid 2px #666666; 26 | border-radius: 10px 10px 0px 0px; 27 | padding: 0px; 28 | box-shadow: 0px 0px 10px 0px #666666; 29 | color: inherit; 30 | background: #666666; 31 | background: #666666 linear-gradient(to bottom, #999999, #666666 15px, #999999); 32 | } 33 | h3#modalhead { 34 | border: 0px; 35 | padding: 5px 10px 5px 10px; 36 | margin: 0px; 37 | color: #FFFFFF; 38 | background: transparent; 39 | text-shadow: 0px 0px 5px #333333; 40 | text-align: center; 41 | text-indent: 1px; 42 | font-weight: bold; 43 | font-size: 90%; 44 | line-height: 120%; 45 | letter-spacing: 1px; 46 | } 47 | div#modalbody { 48 | padding: 10px; 49 | font-size: 90%; 50 | color: inherit; 51 | background: #FFFFFF; 52 | } 53 | div#modalfoot { 54 | padding: 0px 10px 10px 10px; 55 | color: inherit; 56 | background: #FFFFFF; 57 | } 58 | table { 59 | border: solid 1px #CCCCCC; 60 | padding: 0px; 61 | margin: 0px auto 0px auto; 62 | color: inherit; 63 | background: #FFFFFF; 64 | } 65 | thead, tfoot { 66 | color: #666666; 67 | background: #CCCCCC; 68 | text-shadow: 0px 0px 2px #CCCCCC; 69 | } 70 | thead { 71 | color: inherit; 72 | background: #EEEEEE; 73 | background: #EEEEEE linear-gradient(to bottom, #EEEEEE, #FFFFFF); 74 | } 75 | tfoot { 76 | color: inherit; 77 | background: #EEEEEE; 78 | background: #EEEEEE linear-gradient(to bottom, #FFFFFF, #EEEEEE); 79 | } 80 | tbody.pending { 81 | color: #FFFFFF; 82 | background: #FF6600; 83 | } 84 | tbody.ready { 85 | color: #999999; 86 | background: transparent; 87 | } 88 | tbody.error { 89 | color: #FF6600; 90 | background: transparent; 91 | } 92 | thead th.fi, thead th.accttype, thead th.balance, thead th.timestamp, tbody td.fi, tbody td.accttype, tbody td.balance, tbody td.timestamp, tfoot th { 93 | font-size: 90%; 94 | } 95 | tbody.pending td a:link, tbody.pending td a:hover, tbody.pending td a:visited, tbody.pending td a:active { 96 | color: #FFFFFF; 97 | background: transparent; 98 | } 99 | caption { 100 | border: solid 1px #CCCCCC; 101 | border-radius: 10px 10px 0px 0px; 102 | padding: 5px 10px 5px 10px; 103 | color: inherit; 104 | background: #CCCCCC; 105 | background: #CCCCCC linear-gradient(to bottom, #FFFFFF, #CCCCCC 50%, #FFFFFF); 106 | text-shadow: 0px 0px 5px #999999; 107 | font-size: 85%; 108 | font-weight: bold; 109 | line-height: 150%; 110 | text-indent: 2px; 111 | letter-spacing: 2px; 112 | } 113 | th, td { 114 | border: solid #CCCCCC; 115 | border-width: 1px 0px 1px 0px; 116 | } 117 | th { 118 | font-weight: normal; 119 | } 120 | td.fi { 121 | max-width: 90px; 122 | } 123 | td.accttype { 124 | max-width: 120px; 125 | } 126 | td.timestamp { 127 | max-width: 60px; 128 | } 129 | a:link, a:visited { 130 | color: #FF6600; 131 | background: transparent; 132 | text-decoration: underline; 133 | } 134 | a:hover, a:active { 135 | color: #FF0000; 136 | background: transparent; 137 | } 138 | input[type="button"], input[type="submit"], input[type="reset"] { 139 | min-width: 4em; 140 | border: 0px; 141 | border-radius: 5px; 142 | padding: 8px 10px 8px 10px; 143 | margin: 2px 0px 2px 0px; 144 | color: #FFFFFF; 145 | background: #FF6600; 146 | background: #FF6600 linear-gradient(to bottom, #FF9933, #FF6600 50%, #FF9933); 147 | box-shadow: 0px 0px 2px 0px #666666; 148 | text-shadow: 0px 0px 5px #FF9933; 149 | text-decoration: none; 150 | font-weight: bold; 151 | } 152 | input[type="button"]:hover, input[type="submit"]:hover, input[type="reset"]:hover { 153 | color: #FFFFFF; 154 | background: #CC3300; 155 | background: #CC3300 linear-gradient(to bottom, #FF6600, #CC3300 50%, #FF6600); 156 | } 157 | input[type="button"]:active, input[type="submit"]:active, input[type="reset"]:active { 158 | color: #FFFFFF; 159 | background: #FF6600; 160 | text-shadow: 0px 0px 5px #FF6600; 161 | box-shadow: 0px 0px 2px 0px #FFFFFF; 162 | } 163 | input[type="button"]:disabled, input[type="submit"]:disabled, input[type="reset"]:disabled { 164 | color: #FFFFFF; 165 | background: #999999; 166 | text-shadow: 0px 0px 5px #999999; 167 | box-shadow: 0px 0px 2px 0px #FFFFFF; 168 | } 169 | input[type="button"] + input[type="button"], input[type="submit"] + input[type="reset"] { 170 | margin: 0px 0px 0px 9px; 171 | } 172 | input, select { 173 | font-size: 130%; 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /client/template.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | マネーサウンド 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 |

マネーサウンド

21 |
22 | 25 |
26 |

口座一覧

27 | 28 | 29 | 30 | 31 | 32 |
マネーサウンド
金融機関口座種目残高更新日時
合計0
口座一覧
33 | 34 | 35 | 36 | 39 |
40 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /common.inc: -------------------------------------------------------------------------------- 1 | fi as $fi) { 36 | $id = mb_htmlspecialchars((string)$fi["id"]); 37 | $settings[$id]["fiid"] = mb_htmlspecialchars((string)$id); 38 | $settings[$id]["type"] = mb_htmlspecialchars((string)$fi->type); 39 | $settings[$id]["name"] = mb_htmlspecialchars((string)$fi->name); 40 | $settings[$id]["home"] = mb_htmlspecialchars((string)$fi->home); 41 | if(isset($fi["code"]) == true) $settings[$id]["code"] = mb_htmlspecialchars((string)$fi["code"]); 42 | if(isset($fi->additional) == true) $settings[$id]["additional"] = mb_htmlspecialchars(implode("|", array((string)$fi->additional, (string)$fi->additional["input"], (string)$fi->additional["type"]))); 43 | if(isset($fi->help) == true) $settings[$id]["help"] = preg_replace("/^[\r\n]*([\w\W]*?)<\/help>[\r\n]*$/", "\\1", $fi->help->asXML()); 44 | 45 | $inputs = array(); 46 | foreach($fi->form->input as $input) { 47 | array_push($inputs, mb_htmlspecialchars((string)$input["id"])); 48 | $settings[$id][(string)$input["id"]] = mb_htmlspecialchars(implode("|", array((string)$input, (string)$input["type"]))); 49 | } 50 | $settings[$id]["form"] = implode("|", $inputs); 51 | 52 | if(isset($fi->itemlist) == true) foreach($fi->itemlist->item as $item) $settings[$id][(string)$item["id"]] = mb_htmlspecialchars((string)$item); 53 | } 54 | 55 | $ret = ($fiid != "" && isset($settings[$fiid]) == true? $settings[$fiid]: $settings); 56 | 57 | return $ret; 58 | } 59 | 60 | function mb_htmlspecialchars($str) { 61 | return htmlspecialchars($str, ENT_COMPAT | ENT_XML1, "UTF-8"); 62 | } 63 | 64 | // $codeに合致するHTTP/1.1ステータスコードの文字列を取得する 65 | function get_http_status($code) { 66 | $status = "Unknown Status-code"; 67 | switch((integer)$code) { 68 | // 100 69 | case 100: 70 | $status = "Continue"; 71 | break; 72 | case 101: 73 | $status = "Switching Protocols"; 74 | break; 75 | case 102: 76 | $status = "Processing"; 77 | break; 78 | // 200 79 | case 200: 80 | $status = "OK"; 81 | break; 82 | case 201: 83 | $status = "Created"; 84 | break; 85 | case 202: 86 | $status = "Accepted"; 87 | break; 88 | case 203: 89 | $status = "Non-Authoritative Information"; 90 | break; 91 | case 204: 92 | $status = "No Content"; 93 | break; 94 | case 205: 95 | $status = "Reset Content"; 96 | break; 97 | case 206: 98 | $status = "Partial Content"; 99 | break; 100 | case 207: 101 | $status = "Multi-Status"; 102 | break; 103 | case 208: 104 | $status = "Already Reported"; 105 | break; 106 | case 226: 107 | $status = "IM Used"; 108 | break; 109 | // 300 110 | case 300: 111 | $status = "Multiple Choices"; 112 | break; 113 | case 301: 114 | $status = "Moved Parmanently"; 115 | break; 116 | case 302: 117 | $status = "Found"; 118 | break; 119 | case 303: 120 | $status = "See Other"; 121 | break; 122 | case 304: 123 | $status = "Not Modified"; 124 | break; 125 | case 305: 126 | $status = "Use Proxy"; 127 | break; 128 | case 306: 129 | $status = "(Unused)"; 130 | break; 131 | case 307: 132 | $status = "Temporary Redirect"; 133 | break; 134 | case 308: 135 | $status = "Permanent Redirect"; 136 | break; 137 | // 400 138 | case 400: 139 | $status = "Bad Request"; 140 | break; 141 | case 401: 142 | $status = "Unautorized"; 143 | break; 144 | case 402: 145 | $status = "Payment Required"; 146 | break; 147 | case 403: 148 | $status = "Forbidden"; 149 | break; 150 | case 404: 151 | $status = "Not Found"; 152 | break; 153 | case 405: 154 | $status = "Method Not Allowed"; 155 | break; 156 | case 406: 157 | $status = "Not Acceptable"; 158 | break; 159 | case 407: 160 | $status = "Proxy Authentication Required"; 161 | break; 162 | case 408: 163 | $status = "Request Timeout"; 164 | break; 165 | case 409: 166 | $status = "Conflict"; 167 | break; 168 | case 410: 169 | $status = "Gone"; 170 | break; 171 | case 411: 172 | $status = "Length Required"; 173 | break; 174 | case 412: 175 | $status = "Precondition Failed"; 176 | break; 177 | case 413: 178 | $status = "Request Entity Too Large"; 179 | break; 180 | case 414: 181 | $status = "Request-URI Too Long"; 182 | break; 183 | case 415: 184 | $status = "Unsupported Media Type"; 185 | break; 186 | case 416: 187 | $status = "Requested Range Not Satisfiable"; 188 | break; 189 | case 417: 190 | $status = "Expectation Failed"; 191 | break; 192 | case 422: 193 | $status = "Unprocessable Entity"; 194 | break; 195 | case 423: 196 | $status = "Locked"; 197 | break; 198 | case 424: 199 | $status = "Failed Dependency"; 200 | break; 201 | case 426: 202 | $status = "Upgrade Required"; 203 | break; 204 | case 428: 205 | $status = "Precondition Required"; 206 | break; 207 | case 429: 208 | $status = "Too Many Requests"; 209 | break; 210 | case 431: 211 | $status = "Request Header Fields Too Large"; 212 | break; 213 | // 500 214 | case 500: 215 | $status = "Internal Server Error"; 216 | break; 217 | case 501: 218 | $status = "Not Implemented"; 219 | break; 220 | case 502: 221 | $status = "Bad Gateway"; 222 | break; 223 | case 503: 224 | $status = "Service Unavailable"; 225 | break; 226 | case 504: 227 | $status = "Gateway Timeout"; 228 | break; 229 | case 505: 230 | $status = "HTTP Version Not Supported"; 231 | break; 232 | case 506: 233 | $status = "Variant Also Negotiates"; 234 | break; 235 | case 507: 236 | $status = "Insufficient Storage"; 237 | break; 238 | case 508: 239 | $status = "Loop Detected"; 240 | break; 241 | case 510: 242 | $status = "Not Extended"; 243 | break; 244 | case 511: 245 | $status = "Network Authentication Required"; 246 | break; 247 | default: 248 | // 何もしない 249 | break; 250 | } 251 | return "HTTP/1.1 " . (string)$code . " " . $status; 252 | } 253 | 254 | ?> 255 | -------------------------------------------------------------------------------- /common/ofx.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 14 | 15 | 0INFOJPN 16 | 17 | 18 | -------------------------------------------------------------------------------- /common/pdf.dat: -------------------------------------------------------------------------------- 1 | %PDF-1.2 2 | 3 | 1 0 obj 4 | << 5 | /ProcSet [ /PDF /Text ] 6 | /Font << /F1 2 0 R >> 7 | >> 8 | endobj 9 | 10 | 2 0 obj 11 | << 12 | /Type /Font 13 | /Subtype /Type0 14 | /BaseFont /#82l#82r#83S#83V#83b#83N 15 | /DescendantFonts [ 3 0 R ] 16 | /Encoding /90ms-RKSJ-H 17 | >> 18 | endobj 19 | 20 | 3 0 obj 21 | << 22 | /Type /Font 23 | /Subtype /CIDFontType2 24 | /BaseFont /#82l#82r#83S#83V#83b#83N 25 | /WinCharSet 128 26 | /FontDescriptor 4 0 R 27 | /CIDSystemInfo 28 | << 29 | /Registry (Adobe) 30 | /Ordering (Japan1) 31 | /Supplement 2 32 | >> 33 | /DW 1000 34 | /W [231 389 500 631 631 500] 35 | >> 36 | endobj 37 | 38 | 4 0 obj 39 | << 40 | /Type /FontDescriptor 41 | /FontName /#82l#82r#83S#83V#83b#83N 42 | /Flags 39 43 | /FontBBox [ -150 -147 1100 853 ] 44 | /MissingWidth 507 45 | /StemV 92 46 | /StemH 92 47 | /ItalicAngle 0 48 | /CapHeight 853 49 | /XHeight 597 50 | /Ascent 853 51 | /Descent -147 52 | /Leading 0 53 | /MaxWidth 1000 54 | /AvgWidth 507 55 | /Style << /Panose <0805020B0609000000000000> >> 56 | >> 57 | endobj 58 | 59 | 5 0 obj 60 | << 61 | /Type /Catalog 62 | /Pages 7 0 R 63 | >> 64 | endobj 65 | 66 | 6 0 obj 67 | << 68 | /Title () 69 | /Subject () 70 | /Creator () 71 | /Producer () 72 | /CreationDate (D:+09'00') 73 | >> 74 | endobj 75 | 76 | 7 0 obj 77 | << 78 | /Type /Pages 79 | /Kids [] 80 | /Count 81 | /MediaBox [ 0 0 595 842 ] 82 | >> 83 | endobj 84 | 85 | xref 86 | 0 87 | 0000000000 65535 f 88 | 89 | trailer 90 | << 91 | /Root 5 0 R 92 | /Info 6 0 R 93 | /Size 10 94 | >> 95 | startxref 96 | 97 | %%EOF 98 | -------------------------------------------------------------------------------- /cryptojs.js: -------------------------------------------------------------------------------- 1 | /* 2 | CryptoJS v3.1.2 3 | code.google.com/p/crypto-js 4 | (c) 2009-2013 by Jeff Mott. All rights reserved. 5 | code.google.com/p/crypto-js/wiki/License 6 | */ 7 | var CryptoJS=CryptoJS||function(u,p){var d={},l=d.lib={},s=function(){},t=l.Base={extend:function(a){s.prototype=this;var c=new s;a&&c.mixIn(a);c.hasOwnProperty("init")||(c.init=function(){c.$super.init.apply(this,arguments)});c.init.prototype=c;c.$super=this;return c},create:function(){var a=this.extend();a.init.apply(a,arguments);return a},init:function(){},mixIn:function(a){for(var c in a)a.hasOwnProperty(c)&&(this[c]=a[c]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}}, 8 | r=l.WordArray=t.extend({init:function(a,c){a=this.words=a||[];this.sigBytes=c!=p?c:4*a.length},toString:function(a){return(a||v).stringify(this)},concat:function(a){var c=this.words,e=a.words,j=this.sigBytes;a=a.sigBytes;this.clamp();if(j%4)for(var k=0;k>>2]|=(e[k>>>2]>>>24-8*(k%4)&255)<<24-8*((j+k)%4);else if(65535>>2]=e[k>>>2];else c.push.apply(c,e);this.sigBytes+=a;return this},clamp:function(){var a=this.words,c=this.sigBytes;a[c>>>2]&=4294967295<< 9 | 32-8*(c%4);a.length=u.ceil(c/4)},clone:function(){var a=t.clone.call(this);a.words=this.words.slice(0);return a},random:function(a){for(var c=[],e=0;e>>2]>>>24-8*(j%4)&255;e.push((k>>>4).toString(16));e.push((k&15).toString(16))}return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>3]|=parseInt(a.substr(j, 10 | 2),16)<<24-4*(j%8);return new r.init(e,c/2)}},b=w.Latin1={stringify:function(a){var c=a.words;a=a.sigBytes;for(var e=[],j=0;j>>2]>>>24-8*(j%4)&255));return e.join("")},parse:function(a){for(var c=a.length,e=[],j=0;j>>2]|=(a.charCodeAt(j)&255)<<24-8*(j%4);return new r.init(e,c)}},x=w.Utf8={stringify:function(a){try{return decodeURIComponent(escape(b.stringify(a)))}catch(c){throw Error("Malformed UTF-8 data");}},parse:function(a){return b.parse(unescape(encodeURIComponent(a)))}}, 11 | q=l.BufferedBlockAlgorithm=t.extend({reset:function(){this._data=new r.init;this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=x.parse(a));this._data.concat(a);this._nDataBytes+=a.sigBytes},_process:function(a){var c=this._data,e=c.words,j=c.sigBytes,k=this.blockSize,b=j/(4*k),b=a?u.ceil(b):u.max((b|0)-this._minBufferSize,0);a=b*k;j=u.min(4*a,j);if(a){for(var q=0;q>>2]>>>24-8*(r%4)&255)<<16|(l[r+1>>>2]>>>24-8*((r+1)%4)&255)<<8|l[r+2>>>2]>>>24-8*((r+2)%4)&255,v=0;4>v&&r+0.75*v>>6*(3-v)&63));if(l=t.charAt(64))for(;d.length%4;)d.push(l);return d.join("")},parse:function(d){var l=d.length,s=this._map,t=s.charAt(64);t&&(t=d.indexOf(t),-1!=t&&(l=t));for(var t=[],r=0,w=0;w< 15 | l;w++)if(w%4){var v=s.indexOf(d.charAt(w-1))<<2*(w%4),b=s.indexOf(d.charAt(w))>>>6-2*(w%4);t[r>>>2]|=(v|b)<<24-8*(r%4);r++}return p.create(t,r)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="}})(); 16 | (function(u){function p(b,n,a,c,e,j,k){b=b+(n&a|~n&c)+e+k;return(b<>>32-j)+n}function d(b,n,a,c,e,j,k){b=b+(n&c|a&~c)+e+k;return(b<>>32-j)+n}function l(b,n,a,c,e,j,k){b=b+(n^a^c)+e+k;return(b<>>32-j)+n}function s(b,n,a,c,e,j,k){b=b+(a^(n|~c))+e+k;return(b<>>32-j)+n}for(var t=CryptoJS,r=t.lib,w=r.WordArray,v=r.Hasher,r=t.algo,b=[],x=0;64>x;x++)b[x]=4294967296*u.abs(u.sin(x+1))|0;r=r.MD5=v.extend({_doReset:function(){this._hash=new w.init([1732584193,4023233417,2562383102,271733878])}, 17 | _doProcessBlock:function(q,n){for(var a=0;16>a;a++){var c=n+a,e=q[c];q[c]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360}var a=this._hash.words,c=q[n+0],e=q[n+1],j=q[n+2],k=q[n+3],z=q[n+4],r=q[n+5],t=q[n+6],w=q[n+7],v=q[n+8],A=q[n+9],B=q[n+10],C=q[n+11],u=q[n+12],D=q[n+13],E=q[n+14],x=q[n+15],f=a[0],m=a[1],g=a[2],h=a[3],f=p(f,m,g,h,c,7,b[0]),h=p(h,f,m,g,e,12,b[1]),g=p(g,h,f,m,j,17,b[2]),m=p(m,g,h,f,k,22,b[3]),f=p(f,m,g,h,z,7,b[4]),h=p(h,f,m,g,r,12,b[5]),g=p(g,h,f,m,t,17,b[6]),m=p(m,g,h,f,w,22,b[7]), 18 | f=p(f,m,g,h,v,7,b[8]),h=p(h,f,m,g,A,12,b[9]),g=p(g,h,f,m,B,17,b[10]),m=p(m,g,h,f,C,22,b[11]),f=p(f,m,g,h,u,7,b[12]),h=p(h,f,m,g,D,12,b[13]),g=p(g,h,f,m,E,17,b[14]),m=p(m,g,h,f,x,22,b[15]),f=d(f,m,g,h,e,5,b[16]),h=d(h,f,m,g,t,9,b[17]),g=d(g,h,f,m,C,14,b[18]),m=d(m,g,h,f,c,20,b[19]),f=d(f,m,g,h,r,5,b[20]),h=d(h,f,m,g,B,9,b[21]),g=d(g,h,f,m,x,14,b[22]),m=d(m,g,h,f,z,20,b[23]),f=d(f,m,g,h,A,5,b[24]),h=d(h,f,m,g,E,9,b[25]),g=d(g,h,f,m,k,14,b[26]),m=d(m,g,h,f,v,20,b[27]),f=d(f,m,g,h,D,5,b[28]),h=d(h,f, 19 | m,g,j,9,b[29]),g=d(g,h,f,m,w,14,b[30]),m=d(m,g,h,f,u,20,b[31]),f=l(f,m,g,h,r,4,b[32]),h=l(h,f,m,g,v,11,b[33]),g=l(g,h,f,m,C,16,b[34]),m=l(m,g,h,f,E,23,b[35]),f=l(f,m,g,h,e,4,b[36]),h=l(h,f,m,g,z,11,b[37]),g=l(g,h,f,m,w,16,b[38]),m=l(m,g,h,f,B,23,b[39]),f=l(f,m,g,h,D,4,b[40]),h=l(h,f,m,g,c,11,b[41]),g=l(g,h,f,m,k,16,b[42]),m=l(m,g,h,f,t,23,b[43]),f=l(f,m,g,h,A,4,b[44]),h=l(h,f,m,g,u,11,b[45]),g=l(g,h,f,m,x,16,b[46]),m=l(m,g,h,f,j,23,b[47]),f=s(f,m,g,h,c,6,b[48]),h=s(h,f,m,g,w,10,b[49]),g=s(g,h,f,m, 20 | E,15,b[50]),m=s(m,g,h,f,r,21,b[51]),f=s(f,m,g,h,u,6,b[52]),h=s(h,f,m,g,k,10,b[53]),g=s(g,h,f,m,B,15,b[54]),m=s(m,g,h,f,e,21,b[55]),f=s(f,m,g,h,v,6,b[56]),h=s(h,f,m,g,x,10,b[57]),g=s(g,h,f,m,t,15,b[58]),m=s(m,g,h,f,D,21,b[59]),f=s(f,m,g,h,z,6,b[60]),h=s(h,f,m,g,C,10,b[61]),g=s(g,h,f,m,j,15,b[62]),m=s(m,g,h,f,A,21,b[63]);a[0]=a[0]+f|0;a[1]=a[1]+m|0;a[2]=a[2]+g|0;a[3]=a[3]+h|0},_doFinalize:function(){var b=this._data,n=b.words,a=8*this._nDataBytes,c=8*b.sigBytes;n[c>>>5]|=128<<24-c%32;var e=u.floor(a/ 21 | 4294967296);n[(c+64>>>9<<4)+15]=(e<<8|e>>>24)&16711935|(e<<24|e>>>8)&4278255360;n[(c+64>>>9<<4)+14]=(a<<8|a>>>24)&16711935|(a<<24|a>>>8)&4278255360;b.sigBytes=4*(n.length+1);this._process();b=this._hash;n=b.words;for(a=0;4>a;a++)c=n[a],n[a]=(c<<8|c>>>24)&16711935|(c<<24|c>>>8)&4278255360;return b},clone:function(){var b=v.clone.call(this);b._hash=this._hash.clone();return b}});t.MD5=v._createHelper(r);t.HmacMD5=v._createHmacHelper(r)})(Math); 22 | (function(){var u=CryptoJS,p=u.lib,d=p.Base,l=p.WordArray,p=u.algo,s=p.EvpKDF=d.extend({cfg:d.extend({keySize:4,hasher:p.MD5,iterations:1}),init:function(d){this.cfg=this.cfg.extend(d)},compute:function(d,r){for(var p=this.cfg,s=p.hasher.create(),b=l.create(),u=b.words,q=p.keySize,p=p.iterations;u.length>>2]&255}};d.BlockCipher=v.extend({cfg:v.cfg.extend({mode:b,padding:q}),reset:function(){v.reset.call(this);var a=this.cfg,b=a.iv,a=a.mode;if(this._xformMode==this._ENC_XFORM_MODE)var c=a.createEncryptor;else c=a.createDecryptor,this._minBufferSize=1;this._mode=c.call(a, 28 | this,b&&b.words)},_doProcessBlock:function(a,b){this._mode.processBlock(a,b)},_doFinalize:function(){var a=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE){a.pad(this._data,this.blockSize);var b=this._process(!0)}else b=this._process(!0),a.unpad(b);return b},blockSize:4});var n=d.CipherParams=l.extend({init:function(a){this.mixIn(a)},toString:function(a){return(a||this.formatter).stringify(this)}}),b=(p.format={}).OpenSSL={stringify:function(a){var b=a.ciphertext;a=a.salt;return(a?s.create([1398893684, 29 | 1701076831]).concat(a).concat(b):b).toString(r)},parse:function(a){a=r.parse(a);var b=a.words;if(1398893684==b[0]&&1701076831==b[1]){var c=s.create(b.slice(2,4));b.splice(0,4);a.sigBytes-=16}return n.create({ciphertext:a,salt:c})}},a=d.SerializableCipher=l.extend({cfg:l.extend({format:b}),encrypt:function(a,b,c,d){d=this.cfg.extend(d);var l=a.createEncryptor(c,d);b=l.finalize(b);l=l.cfg;return n.create({ciphertext:b,key:c,iv:l.iv,algorithm:a,mode:l.mode,padding:l.padding,blockSize:a.blockSize,formatter:d.format})}, 30 | decrypt:function(a,b,c,d){d=this.cfg.extend(d);b=this._parse(b,d.format);return a.createDecryptor(c,d).finalize(b.ciphertext)},_parse:function(a,b){return"string"==typeof a?b.parse(a,this):a}}),p=(p.kdf={}).OpenSSL={execute:function(a,b,c,d){d||(d=s.random(8));a=w.create({keySize:b+c}).compute(a,d);c=s.create(a.words.slice(b),4*c);a.sigBytes=4*b;return n.create({key:a,iv:c,salt:d})}},c=d.PasswordBasedCipher=a.extend({cfg:a.cfg.extend({kdf:p}),encrypt:function(b,c,d,l){l=this.cfg.extend(l);d=l.kdf.execute(d, 31 | b.keySize,b.ivSize);l.iv=d.iv;b=a.encrypt.call(this,b,c,d.key,l);b.mixIn(d);return b},decrypt:function(b,c,d,l){l=this.cfg.extend(l);c=this._parse(c,l.format);d=l.kdf.execute(d,b.keySize,b.ivSize,c.salt);l.iv=d.iv;return a.decrypt.call(this,b,c,d.key,l)}})}(); 32 | (function(){for(var u=CryptoJS,p=u.lib.BlockCipher,d=u.algo,l=[],s=[],t=[],r=[],w=[],v=[],b=[],x=[],q=[],n=[],a=[],c=0;256>c;c++)a[c]=128>c?c<<1:c<<1^283;for(var e=0,j=0,c=0;256>c;c++){var k=j^j<<1^j<<2^j<<3^j<<4,k=k>>>8^k&255^99;l[e]=k;s[k]=e;var z=a[e],F=a[z],G=a[F],y=257*a[k]^16843008*k;t[e]=y<<24|y>>>8;r[e]=y<<16|y>>>16;w[e]=y<<8|y>>>24;v[e]=y;y=16843009*G^65537*F^257*z^16843008*e;b[k]=y<<24|y>>>8;x[k]=y<<16|y>>>16;q[k]=y<<8|y>>>24;n[k]=y;e?(e=z^a[a[a[G^z]]],j^=a[a[j]]):e=j=1}var H=[0,1,2,4,8, 33 | 16,32,64,128,27,54],d=d.AES=p.extend({_doReset:function(){for(var a=this._key,c=a.words,d=a.sigBytes/4,a=4*((this._nRounds=d+6)+1),e=this._keySchedule=[],j=0;j>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255]):(k=k<<8|k>>>24,k=l[k>>>24]<<24|l[k>>>16&255]<<16|l[k>>>8&255]<<8|l[k&255],k^=H[j/d|0]<<24);e[j]=e[j-d]^k}c=this._invKeySchedule=[];for(d=0;dd||4>=j?k:b[l[k>>>24]]^x[l[k>>>16&255]]^q[l[k>>> 34 | 8&255]]^n[l[k&255]]},encryptBlock:function(a,b){this._doCryptBlock(a,b,this._keySchedule,t,r,w,v,l)},decryptBlock:function(a,c){var d=a[c+1];a[c+1]=a[c+3];a[c+3]=d;this._doCryptBlock(a,c,this._invKeySchedule,b,x,q,n,s);d=a[c+1];a[c+1]=a[c+3];a[c+3]=d},_doCryptBlock:function(a,b,c,d,e,j,l,f){for(var m=this._nRounds,g=a[b]^c[0],h=a[b+1]^c[1],k=a[b+2]^c[2],n=a[b+3]^c[3],p=4,r=1;r>>24]^e[h>>>16&255]^j[k>>>8&255]^l[n&255]^c[p++],s=d[h>>>24]^e[k>>>16&255]^j[n>>>8&255]^l[g&255]^c[p++],t= 35 | d[k>>>24]^e[n>>>16&255]^j[g>>>8&255]^l[h&255]^c[p++],n=d[n>>>24]^e[g>>>16&255]^j[h>>>8&255]^l[k&255]^c[p++],g=q,h=s,k=t;q=(f[g>>>24]<<24|f[h>>>16&255]<<16|f[k>>>8&255]<<8|f[n&255])^c[p++];s=(f[h>>>24]<<24|f[k>>>16&255]<<16|f[n>>>8&255]<<8|f[g&255])^c[p++];t=(f[k>>>24]<<24|f[n>>>16&255]<<16|f[g>>>8&255]<<8|f[h&255])^c[p++];n=(f[n>>>24]<<24|f[g>>>16&255]<<16|f[h>>>8&255]<<8|f[k&255])^c[p++];a[b]=q;a[b+1]=s;a[b+2]=t;a[b+3]=n},keySize:8});u.AES=p._createHelper(d)})(); 36 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 24 | -------------------------------------------------------------------------------- /index.txt: -------------------------------------------------------------------------------- 1 | PHP関数インデックス 2 | 3 | ■(boolean)env_dlog((string)$html, (string)$tag) 4 | 【説明】 5 | ENV_BOOL_DEBUGがtrueの場合、デバッグログを出力する。 6 | 7 | ■(array)get_fi_settings((string)$fiid = "") { 8 | 【説明】 9 | XMLファイルより$fiidセクションの定義を取得する。 10 | 11 | ■(string)mb_htmlspecialchars((string)$str) 12 | 【説明】 13 | 特殊文字をXHTMLエンティティーを変換する。 14 | 15 | ■(string)sess_encode((string)$str) 16 | 【説明】 17 | $strよりセッション保持用文字列を作成する。 18 | 19 | ■(string)sess_decode((string)$str) 20 | 【説明】 21 | セッション保持用文字列($str)より元データを取得する。 22 | 23 | ■(string)mb_convert_uniqueid((string)$str) 24 | 【説明】 25 | $strより32バイトの一意な文字列を生成する。 26 | 27 | ■(string)mb_convert_uniquename((string)$str) 28 | 【説明】 29 | 文字列を正規化する。 30 | 31 | ■(string)mb_convert_string((string)$str) 32 | 【説明】 33 | 文字エンコーディングをShift_JISからUTF-8へと変換する。 34 | 35 | ■class ofxDOM 36 | Copyright (C) 2012-2017 Hiromu Takahashi All Rights Reserved. 37 | mailto:hiromu2000@hotmail.com 38 | 39 | ■(string)parse_amount((string)$str) 40 | 【説明】 41 | 金額をパースする。 42 | 43 | ■(string)parse_date((string)$str) 44 | 【説明】 45 | 日付をパースする。 46 | 47 | ■(string)parse_param((string)$str) 48 | 【説明】 49 | フォーム経由で送受信されるパラメータをパースする。 50 | ※urlencode()やurldecode()で変換されない文字列も変換する。 51 | 52 | ■(array)parse_tag((string)$html, (string)$tag, (boolean)$recursive) 53 | 【説明】 54 | 指定された開始タグから終了タグまでのHTML、およびタグの属性を取得する。 55 | $recursiveがtrueの場合、タグの入れ子内部も再帰的に取得する。 56 | 【例】 57 | $html = "" . "
"; 58 | $tag = "select"; 59 | parse_tag($html, $tag) = array(2) { 60 | [0]=> 61 | array(3) { 62 | ["name"]=> 63 | string(3) "abc" 64 | ["class"]=> 65 | string(1) "x" 66 | ["innerHTML"]=> 67 | string(76) "" 68 | } 69 | [1]=> 70 | array(3) { 71 | ["name"]=> 72 | string(3) "def" 73 | ["class"]=> 74 | string(1) "Y" 75 | ["innerHTML"]=> 76 | string(73) "" 77 | } 78 | } 79 | 80 | ■(array)parse_tag_attributes((string)$html, (string)$tag) 81 | 【説明】 82 | 指定されたタグの属性を取得する。 83 | 【例】 84 | $html = "" . ""; 85 | $tag = "input"; 86 | parse_tag_attributes($html, $tag) = array(2) { 87 | [0]=> 88 | array(3) { 89 | ["type"]=> 90 | string(4) "text" 91 | ["name"]=> 92 | string(3) "abc" 93 | ["value"]=> 94 | string(0) "" 95 | } 96 | [1]=> 97 | array(3) { 98 | ["type"]=> 99 | string(6) "HIDDEN" 100 | ["name"]=> 101 | string(3) "def" 102 | ["value"]=> 103 | string(3) "xyz" 104 | } 105 | } 106 | 107 | ■(integer)parse_tag_search((array)$tags, (string)$key, (string)$value) 108 | 【説明】 109 | 指定されたタグ配列より属性が一致($key=$value)するタグの配列番号を取得する。 110 | 【例】 111 | $tags = array(); 112 | $tags[0] = array("type" => "text", "name" => "abc", "value" => "", "innerHTML" => ""); 113 | $tags[1] = array("type" => "hidden", "name" => "def", "value" => "xyz", "innerHTML" => ""); 114 | $key = "name"; 115 | $value = "def"; 116 | parse_tag_search($tags, $key, $value) = int(1) 117 | 118 | ■(array)parse_header((string)$http, (string)$head) 119 | 【説明】 120 | $headに一致するHTTPヘッダーの配列を取得する。 121 | 122 | ■(array)parse_uri((string)$uri_next, (array)$uris = array()) 123 | 【説明】 124 | $uri_nextを$urisからの絶対・相対パスURIとしてパースする。 125 | PHPの標準関数parse_url()と異なり、クエリーは"query"ではなく、"path"に含めて返却する。 126 | 【例】 127 | $uri_next = "../global.html?lang=en"; 128 | $uris = array(); 129 | $uris["scheme"] = "http"; 130 | $uris["host"] = "www.example.com"; 131 | $uris["path"] = "/japan/index.html"; 132 | parse_uri($uri_next, $uris) = array(3) { 133 | ["scheme"]=> 134 | string(4) "http" 135 | ["host"]=> 136 | string(15) "www.example.com" 137 | ["path"]=> 138 | string(19) "/global.html?lang=en" 139 | } 140 | 141 | ■(array)parse_csv((string)$csv, (string)$delimiter = ",", (string)$enclosure = "\"") 142 | 【説明】 143 | CSV形式のデータをパースする。 144 | 145 | ■(string)http11((string)$method, (string)$protocol, (string)$host, (integer)$port = 0, (string)$page = "/", (string)$query = "", (string)$basic = "", (string)$cookie = "", (boolean)$autoconv = true, (string)$ua = ENV_PRODUCT_UA, (string)$fr = "", (string)$referer = "") 146 | 【説明】 147 | HTTP/1.1プロトコルでアクセスする。 148 | 149 | ■(string)http11_fread_blocking((resource)$fp, (integer)$len) 150 | 【説明】 151 | Chunkedのデータをfreadで読み込みする際、指定サイズ未満しか取得できない場合があるのを改善する。 152 | 153 | ■(string)update_cookie((array)$memories, (array)$heads, (string)$cookie) 154 | 【説明】 155 | $memoriesに存在するキーを$headsより探し、$cookieの値を更新する。 156 | 157 | ■(string)convert_ofx((string)$ofx) 158 | 【説明】 159 | OFX 1.0.2からOFX 2.1.1へと整形する。 160 | 161 | ■(string)generate_ofx((string)$status, (string)$str = ENV_STR_OFX_NODATA, (string)$cook = "", (string)$akey = "") 162 | 【説明】 163 | テンプレートよりOFX 2.1.1を生成する。 164 | 165 | ■(string)generate_html((string)$settings, (array)$resp) 166 | 【説明】 167 | テンプレートよりHTMLを生成する。 168 | 169 | ■(string)get_http_status((integer)$code) 170 | 【説明】 171 | $codeに合致するHTTP/1.1ステータスコードの文字列を取得する。 172 | 173 | -------------------------------------------------------------------------------- /log/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/outerguy/moneysound/fc8d6f8ce19b7fd79aa418d2de4dd193bfaced7b/log/.gitkeep -------------------------------------------------------------------------------- /php.ini: -------------------------------------------------------------------------------- 1 | [PHP] 2 | extension_dir = ".\ext"; 3 | extension=php_mbstring.dll 4 | extension=php_openssl.dll 5 | 6 | [Date] 7 | date.timezone = "Asia/Tokyo" 8 | -------------------------------------------------------------------------------- /php_mac.ini: -------------------------------------------------------------------------------- 1 | [Date] 2 | date.timezone = "Asia/Tokyo" 3 | -------------------------------------------------------------------------------- /server.php: -------------------------------------------------------------------------------- 1 | 64 | -------------------------------------------------------------------------------- /server/chocom.inc: -------------------------------------------------------------------------------- 1 | 0) { 32 | $method = "GET"; 33 | $uris = parse_uri($locations[0], $uris); 34 | $query = ""; 35 | $cookie = chocom_update_cookie($head, $cookie); 36 | list($head, $body) = chocom_http11($method, $uris, $query, $cookie); 37 | } 38 | } 39 | 40 | // ログイン画面を取得する 41 | $as = parse_tag($body, "a"); 42 | foreach($as as $a) if(parse_tag_search(parse_tag($a["innerHTML"], "img"), "alt", "会員ログイン") != -1) { 43 | $method = "GET"; 44 | $uris = parse_uri($a["href"], $uris); 45 | $query = ""; 46 | $cookie = chocom_update_cookie($head, $cookie); 47 | list($head, $body) = chocom_http11($method, $uris, $query, $cookie); 48 | break; 49 | } 50 | 51 | // リダイレクトする 52 | $scripts = parse_tag($body, "script"); 53 | foreach($scripts as $script) if(preg_match("/location\.replace\(\'(.*?)\'/i", $script["innerHTML"], $matches) > 0) { 54 | $method = "GET"; 55 | $uris = parse_uri($matches[1], $uris); 56 | $query = ""; 57 | $cookie = chocom_update_cookie($head, $cookie); 58 | list($head, $body) = chocom_http11($method, $uris, $query, $cookie); 59 | break; 60 | } 61 | 62 | // ログインする 63 | $forms = parse_tag($body, "form"); 64 | $c = parse_tag_search($forms, "name", "form1"); 65 | if($c != -1) { 66 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 67 | $queries = array(); 68 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 69 | $queries["MAILADDR"] = "MAILADDR=" . $user; 70 | $queries["TELEPHONE"] = "TELEPHONE=" . $tel; 71 | $queries["PASSWORD"] = "PASSWORD=" . $pass; 72 | 73 | $method = $forms[$c]["method"]; 74 | $uris = parse_uri($forms[$c]["action"], $uris); 75 | $query = implode("&", $queries); 76 | $cookie = chocom_update_cookie($head, $cookie); 77 | list($head, $body) = chocom_http11($method, $uris, $query, $cookie); 78 | } 79 | 80 | if(strpos($body, "ログインすることが出来ませんでした") !== false) { 81 | // システムメンテナンス画面の場合 82 | $resp["status"] = ENV_NUM_STATUS_MAINTENANCE; 83 | $resp["method"] = $method; 84 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 85 | $resp["query"] = $query; 86 | $resp["cookie"] = $cookie; 87 | $resp["head"] = $head; 88 | $resp["body"] = $body; 89 | $resp["ofx"] = generate_ofx($resp["status"]); 90 | } else if(strpos($body, "ご利用履歴") === false) { 91 | // ログイン失敗の場合 92 | $resp["status"] = ENV_NUM_STATUS_FAILURE; 93 | $resp["method"] = $method; 94 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 95 | $resp["query"] = $query; 96 | $resp["cookie"] = $cookie; 97 | $resp["head"] = $head; 98 | $resp["body"] = $body; 99 | $resp["ofx"] = generate_ofx($resp["status"]); 100 | } else { 101 | // ログアウト画面を退避する 102 | $forms = parse_tag($body, "form"); 103 | $c = parse_tag_search($forms, "name", "clickChecker"); 104 | if($c != -1) { 105 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 106 | $queries = array(); 107 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 108 | $queries["clickCounter"] = "clickCounter=1"; 109 | 110 | $method_old = $forms[$c]["method"]; 111 | $uris_old = parse_uri($forms[$c]["action"], $uris); 112 | $query_old = implode("&", $queries); 113 | } 114 | 115 | $account = array(); 116 | 117 | $account["acctname"] = $settings["name"] . ENV_CHR_CONCATENATOR . $user; 118 | 119 | // 支店番号を取得する 120 | if(preg_match("/" . preg_quote("貯金箱番号") . "[\s\t]*([0-9]+)/", $body, $matches) > 0) $account["branchid"] = $matches[1]; 121 | 122 | // 口座番号を取得する 123 | if(preg_match("/\.Com\-ID[\s\t]*([0-9]{4}\-[0-9]{4}\-[0-9]{4}\-[0-9]{4}\-[0-9]{4}\-[0-9])/", $body, $matches) > 0) $account["acctid"] = str_replace("-", "", $matches[1]); 124 | 125 | // 残高を取得する 126 | if(preg_match("/" . preg_quote("貯金箱残高") . "[\s\t]*:[\s\t]*([0-9]+)/", $body, $matches) > 0) $account["balance"] = parse_amount($matches[1]); 127 | 128 | // 履歴残高照会画面を取得する 129 | $as = parse_tag($body, "a"); 130 | $c = parse_tag_search($as, "innerHTML", "履歴照会"); 131 | if($c != -1) { 132 | $method = "GET"; 133 | $uris = parse_uri($as[$c]["href"], $uris); 134 | $query = ""; 135 | $cookie = chocom_update_cookie($head, $cookie); 136 | list($head, $body) = chocom_http11($method, $uris, $query, $cookie, false); // 文字コードを変換しない 137 | } 138 | 139 | // 履歴表示画面(1ページ目)を取得する 140 | $forms = parse_tag($body, "form"); 141 | $c = parse_tag_search($forms, "name", "sForm"); 142 | if($c != -1) { 143 | $queries = array(); 144 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 145 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 146 | $selects = parse_tag($forms[$c]["innerHTML"], "select"); 147 | foreach($selects as $select) { 148 | $options = parse_tag($select["innerHTML"], "option"); 149 | foreach($options as $option) if($select["name"] != "" && $option["selected"] == "selected") $queries[$select["name"]] = urlencode($select["name"]) . "=" . urlencode($option["value"]); 150 | } 151 | $queries["yearStart"] = "yearStart=" . (string)(integer)substr(ENV_STR_DATE_PASTDAY, 0, 4); 152 | $queries["monthStart"] = "monthStart=" . (string)(integer)substr(ENV_STR_DATE_PASTDAY, 4, 2); 153 | $queries["dayStart"] = "dayStart=" . (string)(integer)substr(ENV_STR_DATE_PASTDAY, 6, 2); 154 | $queries["yearFinish"] = "yearFinish=" . (string)(integer)substr(ENV_STR_DATE_TODAY, 0, 4); 155 | $queries["monthFinish"] = "monthFinish=" . (string)(integer)substr(ENV_STR_DATE_TODAY, 4, 2); 156 | $queries["dayFinish"] = "dayFinish=" . (string)(integer)substr(ENV_STR_DATE_TODAY, 6, 2); 157 | 158 | $method = $forms[$c]["method"]; 159 | $uris = parse_uri($forms[$c]["action"], $uris); 160 | $query = implode("&", $queries); 161 | $cookie = chocom_update_cookie($head, $cookie); 162 | list($head, $body) = chocom_http11($method, $uris, $query, $cookie, false); // 文字コードを変換しない 163 | } 164 | 165 | $account["details"] = chocom_get_details($body); 166 | 167 | // 履歴表示画面(2ページ目以降)を取得する 168 | while(parse_tag_search(parse_tag($body, "a"), "innerHTML", "以前の履歴") != -1) { 169 | $forms = parse_tag($body, "form"); 170 | $c = parse_tag_search($forms, "name", "hisForm"); 171 | if($c != -1) { 172 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 173 | $queries = array(); 174 | foreach($inputs as $input) { 175 | switch($input["name"]) { 176 | case "": 177 | // 何もしない 178 | break; 179 | case "E2BURL": 180 | $forms[$c]["action"] = $input["value"]; 181 | // breakしない 182 | default: 183 | $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 184 | break; 185 | } 186 | } 187 | $queries["REQ_PAGE"] = "REQ_PAGE=NEXT"; 188 | 189 | $method = $forms[$c]["method"]; 190 | $uris = parse_uri($forms[$c]["action"], $uris); 191 | $query = implode("&", $queries); 192 | $cookie = chocom_update_cookie($head, $cookie); 193 | list($head, $body) = chocom_http11($method, $uris, $query, $cookie, false); // 文字コードを変換しない 194 | 195 | $account["details"] = array_merge(chocom_get_details($body), $account["details"]); 196 | } 197 | } 198 | 199 | // 実行時間(タイムアウト)を再設定する 200 | @set_time_limit(ENV_NUM_TIMEOUT); 201 | 202 | // ログアウトする 203 | $method = $method_old; 204 | $uris = $uris_old; 205 | $query = $query_old; 206 | $cookie = chocom_update_cookie($head, $cookie); 207 | list($head, $body) = chocom_http11($method, $uris, $query, $cookie); 208 | 209 | // リダイレクトする 210 | $retry = 0; 211 | while($retry++ < ENV_NUM_HTTP11_RETRY) { 212 | $locations = parse_header($head, "location"); 213 | if(count($locations) > 0) { 214 | $method = "GET"; 215 | $uris = parse_uri($locations[0], $uris); 216 | $query = ""; 217 | $cookie = chocom_update_cookie($head, $cookie); 218 | list($head, $body) = chocom_http11($method, $uris, $query, $cookie); 219 | } 220 | } 221 | 222 | // 実行時間(タイムアウト)を再設定する 223 | @set_time_limit(ENV_NUM_TIMEOUT); 224 | 225 | $bankmsgsrsv1 = ""; 226 | $bankmsgsrsv1 .= ""; 227 | $bankmsgsrsv1 .= "\r\n"; 228 | 229 | // 口座情報を取得する 230 | $bankmsgsrsv1 .= ""; 231 | $bankmsgsrsv1 .= "\r\n"; 232 | $bankmsgsrsv1 .= "0"; 233 | $bankmsgsrsv1 .= "\r\n"; 234 | $bankmsgsrsv1 .= "0INFO"; 235 | $bankmsgsrsv1 .= "\r\n"; 236 | $bankmsgsrsv1 .= ""; 237 | $bankmsgsrsv1 .= "\r\n"; 238 | $bankmsgsrsv1 .= "" . ENV_STR_OFX_CURRENCY_JPY . ""; 239 | $bankmsgsrsv1 .= "\r\n"; 240 | $bankmsgsrsv1 .= ""; 241 | $bankmsgsrsv1 .= "" . $settings["code"] . ""; 242 | $bankmsgsrsv1 .= "" . $account["branchid"] . ""; 243 | $bankmsgsrsv1 .= "" . $account["acctid"] . ""; 244 | $bankmsgsrsv1 .= "" . ENV_STR_ACCTTYPE_CHECKING . ""; 245 | $bankmsgsrsv1 .= ""; 246 | $bankmsgsrsv1 .= "\r\n"; 247 | $bankmsgsrsv1 .= chocom_parse_details($account); 248 | $bankmsgsrsv1 .= ""; 249 | $bankmsgsrsv1 .= "\r\n"; 250 | $bankmsgsrsv1 .= ""; 251 | $bankmsgsrsv1 .= "\r\n"; 252 | 253 | $bankmsgsrsv1 .= ""; 254 | $bankmsgsrsv1 .= "\r\n"; 255 | 256 | // OFXファイルを出力する 257 | $resp["status"] = ENV_NUM_STATUS_SUCCESS; 258 | $resp["ofx"] = generate_ofx($resp["status"], $bankmsgsrsv1); 259 | } 260 | return $resp; 261 | 262 | // HTTP/1.1 263 | function chocom_http11($method, $uris, $query = "", $cookie = "", $autoconv = true) { 264 | $ret = "INVALID HOST"; 265 | if(preg_match("/\.chocom\.(?:jp|net)$/", $uris["host"]) > 0) $ret = http11(strtoupper($method), $uris["scheme"], $uris["host"], 0, $uris["path"], $query, "", $cookie, $autoconv); 266 | return explode("\r\n\r\n", $ret, 2); 267 | } 268 | 269 | function chocom_update_cookie($head, $cookie) { 270 | return update_cookie(array("AlteonP", "JSESSIONID"), parse_header($head, "set-cookie"), $cookie); 271 | } 272 | 273 | function chocom_get_details($body) { 274 | $rets = array(); 275 | $i = 0; 276 | $trs = parse_tag(mb_convert_string($body), "tr"); 277 | foreach($trs as $tr) { 278 | $tds = parse_tag($tr["innerHTML"], "td"); 279 | if(count($tds) == 6) { 280 | // 利用日付を取得する 281 | $rets[$i]["date"] = parse_date(trim(strip_tags($tds[0]["innerHTML"]))); 282 | 283 | // ご利用先を取得する 284 | $name1 = str_replace(" ", "", trim(strip_tags($tds[1]["innerHTML"]))); 285 | $name2 = str_replace(" ", "", trim(strip_tags($tds[3]["innerHTML"]))); 286 | $rets[$i]["summary"] = ($name1 == "" || $name2 == ""? $name1 . $name2: implode(ENV_CHR_CONCATENATOR, array($name1, $name2))); 287 | 288 | // ご利用金額を取得する 289 | $rets[$i]["amount"] = parse_amount($tds[4]["innerHTML"]); 290 | 291 | $i++; 292 | } 293 | } 294 | 295 | return $rets; 296 | } 297 | 298 | function chocom_parse_details($account) { 299 | $ret = ""; 300 | $cds = array(); 301 | $cd_date = ""; 302 | $cd_num = 0; 303 | foreach($account["details"] as $line) { 304 | $cd = array(); 305 | $cd["TRNTYPE"] = ENV_STR_OFX_TRNTYPE_DIRECTDEBIT; 306 | 307 | // 日付を取得する 308 | $cd["DTPOSTED"] = $line["date"]; 309 | 310 | // 通番を生成する 311 | if($cd["DTPOSTED"] == $cd_date) $cd_num++; else $cd_num = 0; 312 | 313 | // トランザクション番号を生成する 314 | $cd["FITID"] = $cd["DTPOSTED"] . "0000000" . sprintf("%05d", $cd_num); 315 | 316 | // 摘要を取得する 317 | $cd["NAME"] = $line["summary"]; 318 | 319 | // 金額を取得する 320 | $cd["TRNAMT"] = parse_amount($line["amount"]); 321 | $cd["MEMO"] = ENV_STR_OFX_MEMO; 322 | 323 | array_push($cds, $cd); 324 | $cd_date = $cd["DTPOSTED"]; 325 | } 326 | // BANKTRANLIST 327 | $ret .= ""; 328 | $ret .= "\r\n"; 329 | $ret .= "" . ENV_STR_DATE_PASTDAY . ENV_STR_OFX_TZ . ""; 330 | $ret .= "" . ENV_STR_DATE_TODAY . ENV_STR_OFX_TZ . ""; 331 | $ret .= "\r\n"; 332 | 333 | foreach($cds as $cd) { 334 | $ret .= ""; 335 | $ret .= "" . $cd["TRNTYPE"] . ""; 336 | $ret .= "" . $cd["DTPOSTED"] . ENV_STR_OFX_TZ . ""; 337 | $ret .= "" . $cd["TRNAMT"] . ""; 338 | $ret .= "" . $cd["FITID"] . ""; 339 | $ret .= "" . $cd["NAME"] . ""; 340 | $ret .= "" . $cd["MEMO"] . ""; 341 | $ret .= ""; 342 | $ret .= "\r\n"; 343 | } 344 | 345 | $ret .= ""; 346 | $ret .= "\r\n"; 347 | $ret .= ""; 348 | $ret .= "" . $account["balance"] . ""; 349 | $ret .= "" . ENV_STR_DATE_TODAY . ENV_STR_OFX_TZ . ""; 350 | $ret .= ""; 351 | $ret .= "\r\n"; 352 | 353 | // 口座名称を出力する 354 | if($account["acctname"] != "") { 355 | $ret .= "" . $account["acctname"] . ""; 356 | $ret .= "\r\n"; 357 | } 358 | 359 | return $ret; 360 | } 361 | 362 | ?> 363 | -------------------------------------------------------------------------------- /server/jaccscard.inc: -------------------------------------------------------------------------------- 1 | 0) { 76 | $method = "GET"; 77 | $uris = parse_uri($locations[0], $uris); 78 | $query = ""; 79 | $cookie = jaccscard_update_cookie($head, $cookie); 80 | list($head, $body) = jaccscard_http11($method, $uris, $query, $cookie); 81 | } 82 | } 83 | 84 | if(strpos($body, "メンテナンスを行っております") !== false) { 85 | // システムメンテナンス画面の場合 86 | $resp["status"] = ENV_NUM_STATUS_MAINTENANCE; 87 | $resp["method"] = $method; 88 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 89 | $resp["query"] = $query; 90 | $resp["cookie"] = $cookie; 91 | $resp["head"] = $head; 92 | $resp["body"] = $body; 93 | $resp["ofx"] = generate_ofx($resp["status"]); 94 | } else if(strpos($body, "前回ログイン") === false) { 95 | // ログイン失敗の場合 96 | $resp["status"] = ENV_NUM_STATUS_FAILURE; 97 | $resp["method"] = $method; 98 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 99 | $resp["query"] = $query; 100 | $resp["cookie"] = $cookie; 101 | $resp["head"] = $head; 102 | $resp["body"] = $body; 103 | $resp["ofx"] = generate_ofx($resp["status"]); 104 | } else { 105 | $account = array(); 106 | 107 | // 実行時間(タイムアウト)を再設定する 108 | @set_time_limit(ENV_NUM_TIMEOUT); 109 | 110 | // ご利用状況の確認画面を取得する 111 | $forms = parse_tag($body, "form"); 112 | $c = parse_tag_search($forms, "name", "MainForm"); 113 | if($c != -1) { 114 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 115 | $queries = array(); 116 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 117 | $queries["_TRANID"] = "_TRANID=JAMY00001_01M"; // ご利用状況の確認 118 | 119 | $method = $forms[$c]["method"]; 120 | $uris = parse_uri($forms[$c]["action"], $uris); 121 | $query = implode("&", $queries); 122 | $cookie = jaccscard_update_cookie($head, $cookie); 123 | list($head, $body) = jaccscard_http11($method, $uris, $query, $cookie); 124 | } 125 | 126 | // ご利用代金明細を見る画面を取得する 127 | $forms = parse_tag($body, "form"); 128 | $c = parse_tag_search($forms, "name", "MainForm"); 129 | if($c != -1) { 130 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 131 | $queries = array(); 132 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 133 | $queries["_TRANID"] = "_TRANID=JAST00001_21M"; // ご利用代金明細を見る 134 | $queries["_SUBINDEX"] = "_SUBINDEX=0"; // (カードが複数枚存在する場合)最初のカード 135 | 136 | $method = $forms[$c]["method"]; 137 | $uris = parse_uri($forms[$c]["action"], $uris); 138 | $query = implode("&", $queries); 139 | $cookie = jaccscard_update_cookie($head, $cookie); 140 | list($head, $body) = jaccscard_http11($method, $uris, $query, $cookie); 141 | } 142 | 143 | // お支払日を取得する 144 | $trs = parse_tag($body, "tr", true); // 再帰的に取得する 145 | $c = parse_tag_search($trs, "class", "first"); 146 | if($c != -1) { 147 | $tds = parse_tag($trs[$c]["innerHTML"], "td"); 148 | if(count($tds) >= 1) $account["paydate"] = parse_date(trim(str_replace("\t", "", $tds[0]["innerHTML"]))); 149 | } 150 | 151 | // カード名・カード番号を取得する 152 | $dds = parse_tag($body, "dd"); 153 | if(count($dds) >= 2) { 154 | $account["acctname"] = implode(ENV_CHR_CONCATENATOR, array($settings["name"], $dds[0]["innerHTML"])); 155 | $account["name"] = $settings["name"]; 156 | $account["acctid"] = strip_tags(str_replace("∗", "*", $dds[1]["innerHTML"])); 157 | } 158 | 159 | $body_old = $body; 160 | 161 | // CSVファイルをダウンロードする 162 | $forms = parse_tag($body, "form"); 163 | $c = parse_tag_search($forms, "name", "MainForm"); 164 | if($c != -1) { 165 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 166 | $queries = array(); 167 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 168 | $queries["_TRANID"] = "_TRANID=JAST00016_23C"; // 明細をCSVで保存する 169 | 170 | $method = $forms[$c]["method"]; 171 | $uris = parse_uri($forms[$c]["action"], $uris); 172 | $query = implode("&", $queries); 173 | $cookie = jaccscard_update_cookie($head, $cookie); 174 | list($head, $body) = jaccscard_http11($method, $uris, $query, $cookie); 175 | 176 | if(strpos($head, "Content-Type: text/html") === false) { 177 | $creditcardmsgsrsv1 = ""; 178 | $creditcardmsgsrsv1 .= ""; 179 | $creditcardmsgsrsv1 .= "\r\n"; 180 | 181 | $creditcardmsgsrsv1 .= ""; 182 | $creditcardmsgsrsv1 .= "\r\n"; 183 | $creditcardmsgsrsv1 .= "0"; 184 | $creditcardmsgsrsv1 .= "\r\n"; 185 | $creditcardmsgsrsv1 .= "0INFO"; 186 | $creditcardmsgsrsv1 .= "\r\n"; 187 | $creditcardmsgsrsv1 .= ""; 188 | $creditcardmsgsrsv1 .= "\r\n"; 189 | $creditcardmsgsrsv1 .= "" . ENV_STR_OFX_CURRENCY_JPY . ""; 190 | $creditcardmsgsrsv1 .= "\r\n"; 191 | $creditcardmsgsrsv1 .= ""; 192 | $creditcardmsgsrsv1 .= "" . $account["acctid"] . ""; 193 | $creditcardmsgsrsv1 .= ""; 194 | $creditcardmsgsrsv1 .= "\r\n"; 195 | $creditcardmsgsrsv1 .= jaccscard_parse_csv($body, $account); 196 | $creditcardmsgsrsv1 .= ""; 197 | $creditcardmsgsrsv1 .= "\r\n"; 198 | $creditcardmsgsrsv1 .= ""; 199 | $creditcardmsgsrsv1 .= "\r\n"; 200 | 201 | $creditcardmsgsrsv1 .= ""; 202 | $creditcardmsgsrsv1 .= "\r\n"; 203 | } 204 | 205 | } 206 | 207 | $body = $body_old; 208 | 209 | // 実行時間(タイムアウト)を再設定する 210 | @set_time_limit(ENV_NUM_TIMEOUT); 211 | 212 | // ログアウトする 213 | $forms = parse_tag($body, "form"); 214 | $c = parse_tag_search($forms, "name", "MainForm"); 215 | if($c != -1) { 216 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 217 | $queries = array(); 218 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 219 | $queries["_TRANID"] = "_TRANID=JALG00012_00M"; // ログアウト 220 | 221 | $method = $forms[$c]["method"]; 222 | $uris = parse_uri($forms[$c]["action"], $uris); 223 | $query = implode("&", $queries); 224 | $cookie = jaccscard_update_cookie($head, $cookie); 225 | list($head, $body) = jaccscard_http11($method, $uris, $query, $cookie); 226 | } 227 | 228 | // OFXファイルを出力する 229 | $resp["status"] = ENV_NUM_STATUS_SUCCESS; 230 | if(strpos($creditcardmsgsrsv1, "") === false) { 231 | // 明細が存在しない場合 232 | $resp["ofx"] = generate_ofx($resp["status"]); 233 | } else { 234 | // 明細が存在する場合 235 | $resp["ofx"] = generate_ofx($resp["status"], $creditcardmsgsrsv1); 236 | } 237 | } 238 | return $resp; 239 | 240 | // HTTP/1.1 241 | function jaccscard_http11($method, $uris, $query = "", $cookie = "") { 242 | $ret = "INVALID HOST"; 243 | if(preg_match("/\.jaccs\.co\.jp$/", $uris["host"]) > 0) $ret = http11(strtoupper($method), $uris["scheme"], $uris["host"], 0, $uris["path"], $query, "", $cookie); 244 | return explode("\r\n\r\n", $ret, 2); 245 | } 246 | 247 | function jaccscard_update_cookie($head, $cookie) { 248 | return update_cookie(array("JSESSIONID", "[0-9]{17}"), parse_header($head, "set-cookie"), $cookie); 249 | } 250 | 251 | function jaccscard_parse_csv($str, $account) { 252 | $ret = ""; 253 | $lines = parse_csv(mb_convert_string($str)); 254 | $cds = array(); 255 | $cds_balamt = "0"; 256 | $cds_paydate = $account["paydate"]; 257 | $cds_s = ""; 258 | $cds_e = ""; 259 | $cd_date = ""; 260 | $cd_num = 0; 261 | $ledge_balamt = 0; 262 | $flg = false; 263 | 264 | foreach($lines as $line) { 265 | $cd = array(); 266 | 267 | if(count($line) == 2 && $line[0] == "(A)1回・2回・分割・ボーナス払の今回お支払金額小計") { 268 | // 今回お支払金額を取得する 269 | $cds_balamt = (string)((double)parse_amount($line[1])); 270 | } else if(count($line) == 13 && $line[1] == "<<次回以降のお支払明細>>") { 271 | // 次回以降のお支払明細を処理しない 272 | $flg = true; 273 | // break; 274 | } else if(count($line) == 13 && $line[0] != "ご利用年月日" && $line[0] != "" && $flg == false) { 275 | // PAYMENT固定とする 276 | $cd["TRNTYPE"] = ENV_STR_OFX_TRNTYPE_PAYMENT; 277 | 278 | // 日付を取得する 279 | $cd["DTPOSTED"] = parse_date($line[0]); 280 | if($cds_s == "") $cds_s = $cd["DTPOSTED"]; 281 | $cds_e = $cd["DTPOSTED"]; 282 | 283 | // 通番を生成する 284 | if($cd["DTPOSTED"] == $cd_date) $cd_num++; else $cd_num = 0; 285 | 286 | // トランザクション番号を生成する 287 | $cd["FITID"] = $cd["DTPOSTED"] . sprintf("%04d", $account["id"]) . substr($account["paydate"], 4, 2) . "0" . sprintf("%05d", $cd_num); 288 | 289 | // 摘要を取得する 290 | $cd["NAME"] = $line[1]; 291 | 292 | // 金額を取得する 293 | $cd["TRNAMT"] = (string)(-1 * (double)parse_amount($line[7])); 294 | 295 | // 費目を取得する 296 | $cd["MEMO"] = ($line[12] != "未設定"? $line[12]: ENV_STR_OFX_MEMO); 297 | 298 | // 残高を取得する 299 | $ledge_balamt += (double)$cd["TRNAMT"]; 300 | 301 | array_push($cds, $cd); 302 | $cd_date = $cd["DTPOSTED"]; 303 | } 304 | } 305 | 306 | $ledge_balamt += (double)$cds_balamt; 307 | 308 | if($cds_s == "") $cds_s = ENV_STR_DATE_TODAY; 309 | if($cds_e == "") $cds_e = ENV_STR_DATE_TODAY; 310 | if($cds_s > $cds_e) $cds_e = $cds_s; 311 | 312 | // クレジットカード支払請求を明細に追加する 313 | $i = count($cds); 314 | $cds[$i]["DTPOSTED"] = $cds_paydate; 315 | $cds[$i]["NAME"] = $account["name"]; 316 | $cds[$i]["MEMO"] = ENV_STR_OFX_MEMO; 317 | $cds[$i]["TRNAMT"] = $cds_balamt; 318 | $cds[$i]["TRNTYPE"] = ENV_STR_OFX_TRNTYPE_DIRECTDEBIT; 319 | $cds[$i]["FITID"] = $cds[$i]["DTPOSTED"] . sprintf("%04d", $account["id"]) . substr($account["paydate"], 4, 2) . "100000"; 320 | 321 | // BANKTRANLIST 322 | $ret .= ""; 323 | $ret .= "\r\n"; 324 | $ret .= "" . $cds_s . ENV_STR_OFX_TZ . ""; 325 | $ret .= "" . $cds_e . ENV_STR_OFX_TZ . ""; 326 | $ret .= "\r\n"; 327 | 328 | foreach($cds as $cd) { 329 | $ret .= ""; 330 | $ret .= "" . $cd["TRNTYPE"] . ""; 331 | $ret .= "" . $cd["DTPOSTED"] . ENV_STR_OFX_TZ . ""; 332 | $ret .= "" . $cd["TRNAMT"] . ""; 333 | $ret .= "" . $cd["FITID"] . ""; 334 | $ret .= "" . $cd["NAME"] . ""; 335 | $ret .= "" . $cd["MEMO"] . ""; 336 | $ret .= ""; 337 | $ret .= "\r\n"; 338 | } 339 | 340 | $ret .= ""; 341 | $ret .= "\r\n"; 342 | 343 | // 支払後残高を出力する 344 | $ret .= ""; 345 | $ret .= "" . (string)$ledge_balamt . ""; 346 | $ret .= "" . ENV_STR_DATE_TODAY . ENV_STR_OFX_TZ . ""; 347 | $ret .= ""; 348 | $ret .= "\r\n"; 349 | 350 | // カード名称を出力する 351 | if($account["acctname"] != "") { 352 | $ret .= "" . $account["acctname"] . ""; 353 | $ret .= "\r\n"; 354 | } 355 | 356 | return $ret; 357 | } 358 | 359 | ?> 360 | -------------------------------------------------------------------------------- /server/mobilesuica.inc: -------------------------------------------------------------------------------- 1 | 0) { 76 | // セッションを引き継ぐ 77 | $resp["status"] = ENV_NUM_STATUS_ADDITION; 78 | $resp["aid"] = "WebCaptcha1__editor"; 79 | $resp["additional"] = $imgsrc; 80 | $resp["sid"] = $sid; 81 | $resp["sesscookie"] = sess_encode(implode("\t", array($cookie, ENV_STR_SESSION_PADDING))); 82 | $resp["accesskey"] = sess_encode(implode("\t", array((string)$sid, $method, $uris["scheme"] . "://" . $uris["host"] . $uris["path"], $query, $user, ENV_STR_SESSION_PADDING))); 83 | 84 | $mfachallengetrnrs = ""; 85 | $mfachallengetrnrs .= ""; 86 | $mfachallengetrnrs .= ""; 87 | $mfachallengetrnrs .= ""; 88 | $mfachallengetrnrs .= "" . $resp["aid"] . ""; 89 | $mfachallengetrnrs .= "" . $resp["additional"] . ""; 90 | $mfachallengetrnrs .= ""; 91 | $mfachallengetrnrs .= ""; 92 | $mfachallengetrnrs .= ""; 93 | 94 | $resp["ofx"] = generate_ofx($resp["status"], $mfachallengetrnrs, $resp["sesscookie"], $resp["accesskey"]); 95 | } else if(strpos($body, "SF(電子マネー)利用履歴") === false) { 96 | // ログイン失敗の場合 97 | $resp["status"] = ENV_NUM_STATUS_FAILURE; 98 | $resp["method"] = $method; 99 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 100 | $resp["query"] = $query; 101 | $resp["cookie"] = $cookie; 102 | $resp["head"] = $head; 103 | $resp["body"] = $body; 104 | $resp["ofx"] = generate_ofx($resp["status"]); 105 | } else { 106 | $account = array(); 107 | 108 | $account["acctname"] = $settings["name"] . ENV_CHR_CONCATENATOR . $user; 109 | 110 | // 支店番号を取得する 111 | $account["branchid"] = "0"; 112 | 113 | // 口座番号を取得する 114 | $account["acctid"] = $user; 115 | 116 | // 残高を取得する 117 | $account["balance"] = 0; 118 | 119 | // SF(電子マネー)利用履歴画面を取得する 120 | $as = parse_tag($body, "a"); 121 | foreach($as as $a) if(parse_tag_search(parse_tag($a["innerHTML"], "img"), "alt", "SF(電子マネー)利用履歴") != -1) { 122 | $method = "POST"; 123 | if(preg_match("/javascript:[^\']+?\'([^\']+)\'.*?/i", $a["href"], $matches) > 0) $uris = parse_uri($matches[1], $uris); 124 | $query = ""; 125 | $cookie = mobilesuica_update_cookie($head, $cookie); 126 | list($head, $body) = mobilesuica_http11($method, $uris, $query, $cookie); 127 | break; 128 | } 129 | 130 | $account["details"] = array(); 131 | $tables = parse_tag($body, "table", true); // 再帰的に取得する 132 | foreach($tables as $table) if($table["cellpadding"] == "8") { 133 | $account["details"] = mobilesuica_get_details($table["innerHTML"]); 134 | $detail = array_shift($account["details"]); 135 | $account["balance"] = $detail["amount"]; 136 | } 137 | 138 | // SuicaID番号を取得する 139 | $forms = parse_tag($body, "form", true); // 再帰的に取得する 140 | $c = parse_tag_search($forms, "name", "form1"); 141 | if($c != -1) { 142 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 143 | $queries = array(); 144 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 145 | $selects = parse_tag($forms[$c]["innerHTML"], "select"); 146 | foreach($selects as $select) { 147 | $options = parse_tag($select["innerHTML"], "option"); 148 | foreach($options as $option) if($select["name"] != "" && $option["selected"] == "selected") $queries[$select["name"]] = urlencode($select["name"]) . "=" . urlencode($option["value"]); 149 | } 150 | $queries["baseVarCopy"] = "baseVarCopy=" . substr($queries["baseVariable"], strpos($queries["baseVariable"], "=") + 1); 151 | if($queries["SEARCH"] != "") unset($queries["SEARCH"]); 152 | if($queries["RETURNMENU"] != "") unset($queries["RETURNMENU"]); 153 | 154 | $method = $forms[$c]["method"]; 155 | $uris = parse_uri($forms[$c]["action"], $uris); 156 | $query = implode("&", $queries); 157 | $cookie = mobilesuica_update_cookie($head, $cookie); 158 | list($head, $body) = mobilesuica_http11($method, $uris, $query, $cookie); 159 | 160 | $contentdispositions = parse_header($head, "content-disposition"); 161 | if(count($contentdispositions) > 0) { 162 | $account["acctid"] = substr($contentdispositions[0], strpos($contentdispositions[0], "=") + 1, 17); 163 | } 164 | 165 | } 166 | 167 | // 実行時間(タイムアウト)を再設定する 168 | @set_time_limit(ENV_NUM_TIMEOUT); 169 | 170 | // ログアウトする 171 | $method = "POST"; 172 | $uris = parse_uri("/ka/lg/LogoutComplete.aspx", $uris); 173 | $query = ""; 174 | $cookie = mobilesuica_update_cookie($head, $cookie); 175 | list($head, $body) = mobilesuica_http11($method, $uris, $query, $cookie); 176 | 177 | // 実行時間(タイムアウト)を再設定する 178 | @set_time_limit(ENV_NUM_TIMEOUT); 179 | 180 | $bankmsgsrsv1 = ""; 181 | $bankmsgsrsv1 .= ""; 182 | $bankmsgsrsv1 .= "\r\n"; 183 | 184 | // 口座情報を取得する 185 | $bankmsgsrsv1 .= ""; 186 | $bankmsgsrsv1 .= "\r\n"; 187 | $bankmsgsrsv1 .= "0"; 188 | $bankmsgsrsv1 .= "\r\n"; 189 | $bankmsgsrsv1 .= "0INFO"; 190 | $bankmsgsrsv1 .= "\r\n"; 191 | $bankmsgsrsv1 .= ""; 192 | $bankmsgsrsv1 .= "\r\n"; 193 | $bankmsgsrsv1 .= "" . ENV_STR_OFX_CURRENCY_JPY . ""; 194 | $bankmsgsrsv1 .= "\r\n"; 195 | $bankmsgsrsv1 .= ""; 196 | $bankmsgsrsv1 .= "" . $settings["code"] . ""; 197 | $bankmsgsrsv1 .= "" . $account["branchid"] . ""; 198 | $bankmsgsrsv1 .= "" . $account["acctid"] . ""; 199 | $bankmsgsrsv1 .= "" . ENV_STR_ACCTTYPE_CHECKING . ""; 200 | $bankmsgsrsv1 .= ""; 201 | $bankmsgsrsv1 .= "\r\n"; 202 | $bankmsgsrsv1 .= mobilesuica_parse_details($account); 203 | $bankmsgsrsv1 .= ""; 204 | $bankmsgsrsv1 .= "\r\n"; 205 | $bankmsgsrsv1 .= ""; 206 | $bankmsgsrsv1 .= "\r\n"; 207 | 208 | $bankmsgsrsv1 .= ""; 209 | $bankmsgsrsv1 .= "\r\n"; 210 | 211 | // OFXファイルを出力する 212 | $resp["status"] = ENV_NUM_STATUS_SUCCESS; 213 | $resp["ofx"] = generate_ofx($resp["status"], $bankmsgsrsv1); 214 | } 215 | return $resp; 216 | 217 | // HTTP/1.1 218 | function mobilesuica_http11($method, $uris, $query = "", $cookie = "", $referer = "", $autoconv = true) { 219 | $ret = "INVALID HOST"; 220 | if(preg_match("/\.mobilesuica\.com$/", $uris["host"]) > 0) $ret = http11(strtoupper($method), $uris["scheme"], $uris["host"], 0, $uris["path"], $query, "", $cookie, $autoconv, ENV_PRODUCT_UA . " MSIE 7.0", "", $referer); // ログイン時にUser-Agentをチェックされる 221 | return explode("\r\n\r\n", $ret, 2); 222 | } 223 | 224 | function mobilesuica_update_cookie($head, $cookie) { 225 | return update_cookie(array("ASP.NET_SessionId", "sc_auth"), parse_header($head, "set-cookie"), $cookie); 226 | } 227 | 228 | function mobilesuica_get_details($body) { 229 | $rets = array(); 230 | $trs = parse_tag($body, "tr"); 231 | array_shift($trs); 232 | $i = count($trs) - 1; 233 | $prev = ""; 234 | $last = ""; 235 | foreach($trs as $tr) { 236 | $tds = parse_tag($tr["innerHTML"], "td"); 237 | if(count($tds) == 7) { 238 | // 日時を取得する 239 | $dt = trim(str_replace("/", "", strip_tags($tds[0]["innerHTML"]))); 240 | if($dt > substr(ENV_STR_DATE_TODAY, 4, 4)) { 241 | $dt = (string)((integer)substr(ENV_STR_DATE_TODAY, 0, 4) - 1) . $dt; 242 | } else { 243 | $dt = substr(ENV_STR_DATE_TODAY, 0, 4) . $dt; 244 | } 245 | 246 | // 取引種別、および場所を取得する 247 | $class1 = mobilesuica_parse_string($tds[1]["innerHTML"]); 248 | $place1 = mobilesuica_parse_string($tds[2]["innerHTML"]); 249 | $class2 = mobilesuica_parse_string($tds[3]["innerHTML"]); 250 | $place2 = mobilesuica_parse_string($tds[4]["innerHTML"]); 251 | 252 | $name = $class1 . $class2; 253 | $memo = $place1; 254 | if($place2 != "") $memo .= "-" . $place2; 255 | if($memo == "") $memo = ENV_STR_OFX_MEMO; 256 | 257 | // 収支を計算する 258 | $amount = mobilesuica_parse_string($tds[6]["innerHTML"]); 259 | 260 | // 残高を取得する 261 | if($last == "") $last = parse_amount(str_replace("¥", "", trim(strip_tags($tds[5]["innerHTML"])))); 262 | 263 | $rets[$i]["date"] = $dt; 264 | $rets[$i]["summary"] = $name; 265 | $rets[$i]["amount"] = $amount; 266 | $rets[$i]["memo"] = $memo; 267 | 268 | $i--; 269 | } 270 | } 271 | $rets[0]["amount"] = $last; 272 | 273 | // 戻り値の配列の先頭が残高となる(明細としては無効) 274 | return array_reverse($rets); 275 | } 276 | 277 | function mobilesuica_parse_string($str) { 278 | return trim(mb_convert_kana(strip_tags($str), "sKV", "UTF-8")); 279 | } 280 | 281 | function mobilesuica_parse_details($account) { 282 | $ret = ""; 283 | $cds = array(); 284 | $cd_date = ""; 285 | $cd_num = 0; 286 | $dtstart = ENV_STR_DATE_PASTDAY; 287 | foreach($account["details"] as $line) { 288 | if($dtstart > $line["date"]) $dtstart = $line["date"]; 289 | 290 | $cd = array(); 291 | $cd["TRNTYPE"] = ENV_STR_OFX_TRNTYPE_DIRECTDEBIT; 292 | 293 | // 日付を取得する 294 | $cd["DTPOSTED"] = $line["date"]; 295 | 296 | // 通番を生成する 297 | if($cd["DTPOSTED"] == $cd_date) $cd_num++; else $cd_num = 0; 298 | 299 | // トランザクション番号を生成する 300 | $cd["FITID"] = $cd["DTPOSTED"] . "0000000" . sprintf("%05d", $cd_num); 301 | 302 | // 摘要を取得する 303 | $cd["NAME"] = $line["summary"]; 304 | 305 | // 金額を取得する 306 | $cd["TRNAMT"] = parse_amount($line["amount"]); 307 | $cd["MEMO"] = ($line["memo"] != ""? $line["memo"]: ENV_STR_OFX_MEMO); 308 | 309 | array_push($cds, $cd); 310 | $cd_date = $cd["DTPOSTED"]; 311 | } 312 | // BANKTRANLIST 313 | $ret .= ""; 314 | $ret .= "\r\n"; 315 | $ret .= "" . $dtstart . ENV_STR_OFX_TZ . ""; 316 | $ret .= "" . ENV_STR_DATE_TODAY . ENV_STR_OFX_TZ . ""; 317 | $ret .= "\r\n"; 318 | 319 | foreach($cds as $cd) { 320 | $ret .= ""; 321 | $ret .= "" . $cd["TRNTYPE"] . ""; 322 | $ret .= "" . $cd["DTPOSTED"] . ENV_STR_OFX_TZ . ""; 323 | $ret .= "" . $cd["TRNAMT"] . ""; 324 | $ret .= "" . $cd["FITID"] . ""; 325 | $ret .= "" . $cd["NAME"] . ""; 326 | $ret .= "" . $cd["MEMO"] . ""; 327 | $ret .= ""; 328 | $ret .= "\r\n"; 329 | } 330 | 331 | $ret .= ""; 332 | $ret .= "\r\n"; 333 | $ret .= ""; 334 | $ret .= "" . $account["balance"] . ""; 335 | $ret .= "" . ENV_STR_DATE_TODAY . ENV_STR_OFX_TZ . ""; 336 | $ret .= ""; 337 | $ret .= "\r\n"; 338 | 339 | // 口座名称を出力する 340 | if($account["acctname"] != "") { 341 | $ret .= "" . $account["acctname"] . ""; 342 | $ret .= "\r\n"; 343 | } 344 | 345 | return $ret; 346 | } 347 | 348 | ?> 349 | -------------------------------------------------------------------------------- /server/mufgcard.inc: -------------------------------------------------------------------------------- 1 | 0) { 74 | $method = "GET"; 75 | $uris = parse_uri($locations[0], $uris); 76 | $query = ""; 77 | $cookie = mun_update_cookie($head, $cookie); 78 | list($head, $body) = mun_http11($method, $uris, $query, $cookie); 79 | } 80 | } 81 | 82 | $as = parse_tag($body, "a"); 83 | foreach($as as $a) { 84 | switch(trim(strip_tags($a["innerHTML"]))) { 85 | case "ログアウト": 86 | // ログアウト画面を退避する(NEWS+PLUS) 87 | $method_mun = "GET"; 88 | $uris_mun = parse_uri($a["href"], $uris); 89 | $query_mun = ""; 90 | $cookie_mun = $cookie; 91 | break; 92 | case "WEBサービストップ": 93 | // WEBサービストップ画面を取得する(NEWS+PLUS) 94 | $method = "GET"; 95 | $uris = parse_uri($a["href"], $uris); 96 | $query = ""; 97 | $cookie = mun_update_cookie($head, $cookie); 98 | list($head, $body) = mun_http11($method, $uris, $query, $cookie); 99 | break; 100 | default: 101 | break; 102 | } 103 | } 104 | 105 | // 以降は各カードブランドの画面に遷移する 106 | $cookie = ""; 107 | 108 | // 実行時間(タイムアウト)を再設定する 109 | @set_time_limit(ENV_NUM_TIMEOUT); 110 | 111 | // ログインする 112 | $forms = parse_tag($body, "form"); 113 | $c = parse_tag_search($forms, "id", "seamlessForm"); 114 | if($c != -1) { 115 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 116 | $queries = array(); 117 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 118 | 119 | $method = $forms[$c]["method"]; 120 | $uris = parse_uri($forms[$c]["action"], $uris); 121 | $query = implode("&", $queries); 122 | $cookie = mufgcard_updatecookie($head, $cookie); 123 | list($head, $body) = mufgcard_http11($method, $uris["scheme"], $uris["host"], $uris["path"], $query, $cookie); 124 | } 125 | 126 | // リダイレクトする 127 | $retry = 0; 128 | while($retry++ < ENV_NUM_HTTP11_RETRY) { 129 | $locations = parse_header($head, "location"); 130 | if(count($locations) > 0) { 131 | $method = "GET"; 132 | $uris = parse_uri($locations[0], $uris); 133 | $query = ""; 134 | $cookie = mufgcard_updatecookie($head, $cookie); 135 | list($head, $body) = mufgcard_http11($method, $uris["scheme"], $uris["host"], $uris["path"], $query, $cookie); 136 | } 137 | } 138 | 139 | if(strpos($body, "現在サービス停止中") !== false || strpos($body, "システムメンテナンスのため") !== false) { 140 | // システムメンテナンス画面の場合 141 | $resp["status"] = ENV_NUM_STATUS_MAINTENANCE; 142 | $resp["method"] = $method; 143 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 144 | $resp["query"] = $query; 145 | $resp["cookie"] = $cookie; 146 | $resp["head"] = $head; 147 | $resp["body"] = $body; 148 | $resp["ofx"] = generate_ofx($resp["status"]); 149 | } else if(strpos($body, "前回ログイン") === false) { 150 | // ログイン失敗の場合 151 | $resp["status"] = ENV_NUM_STATUS_FAILURE; 152 | $resp["method"] = $method; 153 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 154 | $resp["query"] = $query; 155 | $resp["cookie"] = $cookie; 156 | $resp["head"] = $head; 157 | $resp["body"] = $body; 158 | $resp["ofx"] = generate_ofx($resp["status"]); 159 | } else { 160 | // ログアウト画面を退避する 161 | $uris_old = parse_uri("/inet/dy/logout.html", $uris); 162 | 163 | // 請求額・利用明細照会 164 | $method = "GET"; 165 | $uris = parse_uri("/inet/dy/meisaisyokai/index.html", $uris); 166 | $query = ""; 167 | $cookie = mufgcard_updatecookie($head, $cookie); 168 | list($head, $body) = mufgcard_http11($method, $uris["scheme"], $uris["host"], $uris["path"], $query, $cookie); 169 | 170 | $tables = parse_tag($body, "table"); 171 | $tds = parse_tag($tables[0]["innerHTML"], "td"); 172 | // カード名称を取得する 173 | $account["acctname"] = implode(ENV_CHR_CONCATENATOR, array($settings["name"], $tds[1]["innerHTML"])); 174 | 175 | // カード番号を取得する 176 | if(preg_match("/XXXX-([0-9X]{4})/", $tds[2]["innerHTML"], $matches) > 0) { 177 | $account["acctid"] = $matches[1]; 178 | } 179 | 180 | // お支払日を取得する 181 | $tds = parse_tag($tables[1]["innerHTML"], "td"); 182 | $account["paydate"] = parse_date($tds[1]["innerHTML"]); 183 | 184 | // 今回ご請求合計額を取得する 185 | $account["ledge_balamt"] = 0; 186 | for( $i = 0 ; $i < 3 ; $i++ ) { 187 | $tmp = parse_amount($tds[2+$i*4]["innerHTML"]); 188 | $account["ledge_balamt"] += (-1)*$tmp; 189 | } 190 | 191 | // 実行時間(タイムアウト)を再設定する 192 | @set_time_limit(ENV_NUM_TIMEOUT); 193 | 194 | $bodies = array(); 195 | // カード・照会月を選択する 196 | $as = parse_tag($body, "a"); 197 | foreach($as as $a){ 198 | if(preg_match("/.*detail.*/", $a["href"])) { 199 | $method = "GET"; 200 | $uris = parse_uri($a["href"], $uris); 201 | $cookie = mufgcard_updatecookie($head, $cookie); 202 | list($head, $body) = mufgcard_http11($method, $uris["scheme"], $uris["host"], $uris["path"], $uris["query"], $cookie); 203 | array_push($bodies, $body); 204 | while(preg_match("/.*next\.html.*/", $body)) { 205 | $forms = parse_tag($body, "form"); 206 | $c = parse_tag_search($forms, "action", "/inet/dy/meisaisyokai/next.html#meisai"); 207 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 208 | $queries = array(); 209 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 210 | 211 | $method = $forms[$c]["method"]; 212 | $uris = parse_uri($forms[$c]["action"], $uris); 213 | $query = implode("&", $queries); 214 | $cookie = mufgcard_updatecookie($head, $cookie); 215 | list($head, $body) = mufgcard_http11($method, $uris["scheme"], $uris["host"], $uris["path"], $query, $cookie); 216 | array_push($bodies, $body); 217 | } 218 | } 219 | } 220 | 221 | // DOMツリーを生成 222 | $ofxdom = new ofxDOM("CREDITCARD", $account["acctname"]); 223 | $ofxdom->setAcctfrom(array("ACCTID" => $account["acctid"])); 224 | 225 | // 明細をパース 226 | $cds = array(); 227 | foreach($bodies as $body){ 228 | $cds_tmp = mufgcard_parsedom($body); 229 | if ($cds_tmp != false) { 230 | $cds = array_merge($cds, $cds_tmp); 231 | } 232 | } 233 | usort($cds, function($a, $b) { 234 | return $a['DTPOSTED'] > $b['DTPOSTED']; 235 | }); 236 | foreach($cds as $cd) { 237 | $ofxdom->addTran($cd); 238 | } 239 | 240 | $cds_s = ""; 241 | $cds_e = ""; 242 | $items = $ofxdom->getTrans(); 243 | foreach ($items as $item) { 244 | $dtposted = $item->DTPOSTED; 245 | // DTSTART, DTENDを取得 246 | if($cds_s == "") $cds_s = $dtposted; 247 | $cds_e = $dtposted; 248 | } 249 | 250 | // DTSTARTとDTENDを設定する 251 | $ofxdom->setDateRange($cds_s, $cds_e); 252 | 253 | // 残高を処理 254 | $account["ledge_balamt"] = parse_amount($account["ledge_balamt"]); 255 | $ofxdom->setBalance(array( 256 | 'BALAMT' => $account["ledge_balamt"], 257 | 'DTASOF' => ENV_STR_DATE_TODAY . ENV_STR_OFX_TZ 258 | )); 259 | 260 | // FITIDを仕上げる 261 | $ofxdom->setFitid(); 262 | // XML DOMツリーを文字列に変換 263 | $xml = $ofxdom->getXML(); 264 | 265 | $resp["status"] = ENV_NUM_STATUS_SUCCESS; 266 | $resp["ofx"] = generate_ofx($resp["status"], $xml); 267 | 268 | // 実行時間(タイムアウト)を再設定する 269 | @set_time_limit(ENV_NUM_TIMEOUT); 270 | 271 | // ログアウトする 272 | $method = "GET"; 273 | $uris = $uris_old; 274 | $query = ""; 275 | $cookie = mufgcard_updatecookie($head, $cookie); 276 | list($head, $body) = mufgcard_http11($method, $uris["scheme"], $uris["host"], $uris["path"], $query, $cookie); 277 | 278 | // ログアウトする(NEWS+PLUS) 279 | $method = $method_mun; 280 | $uris = $uris_mun; 281 | $query = $query_mun; 282 | $cookie = $cookie_mun; 283 | list($head, $body) = mun_http11($method, $uris, $query, $cookie); 284 | } 285 | return $resp; 286 | 287 | // HTTP/1.1(NEWS+PLUS) 288 | function mun_http11($method, $uris, $query = "", $cookie = "") { 289 | $ret = "INVALID HOST"; 290 | if(preg_match("/\.cr\.mufg\.jp$/", $uris["host"]) > 0) $ret = http11(strtoupper($method), $uris["scheme"], $uris["host"], 0, $uris["path"], $query, "", $cookie); 291 | return explode("\r\n\r\n", $ret, 2); 292 | } 293 | 294 | function mun_update_cookie($head, $cookie) { 295 | return update_cookie(array("PHPSESSID", "session-srv", "m_cardBrand"), parse_header($head, "set-cookie"), $cookie); 296 | } 297 | 298 | // HTTP/1.1 299 | function mufgcard_http11($method, $protocol, $host, $page = "/", $query = "", $cookie = "") { 300 | $ret = "INVALID HOST"; 301 | if(preg_match("/\.mufgcard\.com$/", $host) > 0) $ret = http11(strtoupper($method), $protocol, $host, 0, $page, $query, "", $cookie); 302 | return explode("\r\n\r\n", $ret, 2); 303 | } 304 | 305 | function mufgcard_updatecookie($head, $cookie) { 306 | $ret = ""; 307 | $cookies = array(); 308 | 309 | $ckvs = explode(";", $cookie); 310 | foreach($ckvs as $ckv) { 311 | list($ck, $cv) = explode("=", $ckv, 2); 312 | $ck = trim($ck); 313 | $cv = trim($cv); 314 | if($ck != "" && $cv != "") $cookies[$ck] = $ck . "=" . $cv; 315 | } 316 | 317 | $cks = array("AS0[1-9]"); 318 | foreach($cks as $ck) { 319 | $c = preg_match_all("/[Ss][Ee][Tt]-[Cc][Oo][Oo][Kk][Ii][Ee][\s\t]*:[\s\t]*(" . $ck . ")=([^;\r\n]*)/", $head, $matches); 320 | for($i = 0; $i < $c; $i++) $cookies[$matches[1][$i]] = $matches[1][$i] . "=" . $matches[2][$i]; 321 | } 322 | $ret = implode("; ", $cookies); 323 | return $ret; 324 | } 325 | 326 | function mufgcard_parsedom($str) { 327 | // 明細表読み込み用DOMツリー作成 328 | $doc = new DOMDocument(); 329 | // 引き落とし月取得 330 | $month = (preg_match("/" .preg_quote("お支払日") . ".*?" . preg_quote("年") . "([0-9]+)" . preg_quote("月") . "/s", $str, $matches) > 0 ? $matches[1] : "00"); 331 | // の前のが,文字化けの原因となるため,削除 332 | $str = preg_replace('/<title>.*<\/title>/', '', $str); 333 | //   334 | $str = str_replace(" ", "", $str); 335 | // 文字エンコード変換 336 | // $str = mb_convert_encoding($str, 'UTF-8', 'SJIS'); 337 | // $str = str_replace('Shift_JIS','UTF-8',$str); 338 | // HTMLからDOMツリー作成 339 | $doc->loadHTML($str); 340 | $xpath = new DOMXPath($doc); 341 | // 明細表のテーブルを指定 342 | $tables = $xpath->query("//table[@class='mod-table font-x-small sp-font-normal transform']"); 343 | // 請求がない場合 344 | if($tables->length == 0) { 345 | return false; 346 | } 347 | $rows = $tables->item(0)->getElementsByTagName('tr'); 348 | 349 | $ret = ""; 350 | $cds = array(); 351 | $nrow = $rows->length; 352 | for($i=3; $i<$nrow; $i++) { 353 | $cd = array(); 354 | $row = $rows->item($i); 355 | $cols = $row->getElementsByTagName('dd'); 356 | // 利用明細でない行はスキップ 357 | if(empty($cols->item(0)->nodeValue)) continue; 358 | 359 | $cd["TRNTYPE"] = ENV_STR_OFX_TRNTYPE_CREDIT; 360 | 361 | // 日付を取得する 362 | $cd["DTPOSTED"] = parse_date(trim($cols->item(0)->nodeValue)); 363 | $cd["DTPOSTED"] .= ENV_STR_OFX_TZ; 364 | // トランザクション番号(請求月とデータ種別)を生成する 365 | $cd["FITID"] = sprintf("%02d0", $month); 366 | // 摘要を取得する 367 | $cd["NAME"] = $cols->item(1)->nodeValue; 368 | // 金額を取得する 369 | $cd["TRNAMT"] = (-1)*(double)parse_amount(trim($cols->item(4)->nodeValue)); 370 | 371 | array_push($cds, $cd); 372 | $cd_date = $cd["DTPOSTED"]; 373 | } 374 | return $cds; 375 | } 376 | ?> 377 | -------------------------------------------------------------------------------- /server/nanaco.inc: -------------------------------------------------------------------------------- 1 | <?php 2 | /* 3 | nanaco.inc: nanacoのHTMLよりOFXファイルを生成する 4 | Copyright (C) 2014-2017 OFFICE OUTERGUY. All rights reserved. 5 | mailto:contact@beatrek.com 6 | Licensed under the GNU AGPLv3. 7 | */ 8 | 9 | // ログイン情報を取得する 10 | $user = str_replace("-", "", $ofxforms["XCID"]); 11 | $pass = $ofxforms["LOGIN_PWD"]; 12 | 13 | $resp = array(); 14 | $ofx = ""; 15 | 16 | // 実行時間(タイムアウト)を再設定する 17 | @set_time_limit(ENV_NUM_TIMEOUT); 18 | 19 | // ホーム画面を取得する 20 | $method = "GET"; 21 | $uris = parse_uri($settings["home"]); 22 | $query = ""; 23 | $cookie = ""; 24 | list($head, $body) = nanaco_http11($method, $uris, $query, $cookie); 25 | 26 | // ログイン画面を取得する 27 | $as = parse_tag($body, "a"); 28 | $c = parse_tag_search($as, "innerHTML", "会員メニューログイン"); 29 | if($c != -1) { 30 | $method = "GET"; 31 | $uris = parse_uri($as[$c]["href"]); 32 | $query = ""; 33 | list($head, $body) = nanaco_http11($method, $uris, $query, $cookie); 34 | } 35 | 36 | // ログインする 37 | $forms = parse_tag($body, "form"); 38 | $c = parse_tag_search($forms, "id", "login_password"); 39 | if($c != -1) { 40 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 41 | $queries = array(); 42 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 43 | $queries["XCID"] = "XCID=" . $user; 44 | $queries["LOGIN_PWD"] = "LOGIN_PWD=" . $pass; 45 | 46 | $method = $forms[$c]["method"]; 47 | $uris = parse_uri($forms[$c]["action"], $uris); 48 | $query = implode("&", $queries); 49 | $cookie = nanaco_update_cookie($head, $cookie); 50 | list($head, $body) = nanaco_http11($method, $uris, $query, $cookie); 51 | } 52 | 53 | if(strpos($body, "残高・履歴確認") === false) { 54 | // ログイン失敗の場合 55 | $resp["status"] = ENV_NUM_STATUS_FAILURE; 56 | $resp["method"] = $method; 57 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 58 | $resp["query"] = $query; 59 | $resp["cookie"] = $cookie; 60 | $resp["head"] = $head; 61 | $resp["body"] = $body; 62 | $resp["ofx"] = generate_ofx($resp["status"]); 63 | } else { 64 | $account = array(); 65 | 66 | $account["acctname"] = $settings["name"]; 67 | 68 | // 支店番号を取得する 69 | $account["branchid"] = "0"; 70 | 71 | // 口座番号を取得する 72 | $account["acctid"] = $user; 73 | 74 | // 残高を取得する 75 | $account["balance"] = 0; 76 | $divs = parse_tag($body, "div", true); // 再帰的に取得する 77 | $c = parse_tag_search($divs, "class", "moneyBox"); 78 | if($c != -1) { 79 | $div2s = parse_tag($divs[$c]["innerHTML"], "div"); 80 | $c = parse_tag_search($div2s, "class", "fRight"); 81 | if($c != -1) $account["balance"] = parse_amount(strip_tags($div2s[$c]["innerHTML"])); 82 | } 83 | 84 | // 残高・履歴確認画面(1ページ目)を取得する 85 | $as = parse_tag($body, "a"); 86 | $c = parse_tag_search($as, "innerHTML", "残高・履歴確認"); 87 | if($c != -1) { 88 | $method = "GET"; 89 | $uris = parse_uri($as[$c]["href"], $uris); 90 | $query = ""; 91 | $cookie = nanaco_update_cookie($head, $cookie); 92 | list($head, $body) = nanaco_http11($method, $uris, $query, $cookie); 93 | } 94 | $account["details"] = array(); 95 | 96 | // 無限ループする 97 | while(true) { 98 | // 明細を取得する 99 | $tables = parse_tag($body, "table"); 100 | $c = parse_tag_search($tables, "id", "historyTbl"); 101 | if($c != -1) $account["details"] = array_merge(nanaco_get_details($tables[$c]["innerHTML"]), $account["details"]); 102 | 103 | // 残高・履歴確認画面(2ページ目以降)を取得する 104 | $as = parse_tag($body, "a"); 105 | $c = parse_tag_search($as, "innerHTML", " >>次へ"); 106 | if($c != -1) { 107 | $method = "GET"; 108 | $uris = parse_uri($as[$c]["href"], $uris); 109 | $query = ""; 110 | $cookie = nanaco_update_cookie($head, $cookie); 111 | list($head, $body) = nanaco_http11($method, $uris, $query, $cookie); 112 | } else { 113 | // 見つからない場合、ループを抜ける 114 | break; 115 | } 116 | } 117 | 118 | 119 | // 実行時間(タイムアウト)を再設定する 120 | @set_time_limit(ENV_NUM_TIMEOUT); 121 | 122 | // ログアウトする 123 | $as = parse_tag($body, "a"); 124 | $c = parse_tag_search($as, "innerHTML", "ログアウト"); 125 | if($c != -1) { 126 | $method = "GET"; 127 | $uris = parse_uri($as[$c]["href"], $uris); 128 | $query = ""; 129 | $cookie = nanaco_update_cookie($head, $cookie); 130 | list($head, $body) = nanaco_http11($method, $uris, $query, $cookie); 131 | } 132 | 133 | // 実行時間(タイムアウト)を再設定する 134 | @set_time_limit(ENV_NUM_TIMEOUT); 135 | 136 | $bankmsgsrsv1 = ""; 137 | $bankmsgsrsv1 .= "<BANKMSGSRSV1>"; 138 | $bankmsgsrsv1 .= "\r\n"; 139 | 140 | // 口座情報を取得する 141 | $bankmsgsrsv1 .= "<STMTTRNRS>"; 142 | $bankmsgsrsv1 .= "\r\n"; 143 | $bankmsgsrsv1 .= "<TRNUID>0</TRNUID>"; 144 | $bankmsgsrsv1 .= "\r\n"; 145 | $bankmsgsrsv1 .= "<STATUS><CODE>0</CODE><SEVERITY>INFO</SEVERITY></STATUS>"; 146 | $bankmsgsrsv1 .= "\r\n"; 147 | $bankmsgsrsv1 .= "<STMTRS>"; 148 | $bankmsgsrsv1 .= "\r\n"; 149 | $bankmsgsrsv1 .= "<CURDEF>" . ENV_STR_OFX_CURRENCY_JPY . "</CURDEF>"; 150 | $bankmsgsrsv1 .= "\r\n"; 151 | $bankmsgsrsv1 .= "<BANKACCTFROM>"; 152 | $bankmsgsrsv1 .= "<BANKID>" . $settings["code"] . "</BANKID>"; 153 | $bankmsgsrsv1 .= "<BRANCHID>" . $account["branchid"] . "</BRANCHID>"; 154 | $bankmsgsrsv1 .= "<ACCTID>" . $account["acctid"] . "</ACCTID>"; 155 | $bankmsgsrsv1 .= "<ACCTTYPE>" . ENV_STR_ACCTTYPE_CHECKING . "</ACCTTYPE>"; 156 | $bankmsgsrsv1 .= "</BANKACCTFROM>"; 157 | $bankmsgsrsv1 .= "\r\n"; 158 | $bankmsgsrsv1 .= nanaco_parse_details($account); 159 | $bankmsgsrsv1 .= "</STMTRS>"; 160 | $bankmsgsrsv1 .= "\r\n"; 161 | $bankmsgsrsv1 .= "</STMTTRNRS>"; 162 | $bankmsgsrsv1 .= "\r\n"; 163 | 164 | $bankmsgsrsv1 .= "</BANKMSGSRSV1>"; 165 | $bankmsgsrsv1 .= "\r\n"; 166 | 167 | // OFXファイルを出力する 168 | $resp["status"] = ENV_NUM_STATUS_SUCCESS; 169 | $resp["ofx"] = generate_ofx($resp["status"], $bankmsgsrsv1); 170 | } 171 | return $resp; 172 | 173 | // HTTP/1.1 174 | function nanaco_http11($method, $uris, $query = "", $cookie = "") { 175 | $ret = "INVALID HOST"; 176 | if(preg_match("/\.nanaco-net\.jp$/", $uris["host"]) > 0) $ret = http11(strtoupper($method), $uris["scheme"], $uris["host"], 0, $uris["path"], $query, "", $cookie); 177 | return explode("\r\n\r\n", $ret, 2); 178 | } 179 | 180 | function nanaco_update_cookie($head, $cookie) { 181 | return update_cookie(array("JSESSIONID", "BIGipServerPool_443_pc"), parse_header($head, "set-cookie"), $cookie); 182 | } 183 | 184 | function nanaco_get_details($body) { 185 | $rets = array(); 186 | $i = 0; 187 | $trs = parse_tag($body, "tr"); 188 | foreach(array_reverse($trs) as $tr) { 189 | $tds = parse_tag($tr["innerHTML"], "td"); 190 | if(count($tds) == 10) { 191 | // 日時を取得する 192 | $dt = explode("<br>", $tds[0]["innerHTML"]); 193 | 194 | // 取引種別、および場所を取得する 195 | $name = trim(strip_tags($tds[1]["innerHTML"])); 196 | $memo = trim(strip_tags($tds[9]["innerHTML"])); 197 | 198 | // nanacoチャージ額・支払額を取得する 199 | $am = explode("<br>", $tds[2]["innerHTML"]); 200 | $amount = (string)((integer)parse_amount(trim(strip_tags($am[0]))) + (integer)parse_amount(trim(strip_tags(str_replace(array("(", ")"), array("", ""), $am[1]))))); 201 | if($amount == "0") $amount = (string)(-1 * (integer)parse_amount(trim(strip_tags($tds[3]["innerHTML"])))); 202 | 203 | if($amount != "0") { 204 | $rets[$i]["date"] = parse_date(trim(strip_tags($dt[0]))); 205 | $rets[$i]["summary"] = $name; 206 | $rets[$i]["memo"] = $memo; 207 | $rets[$i]["amount"] = $amount; 208 | 209 | $i++; 210 | } 211 | } 212 | } 213 | 214 | return $rets; 215 | } 216 | 217 | function nanaco_parse_details($account) { 218 | $ret = ""; 219 | $cds = array(); 220 | $cd_date = ""; 221 | $cd_num = 0; 222 | $dtstart = ENV_STR_DATE_PASTDAY; 223 | foreach($account["details"] as $line) { 224 | if($dtstart > $line["date"]) $dtstart = $line["date"]; 225 | 226 | $cd = array(); 227 | $cd["TRNTYPE"] = ENV_STR_OFX_TRNTYPE_DIRECTDEBIT; 228 | 229 | // 日付を取得する 230 | $cd["DTPOSTED"] = $line["date"]; 231 | 232 | // 通番を生成する 233 | if($cd["DTPOSTED"] == $cd_date) $cd_num++; else $cd_num = 0; 234 | 235 | // トランザクション番号を生成する 236 | $cd["FITID"] = $cd["DTPOSTED"] . "0000000" . sprintf("%05d", $cd_num); 237 | 238 | // 摘要を取得する 239 | $cd["NAME"] = $line["summary"]; 240 | 241 | // 金額を取得する 242 | $cd["TRNAMT"] = parse_amount($line["amount"]); 243 | $cd["MEMO"] = ($line["memo"] != ""? $line["memo"]: ENV_STR_OFX_MEMO); 244 | 245 | array_push($cds, $cd); 246 | $cd_date = $cd["DTPOSTED"]; 247 | } 248 | // BANKTRANLIST 249 | $ret .= "<BANKTRANLIST>"; 250 | $ret .= "\r\n"; 251 | $ret .= "<DTSTART>" . $dtstart . ENV_STR_OFX_TZ . "</DTSTART>"; 252 | $ret .= "<DTEND>" . ENV_STR_DATE_TODAY . ENV_STR_OFX_TZ . "</DTEND>"; 253 | $ret .= "\r\n"; 254 | 255 | foreach($cds as $cd) { 256 | $ret .= "<STMTTRN>"; 257 | $ret .= "<TRNTYPE>" . $cd["TRNTYPE"] . "</TRNTYPE>"; 258 | $ret .= "<DTPOSTED>" . $cd["DTPOSTED"] . ENV_STR_OFX_TZ . "</DTPOSTED>"; 259 | $ret .= "<TRNAMT>" . $cd["TRNAMT"] . "</TRNAMT>"; 260 | $ret .= "<FITID>" . $cd["FITID"] . "</FITID>"; 261 | $ret .= "<NAME>" . $cd["NAME"] . "</NAME>"; 262 | $ret .= "<MEMO>" . $cd["MEMO"] . "</MEMO>"; 263 | $ret .= "</STMTTRN>"; 264 | $ret .= "\r\n"; 265 | } 266 | 267 | $ret .= "</BANKTRANLIST>"; 268 | $ret .= "\r\n"; 269 | $ret .= "<LEDGERBAL>"; 270 | $ret .= "<BALAMT>" . $account["balance"] . "</BALAMT>"; 271 | $ret .= "<DTASOF>" . ENV_STR_DATE_TODAY . ENV_STR_OFX_TZ . "</DTASOF>"; 272 | $ret .= "</LEDGERBAL>"; 273 | $ret .= "\r\n"; 274 | 275 | // 口座名称を出力する 276 | if($account["acctname"] != "") { 277 | $ret .= "<MKTGINFO>" . $account["acctname"] . "</MKTGINFO>"; 278 | $ret .= "\r\n"; 279 | } 280 | 281 | return $ret; 282 | } 283 | 284 | ?> 285 | -------------------------------------------------------------------------------- /server/rakutensec.inc: -------------------------------------------------------------------------------- 1 | <?php 2 | /* 3 | rakutensec.inc: 楽天証券のHTMLよりOFXファイルを生成する 4 | Copyright (C) 2012-2017 Hiromu2000. All Rights Reserved. 5 | mailto:hiromu2000@hotmail.com 6 | Licensed under the GNU AGPLv3. 7 | */ 8 | 9 | $resp = array(); 10 | $ofx = ""; 11 | 12 | // 実行時間(タイムアウト)を再設定する 13 | @set_time_limit(ENV_NUM_TIMEOUT); 14 | 15 | // ログイン画面を取得する 16 | $uris = parse_uri($settings["home"]); 17 | $query = ""; 18 | $cookie = ""; 19 | list($head, $body) = rakutensec_http11('GET', $uris, $query, $cookie); 20 | 21 | // ログインする 22 | $forms = parse_tag($body, "form"); 23 | $c = parse_tag_search($forms, "name", "loginform"); 24 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 25 | $queries = array(); 26 | foreach($inputs as $input) { 27 | if($input["name"] != "") { 28 | $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 29 | } 30 | } 31 | $queries["loginid"] .= $ofxforms["loginid"]; 32 | $queries["passwd"] .= $ofxforms["passwd"]; 33 | $queries["homeid"] = "homeid=HOME"; 34 | $uris = parse_uri('https://member.rakuten-sec.co.jp/bv/app/MhLogin.do', $uris); 35 | $query = implode("&", $queries); 36 | $cookie = rakutensec_update_cookie($head, $cookie); 37 | list($head, $body) = rakutensec_http11('POST', $uris, $query, $cookie); 38 | 39 | if (strpos($body, "未実装") !== false) { 40 | // システムメンテナンスの場合 41 | $resp["status"] = ENV_NUM_STATUS_MAINTENANCE; 42 | $resp["method"] = $method; 43 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 44 | $resp["query"] = $query; 45 | $resp["cookie"] = $cookie; 46 | $resp["head"] = $head; 47 | $resp["body"] = $body; 48 | $resp["ofx"] = generate_ofx($resp["status"]); 49 | return $resp; 50 | } else if (!preg_match("/\"(\/app\/home\.do.*)\"/", $body, $matches)) { 51 | // ログイン失敗の場合 52 | $resp["status"] = ENV_NUM_STATUS_FAILURE; 53 | $resp["method"] = $method; 54 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 55 | $resp["query"] = $query; 56 | $resp["cookie"] = $cookie; 57 | $resp["head"] = $head; 58 | $resp["body"] = $body; 59 | $resp["ofx"] = generate_ofx($resp["status"]); 60 | return $resp; 61 | } 62 | 63 | // リダイレクトし、ホーム画面のHTMLを取得する 64 | $uris = parse_uri($matches[1], $uris); 65 | preg_match('/(BV_SessionID=.*)\?/', $matches[1], $matches); 66 | $sessionid = $matches[1]; 67 | $query = ""; 68 | $cookie = rakutensec_update_cookie($head, $cookie); 69 | list($head, $body_home) = rakutensec_http11('GET', $uris, $query, $cookie); 70 | 71 | // 資産情報のHTMLを取得する 72 | $uris['path'] = '/app/async_change_home_balance_lst.do;' . $sessionid; 73 | $query = 'updateKbn=lastDay&openCode=1'; 74 | list($head, $body_balance) = rakutensec_http11('POST', $uris, $query, $cookie); 75 | 76 | // 入出金履歴のCSVを取得する 77 | // 一度ページ遷移をしないと、CSVをダウンロードできない模様 78 | $uris['path'] = '/app/ass_money_trans_lst.do;' . $sessionid; 79 | $query = 'eventType=init'; 80 | $cookie = rakutensec_update_cookie($head, $cookie); 81 | list($head, $body_trans) = rakutensec_http11('GET', $uris, $query, $cookie); 82 | 83 | $uris['path'] = '/app/ass_money_trans_lst_csv_output.do;' . $sessionid; 84 | $query = 'eventType=csv'; 85 | $cookie = rakutensec_update_cookie($head, $cookie); 86 | list($head, $body_trans) = rakutensec_http11('GET', $uris, $query, $cookie); 87 | 88 | // 取引履歴(国内株式)のCSVを取得する 89 | $uris['path'] = '/app/assTradJpLstCsvServlet;' . $sessionid; 90 | $queries = array(); 91 | $queries['searchFlg'] = 'searchFlg=0'; 92 | $queries['termCd'] = 'termCd=ALL'; 93 | $queries['trustKbn'] = 'trustKbn=A'; 94 | $queries['accCd'] = 'accCd=A'; 95 | foreach(array('yyyyFrom', 'mmFrom', 'ddFrom', 96 | 'yyyyTo', 'mmTo', 'ddTo', 97 | 'dscrCdNm', 98 | 'hiddenSearchFlag', 99 | 'hiddenYearFrom', 'hiddenMonthFrom', 'hiddenDayFrom', 100 | 'hiddenYearTo', 'hiddenMonthTo', 'hiddenDayTo', 101 | 'hiddenSpotTrustKbn', 'hiddenAccountCd', 'hiddenDscr', 102 | 'offsetRow') as $key) { 103 | $queries[$key] = $key . '='; 104 | } 105 | $query = implode("&", $queries); 106 | $cookie = rakutensec_update_cookie($head, $cookie); 107 | list($head, $body_trade_jp) = rakutensec_http11('GET', $uris, $query, $cookie); 108 | 109 | // 取引履歴(投資信託)のCSVを取得する 110 | $uris['path'] = '/app/assTradFuLstCsvServlet;' . $sessionid; 111 | unset($queries['trustKbn']); 112 | unset($queries['hiddenSpotTrustKbn']); 113 | $queries['hiddenTermCd'] = 'hiddenTermCd='; 114 | $query = implode("&", $queries); 115 | $cookie = rakutensec_update_cookie($head, $cookie); 116 | list($head, $body_trade_mf) = rakutensec_http11('GET', $uris, $query, $cookie); 117 | 118 | // 保有商品一覧(国内株式)のCSVを取得する 119 | $uris['path'] = '/app/ass_jp_possess_lst_csv_output.do;' . $sessionid; 120 | $query = 'eventType=csv'; 121 | $cookie = rakutensec_update_cookie($head, $cookie); 122 | list($head, $body_pos_jp) = rakutensec_http11('GET', $uris, $query, $cookie); 123 | 124 | // 保有商品一覧(投資信託)のCSVを取得する 125 | $uris['path'] = '/app/ass_fu_possess_lst_csv_output.do;' . $sessionid; 126 | $query = 'eventType=csv'; 127 | $cookie = rakutensec_update_cookie($head, $cookie); 128 | list($head, $body_pos_mf) = rakutensec_http11('GET', $uris, $query, $cookie); 129 | 130 | // ログアウトする 131 | $uris['path'] = '/app/logout.do;' . $sessionid; 132 | $query = ''; 133 | list($head, $body) = rakutensec_http11('GET', $uris, $query, $cookie); 134 | 135 | // リダイレクトする 136 | $uris['path'] = '/app/logout;' . $sessionid; 137 | list($head, $body) = rakutensec_http11('GET', $uris, $query, $cookie); 138 | 139 | /********** ページ遷移ここまで **********/ 140 | 141 | // ホーム画面のHTMLを処理し、部店-お客様コード(口座番号)を取得する 142 | if (preg_match('/[0-9]{3}-[0-9]{6}/', $body_home, $matches)) $acctid = $matches[0]; 143 | 144 | // DOMツリーを生成 145 | $ofxdom = new ofxDOM("INVSTMT", $settings["name"]); 146 | $ofxdom->setAcctfrom(array( 147 | "BROKERID" => $settings["code"], 148 | "ACCTID" => $acctid 149 | )); 150 | 151 | // 資産情報のHTMLを処理する 152 | $divs = parse_tag($body_balance, 'div'); 153 | $c = parse_tag_search($divs, 'id', 'balance_data_actual_data'); 154 | $tds = parse_tag($divs[$c]['innerHTML'], 'td'); 155 | preg_match('/[0-9,]+/', $tds[21]['innerHTML'], $matches); 156 | $availcash = parse_amount($matches[0]); 157 | 158 | // 残高を設定 159 | $ofxdom->setBalance(array( 160 | 'AVAILCASH' => $availcash, 161 | 'MARGINBALANCE' => $availcash, 162 | 'SHORTBALANCE' => 0 163 | )); 164 | 165 | // 入出力履歴のCSVを処理する 166 | $body_trans = mb_convert_encoding($body_trans, "UTF-8", "sjis-win"); 167 | $rows = parse_csv($body_trans); 168 | array_splice($rows, 0, 4); // ヘッダー行等最初の4行(+空行1行)をスキップする 169 | foreach ($rows as $row) { 170 | $cd = array(); 171 | $date = date_parse($row[0]); 172 | $cd['DTPOSTED'] = sprintf("%d%02d%02d", $date['year'], $date['month'], $date['day']); 173 | $cd['DTPOSTED'] .= ENV_STR_OFX_TZ; 174 | if (preg_match('/[0-9,]+/', $row[1]) > 0) { // 入金 175 | $cd['TRNAMT'] = $row[1]; 176 | } else { // 出金 177 | $cd['TRNAMT'] = '-' . $row[2]; 178 | } 179 | $cd["TRNTYPE"] = ENV_STR_OFX_TRNTYPE_DIRECTDEP; 180 | $cd['NAME'] = $row[3] . ' ' . $row[4]; 181 | // トランザクション番号(請求月とデータ種別)を生成する 182 | $cd["FITID"] = '000'; 183 | 184 | // 入出力履歴をDOMに書き込む 185 | if (strtotime(ENV_STR_DATE_PASTDAY) <= strtotime($row[0]) && strtotime($row[0]) <= strtotime(ENV_STR_DATE_TODAY)) { 186 | $ofxdom->addTran($cd); 187 | } else { 188 | break; 189 | } 190 | } 191 | 192 | // DTSTARTとDTENDを設定する 193 | $ofxdom->setDateRange(ENV_STR_DATE_PASTDAY . ENV_STR_OFX_TZ, ENV_STR_DATE_TODAY . ENV_STR_OFX_TZ); 194 | 195 | // 取引履歴(国内株式)のCSVを処理する 196 | $body_trade_jp = mb_convert_encoding($body_trade_jp, "UTF-8", "sjis-win"); 197 | $rows = parse_csv($body_trade_jp); 198 | array_shift($rows); // ヘッダー行をスキップする 199 | foreach ($rows as $row) { 200 | $ct = array(); 201 | $ct['CATEGORY'] = ENV_STR_OFX_STOCK; 202 | $date = date_parse($row[0]); 203 | $ct['DTTRADE'] = sprintf("%d%02d%02d000000", $date['year'], $date['month'], $date['day']) 204 | . ENV_STR_OFX_TZ; 205 | $ct['UNIQUEID'] = $row[2]; 206 | $ct['SECNAME'] = $row[3]; 207 | $ct['UNIQUEIDTYPE'] = ENV_STR_OFX_CODE_STOCK; 208 | $ct['UNITS'] = (int)parse_amount($row[10]); 209 | $ct['UNITPRICE'] = parse_amount($row[11]); 210 | $ct['FEES'] = (int)parse_amount($row[12]); 211 | $ct['TAXES'] = (int)parse_amount($row[13]); 212 | $ct['COMMISSION'] = (int)parse_amount($row[14]); 213 | $ct['TOTAL'] = (int)parse_amount($row[16]); 214 | $ct['SUBACCTSEC'] = ENV_STR_OFX_CASH; 215 | $ct['SUBACCTFUND'] = ENV_STR_OFX_CASH; 216 | $ct['FITID'] = '000'; 217 | if (preg_match('/買付/', $row[7]) > 0) { 218 | $ct['BUYTYPE'] = ENV_STR_OFX_BUY; 219 | $ct['TOTAL'] *= -1; 220 | } else { 221 | $ct['BUYTYPE'] = ENV_STR_OFX_SELL; 222 | $ct['UNITS'] *= -1; 223 | } 224 | 225 | if (strtotime(ENV_STR_DATE_PASTDAY) <= strtotime($row[0]) && strtotime($row[0]) <= strtotime(ENV_STR_DATE_TODAY)) { 226 | $ofxdom->addTrade($ct); 227 | } 228 | } 229 | 230 | // 取引履歴(投資信託)のCSVを処理する 231 | $body_trade_mf = mb_convert_encoding($body_trade_mf, "UTF-8", "sjis-win"); 232 | $rows = parse_csv($body_trade_mf); 233 | array_shift($rows); // ヘッダー行をスキップする 234 | foreach ($rows as $row) { 235 | $ct = array(); 236 | $ct['CATEGORY'] = ENV_STR_OFX_FUND; 237 | $date = date_parse($row[0]); 238 | $ct['DTTRADE'] = sprintf("%d%02d%02d", $date['year'], $date['month'], $date['day']) 239 | . ENV_STR_OFX_TZ; 240 | $ct['UNIQUEID'] = md5($row[2]); 241 | $ct['SECNAME'] = $row[2]; 242 | $ct['UNIQUEIDTYPE'] = ENV_STR_OFX_CODE_FUND; 243 | $ct['UNITS'] = (int)parse_amount($row[7]); 244 | $ct['UNITPRICE'] = parse_amount($row[8]); 245 | //$ct['FEES'] = (int)parse_amount($row[9]); 246 | // total = units * unitprice + (commission + fee + taxes)とするため、feeを0にする 247 | $ct['FEES'] = 0; 248 | $ct['TAXES'] = 0; 249 | $ct['COMMISSION'] = 0; 250 | $ct['TOTAL'] = (int)parse_amount($row[10]); 251 | $ct['SUBACCTSEC'] = ENV_STR_OFX_CASH; 252 | $ct['FITID'] = '000'; 253 | switch ($row[5]) { 254 | case '買付': 255 | $ct['BUYTYPE'] = ENV_STR_OFX_BUY; 256 | $ct['SUBACCTFUND'] = ENV_STR_OFX_CASH; 257 | $ct['TOTAL'] *= -1; 258 | break; 259 | case '解約': 260 | $ct['BUYTYPE'] = ENV_STR_OFX_SELL; 261 | $ct['SUBACCTFUND'] = ENV_STR_OFX_CASH; 262 | $ct['UNITS'] *= -1; 263 | break; 264 | case '再投資': 265 | default: 266 | $ct['BUYTYPE'] = ENV_STR_OFX_REINVEST; 267 | $ct['INCOMETYPE'] = ENV_STR_OFX_TRNTYPE_INT; 268 | $ct['TOTAL'] *= -1; 269 | break; 270 | } 271 | 272 | if (strtotime(ENV_STR_DATE_PASTDAY) <= strtotime($row[0]) && strtotime($row[0]) <= strtotime(ENV_STR_DATE_TODAY)) { 273 | $ofxdom->addTrade($ct); 274 | } 275 | } 276 | 277 | // 保有商品一覧(国内株式)のCSVを処理する 278 | $body_pos_jp = mb_convert_encoding($body_pos_jp, "UTF-8", "sjis-win"); 279 | $rows = parse_csv($body_pos_jp); 280 | array_shift($rows); // ヘッダー行をスキップする 281 | foreach ($rows as $row) { 282 | $cl = array(); 283 | $cl['CATEGORY'] = ENV_STR_OFX_STOCK; 284 | $cl['HELDINACCT'] = ENV_STR_OFX_CASH; 285 | $cl['POSTYPE'] = 'LONG'; 286 | $cl['DTPRICEASOF'] = ENV_STR_DATE_TODAY; 287 | $cl['UNIQUEIDTYPE'] = ENV_STR_OFX_CODE_STOCK; 288 | $cl['UNIQUEID'] = $row[1]; 289 | $cl['SECNAME'] = $row[2]; 290 | $cl['UNITS'] = (int)parse_amount($row[3]); 291 | $cl['UNITPRICE'] = parse_amount($row[6]); 292 | $cl['MKTVAL'] = (int)parse_amount($row[7]); 293 | $cl['MEMO'] = (int)parse_amount($row[8]); 294 | 295 | $ofxdom->addPos($cl); 296 | $ofxdom->addSec($cl); 297 | } 298 | 299 | // 保有商品一覧(投資信託)のCSVを処理する 300 | $body_pos_mf = mb_convert_encoding($body_pos_mf, "UTF-8", "sjis-win"); 301 | $rows = parse_csv($body_pos_mf); 302 | array_shift($rows); // ヘッダー行をスキップする 303 | foreach ($rows as $row) { 304 | $cl = array(); 305 | $cl['CATEGORY'] = ENV_STR_OFX_FUND; 306 | $cl['HELDINACCT'] = ENV_STR_OFX_CASH; 307 | $cl['POSTYPE'] = 'LONG'; 308 | $cl['DTPRICEASOF'] = ENV_STR_DATE_TODAY; 309 | $cl['UNIQUEID'] = md5($row[2]); 310 | $cl['UNIQUEIDTYPE'] = ENV_STR_OFX_CODE_FUND; 311 | $cl['SECNAME'] = $row[2]; 312 | $cl['UNITS'] = (int)parse_amount($row[4]); 313 | $cl['UNITPRICE'] = 1; 314 | $cl['MKTVAL'] = (int)parse_amount($row[14]); 315 | $cl['MEMO'] = $row[10]; 316 | 317 | $ofxdom->addPos($cl); 318 | $ofxdom->addSec($cl); 319 | } 320 | 321 | // FITIDを仕上げる 322 | $ofxdom->setFitid(); 323 | // XML DOMツリーを文字列に変換 324 | $xml = $ofxdom->getXML(); 325 | $resp["status"] = ENV_NUM_STATUS_SUCCESS; 326 | $resp["ofx"] = generate_ofx($mode, $xml); 327 | 328 | return $resp; 329 | 330 | // HTTP/1.1 331 | function rakutensec_http11($method, $uris, $query = "", $cookie = "") { 332 | $ret = "INVALID HOST"; 333 | if(preg_match("/\.rakuten-sec\.co\.jp$/", $uris["host"]) > 0) $ret = http11(strtoupper($method), $uris["scheme"], $uris["host"], 0, $uris["path"], $query, "", $cookie); 334 | return explode("\r\n\r\n", $ret, 2); 335 | } 336 | function rakutensec_update_cookie($head, $cookie) { 337 | return update_cookie(array( 338 | "Rg_sec", 339 | "checkTk", 340 | ), parse_header($head, "set-cookie"), $cookie); 341 | } 342 | ?> 343 | -------------------------------------------------------------------------------- /server/saisoncard.inc: -------------------------------------------------------------------------------- 1 | <?php 2 | /* 3 | saisoncard.inc: セゾンカードのCSVよりOFXファイルを生成する 4 | Copyright (C) 2012-2017 OFFICE OUTERGUY. All rights reserved. 5 | mailto:contact@beatrek.com 6 | Licensed under the GNU AGPLv3. 7 | */ 8 | 9 | // ログイン情報を取得する 10 | $user = $ofxforms["inputId"]; 11 | $pass = $ofxforms["inputPassword"]; 12 | $auth = urlencode(mb_convert_encoding(urldecode($ofxforms["secretAnswer"]), "Shift_JIS", "UTF-8")); 13 | $sesscookie = $ofxforms["sesscookie"]; 14 | $accesskey = $ofxforms["accesskey"]; 15 | 16 | $resp = array(); 17 | $sid = 0; 18 | $method = ""; 19 | $query = ""; 20 | $cookie = ""; 21 | $head = ""; 22 | $body = ""; 23 | 24 | if($sesscookie != "") list($cookie, $dummy) = explode("\t", sess_decode($sesscookie)); 25 | if($accesskey != "") { 26 | list($ssid, $method, $uri, $query, $pass, $dummy) = explode("\t", sess_decode($accesskey), 6); 27 | $sid = (integer)$ssid; 28 | } 29 | 30 | // 実行時間(タイムアウト)を再設定する 31 | @set_time_limit(ENV_NUM_TIMEOUT); 32 | 33 | if($sid == 0) { 34 | // ホーム画面を取得する 35 | $method = "GET"; 36 | $uris = parse_uri($settings["home"]); 37 | $query = ""; 38 | $cookie = ""; 39 | list($head, $body) = saisoncard_http11($method, $uris, $query, $cookie); 40 | 41 | // ログイン画面を取得する 42 | $as = parse_tag($body, "a", true); // 再帰的に取得する 43 | foreach($as as $a) if(parse_tag_search(parse_tag($a["innerHTML"], "img"), "alt", "ログインはこちらから") != -1) { 44 | $method = "GET"; 45 | $uris = parse_uri($a["href"], $uris); 46 | $query = ""; 47 | $cookie = saisoncard_update_cookie($head, $cookie); 48 | list($head, $body) = saisoncard_http11($method, $uris, $query, $cookie); 49 | break; 50 | } 51 | 52 | // ログインする 53 | $forms = parse_tag($body, "form"); 54 | $c = parse_tag_search($forms, "name", "_USA01Form"); 55 | if($c != -1) { 56 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 57 | $queries = array(); 58 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 59 | $queries["inputId"] = "inputId=" . $user; 60 | $queries["inputPassword"] = "inputPassword=" . $pass; 61 | if(isset($queries["inputIdCheckBox"]) == true) unset($queries["inputIdCheckBox"]); 62 | 63 | $method = $forms[$c]["method"]; 64 | $uris = parse_uri($forms[$c]["action"], $uris); 65 | $query = implode("&", $queries); 66 | $cookie = saisoncard_update_cookie($head, $cookie); 67 | list($head, $body) = saisoncard_http11($method, $uris, $query, $cookie); 68 | } 69 | } 70 | 71 | if(strpos($body, "秘密の質問によるご本人様確認") !== false) { 72 | // 秘密の答えを入力する 73 | $tds = parse_tag($body, "td"); 74 | $shitsumon = ""; 75 | foreach($tds as $td) if($td["class"] == "td-01") { 76 | $shitsumon = trim(strip_tags($td["innerHTML"])); 77 | break; 78 | } 79 | 80 | $forms = parse_tag($body, "form"); 81 | $c = parse_tag_search($forms, "name", "_UST00Form"); 82 | if($c != -1) { 83 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 84 | $queries = array(); 85 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 86 | $queries["secretAnswer"] = "secretAnswer="; 87 | 88 | $method = $forms[$c]["method"]; 89 | $uris = parse_uri($forms[$c]["action"], $uris); 90 | $query = implode("&", $queries); 91 | $cookie = saisoncard_update_cookie($head, $cookie); 92 | } 93 | 94 | // セッションを退避する 95 | $sid = 1; 96 | $head = ""; 97 | $body = ""; 98 | } else if($sid == 1) { 99 | // セッションを復元する 100 | $sid = 0; 101 | $uris = parse_uri($uri); 102 | $query = str_replace("secretAnswer=", "secretAnswer=" . $auth, $query); 103 | list($head, $body) = saisoncard_http11($method, $uris, $query, $cookie); 104 | } 105 | 106 | if($sid > 0) { 107 | // セッションを引き継ぐ 108 | $resp["status"] = ENV_NUM_STATUS_ADDITION; 109 | $resp["aid"] = "secretAnswer"; 110 | $resp["additional"] = $shitsumon; 111 | $resp["sid"] = $sid; 112 | $resp["sesscookie"] = sess_encode(implode("\t", array($cookie, ENV_STR_SESSION_PADDING))); 113 | $resp["accesskey"] = sess_encode(implode("\t", array((string)$sid, $method, $uris["scheme"] . "://" . $uris["host"] . $uris["path"], $query, $pass, ENV_STR_SESSION_PADDING))); 114 | 115 | $mfachallengetrnrs = ""; 116 | $mfachallengetrnrs .= "<MFACHALLENGETRNRS>"; 117 | $mfachallengetrnrs .= "<MFACHALLENGERS>"; 118 | $mfachallengetrnrs .= "<MFACHALLENGE>"; 119 | $mfachallengetrnrs .= "<MFAPHRASEID>" . $resp["aid"] . "</MFAPHRASEID>"; 120 | $mfachallengetrnrs .= "<MFAPHRASELABEL>" . $resp["additional"] . "</MFAPHRASELABEL>"; 121 | $mfachallengetrnrs .= "</MFACHALLENGE>"; 122 | $mfachallengetrnrs .= "</MFACHALLENGERS>"; 123 | $mfachallengetrnrs .= "</MFACHALLENGETRNRS>"; 124 | 125 | $resp["ofx"] = generate_ofx($resp["status"], $mfachallengetrnrs, $resp["sesscookie"], $resp["accesskey"]); 126 | } else if(strpos($body, "秘密の質問設定") !== false) { 127 | // ログイン後の画面が通常と異なる場合 128 | $resp["status"] = ENV_NUM_STATUS_CAUTION; 129 | $resp["method"] = $method; 130 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 131 | $resp["query"] = $query; 132 | $resp["cookie"] = $cookie; 133 | $resp["head"] = $head; 134 | $resp["body"] = $body; 135 | $resp["ofx"] = generate_ofx($resp["status"]); 136 | } else if(strpos($body, "メンテナンス中") !== false || strpos($body, "サービスがご利用いただけません") !== false) { 137 | // システムメンテナンス画面の場合 138 | $resp["status"] = ENV_NUM_STATUS_MAINTENANCE; 139 | $resp["method"] = $method; 140 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 141 | $resp["query"] = $query; 142 | $resp["cookie"] = $cookie; 143 | $resp["head"] = $head; 144 | $resp["body"] = $body; 145 | $resp["ofx"] = generate_ofx($resp["status"]); 146 | } else if(strpos($body, "前回ログイン") === false) { 147 | // ログイン失敗の場合 148 | $resp["status"] = ENV_NUM_STATUS_FAILURE; 149 | $resp["method"] = $method; 150 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 151 | $resp["query"] = $query; 152 | $resp["cookie"] = $cookie; 153 | $resp["head"] = $head; 154 | $resp["body"] = $body; 155 | $resp["ofx"] = generate_ofx($resp["status"]); 156 | } else { 157 | $account = array(); 158 | $account["id"] = 0; 159 | 160 | // 実行時間(タイムアウト)を再設定する 161 | @set_time_limit(ENV_NUM_TIMEOUT); 162 | 163 | // Netアンサー情報照会画面を取得する 164 | $as = parse_tag($body, "a"); 165 | foreach($as as $a) if(parse_tag_search(parse_tag($a["innerHTML"], "img"), "alt", "Netアンサー登録内容変更 NetアンサーID、パスワード、 メールアドレスなど ") != -1) { 166 | $method = "GET"; 167 | $uris = parse_uri($a["href"], $uris); 168 | $query = ""; 169 | $cookie = saisoncard_update_cookie($head, $cookie); 170 | list($head, $body) = saisoncard_http11($method, $uris, $query, $cookie); 171 | break; 172 | } 173 | 174 | $tds = parse_tag($body, "td", true); // 再帰的に取得する 175 | $bufs = array(); 176 | foreach($tds as $td) if($td["class"] == "td-01") array_push($bufs, trim(strip_tags($td["innerHTML"]))); 177 | if(count($bufs) >= 2) { 178 | // カード名称を取得する 179 | $account["acctname"] = implode(ENV_CHR_CONCATENATOR, array($settings["name"], $bufs[0])); 180 | $account["name"] = $settings["name"]; 181 | 182 | // カード番号を取得する 183 | $account["acctid"] = $bufs[2]; 184 | } 185 | 186 | // ご利用明細画面を取得する 187 | $as = parse_tag($body, "a"); 188 | $c = parse_tag_search($as, "innerHTML", "ご利用明細照会"); 189 | if($c != -1) { 190 | $method = "GET"; 191 | $uris = parse_uri($as[$c]["href"], $uris); 192 | $query = ""; 193 | $cookie = saisoncard_update_cookie($head, $cookie); 194 | list($head, $body) = saisoncard_http11($method, $uris, $query, $cookie); 195 | } 196 | 197 | // 最新の請求月を取得する(お支払日は4日であると仮定する) 198 | $c = preg_match_all("/([0-9]{1,2})" . preg_quote("月お支払分") . "/", $body, $matches); 199 | if($c > 0) { 200 | $matches[1][0] = sprintf("%02d", (integer)$matches[1][0]); 201 | $account["paydate"] = (date("m") <= $matches[1][0]? date("Y"): (string)((integer)date("Y") + 1)) . $matches[1][0] . "04"; 202 | } 203 | 204 | $body_old = $body; 205 | 206 | // CSVファイルをダウンロードする 207 | $as = parse_tag($body, "a"); 208 | foreach($as as $a) if(parse_tag_search(parse_tag($a["innerHTML"], "img"), "alt", "CSVダウンロード") != -1) { 209 | $method = "GET"; 210 | $uris = parse_uri($a["href"], $uris); 211 | $query = ""; 212 | $cookie = saisoncard_update_cookie($head, $cookie); 213 | list($head, $body) = saisoncard_http11($method, $uris, $query, $cookie); 214 | break; 215 | } 216 | 217 | if(strpos($head, "Content-Type: text/html") === false) { 218 | $creditcardmsgsrsv1 = ""; 219 | $creditcardmsgsrsv1 .= "<CREDITCARDMSGSRSV1>"; 220 | $creditcardmsgsrsv1 .= "\r\n"; 221 | 222 | $creditcardmsgsrsv1 .= "<CCSTMTTRNRS>"; 223 | $creditcardmsgsrsv1 .= "\r\n"; 224 | $creditcardmsgsrsv1 .= "<TRNUID>0</TRNUID>"; 225 | $creditcardmsgsrsv1 .= "\r\n"; 226 | $creditcardmsgsrsv1 .= "<STATUS><CODE>0</CODE><SEVERITY>INFO</SEVERITY></STATUS>"; 227 | $creditcardmsgsrsv1 .= "\r\n"; 228 | $creditcardmsgsrsv1 .= "<CCSTMTRS>"; 229 | $creditcardmsgsrsv1 .= "\r\n"; 230 | $creditcardmsgsrsv1 .= "<CURDEF>" . ENV_STR_OFX_CURRENCY_JPY . "</CURDEF>"; 231 | $creditcardmsgsrsv1 .= "\r\n"; 232 | $creditcardmsgsrsv1 .= "<CCACCTFROM>"; 233 | $creditcardmsgsrsv1 .= "<ACCTID>" . $account["acctid"] . "</ACCTID>"; 234 | $creditcardmsgsrsv1 .= "</CCACCTFROM>"; 235 | $creditcardmsgsrsv1 .= "\r\n"; 236 | $creditcardmsgsrsv1 .= saisoncard_parse_csv($body, $account); 237 | $creditcardmsgsrsv1 .= "</CCSTMTRS>"; 238 | $creditcardmsgsrsv1 .= "\r\n"; 239 | $creditcardmsgsrsv1 .= "</CCSTMTTRNRS>"; 240 | $creditcardmsgsrsv1 .= "\r\n"; 241 | 242 | $creditcardmsgsrsv1 .= "</CREDITCARDMSGSRSV1>"; 243 | $creditcardmsgsrsv1 .= "\r\n"; 244 | } 245 | 246 | $body = $body_old; 247 | 248 | // 実行時間(タイムアウト)を再設定する 249 | @set_time_limit(ENV_NUM_TIMEOUT); 250 | 251 | // ログアウトする 252 | $as = parse_tag($body, "a"); 253 | foreach($as as $a) if(parse_tag_search(parse_tag($a["innerHTML"], "img"), "alt", "ログアウト") != -1) { 254 | $method = "GET"; 255 | $uris = parse_uri($a["href"], $uris); 256 | $query = ""; 257 | $cookie = saisoncard_update_cookie($head, $cookie); 258 | list($head, $body) = saisoncard_http11($method, $uris, $query, $cookie); 259 | break; 260 | } 261 | 262 | // OFXファイルを出力する 263 | $resp["status"] = ENV_NUM_STATUS_SUCCESS; 264 | if(strpos($creditcardmsgsrsv1, "<BANKTRANLIST>") === false) { 265 | // 明細が存在しない場合 266 | $resp["ofx"] = generate_ofx($resp["status"]); 267 | } else { 268 | // 明細が存在する場合 269 | $resp["ofx"] = generate_ofx($resp["status"], $creditcardmsgsrsv1); 270 | } 271 | } 272 | return $resp; 273 | 274 | // HTTP/1.1 275 | function saisoncard_http11($method, $uris, $query = "", $cookie = "") { 276 | $ret = "INVALID HOST"; 277 | if(preg_match("/\.saisoncard\.co\.jp$/", $uris["host"]) > 0) $ret = http11(strtoupper($method), $uris["scheme"], $uris["host"], 0, $uris["path"], $query, "", $cookie); 278 | return explode("\r\n\r\n", $ret, 2); 279 | } 280 | 281 | function saisoncard_update_cookie($head, $cookie) { 282 | return update_cookie(array("JSESSIONID"), parse_header($head, "set-cookie"), $cookie); 283 | } 284 | 285 | function saisoncard_parse_csv($str, $account) { 286 | $ret = ""; 287 | $lines = parse_csv(mb_convert_string($str)); 288 | $cds = array(); 289 | $cds_balamt = "0"; 290 | $cds_paydate = $account["paydate"]; 291 | $cds_s = ""; 292 | $cds_e = ""; 293 | $cd_date = ""; 294 | $cd_num = 0; 295 | $ledge_balamt = 0; 296 | 297 | foreach($lines as $line) { 298 | $cd = array(); 299 | 300 | if(count($line) == 2) { 301 | switch($line[0]) { 302 | case "お支払日": 303 | $cds_paydate = parse_date($line[1]); 304 | break; 305 | case "今回ご請求額": 306 | $cds_balamt = (string)(double)parse_amount($line[1]); 307 | $ledge_balamt = (double)$cds_balamt; 308 | break; 309 | case "カード名称": 310 | default: 311 | break; 312 | } 313 | } else if(count($line) == 7 && $line[0] != "利用日") { 314 | // PAYMENT固定とする 315 | $cd["TRNTYPE"] = ENV_STR_OFX_TRNTYPE_PAYMENT; 316 | 317 | // 日付を取得する 318 | $cd["DTPOSTED"] = parse_date($line[0]); 319 | if($cds_s == "") $cds_s = $cd["DTPOSTED"]; 320 | $cds_e = $cd["DTPOSTED"]; 321 | 322 | // 通番を生成する 323 | if($cd["DTPOSTED"] == $cd_date) $cd_num++; else $cd_num = 0; 324 | 325 | // トランザクション番号を生成する 326 | $cd["FITID"] = $cd["DTPOSTED"] . sprintf("%04d", $account["id"]) . substr($account["paydate"], 4, 2) . "0" . sprintf("%05d", $cd_num); 327 | 328 | // 摘要を取得する 329 | $cd["NAME"] = $line[1]; 330 | 331 | // 金額を取得する 332 | $cd["TRNAMT"] = (string)(-1 * (double)parse_amount($line[5])); 333 | $ledge_balamt += (double)$cd["TRNAMT"]; 334 | 335 | // 残高を取得する 336 | $cd["MEMO"] = ($line[6] != ""? $line[6]: ENV_STR_OFX_MEMO); 337 | 338 | array_push($cds, $cd); 339 | $cd_date = $cd["DTPOSTED"]; 340 | } 341 | } 342 | 343 | if($cds_s == "") $cds_s = ENV_STR_DATE_TODAY; 344 | if($cds_e == "") $cds_e = ENV_STR_DATE_TODAY; 345 | if($cds_s > $cds_e) $cds_e = $cds_s; 346 | 347 | // クレジットカード支払請求を明細に追加する 348 | $i = count($cds); 349 | $cds[$i]["DTPOSTED"] = $cds_paydate; 350 | $cds[$i]["NAME"] = $account["name"]; 351 | $cds[$i]["MEMO"] = ENV_STR_OFX_MEMO; 352 | $cds[$i]["TRNAMT"] = $cds_balamt; 353 | $cds[$i]["TRNTYPE"] = ENV_STR_OFX_TRNTYPE_DIRECTDEBIT; 354 | $cds[$i]["FITID"] = $cds[$i]["DTPOSTED"] . sprintf("%04d", $account["id"]) . substr($account["paydate"], 4, 2) . "100000"; 355 | 356 | // BANKTRANLIST 357 | $ret .= "<BANKTRANLIST>"; 358 | $ret .= "\r\n"; 359 | $ret .= "<DTSTART>" . $cds_s . ENV_STR_OFX_TZ . "</DTSTART>"; 360 | $ret .= "<DTEND>" . $cds_e . ENV_STR_OFX_TZ . "</DTEND>"; 361 | $ret .= "\r\n"; 362 | 363 | foreach($cds as $cd) { 364 | $ret .= "<STMTTRN>"; 365 | $ret .= "<TRNTYPE>" . $cd["TRNTYPE"] . "</TRNTYPE>"; 366 | $ret .= "<DTPOSTED>" . $cd["DTPOSTED"] . ENV_STR_OFX_TZ . "</DTPOSTED>"; 367 | $ret .= "<TRNAMT>" . $cd["TRNAMT"] . "</TRNAMT>"; 368 | $ret .= "<FITID>" . $cd["FITID"] . "</FITID>"; 369 | $ret .= "<NAME>" . $cd["NAME"] . "</NAME>"; 370 | $ret .= "<MEMO>" . $cd["MEMO"] . "</MEMO>"; 371 | $ret .= "</STMTTRN>"; 372 | $ret .= "\r\n"; 373 | } 374 | 375 | $ret .= "</BANKTRANLIST>"; 376 | $ret .= "\r\n"; 377 | 378 | // 支払後残高を出力する 379 | $ret .= "<LEDGERBAL>"; 380 | $ret .= "<BALAMT>" . (string)$ledge_balamt . "</BALAMT>"; 381 | $ret .= "<DTASOF>" . ENV_STR_DATE_TODAY . ENV_STR_OFX_TZ . "</DTASOF>"; 382 | $ret .= "</LEDGERBAL>"; 383 | $ret .= "\r\n"; 384 | 385 | // カード名称を出力する 386 | if($account["acctname"] != "") { 387 | $ret .= "<MKTGINFO>" . $account["acctname"] . "</MKTGINFO>"; 388 | $ret .= "\r\n"; 389 | } 390 | 391 | return $ret; 392 | } 393 | 394 | ?> 395 | -------------------------------------------------------------------------------- /server/surugavisacard.inc: -------------------------------------------------------------------------------- 1 | <?php 2 | /* 3 | surugavisacard.inc: スルガ銀行 VISAデビット/VISAクレジットのHTMLよりOFXファイルを生成する 4 | Copyright (C) 2012-2017 Hiromu2000. All Rights Reserved. 5 | mailto:hiromu2000@hotmail.com 6 | Licensed under the GNU AGPLv3. 7 | */ 8 | 9 | // ログイン情報を取得する 10 | $user = $ofxforms["loginID"]; 11 | $pass1 = $ofxforms["telPin"]; 12 | $pass2 = $ofxforms["webPin"]; 13 | $mode = $ofxforms["mode"]; 14 | 15 | $resp = array(); 16 | $resp["status"] = ENV_NUM_STATUS_NONE; 17 | $ofx = ""; 18 | 19 | // 実行時間(タイムアウト)を再設定する 20 | @set_time_limit(ENV_NUM_TIMEOUT); 21 | 22 | // ホーム画面を取得する 23 | $urls = parse_url($settings["home"]); 24 | $method = "GET"; 25 | $protocol = ($urls["scheme"] != ""? $urls["scheme"]: ""); 26 | $host = ($urls["host"] != ""? $urls["host"]: ""); 27 | $page = ($urls["path"] != ""? $urls["path"]: "/"); 28 | $query = ""; 29 | $cookie = ""; 30 | list($head, $body) = surugavisa_http11($method, $protocol, $host, $page, $query, $cookie); 31 | 32 | // ログイン画面を取得する 33 | $protocol = 'https'; 34 | $page = '/Top.do'; 35 | $cookie = surugavisa_updatecookie($head, $cookie); 36 | list($head, $body) = surugavisa_http11($method, $protocol, $host, $page, $query, $cookie); 37 | 38 | // ログインする 39 | $forms = parse_tag($body, "form"); 40 | $c = parse_tag_search($forms, "name", "loginForm"); 41 | $method = "POST"; 42 | $urls = parse_url($forms[$c]['action']); 43 | if($urls["scheme"] != "") $protocol = $urls["scheme"]; 44 | if($urls["host"] != "") $host = $urls["host"]; 45 | if($urls["path"] != "") $page = $urls["path"]; 46 | if($urls["query"] != "") $page .= "?" . $urls["query"]; 47 | 48 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 49 | $queries = array(); 50 | foreach ($inputs as $input) { 51 | if ($input["name"] != "") { 52 | $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 53 | } 54 | } 55 | $queries["loginID"] .= $user; 56 | $queries["telPin"] .= $pass1; 57 | $queries["webPin"] .= $pass2; 58 | $query = implode("&", $queries); 59 | $cookie = surugavisa_updatecookie($head, $cookie); 60 | list($head, $body) = surugavisa_http11($method, $protocol, $host, $page, $query, $cookie); 61 | 62 | if(strpos($body, "只今メンテナンス中です") !== false) { 63 | // システムメンテナンス画面の場合 64 | $resp["status"] = ENV_NUM_STATUS_MAINTENANCE; 65 | $resp["method"] = $method; 66 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 67 | $resp["query"] = $query; 68 | $resp["cookie"] = $cookie; 69 | $resp["head"] = $head; 70 | $resp["body"] = $body; 71 | $resp["ofx"] = generate_ofx($resp["status"]); 72 | } else if(strpos($body, "loginForm") !== false) { 73 | // ログイン失敗の場合 74 | $resp["status"] = ENV_NUM_STATUS_FAILURE; 75 | $resp["method"] = $method; 76 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 77 | $resp["query"] = $query; 78 | $resp["cookie"] = $cookie; 79 | $resp["head"] = $head; 80 | $resp["body"] = $body; 81 | $resp["ofx"] = generate_ofx($resp["status"]); 82 | } else { 83 | // カード名称・カード番号を取得する 84 | $account['acctname'] = 'スルガ Visaデビット/クレジット'; 85 | $account['acctid'] = substr($user, 12); 86 | // DOMツリーを生成 87 | $ofxdom = new ofxDOM("CREDITCARD", $settings["name"]); 88 | $ofxdom->setAcctfrom(array("ACCTID" => $account["acctid"])); 89 | 90 | // メニューから「ご利用明細」を選択 91 | $cds = array(); 92 | for ($i=0;$i<6;$i++) { 93 | $forms = parse_tag($body, "form"); 94 | $c = parse_tag_search($forms, "name", "meisaiForm"); 95 | $page = '/meisai.do'; 96 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 97 | $queries = array(); 98 | foreach ($inputs as $input) { 99 | if ($input["name"] != "") { 100 | $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 101 | } 102 | } 103 | $queries["month"] = "month=" . $i; 104 | $query = implode("&", $queries); 105 | $cookie = surugavisa_updatecookie($head, $cookie); 106 | list($head, $body) = surugavisa_http11($method, $protocol, $host, $page, $query, $cookie); 107 | // 明細をパース 108 | $cds = array_merge($cds, surugavisa_parsedom($body)); 109 | } 110 | usort($cds, function($a, $b) { 111 | return $a['DTPOSTED'] > $b['DTPOSTED']; 112 | }); 113 | foreach($cds as $cd) { 114 | $ofxdom->addTran($cd); 115 | } 116 | $cds_balamt = 0; 117 | $cds_s = ""; 118 | $cds_e = ""; 119 | $items = $ofxdom->getTrans(); 120 | foreach ($items as $item) { 121 | $dtposted = $item->DTPOSTED; 122 | // DTSTART, DTENDを取得 123 | if($cds_s == "") $cds_s = $dtposted; 124 | $cds_e = $dtposted; 125 | // 残高を計算 126 | $cds_balamt += (double)$item->TRNAMT; 127 | } 128 | 129 | // DTSTARTとDTENDを設定する 130 | $ofxdom->setDateRange($cds_s, $cds_e); 131 | 132 | // 残高を処理 133 | $cds_balamt = (-1)*$cds_balamt; 134 | $ofxdom->setBalance(array( 135 | 'BALAMT' => $cds_balamt, 136 | 'DTASOF' => ENV_STR_DATE_TODAY . ENV_STR_OFX_TZ 137 | )); 138 | 139 | // FITIDを仕上げる 140 | $ofxdom->setFitid(); 141 | // XML DOMツリーを文字列に変換 142 | $xml = $ofxdom->getXML(); 143 | 144 | $resp["status"] = ENV_NUM_STATUS_SUCCESS; 145 | $resp["ofx"] = generate_ofx($mode, $xml); 146 | 147 | // 実行時間(タイムアウト)を再設定する 148 | @set_time_limit(ENV_NUM_TIMEOUT); 149 | 150 | // ログアウトする 151 | $forms = parse_tag($body, "form"); 152 | $c = parse_tag_search($forms, "name", "logoutForm"); 153 | $page = '/logout.do'; 154 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 155 | $queries = array(); 156 | foreach ($inputs as $input) { 157 | if ($input["name"] != "") { 158 | $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 159 | } 160 | } 161 | $query = implode("&", $queries); 162 | $cookie = surugavisa_updatecookie($head, $cookie); 163 | list($head, $body) = surugavisa_http11($method, $protocol, $host, $page, $query, $cookie); 164 | } 165 | return $resp; 166 | 167 | // HTTP/1.1 168 | function surugavisa_http11($method, $protocol, $host, $page = "/", $query = "", $cookie = "") { 169 | $ret = "INVALID HOST"; 170 | if(preg_match("/card\.surugabank\.co\.jp$/", $host) > 0) $ret = http11($method, $protocol, $host, 0, $page, $query, "", $cookie); 171 | if(preg_match("/[Ll][Oo][Cc][Aa][Tt][Ii][Oo][Nn][\s\t]*:[\s\t]*([^\r\n]+)/", $ret, $matches) > 0) { 172 | $urls = parse_url($matches[1]); 173 | if($urls["scheme"] != "") $protocol = $urls["scheme"]; 174 | if($urls["host"] != "") $host = $urls["host"]; 175 | if($urls["path"] != "") $page = $urls["path"]; 176 | $query = ($urls["query"] != ""? $urls["query"]: ""); 177 | return surugavisa_http11($method, $protocol, $host, $page, $query, $cookie); 178 | } 179 | return explode("\r\n\r\n", $ret, 2); 180 | } 181 | 182 | function surugavisa_updatecookie($head, $cookie) { 183 | return update_cookie(array("JSESSIONID"), parse_header($head, "set-cookie"), $cookie); 184 | } 185 | 186 | function surugavisa_parsedom($str) { 187 | // 明細表読み込み用DOMツリー作成 188 | $doc = new DOMDocument(); 189 | // <meta … charset=Shift_JIS">の前の<title>が,文字化けの原因となるため,削除 190 | preg_match("/(<body.*<\/body>)/s", $str, $matches); 191 | $str = $matches[1]; 192 | // ヘッダ付加 193 | $str = "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\"><\/head>" . $str . "<\/html>"; 194 | // 文字エンコード変換 195 | // $str = mb_convert_encoding($str, 'UTF-8', 'SJIS'); 196 | //   197 | $str = str_replace(" ", "", $str); 198 | // HTMLからDOMツリー作成 199 | @$doc->loadHTML($str); 200 | $xpath = new DOMXPath($doc); 201 | // 明細表のテーブルを指定 202 | $rows = $xpath->query("//table[@class='table-type2 clear margin-b-10px']/tr"); 203 | 204 | $ret = ""; 205 | $cds = array(); 206 | $nrow = $rows->length; 207 | 208 | for($i=0; $i<$nrow; $i++) { 209 | $cd = array(); 210 | $row = $rows->item($i); 211 | $cols1 = $row->getElementsByTagName('th'); 212 | $cols2 = $row->getElementsByTagName('td'); 213 | // 利用明細でない行はスキップ 214 | if ($cols1->length != 2) continue; 215 | 216 | $cd["TRNTYPE"] = ENV_STR_OFX_TRNTYPE_CREDIT; 217 | 218 | // 日付を取得する 219 | preg_match("/([0-9]{4}).*?([0-9]{1,2}).*?([0-9]{1,2})/", str_replace(" ", "", $cols1->item(1)->nodeValue), $matches); 220 | $cd["DTPOSTED"] = sprintf("%d%02d%02d", $matches[1], $matches[2], $matches[3]); 221 | $cd["DTPOSTED"] .= ENV_STR_OFX_TZ; 222 | 223 | // トランザクション番号(請求月とデータ種別)を生成する 224 | $cd["FITID"] = '000'; 225 | // 摘要を取得する 226 | $cd["NAME"] = $cols2->item(0)->nodeValue; 227 | // $cd["NAME"] = preg_replace('/-/', mb_convert_encoding('ー', 'UTF-8', 'sjis-win'), $cd["NAME"]); 228 | $cd["NAME"] = str_replace('-', 'ー', $cd["NAME"]); 229 | // 金額を取得する 230 | $cd["TRNAMT"] = (-1)*(double)parse_amount(trim($cols2->item(1)->nodeValue)); 231 | if (strpos($cols1->item(0)->nodeValue, "取消") !== false) { 232 | $cd["NAME"] .= "(取消)"; 233 | $cd["TRNAMT"] *= -1; 234 | } 235 | array_push($cds, $cd); 236 | } 237 | return $cds; 238 | 239 | } 240 | ?> 241 | -------------------------------------------------------------------------------- /server/viewcard.inc: -------------------------------------------------------------------------------- 1 | <?php 2 | /* 3 | viewcard.inc: ビューカードのCSVよりOFXファイルを生成する 4 | Copyright (C) 2012-2017 OFFICE OUTERGUY. All rights reserved. 5 | mailto:contact@beatrek.com 6 | Licensed under the GNU AGPLv3. 7 | */ 8 | 9 | // ログイン情報を取得する 10 | $user = $ofxforms["id"]; 11 | $pass = $ofxforms["pass"]; 12 | 13 | $resp = array(); 14 | $ofx = ""; 15 | 16 | // 実行時間(タイムアウト)を再設定する 17 | @set_time_limit(ENV_NUM_TIMEOUT); 18 | 19 | // ホーム画面を取得する 20 | $method = "GET"; 21 | $uris = parse_uri($settings["home"]); 22 | $query = ""; 23 | $cookie = ""; 24 | list($head, $body) = viewcard_http11($method, $uris, $query, $cookie); 25 | 26 | // ログイン画面を取得する 27 | $as = parse_tag($body, "a"); 28 | foreach($as as $a) if(strip_tags($a["innerHTML"]) == "VIEW's NETログイン(VIEW's NET IDの方)") { 29 | $method = "GET"; 30 | $uris = parse_uri($a["href"], $uris); 31 | $query = ""; 32 | $cookie = viewcard_update_cookie($head, $cookie); 33 | list($head, $body) = viewcard_http11($method, $uris, $query, $cookie); 34 | break; 35 | } 36 | 37 | // リダイレクトする 38 | $retry = 0; 39 | while($retry++ < ENV_NUM_HTTP11_RETRY) { 40 | $locations = parse_header($head, "location"); 41 | if(count($locations) > 0) { 42 | $method = "GET"; 43 | $uris = parse_uri($locations[0], $uris); 44 | $query = ""; 45 | $cookie = viewcard_update_cookie($head, $cookie); 46 | list($head, $body) = viewcard_http11($method, $uris, $query, $cookie); 47 | } 48 | } 49 | 50 | // ログインする 51 | $forms = parse_tag($body, "form"); 52 | $c = parse_tag_search($forms, "target", "_self"); 53 | if($c != -1) { 54 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 55 | $queries = array(); 56 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 57 | $queries["id"] = "id=" . $user; 58 | $queries["pass"] = "pass=" . $pass; 59 | 60 | $method = $forms[$c]["method"]; 61 | $uris = parse_uri($forms[$c]["action"], $uris); 62 | $query = implode("&", $queries); 63 | $cookie = viewcard_update_cookie($head, $cookie); 64 | list($head, $body) = viewcard_http11($method, $uris, $query, $cookie); 65 | } 66 | 67 | // リダイレクトする 68 | $retry = 0; 69 | while($retry++ < ENV_NUM_HTTP11_RETRY) { 70 | $locations = parse_header($head, "location"); 71 | if(count($locations) > 0) { 72 | $method = "GET"; 73 | $uris = parse_uri($locations[0], $uris); 74 | $query = ""; 75 | $cookie = viewcard_update_cookie($head, $cookie); 76 | list($head, $body) = viewcard_http11($method, $uris, $query, $cookie); 77 | } 78 | } 79 | 80 | if(strpos($body, "前回ログイン") === false) { 81 | // ログイン失敗の場合 82 | $resp["status"] = ENV_NUM_STATUS_FAILURE; 83 | $resp["method"] = $method; 84 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 85 | $resp["query"] = $query; 86 | $resp["cookie"] = $cookie; 87 | $resp["head"] = $head; 88 | $resp["body"] = $body; 89 | $resp["ofx"] = generate_ofx($resp["status"]); 90 | } else { 91 | // ご利用明細照会(お支払方法の変更)画面を取得する 92 | $as = parse_tag($body, "a"); 93 | $c = parse_tag_search($as, "alt", "ご利用明細照会(お支払方法の変更)"); 94 | if($c != -1) { 95 | $method = "GET"; 96 | $uris = parse_uri($as[$c]["href"], $uris); 97 | $query = ""; 98 | $cookie = viewcard_update_cookie($head, $cookie); 99 | list($head, $body) = viewcard_http11($method, $uris, $query, $cookie); 100 | } 101 | 102 | // リダイレクトする 103 | $retry = 0; 104 | while($retry++ < ENV_NUM_HTTP11_RETRY) { 105 | $locations = parse_header($head, "location"); 106 | if(count($locations) > 0) { 107 | $method = "GET"; 108 | $uris = parse_uri($locations[0], $uris); 109 | $query = ""; 110 | $cookie = viewcard_update_cookie($head, $cookie); 111 | list($head, $body) = viewcard_http11($method, $uris, $query, $cookie); 112 | } 113 | } 114 | 115 | $accounts = array(); 116 | 117 | // カード数を取得する 118 | $selects = parse_tag($body, "select"); 119 | $c = parse_tag_search($selects, "name", "DdlCardNO"); 120 | if($c != -1) { 121 | $options = parse_tag($selects[$c]["innerHTML"], "option"); 122 | for($i = 0; $i < count($options); $i++) { 123 | $accounts[$i]["id"] = $options[$i]["value"]; 124 | $accounts[$i]["ym"] = $ym; 125 | if(preg_match("/(.*?)[\s\t]*([0-9\*\-]+)/", trim(strip_tags($options[$i]["innerHTML"])), $matches) > 0) { 126 | // カード名称を取得する 127 | $accounts[$i]["acctname"] = implode(ENV_CHR_CONCATENATOR, array($settings["name"], $matches[1])); 128 | 129 | $accounts[$i]["name"] = $settings["name"]; 130 | 131 | // カード番号を取得する 132 | $accounts[$i]["acctid"] = $matches[2]; 133 | } 134 | } 135 | } 136 | 137 | $body_old = $body; 138 | 139 | $creditcardmsgsrsv1 = ""; 140 | $creditcardmsgsrsv1 .= "<CREDITCARDMSGSRSV1>"; 141 | $creditcardmsgsrsv1 .= "\r\n"; 142 | 143 | // カード数分ループする 144 | foreach($accounts as $account) { 145 | $body = $body_old; 146 | 147 | // 実行時間(タイムアウト)を再設定する 148 | @set_time_limit(ENV_NUM_TIMEOUT); 149 | 150 | // 確定済みの最新明細画面を取得する 151 | $forms = parse_tag($body, "form"); 152 | $c = parse_tag_search($forms, "name", "Frm002"); 153 | if($c != -1) { 154 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 155 | $queries = array(); 156 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 157 | $queries["DdlCardNO"] = "DdlCardNO=" . $account["id"]; 158 | $queries["__EVENTTARGET"] = "__EVENTTARGET=LnkClaimYm1"; // 確定済みの最新明細 159 | 160 | $method = $forms[$c]["method"]; 161 | $uris = parse_uri($forms[$c]["action"], $uris); 162 | $query = implode("&", $queries); 163 | $cookie = viewcard_update_cookie($head, $cookie); 164 | list($head, $body) = viewcard_http11($method, $uris, $query, $cookie); 165 | } 166 | 167 | // リダイレクトする 168 | $retry = 0; 169 | while($retry++ < ENV_NUM_HTTP11_RETRY) { 170 | $locations = parse_header($head, "location"); 171 | if(count($locations) > 0) { 172 | $method = "GET"; 173 | $uris = parse_uri($locations[0], $uris); 174 | $query = ""; 175 | $cookie = viewcard_update_cookie($head, $cookie); 176 | list($head, $body) = viewcard_http11($method, $uris, $query, $cookie); 177 | } 178 | } 179 | 180 | // お支払日は4日であると仮定する 181 | if(strpos($body, "ご請求はございません。") !== false) { 182 | $body = ""; 183 | $account["paydate"] = substr(ENV_STR_DATE_TODAY, 0, 6) . "04"; 184 | } 185 | 186 | $body_old = $body; 187 | 188 | // 明細CSVをダウンロードする 189 | $forms = parse_tag($body, "form"); 190 | $c = parse_tag_search($forms, "name", "Form1"); 191 | if($c != -1) { 192 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 193 | $queries = array(); 194 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 195 | $queries["DdlCardNO"] = "DdlCardNO=" . $account["id"]; 196 | $queries["BtnCsvDownloadTop.x"] = "BtnCsvDownloadTop.x=1"; 197 | $queries["BtnCsvDownloadTop.y"] = "BtnCsvDownloadTop.y=1"; 198 | if(isset($queries["BtnCsvDownloadTop"]) == true) unset($queries["BtnCsvDownloadTop"]); 199 | if(isset($queries["BtnCsvDownloadBottom"]) == true) unset($queries["BtnCsvDownloadBottom"]); 200 | if(isset($queries["BtnPdfDownloadTop"]) == true) unset($queries["BtnPdfDownloadTop"]); 201 | if(isset($queries["BtnPdfDownloadBottom"]) == true) unset($queries["BtnPdfDownloadBottom"]); 202 | if(isset($queries["BtnList"]) == true) unset($queries["BtnList"]); 203 | 204 | $method = $forms[$c]["method"]; 205 | $uris = parse_uri($forms[$c]["action"], $uris); 206 | $query = implode("&", $queries); 207 | $cookie = viewcard_update_cookie($head, $cookie); 208 | list($head, $body) = viewcard_http11($method, $uris, $query, $cookie); 209 | } 210 | 211 | if($body == "" || strpos($head, "Content-Type: text/html") === false) { 212 | $creditcardmsgsrsv1 .= "<CCSTMTTRNRS>"; 213 | $creditcardmsgsrsv1 .= "\r\n"; 214 | $creditcardmsgsrsv1 .= "<TRNUID>0</TRNUID>"; 215 | $creditcardmsgsrsv1 .= "\r\n"; 216 | $creditcardmsgsrsv1 .= "<STATUS><CODE>0</CODE><SEVERITY>INFO</SEVERITY></STATUS>"; 217 | $creditcardmsgsrsv1 .= "\r\n"; 218 | $creditcardmsgsrsv1 .= "<CCSTMTRS>"; 219 | $creditcardmsgsrsv1 .= "\r\n"; 220 | $creditcardmsgsrsv1 .= "<CURDEF>" . ENV_STR_OFX_CURRENCY_JPY . "</CURDEF>"; 221 | $creditcardmsgsrsv1 .= "\r\n"; 222 | $creditcardmsgsrsv1 .= "<CCACCTFROM>"; 223 | $creditcardmsgsrsv1 .= "<ACCTID>" . $account["acctid"] . "</ACCTID>"; 224 | $creditcardmsgsrsv1 .= "</CCACCTFROM>"; 225 | $creditcardmsgsrsv1 .= "\r\n"; 226 | $creditcardmsgsrsv1 .= viewcard_parse_csv($body, $account); 227 | $creditcardmsgsrsv1 .= "</CCSTMTRS>"; 228 | $creditcardmsgsrsv1 .= "\r\n"; 229 | $creditcardmsgsrsv1 .= "</CCSTMTTRNRS>"; 230 | $creditcardmsgsrsv1 .= "\r\n"; 231 | } 232 | 233 | $body = $body_old; 234 | } 235 | 236 | $creditcardmsgsrsv1 .= "</CREDITCARDMSGSRSV1>"; 237 | $creditcardmsgsrsv1 .= "\r\n"; 238 | 239 | // 実行時間(タイムアウト)を再設定する 240 | @set_time_limit(ENV_NUM_TIMEOUT); 241 | 242 | // ログアウトする 243 | $as = parse_tag($body, "a"); 244 | $c = parse_tag_search($as, "innerHTML", "ログアウト"); // ログアウト 245 | if($c != -1) { 246 | $method = "GET"; 247 | $uris = parse_uri($as[$c]["href"], $uris); 248 | $query = ""; 249 | $cookie = viewcard_update_cookie($head, $cookie); 250 | list($head, $body) = viewcard_http11($method, $uris, $query, $cookie); 251 | } 252 | 253 | // リダイレクトする 254 | $forms = parse_tag($body, "form"); 255 | $c = parse_tag_search($forms, "name", "frmMain"); 256 | if($c != -1) { 257 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 258 | $queries = array(); 259 | foreach($inputs as $input) if($input["name"] != "") $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 260 | $queries["Logout.x"] = "Logout.x=0"; 261 | $queries["Logout.y"] = "Logout.y=0"; 262 | 263 | $method = $forms[$c]["method"]; 264 | $uris = parse_uri($forms[$c]["action"], $uris); 265 | $query = implode("&", $queries); 266 | $cookie = viewcard_update_cookie($head, $cookie); 267 | list($head, $body) = viewcard_http11($method, $uris, $query, $cookie); 268 | } 269 | 270 | // リダイレクトする 271 | $retry = 0; 272 | while($retry++ < ENV_NUM_HTTP11_RETRY) { 273 | $locations = parse_header($head, "location"); 274 | if(count($locations) > 0) { 275 | $method = "GET"; 276 | $uris = parse_uri($locations[0], $uris); 277 | $query = ""; 278 | $cookie = viewcard_update_cookie($head, $cookie); 279 | list($head, $body) = viewcard_http11($method, $uris, $query, $cookie); 280 | } 281 | } 282 | 283 | // OFXファイルを出力する 284 | $resp["status"] = ENV_NUM_STATUS_SUCCESS; 285 | if(strpos($creditcardmsgsrsv1, "<BANKTRANLIST>") === false) { 286 | // 明細が存在しない場合 287 | $resp["ofx"] = generate_ofx($resp["status"]); 288 | } else { 289 | // 明細が存在する場合 290 | $resp["ofx"] = generate_ofx($resp["status"], $creditcardmsgsrsv1); 291 | } 292 | } 293 | return $resp; 294 | 295 | // HTTP/1.1 296 | function viewcard_http11($method, $uris, $query = "", $cookie = "") { 297 | $ret = "INVALID HOST"; 298 | if(preg_match("/^viewsnet\.jp$/", $uris["host"]) > 0 || (strtoupper($method) == "GET" && preg_match("/\.jreast\.co\.jp$/", $uris["host"]) > 0)) $ret = http11(strtoupper($method), $uris["scheme"], $uris["host"], 0, $uris["path"], $query, "", $cookie); 299 | return explode("\r\n\r\n", $ret, 2); 300 | } 301 | 302 | function viewcard_update_cookie($head, $cookie) { 303 | return update_cookie(array("BIGipServerPL-VNWEB-PC_WAF-TCP80", "VIEWSNET_WEB", "ASP.NET_SessionId", "citrix_ns_id", "citrix_ns_id_.viewsnet.jp_%2F_wat"), parse_header($head, "set-cookie"), $cookie); 304 | } 305 | 306 | function viewcard_parse_csv($str, $account) { 307 | $ret = ""; 308 | $lines = parse_csv(mb_convert_string($str)); 309 | $cds = array(); 310 | $cds_balamt = "0"; 311 | $cds_paydate = $account["paydate"]; 312 | $cds_s = ""; 313 | $cds_e = ""; 314 | $cd_date = ""; 315 | $cd_num = 0; 316 | $ledge_balamt = 0; 317 | 318 | foreach($lines as $line) { 319 | $cd = array(); 320 | 321 | if(count($line) == 2) { 322 | switch($line[0]) { 323 | case "お支払日": 324 | $cds_paydate = parse_date($line[1]); 325 | break; 326 | case "今回お支払金額": 327 | $cds_balamt = (string)(double)parse_amount($line[1]); 328 | $ledge_balamt = (double)$cds_balamt; 329 | break; 330 | case "会員番号": 331 | case "対象カード": 332 | default: 333 | break; 334 | } 335 | } else if(count($line) == 11 && $line[0] != "ご利用年月日") { 336 | 337 | // 日付を取得する 338 | $cd["DTPOSTED"] = parse_date($line[0]); 339 | if($line[1] == "ショッピングリボ弁済金") { 340 | $cd["DTPOSTED"] = $cds_paydate; 341 | $cd["TRNTYPE"] = ENV_STR_OFX_TRNTYPE_INT; 342 | } else { 343 | // PAYMENT固定とする 344 | $cd["TRNTYPE"] = ENV_STR_OFX_TRNTYPE_PAYMENT; 345 | } 346 | if($cds_s == "") $cds_s = $cd["DTPOSTED"]; 347 | $cds_e = $cd["DTPOSTED"]; 348 | 349 | // 通番を生成する 350 | if($cd["DTPOSTED"] == $cd_date) $cd_num++; else $cd_num = 0; 351 | 352 | // トランザクション番号を生成する 353 | $cd["FITID"] = $cd["DTPOSTED"] . sprintf("%04d", $account["id"]) . substr($account["paydate"], 4, 2) . "0" . sprintf("%05d", $cd_num); 354 | 355 | // 摘要を取得する 356 | $cd["NAME"] = $line[1]; 357 | 358 | // 金額を取得する 359 | $cd["TRNAMT"] = (string)(-1 * (double)parse_amount($line[7])); 360 | $ledge_balamt += (double)$cd["TRNAMT"]; 361 | 362 | // 残高を取得する 363 | $cd["MEMO"] = ($line[5] != ""? $line[5]: ENV_STR_OFX_MEMO); 364 | 365 | array_push($cds, $cd); 366 | $cd_date = $cd["DTPOSTED"]; 367 | } 368 | } 369 | 370 | if($cds_s == "") $cds_s = ENV_STR_DATE_TODAY; 371 | if($cds_e == "") $cds_e = ENV_STR_DATE_TODAY; 372 | if($cds_s > $cds_e) $cds_e = $cds_s; 373 | 374 | // クレジットカード支払請求を明細に追加する 375 | $i = count($cds); 376 | $cds[$i]["DTPOSTED"] = $cds_paydate; 377 | $cds[$i]["NAME"] = $account["name"]; 378 | $cds[$i]["MEMO"] = ENV_STR_OFX_MEMO; 379 | $cds[$i]["TRNAMT"] = $cds_balamt; 380 | $cds[$i]["TRNTYPE"] = ENV_STR_OFX_TRNTYPE_DIRECTDEBIT; 381 | $cds[$i]["FITID"] = $cds[$i]["DTPOSTED"] . sprintf("%04d", $account["id"]) . substr($account["paydate"], 4, 2) . "100000"; 382 | 383 | // BANKTRANLIST 384 | $ret .= "<BANKTRANLIST>"; 385 | $ret .= "\r\n"; 386 | $ret .= "<DTSTART>" . $cds_s . ENV_STR_OFX_TZ . "</DTSTART>"; 387 | $ret .= "<DTEND>" . $cds_e . ENV_STR_OFX_TZ . "</DTEND>"; 388 | $ret .= "\r\n"; 389 | 390 | foreach($cds as $cd) { 391 | $ret .= "<STMTTRN>"; 392 | $ret .= "<TRNTYPE>" . $cd["TRNTYPE"] . "</TRNTYPE>"; 393 | $ret .= "<DTPOSTED>" . $cd["DTPOSTED"] . ENV_STR_OFX_TZ . "</DTPOSTED>"; 394 | $ret .= "<TRNAMT>" . $cd["TRNAMT"] . "</TRNAMT>"; 395 | $ret .= "<FITID>" . $cd["FITID"] . "</FITID>"; 396 | $ret .= "<NAME>" . $cd["NAME"] . "</NAME>"; 397 | $ret .= "<MEMO>" . $cd["MEMO"] . "</MEMO>"; 398 | $ret .= "</STMTTRN>"; 399 | $ret .= "\r\n"; 400 | } 401 | 402 | $ret .= "</BANKTRANLIST>"; 403 | $ret .= "\r\n"; 404 | 405 | // 支払後残高を出力する 406 | $ret .= "<LEDGERBAL>"; 407 | $ret .= "<BALAMT>" . (string)$ledge_balamt . "</BALAMT>"; 408 | $ret .= "<DTASOF>" . ENV_STR_DATE_TODAY . ENV_STR_OFX_TZ . "</DTASOF>"; 409 | $ret .= "</LEDGERBAL>"; 410 | $ret .= "\r\n"; 411 | 412 | // カード名称を出力する 413 | if($account["acctname"] != "") { 414 | $ret .= "<MKTGINFO>" . $account["acctname"] . "</MKTGINFO>"; 415 | $ret .= "\r\n"; 416 | } 417 | 418 | return $ret; 419 | } 420 | 421 | ?> 422 | -------------------------------------------------------------------------------- /server/waon.inc: -------------------------------------------------------------------------------- 1 | <?php 2 | /* 3 | waon.inc: WAONネットステーションのHTMLよりOFXファイルを生成する 4 | Copyright (C) 2012-2017 Hiromu2000. All Rights Reserved. 5 | mailto:hiromu2000@hotmail.com 6 | Licensed under the GNU AGPLv3. 7 | */ 8 | 9 | $resp = array(); 10 | $ofx = ""; 11 | 12 | // 実行時間(タイムアウト)を再設定する 13 | @set_time_limit(ENV_NUM_TIMEOUT); 14 | 15 | // ログイン画面を取得する 16 | $uris = parse_uri($settings["home"]); 17 | $query = ""; 18 | $cookie = ""; 19 | list($head, $body) = waon_http11('GET', $uris, $query, $cookie); 20 | 21 | // ログインする 22 | $forms = parse_tag($body, "form"); 23 | $c = parse_tag_search($forms, "name", "loginForm"); 24 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 25 | $queries = array(); 26 | foreach($inputs as $input) { 27 | if($input["name"] != "") { 28 | $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 29 | } 30 | } 31 | $queries["cardNo1"] .= substr($ofxforms["cardNo"], 0, 4); 32 | $queries["cardNo2"] .= substr($ofxforms["cardNo"], 4, 4); 33 | $queries["cardNo3"] .= substr($ofxforms["cardNo"], 8, 4); 34 | $queries["cardNo4"] .= substr($ofxforms["cardNo"], 12, 4); 35 | $queries["secNo"] .= $ofxforms["secNo"]; 36 | $uris = parse_uri('/wmUseHistoryInq/login.do', $uris); 37 | $query = implode("&", $queries); 38 | $cookie = waon_update_cookie($head, $cookie); 39 | list($head, $body) = waon_http11('POST', $uris, $query, $cookie); 40 | 41 | if (strpos($body, "未実装") !== false) { 42 | // システムメンテナンス画面の場合 43 | $resp["status"] = ENV_NUM_STATUS_MAINTENANCE; 44 | $resp["method"] = $method; 45 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 46 | $resp["query"] = $query; 47 | $resp["cookie"] = $cookie; 48 | $resp["head"] = $head; 49 | $resp["body"] = $body; 50 | $resp["ofx"] = generate_ofx($resp["status"]); 51 | } else if (strpos($body, "が正しく入力されていません。") !== false) { 52 | // ログイン失敗の場合 53 | $resp["status"] = ENV_NUM_STATUS_FAILURE; 54 | $resp["method"] = $method; 55 | $resp["uri"] = $uris["scheme"] . "://" . $uris["host"] . $uris["path"]; 56 | $resp["query"] = $query; 57 | $resp["cookie"] = $cookie; 58 | $resp["head"] = $head; 59 | $resp["body"] = $body; 60 | $resp["ofx"] = generate_ofx($resp["status"]); 61 | } else { 62 | // 今月の明細を処理する 63 | $cds = waon_parsedom($body); 64 | 65 | // 前月の明細を取得する 66 | $as = parse_tag($body, "a"); 67 | foreach($as as $a) { 68 | if (preg_match("/.*beforeMonth=1.*/", $a["href"])) { $url = $a["href"]; } 69 | } 70 | $urls = parse_url($url); 71 | $queries = array(); 72 | foreach(explode("&", htmlspecialchars_decode($urls["query"])) as $pair) { 73 | list($key, $value) = explode("=", $pair); 74 | $queries[$key] = $key . "=" . $value; 75 | } 76 | $uris = parse_uri($urls["path"], $uris); 77 | $query = implode("&", $queries); 78 | $cookie = waon_update_cookie($head, $cookie); 79 | list($head, $body) = waon_http11('GET', $uris, $query, $cookie); 80 | // 前月の明細を処理する 81 | $cds = array_merge($cds, waon_parsedom($body)); 82 | 83 | // ログアウトする 84 | $forms = parse_tag($body, "form"); 85 | $c = parse_tag_search($forms, "name", "logoutForm"); 86 | $inputs = parse_tag($forms[$c]["innerHTML"], "input"); 87 | $queries = array(); 88 | foreach($inputs as $input) { 89 | if($input["name"] != "") { 90 | $queries[$input["name"]] = urlencode($input["name"]) . "=" . urlencode($input["value"]); 91 | } 92 | } 93 | $uris = parse_uri('/wmUseHistoryInq/logout.do', $uris); 94 | $query = implode("&", $queries); 95 | $cookie = waon_update_cookie($head, $cookie); 96 | list($head, $body) = waon_http11('POST', $uris, $query, $cookie); 97 | 98 | // DOMツリーを生成 99 | $ofxdom = new ofxDOM("BANK", $settings["name"]); 100 | $ofxdom->setAcctfrom(array( 101 | "BANKID" => $settings["code"], 102 | "BRANCHID" => "0", 103 | "ACCTID" => $ofxforms["cardNo"], 104 | "ACCTTYPE" => "CHECKING" 105 | )); 106 | // 日付順に昇順ソート 107 | usort($cds, function($a, $b) { 108 | return $a['DTPOSTED'] > $b['DTPOSTED']; 109 | }); 110 | foreach($cds as $cd) { 111 | $ofxdom->addTran($cd); 112 | } 113 | // DTSTARTとDTENDを設定する 114 | $ofxdom->setDateRange(ENV_STR_DATE_PASTDAY . ENV_STR_OFX_TZ, ENV_STR_DATE_TODAY . ENV_STR_OFX_TZ); 115 | 116 | // 残高を処理。ただし、取得できないため、便宜上0円とする。 117 | $ofxdom->setBalance(array( 118 | 'BALAMT' => 0, 119 | 'DTASOF' => ENV_STR_DATE_TODAY . ENV_STR_OFX_TZ 120 | )); 121 | 122 | // FITIDを仕上げる 123 | $ofxdom->setFitid(); 124 | // XML DOMツリーを文字列に変換 125 | $xml = $ofxdom->getXML(); 126 | $resp["status"] = ENV_NUM_STATUS_SUCCESS; 127 | $resp["ofx"] = generate_ofx($mode, $xml); 128 | } 129 | return $resp; 130 | 131 | // HTTP/1.1 132 | function waon_http11($method, $uris, $query = "", $cookie = "") { 133 | $ret = "INVALID HOST"; 134 | if(preg_match("/\.waon\.com$/", $uris["host"]) > 0) $ret = http11(strtoupper($method), $uris["scheme"], $uris["host"], 0, $uris["path"], $query, "", $cookie); 135 | return explode("\r\n\r\n", $ret, 2); 136 | } 137 | function waon_update_cookie($head, $cookie) { 138 | return update_cookie(array( 139 | "JSESSIONID", 140 | "citrix_ns_id_.waon.com_%2F_wat", 141 | "Money-VS32-Cookie", 142 | "citrix_ns_id", 143 | "Waon-SSLVS04-Cookie", 144 | ), parse_header($head, "set-cookie"), $cookie); 145 | } 146 | 147 | function waon_parsedom($str) { 148 | $str = str_replace("Shift_JIS", "UTF-8", $str); 149 | $doc = new DOMDocument(); 150 | @$doc->loadHTML($str); 151 | $xpath = new DOMXPath($doc); 152 | $rows = $xpath->query("//table[@class='y']/tr"); 153 | 154 | $cds = array(); 155 | $nrow = $rows->length; 156 | 157 | for ($i=1; $i<$nrow; $i++) { 158 | $cd = array(); 159 | $cd["TRNTYPE"] = ENV_STR_OFX_TRNTYPE_DIRECTDEBIT; 160 | 161 | $row = $rows->item($i); 162 | $cols = $row->getElementsByTagName('td'); 163 | // 日付を取得する 164 | if (!preg_match("/([0-9]{4})\/([0-9]{1,2})\/([0-9]{1,2})/", trim($cols->item(0)->nodeValue), $matches)) { 165 | // 当月に明細が存在しなければスキップ 166 | break; 167 | } 168 | $cd["DTPOSTED"] = sprintf("%d%02d%02d", $matches[1], $matches[2], $matches[3]); 169 | $cd["DTPOSTED"] .= ENV_STR_OFX_TZ; 170 | 171 | // トランザクション番号(請求月とデータ種別)を生成する 172 | $cd["FITID"] = '000'; 173 | 174 | $cd['NAME'] = trim($cols->item(1)->nodeValue); 175 | $cd['TRNAMT'] = (int)parse_amount(trim($cols->item(2)->nodeValue)); 176 | if (preg_match("/支払/", $cols->item(3)->nodeValue) && !preg_match("/支払取消/", $cols->item(3)->nodeValue)) { 177 | $cd['TRNAMT'] *= -1; 178 | } 179 | array_push($cds, $cd); 180 | } 181 | return $cds; 182 | } 183 | ?> 184 | -------------------------------------------------------------------------------- /start_php.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | cd /d %~dp0 3 | php.exe -S 127.0.0.1:8000 4 | --------------------------------------------------------------------------------