Postie - Version 1.1.5

Version Description

Download this release

Release Info

Developer robfelty
Plugin Icon 128x128 Postie
Version 1.1.5
Comparing to
See all releases

Version 1.1.5

COPYING ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 2, June 1991
3
+
4
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5
+ 675 Mass Ave, Cambridge, MA 02139, USA
6
+ Everyone is permitted to copy and distribute verbatim copies
7
+ of this license document, but changing it is not allowed.
8
+
9
+ Preamble
10
+
11
+ The licenses for most software are designed to take away your
12
+ freedom to share and change it. By contrast, the GNU General Public
13
+ License is intended to guarantee your freedom to share and change free
14
+ software--to make sure the software is free for all its users. This
15
+ General Public License applies to most of the Free Software
16
+ Foundation's software and to any other program whose authors commit to
17
+ using it. (Some other Free Software Foundation software is covered by
18
+ the GNU Library General Public License instead.) You can apply it to
19
+ your programs, too.
20
+
21
+ When we speak of free software, we are referring to freedom, not
22
+ price. Our General Public Licenses are designed to make sure that you
23
+ have the freedom to distribute copies of free software (and charge for
24
+ this service if you wish), that you receive source code or can get it
25
+ if you want it, that you can change the software or use pieces of it
26
+ in new free programs; and that you know you can do these things.
27
+
28
+ To protect your rights, we need to make restrictions that forbid
29
+ anyone to deny you these rights or to ask you to surrender the rights.
30
+ These restrictions translate to certain responsibilities for you if you
31
+ distribute copies of the software, or if you modify it.
32
+
33
+ For example, if you distribute copies of such a program, whether
34
+ gratis or for a fee, you must give the recipients all the rights that
35
+ you have. You must make sure that they, too, receive or can get the
36
+ source code. And you must show them these terms so they know their
37
+ rights.
38
+
39
+ We protect your rights with two steps: (1) copyright the software, and
40
+ (2) offer you this license which gives you legal permission to copy,
41
+ distribute and/or modify the software.
42
+
43
+ Also, for each author's protection and ours, we want to make certain
44
+ that everyone understands that there is no warranty for this free
45
+ software. If the software is modified by someone else and passed on, we
46
+ want its recipients to know that what they have is not the original, so
47
+ that any problems introduced by others will not reflect on the original
48
+ authors' reputations.
49
+
50
+ Finally, any free program is threatened constantly by software
51
+ patents. We wish to avoid the danger that redistributors of a free
52
+ program will individually obtain patent licenses, in effect making the
53
+ program proprietary. To prevent this, we have made it clear that any
54
+ patent must be licensed for everyone's free use or not licensed at all.
55
+
56
+ The precise terms and conditions for copying, distribution and
57
+ modification follow.
58
+
59
+ GNU GENERAL PUBLIC LICENSE
60
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61
+
62
+ 0. This License applies to any program or other work which contains
63
+ a notice placed by the copyright holder saying it may be distributed
64
+ under the terms of this General Public License. The "Program", below,
65
+ refers to any such program or work, and a "work based on the Program"
66
+ means either the Program or any derivative work under copyright law:
67
+ that is to say, a work containing the Program or a portion of it,
68
+ either verbatim or with modifications and/or translated into another
69
+ language. (Hereinafter, translation is included without limitation in
70
+ the term "modification".) Each licensee is addressed as "you".
71
+
72
+ Activities other than copying, distribution and modification are not
73
+ covered by this License; they are outside its scope. The act of
74
+ running the Program is not restricted, and the output from the Program
75
+ is covered only if its contents constitute a work based on the
76
+ Program (independent of having been made by running the Program).
77
+ Whether that is true depends on what the Program does.
78
+
79
+ 1. You may copy and distribute verbatim copies of the Program's
80
+ source code as you receive it, in any medium, provided that you
81
+ conspicuously and appropriately publish on each copy an appropriate
82
+ copyright notice and disclaimer of warranty; keep intact all the
83
+ notices that refer to this License and to the absence of any warranty;
84
+ and give any other recipients of the Program a copy of this License
85
+ along with the Program.
86
+
87
+ You may charge a fee for the physical act of transferring a copy, and
88
+ you may at your option offer warranty protection in exchange for a fee.
89
+
90
+ 2. You may modify your copy or copies of the Program or any portion
91
+ of it, thus forming a work based on the Program, and copy and
92
+ distribute such modifications or work under the terms of Section 1
93
+ above, provided that you also meet all of these conditions:
94
+
95
+ a) You must cause the modified files to carry prominent notices
96
+ stating that you changed the files and the date of any change.
97
+
98
+ b) You must cause any work that you distribute or publish, that in
99
+ whole or in part contains or is derived from the Program or any
100
+ part thereof, to be licensed as a whole at no charge to all third
101
+ parties under the terms of this License.
102
+
103
+ c) If the modified program normally reads commands interactively
104
+ when run, you must cause it, when started running for such
105
+ interactive use in the most ordinary way, to print or display an
106
+ announcement including an appropriate copyright notice and a
107
+ notice that there is no warranty (or else, saying that you provide
108
+ a warranty) and that users may redistribute the program under
109
+ these conditions, and telling the user how to view a copy of this
110
+ License. (Exception: if the Program itself is interactive but
111
+ does not normally print such an announcement, your work based on
112
+ the Program is not required to print an announcement.)
113
+
114
+ These requirements apply to the modified work as a whole. If
115
+ identifiable sections of that work are not derived from the Program,
116
+ and can be reasonably considered independent and separate works in
117
+ themselves, then this License, and its terms, do not apply to those
118
+ sections when you distribute them as separate works. But when you
119
+ distribute the same sections as part of a whole which is a work based
120
+ on the Program, the distribution of the whole must be on the terms of
121
+ this License, whose permissions for other licensees extend to the
122
+ entire whole, and thus to each and every part regardless of who wrote it.
123
+ Thus, it is not the intent of this section to claim rights or contest
124
+ your rights to work written entirely by you; rather, the intent is to
125
+ exercise the right to control the distribution of derivative or
126
+ collective works based on the Program.
127
+
128
+ In addition, mere aggregation of another work not based on the Program
129
+ with the Program (or with a work based on the Program) on a volume of
130
+ a storage or distribution medium does not bring the other work under
131
+ the scope of this License.
132
+
133
+ 3. You may copy and distribute the Program (or a work based on it,
134
+ under Section 2) in object code or executable form under the terms of
135
+ Sections 1 and 2 above provided that you also do one of the following:
136
+
137
+ a) Accompany it with the complete corresponding machine-readable
138
+ source code, which must be distributed under the terms of Sections
139
+ 1 and 2 above on a medium customarily used for software interchange; or,
140
+
141
+ b) Accompany it with a written offer, valid for at least three
142
+ years, to give any third party, for a charge no more than your
143
+ cost of physically performing source distribution, a complete
144
+ machine-readable copy of the corresponding source code, to be
145
+ distributed under the terms of Sections 1 and 2 above on a medium
146
+ customarily used for software interchange; or,
147
+
148
+ c) Accompany it with the information you received as to the offer
149
+ to distribute corresponding source code. (This alternative is
150
+ allowed only for noncommercial distribution and only if you
151
+ received the program in object code or executable form with such
152
+ an offer, in accord with Subsection b above.)
153
+
154
+ The source code for a work means the preferred form of the work for
155
+ making modifications to it. For an executable work, complete source
156
+ code means all the source code for all modules it contains, plus any
157
+ associated interface definition files, plus the scripts used to
158
+ control compilation and installation of the executable. However, as a
159
+ special exception, the source code distributed need not include
160
+ anything that is normally distributed (in either source or binary
161
+ form) with the major components (compiler, kernel, and so on) of the
162
+ operating system on which the executable runs, unless that component
163
+ itself accompanies the executable.
164
+
165
+ If distribution of executable or object code is made by offering
166
+ access to copy from a designated place, then offering equivalent
167
+ access to copy the source code from the same place counts as
168
+ distribution of the source code, even though third parties are not
169
+ compelled to copy the source along with the object code.
170
+
171
+ 4. You may not copy, modify, sublicense, or distribute the Program
172
+ except as expressly provided under this License. Any attempt
173
+ otherwise to copy, modify, sublicense or distribute the Program is
174
+ void, and will automatically terminate your rights under this License.
175
+ However, parties who have received copies, or rights, from you under
176
+ this License will not have their licenses terminated so long as such
177
+ parties remain in full compliance.
178
+
179
+ 5. You are not required to accept this License, since you have not
180
+ signed it. However, nothing else grants you permission to modify or
181
+ distribute the Program or its derivative works. These actions are
182
+ prohibited by law if you do not accept this License. Therefore, by
183
+ modifying or distributing the Program (or any work based on the
184
+ Program), you indicate your acceptance of this License to do so, and
185
+ all its terms and conditions for copying, distributing or modifying
186
+ the Program or works based on it.
187
+
188
+ 6. Each time you redistribute the Program (or any work based on the
189
+ Program), the recipient automatically receives a license from the
190
+ original licensor to copy, distribute or modify the Program subject to
191
+ these terms and conditions. You may not impose any further
192
+ restrictions on the recipients' exercise of the rights granted herein.
193
+ You are not responsible for enforcing compliance by third parties to
194
+ this License.
195
+
196
+ 7. If, as a consequence of a court judgment or allegation of patent
197
+ infringement or for any other reason (not limited to patent issues),
198
+ conditions are imposed on you (whether by court order, agreement or
199
+ otherwise) that contradict the conditions of this License, they do not
200
+ excuse you from the conditions of this License. If you cannot
201
+ distribute so as to satisfy simultaneously your obligations under this
202
+ License and any other pertinent obligations, then as a consequence you
203
+ may not distribute the Program at all. For example, if a patent
204
+ license would not permit royalty-free redistribution of the Program by
205
+ all those who receive copies directly or indirectly through you, then
206
+ the only way you could satisfy both it and this License would be to
207
+ refrain entirely from distribution of the Program.
208
+
209
+ If any portion of this section is held invalid or unenforceable under
210
+ any particular circumstance, the balance of the section is intended to
211
+ apply and the section as a whole is intended to apply in other
212
+ circumstances.
213
+
214
+ It is not the purpose of this section to induce you to infringe any
215
+ patents or other property right claims or to contest validity of any
216
+ such claims; this section has the sole purpose of protecting the
217
+ integrity of the free software distribution system, which is
218
+ implemented by public license practices. Many people have made
219
+ generous contributions to the wide range of software distributed
220
+ through that system in reliance on consistent application of that
221
+ system; it is up to the author/donor to decide if he or she is willing
222
+ to distribute software through any other system and a licensee cannot
223
+ impose that choice.
224
+
225
+ This section is intended to make thoroughly clear what is believed to
226
+ be a consequence of the rest of this License.
227
+
228
+ 8. If the distribution and/or use of the Program is restricted in
229
+ certain countries either by patents or by copyrighted interfaces, the
230
+ original copyright holder who places the Program under this License
231
+ may add an explicit geographical distribution limitation excluding
232
+ those countries, so that distribution is permitted only in or among
233
+ countries not thus excluded. In such case, this License incorporates
234
+ the limitation as if written in the body of this License.
235
+
236
+ 9. The Free Software Foundation may publish revised and/or new versions
237
+ of the General Public License from time to time. Such new versions will
238
+ be similar in spirit to the present version, but may differ in detail to
239
+ address new problems or concerns.
240
+
241
+ Each version is given a distinguishing version number. If the Program
242
+ specifies a version number of this License which applies to it and "any
243
+ later version", you have the option of following the terms and conditions
244
+ either of that version or of any later version published by the Free
245
+ Software Foundation. If the Program does not specify a version number of
246
+ this License, you may choose any version ever published by the Free Software
247
+ Foundation.
248
+
249
+ 10. If you wish to incorporate parts of the Program into other free
250
+ programs whose distribution conditions are different, write to the author
251
+ to ask for permission. For software which is copyrighted by the Free
252
+ Software Foundation, write to the Free Software Foundation; we sometimes
253
+ make exceptions for this. Our decision will be guided by the two goals
254
+ of preserving the free status of all derivatives of our free software and
255
+ of promoting the sharing and reuse of software generally.
256
+
257
+ NO WARRANTY
258
+
259
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
260
+ FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
261
+ OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
262
+ PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
263
+ OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
264
+ MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
265
+ TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
266
+ PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
267
+ REPAIR OR CORRECTION.
268
+
269
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
270
+ WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
271
+ REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
272
+ INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
273
+ OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
274
+ TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
275
+ YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
276
+ PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
277
+ POSSIBILITY OF SUCH DAMAGES.
278
+
279
+ END OF TERMS AND CONDITIONS
280
+
CREDITS ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2003-2005 The Wordpress Team
2
+ Copyright (c) 2004-2005 - John B. Hewitt - jb@stcpl.com.au
3
+ Copyright (c) 2004 - Dan Cech - dcech@lansmash.com
4
+ Copyright (c) 2005 - Dirk Elmendorf - dirk@economysizegeek.com
5
+ Copyright (c) 2005 - David Luden
6
+ Copyright (c) 2005 - Adrian Heydecker - http://wavestyle.ch
7
+ Copyright (c) 2005 - Jay Talbot - webmaster@jaytalbot.com
8
+
9
+ Licensed under the GNU GPL. For full terms see the file COPYING
HISTORY ADDED
@@ -0,0 +1,300 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -= History =-
2
+ Below is all the of the version information. As far as I can tell there once was a guy named John Blade. He took some of the orignal wp-mail.php code and started hacking away on it. He actually got pretty far. About the time I discovered WordPress and his little hack - called WP-Mail at the time - he went on a vacation or something. There were some problems with the script, and it was missing some features I wanted. I hacked away at it and got it into a place where it did what I wanted. I started posting about it since I figured other people might want the features.
3
+
4
+ John didn't release any more versions at least up til July 2005. So I started accepting submissions and feature requests from people to help make the code better. In June/July 2005 I discovered a little plugin by Chris J Davis (http://www.chrisjdavis.org/cjd-notepad/) called notepad. I added a small feature to it (basically a bookmarklet). In the process I started looking at his code and realized how much you could do with the plugin system available in Word Press.
5
+
6
+ So I decided to make an offical fork. I put up an article on my blog asking for new names. I picked Postie. I then modified the code to be a proper plugin. And the rest is history :)
7
+
8
+ Version 1.1.2 (robfelty@gmail.com) 2008.07.12
9
+ - allow negative delays
10
+ - will glean author information from forwarded or redirected e-mails
11
+ - replying to an e-mail adds a comment to a post
12
+ - fixed category handling to work with taxonomy
13
+ - fixed one syntax error
14
+ - added option to wrap posts and comments in <pre> tags
15
+
16
+ Version 1.1.1
17
+ BUGFIX -problem with subject
18
+ BUGFIX -cronless postie typo
19
+
20
+ Version 1.1
21
+ FEATURE: Updated and tested with WordPress 2.1
22
+ BUGFIX:Removed deprecated functions
23
+ FEATURE: Cronless Postie now uses the WordPress native Psuedo Cron.
24
+
25
+ Version 1.0
26
+ BUGFIX: TestWPVersion broke with 2.1
27
+ FEATURE: end: now marks the end of a message (Dan Cunningham)
28
+ FEATURE: Better Readme (Michael Rasmussen)
29
+ FEATURE: Smart Sharpen Option -EXPERIMENTAL- (Jonas Rhodin)
30
+ BUGFIX: Issue with google imap fixed (Jim Hodgson)
31
+ BUGFIX: Fixed espacing issue in subjects (Paul Clip)
32
+ BUGFIX: Typo in Div fixed (phil)
33
+
34
+ Version 0.9.9.3.2
35
+ BUGFIX: Typo
36
+ Version 0.9.9.3.1
37
+ BUGFIX: Removed debugging code
38
+
39
+ Version 0.9.9.3
40
+ BUGFIX: If your email address matches an existing user - then it will post as that user - even if you allow anyone to post.
41
+ BUGFIX: Replaced get_settings('home') with get_settings('siteurl')
42
+ BUGFIX: Better handling for Japanese charactersets - Thanks to http://www.souzouzone.jp/blog/archives/009531.html
43
+ BUGFIX: Better thumbnail window opening code - thanks to Gabi & Duntello!
44
+ FEATURE: Added an option to set the MAX Height of an image - idea from Duntello
45
+ BUGFIX: Modified the FilterNewLines for better flowed text handling - You now HAVE TO PUT TWO NEW LINES to end a paragraph.
46
+ FEATURE: Added new CSS tags to support positioning images/attachments/3gp videos
47
+ BUGFIX: Tries to use the date in the message (Thanks Ravan) I tried this once before and it never worked - hopefully this time it will.
48
+ BUGFIX: Added a workaround to fix the problem with Subscribe2 - it will now notify on posts that are not set to show up in the future.
49
+
50
+
51
+
52
+ Version 0.9.9.2
53
+ BUGFIX: Looks for the NOOP error and disgards it
54
+ FEATURE: Postie now detects the version of WordPress being used
55
+ FEATURE: Smarter Parsing of VodaPhone
56
+ FEATURE: Easy place to add new code to handle other brain-dead mail clients
57
+ BUGFIX: Handles insertion of single quotes properly
58
+ BUGFIX: Thumbnails should now link properly
59
+
60
+ Version 0.9.9.1
61
+ BUGFIX: Needed a strtolower in places to catch all iso-8859 - thx to Gitte Wange for the catch
62
+ BUGFIX: Fixed issue with the category not being posted properly
63
+
64
+ Version 0.9.9
65
+ UPDATE TO WP 2.0
66
+ BUGFIX: Config Page now works
67
+ FEATURES: Supports role based posting
68
+ BUGFIX: Posting updates the category counts.
69
+
70
+ Version 0.9.8.6
71
+ BUGFIX: Fixed problems with config page <%php became <?php
72
+
73
+ Version 0.9.8.5
74
+ BUGFIX: onClick changed to onclick
75
+ BUGFIX: strolower added to test for iso - thanks daniele
76
+ BUGFIX: Added a class to the 3gp video tags
77
+ FEATURE: Added the option to put the images before the article
78
+ BUGFIX: Added in selection for charsets - thanks Psykotik - this may cause problems for other encodings
79
+ FEATURE: Added option to turn of quoted printable decoding
80
+ FEATURE: :start tag - now postie looks for this tag before looking for you message - handy if your service provider prepends a message
81
+ FEATURE: Template for translation now included
82
+ Version 0.9.8.4
83
+ BUGFIX: Fixed problem with config_form.php - select had "NULL" instead of ""
84
+ BUGFIX: 3g2 now supported
85
+ BUGFIX: More line break issues addressed
86
+ BUGFIX: QuickTime controls are now visible even if the movie is done playing
87
+ BUGFIX: Email addresses in the format <some@domain.com> (Full Name) supported
88
+ BUGFIX: Some images that were not being resized - are now
89
+ BUGFIX: HTML problems - if you posted plain text with HTML on it ignored all images
90
+ BUGFIX: The test system blew up on the thumbnails
91
+ BUGFIX: Selected HTML for preferred text is now shown in the config form properly
92
+ BUGFIX: Postie now complains if it is not in its own directory
93
+ BUGFIX: Postie doesn't include PEAR if it is already available
94
+ BUGFIX: In Test mode rejected emails are simply dropped
95
+ BUGFIX: Markdown messes up Postie - it will warn you if you turn it on.
96
+
97
+ Version 0.9.8.3
98
+ BUGFIX: Fixed issue with the line feed replacement
99
+ BUGFIX: Added Banned File Config back in
100
+ FEATURE: Added in a link around 3gp video embedded via QT
101
+ BUGFIX: Email that has both Plain and HTML content will show the HTML content and not the plain if html is preferred
102
+
103
+ Version 0.9.8.2
104
+ BUGFIX: Fixed an extra new line after attachin non-image files.
105
+ BUGFIX: The Test system now displays any missing gd functions
106
+ BUGFIX: The test system was only using ImageMagick
107
+
108
+ Version 0.9.8.1
109
+ BUGFIX: The test images are now included in the zip
110
+
111
+ Version 0.9.8
112
+ BUGFIX: New Lines detected and handled properly in cases where the mail client doesn't put a space before the new line (Miss Distance)
113
+ BUGFIX: 3gp mime type added (Paco Cotera)
114
+ BUGFIX: Authorized Email Addresses are not case-insensitive
115
+ FEATURE: The larger image now does a proper pop up
116
+ BUGFIX: Fixed Timeing Issue - turns out it wasn't reading the db at all
117
+ FEATURE: New Test Screen - to help track down problems
118
+
119
+ Version 0.9.7
120
+ BUGFIX: removed all short tags
121
+ BUGFIX: There were spacing issues in the way I wrote the QT embed statements
122
+ FEATURE: Added calls to WP-Cron - should work with that properly now if you activate Cronless Postie
123
+ FEATURE: ImageMagick version works without any calls to GD
124
+ BUGFIX: Postie now correctly handles cases wjere tjere are multiple blogs in one db
125
+ BUGFIX: Turned off warnings when using without GD
126
+ FEATURE: add the rotate:X to your message to rotate all images
127
+ FEATURE: new filter_postie_thumbnail_with_full which makes it easy to show a thumbnail on the front page but full image on the single page - see FAQ
128
+
129
+ Version 0.9.6
130
+ BUGFIX: handles email addresses that are no name and just <email@email.com> (Steve Cooley Reported)
131
+ FEATURE: Basic support for embedding flash files
132
+ BUGFIX: Postie now handles creating the correct URL on non Unix platforms
133
+ BUGFIX: Fixed problem with file attachments not being put in the right place.
134
+ FEATURE: You can now choose to use imagemagick convert to handle making thumbnails
135
+ BUGFIX: Rewrote Cronless Postie to use direct sockets
136
+ BUGFIX: Time offset is now settable just for Postie - hopefully this will fix problems for cases where the normal time offset doesn't work properly.
137
+ FEATURE: First draft of frame for a 3GP video
138
+ FEATURE: Option to embed 3GP in QuickTime Controller.
139
+
140
+ Version 0.9.5.2
141
+ BUGFIX: gmt varialble not being set correctly
142
+ BUGFIX: Changed the name of the Check Mail button to fix an issue with mod_security
143
+ BUGFIX: Fixed issue with Cronless-Postie
144
+ BUGFIX: There was an argument passed by reference incorrectly
145
+ FEATURE: Added in Cronless Postie Readme
146
+ FEATURE: Added in Postie Readme
147
+
148
+ Version 0.9.5.1
149
+ BUGFIX: Confirmed POP3-SSL on debian-3.0
150
+ BUGFIX: Updated the plugin version
151
+ BUGFIX: Stopped displaying the email account
152
+
153
+ Version 0.9.5
154
+ BUGFIX: Postie handles cases where you do not have GD
155
+ FEATURE: You can now set the access level for posting - so other people can use the gate way
156
+ BUGFIX: Fixed issue when admininstrator email is not tied to a user account.
157
+ FEATURE: Can now reset all Postie configurations back to defaults
158
+ BUGFIX: HTML Emails with embedded images are now handled properly.
159
+ BUGFIX: The time difference should work correctly now
160
+ BUGFIX: Postie's configs are completely seperate from Writing-By-Mail
161
+ FEATURE: Warning if you use Gmail to make sure you turn on POP support
162
+ BUGFIX: Manual Check Mail Button in interface
163
+ BUGFIX: fixed issue of compatability with cjd-notepad
164
+ BUGFIX: Windows Works Now
165
+
166
+
167
+ Version 0.9.4
168
+ BUGFIX: Cronless Postie - fixed the include statement
169
+ BUGFIX: Authorized Addresses now supports a single address
170
+ FEATURE: All configuration in Postie done in a single screen
171
+ FEATURE: AUTHORIZATION can be completely overridden
172
+ BUGFIX: line 1159 - didn't handle cases where the table didn't exist already very well
173
+ FEATURE: Detects if you can do IMAP
174
+ FEATURE: Added IMAP Support
175
+ FEATURE: Added IMAP-SSL Support
176
+ FEATURE: Added POP3-SSL Support
177
+
178
+ Version 0.9.3
179
+ Bug fixes for IIS
180
+ Version 0.9.2
181
+ Moved to more of a DIRECTORY_SEPARATOR structure
182
+ Version 0.9.1
183
+ Added a define to fix a problem with over including
184
+ Version 0.9
185
+ Converted to an honest to god plugin
186
+ BUGFIX: If you put a single category:subject it now works
187
+ BUGFIX: ? Special characters may be supported? The test post now shows a lot of umlats and accents?
188
+ BUGFIX: The last ] in a subject with categories is now filtered out
189
+ FEATURE: -1- subject - will put the post in category 1
190
+ Version 0.312.13
191
+ Code clean up - The main loop is finally readable by even non programmers
192
+ FEATURE - You can now post to multiple categories at one time by using the [#],[Category Name], [Cat] in the subject
193
+ FEATURE - You can now select a category by just including the begining characters [G] will select General
194
+ if you don't have any other categories that start with g
195
+ FEATURE - Jay Talbot - added a new feature so you can have multiple email addresses be allowed in
196
+ Make multi category posting more obvious
197
+ BUG FIX: Timezones of GMT+? should now work properly
198
+ BUG FIX: Able to handle mis-mime typed images as long as they are named with .jpg/.gif/.png
199
+
200
+ Version 0.312.12
201
+ Code clean up - slowing shrinking the main to make it easiery to fix things
202
+ FEATURE: Be able to turn on/off allowing comments in an email
203
+ BUG FIX: AppleDouble now mostly supported
204
+ BUG FIX: MIME handling improved.
205
+ BUG FIX: Fix issue with timing delay
206
+ Version 0.312.11
207
+ FEATURE: Patterns to define where a sig starts are user configurable
208
+ FEATURE: Add filter options for banned file names
209
+ BUG FIX: Made it possible to turn off posting to the db for testing purposes
210
+ Version 0.312.10
211
+ FEATURE: Added in code to diplay the mime type of the file being linked to
212
+ BUG FIX: It now tests for the existance of the directories and makes sure
213
+ that the web server can write to them
214
+ Version 0.312.9
215
+ FEATURE:Should handle jpg as well as jpeg as the file type
216
+ BUG FIX: Now correctly handles the subject in the message
217
+ BUG FIX: Should handle Text preferences correctly
218
+ Version 0.312.8
219
+ Some general code tidying.
220
+ FEATURE: Can now have email from invalid email addresses automatically forwared
221
+ to the admin's email account. This forward includes all attachments.
222
+ Props to David Luden for getting this started.
223
+ Minor change: The system will continue if it runs into a message that doesn't have
224
+ any content - it will also continue to process if it gets an email from
225
+ someone not in the system. In the past this could result in deleted mail
226
+ if your cron job didn't run often enough.
227
+ Version 0.312.7
228
+ Confirm the handling of 3gp video for cell phones o
229
+ Added in new directive SUPPORTED_FILE_TYPES -if the mime type is listed here then the system will try to make a link to it without making a thumb nail.
230
+ Version 0.312.6
231
+ Bug Fix: Ok the last bug I fixed - actually caused another bug - man I should set up some unit tests. Now it handles mail from the nokia mail client correctly.
232
+ Version 0.312.5
233
+ Bug Fix : The system was accepting all test/* types. Now you can set a preference (defaults to text/plain)
234
+ to use as the main text for the post.
235
+ Version 0.312.4
236
+ Added in sanitize_title call suggested by Jemima
237
+ Added in ability to provide a subject in an mms - by using #Subject#
238
+ Fixed an issue with the time stamp system so it now automatically uses the gmt_offset from WordPress
239
+ Fixed issue with the delay:1d1h tag that prevented it from being removed from the body.
240
+ Fixed issue with the delay tag that caused problems if it was the last thing before an image.
241
+
242
+ Version 0.312.3-HEY (2005-05)
243
+ -> Some changes and Bugfixes by Adrian Heydecker
244
+ -> Not (yet) in main development branch.
245
+ Fixed bug: JPEG-thumbnails had a bigger filesize than full images caused by bad hardcoded compression value.
246
+ Fixed bug: If images and signatures were present but no placeholder tags, the images were deleted together with the signature.
247
+ Fixed bug: Generates valid postnames for users of mod_rewrite. Permalinks to posts should now work even when whitespaces are present in the subject line.
248
+ Added support for Quoted Printable encoded mail.
249
+ Added ability to encode Wordpress-posts in charset ISO-8859-1 instead of UTF-8.
250
+ Added ability to choose JPEG-compression value for thumbnails.
251
+ Added ability to add class="" and style="" to images.
252
+ Added ability to use a different mailadress (eg. mobile) without setting up a new Wordpress-account.
253
+
254
+ Version 0.312.2
255
+ BUGFIX: It now removes the delay tag from the message
256
+ Version 0.312.1
257
+ Added modification for placeholder support for images (David Luden)
258
+ Added in support to automatically scale down big images (Dirk Elmendorf)
259
+ Fixed bug with multiple emails all getting the contents of the first image tag (Dirk Elmendorf)
260
+ Added option to allow HTML in the body and subject of the email (Dirk Elmendorf)
261
+ Switch config options to defines to reduce the number of global variables (Dirk Elmendorf)
262
+ Added tests to make sure there is a trailing slash on the DIR definitions (Dirk Elmendorf)
263
+ Add tests to see if they have gd installed (Dirk Elmendorf)
264
+ Seperate the scaling out to a function for easier usage (Dirk Elmendorf)
265
+ Add delay feature for future posting. (Dirk Elmendorf)
266
+ Added in ability to use strtotime if it is available (Dirk ELmendorf)
267
+
268
+ Todo
269
+ Have option to have the email that is rejected forwarded on to another address.
270
+ Fix bug that id still diplays the delay tag in the body
271
+ Version 0.312 - 2005-03
272
+ - CHANGE FOR DEFAULT E-mail Categories, instead of [General] Subject you can now use General: Subject in the subject line. Less typing, and there must be a space after the colon.
273
+ - Fixed bugs with no default posting for categories and user
274
+ Version 0.311 - 2005-01
275
+ - eep, major bug for pop3 server. Next time I test my code more before I released, fixed so that pop3 now works.`
276
+ Version 0.31 - 2004-12 & 2005-01
277
+ (Has it been this long, best get back into the swing of things... did most of this coding on my holiday as I didn't have a machine to play WoW on :)
278
+ - moved the deletion of pop3 emails into a check so that e-mails aren't deleted without proper checking.
279
+ - added HTML 'decoding' (basic support for Thunderbird & Outlook)
280
+ - updated the Category search so that it matches words as well as numbers (i.e. [General] Subjectname will work instead of just [1] Subjectname)
281
+ - Changed time function from time to strtotime (as per Senior Pez's suggestion), but found out that strtotime isn't in default php distro so removed...
282
+
283
+ Vesion 0.3 - 2004-09
284
+ - Added UBB decoding support
285
+ - Added default title (when there is no subject assigned)
286
+ - Started doing a little code cleanup, been reading Advanced PHP Book :)
287
+
288
+ Version 0.2 - 2004-08
289
+ - Stopped using pear body decoding in favour of own decoding (may be slower but more modifiable) because of enriched text decoding
290
+ - Added base64_decode checking (may help mobile phone users)
291
+ - Fixed Subject line for non-english users (htmlentities instead of just trim)
292
+ - Fixed error in some pop hanging -> more graceful exit on event on no emails in inbox ($pop3->quit)
293
+ - Added work around for email addresses with exta <> in field (ie: <blade@lansmash.com> instead of blade@lasmash.com
294
+ - Added some ===basic=== enriched text support
295
+ - Updated readme file for easier install
296
+ - Easy modify of globals (such as PHOTOSDIR and FILESDIR)
297
+ - Cleaned up some pear stuff in install
298
+
299
+ Version 0.1 - 2004-06
300
+ First release
PEAR.php ADDED
@@ -0,0 +1,975 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //
3
+ // +--------------------------------------------------------------------+
4
+ // | PEAR, the PHP Extension and Application Repository |
5
+ // +--------------------------------------------------------------------+
6
+ // | Copyright (c) 1997-2004 The PHP Group |
7
+ // +--------------------------------------------------------------------+
8
+ // | This source file is subject to version 2.0 of the PHP license, |
9
+ // | that is bundled with this package in the file LICENSE, and is |
10
+ // | available through the world-wide-web at the following url: |
11
+ // | http://www.php.net/license/3_0.txt. |
12
+ // | If you did not receive a copy of the PHP license and are unable to |
13
+ // | obtain it through the world-wide-web, please send a note to |
14
+ // | license@php.net so we can mail you a copy immediately. |
15
+ // +--------------------------------------------------------------------+
16
+ // | Authors: Sterling Hughes <sterling@php.net> |
17
+ // | Stig Bakken <ssb@php.net> |
18
+ // | Tomas V.V.Cox <cox@idecnet.com> |
19
+ // +--------------------------------------------------------------------+
20
+ //
21
+ // $Id: PEAR.php,v 1.1 2005/01/28 02:20:39 johnhewitt Exp $
22
+ //
23
+
24
+ define('PEAR_ERROR_RETURN', 1);
25
+ define('PEAR_ERROR_PRINT', 2);
26
+ define('PEAR_ERROR_TRIGGER', 4);
27
+ define('PEAR_ERROR_DIE', 8);
28
+ define('PEAR_ERROR_CALLBACK', 16);
29
+ /**
30
+ * WARNING: obsolete
31
+ * @deprecated
32
+ */
33
+ define('PEAR_ERROR_EXCEPTION', 32);
34
+ define('PEAR_ZE2', (function_exists('version_compare') &&
35
+ version_compare(zend_version(), "2-dev", "ge")));
36
+
37
+ if (substr(PHP_OS, 0, 3) == 'WIN') {
38
+ define('OS_WINDOWS', true);
39
+ define('OS_UNIX', false);
40
+ define('PEAR_OS', 'Windows');
41
+ } else {
42
+ define('OS_WINDOWS', false);
43
+ define('OS_UNIX', true);
44
+ define('PEAR_OS', 'Unix'); // blatant assumption
45
+ }
46
+
47
+ // instant backwards compatibility
48
+ if (!defined('PATH_SEPARATOR')) {
49
+ if (OS_WINDOWS) {
50
+ define('PATH_SEPARATOR', ';');
51
+ } else {
52
+ define('PATH_SEPARATOR', ':');
53
+ }
54
+ }
55
+
56
+ $GLOBALS['_PEAR_default_error_mode'] = PEAR_ERROR_RETURN;
57
+ $GLOBALS['_PEAR_default_error_options'] = E_USER_NOTICE;
58
+ $GLOBALS['_PEAR_destructor_object_list'] = array();
59
+ $GLOBALS['_PEAR_shutdown_funcs'] = array();
60
+ $GLOBALS['_PEAR_error_handler_stack'] = array();
61
+
62
+ ini_set('track_errors', true);
63
+
64
+ /**
65
+ * Base class for other PEAR classes. Provides rudimentary
66
+ * emulation of destructors.
67
+ *
68
+ * If you want a destructor in your class, inherit PEAR and make a
69
+ * destructor method called _yourclassname (same name as the
70
+ * constructor, but with a "_" prefix). Also, in your constructor you
71
+ * have to call the PEAR constructor: $this->PEAR();.
72
+ * The destructor method will be called without parameters. Note that
73
+ * at in some SAPI implementations (such as Apache), any output during
74
+ * the request shutdown (in which destructors are called) seems to be
75
+ * discarded. If you need to get any debug information from your
76
+ * destructor, use error_log(), syslog() or something similar.
77
+ *
78
+ * IMPORTANT! To use the emulated destructors you need to create the
79
+ * objects by reference: $obj =& new PEAR_child;
80
+ *
81
+ * @since PHP 4.0.2
82
+ * @author Stig Bakken <ssb@php.net>
83
+ * @see http://pear.php.net/manual/
84
+ */
85
+ class PEAR
86
+ {
87
+ // {{{ properties
88
+
89
+ /**
90
+ * Whether to enable internal debug messages.
91
+ *
92
+ * @var bool
93
+ * @access private
94
+ */
95
+ var $_debug = false;
96
+
97
+ /**
98
+ * Default error mode for this object.
99
+ *
100
+ * @var int
101
+ * @access private
102
+ */
103
+ var $_default_error_mode = null;
104
+
105
+ /**
106
+ * Default error options used for this object when error mode
107
+ * is PEAR_ERROR_TRIGGER.
108
+ *
109
+ * @var int
110
+ * @access private
111
+ */
112
+ var $_default_error_options = null;
113
+
114
+ /**
115
+ * Default error handler (callback) for this object, if error mode is
116
+ * PEAR_ERROR_CALLBACK.
117
+ *
118
+ * @var string
119
+ * @access private
120
+ */
121
+ var $_default_error_handler = '';
122
+
123
+ /**
124
+ * Which class to use for error objects.
125
+ *
126
+ * @var string
127
+ * @access private
128
+ */
129
+ var $_error_class = 'PEAR_Error';
130
+
131
+ /**
132
+ * An array of expected errors.
133
+ *
134
+ * @var array
135
+ * @access private
136
+ */
137
+ var $_expected_errors = array();
138
+
139
+ // }}}
140
+
141
+ // {{{ constructor
142
+
143
+ /**
144
+ * Constructor. Registers this object in
145
+ * $_PEAR_destructor_object_list for destructor emulation if a
146
+ * destructor object exists.
147
+ *
148
+ * @param string $error_class (optional) which class to use for
149
+ * error objects, defaults to PEAR_Error.
150
+ * @access public
151
+ * @return void
152
+ */
153
+ function PEAR($error_class = null)
154
+ {
155
+ $classname = get_class($this);
156
+ if ($this->_debug) {
157
+ print "PEAR constructor called, class=$classname\n";
158
+ }
159
+ if ($error_class !== null) {
160
+ $this->_error_class = $error_class;
161
+ }
162
+ while ($classname) {
163
+ $destructor = "_$classname";
164
+ if (method_exists($this, $destructor)) {
165
+ global $_PEAR_destructor_object_list;
166
+ $_PEAR_destructor_object_list[] = &$this;
167
+ break;
168
+ } else {
169
+ $classname = get_parent_class($classname);
170
+ }
171
+ }
172
+ }
173
+
174
+ // }}}
175
+ // {{{ destructor
176
+
177
+ /**
178
+ * Destructor (the emulated type of...). Does nothing right now,
179
+ * but is included for forward compatibility, so subclass
180
+ * destructors should always call it.
181
+ *
182
+ * See the note in the class desciption about output from
183
+ * destructors.
184
+ *
185
+ * @access public
186
+ * @return void
187
+ */
188
+ function _PEAR() {
189
+ if ($this->_debug) {
190
+ printf("PEAR destructor called, class=%s\n", get_class($this));
191
+ }
192
+ }
193
+
194
+ // }}}
195
+ // {{{ getStaticProperty()
196
+
197
+ /**
198
+ * If you have a class that's mostly/entirely static, and you need static
199
+ * properties, you can use this method to simulate them. Eg. in your method(s)
200
+ * do this: $myVar = &PEAR::getStaticProperty('myclass', 'myVar');
201
+ * You MUST use a reference, or they will not persist!
202
+ *
203
+ * @access public
204
+ * @param string $class The calling classname, to prevent clashes
205
+ * @param string $var The variable to retrieve.
206
+ * @return mixed A reference to the variable. If not set it will be
207
+ * auto initialised to NULL.
208
+ */
209
+ function &getStaticProperty($class, $var)
210
+ {
211
+ static $properties;
212
+ return $properties[$class][$var];
213
+ }
214
+
215
+ // }}}
216
+ // {{{ registerShutdownFunc()
217
+
218
+ /**
219
+ * Use this function to register a shutdown method for static
220
+ * classes.
221
+ *
222
+ * @access public
223
+ * @param mixed $func The function name (or array of class/method) to call
224
+ * @param mixed $args The arguments to pass to the function
225
+ * @return void
226
+ */
227
+ function registerShutdownFunc($func, $args = array())
228
+ {
229
+ $GLOBALS['_PEAR_shutdown_funcs'][] = array($func, $args);
230
+ }
231
+
232
+ // }}}
233
+ // {{{ isError()
234
+
235
+ /**
236
+ * Tell whether a value is a PEAR error.
237
+ *
238
+ * @param mixed $data the value to test
239
+ * @param int $code if $data is an error object, return true
240
+ * only if $code is a string and
241
+ * $obj->getMessage() == $code or
242
+ * $code is an integer and $obj->getCode() == $code
243
+ * @access public
244
+ * @return bool true if parameter is an error
245
+ */
246
+ function isError($data, $code = null)
247
+ {
248
+ if (is_a($data, 'PEAR_Error')) {
249
+ if (is_null($code)) {
250
+ return true;
251
+ } elseif (is_string($code)) {
252
+ return $data->getMessage() == $code;
253
+ } else {
254
+ return $data->getCode() == $code;
255
+ }
256
+ }
257
+ return false;
258
+ }
259
+
260
+ // }}}
261
+ // {{{ setErrorHandling()
262
+
263
+ /**
264
+ * Sets how errors generated by this object should be handled.
265
+ * Can be invoked both in objects and statically. If called
266
+ * statically, setErrorHandling sets the default behaviour for all
267
+ * PEAR objects. If called in an object, setErrorHandling sets
268
+ * the default behaviour for that object.
269
+ *
270
+ * @param int $mode
271
+ * One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
272
+ * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
273
+ * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION.
274
+ *
275
+ * @param mixed $options
276
+ * When $mode is PEAR_ERROR_TRIGGER, this is the error level (one
277
+ * of E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
278
+ *
279
+ * When $mode is PEAR_ERROR_CALLBACK, this parameter is expected
280
+ * to be the callback function or method. A callback
281
+ * function is a string with the name of the function, a
282
+ * callback method is an array of two elements: the element
283
+ * at index 0 is the object, and the element at index 1 is
284
+ * the name of the method to call in the object.
285
+ *
286
+ * When $mode is PEAR_ERROR_PRINT or PEAR_ERROR_DIE, this is
287
+ * a printf format string used when printing the error
288
+ * message.
289
+ *
290
+ * @access public
291
+ * @return void
292
+ * @see PEAR_ERROR_RETURN
293
+ * @see PEAR_ERROR_PRINT
294
+ * @see PEAR_ERROR_TRIGGER
295
+ * @see PEAR_ERROR_DIE
296
+ * @see PEAR_ERROR_CALLBACK
297
+ * @see PEAR_ERROR_EXCEPTION
298
+ *
299
+ * @since PHP 4.0.5
300
+ */
301
+
302
+ function setErrorHandling($mode = null, $options = null)
303
+ {
304
+ if (isset($this) && is_a($this, 'PEAR')) {
305
+ $setmode = &$this->_default_error_mode;
306
+ $setoptions = &$this->_default_error_options;
307
+ } else {
308
+ $setmode = &$GLOBALS['_PEAR_default_error_mode'];
309
+ $setoptions = &$GLOBALS['_PEAR_default_error_options'];
310
+ }
311
+
312
+ switch ($mode) {
313
+ case PEAR_ERROR_EXCEPTION:
314
+ case PEAR_ERROR_RETURN:
315
+ case PEAR_ERROR_PRINT:
316
+ case PEAR_ERROR_TRIGGER:
317
+ case PEAR_ERROR_DIE:
318
+ case null:
319
+ $setmode = $mode;
320
+ $setoptions = $options;
321
+ break;
322
+
323
+ case PEAR_ERROR_CALLBACK:
324
+ $setmode = $mode;
325
+ // class/object method callback
326
+ if (is_callable($options)) {
327
+ $setoptions = $options;
328
+ } else {
329
+ trigger_error("invalid error callback", E_USER_WARNING);
330
+ }
331
+ break;
332
+
333
+ default:
334
+ trigger_error("invalid error mode", E_USER_WARNING);
335
+ break;
336
+ }
337
+ }
338
+
339
+ // }}}
340
+ // {{{ expectError()
341
+
342
+ /**
343
+ * This method is used to tell which errors you expect to get.
344
+ * Expected errors are always returned with error mode
345
+ * PEAR_ERROR_RETURN. Expected error codes are stored in a stack,
346
+ * and this method pushes a new element onto it. The list of
347
+ * expected errors are in effect until they are popped off the
348
+ * stack with the popExpect() method.
349
+ *
350
+ * Note that this method can not be called statically
351
+ *
352
+ * @param mixed $code a single error code or an array of error codes to expect
353
+ *
354
+ * @return int the new depth of the "expected errors" stack
355
+ * @access public
356
+ */
357
+ function expectError($code = '*')
358
+ {
359
+ if (is_array($code)) {
360
+ array_push($this->_expected_errors, $code);
361
+ } else {
362
+ array_push($this->_expected_errors, array($code));
363
+ }
364
+ return sizeof($this->_expected_errors);
365
+ }
366
+
367
+ // }}}
368
+ // {{{ popExpect()
369
+
370
+ /**
371
+ * This method pops one element off the expected error codes
372
+ * stack.
373
+ *
374
+ * @return array the list of error codes that were popped
375
+ */
376
+ function popExpect()
377
+ {
378
+ return array_pop($this->_expected_errors);
379
+ }
380
+
381
+ // }}}
382
+ // {{{ _checkDelExpect()
383
+
384
+ /**
385
+ * This method checks unsets an error code if available
386
+ *
387
+ * @param mixed error code
388
+ * @return bool true if the error code was unset, false otherwise
389
+ * @access private
390
+ * @since PHP 4.3.0
391
+ */
392
+ function _checkDelExpect($error_code)
393
+ {
394
+ $deleted = false;
395
+
396
+ foreach ($this->_expected_errors AS $key => $error_array) {
397
+ if (in_array($error_code, $error_array)) {
398
+ unset($this->_expected_errors[$key][array_search($error_code, $error_array)]);
399
+ $deleted = true;
400
+ }
401
+
402
+ // clean up empty arrays
403
+ if (0 == count($this->_expected_errors[$key])) {
404
+ unset($this->_expected_errors[$key]);
405
+ }
406
+ }
407
+ return $deleted;
408
+ }
409
+
410
+ // }}}
411
+ // {{{ delExpect()
412
+
413
+ /**
414
+ * This method deletes all occurences of the specified element from
415
+ * the expected error codes stack.
416
+ *
417
+ * @param mixed $error_code error code that should be deleted
418
+ * @return mixed list of error codes that were deleted or error
419
+ * @access public
420
+ * @since PHP 4.3.0
421
+ */
422
+ function delExpect($error_code)
423
+ {
424
+ $deleted = false;
425
+
426
+ if ((is_array($error_code) && (0 != count($error_code)))) {
427
+ // $error_code is a non-empty array here;
428
+ // we walk through it trying to unset all
429
+ // values
430
+ foreach($error_code as $key => $error) {
431
+ if ($this->_checkDelExpect($error)) {
432
+ $deleted = true;
433
+ } else {
434
+ $deleted = false;
435
+ }
436
+ }
437
+ return $deleted ? true : PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
438
+ } elseif (!empty($error_code)) {
439
+ // $error_code comes alone, trying to unset it
440
+ if ($this->_checkDelExpect($error_code)) {
441
+ return true;
442
+ } else {
443
+ return PEAR::raiseError("The expected error you submitted does not exist"); // IMPROVE ME
444
+ }
445
+ } else {
446
+ // $error_code is empty
447
+ return PEAR::raiseError("The expected error you submitted is empty"); // IMPROVE ME
448
+ }
449
+ }
450
+
451
+ // }}}
452
+ // {{{ raiseError()
453
+
454
+ /**
455
+ * This method is a wrapper that returns an instance of the
456
+ * configured error class with this object's default error
457
+ * handling applied. If the $mode and $options parameters are not
458
+ * specified, the object's defaults are used.
459
+ *
460
+ * @param mixed $message a text error message or a PEAR error object
461
+ *
462
+ * @param int $code a numeric error code (it is up to your class
463
+ * to define these if you want to use codes)
464
+ *
465
+ * @param int $mode One of PEAR_ERROR_RETURN, PEAR_ERROR_PRINT,
466
+ * PEAR_ERROR_TRIGGER, PEAR_ERROR_DIE,
467
+ * PEAR_ERROR_CALLBACK, PEAR_ERROR_EXCEPTION.
468
+ *
469
+ * @param mixed $options If $mode is PEAR_ERROR_TRIGGER, this parameter
470
+ * specifies the PHP-internal error level (one of
471
+ * E_USER_NOTICE, E_USER_WARNING or E_USER_ERROR).
472
+ * If $mode is PEAR_ERROR_CALLBACK, this
473
+ * parameter specifies the callback function or
474
+ * method. In other error modes this parameter
475
+ * is ignored.
476
+ *
477
+ * @param string $userinfo If you need to pass along for example debug
478
+ * information, this parameter is meant for that.
479
+ *
480
+ * @param string $error_class The returned error object will be
481
+ * instantiated from this class, if specified.
482
+ *
483
+ * @param bool $skipmsg If true, raiseError will only pass error codes,
484
+ * the error message parameter will be dropped.
485
+ *
486
+ * @access public
487
+ * @return object a PEAR error object
488
+ * @see PEAR::setErrorHandling
489
+ * @since PHP 4.0.5
490
+ */
491
+ function raiseError($message = null,
492
+ $code = null,
493
+ $mode = null,
494
+ $options = null,
495
+ $userinfo = null,
496
+ $error_class = null,
497
+ $skipmsg = false)
498
+ {
499
+ // The error is yet a PEAR error object
500
+ if (is_object($message)) {
501
+ $code = $message->getCode();
502
+ $userinfo = $message->getUserInfo();
503
+ $error_class = $message->getType();
504
+ $message->error_message_prefix = '';
505
+ $message = $message->getMessage();
506
+ }
507
+
508
+ if (isset($this) && isset($this->_expected_errors) && sizeof($this->_expected_errors) > 0 && sizeof($exp = end($this->_expected_errors))) {
509
+ if ($exp[0] == "*" ||
510
+ (is_int(reset($exp)) && in_array($code, $exp)) ||
511
+ (is_string(reset($exp)) && in_array($message, $exp))) {
512
+ $mode = PEAR_ERROR_RETURN;
513
+ }
514
+ }
515
+ // No mode given, try global ones
516
+ if ($mode === null) {
517
+ // Class error handler
518
+ if (isset($this) && isset($this->_default_error_mode)) {
519
+ $mode = $this->_default_error_mode;
520
+ $options = $this->_default_error_options;
521
+ // Global error handler
522
+ } elseif (isset($GLOBALS['_PEAR_default_error_mode'])) {
523
+ $mode = $GLOBALS['_PEAR_default_error_mode'];
524
+ $options = $GLOBALS['_PEAR_default_error_options'];
525
+ }
526
+ }
527
+
528
+ if ($error_class !== null) {
529
+ $ec = $error_class;
530
+ } elseif (isset($this) && isset($this->_error_class)) {
531
+ $ec = $this->_error_class;
532
+ } else {
533
+ $ec = 'PEAR_Error';
534
+ }
535
+ if ($skipmsg) {
536
+ return new $ec($code, $mode, $options, $userinfo);
537
+ } else {
538
+ return new $ec($message, $code, $mode, $options, $userinfo);
539
+ }
540
+ }
541
+
542
+ // }}}
543
+ // {{{ throwError()
544
+
545
+ /**
546
+ * Simpler form of raiseError with fewer options. In most cases
547
+ * message, code and userinfo are enough.
548
+ *
549
+ * @param string $message
550
+ *
551
+ */
552
+ function throwError($message = null,
553
+ $code = null,
554
+ $userinfo = null)
555
+ {
556
+ if (isset($this) && is_a($this, 'PEAR')) {
557
+ return $this->raiseError($message, $code, null, null, $userinfo);
558
+ } else {
559
+ return PEAR::raiseError($message, $code, null, null, $userinfo);
560
+ }
561
+ }
562
+
563
+ // }}}
564
+ // {{{ pushErrorHandling()
565
+
566
+ /**
567
+ * Push a new error handler on top of the error handler options stack. With this
568
+ * you can easily override the actual error handler for some code and restore
569
+ * it later with popErrorHandling.
570
+ *
571
+ * @param mixed $mode (same as setErrorHandling)
572
+ * @param mixed $options (same as setErrorHandling)
573
+ *
574
+ * @return bool Always true
575
+ *
576
+ * @see PEAR::setErrorHandling
577
+ */
578
+ function pushErrorHandling($mode, $options = null)
579
+ {
580
+ $stack = &$GLOBALS['_PEAR_error_handler_stack'];
581
+ if (isset($this) && is_a($this, 'PEAR')) {
582
+ $def_mode = &$this->_default_error_mode;
583
+ $def_options = &$this->_default_error_options;
584
+ } else {
585
+ $def_mode = &$GLOBALS['_PEAR_default_error_mode'];
586
+ $def_options = &$GLOBALS['_PEAR_default_error_options'];
587
+ }
588
+ $stack[] = array($def_mode, $def_options);
589
+
590
+ if (isset($this) && is_a($this, 'PEAR')) {
591
+ $this->setErrorHandling($mode, $options);
592
+ } else {
593
+ PEAR::setErrorHandling($mode, $options);
594
+ }
595
+ $stack[] = array($mode, $options);
596
+ return true;
597
+ }
598
+
599
+ // }}}
600
+ // {{{ popErrorHandling()
601
+
602
+ /**
603
+ * Pop the last error handler used
604
+ *
605
+ * @return bool Always true
606
+ *
607
+ * @see PEAR::pushErrorHandling
608
+ */
609
+ function popErrorHandling()
610
+ {
611
+ $stack = &$GLOBALS['_PEAR_error_handler_stack'];
612
+ array_pop($stack);
613
+ list($mode, $options) = $stack[sizeof($stack) - 1];
614
+ array_pop($stack);
615
+ if (isset($this) && is_a($this, 'PEAR')) {
616
+ $this->setErrorHandling($mode, $options);
617
+ } else {
618
+ PEAR::setErrorHandling($mode, $options);
619
+ }
620
+ return true;
621
+ }
622
+
623
+ // }}}
624
+ // {{{ loadExtension()
625
+
626
+ /**
627
+ * OS independant PHP extension load. Remember to take care
628
+ * on the correct extension name for case sensitive OSes.
629
+ *
630
+ * @param string $ext The extension name
631
+ * @return bool Success or not on the dl() call
632
+ */
633
+ function loadExtension($ext)
634
+ {
635
+ if (!extension_loaded($ext)) {
636
+ // if either returns true dl() will produce a FATAL error, stop that
637
+ if ((ini_get('enable_dl') != 1) || (ini_get('safe_mode') == 1)) {
638
+ return false;
639
+ }
640
+ if (OS_WINDOWS) {
641
+ $suffix = '.dll';
642
+ } elseif (PHP_OS == 'HP-UX') {
643
+ $suffix = '.sl';
644
+ } elseif (PHP_OS == 'AIX') {
645
+ $suffix = '.a';
646
+ } elseif (PHP_OS == 'OSX') {
647
+ $suffix = '.bundle';
648
+ } else {
649
+ $suffix = '.so';
650
+ }
651
+ return @dl('php_'.$ext.$suffix) || @dl($ext.$suffix);
652
+ }
653
+ return true;
654
+ }
655
+
656
+ // }}}
657
+ }
658
+
659
+ // {{{ _PEAR_call_destructors()
660
+
661
+ function _PEAR_call_destructors()
662
+ {
663
+ global $_PEAR_destructor_object_list;
664
+ if (is_array($_PEAR_destructor_object_list) &&
665
+ sizeof($_PEAR_destructor_object_list))
666
+ {
667
+ reset($_PEAR_destructor_object_list);
668
+ while (list($k, $objref) = each($_PEAR_destructor_object_list)) {
669
+ $classname = get_class($objref);
670
+ while ($classname) {
671
+ $destructor = "_$classname";
672
+ if (method_exists($objref, $destructor)) {
673
+ $objref->$destructor();
674
+ break;
675
+ } else {
676
+ $classname = get_parent_class($classname);
677
+ }
678
+ }
679
+ }
680
+ // Empty the object list to ensure that destructors are
681
+ // not called more than once.
682
+ $_PEAR_destructor_object_list = array();
683
+ }
684
+
685
+ // Now call the shutdown functions
686
+ if (is_array($GLOBALS['_PEAR_shutdown_funcs']) AND !empty($GLOBALS['_PEAR_shutdown_funcs'])) {
687
+ foreach ($GLOBALS['_PEAR_shutdown_funcs'] as $value) {
688
+ call_user_func_array($value[0], $value[1]);
689
+ }
690
+ }
691
+ }
692
+
693
+ // }}}
694
+
695
+ class PEAR_Error
696
+ {
697
+ // {{{ properties
698
+
699
+ var $error_message_prefix = '';
700
+ var $mode = PEAR_ERROR_RETURN;
701
+ var $level = E_USER_NOTICE;
702
+ var $code = -1;
703
+ var $message = '';
704
+ var $userinfo = '';
705
+ var $backtrace = null;
706
+
707
+ // }}}
708
+ // {{{ constructor
709
+
710
+ /**
711
+ * PEAR_Error constructor
712
+ *
713
+ * @param string $message message
714
+ *
715
+ * @param int $code (optional) error code
716
+ *
717
+ * @param int $mode (optional) error mode, one of: PEAR_ERROR_RETURN,
718
+ * PEAR_ERROR_PRINT, PEAR_ERROR_DIE, PEAR_ERROR_TRIGGER,
719
+ * PEAR_ERROR_CALLBACK or PEAR_ERROR_EXCEPTION
720
+ *
721
+ * @param mixed $options (optional) error level, _OR_ in the case of
722
+ * PEAR_ERROR_CALLBACK, the callback function or object/method
723
+ * tuple.
724
+ *
725
+ * @param string $userinfo (optional) additional user/debug info
726
+ *
727
+ * @access public
728
+ *
729
+ */
730
+ function PEAR_Error($message = 'unknown error', $code = null,
731
+ $mode = null, $options = null, $userinfo = null)
732
+ {
733
+ if ($mode === null) {
734
+ $mode = PEAR_ERROR_RETURN;
735
+ }
736
+ $this->message = $message;
737
+ $this->code = $code;
738
+ $this->mode = $mode;
739
+ $this->userinfo = $userinfo;
740
+ if (function_exists("debug_backtrace")) {
741
+ $this->backtrace = debug_backtrace();
742
+ }
743
+ if ($mode & PEAR_ERROR_CALLBACK) {
744
+ $this->level = E_USER_NOTICE;
745
+ $this->callback = $options;
746
+ } else {
747
+ if ($options === null) {
748
+ $options = E_USER_NOTICE;
749
+ }
750
+ $this->level = $options;
751
+ $this->callback = null;
752
+ }
753
+ if ($this->mode & PEAR_ERROR_PRINT) {
754
+ if (is_null($options) || is_int($options)) {
755
+ $format = "%s";
756
+ } else {
757
+ $format = $options;
758
+ }
759
+ printf($format, $this->getMessage());
760
+ }
761
+ if ($this->mode & PEAR_ERROR_TRIGGER) {
762
+ trigger_error($this->getMessage(), $this->level);
763
+ }
764
+ if ($this->mode & PEAR_ERROR_DIE) {
765
+ $msg = $this->getMessage();
766
+ if (is_null($options) || is_int($options)) {
767
+ $format = "%s";
768
+ if (substr($msg, -1) != "\n") {
769
+ $msg .= "\n";
770
+ }
771
+ } else {
772
+ $format = $options;
773
+ }
774
+ die(sprintf($format, $msg));
775
+ }
776
+ if ($this->mode & PEAR_ERROR_CALLBACK) {
777
+ if (is_callable($this->callback)) {
778
+ call_user_func($this->callback, $this);
779
+ }
780
+ }
781
+ if ($this->mode & PEAR_ERROR_EXCEPTION) {
782
+ trigger_error("PEAR_ERROR_EXCEPTION is obsolete, use class PEAR_ErrorStack for exceptions", E_USER_WARNING);
783
+ eval('$e = new Exception($this->message, $this->code);$e->PEAR_Error = $this;throw($e);');
784
+ }
785
+ }
786
+
787
+ // }}}
788
+ // {{{ getMode()
789
+
790
+ /**
791
+ * Get the error mode from an error object.
792
+ *
793
+ * @return int error mode
794
+ * @access public
795
+ */
796
+ function getMode() {
797
+ return $this->mode;
798
+ }
799
+
800
+ // }}}
801
+ // {{{ getCallback()
802
+
803
+ /**
804
+ * Get the callback function/method from an error object.
805
+ *
806
+ * @return mixed callback function or object/method array
807
+ * @access public
808
+ */
809
+ function getCallback() {
810
+ return $this->callback;
811
+ }
812
+
813
+ // }}}
814
+ // {{{ getMessage()
815
+
816
+
817
+ /**
818
+ * Get the error message from an error object.
819
+ *
820
+ * @return string full error message
821
+ * @access public
822
+ */
823
+ function getMessage()
824
+ {
825
+ return ($this->error_message_prefix . $this->message);
826
+ }
827
+
828
+
829
+ // }}}
830
+ // {{{ getCode()
831
+
832
+ /**
833
+ * Get error code from an error object
834
+ *
835
+ * @return int error code
836
+ * @access public
837
+ */
838
+ function getCode()
839
+ {
840
+ return $this->code;
841
+ }
842
+
843
+ // }}}
844
+ // {{{ getType()
845
+
846
+ /**
847
+ * Get the name of this error/exception.
848
+ *
849
+ * @return string error/exception name (type)
850
+ * @access public
851
+ */
852
+ function getType()
853
+ {
854
+ return get_class($this);
855
+ }
856
+
857
+ // }}}
858
+ // {{{ getUserInfo()
859
+
860
+ /**
861
+ * Get additional user-supplied information.
862
+ *
863
+ * @return string user-supplied information
864
+ * @access public
865
+ */
866
+ function getUserInfo()
867
+ {
868
+ return $this->userinfo;
869
+ }
870
+
871
+ // }}}
872
+ // {{{ getDebugInfo()
873
+
874
+ /**
875
+ * Get additional debug information supplied by the application.
876
+ *
877
+ * @return string debug information
878
+ * @access public
879
+ */
880
+ function getDebugInfo()
881
+ {
882
+ return $this->getUserInfo();
883
+ }
884
+
885
+ // }}}
886
+ // {{{ getBacktrace()
887
+
888
+ /**
889
+ * Get the call backtrace from where the error was generated.
890
+ * Supported with PHP 4.3.0 or newer.
891
+ *
892
+ * @param int $frame (optional) what frame to fetch
893
+ * @return array Backtrace, or NULL if not available.
894
+ * @access public
895
+ */
896
+ function getBacktrace($frame = null)
897
+ {
898
+ if ($frame === null) {
899
+ return $this->backtrace;
900
+ }
901
+ return $this->backtrace[$frame];
902
+ }
903
+
904
+ // }}}
905
+ // {{{ addUserInfo()
906
+
907
+ function addUserInfo($info)
908
+ {
909
+ if (empty($this->userinfo)) {
910
+ $this->userinfo = $info;
911
+ } else {
912
+ $this->userinfo .= " ** $info";
913
+ }
914
+ }
915
+
916
+ // }}}
917
+ // {{{ toString()
918
+
919
+ /**
920
+ * Make a string representation of this object.
921
+ *
922
+ * @return string a string with an object summary
923
+ * @access public
924
+ */
925
+ function toString() {
926
+ $modes = array();
927
+ $levels = array(E_USER_NOTICE => 'notice',
928
+ E_USER_WARNING => 'warning',
929
+ E_USER_ERROR => 'error');
930
+ if ($this->mode & PEAR_ERROR_CALLBACK) {
931
+ if (is_array($this->callback)) {
932
+ $callback = get_class($this->callback[0]) . '::' .
933
+ $this->callback[1];
934
+ } else {
935
+ $callback = $this->callback;
936
+ }
937
+ return sprintf('[%s: message="%s" code=%d mode=callback '.
938
+ 'callback=%s prefix="%s" info="%s"]',
939
+ get_class($this), $this->message, $this->code,
940
+ $callback, $this->error_message_prefix,
941
+ $this->userinfo);
942
+ }
943
+ if ($this->mode & PEAR_ERROR_PRINT) {
944
+ $modes[] = 'print';
945
+ }
946
+ if ($this->mode & PEAR_ERROR_TRIGGER) {
947
+ $modes[] = 'trigger';
948
+ }
949
+ if ($this->mode & PEAR_ERROR_DIE) {
950
+ $modes[] = 'die';
951
+ }
952
+ if ($this->mode & PEAR_ERROR_RETURN) {
953
+ $modes[] = 'return';
954
+ }
955
+ return sprintf('[%s: message="%s" code=%d mode=%s level=%s '.
956
+ 'prefix="%s" info="%s"]',
957
+ get_class($this), $this->message, $this->code,
958
+ implode("|", $modes), $levels[$this->level],
959
+ $this->error_message_prefix,
960
+ $this->userinfo);
961
+ }
962
+
963
+ // }}}
964
+ }
965
+
966
+ register_shutdown_function("_PEAR_call_destructors");
967
+
968
+ /*
969
+ * Local Variables:
970
+ * mode: php
971
+ * tab-width: 4
972
+ * c-basic-offset: 4
973
+ * End:
974
+ */
975
+ ?>
config_form.php ADDED
@@ -0,0 +1,480 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ require_once('admin.php');
3
+ require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'postie-functions.php');
4
+ global $wpdb,$wp_roles;
5
+
6
+ if (!TestWPVersion()) {
7
+ print("<h1>Warning!</h1>
8
+ <p>Postie only works on on Word Press version 2.0 and above</p>");
9
+ exit();
10
+ }
11
+ $title = __('Postie Options');
12
+ $parent_file = 'options-general.php';
13
+ $config = GetConfig();
14
+ $messages[1] = "Configuration successfully updated!";
15
+ $messages[2] = "Error - unable to save configuration";
16
+
17
+ ?>
18
+ <style type='text/css'>
19
+ legend {font-weight:bold;
20
+ border:1px solid black;
21
+ background:white;
22
+ padding:.3em;}
23
+ fieldset {border: 1px solid black;}
24
+ </style>
25
+ <?php if (isset($_GET['message'])) : ?>
26
+ <div class="updated"><p><?php _e($messages[$_GET['message']]); ?></p></div>
27
+ <?php endif; ?>
28
+ <div class="wrap">
29
+ <h2><?php _e('Postie Options') ?></h2>
30
+ <p>
31
+ <form name="postie-options" method="post" action="<?php echo get_option('siteurl') . "/wp-content/plugins/postie/config_handler.php"?>">
32
+ <input type="hidden" name="action" value="reset" />
33
+ <p align="right"><?php _e("If you would like to start over - you can click the button on the right to reset all configurations to the default.");?></p>
34
+ <p class="submit">
35
+ <input name="Submit" value="<?php _e("Reset Configs To Default")?> &raquo" type="submit">
36
+ </p>
37
+ </form>
38
+ </p>
39
+ <p>
40
+ <form name="postie-options" method="get" action="<?php echo get_option('siteurl') . "/wp-content/plugins/postie/get_mail.php"?>">
41
+ <p align="right"><?php _e("To run the check mail script manually");?></p>
42
+ <p class="submit">
43
+ <input name="Submit" value="<?php _e("Run Postie");?> &raquo;" type="submit">
44
+ </p>
45
+ </form>
46
+ </p>
47
+ <p>
48
+ <form name="postie-options" method="post" action="<?php echo get_option('siteurl') . "/wp-content/plugins/postie/config_handler.php"?>">
49
+ <input type="hidden" name="action" value="test" />
50
+ <p align="right"><?php _e("If you have problems with Postie this will run a special script to test your configuraiton options");?></p>
51
+ <p class="submit">
52
+ <input name="Submit" value="<?php _e("Test Config");?>&raquo;" type="submit">
53
+ </p>
54
+ </form>
55
+ </p>
56
+ <form name="postie-options" method="post" action="<?php echo get_option('siteurl') . "/wp-content/plugins/postie/config_handler.php"?>">
57
+ <input type="hidden" name="action" value="config" />
58
+ <table width="100%" cellspacing="2" cellpadding="5" class="editform">
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+ <tr><td colspan=2>
67
+ <fieldset class="options">
68
+ <legend><?php _e('Authorization Settings');?></legend>
69
+ <table width="100%" cellspacing="2" cellpadding="5" class="editform">
70
+ <?php echo BuildBooleanSelect("Allow Anyone To Post Via Email","TURN_AUTHORIZATION_OFF",$config["TURN_AUTHORIZATION_OFF"],"Changing this to yes is NOT RECOMMEDED - anything that gets sent in will automatically be posted. This could make it easier to compromise your server - YOU HAVE BEEN WARNED.");?>
71
+ <tr>
72
+ <th scope="row"><?php _e('Roles That Can Post:') ?></th>
73
+ <td>
74
+ <table>
75
+ <tr><th>Administrator role can always post.</th>
76
+ <?php
77
+ foreach($wp_roles->role_names as $roleId => $name) {
78
+ $role = &$wp_roles->get_role($roleId);
79
+ if ($role->has_cap("post_via_postie")) {
80
+ $checked = " CHECKED ";
81
+ }
82
+ else {
83
+ $checked = "";
84
+ }
85
+ if ($roleId != "administrator") {
86
+ print("<tr><td><input type='checkbox' value='1' name='ROLE_ACCESS[$roleId]' $checked >".$name."</td></tr>");
87
+ }
88
+ }
89
+ ?>
90
+ </table>
91
+ <br />
92
+ <code><?php _e("This allows you to grant access to other users to post if they have the proper access level");?></code>
93
+ </td>
94
+ </tr>
95
+ <tr>
96
+ <th width="33%" valign="top" scope="row"><?php _e('Post status:') ?> </th>
97
+ <td>
98
+ <select name="POST_STATUS" id="POST_STATUS">
99
+ <option value="publish" <?php if($config["POST_STATUS"] == "publish") { echo
100
+ "SELECTED";} ?>>Published</option>
101
+ <option value="draft" <?php if($config["POST_STATUS"] == "draft") { echo
102
+ "SELECTED";} ?>>Draft</option>
103
+ <option value="pending" <?php if($config["POST_STATUS"] == "pending") { echo
104
+ "SELECTED";} ?>>Pending Review</option>
105
+ </select><br />
106
+ <?php _e("Recommended");?>: <code>plain</code>
107
+ <br />
108
+ </td>
109
+ </tr>
110
+ <?php echo BuildTextArea("Authorized Addresses","AUTHORIZED_ADDRESSES",$config["AUTHORIZED_ADDRESSES"],"Put each email address on a single line. Posts from emails in this list will be treated as if they came from the admin. If you would prefer to have users post under their own name - create a WordPress user with the correct access level.");?>
111
+ <tr>
112
+ <th width="33%" valign="top" scope="row"><?php _e('Admin
113
+ username:') ?> </th>
114
+ <td>
115
+ <input name="ADMIN_USERNAME" type="text" id="ADMIN_USERNAME"
116
+ value="<?php echo $config["ADMIN_USERNAME"]; ?>" size="50" /><br />
117
+ <?php _e("Recommended");?>: <code>admin</code>
118
+ <br />
119
+ </td>
120
+ </tr>
121
+ </table>
122
+ </fieldset>
123
+ </td>
124
+ </tr>
125
+
126
+
127
+ <tr><td colspan=2>
128
+ <fieldset class="options">
129
+ <legend><?php _e('Directory Settings');?></legend>
130
+ <table width="100%" cellspacing="2" cellpadding="5" class="editform">
131
+ <tr>
132
+ <th width="33%" valign="top" scope="row"><?php _e('Directory For Photos:') ?> </th>
133
+ <td>
134
+ <input name="PHOTOSDIR" type="text" id="PHOTOSDIR" value="<?php echo $config["PHOTOSDIR"]; ?>" size="50" /><br />
135
+ <?php _e("Recommended");?>: <code>/wp-photos/</code>
136
+ <br />
137
+ </td>
138
+ </tr>
139
+ <tr>
140
+ <th width="33%" valign="top" scope="row"><?php _e('Directory For Files:') ?> </th>
141
+ <td>
142
+ <input name="FILESDIR" type="text" id="FILESDIR" value="<?php echo $config["FILESDIR"]; ?>" size="50" /><br />
143
+ <?php _e("Recommended");?>: <code>/wp-filez/</code>
144
+ <br />
145
+ </td>
146
+ </tr>
147
+ </table>
148
+ </fieldset>
149
+ </td>
150
+ </tr>
151
+
152
+ <tr><td colspan=2>
153
+ <fieldset class="options">
154
+ <legend><?php _e('Message Settings');?></legend>
155
+ <table width="100%" cellspacing="2" cellpadding="5" class="editform">
156
+ <tr valign="top">
157
+ <th scope="row"><?php _e('Default post by mail category:') ?></th>
158
+ <td><select name="DEFAULT_POST_CATEGORY" id="DEFAULT_POST_CATEGORY">
159
+ <?php
160
+ $categories = $wpdb->get_results("SELECT * FROM $wpdb->terms ORDER BY name");
161
+ foreach ($categories as $category) {
162
+ $selected = ($category->term_id == $config["DEFAULT_POST_CATEGORY"] ? "SELECTED": NULL);
163
+ echo "\n\t<option value='$category->term_id' $selected>$category->name</option>";
164
+ }
165
+ ?>
166
+ </select></td>
167
+ </tr>
168
+ <tr valign="top">
169
+ <th scope="row"><?php _e('Default post by mail tag(s):
170
+ (separated by commas)') ?></th>
171
+ <td><input type='text' name="DEFAULT_POST_TAGS"
172
+ id="DEFAULT_POST_TAGS" value='<?php echo
173
+ $config["DEFAULT_POST_TAGS"] ?>' />
174
+ </td>
175
+ </tr>
176
+ <tr>
177
+ <th width="33%" valign="top" scope="row"><?php _e('Default Title:') ?> </th>
178
+ <td>
179
+ <input name="DEFAULT_TITLE" type="text" id="DEFAULT_TITLE" value="<?php echo $config["DEFAULT_TITLE"]; ?>" size="50" /><br />
180
+ <?php _e("Recommended");?>: <code>Live from the field</code>
181
+ <br />
182
+ </td>
183
+ </tr>
184
+ <tr>
185
+ <th width="33%" valign="top" scope="row"><?php _e('Prefered Text Type (HTML/plain):') ?> </th>
186
+ <td>
187
+ <select name="PREFER_TEXT_TYPE" id="PREFER_TEXT_TYPE">
188
+ <option value="plain">plain</option>
189
+ <option value="html" <?php if($config["PREFER_TEXT_TYPE"] == "html") { echo "SELECTED";} ?>>html</option>
190
+ </select><br />
191
+ <?php _e("Recommended");?>: <code>plain</code>
192
+ <br />
193
+ </td>
194
+ </tr>
195
+ <tr>
196
+ <th width="33%" valign="top" scope="row"><?php _e('Wrap content in pre tags:') ?> </th>
197
+ <td>
198
+ <select name="WRAP_PRE" id="WRAP_PRE">
199
+ <option value="no">no</option>
200
+ <option value="yes" <?php if($config["WRAP_PRE"] == "yes") { echo "SELECTED";} ?>>yes</option>
201
+ </select><br />
202
+ <?php _e("Recommended");?>: <code>no</code>
203
+ <br />
204
+ </td>
205
+ </tr>
206
+ <tr>
207
+ <th width="33%" valign="top" scope="row"><?php _e('Add more meta information right before post:') ?> </th>
208
+ <td>
209
+ <select name="ADD_META" id="ADD_META">
210
+ <option value="no">no</option>
211
+ <option value="yes" <?php if($config["ADD_META"] == "yes") { echo "SELECTED";} ?>>yes</option>
212
+ </select><br />
213
+ <?php _e("Recommended");?>: <code>no</code>
214
+ <br />
215
+ </td>
216
+ </tr>
217
+ <?php echo BuildBooleanSelect("Replace newline characters with
218
+ html line breaks (&lt;br
219
+ /&gt;)","CONVERTNEWLINE",$config["CONVERTNEWLINE"]);?>
220
+ <?php echo BuildBooleanSelect("Forward Rejected Mail","FORWARD_REJECTED_MAIL",$config["FORWARD_REJECTED_MAIL"]);?>
221
+ <?php echo BuildBooleanSelect("Allow Subject In Mail","ALLOW_SUBJECT_IN_MAIL",$config["ALLOW_SUBJECT_IN_MAIL"]);?>
222
+ <?php echo BuildBooleanSelect("Allow HTML In Mail Subject","ALLOW_HTML_IN_SUBJECT",$config["ALLOW_HTML_IN_SUBJECT"]);?>
223
+ <?php echo BuildBooleanSelect("Allow HTML In Mail Body","ALLOW_HTML_IN_BODY",$config["ALLOW_HTML_IN_BODY"]);?>
224
+ <tr>
225
+ <th width="33%" valign="top" scope="row"><?php _e('Encoding for pages and feeds:') ?> </th>
226
+ <td>
227
+ <input name="MESSAGE_ENCODING" type="text" id="MESSAGE_ENCODING" value="<?php echo $config["MESSAGE_ENCODING"]; ?>" size="50" /><br />
228
+ <?php _e("Recommended");?>: <code>UTF-8</code> - it should handle ISO-8859-1 as well
229
+ <br />
230
+ </td>
231
+ </tr>
232
+ <?php echo BuildBooleanSelect("Decode Quoted Printable Data","MESSAGE_DEQUOTE",$config["MESSAGE_DEQUOTE"], "Should be yes in most cases.");?>
233
+ <?php echo BuildTextArea("Supported File Types","SUPPORTED_FILE_TYPES",$config["SUPPORTED_FILE_TYPES"],"Put each type on a single line.");?>
234
+ <?php echo BuildTextArea("Banned File Names","BANNED_FILES_LIST",$config["BANNED_FILES_LIST"],"Put each file name on a single line.Files matching this list will never be posted to your blog.");?>
235
+ <tr>
236
+ <th width="33%" valign="top" scope="row"><?php _e('Tag Of Message Start:') ?> </th>
237
+ <td>
238
+ <p>This tag can be used to remove any text from a message that the email provider puts at the top of the message</p>
239
+ <input name="MESSAGE_START" type="text" id="MESSAGE_START" value="<?php echo $config["MESSAGE_START"]; ?>" size="50" /><br />
240
+ <?php _e("Recommended");?>: <code>:start</code>
241
+ <br />
242
+ </td>
243
+ </tr>
244
+ <tr>
245
+ <th width="33%" valign="top" scope="row"><?php _e('Tag Of Message End:') ?> </th>
246
+ <td>
247
+ <p>This tag can be used to remove any text from a message that the email provider puts at the bottom of the message</p>
248
+ <input name="MESSAGE_END" type="text" id="MESSAGE_END" value="<?php echo $config["MESSAGE_END"]; ?>" size="50" /><br />
249
+ <?php _e("Recommended");?>: <code>:end</code>
250
+ <br />
251
+ </td>
252
+ </tr>
253
+ <?php echo BuildBooleanSelect("Drop The Signature From Mail","DROP_SIGNATURE",$config["DROP_SIGNATURE"]);?>
254
+ <?php echo BuildTextArea("Signature Patterns","SIG_PATTERN_LIST",$config["SIG_PATTERN_LIST"],"Put each pattern on a seperate line and make sure to escape any special characters.");?>
255
+ </table>
256
+ </fieldset>
257
+ </td>
258
+ </tr>
259
+
260
+
261
+ <tr><td colspan=2>
262
+ <fieldset class="options">
263
+ <legend><?php _e('Image Settings');?></legend>
264
+ <table width="100%" cellspacing="2" cellpadding="5" class="editform">
265
+ <?php if (!HasGDInstalled()):?>
266
+ <tr>
267
+ <th scope="row">No GD Support </th>
268
+ <td>Currently your installation of PHP does not have GD installed so no image resizing can occur.
269
+ <input type="hidden" name="RESIZE_LARGE_IMAGES" value="0">
270
+ <input type="hidden" name="JPEGQUALITY"" value="80">
271
+ </td>
272
+ </tr>
273
+ <?php else:?>
274
+ <?php echo BuildBooleanSelect("Post Images At End","IMAGES_APPEND",$config["IMAGES_APPEND"],"No means they will be put before the text of the message.");?>
275
+ <?php echo BuildBooleanSelect("Resize Large Images","RESIZE_LARGE_IMAGES",$config["RESIZE_LARGE_IMAGES"]);?>
276
+ <tr>
277
+ <th scope="row"><?php _e('Maximum Image Width:') ?> </th>
278
+ <td><input name="MAX_IMAGE_WIDTH" type="text" id="MAX_IMAGE_WIDTH" value="<?php echo $config['MAX_IMAGE_WIDTH']; ?>" size="4" />
279
+ <?php _e('pixels') ?>
280
+ <br /><?php _e("Recommended");?>: <code>400</code><br />
281
+ </td>
282
+ </tr>
283
+ <tr>
284
+ <th scope="row"><?php _e('Maximum Image Height:') ?> </th>
285
+ <td><input name="MAX_IMAGE_HEIGHT" type="text" id="MAX_IMAGE_HEIGHT" value="<?php echo $config['MAX_IMAGE_HEIGHT']; ?>" size="4" />
286
+ <?php _e('pixels') ?>
287
+ <br /><?php _e("Recommended");?>: <code>Leave Blank</code><br />
288
+ </td>
289
+ </tr>
290
+ <tr>
291
+ <th scope="row"><?php _e('JPEG Compression:') ?> </th>
292
+ <td><input name="JPEGQUALITY" type="text" id="JPEGQUALITY" value="<?php echo $config['JPEGQUALITY']; ?>" size="3" />
293
+ <?php _e('%') ?>
294
+ <br /><?php _e("Recommended");?>: <code>80</code>%
295
+ </td>
296
+ </tr>
297
+ <?php endif;?>
298
+ <?php echo BuildBooleanSelect("Use ImageMagick","USE_IMAGEMAGICK",$config["USE_IMAGEMAGICK"]);?>
299
+ <tr>
300
+ <th scope="row"><?php _e('convert binary location:') ?> </th>
301
+ <td><input name="IMAGEMAGICK_CONVERT" type="text" id="IMAGEMAGICK_CONVERT" value="<?php echo $config['IMAGEMAGICK_CONVERT']; ?>" size="30" />
302
+ <br /><?php _e("Recommended");?>: <code>only needed if you are using ImageMagick <br /> should be /usr/bin/convert</code>
303
+ </td>
304
+ </tr>
305
+ <?php echo BuildBooleanSelect("Automatic SmartSharp Mask","AUTO_SMART_SHARP",$config["AUTO_SMART_SHARP"],"This automatically smart sharpens the images that are posted. This feature is <b>EXPERIMENTAL</b>. It alsot takes a lot of processing power");?>
306
+
307
+ <?php echo BuildBooleanSelect("Start Image Count At 0","START_IMAGE_COUNT_AT_ZERO",$config["START_IMAGE_COUNT_AT_ZERO"]);?>
308
+ <tr>
309
+ <th width="33%" valign="top" scope="row"><?php _e('Image Place Holder Tag:') ?> </th>
310
+ <td>
311
+ <input name="IMAGE_PLACEHOLDER" type="text" id="IMAGE_PLACEHOLDER" value="<?php echo $config["IMAGE_PLACEHOLDER"]; ?>" size="50" /><br />
312
+ <?php _e("Recommended");?>: <code>#img%#</code>
313
+ <br />
314
+ </td>
315
+ </tr>
316
+ <tr>
317
+ <th width="33%" valign="top" scope="row"><?php _e('Image CSS Class:') ?> </th>
318
+ <td>
319
+ <input name="IMAGECLASS" type="text" id="IMAGECLASS" value="<?php echo $config["IMAGECLASS"]; ?>" size="50" /><br />
320
+ <?php _e("Recommended");?>: <code>postie-image</code>
321
+ <br />
322
+ </td>
323
+ </tr>
324
+ <tr>
325
+ <th width="33%" valign="top" scope="row"><?php _e('Image CSS Style:') ?> </th>
326
+ <td>
327
+ <input name="IMAGESTYLE" type="text" id="IMAGESTYLE" value="<?php echo $config["IMAGESTYLE"]; ?>" size="50" /><br />
328
+ <?php _e("Recommended");?>: <code>border: none;</code>
329
+ <br />
330
+ </td>
331
+ </tr>
332
+ <tr>
333
+ <th width="33%" valign="top" scope="row"><?php _e('Image Div CSS:') ?> </th>
334
+ <td>
335
+ <input name="IMAGEDIV" type="text" id="IMAGEDIV" value="<?php echo $config["IMAGEDIV"]; ?>" size="50" /><br />
336
+ <?php _e("Recommended");?>: <code>postie-image-div</code><p>This is the CSS class of a div that wraps each image. Can be used to style the post</p>
337
+ <br />
338
+ </td>
339
+ </tr>
340
+ <?php echo BuildBooleanSelect("Open images in new
341
+ window","IMAGE_NEW_WINDOW",$config["IMAGE_NEW_WINDOW"],"Recommended:
342
+ no");?>
343
+ <tr>
344
+ <?php echo BuildBooleanSelect("Use custom image
345
+ template","USEIMAGETEMPLATE",$config["USEIMAGETEMPLATE"],"If you
346
+ don't like the default html output around images, you can enter
347
+ your own below. The default template is already there. See the
348
+ readme for more details");?>
349
+ <th width="33%" valign="top" scope="row"> <td>
350
+ <textarea cols="50" rows="6" name="IMAGETEMPLATE"
351
+ id="IMAGETEMPLATE"><?php
352
+ echo $config["IMAGETEMPLATE"]; ?>
353
+ </textarea>
354
+ </td>
355
+ </tr>
356
+ <tr>
357
+ <th width="33%" valign="top" scope="row"><?php _e('Attachment Div CSS:') ?> </th>
358
+ <td>
359
+ <input name="ATTACHMENTDIV" type="text" id="ATTACHMENTDIV" value="<?php echo $config["ATTACHMENTDIV"]; ?>" size="50" /><br />
360
+ <?php _e("Recommended");?>: <code>postie-attachment-div</code><p>This is the CSS class of a div that wraps each file attachment. Can be used to style the post</p>
361
+ <br />
362
+ </td>
363
+ </tr>
364
+ </table>
365
+ </fieldset>
366
+ </td>
367
+ </tr>
368
+
369
+
370
+ <tr><td colspan=2>
371
+ <fieldset class="options">
372
+ <legend><?php _e('3GP');?></legend>
373
+ <table width="100%" cellspacing="2" cellpadding="5" class="editform">
374
+ <?php echo BuildBooleanSelect("Embed 3GP videos as QuickTime","3GP_QT",$config["3GP_QT"],"This controls if the video is just a link or embeded in the page using QuickTime");?>
375
+ <tr>
376
+ <th scope="row"><?php _e('Location of ffmpeg:') ?> </th>
377
+ <td><input name="3GP_FFMPEG" type="text" id="3GP_FFMPEG" value="<?php echo $config['3GP_FFMPEG']; ?>" size="30" />
378
+ <br /><?php _e("Recommended");?>: <code><?php _e("only needed if you are on a Linux server and use 3gp video,and don't embed the video. This allows postie to make thumbnail of the very first frame");?> <br /><?php _e("should be /usr/bin/ffmpeg");?></code>
379
+ </td>
380
+ </tr>
381
+ <tr>
382
+ <th width="33%" valign="top" scope="row"><?php _e('3GP CSS Class:') ?> </th>
383
+ <td>
384
+ <input name="3GPCLASS" type="text" id="3GPCLASS" value="<?php echo $config["3GPCLASS"]; ?>" size="50" /><br />
385
+ <?php _e("Recommended");?>: <code>wp-mailvideo</code>
386
+ <br />
387
+ </td>
388
+ </tr>
389
+ <tr>
390
+ <th width="33%" valign="top" scope="row"><?php _e('3GP Div CSS:') ?> </th>
391
+ <td>
392
+ <input name="3GPDIV" type="text" id="3GPDIV" value="<?php echo $config["3GPDIV"]; ?>" size="50" /><br />
393
+ <?php _e("Recommended");?>: <code>postie-3gp-div</code><p>This is the CSS class of a div that wraps each 3GP video. Can be used to style the post</p>
394
+ <br />
395
+ </td>
396
+ </tr>
397
+ </table>
398
+ </fieldset>
399
+ </td>
400
+ </tr>
401
+
402
+
403
+
404
+
405
+
406
+ <tr><td colspan=2>
407
+ <fieldset class="options">
408
+ <legend><?php _e('Mailserver Settings');?></legend>
409
+
410
+
411
+ <table width="100%" cellspacing="2" cellpadding="5" class="editform">
412
+ <tr>
413
+ <th scope="row"><?php _e('Mail Protocol:') ?></th>
414
+ <td>
415
+ <table>
416
+ <tr><td>
417
+ <select name="INPUT_PROTOCOL" id="INPUT_PROTOCOL">
418
+ <option value="pop3">POP3</option>
419
+ <?php if (HasIMAPSupport(false)):?>
420
+ <option value="imap" <?php if($config["INPUT_PROTOCOL"] == "imap") { echo "SELECTED";} ?>>IMAP</option>
421
+ <option value="pop3-ssl" <?php if($config["INPUT_PROTOCOL"] == "pop3-ssl") { echo "SELECTED";} ?>>POP3-SSL</option>
422
+ <option value="imap-ssl" <?php if($config["INPUT_PROTOCOL"] == "imap-ssl") { echo "SELECTED";} ?>>IMAP-SSL</option>
423
+ <?php else:?>
424
+ <option value="pop3" ><?php _e("IMAP/IMAP-SSL/POP3-SSL unavailable");?></option>
425
+ <?php endif;?>
426
+ </select>
427
+ </td><td>
428
+ <code><?php _e("Standard Ports:");?><br />
429
+ <?php _e("POP3");?> - 110<br />
430
+ <?php _e("IMAP");?> - 143<br />
431
+ <?php _e("IMAP-SSL");?>- 993 <br />
432
+ <?php _e("POP3-SSL");?> - 995 <br />
433
+ </code>
434
+ </td></tr></table></td>
435
+ <tr>
436
+ <th scope="row"><?php _e('Postie Time Correction:') ?> </th>
437
+ <td><input name="TIME_OFFSET" type="text" id="TIME_OFFSET" size="2" value="<?php echo $config['TIME_OFFSET']; ?>" />
438
+ <?php _e('hours') ?>
439
+ <br />
440
+ <?php _e("Recommended");?>: <code><?php _e("Should be the same as your normal offset - but this lets you adjust it in cases where that doesn't work.");?></code>
441
+ <br />
442
+
443
+ </td>
444
+ </tr>
445
+ </tr>
446
+ <tr valign="top">
447
+ <th scope="row"><?php _e('Mail Server:') ?></th>
448
+ <td><input name="MAIL_SERVER" type="text" id="MAIL_SERVER" value="<?php echo $config["MAIL_SERVER"];?>" size="40" />
449
+ <?php _e('Port:') ?>
450
+ <input name="MAIL_SERVER_PORT" type="text" id="MAIL_SERVER_PORT" value="<?php echo $config["MAIL_SERVER_PORT"];?>" size="6" />
451
+ </td>
452
+ </tr>
453
+ <tr valign="top">
454
+ <th width="33%" scope="row"><?php _e('Mail Userid:') ?></th>
455
+ <td><input name="MAIL_USERID" type="text" id="MAIL_USERID" value="<?php echo $config["MAIL_USERID"]; ?>" size="40" /></td>
456
+ </tr>
457
+ <tr valign="top">
458
+ <th scope="row"><?php _e('Mail Password:') ?></th>
459
+ <td>
460
+ <input name="MAIL_PASSWORD" type="text" id="MAIL_PASSWORD" value="<?php echo $config["MAIL_PASSWORD"]; ?>" size="40" />
461
+ </td>
462
+ </tr>
463
+ </table>
464
+ </fieldset>
465
+ </td>
466
+ </tr>
467
+
468
+
469
+
470
+
471
+
472
+
473
+
474
+
475
+ </table>
476
+ <p class="submit">
477
+ <input type="submit" name="Submit" value="<?php _e('Update Options') ?> &raquo;" />
478
+ </p>
479
+ </form>
480
+ </div>
config_handler.php ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * This file handles submissions from the config form
4
+ */
5
+ require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR ."postie-functions.php");
6
+
7
+ if (isset($_POST["action"])) {
8
+ switch($_POST["action"]) {
9
+
10
+ case "reset":
11
+ ResetPostieConfig();
12
+ $message = 1;
13
+ break;
14
+ case "cronless":
15
+ check_postie();
16
+ $message = 1;
17
+ break;
18
+ case "test":
19
+ $location = get_option('siteurl') . '/wp-admin/options-general.php?page=postie/postie_test.php';
20
+ header("Location: $location\n\n");
21
+ exit;
22
+ break;
23
+ case "config":
24
+ if( UpdatePostieConfig($_POST)) {
25
+ $message = 1;
26
+ }
27
+ else {
28
+ $message = 2;
29
+ }
30
+ break;
31
+ default:
32
+ $message = 2;
33
+ break;
34
+ }
35
+ $location = get_option('siteurl') . '/wp-admin/options-general.php?page=postie/postie.php';
36
+ header("Location: $location&message=$message\n\n");
37
+ exit();
38
+ }
39
+ ?>
cronless_postie.php ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: Cronless Postie
4
+ Plugin URI: http://www.economysizegeek.com/?page_id=395
5
+ Description: This plugin allows you to setup your rss feeds to trigger postie (See <a href="../wp-content/plugins/postie/cronless_postie.php?cronless_postie_read_me=1">Quick Readme</a>)
6
+ Author: Dirk Elmendorf
7
+ Version: 1.1.5
8
+ Author URI: http://www.economysizegeek.com/
9
+ */
10
+
11
+ include_once (dirname(dirname(dirname(dirname(__FILE__)))) . DIRECTORY_SEPARATOR. "wp-config.php");
12
+ function check_postie() {
13
+ $host = get_option('siteurl');
14
+ preg_match("/http:\/\/(.[^\/]*)(.*)/",$host,$matches);
15
+ $host = $matches[1];
16
+ $url = "";
17
+ if (isset($matches[2])) {
18
+ $url .= $matches[2];
19
+ }
20
+ $url .= "/wp-content/plugins/postie/get_mail.php";
21
+ $port = 80;
22
+ $fp=fsockopen($host,$port,$errno,$errstr);
23
+ fputs($fp,"GET $url HTTP/1.0\r\n");
24
+ fputs($fp,"User-Agent: Cronless-Postie\r\n");
25
+ fputs($fp,"Host: $host\r\n");
26
+ fputs($fp,"\r\n");
27
+ $page = '';
28
+ while(!feof($fp)) {
29
+ $page.=fgets($fp,128);
30
+ }
31
+ #var_dump($page);
32
+ fclose($fp);
33
+ }
34
+ function cronless_read_me() {
35
+ include_once("cronless_read_me.php");
36
+ }
37
+ if (isset($_GET["cronless_postie_read_me"])) {
38
+ include_once(ABSPATH . "wp-admin/admin.php");
39
+ $title = __("Edit Plugins");
40
+ $parent_file = 'plugins.php';
41
+ include(ABSPATH . 'wp-admin/admin-header.php');
42
+ cronless_read_me();
43
+ include(ABSPATH . 'wp-admin/admin-footer.php');
44
+ exit();
45
+ }
46
+
47
+
48
+ add_action('init','postie_cron');
49
+ function postie_cron() {
50
+ if (!wp_next_scheduled('check_postie')) {
51
+ wp_schedule_event(time(),'hourly','check_postie');
52
+ }
53
+ }
54
+ add_action('check_postie', 'check_postie');
55
+ /**
56
+ * Now just add the following line to all of the rss/atom pages
57
+ * Just make sure it is after the opening if statement
58
+
59
+ do_action('check_postie');
60
+
61
+ */
62
+
63
+ ?>
cronless_read_me.php ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
1
+
2
+ <div class="wrap">
3
+ <h1>Cronless Postie</h1>
4
+ <p>First off - this is a bit of a hack. I would love feedback on this since I don't use this - I have cron on my server :(</p>
5
+ <p>I'm trying to use the new Psuedo Cron that is part of WP2.1. It's not documented very well so I'm hoping this works </p>
6
+ </div>
get_mail.php ADDED
@@ -0,0 +1,50 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/php -q
2
+ <?php
3
+
4
+ //Load up some usefull libraries
5
+ include_once (dirname(dirname(dirname(dirname(__FILE__)))) . DIRECTORY_SEPARATOR."wp-config.php");
6
+ require_once (dirname(__FILE__). DIRECTORY_SEPARATOR . 'mimedecode.php');
7
+ require_once (dirname(__FILE__). DIRECTORY_SEPARATOR . 'postie-functions.php');
8
+
9
+ if (!TestWPVersion()) {
10
+ print("<p>Postie Only Works For Word Press 2.0 and above.</p>");
11
+ exit();
12
+ }
13
+
14
+ /* END OF USER VARIABLES */
15
+ //some variables
16
+ error_reporting(2037);
17
+ TestWPMailInstallation();
18
+
19
+ //Retreive emails
20
+ print("<pre>\n");
21
+ $emails = FetchMail();
22
+ //loop through messages
23
+ foreach ($emails as $email) {
24
+ //sanity check to see if there is any info in the message
25
+ if ($email == NULL ) { print 'Dang, message is empty!'; continue; }
26
+
27
+ $mimeDecodedEmail = DecodeMimeMail($email);
28
+ $from = RemoveExtraCharactersInEmailAddress(trim($mimeDecodedEmail->headers["from"]));
29
+ /*
30
+ if ($from != "") {
31
+ continue;
32
+ }
33
+ */
34
+
35
+ //Check poster to see if a valid person
36
+ $poster = ValidatePoster($mimeDecodedEmail);
37
+ if (!empty($poster)) {
38
+ DebugEmailOutput($email,$mimeDecodedEmail);
39
+ PostEmail($poster,$mimeDecodedEmail);
40
+ }
41
+ else {
42
+ print("<p>Ignoring email - not authorized.\n");
43
+ }
44
+ } // end looping over messages
45
+ print("</pre>\n");
46
+
47
+ /* END PROGRAM */
48
+
49
+ // end of script
50
+ ?>
languages/postie-en_US.mo ADDED
Binary file
languages/postie-en_US.po ADDED
@@ -0,0 +1,362 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Postie Translation File
2
+ # Copyright (C) 2005 Dirk Elmendorf <headgeek@economysizegeek.com>
3
+ # This file is distributed under the same license as Postie.
4
+ # Dirk Elmendorf <headgeek@economysizegeek.com>, 2005
5
+ #
6
+ msgid ""
7
+ msgstr ""
8
+ "Project-Id-Version: Postie\n"
9
+ "Report-Msgid-Bugs-To: \n"
10
+ "POT-Creation-Date: 2005-11-10 11:48-0600\n"
11
+ "PO-Revision-Date: 2005-11-10 12:42-0600\n"
12
+ "Last-Translator: Head Geek <headgeek@economysizegeek.com>\n"
13
+ "Language-Team: EconomysizeGeek <headgeek@economysizegeek.com>\n"
14
+ "MIME-Version: 1.0\n"
15
+ "Content-Type: text/plain; charset=utf-8\n"
16
+ "Content-Transfer-Encoding: 8bit\n"
17
+ "X-Poedit-Language: English\n"
18
+ "X-Poedit-Country: UNITED STATES\n"
19
+ "X-Poedit-SourceCharset: utf-8\n"
20
+
21
+ #: config_form.php:18
22
+ msgid "Postie Options"
23
+ msgstr "Postie Options"
24
+
25
+ #: config_form.php:18
26
+ msgid "Reset Configs To Default"
27
+ msgstr "Reset Configs To Default"
28
+
29
+ #: config_form.php:2
30
+ msgid "If you would like to start over - you can click the button on the right to reset all configurations to the default."
31
+ msgstr "If you would like to start over - you can click the button on the right to reset all configurations to the default."
32
+
33
+ #: config_form.php:30
34
+ msgid "To run the check mail script manually"
35
+ msgstr "To run the check mail script manually"
36
+
37
+ #: config_form.php:32
38
+ msgid "Run Postie"
39
+ msgstr "Run Postie"
40
+
41
+ #: config_form.php:39
42
+ msgid "If you have problems with Postie this will run a special script to test your configuraiton options"
43
+ msgstr "If you have problems with Postie this will run a special script to test your configuraiton options"
44
+
45
+ #: config_form.php:41
46
+ msgid "Test Config"
47
+ msgstr "Test Config"
48
+
49
+ msgid "Yes"
50
+ msgstr "Yes"
51
+
52
+ msgid "No"
53
+ msgstr "No"
54
+
55
+ #: config_form.php
56
+ msgid "Authorization Settings"
57
+ msgstr "Authorization Settings"
58
+
59
+ #: config_form.php
60
+ msgid "Allow Anyone To Post Via Email"
61
+ msgstr "Allow Anyone To Post Via Email"
62
+
63
+ #: config_form.php
64
+ msgid "Changing this to yes is NOT RECOMMEDED - anything that gets sent in will automatically be posted. This could make it easier to compromise your server - YOU HAVE BEEN WARNED."
65
+ msgstr "Changing this to yes is NOT RECOMMEDED - anything that gets sent in will automatically be posted. This could make it easier to compromise your server - YOU HAVE BEEN WARNED."
66
+
67
+ #: config_form.php
68
+ msgid "Minimum Access Level Required To Post:"
69
+ msgstr "Minimum Access Level Required To Post:"
70
+
71
+ #: config_form.php
72
+ msgid "This allows you to grant access to other users to post if they have the proper access level"
73
+ msgstr "This allows you to grant access to other users to post if they have the proper access level"
74
+
75
+ #: config_form.php
76
+ msgid "Authorized Addresses"
77
+ msgstr "Authorized Addresses"
78
+
79
+ #: config_form.php
80
+ msgid "Put each email address on a single line. Posts from emails in this list will be treated as if they came from the admin. If you would prefer to have users post under their own name - create a WordPress user with the correct access level."
81
+ msgstr "Put each email address on a single line. Posts from emails in this list will be treated as if they came from the admin. If you would prefer to have users post under their own name - create a WordPress user with the correct access level."
82
+
83
+ #: config_form.php
84
+ msgid "Directory Settings"
85
+ msgstr "Directory Settings"
86
+
87
+ #: config_form.php
88
+ msgid "Directory For Photos:"
89
+ msgstr "Directory For Photos:"
90
+
91
+ #: config_form.php
92
+ msgid "Recommended"
93
+ msgstr "Recommended"
94
+
95
+ #: config_form.php
96
+ msgid "Directory For Files:"
97
+ msgstr "Directory For Files:"
98
+
99
+ #: config_form.php
100
+ msgid "Message Settings"
101
+ msgstr "Message Settings"
102
+
103
+ #: config_form.php
104
+ msgid "Default post by mail category:"
105
+ msgstr "Default post by mail category:"
106
+
107
+ #: config_form.php
108
+ msgid "Default Title:"
109
+ msgstr "Default Title:"
110
+
111
+ #: config_form.php
112
+ msgid "Live from the field"
113
+ msgstr "Live from the field"
114
+
115
+ #: config_form.php
116
+ msgid "Prefered Text Type (HTML/plain):"
117
+ msgstr "Prefered Text Type (HTML/plain):"
118
+
119
+ #: config_form.php
120
+ msgid "plain"
121
+ msgstr "plain"
122
+
123
+ #: config_form.php
124
+ msgid "html"
125
+ msgstr "html"
126
+
127
+ #: config_form.php
128
+ msgid "Forward Rejected Mail"
129
+ msgstr "Forward Rejected Mail"
130
+
131
+ #: config_form.php
132
+ msgid "Allow Subject In Mail"
133
+ msgstr "Allow Subject In Mail"
134
+
135
+ #: config_form.php
136
+ msgid "Allow HTML In Mail Subject"
137
+ msgstr "Allow HTML In Mail Subject"
138
+
139
+ #: config_form.php
140
+ msgid "Allow HTML In Mail Body"
141
+ msgstr "Allow HTML In Mail Body"
142
+
143
+ #: config_form.php
144
+ msgid "Encoding for pages and feeds:"
145
+ msgstr "Encoding for pages and feeds:"
146
+
147
+ #: config_form.php
148
+ msgid "UTF-8"
149
+ msgstr "UTF-8"
150
+
151
+ #: config_form.php
152
+ msgid "it should handle ISO-8859-1 as well"
153
+ msgstr "it should handle ISO-8859-1 as well"
154
+
155
+ #: config_form.php
156
+ msgid "Decode Quoted Printable Data"
157
+ msgstr "Decode Quoted Printable Data"
158
+
159
+ #: config_form.php
160
+ msgid "Should be yes in most cases."
161
+ msgstr "Should be yes in most cases."
162
+
163
+ #: config_form.php
164
+ msgid "Supported File Types"
165
+ msgstr "Supported File Types"
166
+
167
+ #: config_form.php
168
+ msgid "Put each type on a single line."
169
+ msgstr "Put each type on a single line."
170
+
171
+ #: config_form.php
172
+ msgid "Banned File Names"
173
+ msgstr "Banned File Names"
174
+
175
+ #: config_form.php
176
+ msgid "Put each file name on a single line.Files matching this list will never be posted to your blog."
177
+ msgstr "Put each file name on a single line.Files matching this list will never be posted to your blog."
178
+
179
+ #: config_form.php
180
+ msgid "Drop The Signature From Mail"
181
+ msgstr "Drop The Signature From Mail"
182
+
183
+ #: config_form.php
184
+ msgid "Signature Patterns"
185
+ msgstr "Signature Patterns"
186
+
187
+ #: config_form.php
188
+ msgid "Put each pattern on a seperate line and make sure to escape any special characters."
189
+ msgstr "Put each pattern on a seperate line and make sure to escape any special characters."
190
+
191
+ #: config_form.php
192
+ msgid "Image Settings"
193
+ msgstr "Image Settings"
194
+
195
+ #: config_form.php
196
+ msgid "No GD Support"
197
+ msgstr "No GD Support"
198
+
199
+ #: config_form.php
200
+ msgid "Currently your installation of PHP does not have GD installed so no image resizing can occur."
201
+ msgstr "Currently your installation of PHP does not have GD installed so no image resizing can occur."
202
+
203
+ #: config_form.php
204
+ msgid "Post Images At End"
205
+ msgstr "Post Images At End"
206
+
207
+ #: config_form.php
208
+ msgid "No means they will be put before the text of the message."
209
+ msgstr "No means they will be put before the text of the message."
210
+
211
+ #: config_form.php
212
+ msgid "Resize Large Images"
213
+ msgstr "Resize Large Images"
214
+
215
+ #: config_form.php
216
+ msgid "Maximum Image Width:"
217
+ msgstr "Maximum Image Width:"
218
+
219
+ #: config_form.php
220
+ msgid "pixels"
221
+ msgstr "pixels"
222
+
223
+ #: config_form.php
224
+ msgid "JPEG Compression:"
225
+ msgstr "JPEG Compression:"
226
+
227
+ #: config_form.php
228
+ msgid "%"
229
+ msgstr "%"
230
+
231
+ #: config_form.php
232
+ msgid "Use ImageMagick"
233
+ msgstr "Use ImageMagick"
234
+
235
+ #: config_form.php
236
+ msgid "convert binary location:"
237
+ msgstr "convert binary location:"
238
+
239
+ #: config_form.php
240
+ msgid "only needed if you are using ImageMagick"
241
+ msgstr "only needed if you are using ImageMagick"
242
+
243
+ #: config_form.php
244
+ msgid "should be /usr/bin/convert"
245
+ msgstr "should be /usr/bin/convert"
246
+
247
+ #: config_form.php
248
+ msgid "identify binary location:"
249
+ msgstr "identify binary location:"
250
+
251
+ #: config_form.php
252
+ msgid "should be /usr/bin/identify"
253
+ msgstr "should be /usr/bin/identify"
254
+
255
+ #: config_form.php
256
+ msgid "Start Image Count At 0"
257
+ msgstr "Start Image Count At 0"
258
+
259
+ #: config_form.php
260
+ msgid "Image Place Holder Tag:"
261
+ msgstr "Image Place Holder Tag:"
262
+
263
+ #: config_form.php
264
+ msgid "Image CSS Class:"
265
+ msgstr "Image CSS Class:"
266
+
267
+ #: config_form.php
268
+ msgid "Image CSS Style:"
269
+ msgstr "Image CSS Style:"
270
+
271
+ #: config_form.php
272
+ msgid "3GP"
273
+ msgstr "3GP"
274
+
275
+ #: config_form.php
276
+ msgid "Embed 3GP videos as QuickTime"
277
+ msgstr "Embed 3GP videos as QuickTime"
278
+
279
+ #: config_form.php
280
+ msgid "This controls if the video is just a link or embeded in the page using QuickTime"
281
+ msgstr "This controls if the video is just a link or embeded in the page using QuickTime"
282
+
283
+ #: config_form.php
284
+ msgid "Location of ffmpeg:"
285
+ msgstr "Location of ffmpeg:"
286
+
287
+ #: config_form.php
288
+ msgid "only needed if you are on a Linux server and use 3gp video,and don't embed the video. This allows postie to make thumbnail of the very first frame"
289
+ msgstr "only needed if you are on a Linux server and use 3gp video,and don't embed the video. This allows postie to make thumbnail of the very first frame"
290
+
291
+ #: config_form.php
292
+ msgid "should be /usr/bin/ffmpeg"
293
+ msgstr "should be /usr/bin/ffmpeg"
294
+
295
+ #: config_form.php
296
+ msgid "3GP CSS Class:"
297
+ msgstr "3GP CSS Class:"
298
+
299
+ #: config_form.php
300
+ msgid "Mailserver Settings"
301
+ msgstr "Mailserver Settings"
302
+
303
+ #: config_form.php
304
+ msgid "Mail Protocol:"
305
+ msgstr "Mail Protocol:"
306
+
307
+ #: config_form.php
308
+ msgid "IMAP/IMAP-SSL/POP3-SSL unavailable"
309
+ msgstr "IMAP/IMAP-SSL/POP3-SSL unavailable"
310
+
311
+ #: config_form.php
312
+ msgid "Standard Ports:"
313
+ msgstr "Standard Ports:"
314
+
315
+ #: config_form.php
316
+ msgid "POP3"
317
+ msgstr "POP3"
318
+
319
+ #: config_form.php
320
+ msgid "IMAP"
321
+ msgstr "IMAP"
322
+
323
+ #: config_form.php
324
+ msgid "IMAP-SSL"
325
+ msgstr "IMAP-SSL"
326
+
327
+ #: config_form.php
328
+ msgid "POP3-SSL"
329
+ msgstr "POP3-SSL"
330
+
331
+ #: config_form.php
332
+ msgid "Postie Time Correction:"
333
+ msgstr "Postie Time Correction:"
334
+
335
+ #: config_form.php
336
+ msgid "hours"
337
+ msgstr "hours"
338
+
339
+ #: config_form.php
340
+ msgid "Should be the same as your normal offset - but this lets you adjust it in cases where that doesn't work."
341
+ msgstr "Should be the same as your normal offset - but this lets you adjust it in cases where that doesn't work."
342
+
343
+ #: config_form.php
344
+ msgid "Mail Server:"
345
+ msgstr "Mail Server:"
346
+
347
+ #: config_form.php
348
+ msgid "Port:"
349
+ msgstr "Port:"
350
+
351
+ #: config_form.php
352
+ msgid "Mail Userid:"
353
+ msgstr "Mail Userid:"
354
+
355
+ #: config_form.php
356
+ msgid "Mail Password:"
357
+ msgstr "Mail Password:"
358
+
359
+ #: config_form.php
360
+ msgid "Update Options"
361
+ msgstr "Update Options"
362
+
languages/postie.pot ADDED
@@ -0,0 +1,356 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Postie Translation File
2
+ # Copyright (C) YEAR Translator <translator@invalid>
3
+ # This file is distributed under the same license as the PACKAGE package.
4
+ # FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
5
+ #
6
+ #, fuzzy
7
+
8
+ msgid ""
9
+ msgstr ""
10
+ "Project-Id-Version: Postie\n"
11
+ "Report-Msgid-Bugs-To: \n"
12
+ "POT-Creation-Date: 2005-11-10 11:48-0600 \n"
13
+ "PO-Revision-Date: 2005-11-10 11:48-0600\n"
14
+ "Last-Translator: Head Geek <headgeek@economysizegeek.com>\n"
15
+ "Language-Team: \n"
16
+ "MIME-Version: 1.0\n"
17
+ "Content-Type: text/plain; charset=utf-8\n"
18
+ "Content-Transfer-Encoding: 8bit\n"
19
+
20
+ #: config_form.php:18
21
+ msgid "Postie Options"
22
+ msgstr ""
23
+ #: config_form.php:18
24
+ msgid "Reset Configs To Default"
25
+ msgstr ""
26
+ #: config_form.php:2
27
+ msgid "If you would like to start over - you can click the button on the right to reset all configurations to the default."
28
+ msgstr ""
29
+ #: config_form.php:30
30
+ msgid "To run the check mail script manually"
31
+ msgstr ""
32
+ #: config_form.php:32
33
+ msgid "Run Postie"
34
+ msgstr ""
35
+ #: config_form.php:39
36
+ msgid "If you have problems with Postie this will run a special script to test your configuraiton options"
37
+ msgstr ""
38
+ #: config_form.php:41
39
+ msgid "Test Config"
40
+ msgstr ""
41
+ msgid "Recommended"
42
+ msgstr ""
43
+ msgid "Yes"
44
+ msgstr ""
45
+ msgid "No"
46
+ msgstr ""
47
+ #: config_form.php
48
+ msgid "Authorization Settings"
49
+ msgstr ""
50
+
51
+ #: config_form.php
52
+ msgid "Allow Anyone To Post Via Email"
53
+ msgstr ""
54
+
55
+ #: config_form.php
56
+ msgid "Changing this to yes is NOT RECOMMEDED - anything that gets sent in will automatically be posted. This could make it easier to compromise your server - YOU HAVE BEEN WARNED."
57
+ msgstr ""
58
+
59
+ #: config_form.php
60
+ msgid "Minimum Access Level Required To Post:"
61
+ msgstr ""
62
+
63
+ #: config_form.php
64
+ msgid "This allows you to grant access to other users to post if they have the proper access level"
65
+ msgstr ""
66
+
67
+ #: config_form.php
68
+ msgid "Authorized Addresses"
69
+ msgstr ""
70
+
71
+ #: config_form.php
72
+ msgid "Put each email address on a single line. Posts from emails in this list will be treated as if they came from the admin. If you would prefer to have users post under their own name - create a WordPress user with the correct access level."
73
+ msgstr ""
74
+
75
+ #: config_form.php
76
+ msgid "Directory Settings"
77
+ msgstr ""
78
+
79
+ #: config_form.php
80
+ msgid "Directory For Photos:"
81
+ msgstr ""
82
+
83
+
84
+ #: config_form.php
85
+ msgid "Directory For Files:"
86
+ msgstr ""
87
+
88
+ #: config_form.php
89
+ msgid "Message Settings"
90
+ msgstr ""
91
+
92
+ #: config_form.php
93
+ msgid "Default post by mail category:"
94
+ msgstr ""
95
+
96
+ #: config_form.php
97
+ msgid "Default Title:"
98
+ msgstr ""
99
+
100
+ #: config_form.php
101
+ msgid "Live from the field"
102
+ msgstr ""
103
+
104
+ #: config_form.php
105
+ msgid "Prefered Text Type (HTML/plain):"
106
+ msgstr ""
107
+
108
+ #: config_form.php
109
+ msgid "plain"
110
+ msgstr ""
111
+
112
+ #: config_form.php
113
+ msgid "html"
114
+ msgstr ""
115
+
116
+ #: config_form.php
117
+ msgid "Forward Rejected Mail"
118
+ msgstr ""
119
+
120
+ #: config_form.php
121
+ msgid "Allow Subject In Mail"
122
+ msgstr ""
123
+
124
+ #: config_form.php
125
+ msgid "Allow HTML In Mail Subject"
126
+ msgstr ""
127
+
128
+ #: config_form.php
129
+ msgid "Allow HTML In Mail Body"
130
+ msgstr ""
131
+
132
+ #: config_form.php
133
+ msgid "Encoding for pages and feeds:"
134
+ msgstr ""
135
+
136
+ #: config_form.php
137
+ msgid "UTF-8"
138
+ msgstr ""
139
+
140
+ #: config_form.php
141
+ msgid "it should handle ISO-8859-1 as well"
142
+ msgstr ""
143
+
144
+ #: config_form.php
145
+ msgid "Decode Quoted Printable Data"
146
+ msgstr ""
147
+
148
+ #: config_form.php
149
+ msgid "Should be yes in most cases."
150
+ msgstr ""
151
+
152
+ #: config_form.php
153
+ msgid "Supported File Types"
154
+ msgstr ""
155
+
156
+ #: config_form.php
157
+ msgid "Put each type on a single line."
158
+ msgstr ""
159
+
160
+ #: config_form.php
161
+ msgid "Banned File Names"
162
+ msgstr ""
163
+
164
+ #: config_form.php
165
+ msgid "Put each file name on a single line.Files matching this list will never be posted to your blog."
166
+ msgstr ""
167
+
168
+
169
+ #: config_form.php
170
+ msgid :start
171
+ msgstr ""
172
+
173
+ #: config_form.php
174
+ msgid "Drop The Signature From Mail"
175
+ msgstr ""
176
+
177
+ #: config_form.php
178
+ msgid "Signature Patterns"
179
+ msgstr ""
180
+
181
+ #: config_form.php
182
+ msgid "Put each pattern on a seperate line and make sure to escape any special characters."
183
+ msgstr ""
184
+
185
+ #: config_form.php
186
+ msgid "Image Settings"
187
+ msgstr ""
188
+
189
+ #: config_form.php
190
+ msgid "No GD Support"
191
+ msgstr ""
192
+
193
+ #: config_form.php
194
+ msgid "Currently your installation of PHP does not have GD installed so no image resizing can occur."
195
+ msgstr ""
196
+
197
+ #: config_form.php
198
+ msgid "Post Images At End"
199
+ msgstr ""
200
+
201
+ #: config_form.php
202
+ msgid "No means they will be put before the text of the message."
203
+ msgstr ""
204
+
205
+ #: config_form.php
206
+ msgid "Resize Large Images"
207
+ msgstr ""
208
+
209
+ #: config_form.php
210
+ msgid "Maximum Image Width:"
211
+ msgstr ""
212
+
213
+ #: config_form.php
214
+ msgid "pixels"
215
+ msgstr ""
216
+
217
+ #: config_form.php
218
+ msgid "JPEG Compression:"
219
+ msgstr ""
220
+
221
+ #: config_form.php
222
+ msgid "%"
223
+ msgstr ""
224
+
225
+ #: config_form.php
226
+ msgid "Use ImageMagick"
227
+ msgstr ""
228
+
229
+ #: config_form.php
230
+ msgid "convert binary location:"
231
+ msgstr ""
232
+
233
+ #: config_form.php
234
+ msgid "only needed if you are using ImageMagick"
235
+ msgstr ""
236
+
237
+ #: config_form.php
238
+ msgid "should be /usr/bin/convert"
239
+ msgstr ""
240
+
241
+ #: config_form.php
242
+ msgid "identify binary location:"
243
+ msgstr ""
244
+
245
+ #: config_form.php
246
+ msgid "should be /usr/bin/identify"
247
+ msgstr ""
248
+
249
+ #: config_form.php
250
+ msgid "Start Image Count At 0"
251
+ msgstr ""
252
+
253
+ #: config_form.php
254
+ msgid "Image Place Holder Tag:"
255
+ msgstr ""
256
+
257
+ #: config_form.php
258
+ msgid "Image CSS Class:"
259
+ msgstr ""
260
+
261
+ #: config_form.php
262
+ msgid "Image CSS Style:"
263
+ msgstr ""
264
+
265
+ #: config_form.php
266
+ msgid "3GP"
267
+ msgstr ""
268
+
269
+ #: config_form.php
270
+ msgid "Embed 3GP videos as QuickTime"
271
+ msgstr ""
272
+
273
+ #: config_form.php
274
+ msgid "This controls if the video is just a link or embeded in the page using QuickTime"
275
+ msgstr ""
276
+
277
+ #: config_form.php
278
+ msgid "Location of ffmpeg:"
279
+ msgstr ""
280
+
281
+ #: config_form.php
282
+ msgid "only needed if you are on a Linux server and use 3gp video,and don't embed the video. This allows postie to make thumbnail of the very first frame"
283
+ msgstr ""
284
+
285
+ #: config_form.php
286
+ msgid "should be /usr/bin/ffmpeg"
287
+ msgstr ""
288
+
289
+ #: config_form.php
290
+ msgid "3GP CSS Class:"
291
+ msgstr ""
292
+
293
+ #: config_form.php
294
+ msgid "Mailserver Settings"
295
+ msgstr ""
296
+
297
+ #: config_form.php
298
+ msgid "Mail Protocol:"
299
+ msgstr ""
300
+
301
+ #: config_form.php
302
+ msgid "IMAP/IMAP-SSL/POP3-SSL unavailable"
303
+ msgstr ""
304
+
305
+ #: config_form.php
306
+ msgid "Standard Ports:"
307
+ msgstr ""
308
+
309
+ #: config_form.php
310
+ msgid "POP3"
311
+ msgstr ""
312
+
313
+ #: config_form.php
314
+ msgid "IMAP"
315
+ msgstr ""
316
+
317
+ #: config_form.php
318
+ msgid "IMAP-SSL"
319
+ msgstr ""
320
+
321
+ #: config_form.php
322
+ msgid "POP3-SSL"
323
+ msgstr ""
324
+
325
+ #: config_form.php
326
+ msgid "Postie Time Correction:"
327
+ msgstr ""
328
+
329
+ #: config_form.php
330
+ msgid "hours"
331
+ msgstr ""
332
+
333
+ #: config_form.php
334
+ msgid "Should be the same as your normal offset - but this lets you adjust it in cases where that doesn't work."
335
+ msgstr ""
336
+
337
+ #: config_form.php
338
+ msgid "Mail Server:"
339
+ msgstr ""
340
+
341
+ #: config_form.php
342
+ msgid "Port:"
343
+ msgstr ""
344
+
345
+ #: config_form.php
346
+ msgid "Mail Userid:"
347
+ msgstr ""
348
+
349
+ #: config_form.php
350
+ msgid "Mail Password:"
351
+ msgstr ""
352
+
353
+ #: config_form.php
354
+ msgid "Update Options"
355
+ msgstr ""
356
+
mimedecode.php ADDED
@@ -0,0 +1,831 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?Php
2
+ // +-----------------------------------------------------------------------+
3
+ // | Copyright (c) 2002-2003 Richard Heyes |
4
+ // | All rights reserved. |
5
+ // | |
6
+ // | Redistribution and use in source and binary forms, with or without |
7
+ // | modification, are permitted provided that the following conditions |
8
+ // | are met: |
9
+ // | |
10
+ // | o Redistributions of source code must retain the above copyright |
11
+ // | notice, this list of conditions and the following disclaimer. |
12
+ // | o Redistributions in binary form must reproduce the above copyright |
13
+ // | notice, this list of conditions and the following disclaimer in the |
14
+ // | documentation and/or other materials provided with the distribution.|
15
+ // | o The names of the authors may not be used to endorse or promote |
16
+ // | products derived from this software without specific prior written |
17
+ // | permission. |
18
+ // | |
19
+ // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
20
+ // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
21
+ // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
22
+ // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
23
+ // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
24
+ // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
25
+ // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
26
+ // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
27
+ // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
28
+ // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
29
+ // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
30
+ // | |
31
+ // +-----------------------------------------------------------------------+
32
+ // | Author: Richard Heyes <richard@phpguru.org> |
33
+ // +-----------------------------------------------------------------------+
34
+
35
+ if (!function_exists("_PEAR_call_destructors")) {
36
+ include_once (dirname(__FILE__). DIRECTORY_SEPARATOR . 'PEAR.php');
37
+ }
38
+ /**
39
+ * +----------------------------- IMPORTANT ------------------------------+
40
+ * | Usage of this class compared to native php extensions such as |
41
+ * | mailparse or imap, is slow and may be feature deficient. If available|
42
+ * | you are STRONGLY recommended to use the php extensions. |
43
+ * +----------------------------------------------------------------------+
44
+ *
45
+ * Mime Decoding class
46
+ *
47
+ * This class will parse a raw mime email and return
48
+ * the structure. Returned structure is similar to
49
+ * that returned by imap_fetchstructure().
50
+ *
51
+ * USAGE: (assume $input is your raw email)
52
+ *
53
+ * $decode = new Mail_mimeDecode($input, "\r\n");
54
+ * $structure = $decode->decode();
55
+ * print_r($structure);
56
+ *
57
+ * Or statically:
58
+ *
59
+ * $params['input'] = $input;
60
+ * $structure = Mail_mimeDecode::decode($params);
61
+ * print_r($structure);
62
+ *
63
+ * TODO:
64
+ * o Implement multipart/appledouble
65
+ * o UTF8: ???
66
+
67
+ > 4. We have also found a solution for decoding the UTF-8
68
+ > headers. Therefore I made the following function:
69
+ >
70
+ > function decode_utf8($txt) {
71
+ > $trans=array("�&#8216;"=>"õ","ű"=>"û","Ő"=>"�&#8226;","Ű"
72
+ =>"�&#8250;");
73
+ > $txt=strtr($txt,$trans);
74
+ > return(utf8_decode($txt));
75
+ > }
76
+ >
77
+ > And I have inserted the following line to the class:
78
+ >
79
+ > if (strtolower($charset)=="utf-8") $text=decode_utf8($text);
80
+ >
81
+ > ... before the following one in the "_decodeHeader" function:
82
+ >
83
+ > $input = str_replace($encoded, $text, $input);
84
+ >
85
+ > This way from now on it can easily decode the UTF-8 headers too.
86
+
87
+ *
88
+ * @author Richard Heyes <richard@phpguru.org>
89
+ * @version $Revision: 1.1 $
90
+ * @package Mail
91
+ */
92
+
93
+ class Mail_mimeDecode extends PEAR
94
+ {
95
+
96
+ /**
97
+ * The raw email to decode
98
+ * @var string
99
+ */
100
+ var $_input;
101
+
102
+ /**
103
+ * The header part of the input
104
+ * @var string
105
+ */
106
+ var $_header;
107
+
108
+ /**
109
+ * The body part of the input
110
+ * @var string
111
+ */
112
+ var $_body;
113
+
114
+ /**
115
+ * If an error occurs, this is used to store the message
116
+ * @var string
117
+ */
118
+ var $_error;
119
+
120
+ /**
121
+ * Flag to determine whether to include bodies in the
122
+ * returned object.
123
+ * @var boolean
124
+ */
125
+ var $_include_bodies;
126
+
127
+ /**
128
+ * Flag to determine whether to decode bodies
129
+ * @var boolean
130
+ */
131
+ var $_decode_bodies;
132
+
133
+ /**
134
+ * Flag to determine whether to decode headers
135
+ * @var boolean
136
+ */
137
+ var $_decode_headers;
138
+
139
+ /**
140
+ * If invoked from a class, $this will be set. This has problematic
141
+ * connotations for calling decode() statically. Hence this variable
142
+ * is used to determine if we are indeed being called statically or
143
+ * via an object.
144
+ */
145
+ var $mailMimeDecode;
146
+
147
+ /**
148
+ * Constructor.
149
+ *
150
+ * Sets up the object, initialise the variables, and splits and
151
+ * stores the header and body of the input.
152
+ *
153
+ * @param string The input to decode
154
+ * @access public
155
+ */
156
+ function Mail_mimeDecode($input)
157
+ {
158
+ list($header, $body) = $this->_splitBodyHeader($input);
159
+
160
+ $this->_input = $input;
161
+ $this->_header = $header;
162
+ $this->_body = $body;
163
+ $this->_decode_bodies = false;
164
+ $this->_include_bodies = true;
165
+
166
+ $this->mailMimeDecode = true;
167
+ }
168
+
169
+ /**
170
+ * Begins the decoding process. If called statically
171
+ * it will create an object and call the decode() method
172
+ * of it.
173
+ *
174
+ * @param array An array of various parameters that determine
175
+ * various things:
176
+ * include_bodies - Whether to include the body in the returned
177
+ * object.
178
+ * decode_bodies - Whether to decode the bodies
179
+ * of the parts. (Transfer encoding)
180
+ * decode_headers - Whether to decode headers
181
+ * input - If called statically, this will be treated
182
+ * as the input
183
+ * @return object Decoded results
184
+ * @access public
185
+ */
186
+ function decode($params = null)
187
+ {
188
+
189
+ // Have we been called statically? If so, create an object and pass details to that.
190
+ if (!is_object($this) AND isset($params['input'])) {
191
+ $obj = new Mail_mimeDecode($params['input']);
192
+ $structure = $obj->decode($params);
193
+
194
+ // Called statically but no input
195
+ // } elseif (!isset($this->mailMimeDecode)) {
196
+ //return PEAR::raiseError('Called statically and no input given');
197
+
198
+ // Called via an object
199
+ } else {
200
+ $this->_include_bodies = isset($params['include_bodies']) ? $params['include_bodies'] : false;
201
+ $this->_decode_bodies = isset($params['decode_bodies']) ? $params['decode_bodies'] : false;
202
+ $this->_decode_headers = isset($params['decode_headers']) ? $params['decode_headers'] : false;
203
+
204
+ $structure = $this->_decode($this->_header, $this->_body);
205
+ if ($structure === false) {
206
+ $structure = $this->raiseError($this->_error);
207
+ }
208
+ }
209
+ return $structure;
210
+ }
211
+
212
+ /**
213
+ * Performs the decoding. Decodes the body string passed to it
214
+ * If it finds certain content-types it will call itself in a
215
+ * recursive fashion
216
+ *
217
+ * @param string Header section
218
+ * @param string Body section
219
+ * @return object Results of decoding process
220
+ * @access private
221
+ */
222
+ function _decode($headers, $body, $default_ctype = 'text/plain')
223
+ {
224
+ $return = new stdClass;
225
+ $return->headers = array();
226
+ $headers = $this->_parseHeaders($headers);
227
+
228
+ foreach ($headers as $value) {
229
+ if (isset($return->headers[strtolower($value['name'])]) AND !is_array($return->headers[strtolower($value['name'])])) {
230
+ $return->headers[strtolower($value['name'])] = array($return->headers[strtolower($value['name'])]);
231
+ $return->headers[strtolower($value['name'])][] = $value['value'];
232
+
233
+ } elseif (isset($return->headers[strtolower($value['name'])])) {
234
+ $return->headers[strtolower($value['name'])][] = $value['value'];
235
+
236
+ } else {
237
+ $return->headers[strtolower($value['name'])] = $value['value'];
238
+ }
239
+ }
240
+
241
+ reset($headers);
242
+ while (list($key, $value) = each($headers)) {
243
+ $headers[$key]['name'] = strtolower($headers[$key]['name']);
244
+ switch ($headers[$key]['name']) {
245
+
246
+ case 'content-type':
247
+ $content_type = $this->_parseHeaderValue($headers[$key]['value']);
248
+
249
+ if (preg_match('/([0-9a-z+.-]+)\/([0-9a-z+.-]+)/i', $content_type['value'], $regs)) {
250
+ $return->ctype_primary = $regs[1];
251
+ $return->ctype_secondary = $regs[2];
252
+ }
253
+
254
+ if (isset($content_type['other'])) {
255
+ while (list($p_name, $p_value) = each($content_type['other'])) {
256
+ $return->ctype_parameters[$p_name] = $p_value;
257
+ }
258
+ }
259
+ break;
260
+
261
+ case 'content-disposition';
262
+ $content_disposition = $this->_parseHeaderValue($headers[$key]['value']);
263
+ $return->disposition = $content_disposition['value'];
264
+ if (isset($content_disposition['other'])) {
265
+ while (list($p_name, $p_value) = each($content_disposition['other'])) {
266
+ $return->d_parameters[$p_name] = $p_value;
267
+ }
268
+ }
269
+ break;
270
+
271
+ case 'content-transfer-encoding':
272
+ $content_transfer_encoding = $this->_parseHeaderValue($headers[$key]['value']);
273
+ break;
274
+ }
275
+ }
276
+
277
+ if (isset($content_type)) {
278
+ switch (strtolower($content_type['value'])) {
279
+ case 'text/plain':
280
+ $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
281
+ $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null;
282
+ break;
283
+
284
+ case 'text/html':
285
+ $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
286
+ $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null;
287
+ break;
288
+
289
+ case 'multipart/parallel':
290
+ case 'multipart/report': // RFC1892
291
+ case 'multipart/signed': // PGP
292
+ case 'multipart/digest':
293
+ case 'multipart/alternative':
294
+ case 'multipart/related':
295
+ case 'multipart/mixed':
296
+ if(!isset($content_type['other']['boundary'])){
297
+ $this->_error = 'No boundary found for ' . $content_type['value'] . ' part';
298
+ return false;
299
+ }
300
+
301
+ $default_ctype = (strtolower($content_type['value']) === 'multipart/digest') ? 'message/rfc822' : 'text/plain';
302
+
303
+ $parts = $this->_boundarySplit($body, $content_type['other']['boundary']);
304
+ for ($i = 0; $i < count($parts); $i++) {
305
+ list($part_header, $part_body) = $this->_splitBodyHeader($parts[$i]);
306
+ $part = $this->_decode($part_header, $part_body, $default_ctype);
307
+ if($part === false)
308
+ $part = $this->raiseError($this->_error);
309
+ $return->parts[] = $part;
310
+ }
311
+ break;
312
+
313
+ case 'message/rfc822':
314
+ $obj = &new Mail_mimeDecode($body);
315
+ $return->parts[] = $obj->decode(array('include_bodies' => $this->_include_bodies,
316
+ 'decode_bodies' => $this->_decode_bodies,
317
+ 'decode_headers' => $this->_decode_headers));
318
+ unset($obj);
319
+ break;
320
+
321
+ default:
322
+ if(!isset($content_transfer_encoding['value']))
323
+ $content_transfer_encoding['value'] = '7bit';
324
+ $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $content_transfer_encoding['value']) : $body) : null;
325
+ break;
326
+ }
327
+
328
+ } else {
329
+ $ctype = explode('/', $default_ctype);
330
+ $return->ctype_primary = $ctype[0];
331
+ $return->ctype_secondary = $ctype[1];
332
+ $this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body) : $body) : null;
333
+ }
334
+
335
+ return $return;
336
+ }
337
+
338
+ /**
339
+ * Given the output of the above function, this will return an
340
+ * array of references to the parts, indexed by mime number.
341
+ *
342
+ * @param object $structure The structure to go through
343
+ * @param string $mime_number Internal use only.
344
+ * @return array Mime numbers
345
+ */
346
+ function &getMimeNumbers(&$structure, $no_refs = false, $mime_number = '', $prepend = '')
347
+ {
348
+ $return = array();
349
+ if (!empty($structure->parts)) {
350
+ if ($mime_number != '') {
351
+ $structure->mime_id = $prepend . $mime_number;
352
+ $return[$prepend . $mime_number] = &$structure;
353
+ }
354
+ for ($i = 0; $i < count($structure->parts); $i++) {
355
+
356
+
357
+ if (!empty($structure->headers['content-type']) AND substr(strtolower($structure->headers['content-type']), 0, 8) == 'message/') {
358
+ $prepend = $prepend . $mime_number . '.';
359
+ $_mime_number = '';
360
+ } else {
361
+ $_mime_number = ($mime_number == '' ? $i + 1 : sprintf('%s.%s', $mime_number, $i + 1));
362
+ }
363
+
364
+ $arr = &Mail_mimeDecode::getMimeNumbers($structure->parts[$i], $no_refs, $_mime_number, $prepend);
365
+ foreach ($arr as $key => $val) {
366
+ $no_refs ? $return[$key] = '' : $return[$key] = &$arr[$key];
367
+ }
368
+ }
369
+ } else {
370
+ if ($mime_number == '') {
371
+ $mime_number = '1';
372
+ }
373
+ $structure->mime_id = $prepend . $mime_number;
374
+ $no_refs ? $return[$prepend . $mime_number] = '' : $return[$prepend . $mime_number] = &$structure;
375
+ }
376
+
377
+ return $return;
378
+ }
379
+
380
+ /**
381
+ * Given a string containing a header and body
382
+ * section, this function will split them (at the first
383
+ * blank line) and return them.
384
+ *
385
+ * @param string Input to split apart
386
+ * @return array Contains header and body section
387
+ * @access private
388
+ */
389
+ function _splitBodyHeader($input)
390
+ {
391
+ if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) {
392
+ return array($match[1], $match[2]);
393
+ }
394
+ $this->_error = 'Could not split header and body';
395
+ return false;
396
+ }
397
+
398
+ /**
399
+ * Parse headers given in $input and return
400
+ * as assoc array.
401
+ *
402
+ * @param string Headers to parse
403
+ * @return array Contains parsed headers
404
+ * @access private
405
+ */
406
+ function _parseHeaders($input)
407
+ {
408
+
409
+ if ($input !== '') {
410
+ // Unfold the input
411
+ $input = preg_replace("/\r?\n/", "\r\n", $input);
412
+ $input = preg_replace("/\r\n(\t| )+/", ' ', $input);
413
+ $headers = explode("\r\n", trim($input));
414
+
415
+ foreach ($headers as $value) {
416
+ $hdr_name = substr($value, 0, $pos = strpos($value, ':'));
417
+ $hdr_value = substr($value, $pos+1);
418
+ if($hdr_value[0] == ' ')
419
+ $hdr_value = substr($hdr_value, 1);
420
+
421
+ $return[] = array(
422
+ 'name' => $hdr_name,
423
+ 'value' => $this->_decode_headers ? $this->_decodeHeader($hdr_value) : $hdr_value
424
+ );
425
+ }
426
+ } else {
427
+ $return = array();
428
+ }
429
+
430
+ return $return;
431
+ }
432
+
433
+ /**
434
+ * Function to parse a header value,
435
+ * extract first part, and any secondary
436
+ * parts (after ;) This function is not as
437
+ * robust as it could be. Eg. header comments
438
+ * in the wrong place will probably break it.
439
+ *
440
+ * @param string Header value to parse
441
+ * @return array Contains parsed result
442
+ * @access private
443
+ */
444
+ function _parseHeaderValue($input)
445
+ {
446
+
447
+ if (($pos = strpos($input, ';')) !== false) {
448
+
449
+ $return['value'] = trim(substr($input, 0, $pos));
450
+ $input = trim(substr($input, $pos+1));
451
+
452
+ if (strlen($input) > 0) {
453
+
454
+ // This splits on a semi-colon, if there's no preceeding backslash
455
+ // Can't handle if it's in double quotes however. (Of course anyone
456
+ // sending that needs a good slap).
457
+ $parameters = preg_split('/\s*(?<!\\\\);\s*/i', $input);
458
+
459
+ for ($i = 0; $i < count($parameters); $i++) {
460
+ $param_name = substr($parameters[$i], 0, $pos = strpos($parameters[$i], '='));
461
+ $param_value = substr($parameters[$i], $pos + 1);
462
+ if ($param_value[0] == '"') {
463
+ $param_value = substr($param_value, 1, -1);
464
+ }
465
+ $return['other'][$param_name] = $param_value;
466
+ $return['other'][strtolower($param_name)] = $param_value;
467
+ }
468
+ }
469
+ } else {
470
+ $return['value'] = trim($input);
471
+ }
472
+
473
+ return $return;
474
+ }
475
+
476
+ /**
477
+ * This function splits the input based
478
+ * on the given boundary
479
+ *
480
+ * @param string Input to parse
481
+ * @return array Contains array of resulting mime parts
482
+ * @access private
483
+ */
484
+ function _boundarySplit($input, $boundary)
485
+ {
486
+ $parts = array();
487
+
488
+ $bs_possible = substr($boundary, 2, -2);
489
+ $bs_check = '\"' . $bs_possible . '\"';
490
+
491
+ if ($boundary == $bs_check) {
492
+ $boundary = $bs_possible;
493
+ }
494
+
495
+ $tmp = explode('--' . $boundary, $input);
496
+
497
+ for ($i = 1; $i < count($tmp) - 1; $i++) {
498
+ $parts[] = $tmp[$i];
499
+ }
500
+
501
+ return $parts;
502
+ }
503
+
504
+ /**
505
+ * Given a header, this function will decode it
506
+ * according to RFC2047. Probably not *exactly*
507
+ * conformant, but it does pass all the given
508
+ * examples (in RFC2047).
509
+ *
510
+ * @param string Input header value to decode
511
+ * @return string Decoded header value
512
+ * @access private
513
+ */
514
+ function _decodeHeader($input)
515
+ {
516
+ // Remove white space between encoded-words
517
+ $input = preg_replace('/(=\?[^?]+\?(q|b)\?[^?]*\?=)(\s)+=\?/i', '\1=?', $input);
518
+
519
+ // For each encoded-word...
520
+ while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i', $input, $matches)) {
521
+
522
+ $encoded = $matches[1];
523
+ $charset = $matches[2];
524
+ $encoding = $matches[3];
525
+ $text = $matches[4];
526
+
527
+ switch (strtolower($encoding)) {
528
+ case 'b':
529
+ $text = base64_decode($text);
530
+ break;
531
+
532
+ case 'q':
533
+ $text = str_replace('_', ' ', $text);
534
+ preg_match_all('/=([a-f0-9]{2})/i', $text, $matches);
535
+ foreach($matches[1] as $value)
536
+ $text = str_replace('='.$value, chr(hexdec($value)), $text);
537
+ break;
538
+ }
539
+
540
+ $input = str_replace($encoded, $text, $input);
541
+ }
542
+
543
+ return $input;
544
+ }
545
+
546
+ /**
547
+ * Given a body string and an encoding type,
548
+ * this function will decode and return it.
549
+ *
550
+ * @param string Input body to decode
551
+ * @param string Encoding type to use.
552
+ * @return string Decoded body
553
+ * @access private
554
+ */
555
+ function _decodeBody($input, $encoding = '7bit')
556
+ {
557
+ switch (strtolower($encoding)) {
558
+ case '7bit':
559
+ return $input;
560
+ break;
561
+
562
+ case 'quoted-printable':
563
+ return $this->_quotedPrintableDecode($input);
564
+ break;
565
+
566
+ case 'base64':
567
+ return base64_decode($input);
568
+ break;
569
+
570
+ default:
571
+ return $input;
572
+ }
573
+ }
574
+
575
+ /**
576
+ * Given a quoted-printable string, this
577
+ * function will decode and return it.
578
+ *
579
+ * @param string Input body to decode
580
+ * @return string Decoded body
581
+ * @access private
582
+ */
583
+ function _quotedPrintableDecode($input)
584
+ {
585
+ // Remove soft line breaks
586
+ $input = preg_replace("/=\r?\n/", '', $input);
587
+
588
+ // Replace encoded characters
589
+ $input = preg_replace('/=([a-f0-9]{2})/ie', "chr(hexdec('\\1'))", $input);
590
+
591
+ return $input;
592
+ }
593
+
594
+ /**
595
+ * Checks the input for uuencoded files and returns
596
+ * an array of them. Can be called statically, eg:
597
+ *
598
+ * $files =& Mail_mimeDecode::uudecode($some_text);
599
+ *
600
+ * It will check for the begin 666 ... end syntax
601
+ * however and won't just blindly decode whatever you
602
+ * pass it.
603
+ *
604
+ * @param string Input body to look for attahcments in
605
+ * @return array Decoded bodies, filenames and permissions
606
+ * @access public
607
+ * @author Unknown
608
+ */
609
+ function &uudecode($input)
610
+ {
611
+ // Find all uuencoded sections
612
+ preg_match_all("/begin ([0-7]{3}) (.+)\r?\n(.+)\r?\nend/Us", $input, $matches);
613
+
614
+ for ($j = 0; $j < count($matches[3]); $j++) {
615
+
616
+ $str = $matches[3][$j];
617
+ $filename = $matches[2][$j];
618
+ $fileperm = $matches[1][$j];
619
+
620
+ $file = '';
621
+ $str = preg_split("/\r?\n/", trim($str));
622
+ $strlen = count($str);
623
+
624
+ for ($i = 0; $i < $strlen; $i++) {
625
+ $pos = 1;
626
+ $d = 0;
627
+ $len=(int)(((ord(substr($str[$i],0,1)) -32) - ' ') & 077);
628
+
629
+ while (($d + 3 <= $len) AND ($pos + 4 <= strlen($str[$i]))) {
630
+ $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
631
+ $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
632
+ $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20);
633
+ $c3 = (ord(substr($str[$i],$pos+3,1)) ^ 0x20);
634
+ $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
635
+
636
+ $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2));
637
+
638
+ $file .= chr(((($c2 - ' ') & 077) << 6) | (($c3 - ' ') & 077));
639
+
640
+ $pos += 4;
641
+ $d += 3;
642
+ }
643
+
644
+ if (($d + 2 <= $len) && ($pos + 3 <= strlen($str[$i]))) {
645
+ $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
646
+ $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
647
+ $c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20);
648
+ $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
649
+
650
+ $file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2));
651
+
652
+ $pos += 3;
653
+ $d += 2;
654
+ }
655
+
656
+ if (($d + 1 <= $len) && ($pos + 2 <= strlen($str[$i]))) {
657
+ $c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
658
+ $c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
659
+ $file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
660
+
661
+ }
662
+ }
663
+ $files[] = array('filename' => $filename, 'fileperm' => $fileperm, 'filedata' => $file);
664
+ }
665
+
666
+ return $files;
667
+ }
668
+
669
+ /**
670
+ * getSendArray() returns the arguments required for Mail::send()
671
+ * used to build the arguments for a mail::send() call
672
+ *
673
+ * Usage:
674
+ * $mailtext = Full email (for example generated by a template)
675
+ * $decoder = new Mail_mimeDecode($mailtext);
676
+ * $parts = $decoder->getSendArray();
677
+ * if (!PEAR::isError($parts) {
678
+ * list($recipents,$headers,$body) = $parts;
679
+ * $mail = Mail::factory('smtp');
680
+ * $mail->send($recipents,$headers,$body);
681
+ * } else {
682
+ * echo $parts->message;
683
+ * }
684
+ * @return mixed array of recipeint, headers,body or Pear_Error
685
+ * @access public
686
+ * @author Alan Knowles <alan@akbkhome.com>
687
+ */
688
+ function getSendArray()
689
+ {
690
+ // prevent warning if this is not set
691
+ $this->_decode_headers = FALSE;
692
+ $headerlist =$this->_parseHeaders($this->_header);
693
+ $to = "";
694
+ if (!$headerlist) {
695
+ return $this->raiseError("Message did not contain headers");
696
+ }
697
+ foreach($headerlist as $item) {
698
+ $header[$item['name']] = $item['value'];
699
+ switch (strtolower($item['name'])) {
700
+ case "to":
701
+ case "cc":
702
+ case "bcc":
703
+ $to = ",".$item['value'];
704
+ default:
705
+ break;
706
+ }
707
+ }
708
+ if ($to == "") {
709
+ return $this->raiseError("Message did not contain any recipents");
710
+ }
711
+ $to = substr($to,1);
712
+ return array($to,$header,$this->_body);
713
+ }
714
+
715
+ /**
716
+ * Returns a xml copy of the output of
717
+ * Mail_mimeDecode::decode. Pass the output in as the
718
+ * argument. This function can be called statically. Eg:
719
+ *
720
+ * $output = $obj->decode();
721
+ * $xml = Mail_mimeDecode::getXML($output);
722
+ *
723
+ * The DTD used for this should have been in the package. Or
724
+ * alternatively you can get it from cvs, or here:
725
+ * http://www.phpguru.org/xmail/xmail.dtd.
726
+ *
727
+ * @param object Input to convert to xml. This should be the
728
+ * output of the Mail_mimeDecode::decode function
729
+ * @return string XML version of input
730
+ * @access public
731
+ */
732
+ function getXML($input)
733
+ {
734
+ $crlf = "\r\n";
735
+ $output = '<?xml version=\'1.0\'?>' . $crlf .
736
+ '<!DOCTYPE email SYSTEM "http://www.phpguru.org/xmail/xmail.dtd">' . $crlf .
737
+ '<email>' . $crlf .
738
+ Mail_mimeDecode::_getXML($input) .
739
+ '</email>';
740
+
741
+ return $output;
742
+ }
743
+
744
+ /**
745
+ * Function that does the actual conversion to xml. Does a single
746
+ * mimepart at a time.
747
+ *
748
+ * @param object Input to convert to xml. This is a mimepart object.
749
+ * It may or may not contain subparts.
750
+ * @param integer Number of tabs to indent
751
+ * @return string XML version of input
752
+ * @access private
753
+ */
754
+ function _getXML($input, $indent = 1)
755
+ {
756
+ $htab = "\t";
757
+ $crlf = "\r\n";
758
+ $output = '';
759
+ $headers = @(array)$input->headers;
760
+
761
+ foreach ($headers as $hdr_name => $hdr_value) {
762
+
763
+ // Multiple headers with this name
764
+ if (is_array($headers[$hdr_name])) {
765
+ for ($i = 0; $i < count($hdr_value); $i++) {
766
+ $output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value[$i], $indent);
767
+ }
768
+
769
+ // Only one header of this sort
770
+ } else {
771
+ $output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value, $indent);
772
+ }
773
+ }
774
+
775
+ if (!empty($input->parts)) {
776
+ for ($i = 0; $i < count($input->parts); $i++) {
777
+ $output .= $crlf . str_repeat($htab, $indent) . '<mimepart>' . $crlf .
778
+ Mail_mimeDecode::_getXML($input->parts[$i], $indent+1) .
779
+ str_repeat($htab, $indent) . '</mimepart>' . $crlf;
780
+ }
781
+ } elseif (isset($input->body)) {
782
+ $output .= $crlf . str_repeat($htab, $indent) . '<body><![CDATA[' .
783
+ $input->body . ']]></body>' . $crlf;
784
+ }
785
+
786
+ return $output;
787
+ }
788
+
789
+ /**
790
+ * Helper function to _getXML(). Returns xml of a header.
791
+ *
792
+ * @param string Name of header
793
+ * @param string Value of header
794
+ * @param integer Number of tabs to indent
795
+ * @return string XML version of input
796
+ * @access private
797
+ */
798
+ function _getXML_helper($hdr_name, $hdr_value, $indent)
799
+ {
800
+ $htab = "\t";
801
+ $crlf = "\r\n";
802
+ $return = '';
803
+
804
+ $new_hdr_value = ($hdr_name != 'received') ? Mail_mimeDecode::_parseHeaderValue($hdr_value) : array('value' => $hdr_value);
805
+ $new_hdr_name = str_replace(' ', '-', ucwords(str_replace('-', ' ', $hdr_name)));
806
+
807
+ // Sort out any parameters
808
+ if (!empty($new_hdr_value['other'])) {
809
+ foreach ($new_hdr_value['other'] as $paramname => $paramvalue) {
810
+ $params[] = str_repeat($htab, $indent) . $htab . '<parameter>' . $crlf .
811
+ str_repeat($htab, $indent) . $htab . $htab . '<paramname>' . htmlspecialchars($paramname) . '</paramname>' . $crlf .
812
+ str_repeat($htab, $indent) . $htab . $htab . '<paramvalue>' . htmlspecialchars($paramvalue) . '</paramvalue>' . $crlf .
813
+ str_repeat($htab, $indent) . $htab . '</parameter>' . $crlf;
814
+ }
815
+
816
+ $params = implode('', $params);
817
+ } else {
818
+ $params = '';
819
+ }
820
+
821
+ $return = str_repeat($htab, $indent) . '<header>' . $crlf .
822
+ str_repeat($htab, $indent) . $htab . '<headername>' . htmlspecialchars($new_hdr_name) . '</headername>' . $crlf .
823
+ str_repeat($htab, $indent) . $htab . '<headervalue>' . htmlspecialchars($new_hdr_value['value']) . '</headervalue>' . $crlf .
824
+ $params .
825
+ str_repeat($htab, $indent) . '</header>' . $crlf;
826
+
827
+ return $return;
828
+ }
829
+
830
+ } // End of class
831
+ ?>
package.xml ADDED
@@ -0,0 +1,426 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <package packagerversion="1.6.0" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
3
+ <name>Mail_Mime</name>
4
+ <channel>pear.php.net</channel>
5
+ <summary>Mail_Mime provides classes to create mime messages.</summary>
6
+ <description>Mail_Mime provides classes to deal with the creation and manipulation of mime messages.
7
+ It allows people to create Email messages consisting of:
8
+ * Text Parts
9
+ * HTML Parts
10
+ * Inline HTML Images
11
+ * Attachments
12
+ * Attached messages
13
+
14
+ Starting with version 1.4.0, it also allows non US-ASCII chars in filenames, subjects, recipients, etc, etc.</description>
15
+ <lead>
16
+ <name>Cipriano Groenendal</name>
17
+ <user>cipri</user>
18
+ <email>cipri@php.net</email>
19
+ <active>yes</active>
20
+ </lead>
21
+ <date>2007-06-21</date>
22
+ <time>21:10:11</time>
23
+ <version>
24
+ <release>1.5.2</release>
25
+ <api>1.3.1</api>
26
+ </version>
27
+ <stability>
28
+ <release>stable</release>
29
+ <api>stable</api>
30
+ </stability>
31
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license>
32
+ <notes>* Fix Bug #11381: domain name is attached to content-id, trailing greater-than sign is
33
+ not remove [cipri]</notes>
34
+ <contents>
35
+ <dir name="/">
36
+ <file baseinstalldir="Mail" md5sum="a2899bc69329c9533205aeb4221ab775" name="scripts/phail.php" role="doc" />
37
+ <file baseinstalldir="Mail" md5sum="edd138f6c5497ae2b5d63620a67a931e" name="tests/class-filename.phpt" role="test" />
38
+ <file baseinstalldir="Mail" md5sum="494526cc12e4edec45e0207f569d57d9" name="tests/encoding_case.phpt" role="test" />
39
+ <file baseinstalldir="Mail" md5sum="1016a2a921d414f52fbc6d3a028945f4" name="tests/sleep_wakeup_EOL-bug3488-part1.phpt" role="test" />
40
+ <file baseinstalldir="Mail" md5sum="61c745f92e8162e6e2971464a15990d4" name="tests/sleep_wakeup_EOL-bug3488-part2.phpt" role="test" />
41
+ <file baseinstalldir="Mail" md5sum="494526cc12e4edec45e0207f569d57d9" name="tests/tabs_quoted_printable.phpt" role="test" />
42
+ <file baseinstalldir="Mail" md5sum="844305aaa9ca4820a1672ba6da0a94c7" name="tests/test_Bug_30_1.phpt" role="test" />
43
+ <file baseinstalldir="Mail" md5sum="2d0bd00382e3f9c5f2e3e9512b731d68" name="tests/test_Bug_30_2.phpt" role="test" />
44
+ <file baseinstalldir="Mail" md5sum="83d326b6ca7d9f704ff2544edeb601ab" name="tests/test_Bug_30_3.phpt" role="test" />
45
+ <file baseinstalldir="Mail" md5sum="c2ea41bc1d78cb2b88e4514d8044a98d" name="tests/test_Bug_30_4.phpt" role="test" />
46
+ <file baseinstalldir="Mail" md5sum="6af58588ed4e35df8845f6704d7384ba" name="tests/test_Bug_3513_1.phpt" role="test" />
47
+ <file baseinstalldir="Mail" md5sum="efaa5d82baea0b46560752817d455bf4" name="tests/test_Bug_3513_2.phpt" role="test" />
48
+ <file baseinstalldir="Mail" md5sum="27020435d9432ebece744308e803030f" name="tests/test_Bug_3513_3.phpt" role="test" />
49
+ <file baseinstalldir="Mail" md5sum="dc2b1be6fab962386f16f6d710cf2d0a" name="tests/test_Bug_7561_1.phpt" role="test" />
50
+ <file baseinstalldir="Mail" md5sum="cd9c56b628649f92f067920d2e8a6214" name="tests/test_Bug_8223_1.phpt" role="test" />
51
+ <file baseinstalldir="Mail" md5sum="51888d86ce4fb58fc89a366736f5910a" name="tests/test_Bug_8386_1.phpt" role="test" />
52
+ <file baseinstalldir="Mail" md5sum="440c46d4ea863539caec007af431b307" name="tests/test_Bug_8541_1.phpt" role="test" />
53
+ <file baseinstalldir="Mail" md5sum="a1f598cf82774fde322ac4f3f3a7e0be" name="tests/test_Bug_9558_1.phpt" role="test" />
54
+ <file baseinstalldir="Mail" md5sum="5adfb0668904b72d2c04073f55f8144c" name="tests/test_Bug_9722_1.phpt" role="test" />
55
+ <file baseinstalldir="Mail" md5sum="18160c212dd0042bf21eb703e58de9ce" name="tests/test_Bug_9725_1.phpt" role="test" />
56
+ <file baseinstalldir="Mail" md5sum="e07949f077db4cfeaad0bffe9d4d37da" name="tests/test_Bug_9976_1.phpt" role="test" />
57
+ <file baseinstalldir="Mail" md5sum="fcc6eeedeb8ae7ddcf1637c048ab7f93" name="tests/test_Bug_10298_1.phpt" role="test" />
58
+ <file baseinstalldir="Mail" md5sum="c64c1115b7fe7f3a8d8c6fd8f8d7c268" name="tests/test_Bug_10596_1.phpt" role="test" />
59
+ <file baseinstalldir="Mail" md5sum="0eacb8c485ade073b61fe2daeae3124f" name="tests/test_Bug_10816_1.phpt" role="test" />
60
+ <file baseinstalldir="Mail" md5sum="93a00275edb0d9e94364ae11175741d1" name="mime.php" role="php" />
61
+ <file baseinstalldir="Mail" md5sum="53aedbcc104a9bd15cf96e5511b6498b" name="mimePart.php" role="php" />
62
+ <file baseinstalldir="Mail" md5sum="194810c478066eaeb28f51116b88e25a" name="xmail.dtd" role="data" />
63
+ <file baseinstalldir="Mail" md5sum="61cea06fb6b4bd3a4b5e2d37384e14a9" name="xmail.xsl" role="data" />
64
+ </dir>
65
+ </contents>
66
+ <dependencies>
67
+ <required>
68
+ <php>
69
+ <min>4.0.0</min>
70
+ </php>
71
+ <pearinstaller>
72
+ <min>1.6.0</min>
73
+ </pearinstaller>
74
+ <subpackage>
75
+ <name>Mail_mimeDecode</name>
76
+ <channel>pear.php.net</channel>
77
+ </subpackage>
78
+ </required>
79
+ </dependencies>
80
+ <phprelease />
81
+ <changelog>
82
+ <release>
83
+ <version>
84
+ <release>1.0</release>
85
+ <api>1.0</api>
86
+ </version>
87
+ <stability>
88
+ <release>stable</release>
89
+ <api>stable</api>
90
+ </stability>
91
+ <date>2001-12-28</date>
92
+ <license uri="http://www.php.net/license">PHP</license>
93
+ <notes>This is the initial release of the Mime_Mail package.</notes>
94
+ </release>
95
+ <release>
96
+ <version>
97
+ <release>1.1</release>
98
+ <api>1.1</api>
99
+ </version>
100
+ <stability>
101
+ <release>stable</release>
102
+ <api>stable</api>
103
+ </stability>
104
+ <date>2002-04-03</date>
105
+ <license uri="http://www.php.net/license">PHP</license>
106
+ <notes>This is a maintenance release with various bugfixes and minor enhancements.</notes>
107
+ </release>
108
+ <release>
109
+ <version>
110
+ <release>1.2</release>
111
+ <api>1.2</api>
112
+ </version>
113
+ <stability>
114
+ <release>stable</release>
115
+ <api>stable</api>
116
+ </stability>
117
+ <date>2002-07-14</date>
118
+ <license uri="http://www.php.net/license">PHP</license>
119
+ <notes>o Added header encoding
120
+ o Altered mimePart to put boundary parameter on newline
121
+ o Changed addFrom() to setFrom()
122
+ o Added setSubject()
123
+ o Made mimePart inherit crlf setting from mime</notes>
124
+ </release>
125
+ <release>
126
+ <version>
127
+ <release>1.2.1</release>
128
+ <api>1.2.1</api>
129
+ </version>
130
+ <stability>
131
+ <release>stable</release>
132
+ <api>stable</api>
133
+ </stability>
134
+ <date>2002-07-27</date>
135
+ <license uri="http://www.php.net/license">PHP</license>
136
+ <notes>o License change
137
+ o Applied a few changes From Ilia Alshanetsky</notes>
138
+ </release>
139
+ <release>
140
+ <version>
141
+ <release>1.3.0RC1</release>
142
+ <api>1.3.0RC1</api>
143
+ </version>
144
+ <stability>
145
+ <release>beta</release>
146
+ <api>beta</api>
147
+ </stability>
148
+ <date>2005-03-20</date>
149
+ <license uri="http://www.php.net/license">PHP</license>
150
+ <notes>o First release in over 2.5 years (!)
151
+ o MANY bugfixes (see the bugtracker)
152
+ o added a few tests</notes>
153
+ </release>
154
+ <release>
155
+ <version>
156
+ <release>1.3.0</release>
157
+ <api>1.3.0</api>
158
+ </version>
159
+ <stability>
160
+ <release>stable</release>
161
+ <api>stable</api>
162
+ </stability>
163
+ <date>2005-04-01</date>
164
+ <license uri="http://www.php.net/license">PHP</license>
165
+ <notes>o First (stable) release in over 2.5 years (!)
166
+ o MANY bugfixes (see the bugtracker)
167
+ o added a few tests
168
+ o one small fix after RC1 (bug #3940)</notes>
169
+ </release>
170
+ <release>
171
+ <version>
172
+ <release>1.3.1</release>
173
+ <api>1.3.1</api>
174
+ </version>
175
+ <stability>
176
+ <release>stable</release>
177
+ <api>stable</api>
178
+ </stability>
179
+ <date>2005-07-13</date>
180
+ <license uri="http://www.php.net/license">PHP</license>
181
+ <notes>A bugfix release:</notes>
182
+ </release>
183
+ <release>
184
+ <version>
185
+ <release>1.4.0a1</release>
186
+ <api>1.3.1</api>
187
+ </version>
188
+ <stability>
189
+ <release>alpha</release>
190
+ <api>stable</api>
191
+ </stability>
192
+ <date>2007-03-08</date>
193
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">bsd style</license>
194
+ <notes>* Changed License to BSD Style license, as that&apos;s what the code was since the beginning [cipri]
195
+ * Fix Bug #30: Mail_Mime: _encodeHeaders is not RFC-2047 compliant. [cipri]
196
+ * Fix Bug #3513: support of RFC2231 in header fields. [cipri]
197
+ * Fix Bug #4696: addAttachment crash [cipri]
198
+ * Fix Bug #5333: Only variables should be returned by reference; triggers notices since php 4.4.0 [cipri]
199
+ * Fix Bug #7561: Mail_mimePart::_quotedPrintableEncode() misbehavior with mbstring overload [cipri]
200
+ * Fix Bug #8223: Incorrectly encoded quoted-printable headers [cipri]
201
+ * Fix Bug #8386: HTML body not correctly encoded if attachments present [cipri]
202
+ * Fix Bug #8541: mimePart.php line delimiter is \r [cipri]
203
+ * Fix Bug #9347: Notices about references [cweiske]
204
+ * Fix Bug #9558: Broken multiline headers [cipri]
205
+ * Fix Bug #9956: Notices being thrown [cipri]
206
+ * Fix Bug #9976: Subject encoded twice [cipri]
207
+ * Implement Feature #2952: Mail_mime::headers() saves extra headers [cipri]
208
+ * Implement Feature #3636: Allow specification of charsets and encoding [cipri]
209
+ * Implement Feature #4057: Mail_Mime: Add name parameter for Content-Type [cipri]
210
+ * Implement Feature #4504: addHTMLImage does not work in cases when filename contains a path [cipri]
211
+ * Implement Feature #5837: Mail_Mime: Build message for Net_SMTP [cipri]
212
+ * Implement Feature #5934: Mail_Mime: choice for content disposition [cipri]
213
+ * Implement Feature #6568: Mail_Mime: inline images referenced in CSS definitions not replaced. [cipri]</notes>
214
+ </release>
215
+ <release>
216
+ <version>
217
+ <release>1.4.0a2</release>
218
+ <api>1.3.1</api>
219
+ </version>
220
+ <stability>
221
+ <release>alpha</release>
222
+ <api>stable</api>
223
+ </stability>
224
+ <date>2007-04-05</date>
225
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">bsd style</license>
226
+ <notes>* Fix Bug #9722: _quotedPrintableEncode does not encode dot at start of line on Windows
227
+ platform [cipri]
228
+ * Fix Bug #9725: multipart/related &amp; alternative wrong order [cipri]
229
+ * Fix Bug #10146: mbstring fails to recognize encodings. [cipri]
230
+ * Fix Bug #10158: Inline images not displayed on Mozilla Thunderbird [cipri]
231
+ * Fix Bug #10298: Mail_mime, double Quotes and Specialchars in from and to Adress [cipri]
232
+ * Fix Bug #10306: Strings with Double Quotes get encoded wrongly [cipri]
233
+ * Fix Bug #10596: Incorrect handling of text and html &apos;0&apos; bodies [cipri]</notes>
234
+ </release>
235
+ <release>
236
+ <version>
237
+ <release>1.4.0a3</release>
238
+ <api>1.3.1</api>
239
+ </version>
240
+ <stability>
241
+ <release>alpha</release>
242
+ <api>stable</api>
243
+ </stability>
244
+ <date>2007-04-05</date>
245
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">bsd style</license>
246
+ <notes>* Fix Bug #10298: Mail_mime, double Quotes and Specialchars in from and to Adress [cipri]
247
+ * Fix Bug #10306: Strings with Double Quotes get encoded wrongly [cipri]</notes>
248
+ </release>
249
+ <release>
250
+ <version>
251
+ <release>1.4.0RC1</release>
252
+ <api>1.3.1</api>
253
+ </version>
254
+ <stability>
255
+ <release>beta</release>
256
+ <api>stable</api>
257
+ </stability>
258
+ <date>2007-04-12</date>
259
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">bsd style</license>
260
+ <notes>* Fix Bug #10232: Gmail creates double line break when \r\n is used [cipri]</notes>
261
+ </release>
262
+ <release>
263
+ <version>
264
+ <release>1.4.0RC2</release>
265
+ <api>1.3.1</api>
266
+ </version>
267
+ <stability>
268
+ <release>beta</release>
269
+ <api>stable</api>
270
+ </stability>
271
+ <date>2007-04-22</date>
272
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">bsd style</license>
273
+ <notes>* Fix Bug #10791: Unit tests fail [cipri]
274
+ * Fix Bug #10792: No unit tests for recently fixed bugs [cipri]
275
+ * Fix Bug #10793: Long headers don&apos;t get wrapped since fix for Bug #10298 [cipri]</notes>
276
+ </release>
277
+ <release>
278
+ <version>
279
+ <release>1.4.0RC3</release>
280
+ <api>1.3.1</api>
281
+ </version>
282
+ <stability>
283
+ <release>beta</release>
284
+ <api>stable</api>
285
+ </stability>
286
+ <date>2007-04-24</date>
287
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">bsd style</license>
288
+ <notes>* Fix Bug #10816: Unwanted linebreak at the end of output [cipri]</notes>
289
+ </release>
290
+ <release>
291
+ <version>
292
+ <release>1.4.0RC4</release>
293
+ <api>1.3.1</api>
294
+ </version>
295
+ <stability>
296
+ <release>beta</release>
297
+ <api>stable</api>
298
+ </stability>
299
+ <date>2007-04-28</date>
300
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">bsd style</license>
301
+ <notes>* Fix Bug #3513: support of RFC2231 in header fields. [cipri]
302
+ * Fix Bug #10838: bad use of MIME encoding in header. [cipri]</notes>
303
+ </release>
304
+ <release>
305
+ <version>
306
+ <release>1.4.0</release>
307
+ <api>1.3.1</api>
308
+ </version>
309
+ <stability>
310
+ <release>stable</release>
311
+ <api>stable</api>
312
+ </stability>
313
+ <date>2007-05-05</date>
314
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license>
315
+ <notes>Release nots:
316
+ * No more notices in PHP 5 /4.4.0.
317
+ * Improved inline HTML image function.
318
+ * Improved header encoding with foreign charsets.
319
+ * Improved long header rendering.
320
+ * More control over used Charsets and encoding schemes.
321
+ * More configurable attachments and inline images.
322
+ * Full RFC 2047 Support
323
+ * Full RFC 2231 Support
324
+ * Unit-tests
325
+
326
+ Fixed bugs:
327
+ * Fix Bug #30: Mail_Mime: _encodeHeaders is not RFC-2047 compliant. [cipri]
328
+ * Fix Bug #3513: support of RFC2231 in header fields. [cipri]
329
+ * Fix Bug #4696: addAttachment crash [cipri]
330
+ * Fix Bug #5333: Only variables should be returned by reference; triggers notices since
331
+ php 4.4.0 [cipri]
332
+ * Fix Bug #5400: Do not return function reference [cipri]
333
+ * Fix Bug #5710: Little reference bugs [cipri]
334
+ * Fix Bug #5890: Only variable references should be returned by reference [cipri]
335
+ * Fix Bug #6260: Just a notice with PHP5 [cipri]
336
+ * Fix Bug #6261: php 5.1.1 upgrade [cipri]
337
+ * Fix Bug #6663: Notice about reference passing [cipri]
338
+ * Fix Bug #7561: Mail_mimePart::_quotedPrintableEncode() misbehavior with mbstring
339
+ overload [cipri]
340
+ * Fix Bug #7713: PHP5 Notice: Only variable references should be returned by reference [cipri]
341
+ * Fix Bug #8223: Incorrectly encoded quoted-printable headers [cipri]
342
+ * Fix Bug #8386: HTML body not correctly encoded if attachments present [cipri]
343
+ * Fix Bug #8541: mimePart.php line delimiter is \r [cipri]
344
+ * Fix Bug #8812: user header updates overwritten [cipri]
345
+ * Fix Bug #9347: Notices about references [cweiske]
346
+ * Fix Bug #9558: Broken multiline headers [cipri]
347
+ * Fix Bug #9722: _quotedPrintableEncode does not encode dot at start of line on Windows
348
+ platform [cipri]
349
+ * Fix Bug #9725: multipart/related &amp; alternative wrong order [cipri]
350
+ * Fix Bug #9956: Notices being thrown [cipri]
351
+ * Fix Bug #9976: Subject encoded twice [cipri]
352
+ * Fix Bug #10146: mbstring fails to recognize encodings. [cipri]
353
+ * Fix Bug #10158: Inline images not displayed on Mozilla Thunderbird [cipri]
354
+ * Fix Bug #10232: Gmail creates double line break when \r\n is used [cipri]
355
+ * Fix Bug #10298: Mail_mime, double Quotes and Specialchars in from and to Adress [cipri]
356
+ * Fix Bug #10306: Strings with Double Quotes get encoded wrongly [cipri]
357
+ * Fix Bug #10596: Incorrect handling of text and html &apos;0&apos; bodies [cipri]
358
+ * Fix Bug #10791: Unit tests fail [cipri]
359
+ * Fix Bug #10792: No unit tests for recently fixed bugs [cipri]
360
+ * Fix Bug #10793: Long headers don&apos;t get wrapped since fix for Bug #10298 [cipri]
361
+ * Fix Bug #10816: Unwanted linebreak at the end of output [cipri]
362
+ * Fix Bug #10838: bad use of MIME encoding in header. [cipri]
363
+ Implemented Features:
364
+ * Implement Feature #2952: Mail_mime::headers() saves extra headers [cipri]
365
+ * Implement Feature #3636: Allow specification of charsets and encoding [cipri]
366
+ * Implement Feature #4057: Mail_Mime: Add name parameter for Content-Type [cipri]
367
+ * Implement Feature #4504: addHTMLImage does not work in cases when filename contains a path [cipri]
368
+ * Implement Feature #5837: Mail_Mime: Build message for Net_SMTP [cipri]
369
+ * Implement Feature #5934: Mail_Mime: choice for content disposition [cipri]
370
+ * Implement Feature #6568: Mail_Mime: inline images referenced in CSS definitions not replaced. [cipri]
371
+ * Implement Feature #10604: Put an option to specify Content-Location in the header [cipri]</notes>
372
+ </release>
373
+ <release>
374
+ <version>
375
+ <release>1.5.0a1</release>
376
+ <api>1.3.1</api>
377
+ </version>
378
+ <stability>
379
+ <release>alpha</release>
380
+ <api>stable</api>
381
+ </stability>
382
+ <date>2007-06-10</date>
383
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license>
384
+ <notes>Split off mail_MimeDecode</notes>
385
+ </release>
386
+ <release>
387
+ <version>
388
+ <release>1.5.0RC1</release>
389
+ <api>1.3.1</api>
390
+ </version>
391
+ <stability>
392
+ <release>beta</release>
393
+ <api>stable</api>
394
+ </stability>
395
+ <date>2007-06-10</date>
396
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license>
397
+ <notes>Split off mail_MimeDecode</notes>
398
+ </release>
399
+ <release>
400
+ <version>
401
+ <release>1.5.0</release>
402
+ <api>1.3.1</api>
403
+ </version>
404
+ <stability>
405
+ <release>stable</release>
406
+ <api>stable</api>
407
+ </stability>
408
+ <date>2007-06-17</date>
409
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license>
410
+ <notes>Split off Mail_MimeDecode</notes>
411
+ </release>
412
+ <release>
413
+ <version>
414
+ <release>1.5.1</release>
415
+ <api>1.3.1</api>
416
+ </version>
417
+ <stability>
418
+ <release>stable</release>
419
+ <api>stable</api>
420
+ </stability>
421
+ <date>2007-06-20</date>
422
+ <license uri="http://www.opensource.org/licenses/bsd-license.php">BSD Style</license>
423
+ <notes>* Fix Bug #11344: Error at line 644 in mime.php [cipri]</notes>
424
+ </release>
425
+ </changelog>
426
+ </package>
postie-functions.php ADDED
@@ -0,0 +1,2322 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ //TODO option to set posts for review (not publish immediately)
3
+ include_once (dirname(dirname(dirname(dirname(__FILE__)))) . DIRECTORY_SEPARATOR . "wp-config.php");
4
+ define("POSTIE_ROOT",dirname(__FILE__));
5
+ define("POSTIE_TABLE",$GLOBALS["table_prefix"]. "postie_config");
6
+
7
+ /**
8
+ * This is the main handler for all of the processing
9
+ */
10
+ function PostEmail($poster,$mimeDecodedEmail) {
11
+ $config = GetConfig();
12
+ $GLOBALS["POSTIE_IMAGE_ROTATION"] = 0;
13
+ $attachments = array(
14
+ "html" => array(), //holds the html for each image
15
+ "cids" => array(), //holds the cids for HTML email
16
+ "image_files" => array() //holds the files for each image
17
+ );
18
+ print("<p>Message Id is :" . $mimeDecodedEmail->headers["message-id"] . "</p><br/>\n");
19
+ print("<p>Email has following attachments:</p>");
20
+ foreach($mimeDecodedEmail->parts as $parts) {
21
+ print("<p>".$parts->ctype_primary ." ".$parts->ctype_secondary) ."</p><br />\n";
22
+ }
23
+ FilterTextParts($mimeDecodedEmail);
24
+ #print("<p>Email has following attachments after filtering:");
25
+ # foreach($mimeDecodedEmail->parts as $parts) {
26
+ # print("<p>".$parts->ctype_primary ." ".$parts->ctype_secondary) ."<br />\n";
27
+ # }
28
+ $content = GetContent($mimeDecodedEmail,$attachments);
29
+ $subject = GetSubject($mimeDecodedEmail,$content);
30
+ echo "the subject is $subject, right after calling GetSubject\n";
31
+ $rotation = GetRotation($mimeDecodedEmail,$content);
32
+ if ($rotation != "0"
33
+ && count($attachments["image_files"])) {
34
+ RotateImages($rotation,$attachments["image_files"]);
35
+ }
36
+ SpecialMessageParsing($content,$attachments);
37
+ $postAuthorDetails=getPostAuthorDetails($subject,$content,
38
+ $mimeDecodedEmail);
39
+ $message_date = NULL;
40
+ if (array_key_exists("date",$mimeDecodedEmail->headers)
41
+ && !empty($mimeDecodedEmail->headers["date"])) {
42
+ HandleMessageEncoding($mimeDecodedEmail->headers["content-transfer-encoding"],
43
+ $mimeDecodedEmail->ctype_parameters["charset"],
44
+ $mimeDecodedEmail->headers["date"]);
45
+ $message_date = $mimeDecodedEmail->headers['date'];
46
+ }
47
+ list($post_date,$post_date_gmt) = DeterminePostDate($content, $message_date);
48
+
49
+ ubb2HTML($content);
50
+
51
+ $content = FilterNewLines($content);
52
+ //$content = FixEmailQuotes($content);
53
+
54
+ $id=checkReply($subject);
55
+ $post_categories = GetPostCategories($subject);
56
+ $post_tags = GetPostTags($content);
57
+ echo "the subject is $subject, right after calling GetPostCategories\n";
58
+ $comment_status = AllowCommentsOnPost($content);
59
+
60
+ if ((empty($id) || is_null($id)) &&
61
+ $config['ADD_META']=='yes') {
62
+ if ($config['WRAP_PRE']=='yes') {
63
+ //BMS: removing metadata from post body?
64
+ //$content = $postAuthorDetails['content'] . "<pre>\n" . $content . "</pre>\n";
65
+ $content = "<pre>\n" . $content . "</pre>\n";
66
+ } else {
67
+ //BMS: removing metadata from post body?
68
+ //$content = $postAuthorDetails['content'] . $content;
69
+ $content = $content;
70
+ }
71
+ echo "id is empty\n";
72
+ } else {
73
+ if ($config['WRAP_PRE']=='yes') {
74
+ $content = "<pre>\n" . $content . "</pre>\n";
75
+ }
76
+ }
77
+ $post_status=$config['POST_STATUS'];
78
+ $details = array(
79
+ 'post_author' => $poster,
80
+ 'comment_author' => $postAuthorDetails['author'],
81
+ 'email_author' => $postAuthorDetails['email'],
82
+ 'post_date' => $post_date,
83
+ 'post_date_gmt' => $post_date_gmt,
84
+ 'post_content' => addslashes($content),
85
+ 'post_title' => preg_replace("/'/","\\'",$subject),
86
+ 'post_modified' => $post_date,
87
+ 'post_modified_gmt' => $post_date_gmt,
88
+ 'ping_status' => get_option('default_ping_status'),
89
+ 'post_category' => $post_categories,
90
+ 'tags_input' => $post_tags,
91
+ 'comment_status' => $comment_status,
92
+ 'post_name' => sanitize_title($subject),
93
+ 'ID' => $id,
94
+ 'post_status' => $post_status
95
+ );
96
+ DisplayEmailPost($details);
97
+ PostToDB($details);
98
+ }
99
+ /** FUNCTIONS **/
100
+
101
+ function getPostAuthorDetails(&$subject,&$content,&$mimeDecodedEmail) {
102
+ /* we check whether or not the e-mail is a forwards or a redirect. If it is
103
+ * a fwd, then we glean the author details from the body of the post.
104
+ * Otherwise we get them from the headers
105
+ */
106
+
107
+ global $wpdb;
108
+ // see if subject starts with Fwd:
109
+ if (preg_match("/(^Fwd:) (.*)/", $subject, $matches)) {
110
+ $subject=trim($matches[2]);
111
+ if (preg_match("/\nfrom:(.*?)\n/i",$content,$matches)) {
112
+ $theAuthor=GetNameFromEmail($matches[1]);
113
+ $mimeDecodedEmail->headers['from']=$theAuthor;
114
+ }
115
+ if (preg_match("/\ndate:(.*?)\n/i",$content,$matches)) {
116
+ $theDate=$matches[1];
117
+ $mimeDecodedEmail->headers['date']=$theDate;
118
+ }
119
+ } else {
120
+ $theDate=$mimeDecodedEmail->headers['date'];
121
+ $theAuthor=GetNameFromEmail($mimeDecodedEmail->headers['from']);
122
+ $theEmail = RemoveExtraCharactersInEmailAddress(trim(
123
+ $mimeDecodedEmail->headers["from"]));
124
+ }
125
+ // now get rid of forwarding info in the content
126
+ $lines=preg_split("/\r\n/",$content);
127
+ $newContents='';
128
+ foreach ($lines as $line) {
129
+ if (preg_match("/^(from|subject|to|date):.*?/i",$line,$matches)==0 &&
130
+ // preg_match("/^$/i",$line,$matches)==0 &&
131
+ preg_match("/^-+\s*forwarded\s*message\s*-+/i",$line,$matches)==0) {
132
+ $newContents.=preg_replace("/\r/","",$line) . "\n" ;
133
+ }
134
+ }
135
+ $content=$newContents;
136
+ echo $newContents;
137
+ $theDetails=array(
138
+ 'content' =>"<div class='postmetadata alt'>On $theDate, $theAuthor" .
139
+ " posted:</div>",
140
+ 'emaildate' => $theDate,
141
+ 'author' => $theAuthor,
142
+ 'email' => $theEmail
143
+ );
144
+ return($theDetails);
145
+ }
146
+ function checkReply(&$subject) {
147
+ /* we check whether or not the e-mail is a reply to a previously
148
+ * published post. First we check whether it starts with Re:, and then
149
+ * we see if the remainder matches an already existing post. If so,
150
+ * then we add that post id to the details array, which will cause the
151
+ * existing post to be overwritten, instead of a new one being
152
+ * generated
153
+ */
154
+
155
+ global $wpdb;
156
+ // see if subject starts with Re:
157
+ if (preg_match("/(^Re:) (.*)/", $subject, $matches)) {
158
+ $subject=trim($matches[2]);
159
+ // strip out category info into temporary variable
160
+ $tmpSubject=$subject;
161
+ if ( preg_match('/(.+): (.*)/', $tmpSubject, $matches)) {
162
+ $tmpSubject = trim($matches[2]);
163
+ $matches[1] = array($matches[1]);
164
+ }
165
+ else if (preg_match_all('/\[(.[^\[]*)\]/', $tmpSubject, $matches)) {
166
+ preg_match("/](.[^\[]*)$/",$tmpSubject,$tmpSubject_matches);
167
+ $tmpSubject = trim($tmpSubject_matches[1]);
168
+ }
169
+ else if ( preg_match_all('/-(.[^-]*)-/', $tmpSubject, $matches) ) {
170
+ preg_match("/-(.[^-]*)$/",$tmpSubject,$tmpSubject_matches);
171
+ $tmpSubject = trim($tmpSubject_matches[1]);
172
+ }
173
+ $checkExistingPostQuery= "SELECT ID FROM $wpdb->posts WHERE
174
+ '$tmpSubject' = post_title";
175
+ echo "query = $checkExistingPostQuery\n";
176
+ if ($id=$wpdb->get_var($checkExistingPostQuery)) {
177
+ echo "results = $id\n";
178
+ if (is_array($id)) {
179
+ $id=$id[count($id)-1];
180
+ }
181
+ } else {
182
+ $id=NULL;
183
+ }
184
+ }
185
+ return($id);
186
+ }
187
+
188
+ function postie_read_me() {
189
+ include(POSTIE_ROOT . DIRECTORY_SEPARATOR. "postie_read_me.php");
190
+ }
191
+ /**
192
+ * This sets up the configuration menu
193
+ */
194
+ function PostieMenu() {
195
+ add_options_page("Configure Postie",
196
+ "Configure Postie" ,
197
+ 0,
198
+ POSTIE_ROOT . "/postie.php",
199
+ "ConfigurePostie");
200
+ }
201
+ /**
202
+ * This handles actually showing the form
203
+ */
204
+ function ConfigurePostie() {
205
+ PostieAdminPermissions();
206
+ if (current_user_can('config_postie')) {
207
+ include(POSTIE_ROOT . DIRECTORY_SEPARATOR. "config_form.php");
208
+ }
209
+ else {
210
+ postie_read_me();
211
+ }
212
+ }
213
+
214
+ /**
215
+ * This function handles determining the protocol and fetching the mail
216
+ * @return array
217
+ */
218
+ function FetchMail() {
219
+ $config = GetConfig();
220
+ $emails = array();
221
+ if (!$config["MAIL_SERVER"]
222
+ || !$config["MAIL_SERVER_PORT"]
223
+ || !$config["MAIL_USERID"]) {
224
+ die("Missing Configuration For Mail Server\n");
225
+ }
226
+ if ($config["MAIL_SERVER"] == "pop.gmail.com") {
227
+ print("\nMAKE SURE POP IS TURNED ON IN SETTING AT Gmail\n");
228
+ }
229
+ switch ( strtolower($config["INPUT_PROTOCOL"]) ) {
230
+ case 'smtp': //direct
231
+ $fd = fopen("php://stdin", "r");
232
+ $input = "";
233
+ while (!feof($fd)) {
234
+ $input .= fread($fd, 1024);
235
+ }
236
+ fclose($fd);
237
+ $emails[0] = $input;
238
+ break;
239
+ case 'imap':
240
+ case 'imap-ssl':
241
+ case 'pop3-ssl':
242
+ HasIMAPSupport(false);
243
+ if ($config["TEST_EMAIL"]) {
244
+ $emails = TestIMAPMessageFetch();
245
+ }
246
+ else {
247
+ $emails = IMAPMessageFetch();
248
+ }
249
+ break;
250
+ case 'pop3':
251
+ default:
252
+ if ($config["TEST_EMAIL"]) {
253
+ $emails = TestPOP3MessageFetch();
254
+ }
255
+ else {
256
+ $emails = POP3MessageFetch();
257
+ }
258
+ }
259
+ if (!$emails) {
260
+ die("\nThere does not seem to be any new mail.\n");
261
+ }
262
+ return($emails);
263
+ }
264
+ /**
265
+ *Handles fetching messages from an imap server
266
+ */
267
+ function TestIMAPMessageFetch ( ) {
268
+ print("**************RUNING IN TESTING MODE************\n");
269
+ $config = GetConfig();
270
+ $config["MAIL_USERID"] = $config["TEST_EMAIL_ACCOUNT"];
271
+ $config["MAIL_PASSWORD"] = $config["TEST_EMAIL_PASSWORD"];
272
+ return(IMAPMessageFetch($config));
273
+
274
+ }
275
+ /**
276
+ *Handles fetching messages from an imap server
277
+ */
278
+ function IMAPMessageFetch ($config = NULL ) {
279
+ if (!$config) {
280
+ $config = GetConfig();
281
+ }
282
+ require_once("postieIMAP.php");
283
+
284
+ $mail_server = &PostieIMAP::Factory($config["INPUT_PROTOCOL"]);
285
+ print("\nConnecting to $config[MAIL_SERVER]:$config[MAIL_SERVER_PORT] ($config[INPUT_PROTOCOL])) \n");
286
+ if (!$mail_server->connect($config["MAIL_SERVER"], $config["MAIL_SERVER_PORT"],$config["MAIL_USERID"],$config["MAIL_PASSWORD"])) {
287
+ print("Mail Connection Time Out\n
288
+ Common Reasons: \n
289
+ Server Down \n
290
+ Network Issue \n
291
+ Port/Protocol MisMatch \n
292
+ ");
293
+ die("The Server said:".$mail_server->error()."\n");
294
+ }
295
+ $msg_count = $mail_server->getNumberOfMessages();
296
+ $emails = array();
297
+ // loop through messages
298
+ for ($i=1; $i <= $msg_count; $i++) {
299
+ $emails[$i] = $mail_server->fetchEmail($i);
300
+ if ( $config["DELETE_MAIL_AFTER_PROCESSING"]) {
301
+ $mail_server->deleteMessage($i);
302
+ }
303
+ else {
304
+ print("Not deleting messages!\n");
305
+ }
306
+ }
307
+ if ( $config["DELETE_MAIL_AFTER_PROCESSING"]) {
308
+ $mail_server->expungeMessages();
309
+ }
310
+ //clean up
311
+ $mail_server->disconnect();
312
+ return $emails;
313
+ }
314
+ function TestPOP3MessageFetch ( ) {
315
+ print("**************RUNING IN TESTING MODE************\n");
316
+ $config = GetConfig();
317
+ $config["MAIL_USERID"] = $config["TEST_EMAIL_ACCOUNT"];
318
+ $config["MAIL_PASSWORD"] = $config["TEST_EMAIL_PASSWORD"];
319
+ return(POP3MessageFetch($config));
320
+ }
321
+ /**
322
+ *Retrieves email via POP3
323
+ */
324
+ function POP3MessageFetch ($config = NULL) {
325
+ if (!$config) {
326
+ $config = GetConfig();
327
+ }
328
+ require_once(ABSPATH.WPINC.DIRECTORY_SEPARATOR.'class-pop3.php');
329
+ $pop3 = &new POP3();
330
+ print("\nConnecting to $config[MAIL_SERVER]:$config[MAIL_SERVER_PORT] ($config[INPUT_PROTOCOL])) \n");
331
+ if (!$pop3->connect($config["MAIL_SERVER"], $config["MAIL_SERVER_PORT"])) {
332
+ if (strpos($pop3->ERROR,"POP3: premature NOOP OK, NOT an RFC 1939 Compliant server") === false) {
333
+ print("Mail Connection Time Out\n
334
+ Common Reasons: \n
335
+ Server Down \n
336
+ Network Issue \n
337
+ Port/Protocol MisMatch \n
338
+ ");
339
+ die("The Server Said $pop3->ERROR \n");
340
+ }
341
+ }
342
+
343
+ //Check to see if there is any mail, if not die
344
+ $msg_count = $pop3->login($config["MAIL_USERID"], $config["MAIL_PASSWORD"]);
345
+ if (!$msg_count) {
346
+ $pop3->quit();
347
+ return(array());
348
+ }
349
+
350
+ // loop through messages
351
+ for ($i=1; $i <= $msg_count; $i++) {
352
+ $emails[$i] = implode ('',$pop3->get($i));
353
+ if ( $config["DELETE_MAIL_AFTER_PROCESSING"]) {
354
+ if( !$pop3->delete($i) ) {
355
+ echo 'Oops '.$pop3->ERROR.'\n';
356
+ $pop3->reset();
357
+ exit;
358
+ } else {
359
+ echo "Mission complete, message $i deleted.\n";
360
+ }
361
+ }
362
+ else {
363
+ print("Not deleting messages!\n");
364
+ }
365
+ }
366
+ //clean up
367
+ $pop3->quit();
368
+ return $emails;
369
+ }
370
+ /**
371
+ * Determines if it is a writable directory
372
+ */
373
+ function IsWritableDirectory($directory) {
374
+ if (!is_dir($directory)) {
375
+ die ("Sorry but ".$directory." is not a valid directory.");
376
+ }
377
+ if (!is_writable($directory)) {
378
+ die("The web server cannot write to ".$directory." please correct the permissions");
379
+ }
380
+
381
+ }
382
+ /**
383
+ * This function handles putting the actual entry into the database
384
+ * @param array - categories to be posted to
385
+ * @param array - details of the post
386
+ */
387
+ function PostToDB($details) {
388
+ $config = GetConfig();
389
+ if ($config["POST_TO_DB"]) {
390
+ //generate sql for insertion
391
+ $_POST['publish'] = true; //Added to make subscribe2 work - it will only handle it if the global varilable _POST is set
392
+ if ($details['ID']==NULL) {
393
+ $post_ID = wp_insert_post($details);
394
+ } else {
395
+ // strip out quoted content
396
+ $lines=preg_split("/[\r\n]/",$details['post_content']);
397
+ print_r($lines);
398
+ $newContents='';
399
+ foreach ($lines as $line) {
400
+ //$match=preg_match("/^>.*/i",$line);
401
+ //echo "line=$line, match=$match";
402
+ if (preg_match("/^>.*/i",$line)==0 &&
403
+ preg_match("/^(from|subject|to|date):.*?/i",$line)==0 &&
404
+ preg_match("/^-+.*?(from|subject|to|date).*?/i",$line)==0 &&
405
+ preg_match("/^on.*?wrote:$/i",$line)==0 &&
406
+ preg_match("/^-+\s*forwarded\s*message\s*-+/i",$line)==0) {
407
+ $newContents.="$line\n";
408
+ }
409
+ }
410
+ $comment = array(
411
+ 'comment_author'=>$details['comment_author'],
412
+ 'comment_post_ID' =>$details['ID'],
413
+ 'comment_author_email' => $details['email_author'],
414
+ 'comment_date' =>$details['post_date'],
415
+ 'comment_date_gmt' =>$details['post_date_gmt'],
416
+ 'comment_content' =>$newContents,
417
+ 'comment_author_url' =>'',
418
+ 'comment_author_IP' =>'',
419
+ 'comment_approved' =>1,
420
+ 'comment_agent' =>'',
421
+ 'comment_type' =>'',
422
+ 'comment_parent' => 0
423
+ );
424
+
425
+ echo "the comment is:\n";
426
+ print_r($comment);
427
+ $post_ID = wp_insert_comment($comment);
428
+ }
429
+ //do_action('publish_post', $post_ID); - no longer needed
430
+ //do_action('publish_phone', $post_ID); -- seems to triger a double
431
+
432
+ }
433
+ }
434
+
435
+ /**
436
+ * This function determines if the mime attachment is on the BANNED_FILE_LIST
437
+ * @param string
438
+ * @return boolean
439
+ */
440
+ function BannedFileName($filename) {
441
+ $config = GetConfig();
442
+ if (in_array($filename,$config["BANNED_FILES_LIST"])) {
443
+ print("<p>Ignoreing $filename - it is on the banned files list.");
444
+ return(true);
445
+ }
446
+ return(false);
447
+ }
448
+
449
+ //tear apart the meta part for useful information
450
+ function GetContent ($part,&$attachments) {
451
+ $config = GetConfig();
452
+ $meta_return = NULL;
453
+
454
+ DecodeBase64Part($part);
455
+ if (BannedFileName($part->ctype_parameters['name'])
456
+ || BannedFileName($part->ctype_parameters['name'])) {
457
+ return(NULL);
458
+ }
459
+
460
+ if ($part->ctype_primary == "application"
461
+ && $part->ctype_secondary == "octet-stream") {
462
+ if ($part->disposition == "attachment") {
463
+ $image_endings = array("jpg","png","gif","jpeg","pjpeg");
464
+ foreach ($image_endings as $type) {
465
+ if (eregi(".$type\$",$part->d_parameters["filename"])) {
466
+ $part->ctype_primary = "image";
467
+ $part->ctype_secondary = $type;
468
+ break;
469
+ }
470
+ }
471
+ }
472
+ else {
473
+ $mimeDecodedEmail = DecodeMIMEMail($part->body);
474
+ FilterTextParts($mimeDecodedEmail);
475
+ foreach($mimeDecodedEmail->parts as $section) {
476
+ $meta_return .= GetContent($section,$attachments);
477
+ }
478
+ }
479
+ }
480
+ if ($part->ctype_primary == "multipart"
481
+ && $part->ctype_secondary == "appledouble") {
482
+ $mimeDecodedEmail = DecodeMIMEMail("Content-Type: multipart/mixed; boundary=".$part->ctype_parameters["boundary"]."\n".$part->body);
483
+ FilterTextParts($mimeDecodedEmail);
484
+ FilterAppleFile($mimeDecodedEmail);
485
+ foreach($mimeDecodedEmail->parts as $section) {
486
+ $meta_return .= GetContent($section,$attachments);
487
+ }
488
+ }
489
+ else {
490
+ switch ( strtolower($part->ctype_primary) ) {
491
+ case 'multipart':
492
+ FilterTextParts($part);
493
+ foreach ($part->parts as $section) {
494
+ $meta_return .= GetContent($section,$attachments);
495
+ }
496
+ break;
497
+ case 'text':
498
+
499
+ HandleMessageEncoding($part->headers["content-transfer-encoding"],
500
+ $part->ctype_parameters["charset"],
501
+ $part->body);
502
+
503
+ //go through each sub-section
504
+ if ($part->ctype_secondary=='enriched') {
505
+ //convert enriched text to HTML
506
+ $meta_return .= etf2HTML($part->body ) . "\n";
507
+ } elseif ($part->ctype_secondary=='html') {
508
+ //strip excess HTML
509
+ $meta_return .= HTML2HTML($part->body ) . "\n";
510
+ } else {
511
+ //regular text, so just strip the pgp signature
512
+ if (ALLOW_HTML_IN_BODY) {
513
+ $meta_return .= $part->body . "\n";
514
+ }
515
+ else {
516
+ $meta_return .= htmlentities( $part->body ) . "\n";
517
+ }
518
+ $meta_return = StripPGP($meta_return);
519
+ }
520
+ break;
521
+
522
+ case 'image':
523
+ $file = GenerateImageFileName($config["REALPHOTOSDIR"], $part->ctype_secondary);
524
+ //This makes sure there is no collision
525
+ $ctr = 0;
526
+ while(file_exists($file) && $ctr < 1000) {
527
+ $file = GenerateImageFileName($config["REALPHOTOSDIR"], $part->ctype_secondary);
528
+ $ctr++;
529
+ }
530
+ if ($ctr >= 1000) {
531
+ die("Unable to find a name for images that does not collide\n");
532
+ }
533
+ $fileName = basename($file);
534
+ $fp = fopen($file, 'w');
535
+ fwrite($fp, $part->body);
536
+ fclose($fp);
537
+ @exec ('chmod 755 ' . $file);
538
+ if ($config["USE_IMAGEMAGICK"] && $config["AUTO_SMART_SHARP"]) {
539
+ ImageMagickSharpen($file);
540
+ }
541
+ $mimeTag = '<!--Mime Type of File is '.$part->ctype_primary."/".$part->ctype_secondary.' -->';
542
+ $thumbImage = NULL;
543
+ $cid = trim($part->headers["content-id"],"<>");; //cids are in <cid>
544
+ if ($config["RESIZE_LARGE_IMAGES"]) {
545
+ echo "going to resize now \n<br />";
546
+ list($thumbImage, $fullImage, $caption) = ResizeImage($file,strtolower($part->ctype_secondary));
547
+ echo "caption=$caption\n<br />";
548
+ echo "thumbImage=$thumbImage\n<br />";
549
+ }
550
+ $attachments["image_files"][] = array(($thumbImage ? $config["REALPHOTOSDIR"] . $thumbImage:NULL),
551
+ $config["REALPHOTOSDIR"] . $fileName,
552
+ $part->ctype_secondary);
553
+ $onclick='';
554
+ if ($config['IMAGE_NEW_WINDOW']) {
555
+ $onclick='" onclick="window.open(' . "'"
556
+ . $config["URLPHOTOSDIR"] . $fullImage . "','"
557
+ . "full_size_image" . "','"
558
+ . "toolbar=0,scrollbars=0,location=0,status=0,menubar=0,resizable=1,height=" . $marimey . ",width=" . $marimex . "');" . "return false;";
559
+ }
560
+ if ($thumbImage) {
561
+ //TODO image template
562
+ list($marime,$tmpcaption)=DetermineImageSize($file);
563
+ $marimex=$marime[0]+20;
564
+ $marimey=$marime[1]+20;
565
+ if ($config['USEIMAGETEMPLATE']) {
566
+ $imageTemplate=str_replace('{THUMBNAIL}',
567
+ $config['URLPHOTOSDIR'] . $thumbImage,
568
+ $config['IMAGETEMPLATE']);
569
+ $imageTemplate=str_replace('{IMAGE}',
570
+ $config['URLPHOTOSDIR'] . $fullImage,
571
+ $imageTemplate);
572
+ $imageTemplate=str_replace('{FILENAME}',
573
+ $config['REALPHOTOSDIR'] . $fullImage,
574
+ $imageTemplate);
575
+ if ($caption!='') {
576
+ $imageTemplate=str_replace('{CAPTION}',
577
+ $caption, $imageTemplate);
578
+ }
579
+ $attachments["html"][] .=$imageTemplate;
580
+ } else {
581
+ $attachments["html"][] .= $mimeTag.'<div class="' . $config["IMAGEDIV"].'"><a href="' . $config["URLPHOTOSDIR"] . $fullImage .
582
+ $onclick . '"><img src="' . $config["URLPHOTOSDIR"] . $thumbImage . '" alt="'
583
+ . $part->ctype_parameters['name'] . '" title="' . $part->ctype_parameters['name'] . '" style="'.$config["IMAGESTYLE"].'" class="'.$config["IMAGECLASS"].'" /></a></div>' . "\n";
584
+ }
585
+ if ($cid) {
586
+ $attachments["cids"][$cid] = array($config["URLPHOTOSDIR"] . $fullImage,count($attachments["html"]) - 1);
587
+ }
588
+ }
589
+ else {
590
+ $attachments["html"][] .= $mimeTag .'<div class="' . $config["IMAGEDIV"].'"><img src="' . $config["URLPHOTOSDIR"] . $fileName
591
+ . '" alt="' . $part->ctype_parameters['name'] . '" style="'
592
+ . $config["IMAGESTYLE"] . '" class="' . $config["IMAGECLASS"] . '" /></div>' . "\n";
593
+ if ($cid) {
594
+ $attachments["cids"][$cid] = array($config["URLPHOTOSDIR"] . $fileName,count($attachments["html"]) - 1);
595
+ }
596
+ }
597
+ break;
598
+ default:
599
+ if (in_array(strtolower($part->ctype_primary),$config["SUPPORTED_FILE_TYPES"])) {
600
+ //pgp signature - then forget it
601
+ if ( $part->ctype_secondary == 'pgp-signature' ) {break;}
602
+ //other attachments save to FILESDIR
603
+ $filename = $part->ctype_parameters['name'];
604
+ $file = $config["REALFILESDIR"] . $filename;
605
+ $fp = fopen($file, 'w');
606
+ fwrite($fp, $part->body );
607
+ fclose($fp);
608
+ @exec ('chmod 755 ' . $file);
609
+ $cid = trim($part->headers["content-id"],"<>");; //cids are in <cid>
610
+
611
+ if ($part->ctype_secondary == "3gpp"
612
+ || $part->ctype_secondary == "3gp"
613
+ || $part->ctype_secondary == "3g2"
614
+ || $part->ctype_secondary == "3gpp2") {
615
+ if ($config["3GP_QT"]) {
616
+ //Shamelessly borrowed from http://www.postneo.com/2003/12/19/embedding-3gpp-in-html
617
+ $attachments["html"][] = '<!--Mime Type of File is '.$part->ctype_primary."/".$part->ctype_secondary.' -->' .
618
+ '<a href="'.$config["URLFILESDIR"] . $filename.'">Video'.
619
+ '<object '.
620
+ 'classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" '.
621
+ 'codebase="http://www.apple.com/qtactivex/qtplugin.cab" '.
622
+ 'width="128" '.
623
+ 'height="112"> '.
624
+ '<param name="src" VALUE="'. $config["URLFILESDIR"] . $filename .'"> '.
625
+ '<param name="autoplay" VALUE="false"> '.
626
+ '<param name="controller" VALUE="true"> '.
627
+ '<embed '.
628
+ 'src="'. $config["URLFILESDIR"] . $filename .'" '.
629
+ 'width="128" '.
630
+ 'height="112" '.
631
+ 'autoplay="true" '.
632
+ 'controller="true" '.
633
+ 'type="video/quicktime" '.
634
+ 'pluginspage="http://www.apple.com/quicktime/download/" '.
635
+ 'width="128" '.
636
+ 'height="150"></embed> '.
637
+ '</object></a>';
638
+ }
639
+ else {
640
+ if (file_exists($config["3GP_FFMPEG"])) {
641
+ $fileName = basename($file);
642
+ //options from http://www.getid3.org/phpBB2/viewtopic.php?p=1290&
643
+ $scaledFileName = "thumb.".$fileName;
644
+ $scaledFile = $config["REALPHOTOSDIR"] . $scaledFileName;
645
+
646
+ @exec (escapeshellcmd($config["3GP_FFMPEG"]) .
647
+ " -i " .
648
+ escapeshellarg($file) .
649
+ " -y -ss 00:00:01 -vframes 1 -an -sameq -f gif " .
650
+ escapeshellarg($scaledFile) );
651
+ @exec ('chmod 755 ' . escapeshellarg($scaledFile));
652
+
653
+ $attachments["html"][] .= '<!--Mime Type of File is '.$part->ctype_primary."/".$part->ctype_secondary.' --><div class="' . $config["3GPDIV"].'"><a href="' . $config["URLPHOTOSDIR"] . $fileName. '"><img src="' . $config["URLPHOTOSDIR"] . $scaledFileName . '" alt="' . $part->ctype_parameters['name'] . '" style="'.$config["IMAGESTYLE"].'" class="'.$config["IMAGECLASS"].'" /></a></div>' . "\n";
654
+ }
655
+ else {
656
+ $attachments["html"][] = '<!--Mime Type of File is '.$part->ctype_primary."/".$part->ctype_secondary.' --><div class="' . $config["ATTACHMENTDIV"].'"><a href="' . $config["URLFILESDIR"] . $filename . '" class="' . $config["3GPCLASS"].'">' . $part->ctype_parameters['name'] . '</a></div>' . "\n";
657
+ }
658
+
659
+ }
660
+ }
661
+ elseif ($part->ctype_secondary == "x-shockwave-flash") {
662
+ $attachments["html"][] = '<!--Mime Type of File is '.$part->ctype_primary."/".$part->ctype_secondary.' -->'.
663
+ '<object '.
664
+ 'classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" '.
665
+ 'codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0" '.
666
+ 'width="" '.
667
+ 'height=""> '.
668
+ '<param name="movie" value="'. $config["URLFILESDIR"] . $filename .'"> '.
669
+ '<param name="quality" value="high"> '.
670
+ '<embed '.
671
+ 'src="'. $config["URLFILESDIR"] . $filename .'" '.
672
+ 'width="" '.
673
+ 'height="" '.
674
+ 'quality="high" '.
675
+ 'pluginspage="http://www.macromedia.com/go/getflashplayer" '.
676
+ 'type="application/x-shockwave-flash" '.
677
+ 'width="" '.
678
+ 'height=""></embed> '.
679
+ '</object>';
680
+ }
681
+ else {
682
+ $attachments["html"][] = '<!--Mime Type of File is '.$part->ctype_primary."/".$part->ctype_secondary.' --><a href="' . $config["URLFILESDIR"] . $filename . '">' . $part->ctype_parameters['name'] . '</a>' . "\n";
683
+ }
684
+ if ($cid) {
685
+ $attachments["cids"][$cid] = array($config["URLFILESDIR"] . $filename,count($attachments["html"]) - 1);
686
+ }
687
+ }
688
+ break;
689
+ }
690
+ }
691
+ return $meta_return;
692
+ }
693
+
694
+ function ubb2HTML(&$text) {
695
+ // Array of tags with opening and closing
696
+ $tagArray['img'] = array('open'=>'<img src="','close'=>'">');
697
+ $tagArray['b'] = array('open'=>'<b>','close'=>'</b>');
698
+ $tagArray['i'] = array('open'=>'<i>','close'=>'</i>');
699
+ $tagArray['u'] = array('open'=>'<u>','close'=>'</u>');
700
+ $tagArray['url'] = array('open'=>'<a href="','close'=>'">\\1</a>');
701
+ $tagArray['email'] = array('open'=>'<a href="mailto:','close'=>'">\\1</a>');
702
+ $tagArray['url=(.*)'] = array('open'=>'<a href="','close'=>'">\\2</a>');
703
+ $tagArray['email=(.*)'] = array('open'=>'<a href="mailto:','close'=>'">\\2</a>');
704
+ $tagArray['color=(.*)'] = array('open'=>'<font color="','close'=>'">\\2</font>');
705
+ $tagArray['size=(.*)'] = array('open'=>'<font size="','close'=>'">\\2</font>');
706
+ $tagArray['font=(.*)'] = array('open'=>'<font face="','close'=>'">\\2</font>');
707
+ // Array of tags with only one part
708
+ $sTagArray['br'] = array('tag'=>'<br>');
709
+ $sTagArray['hr'] = array('tag'=>'<hr>');
710
+
711
+ foreach($tagArray as $tagName=>$replace) {
712
+ $tagEnd = preg_replace('/\W/Ui','',$tagName);
713
+ $text = preg_replace("|\[$tagName\](.*)\[/$tagEnd\]|Ui","$replace[open]\\1$replace[close]",$text);
714
+ }
715
+ foreach($sTagArray as $tagName=>$replace) {
716
+ $text = preg_replace("|\[$tagName\]|Ui","$replace[tag]",$text);
717
+ }
718
+ return $text;
719
+ }
720
+
721
+
722
+ // This function turns Enriched Text into something similar to HTML
723
+ // Very basic at the moment, only supports some functionality and dumps the rest
724
+ // FIXME: fix colours: <color><param>FFFF,C2FE,0374</param>some text </color>
725
+ function etf2HTML ( $content ) {
726
+
727
+ $search = array(
728
+ '/<bold>/',
729
+ '/<\/bold>/',
730
+ '/<underline>/',
731
+ '/<\/underline>/',
732
+ '/<italic>/',
733
+ '/<\/italic>/',
734
+ '/<fontfamily><param>.*<\/param>/',
735
+ '/<\/fontfamily>/',
736
+ '/<x-tad-bigger>/',
737
+ '/<\/x-tad-bigger>/',
738
+ '/<bigger>/',
739
+ '</bigger>/',
740
+ '/<color>/',
741
+ '/<\/color>/',
742
+ '/<param>.+<\/param>/'
743
+ );
744
+
745
+ $replace = array (
746
+ '<b>',
747
+ '</b>',
748
+ '<u>',
749
+ '</u>',
750
+ '<i>',
751
+ '</i>',
752
+ '',
753
+ '',
754
+ '',
755
+ '',
756
+ '',
757
+ '',
758
+ '',
759
+ '',
760
+ ''
761
+ );
762
+ // strip extra line breaks
763
+ $content = preg_replace($search,$replace,$content);
764
+ return trim($content);
765
+ }
766
+
767
+
768
+ // This function cleans up HTML in the e-mail
769
+ function HTML2HTML ( $content ) {
770
+ $search = array(
771
+ '/<html>/',
772
+ '/<\/html>/',
773
+ '/<title>/',
774
+ '/<\/title>/',
775
+ '/<body.*>/',
776
+ '/<\/body>/',
777
+ '/<head>/',
778
+ '/<\/head>/',
779
+ '/<meta content=.*>/',
780
+ '/<!DOCTYPE.*>/',
781
+ '/<img src=".*>/'
782
+ // '/<img src="cid:(.*)" .*>/'
783
+ );
784
+
785
+ $replace = array (
786
+ '',
787
+ '',
788
+ '',
789
+ '',
790
+ '',
791
+ '',
792
+ '',
793
+ '',
794
+ '',
795
+ '',
796
+ '',
797
+ ''
798
+ );
799
+ // strip extra line breaks
800
+ $content = preg_replace($search,$replace,trim($content));
801
+ return ($content);
802
+ }
803
+
804
+
805
+
806
+ /**
807
+ * Determines if the sender is a valid user.
808
+ * @return integer|NULL
809
+ */
810
+ function ValidatePoster( &$mimeDecodedEmail ) {
811
+ global $wpdb;
812
+ $config = GetConfig();
813
+ $poster = NULL;
814
+ $from = RemoveExtraCharactersInEmailAddress(trim($mimeDecodedEmail->headers["from"]));
815
+ $resentFrom = RemoveExtraCharactersInEmailAddress(trim($mimeDecodedEmail->headers["resent-from"]));
816
+
817
+ if ( empty($from) ) {
818
+ echo 'Invalid Sender - Emtpy! ';
819
+ return;
820
+ }
821
+
822
+ //See if the email address is one of the special authorized ones
823
+ print("Confirming Access For $from \n");
824
+ $sql = 'SELECT id FROM '. $wpdb->users.' WHERE user_email=\'' . addslashes($from) . "' LIMIT 1;";
825
+ $user_ID= $wpdb->get_var($sql);
826
+ $user = new WP_User($user_ID);
827
+ if ($config["TURN_AUTHORIZATION_OFF"] || CheckEmailAddress($from) || CheckEmailAddress($resentFrom)) {
828
+ if (empty($user_ID)){
829
+ print("$from is authorized to post as the administrator\n");
830
+ $from = get_option("admin_email");
831
+ $adminUser=$config['ADMIN_USERNAME'];
832
+ echo "adminUser='$adminUser'";
833
+ $poster = $wpdb->get_var("SELECT ID FROM $wpdb->users WHERE
834
+ user_login = '$adminUser'");
835
+ }
836
+ else {
837
+ $poster = $user_ID;
838
+ }
839
+ }
840
+ else if ($user->has_cap("post_via_postie")) {
841
+ $poster = $user_ID;
842
+ }
843
+ if (!$poster) {
844
+ echo 'Invalid sender: ' . htmlentities($from) . "! Not adding email!\n";
845
+ if ($config["FORWARD_REJECTED_MAIL"]) {
846
+ if (ForwardRejectedMailToAdmin($mimeDecodedEmail)) {
847
+ echo "A copy of the message has been forwarded to the administrator.\n";
848
+ } else {
849
+ echo "The message was unable to be forwarded to the adminstrator.\n";
850
+ }
851
+ }
852
+ return;
853
+ }
854
+ return $poster;
855
+ }
856
+
857
+ /**
858
+ * Looks at the content for the start of the message and removes everything before that
859
+ * If the pattern is not found everything is returned
860
+ * @param string
861
+ * @param string
862
+ */
863
+ function StartFilter(&$content,$start) {
864
+ $pos = strpos($content,$start);
865
+ if ( $pos === false) {
866
+ return($content);
867
+ }
868
+ $content = substr($content, $pos + strlen($start), strlen($content));
869
+ }
870
+
871
+ /**
872
+ * Looks at the content for the start of the signature and removes all text
873
+ * after that point
874
+ * @param string
875
+ * @param array - a list of patterns to determine if it is a sig block
876
+ */
877
+ function RemoveSignature( &$content,$filterList = array('--','- --' )) {
878
+ $arrcontent = explode("\n", $content);
879
+ $i = 0;
880
+ for ($i = 0; $i<=count($arrcontent); $i++) {
881
+ $line = $arrcontent[$i];
882
+ $nextline = $arrcontent[$i+1];
883
+ foreach ($filterList as $pattern) {
884
+ if (preg_match("/^$pattern/",trim($line))) {
885
+ //print("<p>Found in $line");
886
+ break 2;
887
+ }
888
+ }
889
+ $strcontent .= $line ."\n";
890
+ }
891
+ $content = $strcontent;
892
+ }
893
+ /**
894
+ * Looks at the content for the given tag and removes all text
895
+ * after that point
896
+ * @param string
897
+ * @param filter
898
+ */
899
+ function EndFilter( &$content,$filter) {
900
+ $arrcontent = explode("\n", $content);
901
+ $i = 0;
902
+ for ($i = 0; $i<=count($arrcontent); $i++) {
903
+ $line = $arrcontent[$i];
904
+ $nextline = $arrcontent[$i+1];
905
+ if (preg_match("/^$filter/",trim($line))) {
906
+ //print("<p>Found in $line");
907
+ break;
908
+ }
909
+ $strcontent .= $line ."\n";
910
+ }
911
+ $content = $strcontent;
912
+ }
913
+
914
+ //filter content for new lines
915
+ function FilterNewLines ( $content ) {
916
+ $config=GetConfig();
917
+ $search = array (
918
+ "/\r\n/",
919
+ "/\r/",
920
+ "/\n\n/",
921
+ "/\n/"
922
+ );
923
+ $replace = array (
924
+ "\n",
925
+ "\n",
926
+ 'ACTUAL_NEW_LINE',
927
+ 'LINEBREAK'
928
+ );
929
+ // strip extra line breaks, and replace double line breaks with paragraph
930
+ // tags
931
+ $result = preg_replace($search,$replace,$content);
932
+ $newContent='<p>' . preg_replace('/ACTUAL_NEW_LINE/',"</p>\n<p>",$result);
933
+ $newContent=preg_replace('/<p>LINEBREAK$/', '', $newContent);
934
+ if ($config['CONVERTNEWLINE']) {
935
+ $newContent= preg_replace('/LINEBREAK/',"<br />\n",$newContent);
936
+ echo "converting newlines\n";
937
+ } else {
938
+ $newContent= preg_replace('/LINEBREAK/'," ",$newContent);
939
+ echo "not converting newlines\n";
940
+ }
941
+ return($newContent);
942
+ }
943
+ function FixEmailQuotes ( $content ) {
944
+ # place e-mails quotes (indicated with >) in blockquote and pre tags
945
+ $search = array (
946
+ "/^>/"
947
+ );
948
+ $replace = array (
949
+ '<br />&gt;'
950
+ );
951
+ // strip extra line breaks, and replace double line breaks with paragraph
952
+ // tags
953
+ $result = preg_replace($search,$replace,$content);
954
+ //return('<p>' . preg_replace('/ACTUAL_NEW_LINE/',"<\/p>\n<p>",$result)
955
+ //. '</p>');
956
+ return($result);
957
+ }
958
+
959
+ //strip pgp stuff
960
+ function StripPGP ( $content ) {
961
+ $search = array (
962
+ '/-----BEGIN PGP SIGNED MESSAGE-----/',
963
+ '/Hash: SHA1/'
964
+ );
965
+ $replace = array (
966
+ ' ',
967
+ ''
968
+ );
969
+ // strip extra line breaks
970
+ $return = preg_replace($search,$replace,$content);
971
+ return $return;
972
+ }
973
+
974
+ function ConvertToISO_8859_1($encoding,$charset, &$body ) {
975
+ $config = GetConfig();
976
+ $charset = strtolower($charset);
977
+ $encoding = strtolower($encoding);
978
+ if( (strtolower($config["MESSAGE_ENCODING"]) == "iso-8859-1") && (strtolower($charset) != 'iso-8859-1')) {
979
+ if( $encoding == 'base64' || $encoding == 'quoted-printable' ) {
980
+ $body = utf8_decode($body);
981
+ }
982
+ }
983
+ }
984
+ function IsISO88591Blog() {
985
+ $config = GetConfig();
986
+ if( (strtolower($config["MESSAGE_ENCODING"]) == "iso-8859-1")) {
987
+ return(true);
988
+ }
989
+ return(false);
990
+ }
991
+ function IsUTF8Blog() {
992
+ $config = GetConfig();
993
+ if( (strtolower($config["MESSAGE_ENCODING"]) == "utf-8")) {
994
+ return(true);
995
+ }
996
+ return(false);
997
+ }
998
+ function HandleMessageEncoding($encoding, $charset,&$body) {
999
+ $charset = strtolower($charset);
1000
+ $encoding = strtolower($encoding);
1001
+ /*
1002
+ if ($encoding == '') {
1003
+ $encoding = '7bit';
1004
+ }
1005
+ */
1006
+ HandleQuotedPrintable($encoding, $body);
1007
+ if (isISO88591Blog()) {
1008
+ ConvertToISO_8859_1($encoding,$charset,$body);
1009
+ }
1010
+ else {
1011
+ ConvertToUTF_8($encoding,$charset,$body);
1012
+ }
1013
+ }
1014
+ function ConvertToUTF_8($encoding,$charset,&$body) {
1015
+ $charset = strtolower($charset);
1016
+ $encoding = strtolower($encoding);
1017
+ switch($charset) {
1018
+ case "iso-8859-1":
1019
+ $body = utf8_encode($body);
1020
+ break;
1021
+ case "iso-2022-jp":
1022
+ $body = iconv("ISO-2022-JP//TRANSLIT","UTF-8",$body);
1023
+ break;
1024
+ }
1025
+ }
1026
+
1027
+ /**
1028
+ * This function handles decoding base64 if needed
1029
+ */
1030
+ function DecodeBase64Part( &$part ) {
1031
+ if ( strtolower($part->headers['content-transfer-encoding']) == 'base64' ) {
1032
+ $part->body = base64_decode($part->body);
1033
+ }
1034
+ }
1035
+
1036
+ function HandleQuotedPrintable($encoding, &$body ) {
1037
+ $config = GetConfig();
1038
+ if ( $config["MESSAGE_DEQUOTE"] && strtolower($encoding) == 'quoted-printable' ) {
1039
+ $body = quoted_printable_decode($body);
1040
+ }
1041
+ }
1042
+
1043
+
1044
+ function GenerateImageFileName($dir,$type) {
1045
+ static $ctr;
1046
+ $config = GetConfig();
1047
+ $ctr++;
1048
+ $type = strtolower($type);
1049
+ if ($type == "jpeg"
1050
+ || $type = "pjpeg") {
1051
+ $type = "jpg";
1052
+ }
1053
+ if ($config["TEST_EMAIL"]) {
1054
+ return($dir . "TEST-" . date("Ymd-His-",time()) . $ctr . "." . $type);
1055
+ }
1056
+ else {
1057
+ return($dir . date("Ymd-His-",time()) . $ctr . "." . $type);
1058
+ }
1059
+ }
1060
+ function ConfirmTrailingDirectorySeperator($string) {
1061
+ if (substr($string,strlen($string) - 1,1) == DIRECTORY_SEPARATOR) {
1062
+ return(true);
1063
+ }
1064
+ return(false);
1065
+ }
1066
+ /**
1067
+ * This function handles figuring out the size of the image
1068
+ *@return array - array(width,height)
1069
+ */
1070
+ function DetermineImageSize($file) {
1071
+ $config = GetConfig();
1072
+ if ($config["USE_IMAGEMAGICK"]) {
1073
+ list($size,$caption)=DetermineImageSizeWithImageMagick($file);
1074
+ }
1075
+ else {
1076
+ echo "determining image size with GD\n<br />";
1077
+ list($size,$caption)=DetermineImageSizeWithGD($file);
1078
+ }
1079
+ return(array($size,$caption));
1080
+ }
1081
+ /**
1082
+ * This function handles figuring out the size of the image
1083
+ *@return array - array(width,height)
1084
+ */
1085
+ function DetermineImageSizeWithImageMagick($file) {
1086
+ $config = GetConfig();
1087
+ $size = array(0,0);
1088
+ if (file_exists($config["IMAGEMAGICK_IDENTIFY"])) {
1089
+ $geometry = @exec (escapeshellcmd($config["IMAGEMAGICK_IDENTIFY"]) .
1090
+ " -ping " .
1091
+ escapeshellarg($file));
1092
+ preg_match("/([0-9]+)x([0-9]+)/",$geometry,$matches);
1093
+ if (isset($matches[1])) {
1094
+ $size[0] = $matches[1];
1095
+ }
1096
+ if (isset($matches[2])) {
1097
+ $size[1] = $matches[2];
1098
+ }
1099
+ }
1100
+ if (file_exists($config["IMAGEMAGICK_CONVERT"])) {
1101
+ $caption = @exec (escapeshellcmd($config["IMAGEMAGICK_CONVERT"]) .
1102
+ " " . escapeshellarg($file)) . '8BIMTEXT:- ';
1103
+ preg_match('/Caption="(.*)"/', $caption, $matches);
1104
+ if (isset($matches[1])) {
1105
+ $caption = $matches[1];
1106
+ }
1107
+ }
1108
+ return(array($size,$caption));
1109
+ }
1110
+ /**
1111
+ * This function handles figuring out the size of the image
1112
+ *@return array - array(width,height)
1113
+ */
1114
+ function DetermineImageSizeWithGD($file) {
1115
+ $size = getimagesize($file, $info);
1116
+ if(isset($info['APP13'])) {
1117
+ $iptc = iptcparse($info['APP13']);
1118
+ $caption= $iptc['2#120'][0];
1119
+ }
1120
+ return(array($size,$caption));
1121
+ }
1122
+
1123
+ function ResizeImage($file,$type) {
1124
+ $config = GetConfig();
1125
+ list($sizeInfo,$caption) = DetermineImageSize($file);
1126
+ $fileName = basename($file);
1127
+ if (DetermineScale($sizeInfo[0],$sizeInfo[1],$config["MAX_IMAGE_WIDTH"], $config["MAX_IMAGE_HEIGHT"]) != 1) {
1128
+ if ($config["USE_IMAGEMAGICK"]) {
1129
+ list($scaledFileName, $fileName,$caption)=ResizeImageWithImageMagick($file,$type);
1130
+ } else {
1131
+ echo "using GD to resize\n";
1132
+ list($scaledFileName, $fileName,$caption)=ResizeImageWithGD($file,$type);
1133
+ }
1134
+ }
1135
+ return(array($scaledFileName,$fileName, $caption));
1136
+
1137
+ }
1138
+ function RotateImages($rotation,$imageList) {
1139
+ $config = GetConfig();
1140
+ foreach ($imageList as $data) {
1141
+ if ($config["USE_IMAGEMAGICK"]) {
1142
+ if ($data[0]) {
1143
+ RotateImageWithImageMagick($data[0],$data[2],$rotation);
1144
+ }
1145
+ RotateImageWithImageMagick($data[1],$data[2],$rotation);
1146
+ }
1147
+ else {
1148
+ if ($data[0]) {
1149
+ RotateImageWithGD($data[0],$data[2],$rotation);
1150
+ }
1151
+ RotateImageWithGD($data[1],$data[2],$rotation);
1152
+ }
1153
+ }
1154
+ }
1155
+ function ImageMagickSharpen($source,$dest = null) {
1156
+ $config = GetConfig();
1157
+ if (!$dest) {
1158
+ $dest = $source;
1159
+ }
1160
+ @exec (escapeshellcmd($config["IMAGEMAGICK_CONVERT"]) . " ".
1161
+ escapeshellarg($source) . " ".
1162
+ '\( +clone -modulate 100,0 \) \( +clone -unsharp 0x1+200+0 \) \( -clone 0 -edge 3 -colorspace GRAY -colors 256 -level 20%,95% -gaussian 10 -level 10%,95% \) -colorspace RGB -fx "u[0]+(((u[2]+1)/(u[1]+1))-1)*u[0]*u[3]" ' .
1163
+ escapeshellarg($dest) );
1164
+ @exec ('chmod 755 ' . escapeshellarg($dest));
1165
+
1166
+ }
1167
+ function RotateImageWithImageMagick($file,$type,$rotation) {
1168
+ $config = GetConfig();
1169
+ @exec (escapeshellcmd($config["IMAGEMAGICK_CONVERT"]) .
1170
+ " -rotate " .
1171
+ escapeshellarg($rotation) .
1172
+ " " .
1173
+ escapeshellarg($file) .
1174
+ " " .
1175
+ escapeshellarg($file) );
1176
+ @exec ('chmod 755 ' . escapeshellarg($file));
1177
+ }
1178
+ function RotateImageWithGD($file,$type,$rotation) {
1179
+ $config = GetConfig();
1180
+ $fileName = basename($file);
1181
+ $sourceImage = NULL;
1182
+
1183
+ switch($type) {
1184
+ case "jpeg":
1185
+ case "jpg":
1186
+ case "pjpeg":
1187
+ $typePrefix = "jpeg";
1188
+ break;
1189
+ case "gif":
1190
+ $typePrefix = "gif";
1191
+ break;
1192
+ case "png":
1193
+ $typePrefix = "png";
1194
+ break;
1195
+ default:
1196
+ $typePrefix = NULL;
1197
+ break;
1198
+ }
1199
+ if ($typePrefix) {
1200
+ eval ('$sourceImage = imagecreatefrom'.$typePrefix.'($file);');
1201
+ if (function_exists("imagerotate")) {
1202
+ $rotatedImage = imagerotate($sourceImage,$rotation,0);
1203
+ }
1204
+ else {
1205
+ $rotatedImage = CustomImageRotate($sourceImage,$rotation);
1206
+ }
1207
+ eval ('image'.$typePrefix.'($rotatedImage,$file);');
1208
+ imagedestroy($sourceImage);
1209
+ @exec ('chmod 755 ' . escapeshellarg($file));
1210
+ }
1211
+ }
1212
+ /**
1213
+ * This function handles rotating in GD when you do not have imagerotate available
1214
+ * Writen byu wulff at fyens dot dk
1215
+ * From http://us2.php.net/manual/en/function.imagerotate.php#50487
1216
+ */
1217
+ // $src_img - a GD image resource
1218
+ // $angle - degrees to rotate clockwise, in degrees
1219
+ // returns a GD image resource
1220
+ // USAGE:
1221
+ // $im = imagecreatefrompng('test.png');
1222
+ // $im = imagerotate($im, 15);
1223
+ // header('Content-type: image/png');
1224
+ // imagepng($im);
1225
+ function CustomImageRotate($src_img, $angle, $bicubic=false) {
1226
+
1227
+ // convert degrees to radians
1228
+ $angle = $angle + 180;
1229
+ $angle = deg2rad($angle);
1230
+
1231
+ $src_x = imagesx($src_img);
1232
+ $src_y = imagesy($src_img);
1233
+
1234
+ $center_x = floor($src_x/2);
1235
+ $center_y = floor($src_y/2);
1236
+
1237
+ $cosangle = cos($angle);
1238
+ $sinangle = sin($angle);
1239
+
1240
+ $corners=array(array(0,0), array($src_x,0), array($src_x,$src_y), array(0,$src_y));
1241
+
1242
+ foreach($corners as $key=>$value) {
1243
+ $value[0]-=$center_x; //Translate coords to center for rotation
1244
+ $value[1]-=$center_y;
1245
+ $temp=array();
1246
+ $temp[0]=$value[0]*$cosangle+$value[1]*$sinangle;
1247
+ $temp[1]=$value[1]*$cosangle-$value[0]*$sinangle;
1248
+ $corners[$key]=$temp;
1249
+ }
1250
+
1251
+ $min_x=1000000000000000;
1252
+ $max_x=-1000000000000000;
1253
+ $min_y=1000000000000000;
1254
+ $max_y=-1000000000000000;
1255
+
1256
+ foreach($corners as $key => $value) {
1257
+ if($value[0]<$min_x)
1258
+ $min_x=$value[0];
1259
+ if($value[0]>$max_x)
1260
+ $max_x=$value[0];
1261
+
1262
+ if($value[1]<$min_y)
1263
+ $min_y=$value[1];
1264
+ if($value[1]>$max_y)
1265
+ $max_y=$value[1];
1266
+ }
1267
+
1268
+ $rotate_width=round($max_x-$min_x);
1269
+ $rotate_height=round($max_y-$min_y);
1270
+
1271
+ $rotate=imagecreatetruecolor($rotate_width,$rotate_height);
1272
+ imagealphablending($rotate, false);
1273
+ imagesavealpha($rotate, true);
1274
+
1275
+ //Reset center to center of our image
1276
+ $newcenter_x = ($rotate_width)/2;
1277
+ $newcenter_y = ($rotate_height)/2;
1278
+
1279
+ for ($y = 0; $y < ($rotate_height); $y++) {
1280
+ for ($x = 0; $x < ($rotate_width); $x++) {
1281
+ // rotate...
1282
+ $old_x = round((($newcenter_x-$x) * $cosangle + ($newcenter_y-$y) * $sinangle))
1283
+ + $center_x;
1284
+ $old_y = round((($newcenter_y-$y) * $cosangle - ($newcenter_x-$x) * $sinangle))
1285
+ + $center_y;
1286
+
1287
+ if ( $old_x >= 0 && $old_x < $src_x
1288
+ && $old_y >= 0 && $old_y < $src_y ) {
1289
+
1290
+ $color = imagecolorat($src_img, $old_x, $old_y);
1291
+ } else {
1292
+ // this line sets the background colour
1293
+ $color = imagecolorallocatealpha($src_img, 255, 255, 255, 127);
1294
+ }
1295
+ imagesetpixel($rotate, $x, $y, $color);
1296
+ }
1297
+ }
1298
+
1299
+ return($rotate);
1300
+ }
1301
+ function DetermineScale($width,$height, $max_width, $max_height) {
1302
+ if (!empty($max_width)) {
1303
+ return($max_width/$width);
1304
+ }
1305
+ else if (!empty($max_height)) {
1306
+ return($max_height/$height);
1307
+ }
1308
+ return(1);
1309
+ }
1310
+
1311
+ function ResizeImageWithImageMagick($file,$type) {
1312
+ //print("<h1>Using ImageMagick</h1>");
1313
+ $config = GetConfig();
1314
+ list($sizeInfo,$caption) = DetermineImageSize($file);
1315
+ $fileName = basename($file);
1316
+ $scaledFileName = "";
1317
+ $scale = DetermineScale($sizeInfo[0],$sizeInfo[1],$config["MAX_IMAGE_WIDTH"], $config["MAX_IMAGE_HEIGHT"]);
1318
+ if ($scale != 1) {
1319
+ $scaledH = round($sizeInfo[1] * $scale );
1320
+ $scaledW = round($sizeInfo[0] * $scale );
1321
+ $scaledFileName = "thumb.".$fileName;
1322
+ $scaledFile = $config["REALPHOTOSDIR"] . $scaledFileName;
1323
+ @exec (escapeshellcmd($config["IMAGEMAGICK_CONVERT"]) .
1324
+ " -resize " .
1325
+ $scaledW .
1326
+ "x" .
1327
+ $scaledH .
1328
+ " " .
1329
+ escapeshellarg($file) .
1330
+ " " .
1331
+ escapeshellarg($scaledFile) );
1332
+
1333
+ @exec ('chmod 755 ' . escapeshellarg($scaledFile));
1334
+ }
1335
+ return(array($scaledFileName,$fileName,$caption));
1336
+
1337
+ }
1338
+ function ResizeImageWithGD($file,$type) {
1339
+ $original_mem_limit = ini_get('memory_limit');
1340
+ ini_set('memory_limit', -1);
1341
+ $config = GetConfig();
1342
+ list($sizeInfo,$caption) = DetermineImageSize($file);
1343
+ $fileName = basename($file);
1344
+ $scaledFileName = "";
1345
+ $scale = DetermineScale($sizeInfo[0],$sizeInfo[1],$config["MAX_IMAGE_WIDTH"], $config["MAX_IMAGE_HEIGHT"]);
1346
+ if ($scale != 1) {
1347
+ echo "scale=$scale, width=". $sizeInfo[0] . "height=". $sizeInfo[1] . "\n<br />";
1348
+ $sourceImage = NULL;
1349
+ switch($type) {
1350
+ case "jpeg":
1351
+ case "jpg":
1352
+ case "pjpeg":
1353
+ $sourceImage = imagecreatefromjpeg($file);
1354
+ break;
1355
+ case "gif":
1356
+ $sourceImage = imagecreatefromgif($file);
1357
+ break;
1358
+ case "png":
1359
+ $sourceImage = imagecreatefrompng($file);
1360
+ break;
1361
+ }
1362
+ if ($sourceImage) {
1363
+ $scaledH = round($sizeInfo[1] * $scale );
1364
+ $scaledW = round($sizeInfo[0] * $scale );
1365
+ $scaledFileName = "thumb.".$fileName;
1366
+ $scaledFile = $config["REALPHOTOSDIR"] . $scaledFileName;
1367
+ $scaledImage = imagecreatetruecolor($scaledW,$scaledH);
1368
+ imagecopyresized($scaledImage,$sourceImage,0,0,0,0,
1369
+ $scaledW,$scaledH,
1370
+ $sizeInfo[0],$sizeInfo[1]);
1371
+ imagejpeg($scaledImage,$scaledFile,$config["JPEGQUALITY"]);
1372
+ @exec ('chmod 755 ' . escapeshellarg($scaledFile));
1373
+ imagedestroy($scaledImage);
1374
+ imagedestroy($sourceImage);
1375
+ }
1376
+ }
1377
+ // Revert to original limit
1378
+ ini_set('memory_limit', $original_mem_limit);
1379
+ echo "inside ResizeImageWithGD - scaledFileName=$scaledFileName\n";
1380
+ return(array($scaledFileName,$fileName,$caption));
1381
+
1382
+ }
1383
+ /**
1384
+ * Checks for the comments tag
1385
+ * @return boolean
1386
+ */
1387
+ function AllowCommentsOnPost(&$content) {
1388
+ $comments_allowed = get_option('default_comment_status');
1389
+ if (eregi("comments:([0|1|2])",$content,$matches)) {
1390
+ $content = ereg_replace("comments:$matches[1]","",$content);
1391
+ if ($matches[1] == "1") {
1392
+ $comments_allowed = "open";
1393
+ }
1394
+ else if ($matches[1] == "2") {
1395
+ $comments_allowed = "registered_only";
1396
+ }
1397
+ else {
1398
+ $comments_allowed = "closed";
1399
+ }
1400
+ }
1401
+ return($comments_allowed);
1402
+ }
1403
+ /**
1404
+ * This function figures out how much rotation should be applied to all images in the message
1405
+ */
1406
+ function GetRotation(&$mimeDecodedEmail,&$content) {
1407
+ $rotation = 0;
1408
+ if (eregi("rotate:([0-9]+)",$content,$matches)
1409
+ && trim($matches[1])) {
1410
+ $delay = (($days * 24 + $hours) * 60 + $minutes) * 60;
1411
+ $rotation = $matches[1];
1412
+ $content = ereg_replace("rotate:$matches[1]","",$content);
1413
+ }
1414
+ return($rotation);
1415
+ }
1416
+ /**
1417
+ * Needed to be able to modify the content to remove the usage of the delay tag
1418
+ */
1419
+ function DeterminePostDate(&$content, $message_date = NULL) {
1420
+ $config = GetConfig();
1421
+ $delay = 0;
1422
+ echo "inside Determine Post Date, message_date = $message_date\n";
1423
+ if (eregi("delay:(-?[0-9dhm]+)",$content,$matches)
1424
+ && trim($matches[1])) {
1425
+ if (eregi("(-?[0-9]+)d",$matches[1],$dayMatches)) {
1426
+ $days = $dayMatches[1];
1427
+ }
1428
+ if (eregi("(-?[0-9]+)h",$matches[1],$hourMatches)) {
1429
+ $hours = $hourMatches[1];
1430
+ }
1431
+ if (eregi("(-?[0-9]+)m",$matches[1],$minuteMatches)) {
1432
+ $minutes = $minuteMatches[1];
1433
+ }
1434
+ $delay = (($days * 24 + $hours) * 60 + $minutes) * 60;
1435
+ $content = ereg_replace("delay:$matches[1]","",$content);
1436
+ }
1437
+ if (!empty($message_date) && $delay==0) {
1438
+ $dateInSeconds = strtotime($message_date);
1439
+ }
1440
+ else {
1441
+ $dateInSeconds = time() + $delay;
1442
+ }
1443
+ $post_date = gmdate('Y-m-d H:i:s',$dateInSeconds + ($config["TIME_OFFSET"] * 3600));
1444
+ $post_date_gmt = gmdate('Y-m-d H:i:s',$dateInSeconds);
1445
+
1446
+ echo "--------------------DELAY------------\n";
1447
+ echo "delay=$delay, dateInSeconds = $dateInSeconds\n";
1448
+ echo "post_date=$post_date\n";
1449
+ echo "--------------------DELAY------------\n";
1450
+ return(array($post_date,$post_date_gmt));
1451
+ }
1452
+ /**
1453
+ * This function takes the content of the message - looks for a subject at the begining surrounded by # and then removes that from the content
1454
+ */
1455
+ function ParseInMessageSubject($content) {
1456
+ $config = GetConfig();
1457
+ if (substr($content,0,1) != "#") {
1458
+ //print("<p>Didn't start with # '".substr(ltrim($content),0,10)."'");
1459
+ return(array($config["DEFAULT_TITLE"],$content));
1460
+ }
1461
+ $subjectEndIndex = strpos($content,"#",1);
1462
+ if (!$subjectEndIndex > 0) {
1463
+ return(array($config["DEFAULT_TITLE"],$content));
1464
+ }
1465
+ $subject = substr($content,1,$subjectEndIndex - 1);
1466
+ $content = substr($content,$subjectEndIndex + 1,strlen($content));
1467
+ return(array($subject,$content));
1468
+ }
1469
+ /**
1470
+ * This method sorts thru the mime parts of the message. It is looking for files labeled - "applefile" - current
1471
+ * this part of the file attachment is not supported
1472
+ *@param object
1473
+ */
1474
+ function FilterAppleFile(&$mimeDecodedEmail) {
1475
+ $newParts = array();
1476
+ $found = false;
1477
+ for ($i = 0; $i < count($mimeDecodedEmail->parts); $i++) {
1478
+ if ($mimeDecodedEmail->parts[$i]->ctype_secondary == "applefile") {
1479
+ $found = true;
1480
+ }
1481
+ else {
1482
+ $newParts[] = &$mimeDecodedEmail->parts[$i];
1483
+ }
1484
+ }
1485
+ if ($found && $newParts) {
1486
+ $mimeDecodedEmail->parts = $newParts; //This is now the filtered list of just the preferred type.
1487
+ }
1488
+ }
1489
+ /**
1490
+ * Searches for the existance of a certain MIME TYPE in the tree of mime attachments
1491
+ * @param primary mime
1492
+ * @param secondary mime
1493
+ * @return boolean
1494
+ */
1495
+ function SearchForMIMEType($part,$primary,$secondary) {
1496
+ if ($part->ctype_primary == $primary && $part->ctype_secondary == $secondary) {
1497
+ return true;
1498
+ }
1499
+ if ($part->ctype_primary == "multipart") {
1500
+ for ($i = 0; $i < count($part->parts); $i++) {
1501
+ if (SearchForMIMEType($part->parts[$i], $primary,$secondary)) {
1502
+ return true;
1503
+ }
1504
+ }
1505
+ }
1506
+ return false;
1507
+ }
1508
+ /**
1509
+ * This method sorts thru the mime parts of the message. It is looking for a certain type of text attachment. If
1510
+ * that type is present it filters out all other text types. If it is not - then nothing is done
1511
+ *@param object
1512
+ */
1513
+ function FilterTextParts(&$mimeDecodedEmail) {
1514
+ $config = GetConfig();
1515
+ $newParts = array();
1516
+ $found = false;
1517
+ for ($i = 0; $i < count($mimeDecodedEmail->parts); $i++) {
1518
+ if (in_array($mimeDecodedEmail->parts[$i]->ctype_primary,array("text","multipart"))) {
1519
+ if (SearchForMIMEType($mimeDecodedEmail->parts[$i],"text",$config["PREFER_TEXT_TYPE"])) {
1520
+ $newParts[] = &$mimeDecodedEmail->parts[$i];
1521
+ $found = true;
1522
+ }
1523
+ }
1524
+ else {
1525
+ $newParts[] = &$mimeDecodedEmail->parts[$i];
1526
+ }
1527
+ }
1528
+ if ($found && $newParts) {
1529
+ $mimeDecodedEmail->parts = $newParts; //This is now the filtered list of just the preferred type.
1530
+ }
1531
+ }
1532
+ /**
1533
+ *This forwards on the mail to the admin for review
1534
+ *It execpts an object containing the entire message
1535
+ */
1536
+ function ForwardRejectedMailToAdmin( &$mail_content) {
1537
+ $config = GetConfig();
1538
+ if ($config["TEST_EMAIL"]) {
1539
+ return;
1540
+ }
1541
+ $user = get_userdata('1');
1542
+ $myname = $user->user_nicename;
1543
+ $myemailadd = get_option("admin_email");
1544
+ $blogname = get_option("blogname");
1545
+ $recipients = $myemailadd;
1546
+ if (count($recipients) == 0) {
1547
+ return false;
1548
+ }
1549
+
1550
+ $from = trim($mail_content->headers["from"]);
1551
+ $subject = $mail_content->headers['subject'];
1552
+
1553
+ // Set email subject
1554
+ $alert_subject = $blogname . ": Unauthorized Post Attempt";
1555
+
1556
+ // Set sender details
1557
+ $headers = "From: " .$from ."\r\n";
1558
+ if (isset($mail_content->headers["mime-version"])) {
1559
+ $headers .= "Mime-Version: ". $mail_content->headers["mime-version"] . "\r\n";
1560
+ }
1561
+ if (isset($mail_content->headers["content-type"])) {
1562
+ $headers .= "Content-Type: ". $mail_content->headers["content-type"] . "\r\n";
1563
+ }
1564
+
1565
+ // SDM 20041123
1566
+ foreach ($recipients as $recipient) {
1567
+ $recipient = trim($recipient);
1568
+ if (! empty($recipient)) {
1569
+ $headers .= "Bcc: " . $recipient . "\r\n";
1570
+ }
1571
+ }
1572
+
1573
+ // construct mail message
1574
+ $message = "An unauthorized message has been sent to " . $blogname . " from " . $from. ". The subject of this message was: '" . $subject . "'.";
1575
+ $message .= "\n\nIf you wish to allow posts from this address, please add " . $from. " to the registered users list and manually add the content of the e-mail found below.";
1576
+ $message .= "\n\nOtherwise, the e-mail has already been deleted from the server and you can ignore this message.";
1577
+ $message .= "\n\nIf you would like to prevent wp-mail from forwarding mail in the future, please change FORWARD_REJECTED_MAIL to false in wp-mail.php.";
1578
+ $message .= "\n\nThe original content of the e-mail has been attached.\n\n";
1579
+ $boundary = "--".$mail_content->ctype_parameters["boundary"] ."\n";
1580
+
1581
+ $mailtext = $boundary;
1582
+ $mailtext .= "Content-Type: text/plain;format=flowed;charset=\"iso-8859-1\";reply-type=original\n";
1583
+ $mailtext .= "Content-Transfer-Encoding: 7bit\n";
1584
+ $mailtext .= "\n";
1585
+ $mailtext .= $message;
1586
+ foreach ($mail_content->parts as $part) {
1587
+ $mailtext .= $boundary;
1588
+ $mailtext .= "Content-Type: ".$part->headers["content-type"] . "\n";
1589
+ $mailtext .= "Content-Transfer-Encoding: ".$part->headers["content-transfer-encoding"] . "\n";
1590
+ if (isset($part->headers["content-disposition"])) {
1591
+ $mailtext .= "Content-Disposition: ".$part->headers["content-disposition"] . "\n";
1592
+ }
1593
+ $mailtext .= "\n";
1594
+ $mailtext .= $part->body;
1595
+ }
1596
+
1597
+ // Send message
1598
+ mail($myemailadd, $alert_subject, $mailtext, $headers);
1599
+
1600
+ return true;
1601
+ }
1602
+ /**
1603
+ * This function handles the basic mime decoding
1604
+ * @param string
1605
+ * @return array
1606
+ */
1607
+ function DecodeMIMEMail($email) {
1608
+ $params = array();
1609
+ $params['include_bodies'] = true;
1610
+ $params['decode_bodies'] = false;
1611
+ $params['decode_headers'] = true;
1612
+ $params['input'] = $email;
1613
+ return(Mail_mimeDecode::decode($params));
1614
+ }
1615
+
1616
+ /**
1617
+ * This is used for debugging the mimeDecodedEmail of the mail
1618
+ */
1619
+ function DisplayMIMEPartTypes($mimeDecodedEmail) {
1620
+ foreach($mimeDecodedEmail->parts as $part) {
1621
+ print("<p>".$part->ctype_primary . " / ".$part->ctype_secondary . "/ ".$part->headers['content-transfer-encoding'] ."\n");
1622
+ }
1623
+ }
1624
+
1625
+ /**
1626
+ * This compares the current address to the list of authorized addresses
1627
+ * @param string - email address
1628
+ * @return boolean
1629
+ */
1630
+ function CheckEmailAddress($address) {
1631
+ $config = GetConfig();
1632
+ $address = strtolower($address);
1633
+ if (!is_array($config["AUTHORIZED_ADDRESSES"])
1634
+ || !count($config["AUTHORIZED_ADDRESSES"])) {
1635
+ return false;
1636
+ }
1637
+ return(in_array($address,$config["AUTHORIZED_ADDRESSES"]));
1638
+ }
1639
+ /**
1640
+ *This method works around a problemw with email address with extra <> in the email address
1641
+ * @param string
1642
+ * @return string
1643
+ */
1644
+ function RemoveExtraCharactersInEmailAddress($address) {
1645
+ $matches = array();
1646
+ if (preg_match('/^[^<>]+<([^<> ()]+)>$/',$address,$matches)) {
1647
+ $address = $matches[1];
1648
+ }
1649
+ else if (preg_match('/<([^<> ()]+)>/',$address,$matches)) {
1650
+ $address = $matches[1];
1651
+ }
1652
+
1653
+ return($address);
1654
+ }
1655
+
1656
+ /**
1657
+ * This function gleans the name from the 'from:' header if available. If not
1658
+ * it just returns the username (everything before @)
1659
+ */
1660
+ function GetNameFromEmail($address) {
1661
+ $matches = array();
1662
+ if (preg_match('/^([^<>]+)<([^<> ()]+)>$/',$address,$matches)) {
1663
+ $name = $matches[1];
1664
+ }
1665
+ else if (preg_match('/<([^<>@ ()]+)>/',$address,$matches)) {
1666
+ $name = $matches[1];
1667
+ }
1668
+
1669
+ return($name);
1670
+ }
1671
+
1672
+ /**
1673
+ * When sending in HTML email the html refers to the content-id(CID) of the image - this replaces
1674
+ * the cid place holder with the actual url of the image sent in
1675
+ * @param string - text of post
1676
+ * @param array - array of HTML for images for post
1677
+ */
1678
+ function ReplaceImageCIDs(&$content,&$attachments) {
1679
+ $used = array();
1680
+ foreach ($attachments["cids"] as $key => $info) {
1681
+ $pattern = "/cid:$key/";
1682
+ if(preg_match($pattern,$content)) {
1683
+ $content = preg_replace($pattern,$info[0],$content);
1684
+ $used[] = $info[1]; //Index of html to ignore
1685
+ }
1686
+ }
1687
+ $html = array();
1688
+ for ($i = 0; $i < count($attachments["html"]); $i++) {
1689
+ if (!in_array($i,$used)) {
1690
+ $html[] = $attachments["html"][$i];
1691
+ }
1692
+ }
1693
+ $attachments["html"] = $html;
1694
+
1695
+ }
1696
+ /**
1697
+ * This function handles replacing image place holder #img1# with the HTML for that image
1698
+ * @param string - text of post
1699
+ * @param array - array of HTML for images for post
1700
+ */
1701
+ function ReplaceImagePlaceHolders(&$content,$attachments) {
1702
+ $config = GetConfig();
1703
+ ($config["START_IMAGE_COUNT_AT_ZERO"] ? $startIndex = 0 :$startIndex = 1);
1704
+ foreach ( $attachments as $i => $value ) {
1705
+ // looks for ' #img1# ' etc... and replaces with image
1706
+ $img_placeholder_temp = str_replace("%", intval($startIndex + $i), $config["IMAGE_PLACEHOLDER"]);
1707
+ $img_placeholder_temp=rtrim($img_placeholder_temp,'#');
1708
+ echo "------------- IMG REPLACEMENT ----------------------\n";
1709
+ echo "<pre>value=$value</pre>\n\n";
1710
+ echo "img_placeholder_temp=$img_placeholder_temp\n";
1711
+ if ( stristr($content, $img_placeholder_temp) ) {
1712
+ // look for caption
1713
+ if ( preg_match("/caption=['\"](.*)['\"]/", $content, $matches)) {
1714
+ $caption =$matches[1];
1715
+ $value = str_replace('{CAPTION}', $caption, $value);
1716
+ echo "caption=$caption----\n";
1717
+ $img_placeholder_temp.=' ' . $matches[0];
1718
+ }
1719
+ $img_placeholder_temp.='#';
1720
+ echo "img_placeholder_temp=$img_placeholder_temp\n";
1721
+ $content = str_replace($img_placeholder_temp, $value, $content);
1722
+ } else {
1723
+ if ($config["IMAGES_APPEND"]) {
1724
+ $content .= $value;
1725
+ } else {
1726
+ $content = $value . $content;
1727
+ }
1728
+ }
1729
+ }
1730
+ }
1731
+ /**
1732
+ *This function handles finding and setting the correct subject
1733
+ * @return array - (subject,content)
1734
+ */
1735
+ function GetSubject(&$mimeDecodedEmail,&$content) {
1736
+ $config = GetConfig();
1737
+ //assign the default title/subject
1738
+ if ( $mimeDecodedEmail->headers['subject'] == NULL ) {
1739
+ if ($config["ALLOW_SUBJECT_IN_MAIL"]) {
1740
+ list($subject,$content) = ParseInMessageSubject($content);
1741
+ }
1742
+ else {
1743
+ $subject = $config["DEFAULT_TITLE"];
1744
+ }
1745
+ $mimeDecodedEmail->headers['subject'] = $subject;
1746
+ } else {
1747
+ $subject = $mimeDecodedEmail->headers['subject'];
1748
+ HandleMessageEncoding($mimeDecodedEmail->headers["content-transfer-encoding"],
1749
+ $mimeDecodedEmail->ctype_parameters["charset"],
1750
+ $subject);
1751
+ if (!$config["ALLOW_HTML_IN_SUBJECT"]) {
1752
+ $subject = htmlentities($subject);
1753
+ }
1754
+ }
1755
+ //This is for ISO-2022-JP - Can anyone confirm that this is still neeeded?
1756
+ // escape sequence is 'ESC $ B' == 1b 24 42 hex.
1757
+ if (strpos($subject, "\x1b\x24\x42") !== false) {
1758
+ // found iso-2022-jp escape sequence in subject... convert!
1759
+ $subject = iconv("ISO-2022-JP//TRANSLIT", "UTF-8", $subject);
1760
+ }
1761
+ return($subject);
1762
+ }
1763
+ /**
1764
+ * this function determines tags for the post
1765
+ *
1766
+ */
1767
+ function GetPostTags(&$content) {
1768
+ $config = GetConfig();
1769
+ global $wpdb;
1770
+ $post_tags = array();
1771
+ //try and determine tags
1772
+ if ( preg_match('/tags: (.*)\n/', $content, $matches)) {
1773
+ $content = preg_replace("/$matches[0]/", "", $content);
1774
+ $post_tags = preg_split("/,\s*/", $matches[1]);
1775
+ }
1776
+ if (!count($post_tags)) {
1777
+ echo "using default tags" . $config["DEFAULT_POST_TAGS"]. "\n";
1778
+ $post_tags = $config["DEFAULT_POST_TAGS"];
1779
+ }
1780
+ return($post_tags);
1781
+ }
1782
+ /**
1783
+ * This function determines categories for the post
1784
+ * @return array
1785
+ */
1786
+ function GetPostCategories(&$subject) {
1787
+ $config = GetConfig();
1788
+ global $wpdb;
1789
+ $post_categories = array();
1790
+ $matches = array();
1791
+ //try and determine category
1792
+ if ( preg_match('/(.+): (.*)/', $subject, $matches)) {
1793
+ $subject = trim($matches[2]);
1794
+ $matches[1] = array($matches[1]);
1795
+ }
1796
+ else if (preg_match_all('/\[(.[^\[]*)\]/', $subject, $matches)) {
1797
+ preg_match("/](.[^\[]*)$/",$subject,$subject_matches);
1798
+ $subject = trim($subject_matches[1]);
1799
+ }
1800
+ else if ( preg_match_all('/-(.[^-]*)-/', $subject, $matches) ) {
1801
+ preg_match("/-(.[^-]*)$/",$subject,$subject_matches);
1802
+ $subject = trim($subject_matches[1]);
1803
+ }
1804
+ if (count($matches)) {
1805
+ foreach($matches[1] as $match) {
1806
+ $match = trim($match);
1807
+ $category = NULL;
1808
+ print("Working on $match\n");
1809
+
1810
+ $sql_name = 'SELECT term_id
1811
+ FROM ' . $wpdb->terms. '
1812
+ WHERE name=\'' . addslashes($match) . '\'';
1813
+ $sql_id = 'SELECT term_id
1814
+ FROM ' . $wpdb->terms. '
1815
+ WHERE term_id=\'' . addslashes($match) . '\'';
1816
+ $sql_sub_name = 'SELECT term_id
1817
+ FROM ' . $wpdb->terms. '
1818
+ WHERE name LIKE \'' . addslashes($match) . '%\' limit 1';
1819
+
1820
+ if ( $category = $wpdb->get_var($sql_name) ) {
1821
+ //then category is a named and found
1822
+ } elseif ( $category = $wpdb->get_var($sql_id) ) {
1823
+ //then cateogry was an ID and found
1824
+ } elseif ( $category = $wpdb->get_var($sql_sub_name) ) {
1825
+ //then cateogry is a start of a name and found
1826
+ }
1827
+ if ($category) {
1828
+ $post_categories[] = $category;
1829
+ }
1830
+ }
1831
+ }
1832
+ if (!count($post_categories)) {
1833
+ echo "using default category" . $config["DEFAULT_POST_CATEGORY"]. "\n";
1834
+ $post_categories[] = $config["DEFAULT_POST_CATEGORY"];
1835
+ }
1836
+ return($post_categories);
1837
+ }
1838
+ /**
1839
+ *This function just outputs a simple html report about what is being posted in
1840
+ */
1841
+ function DisplayEmailPost($details) {
1842
+ $config = GetConfig();
1843
+ print_r($config);
1844
+ print_r($details);
1845
+ $theFinalContent=$details['post_content'];
1846
+ echo "-----------the final content is:\n '$theFinalContent'\n";
1847
+ // Report
1848
+ print '</pre><p><b>Post Author</b>: ' . $details["post_author"]. '<br />' . "\n";
1849
+ print '<b>Date</b>: ' . $details["post_date"] . '<br />' . "\n";
1850
+ print '<b>Date GMT</b>: ' . $details["post_date_gmt"] . '<br />' . "\n";
1851
+ foreach($details["post_category"] as $category) {
1852
+ print '<b>Category</b>: ' . $category . '<br />' . "\n";
1853
+ }
1854
+ print '<b>Ping Status</b>: ' . $details["ping_status"] . '<br />' . "\n";
1855
+ print '<b>Comment Status</b>: ' . $details["comment_status"] . '<br />' . "\n";
1856
+ print '<b>Subject</b>: ' . $details["post_title"]. '<br />' . "\n";
1857
+ print '<b>Postname</b>: ' . $details["post_name"] . '<br />' . "\n";
1858
+ print '<b>Posted content:</b></p><hr />' . $details["post_content"] . '<hr /><pre>';
1859
+ }
1860
+ /**
1861
+ * This function confirms that everything is setup correctly
1862
+ */
1863
+ function TestWPMailInstallation() {
1864
+ $config = GetConfig();
1865
+ IsWritableDirectory($config["REALPHOTOSDIR"]);
1866
+ IsWritableDirectory($config["REALFILESDIR"]);
1867
+ if (!TestPostieDirectory) {
1868
+ print("<p>Postie should be in its own directory in wp-content/plugins/postie</p>");
1869
+ }
1870
+ }
1871
+ /**
1872
+ * Takes a value and builds a simple simple yes/no select box
1873
+ * @param string
1874
+ * @param string
1875
+ * @param string
1876
+ * @param string
1877
+ */
1878
+ function BuildBooleanSelect($label,$id,$current_value,$recommendation = NULL) {
1879
+ $string="<tr>
1880
+ <th scope=\"row\">". __($label).":</th>
1881
+ <td><select name=\"$id\" id=\"$id\">
1882
+ <option value=\"1\">".__("Yes")."</option>
1883
+ <option value=\"0\" ". (!$current_value ? "SELECTED" : NULL) . ">".__("No").'</option>
1884
+ </select>
1885
+ <br />';
1886
+ if ($recommendation!=NULL) {
1887
+ $string.='<code>'.__($recommendation).'</code><br/>';
1888
+ }
1889
+ $string.="</td>\n</tr>";
1890
+ return($string);
1891
+ }
1892
+ /**
1893
+ * This takes an array and display a text box for editing
1894
+ *@param string
1895
+ *@param string
1896
+ *@param array
1897
+ *@param string
1898
+ */
1899
+ function BuildTextArea($label,$id,$current_value,$recommendation = NULL) {
1900
+ $string = "<tr>
1901
+ <th scope=\"row\">".__($label).":</th></tr>";
1902
+
1903
+ if ($recommendation) {
1904
+ $string .= "<tr><td>&nbsp;</td><td><code>".__($recommendation)."</code></td></tr>";
1905
+ }
1906
+ $string .=" <tr>
1907
+ <td>&nbsp;</td>
1908
+ <td><textarea cols=40 rows=5 name=\"$id\" id=\"$id\">";
1909
+ if (is_array($current_value)) {
1910
+ foreach($current_value as $item) {
1911
+ $string .= "$item\n";
1912
+ }
1913
+ }
1914
+ $string .= "</textarea></td>
1915
+ </tr>";
1916
+ return($string);
1917
+ }
1918
+ /**
1919
+ *Handles the creation of the table needed to store all the data
1920
+ */
1921
+ function SetupConfiguration() {
1922
+ if (! function_exists('maybe_create_table')) {
1923
+ require_once(ABSPATH . DIRECTORY_SEPARATOR. 'wp-admin'.DIRECTORY_SEPARATOR.'upgrade-functions.php');
1924
+ }
1925
+ $create_table_sql = "CREATE TABLE ".POSTIE_TABLE ." (
1926
+ label text NOT NULL,
1927
+ value text not NULL
1928
+ );";
1929
+
1930
+ maybe_create_table(POSTIE_TABLE,$create_table_sql);
1931
+ }
1932
+ /**
1933
+ *This function resets all the configuration options to the default
1934
+ */
1935
+ function ResetPostieConfig() {
1936
+ global $wpdb;
1937
+ //Get rid of the old table
1938
+ $wpdb->query("DROP TABLE ". POSTIE_TABLE .";");
1939
+ $config = GetConfig();
1940
+ $key_arrays = GetListOfArrayConfig();
1941
+ foreach($key_arrays as $key) {
1942
+ $config[$key] = join("\n",$config[$key]);
1943
+ }
1944
+ UpdatePostieConfig($config);
1945
+ }
1946
+ /**
1947
+ * This function handles updating the configuration
1948
+ *@return boolean
1949
+ */
1950
+ function UpdatePostieConfig($data) {
1951
+ SetupConfiguration();
1952
+ $key_arrays = GetListOfArrayConfig();
1953
+ $config = GetDBConfig();
1954
+ foreach($config as $key => $value) {
1955
+ if (isset($data[$key])) {
1956
+ if (in_array($key,$key_arrays)) { //This is stored as an array
1957
+ $config[$key] = array();
1958
+ $values = explode("\n",$data[$key]);
1959
+ foreach($values as $item) {
1960
+ if (trim($item)) {
1961
+ $config[$key][] = trim($item);
1962
+ }
1963
+ }
1964
+ }
1965
+ else {
1966
+ $config[$key] = $data[$key];
1967
+ }
1968
+ }
1969
+ }
1970
+ WriteConfig($config);
1971
+ UpdatePostiePermissions($data["ROLE_ACCESS"]);
1972
+ return(1);
1973
+ }
1974
+ /**
1975
+ * This handles actually writing out the changes
1976
+ *@param array
1977
+ */
1978
+ function WriteConfig($config) {
1979
+ global $wpdb;
1980
+ foreach($config as $key=>$value) {
1981
+ $label = apply_filters('content_save_pre', $key);
1982
+ $q = $wpdb->query("DELETE FROM ". POSTIE_TABLE . " WHERE label = '$label';");
1983
+ if (!is_array($value)) {
1984
+ $q = $wpdb->query("INSERT INTO ". POSTIE_TABLE . " (label,value) VALUES ('$label','".apply_filters('content_save_pre', $value)."');");
1985
+ }
1986
+ else {
1987
+ foreach($value as $item) {
1988
+ $q = $wpdb->query("INSERT INTO ". POSTIE_TABLE . " (label,value) VALUES ('$label','".apply_filters('content_save_pre', $item)."');");
1989
+ }
1990
+ }
1991
+ }
1992
+ }
1993
+ /**
1994
+ *This handles actually reading the config from the database
1995
+ * @return array
1996
+ */
1997
+ function ReadDBConfig() {
1998
+ SetupConfiguration();
1999
+ $config = array();
2000
+ global $wpdb;
2001
+ $data = $wpdb->get_results("SELECT label,value FROM ". POSTIE_TABLE .";");
2002
+ if (is_array($data)) {
2003
+ foreach($data as $row) {
2004
+ if (in_array($row->label,GetListOfArrayConfig())) {
2005
+ if (!is_array($config[$row->label])) {
2006
+ $config[$row->label] = array();
2007
+ }
2008
+ $config[$row->label][] = $row->value;
2009
+ }
2010
+ else {
2011
+ $config[$row->label] = $row->value;
2012
+ }
2013
+ }
2014
+ }
2015
+
2016
+ return($config);
2017
+ }
2018
+ /**
2019
+ * This handles the configs that are stored in the data base
2020
+ * You should never call this outside of the library
2021
+ * @return array
2022
+ * @access private
2023
+ */
2024
+ function GetDBConfig() {
2025
+ $config = ReadDBConfig();
2026
+ if (!isset($config["PHOTOSDIR"])) { $config["PHOTOSDIR"] = DIRECTORY_SEPARATOR."wp-photos".DIRECTORY_SEPARATOR;}
2027
+ if (!isset($config["ADMIN_USERNAME"])) { $config["ADMIN_USERNAME"] =
2028
+ 'admin'; }
2029
+ if (!isset($config["FILESDIR"])) { $config["FILESDIR"] = DIRECTORY_SEPARATOR."wp-filez".DIRECTORY_SEPARATOR;}
2030
+ if (!isset($config["PREFER_TEXT_TYPE"])) { $config["PREFER_TEXT_TYPE"] = "plain";}
2031
+ if (!isset($config["RESIZE_LARGE_IMAGES"])) { $config["RESIZE_LARGE_IMAGES"] = true;}
2032
+ if (!isset($config["MAX_IMAGE_WIDTH"])) { $config["MAX_IMAGE_WIDTH"] = 400;}
2033
+ if (!isset($config["MAX_IMAGE_HEIGHT"])) { $config["MAX_IMAGE_HEIGHT"] = "";}
2034
+ if (!isset($config["DEFAULT_TITLE"])) { $config["DEFAULT_TITLE"] = "Live From The Field";}
2035
+ if (!isset($config["INPUT_PROTOCOL"])) { $config["INPUT_PROTOCOL"] = "pop3";}
2036
+ if (!isset($config["IMAGE_PLACEHOLDER"])) { $config["IMAGE_PLACEHOLDER"] = "#img%#";}
2037
+ if (!isset($config["IMAGES_APPEND"])) { $config["IMAGES_APPEND"] = true;}
2038
+ if (!isset($config["IMAGECLASS"])) { $config["IMAGECLASS"] = "postie-image";}
2039
+ if (!isset($config["IMAGEDIV"])) { $config["IMAGEDIV"] = "postie-image-div";}
2040
+ if (!isset($config["3GPDIV"])) { $config["3GPDIV"] = "postie-3gp-div";}
2041
+ if (!isset($config["ATTACHMENTDIV"])) { $config["ATTACHMENTDIV"] = "postie-attachment-div";}
2042
+ if (!isset($config["3GPCLASS"])) { $config["3GPCLASS"] = "postie-video";}
2043
+ if (!isset($config["IMAGESTYLE"])) { $config["IMAGESTYLE"] = "border: none;";}
2044
+ if (!isset($config["JPEGQUALITY"])) { $config["JPEGQUALITY"] = 80;}
2045
+ if (!isset($config["AUTO_SMART_SHARP"])) { $config["AUTO_SMART_SHARP"] = false;}
2046
+ if (!isset($config["ALLOW_SUBJECT_IN_MAIL"])) { $config["ALLOW_SUBJECT_IN_MAIL"] = true;}
2047
+ if (!isset($config["DROP_SIGNATURE"])) { $config["DROP_SIGNATURE"] = true;}
2048
+ if (!isset($config["MESSAGE_START"])) { $config["MESSAGE_START"] = ":start";}
2049
+ if (!isset($config["MESSAGE_END"])) { $config["MESSAGE_END"] = ":end";}
2050
+ if (!isset($config["FORWARD_REJECTED_MAIL"])) { $config["FORWARD_REJECTED_MAIL"] = true;}
2051
+ if (!isset($config["ALLOW_HTML_IN_SUBJECT"])) { $config["ALLOW_HTML_IN_SUBJECT"] = true;}
2052
+ if (!isset($config["ALLOW_HTML_IN_BODY"])) { $config["ALLOW_HTML_IN_BODY"] = true;}
2053
+ if (!isset($config["START_IMAGE_COUNT_AT_ZERO"])) { $config["START_IMAGE_COUNT_AT_ZERO"] = false;}
2054
+ if (!isset($config["MESSAGE_ENCODING"])) { $config["MESSAGE_ENCODING"] = "UTF-8"; }
2055
+ if (!isset($config["MESSAGE_DEQUOTE"])) { $config["MESSAGE_DEQUOTE"] = true; }
2056
+ if (!isset($config["TURN_AUTHORIZATION_OFF"])) { $config["TURN_AUTHORIZATION_OFF"] = false;}
2057
+ if (!isset($config["USE_IMAGEMAGICK"])) { $config["USE_IMAGEMAGICK"] = false;}
2058
+ if (!isset($config["CONVERTNEWLINE"])) { $config["CONVERTNEWLINE"] = false;}
2059
+ if (!isset($config["IMAGEMAGICK_CONVERT"])) { $config["IMAGEMAGICK_CONVERT"] = "/usr/bin/convert";}
2060
+ if (!isset($config["IMAGEMAGICK_IDENTIFY"])) { $config["IMAGEMAGICK_IDENTIFY"] = "/usr/bin/identify";}
2061
+
2062
+
2063
+ if (!isset($config["SIG_PATTERN_LIST"])) { $config["SIG_PATTERN_LIST"] = array('--','- --',"\?--");}
2064
+ if (!isset($config["BANNED_FILES_LIST"])) { $config["BANNED_FILES_LIST"] = array();}
2065
+ if (!isset($config["SUPPORTED_FILE_TYPES"])) { $config["SUPPORTED_FILE_TYPES"] = array("video","application");}
2066
+ if (!isset($config["AUTHORIZED_ADDRESSES"])) { $config["AUTHORIZED_ADDRESSES"] = array();}
2067
+ if (!isset($config["MAIL_SERVER"])) { $config["MAIL_SERVER"] = NULL; }
2068
+ if (!isset($config["MAIL_SERVER_PORT"])) { $config["MAIL_SERVER_PORT"] = NULL; }
2069
+ if (!isset($config["MAIL_USERID"])) { $config["MAIL_USERID"] = NULL; }
2070
+ if (!isset($config["MAIL_PASSWORD"])) { $config["MAIL_PASSWORD"] = NULL; }
2071
+ if (!isset($config["DEFAULT_POST_CATEGORY"])) { $config["DEFAULT_POST_CATEGORY"] = NULL; }
2072
+ if (!isset($config["DEFAULT_POST_TAGS"])) { $config["DEFAULT_POST_TAGS"] = NULL; }
2073
+ if (!isset($config["TIME_OFFSET"])) { $config["TIME_OFFSET"] = get_option('gmt_offset'); }
2074
+ if (!isset($config["3GP_QT"])) { $config["3GP_QT"] = true; }
2075
+ if (!isset($config["3GP_FFMPEG"])) { $config["3GP_FFMPEG"] = "/usr/bin/ffmpeg";}
2076
+ if (!isset($config["WRAP_PRE"])) { $config["WRAP_PRE"] = 'no'; }
2077
+ if (!isset($config["ADD_META"])) { $config["ADD_META"] = 'no'; }
2078
+ if (!isset($config["USEIMAGETEMPLATE"])) { $config["USEIMAGETEMPLATE"] =
2079
+ false; }
2080
+ if (!isset($config["POST_STATUS"])) { $config["POST_STATUS"] =
2081
+ 'publish'; }
2082
+ if (!isset($config["IMAGE_NEW_WINDOW"])) { $config["IMAGE_NEW_WINDOW"] =
2083
+ false; }
2084
+ if (!isset($config["IMAGETEMPLATE"])) { $config["IMAGETEMPLATE"] =
2085
+
2086
+ $mimeTag."<div class='" . '{CONFIG-IMAGEDIV}'."'><a
2087
+ href='" . 'CONFIG-URLPHOTOSDIR' . '{IMAGE}' . "'
2088
+ onclick=\"window.open(' . '"
2089
+ . 'CONFIG-URLPHOTOSDIR' . '{IMAGE}' . '","'
2090
+ . "full_size_image" . "','"
2091
+ . "toolbar=0,scrollbars=0,location=0,status=0,menubar=0,resizable=1,height=" . $marimey . ",width=" . $marimex . "');" . "return false;"
2092
+ . '"><img src="' . 'CONFIG-URLPHOTOSDIR' .
2093
+ '{THUMBNAIL}'. '" alt="'
2094
+ . $part->ctype_parameters['name'] . '" title="' .
2095
+ $part->ctype_parameters['name'] . '"
2096
+ style="'.'CONFIG-IMAGESTYLE'.'" class="'.'CONFIG-IMAGECLASS'.'" /></a></div>' . "\n";
2097
+ }
2098
+ return($config);
2099
+ }
2100
+ /**
2101
+ * This function handles building up the configuration array for the program
2102
+ * @return array
2103
+ */
2104
+ function GetConfig() {
2105
+ $config = GetDBConfig();
2106
+ if (!ConfirmTrailingDirectorySeperator($config["PHOTOSDIR"])) {
2107
+ $config["PHOTOSDIR"] .= DIRECTORY_SEPARATOR;
2108
+ }
2109
+ if (!ConfirmTrailingDirectorySeperator($config["FILESDIR"])) {
2110
+ $config["FILESDIR"] .= DIRECTORY_SEPARATOR;
2111
+ }
2112
+ //These should only be modified if you are testing
2113
+ $config["DELETE_MAIL_AFTER_PROCESSING"] = true;
2114
+ $config["POST_TO_DB"] = true;
2115
+ $config["TEST_EMAIL"] = false;
2116
+ $config["TEST_EMAIL_ACCOUNT"] = "blog.test";
2117
+ $config["TEST_EMAIL_PASSWORD"] = "";
2118
+ //include(POSTIE_ROOT . "/../postie-test.php");
2119
+ // These are computed
2120
+ #$config["TIME_OFFSET"] = get_option('gmt_offset');
2121
+ if ($config["USE_IMAGEMAGICK"]) {
2122
+ if (!file_exists($config["IMAGEMAGICK_IDENTIFY"])
2123
+ ||!file_exists($config["IMAGEMAGICK_CONVERT"])) {
2124
+ $config["RESIZE_LARGE_IMAGES"] = false;
2125
+ }
2126
+ }
2127
+ else {
2128
+ if (!HasGDInstalled(false)) {
2129
+ $config["RESIZE_LARGE_IMAGES"] = false;
2130
+ }
2131
+ }
2132
+ $config["POSTIE_ROOT"] = POSTIE_ROOT;
2133
+ $config["URLPHOTOSDIR"] = get_option('siteurl') . ConvertFilePathToUrl($config["PHOTOSDIR"]);
2134
+ $config["REALPHOTOSDIR"] = realpath(ABSPATH . $config["PHOTOSDIR"]). DIRECTORY_SEPARATOR;
2135
+ $config["URLFILESDIR"] = get_option('siteurl') . ConvertFilePathToUrl($config["FILESDIR"]);
2136
+ $config["REALFILESDIR"] = realpath(ABSPATH . $config["FILESDIR"]) . DIRECTORY_SEPARATOR;
2137
+ for ($i = 0; $i < count($config["AUTHORIZED_ADDRESSES"]); $i++) {
2138
+ $config["AUTHORIZED_ADDRESSES"][$i] = strtolower($config["AUTHORIZED_ADDRESSES"][$i]);
2139
+ }
2140
+ return $config;
2141
+ }
2142
+ /**
2143
+ * Converts from one directory structure to url
2144
+ * @return string
2145
+ */
2146
+ function ConvertFilePathToUrl($path) {
2147
+ return(str_replace(DIRECTORY_SEPARATOR , "/", $path));
2148
+ }
2149
+ /**
2150
+ * Returns a list of config keys that should be arrays
2151
+ *@return array
2152
+ */
2153
+ function GetListOfArrayConfig() {
2154
+ return(array("SUPPORTED_FILE_TYPES","AUTHORIZED_ADDRESSES","SIG_PATTERN_LIST","BANNED_FILES_LIST"));
2155
+ }
2156
+ /**
2157
+ * Detects if they can do IMAP
2158
+ * @return boolean
2159
+ */
2160
+ function HasIMAPSupport($display = true) {
2161
+ $function_list = array("imap_open",
2162
+ "imap_delete",
2163
+ "imap_expunge",
2164
+ "imap_body",
2165
+ "imap_fetchheader");
2166
+ return(HasFunctions($function_list,$display));
2167
+ }
2168
+ function HasIconvInstalled($display = true) {
2169
+ $function_list = array("iconv");
2170
+ return(HasFunctions($function_list,$display));
2171
+ }
2172
+ function HasGDInstalled($display = true) {
2173
+ $function_list = array("getimagesize",
2174
+ "imagecreatefromjpeg",
2175
+ "imagecreatefromgif",
2176
+ "imagecreatefrompng",
2177
+ "imagecreatetruecolor",
2178
+ "imagecreatetruecolor",
2179
+ "imagecopyresized",
2180
+ "imagejpeg",
2181
+ "imagedestroy");
2182
+ return(HasFunctions($function_list,$display));
2183
+ }
2184
+ /**
2185
+ * Handles verifing that a list of functions exists
2186
+ * @return boolean
2187
+ * @param array
2188
+ */
2189
+ function HasFunctions($function_list,$display = true) {
2190
+ foreach ($function_list as $function) {
2191
+ if (!function_exists($function)) {
2192
+ if ($display) {
2193
+ print("<p>Missing $function");
2194
+ }
2195
+ return(false);
2196
+ }
2197
+ }
2198
+ return(true);
2199
+
2200
+ }
2201
+ /**
2202
+ * This filter makes it easy to change the html from showing the thumbnail to the actual picture
2203
+ */
2204
+ function filter_postie_thumbnail_with_full($content) {
2205
+ $content = str_replace("thumb.","",$content);
2206
+ return($content);
2207
+ }
2208
+ /**
2209
+ * This function tests to see if postie is its own directory
2210
+ */
2211
+ function TestPostieDirectory() {
2212
+ $dir_parts = explode(DIRECTORY_SEPARATOR,dirname(__FILE__));
2213
+ $last_dir = array_pop($dir_parts);
2214
+ if ($last_dir != "postie") {
2215
+ return false;
2216
+ }
2217
+ return true;
2218
+ }
2219
+ /**
2220
+ *This function looks for markdown which causes problems with postie
2221
+ */
2222
+ function TestForMarkdown() {
2223
+ if (in_array("markdown.php",get_option("active_plugins"))) {
2224
+ return(true);
2225
+ }
2226
+ return(false);
2227
+
2228
+ }
2229
+ /**
2230
+ * This function handles setting up the basic permissions
2231
+ */
2232
+ function PostieAdminPermissions() {
2233
+ global $wp_roles;
2234
+ $admin = $wp_roles->get_role("administrator");
2235
+ $admin->add_cap("config_postie");
2236
+ $admin->add_cap("post_via_postie");
2237
+
2238
+ }
2239
+ function UpdatePostiePermissions($role_access) {
2240
+ global $wp_roles;
2241
+ PostieAdminPermissions();
2242
+ if (!is_array($role_access)) {
2243
+ $role_access = array();
2244
+ }
2245
+ foreach($wp_roles->role_names as $roleId => $name) {
2246
+ $role = &$wp_roles->get_role($roleId);
2247
+ if ($roleId != "administrator") {
2248
+ if ($role_access[$roleId]) {
2249
+ $role->add_cap("post_via_postie");
2250
+ }
2251
+ else {
2252
+ $role->remove_cap("post_via_postie");
2253
+ }
2254
+ }
2255
+ }
2256
+ }
2257
+ function TestWPVersion() {
2258
+ //fix from Mathew Boedicker
2259
+ $version_parts = explode('.', get_bloginfo('version'));
2260
+ if ((count($version_parts) > 0) && (intval($version_parts[0]) >= 2)) {
2261
+ return true;
2262
+ }
2263
+ return false;
2264
+ }
2265
+ function DebugEmailOutput(&$email,&$mimeDecodedEmail) {
2266
+ $config = GetConfig();
2267
+ if ($config["TEST_EMAIL"]) {
2268
+ $file = fopen("test_emails/" . $mimeDecodedEmail->headers["message-id"].".txt","w");
2269
+ fwrite($file, $email);
2270
+ fclose($file);
2271
+ $file = fopen("test_emails/" . $mimeDecodedEmail->headers["message-id"]."-mime.txt","w");
2272
+ fwrite($file, print_r($mimeDecodedEmail,true));
2273
+ fclose($file);
2274
+ }
2275
+ }
2276
+ /**
2277
+ * This function provides a hook to be able to write special parses for provider emails that are difficult to work with
2278
+ * If you want to extend this functionality - write a new function and call it from here
2279
+ */
2280
+ function SpecialMessageParsing(&$content, &$attachments){
2281
+ $config = GetConfig();
2282
+ if ( preg_match('/You have been sent a message from Vodafone mobile/',$content)) {
2283
+ VodafoneHandler($content, $attachments); //Everything for this type of message is handled below
2284
+ return;
2285
+ }
2286
+ if ( $config["MESSAGE_START"] ) {
2287
+ StartFilter($content,$config["MESSAGE_START"]);
2288
+ }
2289
+ if ( $config["MESSAGE_END"] ) {
2290
+ EndFilter($content,$config["MESSAGE_END"]);
2291
+ }
2292
+ if ( $config["DROP_SIGNATURE"] ) {
2293
+ RemoveSignature($content,$config["SIG_PATTERN_LIST"]);
2294
+ }
2295
+ if ($config["PREFER_TEXT_TYPE"] == "html"
2296
+ && count($attachments["cids"])) {
2297
+ ReplaceImageCIDs($content,$attachments);
2298
+ }
2299
+ ReplaceImagePlaceHolders($content,$attachments["html"]);
2300
+ }
2301
+ /**
2302
+ * Special Vodafone handler - their messages are mostly vendor trash - this strips them down.
2303
+ */
2304
+ function VodafoneHandler(&$content, &$attachments){
2305
+ $index = strpos($content,"TEXT:");
2306
+ if (strpos !== false) {
2307
+ $alt_content = substr($content,$index,strlen($content));
2308
+ if (preg_match("/<font face=\"verdana,helvetica,arial\" class=\"standard\" color=\"#999999\"><b>(.*)<\/b>/",$alt_content,$matches)) {
2309
+ //The content is now just the text of the message
2310
+ $content = $matches[1];
2311
+ //Now to clean up the attachments
2312
+ $vodafone_images = array("live.gif","smiley.gif","border_left_txt.gif","border_top.gif","border_bot.gif","border_right.gif","banner1.gif","i_text.gif","i_picture.gif",);
2313
+ while(list($key,$value) = each($attachments['cids'])) {
2314
+ if (!in_array($key, $vodafone_images)) {
2315
+ $content .= "<br/>".$attachments['html'][$attachments['cids'][$key][1]] ;
2316
+ }
2317
+ }
2318
+ }
2319
+ }
2320
+
2321
+ }
2322
+ ?>
postie.php ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /*
3
+ Plugin Name: Postie
4
+ Plugin URI: http://blog.robfelty.com/plugins/postie
5
+ Description: Signifigantly upgrades the posting by mail features of Word Press (See <a href="../wp-content/plugins/postie/postie.php?postie_read_me=1">Quick Readme</a>)
6
+ Version: 1.1.5
7
+ Author: Robert Felty
8
+ Author URI: http://blog.robfelty.com/
9
+ */
10
+
11
+ /*
12
+ * -= Requests Pending =-
13
+ * German Umlats don't work
14
+ * Problems under PHP5
15
+ * Problem with some mail server
16
+ * Config Form freaks out in some cases
17
+ * Multiple emails should tie to a single account
18
+ * Each user should be able to have a default category
19
+ * WP Switcher not compatible
20
+ * Setup poll
21
+ - web server
22
+ - mail clients
23
+ - plain/html
24
+ - phone/computer
25
+ - os of server
26
+ - os of client
27
+ - number of users posting
28
+ * make sure it handles the case where the url is http://www.site.com/wordpress/ instead of just http://www.site.com/
29
+ * Test for calling from the command line
30
+ * Support userid/domain as a valid username
31
+ * WP-switcher not compatiable http://www.alexking.org/index.php?content=software/wordpress/content.php#wp_120
32
+ * Test out a remote cron system
33
+ * Add ability to post to an existing page
34
+ * Add a download counter
35
+ * Add support for http://unknowngenius.com/wp-plugins/faq.html#one-click
36
+ * www.cdavies.org/code/3gp-thumb.php.txt
37
+ * www.cdavies.org/permalink/watchingbrowserembeddedgpvideosinlinux.php
38
+ * Support draft/private posts
39
+ * Make it possible to post without a script at all
40
+ */
41
+
42
+ //Older Version History is in the HISTORY file
43
+
44
+ include_once (dirname(dirname(dirname(dirname(__FILE__)))) . DIRECTORY_SEPARATOR. "wp-config.php");
45
+ include_once (dirname(dirname(dirname(dirname(__FILE__)))) .
46
+ DIRECTORY_SEPARATOR . 'wp-includes' . DIRECTORY_SEPARATOR . "pluggable.php");
47
+ require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR ."postie-functions.php");
48
+ if (isset($_GET["postie_read_me"])) {
49
+ include_once(ABSPATH . "wp-admin/admin.php");
50
+ $title = __("Edit Plugins");
51
+ $parent_file = 'plugins.php';
52
+ include(ABSPATH . 'wp-admin/admin-header.php');
53
+ postie_read_me();
54
+ include(ABSPATH . 'wp-admin/admin-footer.php');
55
+ }
56
+ //Add Menu Configuration
57
+ if (is_admin()) {
58
+ global $userdata;
59
+ get_currentuserinfo();
60
+ if ($userdata->user_level>9) {
61
+ add_action("admin_menu","PostieMenu");
62
+ }
63
+ }
64
+ ?>
postieIMAP.php ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ /**
3
+ * @author Dirk Elmendorf
4
+ * @style Compliant
5
+ * @testframework Compliant
6
+ * @package Postie
7
+ * @copyright Copyright 2005 Dirk Elmendorf
8
+ */
9
+
10
+ /**
11
+ * This class handles the details of an IMAP connection
12
+ *
13
+ * @author Dirk Elmendorf
14
+ * @package Postie
15
+ */
16
+ class PostieIMAP {
17
+
18
+ var $_connected;
19
+ var $_protocol;
20
+ var $_ssl;
21
+ var $_self_cert;
22
+ var $_tls_on;
23
+ var $_connection;
24
+
25
+ function PostieIMAP($protocol = "imap",$ssl_on = false,$self_cert = true) {
26
+ $this->_connected = false;
27
+ $this->_tls_on = false;
28
+ $this->_protocol = strtolower($protocol);
29
+ $this->_ssl = $ssl_on;
30
+ $this->_self_cert = $self_cert;
31
+ }
32
+ /**
33
+ *call this to turn on TLS
34
+ */
35
+ function TLSOn() {
36
+ $this->_tls_on = true;
37
+ }
38
+ /**
39
+ * call this if you want to verify the cert
40
+ */
41
+ function RealCert() {
42
+ $this->self_cert = false;
43
+ }
44
+ /**
45
+ * Shows if the object is actually connected
46
+ *@return boolean
47
+ */
48
+ function isConnected() {
49
+ return($this->_connected);
50
+ }
51
+ /**
52
+ *Opens a connection to the server
53
+ *@return boolean
54
+ */
55
+ function connect($server,$port,$login,$password) {
56
+ $option = "/service=".$this->_protocol;
57
+
58
+ if ($this->_ssl) {
59
+ $option .= "/ssl";
60
+ }
61
+ if ($this->_tls_on) {
62
+ $option .= "/tls";
63
+ }
64
+ else {
65
+ $option .= "/notls";
66
+ }
67
+ if ($this->_self_cert) {
68
+ $option .= "/novalidate-cert";
69
+ }
70
+ if (eregi("google",$server)) {
71
+ //Fix from Jim Hodgson http://www.jimhodgson.com/2006/07/19/postie/
72
+ $server_string = "{".$server.":".$port.$option."}INBOX";
73
+ }
74
+ else {
75
+ $server_string = "{".$server.":".$port.$option."}";
76
+ }
77
+ $this->_connection = imap_open($server_string,$login,$password);
78
+
79
+ if ($this->_connection) {
80
+ $this->_connected = true;
81
+ }
82
+ return($this->_connected);
83
+ }
84
+ /**
85
+ * Returns a count of the number of messages
86
+ * @return integer
87
+ */
88
+ function getNumberOfMessages() {
89
+ return(imap_num_msg($this->_connection));
90
+ }
91
+ /**
92
+ * Gets the raw email message from the server
93
+ * @return string
94
+ */
95
+ function fetchEmail($index){
96
+ if ($index < 1 || $index > ($this->getNumberOfMessages() + 1)) {
97
+ die("Invalid IMAP/POP3 message index!");
98
+ }
99
+ $email = imap_fetchheader($this->_connection,$index);
100
+ $email .= imap_body($this->_connection,$index);
101
+ return($email);
102
+ }
103
+ /**
104
+ * Marks a message for deletion
105
+ */
106
+ function deleteMessage($index){
107
+ imap_delete($this->_connection,$index);
108
+ }
109
+ /**
110
+ * Handles purging any files that are marked for deletion
111
+ */
112
+ function expungeMessages(){
113
+ imap_expunge($this->_connection);
114
+ }
115
+ /**
116
+ * Handles disconnecting from the server
117
+ */
118
+ function disconnect(){
119
+ imap_close($this->_connection);
120
+ $this->_connection = false;
121
+ }
122
+ /**
123
+ *@return string
124
+ */
125
+ function error() {
126
+ return(imap_last_error());
127
+ }
128
+ /**
129
+ * Handles returning the right kind of object
130
+ * @return PostieIMAP|PostieIMAPSSL|PostimePOP3SSL
131
+ * @static
132
+ */
133
+ function &Factory($protocol) {
134
+ switch(strtolower($protocol)) {
135
+ case "imap":
136
+ $object = &new PostieIMAP();
137
+ break;
138
+ case "imap-ssl":
139
+ $object = &new PostieIMAPSSL();
140
+ break;
141
+ case "pop3-ssl":
142
+ $object = &new PostiePOP3SSL();
143
+ break;
144
+ default:
145
+ die("$protocol not supported");
146
+ }
147
+ return($object);
148
+ }
149
+ }
150
+
151
+ /**
152
+ * This class handles the details of an IMAP-SSL connection
153
+ *
154
+ * @author Dirk Elmendorf
155
+ * @package Postie
156
+ */
157
+ class PostieIMAPSSL Extends PostieIMAP{
158
+
159
+ function PostieIMAPSSL($protocol = "imap",$ssl_on = true,$self_cert = true) {
160
+ PostieIMAP::PostieIMAP($protocol,$ssl_on,$self_cert);
161
+ }
162
+ }
163
+
164
+ /**
165
+ * This class handles the details of an POP3-SSL connection
166
+ *
167
+ * @author Dirk Elmendorf
168
+ * @package Postie
169
+ */
170
+ class PostiePOP3SSL Extends PostieIMAP {
171
+
172
+ function PostiePOP3SSL($protocol = "pop3",$ssl_on = true,$self_cert = true) {
173
+ PostieIMAP::PostieIMAP($protocol,$ssl_on,$self_cert);
174
+ }
175
+ }
176
+ ?>
postie_read_me.php ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
1
+ <div class="wrap">
2
+ <h1>Postie</h1>
3
+ <?php if (!current_user_can("config_postie")) :?>
4
+ <h2>WARNING! - You must be logged in as "admin" to configure Postie.</h2>
5
+
6
+ <?php endif;?>
7
+ <p>I'm working on some more detailed instructions, but for now this will have to do.</p>
8
+ <pre>
9
+ <?php include("readme.txt");?>
10
+ </pre>
11
+ </div>
postie_test.php ADDED
@@ -0,0 +1,218 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?php
2
+ // try to connect to server with different protocols/ and userids
3
+ require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR ."postie-functions.php");
4
+ include_once (dirname(dirname(dirname(dirname(__FILE__)))) . DIRECTORY_SEPARATOR. "wp-config.php");
5
+ require_once('admin.php');
6
+ require_once("postie-functions.php");
7
+ $config = GetConfig();
8
+ $title = __("Postie Diagnosis");
9
+ $parent_file = 'options-general.php?page=postie/postie.php';
10
+ get_currentuserinfo();
11
+ ?>
12
+ <?php if ($GLOBALS["user_level"] != 10 ) :?>
13
+ <h2> Sorry only admin can run this file</h2>
14
+ <?php exit();?>
15
+ <?php endif;?>
16
+
17
+ <?
18
+ $images = array("Test.png",
19
+ "Test.jpg",
20
+ "Test.gif");
21
+ ?>
22
+ <div class="wrap">
23
+ <h1>Postie Configuration Test</h1>
24
+ <?php
25
+ if (TestForMarkdown()) {
26
+ print("<h1>Warning!</h1>
27
+ <p>You currently have the Markdown plugin installed. It will cause problems if you send in HTML
28
+ email. Please turn it off if you intend to send email using HTML</p>");
29
+
30
+ }
31
+ ?>
32
+ <br/>
33
+ <?php
34
+
35
+ if (!TestWPVersion()) {
36
+ print("<h1>Warning!</h1>
37
+ <p>Postie only works on on Word Press version 2.0 and above</p>");
38
+ exit();
39
+ }
40
+ ?>
41
+
42
+ <br/>
43
+ <?php
44
+
45
+ if (!TestPostieDirectory()) {
46
+ print("<h1>Warning!</h1>
47
+ <p>Postie expects to be in its own directory named postie.</p>");
48
+ }
49
+ else {
50
+ print("<p>Postie is in ".dirname(__FILE__)."</p>");
51
+ }
52
+ ?>
53
+
54
+ <br/>
55
+ <h2>GD Library Test<h2>
56
+ <p>
57
+ <?= HasGDInstalled();?>
58
+ </p>
59
+ <h2>Iconv Library Test<h2>
60
+ <p><i>Only required if you want to support ISO-2022-JP</i>
61
+ <?= HasIconvInstalled();?>
62
+ </p>
63
+ <br/>
64
+ <h2>Clock Tests<h2>
65
+ <p>This shows what time it would be if you posted right now</p>
66
+ <?php
67
+ $content ="";
68
+ $data = DeterminePostDate($content);
69
+
70
+ ?>
71
+ <p><?php print("GMT:". $data[1]);?></p>
72
+ <p><?php print("Current:". $data[0]);?></p>
73
+ <h2>Mail Tests</h2>
74
+ <p>These try to confirm that the email configuration is correct.</p>
75
+
76
+ <table>
77
+ <tr>
78
+ <th>Test</th>
79
+ <th>Result</th>
80
+ </tr>
81
+ <tr>
82
+ <th>Connect to Mail Host</th>
83
+ <td>
84
+ <?php
85
+ switch( strtolower($config["INPUT_PROTOCOL"]) ) {
86
+ case 'imap':
87
+ case 'imap-ssl':
88
+ case 'pop3-ssl':
89
+ if (!HasIMAPSupport()) {
90
+ print("Sorry - you do not have IMAP php module installed - it is required for this mail setting.");
91
+ }
92
+ else {
93
+ require_once("postieIMAP.php");
94
+ $mail_server = &PostieIMAP::Factory($config["INPUT_PROTOCOL"]);
95
+ if (!$mail_server->connect($config["MAIL_SERVER"], $config["MAIL_SERVER_PORT"],$config["MAIL_USERID"],$config["MAIL_PASSWORD"])) {
96
+ print("Unable to connect. The server said - ".$mail_server->error());
97
+ print("<br/>Try putting in your full email address as a userid and try again.");
98
+ }
99
+ else {
100
+ print("Yes");
101
+ }
102
+ }
103
+ break;
104
+ case 'pop3':
105
+ default:
106
+ require_once(ABSPATH.WPINC.DIRECTORY_SEPARATOR.'class-pop3.php');
107
+ $pop3 = &new POP3();
108
+ if (!$pop3->connect($config["MAIL_SERVER"], $config["MAIL_SERVER_PORT"])) {
109
+ print("Unable to connect. The server said - ".$pop3->ERROR);
110
+ print("<br/>Try putting in your full email address as a userid and try again.");
111
+ }
112
+ else {
113
+ print("Yes");
114
+ }
115
+ break;
116
+
117
+ }
118
+ ?>
119
+ </td>
120
+ </tr>
121
+
122
+
123
+ </table>
124
+ <h2>File Tests</h2>
125
+
126
+ <table>
127
+ <tr>
128
+ <th>Test</th>
129
+ <th>Result</th>
130
+ </tr>
131
+ <tr>
132
+ <th>Photos Directory Exists</th>
133
+ <td><?php echo (is_dir($config["REALPHOTOSDIR"]) ? "Yes" : "No"); ?></td>
134
+ </tr>
135
+ <tr>
136
+ <th>Files Directory Exists</th>
137
+ <td><?php echo (is_dir($config["REALFILESDIR"]) ? "Yes" : "No"); ?></td>
138
+ </tr>
139
+ <tr>
140
+ <th>Photos Directory Writable</th>
141
+ <td><?php echo (is_writable($config["REALPHOTOSDIR"]) ? "Yes" : "No"); ?></td>
142
+ </tr>
143
+ <tr>
144
+ <th>Files Directory Writable</th>
145
+ <td><?php echo (is_writable($config["REALFILESDIR"]) ? "Yes" : "No"); ?></td>
146
+ </tr>
147
+
148
+ <?php if ($config["USE_IMAGEMAGICK"]):?>
149
+ <tr>
150
+ <th>Convert exists</th>
151
+ <td><?php echo (file_exists($config["IMAGEMAGICK_CONVERT"]) ? "Yes" : "No"); ?></td>
152
+ </tr>
153
+ <tr>
154
+ <th>Identify exists</th>
155
+ <td><?php echo (file_exists($config["IMAGEMAGICK_IDENTIFY"]) ? "Yes" : "No"); ?></td>
156
+ </tr>
157
+
158
+ <?endif;?>
159
+
160
+ </table>
161
+
162
+
163
+
164
+ <h2>Image Tests</h2>
165
+ <p>Three images should be here - they are the test files</p>
166
+ <table>
167
+ <tr>
168
+ <td>&nbsp;</td>
169
+ <td>PNG</td>
170
+ <td>JPG</td>
171
+ <td>GIF</td>
172
+ </tr>
173
+ <tr>
174
+ <th>Plain Images</th>
175
+ <?php
176
+ foreach ($images as $image) {
177
+ $size = DetermineImageSize(POSTIE_ROOT . DIRECTORY_SEPARATOR . "test_files" . DIRECTORY_SEPARATOR .$image);
178
+ print("<td>$size[1] x $size[0]<br/>\n");
179
+ print("<img src='../wp-content/plugins/postie/test_files/$image' ></td>\n");
180
+ }
181
+ ?>
182
+ </tr>
183
+ <tr>
184
+ <?php if($config["AUTO_SMART_SHARP"]){ ?>
185
+ <th> AutoSharpened <br/><p>WARNING-This feature takes a lot of processing power</p></th>
186
+ <?php
187
+ foreach ($images as $image) {
188
+
189
+ print("<td>");
190
+
191
+ ImageMagickSharpen(POSTIE_ROOT . DIRECTORY_SEPARATOR . "test_files" . DIRECTORY_SEPARATOR .$image,
192
+ $config["REALPHOTOSDIR"] ."Sharp-".$image);
193
+ print("<img src='".$config["URLPHOTOSDIR"]."/Sharp-".$image."'>");
194
+ print("</td>\n");
195
+ }
196
+ ?>
197
+ </tr>
198
+ <?php }?>
199
+ <tr>
200
+ <th> Scaled & Rotated</th>
201
+ <?php
202
+ foreach ($images as $image) {
203
+ $result = ResizeImage(POSTIE_ROOT . DIRECTORY_SEPARATOR . "test_files" . DIRECTORY_SEPARATOR .$image,substr($image,-3,3));
204
+
205
+ RotateImages(90,array(
206
+ array(null,$config["REALPHOTOSDIR"] . $result[0],'jpg')
207
+ ));
208
+ print("<td>");
209
+ $size = DetermineImageSize($config["REALPHOTOSDIR"] . DIRECTORY_SEPARATOR .$result[0]);
210
+ print("$size[1] x $size[0]<br\>\n");
211
+ print("<img src='".$config["URLPHOTOSDIR"].$result[0]."'>");
212
+ print("</td>\n");
213
+ }
214
+ ?>
215
+ </tr>
216
+ </table>
217
+
218
+ </div>
readme.txt ADDED
@@ -0,0 +1,485 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ === Postie ===
2
+ Contributors: robfelty,
3
+ Donate link: http://blog.robfelty.com/plugins/postie
4
+ Plugin URI: http://blog.robfelty.com/plugins/postie
5
+ Tags: e-mail
6
+ Requires at least: 2.3
7
+ Tested up to: 2.7.1
8
+ Stable tag: 1.1.5
9
+
10
+ The Postie plugin allows you to blog via e-mail, including many advanced
11
+ features not found in wordpress's default post by e-mail feature.
12
+
13
+ == Description ==
14
+ Postie offers many advanced features for posting to your blog via e-mail,
15
+ including the ability to assign categories by name, included pictures and
16
+ videos, and automatically strip off signatures. It also has support for both
17
+ imap and pop3, with the option for ssl with both. For usage notes, see the
18
+ [other notes](other_notes) page
19
+
20
+ = What's new in 1.1.5 =
21
+ * Added option to have postie posts be pending review, published, or draft
22
+ * Settings panel only shows up for administrators
23
+ * Need not be user "admin" to modify settings or to post from non-registered
24
+ users
25
+ * Can now set administrator name. Authorized e-mail addresses which don't
26
+ have a user get posted under this name
27
+ * Will use IPTC captions if available
28
+ * Added option to replace newline characters with &lt;br /&gt;
29
+
30
+ == Installation ==
31
+ * Make sure all postie code is its own directory inside of wp-content/plugins/postie
32
+ * Make two directories in your main wordpress directory wp-filez and wp-photos
33
+ * Make sure these directories are writable by your web server (chmod 777 or chown to the webserver -- the permissions should be the same as wp-content/uploads)
34
+ * make sure that the postie directory that this file is in is moved to yourwebsite/wp-content/plugins
35
+ * Login to WordPress as an administrator
36
+ * Goto the Plugins tab in the WordPress Admin Site
37
+ * Activate "Postie"
38
+ * Goto to the "Options" tab and click on the sub-tab "Configure Postie" to configure it.
39
+ * (Postie ignores the settings under Options->Writing->Writing-by-Email)
40
+
41
+
42
+ Setup a cronjob to pull down the get_mail.php
43
+ Example:
44
+ */5 * * * * /usr/bin/lynx --source http://www.economysizegeek.com/wp-content/plugins/postie/get_mail.php >/dev/null 2>&1
45
+
46
+ This fetches the mail every five mintues.
47
+
48
+ If you don't have access to cron - check out "Cronless Postie"
49
+
50
+ == Options ==
51
+ * You can set the starting characters for you signature so that it
52
+ is removed from the posting message
53
+ * You can set a list of banned file names so if you provider adds
54
+ images to your post they don't show up in the blog
55
+ * If you post from an email address that is not a valid author the
56
+ email post will be forwarded to the admin
57
+ * You can control if you want HTML allowed in the body or subject
58
+ of your post
59
+ * Lets you set a default subject when you don't set one
60
+ * Defaults to posting to the default category you set in Word Press
61
+
62
+ == Usage ==
63
+ * If you put in :start - the message processing won't start until it sees that string
64
+ * If you put in :end - the message processing will stop once it sees that string
65
+ * Posts can be delayed by adding a line with delayXdXhXm where X is a number.
66
+ * delay:1d - 1 day
67
+ * delay:1h - 1 hour
68
+ * delay:1m - 1 minute
69
+ * delay:1d2h4m - 1 day 2 hours 4m
70
+ * By putting comments:X in your message you can control if comments are allowed
71
+ * comments:0 - means closed
72
+ * comments:1 - means open
73
+ * comments:2 - means registered only
74
+ * Replying to an e-mail gets posted as a comment.
75
+ * For example, you e-mailed a post with the subject line "foo".
76
+ If you then send an e-mail with the subject line "Re: foo", it will
77
+ get posted as a comment to the "foo" post. This works by the subject
78
+ line, so if you have two posts with titles "foo", then the comment
79
+ will get placed in the more recent post.
80
+
81
+ = Category and tag handling =
82
+ * If you put a category name in the subject with a : it will be used
83
+ as the category for the post
84
+ * If you put a category id number in the subject with a : it will
85
+ be used as the category for the post
86
+ * If you put the first part of a category name it will be posted in
87
+ the first category that the system finds that matches - so if you put
88
+
89
+ Subject: Gen: New News
90
+
91
+ The system will post that in General.
92
+
93
+ * All of the above also applies if you put the category in brackets []
94
+ * Using [] or you can post to multiple categories at once
95
+
96
+ Subject: [1] [Mo] [Br] My Subject
97
+
98
+ On my blog it would post to General (Id 1), Moblog, and Brewing all at one time
99
+
100
+ * Using - or you can post to multiple categories at once
101
+
102
+ Subject: -1- -Mo- -Br- My Subject
103
+
104
+ On my blog it would post to General (Id 1), Moblog, and Brewing all at one time
105
+ * You can add tags by adding a line in the body of the message like so:
106
+ tags: foo, bar
107
+ * You can also set a default tag to be applied if no tags are included.
108
+
109
+ = Image Handling =
110
+ * Postie has a filter to make it easy to show full images on individual pages.
111
+ * Tells you if you have GD installed for resizing images
112
+ * Allows you to attach images to your email and automatically post
113
+ them to your blog
114
+ * Large images are automatically thumbnailed and linked to the larger
115
+ image (Requires GD)
116
+ * You can publish images in the text of your message by using #img1#
117
+ #img2# - each one will be replaced with the HTML for the image
118
+ you attached
119
+ * Captions - you can also add a caption like so:
120
+ #img1 caption='foo'#
121
+ #img2 caption='bar'#
122
+
123
+ Or, if you use IPTC captions, this caption will be used (adding a caption
124
+ in many photo editing programs (for example Picasa), will add an IPTC caption)
125
+
126
+ * Image templates
127
+ By default, postie wraps images in a div. You can specify the class of
128
+ the div in the options. You can also choose whether or not to open the
129
+ full-size image in a new window.
130
+
131
+ You can also specify a custom image template. I use the following custom
132
+ template:
133
+
134
+ &lt;div class='imageframe alignleft'&gt;&lt;a href='{IMAGE}'&gt;&lt;img src="{THUMBNAIL}"
135
+ alt="{CAPTION}" title="{CAPTION}"
136
+ class="attachment" /&gt;&lt;/a&gt;&lt;div
137
+ class='imagecaption'&gt;{CAPTION}&lt;/div&gt;&lt;/div&gt;
138
+
139
+ * {IMAGE} gets replaced with the url to the full-size image
140
+ * {THUMBNAIL} gets replaced with the url to the thumbnail image
141
+ * {FILENAME} gets replaced with the absolute path to the full-size image
142
+ * {CAPTION} gets replaced with the caption you specified (if any)
143
+
144
+ * Rotation - if you include the text
145
+
146
+ rotate:90
147
+
148
+ or any other number - all images in the message will be rotated for you.
149
+
150
+ * Images are renamed in a way that makes it impossible to accidentally
151
+ overwrite images you have already posted
152
+
153
+
154
+
155
+ = Interoperability =
156
+ * If your mail client doesn't support setting the subject (nokia) you
157
+ can do so by putting #your title here# at the begining of your message
158
+ * POP3,POP3-SSL,IMAP,IMAP-SSL now supported - last three require
159
+ php-imap support
160
+ * The program understands enough about mime to not duplicate post
161
+ if you send an HTML and plain text message
162
+ * Automatically confirms that you are installed correctly
163
+
164
+
165
+
166
+ == History ==
167
+ * 1.1.5 (2009.03.10)
168
+ * Added option to have postie posts be pending review, published, or draft
169
+ * Settings panel only shows up for administrators
170
+ * Need not be user "admin" to modify settings or to post from non-registered
171
+ users
172
+ * Can now set administrator name. Authorized e-mail addresses which don't
173
+ have a user get posted under this name
174
+ * Will use IPTC captions if available
175
+ * Added option to replace newline characters with &lt;br /&gt;
176
+
177
+ * 1.1.4 (2009.03.06)
178
+ * Added more image options (open in new window, custom image template)
179
+ * can now add captions to images
180
+ * Can now add tags (including default tag option)
181
+
182
+ * 1.1.3 (2009.02.20)
183
+ * Fixed delayed posting
184
+ * updated readme some
185
+
186
+ * 1.1.2 (2008.07.12)
187
+ * now maintained by Robert Felty
188
+ * allow negative delays
189
+ * will glean author information from forwarded or redirected e*mails
190
+ * replying to an e*mail adds a comment to a post
191
+ * fixed category handling to work with taxonomy
192
+ * fixed one syntax error
193
+ * added option to wrap posts and comments in <pre> tags
194
+
195
+ Below is all the of the version information. As far as I can tell there once was a guy named John Blade. He took some of the orignal wp-mail.php code and started hacking away on it. He actually got pretty far. About the time I discovered WordPress and his little hack - called WP-Mail at the time - he went on a vacation or something. There were some problems with the script, and it was missing some features I wanted. I hacked away at it and got it into a place where it did what I wanted. I started posting about it since I figured other people might want the features.
196
+
197
+ John didn't release any more versions at least up til July 2005. So I started accepting submissions and feature requests from people to help make the code better. In June/July 2005 I discovered a little plugin by Chris J Davis (http://www.chrisjdavis.org/cjd-notepad/) called notepad. I added a small feature to it (basically a bookmarklet). In the process I started looking at his code and realized how much you could do with the plugin system available in Word Press.
198
+
199
+ So I decided to make an offical fork. I put up an article on my blog asking for new names. I picked Postie. I then modified the code to be a proper plugin. And the rest is history :)
200
+
201
+ Version 1.1.1
202
+ BUGFIX -problem with subject
203
+ BUGFIX -cronless postie typo
204
+
205
+ Version 1.1
206
+ FEATURE: Updated and tested with WordPress 2.1
207
+ BUGFIX:Removed deprecated functions
208
+ FEATURE: Cronless Postie now uses the WordPress native Psuedo Cron.
209
+
210
+ Version 1.0
211
+ BUGFIX: TestWPVersion broke with 2.1
212
+ FEATURE: end: now marks the end of a message (Dan Cunningham)
213
+ FEATURE: Better Readme (Michael Rasmussen)
214
+ FEATURE: Smart Sharpen Option -EXPERIMENTAL- (Jonas Rhodin)
215
+ BUGFIX: Issue with google imap fixed (Jim Hodgson)
216
+ BUGFIX: Fixed espacing issue in subjects (Paul Clip)
217
+ BUGFIX: Typo in Div fixed (phil)
218
+
219
+ Version 0.9.9.3.2
220
+ BUGFIX: Typo
221
+ Version 0.9.9.3.1
222
+ BUGFIX: Removed debugging code
223
+
224
+ Version 0.9.9.3
225
+ BUGFIX: If your email address matches an existing user - then it will post as that user - even if you allow anyone to post.
226
+ BUGFIX: Replaced get_settings('home') with get_settings('siteurl')
227
+ BUGFIX: Better handling for Japanese charactersets - Thanks to http://www.souzouzone.jp/blog/archives/009531.html
228
+ BUGFIX: Better thumbnail window opening code - thanks to Gabi & Duntello!
229
+ FEATURE: Added an option to set the MAX Height of an image - idea from Duntello
230
+ BUGFIX: Modified the FilterNewLines for better flowed text handling - You now HAVE TO PUT TWO NEW LINES to end a paragraph.
231
+ FEATURE: Added new CSS tags to support positioning images/attachments/3gp videos
232
+ BUGFIX: Tries to use the date in the message (Thanks Ravan) I tried this once before and it never worked - hopefully this time it will.
233
+ BUGFIX: Added a workaround to fix the problem with Subscribe2 - it will now notify on posts that are not set to show up in the future.
234
+
235
+
236
+
237
+ Version 0.9.9.2
238
+ BUGFIX: Looks for the NOOP error and disgards it
239
+ FEATURE: Postie now detects the version of WordPress being used
240
+ FEATURE: Smarter Parsing of VodaPhone
241
+ FEATURE: Easy place to add new code to handle other brain-dead mail clients
242
+ BUGFIX: Handles insertion of single quotes properly
243
+ BUGFIX: Thumbnails should now link properly
244
+
245
+ Version 0.9.9.1
246
+ BUGFIX: Needed a strtolower in places to catch all iso-8859 - thx to Gitte Wange for the catch
247
+ BUGFIX: Fixed issue with the category not being posted properly
248
+
249
+ Version 0.9.9
250
+ UPDATE TO WP 2.0
251
+ BUGFIX: Config Page now works
252
+ FEATURES: Supports role based posting
253
+ BUGFIX: Posting updates the category counts.
254
+
255
+ Version 0.9.8.6
256
+ BUGFIX: Fixed problems with config page <%php became <?php
257
+
258
+ Version 0.9.8.5
259
+ BUGFIX: onClick changed to onclick
260
+ BUGFIX: strolower added to test for iso - thanks daniele
261
+ BUGFIX: Added a class to the 3gp video tags
262
+ FEATURE: Added the option to put the images before the article
263
+ BUGFIX: Added in selection for charsets - thanks Psykotik - this may cause problems for other encodings
264
+ FEATURE: Added option to turn of quoted printable decoding
265
+ FEATURE: :start tag - now postie looks for this tag before looking for you message - handy if your service provider prepends a message
266
+ FEATURE: Template for translation now included
267
+ Version 0.9.8.4
268
+ BUGFIX: Fixed problem with config_form.php - select had "NULL" instead of ""
269
+ BUGFIX: 3g2 now supported
270
+ BUGFIX: More line break issues addressed
271
+ BUGFIX: QuickTime controls are now visible even if the movie is done playing
272
+ BUGFIX: Email addresses in the format <some@domain.com> (Full Name) supported
273
+ BUGFIX: Some images that were not being resized - are now
274
+ BUGFIX: HTML problems - if you posted plain text with HTML on it ignored all images
275
+ BUGFIX: The test system blew up on the thumbnails
276
+ BUGFIX: Selected HTML for preferred text is now shown in the config form properly
277
+ BUGFIX: Postie now complains if it is not in its own directory
278
+ BUGFIX: Postie doesn't include PEAR if it is already available
279
+ BUGFIX: In Test mode rejected emails are simply dropped
280
+ BUGFIX: Markdown messes up Postie - it will warn you if you turn it on.
281
+
282
+ Version 0.9.8.3
283
+ BUGFIX: Fixed issue with the line feed replacement
284
+ BUGFIX: Added Banned File Config back in
285
+ FEATURE: Added in a link around 3gp video embedded via QT
286
+ BUGFIX: Email that has both Plain and HTML content will show the HTML content and not the plain if html is preferred
287
+
288
+ Version 0.9.8.2
289
+ BUGFIX: Fixed an extra new line after attachin non-image files.
290
+ BUGFIX: The Test system now displays any missing gd functions
291
+ BUGFIX: The test system was only using ImageMagick
292
+
293
+ Version 0.9.8.1
294
+ BUGFIX: The test images are now included in the zip
295
+
296
+ Version 0.9.8
297
+ BUGFIX: New Lines detected and handled properly in cases where the mail client doesn't put a space before the new line (Miss Distance)
298
+ BUGFIX: 3gp mime type added (Paco Cotera)
299
+ BUGFIX: Authorized Email Addresses are not case-insensitive
300
+ FEATURE: The larger image now does a proper pop up
301
+ BUGFIX: Fixed Timeing Issue - turns out it wasn't reading the db at all
302
+ FEATURE: New Test Screen - to help track down problems
303
+
304
+ Version 0.9.7
305
+ BUGFIX: removed all short tags
306
+ BUGFIX: There were spacing issues in the way I wrote the QT embed statements
307
+ FEATURE: Added calls to WP-Cron - should work with that properly now if you activate Cronless Postie
308
+ FEATURE: ImageMagick version works without any calls to GD
309
+ BUGFIX: Postie now correctly handles cases wjere tjere are multiple blogs in one db
310
+ BUGFIX: Turned off warnings when using without GD
311
+ FEATURE: add the rotate:X to your message to rotate all images
312
+ FEATURE: new filter_postie_thumbnail_with_full which makes it easy to show a thumbnail on the front page but full image on the single page - see FAQ
313
+
314
+ Version 0.9.6
315
+ BUGFIX: handles email addresses that are no name and just <email@email.com> (Steve Cooley Reported)
316
+ FEATURE: Basic support for embedding flash files
317
+ BUGFIX: Postie now handles creating the correct URL on non Unix platforms
318
+ BUGFIX: Fixed problem with file attachments not being put in the right place.
319
+ FEATURE: You can now choose to use imagemagick convert to handle making thumbnails
320
+ BUGFIX: Rewrote Cronless Postie to use direct sockets
321
+ BUGFIX: Time offset is now settable just for Postie - hopefully this will fix problems for cases where the normal time offset doesn't work properly.
322
+ FEATURE: First draft of frame for a 3GP video
323
+ FEATURE: Option to embed 3GP in QuickTime Controller.
324
+
325
+ Version 0.9.5.2
326
+ BUGFIX: gmt varialble not being set correctly
327
+ BUGFIX: Changed the name of the Check Mail button to fix an issue with mod_security
328
+ BUGFIX: Fixed issue with Cronless-Postie
329
+ BUGFIX: There was an argument passed by reference incorrectly
330
+ FEATURE: Added in Cronless Postie Readme
331
+ FEATURE: Added in Postie Readme
332
+
333
+ Version 0.9.5.1
334
+ BUGFIX: Confirmed POP3-SSL on debian-3.0
335
+ BUGFIX: Updated the plugin version
336
+ BUGFIX: Stopped displaying the email account
337
+
338
+ Version 0.9.5
339
+ BUGFIX: Postie handles cases where you do not have GD
340
+ FEATURE: You can now set the access level for posting - so other people can use the gate way
341
+ BUGFIX: Fixed issue when admininstrator email is not tied to a user account.
342
+ FEATURE: Can now reset all Postie configurations back to defaults
343
+ BUGFIX: HTML Emails with embedded images are now handled properly.
344
+ BUGFIX: The time difference should work correctly now
345
+ BUGFIX: Postie's configs are completely seperate from Writing-By-Mail
346
+ FEATURE: Warning if you use Gmail to make sure you turn on POP support
347
+ BUGFIX: Manual Check Mail Button in interface
348
+ BUGFIX: fixed issue of compatability with cjd-notepad
349
+ BUGFIX: Windows Works Now
350
+
351
+
352
+ Version 0.9.4
353
+ BUGFIX: Cronless Postie - fixed the include statement
354
+ BUGFIX: Authorized Addresses now supports a single address
355
+ FEATURE: All configuration in Postie done in a single screen
356
+ FEATURE: AUTHORIZATION can be completely overridden
357
+ BUGFIX: line 1159 - didn't handle cases where the table didn't exist already very well
358
+ FEATURE: Detects if you can do IMAP
359
+ FEATURE: Added IMAP Support
360
+ FEATURE: Added IMAP-SSL Support
361
+ FEATURE: Added POP3-SSL Support
362
+
363
+ Version 0.9.3
364
+ Bug fixes for IIS
365
+ Version 0.9.2
366
+ Moved to more of a DIRECTORY_SEPARATOR structure
367
+ Version 0.9.1
368
+ Added a define to fix a problem with over including
369
+ Version 0.9
370
+ Converted to an honest to god plugin
371
+ BUGFIX: If you put a single category:subject it now works
372
+ BUGFIX: ? Special characters may be supported? The test post now shows a lot of umlats and accents?
373
+ BUGFIX: The last ] in a subject with categories is now filtered out
374
+ FEATURE: -1- subject - will put the post in category 1
375
+ Version 0.312.13
376
+ Code clean up - The main loop is finally readable by even non programmers
377
+ FEATURE - You can now post to multiple categories at one time by using the [#],[Category Name], [Cat] in the subject
378
+ FEATURE - You can now select a category by just including the begining characters [G] will select General
379
+ if you don't have any other categories that start with g
380
+ FEATURE - Jay Talbot - added a new feature so you can have multiple email addresses be allowed in
381
+ Make multi category posting more obvious
382
+ BUG FIX: Timezones of GMT+? should now work properly
383
+ BUG FIX: Able to handle mis-mime typed images as long as they are named with .jpg/.gif/.png
384
+
385
+ Version 0.312.12
386
+ Code clean up - slowing shrinking the main to make it easiery to fix things
387
+ FEATURE: Be able to turn on/off allowing comments in an email
388
+ BUG FIX: AppleDouble now mostly supported
389
+ BUG FIX: MIME handling improved.
390
+ BUG FIX: Fix issue with timing delay
391
+ Version 0.312.11
392
+ FEATURE: Patterns to define where a sig starts are user configurable
393
+ FEATURE: Add filter options for banned file names
394
+ BUG FIX: Made it possible to turn off posting to the db for testing purposes
395
+ Version 0.312.10
396
+ FEATURE: Added in code to diplay the mime type of the file being linked to
397
+ BUG FIX: It now tests for the existance of the directories and makes sure
398
+ that the web server can write to them
399
+ Version 0.312.9
400
+ FEATURE:Should handle jpg as well as jpeg as the file type
401
+ BUG FIX: Now correctly handles the subject in the message
402
+ BUG FIX: Should handle Text preferences correctly
403
+ Version 0.312.8
404
+ Some general code tidying.
405
+ FEATURE: Can now have email from invalid email addresses automatically forwared
406
+ to the admin's email account. This forward includes all attachments.
407
+ Props to David Luden for getting this started.
408
+ Minor change: The system will continue if it runs into a message that doesn't have
409
+ any content - it will also continue to process if it gets an email from
410
+ someone not in the system. In the past this could result in deleted mail
411
+ if your cron job didn't run often enough.
412
+ Version 0.312.7
413
+ Confirm the handling of 3gp video for cell phones o
414
+ Added in new directive SUPPORTED_FILE_TYPES -if the mime type is listed here then the system will try to make a link to it without making a thumb nail.
415
+ Version 0.312.6
416
+ Bug Fix: Ok the last bug I fixed - actually caused another bug - man I should set up some unit tests. Now it handles mail from the nokia mail client correctly.
417
+ Version 0.312.5
418
+ Bug Fix : The system was accepting all test/* types. Now you can set a preference (defaults to text/plain)
419
+ to use as the main text for the post.
420
+ Version 0.312.4
421
+ Added in sanitize_title call suggested by Jemima
422
+ Added in ability to provide a subject in an mms - by using #Subject#
423
+ Fixed an issue with the time stamp system so it now automatically uses the gmt_offset from WordPress
424
+ Fixed issue with the delay:1d1h tag that prevented it from being removed from the body.
425
+ Fixed issue with the delay tag that caused problems if it was the last thing before an image.
426
+
427
+ Version 0.312.3-HEY (2005-05)
428
+ -> Some changes and Bugfixes by Adrian Heydecker
429
+ -> Not (yet) in main development branch.
430
+ Fixed bug: JPEG-thumbnails had a bigger filesize than full images caused by bad hardcoded compression value.
431
+ Fixed bug: If images and signatures were present but no placeholder tags, the images were deleted together with the signature.
432
+ Fixed bug: Generates valid postnames for users of mod_rewrite. Permalinks to posts should now work even when whitespaces are present in the subject line.
433
+ Added support for Quoted Printable encoded mail.
434
+ Added ability to encode Wordpress-posts in charset ISO-8859-1 instead of UTF-8.
435
+ Added ability to choose JPEG-compression value for thumbnails.
436
+ Added ability to add class="" and style="" to images.
437
+ Added ability to use a different mailadress (eg. mobile) without setting up a new Wordpress-account.
438
+
439
+ Version 0.312.2
440
+ BUGFIX: It now removes the delay tag from the message
441
+ Version 0.312.1
442
+ Added modification for placeholder support for images (David Luden)
443
+ Added in support to automatically scale down big images (Dirk Elmendorf)
444
+ Fixed bug with multiple emails all getting the contents of the first image tag (Dirk Elmendorf)
445
+ Added option to allow HTML in the body and subject of the email (Dirk Elmendorf)
446
+ Switch config options to defines to reduce the number of global variables (Dirk Elmendorf)
447
+ Added tests to make sure there is a trailing slash on the DIR definitions (Dirk Elmendorf)
448
+ Add tests to see if they have gd installed (Dirk Elmendorf)
449
+ Seperate the scaling out to a function for easier usage (Dirk Elmendorf)
450
+ Add delay feature for future posting. (Dirk Elmendorf)
451
+ Added in ability to use strtotime if it is available (Dirk ELmendorf)
452
+
453
+ Todo
454
+ Have option to have the email that is rejected forwarded on to another address.
455
+ Fix bug that id still diplays the delay tag in the body
456
+ Version 0.312 - 2005-03
457
+ - CHANGE FOR DEFAULT E-mail Categories, instead of [General] Subject you can now use General: Subject in the subject line. Less typing, and there must be a space after the colon.
458
+ - Fixed bugs with no default posting for categories and user
459
+ Version 0.311 - 2005-01
460
+ - eep, major bug for pop3 server. Next time I test my code more before I released, fixed so that pop3 now works.`
461
+ Version 0.31 - 2004-12 & 2005-01
462
+ (Has it been this long, best get back into the swing of things... did most of this coding on my holiday as I didn't have a machine to play WoW on :)
463
+ - moved the deletion of pop3 emails into a check so that e-mails aren't deleted without proper checking.
464
+ - added HTML 'decoding' (basic support for Thunderbird & Outlook)
465
+ - updated the Category search so that it matches words as well as numbers (i.e. [General] Subjectname will work instead of just [1] Subjectname)
466
+ - Changed time function from time to strtotime (as per Senior Pez's suggestion), but found out that strtotime isn't in default php distro so removed...
467
+
468
+ Vesion 0.3 - 2004-09
469
+ - Added UBB decoding support
470
+ - Added default title (when there is no subject assigned)
471
+ - Started doing a little code cleanup, been reading Advanced PHP Book :)
472
+
473
+ Version 0.2 - 2004-08
474
+ - Stopped using pear body decoding in favour of own decoding (may be slower but more modifiable) because of enriched text decoding
475
+ - Added base64_decode checking (may help mobile phone users)
476
+ - Fixed Subject line for non-english users (htmlentities instead of just trim)
477
+ - Fixed error in some pop hanging -> more graceful exit on event on no emails in inbox ($pop3->quit)
478
+ - Added work around for email addresses with exta <> in field (ie: <blade@lansmash.com> instead of blade@lasmash.com
479
+ - Added some ===basic=== enriched text support
480
+ - Updated readme file for easier install
481
+ - Easy modify of globals (such as PHOTOSDIR and FILESDIR)
482
+ - Cleaned up some pear stuff in install
483
+
484
+ Version 0.1 - 2004-06
485
+ First release
test_files/Test.gif ADDED
Binary file
test_files/Test.jpg ADDED
Binary file
test_files/Test.png ADDED
Binary file