├── app ├── config │ └── sample_config.ini ├── dispatcher.php ├── include │ ├── defines.php │ ├── external │ │ ├── CardDAV-PHP │ │ │ ├── CHANGELOG │ │ │ ├── LICENSE │ │ │ ├── README │ │ │ ├── carddav.php │ │ │ └── support.php │ │ ├── XMPPHP │ │ │ ├── BOSH.php │ │ │ ├── Exception.php │ │ │ ├── Log.php │ │ │ ├── Roster.php │ │ │ ├── XMLObj.php │ │ │ ├── XMLStream.php │ │ │ ├── XMPP.php │ │ │ └── XMPP_Old.php │ │ └── php-serial │ │ │ ├── LRS_T74.class.php │ │ │ ├── example.php │ │ │ ├── example_VS421CPNTA.php │ │ │ ├── php_serial.class.php │ │ │ └── sms-example.php │ ├── gateways │ │ ├── eu.apksoft.android.smsgateway.php │ │ └── template.php │ └── logger.php └── listener.php ├── docs ├── AUTHORS ├── COPYING └── SUPPORTED_GATEWAYS └── resources ├── easypackage.pl ├── smstoxmpp-httpdconfig.conf ├── smstoxmpp.spec └── smstoxmppd.rcsysinit /app/config/sample_config.ini: -------------------------------------------------------------------------------- 1 | ; 2 | ; SMStoXMPP Configuration File 3 | ; 4 | ; This file is an ini formatted configuration file for SMStoXMPP, an open source 5 | ; gateway designed to be notified about SMSes by an external application and then 6 | ; engage with users in an XMPP conversation, where users can recieve and then 7 | ; reply via XMPP. 8 | ; 9 | 10 | [SMStoXMPP] 11 | 12 | ; General options (don't normally need to adjust these) 13 | app_lock = /var/lock/smstoxmpp.lock 14 | app_log = /var/log/smstoxmpp.log 15 | 16 | ; Non-privilaged user to run as (note: logs & lock file must be writable by this user) 17 | app_user = nobody 18 | app_group = nobody 19 | 20 | ; Optional feature to have the application lookup and resolve phone numbers against a 21 | ; CardDAV network address book. Examples of CardDAV address books include Google 22 | ; contacts used by most Android phones. 23 | ; 24 | ; Example: 25 | ; Google: 26 | ; contacts_lookup = true 27 | ; contacts_url = https://google.com/m8/carddav/principals/__uids__/user@gmail.com/lists/default/ 28 | ; contacts_username = user@gmail.com 29 | ; contacts_password = password1234 30 | ; contacts_store = /var/lib/smstoxmpp/contacts/ 31 | ; 32 | contacts_lookup = false 33 | contacts_url = http://www.example.com/carddav/user 34 | contacts_username = user 35 | contacts_password = password 36 | contacts_store = /var/lib/smstoxmpp/contacts/ 37 | 38 | 39 | ; 40 | ; Multiple devices and target users are supported by defining multiple configuration 41 | ; entries, in the format below. 42 | ; 43 | ; Various application formats are supported, at this stage, the following is the only 44 | ; supported application. More may be added in future. 45 | ; 46 | ; "eu.apksoft.android.smsgateway" 47 | ; SMS Gateway by APK (https://play.google.com/store/apps/details?id=eu.apksoft.android.smsgateway&hl=en) 48 | ; 49 | ; [example] 50 | ; gw_type = eu.apksoft.android.smsgateway 51 | ; gw_path = auto 52 | ; ; By default we figure this out automaticlaly, however this will break if the connection 53 | ; ; between the phone and here goes via NAT. If incorrect, try setting the address explicitly: 54 | ; ; gw_path = 192.168.0.1:9090 55 | ; xmpp_server = xmpp.example.com 56 | ; xmpp_username = sender 57 | ; xmpp_domain = example.com 58 | ; xmpp_password = password 59 | ; xmpp_reciever = targetuser@example.org 60 | ; 61 | 62 | [myphone] 63 | gw_type = eu.apksoft.android.smsgateway 64 | gw_path = auto 65 | xmpp_server = xmpp.sender.com 66 | xmpp_username = sender 67 | xmpp_domain = example.com 68 | xmpp_password = password123 69 | xmpp_reciever = targetuser@example.org 70 | 71 | 72 | -------------------------------------------------------------------------------- /app/include/defines.php: -------------------------------------------------------------------------------- 1 | 29 | -------------------------------------------------------------------------------- /app/include/external/CardDAV-PHP/CHANGELOG: -------------------------------------------------------------------------------- 1 | Changes in SMStoXMPP's fork: 2 | - Code changes to correctly support google.com's CardDAV behaviour 3 | - See https://github.com/jethrocarr/CardDAV-PHP/commit/2c3af2f2b8d2cb03f5145eb8531f24d6cbe196d5 4 | 5 | Changes from v0.5.2 to v0.6 6 | - Added Exception handling 7 | - Each method now analyzes the http status code on it's own 8 | - Minor comment, documentation and phpdoc changes 9 | 10 | Changes from v0.5.1 to v0.5.2 11 | - Added debug function 12 | - Some minor class structure changes 13 | - Some comment, documentation and phpdoc changes 14 | 15 | Changes from v0.5 to v0.5.1 16 | - Added SOGo to the CardDAV server list 17 | - Deleted the method get_last_vcard_id() -> the add method does now returns the vCard id 18 | - Added posibility to get a raw XML vCard response to the get_xml_vcard() method 19 | - Some comment, documentation and phpdoc changes 20 | 21 | Changes from v0.4.9 to v0.5 22 | - Added SOGo support 23 | - Special thanks to xbgmsharp for the great feedback! 24 | - Cache curl connection so that only one authentication process is needed 25 | - Added boolean return value for add-, edit- and delete-methods 26 | - Added addressbook handling 27 | 28 | Changes from v0.4.8 to v0.4.9 29 | - New method: clean_vcard 30 | - New method: get_last_vcard_id 31 | 32 | Changes from v0.4.7 to v0.4.8 33 | - Extended clean_response() method and added utf-encoding 34 | 35 | Changes from v0.4.6 to v0.4.7 36 | - Changed license from LGPLv2 to AGPLv3 37 | - Changed minor wordings in the changelog 38 | 39 | Changes from v0.4.5 to v0.4.6 40 | - Added "get XML vCard"-method to get a single vCard with more detailed information 41 | 42 | Changes from v0.4.4 to v0.4.5 43 | - Minor comment and class changes 44 | 45 | Changes from v0.4.3 to v0.4.4 46 | - Verified ownCloud support 47 | - Store username and password for class internal use 48 | - Cleaned the class 49 | - Automaticly adds a / at the end of an url if it's missing 50 | - Added a URL-Schema list 51 | 52 | Changes from v0.4.2 to v0.4.3 53 | - Added sabreDAV support 54 | 55 | Changes from v0.4.1 to v0.4.2 56 | - Standardized "get last modified" seems not to work with every server configuration -> no standardized date anymore! 57 | 58 | Changes from v0.4 to v0.4.1 59 | - Added memotoo support 60 | - Bugfix: mostly check_connection() returned "true" if the server connection failed 61 | - Removed unused code 62 | - Standardized "get last modified" to unix-timestamp 63 | - Changed version naming 64 | 65 | Changes from v0.3.3 to v0.4 66 | - Switched from "fopen" to curl for all server requests 67 | - get() uses now PROPFIND instead of REPORT 68 | - Simplified response additionally returns "get last modified" 69 | - Added Apple addressbook server support 70 | 71 | Changes from v0.3.3 to v0.3.4 72 | - vCard id returned by get() excludes now the file extension ".vcf" 73 | 74 | Changes from v0.3.2 to v0.3.3 75 | - Minor comment changes 76 | 77 | Changes from v0.3.1 to v0.3.2 78 | - Minor phpdoc changes / extensions 79 | 80 | Changes from v0.3 to v0.3.1 81 | - Get only entries if a vCard id exists 82 | - Get etag bugfix (PROFIND -> REPORT) 83 | - vCard id generator bugfix 84 | - Minor class-structure and comment changes 85 | 86 | Changes from v0.2.2 to v0.3 87 | - Deleted unused methods 88 | - Added server connection check 89 | - Added some more examples 90 | - get() can now return complete vCards 91 | 92 | Changes from v0.2.1 to v0.2.2 93 | - Added error handling 94 | - Added phpdoc support 95 | - Cleaned comments / variables 96 | 97 | Changes from v0.2 to v0.2.1 98 | - XML requests will be built by the XMLWriter 99 | - Added etag to simplified response 100 | 101 | Changes from v0.1.2 to v0.2 102 | - Added add functionality 103 | - Added update functionality 104 | - Added get vCard functionality 105 | - Added user-agent to http-requests 106 | - Added simplified response 107 | - Set vCard standard fields (Version, N, FN) 108 | 109 | Changes from v0.1.1 to v0.1.2 110 | - Added delete functionality 111 | 112 | Changes from v0.1 to v0.1.1 113 | - Added filter type (OR / AND) 114 | 115 | release v0.1 116 | - Query CardDAV server with XML response (only tested on davical) 117 | - Filter functionality for search implementations 118 | - Fieldsets for minimal vCards within the XML response 119 | - Authentification 120 | -------------------------------------------------------------------------------- /app/include/external/CardDAV-PHP/LICENSE: -------------------------------------------------------------------------------- 1 | GNU AFFERO GENERAL PUBLIC LICENSE 2 | Version 3, 19 November 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU Affero General Public License is a free, copyleft license for 11 | software and other kinds of works, specifically designed to ensure 12 | cooperation with the community in the case of network server software. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | our General Public Licenses are intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. 19 | 20 | When we speak of free software, we are referring to freedom, not 21 | price. Our General Public Licenses are designed to make sure that you 22 | have the freedom to distribute copies of free software (and charge for 23 | them if you wish), that you receive source code or can get it if you 24 | want it, that you can change the software or use pieces of it in new 25 | free programs, and that you know you can do these things. 26 | 27 | Developers that use our General Public Licenses protect your rights 28 | with two steps: (1) assert copyright on the software, and (2) offer 29 | you this License which gives you legal permission to copy, distribute 30 | and/or modify the software. 31 | 32 | A secondary benefit of defending all users' freedom is that 33 | improvements made in alternate versions of the program, if they 34 | receive widespread use, become available for other developers to 35 | incorporate. Many developers of free software are heartened and 36 | encouraged by the resulting cooperation. However, in the case of 37 | software used on network servers, this result may fail to come about. 38 | The GNU General Public License permits making a modified version and 39 | letting the public access it on a server without ever releasing its 40 | source code to the public. 41 | 42 | The GNU Affero General Public License is designed specifically to 43 | ensure that, in such cases, the modified source code becomes available 44 | to the community. It requires the operator of a network server to 45 | provide the source code of the modified version running there to the 46 | users of that server. Therefore, public use of a modified version, on 47 | a publicly accessible server, gives the public access to the source 48 | code of the modified version. 49 | 50 | An older license, called the Affero General Public License and 51 | published by Affero, was designed to accomplish similar goals. This is 52 | a different license, not a version of the Affero GPL, but Affero has 53 | released a new version of the Affero GPL which permits relicensing under 54 | this license. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | TERMS AND CONDITIONS 60 | 61 | 0. Definitions. 62 | 63 | "This License" refers to version 3 of the GNU Affero General Public License. 64 | 65 | "Copyright" also means copyright-like laws that apply to other kinds of 66 | works, such as semiconductor masks. 67 | 68 | "The Program" refers to any copyrightable work licensed under this 69 | License. Each licensee is addressed as "you". "Licensees" and 70 | "recipients" may be individuals or organizations. 71 | 72 | To "modify" a work means to copy from or adapt all or part of the work 73 | in a fashion requiring copyright permission, other than the making of an 74 | exact copy. The resulting work is called a "modified version" of the 75 | earlier work or a work "based on" the earlier work. 76 | 77 | A "covered work" means either the unmodified Program or a work based 78 | on the Program. 79 | 80 | To "propagate" a work means to do anything with it that, without 81 | permission, would make you directly or secondarily liable for 82 | infringement under applicable copyright law, except executing it on a 83 | computer or modifying a private copy. Propagation includes copying, 84 | distribution (with or without modification), making available to the 85 | public, and in some countries other activities as well. 86 | 87 | To "convey" a work means any kind of propagation that enables other 88 | parties to make or receive copies. Mere interaction with a user through 89 | a computer network, with no transfer of a copy, is not conveying. 90 | 91 | An interactive user interface displays "Appropriate Legal Notices" 92 | to the extent that it includes a convenient and prominently visible 93 | feature that (1) displays an appropriate copyright notice, and (2) 94 | tells the user that there is no warranty for the work (except to the 95 | extent that warranties are provided), that licensees may convey the 96 | work under this License, and how to view a copy of this License. If 97 | the interface presents a list of user commands or options, such as a 98 | menu, a prominent item in the list meets this criterion. 99 | 100 | 1. Source Code. 101 | 102 | The "source code" for a work means the preferred form of the work 103 | for making modifications to it. "Object code" means any non-source 104 | form of a work. 105 | 106 | A "Standard Interface" means an interface that either is an official 107 | standard defined by a recognized standards body, or, in the case of 108 | interfaces specified for a particular programming language, one that 109 | is widely used among developers working in that language. 110 | 111 | The "System Libraries" of an executable work include anything, other 112 | than the work as a whole, that (a) is included in the normal form of 113 | packaging a Major Component, but which is not part of that Major 114 | Component, and (b) serves only to enable use of the work with that 115 | Major Component, or to implement a Standard Interface for which an 116 | implementation is available to the public in source code form. A 117 | "Major Component", in this context, means a major essential component 118 | (kernel, window system, and so on) of the specific operating system 119 | (if any) on which the executable work runs, or a compiler used to 120 | produce the work, or an object code interpreter used to run it. 121 | 122 | The "Corresponding Source" for a work in object code form means all 123 | the source code needed to generate, install, and (for an executable 124 | work) run the object code and to modify the work, including scripts to 125 | control those activities. However, it does not include the work's 126 | System Libraries, or general-purpose tools or generally available free 127 | programs which are used unmodified in performing those activities but 128 | which are not part of the work. For example, Corresponding Source 129 | includes interface definition files associated with source files for 130 | the work, and the source code for shared libraries and dynamically 131 | linked subprograms that the work is specifically designed to require, 132 | such as by intimate data communication or control flow between those 133 | subprograms and other parts of the work. 134 | 135 | The Corresponding Source need not include anything that users 136 | can regenerate automatically from other parts of the Corresponding 137 | Source. 138 | 139 | The Corresponding Source for a work in source code form is that 140 | same work. 141 | 142 | 2. Basic Permissions. 143 | 144 | All rights granted under this License are granted for the term of 145 | copyright on the Program, and are irrevocable provided the stated 146 | conditions are met. This License explicitly affirms your unlimited 147 | permission to run the unmodified Program. The output from running a 148 | covered work is covered by this License only if the output, given its 149 | content, constitutes a covered work. This License acknowledges your 150 | rights of fair use or other equivalent, as provided by copyright law. 151 | 152 | You may make, run and propagate covered works that you do not 153 | convey, without conditions so long as your license otherwise remains 154 | in force. You may convey covered works to others for the sole purpose 155 | of having them make modifications exclusively for you, or provide you 156 | with facilities for running those works, provided that you comply with 157 | the terms of this License in conveying all material for which you do 158 | not control copyright. Those thus making or running the covered works 159 | for you must do so exclusively on your behalf, under your direction 160 | and control, on terms that prohibit them from making any copies of 161 | your copyrighted material outside their relationship with you. 162 | 163 | Conveying under any other circumstances is permitted solely under 164 | the conditions stated below. Sublicensing is not allowed; section 10 165 | makes it unnecessary. 166 | 167 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 168 | 169 | No covered work shall be deemed part of an effective technological 170 | measure under any applicable law fulfilling obligations under article 171 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 172 | similar laws prohibiting or restricting circumvention of such 173 | measures. 174 | 175 | When you convey a covered work, you waive any legal power to forbid 176 | circumvention of technological measures to the extent such circumvention 177 | is effected by exercising rights under this License with respect to 178 | the covered work, and you disclaim any intention to limit operation or 179 | modification of the work as a means of enforcing, against the work's 180 | users, your or third parties' legal rights to forbid circumvention of 181 | technological measures. 182 | 183 | 4. Conveying Verbatim Copies. 184 | 185 | You may convey verbatim copies of the Program's source code as you 186 | receive it, in any medium, provided that you conspicuously and 187 | appropriately publish on each copy an appropriate copyright notice; 188 | keep intact all notices stating that this License and any 189 | non-permissive terms added in accord with section 7 apply to the code; 190 | keep intact all notices of the absence of any warranty; and give all 191 | recipients a copy of this License along with the Program. 192 | 193 | You may charge any price or no price for each copy that you convey, 194 | and you may offer support or warranty protection for a fee. 195 | 196 | 5. Conveying Modified Source Versions. 197 | 198 | You may convey a work based on the Program, or the modifications to 199 | produce it from the Program, in the form of source code under the 200 | terms of section 4, provided that you also meet all of these conditions: 201 | 202 | a) The work must carry prominent notices stating that you modified 203 | it, and giving a relevant date. 204 | 205 | b) The work must carry prominent notices stating that it is 206 | released under this License and any conditions added under section 207 | 7. This requirement modifies the requirement in section 4 to 208 | "keep intact all notices". 209 | 210 | c) You must license the entire work, as a whole, under this 211 | License to anyone who comes into possession of a copy. This 212 | License will therefore apply, along with any applicable section 7 213 | additional terms, to the whole of the work, and all its parts, 214 | regardless of how they are packaged. This License gives no 215 | permission to license the work in any other way, but it does not 216 | invalidate such permission if you have separately received it. 217 | 218 | d) If the work has interactive user interfaces, each must display 219 | Appropriate Legal Notices; however, if the Program has interactive 220 | interfaces that do not display Appropriate Legal Notices, your 221 | work need not make them do so. 222 | 223 | A compilation of a covered work with other separate and independent 224 | works, which are not by their nature extensions of the covered work, 225 | and which are not combined with it such as to form a larger program, 226 | in or on a volume of a storage or distribution medium, is called an 227 | "aggregate" if the compilation and its resulting copyright are not 228 | used to limit the access or legal rights of the compilation's users 229 | beyond what the individual works permit. Inclusion of a covered work 230 | in an aggregate does not cause this License to apply to the other 231 | parts of the aggregate. 232 | 233 | 6. Conveying Non-Source Forms. 234 | 235 | You may convey a covered work in object code form under the terms 236 | of sections 4 and 5, provided that you also convey the 237 | machine-readable Corresponding Source under the terms of this License, 238 | in one of these ways: 239 | 240 | a) Convey the object code in, or embodied in, a physical product 241 | (including a physical distribution medium), accompanied by the 242 | Corresponding Source fixed on a durable physical medium 243 | customarily used for software interchange. 244 | 245 | b) Convey the object code in, or embodied in, a physical product 246 | (including a physical distribution medium), accompanied by a 247 | written offer, valid for at least three years and valid for as 248 | long as you offer spare parts or customer support for that product 249 | model, to give anyone who possesses the object code either (1) a 250 | copy of the Corresponding Source for all the software in the 251 | product that is covered by this License, on a durable physical 252 | medium customarily used for software interchange, for a price no 253 | more than your reasonable cost of physically performing this 254 | conveying of source, or (2) access to copy the 255 | Corresponding Source from a network server at no charge. 256 | 257 | c) Convey individual copies of the object code with a copy of the 258 | written offer to provide the Corresponding Source. This 259 | alternative is allowed only occasionally and noncommercially, and 260 | only if you received the object code with such an offer, in accord 261 | with subsection 6b. 262 | 263 | d) Convey the object code by offering access from a designated 264 | place (gratis or for a charge), and offer equivalent access to the 265 | Corresponding Source in the same way through the same place at no 266 | further charge. You need not require recipients to copy the 267 | Corresponding Source along with the object code. If the place to 268 | copy the object code is a network server, the Corresponding Source 269 | may be on a different server (operated by you or a third party) 270 | that supports equivalent copying facilities, provided you maintain 271 | clear directions next to the object code saying where to find the 272 | Corresponding Source. Regardless of what server hosts the 273 | Corresponding Source, you remain obligated to ensure that it is 274 | available for as long as needed to satisfy these requirements. 275 | 276 | e) Convey the object code using peer-to-peer transmission, provided 277 | you inform other peers where the object code and Corresponding 278 | Source of the work are being offered to the general public at no 279 | charge under subsection 6d. 280 | 281 | A separable portion of the object code, whose source code is excluded 282 | from the Corresponding Source as a System Library, need not be 283 | included in conveying the object code work. 284 | 285 | A "User Product" is either (1) a "consumer product", which means any 286 | tangible personal property which is normally used for personal, family, 287 | or household purposes, or (2) anything designed or sold for incorporation 288 | into a dwelling. In determining whether a product is a consumer product, 289 | doubtful cases shall be resolved in favor of coverage. For a particular 290 | product received by a particular user, "normally used" refers to a 291 | typical or common use of that class of product, regardless of the status 292 | of the particular user or of the way in which the particular user 293 | actually uses, or expects or is expected to use, the product. A product 294 | is a consumer product regardless of whether the product has substantial 295 | commercial, industrial or non-consumer uses, unless such uses represent 296 | the only significant mode of use of the product. 297 | 298 | "Installation Information" for a User Product means any methods, 299 | procedures, authorization keys, or other information required to install 300 | and execute modified versions of a covered work in that User Product from 301 | a modified version of its Corresponding Source. The information must 302 | suffice to ensure that the continued functioning of the modified object 303 | code is in no case prevented or interfered with solely because 304 | modification has been made. 305 | 306 | If you convey an object code work under this section in, or with, or 307 | specifically for use in, a User Product, and the conveying occurs as 308 | part of a transaction in which the right of possession and use of the 309 | User Product is transferred to the recipient in perpetuity or for a 310 | fixed term (regardless of how the transaction is characterized), the 311 | Corresponding Source conveyed under this section must be accompanied 312 | by the Installation Information. But this requirement does not apply 313 | if neither you nor any third party retains the ability to install 314 | modified object code on the User Product (for example, the work has 315 | been installed in ROM). 316 | 317 | The requirement to provide Installation Information does not include a 318 | requirement to continue to provide support service, warranty, or updates 319 | for a work that has been modified or installed by the recipient, or for 320 | the User Product in which it has been modified or installed. Access to a 321 | network may be denied when the modification itself materially and 322 | adversely affects the operation of the network or violates the rules and 323 | protocols for communication across the network. 324 | 325 | Corresponding Source conveyed, and Installation Information provided, 326 | in accord with this section must be in a format that is publicly 327 | documented (and with an implementation available to the public in 328 | source code form), and must require no special password or key for 329 | unpacking, reading or copying. 330 | 331 | 7. Additional Terms. 332 | 333 | "Additional permissions" are terms that supplement the terms of this 334 | License by making exceptions from one or more of its conditions. 335 | Additional permissions that are applicable to the entire Program shall 336 | be treated as though they were included in this License, to the extent 337 | that they are valid under applicable law. If additional permissions 338 | apply only to part of the Program, that part may be used separately 339 | under those permissions, but the entire Program remains governed by 340 | this License without regard to the additional permissions. 341 | 342 | When you convey a copy of a covered work, you may at your option 343 | remove any additional permissions from that copy, or from any part of 344 | it. (Additional permissions may be written to require their own 345 | removal in certain cases when you modify the work.) You may place 346 | additional permissions on material, added by you to a covered work, 347 | for which you have or can give appropriate copyright permission. 348 | 349 | Notwithstanding any other provision of this License, for material you 350 | add to a covered work, you may (if authorized by the copyright holders of 351 | that material) supplement the terms of this License with terms: 352 | 353 | a) Disclaiming warranty or limiting liability differently from the 354 | terms of sections 15 and 16 of this License; or 355 | 356 | b) Requiring preservation of specified reasonable legal notices or 357 | author attributions in that material or in the Appropriate Legal 358 | Notices displayed by works containing it; or 359 | 360 | c) Prohibiting misrepresentation of the origin of that material, or 361 | requiring that modified versions of such material be marked in 362 | reasonable ways as different from the original version; or 363 | 364 | d) Limiting the use for publicity purposes of names of licensors or 365 | authors of the material; or 366 | 367 | e) Declining to grant rights under trademark law for use of some 368 | trade names, trademarks, or service marks; or 369 | 370 | f) Requiring indemnification of licensors and authors of that 371 | material by anyone who conveys the material (or modified versions of 372 | it) with contractual assumptions of liability to the recipient, for 373 | any liability that these contractual assumptions directly impose on 374 | those licensors and authors. 375 | 376 | All other non-permissive additional terms are considered "further 377 | restrictions" within the meaning of section 10. If the Program as you 378 | received it, or any part of it, contains a notice stating that it is 379 | governed by this License along with a term that is a further 380 | restriction, you may remove that term. If a license document contains 381 | a further restriction but permits relicensing or conveying under this 382 | License, you may add to a covered work material governed by the terms 383 | of that license document, provided that the further restriction does 384 | not survive such relicensing or conveying. 385 | 386 | If you add terms to a covered work in accord with this section, you 387 | must place, in the relevant source files, a statement of the 388 | additional terms that apply to those files, or a notice indicating 389 | where to find the applicable terms. 390 | 391 | Additional terms, permissive or non-permissive, may be stated in the 392 | form of a separately written license, or stated as exceptions; 393 | the above requirements apply either way. 394 | 395 | 8. Termination. 396 | 397 | You may not propagate or modify a covered work except as expressly 398 | provided under this License. Any attempt otherwise to propagate or 399 | modify it is void, and will automatically terminate your rights under 400 | this License (including any patent licenses granted under the third 401 | paragraph of section 11). 402 | 403 | However, if you cease all violation of this License, then your 404 | license from a particular copyright holder is reinstated (a) 405 | provisionally, unless and until the copyright holder explicitly and 406 | finally terminates your license, and (b) permanently, if the copyright 407 | holder fails to notify you of the violation by some reasonable means 408 | prior to 60 days after the cessation. 409 | 410 | Moreover, your license from a particular copyright holder is 411 | reinstated permanently if the copyright holder notifies you of the 412 | violation by some reasonable means, this is the first time you have 413 | received notice of violation of this License (for any work) from that 414 | copyright holder, and you cure the violation prior to 30 days after 415 | your receipt of the notice. 416 | 417 | Termination of your rights under this section does not terminate the 418 | licenses of parties who have received copies or rights from you under 419 | this License. If your rights have been terminated and not permanently 420 | reinstated, you do not qualify to receive new licenses for the same 421 | material under section 10. 422 | 423 | 9. Acceptance Not Required for Having Copies. 424 | 425 | You are not required to accept this License in order to receive or 426 | run a copy of the Program. Ancillary propagation of a covered work 427 | occurring solely as a consequence of using peer-to-peer transmission 428 | to receive a copy likewise does not require acceptance. However, 429 | nothing other than this License grants you permission to propagate or 430 | modify any covered work. These actions infringe copyright if you do 431 | not accept this License. Therefore, by modifying or propagating a 432 | covered work, you indicate your acceptance of this License to do so. 433 | 434 | 10. Automatic Licensing of Downstream Recipients. 435 | 436 | Each time you convey a covered work, the recipient automatically 437 | receives a license from the original licensors, to run, modify and 438 | propagate that work, subject to this License. You are not responsible 439 | for enforcing compliance by third parties with this License. 440 | 441 | An "entity transaction" is a transaction transferring control of an 442 | organization, or substantially all assets of one, or subdividing an 443 | organization, or merging organizations. If propagation of a covered 444 | work results from an entity transaction, each party to that 445 | transaction who receives a copy of the work also receives whatever 446 | licenses to the work the party's predecessor in interest had or could 447 | give under the previous paragraph, plus a right to possession of the 448 | Corresponding Source of the work from the predecessor in interest, if 449 | the predecessor has it or can get it with reasonable efforts. 450 | 451 | You may not impose any further restrictions on the exercise of the 452 | rights granted or affirmed under this License. For example, you may 453 | not impose a license fee, royalty, or other charge for exercise of 454 | rights granted under this License, and you may not initiate litigation 455 | (including a cross-claim or counterclaim in a lawsuit) alleging that 456 | any patent claim is infringed by making, using, selling, offering for 457 | sale, or importing the Program or any portion of it. 458 | 459 | 11. Patents. 460 | 461 | A "contributor" is a copyright holder who authorizes use under this 462 | License of the Program or a work on which the Program is based. The 463 | work thus licensed is called the contributor's "contributor version". 464 | 465 | A contributor's "essential patent claims" are all patent claims 466 | owned or controlled by the contributor, whether already acquired or 467 | hereafter acquired, that would be infringed by some manner, permitted 468 | by this License, of making, using, or selling its contributor version, 469 | but do not include claims that would be infringed only as a 470 | consequence of further modification of the contributor version. For 471 | purposes of this definition, "control" includes the right to grant 472 | patent sublicenses in a manner consistent with the requirements of 473 | this License. 474 | 475 | Each contributor grants you a non-exclusive, worldwide, royalty-free 476 | patent license under the contributor's essential patent claims, to 477 | make, use, sell, offer for sale, import and otherwise run, modify and 478 | propagate the contents of its contributor version. 479 | 480 | In the following three paragraphs, a "patent license" is any express 481 | agreement or commitment, however denominated, not to enforce a patent 482 | (such as an express permission to practice a patent or covenant not to 483 | sue for patent infringement). To "grant" such a patent license to a 484 | party means to make such an agreement or commitment not to enforce a 485 | patent against the party. 486 | 487 | If you convey a covered work, knowingly relying on a patent license, 488 | and the Corresponding Source of the work is not available for anyone 489 | to copy, free of charge and under the terms of this License, through a 490 | publicly available network server or other readily accessible means, 491 | then you must either (1) cause the Corresponding Source to be so 492 | available, or (2) arrange to deprive yourself of the benefit of the 493 | patent license for this particular work, or (3) arrange, in a manner 494 | consistent with the requirements of this License, to extend the patent 495 | license to downstream recipients. "Knowingly relying" means you have 496 | actual knowledge that, but for the patent license, your conveying the 497 | covered work in a country, or your recipient's use of the covered work 498 | in a country, would infringe one or more identifiable patents in that 499 | country that you have reason to believe are valid. 500 | 501 | If, pursuant to or in connection with a single transaction or 502 | arrangement, you convey, or propagate by procuring conveyance of, a 503 | covered work, and grant a patent license to some of the parties 504 | receiving the covered work authorizing them to use, propagate, modify 505 | or convey a specific copy of the covered work, then the patent license 506 | you grant is automatically extended to all recipients of the covered 507 | work and works based on it. 508 | 509 | A patent license is "discriminatory" if it does not include within 510 | the scope of its coverage, prohibits the exercise of, or is 511 | conditioned on the non-exercise of one or more of the rights that are 512 | specifically granted under this License. You may not convey a covered 513 | work if you are a party to an arrangement with a third party that is 514 | in the business of distributing software, under which you make payment 515 | to the third party based on the extent of your activity of conveying 516 | the work, and under which the third party grants, to any of the 517 | parties who would receive the covered work from you, a discriminatory 518 | patent license (a) in connection with copies of the covered work 519 | conveyed by you (or copies made from those copies), or (b) primarily 520 | for and in connection with specific products or compilations that 521 | contain the covered work, unless you entered into that arrangement, 522 | or that patent license was granted, prior to 28 March 2007. 523 | 524 | Nothing in this License shall be construed as excluding or limiting 525 | any implied license or other defenses to infringement that may 526 | otherwise be available to you under applicable patent law. 527 | 528 | 12. No Surrender of Others' Freedom. 529 | 530 | If conditions are imposed on you (whether by court order, agreement or 531 | otherwise) that contradict the conditions of this License, they do not 532 | excuse you from the conditions of this License. If you cannot convey a 533 | covered work so as to satisfy simultaneously your obligations under this 534 | License and any other pertinent obligations, then as a consequence you may 535 | not convey it at all. For example, if you agree to terms that obligate you 536 | to collect a royalty for further conveying from those to whom you convey 537 | the Program, the only way you could satisfy both those terms and this 538 | License would be to refrain entirely from conveying the Program. 539 | 540 | 13. Remote Network Interaction; Use with the GNU General Public License. 541 | 542 | Notwithstanding any other provision of this License, if you modify the 543 | Program, your modified version must prominently offer all users 544 | interacting with it remotely through a computer network (if your version 545 | supports such interaction) an opportunity to receive the Corresponding 546 | Source of your version by providing access to the Corresponding Source 547 | from a network server at no charge, through some standard or customary 548 | means of facilitating copying of software. This Corresponding Source 549 | shall include the Corresponding Source for any work covered by version 3 550 | of the GNU General Public License that is incorporated pursuant to the 551 | following paragraph. 552 | 553 | Notwithstanding any other provision of this License, you have 554 | permission to link or combine any covered work with a work licensed 555 | under version 3 of the GNU General Public License into a single 556 | combined work, and to convey the resulting work. The terms of this 557 | License will continue to apply to the part which is the covered work, 558 | but the work with which it is combined will remain governed by version 559 | 3 of the GNU General Public License. 560 | 561 | 14. Revised Versions of this License. 562 | 563 | The Free Software Foundation may publish revised and/or new versions of 564 | the GNU Affero General Public License from time to time. Such new versions 565 | will be similar in spirit to the present version, but may differ in detail to 566 | address new problems or concerns. 567 | 568 | Each version is given a distinguishing version number. If the 569 | Program specifies that a certain numbered version of the GNU Affero General 570 | Public License "or any later version" applies to it, you have the 571 | option of following the terms and conditions either of that numbered 572 | version or of any later version published by the Free Software 573 | Foundation. If the Program does not specify a version number of the 574 | GNU Affero General Public License, you may choose any version ever published 575 | by the Free Software Foundation. 576 | 577 | If the Program specifies that a proxy can decide which future 578 | versions of the GNU Affero General Public License can be used, that proxy's 579 | public statement of acceptance of a version permanently authorizes you 580 | to choose that version for the Program. 581 | 582 | Later license versions may give you additional or different 583 | permissions. However, no additional obligations are imposed on any 584 | author or copyright holder as a result of your choosing to follow a 585 | later version. 586 | 587 | 15. Disclaimer of Warranty. 588 | 589 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 590 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 591 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 592 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 593 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 594 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 595 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 596 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 597 | 598 | 16. Limitation of Liability. 599 | 600 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 601 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 602 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 603 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 604 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 605 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 606 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 607 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 608 | SUCH DAMAGES. 609 | 610 | 17. Interpretation of Sections 15 and 16. 611 | 612 | If the disclaimer of warranty and limitation of liability provided 613 | above cannot be given local legal effect according to their terms, 614 | reviewing courts shall apply local law that most closely approximates 615 | an absolute waiver of all civil liability in connection with the 616 | Program, unless a warranty or assumption of liability accompanies a 617 | copy of the Program in return for a fee. 618 | 619 | END OF TERMS AND CONDITIONS 620 | 621 | How to Apply These Terms to Your New Programs 622 | 623 | If you develop a new program, and you want it to be of the greatest 624 | possible use to the public, the best way to achieve this is to make it 625 | free software which everyone can redistribute and change under these terms. 626 | 627 | To do so, attach the following notices to the program. It is safest 628 | to attach them to the start of each source file to most effectively 629 | state the exclusion of warranty; and each file should have at least 630 | the "copyright" line and a pointer to where the full notice is found. 631 | 632 | 633 | Copyright (C) 634 | 635 | This program is free software: you can redistribute it and/or modify 636 | it under the terms of the GNU Affero General Public License as published by 637 | the Free Software Foundation, either version 3 of the License, or 638 | (at your option) any later version. 639 | 640 | This program is distributed in the hope that it will be useful, 641 | but WITHOUT ANY WARRANTY; without even the implied warranty of 642 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 643 | GNU Affero General Public License for more details. 644 | 645 | You should have received a copy of the GNU Affero General Public License 646 | along with this program. If not, see . 647 | 648 | Also add information on how to contact you by electronic and paper mail. 649 | 650 | If your software can interact with users remotely through a computer 651 | network, you should also make sure that it provides a way for users to 652 | get its source. For example, if your program is a web application, its 653 | interface could display a "Source" link that leads users to an archive 654 | of the code. There are many ways you could offer source, and different 655 | solutions will be better for different programs; see section 13 for the 656 | specific requirements. 657 | 658 | You should also get your employer (if you work as a programmer) or school, 659 | if any, to sign a "copyright disclaimer" for the program, if necessary. 660 | For more information on this, and how to apply and follow the GNU AGPL, see 661 | . -------------------------------------------------------------------------------- /app/include/external/CardDAV-PHP/README: -------------------------------------------------------------------------------- 1 | Description 2 | ----------- 3 | This is a simple CardDAV client written in PHP called "CardDAV PHP". 4 | 5 | 6 | Features 7 | -------- 8 | * Query your CardDAV server with XML response (simplified or raw) 9 | * Supports many authentication methods 10 | * You can add / update / delete vCards from your CardDAV server 11 | * Get single vCards (raw or extended XML) from your CardDAV server 12 | * Check CardDAV server connection 13 | * Tested CardDAV servers: DAViCal, Apple Addressbook Server, memotoo, SabreDAV, ownCloud, SOGo 14 | 15 | 16 | Installation 17 | ------------ 18 | * Nothing to install - it's standalone 19 | * Requires PHP 5.3 and CURL 20 | * The documentation can be found in the class itself 21 | 22 | 23 | Special thanks 24 | -------------- 25 | * xbgmsharp for the great feedback! 26 | 27 | 28 | Contact 29 | ------- 30 | * Author: Christian Putzke 31 | * Report feature requests and bugs here: https://github.com/graviox/CardDAV-PHP/issues 32 | * Visit my website: http://www.graviox.de/ 33 | * Follow me on Twitter: https://twitter.com/cputzke/ -------------------------------------------------------------------------------- /app/include/external/CardDAV-PHP/carddav.php: -------------------------------------------------------------------------------- 1 | set_auth('username', 'password'); 10 | * echo $carddav->get(); 11 | * 12 | * 13 | * Simple vCard query 14 | * ------------------ 15 | * $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); 16 | * $carddav->set_auth('username', 'password'); 17 | * echo $carddav->get_vcard('0126FFB4-2EB74D0A-302EA17F'); 18 | * 19 | * 20 | * XML vCard query 21 | * ------------------ 22 | * $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); 23 | * $carddav->set_auth('username', 'password'); 24 | * echo $carddav->get_xml_vcard('0126FFB4-2EB74D0A-302EA17F'); 25 | * 26 | * 27 | * Check CardDAV server connection 28 | * ------------------------------- 29 | * $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); 30 | * $carddav->set_auth('username', 'password'); 31 | * var_dump($carddav->check_connection()); 32 | * 33 | * 34 | * CardDAV delete query 35 | * -------------------- 36 | * $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); 37 | * $carddav->set_auth('username', 'password'); 38 | * $carddav->delete('0126FFB4-2EB74D0A-302EA17F'); 39 | * 40 | * 41 | * CardDAV add query 42 | * -------------------- 43 | * $vcard = 'BEGIN:VCARD 44 | * VERSION:3.0 45 | * UID:1f5ea45f-b28a-4b96-25as-ed4f10edf57b 46 | * FN:Christian Putzke 47 | * N:Christian;Putzke;;; 48 | * EMAIL;TYPE=OTHER:christian.putzke@graviox.de 49 | * END:VCARD'; 50 | * 51 | * $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); 52 | * $carddav->set_auth('username', 'password'); 53 | * $vcard_id = $carddav->add($vcard); 54 | * 55 | * 56 | * CardDAV update query 57 | * -------------------- 58 | * $vcard = 'BEGIN:VCARD 59 | * VERSION:3.0 60 | * UID:1f5ea45f-b28a-4b96-25as-ed4f10edf57b 61 | * FN:Christian Putzke 62 | * N:Christian;Putzke;;; 63 | * EMAIL;TYPE=OTHER:christian.putzke@graviox.de 64 | * END:VCARD'; 65 | * 66 | * $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); 67 | * $carddav->set_auth('username', 'password'); 68 | * $carddav->update($vcard, '0126FFB4-2EB74D0A-302EA17F'); 69 | * 70 | * 71 | * CardDAV debug 72 | * ------------- 73 | * $carddav = new carddav_backend('https://davical.example.com/user/contacts/'); 74 | * $carddav->enable_debug(); 75 | * $carddav->set_auth('username', 'password'); 76 | * $carddav->get(); 77 | * var_dump($carddav->get_debug()); 78 | * 79 | * 80 | * CardDAV server list 81 | * ------------------- 82 | * DAViCal: https://example.com/{resource|principal|username}/{collection}/ 83 | * Apple Addressbook Server: https://example.com/addressbooks/users/{resource|principal|username}/{collection}/ 84 | * memotoo: https://sync.memotoo.com/cardDAV/ 85 | * SabreDAV: https://example.com/addressbooks/{resource|principal|username}/{collection}/ 86 | * ownCloud: https://example.com/apps/contacts/carddav.php/addressbooks/{resource|principal|username}/{collection}/ 87 | * SOGo: https://example.com/SOGo/dav/{resource|principal|username}/Contacts/{collection}/ 88 | * Google (direct): https://google.com/m8/carddav/principals/__uids__/{username}/lists/default/ 89 | * 90 | * 91 | * @author Christian Putzke 92 | * @copyright Christian Putzke 93 | * @link http://www.graviox.de/ 94 | * @link https://twitter.com/cputzke/ 95 | * @since 20.07.2011 96 | * @version 0.6 97 | * @license http://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later 98 | * 99 | */ 100 | 101 | class carddav_backend 102 | { 103 | /** 104 | * CardDAV PHP Version 105 | * 106 | * @constant string 107 | */ 108 | const VERSION = '0.6'; 109 | 110 | /** 111 | * User agent displayed in http requests 112 | * 113 | * @constant string 114 | */ 115 | const USERAGENT = 'CardDAV PHP/'; 116 | 117 | /** 118 | * CardDAV server url 119 | * 120 | * @var string 121 | */ 122 | private $url = null; 123 | 124 | /** 125 | * CardDAV server url_parts 126 | * 127 | * @var array 128 | */ 129 | private $url_parts = null; 130 | 131 | /** 132 | * VCard File URL Extension 133 | * 134 | * @var string 135 | */ 136 | private $url_vcard_extension = '.vcf'; 137 | 138 | /** 139 | * Authentication string 140 | * 141 | * @var string 142 | */ 143 | private $auth = null; 144 | 145 | /** 146 | * Authentication: username 147 | * 148 | * @var string 149 | */ 150 | private $username = null; 151 | 152 | /** 153 | * Authentication: password 154 | * 155 | * @var string 156 | */ 157 | private $password = null; 158 | 159 | /** 160 | * Characters used for vCard id generation 161 | * 162 | * @var array 163 | */ 164 | private $vcard_id_chars = array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'A', 'B', 'C', 'D', 'E', 'F'); 165 | 166 | /** 167 | * CardDAV server connection (curl handle) 168 | * 169 | * @var resource 170 | */ 171 | private $curl; 172 | 173 | /** 174 | * Debug on or off 175 | * 176 | * @var boolean 177 | */ 178 | private $debug = false; 179 | 180 | /** 181 | * All available debug information 182 | * 183 | * @var array 184 | */ 185 | private $debug_information = array(); 186 | 187 | /** 188 | * Exception codes 189 | */ 190 | const EXCEPTION_WRONG_HTTP_STATUS_CODE_GET = 1000; 191 | const EXCEPTION_WRONG_HTTP_STATUS_CODE_GET_VCARD = 1001; 192 | const EXCEPTION_WRONG_HTTP_STATUS_CODE_GET_XML_VCARD = 1002; 193 | const EXCEPTION_WRONG_HTTP_STATUS_CODE_DELETE = 1003; 194 | const EXCEPTION_WRONG_HTTP_STATUS_CODE_ADD = 1004; 195 | const EXCEPTION_WRONG_HTTP_STATUS_CODE_UPDATE = 1005; 196 | const EXCEPTION_MALFORMED_XML_RESPONSE = 1006; 197 | const EXCEPTION_COULD_NOT_GENERATE_NEW_VCARD_ID = 1007; 198 | 199 | 200 | /** 201 | * Constructor 202 | * Sets the CardDAV server url 203 | * 204 | * @param string $url CardDAV server url 205 | */ 206 | public function __construct($url = null) 207 | { 208 | if ($url !== null) 209 | { 210 | $this->set_url($url); 211 | } 212 | } 213 | 214 | /** 215 | * Sets debug information 216 | * 217 | * @param array $debug_information Debug information 218 | * @return void 219 | */ 220 | public function set_debug(array $debug_information) 221 | { 222 | $this->debug_information[] = $debug_information; 223 | } 224 | 225 | /** 226 | * Sets the CardDAV server url 227 | * 228 | * @param string $url CardDAV server url 229 | * @return void 230 | */ 231 | public function set_url($url) 232 | { 233 | $this->url = $url; 234 | 235 | if (substr($this->url, -1, 1) !== '/') 236 | { 237 | $this->url = $this->url . '/'; 238 | } 239 | 240 | $this->url_parts = parse_url($this->url); 241 | 242 | // workaround for providers that don't use the default .vcf extension 243 | if (strpos($this->url, "google.com")) 244 | { 245 | $this->set_vcard_extension(""); 246 | } 247 | } 248 | 249 | /** 250 | * Sets the CardDAV vcard url extension 251 | * 252 | * Most providers do requests handling Vcards with .vcf, however 253 | * this isn't always the case and some providers (such as Google) 254 | * returned a 404 if the .vcf extension is used - or the other 255 | * way around, returning 404 unless .vcf is used. 256 | * 257 | * Both approaches are technically correct, see rfc635 258 | * http://tools.ietf.org/html/rfc6352 259 | * 260 | * 261 | * @param string $extension File extension 262 | * @return void 263 | */ 264 | public function set_vcard_extension($extension) 265 | { 266 | $this->url_vcard_extension = $extension; 267 | } 268 | 269 | /** 270 | * Sets authentication information 271 | * 272 | * @param string $username CardDAV server username 273 | * @param string $password CardDAV server password 274 | * @return void 275 | */ 276 | public function set_auth($username, $password) 277 | { 278 | $this->username = $username; 279 | $this->password = $password; 280 | $this->auth = $username . ':' . $password; 281 | } 282 | 283 | /** 284 | * Gets all available debug information 285 | * 286 | * @return array $this->debug_information All available debug information 287 | */ 288 | public function get_debug() 289 | { 290 | return $this->debug_information; 291 | } 292 | 293 | /** 294 | * Gets all vCards including additional information from the CardDAV server 295 | * 296 | * @param boolean $include_vcards Include vCards within the response (simplified only) 297 | * @param boolean $raw Get response raw or simplified 298 | * @return string Raw or simplified XML response 299 | */ 300 | public function get($include_vcards = true, $raw = false) 301 | { 302 | $result = $this->query($this->url, 'PROPFIND'); 303 | 304 | switch ($result['http_code']) 305 | { 306 | case 200: 307 | case 207: 308 | if ($raw === true) 309 | { 310 | return $result['response']; 311 | } 312 | else 313 | { 314 | return $this->simplify($result['response'], $include_vcards); 315 | } 316 | break; 317 | 318 | default: 319 | throw new Exception('Woops, something\'s gone wrong! The CardDAV server returned the http status code ' . $result['http_code'] . '.', self::EXCEPTION_WRONG_HTTP_STATUS_CODE_GET); 320 | break; 321 | } 322 | } 323 | 324 | /** 325 | * Gets a clean vCard from the CardDAV server 326 | * 327 | * @param string $vcard_id vCard id on the CardDAV server 328 | * @return string vCard (text/vcard) 329 | */ 330 | public function get_vcard($vcard_id) 331 | { 332 | $vcard_id = str_replace($this->url_vcard_extension, null, $vcard_id); 333 | $result = $this->query($this->url . $vcard_id . $this->url_vcard_extension, 'GET'); 334 | 335 | switch ($result['http_code']) 336 | { 337 | case 200: 338 | case 207: 339 | return $result['response']; 340 | break; 341 | 342 | default: 343 | throw new Exception('Woops, something\'s gone wrong! The CardDAV server returned the http status code ' . $result['http_code'] . '.', self::EXCEPTION_WRONG_HTTP_STATUS_CODE_GET_VCARD); 344 | break; 345 | } 346 | } 347 | 348 | /** 349 | * Gets a vCard + XML from the CardDAV Server 350 | * 351 | * @param string $vcard_id vCard id on the CardDAV Server 352 | * @return string Raw or simplified vCard (text/xml) 353 | */ 354 | public function get_xml_vcard($vcard_id) 355 | { 356 | $vcard_id = str_replace($this->url_vcard_extension, null, $vcard_id); 357 | 358 | $xml = new XMLWriter(); 359 | $xml->openMemory(); 360 | $xml->setIndent(4); 361 | $xml->startDocument('1.0', 'utf-8'); 362 | $xml->startElement('C:addressbook-multiget'); 363 | $xml->writeAttribute('xmlns:D', 'DAV:'); 364 | $xml->writeAttribute('xmlns:C', 'urn:ietf:params:xml:ns:carddav'); 365 | $xml->startElement('D:prop'); 366 | $xml->writeElement('D:getetag'); 367 | $xml->writeElement('D:getlastmodified'); 368 | $xml->endElement(); 369 | $xml->writeElement('D:href', $this->url_parts['path'] . $vcard_id . $this->url_vcard_extension); 370 | $xml->endElement(); 371 | $xml->endDocument(); 372 | 373 | $result = $this->query($this->url, 'REPORT', $xml->outputMemory(), 'text/xml'); 374 | 375 | switch ($result['http_code']) 376 | { 377 | case 200: 378 | case 207: 379 | return $this->simplify($result['response'], true); 380 | break; 381 | 382 | default: 383 | throw new Exception('Woops, something\'s gone wrong! The CardDAV server returned the http status code ' . $result['http_code'] . '.', self::EXCEPTION_WRONG_HTTP_STATUS_CODE_GET_XML_VCARD); 384 | break; 385 | } 386 | } 387 | 388 | /** 389 | * Enables the debug mode 390 | * 391 | * @return void 392 | */ 393 | public function enable_debug() 394 | { 395 | $this->debug = true; 396 | } 397 | 398 | /** 399 | * Checks if the CardDAV server is reachable 400 | * 401 | * @return boolean 402 | */ 403 | public function check_connection() 404 | { 405 | $result = $this->query($this->url, 'OPTIONS'); 406 | 407 | if ($result['http_code'] === 200) 408 | { 409 | return true; 410 | } 411 | else 412 | { 413 | return false; 414 | } 415 | } 416 | 417 | /** 418 | * Cleans the vCard 419 | * 420 | * @param string $vcard vCard 421 | * @return string $vcard vCard 422 | */ 423 | private function clean_vcard($vcard) 424 | { 425 | $vcard = str_replace("\t", null, $vcard); 426 | 427 | return $vcard; 428 | } 429 | 430 | /** 431 | * Deletes an entry from the CardDAV server 432 | * 433 | * @param string $vcard_id vCard id on the CardDAV server 434 | * @return boolean 435 | */ 436 | public function delete($vcard_id) 437 | { 438 | $result = $this->query($this->url . $vcard_id . $this->url_vcard_extension, 'DELETE'); 439 | 440 | switch ($result['http_code']) 441 | { 442 | case 204: 443 | return true; 444 | break; 445 | 446 | default: 447 | throw new Exception('Woops, something\'s gone wrong! The CardDAV server returned the http status code ' . $result['http_code'] . '.', self::EXCEPTION_WRONG_HTTP_STATUS_CODE_DELETE); 448 | break; 449 | } 450 | } 451 | 452 | /** 453 | * Adds an entry to the CardDAV server 454 | * 455 | * @param string $vcard vCard 456 | * @param string $vcard_id vCard id on the CardDAV server 457 | * @return string The new vCard id 458 | */ 459 | public function add($vcard, $vcard_id = null) 460 | { 461 | if ($vcard_id === null) 462 | { 463 | $vcard_id = $this->generate_vcard_id(); 464 | } 465 | $vcard = $this->clean_vcard($vcard); 466 | $result = $this->query($this->url . $vcard_id . $this->url_vcard_extension, 'PUT', $vcard, 'text/vcard'); 467 | 468 | switch($result['http_code']) 469 | { 470 | case 201: 471 | return $vcard_id; 472 | break; 473 | 474 | default: 475 | throw new Exception('Woops, something\'s gone wrong! The CardDAV server returned the http status code ' . $result['http_code'] . '.', self::EXCEPTION_WRONG_HTTP_STATUS_CODE_ADD); 476 | break; 477 | } 478 | } 479 | 480 | /** 481 | * Updates an entry to the CardDAV server 482 | * 483 | * @param string $vcard vCard 484 | * @param string $vcard_id vCard id on the CardDAV server 485 | * @return boolean 486 | */ 487 | public function update($vcard, $vcard_id) 488 | { 489 | try 490 | { 491 | return $this->add($vcard, $vcard_id); 492 | } 493 | catch (Exception $e) 494 | { 495 | throw new Exception($e->getMessage(), self::EXCEPTION_WRONG_HTTP_STATUS_CODE_UPDATE); 496 | } 497 | } 498 | 499 | /** 500 | * Simplify CardDAV XML response 501 | * 502 | * @param string $response CardDAV XML response 503 | * @param boolean $include_vcards Include vCards or not 504 | * @return string Simplified CardDAV XML response 505 | */ 506 | private function simplify($response, $include_vcards = true) 507 | { 508 | $response = $this->clean_response($response); 509 | 510 | try 511 | { 512 | $xml = new SimpleXMLElement($response); 513 | } 514 | catch(Exception $e) 515 | { 516 | throw new Exception('The XML response seems to be malformed and can\'t be simplified!', self::EXCEPTION_MALFORMED_XML_RESPONSE, $e); 517 | } 518 | 519 | $simplified_xml = new XMLWriter(); 520 | $simplified_xml->openMemory(); 521 | $simplified_xml->setIndent(4); 522 | 523 | $simplified_xml->startDocument('1.0', 'utf-8'); 524 | $simplified_xml->startElement('response'); 525 | 526 | if (!empty($xml->response)) 527 | { 528 | foreach ($xml->response as $response) 529 | { 530 | if (preg_match('/vcard/', $response->propstat->prop->getcontenttype) || preg_match('/vcf/', $response->href)) 531 | { 532 | $id = basename($response->href); 533 | $id = str_replace($this->url_vcard_extension, null, $id); 534 | 535 | if (!empty($id)) 536 | { 537 | $simplified_xml->startElement('element'); 538 | $simplified_xml->writeElement('id', $id); 539 | $simplified_xml->writeElement('etag', str_replace('"', null, $response->propstat->prop->getetag)); 540 | $simplified_xml->writeElement('last_modified', $response->propstat->prop->getlastmodified); 541 | 542 | if ($include_vcards === true) 543 | { 544 | $simplified_xml->writeElement('vcard', $this->get_vcard($id)); 545 | } 546 | $simplified_xml->endElement(); 547 | } 548 | } 549 | else if (preg_match('/unix-directory/', $response->propstat->prop->getcontenttype)) 550 | { 551 | if (isset($response->propstat->prop->href)) 552 | { 553 | $href = $response->propstat->prop->href; 554 | } 555 | else if (isset($response->href)) 556 | { 557 | $href = $response->href; 558 | } 559 | else 560 | { 561 | $href = null; 562 | } 563 | 564 | $url = str_replace($this->url_parts['path'], null, $this->url) . $href; 565 | $simplified_xml->startElement('addressbook_element'); 566 | $simplified_xml->writeElement('display_name', $response->propstat->prop->displayname); 567 | $simplified_xml->writeElement('url', $url); 568 | $simplified_xml->writeElement('last_modified', $response->propstat->prop->getlastmodified); 569 | $simplified_xml->endElement(); 570 | } 571 | } 572 | } 573 | 574 | $simplified_xml->endElement(); 575 | $simplified_xml->endDocument(); 576 | 577 | return $simplified_xml->outputMemory(); 578 | } 579 | 580 | /** 581 | * Cleans CardDAV XML response 582 | * 583 | * @param string $response CardDAV XML response 584 | * @return string $response Cleaned CardDAV XML response 585 | */ 586 | private function clean_response($response) 587 | { 588 | $response = utf8_encode($response); 589 | $response = str_replace('D:', null, $response); 590 | $response = str_replace('d:', null, $response); 591 | $response = str_replace('C:', null, $response); 592 | $response = str_replace('c:', null, $response); 593 | 594 | return $response; 595 | } 596 | 597 | /** 598 | * Curl initialization 599 | * 600 | * @return void 601 | */ 602 | public function curl_init() 603 | { 604 | if (empty($this->curl)) 605 | { 606 | $this->curl = curl_init(); 607 | curl_setopt($this->curl, CURLOPT_HEADER, true); 608 | curl_setopt($this->curl, CURLOPT_SSL_VERIFYHOST, false); 609 | curl_setopt($this->curl, CURLOPT_SSL_VERIFYPEER, false); 610 | curl_setopt($this->curl, CURLOPT_RETURNTRANSFER, true); 611 | curl_setopt($this->curl, CURLOPT_USERAGENT, self::USERAGENT.self::VERSION); 612 | 613 | if ($this->auth !== null) 614 | { 615 | curl_setopt($this->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY); 616 | curl_setopt($this->curl, CURLOPT_USERPWD, $this->auth); 617 | } 618 | } 619 | } 620 | 621 | /** 622 | * Query the CardDAV server via curl and returns the response 623 | * 624 | * @param string $url CardDAV server URL 625 | * @param string $method HTTP method like (OPTIONS, GET, HEAD, POST, PUT, DELETE, TRACE, COPY, MOVE) 626 | * @param string $content Content for CardDAV queries 627 | * @param string $content_type Set content type 628 | * @return array Raw CardDAV Response and http status code 629 | */ 630 | private function query($url, $method, $content = null, $content_type = null) 631 | { 632 | $this->curl_init(); 633 | 634 | curl_setopt($this->curl, CURLOPT_URL, $url); 635 | curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $method); 636 | 637 | if ($content !== null) 638 | { 639 | curl_setopt($this->curl, CURLOPT_POST, true); 640 | curl_setopt($this->curl, CURLOPT_POSTFIELDS, $content); 641 | } 642 | else 643 | { 644 | curl_setopt($this->curl, CURLOPT_POST, false); 645 | curl_setopt($this->curl, CURLOPT_POSTFIELDS, null); 646 | } 647 | 648 | if ($content_type !== null) 649 | { 650 | curl_setopt($this->curl, CURLOPT_HTTPHEADER, array('Content-type: '.$content_type)); 651 | } 652 | else 653 | { 654 | curl_setopt($this->curl, CURLOPT_HTTPHEADER, array()); 655 | } 656 | 657 | $complete_response = curl_exec($this->curl); 658 | $header_size = curl_getinfo($this->curl, CURLINFO_HEADER_SIZE); 659 | $http_code = curl_getinfo($this->curl, CURLINFO_HTTP_CODE); 660 | $header = trim(substr($complete_response, 0, $header_size)); 661 | $response = substr($complete_response, $header_size); 662 | 663 | $return = array( 664 | 'response' => $response, 665 | 'http_code' => $http_code 666 | ); 667 | 668 | if ($this->debug === true) 669 | { 670 | $debug = $return; 671 | $debug['url'] = $url; 672 | $debug['method'] = $method; 673 | $debug['content'] = $content; 674 | $debug['content_type'] = $content_type; 675 | $debug['header'] = $header; 676 | $this->set_debug($debug); 677 | } 678 | 679 | return $return; 680 | } 681 | 682 | /** 683 | * Returns a valid and unused vCard id 684 | * 685 | * @return string $vcard_id Valid vCard id 686 | */ 687 | private function generate_vcard_id() 688 | { 689 | $vcard_id = null; 690 | 691 | for ($number = 0; $number <= 25; $number ++) 692 | { 693 | if ($number == 8 || $number == 17) 694 | { 695 | $vcard_id .= '-'; 696 | } 697 | else 698 | { 699 | $vcard_id .= $this->vcard_id_chars[mt_rand(0, (count($this->vcard_id_chars) - 1))]; 700 | } 701 | } 702 | 703 | try 704 | { 705 | $carddav = new carddav_backend($this->url); 706 | $carddav->set_auth($this->username, $this->password); 707 | 708 | $result = $carddav->query($this->url . $vcard_id . $this->url_vcard_extension, 'GET'); 709 | 710 | if ($result['http_code'] !== 404) 711 | { 712 | $vcard_id = $this->generate_vcard_id(); 713 | } 714 | 715 | return $vcard_id; 716 | } 717 | catch (Exception $e) 718 | { 719 | throw new Exception($e->getMessage(), self::EXCEPTION_COULD_NOT_GENERATE_NEW_VCARD_ID); 720 | } 721 | } 722 | 723 | /** 724 | * Destructor 725 | * Close curl connection if it's open 726 | * 727 | * @return void 728 | */ 729 | public function __destruct() 730 | { 731 | if (!empty($this->curl)) 732 | { 733 | curl_close($this->curl); 734 | } 735 | } 736 | } 737 | -------------------------------------------------------------------------------- /app/include/external/CardDAV-PHP/support.php: -------------------------------------------------------------------------------- 1 | loadXML($xmlstr); 19 | return domnode_to_array($doc->documentElement); 20 | } 21 | function domnode_to_array($node) { 22 | $output = array(); 23 | switch ($node->nodeType) { 24 | case XML_CDATA_SECTION_NODE: 25 | case XML_TEXT_NODE: 26 | $output = trim($node->textContent); 27 | break; 28 | case XML_ELEMENT_NODE: 29 | for ($i=0, $m=$node->childNodes->length; $i<$m; $i++) { 30 | $child = $node->childNodes->item($i); 31 | $v = domnode_to_array($child); 32 | if(isset($child->tagName)) { 33 | $t = $child->tagName; 34 | if(!isset($output[$t])) { 35 | $output[$t] = array(); 36 | } 37 | $output[$t][] = $v; 38 | } 39 | elseif($v) { 40 | $output = (string) $v; 41 | } 42 | } 43 | if(is_array($output)) { 44 | if($node->attributes->length) { 45 | $a = array(); 46 | foreach($node->attributes as $attrName => $attrNode) { 47 | $a[$attrName] = (string) $attrNode->value; 48 | } 49 | $output['@attributes'] = $a; 50 | } 51 | foreach ($output as $t => $v) { 52 | if(is_array($v) && count($v)==1 && $t!='@attributes') { 53 | $output[$t] = $v[0]; 54 | } 55 | } 56 | } 57 | break; 58 | } 59 | return $output; 60 | } 61 | ?> 62 | -------------------------------------------------------------------------------- /app/include/external/XMPPHP/BOSH.php: -------------------------------------------------------------------------------- 1 | 24 | * @author Stephan Wentz 25 | * @author Michael Garvin 26 | * @copyright 2008 Nathanael C. Fritz 27 | */ 28 | 29 | /** XMPPHP_XMLStream */ 30 | require_once dirname(__FILE__) . "/XMPP.php"; 31 | 32 | /** 33 | * XMPPHP Main Class 34 | * 35 | * @category xmpphp 36 | * @package XMPPHP 37 | * @author Nathanael C. Fritz 38 | * @author Stephan Wentz 39 | * @author Michael Garvin 40 | * @copyright 2008 Nathanael C. Fritz 41 | * @version $Id$ 42 | */ 43 | class XMPPHP_BOSH extends XMPPHP_XMPP { 44 | 45 | protected $rid; 46 | protected $sid; 47 | protected $http_server; 48 | protected $http_buffer = Array(); 49 | protected $session = false; 50 | 51 | public function connect($server, $wait='1', $session=false) { 52 | $this->http_server = $server; 53 | $this->use_encryption = false; 54 | $this->session = $session; 55 | 56 | $this->rid = 3001; 57 | $this->sid = null; 58 | if($session) 59 | { 60 | $this->loadSession(); 61 | } 62 | if(!$this->sid) { 63 | $body = $this->__buildBody(); 64 | $body->addAttribute('hold','1'); 65 | $body->addAttribute('to', $this->host); 66 | $body->addAttribute('route', "xmpp:{$this->host}:{$this->port}"); 67 | $body->addAttribute('secure','true'); 68 | $body->addAttribute('xmpp:version','1.6', 'urn:xmpp:xbosh'); 69 | $body->addAttribute('wait', strval($wait)); 70 | $body->addAttribute('ack','1'); 71 | $body->addAttribute('xmlns:xmpp','urn:xmpp:xbosh'); 72 | $buff = ""; 73 | xml_parse($this->parser, $buff, false); 74 | $response = $this->__sendBody($body); 75 | $rxml = new SimpleXMLElement($response); 76 | $this->sid = $rxml['sid']; 77 | 78 | } else { 79 | $buff = ""; 80 | xml_parse($this->parser, $buff, false); 81 | } 82 | } 83 | 84 | public function __sendBody($body=null, $recv=true) { 85 | if(!$body) { 86 | $body = $this->__buildBody(); 87 | } 88 | $ch = curl_init($this->http_server); 89 | curl_setopt($ch, CURLOPT_HEADER, 0); 90 | curl_setopt($ch, CURLOPT_POST, 1); 91 | curl_setopt($ch, CURLOPT_POSTFIELDS, $body->asXML()); 92 | curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); 93 | $header = array('Accept-Encoding: gzip, deflate','Content-Type: text/xml; charset=utf-8'); 94 | curl_setopt($ch, CURLOPT_HTTPHEADER, $header ); 95 | curl_setopt($ch, CURLOPT_VERBOSE, 0); 96 | $output = ''; 97 | if($recv) { 98 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 99 | $output = curl_exec($ch); 100 | $this->http_buffer[] = $output; 101 | } 102 | curl_close($ch); 103 | return $output; 104 | } 105 | 106 | public function __buildBody($sub=null) { 107 | $xml = new SimpleXMLElement(""); 108 | $xml->addAttribute('content', 'text/xml; charset=utf-8'); 109 | $xml->addAttribute('rid', $this->rid); 110 | $this->rid += 1; 111 | if($this->sid) $xml->addAttribute('sid', $this->sid); 112 | #if($this->sid) $xml->addAttribute('xmlns', 'http://jabber.org/protocol/httpbind'); 113 | $xml->addAttribute('xml:lang', 'en'); 114 | if($sub) { // ok, so simplexml is lame 115 | $p = dom_import_simplexml($xml); 116 | $c = dom_import_simplexml($sub); 117 | $cn = $p->ownerDocument->importNode($c, true); 118 | $p->appendChild($cn); 119 | $xml = simplexml_import_dom($p); 120 | } 121 | return $xml; 122 | } 123 | 124 | public function __process() { 125 | if($this->http_buffer) { 126 | $this->__parseBuffer(); 127 | } else { 128 | $this->__sendBody(); 129 | $this->__parseBuffer(); 130 | } 131 | } 132 | 133 | public function __parseBuffer() { 134 | while ($this->http_buffer) { 135 | $idx = key($this->http_buffer); 136 | $buffer = $this->http_buffer[$idx]; 137 | unset($this->http_buffer[$idx]); 138 | if($buffer) { 139 | $xml = new SimpleXMLElement($buffer); 140 | $children = $xml->xpath('child::node()'); 141 | foreach ($children as $child) { 142 | $buff = $child->asXML(); 143 | $this->log->log("RECV: $buff", XMPPHP_Log::LEVEL_VERBOSE); 144 | xml_parse($this->parser, $buff, false); 145 | } 146 | } 147 | } 148 | } 149 | 150 | public function send($msg) { 151 | $this->log->log("SEND: $msg", XMPPHP_Log::LEVEL_VERBOSE); 152 | $msg = new SimpleXMLElement($msg); 153 | #$msg->addAttribute('xmlns', 'jabber:client'); 154 | $this->__sendBody($this->__buildBody($msg), true); 155 | #$this->__parseBuffer(); 156 | } 157 | 158 | public function reset() { 159 | $this->xml_depth = 0; 160 | unset($this->xmlobj); 161 | $this->xmlobj = array(); 162 | $this->setupParser(); 163 | #$this->send($this->stream_start); 164 | $body = $this->__buildBody(); 165 | $body->addAttribute('to', $this->host); 166 | $body->addAttribute('xmpp:restart', 'true', 'urn:xmpp:xbosh'); 167 | $buff = ""; 168 | $response = $this->__sendBody($body); 169 | $this->been_reset = true; 170 | xml_parse($this->parser, $buff, false); 171 | } 172 | 173 | public function loadSession() { 174 | if(isset($_SESSION['XMPPHP_BOSH_RID'])) $this->rid = $_SESSION['XMPPHP_BOSH_RID']; 175 | if(isset($_SESSION['XMPPHP_BOSH_SID'])) $this->sid = $_SESSION['XMPPHP_BOSH_SID']; 176 | if(isset($_SESSION['XMPPHP_BOSH_authed'])) $this->authed = $_SESSION['XMPPHP_BOSH_authed']; 177 | if(isset($_SESSION['XMPPHP_BOSH_jid'])) $this->jid = $_SESSION['XMPPHP_BOSH_jid']; 178 | if(isset($_SESSION['XMPPHP_BOSH_fulljid'])) $this->fulljid = $_SESSION['XMPPHP_BOSH_fulljid']; 179 | } 180 | 181 | public function saveSession() { 182 | $_SESSION['XMPPHP_BOSH_RID'] = (string) $this->rid; 183 | $_SESSION['XMPPHP_BOSH_SID'] = (string) $this->sid; 184 | $_SESSION['XMPPHP_BOSH_authed'] = (boolean) $this->authed; 185 | $_SESSION['XMPPHP_BOSH_jid'] = (string) $this->jid; 186 | $_SESSION['XMPPHP_BOSH_fulljid'] = (string) $this->fulljid; 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /app/include/external/XMPPHP/Exception.php: -------------------------------------------------------------------------------- 1 | 24 | * @author Stephan Wentz 25 | * @author Michael Garvin 26 | * @copyright 2008 Nathanael C. Fritz 27 | */ 28 | 29 | /** 30 | * XMPPHP Exception 31 | * 32 | * @category xmpphp 33 | * @package XMPPHP 34 | * @author Nathanael C. Fritz 35 | * @author Stephan Wentz 36 | * @author Michael Garvin 37 | * @copyright 2008 Nathanael C. Fritz 38 | * @version $Id$ 39 | */ 40 | class XMPPHP_Exception extends Exception { 41 | } 42 | -------------------------------------------------------------------------------- /app/include/external/XMPPHP/Log.php: -------------------------------------------------------------------------------- 1 | 24 | * @author Stephan Wentz 25 | * @author Michael Garvin 26 | * @copyright 2008 Nathanael C. Fritz 27 | */ 28 | 29 | /** 30 | * XMPPHP Log 31 | * 32 | * @package XMPPHP 33 | * @author Nathanael C. Fritz 34 | * @author Stephan Wentz 35 | * @author Michael Garvin 36 | * @copyright 2008 Nathanael C. Fritz 37 | * @version $Id$ 38 | */ 39 | class XMPPHP_Log { 40 | 41 | const LEVEL_ERROR = 0; 42 | const LEVEL_WARNING = 1; 43 | const LEVEL_INFO = 2; 44 | const LEVEL_DEBUG = 3; 45 | const LEVEL_VERBOSE = 4; 46 | 47 | /** 48 | * @var array 49 | */ 50 | protected $data = array(); 51 | 52 | /** 53 | * @var array 54 | */ 55 | protected $names = array('ERROR', 'WARNING', 'INFO', 'DEBUG', 'VERBOSE'); 56 | 57 | /** 58 | * @var integer 59 | */ 60 | protected $runlevel; 61 | 62 | /** 63 | * @var boolean 64 | */ 65 | protected $printout; 66 | 67 | /** 68 | * Constructor 69 | * 70 | * @param boolean $printout 71 | * @param string $runlevel 72 | */ 73 | public function __construct($printout = false, $runlevel = self::LEVEL_INFO) { 74 | $this->printout = (boolean)$printout; 75 | $this->runlevel = (int)$runlevel; 76 | } 77 | 78 | /** 79 | * Add a message to the log data array 80 | * If printout in this instance is set to true, directly output the message 81 | * 82 | * @param string $msg 83 | * @param integer $runlevel 84 | */ 85 | public function log($msg, $runlevel = self::LEVEL_INFO) { 86 | $time = time(); 87 | #$this->data[] = array($this->runlevel, $msg, $time); 88 | if($this->printout and $runlevel <= $this->runlevel) { 89 | $this->writeLine($msg, $runlevel, $time); 90 | } 91 | } 92 | 93 | /** 94 | * Output the complete log. 95 | * Log will be cleared if $clear = true 96 | * 97 | * @param boolean $clear 98 | * @param integer $runlevel 99 | */ 100 | public function printout($clear = true, $runlevel = null) { 101 | if($runlevel === null) { 102 | $runlevel = $this->runlevel; 103 | } 104 | foreach($this->data as $data) { 105 | if($runlevel <= $data[0]) { 106 | $this->writeLine($data[1], $runlevel, $data[2]); 107 | } 108 | } 109 | if($clear) { 110 | $this->data = array(); 111 | } 112 | } 113 | 114 | protected function writeLine($msg, $runlevel, $time) { 115 | //echo date('Y-m-d H:i:s', $time)." [".$this->names[$runlevel]."]: ".$msg."\n"; 116 | echo $time." [".$this->names[$runlevel]."]: ".$msg."\n"; 117 | flush(); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /app/include/external/XMPPHP/Roster.php: -------------------------------------------------------------------------------- 1 | 24 | * @author Stephan Wentz 25 | * @author Michael Garvin 26 | * @copyright 2008 Nathanael C. Fritz 27 | */ 28 | 29 | /** 30 | * XMPPHP Roster Object 31 | * 32 | * @category xmpphp 33 | * @package XMPPHP 34 | * @author Nathanael C. Fritz 35 | * @author Stephan Wentz 36 | * @author Michael Garvin 37 | * @copyright 2008 Nathanael C. Fritz 38 | * @version $Id$ 39 | */ 40 | 41 | class Roster { 42 | /** 43 | * Roster array, handles contacts and presence. Indexed by jid. 44 | * Contains array with potentially two indexes 'contact' and 'presence' 45 | * @var array 46 | */ 47 | protected $roster_array = array(); 48 | /** 49 | * Constructor 50 | * 51 | */ 52 | public function __construct($roster_array = array()) { 53 | if ($this->verifyRoster($roster_array)) { 54 | $this->roster_array = $roster_array; //Allow for prepopulation with existing roster 55 | } else { 56 | $this->roster_array = array(); 57 | } 58 | } 59 | 60 | /** 61 | * 62 | * Check that a given roster array is of a valid structure (empty is still valid) 63 | * 64 | * @param array $roster_array 65 | */ 66 | protected function verifyRoster($roster_array) { 67 | #TODO once we know *what* a valid roster array looks like 68 | return True; 69 | } 70 | 71 | /** 72 | * 73 | * Add given contact to roster 74 | * 75 | * @param string $jid 76 | * @param string $subscription 77 | * @param string $name 78 | * @param array $groups 79 | */ 80 | public function addContact($jid, $subscription, $name='', $groups=array()) { 81 | $contact = array('jid' => $jid, 'subscription' => $subscription, 'name' => $name, 'groups' => $groups); 82 | if ($this->isContact($jid)) { 83 | $this->roster_array[$jid]['contact'] = $contact; 84 | } else { 85 | $this->roster_array[$jid] = array('contact' => $contact); 86 | } 87 | } 88 | 89 | /** 90 | * 91 | * Retrieve contact via jid 92 | * 93 | * @param string $jid 94 | */ 95 | public function getContact($jid) { 96 | if ($this->isContact($jid)) { 97 | return $this->roster_array[$jid]['contact']; 98 | } 99 | } 100 | 101 | /** 102 | * 103 | * Discover if a contact exists in the roster via jid 104 | * 105 | * @param string $jid 106 | */ 107 | public function isContact($jid) { 108 | return (array_key_exists($jid, $this->roster_array)); 109 | } 110 | 111 | /** 112 | * 113 | * Set presence 114 | * 115 | * @param string $presence 116 | * @param integer $priority 117 | * @param string $show 118 | * @param string $status 119 | */ 120 | public function setPresence($presence, $priority, $show, $status) { 121 | list($jid, $resource) = split("/", $presence); 122 | if ($show != 'unavailable') { 123 | if (!$this->isContact($jid)) { 124 | $this->addContact($jid, 'not-in-roster'); 125 | } 126 | $resource = $resource ? $resource : ''; 127 | $this->roster_array[$jid]['presence'][$resource] = array('priority' => $priority, 'show' => $show, 'status' => $status); 128 | } else { //Nuke unavailable resources to save memory 129 | unset($this->roster_array[$jid]['resource'][$resource]); 130 | } 131 | } 132 | 133 | /* 134 | * 135 | * Return best presence for jid 136 | * 137 | * @param string $jid 138 | */ 139 | public function getPresence($jid) { 140 | $split = split("/", $jid); 141 | $jid = $split[0]; 142 | if($this->isContact($jid)) { 143 | $current = array('resource' => '', 'active' => '', 'priority' => -129, 'show' => '', 'status' => ''); //Priorities can only be -128 = 127 144 | foreach($this->roster_array[$jid]['presence'] as $resource => $presence) { 145 | //Highest available priority or just highest priority 146 | if ($presence['priority'] > $current['priority'] and (($presence['show'] == "chat" or $presence['show'] == "available") or ($current['show'] != "chat" or $current['show'] != "available"))) { 147 | $current = $presence; 148 | $current['resource'] = $resource; 149 | } 150 | } 151 | return $current; 152 | } 153 | } 154 | /** 155 | * 156 | * Get roster 157 | * 158 | */ 159 | public function getRoster() { 160 | return $this->roster_array; 161 | } 162 | } 163 | ?> 164 | -------------------------------------------------------------------------------- /app/include/external/XMPPHP/XMLObj.php: -------------------------------------------------------------------------------- 1 | 24 | * @author Stephan Wentz 25 | * @author Michael Garvin 26 | * @copyright 2008 Nathanael C. Fritz 27 | */ 28 | 29 | /** 30 | * XMPPHP XML Object 31 | * 32 | * @category xmpphp 33 | * @package XMPPHP 34 | * @author Nathanael C. Fritz 35 | * @author Stephan Wentz 36 | * @author Michael Garvin 37 | * @copyright 2008 Nathanael C. Fritz 38 | * @version $Id$ 39 | */ 40 | class XMPPHP_XMLObj { 41 | /** 42 | * Tag name 43 | * 44 | * @var string 45 | */ 46 | public $name; 47 | 48 | /** 49 | * Namespace 50 | * 51 | * @var string 52 | */ 53 | public $ns; 54 | 55 | /** 56 | * Attributes 57 | * 58 | * @var array 59 | */ 60 | public $attrs = array(); 61 | 62 | /** 63 | * Subs? 64 | * 65 | * @var array 66 | */ 67 | public $subs = array(); 68 | 69 | /** 70 | * Node data 71 | * 72 | * @var string 73 | */ 74 | public $data = ''; 75 | 76 | /** 77 | * Constructor 78 | * 79 | * @param string $name 80 | * @param string $ns 81 | * @param array $attrs 82 | * @param string $data 83 | */ 84 | public function __construct($name, $ns = '', $attrs = array(), $data = '') { 85 | $this->name = strtolower($name); 86 | $this->ns = $ns; 87 | if(is_array($attrs) && count($attrs)) { 88 | foreach($attrs as $key => $value) { 89 | $this->attrs[strtolower($key)] = $value; 90 | } 91 | } 92 | $this->data = $data; 93 | } 94 | 95 | /** 96 | * Dump this XML Object to output. 97 | * 98 | * @param integer $depth 99 | */ 100 | public function printObj($depth = 0) { 101 | print str_repeat("\t", $depth) . $this->name . " " . $this->ns . ' ' . $this->data; 102 | print "\n"; 103 | foreach($this->subs as $sub) { 104 | $sub->printObj($depth + 1); 105 | } 106 | } 107 | 108 | /** 109 | * Return this XML Object in xml notation 110 | * 111 | * @param string $str 112 | */ 113 | public function toString($str = '') { 114 | $str .= "<{$this->name} xmlns='{$this->ns}' "; 115 | foreach($this->attrs as $key => $value) { 116 | if($key != 'xmlns') { 117 | $value = htmlspecialchars($value); 118 | $str .= "$key='$value' "; 119 | } 120 | } 121 | $str .= ">"; 122 | foreach($this->subs as $sub) { 123 | $str .= $sub->toString(); 124 | } 125 | $body = htmlspecialchars($this->data); 126 | $str .= "$bodyname}>"; 127 | return $str; 128 | } 129 | 130 | /** 131 | * Has this XML Object the given sub? 132 | * 133 | * @param string $name 134 | * @return boolean 135 | */ 136 | public function hasSub($name, $ns = null) { 137 | foreach($this->subs as $sub) { 138 | if(($name == "*" or $sub->name == $name) and ($ns == null or $sub->ns == $ns)) return true; 139 | } 140 | return false; 141 | } 142 | 143 | /** 144 | * Return a sub 145 | * 146 | * @param string $name 147 | * @param string $attrs 148 | * @param string $ns 149 | */ 150 | public function sub($name, $attrs = null, $ns = null) { 151 | #TODO attrs is ignored 152 | foreach($this->subs as $sub) { 153 | if($sub->name == $name and ($ns == null or $sub->ns == $ns)) { 154 | return $sub; 155 | } 156 | } 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /app/include/external/XMPPHP/XMLStream.php: -------------------------------------------------------------------------------- 1 | 24 | * @author Stephan Wentz 25 | * @author Michael Garvin 26 | * @copyright 2008 Nathanael C. Fritz 27 | */ 28 | 29 | /** XMPPHP_Exception */ 30 | require_once dirname(__FILE__) . '/Exception.php'; 31 | 32 | /** XMPPHP_XMLObj */ 33 | require_once dirname(__FILE__) . '/XMLObj.php'; 34 | 35 | /** XMPPHP_Log */ 36 | require_once dirname(__FILE__) . '/Log.php'; 37 | 38 | /** 39 | * XMPPHP XML Stream 40 | * 41 | * @category xmpphp 42 | * @package XMPPHP 43 | * @author Nathanael C. Fritz 44 | * @author Stephan Wentz 45 | * @author Michael Garvin 46 | * @copyright 2008 Nathanael C. Fritz 47 | * @version $Id$ 48 | */ 49 | class XMPPHP_XMLStream { 50 | /** 51 | * @var resource 52 | */ 53 | protected $socket; 54 | /** 55 | * @var resource 56 | */ 57 | protected $parser; 58 | /** 59 | * @var string 60 | */ 61 | protected $buffer; 62 | /** 63 | * @var integer 64 | */ 65 | protected $xml_depth = 0; 66 | /** 67 | * @var string 68 | */ 69 | protected $host; 70 | /** 71 | * @var integer 72 | */ 73 | protected $port; 74 | /** 75 | * @var string 76 | */ 77 | protected $stream_start = ''; 78 | /** 79 | * @var string 80 | */ 81 | protected $stream_end = ''; 82 | /** 83 | * @var boolean 84 | */ 85 | protected $disconnected = false; 86 | /** 87 | * @var boolean 88 | */ 89 | protected $sent_disconnect = false; 90 | /** 91 | * @var array 92 | */ 93 | protected $ns_map = array(); 94 | /** 95 | * @var array 96 | */ 97 | protected $current_ns = array(); 98 | /** 99 | * @var array 100 | */ 101 | protected $xmlobj = null; 102 | /** 103 | * @var array 104 | */ 105 | protected $nshandlers = array(); 106 | /** 107 | * @var array 108 | */ 109 | protected $xpathhandlers = array(); 110 | /** 111 | * @var array 112 | */ 113 | protected $idhandlers = array(); 114 | /** 115 | * @var array 116 | */ 117 | protected $eventhandlers = array(); 118 | /** 119 | * @var integer 120 | */ 121 | protected $lastid = 0; 122 | /** 123 | * @var string 124 | */ 125 | protected $default_ns; 126 | /** 127 | * @var string 128 | */ 129 | protected $until = ''; 130 | /** 131 | * @var string 132 | */ 133 | protected $until_count = ''; 134 | /** 135 | * @var array 136 | */ 137 | protected $until_happened = false; 138 | /** 139 | * @var array 140 | */ 141 | protected $until_payload = array(); 142 | /** 143 | * @var XMPPHP_Log 144 | */ 145 | protected $log; 146 | /** 147 | * @var boolean 148 | */ 149 | protected $reconnect = true; 150 | /** 151 | * @var boolean 152 | */ 153 | protected $been_reset = false; 154 | /** 155 | * @var boolean 156 | */ 157 | protected $is_server; 158 | /** 159 | * @var float 160 | */ 161 | protected $last_send = 0; 162 | /** 163 | * @var boolean 164 | */ 165 | protected $use_ssl = false; 166 | /** 167 | * @var integer 168 | */ 169 | protected $reconnectTimeout = 30; 170 | 171 | /** 172 | * Constructor 173 | * 174 | * @param string $host 175 | * @param string $port 176 | * @param boolean $printlog 177 | * @param string $loglevel 178 | * @param boolean $is_server 179 | */ 180 | public function __construct($host = null, $port = null, $printlog = false, $loglevel = null, $is_server = false) { 181 | $this->reconnect = !$is_server; 182 | $this->is_server = $is_server; 183 | $this->host = $host; 184 | $this->port = $port; 185 | $this->setupParser(); 186 | $this->log = new XMPPHP_Log($printlog, $loglevel); 187 | } 188 | 189 | /** 190 | * Destructor 191 | * Cleanup connection 192 | */ 193 | public function __destruct() { 194 | if(!$this->disconnected && $this->socket) { 195 | $this->disconnect(); 196 | } 197 | } 198 | 199 | /** 200 | * Return the log instance 201 | * 202 | * @return XMPPHP_Log 203 | */ 204 | public function getLog() { 205 | return $this->log; 206 | } 207 | 208 | /** 209 | * Get next ID 210 | * 211 | * @return integer 212 | */ 213 | public function getId() { 214 | $this->lastid++; 215 | return $this->lastid; 216 | } 217 | 218 | /** 219 | * Set SSL 220 | * 221 | * @return integer 222 | */ 223 | public function useSSL($use=true) { 224 | $this->use_ssl = $use; 225 | } 226 | 227 | /** 228 | * Add ID Handler 229 | * 230 | * @param integer $id 231 | * @param string $pointer 232 | * @param string $obj 233 | */ 234 | public function addIdHandler($id, $pointer, $obj = null) { 235 | $this->idhandlers[$id] = array($pointer, $obj); 236 | } 237 | 238 | /** 239 | * Add Handler 240 | * 241 | * @param string $name 242 | * @param string $ns 243 | * @param string $pointer 244 | * @param string $obj 245 | * @param integer $depth 246 | */ 247 | public function addHandler($name, $ns, $pointer, $obj = null, $depth = 1) { 248 | #TODO deprication warning 249 | $this->nshandlers[] = array($name,$ns,$pointer,$obj, $depth); 250 | } 251 | 252 | /** 253 | * Add XPath Handler 254 | * 255 | * @param string $xpath 256 | * @param string $pointer 257 | * @param 258 | */ 259 | public function addXPathHandler($xpath, $pointer, $obj = null) { 260 | if (preg_match_all("/\(?{[^\}]+}\)?(\/?)[^\/]+/", $xpath, $regs)) { 261 | $ns_tags = $regs[0]; 262 | } else { 263 | $ns_tags = array($xpath); 264 | } 265 | foreach($ns_tags as $ns_tag) { 266 | list($l, $r) = split("}", $ns_tag); 267 | if ($r != null) { 268 | $xpart = array(substr($l, 1), $r); 269 | } else { 270 | $xpart = array(null, $l); 271 | } 272 | $xpath_array[] = $xpart; 273 | } 274 | $this->xpathhandlers[] = array($xpath_array, $pointer, $obj); 275 | } 276 | 277 | /** 278 | * Add Event Handler 279 | * 280 | * @param integer $id 281 | * @param string $pointer 282 | * @param string $obj 283 | */ 284 | public function addEventHandler($name, $pointer, $obj) { 285 | $this->eventhandlers[] = array($name, $pointer, $obj); 286 | } 287 | 288 | /** 289 | * Connect to XMPP Host 290 | * 291 | * @param integer $timeout 292 | * @param boolean $persistent 293 | * @param boolean $sendinit 294 | */ 295 | public function connect($timeout = 30, $persistent = false, $sendinit = true) { 296 | $this->sent_disconnect = false; 297 | $starttime = time(); 298 | 299 | do { 300 | $this->disconnected = false; 301 | $this->sent_disconnect = false; 302 | if($persistent) { 303 | $conflag = STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT; 304 | } else { 305 | $conflag = STREAM_CLIENT_CONNECT; 306 | } 307 | $conntype = 'tcp'; 308 | if($this->use_ssl) $conntype = 'ssl'; 309 | $this->log->log("Connecting to $conntype://{$this->host}:{$this->port}"); 310 | try { 311 | $this->socket = @stream_socket_client("$conntype://{$this->host}:{$this->port}", $errno, $errstr, $timeout, $conflag); 312 | } catch (Exception $e) { 313 | throw new XMPPHP_Exception($e->getMessage()); 314 | } 315 | if(!$this->socket) { 316 | $this->log->log("Could not connect.", XMPPHP_Log::LEVEL_ERROR); 317 | $this->disconnected = true; 318 | # Take it easy for a few seconds 319 | sleep(min($timeout, 5)); 320 | } 321 | } while (!$this->socket && (time() - $starttime) < $timeout); 322 | 323 | if ($this->socket) { 324 | stream_set_blocking($this->socket, 1); 325 | if($sendinit) $this->send($this->stream_start); 326 | } else { 327 | throw new XMPPHP_Exception("Could not connect before timeout."); 328 | } 329 | } 330 | 331 | /** 332 | * Reconnect XMPP Host 333 | */ 334 | public function doReconnect() { 335 | if(!$this->is_server) { 336 | $this->log->log("Reconnecting ($this->reconnectTimeout)...", XMPPHP_Log::LEVEL_WARNING); 337 | $this->connect($this->reconnectTimeout, false, false); 338 | $this->reset(); 339 | $this->event('reconnect'); 340 | } 341 | } 342 | 343 | public function setReconnectTimeout($timeout) { 344 | $this->reconnectTimeout = $timeout; 345 | } 346 | 347 | /** 348 | * Disconnect from XMPP Host 349 | */ 350 | public function disconnect() { 351 | $this->log->log("Disconnecting...", XMPPHP_Log::LEVEL_VERBOSE); 352 | if(false == (bool) $this->socket) { 353 | return; 354 | } 355 | $this->reconnect = false; 356 | $this->send($this->stream_end); 357 | $this->sent_disconnect = true; 358 | $this->processUntil('end_stream', 5); 359 | $this->disconnected = true; 360 | } 361 | 362 | /** 363 | * Are we are disconnected? 364 | * 365 | * @return boolean 366 | */ 367 | public function isDisconnected() { 368 | return $this->disconnected; 369 | } 370 | 371 | /** 372 | * Core reading tool 373 | * 0 -> only read if data is immediately ready 374 | * NULL -> wait forever and ever 375 | * integer -> process for this amount of time 376 | */ 377 | 378 | private function __process($maximum=5) { 379 | 380 | $remaining = $maximum; 381 | 382 | do { 383 | $starttime = (microtime(true) * 1000000); 384 | $read = array($this->socket); 385 | $write = array(); 386 | $except = array(); 387 | if (is_null($maximum)) { 388 | $secs = NULL; 389 | $usecs = NULL; 390 | } else if ($maximum == 0) { 391 | $secs = 0; 392 | $usecs = 0; 393 | } else { 394 | $usecs = $remaining % 1000000; 395 | $secs = floor(($remaining - $usecs) / 1000000); 396 | } 397 | $updated = @stream_select($read, $write, $except, $secs, $usecs); 398 | if ($updated === false) { 399 | $this->log->log("Error on stream_select()", XMPPHP_Log::LEVEL_VERBOSE); 400 | if ($this->reconnect) { 401 | $this->doReconnect(); 402 | } else { 403 | fclose($this->socket); 404 | $this->socket = NULL; 405 | return false; 406 | } 407 | } else if ($updated > 0) { 408 | # XXX: Is this big enough? 409 | $buff = @fread($this->socket, 4096); 410 | if(!$buff) { 411 | if($this->reconnect) { 412 | $this->doReconnect(); 413 | } else { 414 | fclose($this->socket); 415 | $this->socket = NULL; 416 | return false; 417 | } 418 | } 419 | $this->log->log("RECV: $buff", XMPPHP_Log::LEVEL_VERBOSE); 420 | xml_parse($this->parser, $buff, false); 421 | } else { 422 | # $updated == 0 means no changes during timeout. 423 | } 424 | $endtime = (microtime(true)*1000000); 425 | $time_past = $endtime - $starttime; 426 | $remaining = $remaining - $time_past; 427 | } while (is_null($maximum) || $remaining > 0); 428 | return true; 429 | } 430 | 431 | /** 432 | * Process 433 | * 434 | * @return string 435 | */ 436 | public function process() { 437 | $this->__process(NULL); 438 | } 439 | 440 | /** 441 | * Process until a timeout occurs 442 | * 443 | * @param integer $timeout 444 | * @return string 445 | */ 446 | public function processTime($timeout=NULL) { 447 | if (is_null($timeout)) { 448 | return $this->__process(NULL); 449 | } else { 450 | return $this->__process($timeout * 1000000); 451 | } 452 | } 453 | 454 | /** 455 | * Process until a specified event or a timeout occurs 456 | * 457 | * @param string|array $event 458 | * @param integer $timeout 459 | * @return string 460 | */ 461 | public function processUntil($event, $timeout=-1) { 462 | $start = time(); 463 | if(!is_array($event)) $event = array($event); 464 | $this->until[] = $event; 465 | end($this->until); 466 | $event_key = key($this->until); 467 | reset($this->until); 468 | $this->until_count[$event_key] = 0; 469 | $updated = ''; 470 | while(!$this->disconnected and $this->until_count[$event_key] < 1 and (time() - $start < $timeout or $timeout == -1)) { 471 | $this->__process(); 472 | } 473 | if(array_key_exists($event_key, $this->until_payload)) { 474 | $payload = $this->until_payload[$event_key]; 475 | } else { 476 | $payload = array(); 477 | } 478 | 479 | unset($this->until_payload[$event_key]); 480 | unset($this->until_count[$event_key]); 481 | unset($this->until[$event_key]); 482 | 483 | return $payload; 484 | } 485 | 486 | /** 487 | * Obsolete? 488 | */ 489 | public function Xapply_socket($socket) { 490 | $this->socket = $socket; 491 | } 492 | 493 | /** 494 | * XML start callback 495 | * 496 | * @see xml_set_element_handler 497 | * 498 | * @param resource $parser 499 | * @param string $name 500 | */ 501 | public function startXML($parser, $name, $attr) { 502 | if($this->been_reset) { 503 | $this->been_reset = false; 504 | $this->xml_depth = 0; 505 | } 506 | $this->xml_depth++; 507 | if(array_key_exists('XMLNS', $attr)) { 508 | $this->current_ns[$this->xml_depth] = $attr['XMLNS']; 509 | } else { 510 | $this->current_ns[$this->xml_depth] = $this->current_ns[$this->xml_depth - 1]; 511 | if(!$this->current_ns[$this->xml_depth]) $this->current_ns[$this->xml_depth] = $this->default_ns; 512 | } 513 | $ns = $this->current_ns[$this->xml_depth]; 514 | foreach($attr as $key => $value) { 515 | if(strstr($key, ":")) { 516 | $key = explode(':', $key); 517 | $key = $key[1]; 518 | $this->ns_map[$key] = $value; 519 | } 520 | } 521 | if(!strstr($name, ":") === false) 522 | { 523 | $name = explode(':', $name); 524 | $ns = $this->ns_map[$name[0]]; 525 | $name = $name[1]; 526 | } 527 | $obj = new XMPPHP_XMLObj($name, $ns, $attr); 528 | if($this->xml_depth > 1) { 529 | $this->xmlobj[$this->xml_depth - 1]->subs[] = $obj; 530 | } 531 | $this->xmlobj[$this->xml_depth] = $obj; 532 | } 533 | 534 | /** 535 | * XML end callback 536 | * 537 | * @see xml_set_element_handler 538 | * 539 | * @param resource $parser 540 | * @param string $name 541 | */ 542 | public function endXML($parser, $name) { 543 | #$this->log->log("Ending $name", XMPPHP_Log::LEVEL_DEBUG); 544 | #print "$name\n"; 545 | if($this->been_reset) { 546 | $this->been_reset = false; 547 | $this->xml_depth = 0; 548 | } 549 | $this->xml_depth--; 550 | if($this->xml_depth == 1) { 551 | #clean-up old objects 552 | #$found = false; #FIXME This didn't appear to be in use --Gar 553 | foreach($this->xpathhandlers as $handler) { 554 | if (is_array($this->xmlobj) && array_key_exists(2, $this->xmlobj)) { 555 | $searchxml = $this->xmlobj[2]; 556 | $nstag = array_shift($handler[0]); 557 | if (($nstag[0] == null or $searchxml->ns == $nstag[0]) and ($nstag[1] == "*" or $nstag[1] == $searchxml->name)) { 558 | foreach($handler[0] as $nstag) { 559 | if ($searchxml !== null and $searchxml->hasSub($nstag[1], $ns=$nstag[0])) { 560 | $searchxml = $searchxml->sub($nstag[1], $ns=$nstag[0]); 561 | } else { 562 | $searchxml = null; 563 | break; 564 | } 565 | } 566 | if ($searchxml !== null) { 567 | if($handler[2] === null) $handler[2] = $this; 568 | $this->log->log("Calling {$handler[1]}", XMPPHP_Log::LEVEL_DEBUG); 569 | $handler[2]->$handler[1]($this->xmlobj[2]); 570 | } 571 | } 572 | } 573 | } 574 | foreach($this->nshandlers as $handler) { 575 | if($handler[4] != 1 and array_key_exists(2, $this->xmlobj) and $this->xmlobj[2]->hasSub($handler[0])) { 576 | $searchxml = $this->xmlobj[2]->sub($handler[0]); 577 | } elseif(is_array($this->xmlobj) and array_key_exists(2, $this->xmlobj)) { 578 | $searchxml = $this->xmlobj[2]; 579 | } 580 | if($searchxml !== null and $searchxml->name == $handler[0] and ($searchxml->ns == $handler[1] or (!$handler[1] and $searchxml->ns == $this->default_ns))) { 581 | if($handler[3] === null) $handler[3] = $this; 582 | $this->log->log("Calling {$handler[2]}", XMPPHP_Log::LEVEL_DEBUG); 583 | $handler[3]->$handler[2]($this->xmlobj[2]); 584 | } 585 | } 586 | foreach($this->idhandlers as $id => $handler) { 587 | if(array_key_exists('id', $this->xmlobj[2]->attrs) and $this->xmlobj[2]->attrs['id'] == $id) { 588 | if($handler[1] === null) $handler[1] = $this; 589 | $handler[1]->$handler[0]($this->xmlobj[2]); 590 | #id handlers are only used once 591 | unset($this->idhandlers[$id]); 592 | break; 593 | } 594 | } 595 | if(is_array($this->xmlobj)) { 596 | $this->xmlobj = array_slice($this->xmlobj, 0, 1); 597 | if(isset($this->xmlobj[0]) && $this->xmlobj[0] instanceof XMPPHP_XMLObj) { 598 | $this->xmlobj[0]->subs = null; 599 | } 600 | } 601 | unset($this->xmlobj[2]); 602 | } 603 | if($this->xml_depth == 0 and !$this->been_reset) { 604 | if(!$this->disconnected) { 605 | if(!$this->sent_disconnect) { 606 | $this->send($this->stream_end); 607 | } 608 | $this->disconnected = true; 609 | $this->sent_disconnect = true; 610 | fclose($this->socket); 611 | if($this->reconnect) { 612 | $this->doReconnect(); 613 | } 614 | } 615 | $this->event('end_stream'); 616 | } 617 | } 618 | 619 | /** 620 | * XML character callback 621 | * @see xml_set_character_data_handler 622 | * 623 | * @param resource $parser 624 | * @param string $data 625 | */ 626 | public function charXML($parser, $data) { 627 | if(array_key_exists($this->xml_depth, $this->xmlobj)) { 628 | $this->xmlobj[$this->xml_depth]->data .= $data; 629 | } 630 | } 631 | 632 | /** 633 | * Event? 634 | * 635 | * @param string $name 636 | * @param string $payload 637 | */ 638 | public function event($name, $payload = null) { 639 | $this->log->log("EVENT: $name", XMPPHP_Log::LEVEL_DEBUG); 640 | foreach($this->eventhandlers as $handler) { 641 | if($name == $handler[0]) { 642 | if($handler[2] === null) { 643 | $handler[2] = $this; 644 | } 645 | $handler[2]->$handler[1]($payload); 646 | } 647 | } 648 | foreach($this->until as $key => $until) { 649 | if(is_array($until)) { 650 | if(in_array($name, $until)) { 651 | $this->until_payload[$key][] = array($name, $payload); 652 | if(!isset($this->until_count[$key])) { 653 | $this->until_count[$key] = 0; 654 | } 655 | $this->until_count[$key] += 1; 656 | #$this->until[$key] = false; 657 | } 658 | } 659 | } 660 | } 661 | 662 | /** 663 | * Read from socket 664 | */ 665 | public function read() { 666 | $buff = @fread($this->socket, 1024); 667 | if(!$buff) { 668 | if($this->reconnect) { 669 | $this->doReconnect(); 670 | } else { 671 | fclose($this->socket); 672 | return false; 673 | } 674 | } 675 | $this->log->log("RECV: $buff", XMPPHP_Log::LEVEL_VERBOSE); 676 | xml_parse($this->parser, $buff, false); 677 | } 678 | 679 | /** 680 | * Send to socket 681 | * 682 | * @param string $msg 683 | */ 684 | public function send($msg, $timeout=NULL) { 685 | 686 | if (is_null($timeout)) { 687 | $secs = NULL; 688 | $usecs = NULL; 689 | } else if ($timeout == 0) { 690 | $secs = 0; 691 | $usecs = 0; 692 | } else { 693 | $maximum = $timeout * 1000000; 694 | $usecs = $maximum % 1000000; 695 | $secs = floor(($maximum - $usecs) / 1000000); 696 | } 697 | 698 | $read = array(); 699 | $write = array($this->socket); 700 | $except = array(); 701 | 702 | $select = @stream_select($read, $write, $except, $secs, $usecs); 703 | 704 | if($select === False) { 705 | $this->log->log("ERROR sending message; reconnecting."); 706 | $this->doReconnect(); 707 | # TODO: retry send here 708 | return false; 709 | } elseif ($select > 0) { 710 | $this->log->log("Socket is ready; send it.", XMPPHP_Log::LEVEL_VERBOSE); 711 | } else { 712 | $this->log->log("Socket is not ready; break.", XMPPHP_Log::LEVEL_ERROR); 713 | return false; 714 | } 715 | 716 | $sentbytes = @fwrite($this->socket, $msg); 717 | $this->log->log("SENT: " . mb_substr($msg, 0, $sentbytes, '8bit'), XMPPHP_Log::LEVEL_VERBOSE); 718 | if($sentbytes === FALSE) { 719 | $this->log->log("ERROR sending message; reconnecting.", XMPPHP_Log::LEVEL_ERROR); 720 | $this->doReconnect(); 721 | return false; 722 | } 723 | $this->log->log("Successfully sent $sentbytes bytes.", XMPPHP_Log::LEVEL_VERBOSE); 724 | return $sentbytes; 725 | } 726 | 727 | public function time() { 728 | list($usec, $sec) = explode(" ", microtime()); 729 | return (float)$sec + (float)$usec; 730 | } 731 | 732 | /** 733 | * Reset connection 734 | */ 735 | public function reset() { 736 | $this->xml_depth = 0; 737 | unset($this->xmlobj); 738 | $this->xmlobj = array(); 739 | $this->setupParser(); 740 | if(!$this->is_server) { 741 | $this->send($this->stream_start); 742 | } 743 | $this->been_reset = true; 744 | } 745 | 746 | /** 747 | * Setup the XML parser 748 | */ 749 | public function setupParser() { 750 | $this->parser = xml_parser_create('UTF-8'); 751 | xml_parser_set_option($this->parser, XML_OPTION_SKIP_WHITE, 1); 752 | xml_parser_set_option($this->parser, XML_OPTION_TARGET_ENCODING, 'UTF-8'); 753 | xml_set_object($this->parser, $this); 754 | xml_set_element_handler($this->parser, 'startXML', 'endXML'); 755 | xml_set_character_data_handler($this->parser, 'charXML'); 756 | } 757 | 758 | public function readyToProcess() { 759 | $read = array($this->socket); 760 | $write = array(); 761 | $except = array(); 762 | $updated = @stream_select($read, $write, $except, 0); 763 | return (($updated !== false) && ($updated > 0)); 764 | } 765 | } 766 | -------------------------------------------------------------------------------- /app/include/external/XMPPHP/XMPP.php: -------------------------------------------------------------------------------- 1 | 24 | * @author Stephan Wentz 25 | * @author Michael Garvin 26 | * @copyright 2008 Nathanael C. Fritz 27 | */ 28 | 29 | /** XMPPHP_XMLStream */ 30 | require_once dirname(__FILE__) . "/XMLStream.php"; 31 | require_once dirname(__FILE__) . "/Roster.php"; 32 | 33 | /** 34 | * XMPPHP Main Class 35 | * 36 | * @category xmpphp 37 | * @package XMPPHP 38 | * @author Nathanael C. Fritz 39 | * @author Stephan Wentz 40 | * @author Michael Garvin 41 | * @copyright 2008 Nathanael C. Fritz 42 | * @version $Id$ 43 | */ 44 | class XMPPHP_XMPP extends XMPPHP_XMLStream { 45 | /** 46 | * @var string 47 | */ 48 | public $server; 49 | 50 | /** 51 | * @var string 52 | */ 53 | public $user; 54 | 55 | /** 56 | * @var string 57 | */ 58 | protected $password; 59 | 60 | /** 61 | * @var string 62 | */ 63 | protected $resource; 64 | 65 | /** 66 | * @var string 67 | */ 68 | protected $fulljid; 69 | 70 | /** 71 | * @var string 72 | */ 73 | protected $basejid; 74 | 75 | /** 76 | * @var boolean 77 | */ 78 | protected $authed = false; 79 | protected $session_started = false; 80 | 81 | /** 82 | * @var boolean 83 | */ 84 | protected $auto_subscribe = false; 85 | 86 | /** 87 | * @var boolean 88 | */ 89 | protected $use_encryption = true; 90 | 91 | /** 92 | * @var boolean 93 | */ 94 | public $track_presence = true; 95 | 96 | /** 97 | * @var object 98 | */ 99 | public $roster; 100 | 101 | /** 102 | * Constructor 103 | * 104 | * @param string $host 105 | * @param integer $port 106 | * @param string $user 107 | * @param string $password 108 | * @param string $resource 109 | * @param string $server 110 | * @param boolean $printlog 111 | * @param string $loglevel 112 | */ 113 | public function __construct($host, $port, $user, $password, $resource, $server = null, $printlog = false, $loglevel = null) { 114 | parent::__construct($host, $port, $printlog, $loglevel); 115 | 116 | $this->user = $user; 117 | $this->password = $password; 118 | $this->resource = $resource; 119 | if(!$server) $server = $host; 120 | $this->basejid = $this->user . '@' . $this->host; 121 | 122 | $this->roster = new Roster(); 123 | $this->track_presence = true; 124 | 125 | $this->stream_start = ''; 126 | $this->stream_end = ''; 127 | $this->default_ns = 'jabber:client'; 128 | 129 | $this->addXPathHandler('{http://etherx.jabber.org/streams}features', 'features_handler'); 130 | $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}success', 'sasl_success_handler'); 131 | $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-sasl}failure', 'sasl_failure_handler'); 132 | $this->addXPathHandler('{urn:ietf:params:xml:ns:xmpp-tls}proceed', 'tls_proceed_handler'); 133 | $this->addXPathHandler('{jabber:client}message', 'message_handler'); 134 | $this->addXPathHandler('{jabber:client}presence', 'presence_handler'); 135 | $this->addXPathHandler('iq/{jabber:iq:roster}query', 'roster_iq_handler'); 136 | } 137 | 138 | /** 139 | * Turn encryption on/ff 140 | * 141 | * @param boolean $useEncryption 142 | */ 143 | public function useEncryption($useEncryption = true) { 144 | $this->use_encryption = $useEncryption; 145 | } 146 | 147 | /** 148 | * Turn on auto-authorization of subscription requests. 149 | * 150 | * @param boolean $autoSubscribe 151 | */ 152 | public function autoSubscribe($autoSubscribe = true) { 153 | $this->auto_subscribe = $autoSubscribe; 154 | } 155 | 156 | /** 157 | * Send XMPP Message 158 | * 159 | * @param string $to 160 | * @param string $body 161 | * @param string $type 162 | * @param string $subject 163 | */ 164 | public function message($to, $body, $type = 'chat', $subject = null, $payload = null) { 165 | if(is_null($type)) 166 | { 167 | $type = 'chat'; 168 | } 169 | 170 | $to = htmlspecialchars($to); 171 | $body = htmlspecialchars($body); 172 | $subject = htmlspecialchars($subject); 173 | 174 | $out = "fulljid}\" to=\"$to\" type='$type'>"; 175 | if($subject) $out .= "$subject"; 176 | $out .= "$body"; 177 | if($payload) $out .= $payload; 178 | $out .= ""; 179 | 180 | $this->send($out); 181 | } 182 | 183 | /** 184 | * Set Presence 185 | * 186 | * @param string $status 187 | * @param string $show 188 | * @param string $to 189 | */ 190 | public function presence($status = null, $show = 'available', $to = null, $type='available', $priority=0) { 191 | if($type == 'available') $type = ''; 192 | $to = htmlspecialchars($to); 193 | $status = htmlspecialchars($status); 194 | if($show == 'unavailable') $type = 'unavailable'; 195 | 196 | $out = "send($out); 210 | } 211 | /** 212 | * Send Auth request 213 | * 214 | * @param string $jid 215 | */ 216 | public function subscribe($jid) { 217 | $this->send(""); 218 | #$this->send(""); 219 | } 220 | 221 | /** 222 | * Message handler 223 | * 224 | * @param string $xml 225 | */ 226 | public function message_handler($xml) { 227 | if(isset($xml->attrs['type'])) { 228 | $payload['type'] = $xml->attrs['type']; 229 | } else { 230 | $payload['type'] = 'chat'; 231 | } 232 | $payload['xml'] = $xml; 233 | $payload['from'] = $xml->attrs['from']; 234 | if (isset($xml->sub('body')->data)) 235 | { 236 | $payload['body'] = $xml->sub('body')->data; 237 | $this->log->log("Message: {$xml->sub('body')->data}", XMPPHP_Log::LEVEL_DEBUG); 238 | } 239 | else 240 | { 241 | $payload['body'] = ''; 242 | } 243 | $this->event('message', $payload); 244 | } 245 | 246 | /** 247 | * Presence handler 248 | * 249 | * @param string $xml 250 | */ 251 | public function presence_handler($xml) { 252 | $payload['type'] = (isset($xml->attrs['type'])) ? $xml->attrs['type'] : 'available'; 253 | $payload['show'] = (isset($xml->sub('show')->data)) ? $xml->sub('show')->data : $payload['type']; 254 | $payload['from'] = $xml->attrs['from']; 255 | $payload['status'] = (isset($xml->sub('status')->data)) ? $xml->sub('status')->data : ''; 256 | $payload['priority'] = (isset($xml->sub('priority')->data)) ? intval($xml->sub('priority')->data) : 0; 257 | $payload['xml'] = $xml; 258 | if($this->track_presence) { 259 | $this->roster->setPresence($payload['from'], $payload['priority'], $payload['show'], $payload['status']); 260 | } 261 | $this->log->log("Presence: {$payload['from']} [{$payload['show']}] {$payload['status']}", XMPPHP_Log::LEVEL_DEBUG); 262 | if(array_key_exists('type', $xml->attrs) and $xml->attrs['type'] == 'subscribe') { 263 | if($this->auto_subscribe) { 264 | $this->send(""); 265 | $this->send(""); 266 | } 267 | $this->event('subscription_requested', $payload); 268 | } elseif(array_key_exists('type', $xml->attrs) and $xml->attrs['type'] == 'subscribed') { 269 | $this->event('subscription_accepted', $payload); 270 | } else { 271 | $this->event('presence', $payload); 272 | } 273 | } 274 | 275 | /** 276 | * Features handler 277 | * 278 | * @param string $xml 279 | */ 280 | protected function features_handler($xml) { 281 | if($xml->hasSub('starttls') and $this->use_encryption) { 282 | $this->send(""); 283 | } elseif($xml->hasSub('bind') and $this->authed) { 284 | $id = $this->getId(); 285 | $this->addIdHandler($id, 'resource_bind_handler'); 286 | $this->send("{$this->resource}"); 287 | } else { 288 | $this->log->log("Attempting Auth..."); 289 | if ($this->password) { 290 | $this->send("" . base64_encode("\x00" . $this->user . "\x00" . $this->password) . ""); 291 | } else { 292 | $this->send(""); 293 | } 294 | } 295 | } 296 | 297 | /** 298 | * SASL success handler 299 | * 300 | * @param string $xml 301 | */ 302 | protected function sasl_success_handler($xml) { 303 | $this->log->log("Auth success!"); 304 | $this->authed = true; 305 | $this->reset(); 306 | } 307 | 308 | /** 309 | * SASL feature handler 310 | * 311 | * @param string $xml 312 | */ 313 | protected function sasl_failure_handler($xml) { 314 | $this->log->log("Auth failed!", XMPPHP_Log::LEVEL_ERROR); 315 | $this->disconnect(); 316 | 317 | throw new XMPPHP_Exception('Auth failed!'); 318 | } 319 | 320 | /** 321 | * Resource bind handler 322 | * 323 | * @param string $xml 324 | */ 325 | protected function resource_bind_handler($xml) { 326 | if($xml->attrs['type'] == 'result') { 327 | $this->log->log("Bound to " . $xml->sub('bind')->sub('jid')->data); 328 | $this->fulljid = $xml->sub('bind')->sub('jid')->data; 329 | $jidarray = explode('/',$this->fulljid); 330 | $this->jid = $jidarray[0]; 331 | } 332 | $id = $this->getId(); 333 | $this->addIdHandler($id, 'session_start_handler'); 334 | $this->send(""); 335 | } 336 | 337 | /** 338 | * Retrieves the roster 339 | * 340 | */ 341 | public function getRoster() { 342 | $id = $this->getID(); 343 | $this->send(""); 344 | } 345 | 346 | /** 347 | * Roster iq handler 348 | * Gets all packets matching XPath "iq/{jabber:iq:roster}query' 349 | * 350 | * @param string $xml 351 | */ 352 | protected function roster_iq_handler($xml) { 353 | $status = "result"; 354 | $xmlroster = $xml->sub('query'); 355 | foreach($xmlroster->subs as $item) { 356 | $groups = array(); 357 | if ($item->name == 'item') { 358 | $jid = $item->attrs['jid']; //REQUIRED 359 | $name = $item->attrs['name']; //MAY 360 | $subscription = $item->attrs['subscription']; 361 | foreach($item->subs as $subitem) { 362 | if ($subitem->name == 'group') { 363 | $groups[] = $subitem->data; 364 | } 365 | } 366 | $contacts[] = array($jid, $subscription, $name, $groups); //Store for action if no errors happen 367 | } else { 368 | $status = "error"; 369 | } 370 | } 371 | if ($status == "result") { //No errors, add contacts 372 | foreach($contacts as $contact) { 373 | $this->roster->addContact($contact[0], $contact[1], $contact[2], $contact[3]); 374 | } 375 | } 376 | if ($xml->attrs['type'] == 'set') { 377 | $this->send("attrs['id']}\" to=\"{$xml->attrs['from']}\" />"); 378 | } 379 | } 380 | 381 | /** 382 | * Session start handler 383 | * 384 | * @param string $xml 385 | */ 386 | protected function session_start_handler($xml) { 387 | $this->log->log("Session started"); 388 | $this->session_started = true; 389 | $this->event('session_start'); 390 | } 391 | 392 | /** 393 | * TLS proceed handler 394 | * 395 | * @param string $xml 396 | */ 397 | protected function tls_proceed_handler($xml) { 398 | $this->log->log("Starting TLS encryption"); 399 | stream_socket_enable_crypto($this->socket, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT); 400 | $this->reset(); 401 | } 402 | 403 | /** 404 | * Retrieves the vcard 405 | * 406 | */ 407 | public function getVCard($jid = Null) { 408 | $id = $this->getID(); 409 | $this->addIdHandler($id, 'vcard_get_handler'); 410 | if($jid) { 411 | $this->send(""); 412 | } else { 413 | $this->send(""); 414 | } 415 | } 416 | 417 | /** 418 | * VCard retrieval handler 419 | * 420 | * @param XML Object $xml 421 | */ 422 | protected function vcard_get_handler($xml) { 423 | $vcard_array = array(); 424 | $vcard = $xml->sub('vcard'); 425 | // go through all of the sub elements and add them to the vcard array 426 | foreach ($vcard->subs as $sub) { 427 | if ($sub->subs) { 428 | $vcard_array[$sub->name] = array(); 429 | foreach ($sub->subs as $sub_child) { 430 | $vcard_array[$sub->name][$sub_child->name] = $sub_child->data; 431 | } 432 | } else { 433 | $vcard_array[$sub->name] = $sub->data; 434 | } 435 | } 436 | $vcard_array['from'] = $xml->attrs['from']; 437 | $this->event('vcard', $vcard_array); 438 | } 439 | } 440 | -------------------------------------------------------------------------------- /app/include/external/XMPPHP/XMPP_Old.php: -------------------------------------------------------------------------------- 1 | 24 | * @author Stephan Wentz 25 | * @author Michael Garvin 26 | * @copyright 2008 Nathanael C. Fritz 27 | */ 28 | 29 | /** XMPPHP_XMPP 30 | * 31 | * This file is unnecessary unless you need to connect to older, non-XMPP-compliant servers like Dreamhost's. 32 | * In this case, use instead of XMPPHP_XMPP, otherwise feel free to delete it. 33 | * The old Jabber protocol wasn't standardized, so use at your own risk. 34 | * 35 | */ 36 | require_once "XMPP.php"; 37 | 38 | class XMPPHP_XMPPOld extends XMPPHP_XMPP { 39 | /** 40 | * 41 | * @var string 42 | */ 43 | protected $session_id; 44 | 45 | public function __construct($host, $port, $user, $password, $resource, $server = null, $printlog = false, $loglevel = null) { 46 | parent::__construct($host, $port, $user, $password, $resource, $server, $printlog, $loglevel); 47 | if(!$server) $server = $host; 48 | $this->stream_start = ''; 49 | $this->fulljid = "{$user}@{$server}/{$resource}"; 50 | } 51 | 52 | /** 53 | * Override XMLStream's startXML 54 | * 55 | * @param parser $parser 56 | * @param string $name 57 | * @param array $attr 58 | */ 59 | public function startXML($parser, $name, $attr) { 60 | if($this->xml_depth == 0) { 61 | $this->session_id = $attr['ID']; 62 | $this->authenticate(); 63 | } 64 | parent::startXML($parser, $name, $attr); 65 | } 66 | 67 | /** 68 | * Send Authenticate Info Request 69 | * 70 | */ 71 | public function authenticate() { 72 | $id = $this->getId(); 73 | $this->addidhandler($id, 'authfieldshandler'); 74 | $this->send("{$this->user}"); 75 | } 76 | 77 | /** 78 | * Retrieve auth fields and send auth attempt 79 | * 80 | * @param XMLObj $xml 81 | */ 82 | public function authFieldsHandler($xml) { 83 | $id = $this->getId(); 84 | $this->addidhandler($id, 'oldAuthResultHandler'); 85 | if($xml->sub('query')->hasSub('digest')) { 86 | $hash = sha1($this->session_id . $this->password); 87 | print "{$this->session_id} {$this->password}\n"; 88 | $out = "{$this->user}{$hash}{$this->resource}"; 89 | } else { 90 | $out = "{$this->user}{$this->password}{$this->resource}"; 91 | } 92 | $this->send($out); 93 | 94 | } 95 | 96 | /** 97 | * Determine authenticated or failure 98 | * 99 | * @param XMLObj $xml 100 | */ 101 | public function oldAuthResultHandler($xml) { 102 | if($xml->attrs['type'] != 'result') { 103 | $this->log->log("Auth failed!", XMPPHP_Log::LEVEL_ERROR); 104 | $this->disconnect(); 105 | throw new XMPPHP_Exception('Auth failed!'); 106 | } else { 107 | $this->log->log("Session started"); 108 | $this->event('session_start'); 109 | } 110 | } 111 | } 112 | 113 | 114 | ?> 115 | -------------------------------------------------------------------------------- /app/include/external/php-serial/LRS_T74.class.php: -------------------------------------------------------------------------------- 1 | 12 | * Released into GPL by uWink Inc. 13 | */ 14 | class LRS_T74 { 15 | 16 | private $serial; 17 | //private $serialport = "/dev/cu.usbserial"; 18 | private $serialport = "/dev/tty.serial"; 19 | // /dev/cu.usbserial for Prolific RS232->USB interface 20 | // /dev/tty.serial for XServe's built in RS232 interface 21 | private $serialbaud = 9600; 22 | private $log; 23 | private $sleep_count = 2; 24 | 25 | 26 | public function __construct () { 27 | /** Method __construct 28 | * Initializes the serial port, opens the serial port 29 | * and sets the baud rate 30 | */ 31 | // TODO: Error checking/exception handling 32 | // TODO throw on error on fail 33 | // TODO : Retry on failed open? 34 | global $log; 35 | $this->log = $log; 36 | 37 | $this->serial = new SerialDriver; 38 | $this->serial->deviceSet($this->serialport); 39 | $this->serial->confBaudRate($this->serialbaud); 40 | $this->log->notify("Opening serial port ".$this->serialport); 41 | $this->serial->deviceOpen(); 42 | $this->log->notify("Successfully opened serial port"); 43 | } 44 | 45 | public function __destruct () { 46 | /** Method __destruct 47 | * Closes the serial port cleanly 48 | * Initializes the serial port, opens the serial port 49 | * and sets the baud rate 50 | */ 51 | // TODO: Error checking/exception handling 52 | // TODO throw on error on fail 53 | $this->log->notify("Closing serial driver"); 54 | $this->serial->deviceClose(); 55 | } 56 | 57 | private function send($msg){ 58 | /** Method send 59 | * Abstracts out EOL and serial interface 60 | * Clean insertion point for error handling 61 | * @param string $msg The message to be sent without an EOL 62 | */ 63 | $msg .= "\n"; 64 | $this->serial->sendMessage($msg); 65 | } 66 | 67 | public function reset() { 68 | /** Method reset 69 | * Resets the LRS T74C232 device. 70 | */ 71 | $this->send("RESET"); 72 | } 73 | // TODO : try catch all sendMessages? or leave to caller to try/catch 74 | 75 | public function setPLL($pllmode){ 76 | /** Method setPLL 77 | * Sets the PLL frequencies for the transmitter 78 | * PLL,37420, 467.7500 - Standard for Alphanum Pagers 79 | * PLL,37422, 467.7750 - Jtech pager frequency 80 | * @param integer $pllmode The 5 digit PLL Code (37420 or 37422) 81 | */ 82 | $this->send("SF,".$pllmode); 83 | } 84 | 85 | public function setEcho($mode=1){ 86 | /** Method setEcho 87 | * Turns on the screen echo mode, great for debugging 88 | * @param integer $mode 0 for off, 1 for on. 1 is default 89 | */ 90 | $this->send("ECHO".$mode); 91 | } 92 | 93 | public function setTime(){ 94 | /** Method setTime 95 | * Sets the correct time on the interface 96 | */ 97 | $this->send("SETT,".date("H,i")); 98 | } 99 | 100 | // TODO implement STAT, need reliable reading from device 101 | // TODO implement reading from serial device 102 | public function pageAlpha($pager_id,$message){ 103 | /** Method pageAlpha 104 | * Pages an LRS Alphanumeric Pager 105 | * 36 characters maximum for large pager view 106 | * 76 characters maximum for tiny pager view (not recommended!) 107 | * @param integer $pager_id The pager number to page 108 | * @param string $message The text to be paged 109 | */ 110 | # print "Page Alpha got $pager_id and $message"; 111 | $this->send("FPG,".$pager_id.",0,3!A".$message); 112 | sleep($this->sleep_count); 113 | 114 | } 115 | } 116 | 117 | ?> 118 | -------------------------------------------------------------------------------- /app/include/external/php-serial/example.php: -------------------------------------------------------------------------------- 1 | deviceSet("COM1"); 10 | 11 | // We can change the baud rate, parity, length, stop bits, flow control 12 | $serial->confBaudRate(2400); 13 | $serial->confParity("none"); 14 | $serial->confCharacterLength(8); 15 | $serial->confStopBits(1); 16 | $serial->confFlowControl("none"); 17 | 18 | // Then we need to open it 19 | $serial->deviceOpen(); 20 | 21 | // To write into 22 | $serial->sendMessage("Hello !"); 23 | 24 | // Or to read from 25 | $read = $serial->readPort(); 26 | 27 | // If you want to change the configuration, the device must be closed 28 | $serial->deviceClose(); 29 | 30 | // We can change the baud rate 31 | $serial->confBaudRate(2400); 32 | 33 | // etc... 34 | // 35 | // 36 | /* Notes from Jim : 37 | > Also, one last thing that would be good to document, maybe in example.php: 38 | > The actual device to be opened caused me a lot of confusion, I was 39 | > attempting to open a tty.* device on my system and was having no luck at 40 | > all, until I found that I should actually be opening a cu.* device instead! 41 | > The following link was very helpful in figuring this out, my USB/Serial 42 | > adapter (as most probably do) lacked DTR, so trying to use the tty.* device 43 | > just caused the code to hang and never return, it took a lot of googling to 44 | > realize what was going wrong and how to fix it. 45 | > 46 | > http://lists.apple.com/archives/darwin-dev/2009/Nov/msg00099.html 47 | 48 | Riz comment : I've definately had a device that didn't work well when using cu., but worked fine with tty. Either way, a good thing to note and keep for reference when debugging. 49 | */ 50 | ?> 51 | -------------------------------------------------------------------------------- /app/include/external/php-serial/example_VS421CPNTA.php: -------------------------------------------------------------------------------- 1 | "; 37 | echo "
38 | 39 | 40 | 41 | 42 | 43 | 44 |
Switch to input? :
45 |
"; 46 | echo ""; 47 | } else { 48 | 49 | include "php_serial.class.php"; 50 | 51 | // Let's start the class 52 | $serial = new phpSerial; 53 | 54 | // First we must specify the device. This works on both linux and windows (if 55 | // your linux serial device is /dev/ttyS0 for COM1, etc) 56 | // $serial->deviceSet("COM1"); 57 | $serial->deviceSet("/dev/cu.usbserial-FTDY7ID6"); 58 | 59 | // We can change the baud rate, parity, length, stop bits, flow control 60 | $serial->confBaudRate(2400); 61 | $serial->confParity("none"); 62 | $serial->confCharacterLength(8); 63 | $serial->confStopBits(1); 64 | $serial->confFlowControl("none"); 65 | 66 | // Then we need to open it 67 | $serial->deviceOpen(); 68 | 69 | // To write into 70 | $serial->sendMessage("I".$the_input); 71 | 72 | // Or to read from 73 | $read = ''; 74 | $theResult = ''; 75 | $start = microtime_float(); 76 | 77 | while ( ($read == '') && (microtime_float() <= $start + 0.5) ) { 78 | $read = $serial->readPort(); 79 | if ($read != '') { 80 | $theResult .= $read; 81 | $read = ''; 82 | } 83 | } 84 | 85 | // If you want to change the configuration, the device must be closed 86 | $serial->deviceClose(); 87 | 88 | // etc... 89 | 90 | echo "Read data: ".$theResult."
"; 91 | 92 | echo "
93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 |
Switch to input? :
101 |
"; 102 | } 103 | 104 | ?> 105 | -------------------------------------------------------------------------------- /app/include/external/php-serial/php_serial.class.php: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jethrocarr/smstoxmpp/3c4b996151ce09dfbec97cda67b34a9d62dd5e0d/app/include/external/php-serial/php_serial.class.php -------------------------------------------------------------------------------- /app/include/external/php-serial/sms-example.php: -------------------------------------------------------------------------------- 1 | > Advanced Port Settings...) 11 | 12 | $serial->deviceSet("/dev/ttyUSB1"); 13 | 14 | // Then we need to open it 15 | $serial->deviceOpen('w+'); 16 | 17 | // We may need to return if nothing happens for 10 seconds 18 | stream_set_timeout($serial->_dHandle, 10); 19 | 20 | // We can change the baud rate 21 | $serial->confBaudRate(9600); 22 | 23 | // SMS inbox query - mode command and list command 24 | $serial->sendMessage("AT\n\r",1); 25 | var_dump($serial->readPort()); 26 | $serial->sendMessage("AT+CMGF=1\n\r",1); 27 | var_dump($serial->readPort()); 28 | $serial->sendMessage("AT+CMGL=\"ALL\"\n\r",2); 29 | var_dump($serial->readPort()); 30 | 31 | 32 | // If you want to change the configuration, the device must be closed 33 | $serial->deviceClose(); 34 | 35 | ?> 36 | -------------------------------------------------------------------------------- /app/include/gateways/eu.apksoft.android.smsgateway.php: -------------------------------------------------------------------------------- 1 | log = &$log; 45 | $this->section = &$section; 46 | } 47 | 48 | 49 | /* 50 | set_address 51 | 52 | Either called with the static IP/port from the configuration file, or 53 | called by the application itself when we discover the current address. 54 | */ 55 | function set_address($address, $port = "9090") 56 | { 57 | if ($this->address != $address) 58 | { 59 | // address has changed, set 60 | $this->address = $address; 61 | $this->port = $port; 62 | 63 | // reset the health check timer 64 | $this->health_check_last = null; 65 | 66 | $this->log->info("[{$this->section}] Updated device address to {$this->address}:{$this->port}"); 67 | } 68 | } 69 | 70 | 71 | /* 72 | set_path 73 | 74 | Provided with the path from the configuration file, this function validates 75 | the input and then calls set_address to save if it's static. 76 | 77 | Returns 78 | -1 Empty Path 79 | 0 Invalid Path 80 | 1 Address Set / Valid / Automatic 81 | */ 82 | function set_path($path) 83 | { 84 | if (empty($path)) 85 | { 86 | return -1; 87 | } 88 | 89 | if ($path == "auto" && $path == "dynamic") 90 | { 91 | // dynamics can't be set, we must wait for the gateway 92 | // to announce itself by sending us an SMS. 93 | return 1; 94 | } 95 | else 96 | { 97 | // gateway device has a static path configured 98 | list($address, $port) = @explode(":", $path); 99 | 100 | if (preg_match("/^[0-9]*$/", $port) && preg_match("/^\S*$/", $address)) 101 | { 102 | $this->set_address($address, $port); 103 | return 1; 104 | } 105 | } 106 | 107 | return 0; 108 | } 109 | 110 | 111 | /* 112 | health_check 113 | 114 | Checks reachability of the remote device based on the current address. 115 | 116 | Returns 117 | 0 Unhealthy 118 | 1 Healthy - send me messages bro! 119 | */ 120 | function health_check($force = false) 121 | { 122 | $curr_time = time(); 123 | 124 | if ($force == true) 125 | { 126 | $this->health_check_last = null; 127 | } 128 | 129 | if ($this->health_check_last < ($curr_time - $this->health_check_freq)) 130 | { 131 | $this->health_check_last = $curr_time; 132 | 133 | if (!$this->address) 134 | { 135 | $this->log->debug("[{$this->section}] Health check failed, gateway IP is unknown"); 136 | $this->health_check_state = 0; 137 | } 138 | else 139 | { 140 | // test if we can open the port within X seconds 141 | if ($fp = @fsockopen($this->address, $this->port, $errno, $errstr, HEALTH_CHECK_TIMEOUT)) 142 | { 143 | fclose($fp); 144 | 145 | $this->log->debug("[{$this->section}] Health check succeeded in opening port. :-)"); 146 | $this->health_check_state = 1; 147 | } 148 | else 149 | { 150 | $this->log->debug("[{$this->section}] Health check failed, unable to connect to IP/port."); 151 | $this->health_check_state = 0; 152 | } 153 | } 154 | } 155 | 156 | return $this->health_check_state; 157 | } 158 | 159 | 160 | /* 161 | message_listen 162 | 163 | Due to the nature of this gateway, this listen function is non-blocking and just checks 164 | the current $_GET variables for valid content and validates, before returning the information 165 | in an array. 166 | 167 | Returns 168 | 0 No message 169 | array Message in array 170 | */ 171 | 172 | function message_listen() 173 | { 174 | // we don't do input validation here, it's done in a standard way 175 | // with the main listener logic 176 | 177 | $message = array(); 178 | 179 | $message["phone"] = $_GET["phone"]; 180 | $message["body"] = $_GET["text"]; 181 | 182 | if (!$message["phone"] || !$message["body"]) 183 | { 184 | return 0; 185 | } 186 | 187 | return $message; 188 | } 189 | 190 | 191 | /* 192 | message_poll 193 | 194 | Actively polls for a new incomming message. This is unused by this gateway, but 195 | is needed with any gateways that are unable to push to an HTTP listener which 196 | can be handled by message_listen() 197 | 198 | Returns 199 | 0 No Message 200 | array Message in array 201 | */ 202 | 203 | function message_poll() 204 | { 205 | /* 206 | Provide multidimensional array of hashes with messages recieved. 207 | 208 | return ( 209 | [0] => ( 210 | phone => value, 211 | body => value, 212 | ) 213 | [1] => ( 214 | phone => value 215 | body => value 216 | ) 217 | ) 218 | etc 219 | 220 | */ 221 | // placeholder only 222 | return 0; 223 | } 224 | 225 | 226 | /* 227 | message_send 228 | 229 | Sends a message out via the gateway. If the gateway is unavailable, we return 230 | an error so the user can be notified. 231 | 232 | TODO: should we implement some form of queuing here for future use? 233 | 234 | Returns 235 | 0 Failure 236 | 1 Success 237 | */ 238 | function message_send($phone, $body) 239 | { 240 | $this->log->debug("[{$this->section}] Sending message to \"$phone\" contents: \"$body\""); 241 | 242 | // ensure that data is SMS & HTTP GET safe 243 | $phone = urlencode($phone); 244 | $body = urlencode($body); 245 | 246 | // don't need to do anything too complex with HTTP, etc... just open up and shove it some data 247 | if (@file_get_contents("http://{$this->address}:{$this->port}/sendsms?phone=$phone&text=$body")) 248 | { 249 | return 1; 250 | } 251 | 252 | return 0; 253 | } 254 | } 255 | 256 | ?> 257 | -------------------------------------------------------------------------------- /app/include/gateways/template.php: -------------------------------------------------------------------------------- 1 | log = &$log; 35 | $this->section = &$section; 36 | } 37 | 38 | 39 | /* 40 | set_address 41 | 42 | Either called with the static IP/port from the configuration file, or 43 | called by the application itself when we discover the current address. 44 | 45 | This code allows us to support both dynamic and statically addressed 46 | devices. If you are supporting a local hardware device only, you can 47 | just turn this function into a place holder. 48 | */ 49 | function set_address($address, $port = "9090") 50 | { 51 | if ($this->address != $address) 52 | { 53 | // address has changed, set 54 | $this->address = $address; 55 | $this->port = $port; 56 | 57 | // reset the health check timer 58 | $this->health_check_last = null; 59 | 60 | $this->log->info("[{$this->section}] Updated device address to {$this->address}:{$this->port}"); 61 | } 62 | } 63 | 64 | 65 | /* 66 | set_path 67 | 68 | Provided with the path from the configuration file, this function validates 69 | the input and then calls set_address to save if it's static. 70 | 71 | Returns 72 | -1 Empty Path 73 | 0 Invalid Path 74 | 1 Address Set / Valid / Automatic 75 | */ 76 | function set_path($path) 77 | { 78 | if (empty($path)) 79 | { 80 | return -1; 81 | } 82 | 83 | if ($path == "auto" && $path == "dynamic") 84 | { 85 | // dynamics can't be set, we must wait for the gateway 86 | // to announce itself by sending us an SMS. 87 | return 1; 88 | } 89 | else 90 | { 91 | // gateway device has a static path configured 92 | list($address, $port) = @explode(":", $path); 93 | 94 | if (preg_match("/^[0-9]*$/", $port) && preg_match("/^\S*$/", $address)) 95 | { 96 | $this->set_address($address, $port); 97 | return 1; 98 | } 99 | } 100 | 101 | return 0; 102 | } 103 | 104 | 105 | /* 106 | health_check 107 | 108 | Checks reachability of the remote device based on the current address. 109 | 110 | Returns 111 | 0 Unhealthy 112 | 1 Healthy - send me messages bro! 113 | */ 114 | function health_check($force = false) 115 | { 116 | $curr_time = time(); 117 | 118 | if ($force == true) 119 | { 120 | $this->health_check_last = null; 121 | } 122 | 123 | if ($this->health_check_last < ($curr_time - $this->health_check_freq)) 124 | { 125 | $this->health_check_last = $curr_time; 126 | 127 | if (!$this->address) 128 | { 129 | $this->log->debug("[{$this->section}] Health check failed, gateway IP is unknown"); 130 | $this->health_check_state = 0; 131 | } 132 | else 133 | { 134 | // test if we can open the port within X seconds 135 | if ($fp = @fsockopen($this->address, $this->port, $errno, $errstr, HEALTH_CHECK_TIMEOUT)) 136 | { 137 | fclose($fp); 138 | 139 | $this->log->debug("[{$this->section}] Health check succeeded in opening port. :-)"); 140 | $this->health_check_state = 1; 141 | } 142 | else 143 | { 144 | $this->log->debug("[{$this->section}] Health check failed, unable to connect to IP/port."); 145 | $this->health_check_state = 0; 146 | } 147 | } 148 | } 149 | 150 | return $this->health_check_state; 151 | } 152 | 153 | 154 | /* 155 | message_listen 156 | 157 | If your gateway sends SMS messages to SMStoXMPP via making an HTTP call (ie webhook) to a 158 | particular HTTP address, this function is called by listener.php when a request is recieved. 159 | 160 | The function takes the incoming message information and adds it to the message queue to be 161 | processed by the application itself. 162 | 163 | Returns 164 | 0 No message 165 | array Message in array 166 | */ 167 | 168 | function message_listen() 169 | { 170 | // we don't do input validation here, it's done in a standard way 171 | // with the main listener logic 172 | 173 | $message = array(); 174 | 175 | $message["phone"] = $_GET["phone"]; 176 | $message["body"] = $_GET["text"]; 177 | 178 | if (!$message["phone"] || !$message["body"]) 179 | { 180 | return 0; 181 | } 182 | 183 | return $message; 184 | } 185 | 186 | 187 | /* 188 | message_poll 189 | 190 | Actively polls for a new incomming message. This is unused by this gateway, but 191 | is needed with any gateways that are unable to push to an HTTP listener which 192 | can be handled by message_listen() 193 | 194 | This function may be useful when detailing with hardware devices or gateways 195 | which store their messages in a poll-only system, such as a POP3 mailbox. 196 | 197 | Returns 198 | 0 No Message 199 | array Message in array 200 | */ 201 | 202 | function message_poll() 203 | { 204 | /* 205 | Once processing has been performed, prepare a multidimensional 206 | array of hashes with messages recieved. 207 | 208 | return ( 209 | [0] => ( 210 | phone => value, 211 | body => value, 212 | ) 213 | [1] => ( 214 | phone => value 215 | body => value 216 | ) 217 | ) 218 | etc 219 | 220 | */ 221 | // placeholder only 222 | return 0; 223 | } 224 | 225 | 226 | /* 227 | message_send 228 | 229 | Sends a message out via the gateway. If the gateway is unavailable, we return 230 | an error so the user can be notified. 231 | 232 | TODO: should we implement some form of queuing here for future use? 233 | 234 | Returns 235 | 0 Failure 236 | 1 Success 237 | */ 238 | function message_send($phone, $body) 239 | { 240 | $this->log->debug("[{$this->section}] Sending message to \"$phone\" contents: \"$body\""); 241 | 242 | /* 243 | The following is an example of sending an SMS to a gateway by connecting 244 | to it via HTTP. Other approaches could include emailing a particular address 245 | using the mail() command. 246 | */ 247 | 248 | // ensure that data is SMS & HTTP GET safe 249 | $phone = urlencode($phone); 250 | $body = urlencode($body); 251 | 252 | // don't need to do anything too complex with HTTP, etc... just open up and shove it some data 253 | if (@file_get_contents("http://{$this->address}:{$this->port}/sendsms?phone=$phone&text=$body")) 254 | { 255 | return 1; 256 | } 257 | 258 | return 0; 259 | } 260 | } 261 | 262 | ?> 263 | -------------------------------------------------------------------------------- /app/include/logger.php: -------------------------------------------------------------------------------- 1 | logfile_handle = fopen($filename, "a")) 57 | { 58 | print "Warning: Unable to open log file $filename for writing.\n"; 59 | return 0; 60 | } 61 | 62 | return 1; 63 | } 64 | 65 | 66 | /* 67 | When running apps in verbose mode, it's often desirable to output to stdout. 68 | */ 69 | function set_stdout() 70 | { 71 | $this->option_stdout = true; 72 | } 73 | 74 | function set_debug() 75 | { 76 | $this->option_debug = true; 77 | } 78 | 79 | 80 | /* 81 | Message Queue Handling 82 | 83 | This is useful when writing forking applications which need to carefully handle their logging 84 | to avoid clashing in the same log file. 85 | 86 | We could leave it up to the kernel and hope for the best, but it's not an ideal solution, we 87 | should handle it properly by using IPC to communicate the log messages. 88 | 89 | To provide for this, we have two functions - a sender that will always send log messages 90 | to the queue and a listener, that can be called for a non-blocking listen for log messages. 91 | */ 92 | 93 | function set_queue($msgqueue_handle, $message_type, $message_maxsize) 94 | { 95 | $this->msgqueue_handle = $msgqueue_handle; 96 | $this->msgqueue_type = $message_type; 97 | $this->msgqueue_maxsize = $message_maxsize; 98 | } 99 | 100 | function set_queue_listener($msgqueue_handle, $message_type, $message_maxsize) 101 | { 102 | $this->set_queue($msgqueue_handle, $message_type, $message_maxsize); 103 | 104 | $this->option_msgqueue_listener = true; 105 | } 106 | 107 | function set_queue_sender($msgqueue_handle, $message_type, $message_maxsize) 108 | { 109 | $this->set_queue($msgqueue_handle, $message_type, $message_maxsize); 110 | 111 | $this->option_msgqueue_sender = true; 112 | } 113 | 114 | 115 | 116 | /* 117 | write() 118 | 119 | Write the provided log message to all enable destinations. 120 | */ 121 | function write($level, $message) 122 | { 123 | $time = date("Y-m-d H:i:s"); 124 | 125 | // to console/display 126 | if ($this->option_stdout) 127 | { 128 | if ($level == "error") 129 | { 130 | fwrite(STDERR, "$time [$level] $message\n"); 131 | } 132 | else 133 | { 134 | print "$time [$level] $message\n"; 135 | } 136 | } 137 | 138 | // via IPC to another process 139 | if ($this->option_msgqueue_sender) 140 | { 141 | // send to queue 142 | $queue_message = array( 143 | "time" => $time, 144 | "level" => $level, 145 | "body" => $message, 146 | ); 147 | 148 | msg_send(&$this->msgqueue_handle, &$this->msgqueue_type, $queue_message); 149 | 150 | unset($queue_message); 151 | } 152 | 153 | 154 | // to log file 155 | if ($this->logfile_handle) 156 | { 157 | fwrite($this->logfile_handle, "$time [$level] $message\n"); 158 | } 159 | } 160 | 161 | 162 | 163 | /* 164 | write_fromqueue() 165 | 166 | Check the IPC queue for any messages and then write them using the standard 167 | process. Non-blocking check. 168 | */ 169 | 170 | function write_fromqueue($blocking = false) 171 | { 172 | if ($this->option_msgqueue_listener) 173 | { 174 | $message = ""; 175 | $message_type = ""; 176 | $errorcode = null; 177 | 178 | if ($blocking == true) 179 | { 180 | $return = msg_receive($this->msgqueue_handle, $this->msgqueue_type, $message_type, $this->msgqueue_maxsize, $message, TRUE, $errorcode); 181 | } 182 | else 183 | { 184 | $return = msg_receive($this->msgqueue_handle, $this->msgqueue_type, $message_type, $this->msgqueue_maxsize, $message, TRUE, MSG_IPC_NOWAIT); 185 | } 186 | 187 | if ($return) 188 | { 189 | // call the appropiate write function for the level defined 190 | $this->$message['level']($message['body']); 191 | } 192 | 193 | if ($errorcode) 194 | { 195 | print "Serious Error: MSG queue recieve failed with $errorcode\n"; 196 | } 197 | 198 | return 1; 199 | } 200 | 201 | return 0; 202 | } 203 | 204 | 205 | 206 | 207 | /* 208 | Loglevel write commands 209 | */ 210 | function debug($message) 211 | { 212 | if ($this->option_debug) 213 | { 214 | $this->write("debug", &$message); 215 | } 216 | 217 | unset($message); 218 | } 219 | 220 | function info($message) 221 | { 222 | $this->write("info", $message); 223 | } 224 | 225 | function warning() 226 | { 227 | $this->write("warning", $message); 228 | } 229 | 230 | function error($message) 231 | { 232 | $this->write("error", $message); 233 | } 234 | 235 | function error_fatal($message) 236 | { 237 | $this->write("error", $message); 238 | die("Fatal Error: $message\n"); 239 | } 240 | 241 | } 242 | 243 | ?> 244 | -------------------------------------------------------------------------------- /app/listener.php: -------------------------------------------------------------------------------- 1 | 16 | 17 | Unless otherwise stated, all parts of this program are licensed under 18 | the GNU AGPL software license version 3 only as detailed in docs/COPYING 19 | */ 20 | 21 | // internal libraries 22 | include 'include/defines.php'; 23 | include 'include/logger.php'; 24 | 25 | 26 | 27 | /* 28 | Load the configuration and establish the connection 29 | to the message queue. This is vital for listener-dispatcher 30 | communications to succeed. 31 | */ 32 | 33 | // load config file 34 | $config = parse_ini_file("config/config.ini", true); 35 | 36 | // verify message queue is up and running 37 | if (!file_exists($config["SMStoXMPP"]["app_lock"])) 38 | { 39 | header('HTTP/1.1 500 Internal Server Error'); 40 | die("Fatal Error: Unable to connect to active message queue for dispatcher\n"); 41 | } 42 | if (!function_exists("msg_get_queue")) 43 | { 44 | header('HTTP/1.1 500 Internal Server Error'); 45 | die("Fatal Error: PHP PCNTL/Process module not installed. This is required for IPC communication. If you have just installed it, make sure you re-start your webserver so it detects the new PHP modules"); 46 | } 47 | if (!$msg_queue = msg_get_queue(ftok($config["SMStoXMPP"]["app_lock"], 'R'),0666 | IPC_CREAT)) 48 | { 49 | header('HTTP/1.1 500 Internal Server Error'); 50 | die("Unable to attach to queue ". $config["SMStoXMPP"]["app_lock"] ."\n"); 51 | } 52 | 53 | 54 | 55 | /* 56 | Create a new logger object, we need to log via the IPC 57 | message queue so that any general warnings/debug/errors 58 | get included in the general daemon log. 59 | */ 60 | 61 | $log = new logger(); 62 | $log->set_debug(); // send all debug through to the daemon, it can then decided whether to retain or toss 63 | $log->set_queue_sender(&$msg_queue, MESSAGE_LOG, MESSAGE_MAX_SIZE); 64 | 65 | $log->debug("[listener] Listener request recieved."); 66 | $log->debug("[listener] Debug URL: {$_SERVER['REQUEST_URI']}"); 67 | 68 | 69 | /* 70 | Determine Device 71 | 72 | SMStoXMPP supports a number of different devices and types, we need to discover 73 | which one is providing information to this page and then fetch and process the 74 | information accordingly. 75 | */ 76 | 77 | $device = null; 78 | 79 | if (isset($_GET["device"])) 80 | { 81 | $device = $_GET["device"]; 82 | } 83 | 84 | // other ID fields for other gateways? 85 | 86 | if (!$device) 87 | { 88 | header('HTTP/1.1 500 Internal Server Error'); 89 | $log->error_fatal("[listener] No destination device was specified - make sure you're setting the ?device=myphone option."); 90 | } 91 | 92 | 93 | /* 94 | Launch gateway/device logic 95 | 96 | All the gateway/device logic is broken into include files that are only loaded into 97 | the particular worker fork which is using that gateway. If we can't load it for some 98 | reason we should fail with an error to all the apps. 99 | */ 100 | 101 | if (!$config[$device]) 102 | { 103 | header('HTTP/1.1 500 Internal Server Error'); 104 | $log->error_fatal("[listener] An invalid destination device was requested - make sure you are using the correct ?device=example tag"); 105 | } 106 | 107 | 108 | if (!$config[$device]["gw_type"]) 109 | { 110 | header('HTTP/1.1 500 Internal Server Error'); 111 | $log->error_fatal("[listener] There is no gateway set! Unable to proceed!"); 112 | } 113 | 114 | $gatewayfile = "include/gateways/". $config[$device]["gw_type"] .".php"; 115 | 116 | if (!file_exists($gatewayfile)) 117 | { 118 | header('HTTP/1.1 500 Internal Server Error'); 119 | $log->error("[listener] The gateway include $gatewayfile could not be located - is this the correct gateway name?"); 120 | $log->error_fatal("[listener] Sorry, there is no such destination device - please check your input."); 121 | } 122 | 123 | include($gatewayfile); 124 | 125 | $gateway = New device_gateway; 126 | 127 | 128 | 129 | /* 130 | Fetch the message details & input validate. Whilst there's no SQL DB to worry about, we do need 131 | to filter the phone number and body to ensure they're valid and that there's no sneaky XML 132 | injection taking place that could mess with the generated XMPP message. 133 | 134 | Format: 135 | $message_raw["phone"] Source phone number 136 | $message_raw["body"] Message string 137 | */ 138 | 139 | $message_raw = $gateway->message_listen(); 140 | 141 | if (!$message_raw) 142 | { 143 | header('HTTP/1.1 500 Internal Server Error'); 144 | $log->error_fatal("[listener] An invalid message request was recieved, unable to process."); 145 | } 146 | 147 | $message = array(); 148 | 149 | if (preg_match("/^[+]*[0-9]{1}[0-9]*$/", $message_raw["phone"])) 150 | { 151 | $message["phone"] = $message_raw["phone"]; 152 | } 153 | else 154 | { 155 | header('HTTP/1.1 500 Internal Server Error'); 156 | $log->error_fatal("[listener] Invalid phone number recieved!"); 157 | } 158 | 159 | if (preg_match("/^[\S\s]*$/", $message_raw["body"])) 160 | { 161 | // quote out special XML characters to prevent 162 | // messing with the XML body of the XMPP message 163 | // that gets generated. 164 | 165 | $message["body"] = htmlspecialchars($message_raw["body"]); 166 | } 167 | else 168 | { 169 | header('HTTP/1.1 500 Internal Server Error'); 170 | $log->error_fatal("[listener] Invalid message content recieved!"); 171 | } 172 | 173 | 174 | $log->info("[listener] Recieved message from phone \"{$message["phone"]}\" with string \"{$message["body"]}\""); 175 | 176 | 177 | /* 178 | Add other useful information for the dispatcher 179 | 180 | We hand some other information such as the device's IP address 181 | to the backend, which may use it for logic such as setting the dynamic 182 | address. 183 | */ 184 | 185 | $message["device_ip"] = $_SERVER["REMOTE_ADDR"]; // device remove IP (may be behind NAT) 186 | 187 | 188 | /* 189 | We have a valid message, process and add it to the message queue 190 | so that it can be processed by the dispatcher daemon. 191 | 192 | (We use the hash to generate unique(ish) ID for this device name 193 | so that the dispatcher can listen to the messages on the IPC queue. 194 | */ 195 | 196 | $msg_mylistener = intval(base_convert(hash("crc32", $device, false), 16, 10)); 197 | 198 | if (!msg_send($msg_queue, $msg_mylistener, $message)) 199 | { 200 | header('HTTP/1.1 500 Internal Server Error'); 201 | $log->error_fatal("Unexpected failure attempting to deliver message to queue."); 202 | } 203 | else 204 | { 205 | // work here is done 206 | print "200/SUCCESS
\n"; 207 | print "Message successfully handled to the backend dispatcher\n"; 208 | } 209 | 210 | ?> 211 | -------------------------------------------------------------------------------- /docs/AUTHORS: -------------------------------------------------------------------------------- 1 | SMStoXMPP Authors 2 | ----------------- 3 | Jethro Carr 4 | 5 | 6 | Bundled Libraries 7 | (app/include/external/*) 8 | ----------------- 9 | 10 | XMPP PHP Library: 11 | Nathanael C. Fritz 12 | Stephan Wentz 13 | Michael Garvin 14 | 15 | CardDAV PHP Library 16 | Christian Putzke 17 | 18 | 19 | -------------------------------------------------------------------------------- /docs/COPYING: -------------------------------------------------------------------------------- 1 | 2 | SMStoXMPP 3 | http://projects.jethrocarr.com/p/SMStoXMPP 4 | 5 | (c) Copyright 2013 Jethro Carr 6 | 7 | Unless otherwise stated, all parts of this program are licensed under 8 | the GNU AGPL software license version 3 only as detailed below. 9 | 10 | An exception is the XMPP library included in this application which 11 | is licensed under GNU GPL version 2 which is compatible with AGPL v3. 12 | 13 | 14 | ===================================================================== 15 | 16 | GNU AFFERO GENERAL PUBLIC LICENSE 17 | 18 | Version 3, 19 November 2007 19 | 20 | Copyright (C) 2007 Free Software Foundation, Inc. 21 | Everyone is permitted to copy and distribute verbatim copies 22 | of this license document, but changing it is not allowed. 23 | 24 | Preamble 25 | 26 | The GNU Affero General Public License is a free, copyleft license for 27 | software and other kinds of works, specifically designed to ensure 28 | cooperation with the community in the case of network server software. 29 | 30 | The licenses for most software and other practical works are designed 31 | to take away your freedom to share and change the works. By contrast, 32 | our General Public Licenses are intended to guarantee your freedom to 33 | share and change all versions of a program--to make sure it remains free 34 | software for all its users. 35 | 36 | When we speak of free software, we are referring to freedom, not 37 | price. Our General Public Licenses are designed to make sure that you 38 | have the freedom to distribute copies of free software (and charge for 39 | them if you wish), that you receive source code or can get it if you 40 | want it, that you can change the software or use pieces of it in new 41 | free programs, and that you know you can do these things. 42 | 43 | Developers that use our General Public Licenses protect your rights 44 | with two steps: (1) assert copyright on the software, and (2) offer 45 | you this License which gives you legal permission to copy, distribute 46 | and/or modify the software. 47 | 48 | A secondary benefit of defending all users' freedom is that 49 | improvements made in alternate versions of the program, if they 50 | receive widespread use, become available for other developers to 51 | incorporate. Many developers of free software are heartened and 52 | encouraged by the resulting cooperation. However, in the case of 53 | software used on network servers, this result may fail to come about. 54 | The GNU General Public License permits making a modified version and 55 | letting the public access it on a server without ever releasing its 56 | source code to the public. 57 | 58 | The GNU Affero General Public License is designed specifically to 59 | ensure that, in such cases, the modified source code becomes available 60 | to the community. It requires the operator of a network server to 61 | provide the source code of the modified version running there to the 62 | users of that server. Therefore, public use of a modified version, on 63 | a publicly accessible server, gives the public access to the source 64 | code of the modified version. 65 | 66 | An older license, called the Affero General Public License and 67 | published by Affero, was designed to accomplish similar goals. This is 68 | a different license, not a version of the Affero GPL, but Affero has 69 | released a new version of the Affero GPL which permits relicensing under 70 | this license. 71 | 72 | The precise terms and conditions for copying, distribution and 73 | modification follow. 74 | 75 | TERMS AND CONDITIONS 76 | 77 | 0. Definitions. 78 | 79 | "This License" refers to version 3 of the GNU Affero General Public License. 80 | 81 | "Copyright" also means copyright-like laws that apply to other kinds of 82 | works, such as semiconductor masks. 83 | 84 | "The Program" refers to any copyrightable work licensed under this 85 | License. Each licensee is addressed as "you". "Licensees" and 86 | "recipients" may be individuals or organizations. 87 | 88 | To "modify" a work means to copy from or adapt all or part of the work 89 | in a fashion requiring copyright permission, other than the making of an 90 | exact copy. The resulting work is called a "modified version" of the 91 | earlier work or a work "based on" the earlier work. 92 | 93 | A "covered work" means either the unmodified Program or a work based 94 | on the Program. 95 | 96 | To "propagate" a work means to do anything with it that, without 97 | permission, would make you directly or secondarily liable for 98 | infringement under applicable copyright law, except executing it on a 99 | computer or modifying a private copy. Propagation includes copying, 100 | distribution (with or without modification), making available to the 101 | public, and in some countries other activities as well. 102 | 103 | To "convey" a work means any kind of propagation that enables other 104 | parties to make or receive copies. Mere interaction with a user through 105 | a computer network, with no transfer of a copy, is not conveying. 106 | 107 | An interactive user interface displays "Appropriate Legal Notices" 108 | to the extent that it includes a convenient and prominently visible 109 | feature that (1) displays an appropriate copyright notice, and (2) 110 | tells the user that there is no warranty for the work (except to the 111 | extent that warranties are provided), that licensees may convey the 112 | work under this License, and how to view a copy of this License. If 113 | the interface presents a list of user commands or options, such as a 114 | menu, a prominent item in the list meets this criterion. 115 | 116 | 1. Source Code. 117 | 118 | The "source code" for a work means the preferred form of the work 119 | for making modifications to it. "Object code" means any non-source 120 | form of a work. 121 | 122 | A "Standard Interface" means an interface that either is an official 123 | standard defined by a recognized standards body, or, in the case of 124 | interfaces specified for a particular programming language, one that 125 | is widely used among developers working in that language. 126 | 127 | The "System Libraries" of an executable work include anything, other 128 | than the work as a whole, that (a) is included in the normal form of 129 | packaging a Major Component, but which is not part of that Major 130 | Component, and (b) serves only to enable use of the work with that 131 | Major Component, or to implement a Standard Interface for which an 132 | implementation is available to the public in source code form. A 133 | "Major Component", in this context, means a major essential component 134 | (kernel, window system, and so on) of the specific operating system 135 | (if any) on which the executable work runs, or a compiler used to 136 | produce the work, or an object code interpreter used to run it. 137 | 138 | The "Corresponding Source" for a work in object code form means all 139 | the source code needed to generate, install, and (for an executable 140 | work) run the object code and to modify the work, including scripts to 141 | control those activities. However, it does not include the work's 142 | System Libraries, or general-purpose tools or generally available free 143 | programs which are used unmodified in performing those activities but 144 | which are not part of the work. For example, Corresponding Source 145 | includes interface definition files associated with source files for 146 | the work, and the source code for shared libraries and dynamically 147 | linked subprograms that the work is specifically designed to require, 148 | such as by intimate data communication or control flow between those 149 | subprograms and other parts of the work. 150 | 151 | The Corresponding Source need not include anything that users 152 | can regenerate automatically from other parts of the Corresponding 153 | Source. 154 | 155 | The Corresponding Source for a work in source code form is that 156 | same work. 157 | 158 | 2. Basic Permissions. 159 | 160 | All rights granted under this License are granted for the term of 161 | copyright on the Program, and are irrevocable provided the stated 162 | conditions are met. This License explicitly affirms your unlimited 163 | permission to run the unmodified Program. The output from running a 164 | covered work is covered by this License only if the output, given its 165 | content, constitutes a covered work. This License acknowledges your 166 | rights of fair use or other equivalent, as provided by copyright law. 167 | 168 | You may make, run and propagate covered works that you do not 169 | convey, without conditions so long as your license otherwise remains 170 | in force. You may convey covered works to others for the sole purpose 171 | of having them make modifications exclusively for you, or provide you 172 | with facilities for running those works, provided that you comply with 173 | the terms of this License in conveying all material for which you do 174 | not control copyright. Those thus making or running the covered works 175 | for you must do so exclusively on your behalf, under your direction 176 | and control, on terms that prohibit them from making any copies of 177 | your copyrighted material outside their relationship with you. 178 | 179 | Conveying under any other circumstances is permitted solely under 180 | the conditions stated below. Sublicensing is not allowed; section 10 181 | makes it unnecessary. 182 | 183 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 184 | 185 | No covered work shall be deemed part of an effective technological 186 | measure under any applicable law fulfilling obligations under article 187 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 188 | similar laws prohibiting or restricting circumvention of such 189 | measures. 190 | 191 | When you convey a covered work, you waive any legal power to forbid 192 | circumvention of technological measures to the extent such circumvention 193 | is effected by exercising rights under this License with respect to 194 | the covered work, and you disclaim any intention to limit operation or 195 | modification of the work as a means of enforcing, against the work's 196 | users, your or third parties' legal rights to forbid circumvention of 197 | technological measures. 198 | 199 | 4. Conveying Verbatim Copies. 200 | 201 | You may convey verbatim copies of the Program's source code as you 202 | receive it, in any medium, provided that you conspicuously and 203 | appropriately publish on each copy an appropriate copyright notice; 204 | keep intact all notices stating that this License and any 205 | non-permissive terms added in accord with section 7 apply to the code; 206 | keep intact all notices of the absence of any warranty; and give all 207 | recipients a copy of this License along with the Program. 208 | 209 | You may charge any price or no price for each copy that you convey, 210 | and you may offer support or warranty protection for a fee. 211 | 212 | 5. Conveying Modified Source Versions. 213 | 214 | You may convey a work based on the Program, or the modifications to 215 | produce it from the Program, in the form of source code under the 216 | terms of section 4, provided that you also meet all of these conditions: 217 | 218 | a) The work must carry prominent notices stating that you modified 219 | it, and giving a relevant date. 220 | 221 | b) The work must carry prominent notices stating that it is 222 | released under this License and any conditions added under section 223 | 7. This requirement modifies the requirement in section 4 to 224 | "keep intact all notices". 225 | 226 | c) You must license the entire work, as a whole, under this 227 | License to anyone who comes into possession of a copy. This 228 | License will therefore apply, along with any applicable section 7 229 | additional terms, to the whole of the work, and all its parts, 230 | regardless of how they are packaged. This License gives no 231 | permission to license the work in any other way, but it does not 232 | invalidate such permission if you have separately received it. 233 | 234 | d) If the work has interactive user interfaces, each must display 235 | Appropriate Legal Notices; however, if the Program has interactive 236 | interfaces that do not display Appropriate Legal Notices, your 237 | work need not make them do so. 238 | 239 | A compilation of a covered work with other separate and independent 240 | works, which are not by their nature extensions of the covered work, 241 | and which are not combined with it such as to form a larger program, 242 | in or on a volume of a storage or distribution medium, is called an 243 | "aggregate" if the compilation and its resulting copyright are not 244 | used to limit the access or legal rights of the compilation's users 245 | beyond what the individual works permit. Inclusion of a covered work 246 | in an aggregate does not cause this License to apply to the other 247 | parts of the aggregate. 248 | 249 | 6. Conveying Non-Source Forms. 250 | 251 | You may convey a covered work in object code form under the terms 252 | of sections 4 and 5, provided that you also convey the 253 | machine-readable Corresponding Source under the terms of this License, 254 | in one of these ways: 255 | 256 | a) Convey the object code in, or embodied in, a physical product 257 | (including a physical distribution medium), accompanied by the 258 | Corresponding Source fixed on a durable physical medium 259 | customarily used for software interchange. 260 | 261 | b) Convey the object code in, or embodied in, a physical product 262 | (including a physical distribution medium), accompanied by a 263 | written offer, valid for at least three years and valid for as 264 | long as you offer spare parts or customer support for that product 265 | model, to give anyone who possesses the object code either (1) a 266 | copy of the Corresponding Source for all the software in the 267 | product that is covered by this License, on a durable physical 268 | medium customarily used for software interchange, for a price no 269 | more than your reasonable cost of physically performing this 270 | conveying of source, or (2) access to copy the 271 | Corresponding Source from a network server at no charge. 272 | 273 | c) Convey individual copies of the object code with a copy of the 274 | written offer to provide the Corresponding Source. This 275 | alternative is allowed only occasionally and noncommercially, and 276 | only if you received the object code with such an offer, in accord 277 | with subsection 6b. 278 | 279 | d) Convey the object code by offering access from a designated 280 | place (gratis or for a charge), and offer equivalent access to the 281 | Corresponding Source in the same way through the same place at no 282 | further charge. You need not require recipients to copy the 283 | Corresponding Source along with the object code. If the place to 284 | copy the object code is a network server, the Corresponding Source 285 | may be on a different server (operated by you or a third party) 286 | that supports equivalent copying facilities, provided you maintain 287 | clear directions next to the object code saying where to find the 288 | Corresponding Source. Regardless of what server hosts the 289 | Corresponding Source, you remain obligated to ensure that it is 290 | available for as long as needed to satisfy these requirements. 291 | 292 | e) Convey the object code using peer-to-peer transmission, provided 293 | you inform other peers where the object code and Corresponding 294 | Source of the work are being offered to the general public at no 295 | charge under subsection 6d. 296 | 297 | A separable portion of the object code, whose source code is excluded 298 | from the Corresponding Source as a System Library, need not be 299 | included in conveying the object code work. 300 | 301 | A "User Product" is either (1) a "consumer product", which means any 302 | tangible personal property which is normally used for personal, family, 303 | or household purposes, or (2) anything designed or sold for incorporation 304 | into a dwelling. In determining whether a product is a consumer product, 305 | doubtful cases shall be resolved in favor of coverage. For a particular 306 | product received by a particular user, "normally used" refers to a 307 | typical or common use of that class of product, regardless of the status 308 | of the particular user or of the way in which the particular user 309 | actually uses, or expects or is expected to use, the product. A product 310 | is a consumer product regardless of whether the product has substantial 311 | commercial, industrial or non-consumer uses, unless such uses represent 312 | the only significant mode of use of the product. 313 | 314 | "Installation Information" for a User Product means any methods, 315 | procedures, authorization keys, or other information required to install 316 | and execute modified versions of a covered work in that User Product from 317 | a modified version of its Corresponding Source. The information must 318 | suffice to ensure that the continued functioning of the modified object 319 | code is in no case prevented or interfered with solely because 320 | modification has been made. 321 | 322 | If you convey an object code work under this section in, or with, or 323 | specifically for use in, a User Product, and the conveying occurs as 324 | part of a transaction in which the right of possession and use of the 325 | User Product is transferred to the recipient in perpetuity or for a 326 | fixed term (regardless of how the transaction is characterized), the 327 | Corresponding Source conveyed under this section must be accompanied 328 | by the Installation Information. But this requirement does not apply 329 | if neither you nor any third party retains the ability to install 330 | modified object code on the User Product (for example, the work has 331 | been installed in ROM). 332 | 333 | The requirement to provide Installation Information does not include a 334 | requirement to continue to provide support service, warranty, or updates 335 | for a work that has been modified or installed by the recipient, or for 336 | the User Product in which it has been modified or installed. Access to a 337 | network may be denied when the modification itself materially and 338 | adversely affects the operation of the network or violates the rules and 339 | protocols for communication across the network. 340 | 341 | Corresponding Source conveyed, and Installation Information provided, 342 | in accord with this section must be in a format that is publicly 343 | documented (and with an implementation available to the public in 344 | source code form), and must require no special password or key for 345 | unpacking, reading or copying. 346 | 347 | 7. Additional Terms. 348 | 349 | "Additional permissions" are terms that supplement the terms of this 350 | License by making exceptions from one or more of its conditions. 351 | Additional permissions that are applicable to the entire Program shall 352 | be treated as though they were included in this License, to the extent 353 | that they are valid under applicable law. If additional permissions 354 | apply only to part of the Program, that part may be used separately 355 | under those permissions, but the entire Program remains governed by 356 | this License without regard to the additional permissions. 357 | 358 | When you convey a copy of a covered work, you may at your option 359 | remove any additional permissions from that copy, or from any part of 360 | it. (Additional permissions may be written to require their own 361 | removal in certain cases when you modify the work.) You may place 362 | additional permissions on material, added by you to a covered work, 363 | for which you have or can give appropriate copyright permission. 364 | 365 | Notwithstanding any other provision of this License, for material you 366 | add to a covered work, you may (if authorized by the copyright holders of 367 | that material) supplement the terms of this License with terms: 368 | 369 | a) Disclaiming warranty or limiting liability differently from the 370 | terms of sections 15 and 16 of this License; or 371 | 372 | b) Requiring preservation of specified reasonable legal notices or 373 | author attributions in that material or in the Appropriate Legal 374 | Notices displayed by works containing it; or 375 | 376 | c) Prohibiting misrepresentation of the origin of that material, or 377 | requiring that modified versions of such material be marked in 378 | reasonable ways as different from the original version; or 379 | 380 | d) Limiting the use for publicity purposes of names of licensors or 381 | authors of the material; or 382 | 383 | e) Declining to grant rights under trademark law for use of some 384 | trade names, trademarks, or service marks; or 385 | 386 | f) Requiring indemnification of licensors and authors of that 387 | material by anyone who conveys the material (or modified versions of 388 | it) with contractual assumptions of liability to the recipient, for 389 | any liability that these contractual assumptions directly impose on 390 | those licensors and authors. 391 | 392 | All other non-permissive additional terms are considered "further 393 | restrictions" within the meaning of section 10. If the Program as you 394 | received it, or any part of it, contains a notice stating that it is 395 | governed by this License along with a term that is a further 396 | restriction, you may remove that term. If a license document contains 397 | a further restriction but permits relicensing or conveying under this 398 | License, you may add to a covered work material governed by the terms 399 | of that license document, provided that the further restriction does 400 | not survive such relicensing or conveying. 401 | 402 | If you add terms to a covered work in accord with this section, you 403 | must place, in the relevant source files, a statement of the 404 | additional terms that apply to those files, or a notice indicating 405 | where to find the applicable terms. 406 | 407 | Additional terms, permissive or non-permissive, may be stated in the 408 | form of a separately written license, or stated as exceptions; 409 | the above requirements apply either way. 410 | 411 | 8. Termination. 412 | 413 | You may not propagate or modify a covered work except as expressly 414 | provided under this License. Any attempt otherwise to propagate or 415 | modify it is void, and will automatically terminate your rights under 416 | this License (including any patent licenses granted under the third 417 | paragraph of section 11). 418 | 419 | However, if you cease all violation of this License, then your 420 | license from a particular copyright holder is reinstated (a) 421 | provisionally, unless and until the copyright holder explicitly and 422 | finally terminates your license, and (b) permanently, if the copyright 423 | holder fails to notify you of the violation by some reasonable means 424 | prior to 60 days after the cessation. 425 | 426 | Moreover, your license from a particular copyright holder is 427 | reinstated permanently if the copyright holder notifies you of the 428 | violation by some reasonable means, this is the first time you have 429 | received notice of violation of this License (for any work) from that 430 | copyright holder, and you cure the violation prior to 30 days after 431 | your receipt of the notice. 432 | 433 | Termination of your rights under this section does not terminate the 434 | licenses of parties who have received copies or rights from you under 435 | this License. If your rights have been terminated and not permanently 436 | reinstated, you do not qualify to receive new licenses for the same 437 | material under section 10. 438 | 439 | 9. Acceptance Not Required for Having Copies. 440 | 441 | You are not required to accept this License in order to receive or 442 | run a copy of the Program. Ancillary propagation of a covered work 443 | occurring solely as a consequence of using peer-to-peer transmission 444 | to receive a copy likewise does not require acceptance. However, 445 | nothing other than this License grants you permission to propagate or 446 | modify any covered work. These actions infringe copyright if you do 447 | not accept this License. Therefore, by modifying or propagating a 448 | covered work, you indicate your acceptance of this License to do so. 449 | 450 | 10. Automatic Licensing of Downstream Recipients. 451 | 452 | Each time you convey a covered work, the recipient automatically 453 | receives a license from the original licensors, to run, modify and 454 | propagate that work, subject to this License. You are not responsible 455 | for enforcing compliance by third parties with this License. 456 | 457 | An "entity transaction" is a transaction transferring control of an 458 | organization, or substantially all assets of one, or subdividing an 459 | organization, or merging organizations. If propagation of a covered 460 | work results from an entity transaction, each party to that 461 | transaction who receives a copy of the work also receives whatever 462 | licenses to the work the party's predecessor in interest had or could 463 | give under the previous paragraph, plus a right to possession of the 464 | Corresponding Source of the work from the predecessor in interest, if 465 | the predecessor has it or can get it with reasonable efforts. 466 | 467 | You may not impose any further restrictions on the exercise of the 468 | rights granted or affirmed under this License. For example, you may 469 | not impose a license fee, royalty, or other charge for exercise of 470 | rights granted under this License, and you may not initiate litigation 471 | (including a cross-claim or counterclaim in a lawsuit) alleging that 472 | any patent claim is infringed by making, using, selling, offering for 473 | sale, or importing the Program or any portion of it. 474 | 475 | 11. Patents. 476 | 477 | A "contributor" is a copyright holder who authorizes use under this 478 | License of the Program or a work on which the Program is based. The 479 | work thus licensed is called the contributor's "contributor version". 480 | 481 | A contributor's "essential patent claims" are all patent claims 482 | owned or controlled by the contributor, whether already acquired or 483 | hereafter acquired, that would be infringed by some manner, permitted 484 | by this License, of making, using, or selling its contributor version, 485 | but do not include claims that would be infringed only as a 486 | consequence of further modification of the contributor version. For 487 | purposes of this definition, "control" includes the right to grant 488 | patent sublicenses in a manner consistent with the requirements of 489 | this License. 490 | 491 | Each contributor grants you a non-exclusive, worldwide, royalty-free 492 | patent license under the contributor's essential patent claims, to 493 | make, use, sell, offer for sale, import and otherwise run, modify and 494 | propagate the contents of its contributor version. 495 | 496 | In the following three paragraphs, a "patent license" is any express 497 | agreement or commitment, however denominated, not to enforce a patent 498 | (such as an express permission to practice a patent or covenant not to 499 | sue for patent infringement). To "grant" such a patent license to a 500 | party means to make such an agreement or commitment not to enforce a 501 | patent against the party. 502 | 503 | If you convey a covered work, knowingly relying on a patent license, 504 | and the Corresponding Source of the work is not available for anyone 505 | to copy, free of charge and under the terms of this License, through a 506 | publicly available network server or other readily accessible means, 507 | then you must either (1) cause the Corresponding Source to be so 508 | available, or (2) arrange to deprive yourself of the benefit of the 509 | patent license for this particular work, or (3) arrange, in a manner 510 | consistent with the requirements of this License, to extend the patent 511 | license to downstream recipients. "Knowingly relying" means you have 512 | actual knowledge that, but for the patent license, your conveying the 513 | covered work in a country, or your recipient's use of the covered work 514 | in a country, would infringe one or more identifiable patents in that 515 | country that you have reason to believe are valid. 516 | 517 | If, pursuant to or in connection with a single transaction or 518 | arrangement, you convey, or propagate by procuring conveyance of, a 519 | covered work, and grant a patent license to some of the parties 520 | receiving the covered work authorizing them to use, propagate, modify 521 | or convey a specific copy of the covered work, then the patent license 522 | you grant is automatically extended to all recipients of the covered 523 | work and works based on it. 524 | 525 | A patent license is "discriminatory" if it does not include within 526 | the scope of its coverage, prohibits the exercise of, or is 527 | conditioned on the non-exercise of one or more of the rights that are 528 | specifically granted under this License. You may not convey a covered 529 | work if you are a party to an arrangement with a third party that is 530 | in the business of distributing software, under which you make payment 531 | to the third party based on the extent of your activity of conveying 532 | the work, and under which the third party grants, to any of the 533 | parties who would receive the covered work from you, a discriminatory 534 | patent license (a) in connection with copies of the covered work 535 | conveyed by you (or copies made from those copies), or (b) primarily 536 | for and in connection with specific products or compilations that 537 | contain the covered work, unless you entered into that arrangement, 538 | or that patent license was granted, prior to 28 March 2007. 539 | 540 | Nothing in this License shall be construed as excluding or limiting 541 | any implied license or other defenses to infringement that may 542 | otherwise be available to you under applicable patent law. 543 | 544 | 12. No Surrender of Others' Freedom. 545 | 546 | If conditions are imposed on you (whether by court order, agreement or 547 | otherwise) that contradict the conditions of this License, they do not 548 | excuse you from the conditions of this License. If you cannot convey a 549 | covered work so as to satisfy simultaneously your obligations under this 550 | License and any other pertinent obligations, then as a consequence you may 551 | not convey it at all. For example, if you agree to terms that obligate you 552 | to collect a royalty for further conveying from those to whom you convey 553 | the Program, the only way you could satisfy both those terms and this 554 | License would be to refrain entirely from conveying the Program. 555 | 556 | 13. Remote Network Interaction; Use with the GNU General Public License. 557 | 558 | Notwithstanding any other provision of this License, if you modify the 559 | Program, your modified version must prominently offer all users 560 | interacting with it remotely through a computer network (if your version 561 | supports such interaction) an opportunity to receive the Corresponding 562 | Source of your version by providing access to the Corresponding Source 563 | from a network server at no charge, through some standard or customary 564 | means of facilitating copying of software. This Corresponding Source 565 | shall include the Corresponding Source for any work covered by version 3 566 | of the GNU General Public License that is incorporated pursuant to the 567 | following paragraph. 568 | 569 | Notwithstanding any other provision of this License, you have 570 | permission to link or combine any covered work with a work licensed 571 | under version 3 of the GNU General Public License into a single 572 | combined work, and to convey the resulting work. The terms of this 573 | License will continue to apply to the part which is the covered work, 574 | but the work with which it is combined will remain governed by version 575 | 3 of the GNU General Public License. 576 | 577 | 14. Revised Versions of this License. 578 | 579 | The Free Software Foundation may publish revised and/or new versions of 580 | the GNU Affero General Public License from time to time. Such new versions 581 | will be similar in spirit to the present version, but may differ in detail to 582 | address new problems or concerns. 583 | 584 | Each version is given a distinguishing version number. If the 585 | Program specifies that a certain numbered version of the GNU Affero General 586 | Public License "or any later version" applies to it, you have the 587 | option of following the terms and conditions either of that numbered 588 | version or of any later version published by the Free Software 589 | Foundation. If the Program does not specify a version number of the 590 | GNU Affero General Public License, you may choose any version ever published 591 | by the Free Software Foundation. 592 | 593 | If the Program specifies that a proxy can decide which future 594 | versions of the GNU Affero General Public License can be used, that proxy's 595 | public statement of acceptance of a version permanently authorizes you 596 | to choose that version for the Program. 597 | 598 | Later license versions may give you additional or different 599 | permissions. However, no additional obligations are imposed on any 600 | author or copyright holder as a result of your choosing to follow a 601 | later version. 602 | 603 | 15. Disclaimer of Warranty. 604 | 605 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 606 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 607 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 608 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 609 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 610 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 611 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 612 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 613 | 614 | 16. Limitation of Liability. 615 | 616 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 617 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 618 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 619 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 620 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 621 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 622 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 623 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 624 | SUCH DAMAGES. 625 | 626 | 17. Interpretation of Sections 15 and 16. 627 | 628 | If the disclaimer of warranty and limitation of liability provided 629 | above cannot be given local legal effect according to their terms, 630 | reviewing courts shall apply local law that most closely approximates 631 | an absolute waiver of all civil liability in connection with the 632 | Program, unless a warranty or assumption of liability accompanies a 633 | copy of the Program in return for a fee. 634 | 635 | END OF TERMS AND CONDITIONS 636 | 637 | How to Apply These Terms to Your New Programs 638 | 639 | If you develop a new program, and you want it to be of the greatest 640 | possible use to the public, the best way to achieve this is to make it 641 | free software which everyone can redistribute and change under these terms. 642 | 643 | To do so, attach the following notices to the program. It is safest 644 | to attach them to the start of each source file to most effectively 645 | state the exclusion of warranty; and each file should have at least 646 | the "copyright" line and a pointer to where the full notice is found. 647 | 648 | 649 | Copyright (C) 650 | 651 | This program is free software: you can redistribute it and/or modify 652 | it under the terms of the GNU Affero General Public License as published by 653 | the Free Software Foundation, either version 3 of the License, or 654 | (at your option) any later version. 655 | 656 | This program is distributed in the hope that it will be useful, 657 | but WITHOUT ANY WARRANTY; without even the implied warranty of 658 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 659 | GNU Affero General Public License for more details. 660 | 661 | You should have received a copy of the GNU Affero General Public License 662 | along with this program. If not, see . 663 | 664 | Also add information on how to contact you by electronic and paper mail. 665 | 666 | If your software can interact with users remotely through a computer 667 | network, you should also make sure that it provides a way for users to 668 | get its source. For example, if your program is a web application, its 669 | interface could display a "Source" link that leads users to an archive 670 | of the code. There are many ways you could offer source, and different 671 | solutions will be better for different programs; see section 13 for the 672 | specific requirements. 673 | 674 | You should also get your employer (if you work as a programmer) or school, 675 | if any, to sign a "copyright disclaimer" for the program, if necessary. 676 | For more information on this, and how to apply and follow the GNU AGPL, see 677 | . 678 | 679 | 680 | -------------------------------------------------------------------------------- /docs/SUPPORTED_GATEWAYS: -------------------------------------------------------------------------------- 1 | SUPPORTED GATEWAYS 2 | ------------------ 3 | 4 | SMStoXMPP has been written to support the use of multiple different gateway devices 5 | by means of a plugin system making it easy to add new systems. 6 | 7 | 8 | The following is a list of currently supported gateways: 9 | 10 | SMS Gateway by APK Soft s.r.o 11 | https://play.google.com/store/apps/details?id=eu.apksoft.android.smsgateway&hl=en 12 | 13 | 14 | For details on configuring these gateways, please refer to: 15 | https://projects.jethrocarr.com/p/oss-smstoxmpp/page/Gateway-Guide/ 16 | 17 | For details on writing new gateways, prefer refer to: 18 | https://projects.jethrocarr.com/p/oss-smstoxmpp/page/Developer-GatewaySupport/ 19 | 20 | -------------------------------------------------------------------------------- /resources/easypackage.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl -w 2 | # 3 | # easypackage.pl 4 | # 5 | # (C) Copyright 2009 Amberdms Ltd 6 | # This utility is licensed under the GNU AGPL Version 3.0 7 | # 8 | # This utility makes it easy to build packages from your unpacked source tree. 9 | # 10 | # It make a copy of the source, remove any CVS folders, rename it to the 11 | # desired version, rename .spec file to the desired version, then finally 12 | # it will tar & bzip it. 13 | # 14 | # Then you can choose to copy the required files to /usr/src/redhat/ in 15 | # order to build an RPM. 16 | # 17 | # 18 | # 19 | 20 | use strict; 21 | 22 | ## SETTINGS ## 23 | my $input; 24 | 25 | 26 | ## PROGRAM ## 27 | 28 | 29 | if ($0 ne "./easypackage.pl") 30 | { 31 | die("Error: Please run this script from within it's directory. (./easypackage)\n"); 32 | } 33 | 34 | # change down to the root of the source tree. 35 | chdir("../") || die("Error: Package is not in expected form.\n"); 36 | 37 | 38 | # get version 39 | print "Please enter version (eg: 20080419_beta0):\n"; 40 | my $version = get_question('^\S*$'); 41 | 42 | # determine final name 43 | my $name_base = "smstoxmpp"; 44 | my $name_withversion = "smstoxmpp-$version"; 45 | 46 | 47 | 48 | # make sure destination data does not exist. 49 | if (-e "/tmp/$name_withversion" || -e "/tmp/$name_withversion.tar.bz2") 50 | { 51 | print "Warning: The dir or tarball /tmp/$name_withversion already exists. Do you wish to replace it? (y/n)\n"; 52 | $input = get_question('^[y|n]$'); 53 | 54 | if ($input eq "n") 55 | { 56 | print "No changes have been made\n"; 57 | exit 0; 58 | } 59 | 60 | system("rm -rf /tmp/$name_base*"); 61 | } 62 | 63 | # create new dir 64 | system("mkdir /tmp/$name_withversion"); 65 | system("cp -avr * /tmp/$name_withversion/"); 66 | 67 | # we have finished with the orignal source 68 | chdir("/tmp"); 69 | 70 | # remove SVN/GIT stuff 71 | system("find $name_withversion/* -type d | grep .svn | sed \"s/^/rm -rf /\" | sh"); 72 | system("find $name_withversion/* -type d | grep .git | sed \"s/^/rm -rf /\" | sh"); 73 | 74 | # remove a config file if one exists 75 | system("rm -f $name_withversion/app/config/config.ini"); 76 | 77 | # insert version into spec file and write changed version to /tmp/ location 78 | open(IN, "$name_withversion/resources/$name_base.spec") || die("Unable to open spec file"); 79 | open(OUT, ">/tmp/$name_base.spec") || die("Unable to open /tmp/$name_base.spec"); 80 | 81 | while (my $line = ) 82 | { 83 | if ($line =~ /^Version:/) 84 | { 85 | $line = "Version: $version\n"; 86 | } 87 | 88 | print OUT $line; 89 | } 90 | close(IN); 91 | close(OUT); 92 | 93 | 94 | # create tarball. 95 | system("tar -cjvf $name_withversion.tar.bz2 $name_withversion"); 96 | 97 | # remove source dir 98 | system("rm -rf $name_withversion/"); 99 | 100 | 101 | 102 | # transfer RPM components to correct location? 103 | print "Would you like to place source + spec into /usr/src/redhat?\n"; 104 | $input = get_question('^[y|n]$'); 105 | 106 | if ($input eq "y") 107 | { 108 | system("cp $name_withversion.tar.bz2 /usr/src/redhat/SOURCES/"); 109 | system("cp $name_base.spec /usr/src/redhat/SPECS/"); 110 | 111 | print "Execute rpmbuild -ba /usr/src/redhat/SPECS/$name_base.spec to build RPM.\n"; 112 | } 113 | 114 | 115 | 116 | print "Complete!\n"; 117 | print "\n"; 118 | print "Tarball:\t/tmp/$name_withversion.tar.bz2\n"; 119 | print "Spec:\t/tmp/$name_base.spec\n"; 120 | exit 0; 121 | 122 | 123 | ### FUNCTIONS ### 124 | 125 | # get_question 126 | # 127 | # Gets user input from CLI and does verification 128 | # 129 | sub get_question { 130 | my $regex = shift; 131 | my $complete = 0; 132 | 133 | 134 | while (!$complete) 135 | { 136 | my $input = ; 137 | chomp($input); 138 | 139 | if ($input =~ /$regex/) 140 | { 141 | return $input; 142 | } 143 | else 144 | { 145 | print "Invalid input! Please re-enter.\n"; 146 | print "Retry: "; 147 | } 148 | } 149 | 150 | } 151 | 152 | 153 | -------------------------------------------------------------------------------- /resources/smstoxmpp-httpdconfig.conf: -------------------------------------------------------------------------------- 1 | # 2 | # This is the listener component for the SMStoXMPP application, a daemon 3 | # which exchanges messages between SMS gateways and XMPP servers 4 | # 5 | Alias /smstoxmpp /usr/share/smstoxmpp/app/listener.php 6 | 7 | 8 | Order deny,allow 9 | Allow from all 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /resources/smstoxmpp.spec: -------------------------------------------------------------------------------- 1 | Summary: A daemon to exchange messages between SMS gateway devices and XMPP 2 | Name: smstoxmpp 3 | Version: 1.0.0 4 | Release: 7%{dist} 5 | License: AGPLv3 6 | URL: http://projects.jethrocarr.com/p/oss-smstoxmpp 7 | Group: Applications/Internet 8 | Source0: smstoxmpp-%{version}.tar.bz2 9 | 10 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) 11 | BuildArch: noarch 12 | BuildRequires: gettext 13 | 14 | Requires: httpd 15 | Requires: php >= 5.1.0, php-xml, php-cli, php-process 16 | 17 | 18 | %description 19 | SMStoXMPP is a daemon which provides a gateway for exchange messages between 20 | SMS gateways and XMPP accounts. 21 | 22 | 23 | %prep 24 | %setup -q -n smstoxmpp-%{version} 25 | 26 | %build 27 | 28 | 29 | %install 30 | rm -rf $RPM_BUILD_ROOT 31 | mkdir -p -m0755 $RPM_BUILD_ROOT%{_sysconfdir}/smstoxmpp/ 32 | mkdir -p -m0755 $RPM_BUILD_ROOT%{_datadir}/smstoxmpp/ 33 | 34 | # install application files and resources 35 | cp -pr * $RPM_BUILD_ROOT%{_datadir}/smstoxmpp/ 36 | 37 | 38 | # install configuration file 39 | install -m0700 app/config/sample_config.ini $RPM_BUILD_ROOT%{_sysconfdir}/smstoxmpp/config.ini 40 | ln -s %{_sysconfdir}/smstoxmpp/config.ini $RPM_BUILD_ROOT%{_datadir}/smstoxmpp/app/config/config.ini 41 | 42 | # install the apache configuration file 43 | mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/httpd/conf.d 44 | install -m 644 resources/smstoxmpp-httpdconfig.conf $RPM_BUILD_ROOT%{_sysconfdir}/httpd/conf.d/smstoxmpp.conf 45 | 46 | # symlink the daemon 47 | mkdir -p $RPM_BUILD_ROOT%{_bindir}/ 48 | ln -s %{_datadir}/smstoxmpp/app/dispatcher.php $RPM_BUILD_ROOT%{_bindir}/smstoxmppd 49 | 50 | # install the daemon bootscript 51 | mkdir -p $RPM_BUILD_ROOT/etc/init.d/ 52 | mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/lib/smstoxmpp/ 53 | install -m 755 resources/smstoxmppd.rcsysinit $RPM_BUILD_ROOT/etc/init.d/smstoxmppd 54 | 55 | 56 | %post 57 | 58 | # Reload apache 59 | echo "Reloading httpd..." 60 | /etc/init.d/httpd reload 61 | 62 | # Restart SMStoXMPP upon install 63 | if [ $1 == 0 ]; 64 | then 65 | echo "Restarting daemon process..." 66 | /etc/init.d/smstoxmppd restart 67 | fi 68 | 69 | 70 | %clean 71 | rm -rf $RPM_BUILD_ROOT 72 | 73 | %files 74 | %defattr(-,root,root) 75 | %config %dir %{_sysconfdir}/smstoxmpp 76 | %attr(770,root,apache) %config(noreplace) %{_sysconfdir}/smstoxmpp/config.ini 77 | %attr(660,root,apache) %config(noreplace) %{_sysconfdir}/httpd/conf.d/smstoxmpp.conf 78 | %{_datadir}/smstoxmpp/app 79 | %{_datadir}/smstoxmpp/resources 80 | %{_datadir}/smstoxmpp/docs/ 81 | %{_bindir}/smstoxmppd 82 | /etc/init.d/smstoxmppd 83 | %attr(775,root,root) %{_localstatedir}/lib/smstoxmpp 84 | %docdir %{_datadir}/smstoxmpp/docs/ 85 | 86 | 87 | %changelog 88 | * Sun Jun 2 2013 Jethro Carr 1.0.0-7 89 | - First stable release 90 | * Mon Mar 11 2013 Jethro Carr 0.0.1-1 91 | - Pre-alpha release for testing & bug fixing 92 | 93 | -------------------------------------------------------------------------------- /resources/smstoxmppd.rcsysinit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # smstoxmppd Daemon that delivers messages between SMS gateways and XMPP 4 | # 5 | # chkconfig: 2345 87 9 6 | # description: smstoxmppd SMStoXMPP message delivery daemon 7 | # 8 | 9 | PROG=/usr/bin/smstoxmppd 10 | CONFIG=/etc/smstoxmpp/config.ini 11 | ARGS="-D -c $CONFIG" 12 | 13 | # Source function library. 14 | . /etc/rc.d/init.d/functions 15 | 16 | 17 | start() 18 | { 19 | echo -n $"Starting smstoxmppd:" 20 | daemon $PROG $ARGS 21 | RETVAL=$? 22 | echo "" 23 | return $RETVAL 24 | } 25 | 26 | stop() 27 | { 28 | echo -n "Stopping smstoxmppd:" 29 | killproc $PROG 30 | RETVAL=$? 31 | echo "" 32 | return $RETVAL 33 | } 34 | 35 | case "$1" in 36 | start) 37 | start 38 | ;; 39 | stop) 40 | stop 41 | ;; 42 | restart|reload) 43 | stop 44 | start 45 | ;; 46 | status) 47 | status smstoxmppd 48 | ;; 49 | *) 50 | echo $"Usage: $0 {start|stop|status|restart}" 51 | exit 1 52 | ;; 53 | esac 54 | 55 | exit 0 56 | 57 | 58 | --------------------------------------------------------------------------------