Forking from Mailzu 0.8RC3

This commit is contained in:
Mikko Husari 2008-12-10 15:33:43 +02:00
commit 2572b1814b
184 changed files with 79039 additions and 0 deletions

180
CHANGELOG Normal file
View File

@ -0,0 +1,180 @@
MailZu 0.8RC3 (06.14.2007):
----------
- Fixed an inconsistency in the FAQ
- Fixed bug when using proxyAddresses attribute in AD authentication
- Added installation requirement of using the TIMESTAMP type for the 'time_iso' field
when using MySQL
- Added more Czech translation; contribution from Petr Stehlik
MailZu 0.8RC2:
----------
- Fixes Email Administrator Header reported by Benny Pedersen.
- Updates description of adminEmail in INSTALL and config.php.sample.
- Isolate OR statements in convertEmailaddresses2SQL
- Fixed $_SESSION['sessionMail'][0] submitted by Serge Algarotti
- Added option toggle for 'Site Quarantine Summary'
- Added $conf['app']['debug'] to config.php.sample
- Debug dumps all SQL Queries to the log file
MailZu 0.8RC1 (03.23.2007):
----------
- Support for binary mail_text column of quarantine table. Since amavisd-new 2.4.4
the mail_text column was changed so that the data would not be affected by
the encoding of the database.
If you are using the binary type on this column, set
$conf['db']['binquar'] = True;
in your config.php.
- Support for recipient delimiters. New option in config.php.
$conf['recipient_delimiter'] = ''; // set to '+' or any delimiter
Only one character for the delimiter is supported. Contribution by Brice Figureau.
- mz_db_clean.pl - changed mysql query to use UTC_TIMESTAMP() by Brice Figureau.
- Removed default use of included PEAR DB and Mail libraries. The default is to use
system PEAR libraries instead.
- Made creation of search fields more dynamic and fixed alignment.
- Added Czech translation, contribution from Vladmir Volcko.
- Added Portuguese translation, contribution from Julio Cesar Webstarb Jr.
* Following changes implemented by Jeremy Fowler <jfowler06@users.sourceforge.net>
- New Summary totals table, group by date
- User Quarantine Summary: Added Viruses and Bad Headers for Addministrator users
- Added Site Quarantine Summary (Spam, Banned, Viruses, Bad Headers, Pending, Total)
- Added Viruses and Bad Headers to Search fields (Administrators Only)
- Added Content Type column
- Multiple email addresses (AD proxyAddresses)
- Adds To: column on table and searches for user quarantine
- Updated config.php.sample
- Query syntax tweaks
- config.php: s_admins/m_admins/restricted_users logins are now case insensitive
- Fixes non-US date format sorting on summaries. Reported by Alan Munday.
- Allow users to view quarantined Bad Header messages with option:
$conf['app']['allowBadHeaders']
- released automatically without admin approval
- Allow users to view quarantined Viruses (Dangerous, use with great trepidation)
$conf['app']['allowViruses']
- stored in Pending Requests for admin approval
- Allow users to search by Mailid
$conf['app']['allowMailid']
- New AmavisdEngine using PEAR::Net_Socket (included with safeMode Libraries)
- faster timeout
- better error reporting
- Fix "From:Array" when sending email from "Email Administrator". Reported by Serge Algarotti
- Can now have multiple adminEmail addresses:
$conf['app']['adminEmail'] = array('support@example.com', 'helpdesk@example.com');
- contrib/additional_indexes.sql: Highly recommended indexes to add to the amavisd database.
- Added 'X-Amavis-Alert' to the full headers list. Shows Banned File/Virus/Bad Heaeder info.
- Added "Loading Summary..." Message while summary queries are loading.
- Added style to list of sanitized tags.
- Fixes foreach data validation bug on invalid MIME messages
MailZu 0.7b:
----------
- Added compatibility for amavisd-new 2.4.0 or later database schema. Needed for
proper handling of file-based quarantining.
If you are currently using amavisd-new 2.4.0 or later, no changes are necessary.
If you are using a version of amavisd-new prior to 2.4.0 (with old database
schema), please add the 'quar_loc' column to your 'msgs' table with:
ALTER TABLE msgs ADD quar_loc varchar(255) DEFAULT '';
This is a mandatory requirement for this version and future versions of MailZu.
In other words, MailZu does not care which version of amavisd-new you are running,
as long as the SQL tables match those that are needed by amavisd-new 2.4.0 or
later.
- Specific SQL queries when listing a quarantine index tended to be optimized when
using MySQL only. These queries are now used only when the site configures MySQL
as their backend. Faster and efficient queries are now the default when any other
database is chosen.
- Admins should have been able to login even though the configuration parameter
login_restriction was set to 'true'. This was not the case and was fixed to work
as intended.
- In a quarantine index, deleting all the items on the last page would then return
a page with no results. Fixed. Reported by Paolo Cravero.
- In a quarantine index, using the "Delete All" button would delete the items on
the first page only. This has been fixed to include all items in a quarantine index.
MailZu 0.6:
----------
- Fix bug when displaying error message after a failed release
- Add a FAQ item on releasing emails and where to get support
- Add Spanish translation, contribution from Ricardo Muñoz
- Modify FAQ and INSTALL file to specify that MailZu only supports
amavisd-new greater than 2.3.0 and less than 2.4.0
MailZu 0.6RC5:
-------------
- Fix bug in authentication class. Bug reported and fixed by Andrew A. Neuschwander
- Define constants for method getGlobalVar(). Bug reported by Andrew A. Neuschwander
- Fix AD LDAP protocol support. Bug reported and fixed by Keith Becker
- Fix From address bug introduced by a change in ['sessionMail']. The latter used
to be a scalar, it is now an array. Bug reported by Rich Wales
- Add the language selection display option
- Fix Exchange authentication broken in 0.6RC4
MailZu 0.6RC4:
-------------
- Fix 'Delete All' localization issue; bug reported by Paolo Cravero
- Fix bug: doing a 'View Orignal' action as a non-privileged user the message source is not displayed
(Bug reported by Paolo Cravero)
- Add MailZu favicon
- Replace mailzu.png with mailzu.gif (transparent). Problem with background color when using PNG.
- Add condition to check if dn exists for LDAP Auth (bug reported by Paolo Cravero)
- Remove localization of mailzu logs
- Fix bug reported by Paolo Cravero: 'Showing messages x to y' was not working properly
- Update the French Help file
- Remove the incomplete Spanish translation
- Fix IMAP auth issue when no domain name is provided. Bug reported by Robert Wohleb.
- Add LDAP over SSL support for LDAP/AD authentication
- Add the option to view site quarantine in search only mode: no message will be displayed when
clicking on 'Site Quarantine', which saves lots of time especially for very larges sites.
MailZu 0.6RC3:
-------------
- Add Exchange 5.5 authentication (contribution from Bogdan Baliuc)
- Add IMAP authentication
- Fix bug in SQL authentication
- Fix bug where all messages were listed regardless of msgs.quar_type
- Add Italian language (contribution from Paolo Cravero)
- Make LDAP authentication more generic (suggestion from Paolo Cravero)
- Improve localization
- Improve error logging
- Clean up DBEngine, Quarantine and AmavisdEngine classes
- Add patch (PHP code) to support MySQL version prior to 4.1.x
- Modify the purging script to be compatible with other databases, run the
script with '--help' or '-h' to see the options.
MailZu 0.6RC2:
-------------
- upgrade PEAR DB
- fix compatibility issues with PostgreSQL in SQL queries
- fix bug by removing dependency to 'quarantine' table in some SQL queries
- modify SQL queries to improve overall speed when viewing quarantines

740
LICENSE Normal file
View File

@ -0,0 +1,740 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Library General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
GNU LESSER GENERAL PUBLIC LICENSE
Version 2.1, February 1999
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the Lesser GPL. It also counts
as the successor of the GNU Library Public License, version 2, hence
the version number 2.1.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Lesser General Public License, applies to some
specially designated software packages--typically libraries--of the
Free Software Foundation and other authors who decide to use it. You
can use it too, but we suggest you first think carefully about whether
this license or the ordinary General Public License is the better
strategy to use in any particular case, based on the explanations below.
When we speak of free software, we are referring to freedom of use,
not price. Our General Public Licenses are designed to make sure that
you have the freedom to distribute copies of free software (and charge
for this service if you wish); that you receive source code or can get
it if you want it; that you can change the software and use pieces of
it in new free programs; and that you are informed that you can do
these things.
To protect your rights, we need to make restrictions that forbid
distributors to deny you these rights or to ask you to surrender these
rights. These restrictions translate to certain responsibilities for
you if you distribute copies of the library or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link other code with the library, you must provide
complete object files to the recipients, so that they can relink them
with the library after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
We protect your rights with a two-step method: (1) we copyright the
library, and (2) we offer you this license, which gives you legal
permission to copy, distribute and/or modify the library.
To protect each distributor, we want to make it very clear that
there is no warranty for the free library. Also, if the library is
modified by someone else and passed on, the recipients should know
that what they have is not the original version, so that the original
author's reputation will not be affected by problems that might be
introduced by others.
Finally, software patents pose a constant threat to the existence of
any free program. We wish to make sure that a company cannot
effectively restrict the users of a free program by obtaining a
restrictive license from a patent holder. Therefore, we insist that
any patent license obtained for a version of the library must be
consistent with the full freedom of use specified in this license.
Most GNU software, including some libraries, is covered by the
ordinary GNU General Public License. This license, the GNU Lesser
General Public License, applies to certain designated libraries, and
is quite different from the ordinary General Public License. We use
this license for certain libraries in order to permit linking those
libraries into non-free programs.
When a program is linked with a library, whether statically or using
a shared library, the combination of the two is legally speaking a
combined work, a derivative of the original library. The ordinary
General Public License therefore permits such linking only if the
entire combination fits its criteria of freedom. The Lesser General
Public License permits more lax criteria for linking other code with
the library.
We call this license the "Lesser" General Public License because it
does Less to protect the user's freedom than the ordinary General
Public License. It also provides other free software developers Less
of an advantage over competing non-free programs. These disadvantages
are the reason we use the ordinary General Public License for many
libraries. However, the Lesser license provides advantages in certain
special circumstances.
For example, on rare occasions, there may be a special need to
encourage the widest possible use of a certain library, so that it becomes
a de-facto standard. To achieve this, non-free programs must be
allowed to use the library. A more frequent case is that a free
library does the same job as widely used non-free libraries. In this
case, there is little to gain by limiting the free library to free
software only, so we use the Lesser General Public License.
In other cases, permission to use a particular library in non-free
programs enables a greater number of people to use a large body of
free software. For example, permission to use the GNU C Library in
non-free programs enables many more people to use the whole GNU
operating system, as well as its variant, the GNU/Linux operating
system.
Although the Lesser General Public License is Less protective of the
users' freedom, it does ensure that the user of a program that is
linked with the Library has the freedom and the wherewithal to run
that program using a modified version of the Library.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, whereas the latter must
be combined with the library in order to run.
GNU LESSER GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library or other
program which contains a notice placed by the copyright holder or
other authorized party saying it may be distributed under the terms of
this Lesser General Public License (also called "this License").
Each licensee is addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also combine or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (1) uses at run time a
copy of the library already present on the user's computer system,
rather than copying library functions into the executable, and (2)
will operate properly with a modified version of the library, if
the user installs one, as long as the modified version is
interface-compatible with the version that the work was made with.
c) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
d) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
e) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the materials to be distributed need not include anything that is
normally distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties with
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Lesser General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS

17
README Normal file
View File

@ -0,0 +1,17 @@
MailZu
====================
http://www.mailzu.net
MailZu is a quarantine management interface for amavisd-new
( http://www.ijs.si/software/amavisd/ ).
It provides users and administrators access to email that is suspected to be
spam or contain banned contents and gives users the ability to release, request,
or delete these messages from their quarantine.
Users can access their personal quarantine by authenticating to various
pre-existent backends such as LDAP ( or Active Directory ) or any PHP PEAR
supported database.
See the INSTALL file in the docs/ directory included with this distribution.

452
config/config.php.sample Normal file
View File

@ -0,0 +1,452 @@
<?php
/**
* This file sets all the configuration options
* All configuration options, such as colors,
* text sizes, email addresses, etc.
* are set in this file.
* @author Samuel Tran <stran2005@users.sourceforge.net>
* @author Brian Wong <bwsource@users.sourceforge.net>
* @author Jeremy Fowler <jfowler06@users.sourceforge.net>
* @version 04-03-07
* @package MailZu
*/
/***************************************
* MailZu *
* Version 0.8 *
* http://www.mailzu.net *
* *
/***************************************/
/**
* Please refer to readme.html and LICENSE for any additional information
*
* Copyright (C) 2003 - 2007 MailZu
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the
* Free Software Foundation, Inc.
* 59 Temple Place
* Suite 330
* Boston, MA
* 02111-1307
* USA
*/
/*************************************************/
/* Instructions *
**************************************************
* + All words (string values) must *
* be enclosed in quotation marks *
* Numbers must not *
* *
* + Default values are *
* given in square brackets [] *
/*************************************************/
/**********
* Amavisd-new Settings
*
* The following settings must correspond to your amavisd-new setup
*
*
***********/
// Amavisd-new AM.PDP port
// Since the port number can not be stored in the database
// all instances of amavisd-new must use the same AM.PDP port
$conf['amavisd']['spam_release_port'] = '9998';
// Database type to be used by PEAR [mysql]
/* Options are:
mysql -> MySQL
pgsql -> PostgreSQL
ibase -> InterBase
msql -> Mini SQL
mssql -> Microsoft SQL Server
oci8 -> Oracle 7/8/8i
odbc -> ODBC (Open Database Connectivity)
sybase -> SyBase
ifx -> Informix
fbsql -> FrontBase
*/
$conf['db']['dbType'] = 'mysql';
// Database user who can access the amavisd database
$conf['db']['dbUser'] = 'user';
// Password for above user to access the amavisd database
$conf['db']['dbPass'] = 'pass';
// Name of database
$conf['db']['dbName'] = 'dbname';
// Database host specification (hostname[:port]) [localhost]
$conf['db']['hostSpec'] = 'hostname.example.com:3306';
// If using the bytea or BLOB mail_text quarantine type set to
// True. Since amavisd-2.4.4.
$conf['db']['binquar'] = false;
/**********
* Authentication Settings
*
* Choose your authentication method ($conf['auth']['serverType']),
* Then fill in the necessary auth information for corresponding method
*
***********/
// Available authentication methods
/* Options are:
ldap -> Standard LDAP server, e.g. OpenLDAP
ad -> MS Active Directory
sql -> PHP PEAR compatible database
exchange -> MS Exchange 5.5
imap -> IMAP protocol
*/
$conf['auth']['serverType'] = 'ldap';
/*** LDAP Authentication Settings ***/
// List of LDAP servers
$conf['auth']['ldap_hosts'] = array( 'ldaphost.example.com' );
// if set to true, LDAP connection over SSL (PHP 4.0.4 minimum)
// if set to false or not set, unencrypted LDAP connection on port 389
$conf['auth']['ldap_ssl'] = false;
// LDAP base dn, e.g. 'dc=example,dc=com'
$conf['auth']['ldap_basedn'] = 'dc=example,dc=org';
// LDAP attribute used for the RDN to identify a person
// For instance if the DN for a given user is uid=joesmith,ou=people,dc=example,dc=com
// the attribute would be 'uid'
$conf['auth']['ldap_user_identifier'] = 'uid';
// Container where all users are kept, e.g. 'ou=people'
// If you have users in multiple containers, leave this option blank.
// In this particular case you will need to allow anonymous binding
// or specify a search user/password to bind with
//$conf['auth']['ldap_user_container'] = 'ou=people';
$conf['auth']['ldap_user_container'] = '';
// LDAP attribute used as login, e.g. 'uid', 'mail' or 'uidNumber'
$conf['auth']['ldap_login'] = 'uid';
// LDAP attribute used as name for the welcome message, e.g. 'givenName', 'cn' or 'displayName'
$conf['auth']['ldap_name'] = 'givenName';
// LDAP mail attribute(s) used as the final recipient address
// Could be the actual mail attribute or another attribute
// (in the latter case look for the "%m" token in the ldap query filter in amavisd.conf)
$conf['auth']['ldap_mailAttr'] = array('mailRoutingAddress');
// If $conf['auth']['ldap_login'] is different from 'uid', we need to determine
// corresponding 'uid' by binding anonymously or with the user defined below.
// Leave blank for anonymous binding.
$conf['auth']['ldap_searchUser'] = '';
$conf['auth']['ldap_searchPassword'] = '';
/*** Active Directory Authentication Settings ***/
// List of AD Domain controllers
$conf['auth']['ad_hosts'] = array( 'dc1.example.com' );
// if set to true, LDAP connection over SSL (PHP 4.0.4 minimum)
// if set to false or not set, unencrypted LDAP connection on port 389
$conf['auth']['ad_ssl'] = false;
// AD base dn, e.g. 'dc=example,dc=com'
$conf['auth']['ad_basedn'] = 'dc=example,dc=com';
// AD domain, e.g. 'example.com'
$conf['auth']['ad_domain'] = 'example.com';
// AD attribute used to identify a person
$conf['auth']['ad_user_identifier'] = 'samaccoutname';
// AD attribute used as login, e.g. 'samaccountname' or 'mail'
$conf['auth']['ad_login'] = 'samaccountname';
// AD attribute used as name for the welcome message, e.g. 'givenName', 'cn' or 'displayName'
$conf['auth']['ad_name'] = 'givenName';
// AD mail attribute(s) used as the final recipient address
// Could be the actual mail attribute or another attribute
// (in the latter case look for the "%m" token in the ldap query filter in amavisd.conf)
// $conf['auth']['ad_mailAttr'] = array('mail'); // old
// For accounts with multiple email address aliases use proxyAddresses
$conf['auth']['ad_mailAttr'] = array('proxyAddresses');
// If $conf['auth']['ad_login'] is different from 'samaccountname', we need to determine
// corresponding 'samaccountname' by binding with the user defined below.
// Ad does not support anonymous bind
$conf['auth']['ad_searchUser'] = 'manager';
$conf['auth']['ad_searchPassword'] = 'secret';
/*** Database Authentication Settings ***/
// Database type to be used by PEAR
/* Options are:
mysql -> MySQL
pgsql -> PostgreSQL
ibase -> InterBase
msql -> Mini SQL
mssql -> Microsoft SQL Server
oci8 -> Oracle 7/8/8i
odbc -> ODBC (Open Database Connectivity)
sybase -> SyBase
ifx -> Informix
fbsql -> FrontBase
*/
$conf['auth']['dbType'] = 'mysql';
// Database host specification (hostname[:port]) [localhost]
$conf['auth']['dbHostSpec'] = '';
// Database user who can access the auth database
$conf['auth']['dbUser'] = '';
// Password for above user to auth database
$conf['auth']['dbPass'] = '';
// Name for auth database
$conf['auth']['dbName'] = '';
// Name for auth table that contains usernames and passwords
$conf['auth']['dbTable'] = '';
// Name of the Username field of the SQL table
$conf['auth']['dbTableUsername'] = '';
// Name of the password field of the SQL table
$conf['auth']['dbTablePassword'] = '';
// Name of the 'first name' or 'full name' field of the SQL table
// This is used for the welcome message
// If such a field does not exist, leave it blank
$conf['auth']['dbTableName'] = '';
// Name of the 'mail address' field of the SQL table
$conf['auth']['dbTableMail'] = '';
// Hash configuration
// true = passwords are md5 encrypted in database
// false = passwords are cleartext in database
$conf['auth']['dbIsMd5'] = true;
/*** Exchange 5.5 Authentication Settings ***/
// Exchange 5.5 server host and IMAP port (e.g.: 10.1.1.20:143)
$conf['auth']['exch_host'] = '';
// Exchange's LDAP server, it usually has the same IP as the Exchange server (e.g.: ldap://10.1.1.20)
$conf['auth']['exch_ldap'] = '';
// Exchange default NT domain
$conf['auth']['exch_domain'] = '';
/*** IMAP Authentication Settings ***/
// List of IMAP servers and ports (e.g.: 10.1.1.20:143)
$conf['auth']['imap_hosts'] = array( 'imaphost.example.com:143' );
// IMAP type
/* Options are:
imap -> default
imaptls -> do not do start-TLS to encrypt the session, even with servers that support it
imapssl -> use the Secure Socket Layer to encrypt the session
imapcert -> use the Secure Socket Layer to encrypt the session,
do not validate certificates from TLS/SSL server, needed if server uses self-signed certificates
*/
$conf['auth']['imap_type'] = 'imapssl';
// Domain name part of the email address, (e.g.: example.com)
$conf['auth']['imap_domain_name'] = 'example.com';
/**
* End of Authentication Settings
*/
/*** Permission listings ****/
/* The items you put in the admin lists
* must be the same as the login ID.
* Example:
* If you login as 'userid' then..
* conf['auth']['s_admins'] = array ('userid','userid2');
*
* OR
*
* If you login as 'userid@example.com' then...
* conf['auth']['s_admins'] = array ('userid@example.com',
* 'userid2@example.com'
* );
*
*/
// List of Super Admins
// Super Admins can do anything mail admins can plus
// change settings
$conf['auth']['s_admins'] = array ('user1', 'user2');
// List of Mail Admins
// Mail Admins can see other users' spam and attachments
// and can perform any action on them
$conf['auth']['m_admins'] = array ();
// User login restriction (Does not affect admins)
// If set to true, users will not be able to login. This is if you do
// not want users to view their quarantine, yet only have admins to
// view quarantines.
$conf['auth']['login_restriction'] = false;
// User restriction exemption
// List of users still allowed to login even if
// $conf['auth']['login_restriction'] = true
//
$conf['auth']['restricted_users'] = array('user1', 'user2');
/**********
* Miscellaneous Settings
*
* The following settings must correspond to your amavisd-new setup
*
***********/
// Image to appear at the top of each page ['img/mailzu.gif']
// Leave this string empty if you are not going to use an image
// Specifiy link as 'directory/filename.gif'
$conf['ui']['logoImage'] = 'img/mailzu.gif';
// Welcome message show at login page ['Welcome to MailZu!']
$conf['ui']['welcome'] = 'Welcome to MailZu!';
// The full url to the root directory of MailZu
// Please do not include the trailing slash
$conf['app']['weburi'] = 'https://mailzuhost.example.com/mailzu';
// How to send email ['mail']
/* Options are:
'mail' for PHP default mail
'smtp' for SMTP
'sendmail' for sendmail
'qmail' for qmail MTA
*/
$conf['app']['emailType'] = 'mail';
// SMTP email host address []
// This is only required if emailType is SMTP
$conf['app']['smtpHost'] = '';
// SMTP port [25]
// This is only required if emailType is SMTP
$conf['app']['smtpPort'] = 25;
// Path to sendmail ['/usr/sbin/sendmail']
// This only needs to be set if the emailType is 'sendmail'
$conf['app']['sendmailPath'] = '/usr/sbin/sendmail';
// Path to qmail ['/var/qmail/bin/sendmail']
// This only needs to be set if the emailType is 'qmail'
$conf['app']['qmailPath'] = '/var/qmail/bin/sendmail';
// Support for recipient delimiters
// Enter the character used as a delimiter for your site
// or leave empty
// $conf['recipient_delimiter'] = '+';
$conf['recipient_delimiter'] = '';
// The email addresses of the support staff and/or administrator
// An email is sent to these addresses when a user reports an error
// or clicks the "Email Administrator" link
$conf['app']['adminEmail'] = array('support@example.com');
// Email admin upon Release Request
// When users try to release a banned file a request is sent to an
// admin. Admins can always look at 'Pending Requests' in the MailZu
// interface regardless.
//
// $conf['app']['notifyAdmin'] = 1;
$conf['app']['notifyAdmin'] = 0;
// Show the "Email Administrator" link for users
// If you have a large userbase, you may not want users to have the
// capability to just email the admin
// Note: The "Report Error" link is still available regardless
// of this option. This link is only visible if a fatal error occurs
// with releasing attachments. Default is 1 (show link).
//
// $conf['app']['showEmailAdmin'] = 0;
$conf['app']['showEmailAdmin'] = 1;
// Site Quarantine Summary display toggle.
// Enable and display the "Site Quarantine Summary" link for admins.
// Viewing the site summary may be an expensive database query.
// Large sites may want to turn this off.
// $conf['app']['siteSummary'] = 1
$conf['app']['siteSummary'] = 1;
// Show Site Quarantine in search only mode if set to 1.
// No message is displayed when clicking on 'Site quarantine'.
// Keep the default for for large sites.
// $conf['app']['searchOnly'] = 1
$conf['app']['searchOnly'] = 1;
// The default language code. This must be included in the language list in
// langs.php
$conf['app']['defaultLanguage'] = 'en_US';
// Display the choice for language selection during the login screen if set to 1
// Otherwise set it to 0
// Default is 1
$conf['app']['selectLanguage'] = '1';
// If you are running PHP in safe mode, set this value to 1.
// This toggles if we use the included Pear DB and Mail_Mime libraries included
// with this distribution
$conf['app']['safeMode'] = 0;
// View time in 12 or 24 hour format [12]
// Only acceptable values are 12 and 24 (if an invalid number is set, 12 hour
// time will be used)
$conf['app']['timeFormat'] = 12;
// Title of application ['MailZu']
// Will be used for page titles and in 'From' field of email responses
$conf['app']['title'] = 'MailZu';
// If we should log system activity or not [0]
// Can be 0 (for no) and 1 (for yes)
$conf['app']['use_log'] = 1;
// If we should log additional debug information
$conf['app']['debug'] = 0;
// Directory/file for log ['/var/log/mailzu.log']
// Specify as /directory/filename.extension
$conf['app']['logfile'] = '/var/log/mailzu.log';
// Maximum number of messages displayed per page
$conf['app']['displaySizeLimit'] = 50;
// Allow users to view quarantined Bad Header messages
// Bad headers are treated like spam and released
// $conf['app']['allowBadHeaders'] = 0
$conf['app']['allowBadHeaders'] = 0;
// Allow users to view quarantined Viruses (Dangerous)
// Virues are treated like Banned files and are placed
// in the Pending Requests and require Admin release
// $conf['app']['allowViruses'] = 0
$conf['app']['allowViruses'] = 0;
// Allow users to search by Mailid
// $conf['app']['allowMailid'] = 0
$conf['app']['allowMailid'] = 0;
include_once('init.php');
?>

16
config/constants.php Normal file
View File

@ -0,0 +1,16 @@
<?
define('INTERNAL_DATE_SEPERATOR', '/');
define('RES_TYPE_ADD', 'r');
define('RES_TYPE_MODIFY', 'm');
define('RES_TYPE_DELETE', 'd');
define('RES_TYPE_VIEW', 'v');
define('RES_TYPE_APPROVE', 'a');
define('INVITE_ACCEPT', 'accept');
define('INVITE_DECLINE', 'decline');
define('MYCALENDARTYPE_DAY', 1);
define('MYCALENDARTYPE_WEEK', 2);
define('MYCALENDARTYPE_MONTH', 3);
define('MYCALENDARTYPE_SIGNUP', 4);
?>

0
config/index.html Normal file
View File

50
config/init.php Normal file
View File

@ -0,0 +1,50 @@
<?php
/**
* Initialization file. Please do not edit.
* @author Nick Korbel <lqqkout13@users.sourceforge.net>
* @version 10-25-04
* @package phpScheduleIt
*/
/**
* Please refer to readme.html and LICENSE for any additional information
*
* Copyright (C) 2003 - 2005 phpScheduleIt
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with
* this program; if not, write to the
* Free Software Foundation, Inc.
* 59 Temple Place
* Suite 330
* Boston, MA
* 02111-1307
* USA
*/
/********************************************************************/
/* DO NOT CHANGE THIS SECTION */
/********************************************************************/
// Start the session (do not edit!)
session_start();
// Turn off magic quotes (do not edit!)
set_magic_quotes_runtime(0);
$conf['app']['version'] = '0.8RC3';
include_once('constants.php');
include_once('langs.php');
if ($lang = determine_language()) { // Functions exist in the langs.php file
set_language($lang);
load_language_file($lang);
}
/********************************************************************/
?>

269
config/langs.php Normal file
View File

@ -0,0 +1,269 @@
<?php
/**
* All functions for determining and loading language files and for
* translating the text
* A few ideas and techniques were taken from the phpMyAdmin project
* @author Nick Korbel <lqqkout13@users.sourceforge.net>
* @version 03-14-05
* @package Languages
*
* Copyright (C) 2003 - 2005 phpScheduleIt
* License: GPL, see LICENSE
*/
/**
* You must add the language infomation for the language that you are including to the
* $languages array below.
* Please keep the language keys in alphabetical order. The basic logic for this array
* is from the phpMyAdmin project.
*
* 1) The first 2 letters are the official language code.
*
* 2) The array must follow this order:
* The first element is a regular expression that validates against possible
* ways to identify the language and is in this format:
* + The official language code and the dialect code (country code) if it is needed.
* For example for all English translations: en([-_][[:alpha:]]{2})?, for Bulgarian: 'bu'
* In any case where there is more than one dialect, it should follow the English format
* In any case where there is only one dialect, it should follow the Bulgarian format
* + the '|' character
* + the full language name (lowercase)
* The second element is the full file name of this translation. This file name should
* always be in the format: 2 letter language code, the word 'lang', the '.php' extension
* For example for all English translatinos: en.lang.php
* The third element is the official two letter language code
* The final element is the full language name. This will appear in the language
* pull down selection menu on the login page. Please capatalize the first letter
*
* If you are unsure of your language/dialect codes, please use the following resources -
* + Standard language codes: http://www.unicode.org/unicode/onlinedat/languages.html
* + Standard country codes: http://www.unicode.org/unicode/onlinedat/countries.html
*/
$languages = array (
'en_US' => array('en([-_]us)?|english', 'en_US.lang.php', 'en', 'English US'),
'en_GB' => array('en([-_]gb)?|english', 'en_GB.lang.php', 'en', 'English GB'),
'es' => array('es([-_][[:alpha:]]{2})?|spanish', 'es.lang.php', 'es', 'Español'),
'cs' => array('cs([-_][[:alpha:]]{2})?|czech', 'cs.lang.php', 'cs', '&#268;esky'),
'fr' => array('fr([-_][[:alpha:]]{2})?|french', 'fr.lang.php', 'fr', 'Fran&ccedil;ais'),
'it' => array('it([-_][[:alpha:]]{2})?|italian', 'it.lang.php', 'it', 'Italiano'),
'pt_BR' => array('pt([-_]br)?|portuguese', 'pt_BR.lang.php', 'pt', 'Portuguese Brazilian')
);
// Language files directory
@define('LANG_DIR', dirname(__FILE__) . '/../lang/');
/**
* Tries to determine the langauge for this user by
* going though all options.
* @param none
* @return mixed language if it can be determined, or false if it cannot
*/
function determine_language() {
global $conf;
$lang = false;
// Set the language
if (isset($_GET['lang']) && !empty($_GET['lang'])) {
$lang = $_GET['lang'];
}
else if (isset($_COOKIE['lang']) && !empty($_COOKIE['lang'])) {
$lang = $_COOKIE['lang'];
}
else if (isset($_SESSION['lang']) && !empty($_SESSION['lang'])) {
$lang = $_SESSION['lang'];
}
else if ($lang = get_browser_lang()) {
// Do nothing, it's done in the if
}
else {
$lang = $conf['app']['defaultLanguage'];
}
return $lang;
}
/**
* Loads the language file
* @param none
*/
function load_language_file() {
global $languages;
global $lang;
// Load the language file
if (isset($languages[$lang]) && file_exists(LANG_DIR . $languages[$lang][1])) {
include_once(LANG_DIR . $languages[$lang][1]);
global $charset;
header("Content-Type: text/html; charset=$charset");
header("Content-Language: {$languages[$lang][2]}");
}
else {
die('Could not load language file: ' . $languages[$lang][1]);
setcookie('lang', '', time() - 2592000, '/');
}
}
/**
* Tries to detect the language based on the current browser settings
* @param none
* @return mixed language value if it can be found, false if it cannot be found
*/
function get_browser_lang() {
global $languages;
if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && !empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) {
$http_accepted = split(',',$_SERVER['HTTP_ACCEPT_LANGUAGE']);
for ($i = 0; $i < count($http_accepted); $i++) {
foreach ($languages as $lang => $vals) {
if (eregi($vals[0], $http_accepted[$i]))
return $lang;
}
}
}
return false; // If we get here, it wasnt found
}
/**
* Sets the session variable for $lang so we do not need to go
* through the determining process each time
* @param string $lang language of current user
*/
function set_language($lang) {
global $languages;
global $conf;
if (!isset($languages[$lang])) {
$lang = $conf['app']['defaultLanguage'];
}
@session_start();
setlocale(LC_ALL, $lang);
setcookie('lang', $lang, time() + 2592000, '/');
}
/**
* Translate the given string into the current lanaguage
* If the trasnlation does not exist, returns the default
* lanaguage translation
* @param string $str string to translate
* @param array $vars optional array of variables to pass to a sprintf translation string
*/
function translate($str, $args = array()) {
global $strings;
$return = '';
if (!isset($strings[$str]) || empty($strings[$str])) {
return '?';
}
if (empty($args)) {
return $strings[$str];
}
else {
$sprintf_args = '';
for ($i = 0; $i < count($args); $i++) {
$sprintf_args .= "'" . addslashes($args[$i]) . "',";
}
$sprintf_args = substr($sprintf_args, 0, strlen($sprintf_args) - 1);
$string = addslashes($strings[$str]);
$return = eval("return sprintf('$string',$sprintf_args);");
return $return;
}
}
/**
* Translates an email message to the proper language
* @param string $email_index index of the email to translate from the lang.php file
* @param mixed unlimited number of arguments to be placed inline into the email
* @return translated email message
*/
function translate_email($email_index) {
global $email;
$return = '';
$args = func_get_args();
if (!isset($email[$email_index]) || empty($email[$email_index])) {
return '?';
}
if (func_num_args() <= 1) {
return $email[$email_index];
}
else {
$sprintf_args = '';
for ($i = 1; $i < count($args); $i++) {
$sprintf_args .= "'" . addslashes($args[$i]) . "',";
}
$sprintf_args = substr($sprintf_args, 0, strlen($sprintf_args) - 1);
$return = eval('return sprintf("' . str_replace('"','\"',$email[$email_index]) . "\",$sprintf_args);");
return $return;
}
}
/**
* Returns a formatted date for current section
* @param string $date_index index of date to get
* @return formatted date for that index
*/
function translate_date($date_index, $date) {
global $dates;
global $days_full;
global $days_abbr;
global $months_abbr;
global $months_full;
if (!isset($dates[$date_index]) || empty($dates[$date_index])) {
return '?';
}
$date_format = $dates[$date_index];
// This takes care of when day/month names are not translated by PHP
if (strpos($date_format, '%a') !== false) {
$date_format = str_replace('%a', '+d', $date_format);
$day_name = $days_abbr[date('w', $date)];
}
if (strpos($date_format, '%A') !== false) {
$date_format = str_replace('%A', '+d', $date_format);
$day_name = $days_full[date('w', $date)];
}
if (strpos($date_format, '%b') !== false) {
$date_format = str_replace('%b', '+m', $date_format);
$month_name = $months_abbr[date('n', $date)-1];
}
if (strpos($date_format, '%B') !== false) {
$date_format = str_replace('%B', '+m', $date_format);
$month_name = $months_full[date('n', $date)-1];
}
$return = strftime($date_format, $date);
if (isset($day_name)) {
$return = str_replace('+d', $day_name, $return);
}
if (isset($month_name)) {
$return = str_replace('+m', $month_name, $return);
}
return $return;
}
/**
* Returns the array of lanugages
* @param none
* @return array of languages
*/
function get_language_list() {
global $languages;
return $languages;
}
?>

View File

@ -0,0 +1,2 @@
-- Index the content field, improves summary queries
CREATE INDEX msgs_idx_content ON msgs (content);

View File

@ -0,0 +1,34 @@
Index: lib/DBEngine.class.php
===================================================================
--- lib/DBEngine.class.php (revision 176)
+++ lib/DBEngine.class.php (working copy)
@@ -316,11 +316,18 @@
$msg_status = $cur_msg_array[0];
if ($msg_status['rs'] == 'p' && $flag == 'v') return true;
+ $query0 = 'SELECT id FROM maddr WHERE email=?';
+ $values0 = array($mail_rcpt);
+ $q0 = $this->db->prepare($query0);
+ $result0 = $this->db->execute($q0, $values0);
+ $rs0 = $result0->fetchRow();
+ $id = $rs0['id'];
+
$query = 'UPDATE msgrcpt SET rs=?'
. ' WHERE mail_id=?'
- . ' AND rid=(SELECT id FROM maddr WHERE email=?)';
+ . ' AND rid=?';
- $values = array($flag, $mail_id, $mail_rcpt);
+ $values = array($flag, $mail_id, $id);
// Prepare query
$q = $this->db->prepare($query);
@@ -329,6 +336,8 @@
// Check if error
$this->check_for_error($result, $query);
+ $result0->free();
+
return true;
}

472
css.css Normal file
View File

@ -0,0 +1,472 @@
/* Last modified 01-24-05 */
body {
font-family: Verdana, Arial, Helvetica, sans-serif;
background-color: #F0F0F0;
margin-top: 5px;
margin-right: 5px;
margin-bottom: 5px;
margin-left: 5px;
color: #333333;
font-size: 11px;
}
a {
/*color: #104E8B;*/
color: #1089CF;
text-decoration: none;
}
a:hover {
color: #474747;
text-decoration: underline;
}
/*
Common text settings
*/
p {
font-size: 11px;
margin-bottom: 2px;
margin-top: 2px;
margin-right: 2px;
margin-left: 2px;
}
h5 {
margin-bottom: 0px;
margin-top: 0px;
font-size: 12px;
}
h4 {
font-size: 13px;
}
h3 {
font-size: 18px;
margin-top: 0px;
}
/*
Error box settings
*/
.alert {
color: #CC0000;
background-color: #FFFFFF;
text-align: center;
width: 60%;
/*border: solid #8B0000 2px;*/
border: solid #CC0000 2px;
padding: 5px;
margin-bottom: 5px;
font-size: 11px;
}
/*
Form text box settings
*/
.textbox {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 11px; /*color: #36648B;*/
color: #05609A;
background-color: #FCFCFC;
}
/*
Form button settings
*/
.button {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 10px;
font-weight: bold;
border: solid 1px #7C7A7A;
/*color: #36648B;*/
color: #05609A;
background-color: #E7E7E7;
}
/*
Data table head row settings
*/
.tableTitle {
font-size: 11px;
font-weight: bold;
color: #FFFFFF;
padding-left: 10px;
padding-top: 1px;
padding-bottom: 1px;
padding-right: 5px; /* background-color: #36648B;*/
background-color: #05609A;
}
.tableTitle a, .tableTitle a:hover {
color: #FFFFFF;
text-decoration: none;
}
/*
Welcome message settings
*/
.welcomeBack {
margin-top: 0px;
margin-right: 0px;
margin-bottom: 0px;
margin-left: 0px;
/*color: #708090;*/
color: #05609A;
font-size: 12px;
}
/*
Table border color
*/
.tableBorder {
/* background-color: #36648B; */
background-color: #05609A;
}
/*
Common data cell settings
*/
td.cellColor, .cellColor td, .cellColor {
padding: 2px;
background-color: #FFFFFF;
font-size: 11px;
}
/*
Alternating row colors
Got rid of the contextual selector '.cellColor0 td'
*/
.cellColor0, td.cellColor0 {
padding: 2px;
background-color: #FFFFFF;
font-size: 11px;
}
td.cellColor1, .cellColor1 {
padding: 2px;
background-color: #F8FAEA;
font-size: 11px;
}
/*
Special Alternating row colors for viruses
*/
td.cellVirus, .cellVirus0 {
padding: 2px;
background-color: #FFCCFF;
font-size: 11px;
}
td.cellVirus, .cellVirus1 {
padding: 2px;
background-color: #FF99FF;
font-size: 11px;
}
/*
Content Type Column Virus Bolding
*/
td.typeVirus, .typeVirus td {
font-weight: bold;
}
/*
Table data row heading settings
*/
td.rowHeaders, .rowHeaders td {
color: #333333;
background-color: #EDEDED;
font-weight: bold;
text-align: center;
font-size: 11px;
}
/*
Summary Table Number values
*/
td.rowNumValues, .rowNumValues td {
text-align: right;
padding-right: 5px;
}
/*
Summary Table Totals
*/
td.rowTotals, .rowTotals td {
font-weight: bold;
text-align: right;
padding-right: 5px;
}
/*
Individal time cells for the scheduler
*/
td.scheduleTimes, .scheduleTimes td {
font-size: 11px;
color: #333333;
text-align: left;
background-color: #EDEDED;
padding-left: 2px;
}
/*
Date cell for the scheduler
*/
td.scheduleDate, .scheduleDate td {
font-size: 11px;
color: #FFFFFF;
background-color: #4BB5F2;
text-align: center;
padding: 2px;
}
td.scheduleDate a {
color: #FFFFFF;
}
/*
Resource name cell for the scheduler
*/
td.resourceName {
color: #333333;
font-size: 11px;
background-color: #EDEDED;
padding-left: 5px;
padding-top: 2px;
padding-bottom: 2px;
padding-right: 5px;
}
/*
Edit form cell settings
*/
td.formNames {
font-size: 11px;
background-color: #EDEDED;
padding-left: 5px;
}
/*
Reserved cell settings for the scheduler
*/
td.reservedCell {
font-size: 10px;
background-color: #C5E7F9;
}
/*
Inactive resource text color
*/
.inact {
color: #BDBDBD;
}
/*
Color of the outermost border on every page
*/
.mainBorder {
border: solid 1px #CCCCCC;
}
/*
Background color of main section on every page
*/
.mainBkgrdClr {
background-color: #FAFAFA;
}
/*
Alert message settings
*/
.message {
background-color: #FEFEFE;
text-align: center;
width: 60%;
border: solid #E0E0E0 1px;
padding: 5px;
margin-bottom: 5px;
font-size: 11px;
}
/*
Summary popup box
*/
.summary_div {
position: absolute;
visibility: hidden;
border: solid #686767 1px;
padding: 3px;
background-color: #E1E1E1;
overflow: visible;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 11px;
}
/*
Recurring reservation box
*/
.recur_box {
background-color: #D0D4E4;
color: #282D42;
border: solid 1px #8B94B1;
}
/*
Calendar settings
*/
.monthNameStyle {
font-size: 11px;
text-align: center;
}
.dayBoxStyle {
font-size: 10px;
background-color: #F0F0F0;
text-align: center;
width: 25px;
height: 25px;
}
.currentDayBoxStyle {
width: 25px;
height: 25px;
font-size: 10px;
background-color: #FFFFFF;
text-align: center;
}
.emptyDayStyle {
background-color: #D5D8D3;
}
.dayNamesStyle {
font-size: 11px;
text-align: center;
height: 25px;
background-color: #DDCAF6;
}
.navMonthStyle {
font-size: 11px;
color: #000000;
}
.selectBoxStyle {
font-size: 11px;
font-family: Verdana, Arial, Helvetica, sans-serif;
}
/* Reservation tab select */
.tab-row td {
text-align: center;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 11px;
padding-top: 3px;
padding-bottom: 2px;
}
.tab-row a {
text-decoration:none;
}
.tab-selected {
border-right:solid 1px #CCCCCC;
border-top:solid 1px #CCCCCC;
border-left:solid 1px #CCCCCC;
width:100px;
color: #0000ff;
height:20px;
}
.tab-selected a {
color: #000000;
}
.tab-not-selected {
border:solid 1px #D1D1D1;
width:100px;
background-color: #EDEDED;
border-bottom: solid 1px #CCCCCC;
}
.tab-not-selected a {
color: #666666;
}
.tab-filler {
border-bottom:solid 1px #CCCCCC;
}
.tab-main {
border-right:solid 1px #CCCCCC;
border-left:solid 1px #CCCCCC;
border-bottom:solid 1px #CCCCCC;
}
/*************************************
/** MyCalendar **/
.MyCalCellColor {
padding: 2px;
background-color: #FFFFFF;
font-size: 11px;
}
.MyCalCellColorEmpty {
background-color: #F0F0F0;
}
.MyCalDayBox {
padding: 2px;
background-color: #FFFFFF;
font-size: 11px;
width: 140px;
height: 120px;
vertical-align: top;
}
.MyCalEmptyDayBox {
padding: 2px;
background-color: #EEEEEE;
font-size: 11px;
vertical-align: top;
}
.MyCalCurrentDayBox {
padding: 2px;
background-color: #FFFFFF;
font-size: 11px;
vertical-align: top;
border: solid 1px #36648B;
}
.MyCalDateNumber, a.MyCalDateNumber {
font-size: 12px;
}
.MyCalCellColor p, .MyCalDayBox p, .MyCalEmptyDayBox p, .MyCalCurrentDayBox p {
margin-bottom: 7px;
}
div.mycal_div {
position: absolute;
visibility: hidden;
/*
border-top: solid #BCBB6E 1px;
border-left: solid #BCBB6E 1px;
border-right: solid #BCBB6E 2px;
border-bottom: solid #BCBB6E 2px;
background-color: #FEFEDA;
*/
border-top: solid #7C7C7C 1px;
border-left: solid #7C7C7C 1px;
border-right: solid #6F6F6F 2px;
border-bottom: solid #6F6F6F 2px;
background-color: #FEFFFE;
padding: 3px;
overflow: visible;
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 11px;
color: #616161;
}
/* SelectUser colors */
.SelectUserRowOver, .SelectUserRowOver td, td.SelectUserRowOver {
background-color: #A2D9F8;
padding: 2px;
font-size: 11px;
}
/* Selected Link */
.selectedLink {
font-size: 11px;
background-color: #D8EFFB;
padding: 2px;
}
/* Header Cells */
.headerName {
border: 1px solid #0F93DF;
background-color: #D8EFFB;
padding: 2px;
width: 10px;
font-size: 11px;
}
.headerValue {
border:solid 1px #0F93DF;
border-right: none;
padding: 2px;
font-size: 11px;
}
.stdFont {
font-size: 11px;
}
.visible {
}
.hidden {
display: none;
}

70
docs/AD_README Normal file
View File

@ -0,0 +1,70 @@
Active Directory Autentication Settings
----------------------------------------
To configure MailZu to authenticate users against Active Directory.
Edit the config/config.php and tailor the variables mentioned here for your
environment.
// Set an authentication method: 'ldap','ad', or 'sql'
$conf['auth']['serverType'] = 'ad';
Set the AD host(s) and search base
// List of AD Domain controllers
$conf['auth']['ad_hosts'] = array( 'dc1.example.com' );
// if set to true, LDAP connection over SSL (PHP 4.0.4 minimum)
// if set to false or not set, unencrypted LDAP connection on port 389
$conf['auth']['ad_ssl'] = false;
// AD base dn, e.g. 'dc=example,dc=com'
$conf['auth']['ad_basedn'] = 'dc=example,dc=com';
Set the Active Directory domain:
// AD domain, e.g. 'example.com'
$conf['auth']['ad_domain'] = 'example.com';
Set the attribute usually used to identify a user in Active Directory:
// AD attribute used to identify a person
$conf['auth']['ad_user_identifier'] = 'samaccoutname';
Now we must set the login format. For AD the default is the 'samaccountname'
attribute, or if you want a fully qualified email address as the login, it
could be 'mail'.
// AD attribute used as login, e.g. 'samaccountname' or 'mail'
$conf['auth']['ad_login'] = 'samaccountname';
At the login page of MailZu, with this setting the user would use the login
'user', or if the configuration variable was set to the 'mail' attribute, the
login would be 'user@example.com'.
These two attributes are enough to be authenticated to the MailZu interface,
but the third attribute is what determines which messages the authenticated
user is permitted to view. This attribute is the final recipient address. It is
the email address that amavisd-new reports as the envelope recipient.
For example, if the login used was 'user', than there must be an attribute or
field that determines the email address associated with this user. Even if the
login was 'user@example.com' the third attribute may or may not be the same.
The address might have been aliased to an internal address
'user@internal.example.com'.
// AD mail attribute used as the final recipient address
// Could be the actual mail attribute or another attribute
// (in the latter case look for the "%m" token in the ldap query filter in
// amavisd.conf)
$conf['auth']['ad_mailAttr'] = 'mail';
If the attribute listed for the login format is not the same as the binding
username, we must be able to search the directory. The settings below binds
using this account to search the directory. AD does not allow anonymous
binds.
$conf['auth']['ad_searchUsername'] = 'manager';
$conf['auth']['ad_searchPassword'] = 'secret';
If you want to specify the name of the user in the welcome message, you need to set the parameter below. AD attribute such as 'g
ivenName', 'cn' or 'displayName' can be used:
$conf['auth']['ad_name'] = 'givenName';

31
docs/CREDITS Normal file
View File

@ -0,0 +1,31 @@
MailZu Credits:
---------------
* Project Creators:
- Samuel Tran <stran2005@users.sourceforge.net>
- Brian Wong <bwsource@users.sourceforge.net>
* Project Principal Developers:
- Samuel Tran <stran2005@users.sourceforge.net>
- Brian Wong <bwsource@users.sourceforge.net>
* Project Developers/Patch Writers:
- Nicolas Peyrussie <peyrouz@users.sourceforge.net>
* Translators:
- Brian Wong <bwsource@users.sourceforge.net> English
- Nicolas Peyrussie <peyrouz@users.sourceforge.net> French
- Paolo Cravero Italian
- Samuel Tran <stran2005@users.sourceforge.net> French
- Ricardo Muñoz Spanish
* Special Thanks to:
- Nick Korbel who allowed us to re-use some codes
from his excellent project PHPScheduleIt (http://www.php.brickhost.com/index.php).
MailZu is based on PHPScheduleIt framework for a more rapid development.
* Contributors:
- Bogdan Baliuci: Exchange 5.5 authentication
- Paolo Cravero: Italian translation and suggestions to improve LDAP authentication
- Ricardo Muñoz: Spanish translation
- Andrew A. Neuschwander: lots of debugging

29
docs/EXCHANGE_5.5_README Normal file
View File

@ -0,0 +1,29 @@
Exchange 5.5 Autentication Settings
-----------------------------------
To configure MailZu to authenticate users against Exchange 5.5,
edit the config/config.php and tailor the variables mentioned here for your
environment.
// Set an authentication method: 'ldap','ad', 'sql' or 'exchange' (Exchange 5.5)
$conf['auth']['serverType'] = 'exchange';
These three attributes are enough to be authenticated to the MailZu interface:
// Exchange 5.5 server host and IMAP port
$conf['auth']['exch_host'] = '10.1.1.20:143';
// Exchange's LDAP server, it usually has the same IP as the Exchange server
$conf['auth']['exch_ldap'] = '10.1.1.20';
// Exchange default NT domain
$conf['auth']['exch_domain'] = 'mycorp';
At the MailZu login, enter the user NT login as username.
This code may not work if the user's Exchange alias is different from the NT login.
Thanks to Bogdan Baliuci <b.baliuc@rogers.com> for his code contribution.

70
docs/FAQ Normal file
View File

@ -0,0 +1,70 @@
Frequently Asked Questions
=======================================
1) What is MailZu?
MailZu is a quarantine management interface for amavisd-new. It allows
users to view their quarantined items and request release (for suspect malware),
release, or mark them for deletion.
2) What version of amavisd-new do I need?
MailZu will work with amavisd-new greater than 2.3.0.
3) Does MailZu support multiple amavisd-new instances?
Yes. If every amavisd-new instance in your environment stores its data into
the same SQL database there should be no problem. The only limitation is that
the AM.PDP protocol must listen on the same port for each amavisd-new
instance.
4) Do I have to configure amavisd-new to quarantine email to SQL?
No. MailZu does not require that the actual message bodies be kept in SQL.
Release is handled by amavisd-new, so MailZu need not be aware of the location
of the quarantine. Quarantine to SQL is only neccessary if you want your users
to be able to view spam in the MailZu interface, otherwise they will only see
the basic headers of the quarantined message.
5) Why do some or all messages in the MailZu message index not viewable?
The reason might be that email is not quarantined to SQL. This can be enabled
by setting these variables in amavisd-new:
$banned_files_quarantine_method = 'sql:';
$spam_quarantine_method = 'sql:';
6) Releasing messages does not seem to work. What is wrong?
There may be a couple of reasons for this behavior. The most common problems
is that PHP is not built with sockets enabled ( --enable-sockets ), or it is
a network related issue.
The first problem is easy to diagnose and fix. If releasing emails is still
not working, then we have to diagnose the network problem.
It is important to understand that in order for MailZu to support more than
one amavisd-new instance, it must connect to the appropriate host. The correct
host is retrieved from the SQL record inserted by amavisd-new. Check the 'host'
column of the 'msgs' table. Please make sure that you can connect to the AM.PDP
port of the host listed in that record from the host that runs MailZu.
user@mailzuhost# telnet <host in SQL record> <AM.PDP port>
If a connection is not made, then review your amavisd-new configuration regarding
the interfaces it listens on, and the ACLs regarding connecting clients. Be
careful, the AM.PDP protocol does not send a greeting or any data whatsoever on
a successful connection. It may appear that a connecion did not work, when in fact
it did.
7) Where can I get support?
If you are having a problem with MailZu and the solution is not obvious, take
a look at the mailing list archive at:
http://sourceforge.net/mailarchive/forum.php?forum=mailzu-users
and/or subscribe at this URL:
https://lists.sourceforge.net/lists/listinfo/mailzu-users

37
docs/IMAP_README Normal file
View File

@ -0,0 +1,37 @@
IMAP Autentication Settings
---------------------------
To configure MailZu to authenticate users against IMAP,
edit the config/config.php and tailor the variables mentioned here for your
environment.
Select the IMAP authentication method:
/* Options are:
ldap -> Standard LDAP server, e.g. OpenLDAP
ad -> MS Active Directory
sql -> PHP PEAR compatible database
exchange -> MS Exchange 5.5
imap -> IMAP protocol
*/
$conf['auth']['serverType'] = 'imap';
These three attributes are enough to be authenticated to the MailZu interface:
/*** IMAP Authentication Settings ***/
// List of IMAP servers and ports (e.g.: 10.1.1.20:143)
$conf['auth']['imap_hosts'] = array( 'imap.example.com:993' );
// IMAP type
/* Options are:
imap -> default
imaptls -> do not do start-TLS to encrypt the session, even with servers that support it
imapssl -> use the Secure Socket Layer to encrypt the session
imapcert -> use the Secure Socket Layer to encrypt the session,
do not validate certificates from TLS/SSL server, needed if server uses self-signed certificates
*/
$conf['auth']['imap_type'] = 'imapssl';
// Domain name part of the email address, (e.g.: example.com)
$conf['auth']['imap_domain_name'] = 'example.com';

416
docs/INSTALL Normal file
View File

@ -0,0 +1,416 @@
Installation instructions for MailZu
=======================================
MailZu, a quarantine management interface for amavisd-new. It allows users
and administrators to view quarantined messages and release, request, or
delete them.
MailZu need not reside on the same host as amavisd-new. MailZu also supports
environments with multiple amavisd-new instances (as long as all instances
report to the same SQL database). MailZu is only suitable for amavisd-new
versions greater than 2.3.0.
Requirements
===============
MailZu requires that amavisd-new has SQL reporting enabled. If you want
users to be able to view more than just the simple message headers, quarantining
to SQL should be enabled.
The requirements for running MailZu is as follows:
1) Amavisd-new greater than 2.3.0.
2) A PHP-compatible web server
3) PHP 4.3.x or greater with socket support ( --enable-sockets )
4) PEAR::PEAR
5) PEAR::DB
6) PEAR::Mail_Mime
7) PEAR::Net_Socket
PHP must also be built with the respective driver for your backend.
For LDAP or Active Directory PHP must be built with '--with-ldap'.
For the database backends you can use '--with-pgsql', '--with-mysql',
etc.
For the included and optional database cleanup script
(scripts/mz_db_clean.pl):
1) Perl 5.6
2) Perl DBI with respective database driver
MailZu utilizes the recommended values for the SQL field msgrcpt.rs as
stated in the README_FILES/README.sql that comes with the amavisd-new
distribution. The cleanup script performs database purging based on old
records and those messages marked for deletion 'D'. If you already have a
script which performs database maintenance, it is recommeneded to quickly
look through the queries in the provided script and merge them.
AMAVISD-NEW SQL REQUIREMENTS
==============================
If you are currently using amavisd-new 2.4.0 or later, no changes are necessary.
If using MySQL, please make sure that you use the TIMESTAMP type for the
database field 'time_iso'. Please refer to the amavisd-new documentation for
details.
If you are using a version of amavisd-new prior to 2.4.0 (with old database
schema), please add the 'quar_loc' column to your 'msgs' table with:
ALTER TABLE msgs ADD quar_loc varchar(255) DEFAULT '';
This is a mandatory requirement for this version and future versions of MailZu.
In other words, MailZu does not care which version of amavisd-new you are running,
as long as the SQL tables match those that are needed by amavisd-new 2.4.0 or
later.
Unpacking the distribution
============================
Fetch the latest tarball from http://www.mailzu.net. The file has a format
of mailzu-x.y.tar.gz where 'x' is the version and 'y' is the revision.
Extract the archive with:
# tar xvfz mailzu-x.y.tar.gz
# cd mailzu-x.y
Overview
================
The amavisd, SQL, and MailZu services act together to offer a complete
quarantine management interface. The relationship is as follows:
-- Amavisd-new populates the SQL database with basic information about every
message processed and optionally quarantining malware to the database
-- MailZu reads from the basic information from the SQL database to give a
webmail like view of quarantined items. If the item was quarantined to the
database, MailZu can also allow viewing of the complete email.
-- MailZu requests the release of email by opening a TCP/IP socket to the
responsible amavisd-new instance. Amavisd-new itself then queries the
database for the message information and releases the email to the user.
These services may reside on one particular hosts or a seperate host for each
application. MailZu cannot communicate to Amavisd-new through a unix socket.
Configuration
================
In order to use MailZu, amavisd-new must be configured to store message
information in an SQL database.
Amavisd-new Configuration
---------------------------
All configuration variables mentioned in this subsection are meant for
amavisd-new.
MailZu is not required to reside on the same host amavisd-new does, but
MailZu must be able to communicate with all instances of amavisd-new in your
environment to release messages.
Since MailZu can support multiple amavisd-new instances it
is important that the mechanism for communication is TCP/IP, not unix
sockets.
Information about every message processed by amavisd-new can be stored in
SQL by setting the amavisd-new configuration variable @storage_sql_dsn.
# Example setting:
@storage_sql_dsn =
( ['DBI:mysql:database=mail;host=127.0.0.1;port=3306', 'user',
'passwd']);
or:
@storage_sql_dsn = @lookup_sql_dsn; # If you plan to use the same database
# as the SQL lookups
Specify the ports that amavisd-new should bind to.
$inet_socket_bind = undef; # Bind on all interfaces
# or check amavisd.conf-sample for
# more specific examples
$inet_socket_port = [10024,9998]; # listen on this local TCP port(s)
(see $protocol)
Specify an arbitrary policy name tied for this port. 'AM.PDP' is recommended
for clarity.
$interface_policy{'9998'} = 'AM.PDP';
Associate a policy bank to that port where the protocol is 'AM.PDP' and
restrict access to that port to the host that MailZu is configured and any
additional hosts you desire.
$policy_bank{'AM.PDP'} = {
protocol => 'AM.PDP',
inet_acl => [qw( 127.0.0.1 [::1] <IP of MailZu host> )],
};
The configuration settings above is the minimal setting required by MailZu.
This allows MailZu to give an index of all messages that were considered spam
or banned. The index displays the To (admins only), From, Subject, Date, and
spam Score, for each message.
If you want users to be able to view the body of their spam messages via MailZu,
you must configure amavisd-new to quarantine messages to SQL. This can be done
with
$banned_files_quarantine_method = 'sql:';
$spam_quarantine_method = 'sql:';
This optional setting has no impact on MailZu's capability to release or
request mail.
Reload amavisd-new and try initiating a telnet session from the MailZu host to
the AM.PDP port
# telnet <Amavisd-new Host> 9998
If a connection is made than configuration of amavisd-new was successful.
Repeat this configuration procedure for every amavisd-new instance.
MailZu Configuration
----------------------
The configuration file for MailZu resides in config/config.php. The settings in
this file determines the authentication mechanism, the administrators, the
AM.PDP port used in your amavisd-new configuration, and other miscellaneous
settings.
The configuration file is populated with helpful comments that explain every
variable and their possible settings. Only the most important settings will be
discussed here.
Amavisd-new related settings
-------------------------------
For MailZu to display message indices and perform actions on the message in
question, it must be able to communicate with the amavisd-new instances and the
database which stores message information. MailZu requires the same read/write
credentials as amavisd-new in order to mark mail read or for deletion.
First specify the port where the AM.PDP protocols listens on. This is the same
port we specified earlier in "Amavisd-new Configuration".
// Amavisd-new AM.PDP port
// Since the port number can not be stored in the database
// all instances of amavisd-new must use the same AM.PDP port
$conf['amavisd']['spam_release_port'] = '9998';
All amavisd-new instances must use the same port number, but not necessarily
9998. Now we must configure MailZu to query the same database that amavisd-new
is populating.
$conf['db']['dbType'] = 'mysql';
$conf['db']['dbUser'] = 'user';
$conf['db']['dbPass'] = 'pass';
$conf['db']['dbName'] = 'dbname';
$conf['db']['hostSpec'] = 'hostname.example.com:port';
These settings should correspond to the credentials entered for the amavisd-new
configuration. The 'dbType' can be any PEAR DB compatible database. Please see
the config/config.php file for more information.
Note: If you are using MySQL database, the preferred version is 4.1.0 or later.
If your version is prior to 4.1.x, you need to apply a patch to make MailZu
compatible with it. The patch is located in contrib/mysql and is called
mysql4.0_compat.diff.
Authentication settings
-------------------------------
You can have a user authenticate to any of the following backends.
/* Options are:
ldap -> Standard LDAP server, e.g. OpenLDAP
ad -> MS Active Directory
sql -> PHP PEAR compatible database
exchange -> MS Exchange 5.5
imap -> IMAP protocol
*/
$conf['auth']['serverType'] = 'ldap';
Each seperate authentication method have related configuration variables that
must be set. Please see the appropriate (MECH)_README for more information.
Regardless of which method you choose, it is important to understand that there
will always be three attributes ( or fields for SQL ) that is critical for a
successful login.
The first of the three is the user password. For LDAP and AD, this need not be
specified, for the authentication is handled by the binding process. But for
SQL, the field of where the password is stored is required.
The second attribute is the login format. For LDAP it is usually the 'uid'
attribute, or if you want a fully qualified email address as the login, it
could be 'mail'. Active Directory has similar attributes.
This setting controls whether the user would use the login 'user', or if the
configuration variable was set to the 'mail' attribute, the login would be
'user@example.com'.
These two attributes are enough to be authenticated to the MailZu interface,
but the third attribute is what determines which messages the authenticated
user is permitted to view. This attribute is the final recipient address. It is
the email address that amavisd-new reports as the envelope recipient.
For example, if the login used was 'user', than there must be an attribute or
field that determines the email address associated with this user. Even if the
login was 'user@example.com' the third attribute may or may not be the same.
The address might have been aliased to an internal address 'user@internal.example.com'.
To get a description on how to set up these critical configuration variables for
your authentication, please see the appropriate (MECH)_README file in docs/.
Miscellaneous Settings
------------------------
Set this option to display the default MailZu logo or your custom logo:
// Image to appear at the top of each page ['img/mailzu.png']
// Leave this string empty if you are not going to use an image
// Specifiy link as 'directory/filename.gif'
$conf['ui']['logoImage'] = 'img/mailzu.png';
You can customize the welcome message with the following option:
// Welcome message show at login page ['Welcome to MailZu!']
$conf['ui']['welcome'] = 'Welcome to MailZu!';
Set the full URL to the root directory of MailZu:
// The full url to the root directory of MailZu
// Please do not include the trailing slash
$conf['app']['weburi'] = 'https://mailzuhost.example.com/mailzu';
This section deals with how mail is sent from MailZu. Please select one of the four available options.
Then define the necessary variables:
// How to send email ['mail']
/* Options are:
'mail' for PHP default mail
'smtp' for SMTP
'sendmail' for sendmail
'qmail' for qmail MTA
*/
$conf['app']['emailType'] = 'mail';
// SMTP email host address []
// This is only required if emailType is SMTP
$conf['app']['smtpHost'] = '';
// SMTP port [25]
// This is only required if emailType is SMTP
$conf['app']['smtpPort'] = 25;
// Path to sendmail ['/usr/sbin/sendmail']
// This only needs to be set if the emailType is 'sendmail'
$conf['app']['sendmailPath'] = '/usr/sbin/sendmail';
// Path to qmail ['/var/qmail/bin/sendmail']
// This only needs to be set if the emailType is 'qmail'
$conf['app']['qmailPath'] = '/var/qmail/bin/sendmail';
Set the support/admin email address with this option:
// The email addresses of the support staff and/or administrator
// An email is sent to these addresses when a user reports an error
// or clicks the "Email Administrator" link
$conf['app']['adminEmail'] = array('support@example.com', 'helpdesk@example.com');
Set this option to 1 if you want to email the admin upon each release request
// Email admin upon Release Request
// When users try to release a banned file a request is sent to an
// admin. Admins can always look at 'Pending Requests' in the MailZu
// interface regardless.
//
// $conf['app']['notifyAdmin'] = 1;
$conf['app']['notifyAdmin'] = 0;
Set this option to show the "Email Administrator" link
// Show the "Email Administrator" link for users
// If you have a large userbase, you may not want users to have the
// capability to just email the admin
// Note: The "Report Error" link is still available regardless
// of this option. This link is only visible if a fatal error occurs
// with releasing attachments. Default is 1 (show link).
//
// $conf['app']['showEmailAdmin'] = 0;
$conf['app']['showEmailAdmin'] = 1;
Set this option to 1 if you want to view the site quarantine in search only mode.
This option is very useful for large sites.
// Show Site Quarantine in search only mode if set to 1.
// No message is displayed when clicking on 'Site quarantine'.
// Keep the default for for large sites.
// $conf['app']['searchOnly'] = 1
$conf['app']['searchOnly'] = 1;
Set the default language code:
// The default language code. This must be included in the language list in
// langs.php
$conf['app']['defaultLanguage'] = 'en_US';
Set this option if you want to allow the language selection
// Display the choice for language selection during the login screen if set to 1
// Otherwise set it to 0
// Default is 1
$conf['app']['selectLanguage'] = '1';
Set this option to 1 if you want to use the Pear DB and Mail_Mime libraries included
with MailZu:
// If you are running PHP in safe mode, set this value to 1.
// This toggles if we use the included Pear DB and Mail_Mime libraries included
// with this distribution
$conf['app']['safeMode'] = 1;
Set the time format:
// View time in 12 or 24 hour format [12]
// Only acceptable values are 12 and 24 (if an invalid number is set, 12 hour
// time will be used)
$conf['app']['timeFormat'] = 12;
Set the title of the application:
// Title of application ['MailZu']
// Will be used for page titles and in 'From' field of email responses
$conf['app']['title'] = 'MailZu';
Set this option to 1 if you want to log system activity and errors:
// If we should log system activity or not [0]
// Can be 0 (for no) and 1 (for yes)
$conf['app']['use_log'] = 1;
Set the log file name (full path) using this option. You will need to create that file beforehand
and make it writable by the user running Apache.
// Directory/file for log ['/var/log/mailzu.log']
// Specify as /directory/filename.extension
$conf['app']['logfile'] = '/var/log/mailzu.log';
Set this option to determine the number of messages displayed per page:
// Maximum number of messages displayed per page
$conf['app']['displaySizeLimit'] = 50;

77
docs/LDAP_README Normal file
View File

@ -0,0 +1,77 @@
LDAP Autentication Settings
-------------------------------
To configure MailZu to authenticate users against LDAP.
Edit the config/config.php and tailor the variables mentioned here for your
environment.
// Set an authentication method: 'ldap','ad', or 'sql'
$conf['auth']['serverType'] = 'ldap';
Set the LDAP host(s) and search base
// List of LDAP servers
$conf['auth']['ldap_hosts'] = array( 'ldaphost' );
// if set to true, LDAP connection over SSL (PHP 4.0.4 minimum)
// if set to false or not set, unencrypted LDAP connection on port 389
$conf['auth']['ldap_ssl'] = false;
// LDAP base dn, e.g. 'dc=example,dc=com'
$conf['auth']['ldap_basedn'] = 'dc=example,dc=com';
Set the LDAP attribute used for the RDN to identify a person:
// LDAP attribute used for the RDN to identify a person
// For instance if the DN for a given user is uid=joesmith,ou=people,dc=example,dc=com
// the attribute would be 'uid'
$conf['auth']['ldap_user_identifier'] = 'uid';
Set the container where all users are kept. If users are stored in multiple
containers leave this option blank.
// Container where all users are kept, e.g. 'ou=people'
// If you have users in multiple containers, leave this option blank.
// In this particular case you will need to allow anonymous binding
// or specify a user/password to bind with
$conf['auth']['ldap_user_container'] = 'ou=people';
Now we must set the login format. For LDAP it is usually the 'uid'
attribute, or if you want a fully qualified email address as the login, it
could be 'mail'.
// LDAP attribute used as login, e.g. 'uid', 'mail' or 'uidNumber'
$conf['auth']['ldap_login'] = 'uid';
At the login page of MailZu, with this setting the user would use the login
'user', or if the configuration variable was set to the 'mail' attribute, the
login would be 'user@example.com'.
These two attributes are enough to be authenticated to the MailZu interface,
but the third attribute is what determines which messages the authenticated
user is permitted to view. This configuration variable is a list of
attributes that contain recipient addresses. In most cases this will be a
list with one item such as the attribute 'mail'. But if you want to include
more address you can add more attribute names to the list.
For example, if the login used was 'user', than there must be an attribute or
field that determines the email address associated with this user. Even if the
login was 'user@example.com' the third attribute may or may not be the same.
The address might have been aliased to an internal address
'user@internal.example.com'.
// LDAP mail attributes used as the final recipient address
// Could be the actual mail attribute or another attribute
// (in the latter case look for the "%m" token in the ldap query filter in
// amavisd.conf)
$conf['auth']['ldap_mailAttr'] = array('mailRoutingAddress');
If the attribute listed for the login format is not the same as the binding
username or if no user container is not specified, we must be able to search the directory.
The settings below binds using this account to search the directory.
Set them to empty string ('') for anonymous bind.
$conf['auth']['ldap_searchUsername'] = 'manager';
$conf['auth']['ldap_searchPassword'] = 'secret';
If you want to specify the name of the user in the welcome message, you need to set the parameter below. LDAP attribute such as 'givenName', 'cn' or 'displayName' can be used:
$conf['auth']['ldap_name'] = 'givenName';

82
docs/SQL_README Normal file
View File

@ -0,0 +1,82 @@
SQL Autentication Settings
-------------------------------
To configure MailZu to authenticate users against a PEAR compatible SQL
database...
// Set an authentication method: 'ldap','ad', or 'sql'
$conf['auth']['serverType'] = 'sql';
Set the type of database to authenticate to...
/*** Database Authentication Settings ***/
// Database type to be used by PEAR
/* Options are:
mysql -> MySQL
pgsql -> PostgreSQL
ibase -> InterBase
msql -> Mini SQL
mssql -> Microsoft SQL Server
oci8 -> Oracle 7/8/8i
odbc -> ODBC (Open Database Connectivity)
sybase -> SyBase
ifx -> Informix
fbsql -> FrontBase
*/
$conf['auth']['dbType'] = 'mysql';
Set the SQL host with optional port
// Database host specification (hostname[:port])
$conf['auth']['dbHostSpec'] = 'dbhost';
Specify the credentials needed to access the database
// Database user who can access the auth database
$conf['auth']['dbUser'] = 'user';
// Password for above user to auth database
$conf['auth']['dbPass'] = 'pass';
// Name for auth database
$conf['auth']['dbName'] = 'dbname';
// Name for auth table that contains usernames and passwords
$conf['auth']['dbTable'] = 'dbtablename';
// Name of the 'first name' or 'full name' field of the SQL table
// If such a field does not exist, leave it blank
$conf['auth']['dbTableName'] = 'givennamefield';
Now we must set the login format.
// Name of the Username field of the SQL table
$conf['auth']['dbTableUsername'] = 'usernamefield';
At the login page of MailZu, with this setting the user would use the value
listed in the above field, which may or may not be the fully qualified email
address.
Now we must set the field for the password.
// Name of the password field of the SQL table
$conf['auth']['dbTablePassword'] = 'passwordfield';
Is the password stored in the database the MD5 digest?
// true = passwords are stored md5 encrypted in database
// false = passwords are stored cleartext in database
$conf['auth']['dbIsMd5'] = true;
These two attributes are enough to be authenticated to the MailZu interface,
but the third attribute is what determines which messages the authenticated
user is permitted to view. This attribute is the final recipient address. It is
the email address that amavisd-new reports as the envelope recipient.
For example, if the login used was 'user', than there must be an attribute or
field that determines the email address associated with this user. Even if the
login was 'user@example.com' the third attribute may or may not be the same.
The address might have been aliased to an internal address
'user@internal.example.com'.
// Name of the 'mail address' field of the SQL table
$conf['auth']['dbTableMail'] = 'mailaddress';

127
functions.js Normal file
View File

@ -0,0 +1,127 @@
// Last modified: 03-04-05
function checkBrowser() {
if ( (navigator.appName.indexOf("Netscape") != -1) && ( parseFloat(navigator.appVersion) <= 4.79 ) ) {
newWin = window.open("","message","height=200,width=300");
newWin.document.writeln("<center><b>This system is optimized for Netscape version 6.0 or higher.<br>" +
"Please visit <a href='http://channels.netscape.com/ns/browsers/download.jsp' target='_blank'>Netscape.com</a> to obtain an update.");
newWin.document.close();
}
}
function help(file) {
window.open("help.php#" + file ,"","width=500,height=500,scrollbars");
void(0);
}
function isIE() {
return document.all;
}
function resOver(cell, color) {
cell.style.backgroundColor=color;
cell.style.cursor='hand'
}
function resOut(cell, color) {
cell.style.backgroundColor = color;
}
function showHideSearch(element) {
var expires = new Date();
var time = expires.getTime() + 2592000000;
expires.setTime(time);
var showHide = "";
if (document.getElementById(element).style.display == "none") {
document.getElementById(element).style.display='block';
showHide = "show";
} else {
document.getElementById(element).style.display='none';
showHide = "hide";
}
document.cookie = element + "=" + showHide + ";expires=" + expires.toGMTString();
}
function showHideFullHeaders(table) {
var expires = new Date();
var time = expires.getTime() + 2592000000;
expires.setTime(time);
var showHide = "";
var cnames = 'visiblehidden';
var i = 0;
var rows = document.getElementById(table).rows;
for (i = 0; i < rows.length; i++) {
rows[i].className = cnames.replace(rows[i].className, '');
showHide = rows[i].className;
}
document.cookie = table + "=" + showHide + ";EXpires=" + expires.toGMTString();
}
function changeLanguage(opt) {
var expires = new Date();
var time = expires.getTime() + 2592000000;
expires.setTime(time);
document.cookie = "lang=" + opt.options[opt.selectedIndex].value + ";expires=" + expires.toGMTString() + ";path=/";
document.location.href = document.URL;
}
function clickTab(tabid, panel_to_show) {
document.getElementById(tabid.getAttribute("id")).className = "tab-selected";
rows = document.getElementById("tab-container").getElementsByTagName("td");
for (i = 0; i < rows.length; i++) {
if (rows[i].className == "tab-selected" && rows[i] != tabid) {
rows[i].className = "tab-not-selected";
}
}
div_to_display = document.getElementById(panel_to_show);
div_to_display.style.display = isIE() ? "inline" : "table";
divs = document.getElementById("main-tab-panel").getElementsByTagName("div");
for (i = 0; i < divs.length; i++) {
// only hide panels with prefix "pnl"
if (divs[i] != div_to_display && divs[i].getAttribute("id").substring(0,3) == "pnl") {
divs[i].style.display = "none";
}
}
}
function showHideMinMax(chk) {
document.getElementById("minH").disabled = document.getElementById("minM").disabled = document.getElementById("maxH").disabled = document.getElementById("maxM").disabled= chk.checked
}
function CheckAll(frm) {
var elmts = frm.elements;
for (i=0;i<elmts.length;i++) {
if (elmts[i].type=="checkbox") {
elmts[i].checked=true;
ColorRow(elmts[i],"lightyellow");
}
}
}
function CheckNone(frm) {
var elmts = frm.elements;
for (i=0;i<elmts.length;i++) {
elmts[i].checked=false;
ColorRow(elmts[i],"lightyellow");
}
}
function ColorRow(obj,color) {
obj.checked==true ? bg=color : bg='';
while (obj.nodeName!='TR') {
obj=obj.parentNode;
}
obj.style.backgroundColor=bg;
}
function ViewOriginal(enc_mail_id,enc_recip_email) {
var url = "read_original.php?mail_id=" + enc_mail_id + "&recip_email=" + enc_recip_email;
window.open(url,'OriginalMessage','width=800,height=600,scrollbars=1');
}

73
help.php Normal file
View File

@ -0,0 +1,73 @@
<?php
/**
* This is the pop-up help file for the system
* This function simply prints out an HTML help file for
* users to reference
* @author Nick Korbel <lqqkout13@users.sourceforge.net>
* @version 07-10-04
* @package phpScheduleIt
*
* Copyright (C) 2003 - 2005 phpScheduleIt
* License: GPL, see LICENSE
*/
include_once('config/config.php');
global $languages;
global $lang;
global $charset;
echo "<?xml version=\"1.0\" encoding=\"$charset\"?" . ">\n";
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?=$languages[$lang][2]?>" lang="<?=$languages[$lang][2]?>">
<head>
<title>MailZu <?=translate('Help')?></title>
<meta http-equiv="Content-Type" content="text/html; charset=<?=$charset?>" />
<style type="text/css">
<!--
li {
font-size: 12px;
margin-top: 0px;
margin-right: 0px;
margin-bottom: 0px;
margin-left: 0px;
}
body {
font-family: Verdana, Arial, Helvetica, sans-serif;
margin-top: 5px;
margin-right: 5px;
margin-bottom: 5px;
margin-left: 5px;
background-color: #F0F0F0;
}
p {
font-size: 12px;
margin-left: 25px;
margin-top: 3px;
}
h5 {
margin-left: 10px;
}
a {
color: #104E8B;
}
a:hover {
color: #474747;
}
-->
</style>
</head>
<body>
<?
$help_file = 'lang/' . $languages[$lang][2] . '.help.php';
if (file_exists($help_file)) {
include_once($help_file);
}
else {
include_once('lang/en.help.php');
}
?>
</body>
</html>

BIN
img/blocked_img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

1
img/en.blocked_img.png Symbolic link
View File

@ -0,0 +1 @@
blocked_img.png

BIN
img/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
img/it.blocked_img.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

BIN
img/mailzu.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

55
index.php Normal file
View File

@ -0,0 +1,55 @@
<?php
/**
* This file is the login page for the system
* It provides a login form and will automatically
* forward any users who have cookies set to ctrlpnl.php
* @author Nick Korbel <lqqkout13@users.sourceforge.net>
* @version 06-25-04
* @package phpScheduleIt
*
* Copyright (C) 2003 - 2005 phpScheduleIt
* License: GPL, see LICENSE
*/
/**
* Include Template class
*/
include_once('lib/Template.class.php');
// Auth included in Template.php
$auth = new Auth();
$t = new Template();
$msg = '';
$resume = (isset($_POST['resume'])) ? $_POST['resume'] : '';
// Logging user out
if (isset($_GET['logout'])) {
$auth->doLogout();
}
else if (isset($_POST['login'])) {
$msg = $auth->doLogin($_POST['email'], $_POST['password'], (isset($_POST['setCookie']) ? 'y' : null), false, $resume, $_POST['language'], isset($_POST['domain'])? $_POST['domain'] : '');
}
else if (isset($_COOKIE['ID'])) {
$msg = $auth->doLogin('', '', 'y', $_COOKIE['ID'], $resume); // Check if user has cookies set up. If so, log them in automatically
}
$t->printHTMLHeader();
// Print out logoImage if it exists
echo (!empty($conf['ui']['logoImage']))
? '<div align="left"><img src="' . $conf['ui']['logoImage'] . '" alt="logo" vspace="5"/></div>'
: '';
$t->startMain();
if (isset($_GET['auth'])) {
$auth->printLoginForm(translate('You are not logged in!'), $_GET['resume']);
}
else {
$auth->printLoginForm($msg);
}
$t->endMain();
// Print HTML footer
$t->printHTMLFooter();
?>

142
lang/cs.help.php Normal file
View File

@ -0,0 +1,142 @@
<?php
/**
* English (en) help translation file.
* This also serves as the base translation file from which to derive
* all other translations.
*
* @author Brian Wong <bwsource@users.sourceforge.net>
* @translator Your Name <your@email.com>
* @version 01-08-05
* @package Languages
*
* Copyright (C) 2003 - 2007 MailZu
* License: GPL, see LICENSE
*/
///////////////////////////////////////////////////////////
// INSTRUCTIONS
///////////////////////////////////////////////////////////
// This file contains all the help file for MailZu. Please save the translated
// file as '2 letter language code'.help.php. For example, en.help.php.
//
// To make MailZu help available in another language, simply translate this
// file into your language. If there is no direct translation, please provide the
// closest translation.
//
// This will be included in the body of the help file.
//
// Please keep the HTML formatting unless you need to change it. Also, please try
// to keep the HTML XHTML 1.0 Transitional complaint.
///////////////////////////////////////////////////////////
?>
<div align="center">
<h3><a name="top" id="top"></a>Introduction to MailZu</h3>
<p><a href="http://mailzu.org" target="_blank">http://mailzu.org</a></p>
<table width="100%" border="0" cellspacing="0" cellpadding="5" style="border: solid #CCCCCC 1px">
<tr>
<td bgcolor="#FAFAFA">
<ul>
<li><b><a href="#getting_started">Getting Started</a></b></li>
<ul>
<li><a href="#logging_in">Logging In</a></li>
<li><a href="#language">Selecting My Language</a></li>
<li><a href="#getting_support">Getting Support</a></li>
</ul>
<li><a href="#using_mailzu"><b>Using MailZu</b></a></li>
<ul>
<li><a href="#quick_links">My Quick Links</a></li>
<li><a href="#msg_summary">Message Summary</a></li>
<li><a href="#msg_index">Message Indexes</a></li>
<li><a href="#search">Message Search</a></li>
<li><a href="#msg_view">Message View</a></li>
</ul>
</ul>
<hr width="95%" size="1" noshade="noshade" />
<h4><a name="getting_started" id="getting_started"></a>Getting Started</h4>
<p> At the top of each page you will see a welcome message and today's date.
If a previous user is displayed in the welcome message, click &quot;Log
Out&quot; to clear out any cookies they were using and <a href="#logging_in">log
in</a> as yourself.
Clicking the &quot;Help&quot; link brings a pop-up help window. Clicking
the &quot;Email Administrator&quot; link will open a new mail addressed to the system's
administrator.</p>
<p align="right"><a href="#top">Top</a></p>
<h5><a name="logging_in" id="logging_in"></a>Logging In</h5>
<p>To log in, users must provide their login id and password. The login id
may be your fully-qualified email address ('user@example.com') or simply
your username ('user'). The administrator shall inform you of the correct
form to use. Selecting the &quot;Keep Me Logged In&quot; option will use
cookies to identify you each time you return to the quarantine, bypassing
the need to log in each time. <i>You should only use this option if
you are the only person using MailZu on your computer.</i> After
logging in, you will be redirected to the <a href="#message_summary">
Message Summary</a>.</p>
<p align="right"><a href="#top">Top</a></p>
<h5><a name="language" id="language"></a>Selecting My Language</h5>
<p>On the login page, there will be a pull down menu with all of the
available language translations that your administrator has included.
Please select the language that you prefer and all MailZu text
will be translated. This will not translate any text related to actual
email messages; it will only translate the application text. You will
need to log out to select a different language.</p>
<p align="right"><a href="#top">Top</a></p>
<h5><a name="getting_support" id="getting_support"></a>Getting
Help</h5>
<p>If you you need assistance with viewing your quarantined messages or any
issue whatsoever, feel free to use the &quot;Email
Administrator&quot; link located in <a href="#quick_links">My Quick Links</a>.</p>
<p align="right"><a href="#top">Top</a></p> <p align="right">&nbsp;</p>
<hr width="95%" size="1" noshade="noshade" />
<h4><a name="using_mailzu" id="using_mailzu"></a>Using MailZu</h4>
<p>MailZu allows the user to view quarantined messages based on the type of messages.
The most prevalent types of messages which will be quarantined are those that are
considered spam, or contain a banned attachment.
<p align="right"><a href="#top">Top</a></p>
<h5><a name="quick_links" id="quick_links"></a>My Quick Links</h5>
<p>The Quick Links table will provide you with common application links.
The first, &quot;Quarantine Summary&quot; will give an overview of your message
quarantines.</p>
<p> &quot;My Quarantine&quot; will take you to
an index of your unsolicited bulk email and banned attachments.</p>
<p>&quot;Email Administrator&quot; is a quick way to contact your support
staff if you require assistance.</p>
<p>&quot;Help&quot; gives you this document.</p>
<p>The final link, &quot;Log Out&quot; will log you out of your current
session and return you to the log in screen.</p>
<p align="right"><a href="#top">Top</a></p>
<h5><a name="msg_summary" id="msg_summary"></a>Message Summary</h5>
<p> The message summary is the default page after login. It gives you a quick count of
how many messages you have in your quarantine and their type.
<p align="right"><a href="#top">Top</a></p>
<h5><a name="msg_index" id="msg_index"></a>Message Indexes</h5>
<p> Message indices show all the email for selected quarantined.
For each email quarantined, the index will show the From, Subject, and Date. Depending
on the quarantine currently in view, the index may show more information.</p>
<p>To sort your index by a specific field, click on the field title. Clicking the field
title again will reverse the sort.</p>
<p>Several buttons are available for handling the messages shown in the index. The
'Release/Request' action removes the message from the index and delivers the email as
if it had never been quarantined. The 'Delete' action only removes the message from the
index. These buttons perform the action on the messages selected through the checkboxes.
The 'Delete All' button ignores the state of the checkboxes and removes all messages in
the quarantine selected.</p>
<p>When viewing your pending requests you can withdraw the request by clicking
'Cancel Request'. The message will no longer be queued for administrator review.
</p>
<p align="right"><a href="#top">Top</a></p>
<h5><a name="search" id="search"></a>Message Search</h5>
<p>Using the search function is a quick way to find a message you believe has been
quarantined. You can search for a message by specifying either who its from, or
what the subject is, or both. The search is not case sensitive.</p>
<p align="right"><a href="#top">Top</a></p>
<h5><a name="msg_view" id="msg_view"></a>Message View</h5>
<p>The Message View allows you to see the contents of the message to help
determine if the message is legitimate. This view offers other options such
as to display the original plain text email and see additional message headers.
</p>
<p align="right"><a href="#top">Top</a></p> <p align="right">&nbsp;</p>
<hr width="95%" size="1" noshade="noshade" />
</td>
</tr>
</table>
</div>

321
lang/cs.lang.php Normal file
View File

@ -0,0 +1,321 @@
<?php
/**
* Czech (cz) translation file.
* Based on phpScheduleIt translation file.
* This also serves as the base translation file from which to derive
* all other translations.
*
* @author Vladimir Volcko <vtg@prolinux.cz>
* @author Petr Stehlik <pstehlik@sophics.cz>
* @version 06-05-07
* @package Languages
*
* Copyright (C) 2005 -2007 MailZu
* License: GPL, see LICENSE
*/
///////////////////////////////////////////////////////////
// INSTRUCTIONS
///////////////////////////////////////////////////////////
// This file contains all of the strings that are used throughout phpScheduleit.
// Please save the translated file as '2 letter language code'.lang.php. For example, en.lang.php.
//
// To make phpScheduleIt available in another language, simply translate each
// of the following strings into the appropriate one for the language. If there
// is no direct translation, please provide the closest translation. Please be sure
// to make the proper additions the /config/langs.php file (instructions are in the file).
// Also, please add a help translation for your language using en.help.php as a base.
//
// You will probably keep all sprintf (%s) tags in their current place. These tags
// are there as a substitution placeholder. Please check the output after translating
// to be sure that the sentences make sense.
//
// + Please use single quotes ' around all $strings. If you need to use the ' character, please enter it as \'
// + Please use double quotes " around all $email. If you need to use the " character, please enter it as \"
//
// + For all $dates please use the PHP strftime() syntax
// http://us2.php.net/manual/en/function.strftime.php
//
// + Non-intuitive parts of this file will be explained with comments. If you
// have any questions, please email lqqkout13@users.sourceforge.net
// or post questions in the Developers forum on SourceForge
// http://sourceforge.net/forum/forum.php?forum_id=331297
///////////////////////////////////////////////////////////
////////////////////////////////
/* Do not modify this section */
////////////////////////////////
global $strings; //
global $email; //
global $dates; //
global $charset; //
global $letters; //
global $days_full; //
global $days_abbr; //
global $days_two; //
global $days_letter; //
global $months_full; //
global $months_abbr; //
global $days_letter; //
/******************************/
// Charset for this language
// 'iso-8859-1' will work for most languages
$charset = 'utf-8';
/***
DAY NAMES
All of these arrays MUST start with Sunday as the first element
and go through the seven day week, ending on Saturday
***/
// The full day name
$days_full = array('Neděle', 'Pondělí', 'Úterý', 'Středa', 'Čtvtek', 'Pátek', 'Sobota');
// The three letter abbreviation
$days_abbr = array('Ne ', 'Po ', 'Út ', 'St ', 'Čt ', 'Pá ', 'So ');
// The two letter abbreviation
$days_two = array('Ne', 'Po', 'Út', 'St', 'Čt', 'Pá', 'So');
// The one letter abbreviation
$days_letter = array('N', 'P', 'Ú', 'S', 'Č', 'P', 'S');
/***
MONTH NAMES
All of these arrays MUST start with January as the first element
and go through the twelve months of the year, ending on December
***/
// The full month name
$months_full = array('Leden', 'Únor', 'Březen', 'Duben', 'Květen', 'Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosinec');
// The three letter month name
$months_abbr = array('Led', 'Úno', 'Bře', 'Dub', 'Kvě', 'Čěr', 'Čec', 'Srp', 'Zář', 'Říj', 'Lis', 'Pro');
// All letters of the alphabet starting with A and ending with Z
$letters = array ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');
/***
DATE FORMATTING
All of the date formatting must use the PHP strftime() syntax
You can include any text/HTML formatting in the translation
***/
// General date formatting used for all date display unless otherwise noted
$dates['general_date'] = '%d/%m/%Y';
// General datetime formatting used for all datetime display unless otherwise noted
// The hour:minute:second will always follow this format
$dates['general_datetime'] = '%d/%m/%Y @';
$dates['header'] = '%A, %B %d, %Y';
/***
STRING TRANSLATIONS
All of these strings should be translated from the English value (right side of the equals sign) to the new language.
- Please keep the keys (between the [] brackets) as they are. The keys will not always be the same as the value.
- Please keep the sprintf formatting (%s) placeholders where they are unless you are sure it needs to be moved.
- Please keep the HTML and punctuation as-is unless you know that you want to change it.
***/
$strings['hours'] = 'hodiny';
$strings['minutes'] = 'minuty';
// The common abbreviation to hint that a user should enter the month as 2 digits
$strings['mm'] = 'mm';
// The common abbreviation to hint that a user should enter the day as 2 digits
$strings['dd'] = 'dd';
// The common abbreviation to hint that a user should enter the year as 4 digits
$strings['yyyy'] = 'rrrr';
$strings['am'] = 'dop';
$strings['pm'] = 'odp';
$strings['Administrator'] = 'Administrátor';
$strings['Welcome Back'] = 'Vítejte zpět, %s';
$strings['Log Out'] = 'Odlogovat';
$strings['Help'] = 'Help';
$strings['Admin Email'] = 'Mail na admina';
$strings['Default'] = 'Default';
$strings['Reset'] = 'Reset';
$strings['Edit'] = 'Změnit';
$strings['Delete'] = 'Smazat';
$strings['Cancel'] = 'Přerušit';
$strings['View'] = 'Zobrazit';
$strings['Modify'] = 'Upravit';
$strings['Save'] = 'Uložit';
$strings['Back'] = 'Zpět';
$strings['BackMessageIndex'] = 'Zpět na zprávy';
$strings['ToggleHeaders'] = 'Přepínat hlavičky';
$strings['ViewOriginal'] = 'Zobrazit originál';
$strings['Next'] = 'Další';
$strings['Close Window'] = 'Zavřít okno';
$strings['Search'] = 'Prohledat';
$strings['Clear'] = 'Vyčistit';
$strings['Days to Show'] = 'Dny k zobrazení';
$strings['Reservation Offset'] = 'Reservation Offset';
$strings['Hidden'] = 'Skrytý';
$strings['Show Summary'] = 'Zobrazit přehled';
$strings['Add Schedule'] = 'Přidat plán ';
$strings['Edit Schedule'] = 'Editovat plán';
$strings['No'] = 'Ne';
$strings['Yes'] = 'Ano';
$strings['Name'] = 'Název';
$strings['First Name'] = 'Jméno';
$strings['Last Name'] = 'Příjmení';
$strings['Resource Name'] = 'Název zdroje';
$strings['Email'] = 'Email';
$strings['Institution'] = 'Instituce';
$strings['Phone'] = 'Telefon';
$strings['Password'] = 'Heslo';
$strings['Permissions'] = 'Oprávnění';
$strings['View information about'] = 'Zobrazit informace o %s %s';
$strings['Send email to'] = 'Poslat email %s %s';
$strings['Reset password for'] = 'Změnit heslo pro %s %s';
$strings['Edit permissions for'] = 'Editovat oprávnění pro %s %s';
$strings['Position'] = 'Pozice';
$strings['Password (6 char min)'] = 'Heslo (%s min. znaků)'; // @since 1.1.0
$strings['Re-Enter Password'] = 'Vložte heslo (znovu)';
$strings['Date'] = 'Datum';
$strings['Email Users'] = 'Email Users';
$strings['Subject'] = 'Předmět';
$strings['Message'] = 'Zpráva';
$strings['Send Email'] = 'Odeslat email';
$strings['problem sending email'] = 'Při odesílání mailu se vyskytla chyba. Zkuste to později znovu.';
$strings['The email sent successfully.'] = 'Email byl úspěšně odeslán.';
$strings['Email address'] = 'Emailová adresa';
$strings['Please Log In'] = 'Zalogujte se';
$strings['Keep me logged in'] = 'Zapamatovat přihlášení <br/>(vyžaduje cookies)';
$strings['Password'] = 'Heslo';
$strings['Log In'] = 'Přihlásit se';
$strings['Get online help'] = 'Získat online help';
$strings['Language'] = 'Jazyky';
$strings['(Default)'] = '(Default)';
$strings['Email Administrator'] = 'Kontaktovat admina';
$strings['N/A'] = 'N/A';
$strings['Summary'] = 'Přehled';
$strings['View stats for schedule'] = 'Zobrazit statistiky pro plán:';
$strings['At A Glance'] = 'Jako celek';
$strings['Total Users'] = 'Celkem uživatelů:';
$strings['Total Resources'] = 'Celkem zdrojů:';
$strings['Total Reservations'] = 'Celkem rezervací:';
$strings['Max Reservation'] = 'Max rezervací:';
$strings['Min Reservation'] = 'Min rezervací:';
$strings['Avg Reservation'] = 'Průměrně rezervací:';
$strings['Most Active Resource'] = 'Nejvíce aktivní zdroje:';
$strings['Most Active User'] = 'Nejvíce aktivní uživatelé:';
$strings['System Stats'] = 'Systémové statistiky';
$strings['phpScheduleIt version'] = 'phpScheduleIt version:';
$strings['Database backend'] = 'Databázový backend:';
$strings['Database name'] = 'Název databáze:';
$strings['PHP version'] = 'PHP verze:';
$strings['Server OS'] = 'Server OS:';
$strings['Server name'] = 'Jméno serveru:';
$strings['phpScheduleIt root directory'] = 'phpScheduleIt root directory:';
$strings['Using permissions'] = 'Používat oprávnění:';
$strings['Using logging'] = 'Používat logování:';
$strings['Log file'] = 'Log soubor:';
$strings['Admin email address'] = 'Admin email address:';
$strings['Tech email address'] = 'Tech email address:';
$strings['CC email addresses'] = 'CC email addresses:';
$strings['Reservation start time'] = 'Reservation start time:';
$strings['Reservation end time'] = 'Reservation end time:';
$strings['Days shown at a time'] = 'Days shown at a time:';
$strings['Reservations'] = 'Reservations';
$strings['Return to top'] = 'Return to top';
$strings['for'] = 'pro';
$strings['Per page'] = 'Po stránce:';
$strings['Page'] = 'Stránka:';
$strings['You are not logged in!'] = 'Nejste zalogován(a)!';
$strings['Setup'] = 'Setup';
$strings['Invalid User Name/Password.'] = 'Neplatný uživatel/heslo.';
$strings['Valid username is required'] = 'Platné uživatelské jméno je požadováno';
$strings['Close'] = 'Zavřít';
$strings['Admin'] = 'Admin';
$strings['My Quick Links'] = 'Moje odkazy';
$strings['Go to first page'] = 'Jít na první stránku';
$strings['Go to last page'] = 'Jít na poslední stránku';
$strings['Sort by descending order'] = 'Setřidit sestupně';
$strings['Sort by ascending order'] = 'Setřídit vzestupně';
$strings['Spam Quarantine'] = 'Spam karanténa';
$strings['Message View'] = 'Zobrazit zprávu';
$strings['Attachment Quarantine'] = 'Přílohy v karanténě';
$strings['No such content type'] = 'No such content type';
$strings['No message was selected'] = 'Žádná zpráva nebyla vybrána ...';
$strings['Unknown action type'] = 'Neznámý typ akce ...';
$strings['A problem occured when trying to release the following messages'] = 'Chyba při pokusu o uvolnění následujících zpráv';
$strings['A problem occured when trying to delete the following messages'] = 'Chyba při pokusu při odstranění následujících zpráv';
$strings['Please release the following messages'] = 'Prosím o uvolnění následujících zpráv';
$strings['To'] = 'Komu';
$strings['From'] = 'Od';
$strings['Subject'] = 'Předmět';
$strings['Date'] = 'Datum';
$strings['Score'] = 'Score';
$strings['Mail ID'] = 'Mail ID';
$strings['Status'] = 'Status';
$strings['Print'] = 'Tisk';
$strings['CloseWindow'] = 'Zavřít';
$strings['Unknown server type'] = 'Neznámý typ serveru ...';
$strings['Showing messages'] = "Zobrazení zpráv %s through %s &nbsp;&nbsp; (%s celkem)\r\n";
$strings['View this message'] = 'Zobrazit zprávu';
$strings['Message Unavailable'] = 'Zpráva není k dispozici';
$strings['My Quarantine'] = 'Moje karanténa';
$strings['Site Quarantine'] = 'Server karanténa';
$strings['Message Processing'] = 'Zpracování zprávy';
$strings['Quarantine Summary'] = 'Přehled karantény';
$strings['Site Quarantine Summary'] = 'Přehled karantény serveru';
$strings['Login'] = 'Login';
$strings['spam(s)'] = 'spam(ů)';
$strings['attachment(s)'] = 'příloh(a)';
$strings['pending release request(s)'] = 'nevyřízené(ých) požadavky(ů) na uvolnění';
$strings['virus(es)'] = 'vir(ů)';
$strings['bad header(s)'] = 'špatná(é) hlavička(y)';
$strings['You have to type some text'] = 'Napište nějaký text';
$strings['Release'] = 'Uvolnit';
$strings['Release/Request release'] = 'Uvolnit/Request release';
$strings['Request release'] = 'Požadavek na uvolnění';
$strings['Delete'] = 'Smazat';
$strings['Delete All'] = 'Smazat vše';
$strings['Send report and go back'] = 'Poslat report a jít zpět';
$strings['Go back'] = "Jít zpět";
$strings['Select All'] = "Vybrat vše";
$strings['Clear All'] = "Odznačit vše";
$strings['Access Denied'] = "Přístup odepřen";
$strings['My Pending Requests'] = "Moje nevyříz. pož.";
$strings['Site Pending Requests'] = "Server nevyříz. pož.";
$strings['Cancel Request'] = "Zrušit požadavek";
$strings['User is not allowed to login'] = "Uživatel nemá oprávnění pro nalogování";
$strings['Authentication successful'] = "Úspěšné prokázání identity";
$strings['Authentication failed'] = "Prokázání identity selhalo";
$strings['LDAP connection failed'] = "LDAP/AD spojení selhalo";
$strings['Logout successful'] = "Úspěšné odhlášení";
$strings['IMAP Authentication: no match'] = "IMAP Authentication: no match";
$strings['Search for messages whose:'] = "Hledat zprávy kde:";
$strings['Content Type'] = "Typ obsahu";
$strings['Clear search results'] = "Vyčistit výsledky vyhledávání";
$strings['contains'] = "obsahuje";
$strings['doesn\'t contain'] = "neobsahuje";
$strings['equals'] = "je shodné";
$strings['doesn\'t equal'] = "není shodné";
$strings['All'] = "Vše";
$strings['Spam'] = "Spam";
$strings['Banned'] = "Zakázané";
$strings['Virus'] = "Vir";
$strings['Viruses'] = "Viry";
$strings['Bad Header'] = "Špatná hlavička";
$strings['Bad Headers'] = "Špatné hlavičky";
$strings['Pending Requests'] = "Pending Requests";
$strings['last'] = "poslední";
$strings['first'] = "první";
$strings['previous'] = "předchozí";
$strings['There was an error executing your query'] = 'Chyba při provádění požadavku:';
$strings['There are no matching records.'] = 'Žádné záznamy neodpovídají zadaným kritériím.';
$strings['Domain'] = 'Doména';
$strings['Total'] = 'Celkem';
$strings['X-Amavis-Alert'] = 'X-Amavis-Alert';
$strings['Loading Summary...'] = 'Loading Summary...';
$strings['Retrieving Messages...'] = 'Retrieving Messages...';
?>

142
lang/en.help.php Normal file
View File

@ -0,0 +1,142 @@
<?php
/**
* English (en) help translation file.
* This also serves as the base translation file from which to derive
* all other translations.
*
* @author Brian Wong <bwsource@users.sourceforge.net>
* @translator Your Name <your@email.com>
* @version 01-08-05
* @package Languages
*
* Copyright (C) 2003 - 2007 MailZu
* License: GPL, see LICENSE
*/
///////////////////////////////////////////////////////////
// INSTRUCTIONS
///////////////////////////////////////////////////////////
// This file contains all the help file for MailZu. Please save the translated
// file as '2 letter language code'.help.php. For example, en.help.php.
//
// To make MailZu help available in another language, simply translate this
// file into your language. If there is no direct translation, please provide the
// closest translation.
//
// This will be included in the body of the help file.
//
// Please keep the HTML formatting unless you need to change it. Also, please try
// to keep the HTML XHTML 1.0 Transitional complaint.
///////////////////////////////////////////////////////////
?>
<div align="center">
<h3><a name="top" id="top"></a>Introduction to MailZu</h3>
<p><a href="http://mailzu.net" target="_blank">http://mailzu.net</a></p>
<table width="100%" border="0" cellspacing="0" cellpadding="5" style="border: solid #CCCCCC 1px">
<tr>
<td bgcolor="#FAFAFA">
<ul>
<li><b><a href="#getting_started">Getting Started</a></b></li>
<ul>
<li><a href="#logging_in">Logging In</a></li>
<li><a href="#language">Selecting My Language</a></li>
<li><a href="#getting_support">Getting Support</a></li>
</ul>
<li><a href="#using_mailzu"><b>Using MailZu</b></a></li>
<ul>
<li><a href="#quick_links">My Quick Links</a></li>
<li><a href="#msg_summary">Message Summary</a></li>
<li><a href="#msg_index">Message Indexes</a></li>
<li><a href="#search">Message Search</a></li>
<li><a href="#msg_view">Message View</a></li>
</ul>
</ul>
<hr width="95%" size="1" noshade="noshade" />
<h4><a name="getting_started" id="getting_started"></a>Getting Started</h4>
<p> At the top of each page you will see a welcome message and today's date.
If a previous user is displayed in the welcome message, click &quot;Log
Out&quot; to clear out any cookies they were using and <a href="#logging_in">log
in</a> as yourself.
Clicking the &quot;Help&quot; link brings a pop-up help window. Clicking
the &quot;Email Administrator&quot; link will open a new mail addressed to the system's
administrator.</p>
<p align="right"><a href="#top">Top</a></p>
<h5><a name="logging_in" id="logging_in"></a>Logging In</h5>
<p>To log in, users must provide their login id and password. The login id
may be your fully-qualified email address ('user@example.com') or simply
your username ('user'). The administrator shall inform you of the correct
form to use. Selecting the &quot;Keep Me Logged In&quot; option will use
cookies to identify you each time you return to the quarantine, bypassing
the need to log in each time. <i>You should only use this option if
you are the only person using MailZu on your computer.</i> After
logging in, you will be redirected to the <a href="#message_summary">
Message Summary</a>.</p>
<p align="right"><a href="#top">Top</a></p>
<h5><a name="language" id="language"></a>Selecting My Language</h5>
<p>On the login page, there will be a pull down menu with all of the
available language translations that your administrator has included.
Please select the language that you prefer and all MailZu text
will be translated. This will not translate any text related to actual
email messages; it will only translate the application text. You will
need to log out to select a different language.</p>
<p align="right"><a href="#top">Top</a></p>
<h5><a name="getting_support" id="getting_support"></a>Getting
Help</h5>
<p>If you you need assistance with viewing your quarantined messages or any
issue whatsoever, feel free to use the &quot;Email
Administrator&quot; link located in <a href="#quick_links">My Quick Links</a>.</p>
<p align="right"><a href="#top">Top</a></p> <p align="right">&nbsp;</p>
<hr width="95%" size="1" noshade="noshade" />
<h4><a name="using_mailzu" id="using_mailzu"></a>Using MailZu</h4>
<p>MailZu allows the user to view quarantined messages based on the type of messages.
The most prevalent types of messages which will be quarantined are those that are
considered spam, or contain a banned attachment.
<p align="right"><a href="#top">Top</a></p>
<h5><a name="quick_links" id="quick_links"></a>My Quick Links</h5>
<p>The Quick Links table will provide you with common application links.
The first, &quot;Quarantine Summary&quot; will give an overview of your message
quarantines.</p>
<p> &quot;My Quarantine&quot; will take you to
an index of your unsolicited bulk email and banned attachments.</p>
<p>&quot;Email Administrator&quot; is a quick way to contact your support
staff if you require assistance.</p>
<p>&quot;Help&quot; gives you this document.</p>
<p>The final link, &quot;Log Out&quot; will log you out of your current
session and return you to the log in screen.</p>
<p align="right"><a href="#top">Top</a></p>
<h5><a name="msg_summary" id="msg_summary"></a>Message Summary</h5>
<p> The message summary is the default page after login. It gives you a quick count of
how many messages you have in your quarantine and their type.
<p align="right"><a href="#top">Top</a></p>
<h5><a name="msg_index" id="msg_index"></a>Message Indexes</h5>
<p> Message indices show all the email for selected quarantined.
For each email quarantined, the index will show the From, Subject, and Date. Depending
on the quarantine currently in view, the index may show more information.</p>
<p>To sort your index by a specific field, click on the field title. Clicking the field
title again will reverse the sort.</p>
<p>Several buttons are available for handling the messages shown in the index. The
'Release/Request' action removes the message from the index and delivers the email as
if it had never been quarantined. The 'Delete' action only removes the message from the
index. These buttons perform the action on the messages selected through the checkboxes.
The 'Delete All' button ignores the state of the checkboxes and removes all messages in
the quarantine selected.</p>
<p>When viewing your pending requests you can withdraw the request by clicking
'Cancel Request'. The message will no longer be queued for administrator review.
</p>
<p align="right"><a href="#top">Top</a></p>
<h5><a name="search" id="search"></a>Message Search</h5>
<p>Using the search function is a quick way to find a message you believe has been
quarantined. You can search for a message by specifying either who its from, or
what the subject is, or both. The search is not case sensitive.</p>
<p align="right"><a href="#top">Top</a></p>
<h5><a name="msg_view" id="msg_view"></a>Message View</h5>
<p>The Message View allows you to see the contents of the message to help
determine if the message is legitimate. This view offers other options such
as to display the original plain text email and see additional message headers.
</p>
<p align="right"><a href="#top">Top</a></p> <p align="right">&nbsp;</p>
<hr width="95%" size="1" noshade="noshade" />
</td>
</tr>
</table>
</div>

322
lang/en_GB.lang.php Normal file
View File

@ -0,0 +1,322 @@
<?php
/**
* English (en) translation file.
* Based on phpScheduleIt translation file.
* This also serves as the base translation file from which to derive
* all other translations.
*
* @author Samuel Tran <stran2005@users.sourceforge.net>
* @author Brian Wong <bwsource@users.sourceforge.net>
* @author Nicolas Peyrussie <peyrouz@users.sourceforge.net>
* @version 04-03-07
* @package Languages
*
* Copyright (C) 2005 - 2007 MailZu
* License: GPL, see LICENSE
*/
///////////////////////////////////////////////////////////
// INSTRUCTIONS
///////////////////////////////////////////////////////////
// This file contains all of the strings that are used throughout phpScheduleit.
// Please save the translated file as '2 letter language code'.lang.php. For example, en.lang.php.
//
// To make phpScheduleIt available in another language, simply translate each
// of the following strings into the appropriate one for the language. If there
// is no direct translation, please provide the closest translation. Please be sure
// to make the proper additions the /config/langs.php file (instructions are in the file).
// Also, please add a help translation for your language using en.help.php as a base.
//
// You will probably keep all sprintf (%s) tags in their current place. These tags
// are there as a substitution placeholder. Please check the output after translating
// to be sure that the sentences make sense.
//
// + Please use single quotes ' around all $strings. If you need to use the ' character, please enter it as \'
// + Please use double quotes " around all $email. If you need to use the " character, please enter it as \"
//
// + For all $dates please use the PHP strftime() syntax
// http://us2.php.net/manual/en/function.strftime.php
//
// + Non-intuitive parts of this file will be explained with comments. If you
// have any questions, please email lqqkout13@users.sourceforge.net
// or post questions in the Developers forum on SourceForge
// http://sourceforge.net/forum/forum.php?forum_id=331297
///////////////////////////////////////////////////////////
////////////////////////////////
/* Do not modify this section */
////////////////////////////////
global $strings; //
global $email; //
global $dates; //
global $charset; //
global $letters; //
global $days_full; //
global $days_abbr; //
global $days_two; //
global $days_letter; //
global $months_full; //
global $months_abbr; //
global $days_letter; //
/******************************/
// Charset for this language
// 'iso-8859-1' will work for most languages
$charset = 'iso-8859-1';
/***
DAY NAMES
All of these arrays MUST start with Sunday as the first element
and go through the seven day week, ending on Saturday
***/
// The full day name
$days_full = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
// The three letter abbreviation
$days_abbr = array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
// The two letter abbreviation
$days_two = array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa');
// The one letter abbreviation
$days_letter = array('S', 'M', 'T', 'W', 'T', 'F', 'S');
/***
MONTH NAMES
All of these arrays MUST start with January as the first element
and go through the twelve months of the year, ending on December
***/
// The full month name
$months_full = array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
// The three letter month name
$months_abbr = array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
// All letters of the alphabet starting with A and ending with Z
$letters = array ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');
/***
DATE FORMATTING
All of the date formatting must use the PHP strftime() syntax
You can include any text/HTML formatting in the translation
***/
// General date formatting used for all date display unless otherwise noted
$dates['general_date'] = '%d/%m/%Y';
// General datetime formatting used for all datetime display unless otherwise noted
// The hour:minute:second will always follow this format
$dates['general_datetime'] = '%d/%m/%Y @';
$dates['header'] = '%A, %B %d, %Y';
/***
STRING TRANSLATIONS
All of these strings should be translated from the English value (right side of the equals sign) to the new language.
- Please keep the keys (between the [] brackets) as they are. The keys will not always be the same as the value.
- Please keep the sprintf formatting (%s) placeholders where they are unless you are sure it needs to be moved.
- Please keep the HTML and punctuation as-is unless you know that you want to change it.
***/
$strings['hours'] = 'hours';
$strings['minutes'] = 'minutes';
// The common abbreviation to hint that a user should enter the month as 2 digits
$strings['mm'] = 'mm';
// The common abbreviation to hint that a user should enter the day as 2 digits
$strings['dd'] = 'dd';
// The common abbreviation to hint that a user should enter the year as 4 digits
$strings['yyyy'] = 'yyyy';
$strings['am'] = 'am';
$strings['pm'] = 'pm';
$strings['Administrator'] = 'Administrator';
$strings['Welcome Back'] = 'Welcome Back, %s';
$strings['Log Out'] = 'Log Out';
$strings['Help'] = 'Help';
$strings['Admin Email'] = 'Admin Email';
$strings['Default'] = 'Default';
$strings['Reset'] = 'Reset';
$strings['Edit'] = 'Edit';
$strings['Delete'] = 'Delete';
$strings['Cancel'] = 'Cancel';
$strings['View'] = 'View';
$strings['Modify'] = 'Modify';
$strings['Save'] = 'Save';
$strings['Back'] = 'Back';
$strings['BackMessageIndex'] = 'Back to Messages';
$strings['ToggleHeaders'] = 'Toggle Headers';
$strings['ViewOriginal'] = 'View Original';
$strings['Next'] = 'Next';
$strings['Close Window'] = 'Close Window';
$strings['Search'] = 'Search';
$strings['Clear'] = 'Clear';
$strings['Days to Show'] = 'Days to Show';
$strings['Reservation Offset'] = 'Reservation Offset';
$strings['Hidden'] = 'Hidden';
$strings['Show Summary'] = 'Show Summary';
$strings['Add Schedule'] = 'Add Schedule';
$strings['Edit Schedule'] = 'Edit Schedule';
$strings['No'] = 'No';
$strings['Yes'] = 'Yes';
$strings['Name'] = 'Name';
$strings['First Name'] = 'First Name';
$strings['Last Name'] = 'Last Name';
$strings['Resource Name'] = 'Resource Name';
$strings['Email'] = 'Email';
$strings['Institution'] = 'Institution';
$strings['Phone'] = 'Phone';
$strings['Password'] = 'Password';
$strings['Permissions'] = 'Permissions';
$strings['View information about'] = 'View information about %s %s';
$strings['Send email to'] = 'Send email to %s %s';
$strings['Reset password for'] = 'Reset password for %s %s';
$strings['Edit permissions for'] = 'Edit permissions for %s %s';
$strings['Position'] = 'Position';
$strings['Password (6 char min)'] = 'Password (%s char min)'; // @since 1.1.0
$strings['Re-Enter Password'] = 'Re-Enter Password';
$strings['Date'] = 'Date';
$strings['Email Users'] = 'Email Users';
$strings['Subject'] = 'Subject';
$strings['Message'] = 'Message';
$strings['Send Email'] = 'Send Email';
$strings['problem sending email'] = 'Sorry, there was a problem sending your email. Please try again later.';
$strings['The email sent successfully.'] = 'The email sent successfully.';
$strings['Email address'] = 'Email address';
$strings['Please Log In'] = 'Please Log In';
$strings['Keep me logged in'] = 'Keep me logged in <br/>(requires cookies)';
$strings['Password'] = 'Password';
$strings['Log In'] = 'Log In';
$strings['Get online help'] = 'Get online help';
$strings['Language'] = 'Language';
$strings['(Default)'] = '(Default)';
$strings['Email Administrator'] = 'Email Administrator';
$strings['N/A'] = 'N/A';
$strings['Summary'] = 'Summary';
$strings['View stats for schedule'] = 'View stats for schedule:';
$strings['At A Glance'] = 'At A Glance';
$strings['Total Users'] = 'Total Users:';
$strings['Total Resources'] = 'Total Resources:';
$strings['Total Reservations'] = 'Total Reservations:';
$strings['Max Reservation'] = 'Max Reservation:';
$strings['Min Reservation'] = 'Min Reservation:';
$strings['Avg Reservation'] = 'Avg Reservation:';
$strings['Most Active Resource'] = 'Most Active Resource:';
$strings['Most Active User'] = 'Most Active User:';
$strings['System Stats'] = 'System Stats';
$strings['phpScheduleIt version'] = 'phpScheduleIt version:';
$strings['Database backend'] = 'Database backend:';
$strings['Database name'] = 'Database name:';
$strings['PHP version'] = 'PHP version:';
$strings['Server OS'] = 'Server OS:';
$strings['Server name'] = 'Server name:';
$strings['phpScheduleIt root directory'] = 'phpScheduleIt root directory:';
$strings['Using permissions'] = 'Using permissions:';
$strings['Using logging'] = 'Using logging:';
$strings['Log file'] = 'Log file:';
$strings['Admin email address'] = 'Admin email address:';
$strings['Tech email address'] = 'Tech email address:';
$strings['CC email addresses'] = 'CC email addresses:';
$strings['Reservation start time'] = 'Reservation start time:';
$strings['Reservation end time'] = 'Reservation end time:';
$strings['Days shown at a time'] = 'Days shown at a time:';
$strings['Reservations'] = 'Reservations';
$strings['Return to top'] = 'Return to top';
$strings['for'] = 'for';
$strings['Per page'] = 'Per page:';
$strings['Page'] = 'Page:';
$strings['You are not logged in!'] = 'You are not logged in!';
$strings['Setup'] = 'Setup';
$strings['Invalid User Name/Password.'] = 'Invalid User Name/Password.';
$strings['Valid username is required'] = 'Valid username is required';
$strings['Close'] = 'Close';
$strings['Admin'] = 'Admin';
$strings['My Quick Links'] = 'My Quick Links';
$strings['Go to first page'] = 'Go to first page';
$strings['Go to last page'] = 'Go to last page';
$strings['Sort by descending order'] = 'Sort by descending order';
$strings['Sort by ascending order'] = 'Sort by ascending order';
$strings['Spam Quarantine'] = 'Spam Quarantine';
$strings['Message View'] = 'Message View';
$strings['Attachment Quarantine'] = 'Attachment Quarantine';
$strings['No such content type'] = 'No such content type';
$strings['No message was selected'] = 'No message was selected ...';
$strings['Unknown action type'] = 'Unknown action type ...';
$strings['A problem occured when trying to release the following messages'] = 'A problem occured when trying to release the following messages';
$strings['A problem occured when trying to delete the following messages'] = 'A problem occured when trying to delete the following messages';
$strings['Please release the following messages'] = 'Please release the following messages';
$strings['To'] = 'To';
$strings['From'] = 'From';
$strings['Subject'] = 'Subject';
$strings['Date'] = 'Date';
$strings['Score'] = 'Score';
$strings['Mail ID'] = 'Mail ID';
$strings['Status'] = 'Status';
$strings['Print'] = 'Print';
$strings['CloseWindow'] = 'Close';
$strings['Unknown server type'] = 'Unknown server type ...';
$strings['Showing messages'] = "Showing messages %s through %s &nbsp;&nbsp; (%s total)\r\n";
$strings['View this message'] = 'View this message';
$strings['Message Unavailable'] = 'Message Unavailable';
$strings['My Quarantine'] = 'My Quarantine';
$strings['Site Quarantine'] = 'Site Quarantine';
$strings['Message Processing'] = 'Message Processing';
$strings['Quarantine Summary'] = 'Quarantine Summary';
$strings['Site Quarantine Summary'] = 'Site Quarantine Summary';
$strings['Login'] = 'Login';
$strings['spam(s)'] = 'spam(s)';
$strings['attachment(s)'] = 'attachment(s)';
$strings['pending release request(s)'] = 'pending release request(s)';
$strings['virus(es)'] = 'virus(es)';
$strings['bad header(s)'] = 'bad header(s)';
$strings['You have to type some text'] = 'You have to type some text';
$strings['Release'] = 'Release';
$strings['Release/Request release'] = 'Release/Request release';
$strings['Request release'] = 'Request release';
$strings['Delete'] = 'Delete';
$strings['Delete All'] = 'Delete All';
$strings['Send report and go back'] = 'Send report and go back';
$strings['Go back'] = "Go back";
$strings['Select All'] = "Select All";
$strings['Clear All'] = "Clear All";
$strings['Access Denied'] = "Access Denied";
$strings['My Pending Requests'] = "My Pending Requests";
$strings['Site Pending Requests'] = "Site Pending Requests";
$strings['Cancel Request'] = "Cancel Request";
$strings['User is not allowed to login'] = "User is not allowed to login";
$strings['Authentication successful'] = "Authentication successful";
$strings['Authentication failed'] = "Authentication failed";
$strings['LDAP connection failed'] = "LDAP/AD connection failed";
$strings['Logout successful'] = "Logout successful";
$strings['IMAP Authentication: no match'] = "IMAP Authentication: no match";
$strings['Search for messages whose:'] = "Search for messages whose:";
$strings['Content Type'] = "Content Type";
$strings['Clear search results'] = "Clear search results";
$strings['contains'] = "contains";
$strings['doesn\'t contain'] = "doesn't contain";
$strings['equals'] = "equals";
$strings['doesn\'t equal'] = "doesn't equal";
$strings['All'] = "All";
$strings['Spam'] = "Spam";
$strings['Banned'] = "Banned";
$strings['Virus'] = "Virus";
$strings['Viruses'] = "Viruses";
$strings['Bad Header'] = "Bad Header";
$strings['Bad Headers'] = "Bad Headers";
$strings['Pending Requests'] = "Pending Requests";
$strings['last'] = "last";
$strings['first'] = "first";
$strings['previous'] = "previous";
$strings['There was an error executing your query'] = 'There was an error executing your query:';
$strings['There are no matching records.'] = 'There are no matching records.';
$strings['Domain'] = 'Domain';
$strings['Total'] = 'Total';
$strings['X-Amavis-Alert'] = 'X-Amavis-Alert';
$strings['Loading Summary...'] = 'Loading Summary...';
$strings['Retrieving Messages...'] = 'Retrieving Messages...';
?>

323
lang/en_US.lang.php Normal file
View File

@ -0,0 +1,323 @@
<?php
/**
* English (en) translation file.
* Based on phpScheduleIt translation file.
* This also serves as the base translation file from which to derive
* all other translations.
*
* @author Samuel Tran <stran2005@users.sourceforge.net>
* @author Brian Wong <bwsource@users.sourceforge.net>
* @author Nicolas Peyrussie <peyrouz@users.sourceforge.net>
* @author Jeremy Fowler <jfowler06@users.sourceforge.net>
* @version 04-03-07
* @package Languages
*
* Copyright (C) 2005 - 2007 MailZu
* License: GPL, see LICENSE
*/
///////////////////////////////////////////////////////////
// INSTRUCTIONS
///////////////////////////////////////////////////////////
// This file contains all of the strings that are used throughout phpScheduleit.
// Please save the translated file as '2 letter language code'.lang.php. For example, en.lang.php.
//
// To make phpScheduleIt available in another language, simply translate each
// of the following strings into the appropriate one for the language. If there
// is no direct translation, please provide the closest translation. Please be sure
// to make the proper additions the /config/langs.php file (instructions are in the file).
// Also, please add a help translation for your language using en.help.php as a base.
//
// You will probably keep all sprintf (%s) tags in their current place. These tags
// are there as a substitution placeholder. Please check the output after translating
// to be sure that the sentences make sense.
//
// + Please use single quotes ' around all $strings. If you need to use the ' character, please enter it as \'
// + Please use double quotes " around all $email. If you need to use the " character, please enter it as \"
//
// + For all $dates please use the PHP strftime() syntax
// http://us2.php.net/manual/en/function.strftime.php
//
// + Non-intuitive parts of this file will be explained with comments. If you
// have any questions, please email lqqkout13@users.sourceforge.net
// or post questions in the Developers forum on SourceForge
// http://sourceforge.net/forum/forum.php?forum_id=331297
///////////////////////////////////////////////////////////
////////////////////////////////
/* Do not modify this section */
////////////////////////////////
global $strings; //
global $email; //
global $dates; //
global $charset; //
global $letters; //
global $days_full; //
global $days_abbr; //
global $days_two; //
global $days_letter; //
global $months_full; //
global $months_abbr; //
global $days_letter; //
/******************************/
// Charset for this language
// 'iso-8859-1' will work for most languages
$charset = 'iso-8859-1';
/***
DAY NAMES
All of these arrays MUST start with Sunday as the first element
and go through the seven day week, ending on Saturday
***/
// The full day name
$days_full = array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
// The three letter abbreviation
$days_abbr = array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
// The two letter abbreviation
$days_two = array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa');
// The one letter abbreviation
$days_letter = array('S', 'M', 'T', 'W', 'T', 'F', 'S');
/***
MONTH NAMES
All of these arrays MUST start with January as the first element
and go through the twelve months of the year, ending on December
***/
// The full month name
$months_full = array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
// The three letter month name
$months_abbr = array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
// All letters of the alphabet starting with A and ending with Z
$letters = array ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');
/***
DATE FORMATTING
All of the date formatting must use the PHP strftime() syntax
You can include any text/HTML formatting in the translation
***/
// General date formatting used for all date display unless otherwise noted
$dates['general_date'] = '%m/%d/%Y';
// General datetime formatting used for all datetime display unless otherwise noted
// The hour:minute:second will always follow this format
$dates['general_datetime'] = '%m/%d/%Y @';
$dates['header'] = '%A, %B %d, %Y';
/***
STRING TRANSLATIONS
All of these strings should be translated from the English value (right side of the equals sign) to the new language.
- Please keep the keys (between the [] brackets) as they are. The keys will not always be the same as the value.
- Please keep the sprintf formatting (%s) placeholders where they are unless you are sure it needs to be moved.
- Please keep the HTML and punctuation as-is unless you know that you want to change it.
***/
$strings['hours'] = 'hours';
$strings['minutes'] = 'minutes';
// The common abbreviation to hint that a user should enter the month as 2 digits
$strings['mm'] = 'mm';
// The common abbreviation to hint that a user should enter the day as 2 digits
$strings['dd'] = 'dd';
// The common abbreviation to hint that a user should enter the year as 4 digits
$strings['yyyy'] = 'yyyy';
$strings['am'] = 'am';
$strings['pm'] = 'pm';
$strings['Administrator'] = 'Administrator';
$strings['Welcome Back'] = 'Welcome Back, %s';
$strings['Log Out'] = 'Log Out';
$strings['Help'] = 'Help';
$strings['Admin Email'] = 'Admin Email';
$strings['Default'] = 'Default';
$strings['Reset'] = 'Reset';
$strings['Edit'] = 'Edit';
$strings['Delete'] = 'Delete';
$strings['Cancel'] = 'Cancel';
$strings['View'] = 'View';
$strings['Modify'] = 'Modify';
$strings['Save'] = 'Save';
$strings['Back'] = 'Back';
$strings['BackMessageIndex'] = 'Back to Messages';
$strings['ToggleHeaders'] = 'Toggle Headers';
$strings['ViewOriginal'] = 'View Original';
$strings['Next'] = 'Next';
$strings['Close Window'] = 'Close Window';
$strings['Search'] = 'Search';
$strings['Clear'] = 'Clear';
$strings['Days to Show'] = 'Days to Show';
$strings['Reservation Offset'] = 'Reservation Offset';
$strings['Hidden'] = 'Hidden';
$strings['Show Summary'] = 'Show Summary';
$strings['Add Schedule'] = 'Add Schedule';
$strings['Edit Schedule'] = 'Edit Schedule';
$strings['No'] = 'No';
$strings['Yes'] = 'Yes';
$strings['Name'] = 'Name';
$strings['First Name'] = 'First Name';
$strings['Last Name'] = 'Last Name';
$strings['Resource Name'] = 'Resource Name';
$strings['Email'] = 'Email';
$strings['Institution'] = 'Institution';
$strings['Phone'] = 'Phone';
$strings['Password'] = 'Password';
$strings['Permissions'] = 'Permissions';
$strings['View information about'] = 'View information about %s %s';
$strings['Send email to'] = 'Send email to %s %s';
$strings['Reset password for'] = 'Reset password for %s %s';
$strings['Edit permissions for'] = 'Edit permissions for %s %s';
$strings['Position'] = 'Position';
$strings['Password (6 char min)'] = 'Password (%s char min)'; // @since 1.1.0
$strings['Re-Enter Password'] = 'Re-Enter Password';
$strings['Date'] = 'Date';
$strings['Email Users'] = 'Email Users';
$strings['Subject'] = 'Subject';
$strings['Message'] = 'Message';
$strings['Send Email'] = 'Send Email';
$strings['problem sending email'] = 'Sorry, there was a problem sending your email. Please try again later.';
$strings['The email sent successfully.'] = 'The email sent successfully.';
$strings['Email address'] = 'Email address';
$strings['Please Log In'] = 'Please Log In';
$strings['Keep me logged in'] = 'Keep me logged in <br/>(requires cookies)';
$strings['Password'] = 'Password';
$strings['Log In'] = 'Log In';
$strings['Get online help'] = 'Get online help';
$strings['Language'] = 'Language';
$strings['(Default)'] = '(Default)';
$strings['Email Administrator'] = 'Email Administrator';
$strings['N/A'] = 'N/A';
$strings['Summary'] = 'Summary';
$strings['View stats for schedule'] = 'View stats for schedule:';
$strings['At A Glance'] = 'At A Glance';
$strings['Total Users'] = 'Total Users:';
$strings['Total Resources'] = 'Total Resources:';
$strings['Total Reservations'] = 'Total Reservations:';
$strings['Max Reservation'] = 'Max Reservation:';
$strings['Min Reservation'] = 'Min Reservation:';
$strings['Avg Reservation'] = 'Avg Reservation:';
$strings['Most Active Resource'] = 'Most Active Resource:';
$strings['Most Active User'] = 'Most Active User:';
$strings['System Stats'] = 'System Stats';
$strings['phpScheduleIt version'] = 'phpScheduleIt version:';
$strings['Database backend'] = 'Database backend:';
$strings['Database name'] = 'Database name:';
$strings['PHP version'] = 'PHP version:';
$strings['Server OS'] = 'Server OS:';
$strings['Server name'] = 'Server name:';
$strings['phpScheduleIt root directory'] = 'phpScheduleIt root directory:';
$strings['Using permissions'] = 'Using permissions:';
$strings['Using logging'] = 'Using logging:';
$strings['Log file'] = 'Log file:';
$strings['Admin email address'] = 'Admin email address:';
$strings['Tech email address'] = 'Tech email address:';
$strings['CC email addresses'] = 'CC email addresses:';
$strings['Reservation start time'] = 'Reservation start time:';
$strings['Reservation end time'] = 'Reservation end time:';
$strings['Days shown at a time'] = 'Days shown at a time:';
$strings['Reservations'] = 'Reservations';
$strings['Return to top'] = 'Return to top';
$strings['for'] = 'for';
$strings['Per page'] = 'Per page:';
$strings['Page'] = 'Page:';
$strings['You are not logged in!'] = 'You are not logged in!';
$strings['Setup'] = 'Setup';
$strings['Invalid User Name/Password.'] = 'Invalid User Name/Password.';
$strings['Valid username is required'] = 'Valid username is required';
$strings['Close'] = 'Close';
$strings['Admin'] = 'Admin';
$strings['My Quick Links'] = 'My Quick Links';
$strings['Go to first page'] = 'Go to first page';
$strings['Go to last page'] = 'Go to last page';
$strings['Sort by descending order'] = 'Sort by descending order';
$strings['Sort by ascending order'] = 'Sort by ascending order';
$strings['Spam Quarantine'] = 'Spam Quarantine';
$strings['Message View'] = 'Message View';
$strings['Attachment Quarantine'] = 'Attachment Quarantine';
$strings['No such content type'] = 'No such content type';
$strings['No message was selected'] = 'No message was selected ...';
$strings['Unknown action type'] = 'Unknown action type ...';
$strings['A problem occured when trying to release the following messages'] = 'A problem occured when trying to release the following messages';
$strings['A problem occured when trying to delete the following messages'] = 'A problem occured when trying to delete the following messages';
$strings['Please release the following messages'] = 'Please release the following messages';
$strings['To'] = 'To';
$strings['From'] = 'From';
$strings['Subject'] = 'Subject';
$strings['Date'] = 'Date';
$strings['Score'] = 'Score';
$strings['Mail ID'] = 'Mail ID';
$strings['Status'] = 'Status';
$strings['Print'] = 'Print';
$strings['CloseWindow'] = 'Close';
$strings['Unknown server type'] = 'Unknown server type ...';
$strings['Showing messages'] = "Showing messages %s through %s &nbsp;&nbsp; (%s total)\r\n";
$strings['View this message'] = 'View this message';
$strings['Message Unavailable'] = 'Message Unavailable';
$strings['My Quarantine'] = 'My Quarantine';
$strings['Site Quarantine'] = 'Site Quarantine';
$strings['Message Processing'] = 'Message Processing';
$strings['Quarantine Summary'] = 'Quarantine Summary';
$strings['Site Quarantine Summary'] = 'Site Quarantine Summary';
$strings['Login'] = 'Login';
$strings['spam(s)'] = 'spam(s)';
$strings['attachment(s)'] = 'attachment(s)';
$strings['pending release request(s)'] = 'pending release request(s)';
$strings['virus(es)'] = 'virus(es)';
$strings['bad header(s)'] = 'bad header(s)';
$strings['You have to type some text'] = 'You have to type some text';
$strings['Release'] = 'Release';
$strings['Release/Request release'] = 'Release/Request release';
$strings['Request release'] = 'Request release';
$strings['Delete'] = 'Delete';
$strings['Delete All'] = 'Delete All';
$strings['Send report and go back'] = 'Send report and go back';
$strings['Go back'] = "Go back";
$strings['Select All'] = "Select All";
$strings['Clear All'] = "Clear All";
$strings['Access Denied'] = "Access Denied";
$strings['My Pending Requests'] = "My Pending Requests";
$strings['Site Pending Requests'] = "Site Pending Requests";
$strings['Cancel Request'] = "Cancel Request";
$strings['User is not allowed to login'] = "User is not allowed to login";
$strings['Authentication successful'] = "Authentication successful";
$strings['Authentication failed'] = "Authentication failed";
$strings['LDAP connection failed'] = "LDAP/AD connection failed";
$strings['Logout successful'] = "Logout successful";
$strings['IMAP Authentication: no match'] = "IMAP Authentication: no match";
$strings['Search for messages whose:'] = "Search for messages whose:";
$strings['Content Type'] = "Content Type";
$strings['Clear search results'] = "Clear search results";
$strings['contains'] = "contains";
$strings['doesn\'t contain'] = "doesn't contain";
$strings['equals'] = "equals";
$strings['doesn\'t equal'] = "doesn't equal";
$strings['All'] = "All";
$strings['Spam'] = "Spam";
$strings['Banned'] = "Banned";
$strings['Virus'] = "Virus";
$strings['Viruses'] = "Viruses";
$strings['Bad Header'] = "Bad Header";
$strings['Bad Headers'] = "Bad Headers";
$strings['Pending Requests'] = "Pending Requests";
$strings['last'] = "last";
$strings['first'] = "first";
$strings['previous'] = "previous";
$strings['There was an error executing your query'] = 'There was an error executing your query:';
$strings['There are no matching records.'] = 'There are no matching records.';
$strings['Domain'] = 'Domain';
$strings['Total'] = 'Total';
$strings['X-Amavis-Alert'] = 'X-Amavis-Alert';
$strings['Loading Summary...'] = 'Loading Summary...';
$strings['Retrieving Messages...'] = 'Retrieving Messages...';
?>

164
lang/es.help.php Normal file
View File

@ -0,0 +1,164 @@
<?php
/**
* Spanish (es) help translation file.
* This also serves as the base translation file from which to derive
* all other translations.
*
* @author Brian Wong <bwsource@users.sourceforge.net>
* @translator Ricardo Muñoz <rmunoz@warp.es>
* @version 03-07-06
* @package Languages
*
* Copyright (C) 2003 - 2007 MailZu
* License: GPL, see LICENSE
*/
///////////////////////////////////////////////////////////
// INSTRUCTIONS
///////////////////////////////////////////////////////////
// This file contains all the help file for MailZu. Please save the translated
// file as '2 letter language code'.help.php. For example, en.help.php.
//
// To make MailZu help available in another language, simply translate this
// file into your language. If there is no direct translation, please provide the
// closest translation.
//
// This will be included in the body of the help file.
//
// Please keep the HTML formatting unless you need to change it. Also, please try
// to keep the HTML XHTML 1.0 Transitional complaint.
///////////////////////////////////////////////////////////
?>
<div align="center">
<h3><a name="top" id="top"></a>Introducción a MailZu</h3>
<p><a href="http://mailzu.net" target="_blank">http://mailzu.net</a></p>
<table width="100%" border="0" cellspacing="0" cellpadding="5" style="border: solid #CCCCCC 1px">
<tr>
<td bgcolor="#FAFAFA">
<ul>
<li><b><a href="#getting_started">Introducción</a></b></li>
<ul>
<li><a href="#logging_in">Iniciar sesión</a></li>
<li><a href="#language">Selección de lenguage</a></li>
<li><a href="#getting_support">Obtener soporte</a></li>
</ul>
<li><a href="#using_mailzu"><b>Usar MailZu</b></a></li>
<ul>
<li><a href="#quick_links">Mis enlaces rápidos</a></li>
<li><a href="#msg_summary">Resumen de mensajes</a></li>
<li><a href="#msg_index">Índices de mensajes</a></li>
<li><a href="#search">Búsqueda de mensajes</a></li>
<li><a href="#msg_view">Ver mensajes</a></li>
</ul>
</ul>
<hr width="95%" size="1" noshade="noshade" />
<h4><a name="getting_started" id="getting_started"></a>Introducción</h4>
<p> En la parte superior de cada p&aacute;gina podr&aacute; ver un
mensaje de bienvenida y la fecha actual.
Si se muestra a un usuario anterior en el mensaje de bienvenida, pulse
en &quot;Salir de sesi&oacute;n&quot; para limpiar cualquier cookie
anterior que haya sido usada e <a href="#logging_in">inicie
sesi&oacute;n</a> con su usuario.
Pulsando en el enlace de &quot;Ayuda&quot; aparecer&aacute; una ventana
emergente con la ayuda. Pulsando en el enlace &quot;Correo al
Administrador&quot; mandar&aacute; un correo electr&oacute;nico al
administrador del sistema.</p>
<p align="right"><a href="#top">Arriba</a></p>
<h5><a name="logging_in" id="logging_in"></a>Iniciando sesi&oacute;n</h5>
<p>Para iniciar sesi&oacute;n, los usuarios deben establecer su
identificador de usuario y su contrase&ntilde;a. El identificador de
usuario debe ser su direcci&oacute;n de correo electr&oacute;nico
completa ('usuario@dominio.com') o simplemente su nombre de usuario
('usuario'). El administrador le informar&aacute; de la manera correcta.
Seleccionando la opci&oacute;n &quot;Mantener inicio de
sesi&oacute;n&quot; se usar&aacute;n cookies para identificarle cada vez
que regrese a ver su cuarentena, sin necesidad de iniciar sesi&oacute;n
cada vez. <i>Solo deber&aacute; usar esta opci&oacute;n si es la
&uacute;nica persona que usa MailZu en su computadora.</i>
Despu&eacute;s de iniciar sesi&oacute;n ser&aacute; redirigido al <a
href="#message_summary">Resumen de mensajes</a>.</p>
<p align="right"><a href="#top">Arriba</a></p>
<h5><a name="language" id="language"></a>Seleccionando Mi Lenguaje</h5>
<p>En la p&aacute;gina de inicio de sesi&oacute;n, encontrar&aacute; un
men&uacute; desplegable con todos los lenguajes traducidos disponibles
que su administrador ha incluido. Seleccione el lenguaje que prefiera y
todo el texto de MailZu ser&aacute; traducido. Esto no
traducir&aacute; el texto relacionado con los mensajes de los correos
electr&oacute;nicos; s&oacute;lo traduce los textos de la
aplicaci&oacute;n. Necesitar&aacute; salir de sesi&oacute;n para
seleccionar un lenguaje diferente.</p>
<p align="right"><a href="#top">Arriba</a></p>
<h5><a name="getting_support" id="getting_support"></a>Obteniendo Ayuda</h5>
<p>Si necesita asistencia de sus mensajes en cuarentena o cualquier otra
cosa, no dude en usar el enlace &quot;Correo al Administrador&quot;
localizado en <a href="#quick_links">Mis enlaces r&aacute;pidos</a>.</p>
<p align="right"><a href="#top">Arriba</a></p> <p align="right">&nbsp;</p>
<hr width="95%" size="1" noshade="noshade" />
<h4><a name="using_mailzu" id="using_mailzu"></a>Usar MailZu</h4>
<p>MailZu permite a los usuarios ver los mensajes en cuarentena
bas&aacute;ndose en el tipo de los mensajes.
Los tipos m&aacute;s frecuentes de mensaje que entrar&aacute;n en
cuarentena ser&aacute;n aquellos que sean considerados spam o que
contengan adjuntos prohibidos.
<p align="right"><a href="#top">Arriba</a></p>
<h5><a name="quick_links" id="quick_links"></a>Mis enlaces rápidos</h5>
<p>La tabla de enlaces rápidos le ofrecer&aacute; los enlaces mas
comunes.
El primero, &quot;Resumen de la cuarentena &quot; le ofrecer&aacute; una
visi&oacute;n general de sus mensajes en cuarentena.</p>
<p> &quot;Mi Cuarentena&quot; le muestra un &iacute;ndice de su correo
electr&oacute;nico no solicitado y adjuntos prohibidos.</p>
<p>&quot;Correo al administrador&quot; es una manera r&aacute;pida de
ponerse en contacto con su administrador si necesita asistencia.</p>
<p>&quot;Ayuda&quot; le muestra este documento.</p>
<p>El &uacute;ltimo enlace, &quot;Salir de sesi&oacute;n&quot;
saldr&aacute; de su sesi&oacute;n actual y volver&aacute; a la pantalla
de inicio de sesi&oacute;n.</p>
<p align="right"><a href="#top">Arriba</a></p>
<h5><a name="msg_summary" id="msg_summary"></a>Resumen de mensajes</h5>
<p> El resumen de mensajes es la p&aacute;gina por defecto tras iniciar
sesi&oacute;n. Le ofrece un contaje r&aacute;pido de cuantos mensajes tiene
en su cuarentena y su tipo.
<p align="right"><a href="#top">Arriba</a></p>
<h5><a name="msg_index" id="msg_index"></a>&Iacute;ndice de mensajes</h5>
<p>&Iacute;ndice de mensajes muestra todos los mensajes de la cuarentena
seleccionada.
Por cada mensaje en cuarentena, el &iacute;ndice muestra el remitente,
el asunto y la fecha.
Dependiendo de la cuarentena que se este viendo, el &iacute;ndice puede
mostrar mas informaci&oacute;n.</p>
<p>Para ordenar sus &iacute;ndices por un campo espec&iacute;fico, pulse
sobre el t&iacute;tulo del campo. Pulsando de nuevo sobre el mismo
obtendr&aacute; la ordenaci&oacute;n inversa.</p>
<p>Estan disponibles varios botones para manejar los mensajes mostrados
en el &iacute;ndice. La acci&oacute;n 'Liberar/Petici&oacute;n' elimina
el mensaje del &iacute;ndice y entrega el correo como si nunca hubiera
estado en cuarentena. La acci&oacute;n 'Eliminar' s&oacute;lo elimina el
mensaje del &iacute;ndice. Estos botones realizan las acciones sobre los
mensajes seleccionados a trav&eacute;s de las cajas de selecci&oacute;n.
El bot&oacute;n 'Eliminar todos' ignora el estado de las cajas de
selecci&oacute;n y elimina todos los mensajes de la cuarentena
seleccionada.</p>
<p>Mientas este viendo sus peticiones pendientes puede retirar la
petici&oacute;n pulsando sobre 'Cancelar petici&oacute;n'. El mensaje ya no
estar&aacute; encolado para que el administrador lo revise.</p>
<p align="right"><a href="#top">Arriba</a></p>
<h5><a name="search" id="search"></a>B&uacute;scar mensaje</h5>
<p>Usando la funci&oacute;n buscar, dispondr&aacute; de una manera
r&aacute;pida para encontrar un mensaje que crea que se encuentra en
cuarentena. Puede buscar un mensaje especificando tanto qui&eacute;n es
remitente, como cual es su asunto, o ambos. La b&uacute;squeda no es
sensible a may&uacute;sculas y min&uacute;sculas.</p>
<p align="right"><a href="#top">Arriba</a></p>
<h5><a name="msg_view" id="msg_view"></a>Ver mensaje</h5>
<p>Ver mensaje le permite ver el contenido del mismo para ayudarle a
determinar si se trata de un mensaje leg&iacute;timo. Esta vista le
ofrece otras opciones como mostrar el mensaje original en texto plano y
ver las cabeceras adicionales. </p>
<p align="right"><a href="#top">Arriba</a></p> <p align="right">&nbsp;</p>
<hr width="95%" size="1" noshade="noshade" />
</td>
</tr>
</table>
</div>

324
lang/es.lang.php Normal file
View File

@ -0,0 +1,324 @@
<?php
/**
* Spanish (es) translation file.
* Based on phpScheduleIt translation file.
* This also serves as the base translation file from which to derive
* all other translations.
*
* @author Samuel Tran <stran2005@users.sourceforge.net>
* @author Brian Wong <bwsource@users.sourceforge.net>
* @author Nicolas Peyrussie <peyrouz@users.sourceforge.net>
* @translator Ricardo Muñoz <rmunoz@warp.es>
* @version 04-03-07
* @package Languages
*
* Copyright (C) 2005 - 2007 MailZu
* License: GPL, see LICENSE
*/
///////////////////////////////////////////////////////////
// INSTRUCTIONS
///////////////////////////////////////////////////////////
// This file contains all of the strings that are used throughout phpScheduleit.
// Please save the translated file as '2 letter language code'.lang.php. For example, en.lang.php.
//
// To make phpScheduleIt available in another language, simply translate each
// of the following strings into the appropriate one for the language. If there
// is no direct translation, please provide the closest translation. Please be sure
// to make the proper additions the /config/langs.php file (instructions are in the file).
// Also, please add a help translation for your language using en.help.php as a base.
//
// You will probably keep all sprintf (%s) tags in their current place. These tags
// are there as a substitution placeholder. Please check the output after translating
// to be sure that the sentences make sense.
//
// + Please use single quotes ' around all $strings. If you need to use the ' character, please enter it as \'
// + Please use double quotes " around all $email. If you need to use the " character, please enter it as \"
//
// + For all $dates please use the PHP strftime() syntax
// http://us2.php.net/manual/en/function.strftime.php
//
// + Non-intuitive parts of this file will be explained with comments. If you
// have any questions, please email lqqkout13@users.sourceforge.net
// or post questions in the Developers forum on SourceForge
// http://sourceforge.net/forum/forum.php?forum_id=331297
///////////////////////////////////////////////////////////
////////////////////////////////
/* Do not modify this section */
////////////////////////////////
global $strings; //
global $email; //
global $dates; //
global $charset; //
global $letters; //
global $days_full; //
global $days_abbr; //
global $days_two; //
global $days_letter; //
global $months_full; //
global $months_abbr; //
global $days_letter; //
/******************************/
// Charset for this language
// 'iso-8859-1' will work for most languages
$charset = 'iso-8859-1';
/***
DAY NAMES
All of these arrays MUST start with Sunday as the first element
and go through the seven day week, ending on Saturday
***/
// The full day name
$days_full = array('Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves',
'Viernes', 'Sábado');
// The three letter abbreviation
$days_abbr = array('Dom', 'Lun', 'Mar', 'Mie', 'Jue', 'Vie', 'Sab');
// The two letter abbreviation
$days_two = array('Do', 'Lu', 'Ma', 'Mi', 'Ju', 'Vi', 'Sa');
// The one letter abbreviation
$days_letter = array('D', 'L', 'M', 'X', 'J', 'V', 'S');
/***
MONTH NAMES
All of these arrays MUST start with January as the first element
and go through the twelve months of the year, ending on December
***/
// The full month name
$months_full = array('Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre');
// The three letter month name
$months_abbr = array('Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Oct', 'Nov', 'Dic');
// All letters of the alphabet starting with A and ending with Z
$letters = array ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');
/***
DATE FORMATTING
All of the date formatting must use the PHP strftime() syntax
You can include any text/HTML formatting in the translation
***/
// General date formatting used for all date display unless otherwise noted
$dates['general_date'] = '%d/%m/%Y';
// General datetime formatting used for all datetime display unless otherwise noted
// The hour:minute:second will always follow this format
$dates['general_datetime'] = '%d/%m/%Y @';
$dates['header'] = '%A, %d %B, %Y';
/***
STRING TRANSLATIONS
All of these strings should be translated from the English value (right side of the equals sign) to the new language.
- Please keep the keys (between the [] brackets) as they are. The keys will not always be the same as the value.
- Please keep the sprintf formatting (%s) placeholders where they are unless you are sure it needs to be moved.
- Please keep the HTML and punctuation as-is unless you know that you want to change it.
***/
$strings['hours'] = 'horas';
$strings['minutes'] = 'minutos';
// The common abbreviation to hint that a user should enter the month as 2 digits
$strings['mm'] = 'mm';
// The common abbreviation to hint that a user should enter the day as 2 digits
$strings['dd'] = 'dd';
// The common abbreviation to hint that a user should enter the year as 4 digits
$strings['yyyy'] = 'aaaa';
$strings['am'] = 'am';
$strings['pm'] = 'pm';
$strings['Administrator'] = 'Administrador';
$strings['Welcome Back'] = 'Bienvenido de nuevo, %s';
$strings['Log Out'] = 'Salir de sesión';
$strings['Help'] = 'Ayuda';
$strings['Admin Email'] = 'Correo administrador';
$strings['Default'] = 'Por defecto';
$strings['Reset'] = 'Reestablecer';
$strings['Edit'] = 'Editar';
$strings['Delete'] = 'Eliminar';
$strings['Cancel'] = 'Cancelar';
$strings['View'] = 'Ver';
$strings['Modify'] = 'Modificar';
$strings['Save'] = 'Guardar';
$strings['Back'] = 'Volver';
$strings['BackMessageIndex'] = 'Volver a mensajes';
$strings['ToggleHeaders'] = 'Mostrar cabeceras';
$strings['ViewOriginal'] = 'Ver original';
$strings['Next'] = 'Siguiente';
$strings['Close Window'] = 'Cerrar ventana';
$strings['Search'] = 'Buscar';
$strings['Clear'] = 'Limpiar';
$strings['Days to Show'] = 'Días a ver';
$strings['Reservation Offset'] = 'Reservation Offset';
$strings['Hidden'] = 'Oculto';
$strings['Show Summary'] = 'Mostrar resumen';
$strings['Add Schedule'] = 'Añadir calendario';
$strings['Edit Schedule'] = 'Editar calendario';
$strings['No'] = 'No';
$strings['Yes'] = 'Sí';
$strings['Name'] = 'Nombre';
$strings['First Name'] = 'Nombre';
$strings['Last Name'] = 'Apellidos';
$strings['Resource Name'] = 'Resource Name';
$strings['Email'] = 'Correo electrónico';
$strings['Institution'] = 'Institución';
$strings['Phone'] = 'Teléfono';
$strings['Password'] = 'Contraseña';
$strings['Permissions'] = 'Permisos';
$strings['View information about'] = 'Ver información sobre %s %s';
$strings['Send email to'] = 'Enviar correo a %s %s';
$strings['Reset password for'] = 'Reestablecer contraseña a %s %s';
$strings['Edit permissions for'] = 'Editar permisos a %s %s';
$strings['Position'] = 'Posición';
$strings['Password (6 char min)'] = 'Contraseña (%s carácteres min.)'; // @since 1.1.0
$strings['Re-Enter Password'] = 'Introducir contraseña de nuevo';
$strings['Date'] = 'Fecha';
$strings['Email Users'] = 'Correo de usuarios';
$strings['Subject'] = 'Asunto';
$strings['Message'] = 'Mensaje';
$strings['Send Email'] = 'Enviar correo';
$strings['problem sending email'] = 'Lo sentimos, hay un problema enviando su correo. Por favor inténtelo mas tarde.';
$strings['The email sent successfully.'] = 'El correo se ha enviado correctamente.';
$strings['Email address'] = 'Dirección de correo';
$strings['Please Log In'] = 'Por favor inicie sesión';
$strings['Keep me logged in'] = 'Mantener sesión <br/>(requiere cookies)';
$strings['Password'] = 'Contraseña';
$strings['Log In'] = 'Iniciar sesión';
$strings['Get online help'] = 'Obtener ayuda';
$strings['Language'] = 'Lenguaje';
$strings['(Default)'] = '(Por defecto)';
$strings['Email Administrator'] = 'Correo al administrador';
$strings['N/A'] = 'N/A';
$strings['Summary'] = 'Resumen';
$strings['View stats for schedule'] = 'Ver estadísticas por calendario';
$strings['At A Glance'] = 'De un vistazo';
$strings['Total Users'] = 'Usuarios totales';
$strings['Total Resources'] = 'Recursos totales';
$strings['Total Reservations'] = 'Reservas totales';
$strings['Max Reservation'] = 'Reservas máximas';
$strings['Min Reservation'] = 'Reservas mínimas';
$strings['Avg Reservation'] = 'Reservas medias';
$strings['Most Active Resource'] = 'Recurso más activo';
$strings['Most Active User'] = 'Usuario más activo';
$strings['System Stats'] = 'Estadísticas del sistema';
$strings['phpScheduleIt version'] = 'Versión de phpScheduleIt';
$strings['Database backend'] = 'Sistema de base de datos';
$strings['Database name'] = 'Nombre de la base de datos';
$strings['PHP version'] = 'Versión de PHP';
$strings['Server OS'] = 'S.O. del servidor';
$strings['Server name'] = 'Nombre del servidor';
$strings['phpScheduleIt root directory'] = 'Directorio raíz de phpScheduleIt';
$strings['Using permissions'] = 'Usando permisos';
$strings['Using logging'] = 'Usando inicio de sesión';
$strings['Log file'] = 'Fichero de log';
$strings['Admin email address'] = 'Dirección de correo del administrador';
$strings['Tech email address'] = 'Dirección de correo de la asistencia técnica';
$strings['CC email addresses'] = 'Dirección de correo en CC';
$strings['Reservation start time'] = 'Hora de comienzo de la reserva';
$strings['Reservation end time'] = 'Hora de finalización de la reserva';
$strings['Days shown at a time'] = 'Días mostrados cada vez';
$strings['Reservations'] = 'Reservas';
$strings['Return to top'] = 'Volver arriba';
$strings['for'] = 'para';
$strings['Per page'] = 'Por página';
$strings['Page'] = 'Página';
$strings['You are not logged in!'] = '¡No ha iniciado sesión!';
$strings['Setup'] = 'Setup';
$strings['Invalid User Name/Password.'] = 'Usuario/Contraseña invalidas.';
$strings['Valid username is required'] = 'Usuario válido requerido.';
$strings['Close'] = 'Cerrar';
$strings['Admin'] = 'Administrar';
$strings['My Quick Links'] = 'Mis enlaces rápidos';
$strings['Go to first page'] = 'Ir a la primera página';
$strings['Go to last page'] = 'Ir a la última página';
$strings['Sort by descending order'] = 'Ordenar en sentido descendente';
$strings['Sort by ascending order'] = 'Ordenar en sentido ascendente';
$strings['Spam Quarantine'] = 'Spam en cuarentena';
$strings['Message View'] = 'Ver mensaje';
$strings['Attachment Quarantine'] = 'Cuarentena de adjuntos';
$strings['No such content type'] = 'No hay tal tipo de contenido ';
$strings['No message was selected'] = 'Ningún mensaje fue seleccionado ...';
$strings['Unknown action type'] = 'Tipo de acción desconocida ...';
$strings['A problem occured when trying to release the following messages'] = 'Ha ocurrido un problema al liberar los siguientes mensajes';
$strings['A problem occured when trying to delete the following messages'] = 'Ha ocurrido un problema al eliminar los siguientes mensajes';
$strings['Please release the following messages'] = 'Por favor, libere los siguiente mensajes';
$strings['To'] = 'Para';
$strings['From'] = 'De';
$strings['Subject'] = 'Asunto';
$strings['Date'] = 'Fecha';
$strings['Score'] = 'Puntuación';
$strings['Mail ID'] = 'ID Correo';
$strings['Status'] = 'Estado';
$strings['Print'] = 'Imprimir';
$strings['CloseWindow'] = 'Cerrar';
$strings['Unknown server type'] = 'Tipo de servidor desconocido ...';
$strings['Showing messages'] = "Mostrando los mensajes %s a %s &nbsp;&nbsp; (%s total)\r\n";
$strings['View this message'] = 'Ver este mensaje';
$strings['Message Unavailable'] = 'Mensaje no disponible';
$strings['My Quarantine'] = 'Mi cuarentena';
$strings['Site Quarantine'] = 'Cuarentena del sitio';
$strings['Message Processing'] = 'Procesando mensaje';
$strings['Quarantine Summary'] = 'Resumen de la cuarentena';
$strings['Site Quarantine Summary'] = 'Resumen de la cuarentena del sitio';
$strings['Login'] = 'Iniciar sesión';
$strings['spam(s)'] = 'spam(s)';
$strings['attachment(s)'] = 'adjunto(s)';
$strings['pending release request(s)'] = 'Peticion(es) de liberación pendientes';
$strings['virus(es)'] = 'virus';
$strings['bad header(s)'] = 'mal(os) jefe(s)';
$strings['You have to type some text'] = 'Tiene que escribir algo de texto';
$strings['Release'] = 'Liberar';
$strings['Release/Request release'] = 'Liberar/Pedir liberación';
$strings['Request release'] = 'Pedir liberar';
$strings['Delete'] = 'Eliminar';
$strings['Delete All'] = 'Eliminar todos';
$strings['Send report and go back'] = 'Enviar un informe y volver';
$strings['Go back'] = "Ir atrás";
$strings['Select All'] = "Seleccionar todos";
$strings['Clear All'] = "No seleccionar ninguno";
$strings['Access Denied'] = "Acceso denegado";
$strings['My Pending Requests'] = "Mis peticiones pendientes";
$strings['Site Pending Requests'] = "Peticion del sitio pendientes";
$strings['Cancel Request'] = "Cancelar petición";
$strings['User is not allowed to login'] = "Inicio de sesión de usuario no permitida.";
$strings['Authentication successful'] = "Autenticación correcta";
$strings['Authentication failed'] = "Autenticación fallida";
$strings['LDAP connection failed'] = "Conexión LDAP/AD fallida";
$strings['Logout successful'] = "Sesión cerrada correctamente";
$strings['IMAP Authentication: no match'] = "Autenticación IMAP: no concuerda";
$strings['Search for messages whose:'] = "Buscar por mensajes los cuales:";
$strings['Content Type'] = "Tipo de contenido";
$strings['Clear search results'] = "Limpiar resultados de la búsqueda";
$strings['contains'] = "contiene";
$strings['doesn\'t contain'] = "no contiene";
$strings['equals'] = "igual";
$strings['doesn\'t equal'] = "no igual";
$strings['All'] = "Todos";
$strings['Spam'] = "Spam";
$strings['Banned'] = "Prohibidos";
$strings['Virus'] = "Virus";
$strings['Viruses'] = 'Viruses';
$strings['Bad Header'] = "Mal Jefe";
$strings['Bad Headers'] = 'Malos Jefes';
$strings['Pending Requests'] = 'Peticiones de liberación';
$strings['last'] = "último";
$strings['first'] = "primero";
$strings['previous'] = "anterior";
$strings['There was an error executing your query'] = 'Ha habido un error ejecutando la petición';
$strings['There are no matching records.'] = 'No hay registros que concuerden con la búsqueda.';
$strings['Domain'] = 'Dominio';
$strings['Total'] = 'Total';
$strings['X-Amavis-Alert'] = 'X-Amavis-Alert';
$strings['Loading Summary...'] = 'Loading Summary...';
$strings['Retrieving Messages...'] = 'Retrieving Messages...';
?>

138
lang/fr.help.php Normal file
View File

@ -0,0 +1,138 @@
<?php
/**
* French (fr) help translation file.
*
* @author Samuel Tran <stran2005@users.sourceforge.net>
* @version 12/15/2005
* @package Languages
*
* Copyright (C) 2003 - 2007 MailZu
* License: GPL, see LICENSE
*/
///////////////////////////////////////////////////////////
// INSTRUCTIONS
///////////////////////////////////////////////////////////
// This file contains all the help file for MailZu. Please save the translated
// file as '2 letter language code'.help.php. For example, en.help.php.
//
// To make MailZu help available in another language, simply translate this
// file into your language. If there is no direct translation, please provide the
// closest translation.
//
// This will be included in the body of the help file.
//
// Please keep the HTML formatting unless you need to change it. Also, please try
// to keep the HTML XHTML 1.0 Transitional complaint.
///////////////////////////////////////////////////////////
?>
<div align="center">
<h3><a name="top" id="top"></a>Introduction</h3>
<p><a href="http://mailzu.net" target="_blank">http://mailzu.net</a></p>
<table width="100%" border="0" cellspacing="0" cellpadding="5" style="border: solid #CCCCCC 1px">
<tr>
<td bgcolor="#FAFAFA">
<ul>
<li><b><a href="#getting_started">Préliminaires</a></b></li>
<ul>
<li><a href="#logging_in">Connexion</a></li>
<li><a href="#language">Choisir ma langue</a></li>
<li><a href="#getting_support">Obtenir de l'aide</a></li>
</ul>
<li><a href="#using_mailzu"><b>Utilisation de MailZu</b></a></li>
<ul>
<li><a href="#quick_links">Mes liens rapides</a></li>
<li><a href="#msg_summary">Résumé de la Quarantaine</a></li>
<li><a href="#msg_index">Liste des Messages</a></li>
<li><a href="#search">Recherche des Messages</a></li>
<li><a href="#msg_view">Affichage des Messages</a></li>
</ul>
</ul>
<hr width="95%" size="1" noshade="noshade" />
<h4><a name="getting_started" id="getting_started"></a>Préliminaires</h4>
<p> En haut de chaque page vous trouverez un message de bienvenue et la date du jour.
Si votre identification n'est pas affichée dans le message de bienvenue, cliquez sur &quot;Quitter
&quot; pour supprimer les cookies de l'utilisateur précédent et <a href="#logging_in">se
connecter</a> avec votre identifiant.
Cliquer sur le lien &quot;Aide&quot; fait apparaître une fenêtre d'aide. Cliquer sur
le lien &quot;Envoi d'un message électronique à l'administrateur&quot; permet de composer un message adressé à
l'administrateur système.</p>
<p align="right"><a href="#top">Retour en haut</a></p>
<h5><a name="logging_in" id="logging_in"></a>Se connecter</h5>
<p>Pour se connecter, l'utilisateur doit fournir son identifiant et mot de passe. L'identifiant
peut être votre adresse électronique ('utilisateur@exemple.fr') ou simplement
votre nom de compte ('utilisateur'). L'administrateur devrait vous informer du type
d'identifiant à utiliser. Selectionner l'option &quot;Maintenir ma connexion&quot; permet d'utiliser
des cookies pour vous identifier à chaque fois que vous retournez à la page de connexion, vous évitant
de vous connecter à nouveau. <i>Vous devriez utiliser cette option si
vous êtes la seule personne utilisant MailZu sur votre poste de travail.</i> Après
la connexion, vous serez redirigé vers la <a href="#message_summary">
Résumé de la quarantaine</a>.</p>
<p align="right"><a href="#top">Retour en haut</a></p>
<h5><a name="language" id="language"></a>Choisir ma langue</h5>
<p>Sur la page de connexion, il y a un menu déroulant avec toutes les langues
qui sont disponibles.
S'il vous plaît, choisissez la langue que vous préférez et tout le texte dans MailZu
sera traduit. Cela ne traduira pas le texte qui est inclus dans les messages
électronique; seulement le texte de l'interface sera traduit. Vous aurez besoin de vous
déconnecter pour choisir une langue différente.</p>
<p align="right"><a href="#top">Retour en haut</a></p>
<h5><a name="getting_support" id="getting_support"></a>Obtenir
de l'aide</h5>
<p>Si vous avez besoin d'assistance pour afficher vos messages en quarantaine ou quelqu'autre
problème, n'hésitez pas à utiliser le lien &quot;Envoi d'un message électronique à
l'administrateur&quot; situé sur <a href="#quick_links">Mes liens rapides</a>.</p>
<p align="right"><a href="#top">Retour en haut</a></p> <p align="right">&nbsp;</p>
<hr width="95%" size="1" noshade="noshade" />
<h4><a name="using_mailzu" id="using_mailzu"></a>Utilisez MailZu</h4>
<p>MailZu permet à l'utilisateur d'afficher ses messages en quarantaine organisés par type de messages.
Les principaux types de messages qui seront mis en quarantaine sont ceux qui sont considérés
comme spam, ou qui contiennent un attachement interdit.
<p align="right"><a href="#top">Retour en haut</a></p>
<h5><a name="quick_links" id="quick_links"></a>Mes liens rapides</h5>
<p>Ce menu vous donne accès aux différentes raccourcis de l'application.
Le premier lien &quot;Résumé de la Quarantaine&quot; vous donnera un aperçu de votre quarantaine.</p>
<p> &quot;Ma Quarantaine&quot; vous conduira à l'index
vos messages non sollicités et attachements interdits.</p>
<p>&quot;Envoi d'un message électronique à l'administrateur'&quot; est un moyen rapide pour contacter
votre support technique si vous avez besoin d'aide.</p>
<p>&quot;Aide&quot; vous donne accès à ce document.</p>
<p>Le dernier lien, &quot;Quitter&quot; vous déconnectera de votre session courante
et vous renverra à la page de connexion.</p>
<p align="right"><a href="#top">Retour en haut</a></p>
<h5><a name="msg_summary" id="msg_summary"></a>Résumé de la Quarantaine</h5>
<p> Le Résumé de la Quarantaine est la première page après la connexion. Il affiche le nombre de messages
dans votre quarantaine par type.
<p align="right"><a href="#top">Retour en haut</a></p>
<h5><a name="msg_index" id="msg_index"></a>Index des Messages</h5>
<p> L'index des Messages affiche tous les messages électroniques mises en quarantaine.
Pour chaque message mise en quarantaine, l'index affiche l'émetteur, l'object, et la date. En fonction
de la quarantaine inspectée, l'index peut afficher plus d'information.</p>
<p>Pour trier votre index par un champ particulier, cliquer sur le nom du champ. Cliquer sur le nom du champ
à nouveau inversera le sens du tri.</p>
<p>Plusieurs boutons sont à votre disposition pour traiter les messages affichés dans l'index. Le bouton
'Réémission/Demande de réémission' retire le message de l'index et ré-émet le message comme s'il n'a jamais
été mis en quarantaine. Le bouton 'Supprimer' retire seulement le message de l'index.
Ces boutons agissent sur le ou les messages sélectionnés à l'aide des cases de sélection.
Le bouton 'Supprimer tout' ne tient pas compte des cases sélectionnées et retire tous les messages de la
quarantaine sélectionnée.</p>
<p>Quand vous visualisez vos requêtes en attente, vous pouvez annuler une requête en cliquant sur
'Annule requête'. Le message ne sera plus dans la file d'attente de l'administrateur pour re-émission.
</p>
<p align="right"><a href="#top">Retour en haut</a></p>
<h5><a name="search" id="search"></a>Recherche de message</h5>
<p>Utiliser la fonction de recherche est un moyen rapide de trouver un message que vous pensez avoir été
mise en quarantaine. Vous pouvez chercher un message en spécifiant l'émetteur, ou
l'objet, or les deux. La recherche ne tient pas compte des majuscules.</p>
<p align="right"><a href="#top">Retour en haut</a></p>
<h5><a name="msg_view" id="msg_view"></a>Voir le message</h5>
<p>Cela vous permet de voir le contenu du message vous aidant ainsi à déterminer
si le message est legitime. La visualisation vous offre d'autres options telles que
l'affichage du message original en mode texte ou l'affichage d'en-têtes additionels.
</p>
<p align="right"><a href="#top">Retour en haut</a></p> <p align="right">&nbsp;</p>
<hr width="95%" size="1" noshade="noshade" />
</td>
</tr>
</table>
</div>

318
lang/fr.lang.php Normal file
View File

@ -0,0 +1,318 @@
<?php
/**
* French (fr) translation file.
* Based on phpScheduleIt translation file.
* This also serves as the base translation file from which to derive
*
* @author Samuel Tran <stran2005@users.sourceforge.net>
* @author Nicolas Peyrussie <peyrouz@users.sourceforge.net>
* @version 04-03-07
* @package Languages
*
* Copyright (C) 2005 - 2007 MailZu
* License: GPL, see LICENSE
*/
///////////////////////////////////////////////////////////
// INSTRUCTIONS
///////////////////////////////////////////////////////////
// This file contains all of the strings that are used throughout phpScheduleit.
//
// To make phpScheduleIt available in another language, simply translate each
// of the following strings into the appropriate one for the language. Please be sure
// to make the proper additions the /config/langs.php file (instructions are in the file).
//
// You will probably keep all sprintf (%s) tags in their current place. These tags
// are there as a substitution placeholder. Please check the output after translating
// to be sure that the sentences make sense.
//
// + Please use single quotes ' around all $strings. If you need to use the ' character, please enter it as \'
// + Please use double quotes " around all $email. If you need to use the " character, please enter it as \"
//
// + For all $dates please use the PHP strftime() syntax
// http://us2.php.net/manual/en/function.strftime.php
//
// + Non-intuitive parts of this file will be explained with comments. If you
// have any questions, please email lqqkout13@users.sourceforge.net
// or post questions in the Developers forum on SourceForge
// http://sourceforge.net/forum/forum.php?forum_id=331297
///////////////////////////////////////////////////////////
////////////////////////////////
/* Do not modify this section */
////////////////////////////////
global $strings; //
global $email; //
global $dates; //
global $charset; //
global $letters; //
global $days_full; //
global $days_abbr; //
global $days_two; //
global $days_letter; //
global $months_full; //
global $months_abbr; //
global $days_letter; //
/******************************/
// Charset for this language
// 'iso-8859-1' will work for most languages
$charset = 'iso-8859-1';
/***
DAY NAMES
All of these arrays MUST start with Sunday as the first element
and go through the seven day week, ending on Saturday
***/
// The full day name
$days_full = array('Dimanche', 'Lundi', 'Mardi', 'Mercredi', 'Jeudi', 'Vendredi', 'Samedi');
// The three letter abbreviation
$days_abbr = array('Dim', 'Lun', 'Mar', 'Mer', 'Jeu', 'Ven', 'Sam');
// The two letter abbreviation
$days_two = array('Di', 'Lu', 'Ma', 'Me', 'Je', 'Ve', 'Sa');
// The one letter abbreviation
$days_letter = array('D', 'L', 'M', 'M', 'J', 'V', 'S');
/***
MONTH NAMES
All of these arrays MUST start with January as the first element
and go through the twelve months of the year, ending on December
***/
// The full month name
$months_full = array('Janvier', 'Fevrier', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Aout', 'Septembre', 'Octobre', 'Novembre', 'Decembre');
// The three letter month name
$months_abbr = array('Jan', 'Fev', 'Mar', 'Avr', 'Mai', 'Jun', 'Jul', 'Aou', 'Sep', 'Oct', 'Nov', 'Dec');
// All letters of the alphabet starting with A and ending with Z
$letters = array ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');
/***
DATE FORMATTING
All of the date formatting must use the PHP strftime() syntax
You can include any text/HTML formatting in the translation
***/
// General date formatting used for all date display unless otherwise noted
$dates['general_date'] = '%d/%m/%Y';
// General datetime formatting used for all datetime display unless otherwise noted
// The hour:minute:second will always follow this format
$dates['general_datetime'] = '%d/%m/%Y @';
// Date on top-right of each page
$dates['header'] = '%A, %B %d, %Y';
/***
STRING TRANSLATIONS
All of these strings should be translated from the English value (right side of the equals sign) to the new language.
- Please keep the keys (between the [] brackets) as they are. The keys will not always be the same as the value.
- Please keep the sprintf formatting (%s) placeholders where they are unless you are sure it needs to be moved.
- Please keep the HTML and punctuation as-is unless you know that you want to change it.
***/
$strings['hours'] = 'heures';
$strings['minutes'] = 'minutes';
// The common abbreviation to hint that a user should enter the month as 2 digits
$strings['mm'] = 'mm';
// The common abbreviation to hint that a user should enter the day as 2 digits
$strings['dd'] = 'jj';
// The common abbreviation to hint that a user should enter the year as 4 digits
$strings['yyyy'] = 'aaaa';
$strings['am'] = 'am';
$strings['pm'] = 'pm';
$strings['Administrator'] = 'Administrateur';
$strings['Welcome Back'] = 'Bienvenue, %s';
$strings['Log Out'] = 'Quitter';
$strings['Help'] = 'Aide';
$strings['Admin Email'] = 'Adresse messagerie de l\'administrateur';
$strings['Default'] = 'Defaut';
$strings['Reset'] = 'Ré-initialisation';
$strings['Edit'] = 'Mise à jour';
$strings['Delete'] = 'Effacement';
$strings['Cancel'] = 'Annulation';
$strings['View'] = 'Visualisation';
$strings['Modify'] = 'Modification';
$strings['Save'] = 'Sauvegarde';
$strings['Back'] = 'Retour';
$strings['BackMessageIndex'] = 'Retour aux messages';
$strings['ToggleHeaders'] = 'Voir/Cacher les en-têtes';
$strings['ViewOriginal'] = 'Voir le message original';
$strings['Next'] = 'Suivant';
$strings['Close Window'] = 'Fermeture de fenêtre';
$strings['Search'] = 'Recherche';
$strings['Clear'] = 'Effacement';
$strings['Days to Show'] = 'Jours à visualiser';
$strings['Reservation Offset'] = 'Période de réservation';
$strings['Hidden'] = 'Caché';
$strings['Show Summary'] = 'Visualisation abrégée';
$strings['Add Schedule'] = 'Ajout d\'une planification';
$strings['Edit Schedule'] = 'Modification d\'une planification';
$strings['No'] = 'Non';
$strings['Yes'] = 'Oui';
$strings['Name'] = 'Nom';
$strings['First Name'] = 'Prénom';
$strings['Last Name'] = 'Patronyme';
$strings['Resource Name'] = 'Nom de la Ressource';
$strings['Email'] = 'Adresse de messagerie';
$strings['Institution'] = 'Institution';
$strings['Phone'] = 'Téléphone';
$strings['Password'] = 'Mot de passe';
$strings['Permissions'] = 'Permissions';
$strings['View information about'] = 'Visualisation des information de %s %s';
$strings['Send email to'] = 'Envoi d\'un message électronique à %s %s';
$strings['Reset password for'] = 'Ré-initialisation du mot de passe de %s %s';
$strings['Edit permissions for'] = 'Modification des privilèges pour %s %s';
$strings['Position'] = 'Position';
$strings['Password (6 char min)'] = 'Mot de passe (%s char min)';
$strings['Re-Enter Password'] = 'Re-Entrer le mot de passe';
$strings['Date'] = 'Date';
$strings['Email Users'] = 'Adresse électronique utilisateur';
$strings['Subject'] = 'Objet';
$strings['Message'] = 'Message';
$strings['Send Email'] = 'Envoi du message électronique';
$strings['problem sending email'] = 'Désolé, des difficultés on étés rencontrées lors de l\'envoi du message. S.V.P. Essayez de nouveau plus tard.';
$strings['The email sent successfully.'] = 'Le message électronique a été envoyé avec succés.';
$strings['Email address'] = 'Adresse électronique';
$strings['Please Log In'] = 'Merci de vous identifier';
$strings['Keep me logged in'] = 'Maintenir ma connexion <br/>(utilisation de cookies requise )';
$strings['Password'] = 'Mot de passe';
$strings['Log In'] = 'Se connecter';
$strings['Get online help'] = 'Obtenir de l\'aide en ligne';
$strings['Language'] = 'Langue';
$strings['(Default)'] = '(Defaut)';
$strings['Email Administrator'] = 'Envoi d\'un message électronique à l\'administrateur';
$strings['N/A'] = 'N/A';
$strings['Summary'] = 'Résumé';
$strings['View stats for schedule'] = 'Visualisation des statistique pour la planification:';
$strings['At A Glance'] = 'D\'un coup d\'oeil';
$strings['Total Users'] = 'Total utilisateur:';
$strings['Total Resources'] = 'Total Ressources:';
$strings['Total Reservations'] = 'Total Reservations:';
$strings['Max Reservation'] = 'Max Reservation:';
$strings['Min Reservation'] = 'Min Reservation:';
$strings['Avg Reservation'] = 'Moy Reservation:';
$strings['Most Active Resource'] = 'Ressource la plus active :';
$strings['Most Active User'] = 'L\'utilisateur le plus actif :';
$strings['System Stats'] = 'Statistiques systèmes';
$strings['phpScheduleIt version'] = 'phpScheduleIt version:';
$strings['Database backend'] = 'Base de données principale :';
$strings['Database name'] = 'Nom de la base de données :';
$strings['PHP version'] = 'version PHP:';
$strings['Server OS'] = 'SE du serveur:';
$strings['Server name'] = 'Nom du serveur:';
$strings['phpScheduleIt root directory'] = 'répertoire racine de phpScheduleIt:';
$strings['Using permissions'] = 'Utilise les permissions:';
$strings['Using logging'] = 'Using logging:';
$strings['Log file'] = 'Fichier historique :';
$strings['Admin email address'] = 'Adresse de messagerie administrateur:';
$strings['Tech email address'] = 'Adresse de messagerie technique:';
$strings['CC email addresses'] = 'Adresses de messagerie en CC:';
$strings['Reservation start time'] = 'Heure de début de reservation :';
$strings['Reservation end time'] = 'Heure de fin de reservation :';
$strings['Days shown at a time'] = 'Nombre de jours visualisés d\'un coup:';
$strings['Reservations'] = 'Réservations';
$strings['Return to top'] = 'Retour en haut';
$strings['for'] = 'pour';
$strings['Per page'] = 'Par page:';
$strings['Page'] = 'Page:';
$strings['You are not logged in!'] = 'Vous n\'êtes pas connecté!';
$strings['Setup'] = 'Installation';
$strings['Invalid User Name/Password.'] = 'Compte Utilisateur/Mot de pass invalide.';
$strings['Valid username is required'] = 'Un compte Utilisateur valide est requis.';
$strings['Close'] = 'Fermer';
$strings['Admin'] = 'Admin';
$strings['My Quick Links'] = 'Mes liens rapides';
$strings['Go to first page'] = 'Allez à la première page';
$strings['Go to last page'] = 'Allez à la dernière page';
$strings['Sort by descending order'] = 'Trier par ordre décroissant';
$strings['Sort by ascending order'] = 'Trier par ordre croissant';
$strings['Spam Quarantine'] = 'Quarantaine de Spam';
$strings['Message View'] = 'Voir le message';
$strings['Attachment Quarantine'] = 'Quarantaine d\'attachements';
$strings['No such content type'] = 'Type de contenu inconnu';
$strings['No message was selected'] = 'Aucun message n\'a été sélectionné ...';
$strings['Unknown action type'] = 'Type d\'action inconnu ...';
$strings['A problem occured when trying to release the following messages'] = 'Une erreur s\'est produite en essayant de réémettre les messages suivants';
$strings['A problem occured when trying to delete the following messages'] = 'Une erreur s\'est produite en essayant de supprimer les messages suivants';
$strings['Please release the following messages'] = 'Veuillez réémettre les messages suivants';
$strings['To'] = 'à';
$strings['From'] = 'De';
$strings['Subject'] = 'Objet';
$strings['Date'] = 'Date';
$strings['Score'] = 'Score';
$strings['Mail ID'] = 'Identifiant mail';
$strings['Status'] = 'Etat';
$strings['Print'] = 'Imprimer';
$strings['CloseWindow'] = 'Fermer';
$strings['Unknown server type'] = 'Type de serveur inconnu ...';
$strings['Showing messages'] = "Messages de %s à %s &nbsp;&nbsp; (%s total)\r\n";
$strings['View this message'] = 'Visualiser ce message';
$strings['Message Unavailable'] = 'Message non disponible';
$strings['My Quarantine'] = 'Ma Quarantaine';
$strings['Site Quarantine'] = 'Quarantaine Globale';
$strings['Message Processing'] = 'Message processing';
$strings['Quarantine Summary'] = 'Résumé de la quarantaine';
$strings['Site Quarantine Summary'] = 'Résumé de la quarantaine Globale';
$strings['Login'] = 'Identifiant';
$strings['spam(s)'] = 'spam(s)';
$strings['attachment(s)'] = 'pièce(s) jointe(s)';
$strings['pending release request(s)'] = 'requêtes de réémission en attente';
$strings['virus(es)'] = 'virus(es)';
$strings['bad header(s)'] = 'mauvais en-tête(s)';
$strings['You have to type some text'] = 'Vous devez entrer du texte';
$strings['Release'] = 'Réémission';
$strings['Release/Request release'] = 'Réémission/Demande de réémission';
$strings['Request release'] = 'Demande de réémission';
$strings['Delete'] = 'Supprimer';
$strings['Delete All'] = 'Supprimer tout';
$strings['Send report and go back'] = 'Envoyer le rapport et retourner en arrière';
$strings['Go back'] = "Retourner en arrière";
$strings['Select All'] = "Sélectionner tout";
$strings['Clear All'] = "Désélectionner tout";
$strings['Access Denied'] = "Accès interdit";
$strings['My Pending Requests'] = "Mes requêtes en attente";
$strings['Site Pending Requests'] = "Requêtes en attente globale";
$strings['Cancel Request'] = "Annule requête";
$strings['User is not allowed to login'] = "L'utilisateur n'est pas autorisé à se connecter";
$strings['Authentication successful'] = "Authentification réussie";
$strings['Authentication failed'] = "Authentification échouée";
$strings['LDAP connection failed'] = "LDAP/AD connexion échouée";
$strings['Logout successful'] = "Déconnexion réussie";
$strings['IMAP Authentication: no match'] = "Authentification IMAP: pas de correspondance";
$strings['Search for messages whose:'] = "Recherche de messages dont les champs:";
$strings['Content Type'] = "Type de contenu";
$strings['Clear search results'] = "Remise à zero des resultats";
$strings['contains'] = "contient";
$strings['doesn\'t contain'] = "ne contient pas";
$strings['equals'] = "est égal à";
$strings['doesn\'t equal'] = "n'est pas égal à";
$strings['All'] = "Tout type";
$strings['Spam'] = "Spam";
$strings['Banned'] = "Attachement interdit";
$strings['Bad Header'] = "Mauvais En-tête";
$strings['Bad Headers'] = "Mauvais En-têtes";
$strings['Pending Requests'] = 'Attendant Des Demandes';
$strings['Virus'] = "Virus";
$strings['Viruses'] = "Viruses";
$strings['last'] = "dernier";
$strings['first'] = "premier";
$strings['previous'] = "précédent";
$strings['There was an error executing your query'] = 'Une erreur s\'est produite lors de l\'exécution de la requête:';
$strings['There are no matching records.'] = "Pas d'entrée correspondante.";
$strings['Domain'] = 'Domaine';
$strings['Total'] = 'Total';
$strings['X-Amavis-Alert'] = 'X-Amavis-Alert';
$strings['Loading Summary...'] = 'Loading Summary...';
$strings['Retrieving Messages...'] = 'Retrieving Messages...';
?>

145
lang/it.help.php Normal file
View File

@ -0,0 +1,145 @@
<?php
/**
* English (en) help translation file.
* This also serves as the base translation file from which to derive
* all other translations.
*
* @author Brian Wong <bwsource@users.sourceforge.net>
* @translator Paolo Cravero <pcravero@as2594.net>
* @version 01-08-05
* @package Languages
*
* Copyright (C) 2003 - 2007 MailZu
* License: GPL, see LICENSE
*/
///////////////////////////////////////////////////////////
// INSTRUCTIONS
///////////////////////////////////////////////////////////
// This file contains all the help file for MailZu. Please save the translated
// file as '2 letter language code'.help.php. For example, en.help.php.
//
// To make MailZu help available in another language, simply translate this
// file into your language. If there is no direct translation, please provide the
// closest translation.
//
// This will be included in the body of the help file.
//
// Please keep the HTML formatting unless you need to change it. Also, please try
// to keep the HTML XHTML 1.0 Transitional complaint.
///////////////////////////////////////////////////////////
?>
<div align="center">
<h3><a name="top" id="top"></a>Introduzione a MailZu</h3>
<p><a href="http://mailzu.net" target="_blank">http://mailzu.net</a></p>
<table width="100%" border="0" cellspacing="0" cellpadding="5" style="border: solid #CCCCCC 1px">
<tr>
<td bgcolor="#FAFAFA">
<ul>
<li><b><a href="#getting_started">Introduzione</a></b></li>
<ul>
<li><a href="#logging_in">Autenticazione</a></li>
<li><a href="#language">Scelta della lingua</a></li>
<li><a href="#getting_support">Come richiedere assistenza</a></li>
</ul>
<li><a href="#using_mailzu"><b>Utilizzo di MailZu</b></a></li>
<ul>
<li><a href="#quick_links">Menu</a></li>
<li><a href="#msg_summary">Statistiche Quarantena</a></li>
<li><a href="#msg_index">Quarantena</a></li>
<li><a href="#search">Funzioni di Ricerca</a></li>
<li><a href="#msg_view">Visualizzazione Messaggio</a></li>
</ul>
</ul>
<hr width="95%" size="1" noshade="noshade" />
<h4><a name="getting_started" id="getting_started"></a>Introduzione</h4>
<p>In cima ad ogni pagina viene mostrato un messaggio di benvenuto e la data odierna.
Se l'utente visualizzato nel messaggio di benvenuto non &egrave; corretto, cliccare
&quot;Esci&quot; per rimuovere eventuali cookie residui ed <a href="#logging_in">autenticarsi</a> con le
proprie credenziali.
Il link &quot;Aiuto&quot; apre una pagina di aiuto in un'altra finestra. Se disponibile,
il link &quot;Scrivi all'Amministratore&quot; inizia la composizione di un email da inviare all'
amministratore del sistema.
</p>
<p align="right"><a href="#top">Torna su</a></p>
<h5><a name="logging_in" id="logging_in"></a>Autenticazione</h5>
<p>L'autenticazione avviene tramite login e password. Il login pu&ograve;
essere l'indirizzo email completo ('utente@dominio.it') o solo il proprio nome utente ('login'),
in funzione delle impostazioni del proprio sistema. La modalit&agrave; corretta di accesso deve
essere comunicata dall'Amministratore/Assistenza.<BR>Con l'opzione &quot;Ricorda le credenziali&quot;
il sistema utilizza i cookie per identificare l'utente ad ogni accesso futuro, senza richiedere
pi&ugrave; login e password. <i>Utilizzare questa opzione solo se la postazione non &egrave;
condivisa con altri utenti!</i><br>Dopo l'autenticazione appare la <a href="#message_summary">pagina principale</a>.</p>
<p align="right"><a href="#top">Torna su</a></p>
<h5><a name="language" id="language"></a>Scelta della Lingua</h5>
<p>Nella pagina di login si pu&ograve; scegliere la lingua con cui navigare nella
propria quarantena. Solamente le lingue impostate dall'amministratore saranno
indicate come disponibili. Con la scelta della lingua i messaggi di MailZu
appariranno tradotti. Non verranno invece tradotti i messaggi email eventualmente
presenti in quarantena.<BR>
Per cambiare la lingua &egrave; necessario uscire e rientrare da MailZu.</p>
<p align="right"><a href="#top">Torna su</a></p>
<h5><a name="getting_support" id="getting_support"></a>Come richiedere assistenza
</h5>
<p>Per ricevere assistenza sull'utilizzo della quarantena delegata si prega di
contattare il servizio di Assistenza o l'Amministratore. Se disponibile si
pu&ograve; inviare una email all'Amministratore tramite il link del menu di sinistra.
<p>
<p align="right"><a href="#top">Torna su</a></p> <p align="right">&nbsp;</p>
<hr width="95%" size="1" noshade="noshade" />
<h4><a name="using_mailzu" id="using_mailzu"></a>Utilizzo di MailZu</h4>
<p>MailZu &egrave; una interfaccia Web per gestire la quarantena personale in sistemi
antispam. I messaggi bloccati in quarantena sono tipicamente spam o contengono
degli allegati non permessi.
<p align="right"><a href="#top">Torna su</a></p>
<h5><a name="quick_links" id="quick_links"></a>Menu</h5>
<p>Il Menu riporta i link alle funzioni principali di questa applicazione.
Il primo, &quot;Statistiche Quarantena&quot; visualizza un riassunto del contenuto
della propria quarantena.
</p>
<p> &quot;Quarantena&quot; mostra l'elenco dei messaggi individuati come spam e/o
con allegati non permessi.</p>
<p>&quot;Scrivi all'Amministratore&quot; (se disponibile) &egrave; un modo rapido
per entrare in contatto con l'Assistenza (per posta elettronica).</p>
<p>&quot;Aiuto&quot; apre questo documento.</p>
<p>L'ultimo link, &quot;Esci&quot;, chiude la sessione corrente e riporta la navigazione
alla pagina di login.</p>
<p align="right"><a href="#top">Torna su</a></p>
<h5><a name="msg_summary" id="message_summary"></a>Statistiche Quarantena</h5>
<p>Le statistiche della propria quarantena compaiono nella prima pagina dopo il login.
Forniscono un panorama sul numero e tipo di messaggi in quarantena.
<p align="right"><a href="#top">Torna su</a></p>
<h5><a name="msg_index" id="msg_index"></a>Quarantena</h5>
<p> La pagina di quarantena mostra l'elenco dei messaggi presenti in quarantena.
Per ogni email bloccato il riassunto mostra il mittente, l'oggetto, la data e il
punteggio.</p>
<p>Con un click sul titolo delle colonne &egrave; possibile cambiare l'ordinamento
della visualizzazione. Con un secondo click sullo stesso titolo si inverte l'ordine.</p>
<p>L'interfaccia propone pi&ugrave; pulsanti per la gestione dei messaggi visualizzati.
L'azione &quot;Sblocca&quot; rimuove i messaggi dalla quarantena e li consegna al
destinatario come se non fossero stati intercettati. La funzione &quot;Cancella&quot;
elimina definitivamente un messaggio dalla quarantena, senza consegnarlo al destinatario.
Queste funzioni vengono applicate solo ai messaggi spuntati. La funzione &quot;Cancella
Tutti&quot; ignora le eventuali spunte ed elimina tutti i messaggi dalla quarantena.</p>
<p>Dall'elenco delle richieste in sospeso &egrave; possibile annullare una richiesta cliccando
su 'Cancella la Richiesta'. In questo modo il messaggio verr&agrave; rimosso dalla coda in
attesa di revisione da parte dell'Amministratore.
</p>
<p align="right"><a href="#top">Torna su</a></p>
<h5><a name="search" id="search"></a>Funzioni di ricerca</h5>
<p>La funzione di ricerca permette di impostare un filtro nella visualizzazione dei messaggi.
&Egrave; possibile specificare il mittente, l'oggetto o il tipo di messaggio (spam o non
permesso). La ricerca non distingue tra maiuscole e minuscole.</p>
<p align="right"><a href="#top">Torna su</a></p>
<h5><a name="msg_view" id="msg_view"></a>Messaggio</h5>
<p>La vista Messaggio mostra una anteprima del messaggio trattenuto in quarantena per determinare
se si tratta effettivamente di spam. Questa pagina consente di visualizzare tutte le intestazioni
(&quot;Intestazioni Si/no&quot;) e il &quot;Messaggio Originale&quot;.
The Message View allows you to see the contents of the message to help
</p>
<p align="right"><a href="#top">Torna su</a></p> <p align="right">&nbsp;</p>
<hr width="95%" size="1" noshade="noshade" />
</td>
</tr>
</table>
</div>

321
lang/it.lang.php Normal file
View File

@ -0,0 +1,321 @@
<?php
/**
* Italian (it) translation file.
* Based on phpScheduleIt translation file.
* This also serves as the base translation file from which to derive
* all other translations.
*
* @author Paolo Cravero <pcravero@as2594.net>
* @version 08-25-05
* @package Languages
*
* Copyright (C) 2005 - MailZu
* License: GPL, see LICENSE
*/
///////////////////////////////////////////////////////////
// INSTRUCTIONS
///////////////////////////////////////////////////////////
// This file contains all of the strings that are used throughout phpScheduleit.
// Please save the translated file as '2 letter language code'.lang.php. For example, en.lang.php.
//
// To make phpScheduleIt available in another language, simply translate each
// of the following strings into the appropriate one for the language. If there
// is no direct translation, please provide the closest translation. Please be sure
// to make the proper additions the /config/langs.php file (instructions are in the file).
// Also, please add a help translation for your language using en.help.php as a base.
//
// You will probably keep all sprintf (%s) tags in their current place. These tags
// are there as a substitution placeholder. Please check the output after translating
// to be sure that the sentences make sense.
//
// + Please use single quotes ' around all $strings. If you need to use the ' character, please enter it as \'
// + Please use double quotes " around all $email. If you need to use the " character, please enter it as \"
//
// + For all $dates please use the PHP strftime() syntax
// http://us2.php.net/manual/en/function.strftime.php
//
// + Non-intuitive parts of this file will be explained with comments. If you
// have any questions, please email lqqkout13@users.sourceforge.net
// or post questions in the Developers forum on SourceForge
// http://sourceforge.net/forum/forum.php?forum_id=331297
///////////////////////////////////////////////////////////
////////////////////////////////
/* Do not modify this section */
////////////////////////////////
global $strings; //
global $email; //
global $dates; //
global $charset; //
global $letters; //
global $days_full; //
global $days_abbr; //
global $days_two; //
global $days_letter; //
global $months_full; //
global $months_abbr; //
global $days_letter; //
/******************************/
// Charset for this language
// 'iso-8859-1' will work for most languages
$charset = 'iso-8859-1';
/***
DAY NAMES
All of these arrays MUST start with Sunday as the first element
and go through the seven day week, ending on Saturday
***/
// The full day name
$days_full = array('Domenica', 'Lunedi', 'Martedi', 'Mercoledi', 'Giovedi', 'Venerdi', 'Sabato');
// The three letter abbreviation
$days_abbr = array('Dom', 'Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab');
// The two letter abbreviation
$days_two = array('Do', 'Lu', 'Ma', 'Me', 'Gi', 'Ve', 'Sa');
// The one letter abbreviation
$days_letter = array('D', 'L', 'm', 'M', 'G', 'V', 'S');
/***
MONTH NAMES
All of these arrays MUST start with January as the first element
and go through the twelve months of the year, ending on December
***/
// The full month name
$months_full = array('Gennaio', 'Febbraio', 'Marzo', 'Aprile', 'Maggio', 'Giugno', 'Luglio', 'Agosto', 'Settembre', 'Ottobre', 'Novembre', 'Dicembre');
// The three letter month name
$months_abbr = array('Gen', 'Feb', 'Mar', 'Apr', 'MaG', 'Giu', 'Lug', 'Ago', 'Set', 'Ott', 'Nov', 'Dic');
// All letters of the alphabet starting with A and ending with Z
$letters = array ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');
/***
DATE FORMATTING
All of the date formatting must use the PHP strftime() syntax
You can include any text/HTML formatting in the translation
***/
// General date formatting used for all date display unless otherwise noted
$dates['general_date'] = '%d/%m/%Y';
// General datetime formatting used for all datetime display unless otherwise noted
// The hour:minute:second will always follow this format
$dates['general_datetime'] = '%d/%m/%Y @';
// Date on top-right of each page
$dates['header'] = '%A, %d %B %Y';
/***
STRING TRANSLATIONS
All of these strings should be translated from the English value (right side of the equals sign) to the new language.
- Please keep the keys (between the [] brackets) as they are. The keys will not always be the same as the value.
- Please keep the sprintf formatting (%s) placeholders where they are unless you are sure it needs to be moved.
- Please keep the HTML and punctuation as-is unless you know that you want to change it.
***/
$strings['hours'] = 'ore';
$strings['minutes'] = 'minuti';
// The common abbreviation to hint that a user should enter the month as 2 digits
$strings['mm'] = 'mm';
// The common abbreviation to hint that a user should enter the day as 2 digits
$strings['dd'] = 'gg';
// The common abbreviation to hint that a user should enter the year as 4 digits
$strings['yyyy'] = 'aaaa';
$strings['am'] = 'am';
$strings['pm'] = 'pm';
$strings['Administrator'] = 'Amministratore';
$strings['Welcome Back'] = 'Benvenuto, %s';
$strings['Log Out'] = 'Esci';
$strings['Help'] = 'Aiuto';
$strings['Admin Email'] = 'Admin Email';
$strings['Default'] = 'Default';
$strings['Reset'] = 'Reset';
$strings['Edit'] = 'Modifica';
$strings['Delete'] = 'Cancella';
$strings['Cancel'] = 'Annulla';
$strings['View'] = 'Visualizza';
$strings['Modify'] = 'Modifica';
$strings['Save'] = 'Salva';
$strings['Back'] = 'Indietro';
$strings['BackMessageIndex'] = 'Elenco Messaggi';
$strings['ToggleHeaders'] = 'Intestazioni Si/No';
$strings['ViewOriginal'] = 'Messaggio Originale';
$strings['Next'] = 'succ.';
$strings['Close Window'] = 'Close Window';
$strings['Search'] = 'Cerca';
$strings['Clear'] = 'Pulisci';
$strings['Days to Show'] = 'Days to Show';
$strings['Reservation Offset'] = 'Reservation Offset';
$strings['Hidden'] = 'Hidden';
$strings['Show Summary'] = 'Show Summary';
$strings['Add Schedule'] = 'Add Schedule';
$strings['Edit Schedule'] = 'Edit Schedule';
$strings['No'] = 'No';
$strings['Yes'] = 'Yes';
$strings['Name'] = 'Name';
$strings['First Name'] = 'First Name';
$strings['Last Name'] = 'Last Name';
$strings['Resource Name'] = 'Resource Name';
$strings['Email'] = 'Email';
$strings['Institution'] = 'Institution';
$strings['Phone'] = 'Phone';
$strings['Password'] = 'Password';
$strings['Permissions'] = 'Permissions';
$strings['View information about'] = 'View information about %s %s';
$strings['Send email to'] = 'Send email to %s %s';
$strings['Reset password for'] = 'Reset password for %s %s';
$strings['Edit permissions for'] = 'Edit permissions for %s %s';
$strings['Position'] = 'Position';
$strings['Password (6 char min)'] = 'Password (%s char min)'; // @since 1.1.0
$strings['Re-Enter Password'] = 'Re-Enter Password';
$strings['Date'] = 'Date';
$strings['Email Users'] = 'Email Users';
$strings['Subject'] = 'Oggetto';
$strings['Message'] = 'Messaggio';
$strings['Send Email'] = 'Send Email';
$strings['problem sending email'] = 'Sorry, there was a problem sending your email. Please try again later.';
$strings['The email sent successfully.'] = 'The email sent successfully.';
$strings['Email address'] = 'Email address';
$strings['Please Log In'] = 'Inserire le proprie credenziali';
$strings['Keep me logged in'] = 'Ricorda le credenziali <br/>(richiede i cookies)';
$strings['Password'] = 'Password';
$strings['Log In'] = 'Entra';
$strings['Get online help'] = 'Get online help';
$strings['Language'] = 'Lingua';
$strings['(Default)'] = '(Default)';
$strings['Email Administrator'] = 'Scrivi all\'amministratore';
$strings['N/A'] = 'N/A';
$strings['Summary'] = 'Summary';
$strings['View stats for schedule'] = 'View stats for schedule:';
$strings['At A Glance'] = 'At A Glance';
$strings['Total Users'] = 'Total Users:';
$strings['Total Resources'] = 'Total Resources:';
$strings['Total Reservations'] = 'Total Reservations:';
$strings['Max Reservation'] = 'Max Reservation:';
$strings['Min Reservation'] = 'Min Reservation:';
$strings['Avg Reservation'] = 'Avg Reservation:';
$strings['Most Active Resource'] = 'Most Active Resource:';
$strings['Most Active User'] = 'Most Active User:';
$strings['System Stats'] = 'System Stats';
$strings['phpScheduleIt version'] = 'phpScheduleIt version:';
$strings['Database backend'] = 'Database backend:';
$strings['Database name'] = 'Database name:';
$strings['PHP version'] = 'PHP version:';
$strings['Server OS'] = 'Server OS:';
$strings['Server name'] = 'Server name:';
$strings['phpScheduleIt root directory'] = 'phpScheduleIt root directory:';
$strings['Using permissions'] = 'Using permissions:';
$strings['Using logging'] = 'Using logging:';
$strings['Log file'] = 'Log file:';
$strings['Admin email address'] = 'Admin email address:';
$strings['Tech email address'] = 'Tech email address:';
$strings['CC email addresses'] = 'CC email addresses:';
$strings['Reservation start time'] = 'Reservation start time:';
$strings['Reservation end time'] = 'Reservation end time:';
$strings['Days shown at a time'] = 'Days shown at a time:';
$strings['Reservations'] = 'Reservations';
$strings['Return to top'] = 'Return to top';
$strings['for'] = 'for';
$strings['Per page'] = 'Per page:';
$strings['Page'] = 'Page:';
$strings['You are not logged in!'] = 'You are not logged in!';
$strings['Setup'] = 'Setup';
$strings['Invalid User Name/Password.'] = 'Login e/o Password errati.';
$strings['Valid username is required'] = 'Valid username is required';
$strings['Close'] = 'Close';
$strings['Admin'] = 'Admin';
$strings['My Quick Links'] = 'Menu';
$strings['Go to first page'] = 'Vai alla prima pagina';
$strings['Go to last page'] = 'Vai all\'ultima pagina';
$strings['Sort by descending order'] = 'Sort by descending order';
$strings['Sort by ascending order'] = 'Sort by ascending order';
$strings['Spam Quarantine'] = 'Quarantena Spam';
$strings['Message View'] = 'Visualizzazione Messaggio';
$strings['Attachment Quarantine'] = 'Quarantena Allegati';
$strings['No such content type'] = 'No such content type';
$strings['No message was selected'] = 'Nessun messaggio selezionato ...';
$strings['Unknown action type'] = 'Tipo di richiesta sconosciuta ...';
$strings['A problem occured when trying to release the following messages'] = 'Si &egrave; verificato un problema cercando di sbloccare i seguenti messaggi';
$strings['A problem occured when trying to delete the following messages'] = 'Si &egrave; verificato un problema cercando di cancellare i seguenti messaggi';
$strings['Please release the following messages'] = 'Per cortesia vogliate sbloccare i seguenti messaggi';
$strings['To'] = 'A';
$strings['From'] = 'Da';
$strings['Subject'] = 'Oggetto';
$strings['Date'] = 'Data';
$strings['Score'] = 'Punteggio';
$strings['Mail ID'] = 'ID Messaggio';
$strings['Status'] = 'Stato';
$strings['Print'] = 'Stampa';
$strings['CloseWindow'] = 'Chiudi';
$strings['Unknown server type'] = 'Tipo di server sconosciuto ...';
$strings['Showing messages'] = "Messaggi dal %s al %s &nbsp;&nbsp; (%s in totale)\r\n";
$strings['View this message'] = 'Apri questo messaggio';
$strings['Message Unavailable'] = 'Messaggio non disponibile';
$strings['My Quarantine'] = 'Quarantena';
$strings['Site Quarantine'] = 'Quarantena globale';
$strings['Message Processing'] = 'Elaborazione Messaggio';
$strings['Quarantine Summary'] = 'Statistiche Quarantena';
$strings['Site Quarantine Summary'] = 'Statistiche Quarantena globale';
$strings['Login'] = 'Login';
$strings['spam(s)'] = 'spam';
$strings['attachment(s)'] = 'allegati';
$strings['pending release request(s)'] = 'richiesta/e di sblocco accodate';
$strings['virus(es)'] = 'virus(es)';
$strings['bad header(s)'] = 'intestazione/i difettosa/e';
$strings['You have to type some text'] = 'E\' obbligatorio inserire del testo';
$strings['Release'] = 'Sblocca';
$strings['Release/Request release'] = 'Sblocca/Richiedi sblocco';
$strings['Request release'] = 'Richiedi slocco';
$strings['Delete'] = 'Cancella';
$strings['Delete All'] = 'Cancella Tutti';
$strings['Send report and go back'] = 'Invia il rapporto e torna alla pagina precedente';
$strings['Go back'] = "Indietro";
$strings['Select All'] = "Seleziona Tutti";
$strings['Clear All'] = "Deseleziona Tutti";
$strings['Access Denied'] = "Accesso Negato ";
$strings['My Pending Requests'] = "Richieste in sospeso";
$strings['Site Pending Requests'] = "Richieste in sospeso (globali)";
$strings['Cancel Request'] = "Cancella la Richiesta";
$strings['User is not allowed to login'] = "Utente non autorizzato al servizio";
$strings['Authentication successful'] = "Autenticazione riuscita";
$strings['Authentication failed'] = "Autenticazione fallita";
$strings['LDAP connection failed'] = "Connessione al server LDAP/AD fallita";
$strings['Logout successful'] = "Logout riuscito";
$strings['IMAP Authentication: no match'] = "Autenticazione IMAP: non trovato";
$strings['Search for messages whose:'] = "Cerca i messaggi che:";
$strings['Content Type'] = "Content Type";
$strings['Clear search results'] = "Azzera il risultato della ricerca";
$strings['contains'] = "contiene";
$strings['doesn\'t contain'] = "non contiene";
$strings['equals'] = "uguale a";
$strings['doesn\'t equal'] = "diverso da";
$strings['All'] = "Tutti";
$strings['Spam'] = "Spam";
$strings['Banned'] = "Non permesso";
$strings['Bad Header'] = "Intestazione Difettosa";
$strings['Bad Headers'] = "Intestazioni Difettose";
$strings['Pending Requests'] = 'Richieste in sospeso';
$strings['Virus'] = "Virus";
$strings['Viruses'] = "Viruses";
$strings['last'] = "ultima";
$strings['first'] = "prima";
$strings['previous'] = "prec.";
$strings['There was an error executing your query'] = 'E\' stato riscontrato un errore durante la ricerca sul database:';
$strings['There are no matching records.'] = 'Nessun record trovato.';
$strings['Domain'] = 'Dominio';
$strings['Total'] = 'Totali';
$strings['X-Amavis-Alert'] = 'X-Amavis-Alert';
$strings['Loading Summary...'] = 'Caricamento in corso...';
$strings['Retrieving Messages...'] = 'Download dei messaggi...';
?>

313
lang/pt_BR.lang.php Normal file
View File

@ -0,0 +1,313 @@
<?php
/**
* English (en) translation file.
* Based on phpScheduleIt translation file.
* This also serves as the base translation file from which to derive
* all other translations.
*
* @author Samuel Tran <stran2005@users.sourceforge.net>
* @author Brian Wong <bwsource@users.sourceforge.net>
* @author Nicolas Peyrussie <peyrouz@users.sourceforge.net>
* @version 04-03-07
* @package Languages
*
* Copyright (C) 2005 - 2007 MailZu
* License: GPL, see LICENSE
*/
///////////////////////////////////////////////////////////
// INSTRUCTIONS
///////////////////////////////////////////////////////////
// This file contains all of the strings that are used throughout phpScheduleit.
// Please save the translated file as '2 letter language code'.lang.php. For example, en.lang.php.
//
// To make phpScheduleIt available in another language, simply translate each
// of the following strings into the appropriate one for the language. If there
// is no direct translation, please provide the closest translation. Please be sure
// to make the proper additions the /config/langs.php file (instructions are in the file).
// Also, please add a help translation for your language using en.help.php as a base.
//
// You will probably keep all sprintf (%s) tags in their current place. These tags
// are there as a substitution placeholder. Please check the output after translating
// to be sure that the sentences make sense.
//
// + Please use single quotes ' around all $strings. If you need to use the ' character, please enter it as \'
// + Please use double quotes " around all $email. If you need to use the " character, please enter it as \"
//
// + For all $dates please use the PHP strftime() syntax
// http://us2.php.net/manual/en/function.strftime.php
//
// + Non-intuitive parts of this file will be explained with comments. If you
// have any questions, please email lqqkout13@users.sourceforge.net
// or post questions in the Developers forum on SourceForge
// http://sourceforge.net/forum/forum.php?forum_id=331297
///////////////////////////////////////////////////////////
////////////////////////////////
/* Do not modify this section */
////////////////////////////////
global $strings; //
global $email; //
global $dates; //
global $charset; //
global $letters; //
global $days_full; //
global $days_abbr; //
global $days_two; //
global $days_letter; //
global $months_full; //
global $months_abbr; //
global $days_letter; //
/******************************/
// Charset for this language
// 'iso-8859-1' will work for most languages
$charset = 'iso-8859-1';
/***
DAY NAMES
All of these arrays MUST start with Sunday as the first element
and go through the seven day week, ending on Saturday
***/
// The full day name
$days_full = array('Domingo', 'Segunda-Feira', 'Terça-Feira', 'Quarta-Feira', 'Quinta-Feira', 'Sexta-Feira', 'Sábado');
// The three letter abbreviation
$days_abbr = array('Dom', 'Seg', 'Ter', 'Qua', 'Qui', 'Sex', 'Sab');
// The two letter abbreviation
$days_two = array('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa');
// The one letter abbreviation
$days_letter = array('D', 'S', 'T', 'Q', 'U', 'S', 'S');
/***
MONTH NAMES
All of these arrays MUST start with January as the first element
and go through the twelve months of the year, ending on December
***/
// The full month name
$months_full = array('Janeiro', 'Fevereiro', 'Março', 'Abril', 'Maio', 'Junho', 'Julho', 'Agosto', 'Setembro', 'Outubro', 'Novembro', 'Dezembro');
// The three letter month name
$months_abbr = array('Jan', 'Fev', 'Mar', 'Abr', 'Mai', 'Jun', 'Jul', 'Ago', 'Set', 'Out', 'Nov', 'Dez');
// All letters of the alphabet starting with A and ending with Z
$letters = array ('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z');
/***
DATE FORMATTING
All of the date formatting must use the PHP strftime() syntax
You can include any text/HTML formatting in the translation
***/
// General date formatting used for all date display unless otherwise noted
$dates['general_date'] = '%m/%d/%Y';
// General datetime formatting used for all datetime display unless otherwise noted
// The hour:minute:second will always follow this format
$dates['general_datetime'] = '%m/%d/%Y @';
$dates['header'] = '%A, %B %d, %Y';
/***
STRING TRANSLATIONS
All of these strings should be translated from the English value (right side of the equals sign) to the new language.
- Please keep the keys (between the [] brackets) as they are. The keys will not always be the same as the value.
- Please keep the sprintf formatting (%s) placeholders where they are unless you are sure it needs to be moved.
- Please keep the HTML and punctuation as-is unless you know that you want to change it.
***/
$strings['hours'] = 'horas';
$strings['minutes'] = 'minutos';
// The common abbreviation to hint that a user should enter the month as 2 digits
$strings['mm'] = 'mm';
// The common abbreviation to hint that a user should enter the day as 2 digits
$strings['dd'] = 'dd';
// The common abbreviation to hint that a user should enter the year as 4 digits
$strings['yyyy'] = 'yyyy';
$strings['am'] = 'am';
$strings['pm'] = 'pm';
$strings['Administrator'] = 'Administrador';
$strings['Welcome Back'] = 'Bem Vindo, %s';
$strings['Log Out'] = 'Sair';
$strings['Help'] = 'Ajuda';
$strings['Admin Email'] = 'Admin Email';
$strings['Default'] = 'Padrão';
$strings['Reset'] = 'Resetar';
$strings['Edit'] = 'Editar';
$strings['Delete'] = 'Deletar';
$strings['Cancel'] = 'Cancelar';
$strings['View'] = 'Ver';
$strings['Modify'] = 'Modificar';
$strings['Save'] = 'Salvar';
$strings['Back'] = 'Voltar';
$strings['BackMessageIndex'] = 'Voltar para Menssagens';
$strings['ToggleHeaders'] = 'Mostrar Cabeçalhos';
$strings['ViewOriginal'] = 'Ver Original';
$strings['Next'] = 'próxima';
$strings['Close Window'] = 'Fechar Janela';
$strings['Search'] = 'Pesquisar';
$strings['Clear'] = 'Limpar';
$strings['Days to Show'] = 'Dias para Mostrar';
$strings['Reservation Offset'] = 'Reservation Offset';
$strings['Hidden'] = 'Esconder';
$strings['Show Summary'] = 'Mastrar Agendamento';
$strings['Add Schedule'] = 'Adicionar Agendamento';
$strings['Edit Schedule'] = 'Editar Agendamento';
$strings['No'] = 'Não';
$strings['Yes'] = 'Sim';
$strings['Name'] = 'Nome';
$strings['First Name'] = 'Primeiro Nome';
$strings['Last Name'] = 'Último Nome';
$strings['Resource Name'] = 'Recurso';
$strings['Email'] = 'Email';
$strings['Institution'] = 'Empresa';
$strings['Phone'] = 'Telefone';
$strings['Password'] = 'Senha';
$strings['Permissions'] = 'Permissões';
$strings['View information about'] = 'Ver Informações sobre %s %s';
$strings['Send email to'] = 'Enviar e-mail para %s %s';
$strings['Reset password for'] = 'Resetar senha para %s %s';
$strings['Edit permissions for'] = 'Editar permissões para %s %s';
$strings['Position'] = 'Posição';
$strings['Password (6 char min)'] = 'Senha (%s caracteres min.)'; // @since 1.1.0
$strings['Re-Enter Password'] = 'Redigitar Senha';
$strings['Date'] = 'Data';
$strings['Email Users'] = 'Email Users';
$strings['Subject'] = 'Assunto';
$strings['Message'] = 'Mensagem';
$strings['Send Email'] = 'Enviar E-mail';
$strings['problem sending email'] = 'Desculpa, ocorreu um erro ao enviar seu E-mail. Tente mais tarde.';
$strings['The email sent successfully.'] = 'E-mail enviado com sucesso.';
$strings['Email address'] = 'Endereço de E-mail';
$strings['Please Log In'] = 'Informações de Login';
$strings['Keep me logged in'] = 'Manter-se logado <br/>(requer cookies)';
$strings['Password'] = 'Senha';
$strings['Log In'] = 'Entrar';
$strings['Get online help'] = 'Ajuda online';
$strings['Language'] = 'Idioma';
$strings['(Default)'] = '(Padrão)';
$strings['Email Administrator'] = 'E-mail p/ Administrador';
$strings['N/A'] = 'N/A';
$strings['Summary'] = 'Sumário';
$strings['View stats for schedule'] = 'Ver status da Agenda:';
$strings['At A Glance'] = 'At A Glance';
$strings['Total Users'] = 'Total Users:';
$strings['Total Resources'] = 'Total Resources:';
$strings['Total Reservations'] = 'Total Reservations:';
$strings['Max Reservation'] = 'Max Reservation:';
$strings['Min Reservation'] = 'Min Reservation:';
$strings['Avg Reservation'] = 'Avg Reservation:';
$strings['Most Active Resource'] = 'Most Active Resource:';
$strings['Most Active User'] = 'Most Active User:';
$strings['System Stats'] = 'System Stats';
$strings['phpScheduleIt version'] = 'phpScheduleIt version:';
$strings['Database backend'] = 'Database backend:';
$strings['Database name'] = 'Database name:';
$strings['PHP version'] = 'PHP version:';
$strings['Server OS'] = 'Server OS:';
$strings['Server name'] = 'Server name:';
$strings['phpScheduleIt root directory'] = 'phpScheduleIt root directory:';
$strings['Using permissions'] = 'Using permissions:';
$strings['Using logging'] = 'Using logging:';
$strings['Log file'] = 'Log file:';
$strings['Admin email address'] = 'Admin email address:';
$strings['Tech email address'] = 'Tech email address:';
$strings['CC email addresses'] = 'CC email addresses:';
$strings['Reservation start time'] = 'Reservation start time:';
$strings['Reservation end time'] = 'Reservation end time:';
$strings['Days shown at a time'] = 'Days shown at a time:';
$strings['Reservations'] = 'Reservations';
$strings['Return to top'] = 'Return to top';
$strings['for'] = 'for';
$strings['Per page'] = 'Por página:';
$strings['Page'] = 'Página:';
$strings['You are not logged in!'] = 'Você não esta logado!';
$strings['Setup'] = 'Setup';
$strings['Invalid User Name/Password.'] = 'Usuário/Senha inválidos.';
$strings['Valid username is required'] = 'Requerido um nome de usuário válido';
$strings['Close'] = 'Fechar';
$strings['Admin'] = 'Admin';
$strings['My Quick Links'] = 'Meus Links';
$strings['Go to first page'] = 'Ir para primeira página';
$strings['Go to last page'] = 'Ir para última página';
$strings['Sort by descending order'] = 'Ordem descendente';
$strings['Sort by ascending order'] = 'Ordem ascendente';
$strings['Spam Quarantine'] = 'Quarentena de Spam';
$strings['Message View'] = 'Visualizando Mensagem';
$strings['Attachment Quarantine'] = 'Quarentena de Anexos';
$strings['No such content type'] = 'Tipo de conteúdo não existe';
$strings['No message was selected'] = 'Nenhuma mensagem foi selecionada ...';
$strings['Unknown action type'] = 'Tipo de ação desconhecido ...';
$strings['A problem occured when trying to release the following messages'] = 'Ocorreu um problema ao tentar liberar as mensagens selecionadas';
$strings['A problem occured when trying to delete the following messages'] = 'Ocorreu um problema ao tentar deletar as mesagens selecionadas';
$strings['Please release the following messages'] = 'Liberar as seguintes mensagens';
$strings['To'] = 'Para';
$strings['From'] = 'De';
$strings['Subject'] = 'Assunto';
$strings['Date'] = 'Data';
$strings['Score'] = 'Pontos';
$strings['Mail ID'] = 'Mail ID';
$strings['Status'] = 'Status';
$strings['Print'] = 'Imprimir';
$strings['CloseWindow'] = 'Fechar';
$strings['Unknown server type'] = 'Tipo de servidor desconhecido ...';
$strings['Showing messages'] = "Mostrando mensagen %s até %s &nbsp;&nbsp; (%s no total)\r\n";
$strings['View this message'] = 'Ver esta Mensagem';
$strings['Message Unavailable'] = 'Mensagem Indisponível';
$strings['My Quarantine'] = 'Minha Quarentena';
$strings['Site Quarantine'] = 'Quarentena do Site';
$strings['Message Processing'] = 'Processando Mensagem';
$strings['Quarantine Summary'] = 'Sumário da Quarantena';
$strings['Login'] = 'Usuário';
$strings['spam(s)'] = 'spam(s)';
$strings['attachment(s)'] = 'bloqueio(s) por anexo(s)';
$strings['pending release request(s)'] = 'pedidos de liberação pendentes';
$strings['You have to type some text'] = 'Você deve digitar algum texto';
$strings['Release'] = 'Liberar';
$strings['Release/Request release'] = 'Liberar/Solicitar Liberação';
$strings['Request release'] = 'Solicitar Liberação';
$strings['Delete'] = 'Deletar';
$strings['Delete All'] = 'Deletar Todas';
$strings['Send report and go back'] = 'Enviar relatório e voltar';
$strings['Go back'] = "Voltar";
$strings['Select All'] = "Selecionar Todas";
$strings['Clear All'] = "Limpar Todas";
$strings['Access Denied'] = "Acesso Negado";
$strings['My Pending Requests'] = "Minhas Pendências<br />&nbsp;&nbsp;de Liberação";
$strings['Site Pending Requests'] = "Pendências de Liberação";
$strings['Cancel Request'] = "Cancelar Requisição";
$strings['User is not allowed to login'] = "Usuário sem permissão para entar";
$strings['Authentication successful'] = "Autenticação efetuada com sucesso";
$strings['Authentication failed'] = "Falha na Autenticação";
$strings['LDAP connection failed'] = "Falha na conexão com LDAP/AD";
$strings['Logout successful'] = "Logout efetuado com sucesso";
$strings['IMAP Authentication: no match'] = "Autenticação IMAP: não corresponde";
$strings['Search for messages whose:'] = "Procurar por mensagens:";
$strings['Content Type'] = "Tipo de Conteúdo";
$strings['Clear search results'] = "Limpar resultados da pesquisa";
$strings['contains'] = "contém";
$strings['doesn\'t contain'] = "não contém";
$strings['equals'] = "é igual";
$strings['doesn\'t equal'] = "não é igual";
$strings['All'] = "Todos";
$strings['Spam'] = "Spam";
$strings['Banned'] = "Anexo";
$strings['last'] = "ultima";
$strings['first'] = "primeira";
$strings['previous'] = "anterior";
$strings['There was an error executing your query'] = 'Ocoreu um erro executando sua pesquisa:';
$strings['There are no matching records.'] = 'Nenhum registro encontrado.';
$strings['Domain'] = 'Dominio';
$strings['X-Amavis-Alert'] = 'X-Amavis-Alert';
$strings['Loading Summary...'] = 'Loading Summary...';
$strings['Retrieving Messages...'] = 'Retrieving Messages...';
?>

127
lib/AmavisdEngine.class.php Normal file
View File

@ -0,0 +1,127 @@
<?php
/**
* AmavisdEngine class
* @author Samuel Tran
* @author Jeremy Fowler
* @version 03-22-07
* @package AmavisdEngine
*
* Copyright (C) 2005 - 2007 MailZu
* License: GPL, see LICENSE
*/
/**
* Base directory of application
*/
@define('BASE_DIR', dirname(__FILE__) . '/..');
/**
* CmnFns class
*/
include_once('CmnFns.class.php');
/**
* PEAR::Net_Socket Library
*/
if ($GLOBALS['conf']['app']['safeMode']) {
ini_set('include_path', ( dirname(__FILE__) . '/pear/' . PATH_SEPARATOR . ini_get('include_path') ));
include_once('pear/PEAR.php');
include_once('pear/Net/Socket.php');
}
else {
include_once 'PEAR.php';
include_once 'Net/Socket.php';
}
/**
* Provide all access/communication to Amavisd AM.PDP
*/
class AmavisdEngine {
var $socket; // Reference to socket
var $port; // Amavisd spam release port
var $connected; // Connection status
var $last_error; // Last error message
/**
* AmavisdEngine object constructor
* $param none
* $return object Amavisd object
*/
function AmavisdEngine($host) {
$this->socket = new Net_Socket();
$this->port = $GLOBALS['conf']['amavisd']['spam_release_port'];
$this->connected = false;
$this->last_error = '';
// Connect to the Amavisd Port or wait 5 seconds and timeout
$result = $this->socket->connect($host, $this->port, true, 5);
if (PEAR::isError($result)) {
$this->last_error = "Error connecting to $host:$this->port, " . $result->getMessage();
} else {
$this->connected = true;
}
}
/**
* Shutdown and close socket
* @param none
*/
function disconnect() {
$this->socket->disconnect();
}
/**
* Release message from quarantine
* @param $mail_id
* @param $secret_id
* @param $recipient
* @result response
*/
function release_message($mail_id, $secret_id, $recipient, $quar_type, $quar_loc) {
if (! $this->connected) {
return $this->last_error;
}
$in = "request=release\r\n";
$in .= "mail_id=$mail_id\r\n";
$in .= "secret_id=$secret_id\r\n";
$in .= "quar_type=$quar_type\r\n";
# If it is file-based quarantine, lets provide the filename on the host
if ( $quar_type == 'F' ) {
$in .= "mail_file=$quar_loc\r\n";
}
$in .= "recipient=<$recipient>\r\n";
$in .= "\r\n";
// Sending request ...
$out = $this->socket->write($in);
if (PEAR::isError($out)) {
$this->last_error = 'Error writing to socket: ' . $out->getMessage();
return $this->last_error;
}
// Set timeout of 5 seconds
$this->socket->setTimeout(5);
// Reading response
$out = $this->socket->read(512);
if (PEAR::isError($out)) {
$this->last_error = 'Error reading from socket: ' . $out->getMessage();
return $this->last_error;
}
return $out;
}
}
?>

386
lib/Auth.class.php Normal file
View File

@ -0,0 +1,386 @@
<?php
/**
* Authorization and login functionality
* @author Nick Korbel <lqqkout13@users.sourceforge.net>
* @author David Poole <David.Poole@fccc.edu>
* @version 02-19-05
* @package phpScheduleIt
*
* Copyright (C) 2003 - 2005 phpScheduleIt
* License: GPL, see LICENSE
*/
/**
* Base directory of application
*/
@define('BASE_DIR', dirname(__FILE__) . '/..');
/**
* DBEngine class
*/
include_once(BASE_DIR . '/lib/DBEngine.class.php');
/**
* PHPMailer
*/
include_once('PHPMailer.class.php');
/**
* Include Auth template functions
*/
include_once(BASE_DIR . '/templates/auth.template.php');
/**
* This class provides all authoritiative and verification
* functionality, including login/logout, registration,
* and user verification
*/
class Auth {
var $is_loggedin = false;
var $login_msg = '';
var $is_attempt = false;
//var $db;
var $success;
/**
* Create a reference to the database class
* and start the session
* @param none
*/
//function Auth() {
// $this->db = new AuthDB();
//}
/**
* Check if user is a super administrator
* This function checks to see if the currently
* logged in user is the administrator, granting
* them special permissions
* @param none
* @return boolean whether the user is a s_admin
*/
function isAdmin() {
return isset($_SESSION['sessionAdmin']);
}
/**
* Check if user is a mail administrator
* This function checks to see if the currently
* logged in user is the administrator, granting
* them special permissions
* @param none
* @return boolean whether the user is a m_admin
*/
function isMailAdmin() {
return (isset($_SESSION['sessionMailAdmin']) || isset($_SESSION['sessionAdmin']));
}
/**
* Check user login
* This function checks to see if the user has
* a valid session set (if they are logged in)
* @param none
* @return boolean whether the user is logged in
*/
function is_logged_in() {
return isset($_SESSION['sessionID']);
}
/**
* Returns the currently logged in user's userid
* @param none
* @return the userid, or null if the user is not logged in
*/
function getCurrentID() {
return $_SESSION['sessionID'];//isset($_SESSION['sessionID']) ? $_SESSION['sessionID'] : null;
}
/**
* Logs the user in
* @param string $login login
* @param string $pass password
* @param string $cookieVal y or n if we are using cookie
* @param string $isCookie id value of user stored in the cookie
* @param string $resume page to forward the user to after a login
* @param string $lang language code to set
* @return any error message that occured during login
*/
function doLogin($login, $pass, $cookieVal = null, $isCookie = false, $resume = '', $lang = '', $domain = '') {
global $conf;
$msg = '';
$allowedToLogin = true;
if (empty($resume)) $resume = 'summary.php'; // Go to control panel by default
$_SESSION['sessionID'] = null;
$_SESSION['sessionName'] = null;
$_SESSION['sessionMail'] = null;
$_SESSION['sessionAdmin'] = null;
$_SESSION['sessionMailAdmin'] = null;
$_SESSION['sessionNav'] = null;
$login = stripslashes($login);
$pass = stripslashes($pass);
$ok_user = $ok_pass = false;
$authMethod = $conf['auth']['serverType'];
if ($isCookie != false) { // Cookie is set
$id = $isCookie;
if ($this->db->verifyID($id))
$ok_user = $ok_pass = true;
else {
$ok_user = $ok_pass = false;
setcookie('ID', '', time()-3600, '/'); // Clear out all cookies
$msg .= translate('That cookie seems to be invalid') . '<br/>';
}
} else {
switch ( strtolower($authMethod) ) {
case "ad":
case "ldap":
// Added this check for LDAP servers that switch to anonymous bind whenever
// provided password is left blank
if ($pass == '') return (translate ('Invalid User Name/Password.'));
// Include LDAPEngine class
include_once('LDAPEngine.class.php');
$ldap = new LDAPEngine();
if( $ldap->connect() ) {
// Get user DN
// For AD it could be of the form of 'user@domain' or standard LDAP dn
$dn = $ldap->getUserDN($login);
// Check if user is allowed to log in
if ( ! $this->isAllowedToLogin($login) ) {
$allowedToLogin = false;
$msg .= 'User is not allowed to login';
// If user is allowed to log in try a bind
} elseif ( ($dn != '') && $ldap->authBind($dn, $pass) ) {
$ldap->logonName = $login;
$ldap->loadUserData($dn);
$data = $ldap->getUserData();
$ok_user = true; $ok_pass = true;
} else {
$msg .= 'Invalid User Name/Password.';
}
$ldap->disconnect();
}
break;
case "sql":
// Include DBAuth class
include_once('DBAuth.class.php');
$db = new DBAuth();
// Check if user is allowed to log in
if ( ! $this->isAllowedToLogin($login) ) {
$allowedToLogin = false;
$msg .= 'User is not allowed to login';
// If user is allowed to log in try to authenticate
} elseif ( $db->authUser($login, $pass) ) {
$data = $db->getUserData();
$ok_user = true; $ok_pass = true;
} else {
$msg .= 'Invalid User Name/Password.';
}
break;
case "exchange":
// Include ExchAuth class
include_once('ExchAuth.class.php');
$exch = new ExchAuth();
// Check if user is allowed to log in
if ( ! $this->isAllowedToLogin($login) ) {
$allowedToLogin = false;
$msg .= 'User is not allowed to login';
// If user is allowed to log in try to authenticate
} elseif ( $exch->authUser($login, $pass, $domain) ) {
$data = $exch->getUserData();
$ok_user = true; $ok_pass = true;
} else {
$msg .= 'Invalid User Name/Password.';
}
break;
case "imap":
// Include IMAPAuth class
include_once('IMAPAuth.class.php');
$imap = new IMAPAuth();
// Check if user is allowed to log in
if ( ! $this->isAllowedToLogin($login) ) {
$allowedToLogin = false;
$msg .= 'User is not allowed to login';
// If user is allowed to log in try to authenticate
} elseif ( $imap->authUser($login, $pass) ) {
$data = $imap->getUserData();
$ok_user = true; $ok_pass = true;
} else {
$msg .= 'Invalid User Name/Password.';
}
break;
default:
CmnFns::do_error_box(translate('Unknown server type'), '', false);
}
}
// If the login failed, notify the user and quit the app
if (!$ok_user || !$ok_pass || !$allowedToLogin) {
CmnFns::write_log('Authentication failed' . ', ' . $msg, $login);
return translate($msg);
} else {
$this->is_loggedin = true;
CmnFns::write_log('Authentication successful', $login);
/*
$user = new User($id); // Get user info
// If the user wants to set a cookie, set it
// for their ID and fname. Expires in 30 days (2592000 seconds)
if (!empty($cookieVal)) {
//die ('Setting cookie');
setcookie('ID', $user->get_id(), time() + 2592000, '/');
}
*/
// Set other session variables
$_SESSION['sessionID'] = $data['logonName'];
$_SESSION['sessionName'] = $data['firstName'];
$_SESSION['sessionMail'] = $data['emailAddress'];
// If it is the super admin, set session variable
foreach ($conf['auth']['s_admins'] as $s_admin) {
if (strtolower($s_admin) == strtolower($_SESSION['sessionID'])) {
$_SESSION['sessionAdmin'] = true;
}
}
// If it is the mail admin, set session variable
foreach ($conf['auth']['m_admins'] as $m_admin) {
if (strtolower($m_admin) == strtolower($_SESSION['sessionID'])) {
$_SESSION['sessionMailAdmin'] = true;
}
}
if ($lang != '') {
set_language($lang);
}
// Send them to the control panel
CmnFns::redirect(urldecode($resume));
}
}
function isAllowedToLogin( $username ) {
global $conf;
// If not defined or set to false, $username is allowed to log in
if ( ! isset($conf['auth']['login_restriction']) || ! $conf['auth']['login_restriction'] ) return true;
// merge the allowed users together and match case-insensitive
$allowed = array_merge($conf['auth']['s_admins'], $conf['auth']['m_admins'], $conf['auth']['restricted_users']);
foreach ($allowed as $allow) {
if ( strtolower($username) == strtolower($allow) ) {
return(true);
}
}
}
/**
* Log the user out of the system
* @param none
*/
function doLogout() {
// Check for valid session
if (!$this->is_logged_in()) {
$this->print_login_msg();
die;
}
else {
$login = $_SESSION['sessionID'];
// Destroy all session variables
unset($_SESSION['sessionID']);
unset($_SESSION['sessionName']);
unset($_SESSION['sessionMail']);
unset($_SESSION['sessionNav']);
if (isset($_SESSION['sessionAdmin'])) unset($_SESSION['sessionAdmin']);
session_destroy();
// Clear out all cookies
setcookie('ID', '', time()-3600, '/');
// Log in logfile
CmnFns::write_log('Logout successful', $login);
// Refresh page
CmnFns::redirect($_SERVER['PHP_SELF']);
}
}
/**
* Returns whether the user is attempting to log in
* @param none
* @return whether the user is attempting to log in
*/
function isAttempting() {
return $this->is_attempt;
}
/**
* Kills app
* @param none
*/
function kill() {
die;
}
/**
* Destroy any lingering sessions
* @param none
*/
function clean() {
// Destroy all session variables
unset($_SESSION['sessionID']);
unset($_SESSION['sessionName']);
unset($_SESSION['sessionMail']);
if (isset($_SESSION['sessionAdmin'])) unset($_SESSION['sessionAdmin']);
session_destroy();
}
/**
* Wrapper function to call template 'printLoginForm' function
* @param string $msg error messages to display for user
* @param string $resume page to resume after a login
*/
function printLoginForm($msg = '', $resume = '') {
printLoginForm($msg, $resume);
}
/**
* Prints a message telling the user to log in
* @param boolean $kill whether to end the program or not
*/
function print_login_msg($kill = true) {
CmnFns::redirect(CmnFns::getScriptURL() . '/index.php?auth=no&resume=' . urlencode($_SERVER['PHP_SELF']) . '?' . urlencode($_SERVER['QUERY_STRING']));
}
/**
* Prints out the latest success box
* @param none
*/
function print_success_box() {
CmnFns::do_message_box($this->success);
}
}
?>

708
lib/CmnFns.class.php Normal file
View File

@ -0,0 +1,708 @@
<?php
/**
* These functions common to most pages
*
* @author Samuel Tran <stran2005@users.sourceforge.net>
* @author Brian Wong <bwsource@users.sourceforge.net>
* @author Jeremy Fowler <jfowler06@users.sourceforge.net>
* @package MailZu
*
* Following functions taken from PhpScheduleIt,
* @author Nick Korbel <lqqkout13@users.sourceforge.net>
* @version 04-03-07:
* formatTime(), formatDate(), formatDateTime(), minutes_to_hours(), getScriptURL(),
* do_error_box(), do_message_box(), getNewLink(), getNewPager(), cleanPostVals(),
* get_vert_order(), get_value_order(), write_log(), get_day_name(), redirect(),
* print_language_pulldown(), html_activate_links()
*
* Copyright (C) 2005 - 2007 MailZu
* License: GPL, see LICENSE
*/
/**
* Base directory of application
*/
@define('BASE_DIR', dirname(__FILE__) . '/..');
/**
* Include configuration file
**/
include_once(BASE_DIR . '/config/config.php');
/**
* Include Link class
*/
include_once('Link.class.php');
/**
* Include Pager class
*/
include_once('Pager.class.php');
// Define constants for method getGlobalVar()
@define('INORDER',0);
@define('GET',1);
@define('POST',2);
@define('SESSION',3);
@define('SERVER',4);
@define('FORM',5);
/**
* Provides functions common to most pages
*/
class CmnFns {
/**
* Convert minutes to hours
* @param double $time time to convert in minutes
* @return string time in 12 hour time
*/
function formatTime($time) {
global $conf;
// Set up time array with $timeArray[0]=hour, $timeArray[1]=minute
// If time does not contain decimal point
// then set time array manually
// else explode on the decimal point
$hour = intval($time / 60);
$min = $time % 60;
if ($conf['app']['timeFormat'] == 24) {
$a = ''; // AM/PM does not exist
if ($hour < 10) $hour = '0' . $hour;
}
else {
$a = ($hour < 12 || $hour == 24) ? translate('am') : translate('pm'); // Set am/pm
if ($hour > 12) $hour = $hour - 12; // Take out of 24hr clock
if ($hour == 0) $hour = 12; // Don't show 0hr, show 12 am
}
// Set proper minutes (the same for 12/24 format)
if ($min < 10) $min = 0 . $min;
// Put into a string and return
return $hour . ':' . $min . $a;
}
/**
* Convert ISO8601 date to date format
* @param string $date string (yyyy-mm-dd)
* @return int timestamp
*/
function formatDateISO($date) {
$time = strtotime($date);
return $time;
}
/**
* Convert timestamp to date format
* @param string $date timestamp
* @param string $format format to put datestamp into
* @return string date as $format or as default format
*/
function formatDate($date, $format = '') {
global $dates;
if (empty($format)) $format = $dates['general_date'];
return strftime($format, $date);
}
/**
* Convert UNIX timestamp to datetime format
* @param string $ts MySQL timestamp
* @param string $format format to put datestamp into
* @return string date/time as $format or as default format
*/
function formatDateTime($ts, $format = '') {
global $conf;
global $dates;
if (empty($format))
$format = $dates['general_datetime'] . ' ' . (($conf['app']['timeFormat'] ==24) ? '%H' : '%I') . ':%M:%S' . (($conf['app']['timeFormat'] == 24) ? '' : ' %p');
return strftime($format, $ts);
}
/**
* Convert minutes to hours/minutes
* @param int $minutes minutes to convert
* @return string version of hours and minutes
*/
function minutes_to_hours($minutes) {
if ($minutes == 0)
return '0 ' . translate('hours');
$hours = (intval($minutes / 60) != 0) ? intval($minutes / 60) . ' ' . translate('hours') : '';
$min = (intval($minutes % 60) != 0) ? intval($minutes % 60) . ' ' . translate('minutes') : '';
return ($hours . ' ' . $min);
}
/**
* Return the current script URL directory
* @param none
* @return url url of curent script directory
*/
function getScriptURL() {
global $conf;
$uri = $conf['app']['weburi'];
return (strrpos($uri, '/') === false) ? $uri : substr($uri, 0, strlen($uri));
}
/**
* Prints an error message box and kills the app
* @param string $msg error message to print
* @param string $style inline CSS style definition to apply to box
* @param boolean $die whether to kill the app or not
*/
function do_error_box($msg, $style='', $die = true) {
global $conf;
echo '<table border="0" cellspacing="0" cellpadding="0" align="center" class="alert" style="' . $style . '"><tr><td>' . $msg . '</td></tr></table>';
if ($die) {
echo '</td></tr></table>'; // endMain() in Template
echo '<p align="center"><a href="http://www.mailzu.net">' . $conf['app']['title'] .' v' . $conf['app']['version'] . '</a></p></body></html>'; // printHTMLFooter() in Template
//$t = new Template();
//$t->endMain();
//$t->printHTMLFooter();
die();
}
}
/**
* Prints out a box with notification message
* @param string $msg message to print out
* @param string $style inline CSS style definition to apply to box
*/
function do_message_box($msg, $style='') {
echo '<table border="0" cellspacing="0" cellpadding="0" align="center" class="message" style="' . $style . '"><tr><td>' . $msg . '</td></tr></table>';
}
/**
* Returns a reference to a new Link object
* Used to make HTML links
* @param none
* @return Link object
*/
function getNewLink() {
return new Link();
}
/**
* Returns a reference to a new Pager object
* Used to iterate over limited recordesets
* @param none
* @return Pager object
*/
function getNewPager() {
return new Pager();
}
/**
* Strip out slahses from POST values
* @param none
* @return array of cleaned up POST values
*/
function cleanPostVals() {
$return = array();
foreach ($_POST as $key => $val)
$return[$key] = stripslashes(trim($val));
return $return;
}
/**
* Strip out slahses from an array of data
* @param none
* @return array of cleaned up data
*/
function cleanVals($data) {
$return = array();
foreach ($data as $key => $val)
$return[$key] = stripslashes($val);
return $return;
}
/**
* Verifies vertical order and returns value
* @param string $vert value of vertical order
* @return string vertical order
*/
function get_vert_order($get_name = 'vert') {
// If no vertical value is specified, use DESC
$vert = isset($_GET[$get_name]) ? $_GET[$get_name] : 'DESC';
// Validate vert value, default to DESC if invalid
switch($vert) {
case 'DESC';
case 'ASC';
break;
default :
$vert = 'DESC';
break;
}
return $vert;
}
/**
* Verifies and returns the order to list recordset results by
* If none of the values are valid, it will return the 1st element in the array
* @param array $orders all valid order names
* @return string order of recorset
*/
function get_value_order($orders = array(), $get_name = 'order') {
if (empty($orders)) // Return null if the order array is empty
return NULL;
// Set default order value
// If a value is specifed in GET, use that. Else use the first element in the array
$order = isset($_GET[$get_name]) ? $_GET[$get_name] : $orders[0];
if (in_array($order, $orders))
$order = $order;
else
$order = $orders[0];
return $order;
}
/**
* Opposite of php's nl2br function.
* Subs in a newline for all brs
* @param string $subject line to make subs on
* @return reformatted line
*/
function br2nl($subject) {
return str_replace('<br />', "\n", $subject);
}
/**
* Writes a log string to the log file specified in config.php
* @param string $string log entry to write to file
* @param string $userid memeber id of user performing the action
* @param string $ip ip address of user performing the action
*/
function write_log($string, $userid = NULL, $ip = NULL) {
global $conf;
$delim = "\t";
$file = $conf['app']['logfile'];
$values = '';
if (!$conf['app']['use_log']) // Return if we aren't going to log
return;
if (empty($ip))
$ip = $_SERVER['REMOTE_ADDR'];
clearstatcache(); // Clear cached results
if (!is_dir(dirname($file)))
mkdir(dirname($file), 0777); // Create the directory
if (!touch($file))
return; // Return if we cant touch the file
if (!$fp = fopen($file, 'a'))
return; // Return if the fopen fails
flock($fp, LOCK_EX); // Lock file for writing
if (!fwrite($fp, '[' . date('D, d M Y H:i:s') . ']' . $delim . $ip . $delim . $userid . $delim . $string . "\r\n")) // Write log entry
return; // Return if we cant write to the file
flock($fp, LOCK_UN); // Unlock file
fclose($fp);
}
/**
* Returns the day name
* @param int $day_of_week day of the week
* @param int $type how to return the day name (0 = full, 1 = one letter, 2 = two letter, 3 = three letter)
*/
function get_day_name($day_of_week, $type = 0) {
global $days_full;
global $days_abbr;
global $days_letter;
global $days_two;
$names = array (
$days_full, $days_letter, $days_two, $days_letter
/*
array ('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'),
array ('S', 'M', 'T', 'W', 'T', 'F', 'S'),
array ('Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'),
array ('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat')
*/
);
return $names[$type][$day_of_week];
}
/**
* Redirects a user to a new location
* @param string $location new http location
* @param int $time time in seconds to wait before redirect
*/
function redirect($location, $time = 0, $die = true) {
header("Refresh: $time; URL=$location");
if ($die) exit;
}
/**
* Prints out the HTML to choose a language
* @param none
*/
function print_language_pulldown() {
global $conf;
?>
<select name="language" class="textbox" onchange="changeLanguage(this);">
<?
$languages = get_language_list();
foreach ($languages as $lang => $settings) {
echo '<option value="' . $lang . '"'
. ((determine_language() == $lang) ? ' selected="selected"' : '' )
. '>' . $settings[3] . ($lang == $conf['app']['defaultLanguage'] ? ' ' . translate('(Default)') : '') . "</option>\n";
}
?>
</select>
<?
}
/**
* Searches the input string and creates links out of any properly formatted 'URL-like' text
* Written by Fredrik Kristiansen (russlndr at online.no)
* and Albrecht Guenther (ag at phprojekt.de).
* @param string $str string to search for links to create
* @return string with 'URL-like' text changed into clickable links
*/
function html_activate_links($str) {
$str = eregi_replace('(((f|ht){1}tp://)[-a-zA-Z0-9@:%_+.~#?&//=]+)', '<a href="\1" target="_blank">\1</a>', $str);
$str = eregi_replace('([[:space:]()[{}])(www.[-a-zA-Z0-9@:%_+.~#?&//=]+)', '\1<a href="http://\2" target="_blank">\2</a>', $str);
$str = eregi_replace('([_.0-9a-z-]+@([0-9a-z][0-9a-z-]+.)+[a-z]{2,3})','<a href="mailto:\1">\1</a>', $str);
return $str;
}
/**
* Verifies current page number and returns value
* @param integer $page value of current page number
* @return integer current page number
*/
function get_current_page_number($get_name = 'page') {
// If no page number is specified, use 0
$page = ( isset($_GET[$get_name]) && is_numeric($_GET[$get_name]) ) ? $_GET[$get_name] : 0;
return $page;
}
/**
* Gets the requested mail_id
* @param none
* @return string mail_id
*/
function get_mail_id($get_name = 'mail_id') {
// If there isnt one set, return NULL
$mail_id = (isset($_GET[$get_name])) ? $_GET[$get_name] : NULL;
return $mail_id;
}
/**
* Verifies and returns the order to list recordset results by
/**
* Convert an array to a query string
* @param array $array
* @param array $exclude_vars to be excluded from the resulting string
* @param boolean $url_encode_ampersands
*/
function array_to_query_string( $array, $exclude_vars=array(), $url_encode_ampersands=true )
{
if( ! is_array( $array ) )
return '';
if( ! $array )
return '';
$str = '';
$i=0;
foreach( $array as $name => $val ) {
if( ! in_array( $name, $exclude_vars ) ) {
if( $i>0 )
if( $url_encode_ampersands )
$str .= '&amp;';
else
$str .= '&';
$str .= urlencode( $name ) . '=' . urlencode( $val );
$i++;
}
}
return $str;
}
/**
* Generate HTML for multipage links
* @param integer $page current page
* @param integer $sizeLimit maximum number of messages per page
* @param integer $count total number of messages
*/
function genMultiPagesLinks( $page, $sizeLimit, $count) {
global $link;
$total_pages = $count / $sizeLimit;
$php_self = $_SERVER['PHP_SELF'];
if( $page != 0 ) {
$query_string = CmnFns::array_to_query_string( $_GET, array( 'page' ) );
$query_string_first = $query_string . '&page=0';
$query_string_previous = $query_string . '&page=' . ($page-1);
$pager_html .= $link->getLink($php_self . '?' . $query_string_first, translate('first'), '', '', translate('Go to first page')) . " | ";
$pager_html .= $link->getLink($php_self . '?' . $query_string_previous, translate('previous'), '', '', translate('Go to previous page')) . " | ";
} else {
$pager_html .= translate('first') . " | " . translate('previous') ." | ";
}
$pager_html .= '&nbsp;&nbsp;';
// for large search results where we page beyone the first 20 pages,
// print elipsis instead of making the pager be super wide.
$elipsis_printed = false;
for( $i=0; $i<$count; $i+=$sizeLimit ) {
$page_num = $i/$sizeLimit;
if( $count > $size_limit * 20 && abs( $page_num - $page ) > 10 ) {
if( ! $elipsis_printed ) {
$pager_html .= '...&nbsp;&nbsp;';
$elipsis_printed = true;
}
} else if( $page == $page_num ) {
$pager_html .= '<b>' . ($page_num + 1) . '</b>';
$pager_html .= '&nbsp;&nbsp;';
$elipsis_printed = false;
} else {
$query_string = CmnFns::array_to_query_string( $_GET, array( 'page' ) );
$query_string .= '&page=' . $page_num;
$pager_html .= $link->getLink($php_self . '?' . $query_string, ($page_num+1), '', '', translate('Go to page') . ' ' . ($page_num+1));
$pager_html .= '&nbsp;&nbsp;';
$elipsis_printed = false;
}
}
if( $page+1 < $total_pages ) {
$query_string = CmnFns::array_to_query_string( $_GET, array( 'page' ) );
$query_string_next .= $query_string . '&page=' . ($page+1);
$query_string_last .= $query_string . '&page=' . (ceil($total_pages)-1);
$pager_html .= ' | ' . $link->getLink($php_self . '?' . $query_string_next, strtolower(translate('Next')), '', '', translate('Go to next page'));
$pager_html .= ' | ' . $link->getLink($php_self . '?' . $query_string_last, translate('last'), '', '', translate('Go to last page'));
} else {
$pager_html .= " | " . strtolower(translate('Next')) . " | " . translate('last');
}
return $pager_html;
}
/**
* Generate HTML for search engine
* @param $content_type: 'B' (attachment) or 'S' (spam)
*/
function searchEngine($content_type, $submit_page, $full_search = false) {
global $conf;
$fields_array = array("f" => translate('From'),
"s" => translate('Subject')
);
if (Auth::isMailAdmin() || $conf['app']['allowMailid']) {
$fields_array = array_merge(array("m" => "Mail ID"), $fields_array);
}
if ($full_search) $fields_array = array_merge(array("t" => translate('To')), $fields_array);
?>
<table border=0 width="100%">
<form action="<? echo $submit_page ?>" method="get" name="quarantine">
<tr><td colspan=2 align="center"><? echo translate('Search for messages whose:'); ?>&nbsp;</td></tr>
<tr><td align="right">&nbsp;
<?
$i = 1;
$array_size = count($fields_array);
foreach ($fields_array as $k => $name) {
echo "\t\t\t$name: \n";
echo "\t\t\t<select name='" . $k . "_criterion' class='button'>\n";
echo "\t\t\t<option value='contains'";
echo "contains" == CmnFns::getGlobalVar($k . '_criterion', GET) ? " selected='true'>" : ">";
echo translate('contains') . "</option>\n";
echo "\t\t\t<option value='not_contain'";
echo "not_contain" == CmnFns::getGlobalVar($k . '_criterion', GET) ? " selected='true'>" : ">";
echo translate('doesn\'t contain') . "</option>\n";
echo "\t\t\t<option value='equals'";
echo "equals" == CmnFns::getGlobalVar($k . '_criterion', GET) ? " selected='true'>" : ">";
echo translate('equals') . "</option>\n";
echo "\t\t\t<option value='not_equal'";
echo "not_equal" == CmnFns::getGlobalVar($k . '_criterion', GET) ? " selected='true'>" : ">";
echo translate('doesn\'t equal') . "</option>\n";
echo "\t\t\t</select>\n";
echo "\t\t\t<input type='text' name='" . $k . "_string' size='20' value='"
. CmnFns::getGlobalVar($k . '_string', GET) . "' />\n";
echo ($i % 2) ? "\t\t\t&nbsp;</td>\n\t\t\t<td align='left'>&nbsp\n" : "\t\t\t&nbsp;</td></tr>\n\t\t\t<tr><td align='right'>&nbsp\n";
$i ++;
}
?>
<? echo translate('Content Type'); ?>:
<select name="ctype" class="button">
<option value="A" <? echo ($content_type == 'A' ? ' selected="true"':''); ?>>
<? echo translate('All'); ?></option>
<option value="S" <? echo ($content_type == 'S' ? ' selected="true"':''); ?>>
<? echo translate('Spam'); ?></option>
<option value="B" <? echo ($content_type == 'B' ? ' selected="true"':''); ?>>
<? echo translate('Banned'); ?></option>
<? if (Auth::isMailAdmin() || $conf['app']['allowViruses']) { ?>
<option value="V" <? echo ($content_type == 'V' ? ' selected="true"':''); ?>>
<? echo translate('Virus'); ?></option>
<? }
if (Auth::isMailAdmin() || $conf['app']['allowBadHeaders']) { ?>
<option value="H" <? echo ($content_type == 'H' ? ' selected="true"':''); ?>>
<? echo translate('Bad Header'); ?></option>
<? }
echo "</select>";
$i ++;
echo ($i % 2) ? "&nbsp;</td></tr>\n\t\t\t<tr><td colspan='2' align='center'>&nbsp\n" : "&nbsp;</td><td align='left'>&nbsp";
?>
<input type="submit" class="button" name="search_action" value="<? echo translate('Search'); ?>" />
<? if (CmnFns::didSearch())
echo "<input type=\"submit\" class=\"button\" name=\"search_action\" value=\"" . translate('Clear search results') . "\" />";
?>
&nbsp;</td></tr>
</form>
</table>
<?
}
/**
* Did we do a search?
* @param none
* @return value boolean
*/
function didSearch() {
$return = false;
$strings = array('f_string','s_string','t_string','m_string');
foreach ($strings as $string) {
if ( CmnFns::getGlobalVar($string, GET) != '') $return = true;
}
return $return;
}
/**
* Function that convert $_GET into query string and exclude array
* @param array of variables to exclude
* @return query string
*/
function querystring_exclude_vars( $excl_array = array() ) {
return CmnFns::array_to_query_string( $_GET, $excl_array );
}
/**
* Gets the 'ctype' value
* @param none
* @return value
*/
function get_ctype($get_name = 'ctype') {
// If there isnt one set, return NULL
$result = NULL;
if ( isset($_GET[$get_name]) )
$result = $_GET[$get_name];
elseif ( isset($_POST[$get_name]) )
$result = $_POST[$get_name];
return $result;
}
/**
* Gets the 'action' value
* @param none
* @return value
*/
function get_action($get_name = 'action') {
// If there isnt one set, return NULL
$result = (isset($_POST[$get_name])) ? $_POST[$get_name] : NULL;
return $result;
}
/**
* Gets the 'query_string' value
* @param none
* @return value
*/
function get_query_string($get_name = 'query_string') {
// If there isnt one set, return NULL
$result = (isset($_POST[$get_name])) ? $_POST[$get_name] : NULL;
return $result;
}
/*
* Search for the var $name in $_SESSION, $_POST, $_GET,
* $_SERVER and set it in provided var.
*
* If $search is not provided, or == INORDER, it will search
* $_SESSION, then $_POST, then $_GET. Otherwise,
* use one of the defined constants to look for
* a var in one place specifically.
*
* Note: $search is an int value equal to one of the
* constants defined above.
*
* example:
* getGlobalVar('page', GET);
* -- no quotes around last param!
*
* @param string $name the name of the var to search
* @param int search constant defining where to look:
* INORDER, SESSION, FORM, POST, GET, SERVER
* @return value of var
*/
function getGlobalVar($name, $search = INORDER) {
switch ($search) {
/* we want the default case to be first here,
so that if a valid value isn't specified,
all four arrays will be searched. */
default:
case INORDER: // check session, post, get
case SESSION:
if( isset($_SESSION[$name]) )
return $_SESSION[$name];
elseif ( $search == SESSION )
break;
case FORM: // check post, get
case POST:
if( isset($_POST[$name]) )
return $_POST[$name];
elseif ( $search == POST )
break;
case GET:
if( isset($_GET[$name]) )
return $_GET[$name];
/* For INORDER case, exit after GET */
break;
case SERVER:
if( isset($_SERVER[$name]) )
return $_SERVER[$name];
break;
}
return NULL;
}
/*
* Redirect using javascript
* @param $location string
*/
function redirect_js($location) {
echo "<SCRIPT LANGUAGE=\"JavaScript\">";
echo "parent.location.href = '" . $location . "';";
echo "</SCRIPT>";
}
}
?>

237
lib/DBAuth.class.php Normal file
View File

@ -0,0 +1,237 @@
<?php
/**
* DBAuth class
* @author Samuel Tran
* @version 04-26-2005
* @package DBAuth
*
* Following functions taken from PhpScheduleIt,
* Nick Korbel <lqqkout13@users.sourceforge.net>:
* db_connect(), cleanRow(), get_err()
*
* Copyright (C) 2005 - 2007 MailZu
* License: GPL, see LICENSE
*/
/**
* Base directory of application
*/
@define('BASE_DIR', dirname(__FILE__) . '/..');
/**
* CmnFns class
*/
include_once('CmnFns.class.php');
/**
* Pear::DB
*/
if ($GLOBALS['conf']['app']['safeMode']) {
ini_set('include_path', ( dirname(__FILE__) . '/pear/' . PATH_SEPARATOR . ini_get('include_path') ));
include_once('pear/DB.php');
}
else {
include_once('DB.php');
}
/**
* Provide all database access/manipulation functionality for SQL Auth
*/
class DBAuth {
// Reference to the database object
var $db;
// The database hostname with port (hostname[:port])
var $dbHost;
// Database type
var $dbType;
// Database name
var $dbName;
// Database user
var $dbUser;
// Password for database user
var $dbPass;
// Name for auth table that contains usernames and passwords
var $dbTable;
// Name of the Username field of the MySQL table
var $dbTableUsername;
// Name of the password field of the MySQL table
var $dbTablePassword;
// Name of the 'first name' or 'full name' field of the MySQL table
var $dbTableName;
// Name of the email address field of the MySQL table
var $dbTableMail;
// Hash configuration
// 1 = passwords will be stored md5 encrypted on database
// other number = passwords will be stored as is on database
var $isMd5;
// The user's logon name
var $logonName;
// The user's first name
var $firstName;
// The user's mail address
var $emailAddress;
var $err_msg = '';
/**
* DBEngine constructor to initialize object
* @param none
*/
function DBAuth() {
global $conf;
$this->dbType = $conf['auth']['dbType'];
$this->dbHost = $conf['auth']['dbHostSpec'];
$this->dbName = $conf['auth']['dbName'];
$this->dbUser = $conf['auth']['dbUser'];
$this->dbPass = $conf['auth']['dbPass'];
$this->isMd5 = $conf['auth']['dbIsMd5'];
$this->dbTable = $conf['auth']['dbTable'];
$this->dbTableUsername = $conf['auth']['dbTableUsername'];
$this->dbTablePassword = $conf['auth']['dbTablePassword'];
$this->dbTableName = $conf['auth']['dbTableName'];
$this->dbTableMail = $conf['auth']['dbTableMail'];
$this->db_connect();
}
// Connection handling methods -------------------------------------------
/**
* Create a persistent connection to the database
* @param none
*/
function db_connect() {
/***********************************************************
/ This uses PEAR::DB
/ See http://www.pear.php.net/manual/en/package.database.php#package.database.db
/ for more information and syntax on PEAR::DB
/**********************************************************/
// Data Source Name: This is the universal connection string
// See http://www.pear.php.net/manual/en/package.database.php#package.database.db
// for more information on DSN
$dsn = $this->dbType . '://' . $this->dbUser . ':' . $this->dbPass
. '@' . $this->dbHost . '/' . $this->dbName;
// Make persistant connection to database
$db = DB::connect($dsn, true);
// If there is an error, print to browser, print to logfile and kill app
if (DB::isError($db)) {
die ('Error connecting to database: ' . $db->getMessage() );
}
// Set fetch mode to return associatve array
$db->setFetchMode(DB_FETCHMODE_ASSOC);
$this->db = $db;
}
// User methods -------------------------------------------
/**
* Authenticates user
* @param string $username
* @param string $password
* @return boolean
*/
function authUser($username, $password) {
if ( $this->isMd5 )
$password = md5( $password );
$query = "SELECT $this->dbTableUsername, $this->dbTableMail"
. (! empty($this->dbTableName) ? ", $this->dbTableName" : '')
. " FROM $this->dbTable"
. " WHERE $this->dbTableUsername=?"
. " AND $this->dbTablePassword=?";
$values = array($username, $password);
// Prepare query
$q = $this->db->prepare($query);
// Execute query
$result = $this->db->execute($q, $values);
// Check if error
$this->check_for_error($result);
if ($result->numRows() <= 0) {
$this->err_msg = translate('There are no records in the table.');
return false;
} else {
// Fetch the first row of data
$rs = $this->cleanRow($result->fetchRow());
$this->logonName = $rs[$this->dbTableUsername];
$this->firstName = ( !empty($rs[$this->dbTableName]) ?
$rs[$this->dbTableName] : $rs[$this->dbTableUsername] );
$this->emailAddress = array( $rs[$this->dbTableMail] );
$result->free();
return true;
}
}
/**
* Checks to see if there was a database error and die if there was
* @param object $result result object of query
*/
function check_for_error($result) {
if (DB::isError($result))
CmnFns::do_error_box(translate('There was an error executing your query') . '<br />'
. $result->getMessage()
. '<br />' . '<a href="javascript: history.back();">' . translate('Back') . '</a>');
return false;
}
/**
* Strips out slashes for all data in the return row
* - THIS MUST ONLY BE ONE ROW OF DATA -
* @param array $data array of data to clean up
* @return array with same key => value pairs (except slashes)
*/
function cleanRow($data) {
$return = array();
foreach ($data as $key => $val)
$return[$key] = stripslashes($val);
return $return;
}
/**
* Returns the last database error message
* @param none
* @return last error message generated
*/
function get_err() {
return $this->err_msg;
}
// Helper methods -------------------------------------------
/**
* Returns user information
* @return array containing user information
*/
function getUserData() {
$return = array(
'logonName' => $this->logonName,
'firstName' => $this->firstName,
'emailAddress' => $this->emailAddress
);
return $return;
}
}
?>

770
lib/DBEngine.class.php Normal file
View File

@ -0,0 +1,770 @@
<?php
/**
* DBEngine class
*
* @author Samuel Tran <stran2005@users.sourceforge.net>
* @author Brian Wong <bwsource@users.sourceforge.net>
* @author Jeremy Fowler <jfowler06@users.sourceforge.net>
* @version 02-21-2007
* @package DBEngine
*
* Following functions taken from PhpScheduleIt,
* @author Nick Korbel <lqqkout13@users.sourceforge.net>
* @version 03-29-05:
* db_connect(), check_for_error(), cleanRow(), get_err()
*
* Copyright (C) 2005 - 2007 MailZu
* License: GPL, see LICENSE
*/
/**
* Base directory of application
*/
@define('BASE_DIR', dirname(__FILE__) . '/..');
/**
* CmnFns class
*/
include_once('CmnFns.class.php');
/**
* Auth class
*/
include_once('lib/Auth.class.php');
/**
* Pear::DB
*/
if ($GLOBALS['conf']['app']['safeMode']) {
ini_set('include_path', ( dirname(__FILE__) . '/pear/' . PATH_SEPARATOR . ini_get('include_path') ));
include_once('pear/DB.php');
}
else {
include_once('DB.php');
}
/**
* Provide all database access/manipulation functionality
*/
class DBEngine {
// Reference to the database object
var $db;
// The database hostname with port (hostname[:port])
var $dbHost;
// Database type
var $dbType;
// Database name
var $dbName;
// Database user
var $dbUser;
// Password for database user
var $dbPass;
var $err_msg = '';
var $numRows;
/**
* DBEngine constructor to initialize object
* @param none
*/
function DBEngine() {
global $conf;
$this->dbType = $conf['db']['dbType'];
$this->dbName = $conf['db']['dbName'];
$this->dbUser = $conf['db']['dbUser'];
$this->dbPass = $conf['db']['dbPass'];
$this->dbHost = $conf['db']['hostSpec'];
$this->db_connect();
}
/**
* Create a persistent connection to the database
* @param none
* @global $conf
*/
function db_connect() {
/***********************************************************
/ This uses PEAR::DB
/ See http://www.pear.php.net/manual/en/package.database.php#package.database.db
/ for more information and syntax on PEAR::DB
/**********************************************************/
// Data Source Name: This is the universal connection string
// See http://www.pear.php.net/manual/en/package.database.php#package.database.db
// for more information on DSN
$dsn = $this->dbType . '://' . $this->dbUser . ':' . $this->dbPass
. '@' . $this->dbHost . '/' . $this->dbName;
// Make persistant connection to database
$db = DB::connect($dsn, true);
// If there is an error, print to browser, print to logfile and kill app
if (DB::isError($db)) {
CmnFns::write_log('Error connecting to database: ' . $db->getMessage(), $_SESSION['sessionID']);
die ('Error connecting to database: ' . $db->getMessage() );
}
// Set fetch mode to return associatve array
$db->setFetchMode(DB_FETCHMODE_ASSOC);
$this->db = $db;
}
/**
* Return counts for spam, banned, viruses, bad headers, and pending
* @return array of the 5 counts
*/
function get_site_summary() {
global $conf;
$return = array();
$total = array( 'spam' => 0, 'banned' => 0, 'virus' => 0, 'header' => 0, 'pending' => 0, 'total' => 0);
$query = "SELECT date,
MAX(stattable.spam) AS spam,
MAX(stattable.banned) AS banned,
MAX(stattable.viruses) AS viruses,
MAX(stattable.badheaders) AS badheaders,
MAX(stattable.pending) AS pending
FROM (
SELECT CAST(time_iso AS DATE) AS date,
COUNT(content) AS spam,
0 AS banned,
0 AS viruses,
0 AS badheaders,
0 AS pending
FROM msgs INNER JOIN msgrcpt ON msgs.mail_id=msgrcpt.mail_id
WHERE content='S' AND NOT (msgs.quar_type = '')
AND msgrcpt.rs IN ('','v')
GROUP BY CAST(time_iso AS DATE)
UNION
SELECT CAST(time_iso AS DATE) AS date,
0 AS spam,
COUNT(content) AS banned,
0 AS viruses,
0 AS badheaders,
0 AS pending
FROM msgs INNER JOIN msgrcpt ON msgs.mail_id=msgrcpt.mail_id
WHERE content='B' AND NOT (msgs.quar_type = '')
AND msgrcpt.rs IN ('','v')
GROUP BY CAST(time_iso AS DATE)
UNION
SELECT CAST(time_iso AS DATE) AS date,
0 AS spam,
0 AS banned,
COUNT(content) AS viruses,
0 AS badheaders,
0 AS pending
FROM msgs INNER JOIN msgrcpt ON msgs.mail_id=msgrcpt.mail_id
WHERE content='V' AND NOT (msgs.quar_type = '')
AND msgrcpt.rs IN ('','v')
GROUP BY CAST(time_iso AS DATE)
UNION
SELECT CAST(time_iso AS DATE) AS date,
0 AS spam,
0 AS banned,
0 AS viruses,
COUNT(content) AS badheaders,
0 AS pending
FROM msgs INNER JOIN msgrcpt ON msgs.mail_id=msgrcpt.mail_id
WHERE content='H' AND NOT (msgs.quar_type = '')
AND msgrcpt.rs IN ('','v')
GROUP BY CAST(time_iso AS DATE)
UNION
SELECT CAST(time_iso AS DATE) AS date,
0 AS spam,
0 AS banned,
0 AS viruses,
0 AS badheaders,
COUNT(content) AS pending
FROM msgs JOIN msgrcpt ON msgs.mail_id=msgrcpt.mail_id
WHERE msgrcpt.rs='p' AND NOT (msgs.quar_type = '')
GROUP BY CAST(time_iso AS DATE)
) AS stattable
GROUP BY date
ORDER BY date";
// Prepare query
$q = $this->db->prepare($query);
// Execute query
$result = $this->db->execute($q);
// Check if error
$this->check_for_error($result, $query);
while ($rs = $result->fetchRow()) {
$timestamp = CmnFns::formatDateISO($rs['date']);
$date = CmnFns::formatDate($timestamp);
$totalthisdate = $rs['spam'] + $rs['banned'] + $rs['viruses'] + $rs['badheaders'] + $rs['pending'];
$return[$date] = array('spam' => $rs['spam'],
'banned' => $rs['banned'],
'virus' => $rs['viruses'],
'header' => $rs['badheaders'],
'pending' => $rs['pending'],
'total' => $totalthisdate);
}
// Total the data
foreach ($return as $date => $typearray) {
foreach ($typearray as $type => $count) {
$total[$type] += $count;
}
}
$return['Total'] = $total;
$result->free();
return $return;
}
// User methods -------------------------------------------
/**
* Return counts for spam, banned, viruses, bad headers, and pending
* @param string full email address
* @return array of the 5 counts
*/
function get_user_summary($emailaddresses) {
global $conf;
$return = array();
$total = array('spam' => 0, 'banned' => 0, 'virus' => 0, 'header' => 0, 'pending' => 0, 'total' => 0);
// Get where clause for recipient email address(es)
$recipEmailClause = $this->convertEmailaddresses2SQL($emailaddresses);
# mysql seems to run faster with a left join
if ($conf['db']['dbtype'] == 'mysql') {
$join_type = ' LEFT JOIN';
} else {
$join_type = ' INNER JOIN';
}
$query = "SELECT date,
MAX(stattable.spam) AS spam,
MAX(stattable.banned) AS banned,
MAX(stattable.viruses) AS viruses,
MAX(stattable.badheaders) AS badheaders,
MAX(stattable.pending) AS pending
FROM (
SELECT CAST(time_iso AS DATE) AS date,
COUNT(content) AS spam,
0 AS banned,
0 AS viruses,
0 AS badheaders,
0 AS pending
FROM msgs INNER JOIN msgrcpt ON msgs.mail_id=msgrcpt.mail_id
$join_type maddr AS recip ON msgrcpt.rid=recip.id
WHERE content='S' AND NOT (msgs.quar_type = '') AND msgrcpt.rs IN ('','v')
AND $recipEmailClause
GROUP BY CAST(time_iso AS DATE)
UNION
SELECT CAST(time_iso AS DATE) AS date,
0 AS spam,
COUNT(content) AS banned,
0 AS viruses,
0 AS badheaders,
0 AS pending
FROM msgs INNER JOIN msgrcpt ON msgs.mail_id=msgrcpt.mail_id
$join_type maddr AS recip ON msgrcpt.rid=recip.id
WHERE content='B' AND NOT (msgs.quar_type = '') AND msgrcpt.rs IN ('','v')
AND $recipEmailClause
GROUP BY CAST(time_iso AS DATE)
UNION
SELECT CAST(time_iso AS DATE) AS date,
0 AS spam,
0 AS banned,
COUNT(content) AS viruses,
0 AS badheaders,
0 AS pending
FROM msgs INNER JOIN msgrcpt ON msgs.mail_id=msgrcpt.mail_id
$join_type maddr AS recip ON msgrcpt.rid=recip.id
WHERE content='V' AND NOT (msgs.quar_type = '') AND msgrcpt.rs IN ('','v')
AND $recipEmailClause
GROUP BY CAST(time_iso AS DATE)
UNION
SELECT CAST(time_iso AS DATE) AS date,
0 AS spam,
0 AS banned,
0 AS viruses,
COUNT(content) AS badheaders,
0 AS pending
FROM msgs INNER JOIN msgrcpt ON msgs.mail_id=msgrcpt.mail_id
$join_type maddr AS recip ON msgrcpt.rid=recip.id
WHERE content='H' AND NOT (msgs.quar_type = '') AND msgrcpt.rs IN ('','v')
AND $recipEmailClause
GROUP BY CAST(time_iso AS DATE)
UNION
SELECT CAST(time_iso AS DATE) AS date,
0 AS spam,
0 AS banned,
0 AS viruses,
0 AS badheaders,
COUNT(content) AS pending
FROM msgs INNER JOIN msgrcpt ON msgs.mail_id=msgrcpt.mail_id
$join_type maddr AS recip ON msgrcpt.rid=recip.id
WHERE msgrcpt.rs='p' AND NOT (msgs.quar_type = '')
AND $recipEmailClause
GROUP BY CAST(time_iso AS DATE)
) AS stattable
GROUP BY date
ORDER BY date";
// Prepare query
$q = $this->db->prepare($query);
// Execute query
$result = $this->db->execute($q);
// Check if error
$this->check_for_error($result, $query);
while ($rs = $result->fetchRow()) {
$timestamp = CmnFns::formatDateISO($rs['date']);
$date = CmnFns::formatDate($timestamp);
$totalthisdate = $rs['spam'] + $rs['banned'] + $rs['viruses'] + $rs['badheaders'] + $rs['pending'];
$return[$date] = array('spam' => $rs['spam'],
'banned' => $rs['banned'],
'virus' => $rs['viruses'],
'header' => $rs['badheaders'],
'pending' => $rs['pending'],
'total' => $totalthisdate);
}
// Total the data
foreach ($return as $date => $typearray) {
foreach ($typearray as $type => $count) {
$total[$type] += $count;
}
}
$return['Total'] = $total;
$result->free();
return $return;
}
/**
* Return all message in quarantine associated with $emailaddress
* @param string $content_type message type ('B', 'S', ...)
* @param array $emailaddresses user email address(es)
* @param string $order sql order string
* @param string $vert sql vertical order string
* @param array $search_array for search engine
* @param boolean $msgs_all if true get messages for all users, if false get messages for users in $emailaddresses
* @param integer $rs_option: 0 for new and read messages; 1 for pending messagesr; 2 for new, read and pending
* @param integer $page: page number, 0 by default
* @param boolean $get_all, if true get all messages. False by default.
* @return array of messages in quarantine
*/
function get_user_messages($content_type, $emailaddresses, $order = 'msgs.time_num', $vert = 'DESC', $search_array = '', $msgs_all = false, $rs_option = 0, $page = 0, $get_all = false) {
global $conf;
# MySQL seems to run faster with a LEFT JOIN
if ($conf['db']['dbType'] == 'mysql') {
$join_type = ' LEFT JOIN';
} else {
$join_type = ' INNER JOIN';
}
// grab the display size limit set in config.php
$sizeLimit = isset ( $conf['app']['displaySizeLimit'] ) && is_numeric( $conf['app']['displaySizeLimit'] ) ?
$conf['app']['displaySizeLimit'] : 50;
$return = array();
if (is_array($search_array)) {
$search_clause = "";
foreach($search_array as $filter) {
$search_clause .= ' AND ' . $filter;
}
}
if ( ! $msgs_all ) {
// Get where clause for recipient email address(es)
$emailaddr_clause = ( ! empty($emailaddresses) ?
' AND ' . $this->convertEmailaddresses2SQL($emailaddresses) :
'' );
}
switch ($rs_option) {
case 0:
$rs_clause = ' AND msgrcpt.rs in (\'\', \'v\')';
break;
case 1:
$rs_clause = ' AND msgrcpt.rs=\'p\'';
break;
case 2:
$rs_clause = ' AND msgrcpt.rs in (\'\', \'v\', \'p\')';
break;
default:
$rs_clause = '';
}
if ( Auth::isMailAdmin() ) {
$type_clause = ($content_type == 'A' ? ' msgs.content in (\'S\', \'B\', \'V\', \'H\')'
: ' msgs.content=?');
} else {
if ( $content_type == 'A' ) {
$type_clause = ' msgs.content in (\'S\', \'B\'';
$type_clause = ( $conf['app']['allowBadHeaders'] ? $type_clause . ', \'H\'' : $type_clause );
$type_clause = ( $conf['app']['allowViruses'] ? $type_clause . ', \'V\')' : $type_clause . ')' );
} else {
$type_clause = ' msgs.content=?';
}
}
$query = "SELECT msgs.time_num, msgs.from_addr,
msgs.mail_id, msgs.subject, msgs.spam_level, msgs.content,
msgrcpt.rs, msgs.quar_type, recip.email
FROM msgs
INNER JOIN msgrcpt ON msgs.mail_id=msgrcpt.mail_id
$join_type maddr AS sender ON msgs.sid=sender.id
$join_type maddr AS recip ON msgrcpt.rid=recip.id
WHERE $type_clause"
// Only check against the email address when not admin
. ($msgs_all ? ' ' : $emailaddr_clause)
. " $rs_clause
$search_clause
AND msgs.quar_type <> ''
ORDER BY $order $vert ";
// Prepare query
$q = $this->db->prepare($query);
if ($content_type != 'A') {
// Prepend the content type if we want a specific type of mail
$values = array($content_type);
// Execute query
$result = $this->db->execute($q, $values);
} else {
$result = $this->db->execute($q);
}
// Check if error
$this->check_for_error($result, $query);
$this->numRows = $result->numRows();
if ($this->numRows <= 0) {
return NULL;
}
if ( $get_all ) {
while ($rs = $result->fetchRow()) {
$return[] = $this->cleanRow($rs);
}
} else {
// the row to start fetching
$from = $page * $sizeLimit;
// how many results per page
$res_per_page = $sizeLimit;
// the last row to fetch for this page
$to = $from + $res_per_page - 1;
foreach (range($from, $to) as $rownum) {
if (!$row = $result->fetchrow(DB_FETCHMODE_ASSOC, $rownum)) {
break;
}
$return[] = $this->cleanRow($row);
}
}
$result->free();
return $return;
}
/**
* Return message(s) in quarantine associated with $emailaddress and $mail_id
* @param string $emailaddress user email address
* @param string $mail_id message mail_id
* @param boolean $isAdmin is true is the logged in user is MailAdmin/SuperAdmin
* @return array of message(s)
*/
function get_message($emailaddress, $mail_id) {
global $conf;
# MySQL seems to run faster with a LEFT JOIN
if ($conf['db']['dbType'] == 'mysql') {
$join_type = ' LEFT JOIN';
} else {
$join_type = ' INNER JOIN';
}
$recipEmailClause = $this->convertEmailaddresses2SQL($emailaddresses);
$return = array();
$query = 'SELECT msgs.time_num, msgs.secret_id, msgs.subject, msgs.from_addr, msgs.spam_level,'
. ' msgrcpt.rs, recip.email, msgs.host, msgs.content, msgs.quar_type, msgs.quar_loc'
. ' FROM msgs'
. ' INNER JOIN msgrcpt ON msgs.mail_id=msgrcpt.mail_id'
. $join_type . ' maddr AS sender ON msgs.sid=sender.id'
. $join_type . ' maddr AS recip ON msgrcpt.rid=recip.id'
. ' WHERE recip.email=? '
. ' AND msgs.mail_id=? ';
$values = array($emailaddress, $mail_id);
// Prepare query
$q = $this->db->prepare($query);
// Execute query
$result = $this->db->execute($q, $values);
// Check if error
$this->check_for_error($result, $query);
if ($result->numRows() <= 0) {
return NULL;
}
while ($rs = $result->fetchRow()) {
$return[] = $this->cleanRow($rs);
}
$result->free();
return $return;
}
/**
* Set RS flag in table 'msgrcpt'
* @param string $mail_id message mail_id
* @param string $mail_rcpt user email address
* @param string $flag status ('', 'R', 'D' ...)
* @param boolean $isAdmin is true is the logged in user is MailAdmin/SuperAdmin
* @return array of message(s)
*/
function update_msgrcpt_rs($mail_id, $mail_rcpt, $flag) {
// If its a pending message, do not set the rs flag to 'v'
$cur_msg_array = $this->get_message($mail_rcpt, $mail_id);
$msg_status = $cur_msg_array[0];
if ($msg_status['rs'] == 'p' && $flag == 'v') return true;
$query = 'UPDATE msgrcpt SET rs=?'
. ' WHERE mail_id=?'
. ' AND rid=(SELECT id FROM maddr WHERE email=?)';
$values = array($flag, $mail_id, $mail_rcpt);
// Prepare query
$q = $this->db->prepare($query);
// Execute query
$result = $this->db->execute($q, $values);
// Check if error
$this->check_for_error($result, $query);
return true;
}
/**
* Function that returns number of entries for logged in user
* where RS flag is equal to $flag
* @param array $emailaddresses user email address(es)
* @param string $flag 'P', 'R', ...
* @return number of message(s)
*/
function get_count_rs($emailaddresses, $flag) {
// Get where clause for recipient email address(es)
$emailaddr_clause = $this->convertEmailaddresses2SQL($emailaddresses);
if ( $emailaddr_clause != '' )
$emailaddr_clause = ' AND ' . $emailaddr_clause;
$query = 'SELECT mail_id FROM msgrcpt, maddr as recip'
. ' WHERE msgrcpt.rid=recip.id'
. $emailaddr_clause
. ' AND rs=?';
$values = array($flag);
// Prepare query
$q = $this->db->prepare($query);
// Execute query
$result = $this->db->execute($q, $values);
// Check if error
$this->check_for_error($result, $query);
$count = $result->numRows();
$result->free();
return $count;
}
/**
* Get the raw email from the database
* @param string The unique identifying mail_id
* @param string The recipient's email address
* @return string The complete email string
*/
function get_raw_mail($mail_id, $email_recip) {
global $conf;
$mail_text_column = ' mail_text';
# If using the bytea or BLOB type for sql quarantine use proper conversion
# (since amavisd 2.4.4
if ($conf['db']['binquar']) {
if ($conf['db']['dbType'] == 'mysql') {
$mail_text_column = ' CONVERT(mail_text USING utf8) AS mail_text';
} else {
$mail_text_column = " encode(mail_text,'escape') AS mail_text";
}
}
if (Auth::isMailAdmin()) {
$values = array($mail_id);
$query = 'SELECT' . $mail_text_column . ' FROM quarantine ' .
'WHERE mail_id=?';
} else {
$values = array($mail_id, $email_recip);
$query = 'SELECT' . $mail_text_column . ' FROM quarantine Q, msgrcpt M, maddr recip ' .
'WHERE (Q.mail_id=?) AND (M.mail_id=Q.mail_id) AND (M.rid=recip.id) ' .
'AND (recip.email=?) ' .
'ORDER BY chunk_ind';
}
// Prepare query
$q = $this->db->prepare($query);
// Execute query
$result = $this->db->execute($q, $values);
// Check if error
$this->check_for_error($result, $query);
if ($result->numRows() <= 0){
return false;
}
while ($rs = $result->fetchRow()) {
$return .= $rs['mail_text'];
}
$result->free();
return $return;
}
/**
* Checks to see if there was a database error, log in file and die if there was
* @param object $result result object of query
* @param SQL query $query
*/
function check_for_error($result, $query) {
global $conf;
if (DB::isError($result)) {
$this->err_msg = $result->getMessage();
CmnFns::write_log($this->err_msg, $_SESSION['sessionID']);
CmnFns::write_log('There was an error executing your query' . ' '
. $query, $_SESSION['sessionID']);
CmnFns::do_error_box(translate('There was an error executing your query') . '<br />'
. $this->err_msg
. '<br />' . '<a href="javascript: history.back();">' . translate('Back') . '</a>');
} else {
if ($conf['app']['debug']) {
CmnFns::write_log("[DEBUG SQL QUERY]: $query");
}
}
return false;
}
/**
* Strips out slashes for all data in the return row
* - THIS MUST ONLY BE ONE ROW OF DATA -
* @param array $data array of data to clean up
* @return array with same key => value pairs (except slashes)
*/
function cleanRow($data) {
$return = array();
foreach ($data as $key => $val)
$return[$key] = stripslashes($val);
return $return;
}
/**
* Returns the last database error message
* @param none
* @return last error message generated
*/
function get_err() {
return $this->err_msg;
}
/**
* Convert search filter into SQL code
* @param string $field field of table to filter on
* @param string $criterion search criterion
* @param string $string search string
* @return array containing SQL code
*/
function convertSearch2SQL($field, $criterion, $string) {
$result = array();
if ( $string != '' ) {
switch ($criterion) {
case "contains":
$search_clause = "(" . $field . " LIKE '%" . $string . "%')" ;
break;
case "not_contain":
$search_clause = "(" . $field . " NOT LIKE '%" . $string . "%')" ;
break;
case "equals":
$search_clause = "(" . $field . "='" . $string . "')" ;
break;
case "not_equal":
$search_clause = "NOT (" . $field . "='" . $string . "')" ;
break;
default:
$search_clause = "";
}
array_push($result, $search_clause);
}
return $result;
}
/**
* Convert array of mail address(es) into SQL search clause
* @param array $emailaddresses list of email address(es)
* @return string containing SQL code
*/
function convertEmailaddresses2SQL($emailaddresses) {
global $conf;
$result = '';
$emailtuple = '';
if ( is_array($emailaddresses) && !empty($emailaddresses) ) {
foreach ( $emailaddresses as $value ) {
// Append an address to lookup
$emailtuple .= ( $emailtuple != '' ? ", '$value'" : "'$value'" );
}
$result = " recip.email in ($emailtuple) ";
// Configured to support recipient delimiters?
if(!empty($conf['recipient_delimiter']) ) {
$delimiter = $conf['recipient_delimiter'];
foreach ( $emailaddresses as $value ) {
// separate localpart and domain
list($localpart, $domain) = explode("@", $value);
// Append any recipient delimited addresses
$result .= "OR recip.email LIKE '$localpart$delimiter%@$domain' ";
}
}
}
// Return results within parentheses to isolate OR statements
return "($result)";
}
}
?>

126
lib/ExchAuth.class.php Normal file
View File

@ -0,0 +1,126 @@
<?php
/**
* ExchAuth class
* @version 07-23-2005
* @Author Bogdan Baliuc <b.baliuc@rogers.com>
* @package ExchAuth
*
* Copyright (C) 2005 - 2007 MailZu
* License: GPL, see LICENSE
*/
/**
* Base directory of application
*/
@define('BASE_DIR', dirname(__FILE__) . '/..');
/**
* CmnFns class
*/
include_once('CmnFns.class.php');
/**
* Provide all database access/manipulation functionality for Exchange Auth
*/
class ExchAuth {
// The exchange hostname with port (hostname[:port])
var $exchHost;
// The exchange LDAP URI (ldap://hostname[:port])
var $exchLDAP;
// The user's logon name
var $logonName;
// The user's first name
var $firstName;
// The user's mail address(es)
var $emailAddress;
var $err_msg = '';
/**
* Constructor to initialize object
* @param none
*/
function ExchAuth() {
global $conf;
$this->exchHost = $conf['auth']['exch_host'];
$this->exchLDAP = $conf['auth']['exch_ldap'];
}
// User methods -------------------------------------------
/**
* Authenticates user
* @param string $username
* @param string $password
* @param string $domain
* @return boolean
*/
function authUser($username, $password, $domain) {
$fulluser = $domain.'/'.$username;
$mbox = imap_open('{'.$this->exchHost.'/imap}Inbox', $fulluser, $password);
if ($mbox === false) {
$this->err_msg = translate('Invalid Username/Password');
return false;
} else {
$ignore = imap_errors();
imap_close($mbox);
}
$ldapconn = ldap_connect($this->exchLDAP);
if ($ldapconn === false) {
$this->err_msg = translate('Can not connect to LDAP server');
return false;
}
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);
$ldapbind = ldap_bind($ldapconn);
if ($ldapbind === false) {
$this->err_msg = translate('Can not bind to LDAP server');
return false;
}
$ldapattr = array('cn', 'rfc822Mailbox' ,'otherMailbox');
$read = ldap_search($ldapconn, '', '(uid='.$username.')', $ldapattr);
if ($read === false) {
$this->err_msg = translate('Unable to search LDAP server');
return false;
}
$info = ldap_get_entries($ldapconn, $read);
$this->logonName = strtolower($username);
$this->firstName = $info[0]['cn'][0];
$this->emailAddress[] = strtolower($info[0]['rfc822mailbox'][0]);
for ($i=0; $i<$info[0]['othermailbox']['count']; $i++) {
$data = $info[0]['othermailbox'][$i];
if (strncasecmp($data, 'smtp$', 5) == 0) {
$this->emailAddress[] = strtolower(substr($data, 5));
}
}
ldap_close($ldapconn);
return true;
}
/**
* Returns the last error message
* @param none
* @return last error message generated
*/
function get_err() {
return $this->err_msg;
}
// Helper methods -------------------------------------------
/**
* Returns user information
* @return array containing user information
*/
function getUserData() {
$return = array(
'logonName' => $this->logonName,
'firstName' => $this->firstName,
'emailAddress' => $this->emailAddress
);
return $return;
}
}
?>

124
lib/IMAPAuth.class.php Normal file
View File

@ -0,0 +1,124 @@
<?php
/**
* IMAPAuth class
* @version 08-11-2005
* @Author Samuel Tran
* @package IMAPAuth
*
* Copyright (C) 2005 - 2007 MailZu
* License: GPL, see LICENSE
*/
/**
* Base directory of application
*/
@define('BASE_DIR', dirname(__FILE__) . '/..');
/**
* CmnFns class
*/
include_once('CmnFns.class.php');
/**
* Provide all database access/manipulation functionality for IMAP Auth
*/
class IMAPAuth {
// The IMAP hosts with port (hostname[:port])
var $imapHosts;
// IMAP authentication type
var $imapType;
// Username
var $imapUsername;
var $err_msg = '';
/**
* Constructor to initialize object
* @param none
*/
function IMAPAuth() {
global $conf;
$this->imapHosts = $conf['auth']['imap_hosts'];
$this->imapType = $conf['auth']['imap_type'];
$this->imapDomainName = $conf['auth']['imap_domain_name'];
}
// User methods -------------------------------------------
/**
* Authenticates user
* @param string $username
* @param string $password
* @return boolean
*/
function authUser ($username, $password) {
// Returns true if the username and password work
// and false if they are wrong or don't exist.
$this->imapUsername = $username;
foreach ($this->imapHosts as $host) { // Try each host in turn
$host = trim($host);
switch ($this->imapType) {
case "imapssl":
$host = '{'.$host."/imap/ssl}INBOX";
break;
case "imapcert":
$host = '{'.$host."/imap/ssl/novalidate-cert}INBOX";
break;
case "imaptls":
$host = '{'.$host."/imap/notls}INBOX";
break;
default:
$host = '{'.$host.'}INBOX';
}
//error_reporting(0);
$connection = imap_open($host, $username, $password, OP_HALFOPEN);
if ($connection) {
imap_close($connection);
return true;
}
}
$this->err_msg = translate('IMAP Authentication: no match');
return false; // No match
}
/**
* Returns the last error message
* @param none
* @return last error message generated
*/
function get_err() {
return $this->err_msg;
}
// Helper methods -------------------------------------------
/**
* Returns user information
* @return array containing user information
*/
function getUserData() {
$return = array(
'logonName' => $this->imapUsername,
'firstName' => $this->imapUsername,
'emailAddress' => array( $this->imapUsername.
( empty($this->imapDomainName) ? '' :
'@'. $this->imapDomainName )
)
);
return $return;
}
}
?>

398
lib/LDAPEngine.class.php Normal file
View File

@ -0,0 +1,398 @@
<?php
/**
* LDAPEngine class
* @author Samuel Tran
* @version 04-24-2005
* @package LDAPEngine
*
* Copyright (C) 2005 - 2007 MailZu
* License: GPL, see LICENSE
*/
/**
* Base directory of application
*/
@define('BASE_DIR', dirname(__FILE__) . '/..');
/**
* CmnFns class
*/
include_once('CmnFns.class.php');
class LDAPEngine {
// The directory server, tested with OpenLDAP and Active Directory
var $serverType;
// An array of server IP address(es) or hostname(s)
var $hosts;
// SSL support
var $ssl;
// The base DN (e.g. "dc=example,dc=org")
var $basedn;
// The user identifier (e.g. "uid")
var $userIdentifier;
/**
/* The user to authenticate with when searching
/* if anonymous binding is not supported
/* (Active Directory doesn't support anonymous access by default)
*/
var $searchUser;
/**
/* The password to authenticate with when searching
/* if anonymous binding is not supported
/* (Active Directory doesn't support anonymous access by default)
*/
var $searchPassword;
/**
* Variable specific to Active Directory:
* Active Directory authenticates using user@domain
*/
var $domain;
/**
* Variables specific to LDAP:
* Container where the user records are kept
*/
var $userContainer;
// The login attribute to authenticate with
var $login;
// The password attribute to authenticate with
var $password;
// The name attribute of the user
var $name;
/**
* The mail attribute used as the recipient final address
* Could be the actual mail attribute or another attribute
* (in the latter case look for the "%m" token in the ldap query filter in amavisd.conf)
*/
var $mailAttr;
// The last error code returned by the LDAP server
var $ldapErrorCode;
// Text of the error message
var $ldapErrorText;
// The internal LDAP connection handle
var $connection;
// Result of any connection
var $bind;
var $connected;
// The user's logon name
var $logonName;
// The user's first name
var $firstName;
// The user's mail address ($mailAttr value)
var $emailAddress;
/**
* LDAPEngine constructor to initialize object
*/
function LDAPEngine() {
global $conf;
$this->serverType = strtolower($conf['auth']['serverType']);
switch ($this->serverType) {
case "ldap":
$this->hosts = $conf['auth']['ldap_hosts'];
$this->ssl = $conf['auth']['ldap_ssl'];
$this->basedn = $conf['auth']['ldap_basedn'];
$this->userIdentifier = $conf['auth']['ldap_user_identifier'];
$this->userContainer = $conf['auth']['ldap_user_container'];
$this->login = $conf['auth']['ldap_login'];
$this->name = $conf['auth']['ldap_name'];
$this->mailAttr = $conf['auth']['ldap_mailAttr'];
$this->searchUser = $conf['auth']['ldap_searchUser'];
$this->searchPassword = $conf['auth']['ldap_searchPassword'];
break;
case "ad":
$this->hosts = $conf['auth']['ad_hosts'];
$this->ssl = $conf['auth']['ad_ssl'];
$this->basedn = $conf['auth']['ad_basedn'];
$this->userIdentifier = $conf['auth']['ad_user_identifier'];
$this->domain = $conf['auth']['ad_domain'];
$this->login = $conf['auth']['ad_login'];
$this->name = $conf['auth']['ad_name'];
$this->mailAttr = $conf['auth']['ad_mailAttr'];
$this->searchUser = $conf['auth']['ad_searchUser'];
$this->searchPassword = $conf['auth']['ad_searchPassword'];
break;
default:
CmnFns::do_error_box(translate('Unknown server type'), '', false);
}
}
// Connection handling methods -------------------------------------------
/**
* Makes a connection to the LDAP server.
* Just creates a connection which is used in all later access.
* If it can't connect and bind anonymously, it creates an error code of -1.
* Returns true if connected, false if failed.
* Takes an array of possible servers - if one doesn't work, it tries the next and so on.
* @param none
*/
function connect() {
foreach ($this->hosts as $host) {
$ldap_url = ( $this->ssl ? "ldaps://".$host : $host );
$this->connection = ldap_connect($ldap_url);
if ($this->connection) {
ldap_set_option($this->connection, LDAP_OPT_PROTOCOL_VERSION, 3);
switch ($this->serverType) {
case "ad":
// Active Directory needs:
ldap_set_option($this->connection, LDAP_OPT_REFERRALS, 0);
break;
default:
break;
}
$this->connected = true;
return true;
} else {
CmnFns::write_log('LDAP connection failed', '');
}
}
$this->ldapErrorCode = -1;
$this->ldapErrorText = "Unable to connect to any server";
$this->connected = false;
return false;
}
/**
* Disconnects from the LDAP server
* @param none
*/
function disconnect() {
if( $this->connected ) {
if ( ! @ldap_close( $this->connection ) ) {
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
return false;
} else {
$this->connected = false;
return true;
}
}
return true;
}
/**
* Anonymously binds to the connection. After this is done,
* queries and searches can be done - but read-only.
*/
function anonBind() {
if ( ! $this->bind = ldap_bind($this->connection) ) {
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
CmnFns::write_log($this->ldapErrorCode . ': ' . $this->ldapErrorText, '');
return false;
} else {
return true;
}
}
/**
* Binds to the directory with a specific username and password:
* @param string $dn full LDAP dn or AD type 'user@domain'
* @param string $password password
* @return bool
*/
function authBind($username, $password) {
if ( ! $this->bind = @ldap_bind($this->connection, $username, $password) ) {
$this->ldapErrorCode = ldap_errno( $this->connection);
$this->ldapErrorText = ldap_error( $this->connection);
CmnFns::write_log($this->ldapErrorCode . ': ' . $this->ldapErrorText, '');
return false;
} else {
return true;
}
}
// User methods -------------------------------------------
/**
* Returns the full user DN to use, based on the ldap server type
* @param string $userlogin
* @return string
*/
function getUserDN($userlogin) {
switch ($this->serverType) {
case "ldap":
if ( $this->userContainer != '' && $this->userIdentifier == $this->login ) {
// If a user container is specified and the login attribute is the same
// as the user identifier attribute, build the user dn
$dn = "$this->userIdentifier=$userlogin," . "$this->userContainer," . $this->basedn;
} else {
// Search for user dn
$searchFilter = $this->login . "=" . $userlogin;
$dn = $this->searchUserDN($searchFilter);
}
break;
case "ad":
if ( strtolower($this->login) == 'samaccountname' ) {
// If the user login attribute is 'samaccountname', build the user AD login
$dn = $userlogin . "@" . $this->domain;
} else {
// Search for user dn
$searchFilter = $this->login . "=" . $userlogin;
$dn = $this->searchUserDN($searchFilter);
}
break;
default:
CmnFns::do_error_box(translate('Unknown server type'), '', false);
}
return $dn;
}
/**
* Returns the correct search base, based on the ldap server type
* @param none
* @return string
*/
function getSearchBase() {
switch ($this->serverType) {
case "ldap":
$searchBase = ( $this->userContainer != '' ? "$this->userContainer," . $this->basedn
: $this->basedn );
break;
case "ad":
$searchBase = $this->basedn;
break;
default:
CmnFns::do_error_box(translate('Unknown server type'), '', false);
}
return $searchBase;
}
/**
* Returns the correct user username that matches the search filter (array with single username)
* If several usernames are found, return the array of usernames.
* @param string $searchFilter search filter in a standard LDAP query
* @return array
*/
function searchUserDN($searchFilter) {
switch ($this->serverType) {
case "ldap":
if ( $this->searchUser != '' ) {
// If a search user is defined bind with this user
$this->authBind($this->searchUser, $this->searchPassword);
} else {
// Otherwise bind anonymously
$this->anonBind();
}
break;
case "ad":
// if the directory is AD, then bind first with the search user
$this->authBind($this->searchUser, $this->searchPassword);
break;
default:
CmnFns::do_error_box(translate('Unknown server type'), '', false);
}
$sr = ldap_search( $this->connection, $this->getSearchBase(), $searchFilter, array('dn'));
$entries = ldap_get_entries( $this->connection, $sr);
if ( $entries["count"] < 1 ) {
// If no results returned
$this->ldapErrorCode = -1;
$this->ldapErrorText = "No users found matching search criteria";
CmnFns::write_log($this->ldapErrorCode . ': ' . $this->ldapErrorText, '');
} else {
// The search should give an unique dn
// If several results are found get the first one
$dn = $entries[0]['dn'];
}
return $dn;
}
/**
* Queries LDAP for user information
* @param string $dn
* @return boolean indicating success or failure
*/
function loadUserData($dn) {
$this->emailAddress = array();
// We are instered in getting just the user's first name and his/her mail attribute(s)
$attributes = $this->mailAttr;
array_push( $attributes, strtolower($this->name) );
switch ($this->serverType) {
case "ldap":
$result = ldap_search( $this->connection, $dn, "objectclass=*", $attributes );
break;
case "ad":
if ( strtolower($this->login) == 'samaccountname' ) {
// dn is of the form 'user@domain'
list($samaccountname, $domain) = explode("@", $dn);
$result = ldap_search( $this->connection, $this->getSearchBase(),
$this->login . "=" . $samaccountname, $attributes );
} else {
// dn is standard LDAP dn
$result = ldap_search( $this->connection, $dn, "objectclass=*", $attributes );
}
break;
}
$entries = ldap_get_entries( $this->connection, $result );
if( $result and ( $entries["count"] > 0 ) ) {
// The search should give a single entry
// If several results are found get the first entry
$this->firstName = $entries[0][strtolower($this->name)][0];
foreach ( $this->mailAttr as $value ) {
// For single value or multiple value attribute
for ($i=0; $i<$entries[0][strtolower($value)]["count"]; $i++) {
# AD proxyAddresses attribute values have 'smtp:' string before the actual email address
if(preg_match("/^smtp:/i", strtolower($entries[0][strtolower($value)][$i])) == 1) {
array_push( $this->emailAddress, preg_replace("/^\w+:/", '', strtolower($entries[0][strtolower($value)][$i])) );
} else {
array_push( $this->emailAddress, strtolower($entries[0][strtolower($value)][$i]) );
}
}
}
} else {
// If no results returned
$this->ldapErrorCode = -1;
$this->ldapErrorText = "No entry found matching search criteria";
CmnFns::write_log($this->ldapErrorCode . ': ' . $this->ldapErrorText, '');
return false;
}
return true;
}
// Helper methods -------------------------------------------
/**
* Returns user information
* @return array containing user information
*/
function getUserData() {
$return = array(
'logonName' => $this->logonName,
'firstName' => $this->firstName,
'emailAddress' => $this->emailAddress
);
return $return;
}
}
?>

223
lib/Link.class.php Normal file
View File

@ -0,0 +1,223 @@
<?php
/**
* XHTML link class
* Creates or prints an XHTML valid link
* @author Nick Korbel <lqqkout13@users.sourceforge.net>
* @version 01-20-05
* @package Link
*
* Copyright (C) 2003 - 2005 phpScheduleIt
* License: GPL, see LICENSE
*/
class Link {
var $url;
var $text;
var $_class;
var $style;
var $text_on_over;
var $img_src;
var $img_alt;
/**
* Link Constructor
* Creates a new XHTML valid link
* @param string $url url to link to
* @param string $text text of link
* @param string $class link class
* @param string $style inline style of link (overrides class)
* @param string $text_on_over text to display in status bar onmouseover
* @param string $on_over javascript to call onmouseover
*/
function Link($url=null, $text=null, $class=null, $style=null, $text_on_over=null) {
$this->url = $url;
$this->text = $text;
$this->_class = $class;
$this->style = $style;
$this->text_on_over = addslashes($text_on_over);
}
//---------------------------------------------
// Setter functions
//---------------------------------------------
/**
* Set the url of the link
* @param string $url url to link to
*/
function setUrl($url) {
$this->url = $url;
}
/**
* Set the text of the link
* @param string $text text of link
*/
function setText($text) {
$this->text = $text;
}
/**
* Set the class of the link
* @param string $class link class
*/
function setClass($class) {
$this->_class = $class;
}
/**
* Set the inline style of the link
* @param string $style inline style of link (overrides class)
*/
function setStyle($style) {
$this->style = $style;
}
/**
* Set the text onmouseover
* @param string $text_on_over text to display in status bar onmouseover
*/
function setTextOnOver($text_on_over) {
$this->text_on_over = addslashes($text_on_over);
}
/**
* Set the image source "src" property
* @param string $img_src image source property
*/
function setImgSrc($img_src) {
$this->img_src = $img_src;
}
/**
* Set the image alt property
* @param string $img_alt image alt property
*/
function setImgAlt($img_alt) {
$this->img_alt = $img_alt;
}
//=============================================
//---------------------------------------------
// Getter functions
//---------------------------------------------
/**
* Return the url of the link
* @return string $url url to link to
*/
function getUrl() {
return $this->url;
}
/**
* Return the text of the link
* @return string $text text of link
*/
function getText() {
return $this->text;
}
/**
* Return the class of the link
* @return string $class link class
*/
function getClass() {
return $this->_class;
}
/**
* Return the inline style of the link
* @return string $style inline style of link (overrides class)
*/
function getStyle() {
return $this->style;
}
/**
* Return the text onmouseover
* @return string $text_on_over text to display in status bar onmouseover
*/
function getTextOnOver() {
return stripslashes($this->text_on_over);
}
/**
* Return the image source "src" property
* @return string
*/
function getImgSrc() {
return $img_src;
}
/**
* Return the image alt property
* @return string
*/
function getImgAlt() {
return $img_alt;
}
//=============================================
/**
* Print out a link without creating a new Link object
* @param string $url url to link to
* @param string $text text of link
* @param string $class link class
* @param string $style inline style of link (overrides class)
* @param string $text_on_over text to display in status bar onmouseover
*/
function doLink($url=null, $text=null, $class=null, $style=null, $text_on_over=null, $boldtext=null) {
echo $this->getLink($url, $text, $class, $style, $text_on_over, $boldtext);
}
/**
* Print out an image link without creating a new Link obejct
* @param string $url url to link to
* @param string $img_src image source "src" property
* @param string $alt image alt property
* @param string $text_on_over text to display in status bar onmouseover
*/
function doImageLink($url = null, $img_src = null, $alt = null, $text_on_over = null) {
echo $this->getImageLink($url, $img_src, $alt, $text_on_over);
}
/**
* Prints out the link using the class values
* @param none
* @see doLink()
*/
function printLink() {
$this->doLink($this->url, $this->text, $this->_class, $this->style, $this->text_on_over);
}
/**
* Returns the HTML for the link with given parameters
* @param string $url url to link to
* @param string $text text of link
* @param string $class link class
* @param string $style inline style of link (overrides class)
* @param string $text_on_over text to display in status bar onmouseover
* @return string of HTML for link
*/
function getLink($url=null, $text=null, $class=null, $style=null, $text_on_over=null, $boldtext=null) {
$text_on_over = (!is_null($text_on_over)) ? $text_on_over : $text; // Use passed in text on mouse over, else just use link text
//return "<a href=\"$url\" class=\"$class\" style=\"$style\" onmouseover=\"javascript: window.status='" . addslashes($text_on_over) . "'; return true;\" onmouseout=\"javascript: window.status=''; return true;\">$text</a>";
return "<a href=\"$url\" class=\"$class\" style=\"$style\" onmouseover=\"javascript: window.status='" . addslashes($text_on_over) . "'; return true;\" onmouseout=\"javascript: window.status=''; return true;\">" . ($boldtext ? "<b>$text</b>" : $text) . "</a>";
}
/**
* Returns the HTML for the link with given parameters
* @param string $url url to link to
* @param string $img_src image source "src" property
* @param string $alt image alt property
* @param string $text_on_over text to display in status bar onmouseover
*/
function getImageLink($url = null, $img_src = null, $alt = null, $text_on_over = null) {
$text_on_over = (!is_null($text_on_over)) ? $text_on_over : $alt; // Use passed in text on mouse over, else just use link text
return "<a href=\"$url\" onmouseover=\"javascript: window.status='" . addslashes($text_on_over) . "'; return true;\" onmouseout=\"javascript: window.status=''; return true;\"><img src=\"$img_src\" alt=\"$alt\" title=\"$alt\" border=\"0\"/></a>\n";
}
}
?>

97
lib/MailEngine.class.php Normal file
View File

@ -0,0 +1,97 @@
<?php
/**
* MailEngine class
* @author Brian Wong <bwsource@users.sourceforge.net>
* @version 04-02-07
* @package MailEngine
*
* Copyright (C) 2003 - 2007 MailZu
* License: GPL, see LICENSE
*/
/**
* Base directory of application
*/
@define('BASE_DIR', dirname(__FILE__) . '/..');
/**
* CmnFns class
*/
include_once('CmnFns.class.php');
/**
* Pear::DB
*/
if ($GLOBALS['conf']['app']['safeMode']) {
ini_set('include_path', ( dirname(__FILE__) . '/pear/' . PATH_SEPARATOR . ini_get('include_path') ));
include_once('pear/PEAR.php');
include_once('pear/Mail/mimeDecode.php');
}
else {
include_once 'PEAR.php';
include_once('Mail/mimeDecode.php');
}
/**
* Provide all mail access/manipulation functionality
*/
class MailEngine {
var $raw; // Raw mail contents
var $struct; // The top-level MIME structure
var $recipient; // The recipient of the email
var $msg_found; // Msg found in database
var $msg_error; // Msg has MIME error
var $last_error; // PEAR Error Messages
/**
* MailEngine object constructor
* $param string The unique mail_id
* $param string The mail addr of the reader
* $return object MailEngine object
*/
function MailEngine($mail_id, $recip) {
$this->recipient = $recip;
$this->getRawContent($mail_id);
$this->msg_error = false;
if ($this->raw) {
$this->msg_found = true;
$this->struct = $this->getDecodedStruct($this->raw);
if (PEAR::isError($this->struct)) {
$this->msg_error = true;
$this->last_error = $this->struct->getMessage();
}
} else {
$this->msg_found = false;
}
return $this->struct;
}
/**
* Decode the raw contents to get the MIME structure
* $param string The complete raw message returned by get_raw_mail
* $return object Mail_mimeDecode::decode object
*/
function getDecodedStruct($contents) {
$message = new Mail_mimeDecode($contents);
$msg_struct = $message->decode( array ( 'include_bodies' => true,
'decode_bodies' => true,
'decode_headers' => true)
);
return $msg_struct;
}
/**
* Get the raw content through a DB call
* $param string The unique mail_id
* $return string The complete raw email
*/
function getRawContent($mail_id) {
$db = new DBEngine();
$this->raw = $db->get_raw_mail($mail_id, $this->recipient);
// Mark read
if (in_array($this->recipient, $_SESSION['sessionMail']) && $this->raw) {
$db->update_msgrcpt_rs($mail_id,$this->recipient,'v');
}
}
}

316
lib/MailMime.class.php Normal file
View File

@ -0,0 +1,316 @@
<?php
/**
* MailEngine class
* @author Brian Wong <bwsource@users.sourceforge.net>
* @version 04-12-05
* @package MailEngine
*
* Copyright (C) 2003 - 2007 MailZu
* License: GPL, see LICENSE
*/
/**
* Base directory of application
*/
@define('BASE_DIR', dirname(__FILE__) . '/..');
/**
* CmnFns class
*/
include_once('CmnFns.class.php');
/**
* Pear::DB
*/
if ($GLOBALS['conf']['app']['safeMode']) {
ini_set('include_path', ( dirname(__FILE__) . '/pear/' . PATH_SEPARATOR . ini_get('include_path') ));
include_once('pear/Mail/mimeDecode.php');
}
else {
include_once('Mail/mimeDecode.php');
}
/**
* Include htmlfilter class
*/
include_once('lib/htmlfilter.php');
/**
* Provide all MIME functionality
*/
/**
* Get full MIME type
* $param The mime structure object
*/
function GetCtype($struct) {
$ctype_p = strtolower(trim($struct->ctype_primary));
$ctype_s = strtolower(trim($struct->ctype_secondary));
$type = $ctype_p . '/' . $ctype_s;
return $type;
}
/**
* Recursively parse MIME structure
* $param The mime structure object
*/
$filelist = array ();
$errors = array ();
function MsgParseBody($struct) {
global $filelist;
global $errors;
$ctype_p = strtolower(trim($struct->ctype_primary));
$ctype_s = strtolower(trim($struct->ctype_secondary));
switch ($ctype_p) {
case "multipart":
switch ($ctype_s) {
case "alternative":
// Handle multipart/alternative parts
$alt_entity = FindMultiAlt($struct->parts);
// Ignore if we return false NEEDS WORK
if ($alt_entity) MsgParseBody($alt_entity);
break;
case "related":
// Handle multipart/related parts
$rel_entities = FindMultiRel($struct);
foreach ($rel_entities as $ent) {
MsgParseBody($ent);
}
break;
default:
// Probably multipart/mixed here
// Recursively process nested mime entities
if ( is_array($struct->parts) || is_object($struct->parts) ) {
foreach ($struct->parts as $cur_part) {
MsgParseBody($cur_part);
}
} else {
$errors['Invalid or Corrupt MIME Detected.'] = true;
}
break;
}
break;
case "text":
// Do not display attached text types
if ($attachment = $struct->d_parameters['filename'] or
$attachment = $struct->d_parameters['name']) {
array_push($filelist, $attachment);
break;
}
switch ($ctype_s) {
// Plain text
case "plain":
MsgBodyPlainText($struct->body);
break;
// HTML text
case "html":
MsgBodyHtmlText($struct->body);
break;
// Text type we do not support
default:
$errors['Portions of text could not be displayed'] = true;
}
break;
default:
// Save the listed filename or notify the
// reader that this mail is not displayed completely
$attachment = $struct->d_parameters['filename'];
$attachment ? array_push($filelist, $attachment) : $errors['Unsupported MIME objects present'] = true;
}
}
/**
* Get the best MIME entity for multipart/alternative
* Adapted from SqurrelMail
* $param Array of MIME entities
* $return Single MIME entity
*/
function FindMultiAlt($parts) {
$alt_pref = array ('text/plain', 'text/html');
$best_view = 0;
// Bad Headers sometimes have invalid MIME....
if ( is_array($parts) || is_object($parts) ) {
foreach ($parts as $cur_part) {
$type = GetCtype($cur_part);
if ($type == 'multipart/related') {
$type = $cur_part->d_parameters['type'];
// Mozilla bug. Mozilla does not provide the parameter type.
if (!$type) $type = 'text/html';
}
$altCount = count($alt_pref);
for ($j = $best_view; $j < $altCount; ++$j) {
if (($alt_pref[$j] == $type) && ($j >= $best_view)) {
$best_view = $j;
$struct = $cur_part;
}
}
}
return $struct;
} else {
$errors['Invalid or Corrupt MIME Detected.'] = true;
}
}
/**
* Get the list of related entities for multipart/related
* Adapted from SqurrelMail
* $param multipart/alternative structure
* @return List of MIME entities
*/
function FindMultiRel($struct) {
$entities = array();
$type = $struct->d_parameters['type'];
// Mozilla bug. Mozilla does not provide the parameter type.
if (!$type) $type = 'text/html';
// Bad Headers sometimes have invalid MIME....
if ( is_array($struct->parts) || is_object($struct->parts) ) {
foreach ($struct->parts as $part) {
if (GetCtype($part) == $type || GetCtype($part) == "multipart/alternative") {
array_push($entities,$part);
}
}
} else {
$errors['Invalid or Corrupt MIME Detected.'] = true;
}
return $entities;
}
// Wrapper script for htmlfilter. Settings taken
// from SquirrelMail
function sanitizeHTML($body) {
if (isset($_COOKIE['lang']) &&
file_exists("img/".substr($_COOKIE['lang'],0,2).".blocked_img.png")) {
$secremoveimg = "img/".substr($_COOKIE['lang'],0,2).".blocked_img.png";
} else {
$secremoveimg = "img/blocked_img.png";
}
$tag_list = Array(
false,
"object",
"meta",
"html",
"head",
"base",
"link",
"frame",
"iframe",
"plaintext",
"marquee"
);
$rm_tags_with_content = Array(
"script",
"applet",
"embed",
"title",
"frameset",
"xml",
"style"
);
$self_closing_tags = Array(
"img",
"br",
"hr",
"input"
);
$force_tag_closing = true;
$rm_attnames = Array(
"/.*/" =>
Array(
"/target/i",
"/^on.*/i",
"/^dynsrc/i",
"/^data.*/i",
"/^lowsrc.*/i"
)
);
$bad_attvals = Array(
"/.*/" =>
Array(
"/^src|background/i" =>
Array(
Array(
"/^([\'\"])\s*\S+script\s*:.*([\'\"])/si",
"/^([\'\"])\s*mocha\s*:*.*([\'\"])/si",
"/^([\'\"])\s*about\s*:.*([\'\"])/si",
"/^([\'\"])\s*https*:.*([\'\"])/si",
"/^([\'\"])\s*cid*:.*([\'\"])/si"
),
Array(
"\\1$secremoveimg\\2",
"\\1$secremoveimg\\2",
"\\1$secremoveimg\\2",
"\\1$secremoveimg\\2",
"\\1$secremoveimg\\2"
)
),
"/^href|action/i" =>
Array(
Array(
"/^([\'\"])\s*\S+script\s*:.*([\'\"])/si",
"/^([\'\"])\s*mocha\s*:*.*([\'\"])/si",
"/^([\'\"])\s*about\s*:.*([\'\"])/si"
),
Array(
"\\1#\\1",
"\\1#\\1",
"\\1#\\1",
"\\1#\\1"
)
),
"/^style/i" =>
Array(
Array(
"/expression/i",
"/binding/i",
"/behaviou*r/i",
"/include-source/i",
"/url\s*\(\s*([\'\"])\s*\S+script\s*:.*([\'\"])\s*\)/si",
"/url\s*\(\s*([\'\"])\s*mocha\s*:.*([\'\"])\s*\)/si",
"/url\s*\(\s*([\'\"])\s*about\s*:.*([\'\"])\s*\)/si",
"/(.*)\s*:\s*url\s*\(\s*([\'\"]*)\s*\S+script\s*:.*([\'\"]*)\s*\)/si",
"/url\(([\'\"])\s*https*:.*([\'\"])\)/si"
),
Array(
"idiocy",
"idiocy",
"idiocy",
"idiocy",
"url(\\1#\\1)",
"url(\\1#\\1)",
"url(\\1#\\1)",
"url(\\1#\\1)",
"url(\\1#\\1)",
"\\1:url(\\2#\\3)",
"url(\\1$secremoveimg\\1)"
)
)
)
);
$add_attr_to_tag = Array(
"/^a$/i" =>
Array('target'=>'"_new"'
)
);
$trusted_html = sanitize($body,
$tag_list,
$rm_tags_with_content,
$self_closing_tags,
$force_tag_closing,
$rm_attnames,
$bad_attvals,
$add_attr_to_tag
);
return $trusted_html;
}

1541
lib/PHPMailer.class.php Normal file

File diff suppressed because it is too large Load Diff

629
lib/Pager.class.php Normal file
View File

@ -0,0 +1,629 @@
<?php
/**
* Paging class to iterate through limited recordsets
* @author Nick Korbel <lqqkout13@users.sourceforge.net>
* @version 02-02-05
* @package Pager
*
* Copyright (C) 2003 - 2005 phpScheduleIt
* License: GPL, see LICENSE
* /
/**
* To actually print out page links, call printPages() function
*
* In order for this object to work correctly, total records
* must be set in either the constructor or by calling
* setTotRecords()
*
* + Warning - The printPages() function cannot be called
* from within a form
*
* === EXAMPLE OF HOW TO USE PAGER ===
* // Initialize new Pager object with default values
* $pager = new Pager();
*
* // Get total # of pages
* $query = "SELECT COUNT(*) as num FROM table";
* $result = $db->query($query);
* $rs = $result->fetchRow();
* $num = $rs['num']; // # of records
*
* $pager->setTotRecords($num);
* $recordset_offset = $pager->getOffset();
* $limit = $pager->getLimit();
*
* // Execute Query (using $offset and $limit values) //
*
* $pager->printPages();
* ==========================================
*
*/
// Should we use the Link class?
$use_link = true;
if ($use_link) {
//include_once('Link.class.php');
$link = new Link();
}
class Pager {
// Application set variables
var $cur_page;
var $query_string;
var $tot_pages;
var $page_var;
var $limit_var;
// Application variables with user modify option
var $limit;
var $tot_records;
var $print_limit_select = true;
// User modifiable variables
var $prev_link = '&laquo;';
var $next_link = '&raquo;';
var $limits = array(10, 25, 50, 100);
var $view_pages = 3;
var $table_width = '100%';
var $table_align = 'center';
var $link_class;
var $tb_class;
var $tb_style;
var $text_class;
var $text_style;
/**
* Pager Constructor
* Sets up Pager variables and initializes values
*
* - All parameters are optional and have default values of:
* $tot_records = 0
* $limit = 25
* $page_var = "page"
* $limit_var = "limit"
*
* @param int $tot_records optional total number of records
* @param int $limit optional limit of recordset
* @param string $page_var optional name of var to use in querystring for page value
* @param string $limit_var optional name of var to use in querystring for limit value
*/
function Pager($tot_records=0, $limit=25, $page_var='page', $limit_var='limit') {
$this->tot_records = $tot_records;
$this->limit = $limit;
$this->page_var = $page_var;
$this->limit_var = $limit_var;
// Call all system setter functions
$this->initCurPage();
$this->initLimit();
$this->initTotPages();
$this->initQueryString();
}
/**
* Print out the pages as links
* Prints out a table of all the pages as links
* and a jump menu to change the number of records
* per page
*
* setCurPage() and setTotPages() must be called
* before this function can be called
*
* @param none
* @see printPrev()
* @see printLink()
* @see printPage()
* @see printNext()
* @see printTotal()
* @see startTable()
* @see startPagesCell()
* @see endPagesCell()
* @see printLimitCell()
* @see endTable()
*/
function printPages() {
$p = $this->view_pages; // How many pages to view
$cur_page = $this->cur_page; // Current page
$tot_pages = $this->tot_pages; // Total pages
// Open up the HTML table
$this->startTable();
// Open up cell for page links
$this->startPagesCell();
// Page to start printing bulk of links
$start = ($cur_page > $p) ? $cur_page - $p : 1;
// Page to end printing bulk of links
$end = ($cur_page + $p) < $tot_pages ? $cur_page + $p : $tot_pages;
// Print 'prev' link
$this->printPrev();
// Print link to first page, if not already there
if ($start != 1) {
$this->printPage(1);
}
// Print '...' if necessary (with link to center page)
if ($cur_page > $p+2) {
$this->printLink(ceil( ($start+1)/2 ), '...');
}
// Print links to pages before current page (up to first page)
// Print current page
// Print links to pages after current page (up to last page)
for ($pg = $start; $pg <= $end; $pg++) {
$this->printPage($pg);
}
// Print '...' if necessary (with link to center page)
if ( $cur_page < ($tot_pages - ($p+1)) ) {
$this->printLink(ceil( ($tot_pages+$end)/2 ), '...' );
}
// Print link to last page, if not already there
if ($end != $tot_pages) {
$this->printPage($tot_pages);
}
// Print 'next' link
$this->printNext();
// Print total records
$this->printTotal();
// Close page links cell
$this->endPagesCell();
// Print out cell with limit jump menu
if ($this->print_limit_select) { $this->printLimitCell(); }
// Close table
$this->endTable();
}
//-----------------------------------------
// Application setter functions
//-----------------------------------------
/**
* Sets current page variable
* @param none
*/
function initCurPage() {
$this->cur_page = isset($_GET[$this->page_var]) ? intval($_GET[$this->page_var]) : 1;
}
/**
* Sets the limit variable if it is passed from querystring
* @param none
*/
function initLimit() {
if (isset($_GET[$this->limit_var]))
$this->limit = intval($_GET[$this->limit_var]);
if (isset($_POST[$this->limit_var]))
$this->limit = intval($_POST[$this->limit_var]);
}
/**
* Pull page information from query string and set $query_string
*
* setLimit() must be called before this function for it to work correctly
* @param none
*/
function initQueryString() {
if (isset($_SERVER['QUERY_STRING'])) {
// Remove page from query string and convert all "&" to "&amp;"
$this->query_string = str_replace('&', '&amp;', preg_replace("/(&|&amp;)?$this->page_var=\d*/",'',$_SERVER['QUERY_STRING']));
// Insert limit into querystring, if it's not there
if ( !strstr($this->query_string, "$this->limit_var=") )
$this->query_string .= "&amp;$this->limit_var=" . $this->limit;
}
else {
$this->query_string = '';
}
}
/**
* Sets the tot_pages variable
*
* tot_records must be set and setLimit() must be called before
* this function can be called
*
* @param none
*/
function initTotPages() {
$this->tot_pages = ceil($this->tot_records/$this->limit);
}
//===========================================
//-------------------------------------------
// Output functions
//-------------------------------------------
/**
* Print out link to a page
* @param int $p page number to print
*/
function printPage($p) {
if ($p == $this->cur_page) {
echo " <b>[$p]</b> ";
}
else {
$this->printLink($p, $p);
}
}
/**
* Print 'prev' link, if necessary
* @param none
*/
function printPrev() {
$cur_page = $this->cur_page;
if ($cur_page > 1)
$this->printLink($cur_page-1, $this->prev_link);
}
/**
* Print 'next' link, if necessary
* @param none
*/
function printNext() {
$cur_page = $this->cur_page;
if ($cur_page < $this->tot_pages && $this->tot_records > 0)
$this->printLink($cur_page+1, $this->next_link);
}
/**
* Print out link to a certain page
* @param int $page page to link to
* @param string $text link text
*/
function printLink($page, $text) {
global $link;
global $use_link;
if ($use_link) {
$link->doLink(
$_SERVER['PHP_SELF'] . "?$this->page_var=$page&amp;" . $this->query_string . '"',
$text,
$this->link_class,
'',
'Page ' . $page
);
}
else {
echo ' <a href="' . $_SERVER['PHP_SELF'] . "?$this->page_var=$page&amp;" . $this->query_string . '"'
. ' class="$this->class"'
. '>'
. $text . '</a> ';
}
}
/**
* Prints out opening table tag
* @param none
*/
function startTable() {
echo "<table align=\"$this->table_align\" border=\"0\" cellpadding=\"0\" cellspacing=\"0\" width=\"$this->table_width\">\n"
. "<tr class=\"$this->text_class\" style=\"$this->text_style\">\n";
}
/**
* Begins cell containing page links
* @param none
*/
function startPagesCell() {
echo '<td>' . translate('Page') . ' ';
}
/**
* Closes cell containing page links
* @param none
*/
function endPagesCell() {
echo '</td>';
}
/**
* Prints out cell containing limit jump menu
* @param none
*/
function printLimitCell() {
$limits = $this->limits;
echo "<td align=\"right\">\n"
. "<form name=\"limit_jump\" id=\"limit_jump\" method=\"post\" action=\"" . $_SERVER['PHP_SELF'] . "?" . preg_replace("/(&|&amp;)?$this->limit_var=\d*/", "", $this->query_string) . "\" style=\"margin: 0px;\">\n"
. translate('Per page') . " <select name=\"$this->limit_var\" onchange=\"document.limit_jump.submit();\" class=\"$this->tb_class\" style=\"$this->tb_style\">\n";
for ($i = 0; $i < count($limits); $i++) {
echo '<option value="' . $limits[$i] . '"';
if ($limits[$i] == $this->limit)
echo ' selected="selected"';
echo '>' . $limits[$i] . "</option>\n";
}
echo "</select>\n"
. "</form>\n"
. "</td>\n";
}
/**
* Prints out the closing row and table HTML tags
* @param none
*/
function endTable() {
echo "</tr>\n</table>\n";
}
/**
* Prints out total number of records returned
* @param none
*/
function printTotal() {
echo '(' . $this->tot_records . ')';
}
//============================================
//--------------------------------------------
// User-Modified Setter Functions
//--------------------------------------------
/**
* Sets the total records for this recordset
*
* - Default setting is 0 (in constructor)
*
* @param int $tot total number of records
*/
function setTotRecords($tot) {
$this->tot_records = intval($tot);
// Call initTotPages again to reset paging
$this->initTotPages();
}
/**
* Sets the default recordset limit
* Note: A limit value set in the querystring
* or in a post value will override this
*
* - Default setting is 25 (in constructor)
*
* @param int $limit new limit value
*/
function setLimit($limit) {
$this->limit = intval($limit);
// Call initLimit() to reinitialzie limit
$this->initLimit();
}
/**
* Sets the text for 'prev' link
*
* - Default setting is "&laquo;"
*
* @param string $text link text
*/
function setPrevLink($text) {
$this->prev_link = trim($text);
}
/**
* Sets the text for 'next' link
*
* - Default setting is "&raquo;"
*
* @param string $text link text
*/
function setNextLink($text) {
$this->next_link = trim($text);
}
/**
* Sets the value of view_pages
* How many pages to print on either side of
* the currently viewed page number
*
* - Default setting is 3
*
* @param int $view_page how many pages to view
*/
function setViewPages($view_page) {
$this->view_pages = intval($view_page);
}
/**
* Sets the array of limits
* Pass in an array of ints to use
* for the limit pull down menu
*
* - Default setting is (10, 25, 50, 100)
*
* @param int $new_limits array of limits
*/
function setLimits($new_limits) {
$this->limits = $new_limits;
}
/**
* Sets the name of the class to be used for the links
*
* - Default setting is null
*
* @param string $link_class name of class
*/
function setLinkClass($link_class) {
$this->link_class = $link_class;
}
/**
* Sets the name of the class to be used for the pull down box
*
* - Default setting is null
*
* @param string $tb_class name of class
*/
function setTbClass($tb_class) {
$this->tb_class = $tb_class;
}
/**
* Sets the inline style of the limit jump menu
* This setting overrides the tb_class value
*
* - Default setting is null
* @param string $tb_style style of limit jump menu box
*/
function setTbStyle($tb_style) {
$this->tb_style = $tb_style;
}
/**
* Sets the name of the class to be used for the text
* ie) "Page:" and "Per page:"
* Should be used to modify all paging text font -amily, size, etc
*
* - Default setting is null
*
* @param string $text_class name of class
*/
function setTextClass($text_class) {
$this->text_class = $text_class;
}
/**
* Sets the inline style to be used for the text
* Should be used to modifiy all paging text font-family, size, etc
* This will override the text_class setting
*
* - Default setting is null
*
* @param string $text_style style to use for the text
*/
function setTextStyle($text_style) {
$this->text_style = $text_style;
}
/**
* Sets the width of the table bounding the pages/jump box
*
* - Default setting is "100%"
*
* @param string $table_width width of table
*/
function setTableWidth($table_width) {
$this->table_width = $table_width;
}
/**
* Sets the horizontial alignment of the table bounding the paging
*
* - Default setting is "center"
*
* @param string $table_align alignment value for table align
*/
function setTableAlign($table_align) {
$this->table_align = $table_align;
}
/**
* Sets the page variable name for the querystring
* @param string $page_var page variable name
*/
function setPageVar($page_var) {
$this->page_var = $page_var;
}
/**
* Sets the limit variable name for the querystring
* @param string $limit_var limit variable name
*/
function setLimitVar($limit_var) {
$this->limit_var = $limit_var;
}
/**
* Sets the print_limit_select variable to decide if we should show the limit select pulldown
* @param bool $view_limit_select if we should show the select pulldown or not
*/
function setViewLimitSelect($view_limit_select) {
$this->print_limit_select = $view_limit_select;
}
//============================================
//--------------------------------------------
// Getter methods
//--------------------------------------------
/**
* Returns the recordset offset
* @param none
* @return integer recorset offset
*/
function getOffset() {
return $this->limit * $this->cur_page - $this->limit;
}
/**
* Returns the total number of pages
* @param none
* @return integer number of pages total
*/
function getTotPages() {
return $this->tot_pages;
}
/**
* Returns the current page number
* @param none
* @return integer current page number
*/
function getPageNum() {
return $this->cur_page;
}
/**
* Returns the current recordset limit
* @param none
* @return integer recordset limit
*/
function getLimit() {
return $this->limit;
}
/**
* Returns value of previous link text
* @param none
* @return string previous link text
*/
function getPrevLink() {
return $this->prev_link;
}
/**
* Returns value of next link text
* @param none
* @return string next link text
*/
function getNextLink() {
return $this->next_link;
}
/**
* Returns the name used for the page querystring variable
* @param none
* @return string page variable name
*/
function getPageVar() {
return $this->page_var;
}
/**
* Returns the name used for the limit querystring variable
* @param none
* @return string limit variable name
*/
function getLimitVar() {
return $this->limit_var;
}
//===========================================
// End class
}
?>

362
lib/Quarantine.lib.php Normal file
View File

@ -0,0 +1,362 @@
<?php
/**
* Quarantine lib
* @author Samuel Tran <stran2005@users.sourceforge.net>
* @author Brian Wong <bwsource@users.sourceforge.net>
* @author Nicolas Peyrussie <peyrouz@users.sourceforge.net>
* @version 04-03-07
*
* Copyright (C) 2005 - 2007 MailZu
* License: GPL, see LICENSE
*/
/**
* Base directory of application
*/
@define('BASE_DIR', dirname(__FILE__) . '/..');
/**
* CmnFns class
*/
include_once('CmnFns.class.php');
/**
* Include AmavisdEngine class
*/
include_once('lib/AmavisdEngine.class.php');
/**
* PHPMailer
*/
include_once('lib/PHPMailer.class.php');
/**
* Provide quarantine related functions
*/
/**
* Release messages function
* @param array $emailaddresses recipient email address(es)
* @param array $mail_id_array containing mail_id of messages to be released
* @result return array of messages whose release failed
*/
function releaseMessages($emailaddresses, $mail_id_array) {
/*** Array pertaining to the release of messages ***/
// This is an array of array, the key being the $mail_id
// and the value being an array containing all the messages info (time, subject, ...) and also the release status.
// The reason for this is that we want to keep the ordering of the messages selected for release.
$release_messages = array();
// This is an array of array, the key being the host
// and the value being an array containing all the release info such as secret_id (one row per message)
$hosts = array();
/*** Variables pertaining to the request of release ***/
// This array contains the messages that the logged in user wants the Admins to release
$release_req_messages = array();
// Counter for the number of release requests
$j = 0;
$nb_failure = 0;
$db = new DBEngine();
// Set autocommit to false to improve speed of 'RS' flag set up
$result = $db->db->autoCommit(false);
$db->check_for_error($result, 'PEAR DB autoCommit(false)');
// Fill the arrays
foreach ($mail_id_array as $mail_id_recip) {
// Get mail_id and recipient email address
$temp = preg_split('/_/', $mail_id_recip, 2);
$mail_id = $temp[0];
$recip_email = $temp[1];
// Check if logged in user is admin or logged in user is trying to release his own messages
if ( Auth::isMailAdmin() || in_array($recip_email, $emailaddresses) )
$result = $db->get_message($recip_email, $mail_id);
else
continue;
$rs = $result[0];
// if content type is 'B' or 'V' and the logged in user is not admin
// add message to array of release request
if ( in_array($rs['content'], array( 'B', 'V')) && ! Auth::isMailAdmin() ) {
$release_req_messages[ $j ] = array(
"mail_id" => $mail_id,
"from_addr" => $rs[ 'from_addr' ],
"subject" => $rs[ 'subject' ],
"time_num" => $rs[ 'time_num' ],
"spam_level" => $rs[ 'spam_level' ],
"content" => $rs['content']
);
// Try to update the RS flag to 'p' for pending
if ( ! $db->update_msgrcpt_rs($mail_id, $recip_email, 'p') ) {
$release_req_messages[ $j ]["status"] = "Error: " . $db->get_err();
} else {
$release_req_messages[ $j ]["status"] = "Pending";
}
$j++;
// Other cases where:
// - content type is 'B' or 'V' but the logged in user is admin, therefore allowed to release message
// - content type is 'S' or 'H'
} else {
// add message to be released to $hosts array
$release_messages[ $mail_id_recip ] = array(
"mail_id" => $mail_id,
"time" => $rs['time_num'],
"subject" => $rs['subject'],
"from_addr" => $rs['from_addr'],
"spam_level" => $rs['spam_level'],
"content" => $rs['content'],
);
$hosts[ $rs['host'] ][ $mail_id_recip ] = array(
"secret_id" => $rs['secret_id'],
"quar_type" => $rs['quar_type'],
"quar_loc" => $rs['quar_loc'],
"recip_email" => $rs['email']
);
}
}
global $conf;
// If release request needs to be sent to Admins
if ( is_array($release_req_messages) && !empty($release_req_messages)
&& $conf['app']['notifyAdmin'] )
sendMailToAdmin(translate('Request release'), $release_req_messages);
// If release needs to be done
if ( is_array($hosts) && !empty($hosts) ) {
// For each host create socket, connect and release all messages pertaining to that host
foreach ($hosts as $host => $message_info ) {
// Create new TCP/IP socket and try to connect to $host using this socket
$am = new AmavisdEngine($host);
if ( ! $am->connected )
foreach ($message_info as $mail_id_recip => $release_info) {
$release_messages[ $mail_id_recip ][ 'error_code' ] = 1;
$release_messages[ $mail_id_recip ][ 'status' ] = $am->last_error;
$nb_failure++;
}
else {
foreach ($message_info as $mail_id_recip => $release_info) {
$socket_binding_result = $am->release_message(
$release_messages[ $mail_id_recip ][ 'mail_id' ],
$release_info[ 'secret_id' ],
$release_info[ 'recip_email' ],
$release_info[ 'quar_type' ],
$release_info[ 'quar_loc' ]
);
if (preg_match('/^setreply=250/', $socket_binding_result)) {
if ( $db->update_msgrcpt_rs($release_messages[ $mail_id_recip ][ 'mail_id' ], $release_info[ 'recip_email' ], 'R') ) {
$release_messages[ $mail_id_recip ][ 'error_code' ] = "0";
CmnFns::write_log('Message Released [' . $release_messages[ $mail_id_recip ][ 'content' ] . ']: '
. $release_messages[ $mail_id_recip ][ 'mail_id' ], $_SESSION['sessionID']);
} else {
$release_messages[ $mail_id_recip ][ 'error_code' ] = 2;
$release_messages[ $mail_id_recip ][ 'status' ] = "Error: " . $db->get_err();
$nb_failure++;
}
} else {
$release_messages[ $mail_id_recip ][ 'error_code' ] = 3;
$release_messages[ $mail_id_recip ][ 'status' ] = $am->last_error;
$nb_failure++;
}
}
// Shuting down and closing socket
$am->disconnect();
}
}
}
// Commit, then set autocommit back to true
$result = $db->db->commit();
$db->check_for_error($result, 'PEAR DB commit()');
$result = $db->db->autoCommit(true);
$db->check_for_error($result, 'PEAR DB autoCommit(true)');
// Build array of messages whose release failed
$failed_array = array();
$i = 0;
if ( $nb_failure > 0 ) {
foreach ($mail_id_array as $mail_id_recip) {
if ($release_messages[ $mail_id_recip ][ 'error_code' ] != 0) {
$failed_array[ $i ] = array(
"mail_id" => $release_messages[ $mail_id_recip ][ 'mail_id' ],
"from_addr" => $release_messages[ $mail_id_recip ][ 'from_addr' ],
"subject" => $release_messages[ $mail_id_recip ][ 'subject' ],
"time_num" => $release_messages[ $mail_id_recip ][ 'time' ],
"spam_level" => $release_messages[ $mail_id_recip ][ 'spam_level' ],
"content" => $release_messages[ $mail_id_recip ][ 'content' ],
"status" => $release_messages[ $mail_id_recip ][ 'status' ]
);
CmnFns::write_log($release_messages[ $mail_id_recip ][ 'status' ], $_SESSION['sessionID']);
$i++;
}
}
}
// Return array of messages whose release failed
return $failed_array;
}
/**
* Update messages function
* @param string $content_type 'B', 'S', ...
* @param array $emailaddresses recipient email address(es)
* @param array $mail_id_array containing mail_id of messages to be deleted
* @param bool $all false (default) or true, if true all messages will be deleted
* @result return array of messages whose release failed
*/
function updateMessages($flag, $content_type, $emailaddresses, $mail_id_array, $all = false) {
$result_array = array();
$db = new DBEngine();
// Set autocommit to false to improve speed of $flag set
$result = $db->db->autoCommit(false);
$db->check_for_error($result, 'PEAR DB autoCommit(false)');
if ( $all ) {
$res = $db->get_user_messages($content_type, $emailaddresses, 'msgs.time_num', 'DESC', '', false, 0, 0, true);
for ($i = 0; is_array($res) && $i < count($res); $i++) {
$rs = $res[$i];
if ( Auth::isMailAdmin() || in_array($rs['email'], $emailaddresses) ) {
if ( ! $db->update_msgrcpt_rs($rs['mail_id'], $rs['email'], $flag ) ) {
$rs = $result[0];
$result_array[ $i ] = array(
"mail_id" => $mail_id,
"from_addr" => $rs[ 'from_addr' ],
"subject" => $rs[ 'subject' ],
"time_num" => $rs[ 'time_num' ],
"spam_level" => $rs[ 'spam_level' ],
"status" => "Error: " . $db->get_err()
);
}
} else {
continue;
}
}
} else {
$i = 0;
foreach ($mail_id_array as $mail_id_recip) {
// Get mail_id and recipient email address
$temp = preg_split('/_/', $mail_id_recip, 2);
$mail_id = $temp[0];
$recip_email = $temp[1];
// Check if logged in user is admin or logged in user is trying to delete his own messages
if ( Auth::isMailAdmin() || in_array($recip_email, $emailaddresses) ) {
$result = $db->get_message($recip_email, $mail_id);
} else {
continue;
}
if ( ! $db->update_msgrcpt_rs($mail_id, $recip_email, $flag) ) {
$rs = $result[0];
$result_array[ $i ] = array(
"mail_id" => $mail_id,
"from_addr" => $rs[ 'from_addr' ],
"subject" => $rs[ 'subject' ],
"time_num" => $rs[ 'time_num' ],
"spam_level" => $rs[ 'spam_level' ],
"status" => "Error: " . $db->get_err()
);
$i++;
}
}
}
// Commit, then set autocommit back to true
$result = $db->db->commit();
$db->check_for_error($result, 'PEAR DB commit()');
$result = $db->db->autoCommit(true);
$db->check_for_error($result, 'PEAR DB autoCommit(true)');
// Return array of messages whose release failed
return $result_array;
}
/**
* Function that sends:
* - an error report if $action = 'Release', 'Delete' or 'Delete All'
* - an request if $action = 'Request release'
* to $conf['app']['adminEmail']
* @param string $action 'Release', 'Delete', 'Delete All', 'Request release'
* @param $messages_array array containing messages info
*/
function sendMailToAdmin($myaction, $messages_array) {
global $conf;
$title = $conf['app']['title'];
$adminEmail = $conf['app']['adminEmail'];
$sub = "[" . $title . "] Notification from '" . $_SESSION['sessionID'] . "'";
$msg = "Mail notification sent by '" . $_SESSION['sessionID'] . "' <" . $_SESSION['sessionMail'][0] . ">.\r\n\r\n";
switch ( $myaction ) {
case translate('Release'):
case translate('Release/Request release'):
$msg .= translate('A problem occured when trying to release the following messages') . ":\r\n\r\n";
break;
case translate('Request release'):
$msg .= translate('Please release the following messages') . ":\r\n\r\n";
break;
case translate('Delete'):
case translate('Delete All'):
$msg .= translate('A problem occured when trying to delete the following messages') . ":\r\n\r\n";
break;
default:
CmnFns::do_error_box(translate('Unknown action type'), '');
}
for ($i = 0; is_array($messages_array) && $i < count($messages_array); $i++) {
$rs = $messages_array[$i];
$msg .= "Message #" . ($i+1) . ":\r\n";
$msg .= "\tmail_id = " . $rs['mail_id'] . "\r\n";
$msg .= "\t" . translate('From') . " = " . $rs['from_addr'] . "\r\n";
$msg .= "\t" . translate('Subject') . " = " . $rs['subject'] . "\r\n";
$msg .= "\t" . translate('Date') . " = " . CmnFns::formatDateTime($rs['time_num']) . "\r\n";
$msg .= "\t" . translate('Score') . " = " . $rs['spam_level'] . "\r\n";
$msg .= "\t" . translate('Status') . " = " . $rs['status'] . "\r\n";
$msg .= "\t" . translate('Content Type') . " = " . $rs['content'] . "\r\n\r\n";
}
// Send email
$mailer = new PHPMailer();
if ( is_array($adminEmail) ) {
foreach ($adminEmail as $email) {
$mailer->AddAddress($email, '');
}
} else {
$mailer->AddAddress($adminEmail, '');
}
$mailer->FromName = $_SESSION['sessionID'];
$mailer->From = $_SESSION['sessionMail'][0];
$mailer->Subject = $sub;
$mailer->Body = $msg;
$mailer->Send();
return true;
}
?>

1039
lib/Smtp.class.php Normal file

File diff suppressed because it is too large Load Diff

194
lib/Template.class.php Normal file
View File

@ -0,0 +1,194 @@
<?php
/**
* This file provides output functions
* @author Nick Korbel <lqqkout13@users.sourceforge.net>
* @version 10-21-04
* @package phpScheduleIt
*
* Copyright (C) 2003 - 2005 phpScheduleIt
* License: GPL, see LICENSE
*/
/**
* Base directory of application
*/
@define('BASE_DIR', dirname(__FILE__) . '/..');
/**
* Include Auth class
*/
include_once('Auth.class.php');
/**
* Provides functions for outputting template HTML
*/
class Template {
var $title;
var $link;
var $dir_path;
/**
* Set the page's title
* @param string $title title of page
* @param int $depth depth of the current page relative to phpScheduleIt root
*/
function Template($title = '', $depth = 0) {
global $conf;
$this->title = (!empty($title)) ? $title : $conf['ui']['welcome'];
$this->dir_path = str_repeat('../', $depth);
$this->link = CmnFns::getNewLink();
//Auth::Auth(); // Starts session
}
/**
* Print all XHTML headers
* This function prints the HTML header code, CSS link, and JavaScript link
*
* DOCTYPE is XHTML 1.0 Transitional
* @param none
*/
function printHTMLHeader() {
global $conf;
global $languages;
global $lang;
global $charset;
$path = $this->dir_path;
echo "<?xml version=\"1.0\" encoding=\"$charset\"?" . ">\n";
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<?=$languages[$lang][2]?>" lang="<?=$languages[$lang][2]?>">
<head>
<title>
<?=$this->title?>
</title>
<meta http-equiv="Content-Type" content="text/html; charset=<?=$charset?>" />
<link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon" />
<script language="JavaScript" type="text/javascript" src="<?=$path?>functions.js"></script>
<!--<link href="<?=$path?>css.css" rel="stylesheet" type="text/css" />-->
<style type="text/css">
@import url(<?=$path?>css.css);
</style>
</head>
<body>
<?
}
/**
* Print welcome header message
* This function prints out a table welcoming
* the user. It prints links to My Control Panel,
* Log Out, Help, and Email Admin.
* If the user is the admin, an admin banner will
* show up
* @global $conf
*/
function printWelcome() {
global $conf;
// Print out logoImage if it exists
echo (!empty($conf['ui']['logoImage']))
? '<div align="left"><img src="' . $conf['ui']['logoImage'] . '" alt="logo" vspace="5" /></div>'
: '';
?>
<table width="100%" border="0" cellspacing="0" cellpadding="5" class="mainBorder">
<tr>
<td class="mainBkgrdClr">
<h4 class="welcomeBack">
<?=
translate('Welcome Back', array($_SESSION['sessionName'], 1));
// Notify if the person logged in is admin
echo (Auth::isMailAdmin() ? ' (' . translate('Administrator') . ')' : '');
?>
</h4>
<!--<p>
<? $this->link->doLink($this->dir_path . 'index.php?logout=true', translate('Log Out')) ?>
|
<? $this->link->doLink($this->dir_path . 'summary.php', translate('My Control Panel')) ?>
</p>-->
</td>
<td class="mainBkgrdClr" valign="top">
<div align="right">
<p>
<?= translate_date('header', mktime());?>
</p>
<!--<p>
<? $this->link->doLink('javascript: help();', translate('Help')) ?>
</p>-->
</div>
</td>
</tr>
</table>
<?
}
/**
* Start main HTML table
* @param none
*/
function startMain() {
?>
<p>&nbsp;</p>
<table width="100%" border="0" cellspacing="0" cellpadding="10" style="border: solid #CCCCCC 1px;">
<tr>
<td bgcolor="#FAFAFA">
<?
}
/**
* End main HTML table
* @param none
*/
function endMain() {
?>
</td>
</tr>
</table>
<?
}
/**
* Print HTML footer
* This function prints out a tech email
* link and closes off HTML page
* @global $conf
*/
function printHTMLFooter() {
global $conf;
?>
<p align="center"><a href="http://www.mailzu.net"><?=$conf['app']['title']?> v<?=$conf['app']['version']?></a></p>
</body>
</html>
<?
}
/**
* Sets the link class variable to reference a new Link object
* @param none
*/
function set_link() {
$this->link = CmnFns::getNewLink();
}
/**
* Returns the link object
* @param none
* @return link object for this class
*/
function get_link() {
return $this->link;
}
/**
* Sets a new title for the template page
* @param string $title title of page
*/
function set_title($title) {
$this->title = $title;
}
}
?>

1021
lib/htmlfilter.php Normal file

File diff suppressed because it is too large Load Diff

0
lib/index.html Normal file
View File

1489
lib/pear/DB.php Normal file

File diff suppressed because it is too large Load Diff

2257
lib/pear/DB/common.php Normal file

File diff suppressed because it is too large Load Diff

510
lib/pear/DB/dbase.php Normal file
View File

@ -0,0 +1,510 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's dbase extension
* for interacting with dBase databases
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Tomas V.V. Cox <cox@idecnet.com>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: dbase.php,v 1.42 2007/01/11 07:43:09 aharvey Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's dbase extension
* for interacting with dBase databases
*
* These methods overload the ones declared in DB_common.
*
* @category Database
* @package DB
* @author Tomas V.V. Cox <cox@idecnet.com>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.11
* @link http://pear.php.net/package/DB
*/
class DB_dbase extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'dbase';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'dbase';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* @var array
*/
var $features = array(
'limit' => false,
'new_link' => false,
'numrows' => true,
'pconnect' => false,
'prepare' => false,
'ssl' => false,
'transactions' => false,
);
/**
* A mapping of native error codes to DB error codes
* @var array
*/
var $errorcode_map = array(
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
/**
* A means of emulating result resources
* @var array
*/
var $res_row = array();
/**
* The quantity of results so far
*
* For emulating result resources.
*
* @var integer
*/
var $result = 0;
/**
* Maps dbase data type id's to human readable strings
*
* The human readable values are based on the output of PHP's
* dbase_get_header_info() function.
*
* @var array
* @since Property available since Release 1.7.0
*/
var $types = array(
'C' => 'character',
'D' => 'date',
'L' => 'boolean',
'M' => 'memo',
'N' => 'number',
);
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_dbase()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database and create it if it doesn't exist
*
* Don't call this method directly. Use DB::connect() instead.
*
* PEAR DB's dbase driver supports the following extra DSN options:
* + mode An integer specifying the read/write mode to use
* (0 = read only, 1 = write only, 2 = read/write).
* Available since PEAR DB 1.7.0.
* + fields An array of arrays that PHP's dbase_create() function needs
* to create a new database. This information is used if the
* dBase file specified in the "database" segment of the DSN
* does not exist. For more info, see the PHP manual's
* {@link http://php.net/dbase_create dbase_create()} page.
* Available since PEAR DB 1.7.0.
*
* Example of how to connect and establish a new dBase file if necessary:
* <code>
* require_once 'DB.php';
*
* $dsn = array(
* 'phptype' => 'dbase',
* 'database' => '/path/and/name/of/dbase/file',
* 'mode' => 2,
* 'fields' => array(
* array('a', 'N', 5, 0),
* array('b', 'C', 40),
* array('c', 'C', 255),
* array('d', 'C', 20),
* ),
* );
* $options = array(
* 'debug' => 2,
* 'portability' => DB_PORTABILITY_ALL,
* );
*
* $db =& DB::connect($dsn, $options);
* if (PEAR::isError($db)) {
* die($db->getMessage());
* }
* </code>
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('dbase')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
/*
* Turn track_errors on for entire script since $php_errormsg
* is the only way to find errors from the dbase extension.
*/
@ini_set('track_errors', 1);
$php_errormsg = '';
if (!file_exists($dsn['database'])) {
$this->dsn['mode'] = 2;
if (empty($dsn['fields']) || !is_array($dsn['fields'])) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
'the dbase file does not exist and '
. 'it could not be created because '
. 'the "fields" element of the DSN '
. 'is not properly set');
}
$this->connection = @dbase_create($dsn['database'],
$dsn['fields']);
if (!$this->connection) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
'the dbase file does not exist and '
. 'the attempt to create it failed: '
. $php_errormsg);
}
} else {
if (!isset($this->dsn['mode'])) {
$this->dsn['mode'] = 0;
}
$this->connection = @dbase_open($dsn['database'],
$this->dsn['mode']);
if (!$this->connection) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
$php_errormsg);
}
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$ret = @dbase_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ &query()
function &query($query = null)
{
// emulate result resources
$this->res_row[(int)$this->result] = 0;
$tmp =& new DB_result($this, $this->result++);
return $tmp;
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
if ($rownum === null) {
$rownum = $this->res_row[(int)$result]++;
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$arr = @dbase_get_record_with_names($this->connection, $rownum);
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$arr = @dbase_get_record($this->connection, $rownum);
}
if (!$arr) {
return null;
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set.
*
* This method is a no-op for dbase, as there aren't result resources in
* the same sense as most other database backends.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult($result)
{
return true;
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($foo)
{
return @dbase_numfields($this->connection);
}
// }}}
// {{{ numRows()
/**
* Gets the number of rows in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numRows() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of rows. A DB_Error object on failure.
*
* @see DB_result::numRows()
*/
function numRows($foo)
{
return @dbase_numrecords($this->connection);
}
// }}}
// {{{ quoteBoolean()
/**
* Formats a boolean value for use within a query in a locale-independent
* manner.
*
* @param boolean the boolean value to be quoted.
* @return string the quoted string.
* @see DB_common::quoteSmart()
* @since Method available since release 1.7.8.
*/
function quoteBoolean($boolean) {
return $boolean ? 'T' : 'F';
}
// }}}
// {{{ tableInfo()
/**
* Returns information about the current database
*
* @param mixed $result THIS IS UNUSED IN DBASE. The current database
* is examined regardless of what is provided here.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::tableInfo()
* @since Method available since Release 1.7.0
*/
function tableInfo($result = null, $mode = null)
{
if (function_exists('dbase_get_header_info')) {
$id = @dbase_get_header_info($this->connection);
if (!$id && $php_errormsg) {
return $this->raiseError(DB_ERROR,
null, null, null,
$php_errormsg);
}
} else {
/*
* This segment for PHP 4 is loosely based on code by
* Hadi Rusiah <deegos@yahoo.com> in the comments on
* the dBase reference page in the PHP manual.
*/
$db = @fopen($this->dsn['database'], 'r');
if (!$db) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
$php_errormsg);
}
$id = array();
$i = 0;
$line = fread($db, 32);
while (!feof($db)) {
$line = fread($db, 32);
if (substr($line, 0, 1) == chr(13)) {
break;
} else {
$pos = strpos(substr($line, 0, 10), chr(0));
$pos = ($pos == 0 ? 10 : $pos);
$id[$i] = array(
'name' => substr($line, 0, $pos),
'type' => $this->types[substr($line, 11, 1)],
'length' => ord(substr($line, 16, 1)),
'precision' => ord(substr($line, 17, 1)),
);
}
$i++;
}
fclose($db);
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$res = array();
$count = count($id);
if ($mode) {
$res['num_fields'] = $count;
}
for ($i = 0; $i < $count; $i++) {
$res[$i] = array(
'table' => $this->dsn['database'],
'name' => $case_func($id[$i]['name']),
'type' => $id[$i]['type'],
'len' => $id[$i]['length'],
'flags' => ''
);
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
return $res;
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>

769
lib/pear/DB/fbsql.php Normal file
View File

@ -0,0 +1,769 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's fbsql extension
* for interacting with FrontBase databases
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Frank M. Kromann <frank@frontbase.com>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: fbsql.php,v 1.87 2007/03/28 08:02:35 aharvey Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's fbsql extension
* for interacting with FrontBase databases
*
* These methods overload the ones declared in DB_common.
*
* @category Database
* @package DB
* @author Frank M. Kromann <frank@frontbase.com>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.11
* @link http://pear.php.net/package/DB
* @since Class functional since Release 1.7.0
*/
class DB_fbsql extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'fbsql';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'fbsql';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* @var array
*/
var $features = array(
'limit' => 'alter',
'new_link' => false,
'numrows' => true,
'pconnect' => true,
'prepare' => false,
'ssl' => false,
'transactions' => true,
);
/**
* A mapping of native error codes to DB error codes
* @var array
*/
var $errorcode_map = array(
22 => DB_ERROR_SYNTAX,
85 => DB_ERROR_ALREADY_EXISTS,
108 => DB_ERROR_SYNTAX,
116 => DB_ERROR_NOSUCHTABLE,
124 => DB_ERROR_VALUE_COUNT_ON_ROW,
215 => DB_ERROR_NOSUCHFIELD,
217 => DB_ERROR_INVALID_NUMBER,
226 => DB_ERROR_NOSUCHFIELD,
231 => DB_ERROR_INVALID,
239 => DB_ERROR_TRUNCATED,
251 => DB_ERROR_SYNTAX,
266 => DB_ERROR_NOT_FOUND,
357 => DB_ERROR_CONSTRAINT_NOT_NULL,
358 => DB_ERROR_CONSTRAINT,
360 => DB_ERROR_CONSTRAINT,
361 => DB_ERROR_CONSTRAINT,
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_fbsql()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database server, log in and open the database
*
* Don't call this method directly. Use DB::connect() instead.
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('fbsql')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
$params = array(
$dsn['hostspec'] ? $dsn['hostspec'] : 'localhost',
$dsn['username'] ? $dsn['username'] : null,
$dsn['password'] ? $dsn['password'] : null,
);
$connect_function = $persistent ? 'fbsql_pconnect' : 'fbsql_connect';
$ini = ini_get('track_errors');
$php_errormsg = '';
if ($ini) {
$this->connection = @call_user_func_array($connect_function,
$params);
} else {
@ini_set('track_errors', 1);
$this->connection = @call_user_func_array($connect_function,
$params);
@ini_set('track_errors', $ini);
}
if (!$this->connection) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
$php_errormsg);
}
if ($dsn['database']) {
if (!@fbsql_select_db($dsn['database'], $this->connection)) {
return $this->fbsqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$ret = @fbsql_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Sends a query to the database server
*
* @param string the SQL query string
*
* @return mixed + a PHP result resrouce for successful SELECT queries
* + the DB_OK constant for other successful queries
* + a DB_Error object on failure
*/
function simpleQuery($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @fbsql_query("$query;", $this->connection);
if (!$result) {
return $this->fbsqlRaiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
if ($this->_checkManip($query)) {
return DB_OK;
}
return $result;
}
// }}}
// {{{ nextResult()
/**
* Move the internal fbsql result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return @fbsql_next_result($result);
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
if ($rownum !== null) {
if (!@fbsql_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$arr = @fbsql_fetch_array($result, FBSQL_ASSOC);
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$arr = @fbsql_fetch_row($result);
}
if (!$arr) {
return null;
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set
*
* This method is not meant to be called directly. Use
* DB_result::free() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult($result)
{
return is_resource($result) ? fbsql_free_result($result) : false;
}
// }}}
// {{{ autoCommit()
/**
* Enables or disables automatic commits
*
* @param bool $onoff true turns it on, false turns it off
*
* @return int DB_OK on success. A DB_Error object if the driver
* doesn't support auto-committing transactions.
*/
function autoCommit($onoff=false)
{
if ($onoff) {
$this->query("SET COMMIT TRUE");
} else {
$this->query("SET COMMIT FALSE");
}
}
// }}}
// {{{ commit()
/**
* Commits the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function commit()
{
@fbsql_commit($this->connection);
}
// }}}
// {{{ rollback()
/**
* Reverts the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function rollback()
{
@fbsql_rollback($this->connection);
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($result)
{
$cols = @fbsql_num_fields($result);
if (!$cols) {
return $this->fbsqlRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Gets the number of rows in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numRows() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of rows. A DB_Error object on failure.
*
* @see DB_result::numRows()
*/
function numRows($result)
{
$rows = @fbsql_num_rows($result);
if ($rows === null) {
return $this->fbsqlRaiseError();
}
return $rows;
}
// }}}
// {{{ affectedRows()
/**
* Determines the number of rows affected by a data maniuplation query
*
* 0 is returned for queries that don't manipulate data.
*
* @return int the number of rows. A DB_Error object on failure.
*/
function affectedRows()
{
if ($this->_last_query_manip) {
$result = @fbsql_affected_rows($this->connection);
} else {
$result = 0;
}
return $result;
}
// }}}
// {{{ nextId()
/**
* Returns the next free id in a sequence
*
* @param string $seq_name name of the sequence
* @param boolean $ondemand when true, the seqence is automatically
* created if it does not exist
*
* @return int the next id number in the sequence.
* A DB_Error object on failure.
*
* @see DB_common::nextID(), DB_common::getSequenceName(),
* DB_fbsql::createSequence(), DB_fbsql::dropSequence()
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
do {
$repeat = 0;
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query('SELECT UNIQUE FROM ' . $seqname);
$this->popErrorHandling();
if ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE) {
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $result;
}
} else {
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->fbsqlRaiseError();
}
$result->fetchInto($tmp, DB_FETCHMODE_ORDERED);
return $tmp[0];
}
/**
* Creates a new sequence
*
* @param string $seq_name name of the new sequence
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::createSequence(), DB_common::getSequenceName(),
* DB_fbsql::nextID(), DB_fbsql::dropSequence()
*/
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
$res = $this->query('CREATE TABLE ' . $seqname
. ' (id INTEGER NOT NULL,'
. ' PRIMARY KEY(id))');
if ($res) {
$res = $this->query('SET UNIQUE = 0 FOR ' . $seqname);
}
return $res;
}
// }}}
// {{{ dropSequence()
/**
* Deletes a sequence
*
* @param string $seq_name name of the sequence to be deleted
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::dropSequence(), DB_common::getSequenceName(),
* DB_fbsql::nextID(), DB_fbsql::createSequence()
*/
function dropSequence($seq_name)
{
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name)
. ' RESTRICT');
}
// }}}
// {{{ modifyLimitQuery()
/**
* Adds LIMIT clauses to a query string according to current DBMS standards
*
* @param string $query the query to modify
* @param int $from the row to start to fetching (0 = the first row)
* @param int $count the numbers of rows to fetch
* @param mixed $params array, string or numeric data to be used in
* execution of the statement. Quantity of items
* passed must match quantity of placeholders in
* query: meaning 1 placeholder for non-array
* parameters or 1 placeholder per array element.
*
* @return string the query string with LIMIT clauses added
*
* @access protected
*/
function modifyLimitQuery($query, $from, $count, $params = array())
{
if (DB::isManip($query) || $this->_next_query_manip) {
return preg_replace('/^([\s(])*SELECT/i',
"\\1SELECT TOP($count)", $query);
} else {
return preg_replace('/([\s(])*SELECT/i',
"\\1SELECT TOP($from, $count)", $query);
}
}
// }}}
// {{{ quoteBoolean()
/**
* Formats a boolean value for use within a query in a locale-independent
* manner.
*
* @param boolean the boolean value to be quoted.
* @return string the quoted string.
* @see DB_common::quoteSmart()
* @since Method available since release 1.7.8.
*/
function quoteBoolean($boolean) {
return $boolean ? 'TRUE' : 'FALSE';
}
// }}}
// {{{ quoteFloat()
/**
* Formats a float value for use within a query in a locale-independent
* manner.
*
* @param float the float value to be quoted.
* @return string the quoted string.
* @see DB_common::quoteSmart()
* @since Method available since release 1.7.8.
*/
function quoteFloat($float) {
return $this->escapeSimple(str_replace(',', '.', strval(floatval($float))));
}
// }}}
// {{{ fbsqlRaiseError()
/**
* Produces a DB_Error object regarding the current problem
*
* @param int $errno if the error is being manually raised pass a
* DB_ERROR* constant here. If this isn't passed
* the error information gathered from the DBMS.
*
* @return object the DB_Error object
*
* @see DB_common::raiseError(),
* DB_fbsql::errorNative(), DB_common::errorCode()
*/
function fbsqlRaiseError($errno = null)
{
if ($errno === null) {
$errno = $this->errorCode(fbsql_errno($this->connection));
}
return $this->raiseError($errno, null, null, null,
@fbsql_error($this->connection));
}
// }}}
// {{{ errorNative()
/**
* Gets the DBMS' native error code produced by the last query
*
* @return int the DBMS' error code
*/
function errorNative()
{
return @fbsql_errno($this->connection);
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* @param object|string $result DB_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::tableInfo()
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
/*
* Probably received a table name.
* Create a result resource identifier.
*/
$id = @fbsql_list_fields($this->dsn['database'],
$result, $this->connection);
$got_string = true;
} elseif (isset($result->result)) {
/*
* Probably received a result object.
* Extract the result resource identifier.
*/
$id = $result->result;
$got_string = false;
} else {
/*
* Probably received a result resource identifier.
* Copy it.
* Deprecated. Here for compatibility only.
*/
$id = $result;
$got_string = false;
}
if (!is_resource($id)) {
return $this->fbsqlRaiseError(DB_ERROR_NEED_MORE_DATA);
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$count = @fbsql_num_fields($id);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
for ($i = 0; $i < $count; $i++) {
$res[$i] = array(
'table' => $case_func(@fbsql_field_table($id, $i)),
'name' => $case_func(@fbsql_field_name($id, $i)),
'type' => @fbsql_field_type($id, $i),
'len' => @fbsql_field_len($id, $i),
'flags' => @fbsql_field_flags($id, $i),
);
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
// free the result only if we were called on a table
if ($got_string) {
@fbsql_free_result($id);
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Obtains the query string needed for listing a given type of objects
*
* @param string $type the kind of objects you want to retrieve
*
* @return string the SQL query string or null if the driver doesn't
* support the object type requested
*
* @access protected
* @see DB_common::getListOf()
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
return 'SELECT "table_name" FROM information_schema.tables'
. ' t0, information_schema.schemata t1'
. ' WHERE t0.schema_pk=t1.schema_pk AND'
. ' "table_type" = \'BASE TABLE\''
. ' AND "schema_name" = current_schema';
case 'views':
return 'SELECT "table_name" FROM information_schema.tables'
. ' t0, information_schema.schemata t1'
. ' WHERE t0.schema_pk=t1.schema_pk AND'
. ' "table_type" = \'VIEW\''
. ' AND "schema_name" = current_schema';
case 'users':
return 'SELECT "user_name" from information_schema.users';
case 'functions':
return 'SELECT "routine_name" FROM'
. ' information_schema.psm_routines'
. ' t0, information_schema.schemata t1'
. ' WHERE t0.schema_pk=t1.schema_pk'
. ' AND "routine_kind"=\'FUNCTION\''
. ' AND "schema_name" = current_schema';
case 'procedures':
return 'SELECT "routine_name" FROM'
. ' information_schema.psm_routines'
. ' t0, information_schema.schemata t1'
. ' WHERE t0.schema_pk=t1.schema_pk'
. ' AND "routine_kind"=\'PROCEDURE\''
. ' AND "schema_name" = current_schema';
default:
return null;
}
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>

1082
lib/pear/DB/ibase.php Normal file

File diff suppressed because it is too large Load Diff

683
lib/pear/DB/ifx.php Normal file
View File

@ -0,0 +1,683 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's ifx extension
* for interacting with Informix databases
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: ifx.php,v 1.74 2007/01/12 03:11:17 aharvey Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's ifx extension
* for interacting with Informix databases
*
* These methods overload the ones declared in DB_common.
*
* More info on Informix errors can be found at:
* http://www.informix.com/answers/english/ierrors.htm
*
* TODO:
* - set needed env Informix vars on connect
* - implement native prepare/execute
*
* @category Database
* @package DB
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.11
* @link http://pear.php.net/package/DB
*/
class DB_ifx extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'ifx';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'ifx';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* @var array
*/
var $features = array(
'limit' => 'emulate',
'new_link' => false,
'numrows' => 'emulate',
'pconnect' => true,
'prepare' => false,
'ssl' => false,
'transactions' => true,
);
/**
* A mapping of native error codes to DB error codes
* @var array
*/
var $errorcode_map = array(
'-201' => DB_ERROR_SYNTAX,
'-206' => DB_ERROR_NOSUCHTABLE,
'-217' => DB_ERROR_NOSUCHFIELD,
'-236' => DB_ERROR_VALUE_COUNT_ON_ROW,
'-239' => DB_ERROR_CONSTRAINT,
'-253' => DB_ERROR_SYNTAX,
'-268' => DB_ERROR_CONSTRAINT,
'-292' => DB_ERROR_CONSTRAINT_NOT_NULL,
'-310' => DB_ERROR_ALREADY_EXISTS,
'-316' => DB_ERROR_ALREADY_EXISTS,
'-319' => DB_ERROR_NOT_FOUND,
'-329' => DB_ERROR_NODBSELECTED,
'-346' => DB_ERROR_CONSTRAINT,
'-386' => DB_ERROR_CONSTRAINT_NOT_NULL,
'-391' => DB_ERROR_CONSTRAINT_NOT_NULL,
'-554' => DB_ERROR_SYNTAX,
'-691' => DB_ERROR_CONSTRAINT,
'-692' => DB_ERROR_CONSTRAINT,
'-703' => DB_ERROR_CONSTRAINT_NOT_NULL,
'-1202' => DB_ERROR_DIVZERO,
'-1204' => DB_ERROR_INVALID_DATE,
'-1205' => DB_ERROR_INVALID_DATE,
'-1206' => DB_ERROR_INVALID_DATE,
'-1209' => DB_ERROR_INVALID_DATE,
'-1210' => DB_ERROR_INVALID_DATE,
'-1212' => DB_ERROR_INVALID_DATE,
'-1213' => DB_ERROR_INVALID_NUMBER,
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
/**
* Should data manipulation queries be committed automatically?
* @var bool
* @access private
*/
var $autocommit = true;
/**
* The quantity of transactions begun
*
* {@internal While this is private, it can't actually be designated
* private in PHP 5 because it is directly accessed in the test suite.}}
*
* @var integer
* @access private
*/
var $transaction_opcount = 0;
/**
* The number of rows affected by a data manipulation query
* @var integer
* @access private
*/
var $affected = 0;
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_ifx()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database server, log in and open the database
*
* Don't call this method directly. Use DB::connect() instead.
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('informix') &&
!PEAR::loadExtension('Informix'))
{
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
$dbhost = $dsn['hostspec'] ? '@' . $dsn['hostspec'] : '';
$dbname = $dsn['database'] ? $dsn['database'] . $dbhost : '';
$user = $dsn['username'] ? $dsn['username'] : '';
$pw = $dsn['password'] ? $dsn['password'] : '';
$connect_function = $persistent ? 'ifx_pconnect' : 'ifx_connect';
$this->connection = @$connect_function($dbname, $user, $pw);
if (!is_resource($this->connection)) {
return $this->ifxRaiseError(DB_ERROR_CONNECT_FAILED);
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$ret = @ifx_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Sends a query to the database server
*
* @param string the SQL query string
*
* @return mixed + a PHP result resrouce for successful SELECT queries
* + the DB_OK constant for other successful queries
* + a DB_Error object on failure
*/
function simpleQuery($query)
{
$ismanip = $this->_checkManip($query);
$this->last_query = $query;
$this->affected = null;
if (preg_match('/(SELECT|EXECUTE)/i', $query)) { //TESTME: Use !DB::isManip()?
// the scroll is needed for fetching absolute row numbers
// in a select query result
$result = @ifx_query($query, $this->connection, IFX_SCROLL);
} else {
if (!$this->autocommit && $ismanip) {
if ($this->transaction_opcount == 0) {
$result = @ifx_query('BEGIN WORK', $this->connection);
if (!$result) {
return $this->ifxRaiseError();
}
}
$this->transaction_opcount++;
}
$result = @ifx_query($query, $this->connection);
}
if (!$result) {
return $this->ifxRaiseError();
}
$this->affected = @ifx_affected_rows($result);
// Determine which queries should return data, and which
// should return an error code only.
if (preg_match('/(SELECT|EXECUTE)/i', $query)) {
return $result;
}
// XXX Testme: free results inside a transaction
// may cause to stop it and commit the work?
// Result has to be freed even with a insert or update
@ifx_free_result($result);
return DB_OK;
}
// }}}
// {{{ nextResult()
/**
* Move the internal ifx result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
// {{{ affectedRows()
/**
* Determines the number of rows affected by a data maniuplation query
*
* 0 is returned for queries that don't manipulate data.
*
* @return int the number of rows. A DB_Error object on failure.
*/
function affectedRows()
{
if ($this->_last_query_manip) {
return $this->affected;
} else {
return 0;
}
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
if (($rownum !== null) && ($rownum < 0)) {
return null;
}
if ($rownum === null) {
/*
* Even though fetch_row() should return the next row if
* $rownum is null, it doesn't in all cases. Bug 598.
*/
$rownum = 'NEXT';
} else {
// Index starts at row 1, unlike most DBMS's starting at 0.
$rownum++;
}
if (!$arr = @ifx_fetch_row($result, $rownum)) {
return null;
}
if ($fetchmode !== DB_FETCHMODE_ASSOC) {
$i=0;
$order = array();
foreach ($arr as $val) {
$order[$i++] = $val;
}
$arr = $order;
} elseif ($fetchmode == DB_FETCHMODE_ASSOC &&
$this->options['portability'] & DB_PORTABILITY_LOWERCASE)
{
$arr = array_change_key_case($arr, CASE_LOWER);
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($result)
{
if (!$cols = @ifx_num_fields($result)) {
return $this->ifxRaiseError();
}
return $cols;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set
*
* This method is not meant to be called directly. Use
* DB_result::free() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult($result)
{
return is_resource($result) ? ifx_free_result($result) : false;
}
// }}}
// {{{ autoCommit()
/**
* Enables or disables automatic commits
*
* @param bool $onoff true turns it on, false turns it off
*
* @return int DB_OK on success. A DB_Error object if the driver
* doesn't support auto-committing transactions.
*/
function autoCommit($onoff = true)
{
// XXX if $this->transaction_opcount > 0, we should probably
// issue a warning here.
$this->autocommit = $onoff ? true : false;
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commits the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function commit()
{
if ($this->transaction_opcount > 0) {
$result = @ifx_query('COMMIT WORK', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->ifxRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Reverts the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function rollback()
{
if ($this->transaction_opcount > 0) {
$result = @ifx_query('ROLLBACK WORK', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->ifxRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ ifxRaiseError()
/**
* Produces a DB_Error object regarding the current problem
*
* @param int $errno if the error is being manually raised pass a
* DB_ERROR* constant here. If this isn't passed
* the error information gathered from the DBMS.
*
* @return object the DB_Error object
*
* @see DB_common::raiseError(),
* DB_ifx::errorNative(), DB_ifx::errorCode()
*/
function ifxRaiseError($errno = null)
{
if ($errno === null) {
$errno = $this->errorCode(ifx_error());
}
return $this->raiseError($errno, null, null, null,
$this->errorNative());
}
// }}}
// {{{ errorNative()
/**
* Gets the DBMS' native error code and message produced by the last query
*
* @return string the DBMS' error code and message
*/
function errorNative()
{
return @ifx_error() . ' ' . @ifx_errormsg();
}
// }}}
// {{{ errorCode()
/**
* Maps native error codes to DB's portable ones.
*
* Requires that the DB implementation's constructor fills
* in the <var>$errorcode_map</var> property.
*
* @param string $nativecode error code returned by the database
* @return int a portable DB error code, or DB_ERROR if this DB
* implementation has no mapping for the given error code.
*/
function errorCode($nativecode)
{
if (ereg('SQLCODE=(.*)]', $nativecode, $match)) {
$code = $match[1];
if (isset($this->errorcode_map[$code])) {
return $this->errorcode_map[$code];
}
}
return DB_ERROR;
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* NOTE: only supports 'table' if <var>$result</var> is a table name.
*
* If analyzing a query result and the result has duplicate field names,
* an error will be raised saying
* <samp>can't distinguish duplicate field names</samp>.
*
* @param object|string $result DB_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::tableInfo()
* @since Method available since Release 1.6.0
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
/*
* Probably received a table name.
* Create a result resource identifier.
*/
$id = @ifx_query("SELECT * FROM $result WHERE 1=0",
$this->connection);
$got_string = true;
} elseif (isset($result->result)) {
/*
* Probably received a result object.
* Extract the result resource identifier.
*/
$id = $result->result;
$got_string = false;
} else {
/*
* Probably received a result resource identifier.
* Copy it.
*/
$id = $result;
$got_string = false;
}
if (!is_resource($id)) {
return $this->ifxRaiseError(DB_ERROR_NEED_MORE_DATA);
}
$flds = @ifx_fieldproperties($id);
$count = @ifx_num_fields($id);
if (count($flds) != $count) {
return $this->raiseError("can't distinguish duplicate field names");
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$i = 0;
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
foreach ($flds as $key => $value) {
$props = explode(';', $value);
$res[$i] = array(
'table' => $got_string ? $case_func($result) : '',
'name' => $case_func($key),
'type' => $props[0],
'len' => $props[1],
'flags' => $props[4] == 'N' ? 'not_null' : '',
);
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
$i++;
}
// free the result only if we were called on a table
if ($got_string) {
@ifx_free_result($id);
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Obtains the query string needed for listing a given type of objects
*
* @param string $type the kind of objects you want to retrieve
*
* @return string the SQL query string or null if the driver doesn't
* support the object type requested
*
* @access protected
* @see DB_common::getListOf()
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
return 'SELECT tabname FROM systables WHERE tabid >= 100';
default:
return null;
}
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>

831
lib/pear/DB/msql.php Normal file
View File

@ -0,0 +1,831 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's msql extension
* for interacting with Mini SQL databases
*
* PHP's mSQL extension did weird things with NULL values prior to PHP
* 4.3.11 and 5.0.4. Make sure your version of PHP meets or exceeds
* those versions.
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: msql.php,v 1.62 2007/01/12 03:11:17 aharvey Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's msql extension
* for interacting with Mini SQL databases
*
* These methods overload the ones declared in DB_common.
*
* PHP's mSQL extension did weird things with NULL values prior to PHP
* 4.3.11 and 5.0.4. Make sure your version of PHP meets or exceeds
* those versions.
*
* @category Database
* @package DB
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.11
* @link http://pear.php.net/package/DB
* @since Class not functional until Release 1.7.0
*/
class DB_msql extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'msql';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'msql';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* @var array
*/
var $features = array(
'limit' => 'emulate',
'new_link' => false,
'numrows' => true,
'pconnect' => true,
'prepare' => false,
'ssl' => false,
'transactions' => false,
);
/**
* A mapping of native error codes to DB error codes
* @var array
*/
var $errorcode_map = array(
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
/**
* The query result resource created by PHP
*
* Used to make affectedRows() work. Only contains the result for
* data manipulation queries. Contains false for other queries.
*
* @var resource
* @access private
*/
var $_result;
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_msql()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database server, log in and open the database
*
* Don't call this method directly. Use DB::connect() instead.
*
* Example of how to connect:
* <code>
* require_once 'DB.php';
*
* // $dsn = 'msql://hostname/dbname'; // use a TCP connection
* $dsn = 'msql:///dbname'; // use a socket
* $options = array(
* 'portability' => DB_PORTABILITY_ALL,
* );
*
* $db =& DB::connect($dsn, $options);
* if (PEAR::isError($db)) {
* die($db->getMessage());
* }
* </code>
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('msql')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
$params = array();
if ($dsn['hostspec']) {
$params[] = $dsn['port']
? $dsn['hostspec'] . ',' . $dsn['port']
: $dsn['hostspec'];
}
$connect_function = $persistent ? 'msql_pconnect' : 'msql_connect';
$ini = ini_get('track_errors');
$php_errormsg = '';
if ($ini) {
$this->connection = @call_user_func_array($connect_function,
$params);
} else {
@ini_set('track_errors', 1);
$this->connection = @call_user_func_array($connect_function,
$params);
@ini_set('track_errors', $ini);
}
if (!$this->connection) {
if (($err = @msql_error()) != '') {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
$err);
} else {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
$php_errormsg);
}
}
if (!@msql_select_db($dsn['database'], $this->connection)) {
return $this->msqlRaiseError();
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$ret = @msql_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Sends a query to the database server
*
* @param string the SQL query string
*
* @return mixed + a PHP result resrouce for successful SELECT queries
* + the DB_OK constant for other successful queries
* + a DB_Error object on failure
*/
function simpleQuery($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @msql_query($query, $this->connection);
if (!$result) {
return $this->msqlRaiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
if ($this->_checkManip($query)) {
$this->_result = $result;
return DB_OK;
} else {
$this->_result = false;
return $result;
}
}
// }}}
// {{{ nextResult()
/**
* Move the internal msql result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* PHP's mSQL extension did weird things with NULL values prior to PHP
* 4.3.11 and 5.0.4. Make sure your version of PHP meets or exceeds
* those versions.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
if ($rownum !== null) {
if (!@msql_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$arr = @msql_fetch_array($result, MSQL_ASSOC);
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$arr = @msql_fetch_row($result);
}
if (!$arr) {
return null;
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set
*
* This method is not meant to be called directly. Use
* DB_result::free() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult($result)
{
return is_resource($result) ? msql_free_result($result) : false;
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($result)
{
$cols = @msql_num_fields($result);
if (!$cols) {
return $this->msqlRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Gets the number of rows in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numRows() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of rows. A DB_Error object on failure.
*
* @see DB_result::numRows()
*/
function numRows($result)
{
$rows = @msql_num_rows($result);
if ($rows === false) {
return $this->msqlRaiseError();
}
return $rows;
}
// }}}
// {{{ affected()
/**
* Determines the number of rows affected by a data maniuplation query
*
* 0 is returned for queries that don't manipulate data.
*
* @return int the number of rows. A DB_Error object on failure.
*/
function affectedRows()
{
if (!$this->_result) {
return 0;
}
return msql_affected_rows($this->_result);
}
// }}}
// {{{ nextId()
/**
* Returns the next free id in a sequence
*
* @param string $seq_name name of the sequence
* @param boolean $ondemand when true, the seqence is automatically
* created if it does not exist
*
* @return int the next id number in the sequence.
* A DB_Error object on failure.
*
* @see DB_common::nextID(), DB_common::getSequenceName(),
* DB_msql::createSequence(), DB_msql::dropSequence()
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
$repeat = false;
do {
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result =& $this->query("SELECT _seq FROM ${seqname}");
$this->popErrorHandling();
if ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE) {
$repeat = true;
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->createSequence($seq_name);
$this->popErrorHandling();
if (DB::isError($result)) {
return $this->raiseError($result);
}
} else {
$repeat = false;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$arr = $result->fetchRow(DB_FETCHMODE_ORDERED);
$result->free();
return $arr[0];
}
// }}}
// {{{ createSequence()
/**
* Creates a new sequence
*
* Also creates a new table to associate the sequence with. Uses
* a separate table to ensure portability with other drivers.
*
* @param string $seq_name name of the new sequence
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::createSequence(), DB_common::getSequenceName(),
* DB_msql::nextID(), DB_msql::dropSequence()
*/
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
$res = $this->query('CREATE TABLE ' . $seqname
. ' (id INTEGER NOT NULL)');
if (DB::isError($res)) {
return $res;
}
$res = $this->query("CREATE SEQUENCE ON ${seqname}");
return $res;
}
// }}}
// {{{ dropSequence()
/**
* Deletes a sequence
*
* @param string $seq_name name of the sequence to be deleted
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::dropSequence(), DB_common::getSequenceName(),
* DB_msql::nextID(), DB_msql::createSequence()
*/
function dropSequence($seq_name)
{
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
}
// }}}
// {{{ quoteIdentifier()
/**
* mSQL does not support delimited identifiers
*
* @param string $str the identifier name to be quoted
*
* @return object a DB_Error object
*
* @see DB_common::quoteIdentifier()
* @since Method available since Release 1.7.0
*/
function quoteIdentifier($str)
{
return $this->raiseError(DB_ERROR_UNSUPPORTED);
}
// }}}
// {{{ quoteFloat()
/**
* Formats a float value for use within a query in a locale-independent
* manner.
*
* @param float the float value to be quoted.
* @return string the quoted string.
* @see DB_common::quoteSmart()
* @since Method available since release 1.7.8.
*/
function quoteFloat($float) {
return $this->escapeSimple(str_replace(',', '.', strval(floatval($float))));
}
// }}}
// {{{ escapeSimple()
/**
* Escapes a string according to the current DBMS's standards
*
* @param string $str the string to be escaped
*
* @return string the escaped string
*
* @see DB_common::quoteSmart()
* @since Method available since Release 1.7.0
*/
function escapeSimple($str)
{
return addslashes($str);
}
// }}}
// {{{ msqlRaiseError()
/**
* Produces a DB_Error object regarding the current problem
*
* @param int $errno if the error is being manually raised pass a
* DB_ERROR* constant here. If this isn't passed
* the error information gathered from the DBMS.
*
* @return object the DB_Error object
*
* @see DB_common::raiseError(),
* DB_msql::errorNative(), DB_msql::errorCode()
*/
function msqlRaiseError($errno = null)
{
$native = $this->errorNative();
if ($errno === null) {
$errno = $this->errorCode($native);
}
return $this->raiseError($errno, null, null, null, $native);
}
// }}}
// {{{ errorNative()
/**
* Gets the DBMS' native error message produced by the last query
*
* @return string the DBMS' error message
*/
function errorNative()
{
return @msql_error();
}
// }}}
// {{{ errorCode()
/**
* Determines PEAR::DB error code from the database's text error message
*
* @param string $errormsg the error message returned from the database
*
* @return integer the error number from a DB_ERROR* constant
*/
function errorCode($errormsg)
{
static $error_regexps;
// PHP 5.2+ prepends the function name to $php_errormsg, so we need
// this hack to work around it, per bug #9599.
$errormsg = preg_replace('/^msql[a-z_]+\(\): /', '', $errormsg);
if (!isset($error_regexps)) {
$error_regexps = array(
'/^Access to database denied/i'
=> DB_ERROR_ACCESS_VIOLATION,
'/^Bad index name/i'
=> DB_ERROR_ALREADY_EXISTS,
'/^Bad order field/i'
=> DB_ERROR_SYNTAX,
'/^Bad type for comparison/i'
=> DB_ERROR_SYNTAX,
'/^Can\'t perform LIKE on/i'
=> DB_ERROR_SYNTAX,
'/^Can\'t use TEXT fields in LIKE comparison/i'
=> DB_ERROR_SYNTAX,
'/^Couldn\'t create temporary table/i'
=> DB_ERROR_CANNOT_CREATE,
'/^Error creating table file/i'
=> DB_ERROR_CANNOT_CREATE,
'/^Field .* cannot be null$/i'
=> DB_ERROR_CONSTRAINT_NOT_NULL,
'/^Index (field|condition) .* cannot be null$/i'
=> DB_ERROR_SYNTAX,
'/^Invalid date format/i'
=> DB_ERROR_INVALID_DATE,
'/^Invalid time format/i'
=> DB_ERROR_INVALID,
'/^Literal value for .* is wrong type$/i'
=> DB_ERROR_INVALID_NUMBER,
'/^No Database Selected/i'
=> DB_ERROR_NODBSELECTED,
'/^No value specified for field/i'
=> DB_ERROR_VALUE_COUNT_ON_ROW,
'/^Non unique value for unique index/i'
=> DB_ERROR_CONSTRAINT,
'/^Out of memory for temporary table/i'
=> DB_ERROR_CANNOT_CREATE,
'/^Permission denied/i'
=> DB_ERROR_ACCESS_VIOLATION,
'/^Reference to un-selected table/i'
=> DB_ERROR_SYNTAX,
'/^syntax error/i'
=> DB_ERROR_SYNTAX,
'/^Table .* exists$/i'
=> DB_ERROR_ALREADY_EXISTS,
'/^Unknown database/i'
=> DB_ERROR_NOSUCHDB,
'/^Unknown field/i'
=> DB_ERROR_NOSUCHFIELD,
'/^Unknown (index|system variable)/i'
=> DB_ERROR_NOT_FOUND,
'/^Unknown table/i'
=> DB_ERROR_NOSUCHTABLE,
'/^Unqualified field/i'
=> DB_ERROR_SYNTAX,
);
}
foreach ($error_regexps as $regexp => $code) {
if (preg_match($regexp, $errormsg)) {
return $code;
}
}
return DB_ERROR;
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* @param object|string $result DB_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::setOption()
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
/*
* Probably received a table name.
* Create a result resource identifier.
*/
$id = @msql_query("SELECT * FROM $result",
$this->connection);
$got_string = true;
} elseif (isset($result->result)) {
/*
* Probably received a result object.
* Extract the result resource identifier.
*/
$id = $result->result;
$got_string = false;
} else {
/*
* Probably received a result resource identifier.
* Copy it.
* Deprecated. Here for compatibility only.
*/
$id = $result;
$got_string = false;
}
if (!is_resource($id)) {
return $this->raiseError(DB_ERROR_NEED_MORE_DATA);
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$count = @msql_num_fields($id);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
for ($i = 0; $i < $count; $i++) {
$tmp = @msql_fetch_field($id);
$flags = '';
if ($tmp->not_null) {
$flags .= 'not_null ';
}
if ($tmp->unique) {
$flags .= 'unique_key ';
}
$flags = trim($flags);
$res[$i] = array(
'table' => $case_func($tmp->table),
'name' => $case_func($tmp->name),
'type' => $tmp->type,
'len' => msql_field_len($id, $i),
'flags' => $flags,
);
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
// free the result only if we were called on a table
if ($got_string) {
@msql_free_result($id);
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Obtain a list of a given type of objects
*
* @param string $type the kind of objects you want to retrieve
*
* @return array the array containing the list of objects requested
*
* @access protected
* @see DB_common::getListOf()
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'databases':
$id = @msql_list_dbs($this->connection);
break;
case 'tables':
$id = @msql_list_tables($this->dsn['database'],
$this->connection);
break;
default:
return null;
}
if (!$id) {
return $this->msqlRaiseError();
}
$out = array();
while ($row = @msql_fetch_row($id)) {
$out[] = $row[0];
}
return $out;
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>

963
lib/pear/DB/mssql.php Normal file
View File

@ -0,0 +1,963 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's mssql extension
* for interacting with Microsoft SQL Server databases
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Sterling Hughes <sterling@php.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: mssql.php,v 1.90 2007/01/12 05:16:22 aharvey Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's mssql extension
* for interacting with Microsoft SQL Server databases
*
* These methods overload the ones declared in DB_common.
*
* DB's mssql driver is only for Microsfoft SQL Server databases.
*
* If you're connecting to a Sybase database, you MUST specify "sybase"
* as the "phptype" in the DSN.
*
* This class only works correctly if you have compiled PHP using
* --with-mssql=[dir_to_FreeTDS].
*
* @category Database
* @package DB
* @author Sterling Hughes <sterling@php.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.11
* @link http://pear.php.net/package/DB
*/
class DB_mssql extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'mssql';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'mssql';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* @var array
*/
var $features = array(
'limit' => 'emulate',
'new_link' => false,
'numrows' => true,
'pconnect' => true,
'prepare' => false,
'ssl' => false,
'transactions' => true,
);
/**
* A mapping of native error codes to DB error codes
* @var array
*/
// XXX Add here error codes ie: 'S100E' => DB_ERROR_SYNTAX
var $errorcode_map = array(
102 => DB_ERROR_SYNTAX,
110 => DB_ERROR_VALUE_COUNT_ON_ROW,
155 => DB_ERROR_NOSUCHFIELD,
156 => DB_ERROR_SYNTAX,
170 => DB_ERROR_SYNTAX,
207 => DB_ERROR_NOSUCHFIELD,
208 => DB_ERROR_NOSUCHTABLE,
245 => DB_ERROR_INVALID_NUMBER,
319 => DB_ERROR_SYNTAX,
321 => DB_ERROR_NOSUCHFIELD,
325 => DB_ERROR_SYNTAX,
336 => DB_ERROR_SYNTAX,
515 => DB_ERROR_CONSTRAINT_NOT_NULL,
547 => DB_ERROR_CONSTRAINT,
1018 => DB_ERROR_SYNTAX,
1035 => DB_ERROR_SYNTAX,
1913 => DB_ERROR_ALREADY_EXISTS,
2209 => DB_ERROR_SYNTAX,
2223 => DB_ERROR_SYNTAX,
2248 => DB_ERROR_SYNTAX,
2256 => DB_ERROR_SYNTAX,
2257 => DB_ERROR_SYNTAX,
2627 => DB_ERROR_CONSTRAINT,
2714 => DB_ERROR_ALREADY_EXISTS,
3607 => DB_ERROR_DIVZERO,
3701 => DB_ERROR_NOSUCHTABLE,
7630 => DB_ERROR_SYNTAX,
8134 => DB_ERROR_DIVZERO,
9303 => DB_ERROR_SYNTAX,
9317 => DB_ERROR_SYNTAX,
9318 => DB_ERROR_SYNTAX,
9331 => DB_ERROR_SYNTAX,
9332 => DB_ERROR_SYNTAX,
15253 => DB_ERROR_SYNTAX,
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
/**
* Should data manipulation queries be committed automatically?
* @var bool
* @access private
*/
var $autocommit = true;
/**
* The quantity of transactions begun
*
* {@internal While this is private, it can't actually be designated
* private in PHP 5 because it is directly accessed in the test suite.}}
*
* @var integer
* @access private
*/
var $transaction_opcount = 0;
/**
* The database specified in the DSN
*
* It's a fix to allow calls to different databases in the same script.
*
* @var string
* @access private
*/
var $_db = null;
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_mssql()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database server, log in and open the database
*
* Don't call this method directly. Use DB::connect() instead.
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('mssql') && !PEAR::loadExtension('sybase')
&& !PEAR::loadExtension('sybase_ct'))
{
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
$params = array(
$dsn['hostspec'] ? $dsn['hostspec'] : 'localhost',
$dsn['username'] ? $dsn['username'] : null,
$dsn['password'] ? $dsn['password'] : null,
);
if ($dsn['port']) {
$params[0] .= ((substr(PHP_OS, 0, 3) == 'WIN') ? ',' : ':')
. $dsn['port'];
}
$connect_function = $persistent ? 'mssql_pconnect' : 'mssql_connect';
$this->connection = @call_user_func_array($connect_function, $params);
if (!$this->connection) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
@mssql_get_last_message());
}
if ($dsn['database']) {
if (!@mssql_select_db($dsn['database'], $this->connection)) {
return $this->raiseError(DB_ERROR_NODBSELECTED,
null, null, null,
@mssql_get_last_message());
}
$this->_db = $dsn['database'];
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$ret = @mssql_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Sends a query to the database server
*
* @param string the SQL query string
*
* @return mixed + a PHP result resrouce for successful SELECT queries
* + the DB_OK constant for other successful queries
* + a DB_Error object on failure
*/
function simpleQuery($query)
{
$ismanip = $this->_checkManip($query);
$this->last_query = $query;
if (!@mssql_select_db($this->_db, $this->connection)) {
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
}
$query = $this->modifyQuery($query);
if (!$this->autocommit && $ismanip) {
if ($this->transaction_opcount == 0) {
$result = @mssql_query('BEGIN TRAN', $this->connection);
if (!$result) {
return $this->mssqlRaiseError();
}
}
$this->transaction_opcount++;
}
$result = @mssql_query($query, $this->connection);
if (!$result) {
return $this->mssqlRaiseError();
}
// Determine which queries that should return data, and which
// should return an error code only.
return $ismanip ? DB_OK : $result;
}
// }}}
// {{{ nextResult()
/**
* Move the internal mssql result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return @mssql_next_result($result);
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
if ($rownum !== null) {
if (!@mssql_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$arr = @mssql_fetch_assoc($result);
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$arr = @mssql_fetch_row($result);
}
if (!$arr) {
return null;
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set
*
* This method is not meant to be called directly. Use
* DB_result::free() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult($result)
{
return is_resource($result) ? mssql_free_result($result) : false;
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($result)
{
$cols = @mssql_num_fields($result);
if (!$cols) {
return $this->mssqlRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Gets the number of rows in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numRows() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of rows. A DB_Error object on failure.
*
* @see DB_result::numRows()
*/
function numRows($result)
{
$rows = @mssql_num_rows($result);
if ($rows === false) {
return $this->mssqlRaiseError();
}
return $rows;
}
// }}}
// {{{ autoCommit()
/**
* Enables or disables automatic commits
*
* @param bool $onoff true turns it on, false turns it off
*
* @return int DB_OK on success. A DB_Error object if the driver
* doesn't support auto-committing transactions.
*/
function autoCommit($onoff = false)
{
// XXX if $this->transaction_opcount > 0, we should probably
// issue a warning here.
$this->autocommit = $onoff ? true : false;
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commits the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function commit()
{
if ($this->transaction_opcount > 0) {
if (!@mssql_select_db($this->_db, $this->connection)) {
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
}
$result = @mssql_query('COMMIT TRAN', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->mssqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Reverts the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function rollback()
{
if ($this->transaction_opcount > 0) {
if (!@mssql_select_db($this->_db, $this->connection)) {
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
}
$result = @mssql_query('ROLLBACK TRAN', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->mssqlRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ affectedRows()
/**
* Determines the number of rows affected by a data maniuplation query
*
* 0 is returned for queries that don't manipulate data.
*
* @return int the number of rows. A DB_Error object on failure.
*/
function affectedRows()
{
if ($this->_last_query_manip) {
$res = @mssql_query('select @@rowcount', $this->connection);
if (!$res) {
return $this->mssqlRaiseError();
}
$ar = @mssql_fetch_row($res);
if (!$ar) {
$result = 0;
} else {
@mssql_free_result($res);
$result = $ar[0];
}
} else {
$result = 0;
}
return $result;
}
// }}}
// {{{ nextId()
/**
* Returns the next free id in a sequence
*
* @param string $seq_name name of the sequence
* @param boolean $ondemand when true, the seqence is automatically
* created if it does not exist
*
* @return int the next id number in the sequence.
* A DB_Error object on failure.
*
* @see DB_common::nextID(), DB_common::getSequenceName(),
* DB_mssql::createSequence(), DB_mssql::dropSequence()
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
if (!@mssql_select_db($this->_db, $this->connection)) {
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
}
$repeat = 0;
do {
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)");
$this->popErrorHandling();
if ($ondemand && DB::isError($result) &&
($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE))
{
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $this->raiseError($result);
}
} elseif (!DB::isError($result)) {
$result =& $this->query("SELECT IDENT_CURRENT('$seqname')");
if (DB::isError($result)) {
/* Fallback code for MS SQL Server 7.0, which doesn't have
* IDENT_CURRENT. This is *not* safe for concurrent
* requests, and really, if you're using it, you're in a
* world of hurt. Nevertheless, it's here to ensure BC. See
* bug #181 for the gory details.*/
$result =& $this->query("SELECT @@IDENTITY FROM $seqname");
}
$repeat = 0;
} else {
$repeat = false;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$result = $result->fetchRow(DB_FETCHMODE_ORDERED);
return $result[0];
}
/**
* Creates a new sequence
*
* @param string $seq_name name of the new sequence
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::createSequence(), DB_common::getSequenceName(),
* DB_mssql::nextID(), DB_mssql::dropSequence()
*/
function createSequence($seq_name)
{
return $this->query('CREATE TABLE '
. $this->getSequenceName($seq_name)
. ' ([id] [int] IDENTITY (1, 1) NOT NULL,'
. ' [vapor] [int] NULL)');
}
// }}}
// {{{ dropSequence()
/**
* Deletes a sequence
*
* @param string $seq_name name of the sequence to be deleted
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::dropSequence(), DB_common::getSequenceName(),
* DB_mssql::nextID(), DB_mssql::createSequence()
*/
function dropSequence($seq_name)
{
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
}
// }}}
// {{{ quoteIdentifier()
/**
* Quotes a string so it can be safely used as a table or column name
*
* @param string $str identifier name to be quoted
*
* @return string quoted identifier string
*
* @see DB_common::quoteIdentifier()
* @since Method available since Release 1.6.0
*/
function quoteIdentifier($str)
{
return '[' . str_replace(']', ']]', $str) . ']';
}
// }}}
// {{{ mssqlRaiseError()
/**
* Produces a DB_Error object regarding the current problem
*
* @param int $errno if the error is being manually raised pass a
* DB_ERROR* constant here. If this isn't passed
* the error information gathered from the DBMS.
*
* @return object the DB_Error object
*
* @see DB_common::raiseError(),
* DB_mssql::errorNative(), DB_mssql::errorCode()
*/
function mssqlRaiseError($code = null)
{
$message = @mssql_get_last_message();
if (!$code) {
$code = $this->errorNative();
}
return $this->raiseError($this->errorCode($code, $message),
null, null, null, "$code - $message");
}
// }}}
// {{{ errorNative()
/**
* Gets the DBMS' native error code produced by the last query
*
* @return int the DBMS' error code
*/
function errorNative()
{
$res = @mssql_query('select @@ERROR as ErrorCode', $this->connection);
if (!$res) {
return DB_ERROR;
}
$row = @mssql_fetch_row($res);
return $row[0];
}
// }}}
// {{{ errorCode()
/**
* Determines PEAR::DB error code from mssql's native codes.
*
* If <var>$nativecode</var> isn't known yet, it will be looked up.
*
* @param mixed $nativecode mssql error code, if known
* @return integer an error number from a DB error constant
* @see errorNative()
*/
function errorCode($nativecode = null, $msg = '')
{
if (!$nativecode) {
$nativecode = $this->errorNative();
}
if (isset($this->errorcode_map[$nativecode])) {
if ($nativecode == 3701
&& preg_match('/Cannot drop the index/i', $msg))
{
return DB_ERROR_NOT_FOUND;
}
return $this->errorcode_map[$nativecode];
} else {
return DB_ERROR;
}
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* NOTE: only supports 'table' and 'flags' if <var>$result</var>
* is a table name.
*
* @param object|string $result DB_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::tableInfo()
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
/*
* Probably received a table name.
* Create a result resource identifier.
*/
if (!@mssql_select_db($this->_db, $this->connection)) {
return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
}
$id = @mssql_query("SELECT * FROM $result WHERE 1=0",
$this->connection);
$got_string = true;
} elseif (isset($result->result)) {
/*
* Probably received a result object.
* Extract the result resource identifier.
*/
$id = $result->result;
$got_string = false;
} else {
/*
* Probably received a result resource identifier.
* Copy it.
* Deprecated. Here for compatibility only.
*/
$id = $result;
$got_string = false;
}
if (!is_resource($id)) {
return $this->mssqlRaiseError(DB_ERROR_NEED_MORE_DATA);
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$count = @mssql_num_fields($id);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
for ($i = 0; $i < $count; $i++) {
if ($got_string) {
$flags = $this->_mssql_field_flags($result,
@mssql_field_name($id, $i));
if (DB::isError($flags)) {
return $flags;
}
} else {
$flags = '';
}
$res[$i] = array(
'table' => $got_string ? $case_func($result) : '',
'name' => $case_func(@mssql_field_name($id, $i)),
'type' => @mssql_field_type($id, $i),
'len' => @mssql_field_length($id, $i),
'flags' => $flags,
);
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
// free the result only if we were called on a table
if ($got_string) {
@mssql_free_result($id);
}
return $res;
}
// }}}
// {{{ _mssql_field_flags()
/**
* Get a column's flags
*
* Supports "not_null", "primary_key",
* "auto_increment" (mssql identity), "timestamp" (mssql timestamp),
* "unique_key" (mssql unique index, unique check or primary_key) and
* "multiple_key" (multikey index)
*
* mssql timestamp is NOT similar to the mysql timestamp so this is maybe
* not useful at all - is the behaviour of mysql_field_flags that primary
* keys are alway unique? is the interpretation of multiple_key correct?
*
* @param string $table the table name
* @param string $column the field name
*
* @return string the flags
*
* @access private
* @author Joern Barthel <j_barthel@web.de>
*/
function _mssql_field_flags($table, $column)
{
static $tableName = null;
static $flags = array();
if ($table != $tableName) {
$flags = array();
$tableName = $table;
// get unique and primary keys
$res = $this->getAll("EXEC SP_HELPINDEX $table", DB_FETCHMODE_ASSOC);
if (DB::isError($res)) {
return $res;
}
foreach ($res as $val) {
$keys = explode(', ', $val['index_keys']);
if (sizeof($keys) > 1) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'multiple_key');
}
}
if (strpos($val['index_description'], 'primary key')) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'primary_key');
}
} elseif (strpos($val['index_description'], 'unique')) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'unique_key');
}
}
}
// get auto_increment, not_null and timestamp
$res = $this->getAll("EXEC SP_COLUMNS $table", DB_FETCHMODE_ASSOC);
if (DB::isError($res)) {
return $res;
}
foreach ($res as $val) {
$val = array_change_key_case($val, CASE_LOWER);
if ($val['nullable'] == '0') {
$this->_add_flag($flags[$val['column_name']], 'not_null');
}
if (strpos($val['type_name'], 'identity')) {
$this->_add_flag($flags[$val['column_name']], 'auto_increment');
}
if (strpos($val['type_name'], 'timestamp')) {
$this->_add_flag($flags[$val['column_name']], 'timestamp');
}
}
}
if (array_key_exists($column, $flags)) {
return(implode(' ', $flags[$column]));
}
return '';
}
// }}}
// {{{ _add_flag()
/**
* Adds a string to the flags array if the flag is not yet in there
* - if there is no flag present the array is created
*
* @param array &$array the reference to the flag-array
* @param string $value the flag value
*
* @return void
*
* @access private
* @author Joern Barthel <j_barthel@web.de>
*/
function _add_flag(&$array, $value)
{
if (!is_array($array)) {
$array = array($value);
} elseif (!in_array($value, $array)) {
array_push($array, $value);
}
}
// }}}
// {{{ getSpecialQuery()
/**
* Obtains the query string needed for listing a given type of objects
*
* @param string $type the kind of objects you want to retrieve
*
* @return string the SQL query string or null if the driver doesn't
* support the object type requested
*
* @access protected
* @see DB_common::getListOf()
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
return "SELECT name FROM sysobjects WHERE type = 'U'"
. ' ORDER BY name';
case 'views':
return "SELECT name FROM sysobjects WHERE type = 'V'";
default:
return null;
}
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>

1038
lib/pear/DB/mysql.php Normal file

File diff suppressed because it is too large Load Diff

1085
lib/pear/DB/mysqli.php Normal file

File diff suppressed because it is too large Load Diff

1154
lib/pear/DB/oci8.php Normal file

File diff suppressed because it is too large Load Diff

883
lib/pear/DB/odbc.php Normal file
View File

@ -0,0 +1,883 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's odbc extension
* for interacting with databases via ODBC connections
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Stig Bakken <ssb@php.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: odbc.php,v 1.80 2007/01/12 03:11:17 aharvey Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's odbc extension
* for interacting with databases via ODBC connections
*
* These methods overload the ones declared in DB_common.
*
* More info on ODBC errors could be found here:
* http://msdn.microsoft.com/library/default.asp?url=/library/en-us/trblsql/tr_err_odbc_5stz.asp
*
* @category Database
* @package DB
* @author Stig Bakken <ssb@php.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.11
* @link http://pear.php.net/package/DB
*/
class DB_odbc extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'odbc';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'sql92';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* NOTE: The feature set of the following drivers are different than
* the default:
* + solid: 'transactions' = true
* + navision: 'limit' = false
*
* @var array
*/
var $features = array(
'limit' => 'emulate',
'new_link' => false,
'numrows' => true,
'pconnect' => true,
'prepare' => false,
'ssl' => false,
'transactions' => false,
);
/**
* A mapping of native error codes to DB error codes
* @var array
*/
var $errorcode_map = array(
'01004' => DB_ERROR_TRUNCATED,
'07001' => DB_ERROR_MISMATCH,
'21S01' => DB_ERROR_VALUE_COUNT_ON_ROW,
'21S02' => DB_ERROR_MISMATCH,
'22001' => DB_ERROR_INVALID,
'22003' => DB_ERROR_INVALID_NUMBER,
'22005' => DB_ERROR_INVALID_NUMBER,
'22008' => DB_ERROR_INVALID_DATE,
'22012' => DB_ERROR_DIVZERO,
'23000' => DB_ERROR_CONSTRAINT,
'23502' => DB_ERROR_CONSTRAINT_NOT_NULL,
'23503' => DB_ERROR_CONSTRAINT,
'23504' => DB_ERROR_CONSTRAINT,
'23505' => DB_ERROR_CONSTRAINT,
'24000' => DB_ERROR_INVALID,
'34000' => DB_ERROR_INVALID,
'37000' => DB_ERROR_SYNTAX,
'42000' => DB_ERROR_SYNTAX,
'42601' => DB_ERROR_SYNTAX,
'IM001' => DB_ERROR_UNSUPPORTED,
'S0000' => DB_ERROR_NOSUCHTABLE,
'S0001' => DB_ERROR_ALREADY_EXISTS,
'S0002' => DB_ERROR_NOSUCHTABLE,
'S0011' => DB_ERROR_ALREADY_EXISTS,
'S0012' => DB_ERROR_NOT_FOUND,
'S0021' => DB_ERROR_ALREADY_EXISTS,
'S0022' => DB_ERROR_NOSUCHFIELD,
'S1009' => DB_ERROR_INVALID,
'S1090' => DB_ERROR_INVALID,
'S1C00' => DB_ERROR_NOT_CAPABLE,
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
/**
* The number of rows affected by a data manipulation query
* @var integer
* @access private
*/
var $affected = 0;
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_odbc()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database server, log in and open the database
*
* Don't call this method directly. Use DB::connect() instead.
*
* PEAR DB's odbc driver supports the following extra DSN options:
* + cursor The type of cursor to be used for this connection.
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('odbc')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
switch ($this->dbsyntax) {
case 'access':
case 'db2':
case 'solid':
$this->features['transactions'] = true;
break;
case 'navision':
$this->features['limit'] = false;
}
/*
* This is hear for backwards compatibility. Should have been using
* 'database' all along, but prior to 1.6.0RC3 'hostspec' was used.
*/
if ($dsn['database']) {
$odbcdsn = $dsn['database'];
} elseif ($dsn['hostspec']) {
$odbcdsn = $dsn['hostspec'];
} else {
$odbcdsn = 'localhost';
}
$connect_function = $persistent ? 'odbc_pconnect' : 'odbc_connect';
if (empty($dsn['cursor'])) {
$this->connection = @$connect_function($odbcdsn, $dsn['username'],
$dsn['password']);
} else {
$this->connection = @$connect_function($odbcdsn, $dsn['username'],
$dsn['password'],
$dsn['cursor']);
}
if (!is_resource($this->connection)) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
$this->errorNative());
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$err = @odbc_close($this->connection);
$this->connection = null;
return $err;
}
// }}}
// {{{ simpleQuery()
/**
* Sends a query to the database server
*
* @param string the SQL query string
*
* @return mixed + a PHP result resrouce for successful SELECT queries
* + the DB_OK constant for other successful queries
* + a DB_Error object on failure
*/
function simpleQuery($query)
{
$this->last_query = $query;
$query = $this->modifyQuery($query);
$result = @odbc_exec($this->connection, $query);
if (!$result) {
return $this->odbcRaiseError(); // XXX ERRORMSG
}
// Determine which queries that should return data, and which
// should return an error code only.
if ($this->_checkManip($query)) {
$this->affected = $result; // For affectedRows()
return DB_OK;
}
$this->affected = 0;
return $result;
}
// }}}
// {{{ nextResult()
/**
* Move the internal odbc result pointer to the next available result
*
* @param a valid fbsql result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return @odbc_next_result($result);
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
$arr = array();
if ($rownum !== null) {
$rownum++; // ODBC first row is 1
if (version_compare(phpversion(), '4.2.0', 'ge')) {
$cols = @odbc_fetch_into($result, $arr, $rownum);
} else {
$cols = @odbc_fetch_into($result, $rownum, $arr);
}
} else {
$cols = @odbc_fetch_into($result, $arr);
}
if (!$cols) {
return null;
}
if ($fetchmode !== DB_FETCHMODE_ORDERED) {
for ($i = 0; $i < count($arr); $i++) {
$colName = @odbc_field_name($result, $i+1);
$a[$colName] = $arr[$i];
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$a = array_change_key_case($a, CASE_LOWER);
}
$arr = $a;
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set
*
* This method is not meant to be called directly. Use
* DB_result::free() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult($result)
{
return is_resource($result) ? odbc_free_result($result) : false;
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($result)
{
$cols = @odbc_num_fields($result);
if (!$cols) {
return $this->odbcRaiseError();
}
return $cols;
}
// }}}
// {{{ affectedRows()
/**
* Determines the number of rows affected by a data maniuplation query
*
* 0 is returned for queries that don't manipulate data.
*
* @return int the number of rows. A DB_Error object on failure.
*/
function affectedRows()
{
if (empty($this->affected)) { // In case of SELECT stms
return 0;
}
$nrows = @odbc_num_rows($this->affected);
if ($nrows == -1) {
return $this->odbcRaiseError();
}
return $nrows;
}
// }}}
// {{{ numRows()
/**
* Gets the number of rows in a result set
*
* Not all ODBC drivers support this functionality. If they don't
* a DB_Error object for DB_ERROR_UNSUPPORTED is returned.
*
* This method is not meant to be called directly. Use
* DB_result::numRows() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of rows. A DB_Error object on failure.
*
* @see DB_result::numRows()
*/
function numRows($result)
{
$nrows = @odbc_num_rows($result);
if ($nrows == -1) {
return $this->odbcRaiseError(DB_ERROR_UNSUPPORTED);
}
if ($nrows === false) {
return $this->odbcRaiseError();
}
return $nrows;
}
// }}}
// {{{ quoteIdentifier()
/**
* Quotes a string so it can be safely used as a table or column name
*
* Use 'mssql' as the dbsyntax in the DB DSN only if you've unchecked
* "Use ANSI quoted identifiers" when setting up the ODBC data source.
*
* @param string $str identifier name to be quoted
*
* @return string quoted identifier string
*
* @see DB_common::quoteIdentifier()
* @since Method available since Release 1.6.0
*/
function quoteIdentifier($str)
{
switch ($this->dsn['dbsyntax']) {
case 'access':
return '[' . $str . ']';
case 'mssql':
case 'sybase':
return '[' . str_replace(']', ']]', $str) . ']';
case 'mysql':
case 'mysqli':
return '`' . $str . '`';
default:
return '"' . str_replace('"', '""', $str) . '"';
}
}
// }}}
// {{{ quote()
/**
* @deprecated Deprecated in release 1.6.0
* @internal
*/
function quote($str)
{
return $this->quoteSmart($str);
}
// }}}
// {{{ nextId()
/**
* Returns the next free id in a sequence
*
* @param string $seq_name name of the sequence
* @param boolean $ondemand when true, the seqence is automatically
* created if it does not exist
*
* @return int the next id number in the sequence.
* A DB_Error object on failure.
*
* @see DB_common::nextID(), DB_common::getSequenceName(),
* DB_odbc::createSequence(), DB_odbc::dropSequence()
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
$repeat = 0;
do {
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("update ${seqname} set id = id + 1");
$this->popErrorHandling();
if ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE) {
$repeat = 1;
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->createSequence($seq_name);
$this->popErrorHandling();
if (DB::isError($result)) {
return $this->raiseError($result);
}
$result = $this->query("insert into ${seqname} (id) values(0)");
} else {
$repeat = 0;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$result = $this->query("select id from ${seqname}");
if (DB::isError($result)) {
return $result;
}
$row = $result->fetchRow(DB_FETCHMODE_ORDERED);
if (DB::isError($row || !$row)) {
return $row;
}
return $row[0];
}
/**
* Creates a new sequence
*
* @param string $seq_name name of the new sequence
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::createSequence(), DB_common::getSequenceName(),
* DB_odbc::nextID(), DB_odbc::dropSequence()
*/
function createSequence($seq_name)
{
return $this->query('CREATE TABLE '
. $this->getSequenceName($seq_name)
. ' (id integer NOT NULL,'
. ' PRIMARY KEY(id))');
}
// }}}
// {{{ dropSequence()
/**
* Deletes a sequence
*
* @param string $seq_name name of the sequence to be deleted
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::dropSequence(), DB_common::getSequenceName(),
* DB_odbc::nextID(), DB_odbc::createSequence()
*/
function dropSequence($seq_name)
{
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
}
// }}}
// {{{ autoCommit()
/**
* Enables or disables automatic commits
*
* @param bool $onoff true turns it on, false turns it off
*
* @return int DB_OK on success. A DB_Error object if the driver
* doesn't support auto-committing transactions.
*/
function autoCommit($onoff = false)
{
if (!@odbc_autocommit($this->connection, $onoff)) {
return $this->odbcRaiseError();
}
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commits the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function commit()
{
if (!@odbc_commit($this->connection)) {
return $this->odbcRaiseError();
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Reverts the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function rollback()
{
if (!@odbc_rollback($this->connection)) {
return $this->odbcRaiseError();
}
return DB_OK;
}
// }}}
// {{{ odbcRaiseError()
/**
* Produces a DB_Error object regarding the current problem
*
* @param int $errno if the error is being manually raised pass a
* DB_ERROR* constant here. If this isn't passed
* the error information gathered from the DBMS.
*
* @return object the DB_Error object
*
* @see DB_common::raiseError(),
* DB_odbc::errorNative(), DB_common::errorCode()
*/
function odbcRaiseError($errno = null)
{
if ($errno === null) {
switch ($this->dbsyntax) {
case 'access':
if ($this->options['portability'] & DB_PORTABILITY_ERRORS) {
$this->errorcode_map['07001'] = DB_ERROR_NOSUCHFIELD;
} else {
// Doing this in case mode changes during runtime.
$this->errorcode_map['07001'] = DB_ERROR_MISMATCH;
}
$native_code = odbc_error($this->connection);
// S1000 is for "General Error." Let's be more specific.
if ($native_code == 'S1000') {
$errormsg = odbc_errormsg($this->connection);
static $error_regexps;
if (!isset($error_regexps)) {
$error_regexps = array(
'/includes related records.$/i' => DB_ERROR_CONSTRAINT,
'/cannot contain a Null value/i' => DB_ERROR_CONSTRAINT_NOT_NULL,
);
}
foreach ($error_regexps as $regexp => $code) {
if (preg_match($regexp, $errormsg)) {
return $this->raiseError($code,
null, null, null,
$native_code . ' ' . $errormsg);
}
}
$errno = DB_ERROR;
} else {
$errno = $this->errorCode($native_code);
}
break;
default:
$errno = $this->errorCode(odbc_error($this->connection));
}
}
return $this->raiseError($errno, null, null, null,
$this->errorNative());
}
// }}}
// {{{ errorNative()
/**
* Gets the DBMS' native error code and message produced by the last query
*
* @return string the DBMS' error code and message
*/
function errorNative()
{
if (!is_resource($this->connection)) {
return @odbc_error() . ' ' . @odbc_errormsg();
}
return @odbc_error($this->connection) . ' ' . @odbc_errormsg($this->connection);
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* @param object|string $result DB_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::tableInfo()
* @since Method available since Release 1.7.0
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
/*
* Probably received a table name.
* Create a result resource identifier.
*/
$id = @odbc_exec($this->connection, "SELECT * FROM $result");
if (!$id) {
return $this->odbcRaiseError();
}
$got_string = true;
} elseif (isset($result->result)) {
/*
* Probably received a result object.
* Extract the result resource identifier.
*/
$id = $result->result;
$got_string = false;
} else {
/*
* Probably received a result resource identifier.
* Copy it.
* Deprecated. Here for compatibility only.
*/
$id = $result;
$got_string = false;
}
if (!is_resource($id)) {
return $this->odbcRaiseError(DB_ERROR_NEED_MORE_DATA);
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$count = @odbc_num_fields($id);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
for ($i = 0; $i < $count; $i++) {
$col = $i + 1;
$res[$i] = array(
'table' => $got_string ? $case_func($result) : '',
'name' => $case_func(@odbc_field_name($id, $col)),
'type' => @odbc_field_type($id, $col),
'len' => @odbc_field_len($id, $col),
'flags' => '',
);
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
// free the result only if we were called on a table
if ($got_string) {
@odbc_free_result($id);
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Obtains the query string needed for listing a given type of objects
*
* Thanks to symbol1@gmail.com and Philippe.Jausions@11abacus.com.
*
* @param string $type the kind of objects you want to retrieve
*
* @return string the list of objects requested
*
* @access protected
* @see DB_common::getListOf()
* @since Method available since Release 1.7.0
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'databases':
if (!function_exists('odbc_data_source')) {
return null;
}
$res = @odbc_data_source($this->connection, SQL_FETCH_FIRST);
if (is_array($res)) {
$out = array($res['server']);
while($res = @odbc_data_source($this->connection,
SQL_FETCH_NEXT))
{
$out[] = $res['server'];
}
return $out;
} else {
return $this->odbcRaiseError();
}
break;
case 'tables':
case 'schema.tables':
$keep = 'TABLE';
break;
case 'views':
$keep = 'VIEW';
break;
default:
return null;
}
/*
* Removing non-conforming items in the while loop rather than
* in the odbc_tables() call because some backends choke on this:
* odbc_tables($this->connection, '', '', '', 'TABLE')
*/
$res = @odbc_tables($this->connection);
if (!$res) {
return $this->odbcRaiseError();
}
$out = array();
while ($row = odbc_fetch_array($res)) {
if ($row['TABLE_TYPE'] != $keep) {
continue;
}
if ($type == 'schema.tables') {
$out[] = $row['TABLE_SCHEM'] . '.' . $row['TABLE_NAME'];
} else {
$out[] = $row['TABLE_NAME'];
}
}
return $out;
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>

1103
lib/pear/DB/pgsql.php Normal file

File diff suppressed because it is too large Load Diff

949
lib/pear/DB/sqlite.php Normal file
View File

@ -0,0 +1,949 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's sqlite extension
* for interacting with SQLite databases
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Urs Gehrig <urs@circle.ch>
* @author Mika Tuupola <tuupola@appelsiini.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0 3.0
* @version CVS: $Id: sqlite.php,v 1.114 2007/01/12 02:41:07 aharvey Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's sqlite extension
* for interacting with SQLite databases
*
* These methods overload the ones declared in DB_common.
*
* NOTICE: This driver needs PHP's track_errors ini setting to be on.
* It is automatically turned on when connecting to the database.
* Make sure your scripts don't turn it off.
*
* @category Database
* @package DB
* @author Urs Gehrig <urs@circle.ch>
* @author Mika Tuupola <tuupola@appelsiini.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0 3.0
* @version Release: 1.7.11
* @link http://pear.php.net/package/DB
*/
class DB_sqlite extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'sqlite';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'sqlite';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* @var array
*/
var $features = array(
'limit' => 'alter',
'new_link' => false,
'numrows' => true,
'pconnect' => true,
'prepare' => false,
'ssl' => false,
'transactions' => false,
);
/**
* A mapping of native error codes to DB error codes
*
* {@internal Error codes according to sqlite_exec. See the online
* manual at http://sqlite.org/c_interface.html for info.
* This error handling based on sqlite_exec is not yet implemented.}}
*
* @var array
*/
var $errorcode_map = array(
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
/**
* SQLite data types
*
* @link http://www.sqlite.org/datatypes.html
*
* @var array
*/
var $keywords = array (
'BLOB' => '',
'BOOLEAN' => '',
'CHARACTER' => '',
'CLOB' => '',
'FLOAT' => '',
'INTEGER' => '',
'KEY' => '',
'NATIONAL' => '',
'NUMERIC' => '',
'NVARCHAR' => '',
'PRIMARY' => '',
'TEXT' => '',
'TIMESTAMP' => '',
'UNIQUE' => '',
'VARCHAR' => '',
'VARYING' => '',
);
/**
* The most recent error message from $php_errormsg
* @var string
* @access private
*/
var $_lasterror = '';
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_sqlite()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database server, log in and open the database
*
* Don't call this method directly. Use DB::connect() instead.
*
* PEAR DB's sqlite driver supports the following extra DSN options:
* + mode The permissions for the database file, in four digit
* chmod octal format (eg "0600").
*
* Example of connecting to a database in read-only mode:
* <code>
* require_once 'DB.php';
*
* $dsn = 'sqlite:///path/and/name/of/db/file?mode=0400';
* $options = array(
* 'portability' => DB_PORTABILITY_ALL,
* );
*
* $db =& DB::connect($dsn, $options);
* if (PEAR::isError($db)) {
* die($db->getMessage());
* }
* </code>
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('sqlite')) {
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
if (!$dsn['database']) {
return $this->sqliteRaiseError(DB_ERROR_ACCESS_VIOLATION);
}
if ($dsn['database'] !== ':memory:') {
if (!file_exists($dsn['database'])) {
if (!touch($dsn['database'])) {
return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND);
}
if (!isset($dsn['mode']) ||
!is_numeric($dsn['mode']))
{
$mode = 0644;
} else {
$mode = octdec($dsn['mode']);
}
if (!chmod($dsn['database'], $mode)) {
return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND);
}
if (!file_exists($dsn['database'])) {
return $this->sqliteRaiseError(DB_ERROR_NOT_FOUND);
}
}
if (!is_file($dsn['database'])) {
return $this->sqliteRaiseError(DB_ERROR_INVALID);
}
if (!is_readable($dsn['database'])) {
return $this->sqliteRaiseError(DB_ERROR_ACCESS_VIOLATION);
}
}
$connect_function = $persistent ? 'sqlite_popen' : 'sqlite_open';
// track_errors must remain on for simpleQuery()
@ini_set('track_errors', 1);
$php_errormsg = '';
if (!$this->connection = @$connect_function($dsn['database'])) {
return $this->raiseError(DB_ERROR_NODBSELECTED,
null, null, null,
$php_errormsg);
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$ret = @sqlite_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Sends a query to the database server
*
* NOTICE: This method needs PHP's track_errors ini setting to be on.
* It is automatically turned on when connecting to the database.
* Make sure your scripts don't turn it off.
*
* @param string the SQL query string
*
* @return mixed + a PHP result resrouce for successful SELECT queries
* + the DB_OK constant for other successful queries
* + a DB_Error object on failure
*/
function simpleQuery($query)
{
$ismanip = $this->_checkManip($query);
$this->last_query = $query;
$query = $this->modifyQuery($query);
$php_errormsg = '';
$result = @sqlite_query($query, $this->connection);
$this->_lasterror = $php_errormsg ? $php_errormsg : '';
$this->result = $result;
if (!$this->result) {
return $this->sqliteRaiseError(null);
}
// sqlite_query() seems to allways return a resource
// so cant use that. Using $ismanip instead
if (!$ismanip) {
$numRows = $this->numRows($result);
if (is_object($numRows)) {
// we've got PEAR_Error
return $numRows;
}
return $result;
}
return DB_OK;
}
// }}}
// {{{ nextResult()
/**
* Move the internal sqlite result pointer to the next available result
*
* @param resource $result the valid sqlite result resource
*
* @return bool true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
if ($rownum !== null) {
if (!@sqlite_seek($this->result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
$arr = @sqlite_fetch_array($result, SQLITE_ASSOC);
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$arr = @sqlite_fetch_array($result, SQLITE_NUM);
}
if (!$arr) {
return null;
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
/*
* Even though this DBMS already trims output, we do this because
* a field might have intentional whitespace at the end that
* gets removed by DB_PORTABILITY_RTRIM under another driver.
*/
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set
*
* This method is not meant to be called directly. Use
* DB_result::free() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult(&$result)
{
// XXX No native free?
if (!is_resource($result)) {
return false;
}
$result = null;
return true;
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($result)
{
$cols = @sqlite_num_fields($result);
if (!$cols) {
return $this->sqliteRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Gets the number of rows in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numRows() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of rows. A DB_Error object on failure.
*
* @see DB_result::numRows()
*/
function numRows($result)
{
$rows = @sqlite_num_rows($result);
if ($rows === null) {
return $this->sqliteRaiseError();
}
return $rows;
}
// }}}
// {{{ affected()
/**
* Determines the number of rows affected by a data maniuplation query
*
* 0 is returned for queries that don't manipulate data.
*
* @return int the number of rows. A DB_Error object on failure.
*/
function affectedRows()
{
return @sqlite_changes($this->connection);
}
// }}}
// {{{ dropSequence()
/**
* Deletes a sequence
*
* @param string $seq_name name of the sequence to be deleted
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::dropSequence(), DB_common::getSequenceName(),
* DB_sqlite::nextID(), DB_sqlite::createSequence()
*/
function dropSequence($seq_name)
{
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
}
/**
* Creates a new sequence
*
* @param string $seq_name name of the new sequence
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::createSequence(), DB_common::getSequenceName(),
* DB_sqlite::nextID(), DB_sqlite::dropSequence()
*/
function createSequence($seq_name)
{
$seqname = $this->getSequenceName($seq_name);
$query = 'CREATE TABLE ' . $seqname .
' (id INTEGER UNSIGNED PRIMARY KEY) ';
$result = $this->query($query);
if (DB::isError($result)) {
return($result);
}
$query = "CREATE TRIGGER ${seqname}_cleanup AFTER INSERT ON $seqname
BEGIN
DELETE FROM $seqname WHERE id<LAST_INSERT_ROWID();
END ";
$result = $this->query($query);
if (DB::isError($result)) {
return($result);
}
}
// }}}
// {{{ nextId()
/**
* Returns the next free id in a sequence
*
* @param string $seq_name name of the sequence
* @param boolean $ondemand when true, the seqence is automatically
* created if it does not exist
*
* @return int the next id number in the sequence.
* A DB_Error object on failure.
*
* @see DB_common::nextID(), DB_common::getSequenceName(),
* DB_sqlite::createSequence(), DB_sqlite::dropSequence()
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
do {
$repeat = 0;
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("INSERT INTO $seqname (id) VALUES (NULL)");
$this->popErrorHandling();
if ($result === DB_OK) {
$id = @sqlite_last_insert_rowid($this->connection);
if ($id != 0) {
return $id;
}
} elseif ($ondemand && DB::isError($result) &&
$result->getCode() == DB_ERROR_NOSUCHTABLE)
{
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $this->raiseError($result);
} else {
$repeat = 1;
}
}
} while ($repeat);
return $this->raiseError($result);
}
// }}}
// {{{ getDbFileStats()
/**
* Get the file stats for the current database
*
* Possible arguments are dev, ino, mode, nlink, uid, gid, rdev, size,
* atime, mtime, ctime, blksize, blocks or a numeric key between
* 0 and 12.
*
* @param string $arg the array key for stats()
*
* @return mixed an array on an unspecified key, integer on a passed
* arg and false at a stats error
*/
function getDbFileStats($arg = '')
{
$stats = stat($this->dsn['database']);
if ($stats == false) {
return false;
}
if (is_array($stats)) {
if (is_numeric($arg)) {
if (((int)$arg <= 12) & ((int)$arg >= 0)) {
return false;
}
return $stats[$arg ];
}
if (array_key_exists(trim($arg), $stats)) {
return $stats[$arg ];
}
}
return $stats;
}
// }}}
// {{{ escapeSimple()
/**
* Escapes a string according to the current DBMS's standards
*
* In SQLite, this makes things safe for inserts/updates, but may
* cause problems when performing text comparisons against columns
* containing binary data. See the
* {@link http://php.net/sqlite_escape_string PHP manual} for more info.
*
* @param string $str the string to be escaped
*
* @return string the escaped string
*
* @since Method available since Release 1.6.1
* @see DB_common::escapeSimple()
*/
function escapeSimple($str)
{
return @sqlite_escape_string($str);
}
// }}}
// {{{ modifyLimitQuery()
/**
* Adds LIMIT clauses to a query string according to current DBMS standards
*
* @param string $query the query to modify
* @param int $from the row to start to fetching (0 = the first row)
* @param int $count the numbers of rows to fetch
* @param mixed $params array, string or numeric data to be used in
* execution of the statement. Quantity of items
* passed must match quantity of placeholders in
* query: meaning 1 placeholder for non-array
* parameters or 1 placeholder per array element.
*
* @return string the query string with LIMIT clauses added
*
* @access protected
*/
function modifyLimitQuery($query, $from, $count, $params = array())
{
return "$query LIMIT $count OFFSET $from";
}
// }}}
// {{{ modifyQuery()
/**
* Changes a query string for various DBMS specific reasons
*
* This little hack lets you know how many rows were deleted
* when running a "DELETE FROM table" query. Only implemented
* if the DB_PORTABILITY_DELETE_COUNT portability option is on.
*
* @param string $query the query string to modify
*
* @return string the modified query string
*
* @access protected
* @see DB_common::setOption()
*/
function modifyQuery($query)
{
if ($this->options['portability'] & DB_PORTABILITY_DELETE_COUNT) {
if (preg_match('/^\s*DELETE\s+FROM\s+(\S+)\s*$/i', $query)) {
$query = preg_replace('/^\s*DELETE\s+FROM\s+(\S+)\s*$/',
'DELETE FROM \1 WHERE 1=1', $query);
}
}
return $query;
}
// }}}
// {{{ sqliteRaiseError()
/**
* Produces a DB_Error object regarding the current problem
*
* @param int $errno if the error is being manually raised pass a
* DB_ERROR* constant here. If this isn't passed
* the error information gathered from the DBMS.
*
* @return object the DB_Error object
*
* @see DB_common::raiseError(),
* DB_sqlite::errorNative(), DB_sqlite::errorCode()
*/
function sqliteRaiseError($errno = null)
{
$native = $this->errorNative();
if ($errno === null) {
$errno = $this->errorCode($native);
}
$errorcode = @sqlite_last_error($this->connection);
$userinfo = "$errorcode ** $this->last_query";
return $this->raiseError($errno, null, null, $userinfo, $native);
}
// }}}
// {{{ errorNative()
/**
* Gets the DBMS' native error message produced by the last query
*
* {@internal This is used to retrieve more meaningfull error messages
* because sqlite_last_error() does not provide adequate info.}}
*
* @return string the DBMS' error message
*/
function errorNative()
{
return $this->_lasterror;
}
// }}}
// {{{ errorCode()
/**
* Determines PEAR::DB error code from the database's text error message
*
* @param string $errormsg the error message returned from the database
*
* @return integer the DB error number
*/
function errorCode($errormsg)
{
static $error_regexps;
// PHP 5.2+ prepends the function name to $php_errormsg, so we need
// this hack to work around it, per bug #9599.
$errormsg = preg_replace('/^sqlite[a-z_]+\(\): /', '', $errormsg);
if (!isset($error_regexps)) {
$error_regexps = array(
'/^no such table:/' => DB_ERROR_NOSUCHTABLE,
'/^no such index:/' => DB_ERROR_NOT_FOUND,
'/^(table|index) .* already exists$/' => DB_ERROR_ALREADY_EXISTS,
'/PRIMARY KEY must be unique/i' => DB_ERROR_CONSTRAINT,
'/is not unique/' => DB_ERROR_CONSTRAINT,
'/columns .* are not unique/i' => DB_ERROR_CONSTRAINT,
'/uniqueness constraint failed/' => DB_ERROR_CONSTRAINT,
'/may not be NULL/' => DB_ERROR_CONSTRAINT_NOT_NULL,
'/^no such column:/' => DB_ERROR_NOSUCHFIELD,
'/column not present in both tables/i' => DB_ERROR_NOSUCHFIELD,
'/^near ".*": syntax error$/' => DB_ERROR_SYNTAX,
'/[0-9]+ values for [0-9]+ columns/i' => DB_ERROR_VALUE_COUNT_ON_ROW,
);
}
foreach ($error_regexps as $regexp => $code) {
if (preg_match($regexp, $errormsg)) {
return $code;
}
}
// Fall back to DB_ERROR if there was no mapping.
return DB_ERROR;
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table
*
* @param string $result a string containing the name of a table
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::tableInfo()
* @since Method available since Release 1.7.0
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
/*
* Probably received a table name.
* Create a result resource identifier.
*/
$id = @sqlite_array_query($this->connection,
"PRAGMA table_info('$result');",
SQLITE_ASSOC);
$got_string = true;
} else {
$this->last_query = '';
return $this->raiseError(DB_ERROR_NOT_CAPABLE, null, null, null,
'This DBMS can not obtain tableInfo' .
' from result sets');
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$count = count($id);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
for ($i = 0; $i < $count; $i++) {
if (strpos($id[$i]['type'], '(') !== false) {
$bits = explode('(', $id[$i]['type']);
$type = $bits[0];
$len = rtrim($bits[1],')');
} else {
$type = $id[$i]['type'];
$len = 0;
}
$flags = '';
if ($id[$i]['pk']) {
$flags .= 'primary_key ';
}
if ($id[$i]['notnull']) {
$flags .= 'not_null ';
}
if ($id[$i]['dflt_value'] !== null) {
$flags .= 'default_' . rawurlencode($id[$i]['dflt_value']);
}
$flags = trim($flags);
$res[$i] = array(
'table' => $case_func($result),
'name' => $case_func($id[$i]['name']),
'type' => $type,
'len' => $len,
'flags' => $flags,
);
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
return $res;
}
// }}}
// {{{ getSpecialQuery()
/**
* Obtains the query string needed for listing a given type of objects
*
* @param string $type the kind of objects you want to retrieve
* @param array $args SQLITE DRIVER ONLY: a private array of arguments
* used by the getSpecialQuery(). Do not use
* this directly.
*
* @return string the SQL query string or null if the driver doesn't
* support the object type requested
*
* @access protected
* @see DB_common::getListOf()
*/
function getSpecialQuery($type, $args = array())
{
if (!is_array($args)) {
return $this->raiseError('no key specified', null, null, null,
'Argument has to be an array.');
}
switch ($type) {
case 'master':
return 'SELECT * FROM sqlite_master;';
case 'tables':
return "SELECT name FROM sqlite_master WHERE type='table' "
. 'UNION ALL SELECT name FROM sqlite_temp_master '
. "WHERE type='table' ORDER BY name;";
case 'schema':
return 'SELECT sql FROM (SELECT * FROM sqlite_master '
. 'UNION ALL SELECT * FROM sqlite_temp_master) '
. "WHERE type!='meta' "
. 'ORDER BY tbl_name, type DESC, name;';
case 'schemax':
case 'schema_x':
/*
* Use like:
* $res = $db->query($db->getSpecialQuery('schema_x',
* array('table' => 'table3')));
*/
return 'SELECT sql FROM (SELECT * FROM sqlite_master '
. 'UNION ALL SELECT * FROM sqlite_temp_master) '
. "WHERE tbl_name LIKE '{$args['table']}' "
. "AND type!='meta' "
. 'ORDER BY type DESC, name;';
case 'alter':
/*
* SQLite does not support ALTER TABLE; this is a helper query
* to handle this. 'table' represents the table name, 'rows'
* the news rows to create, 'save' the row(s) to keep _with_
* the data.
*
* Use like:
* $args = array(
* 'table' => $table,
* 'rows' => "id INTEGER PRIMARY KEY, firstname TEXT, surname TEXT, datetime TEXT",
* 'save' => "NULL, titel, content, datetime"
* );
* $res = $db->query( $db->getSpecialQuery('alter', $args));
*/
$rows = strtr($args['rows'], $this->keywords);
$q = array(
'BEGIN TRANSACTION',
"CREATE TEMPORARY TABLE {$args['table']}_backup ({$args['rows']})",
"INSERT INTO {$args['table']}_backup SELECT {$args['save']} FROM {$args['table']}",
"DROP TABLE {$args['table']}",
"CREATE TABLE {$args['table']} ({$args['rows']})",
"INSERT INTO {$args['table']} SELECT {$rows} FROM {$args['table']}_backup",
"DROP TABLE {$args['table']}_backup",
'COMMIT',
);
/*
* This is a dirty hack, since the above query will not get
* executed with a single query call so here the query method
* will be called directly and return a select instead.
*/
foreach ($q as $query) {
$this->query($query);
}
return "SELECT * FROM {$args['table']};";
default:
return null;
}
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>

506
lib/pear/DB/storage.php Normal file
View File

@ -0,0 +1,506 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* Provides an object interface to a table row
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Stig Bakken <stig@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: storage.php,v 1.22 2005/07/10 13:38:51 danielc Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB class so it can be extended from
*/
require_once 'DB.php';
/**
* Provides an object interface to a table row
*
* It lets you add, delete and change rows using objects rather than SQL
* statements.
*
* @category Database
* @package DB
* @author Stig Bakken <stig@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.11
* @link http://pear.php.net/package/DB
*/
class DB_storage extends PEAR
{
// {{{ properties
/** the name of the table (or view, if the backend database supports
updates in views) we hold data from */
var $_table = null;
/** which column(s) in the table contains primary keys, can be a
string for single-column primary keys, or an array of strings
for multiple-column primary keys */
var $_keycolumn = null;
/** DB connection handle used for all transactions */
var $_dbh = null;
/** an assoc with the names of database fields stored as properties
in this object */
var $_properties = array();
/** an assoc with the names of the properties in this object that
have been changed since they were fetched from the database */
var $_changes = array();
/** flag that decides if data in this object can be changed.
objects that don't have their table's key column in their
property lists will be flagged as read-only. */
var $_readonly = false;
/** function or method that implements a validator for fields that
are set, this validator function returns true if the field is
valid, false if not */
var $_validator = null;
// }}}
// {{{ constructor
/**
* Constructor
*
* @param $table string the name of the database table
*
* @param $keycolumn mixed string with name of key column, or array of
* strings if the table has a primary key of more than one column
*
* @param $dbh object database connection object
*
* @param $validator mixed function or method used to validate
* each new value, called with three parameters: the name of the
* field/column that is changing, a reference to the new value and
* a reference to this object
*
*/
function DB_storage($table, $keycolumn, &$dbh, $validator = null)
{
$this->PEAR('DB_Error');
$this->_table = $table;
$this->_keycolumn = $keycolumn;
$this->_dbh = $dbh;
$this->_readonly = false;
$this->_validator = $validator;
}
// }}}
// {{{ _makeWhere()
/**
* Utility method to build a "WHERE" clause to locate ourselves in
* the table.
*
* XXX future improvement: use rowids?
*
* @access private
*/
function _makeWhere($keyval = null)
{
if (is_array($this->_keycolumn)) {
if ($keyval === null) {
for ($i = 0; $i < sizeof($this->_keycolumn); $i++) {
$keyval[] = $this->{$this->_keycolumn[$i]};
}
}
$whereclause = '';
for ($i = 0; $i < sizeof($this->_keycolumn); $i++) {
if ($i > 0) {
$whereclause .= ' AND ';
}
$whereclause .= $this->_keycolumn[$i];
if (is_null($keyval[$i])) {
// there's not much point in having a NULL key,
// but we support it anyway
$whereclause .= ' IS NULL';
} else {
$whereclause .= ' = ' . $this->_dbh->quote($keyval[$i]);
}
}
} else {
if ($keyval === null) {
$keyval = @$this->{$this->_keycolumn};
}
$whereclause = $this->_keycolumn;
if (is_null($keyval)) {
// there's not much point in having a NULL key,
// but we support it anyway
$whereclause .= ' IS NULL';
} else {
$whereclause .= ' = ' . $this->_dbh->quote($keyval);
}
}
return $whereclause;
}
// }}}
// {{{ setup()
/**
* Method used to initialize a DB_storage object from the
* configured table.
*
* @param $keyval mixed the key[s] of the row to fetch (string or array)
*
* @return int DB_OK on success, a DB error if not
*/
function setup($keyval)
{
$whereclause = $this->_makeWhere($keyval);
$query = 'SELECT * FROM ' . $this->_table . ' WHERE ' . $whereclause;
$sth = $this->_dbh->query($query);
if (DB::isError($sth)) {
return $sth;
}
$row = $sth->fetchRow(DB_FETCHMODE_ASSOC);
if (DB::isError($row)) {
return $row;
}
if (!$row) {
return $this->raiseError(null, DB_ERROR_NOT_FOUND, null, null,
$query, null, true);
}
foreach ($row as $key => $value) {
$this->_properties[$key] = true;
$this->$key = $value;
}
return DB_OK;
}
// }}}
// {{{ insert()
/**
* Create a new (empty) row in the configured table for this
* object.
*/
function insert($newpk)
{
if (is_array($this->_keycolumn)) {
$primarykey = $this->_keycolumn;
} else {
$primarykey = array($this->_keycolumn);
}
settype($newpk, "array");
for ($i = 0; $i < sizeof($primarykey); $i++) {
$pkvals[] = $this->_dbh->quote($newpk[$i]);
}
$sth = $this->_dbh->query("INSERT INTO $this->_table (" .
implode(",", $primarykey) . ") VALUES(" .
implode(",", $pkvals) . ")");
if (DB::isError($sth)) {
return $sth;
}
if (sizeof($newpk) == 1) {
$newpk = $newpk[0];
}
$this->setup($newpk);
}
// }}}
// {{{ toString()
/**
* Output a simple description of this DB_storage object.
* @return string object description
*/
function toString()
{
$info = strtolower(get_class($this));
$info .= " (table=";
$info .= $this->_table;
$info .= ", keycolumn=";
if (is_array($this->_keycolumn)) {
$info .= "(" . implode(",", $this->_keycolumn) . ")";
} else {
$info .= $this->_keycolumn;
}
$info .= ", dbh=";
if (is_object($this->_dbh)) {
$info .= $this->_dbh->toString();
} else {
$info .= "null";
}
$info .= ")";
if (sizeof($this->_properties)) {
$info .= " [loaded, key=";
$keyname = $this->_keycolumn;
if (is_array($keyname)) {
$info .= "(";
for ($i = 0; $i < sizeof($keyname); $i++) {
if ($i > 0) {
$info .= ",";
}
$info .= $this->$keyname[$i];
}
$info .= ")";
} else {
$info .= $this->$keyname;
}
$info .= "]";
}
if (sizeof($this->_changes)) {
$info .= " [modified]";
}
return $info;
}
// }}}
// {{{ dump()
/**
* Dump the contents of this object to "standard output".
*/
function dump()
{
foreach ($this->_properties as $prop => $foo) {
print "$prop = ";
print htmlentities($this->$prop);
print "<br />\n";
}
}
// }}}
// {{{ &create()
/**
* Static method used to create new DB storage objects.
* @param $data assoc. array where the keys are the names
* of properties/columns
* @return object a new instance of DB_storage or a subclass of it
*/
function &create($table, &$data)
{
$classname = strtolower(get_class($this));
$obj =& new $classname($table);
foreach ($data as $name => $value) {
$obj->_properties[$name] = true;
$obj->$name = &$value;
}
return $obj;
}
// }}}
// {{{ loadFromQuery()
/**
* Loads data into this object from the given query. If this
* object already contains table data, changes will be saved and
* the object re-initialized first.
*
* @param $query SQL query
*
* @param $params parameter list in case you want to use
* prepare/execute mode
*
* @return int DB_OK on success, DB_WARNING_READ_ONLY if the
* returned object is read-only (because the object's specified
* key column was not found among the columns returned by $query),
* or another DB error code in case of errors.
*/
// XXX commented out for now
/*
function loadFromQuery($query, $params = null)
{
if (sizeof($this->_properties)) {
if (sizeof($this->_changes)) {
$this->store();
$this->_changes = array();
}
$this->_properties = array();
}
$rowdata = $this->_dbh->getRow($query, DB_FETCHMODE_ASSOC, $params);
if (DB::isError($rowdata)) {
return $rowdata;
}
reset($rowdata);
$found_keycolumn = false;
while (list($key, $value) = each($rowdata)) {
if ($key == $this->_keycolumn) {
$found_keycolumn = true;
}
$this->_properties[$key] = true;
$this->$key = &$value;
unset($value); // have to unset, or all properties will
// refer to the same value
}
if (!$found_keycolumn) {
$this->_readonly = true;
return DB_WARNING_READ_ONLY;
}
return DB_OK;
}
*/
// }}}
// {{{ set()
/**
* Modify an attriute value.
*/
function set($property, $newvalue)
{
// only change if $property is known and object is not
// read-only
if ($this->_readonly) {
return $this->raiseError(null, DB_WARNING_READ_ONLY, null,
null, null, null, true);
}
if (@isset($this->_properties[$property])) {
if (empty($this->_validator)) {
$valid = true;
} else {
$valid = @call_user_func($this->_validator,
$this->_table,
$property,
$newvalue,
$this->$property,
$this);
}
if ($valid) {
$this->$property = $newvalue;
if (empty($this->_changes[$property])) {
$this->_changes[$property] = 0;
} else {
$this->_changes[$property]++;
}
} else {
return $this->raiseError(null, DB_ERROR_INVALID, null,
null, "invalid field: $property",
null, true);
}
return true;
}
return $this->raiseError(null, DB_ERROR_NOSUCHFIELD, null,
null, "unknown field: $property",
null, true);
}
// }}}
// {{{ &get()
/**
* Fetch an attribute value.
*
* @param string attribute name
*
* @return attribute contents, or null if the attribute name is
* unknown
*/
function &get($property)
{
// only return if $property is known
if (isset($this->_properties[$property])) {
return $this->$property;
}
$tmp = null;
return $tmp;
}
// }}}
// {{{ _DB_storage()
/**
* Destructor, calls DB_storage::store() if there are changes
* that are to be kept.
*/
function _DB_storage()
{
if (sizeof($this->_changes)) {
$this->store();
}
$this->_properties = array();
$this->_changes = array();
$this->_table = null;
}
// }}}
// {{{ store()
/**
* Stores changes to this object in the database.
*
* @return DB_OK or a DB error
*/
function store()
{
$params = array();
$vars = array();
foreach ($this->_changes as $name => $foo) {
$params[] = &$this->$name;
$vars[] = $name . ' = ?';
}
if ($vars) {
$query = 'UPDATE ' . $this->_table . ' SET ' .
implode(', ', $vars) . ' WHERE ' .
$this->_makeWhere();
$stmt = $this->_dbh->prepare($query);
$res = $this->_dbh->execute($stmt, $params);
if (DB::isError($res)) {
return $res;
}
$this->_changes = array();
}
return DB_OK;
}
// }}}
// {{{ remove()
/**
* Remove the row represented by this object from the database.
*
* @return mixed DB_OK or a DB error
*/
function remove()
{
if ($this->_readonly) {
return $this->raiseError(null, DB_WARNING_READ_ONLY, null,
null, null, null, true);
}
$query = 'DELETE FROM ' . $this->_table .' WHERE '.
$this->_makeWhere();
$res = $this->_dbh->query($query);
if (DB::isError($res)) {
return $res;
}
foreach ($this->_properties as $prop => $foo) {
unset($this->$prop);
}
$this->_properties = array();
$this->_changes = array();
return DB_OK;
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>

942
lib/pear/DB/sybase.php Normal file
View File

@ -0,0 +1,942 @@
<?php
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
/**
* The PEAR DB driver for PHP's sybase extension
* for interacting with Sybase databases
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category Database
* @package DB
* @author Sterling Hughes <sterling@php.net>
* @author Antônio Carlos Venâncio Júnior <floripa@php.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: sybase.php,v 1.85 2007/02/06 07:35:07 aharvey Exp $
* @link http://pear.php.net/package/DB
*/
/**
* Obtain the DB_common class so it can be extended from
*/
require_once 'DB/common.php';
/**
* The methods PEAR DB uses to interact with PHP's sybase extension
* for interacting with Sybase databases
*
* These methods overload the ones declared in DB_common.
*
* WARNING: This driver may fail with multiple connections under the
* same user/pass/host and different databases.
*
* @category Database
* @package DB
* @author Sterling Hughes <sterling@php.net>
* @author Antônio Carlos Venâncio Júnior <floripa@php.net>
* @author Daniel Convissor <danielc@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.7.11
* @link http://pear.php.net/package/DB
*/
class DB_sybase extends DB_common
{
// {{{ properties
/**
* The DB driver type (mysql, oci8, odbc, etc.)
* @var string
*/
var $phptype = 'sybase';
/**
* The database syntax variant to be used (db2, access, etc.), if any
* @var string
*/
var $dbsyntax = 'sybase';
/**
* The capabilities of this DB implementation
*
* The 'new_link' element contains the PHP version that first provided
* new_link support for this DBMS. Contains false if it's unsupported.
*
* Meaning of the 'limit' element:
* + 'emulate' = emulate with fetch row by number
* + 'alter' = alter the query
* + false = skip rows
*
* @var array
*/
var $features = array(
'limit' => 'emulate',
'new_link' => false,
'numrows' => true,
'pconnect' => true,
'prepare' => false,
'ssl' => false,
'transactions' => true,
);
/**
* A mapping of native error codes to DB error codes
* @var array
*/
var $errorcode_map = array(
);
/**
* The raw database connection created by PHP
* @var resource
*/
var $connection;
/**
* The DSN information for connecting to a database
* @var array
*/
var $dsn = array();
/**
* Should data manipulation queries be committed automatically?
* @var bool
* @access private
*/
var $autocommit = true;
/**
* The quantity of transactions begun
*
* {@internal While this is private, it can't actually be designated
* private in PHP 5 because it is directly accessed in the test suite.}}
*
* @var integer
* @access private
*/
var $transaction_opcount = 0;
/**
* The database specified in the DSN
*
* It's a fix to allow calls to different databases in the same script.
*
* @var string
* @access private
*/
var $_db = '';
// }}}
// {{{ constructor
/**
* This constructor calls <kbd>$this->DB_common()</kbd>
*
* @return void
*/
function DB_sybase()
{
$this->DB_common();
}
// }}}
// {{{ connect()
/**
* Connect to the database server, log in and open the database
*
* Don't call this method directly. Use DB::connect() instead.
*
* PEAR DB's sybase driver supports the following extra DSN options:
* + appname The application name to use on this connection.
* Available since PEAR DB 1.7.0.
* + charset The character set to use on this connection.
* Available since PEAR DB 1.7.0.
*
* @param array $dsn the data source name
* @param bool $persistent should the connection be persistent?
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function connect($dsn, $persistent = false)
{
if (!PEAR::loadExtension('sybase') &&
!PEAR::loadExtension('sybase_ct'))
{
return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
}
$this->dsn = $dsn;
if ($dsn['dbsyntax']) {
$this->dbsyntax = $dsn['dbsyntax'];
}
$dsn['hostspec'] = $dsn['hostspec'] ? $dsn['hostspec'] : 'localhost';
$dsn['password'] = !empty($dsn['password']) ? $dsn['password'] : false;
$dsn['charset'] = isset($dsn['charset']) ? $dsn['charset'] : false;
$dsn['appname'] = isset($dsn['appname']) ? $dsn['appname'] : false;
$connect_function = $persistent ? 'sybase_pconnect' : 'sybase_connect';
if ($dsn['username']) {
$this->connection = @$connect_function($dsn['hostspec'],
$dsn['username'],
$dsn['password'],
$dsn['charset'],
$dsn['appname']);
} else {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
'The DSN did not contain a username.');
}
if (!$this->connection) {
return $this->raiseError(DB_ERROR_CONNECT_FAILED,
null, null, null,
@sybase_get_last_message());
}
if ($dsn['database']) {
if (!@sybase_select_db($dsn['database'], $this->connection)) {
return $this->raiseError(DB_ERROR_NODBSELECTED,
null, null, null,
@sybase_get_last_message());
}
$this->_db = $dsn['database'];
}
return DB_OK;
}
// }}}
// {{{ disconnect()
/**
* Disconnects from the database server
*
* @return bool TRUE on success, FALSE on failure
*/
function disconnect()
{
$ret = @sybase_close($this->connection);
$this->connection = null;
return $ret;
}
// }}}
// {{{ simpleQuery()
/**
* Sends a query to the database server
*
* @param string the SQL query string
*
* @return mixed + a PHP result resrouce for successful SELECT queries
* + the DB_OK constant for other successful queries
* + a DB_Error object on failure
*/
function simpleQuery($query)
{
$ismanip = $this->_checkManip($query);
$this->last_query = $query;
if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
}
$query = $this->modifyQuery($query);
if (!$this->autocommit && $ismanip) {
if ($this->transaction_opcount == 0) {
$result = @sybase_query('BEGIN TRANSACTION', $this->connection);
if (!$result) {
return $this->sybaseRaiseError();
}
}
$this->transaction_opcount++;
}
$result = @sybase_query($query, $this->connection);
if (!$result) {
return $this->sybaseRaiseError();
}
if (is_resource($result)) {
return $result;
}
// Determine which queries that should return data, and which
// should return an error code only.
return $ismanip ? DB_OK : $result;
}
// }}}
// {{{ nextResult()
/**
* Move the internal sybase result pointer to the next available result
*
* @param a valid sybase result resource
*
* @access public
*
* @return true if a result is available otherwise return false
*/
function nextResult($result)
{
return false;
}
// }}}
// {{{ fetchInto()
/**
* Places a row from the result set into the given array
*
* Formating of the array and the data therein are configurable.
* See DB_result::fetchInto() for more information.
*
* This method is not meant to be called directly. Use
* DB_result::fetchInto() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result the query result resource
* @param array $arr the referenced array to put the data in
* @param int $fetchmode how the resulting array should be indexed
* @param int $rownum the row number to fetch (0 = first row)
*
* @return mixed DB_OK on success, NULL when the end of a result set is
* reached or on failure
*
* @see DB_result::fetchInto()
*/
function fetchInto($result, &$arr, $fetchmode, $rownum = null)
{
if ($rownum !== null) {
if (!@sybase_data_seek($result, $rownum)) {
return null;
}
}
if ($fetchmode & DB_FETCHMODE_ASSOC) {
if (function_exists('sybase_fetch_assoc')) {
$arr = @sybase_fetch_assoc($result);
} else {
if ($arr = @sybase_fetch_array($result)) {
foreach ($arr as $key => $value) {
if (is_int($key)) {
unset($arr[$key]);
}
}
}
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
$arr = array_change_key_case($arr, CASE_LOWER);
}
} else {
$arr = @sybase_fetch_row($result);
}
if (!$arr) {
return null;
}
if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
$this->_rtrimArrayValues($arr);
}
if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
$this->_convertNullArrayValuesToEmpty($arr);
}
return DB_OK;
}
// }}}
// {{{ freeResult()
/**
* Deletes the result set and frees the memory occupied by the result set
*
* This method is not meant to be called directly. Use
* DB_result::free() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return bool TRUE on success, FALSE if $result is invalid
*
* @see DB_result::free()
*/
function freeResult($result)
{
return is_resource($result) ? sybase_free_result($result) : false;
}
// }}}
// {{{ numCols()
/**
* Gets the number of columns in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numCols() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of columns. A DB_Error object on failure.
*
* @see DB_result::numCols()
*/
function numCols($result)
{
$cols = @sybase_num_fields($result);
if (!$cols) {
return $this->sybaseRaiseError();
}
return $cols;
}
// }}}
// {{{ numRows()
/**
* Gets the number of rows in a result set
*
* This method is not meant to be called directly. Use
* DB_result::numRows() instead. It can't be declared "protected"
* because DB_result is a separate object.
*
* @param resource $result PHP's query result resource
*
* @return int the number of rows. A DB_Error object on failure.
*
* @see DB_result::numRows()
*/
function numRows($result)
{
$rows = @sybase_num_rows($result);
if ($rows === false) {
return $this->sybaseRaiseError();
}
return $rows;
}
// }}}
// {{{ affectedRows()
/**
* Determines the number of rows affected by a data maniuplation query
*
* 0 is returned for queries that don't manipulate data.
*
* @return int the number of rows. A DB_Error object on failure.
*/
function affectedRows()
{
if ($this->_last_query_manip) {
$result = @sybase_affected_rows($this->connection);
} else {
$result = 0;
}
return $result;
}
// }}}
// {{{ nextId()
/**
* Returns the next free id in a sequence
*
* @param string $seq_name name of the sequence
* @param boolean $ondemand when true, the seqence is automatically
* created if it does not exist
*
* @return int the next id number in the sequence.
* A DB_Error object on failure.
*
* @see DB_common::nextID(), DB_common::getSequenceName(),
* DB_sybase::createSequence(), DB_sybase::dropSequence()
*/
function nextId($seq_name, $ondemand = true)
{
$seqname = $this->getSequenceName($seq_name);
if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
}
$repeat = 0;
do {
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)");
$this->popErrorHandling();
if ($ondemand && DB::isError($result) &&
($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE))
{
$repeat = 1;
$result = $this->createSequence($seq_name);
if (DB::isError($result)) {
return $this->raiseError($result);
}
} elseif (!DB::isError($result)) {
$result =& $this->query("SELECT @@IDENTITY FROM $seqname");
$repeat = 0;
} else {
$repeat = false;
}
} while ($repeat);
if (DB::isError($result)) {
return $this->raiseError($result);
}
$result = $result->fetchRow(DB_FETCHMODE_ORDERED);
return $result[0];
}
/**
* Creates a new sequence
*
* @param string $seq_name name of the new sequence
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::createSequence(), DB_common::getSequenceName(),
* DB_sybase::nextID(), DB_sybase::dropSequence()
*/
function createSequence($seq_name)
{
return $this->query('CREATE TABLE '
. $this->getSequenceName($seq_name)
. ' (id numeric(10, 0) IDENTITY NOT NULL,'
. ' vapor int NULL)');
}
// }}}
// {{{ dropSequence()
/**
* Deletes a sequence
*
* @param string $seq_name name of the sequence to be deleted
*
* @return int DB_OK on success. A DB_Error object on failure.
*
* @see DB_common::dropSequence(), DB_common::getSequenceName(),
* DB_sybase::nextID(), DB_sybase::createSequence()
*/
function dropSequence($seq_name)
{
return $this->query('DROP TABLE ' . $this->getSequenceName($seq_name));
}
// }}}
// {{{ quoteFloat()
/**
* Formats a float value for use within a query in a locale-independent
* manner.
*
* @param float the float value to be quoted.
* @return string the quoted string.
* @see DB_common::quoteSmart()
* @since Method available since release 1.7.8.
*/
function quoteFloat($float) {
return $this->escapeSimple(str_replace(',', '.', strval(floatval($float))));
}
// }}}
// {{{ autoCommit()
/**
* Enables or disables automatic commits
*
* @param bool $onoff true turns it on, false turns it off
*
* @return int DB_OK on success. A DB_Error object if the driver
* doesn't support auto-committing transactions.
*/
function autoCommit($onoff = false)
{
// XXX if $this->transaction_opcount > 0, we should probably
// issue a warning here.
$this->autocommit = $onoff ? true : false;
return DB_OK;
}
// }}}
// {{{ commit()
/**
* Commits the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function commit()
{
if ($this->transaction_opcount > 0) {
if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
}
$result = @sybase_query('COMMIT', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->sybaseRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ rollback()
/**
* Reverts the current transaction
*
* @return int DB_OK on success. A DB_Error object on failure.
*/
function rollback()
{
if ($this->transaction_opcount > 0) {
if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
}
$result = @sybase_query('ROLLBACK', $this->connection);
$this->transaction_opcount = 0;
if (!$result) {
return $this->sybaseRaiseError();
}
}
return DB_OK;
}
// }}}
// {{{ sybaseRaiseError()
/**
* Produces a DB_Error object regarding the current problem
*
* @param int $errno if the error is being manually raised pass a
* DB_ERROR* constant here. If this isn't passed
* the error information gathered from the DBMS.
*
* @return object the DB_Error object
*
* @see DB_common::raiseError(),
* DB_sybase::errorNative(), DB_sybase::errorCode()
*/
function sybaseRaiseError($errno = null)
{
$native = $this->errorNative();
if ($errno === null) {
$errno = $this->errorCode($native);
}
return $this->raiseError($errno, null, null, null, $native);
}
// }}}
// {{{ errorNative()
/**
* Gets the DBMS' native error message produced by the last query
*
* @return string the DBMS' error message
*/
function errorNative()
{
return @sybase_get_last_message();
}
// }}}
// {{{ errorCode()
/**
* Determines PEAR::DB error code from the database's text error message.
*
* @param string $errormsg error message returned from the database
* @return integer an error number from a DB error constant
*/
function errorCode($errormsg)
{
static $error_regexps;
// PHP 5.2+ prepends the function name to $php_errormsg, so we need
// this hack to work around it, per bug #9599.
$errormsg = preg_replace('/^sybase[a-z_]+\(\): /', '', $errormsg);
if (!isset($error_regexps)) {
$error_regexps = array(
'/Incorrect syntax near/'
=> DB_ERROR_SYNTAX,
'/^Unclosed quote before the character string [\"\'].*[\"\']\./'
=> DB_ERROR_SYNTAX,
'/Implicit conversion (from datatype|of NUMERIC value)/i'
=> DB_ERROR_INVALID_NUMBER,
'/Cannot drop the table [\"\'].+[\"\'], because it doesn\'t exist in the system catalogs\./'
=> DB_ERROR_NOSUCHTABLE,
'/Only the owner of object [\"\'].+[\"\'] or a user with System Administrator \(SA\) role can run this command\./'
=> DB_ERROR_ACCESS_VIOLATION,
'/^.+ permission denied on object .+, database .+, owner .+/'
=> DB_ERROR_ACCESS_VIOLATION,
'/^.* permission denied, database .+, owner .+/'
=> DB_ERROR_ACCESS_VIOLATION,
'/[^.*] not found\./'
=> DB_ERROR_NOSUCHTABLE,
'/There is already an object named/'
=> DB_ERROR_ALREADY_EXISTS,
'/Invalid column name/'
=> DB_ERROR_NOSUCHFIELD,
'/does not allow null values/'
=> DB_ERROR_CONSTRAINT_NOT_NULL,
'/Command has been aborted/'
=> DB_ERROR_CONSTRAINT,
'/^Cannot drop the index .* because it doesn\'t exist/i'
=> DB_ERROR_NOT_FOUND,
'/^There is already an index/i'
=> DB_ERROR_ALREADY_EXISTS,
'/^There are fewer columns in the INSERT statement than values specified/i'
=> DB_ERROR_VALUE_COUNT_ON_ROW,
'/Divide by zero/i'
=> DB_ERROR_DIVZERO,
);
}
foreach ($error_regexps as $regexp => $code) {
if (preg_match($regexp, $errormsg)) {
return $code;
}
}
return DB_ERROR;
}
// }}}
// {{{ tableInfo()
/**
* Returns information about a table or a result set
*
* NOTE: only supports 'table' and 'flags' if <var>$result</var>
* is a table name.
*
* @param object|string $result DB_result object from a query or a
* string containing the name of a table.
* While this also accepts a query result
* resource identifier, this behavior is
* deprecated.
* @param int $mode a valid tableInfo mode
*
* @return array an associative array with the information requested.
* A DB_Error object on failure.
*
* @see DB_common::tableInfo()
* @since Method available since Release 1.6.0
*/
function tableInfo($result, $mode = null)
{
if (is_string($result)) {
/*
* Probably received a table name.
* Create a result resource identifier.
*/
if ($this->_db && !@sybase_select_db($this->_db, $this->connection)) {
return $this->sybaseRaiseError(DB_ERROR_NODBSELECTED);
}
$id = @sybase_query("SELECT * FROM $result WHERE 1=0",
$this->connection);
$got_string = true;
} elseif (isset($result->result)) {
/*
* Probably received a result object.
* Extract the result resource identifier.
*/
$id = $result->result;
$got_string = false;
} else {
/*
* Probably received a result resource identifier.
* Copy it.
* Deprecated. Here for compatibility only.
*/
$id = $result;
$got_string = false;
}
if (!is_resource($id)) {
return $this->sybaseRaiseError(DB_ERROR_NEED_MORE_DATA);
}
if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
$case_func = 'strtolower';
} else {
$case_func = 'strval';
}
$count = @sybase_num_fields($id);
$res = array();
if ($mode) {
$res['num_fields'] = $count;
}
for ($i = 0; $i < $count; $i++) {
$f = @sybase_fetch_field($id, $i);
// column_source is often blank
$res[$i] = array(
'table' => $got_string
? $case_func($result)
: $case_func($f->column_source),
'name' => $case_func($f->name),
'type' => $f->type,
'len' => $f->max_length,
'flags' => '',
);
if ($res[$i]['table']) {
$res[$i]['flags'] = $this->_sybase_field_flags(
$res[$i]['table'], $res[$i]['name']);
}
if ($mode & DB_TABLEINFO_ORDER) {
$res['order'][$res[$i]['name']] = $i;
}
if ($mode & DB_TABLEINFO_ORDERTABLE) {
$res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
}
}
// free the result only if we were called on a table
if ($got_string) {
@sybase_free_result($id);
}
return $res;
}
// }}}
// {{{ _sybase_field_flags()
/**
* Get the flags for a field
*
* Currently supports:
* + <samp>unique_key</samp> (unique index, unique check or primary_key)
* + <samp>multiple_key</samp> (multi-key index)
*
* @param string $table the table name
* @param string $column the field name
*
* @return string space delimited string of flags. Empty string if none.
*
* @access private
*/
function _sybase_field_flags($table, $column)
{
static $tableName = null;
static $flags = array();
if ($table != $tableName) {
$flags = array();
$tableName = $table;
/* We're running sp_helpindex directly because it doesn't exist in
* older versions of ASE -- unfortunately, we can't just use
* DB::isError() because the user may be using callback error
* handling. */
$res = @sybase_query("sp_helpindex $table", $this->connection);
if ($res === false || $res === true) {
// Fake a valid response for BC reasons.
return '';
}
while (($val = sybase_fetch_assoc($res)) !== false) {
if (!isset($val['index_keys'])) {
/* No useful information returned. Break and be done with
* it, which preserves the pre-1.7.9 behaviour. */
break;
}
$keys = explode(', ', trim($val['index_keys']));
if (sizeof($keys) > 1) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'multiple_key');
}
}
if (strpos($val['index_description'], 'unique')) {
foreach ($keys as $key) {
$this->_add_flag($flags[$key], 'unique_key');
}
}
}
sybase_free_result($res);
}
if (array_key_exists($column, $flags)) {
return(implode(' ', $flags[$column]));
}
return '';
}
// }}}
// {{{ _add_flag()
/**
* Adds a string to the flags array if the flag is not yet in there
* - if there is no flag present the array is created
*
* @param array $array reference of flags array to add a value to
* @param mixed $value value to add to the flag array
*
* @return void
*
* @access private
*/
function _add_flag(&$array, $value)
{
if (!is_array($array)) {
$array = array($value);
} elseif (!in_array($value, $array)) {
array_push($array, $value);
}
}
// }}}
// {{{ getSpecialQuery()
/**
* Obtains the query string needed for listing a given type of objects
*
* @param string $type the kind of objects you want to retrieve
*
* @return string the SQL query string or null if the driver doesn't
* support the object type requested
*
* @access protected
* @see DB_common::getListOf()
*/
function getSpecialQuery($type)
{
switch ($type) {
case 'tables':
return "SELECT name FROM sysobjects WHERE type = 'U'"
. ' ORDER BY name';
case 'views':
return "SELECT name FROM sysobjects WHERE type = 'V'";
default:
return null;
}
}
// }}}
}
/*
* Local variables:
* tab-width: 4
* c-basic-offset: 4
* End:
*/
?>

1005
lib/pear/Mail/mime.php Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,849 @@
<?php
/**
* The Mail_mimeDecode class is used to decode mail/mime messages
*
* This class will parse a raw mime email and return
* the structure. Returned structure is similar to
* that returned by imap_fetchstructure().
*
* +----------------------------- IMPORTANT ------------------------------+
* | Usage of this class compared to native php extensions such as |
* | mailparse or imap, is slow and may be feature deficient. If available|
* | you are STRONGLY recommended to use the php extensions. |
* +----------------------------------------------------------------------+
*
* Compatible with PHP versions 4 and 5
*
* LICENSE: This LICENSE is in the BSD license style.
* Copyright (c) 2002-2003, Richard Heyes <richard@phpguru.org>
* Copyright (c) 2003-2006, PEAR <pear-group@php.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the authors, nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Mail
* @package Mail_Mime
* @author Richard Heyes <richard@phpguru.org>
* @author George Schlossnagle <george@omniti.com>
* @author Cipriano Groenendal <cipri@php.net>
* @author Sean Coates <sean@php.net>
* @copyright 2003-2006 PEAR <pear-group@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: mimeDecode.php,v 1.48 2006/12/03 13:43:33 cipri Exp $
* @link http://pear.php.net/package/Mail_mime
*/
/**
* require PEAR
*
* This package depends on PEAR to raise errors.
*/
require_once 'PEAR.php';
/**
* The Mail_mimeDecode class is used to decode mail/mime messages
*
* This class will parse a raw mime email and return the structure.
* Returned structure is similar to that returned by imap_fetchstructure().
*
* +----------------------------- IMPORTANT ------------------------------+
* | Usage of this class compared to native php extensions such as |
* | mailparse or imap, is slow and may be feature deficient. If available|
* | you are STRONGLY recommended to use the php extensions. |
* +----------------------------------------------------------------------+
*
* @category Mail
* @package Mail_Mime
* @author Richard Heyes <richard@phpguru.org>
* @author George Schlossnagle <george@omniti.com>
* @author Cipriano Groenendal <cipri@php.net>
* @author Sean Coates <sean@php.net>
* @copyright 2003-2006 PEAR <pear-group@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/Mail_mime
*/
class Mail_mimeDecode extends PEAR
{
/**
* The raw email to decode
*
* @var string
* @access private
*/
var $_input;
/**
* The header part of the input
*
* @var string
* @access private
*/
var $_header;
/**
* The body part of the input
*
* @var string
* @access private
*/
var $_body;
/**
* If an error occurs, this is used to store the message
*
* @var string
* @access private
*/
var $_error;
/**
* Flag to determine whether to include bodies in the
* returned object.
*
* @var boolean
* @access private
*/
var $_include_bodies;
/**
* Flag to determine whether to decode bodies
*
* @var boolean
* @access private
*/
var $_decode_bodies;
/**
* Flag to determine whether to decode headers
*
* @var boolean
* @access private
*/
var $_decode_headers;
/**
* Constructor.
*
* Sets up the object, initialise the variables, and splits and
* stores the header and body of the input.
*
* @param string The input to decode
* @access public
*/
function Mail_mimeDecode($input)
{
list($header, $body) = $this->_splitBodyHeader($input);
$this->_input = $input;
$this->_header = $header;
$this->_body = $body;
$this->_decode_bodies = false;
$this->_include_bodies = true;
}
/**
* Begins the decoding process. If called statically
* it will create an object and call the decode() method
* of it.
*
* @param array An array of various parameters that determine
* various things:
* include_bodies - Whether to include the body in the returned
* object.
* decode_bodies - Whether to decode the bodies
* of the parts. (Transfer encoding)
* decode_headers - Whether to decode headers
* input - If called statically, this will be treated
* as the input
* @return object Decoded results
* @access public
*/
function decode($params = null)
{
// determine if this method has been called statically
$isStatic = !(isset($this) && get_class($this) == __CLASS__);
// Have we been called statically?
// If so, create an object and pass details to that.
if ($isStatic AND isset($params['input'])) {
$obj = new Mail_mimeDecode($params['input']);
$structure = $obj->decode($params);
// Called statically but no input
} elseif ($isStatic) {
return PEAR::raiseError('Called statically and no input given');
// Called via an object
} else {
$this->_include_bodies = isset($params['include_bodies']) ?
$params['include_bodies'] : false;
$this->_decode_bodies = isset($params['decode_bodies']) ?
$params['decode_bodies'] : false;
$this->_decode_headers = isset($params['decode_headers']) ?
$params['decode_headers'] : false;
$structure = $this->_decode($this->_header, $this->_body);
if ($structure === false) {
$structure = $this->raiseError($this->_error);
}
}
return $structure;
}
/**
* Performs the decoding. Decodes the body string passed to it
* If it finds certain content-types it will call itself in a
* recursive fashion
*
* @param string Header section
* @param string Body section
* @return object Results of decoding process
* @access private
*/
function _decode($headers, $body, $default_ctype = 'text/plain')
{
$return = new stdClass;
$return->headers = array();
$headers = $this->_parseHeaders($headers);
foreach ($headers as $value) {
if (isset($return->headers[strtolower($value['name'])]) AND !is_array($return->headers[strtolower($value['name'])])) {
$return->headers[strtolower($value['name'])] = array($return->headers[strtolower($value['name'])]);
$return->headers[strtolower($value['name'])][] = $value['value'];
} elseif (isset($return->headers[strtolower($value['name'])])) {
$return->headers[strtolower($value['name'])][] = $value['value'];
} else {
$return->headers[strtolower($value['name'])] = $value['value'];
}
}
reset($headers);
while (list($key, $value) = each($headers)) {
$headers[$key]['name'] = strtolower($headers[$key]['name']);
switch ($headers[$key]['name']) {
case 'content-type':
$content_type = $this->_parseHeaderValue($headers[$key]['value']);
if (preg_match('/([0-9a-z+.-]+)\/([0-9a-z+.-]+)/i', $content_type['value'], $regs)) {
$return->ctype_primary = $regs[1];
$return->ctype_secondary = $regs[2];
}
if (isset($content_type['other'])) {
while (list($p_name, $p_value) = each($content_type['other'])) {
$return->ctype_parameters[$p_name] = $p_value;
}
}
break;
case 'content-disposition':
$content_disposition = $this->_parseHeaderValue($headers[$key]['value']);
$return->disposition = $content_disposition['value'];
if (isset($content_disposition['other'])) {
while (list($p_name, $p_value) = each($content_disposition['other'])) {
$return->d_parameters[$p_name] = $p_value;
}
}
break;
case 'content-transfer-encoding':
$content_transfer_encoding = $this->_parseHeaderValue($headers[$key]['value']);
break;
}
}
if (isset($content_type)) {
switch (strtolower($content_type['value'])) {
case 'text/plain':
$encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
$this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null;
break;
case 'text/html':
$encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit';
$this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body) : null;
break;
case 'multipart/parallel':
case 'multipart/appledouble': // Appledouble mail
case 'multipart/report': // RFC1892
case 'multipart/signed': // PGP
case 'multipart/digest':
case 'multipart/alternative':
case 'multipart/related':
case 'multipart/mixed':
if(!isset($content_type['other']['boundary'])){
$this->_error = 'No boundary found for ' . $content_type['value'] . ' part';
return false;
}
$default_ctype = (strtolower($content_type['value']) === 'multipart/digest') ? 'message/rfc822' : 'text/plain';
$parts = $this->_boundarySplit($body, $content_type['other']['boundary']);
for ($i = 0; $i < count($parts); $i++) {
list($part_header, $part_body) = $this->_splitBodyHeader($parts[$i]);
$part = $this->_decode($part_header, $part_body, $default_ctype);
if($part === false)
$part = $this->raiseError($this->_error);
$return->parts[] = $part;
}
break;
case 'message/rfc822':
$obj = &new Mail_mimeDecode($body);
$return->parts[] = $obj->decode(array('include_bodies' => $this->_include_bodies,
'decode_bodies' => $this->_decode_bodies,
'decode_headers' => $this->_decode_headers));
unset($obj);
break;
default:
if(!isset($content_transfer_encoding['value']))
$content_transfer_encoding['value'] = '7bit';
$this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $content_transfer_encoding['value']) : $body) : null;
break;
}
} else {
$ctype = explode('/', $default_ctype);
$return->ctype_primary = $ctype[0];
$return->ctype_secondary = $ctype[1];
$this->_include_bodies ? $return->body = ($this->_decode_bodies ? $this->_decodeBody($body) : $body) : null;
}
return $return;
}
/**
* Given the output of the above function, this will return an
* array of references to the parts, indexed by mime number.
*
* @param object $structure The structure to go through
* @param string $mime_number Internal use only.
* @return array Mime numbers
*/
function &getMimeNumbers(&$structure, $no_refs = false, $mime_number = '', $prepend = '')
{
$return = array();
if (!empty($structure->parts)) {
if ($mime_number != '') {
$structure->mime_id = $prepend . $mime_number;
$return[$prepend . $mime_number] = &$structure;
}
for ($i = 0; $i < count($structure->parts); $i++) {
if (!empty($structure->headers['content-type']) AND substr(strtolower($structure->headers['content-type']), 0, 8) == 'message/') {
$prepend = $prepend . $mime_number . '.';
$_mime_number = '';
} else {
$_mime_number = ($mime_number == '' ? $i + 1 : sprintf('%s.%s', $mime_number, $i + 1));
}
$arr = &Mail_mimeDecode::getMimeNumbers($structure->parts[$i], $no_refs, $_mime_number, $prepend);
foreach ($arr as $key => $val) {
$no_refs ? $return[$key] = '' : $return[$key] = &$arr[$key];
}
}
} else {
if ($mime_number == '') {
$mime_number = '1';
}
$structure->mime_id = $prepend . $mime_number;
$no_refs ? $return[$prepend . $mime_number] = '' : $return[$prepend . $mime_number] = &$structure;
}
return $return;
}
/**
* Given a string containing a header and body
* section, this function will split them (at the first
* blank line) and return them.
*
* @param string Input to split apart
* @return array Contains header and body section
* @access private
*/
function _splitBodyHeader($input)
{
if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) {
return array($match[1], $match[2]);
}
$this->_error = 'Could not split header and body';
return false;
}
/**
* Parse headers given in $input and return
* as assoc array.
*
* @param string Headers to parse
* @return array Contains parsed headers
* @access private
*/
function _parseHeaders($input)
{
if ($input !== '') {
// Unfold the input
$input = preg_replace("/\r?\n/", "\r\n", $input);
$input = preg_replace("/\r\n(\t| )+/", ' ', $input);
$headers = explode("\r\n", trim($input));
foreach ($headers as $value) {
$hdr_name = substr($value, 0, $pos = strpos($value, ':'));
$hdr_value = substr($value, $pos+1);
if($hdr_value[0] == ' ')
$hdr_value = substr($hdr_value, 1);
$return[] = array(
'name' => $hdr_name,
'value' => $this->_decode_headers ? $this->_decodeHeader($hdr_value) : $hdr_value
);
}
} else {
$return = array();
}
return $return;
}
/**
* Function to parse a header value,
* extract first part, and any secondary
* parts (after ;) This function is not as
* robust as it could be. Eg. header comments
* in the wrong place will probably break it.
*
* @param string Header value to parse
* @return array Contains parsed result
* @access private
*/
function _parseHeaderValue($input)
{
if (($pos = strpos($input, ';')) !== false) {
$return['value'] = trim(substr($input, 0, $pos));
$input = trim(substr($input, $pos+1));
if (strlen($input) > 0) {
// This splits on a semi-colon, if there's no preceeding backslash
// Now works with quoted values; had to glue the \; breaks in PHP
// the regex is already bordering on incomprehensible
$splitRegex = '/([^;\'"]*[\'"]([^\'"]*([^\'"]*)*)[\'"][^;\'"]*|([^;]+))(;|$)/';
preg_match_all($splitRegex, $input, $matches);
$parameters = array();
for ($i=0; $i<count($matches[0]); $i++) {
$param = $matches[0][$i];
while (substr($param, -2) == '\;') {
$param .= $matches[0][++$i];
}
$parameters[] = $param;
}
for ($i = 0; $i < count($parameters); $i++) {
$param_name = trim(substr($parameters[$i], 0, $pos = strpos($parameters[$i], '=')), "'\";\t\\ ");
$param_value = trim(str_replace('\;', ';', substr($parameters[$i], $pos + 1)), "'\";\t\\ ");
if ($param_value[0] == '"') {
$param_value = substr($param_value, 1, -1);
}
$return['other'][$param_name] = $param_value;
$return['other'][strtolower($param_name)] = $param_value;
}
}
} else {
$return['value'] = trim($input);
}
return $return;
}
/**
* This function splits the input based
* on the given boundary
*
* @param string Input to parse
* @return array Contains array of resulting mime parts
* @access private
*/
function _boundarySplit($input, $boundary)
{
$parts = array();
$bs_possible = substr($boundary, 2, -2);
$bs_check = '\"' . $bs_possible . '\"';
if ($boundary == $bs_check) {
$boundary = $bs_possible;
}
$tmp = explode('--' . $boundary, $input);
for ($i = 1; $i < count($tmp) - 1; $i++) {
$parts[] = $tmp[$i];
}
return $parts;
}
/**
* Given a header, this function will decode it
* according to RFC2047. Probably not *exactly*
* conformant, but it does pass all the given
* examples (in RFC2047).
*
* @param string Input header value to decode
* @return string Decoded header value
* @access private
*/
function _decodeHeader($input)
{
// Remove white space between encoded-words
$input = preg_replace('/(=\?[^?]+\?(q|b)\?[^?]*\?=)(\s)+=\?/i', '\1=?', $input);
// For each encoded-word...
while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i', $input, $matches)) {
$encoded = $matches[1];
$charset = $matches[2];
$encoding = $matches[3];
$text = $matches[4];
switch (strtolower($encoding)) {
case 'b':
$text = base64_decode($text);
break;
case 'q':
$text = str_replace('_', ' ', $text);
preg_match_all('/=([a-f0-9]{2})/i', $text, $matches);
foreach($matches[1] as $value)
$text = str_replace('='.$value, chr(hexdec($value)), $text);
break;
}
$input = str_replace($encoded, $text, $input);
}
return $input;
}
/**
* Given a body string and an encoding type,
* this function will decode and return it.
*
* @param string Input body to decode
* @param string Encoding type to use.
* @return string Decoded body
* @access private
*/
function _decodeBody($input, $encoding = '7bit')
{
switch (strtolower($encoding)) {
case '7bit':
return $input;
break;
case 'quoted-printable':
return $this->_quotedPrintableDecode($input);
break;
case 'base64':
return base64_decode($input);
break;
default:
return $input;
}
}
/**
* Given a quoted-printable string, this
* function will decode and return it.
*
* @param string Input body to decode
* @return string Decoded body
* @access private
*/
function _quotedPrintableDecode($input)
{
// Remove soft line breaks
$input = preg_replace("/=\r?\n/", '', $input);
// Replace encoded characters
$input = preg_replace('/=([a-f0-9]{2})/ie', "chr(hexdec('\\1'))", $input);
return $input;
}
/**
* Checks the input for uuencoded files and returns
* an array of them. Can be called statically, eg:
*
* $files =& Mail_mimeDecode::uudecode($some_text);
*
* It will check for the begin 666 ... end syntax
* however and won't just blindly decode whatever you
* pass it.
*
* @param string Input body to look for attahcments in
* @return array Decoded bodies, filenames and permissions
* @access public
* @author Unknown
*/
function &uudecode($input)
{
// Find all uuencoded sections
preg_match_all("/begin ([0-7]{3}) (.+)\r?\n(.+)\r?\nend/Us", $input, $matches);
for ($j = 0; $j < count($matches[3]); $j++) {
$str = $matches[3][$j];
$filename = $matches[2][$j];
$fileperm = $matches[1][$j];
$file = '';
$str = preg_split("/\r?\n/", trim($str));
$strlen = count($str);
for ($i = 0; $i < $strlen; $i++) {
$pos = 1;
$d = 0;
$len=(int)(((ord(substr($str[$i],0,1)) -32) - ' ') & 077);
while (($d + 3 <= $len) AND ($pos + 4 <= strlen($str[$i]))) {
$c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
$c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
$c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20);
$c3 = (ord(substr($str[$i],$pos+3,1)) ^ 0x20);
$file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
$file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2));
$file .= chr(((($c2 - ' ') & 077) << 6) | (($c3 - ' ') & 077));
$pos += 4;
$d += 3;
}
if (($d + 2 <= $len) && ($pos + 3 <= strlen($str[$i]))) {
$c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
$c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
$c2 = (ord(substr($str[$i],$pos+2,1)) ^ 0x20);
$file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
$file .= chr(((($c1 - ' ') & 077) << 4) | ((($c2 - ' ') & 077) >> 2));
$pos += 3;
$d += 2;
}
if (($d + 1 <= $len) && ($pos + 2 <= strlen($str[$i]))) {
$c0 = (ord(substr($str[$i],$pos,1)) ^ 0x20);
$c1 = (ord(substr($str[$i],$pos+1,1)) ^ 0x20);
$file .= chr(((($c0 - ' ') & 077) << 2) | ((($c1 - ' ') & 077) >> 4));
}
}
$files[] = array('filename' => $filename, 'fileperm' => $fileperm, 'filedata' => $file);
}
return $files;
}
/**
* getSendArray() returns the arguments required for Mail::send()
* used to build the arguments for a mail::send() call
*
* Usage:
* $mailtext = Full email (for example generated by a template)
* $decoder = new Mail_mimeDecode($mailtext);
* $parts = $decoder->getSendArray();
* if (!PEAR::isError($parts) {
* list($recipents,$headers,$body) = $parts;
* $mail = Mail::factory('smtp');
* $mail->send($recipents,$headers,$body);
* } else {
* echo $parts->message;
* }
* @return mixed array of recipeint, headers,body or Pear_Error
* @access public
* @author Alan Knowles <alan@akbkhome.com>
*/
function getSendArray()
{
// prevent warning if this is not set
$this->_decode_headers = FALSE;
$headerlist =$this->_parseHeaders($this->_header);
$to = "";
if (!$headerlist) {
return $this->raiseError("Message did not contain headers");
}
foreach($headerlist as $item) {
$header[$item['name']] = $item['value'];
switch (strtolower($item['name'])) {
case "to":
case "cc":
case "bcc":
$to = ",".$item['value'];
default:
break;
}
}
if ($to == "") {
return $this->raiseError("Message did not contain any recipents");
}
$to = substr($to,1);
return array($to,$header,$this->_body);
}
/**
* Returns a xml copy of the output of
* Mail_mimeDecode::decode. Pass the output in as the
* argument. This function can be called statically. Eg:
*
* $output = $obj->decode();
* $xml = Mail_mimeDecode::getXML($output);
*
* The DTD used for this should have been in the package. Or
* alternatively you can get it from cvs, or here:
* http://www.phpguru.org/xmail/xmail.dtd.
*
* @param object Input to convert to xml. This should be the
* output of the Mail_mimeDecode::decode function
* @return string XML version of input
* @access public
*/
function getXML($input)
{
$crlf = "\r\n";
$output = '<?xml version=\'1.0\'?>' . $crlf .
'<!DOCTYPE email SYSTEM "http://www.phpguru.org/xmail/xmail.dtd">' . $crlf .
'<email>' . $crlf .
Mail_mimeDecode::_getXML($input) .
'</email>';
return $output;
}
/**
* Function that does the actual conversion to xml. Does a single
* mimepart at a time.
*
* @param object Input to convert to xml. This is a mimepart object.
* It may or may not contain subparts.
* @param integer Number of tabs to indent
* @return string XML version of input
* @access private
*/
function _getXML($input, $indent = 1)
{
$htab = "\t";
$crlf = "\r\n";
$output = '';
$headers = @(array)$input->headers;
foreach ($headers as $hdr_name => $hdr_value) {
// Multiple headers with this name
if (is_array($headers[$hdr_name])) {
for ($i = 0; $i < count($hdr_value); $i++) {
$output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value[$i], $indent);
}
// Only one header of this sort
} else {
$output .= Mail_mimeDecode::_getXML_helper($hdr_name, $hdr_value, $indent);
}
}
if (!empty($input->parts)) {
for ($i = 0; $i < count($input->parts); $i++) {
$output .= $crlf . str_repeat($htab, $indent) . '<mimepart>' . $crlf .
Mail_mimeDecode::_getXML($input->parts[$i], $indent+1) .
str_repeat($htab, $indent) . '</mimepart>' . $crlf;
}
} elseif (isset($input->body)) {
$output .= $crlf . str_repeat($htab, $indent) . '<body><![CDATA[' .
$input->body . ']]></body>' . $crlf;
}
return $output;
}
/**
* Helper function to _getXML(). Returns xml of a header.
*
* @param string Name of header
* @param string Value of header
* @param integer Number of tabs to indent
* @return string XML version of input
* @access private
*/
function _getXML_helper($hdr_name, $hdr_value, $indent)
{
$htab = "\t";
$crlf = "\r\n";
$return = '';
$new_hdr_value = ($hdr_name != 'received') ? Mail_mimeDecode::_parseHeaderValue($hdr_value) : array('value' => $hdr_value);
$new_hdr_name = str_replace(' ', '-', ucwords(str_replace('-', ' ', $hdr_name)));
// Sort out any parameters
if (!empty($new_hdr_value['other'])) {
foreach ($new_hdr_value['other'] as $paramname => $paramvalue) {
$params[] = str_repeat($htab, $indent) . $htab . '<parameter>' . $crlf .
str_repeat($htab, $indent) . $htab . $htab . '<paramname>' . htmlspecialchars($paramname) . '</paramname>' . $crlf .
str_repeat($htab, $indent) . $htab . $htab . '<paramvalue>' . htmlspecialchars($paramvalue) . '</paramvalue>' . $crlf .
str_repeat($htab, $indent) . $htab . '</parameter>' . $crlf;
}
$params = implode('', $params);
} else {
$params = '';
}
$return = str_repeat($htab, $indent) . '<header>' . $crlf .
str_repeat($htab, $indent) . $htab . '<headername>' . htmlspecialchars($new_hdr_name) . '</headername>' . $crlf .
str_repeat($htab, $indent) . $htab . '<headervalue>' . htmlspecialchars($new_hdr_value['value']) . '</headervalue>' . $crlf .
$params .
str_repeat($htab, $indent) . '</header>' . $crlf;
return $return;
}
} // End of class

341
lib/pear/Mail/mimePart.php Normal file
View File

@ -0,0 +1,341 @@
<?php
/**
* The Mail_mimePart class is used to create MIME E-mail messages
*
* This class enables you to manipulate and build a mime email
* from the ground up. The Mail_Mime class is a userfriendly api
* to this class for people who aren't interested in the internals
* of mime mail.
* This class however allows full control over the email.
*
* Compatible with PHP versions 4 and 5
*
* LICENSE: This LICENSE is in the BSD license style.
* Copyright (c) 2002-2003, Richard Heyes <richard@phpguru.org>
* Copyright (c) 2003-2006, PEAR <pear-group@php.net>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or
* without modification, are permitted provided that the following
* conditions are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of the authors, nor the names of its contributors
* may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* @category Mail
* @package Mail_Mime
* @author Richard Heyes <richard@phpguru.org>
* @author Cipriano Groenendal <cipri@php.net>
* @author Sean Coates <sean@php.net>
* @copyright 2003-2006 PEAR <pear-group@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: mimePart.php,v 1.19 2006/12/03 20:22:48 cipri Exp $
* @link http://pear.php.net/package/Mail_mime
*/
/**
* The Mail_mimePart class is used to create MIME E-mail messages
*
* This class enables you to manipulate and build a mime email
* from the ground up. The Mail_Mime class is a userfriendly api
* to this class for people who aren't interested in the internals
* of mime mail.
* This class however allows full control over the email.
*
* @category Mail
* @package Mail_Mime
* @author Richard Heyes <richard@phpguru.org>
* @author Cipriano Groenendal <cipri@php.net>
* @author Sean Coates <sean@php.net>
* @copyright 2003-2006 PEAR <pear-group@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version Release: @package_version@
* @link http://pear.php.net/package/Mail_mime
*/
class Mail_mimePart {
/**
* The encoding type of this part
*
* @var string
* @access private
*/
var $_encoding;
/**
* An array of subparts
*
* @var array
* @access private
*/
var $_subparts;
/**
* The output of this part after being built
*
* @var string
* @access private
*/
var $_encoded;
/**
* Headers for this part
*
* @var array
* @access private
*/
var $_headers;
/**
* The body of this part (not encoded)
*
* @var string
* @access private
*/
var $_body;
/**
* Constructor.
*
* Sets up the object.
*
* @param $body - The body of the mime part if any.
* @param $params - An associative array of parameters:
* content_type - The content type for this part eg multipart/mixed
* encoding - The encoding to use, 7bit, 8bit, base64, or quoted-printable
* cid - Content ID to apply
* disposition - Content disposition, inline or attachment
* dfilename - Optional filename parameter for content disposition
* description - Content description
* charset - Character set to use
* @access public
*/
function Mail_mimePart($body = '', $params = array())
{
if (!defined('MAIL_MIMEPART_CRLF')) {
define('MAIL_MIMEPART_CRLF', defined('MAIL_MIME_CRLF') ? MAIL_MIME_CRLF : "\r\n", TRUE);
}
foreach ($params as $key => $value) {
switch ($key) {
case 'content_type':
$headers['Content-Type'] = $value . (isset($charset) ? '; charset="' . $charset . '"' : '');
break;
case 'encoding':
$this->_encoding = $value;
$headers['Content-Transfer-Encoding'] = $value;
break;
case 'cid':
$headers['Content-ID'] = '<' . $value . '>';
break;
case 'disposition':
$headers['Content-Disposition'] = $value . (isset($dfilename) ? '; filename="' . $dfilename . '"' : '');
break;
case 'dfilename':
if (isset($headers['Content-Disposition'])) {
$headers['Content-Disposition'] .= '; filename="' . $value . '"';
} else {
$dfilename = $value;
}
break;
case 'description':
$headers['Content-Description'] = $value;
break;
case 'charset':
if (isset($headers['Content-Type'])) {
$headers['Content-Type'] .= '; charset="' . $value . '"';
} else {
$charset = $value;
}
break;
}
}
// Default content-type
if (!isset($headers['Content-Type'])) {
$headers['Content-Type'] = 'text/plain';
}
//Default encoding
if (!isset($this->_encoding)) {
$this->_encoding = '7bit';
}
// Assign stuff to member variables
$this->_encoded = array();
$this->_headers = $headers;
$this->_body = $body;
}
/**
* encode()
*
* Encodes and returns the email. Also stores
* it in the encoded member variable
*
* @return An associative array containing two elements,
* body and headers. The headers element is itself
* an indexed array.
* @access public
*/
function encode()
{
$encoded =& $this->_encoded;
if (!empty($this->_subparts)) {
srand((double)microtime()*1000000);
$boundary = '=_' . md5(rand() . microtime());
$this->_headers['Content-Type'] .= ';' . MAIL_MIMEPART_CRLF . "\t" . 'boundary="' . $boundary . '"';
// Add body parts to $subparts
for ($i = 0; $i < count($this->_subparts); $i++) {
$headers = array();
$tmp = $this->_subparts[$i]->encode();
foreach ($tmp['headers'] as $key => $value) {
$headers[] = $key . ': ' . $value;
}
$subparts[] = implode(MAIL_MIMEPART_CRLF, $headers) . MAIL_MIMEPART_CRLF . MAIL_MIMEPART_CRLF . $tmp['body'];
}
$encoded['body'] = '--' . $boundary . MAIL_MIMEPART_CRLF .
implode('--' . $boundary . MAIL_MIMEPART_CRLF, $subparts) .
'--' . $boundary.'--' . MAIL_MIMEPART_CRLF . MAIL_MIMEPART_CRLF;
} else {
$encoded['body'] = $this->_getEncodedData($this->_body, $this->_encoding) . MAIL_MIMEPART_CRLF;
}
// Add headers to $encoded
$encoded['headers'] =& $this->_headers;
return $encoded;
}
/**
* &addSubPart()
*
* Adds a subpart to current mime part and returns
* a reference to it
*
* @param $body The body of the subpart, if any.
* @param $params The parameters for the subpart, same
* as the $params argument for constructor.
* @return A reference to the part you just added. It is
* crucial if using multipart/* in your subparts that
* you use =& in your script when calling this function,
* otherwise you will not be able to add further subparts.
* @access public
*/
function &addSubPart($body, $params)
{
$this->_subparts[] = new Mail_mimePart($body, $params);
return $this->_subparts[count($this->_subparts) - 1];
}
/**
* _getEncodedData()
*
* Returns encoded data based upon encoding passed to it
*
* @param $data The data to encode.
* @param $encoding The encoding type to use, 7bit, base64,
* or quoted-printable.
* @access private
*/
function _getEncodedData($data, $encoding)
{
switch ($encoding) {
case '8bit':
case '7bit':
return $data;
break;
case 'quoted-printable':
return $this->_quotedPrintableEncode($data);
break;
case 'base64':
return rtrim(chunk_split(base64_encode($data), 76, MAIL_MIMEPART_CRLF));
break;
default:
return $data;
}
}
/**
* quotedPrintableEncode()
*
* Encodes data to quoted-printable standard.
*
* @param $input The data to encode
* @param $line_max Optional max line length. Should
* not be more than 76 chars
*
* @access private
*/
function _quotedPrintableEncode($input , $line_max = 76)
{
$lines = preg_split("/\r?\n/", $input);
$eol = MAIL_MIMEPART_CRLF;
$escape = '=';
$output = '';
while(list(, $line) = each($lines)){
$line = preg_split('||', $line, -1, PREG_SPLIT_NO_EMPTY);
$linlen = count($line);
$newline = '';
for ($i = 0; $i < $linlen; $i++) {
$char = $line[$i];
$dec = ord($char);
if (($dec == 32) AND ($i == ($linlen - 1))){ // convert space at eol only
$char = '=20';
} elseif(($dec == 9) AND ($i == ($linlen - 1))) { // convert tab at eol only
$char = '=09';
} elseif($dec == 9) {
; // Do nothing if a tab.
} elseif(($dec == 61) OR ($dec < 32 ) OR ($dec > 126)) {
$char = $escape . strtoupper(sprintf('%02s', dechex($dec)));
}
if ((strlen($newline) + strlen($char)) >= $line_max) { // MAIL_MIMEPART_CRLF is not counted
$output .= $newline . $escape . $eol; // soft line break; " =\r\n" is okay
$newline = '';
}
$newline .= $char;
} // end of for
$output .= $newline . $eol;
}
$output = substr($output, 0, -1 * strlen($eol)); // Don't want last crlf
return $output;
}
} // End of class

528
lib/pear/Net/Socket.php Normal file
View File

@ -0,0 +1,528 @@
<?php
//
// +----------------------------------------------------------------------+
// | PHP Version 4 |
// +----------------------------------------------------------------------+
// | Copyright (c) 1997-2003 The PHP Group |
// +----------------------------------------------------------------------+
// | This source file is subject to version 2.0 of the PHP license, |
// | that is bundled with this package in the file LICENSE, and is |
// | available at through the world-wide-web at |
// | http://www.php.net/license/2_02.txt. |
// | If you did not receive a copy of the PHP license and are unable to |
// | obtain it through the world-wide-web, please send a note to |
// | license@php.net so we can mail you a copy immediately. |
// +----------------------------------------------------------------------+
// | Authors: Stig Bakken <ssb@php.net> |
// | Chuck Hagenbuch <chuck@horde.org> |
// +----------------------------------------------------------------------+
//
// $Id: Socket.php,v 1.24 2005/02/03 20:40:16 chagenbu Exp $
require_once 'PEAR.php';
define('NET_SOCKET_READ', 1);
define('NET_SOCKET_WRITE', 2);
define('NET_SOCKET_ERROR', 3);
/**
* Generalized Socket class.
*
* @version 1.1
* @author Stig Bakken <ssb@php.net>
* @author Chuck Hagenbuch <chuck@horde.org>
*/
class Net_Socket extends PEAR {
/**
* Socket file pointer.
* @var resource $fp
*/
var $fp = null;
/**
* Whether the socket is blocking. Defaults to true.
* @var boolean $blocking
*/
var $blocking = true;
/**
* Whether the socket is persistent. Defaults to false.
* @var boolean $persistent
*/
var $persistent = false;
/**
* The IP address to connect to.
* @var string $addr
*/
var $addr = '';
/**
* The port number to connect to.
* @var integer $port
*/
var $port = 0;
/**
* Number of seconds to wait on socket connections before assuming
* there's no more data. Defaults to no timeout.
* @var integer $timeout
*/
var $timeout = false;
/**
* Number of bytes to read at a time in readLine() and
* readAll(). Defaults to 2048.
* @var integer $lineLength
*/
var $lineLength = 2048;
/**
* Connect to the specified port. If called when the socket is
* already connected, it disconnects and connects again.
*
* @param string $addr IP address or host name.
* @param integer $port TCP port number.
* @param boolean $persistent (optional) Whether the connection is
* persistent (kept open between requests
* by the web server).
* @param integer $timeout (optional) How long to wait for data.
* @param array $options See options for stream_context_create.
*
* @access public
*
* @return boolean | PEAR_Error True on success or a PEAR_Error on failure.
*/
function connect($addr, $port = 0, $persistent = null, $timeout = null, $options = null)
{
if (is_resource($this->fp)) {
@fclose($this->fp);
$this->fp = null;
}
if (!$addr) {
return $this->raiseError('$addr cannot be empty');
} elseif (strspn($addr, '.0123456789') == strlen($addr) ||
strstr($addr, '/') !== false) {
$this->addr = $addr;
} else {
$this->addr = @gethostbyname($addr);
}
$this->port = $port % 65536;
if ($persistent !== null) {
$this->persistent = $persistent;
}
if ($timeout !== null) {
$this->timeout = $timeout;
}
$openfunc = $this->persistent ? 'pfsockopen' : 'fsockopen';
$errno = 0;
$errstr = '';
if ($options && function_exists('stream_context_create')) {
if ($this->timeout) {
$timeout = $this->timeout;
} else {
$timeout = 0;
}
$context = stream_context_create($options);
$fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $timeout, $context);
} else {
if ($this->timeout) {
$fp = @$openfunc($this->addr, $this->port, $errno, $errstr, $this->timeout);
} else {
$fp = @$openfunc($this->addr, $this->port, $errno, $errstr);
}
}
if (!$fp) {
return $this->raiseError($errstr, $errno);
}
$this->fp = $fp;
return $this->setBlocking($this->blocking);
}
/**
* Disconnects from the peer, closes the socket.
*
* @access public
* @return mixed true on success or an error object otherwise
*/
function disconnect()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
@fclose($this->fp);
$this->fp = null;
return true;
}
/**
* Find out if the socket is in blocking mode.
*
* @access public
* @return boolean The current blocking mode.
*/
function isBlocking()
{
return $this->blocking;
}
/**
* Sets whether the socket connection should be blocking or
* not. A read call to a non-blocking socket will return immediately
* if there is no data available, whereas it will block until there
* is data for blocking sockets.
*
* @param boolean $mode True for blocking sockets, false for nonblocking.
* @access public
* @return mixed true on success or an error object otherwise
*/
function setBlocking($mode)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$this->blocking = $mode;
socket_set_blocking($this->fp, $this->blocking);
return true;
}
/**
* Sets the timeout value on socket descriptor,
* expressed in the sum of seconds and microseconds
*
* @param integer $seconds Seconds.
* @param integer $microseconds Microseconds.
* @access public
* @return mixed true on success or an error object otherwise
*/
function setTimeout($seconds, $microseconds)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
return socket_set_timeout($this->fp, $seconds, $microseconds);
}
/**
* Returns information about an existing socket resource.
* Currently returns four entries in the result array:
*
* <p>
* timed_out (bool) - The socket timed out waiting for data<br>
* blocked (bool) - The socket was blocked<br>
* eof (bool) - Indicates EOF event<br>
* unread_bytes (int) - Number of bytes left in the socket buffer<br>
* </p>
*
* @access public
* @return mixed Array containing information about existing socket resource or an error object otherwise
*/
function getStatus()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
return socket_get_status($this->fp);
}
/**
* Get a specified line of data
*
* @access public
* @return $size bytes of data from the socket, or a PEAR_Error if
* not connected.
*/
function gets($size)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
return @fgets($this->fp, $size);
}
/**
* Read a specified amount of data. This is guaranteed to return,
* and has the added benefit of getting everything in one fread()
* chunk; if you know the size of the data you're getting
* beforehand, this is definitely the way to go.
*
* @param integer $size The number of bytes to read from the socket.
* @access public
* @return $size bytes of data from the socket, or a PEAR_Error if
* not connected.
*/
function read($size)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
return @fread($this->fp, $size);
}
/**
* Write a specified amount of data.
*
* @param string $data Data to write.
* @param integer $blocksize Amount of data to write at once.
* NULL means all at once.
*
* @access public
* @return mixed true on success or an error object otherwise
*/
function write($data, $blocksize = null)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
if (is_null($blocksize) && !OS_WINDOWS) {
return fwrite($this->fp, $data);
} else {
if (is_null($blocksize)) {
$blocksize = 1024;
}
$pos = 0;
$size = strlen($data);
while ($pos < $size) {
$written = @fwrite($this->fp, substr($data, $pos, $blocksize));
if ($written === false) {
return false;
}
$pos += $written;
}
return $pos;
}
}
/**
* Write a line of data to the socket, followed by a trailing "\r\n".
*
* @access public
* @return mixed fputs result, or an error
*/
function writeLine($data)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
return fwrite($this->fp, $data . "\r\n");
}
/**
* Tests for end-of-file on a socket descriptor.
*
* @access public
* @return bool
*/
function eof()
{
return (is_resource($this->fp) && feof($this->fp));
}
/**
* Reads a byte of data
*
* @access public
* @return 1 byte of data from the socket, or a PEAR_Error if
* not connected.
*/
function readByte()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
return ord(@fread($this->fp, 1));
}
/**
* Reads a word of data
*
* @access public
* @return 1 word of data from the socket, or a PEAR_Error if
* not connected.
*/
function readWord()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$buf = @fread($this->fp, 2);
return (ord($buf[0]) + (ord($buf[1]) << 8));
}
/**
* Reads an int of data
*
* @access public
* @return integer 1 int of data from the socket, or a PEAR_Error if
* not connected.
*/
function readInt()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$buf = @fread($this->fp, 4);
return (ord($buf[0]) + (ord($buf[1]) << 8) +
(ord($buf[2]) << 16) + (ord($buf[3]) << 24));
}
/**
* Reads a zero-terminated string of data
*
* @access public
* @return string, or a PEAR_Error if
* not connected.
*/
function readString()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$string = '';
while (($char = @fread($this->fp, 1)) != "\x00") {
$string .= $char;
}
return $string;
}
/**
* Reads an IP Address and returns it in a dot formated string
*
* @access public
* @return Dot formated string, or a PEAR_Error if
* not connected.
*/
function readIPAddress()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$buf = @fread($this->fp, 4);
return sprintf("%s.%s.%s.%s", ord($buf[0]), ord($buf[1]),
ord($buf[2]), ord($buf[3]));
}
/**
* Read until either the end of the socket or a newline, whichever
* comes first. Strips the trailing newline from the returned data.
*
* @access public
* @return All available data up to a newline, without that
* newline, or until the end of the socket, or a PEAR_Error if
* not connected.
*/
function readLine()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$line = '';
$timeout = time() + $this->timeout;
while (!feof($this->fp) && (!$this->timeout || time() < $timeout)) {
$line .= @fgets($this->fp, $this->lineLength);
if (substr($line, -1) == "\n") {
return rtrim($line, "\r\n");
}
}
return $line;
}
/**
* Read until the socket closes, or until there is no more data in
* the inner PHP buffer. If the inner buffer is empty, in blocking
* mode we wait for at least 1 byte of data. Therefore, in
* blocking mode, if there is no data at all to be read, this
* function will never exit (unless the socket is closed on the
* remote end).
*
* @access public
*
* @return string All data until the socket closes, or a PEAR_Error if
* not connected.
*/
function readAll()
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$data = '';
while (!feof($this->fp)) {
$data .= @fread($this->fp, $this->lineLength);
}
return $data;
}
/**
* Runs the equivalent of the select() system call on the socket
* with a timeout specified by tv_sec and tv_usec.
*
* @param integer $state Which of read/write/error to check for.
* @param integer $tv_sec Number of seconds for timeout.
* @param integer $tv_usec Number of microseconds for timeout.
*
* @access public
* @return False if select fails, integer describing which of read/write/error
* are ready, or PEAR_Error if not connected.
*/
function select($state, $tv_sec, $tv_usec = 0)
{
if (!is_resource($this->fp)) {
return $this->raiseError('not connected');
}
$read = null;
$write = null;
$except = null;
if ($state & NET_SOCKET_READ) {
$read[] = $this->fp;
}
if ($state & NET_SOCKET_WRITE) {
$write[] = $this->fp;
}
if ($state & NET_SOCKET_ERROR) {
$except[] = $this->fp;
}
if (false === ($sr = stream_select($read, $write, $except, $tv_sec, $tv_usec))) {
return false;
}
$result = 0;
if (count($read)) {
$result |= NET_SOCKET_READ;
}
if (count($write)) {
$result |= NET_SOCKET_WRITE;
}
if (count($except)) {
$result |= NET_SOCKET_ERROR;
}
return $result;
}
}

345
lib/pear/OS/Guess.php Normal file
View File

@ -0,0 +1,345 @@
<?php
/**
* The OS_Guess class
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Gregory Beaver <cellog@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: Guess.php,v 1.20.2.1 2006/06/16 11:41:16 pajoye Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since PEAR 0.1
*/
// {{{ uname examples
// php_uname() without args returns the same as 'uname -a', or a PHP-custom
// string for Windows.
// PHP versions prior to 4.3 return the uname of the host where PHP was built,
// as of 4.3 it returns the uname of the host running the PHP code.
//
// PC RedHat Linux 7.1:
// Linux host.example.com 2.4.2-2 #1 Sun Apr 8 20:41:30 EDT 2001 i686 unknown
//
// PC Debian Potato:
// Linux host 2.4.17 #2 SMP Tue Feb 12 15:10:04 CET 2002 i686 unknown
//
// PC FreeBSD 3.3:
// FreeBSD host.example.com 3.3-STABLE FreeBSD 3.3-STABLE #0: Mon Feb 21 00:42:31 CET 2000 root@example.com:/usr/src/sys/compile/CONFIG i386
//
// PC FreeBSD 4.3:
// FreeBSD host.example.com 4.3-RELEASE FreeBSD 4.3-RELEASE #1: Mon Jun 25 11:19:43 EDT 2001 root@example.com:/usr/src/sys/compile/CONFIG i386
//
// PC FreeBSD 4.5:
// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb 6 23:59:23 CET 2002 root@example.com:/usr/src/sys/compile/CONFIG i386
//
// PC FreeBSD 4.5 w/uname from GNU shellutils:
// FreeBSD host.example.com 4.5-STABLE FreeBSD 4.5-STABLE #0: Wed Feb i386 unknown
//
// HP 9000/712 HP-UX 10:
// HP-UX iq B.10.10 A 9000/712 2008429113 two-user license
//
// HP 9000/712 HP-UX 10 w/uname from GNU shellutils:
// HP-UX host B.10.10 A 9000/712 unknown
//
// IBM RS6000/550 AIX 4.3:
// AIX host 3 4 000003531C00
//
// AIX 4.3 w/uname from GNU shellutils:
// AIX host 3 4 000003531C00 unknown
//
// SGI Onyx IRIX 6.5 w/uname from GNU shellutils:
// IRIX64 host 6.5 01091820 IP19 mips
//
// SGI Onyx IRIX 6.5:
// IRIX64 host 6.5 01091820 IP19
//
// SparcStation 20 Solaris 8 w/uname from GNU shellutils:
// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc
//
// SparcStation 20 Solaris 8:
// SunOS host.example.com 5.8 Generic_108528-12 sun4m sparc SUNW,SPARCstation-20
//
// Mac OS X (Darwin)
// Darwin home-eden.local 7.5.0 Darwin Kernel Version 7.5.0: Thu Aug 5 19:26:16 PDT 2004; root:xnu/xnu-517.7.21.obj~3/RELEASE_PPC Power Macintosh
//
// Mac OS X early versions
//
// }}}
/* TODO:
* - define endianness, to allow matchSignature("bigend") etc.
*/
/**
* Retrieves information about the current operating system
*
* This class uses php_uname() to grok information about the current OS
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Gregory Beaver <cellog@php.net>
* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.4.11
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class OS_Guess
{
var $sysname;
var $nodename;
var $cpu;
var $release;
var $extra;
function OS_Guess($uname = null)
{
list($this->sysname,
$this->release,
$this->cpu,
$this->extra,
$this->nodename) = $this->parseSignature($uname);
}
function parseSignature($uname = null)
{
static $sysmap = array(
'HP-UX' => 'hpux',
'IRIX64' => 'irix',
);
static $cpumap = array(
'i586' => 'i386',
'i686' => 'i386',
'ppc' => 'powerpc',
);
if ($uname === null) {
$uname = php_uname();
}
$parts = split('[[:space:]]+', trim($uname));
$n = count($parts);
$release = $machine = $cpu = '';
$sysname = $parts[0];
$nodename = $parts[1];
$cpu = $parts[$n-1];
$extra = '';
if ($cpu == 'unknown') {
$cpu = $parts[$n-2];
}
switch ($sysname) {
case 'AIX' :
$release = "$parts[3].$parts[2]";
break;
case 'Windows' :
switch ($parts[1]) {
case '95/98':
$release = '9x';
break;
default:
$release = $parts[1];
break;
}
$cpu = 'i386';
break;
case 'Linux' :
$extra = $this->_detectGlibcVersion();
// use only the first two digits from the kernel version
$release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]);
break;
case 'Mac' :
$sysname = 'darwin';
$nodename = $parts[2];
$release = $parts[3];
if ($cpu == 'Macintosh') {
if ($parts[$n - 2] == 'Power') {
$cpu = 'powerpc';
}
}
break;
case 'Darwin' :
if ($cpu == 'Macintosh') {
if ($parts[$n - 2] == 'Power') {
$cpu = 'powerpc';
}
}
$release = ereg_replace('^([[:digit:]]+\.[[:digit:]]+).*', '\1', $parts[2]);
break;
default:
$release = ereg_replace('-.*', '', $parts[2]);
break;
}
if (isset($sysmap[$sysname])) {
$sysname = $sysmap[$sysname];
} else {
$sysname = strtolower($sysname);
}
if (isset($cpumap[$cpu])) {
$cpu = $cpumap[$cpu];
}
return array($sysname, $release, $cpu, $extra, $nodename);
}
function _detectGlibcVersion()
{
static $glibc = false;
if ($glibc !== false) {
return $glibc; // no need to run this multiple times
}
include_once "System.php";
if (!@file_exists('/usr/bin/cpp') || !@is_executable('/usr/bin/cpp')) {
// Use glibc's <features.h> header file to
// get major and minor version number:
if (@file_exists('/usr/include/features.h') &&
@is_readable('/usr/include/features.h')) {
$features_file = fopen('/usr/include/features.h', 'rb');
while (!feof($features_file)) {
$line = fgets($features_file, 8192);
if (!$line || (strpos($line, '#define') === false)) {
continue;
}
if (strpos($line, '__GLIBC__')) {
// major version number #define __GLIBC__ version
$line = preg_split('/\s+/', $line);
$glibc_major = trim($line[2]);
if (isset($glibc_minor)) {
break;
}
continue;
}
if (strpos($line, '__GLIBC_MINOR__')) {
// got the minor version number
// #define __GLIBC_MINOR__ version
$line = preg_split('/\s+/', $line);
$glibc_minor = trim($line[2]);
if (isset($glibc_major)) {
break;
}
continue;
}
}
fclose($features_file);
if (!isset($glibc_major) || !isset($glibc_minor)) {
return $glibc = '';
}
return $glibc = 'glibc' . trim($glibc_major) . "." . trim($glibc_minor) ;
}
return $glibc = '';
}
$tmpfile = System::mktemp("glibctest");
$fp = fopen($tmpfile, "w");
fwrite($fp, "#include <features.h>\n__GLIBC__ __GLIBC_MINOR__\n");
fclose($fp);
$cpp = popen("/usr/bin/cpp $tmpfile", "r");
$major = $minor = 0;
while ($line = fgets($cpp, 1024)) {
if ($line{0} == '#' || trim($line) == '') {
continue;
}
if (list($major, $minor) = explode(' ', trim($line))) {
break;
}
}
pclose($cpp);
unlink($tmpfile);
if (!($major && $minor) && is_link('/lib/libc.so.6')) {
// Let's try reading the libc.so.6 symlink
if (ereg('^libc-([.*])\.so$', basename(readlink('/lib/libc.so.6')), $matches)) {
list($major, $minor) = explode('.', $matches);
}
}
if (!($major && $minor)) {
return $glibc = '';
}
return $glibc = "glibc{$major}.{$minor}";
}
function getSignature()
{
if (empty($this->extra)) {
return "{$this->sysname}-{$this->release}-{$this->cpu}";
}
return "{$this->sysname}-{$this->release}-{$this->cpu}-{$this->extra}";
}
function getSysname()
{
return $this->sysname;
}
function getNodename()
{
return $this->nodename;
}
function getCpu()
{
return $this->cpu;
}
function getRelease()
{
return $this->release;
}
function getExtra()
{
return $this->extra;
}
function matchSignature($match)
{
if (is_array($match)) {
$fragments = $match;
} else {
$fragments = explode('-', $match);
}
$n = count($fragments);
$matches = 0;
if ($n > 0) {
$matches += $this->_matchFragment($fragments[0], $this->sysname);
}
if ($n > 1) {
$matches += $this->_matchFragment($fragments[1], $this->release);
}
if ($n > 2) {
$matches += $this->_matchFragment($fragments[2], $this->cpu);
}
if ($n > 3) {
$matches += $this->_matchFragment($fragments[3], $this->extra);
}
return ($matches == $n);
}
function _matchFragment($fragment, $value)
{
if (strcspn($fragment, '*?') < strlen($fragment)) {
$reg = '^' . str_replace(array('*', '?', '/'), array('.*', '.', '\\/'), $fragment) . '$';
return eregi($reg, $value);
}
return ($fragment == '*' || !strcasecmp($fragment, $value));
}
}
/*
* Local Variables:
* indent-tabs-mode: nil
* c-basic-offset: 4
* End:
*/
?>

1101
lib/pear/PEAR.php Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,223 @@
<?php
/**
* Class auto-loader
*
* PHP versions 4
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: Autoloader.php,v 1.13 2006/01/06 04:47:36 cellog Exp $
* @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader
* @since File available since Release 0.1
* @deprecated File deprecated in Release 1.4.0a1
*/
// /* vim: set expandtab tabstop=4 shiftwidth=4: */
if (!extension_loaded("overload")) {
// die hard without ext/overload
die("Rebuild PHP with the `overload' extension to use PEAR_Autoloader");
}
/**
* Include for PEAR_Error and PEAR classes
*/
require_once "PEAR.php";
/**
* This class is for objects where you want to separate the code for
* some methods into separate classes. This is useful if you have a
* class with not-frequently-used methods that contain lots of code
* that you would like to avoid always parsing.
*
* The PEAR_Autoloader class provides autoloading and aggregation.
* The autoloading lets you set up in which classes the separated
* methods are found. Aggregation is the technique used to import new
* methods, an instance of each class providing separated methods is
* stored and called every time the aggregated method is called.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.4.11
* @link http://pear.php.net/manual/en/core.ppm.php#core.ppm.pear-autoloader
* @since File available since Release 0.1
* @deprecated File deprecated in Release 1.4.0a1
*/
class PEAR_Autoloader extends PEAR
{
// {{{ properties
/**
* Map of methods and classes where they are defined
*
* @var array
*
* @access private
*/
var $_autoload_map = array();
/**
* Map of methods and aggregate objects
*
* @var array
*
* @access private
*/
var $_method_map = array();
// }}}
// {{{ addAutoload()
/**
* Add one or more autoload entries.
*
* @param string $method which method to autoload
*
* @param string $classname (optional) which class to find the method in.
* If the $method parameter is an array, this
* parameter may be omitted (and will be ignored
* if not), and the $method parameter will be
* treated as an associative array with method
* names as keys and class names as values.
*
* @return void
*
* @access public
*/
function addAutoload($method, $classname = null)
{
if (is_array($method)) {
array_walk($method, create_function('$a,&$b', '$b = strtolower($b);'));
$this->_autoload_map = array_merge($this->_autoload_map, $method);
} else {
$this->_autoload_map[strtolower($method)] = $classname;
}
}
// }}}
// {{{ removeAutoload()
/**
* Remove an autoload entry.
*
* @param string $method which method to remove the autoload entry for
*
* @return bool TRUE if an entry was removed, FALSE if not
*
* @access public
*/
function removeAutoload($method)
{
$method = strtolower($method);
$ok = isset($this->_autoload_map[$method]);
unset($this->_autoload_map[$method]);
return $ok;
}
// }}}
// {{{ addAggregateObject()
/**
* Add an aggregate object to this object. If the specified class
* is not defined, loading it will be attempted following PEAR's
* file naming scheme. All the methods in the class will be
* aggregated, except private ones (name starting with an
* underscore) and constructors.
*
* @param string $classname what class to instantiate for the object.
*
* @return void
*
* @access public
*/
function addAggregateObject($classname)
{
$classname = strtolower($classname);
if (!class_exists($classname)) {
$include_file = preg_replace('/[^a-z0-9]/i', '_', $classname);
include_once $include_file;
}
$obj =& new $classname;
$methods = get_class_methods($classname);
foreach ($methods as $method) {
// don't import priviate methods and constructors
if ($method{0} != '_' && $method != $classname) {
$this->_method_map[$method] = $obj;
}
}
}
// }}}
// {{{ removeAggregateObject()
/**
* Remove an aggregate object.
*
* @param string $classname the class of the object to remove
*
* @return bool TRUE if an object was removed, FALSE if not
*
* @access public
*/
function removeAggregateObject($classname)
{
$ok = false;
$classname = strtolower($classname);
reset($this->_method_map);
while (list($method, $obj) = each($this->_method_map)) {
if (is_a($obj, $classname)) {
unset($this->_method_map[$method]);
$ok = true;
}
}
return $ok;
}
// }}}
// {{{ __call()
/**
* Overloaded object call handler, called each time an
* undefined/aggregated method is invoked. This method repeats
* the call in the right aggregate object and passes on the return
* value.
*
* @param string $method which method that was called
*
* @param string $args An array of the parameters passed in the
* original call
*
* @return mixed The return value from the aggregated method, or a PEAR
* error if the called method was unknown.
*/
function __call($method, $args, &$retval)
{
$method = strtolower($method);
if (empty($this->_method_map[$method]) && isset($this->_autoload_map[$method])) {
$this->addAggregateObject($this->_autoload_map[$method]);
}
if (isset($this->_method_map[$method])) {
$retval = call_user_func_array(array($this->_method_map[$method], $method), $args);
return true;
}
return false;
}
// }}}
}
overload("PEAR_Autoloader");
?>

455
lib/pear/PEAR/Builder.php Normal file
View File

@ -0,0 +1,455 @@
<?php
/**
* PEAR_Builder for building PHP extensions (PECL packages)
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: Builder.php,v 1.27 2006/01/06 04:47:36 cellog Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* Needed for extending PEAR_Builder
*/
require_once 'PEAR/Common.php';
require_once 'PEAR/PackageFile.php';
/**
* Class to handle building (compiling) extensions.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.4.11
* @link http://pear.php.net/package/PEAR
* @since Class available since PHP 4.0.2
* @see http://pear.php.net/manual/en/core.ppm.pear-builder.php
*/
class PEAR_Builder extends PEAR_Common
{
// {{{ properties
var $php_api_version = 0;
var $zend_module_api_no = 0;
var $zend_extension_api_no = 0;
var $extensions_built = array();
var $current_callback = null;
// used for msdev builds
var $_lastline = null;
var $_firstline = null;
// }}}
// {{{ constructor
/**
* PEAR_Builder constructor.
*
* @param object $ui user interface object (instance of PEAR_Frontend_*)
*
* @access public
*/
function PEAR_Builder(&$ui)
{
parent::PEAR_Common();
$this->setFrontendObject($ui);
}
// }}}
// {{{ _build_win32()
/**
* Build an extension from source on windows.
* requires msdev
*/
function _build_win32($descfile, $callback = null)
{
if (is_object($descfile)) {
$pkg = $descfile;
} else {
$pf = &new PEAR_PackageFile($this->config, $this->debug);
$pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
if (PEAR::isError($pkg)) {
return $pkg;
}
}
$dir = dirname($pkg->getArchiveFile());
$old_cwd = getcwd();
if (!@chdir($dir)) {
return $this->raiseError("could not chdir to $dir");
}
$this->log(2, "building in $dir");
$dsp = $pkg->getPackage().'.dsp';
if (!@is_file("$dir/$dsp")) {
return $this->raiseError("The DSP $dsp does not exist.");
}
// XXX TODO: make release build type configurable
$command = 'msdev '.$dsp.' /MAKE "'.$info['package']. ' - Release"';
$this->current_callback = $callback;
$err = $this->_runCommand($command, array(&$this, 'msdevCallback'));
if (PEAR::isError($err)) {
return $err;
}
// figure out the build platform and type
$platform = 'Win32';
$buildtype = 'Release';
if (preg_match('/.*?'.$pkg->getPackage().'\s-\s(\w+)\s(.*?)-+/i',$this->_firstline,$matches)) {
$platform = $matches[1];
$buildtype = $matches[2];
}
if (preg_match('/(.*)?\s-\s(\d+).*?(\d+)/',$this->_lastline,$matches)) {
if ($matches[2]) {
// there were errors in the build
return $this->raiseError("There were errors during compilation.");
}
$out = $matches[1];
} else {
return $this->raiseError("Did not understand the completion status returned from msdev.exe.");
}
// msdev doesn't tell us the output directory :/
// open the dsp, find /out and use that directory
$dsptext = join(file($dsp),'');
// this regex depends on the build platform and type having been
// correctly identified above.
$regex ='/.*?!IF\s+"\$\(CFG\)"\s+==\s+("'.
$pkg->getPackage().'\s-\s'.
$platform.'\s'.
$buildtype.'").*?'.
'\/out:"(.*?)"/is';
if ($dsptext && preg_match($regex,$dsptext,$matches)) {
// what we get back is a relative path to the output file itself.
$outfile = realpath($matches[2]);
} else {
return $this->raiseError("Could not retrieve output information from $dsp.");
}
if (@copy($outfile, "$dir/$out")) {
$outfile = "$dir/$out";
}
$built_files[] = array(
'file' => "$outfile",
'php_api' => $this->php_api_version,
'zend_mod_api' => $this->zend_module_api_no,
'zend_ext_api' => $this->zend_extension_api_no,
);
return $built_files;
}
// }}}
// {{{ msdevCallback()
function msdevCallback($what, $data)
{
if (!$this->_firstline)
$this->_firstline = $data;
$this->_lastline = $data;
}
// }}}
// {{{ _harventInstDir
/**
* @param string
* @param string
* @param array
* @access private
*/
function _harvestInstDir($dest_prefix, $dirname, &$built_files)
{
$d = opendir($dirname);
if (!$d)
return false;
$ret = true;
while (($ent = readdir($d)) !== false) {
if ($ent{0} == '.')
continue;
$full = $dirname . DIRECTORY_SEPARATOR . $ent;
if (is_dir($full)) {
if (!$this->_harvestInstDir(
$dest_prefix . DIRECTORY_SEPARATOR . $ent,
$full, $built_files)) {
$ret = false;
break;
}
} else {
$dest = $dest_prefix . DIRECTORY_SEPARATOR . $ent;
$built_files[] = array(
'file' => $full,
'dest' => $dest,
'php_api' => $this->php_api_version,
'zend_mod_api' => $this->zend_module_api_no,
'zend_ext_api' => $this->zend_extension_api_no,
);
}
}
closedir($d);
return $ret;
}
// }}}
// {{{ build()
/**
* Build an extension from source. Runs "phpize" in the source
* directory, but compiles in a temporary directory
* (/var/tmp/pear-build-USER/PACKAGE-VERSION).
*
* @param string|PEAR_PackageFile_v* $descfile path to XML package description file, or
* a PEAR_PackageFile object
*
* @param mixed $callback callback function used to report output,
* see PEAR_Builder::_runCommand for details
*
* @return array an array of associative arrays with built files,
* format:
* array( array( 'file' => '/path/to/ext.so',
* 'php_api' => YYYYMMDD,
* 'zend_mod_api' => YYYYMMDD,
* 'zend_ext_api' => YYYYMMDD ),
* ... )
*
* @access public
*
* @see PEAR_Builder::_runCommand
*/
function build($descfile, $callback = null)
{
if (PEAR_OS == "Windows") {
return $this->_build_win32($descfile,$callback);
}
if (PEAR_OS != 'Unix') {
return $this->raiseError("building extensions not supported on this platform");
}
if (is_object($descfile)) {
$pkg = $descfile;
$descfile = $pkg->getPackageFile();
} else {
$pf = &new PEAR_PackageFile($this->config);
$pkg = &$pf->fromPackageFile($descfile, PEAR_VALIDATE_NORMAL);
if (PEAR::isError($pkg)) {
return $pkg;
}
}
$dir = dirname($descfile);
$old_cwd = getcwd();
if (!@chdir($dir)) {
return $this->raiseError("could not chdir to $dir");
}
$vdir = $pkg->getPackage() . '-' . $pkg->getVersion();
if (is_dir($vdir)) {
chdir($vdir);
}
$dir = getcwd();
$this->log(2, "building in $dir");
$this->current_callback = $callback;
putenv('PATH=' . $this->config->get('bin_dir') . ':' . getenv('PATH'));
$err = $this->_runCommand("phpize", array(&$this, 'phpizeCallback'));
if (PEAR::isError($err)) {
return $err;
}
if (!$err) {
return $this->raiseError("`phpize' failed");
}
// {{{ start of interactive part
$configure_command = "$dir/configure";
$configure_options = $pkg->getConfigureOptions();
if ($configure_options) {
foreach ($configure_options as $o) {
list($r) = $this->ui->userDialog('build',
array($o['prompt']),
array('text'),
array(@$o['default']));
if (substr($o['name'], 0, 5) == 'with-' &&
($r == 'yes' || $r == 'autodetect')) {
$configure_command .= " --$o[name]";
} else {
$configure_command .= " --$o[name]=".trim($r);
}
}
}
// }}} end of interactive part
// FIXME make configurable
if(!$user=getenv('USER')){
$user='defaultuser';
}
$build_basedir = "/var/tmp/pear-build-$user";
$build_dir = "$build_basedir/$vdir";
$inst_dir = "$build_basedir/install-$vdir";
$this->log(1, "building in $build_dir");
if (is_dir($build_dir)) {
System::rm(array('-rf', $build_dir));
}
if (!System::mkDir(array('-p', $build_dir))) {
return $this->raiseError("could not create build dir: $build_dir");
}
$this->addTempFile($build_dir);
if (!System::mkDir(array('-p', $inst_dir))) {
return $this->raiseError("could not create temporary install dir: $inst_dir");
}
$this->addTempFile($inst_dir);
if (getenv('MAKE')) {
$make_command = getenv('MAKE');
} else {
$make_command = 'make';
}
$to_run = array(
$configure_command,
$make_command,
"$make_command INSTALL_ROOT=\"$inst_dir\" install",
"find \"$inst_dir\" -ls"
);
if (!@chdir($build_dir)) {
return $this->raiseError("could not chdir to $build_dir");
}
putenv('PHP_PEAR_VERSION=1.4.11');
foreach ($to_run as $cmd) {
$err = $this->_runCommand($cmd, $callback);
if (PEAR::isError($err)) {
chdir($old_cwd);
return $err;
}
if (!$err) {
chdir($old_cwd);
return $this->raiseError("`$cmd' failed");
}
}
if (!($dp = opendir("modules"))) {
chdir($old_cwd);
return $this->raiseError("no `modules' directory found");
}
$built_files = array();
$prefix = exec("php-config --prefix");
$this->_harvestInstDir($prefix, $inst_dir . DIRECTORY_SEPARATOR . $prefix, $built_files);
chdir($old_cwd);
return $built_files;
}
// }}}
// {{{ phpizeCallback()
/**
* Message callback function used when running the "phpize"
* program. Extracts the API numbers used. Ignores other message
* types than "cmdoutput".
*
* @param string $what the type of message
* @param mixed $data the message
*
* @return void
*
* @access public
*/
function phpizeCallback($what, $data)
{
if ($what != 'cmdoutput') {
return;
}
$this->log(1, rtrim($data));
if (preg_match('/You should update your .aclocal.m4/', $data)) {
return;
}
$matches = array();
if (preg_match('/^\s+(\S[^:]+):\s+(\d{8})/', $data, $matches)) {
$member = preg_replace('/[^a-z]/', '_', strtolower($matches[1]));
$apino = (int)$matches[2];
if (isset($this->$member)) {
$this->$member = $apino;
//$msg = sprintf("%-22s : %d", $matches[1], $apino);
//$this->log(1, $msg);
}
}
}
// }}}
// {{{ _runCommand()
/**
* Run an external command, using a message callback to report
* output. The command will be run through popen and output is
* reported for every line with a "cmdoutput" message with the
* line string, including newlines, as payload.
*
* @param string $command the command to run
*
* @param mixed $callback (optional) function to use as message
* callback
*
* @return bool whether the command was successful (exit code 0
* means success, any other means failure)
*
* @access private
*/
function _runCommand($command, $callback = null)
{
$this->log(1, "running: $command");
$pp = @popen("$command 2>&1", "r");
if (!$pp) {
return $this->raiseError("failed to run `$command'");
}
if ($callback && $callback[0]->debug == 1) {
$olddbg = $callback[0]->debug;
$callback[0]->debug = 2;
}
while ($line = fgets($pp, 1024)) {
if ($callback) {
call_user_func($callback, 'cmdoutput', $line);
} else {
$this->log(2, rtrim($line));
}
}
if ($callback && isset($olddbg)) {
$callback[0]->debug = $olddbg;
}
$exitcode = @pclose($pp);
return ($exitcode == 0);
}
// }}}
// {{{ log()
function log($level, $msg)
{
if ($this->current_callback) {
if ($this->debug >= $level) {
call_user_func($this->current_callback, 'output', $msg);
}
return;
}
return PEAR_Common::log($level, $msg);
}
// }}}
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,73 @@
<?php
/**
* PEAR_ChannelFile_Parser for parsing channel.xml
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: Parser.php,v 1.4 2006/01/06 04:47:36 cellog Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* base xml parser class
*/
require_once 'PEAR/XMLParser.php';
require_once 'PEAR/ChannelFile.php';
/**
* Parser for channel.xml
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.4.11
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_ChannelFile_Parser extends PEAR_XMLParser
{
var $_config;
var $_logger;
var $_registry;
function setConfig(&$c)
{
$this->_config = &$c;
$this->_registry = &$c->getRegistry();
}
function setLogger(&$l)
{
$this->_logger = &$l;
}
function parse($data, $file)
{
if (PEAR::isError($err = parent::parse($data, $file))) {
return $err;
}
$ret = new PEAR_ChannelFile;
$ret->setConfig($this->_config);
if (isset($this->_logger)) {
$ret->setLogger($this->_logger);
}
$ret->fromArray($this->_unserializedData);
// make sure the filelist is in the easy to read format needed
$ret->flattenFilelist();
$ret->setPackagefile($file, $archive);
return $ret;
}
}
?>

412
lib/pear/PEAR/Command.php Normal file
View File

@ -0,0 +1,412 @@
<?php
/**
* PEAR_Command, command pattern class
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: Command.php,v 1.36.2.1 2006/06/16 13:01:59 pajoye Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* Needed for error handling
*/
require_once 'PEAR.php';
require_once 'PEAR/Frontend.php';
require_once 'PEAR/XMLParser.php';
/**
* List of commands and what classes they are implemented in.
* @var array command => implementing class
*/
$GLOBALS['_PEAR_Command_commandlist'] = array();
/**
* List of shortcuts to common commands.
* @var array shortcut => command
*/
$GLOBALS['_PEAR_Command_shortcuts'] = array();
/**
* Array of command objects
* @var array class => object
*/
$GLOBALS['_PEAR_Command_objects'] = array();
/**
* PEAR command class, a simple factory class for administrative
* commands.
*
* How to implement command classes:
*
* - The class must be called PEAR_Command_Nnn, installed in the
* "PEAR/Common" subdir, with a method called getCommands() that
* returns an array of the commands implemented by the class (see
* PEAR/Command/Install.php for an example).
*
* - The class must implement a run() function that is called with three
* params:
*
* (string) command name
* (array) assoc array with options, freely defined by each
* command, for example:
* array('force' => true)
* (array) list of the other parameters
*
* The run() function returns a PEAR_CommandResponse object. Use
* these methods to get information:
*
* int getStatus() Returns PEAR_COMMAND_(SUCCESS|FAILURE|PARTIAL)
* *_PARTIAL means that you need to issue at least
* one more command to complete the operation
* (used for example for validation steps).
*
* string getMessage() Returns a message for the user. Remember,
* no HTML or other interface-specific markup.
*
* If something unexpected happens, run() returns a PEAR error.
*
* - DON'T OUTPUT ANYTHING! Return text for output instead.
*
* - DON'T USE HTML! The text you return will be used from both Gtk,
* web and command-line interfaces, so for now, keep everything to
* plain text.
*
* - DON'T USE EXIT OR DIE! Always use pear errors. From static
* classes do PEAR::raiseError(), from other classes do
* $this->raiseError().
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.4.11
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Command
{
// {{{ factory()
/**
* Get the right object for executing a command.
*
* @param string $command The name of the command
* @param object $config Instance of PEAR_Config object
*
* @return object the command object or a PEAR error
*
* @access public
* @static
*/
function &factory($command, &$config)
{
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
PEAR_Command::registerCommands();
}
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
}
if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
$a = PEAR::raiseError("unknown command `$command'");
return $a;
}
$class = $GLOBALS['_PEAR_Command_commandlist'][$command];
if (!class_exists($class)) {
require_once $GLOBALS['_PEAR_Command_objects'][$class];
}
if (!class_exists($class)) {
$a = PEAR::raiseError("unknown command `$command'");
return $a;
}
$ui =& PEAR_Command::getFrontendObject();
$obj = &new $class($ui, $config);
return $obj;
}
// }}}
// {{{ & getObject()
function &getObject($command)
{
$class = $GLOBALS['_PEAR_Command_commandlist'][$command];
if (!class_exists($class)) {
require_once $GLOBALS['_PEAR_Command_objects'][$class];
}
if (!class_exists($class)) {
return PEAR::raiseError("unknown command `$command'");
}
$ui =& PEAR_Command::getFrontendObject();
$config = &PEAR_Config::singleton();
$obj = &new $class($ui, $config);
return $obj;
}
// }}}
// {{{ & getFrontendObject()
/**
* Get instance of frontend object.
*
* @return object|PEAR_Error
* @static
*/
function &getFrontendObject()
{
$a = &PEAR_Frontend::singleton();
return $a;
}
// }}}
// {{{ & setFrontendClass()
/**
* Load current frontend class.
*
* @param string $uiclass Name of class implementing the frontend
*
* @return object the frontend object, or a PEAR error
* @static
*/
function &setFrontendClass($uiclass)
{
$a = &PEAR_Frontend::setFrontendClass($uiclass);
return $a;
}
// }}}
// {{{ setFrontendType()
/**
* Set current frontend.
*
* @param string $uitype Name of the frontend type (for example "CLI")
*
* @return object the frontend object, or a PEAR error
* @static
*/
function setFrontendType($uitype)
{
$uiclass = 'PEAR_Frontend_' . $uitype;
return PEAR_Command::setFrontendClass($uiclass);
}
// }}}
// {{{ registerCommands()
/**
* Scan through the Command directory looking for classes
* and see what commands they implement.
*
* @param bool (optional) if FALSE (default), the new list of
* commands should replace the current one. If TRUE,
* new entries will be merged with old.
*
* @param string (optional) where (what directory) to look for
* classes, defaults to the Command subdirectory of
* the directory from where this file (__FILE__) is
* included.
*
* @return bool TRUE on success, a PEAR error on failure
*
* @access public
* @static
*/
function registerCommands($merge = false, $dir = null)
{
$parser = new PEAR_XMLParser;
if ($dir === null) {
$dir = dirname(__FILE__) . '/Command';
}
if (!@is_dir($dir)) {
return PEAR::raiseError("registerCommands: opendir($dir) '$dir' does not exist or is not a directory");
}
$dp = @opendir($dir);
if (empty($dp)) {
return PEAR::raiseError("registerCommands: opendir($dir) failed");
}
if (!$merge) {
$GLOBALS['_PEAR_Command_commandlist'] = array();
}
while ($entry = readdir($dp)) {
if ($entry{0} == '.' || substr($entry, -4) != '.xml') {
continue;
}
$class = "PEAR_Command_".substr($entry, 0, -4);
$file = "$dir/$entry";
$parser->parse(file_get_contents($file));
$implements = $parser->getData();
// List of commands
if (empty($GLOBALS['_PEAR_Command_objects'][$class])) {
$GLOBALS['_PEAR_Command_objects'][$class] = "$dir/" . substr($entry, 0, -4) .
'.php';
}
foreach ($implements as $command => $desc) {
if ($command == 'attribs') {
continue;
}
if (isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
return PEAR::raiseError('Command "' . $command . '" already registered in ' .
'class "' . $GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
}
$GLOBALS['_PEAR_Command_commandlist'][$command] = $class;
$GLOBALS['_PEAR_Command_commanddesc'][$command] = $desc['summary'];
if (isset($desc['shortcut'])) {
$shortcut = $desc['shortcut'];
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$shortcut])) {
return PEAR::raiseError('Command shortcut "' . $shortcut . '" already ' .
'registered to command "' . $command . '" in class "' .
$GLOBALS['_PEAR_Command_commandlist'][$command] . '"');
}
$GLOBALS['_PEAR_Command_shortcuts'][$shortcut] = $command;
}
if (isset($desc['options']) && $desc['options']) {
foreach ($desc['options'] as $oname => $option) {
if (isset($option['shortopt']) && strlen($option['shortopt']) > 1) {
return PEAR::raiseError('Option "' . $oname . '" short option "' .
$option['shortopt'] . '" must be ' .
'only 1 character in Command "' . $command . '" in class "' .
$class . '"');
}
}
}
}
}
ksort($GLOBALS['_PEAR_Command_shortcuts']);
ksort($GLOBALS['_PEAR_Command_commandlist']);
@closedir($dp);
return true;
}
// }}}
// {{{ getCommands()
/**
* Get the list of currently supported commands, and what
* classes implement them.
*
* @return array command => implementing class
*
* @access public
* @static
*/
function getCommands()
{
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
PEAR_Command::registerCommands();
}
return $GLOBALS['_PEAR_Command_commandlist'];
}
// }}}
// {{{ getShortcuts()
/**
* Get the list of command shortcuts.
*
* @return array shortcut => command
*
* @access public
* @static
*/
function getShortcuts()
{
if (empty($GLOBALS['_PEAR_Command_shortcuts'])) {
PEAR_Command::registerCommands();
}
return $GLOBALS['_PEAR_Command_shortcuts'];
}
// }}}
// {{{ getGetoptArgs()
/**
* Compiles arguments for getopt.
*
* @param string $command command to get optstring for
* @param string $short_args (reference) short getopt format
* @param array $long_args (reference) long getopt format
*
* @return void
*
* @access public
* @static
*/
function getGetoptArgs($command, &$short_args, &$long_args)
{
if (empty($GLOBALS['_PEAR_Command_commandlist'])) {
PEAR_Command::registerCommands();
}
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
}
if (!isset($GLOBALS['_PEAR_Command_commandlist'][$command])) {
return null;
}
$obj = &PEAR_Command::getObject($command);
return $obj->getGetoptArgs($command, $short_args, $long_args);
}
// }}}
// {{{ getDescription()
/**
* Get description for a command.
*
* @param string $command Name of the command
*
* @return string command description
*
* @access public
* @static
*/
function getDescription($command)
{
if (!isset($GLOBALS['_PEAR_Command_commanddesc'][$command])) {
return null;
}
return $GLOBALS['_PEAR_Command_commanddesc'][$command];
}
// }}}
// {{{ getHelp()
/**
* Get help for command.
*
* @param string $command Name of the command to return help for
*
* @access public
* @static
*/
function getHelp($command)
{
$cmds = PEAR_Command::getCommands();
if (isset($GLOBALS['_PEAR_Command_shortcuts'][$command])) {
$command = $GLOBALS['_PEAR_Command_shortcuts'][$command];
}
if (isset($cmds[$command])) {
$obj = &PEAR_Command::getObject($command);
return $obj->getHelp($command);
}
return false;
}
// }}}
}
?>

View File

@ -0,0 +1,186 @@
<?php
/**
* PEAR_Command_Auth (login, logout commands)
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: Auth.php,v 1.23 2006/03/02 18:14:13 cellog Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR/Command/Common.php';
require_once 'PEAR/Config.php';
/**
* PEAR commands for login/logout
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.4.11
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Command_Auth extends PEAR_Command_Common
{
// {{{ properties
var $commands = array(
'login' => array(
'summary' => 'Connects and authenticates to remote server',
'shortcut' => 'li',
'function' => 'doLogin',
'options' => array(),
'doc' => '
Log in to the remote server. To use remote functions in the installer
that require any kind of privileges, you need to log in first. The
username and password you enter here will be stored in your per-user
PEAR configuration (~/.pearrc on Unix-like systems). After logging
in, your username and password will be sent along in subsequent
operations on the remote server.',
),
'logout' => array(
'summary' => 'Logs out from the remote server',
'shortcut' => 'lo',
'function' => 'doLogout',
'options' => array(),
'doc' => '
Logs out from the remote server. This command does not actually
connect to the remote server, it only deletes the stored username and
password from your user configuration.',
)
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Auth constructor.
*
* @access public
*/
function PEAR_Command_Auth(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
// }}}
// {{{ doLogin()
/**
* Execute the 'login' command.
*
* @param string $command command name
*
* @param array $options option_name => value
*
* @param array $params list of additional parameters
*
* @return bool TRUE on success or
* a PEAR error on failure
*
* @access public
*/
function doLogin($command, $options, $params)
{
$reg = &$this->config->getRegistry();
$channel = $this->config->get('default_channel');
$chan = $reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $this->raiseError($chan);
}
$server = $this->config->get('preferred_mirror');
$remote = &$this->config->getRemote();
$username = $this->config->get('username');
if (empty($username)) {
$username = @$_ENV['USER'];
}
$this->ui->outputData("Logging in to $server.", $command);
list($username, $password) = $this->ui->userDialog(
$command,
array('Username', 'Password'),
array('text', 'password'),
array($username, '')
);
$username = trim($username);
$password = trim($password);
$this->config->set('username', $username);
$this->config->set('password', $password);
if ($chan->supportsREST()) {
$ok = true;
} else {
$remote->expectError(401);
$ok = $remote->call('logintest');
$remote->popExpect();
}
if ($ok === true) {
$this->ui->outputData("Logged in.", $command);
$this->config->store();
} else {
return $this->raiseError("Login failed!");
}
return true;
}
// }}}
// {{{ doLogout()
/**
* Execute the 'logout' command.
*
* @param string $command command name
*
* @param array $options option_name => value
*
* @param array $params list of additional parameters
*
* @return bool TRUE on success or
* a PEAR error on failure
*
* @access public
*/
function doLogout($command, $options, $params)
{
$reg = &$this->config->getRegistry();
$channel = $this->config->get('default_channel');
$chan = $reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $this->raiseError($chan);
}
$server = $this->config->get('preferred_mirror');
$this->ui->outputData("Logging out from $server.", $command);
$this->config->remove('username');
$this->config->remove('password');
$this->config->store();
return true;
}
// }}}
}
?>

View File

@ -0,0 +1,25 @@
<commands version="1.0">
<login>
<summary>Connects and authenticates to remote server</summary>
<shortcut>li</shortcut>
<function>doLogin</function>
<options />
<doc>
Log in to the remote server. To use remote functions in the installer
that require any kind of privileges, you need to log in first. The
username and password you enter here will be stored in your per-user
PEAR configuration (~/.pearrc on Unix-like systems). After logging
in, your username and password will be sent along in subsequent
operations on the remote server.</doc>
</login>
<logout>
<summary>Logs out from the remote server</summary>
<shortcut>lo</shortcut>
<function>doLogout</function>
<options />
<doc>
Logs out from the remote server. This command does not actually
connect to the remote server, it only deletes the stored username and
password from your user configuration.</doc>
</logout>
</commands>

View File

@ -0,0 +1,104 @@
<?php
/**
* PEAR_Command_Auth (build command)
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: Build.php,v 1.13 2006/01/06 04:47:36 cellog Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for building extensions.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Tomas V.V.Cox <cox@idecnet.com>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.4.11
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Command_Build extends PEAR_Command_Common
{
// {{{ properties
var $commands = array(
'build' => array(
'summary' => 'Build an Extension From C Source',
'function' => 'doBuild',
'shortcut' => 'b',
'options' => array(),
'doc' => '[package.xml]
Builds one or more extensions contained in a package.'
),
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Build constructor.
*
* @access public
*/
function PEAR_Command_Build(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
// }}}
// {{{ doBuild()
function doBuild($command, $options, $params)
{
require_once 'PEAR/Builder.php';
if (sizeof($params) < 1) {
$params[0] = 'package.xml';
}
$builder = &new PEAR_Builder($this->ui);
$this->debug = $this->config->get('verbose');
$err = $builder->build($params[0], array(&$this, 'buildCallback'));
if (PEAR::isError($err)) {
return $err;
}
return true;
}
// }}}
// {{{ buildCallback()
function buildCallback($what, $data)
{
if (($what == 'cmdoutput' && $this->debug > 1) ||
($what == 'output' && $this->debug > 0)) {
$this->ui->outputData(rtrim($data), 'build');
}
}
// }}}
}

View File

@ -0,0 +1,10 @@
<commands version="1.0">
<build>
<summary>Build an Extension From C Source</summary>
<function>doBuild</function>
<shortcut>b</shortcut>
<options />
<doc>[package.xml]
Builds one or more extensions contained in a package.</doc>
</build>
</commands>

View File

@ -0,0 +1,780 @@
<?php
// /* vim: set expandtab tabstop=4 shiftwidth=4: */
/**
* PEAR_Command_Channels (list-channels, update-channels, channel-delete, channel-add,
* channel-update, channel-info, channel-alias, channel-discover commands)
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: Channels.php,v 1.44.2.1 2006/07/17 18:24:10 pajoye Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.0a1
*/
/**
* base class
*/
require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for managing channels.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.4.11
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.0a1
*/
class PEAR_Command_Channels extends PEAR_Command_Common
{
// {{{ properties
var $commands = array(
'list-channels' => array(
'summary' => 'List Available Channels',
'function' => 'doList',
'shortcut' => 'lc',
'options' => array(),
'doc' => '
List all available channels for installation.
',
),
'update-channels' => array(
'summary' => 'Update the Channel List',
'function' => 'doUpdateAll',
'shortcut' => 'uc',
'options' => array(),
'doc' => '
List all installed packages in all channels.
'
),
'channel-delete' => array(
'summary' => 'Remove a Channel From the List',
'function' => 'doDelete',
'shortcut' => 'cde',
'options' => array(),
'doc' => '<channel name>
Delete a channel from the registry. You may not
remove any channel that has installed packages.
'
),
'channel-add' => array(
'summary' => 'Add a Channel',
'function' => 'doAdd',
'shortcut' => 'ca',
'options' => array(),
'doc' => '<channel.xml>
Add a private channel to the channel list. Note that all
public channels should be synced using "update-channels".
Parameter may be either a local file or remote URL to a
channel.xml.
'
),
'channel-update' => array(
'summary' => 'Update an Existing Channel',
'function' => 'doUpdate',
'shortcut' => 'cu',
'options' => array(
'force' => array(
'shortopt' => 'f',
'doc' => 'will force download of new channel.xml if an existing channel name is used',
),
'channel' => array(
'shortopt' => 'c',
'arg' => 'CHANNEL',
'doc' => 'will force download of new channel.xml if an existing channel name is used',
),
),
'doc' => '[<channel.xml>|<channel name>]
Update a channel in the channel list directly. Note that all
public channels can be synced using "update-channels".
Parameter may be a local or remote channel.xml, or the name of
an existing channel.
'
),
'channel-info' => array(
'summary' => 'Retrieve Information on a Channel',
'function' => 'doInfo',
'shortcut' => 'ci',
'options' => array(),
'doc' => '<package>
List the files in an installed package.
'
),
'channel-alias' => array(
'summary' => 'Specify an alias to a channel name',
'function' => 'doAlias',
'shortcut' => 'cha',
'options' => array(),
'doc' => '<channel> <alias>
Specify a specific alias to use for a channel name.
The alias may not be an existing channel name or
alias.
'
),
'channel-discover' => array(
'summary' => 'Initialize a Channel from its server',
'function' => 'doDiscover',
'shortcut' => 'di',
'options' => array(),
'doc' => '[<channel.xml>|<channel name>]
Initialize a Channel from its server and creates the local channel.xml.
'
),
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Registry constructor.
*
* @access public
*/
function PEAR_Command_Channels(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
// }}}
// {{{ doList()
function _sortChannels($a, $b)
{
return strnatcasecmp($a->getName(), $b->getName());
}
function doList($command, $options, $params)
{
$reg = &$this->config->getRegistry();
$registered = $reg->getChannels();
usort($registered, array(&$this, '_sortchannels'));
$i = $j = 0;
$data = array(
'caption' => 'Registered Channels:',
'border' => true,
'headline' => array('Channel', 'Summary')
);
foreach ($registered as $channel) {
$data['data'][] = array($channel->getName(),
$channel->getSummary());
}
if (count($registered)==0) {
$data = '(no registered channels)';
}
$this->ui->outputData($data, $command);
return true;
}
function doUpdateAll($command, $options, $params)
{
$reg = &$this->config->getRegistry();
$savechannel = $this->config->get('default_channel');
if (isset($options['channel'])) {
if (!$reg->channelExists($options['channel'])) {
return $this->raiseError('Unknown channel "' . $options['channel'] . '"');
}
$this->config->set('default_channel', $options['channel']);
} else {
$this->config->set('default_channel', 'pear.php.net');
}
$remote = &$this->config->getRemote();
$channels = $remote->call('channel.listAll');
if (PEAR::isError($channels)) {
$this->config->set('default_channel', $savechannel);
return $channels;
}
if (!is_array($channels) || isset($channels['faultCode'])) {
$this->config->set('default_channel', $savechannel);
return $this->raiseError("Incorrect channel listing returned from channel '$chan'");
}
if (!count($channels)) {
$data = 'no updates available';
}
$dl = &$this->getDownloader();
if (!class_exists('System')) {
require_once 'System.php';
}
$tmpdir = System::mktemp(array('-d'));
foreach ($channels as $channel) {
$channel = $channel[0];
$save = $channel;
if ($reg->channelExists($channel, true)) {
$this->ui->outputData("Updating channel \"$channel\"", $command);
$test = $reg->getChannel($channel, true);
if (PEAR::isError($test)) {
$this->ui->outputData("Channel '$channel' is corrupt in registry!", $command);
$lastmodified = false;
} else {
$lastmodified = $test->lastModified();
}
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$contents = $dl->downloadHttp('http://' . $test->getName() . '/channel.xml',
$this->ui, $tmpdir, null, $lastmodified);
PEAR::staticPopErrorHandling();
if (PEAR::isError($contents)) {
$this->ui->outputData('ERROR: Cannot retrieve channel.xml for channel "' .
$test->getName() . '"', $command);
continue;
}
if (!$contents) {
$this->ui->outputData("Channel \"$channel\" is up-to-date", $command);
continue;
}
list($contents, $lastmodified) = $contents;
$info = implode('', file($contents));
if (!$info) {
$this->ui->outputData("Channel \"$channel\" is up-to-date", $command);
continue;
}
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$channelinfo = new PEAR_ChannelFile;
$channelinfo->fromXmlString($info);
if ($channelinfo->getErrors()) {
$this->ui->outputData("Downloaded channel data from channel \"$channel\" " .
'is corrupt, skipping', $command);
continue;
}
$channel = $channelinfo;
if ($channel->getName() != $save) {
$this->ui->outputData('ERROR: Security risk - downloaded channel ' .
'definition file for channel "'
. $channel->getName() . ' from channel "' . $save .
'". To use anyway, use channel-update', $command);
continue;
}
$reg->updateChannel($channel, $lastmodified);
} else {
if ($reg->isAlias($channel)) {
$temp = &$reg->getChannel($channel);
if (PEAR::isError($temp)) {
return $this->raiseError($temp);
}
$temp->setAlias($temp->getName(), true); // set the alias to the channel name
if ($reg->channelExists($temp->getName())) {
$this->ui->outputData('ERROR: existing channel "' . $temp->getName() .
'" is aliased to "' . $channel . '" already and cannot be ' .
're-aliased to "' . $temp->getName() . '" because a channel with ' .
'that name or alias already exists! Please re-alias and try ' .
'again.', $command);
continue;
}
}
$this->ui->outputData("Adding new channel \"$channel\"", $command);
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$contents = $dl->downloadHttp('http://' . $channel . '/channel.xml',
$this->ui, $tmpdir, null, false);
PEAR::staticPopErrorHandling();
if (PEAR::isError($contents)) {
$this->ui->outputData('ERROR: Cannot retrieve channel.xml for channel "' .
$channel . '"', $command);
continue;
}
list($contents, $lastmodified) = $contents;
$info = implode('', file($contents));
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$channelinfo = new PEAR_Channelfile;
$channelinfo->fromXmlString($info);
if ($channelinfo->getErrors()) {
$this->ui->outputData("Downloaded channel data from channel \"$channel\"" .
' is corrupt, skipping', $command);
continue;
}
$channel = $channelinfo;
if ($channel->getName() != $save) {
$this->ui->outputData('ERROR: Security risk - downloaded channel ' .
'definition file for channel "'
. $channel->getName() . '" from channel "' . $save .
'". To use anyway, use channel-update', $command);
continue;
}
$reg->addChannel($channel, $lastmodified);
}
}
$this->config->set('default_channel', $savechannel);
$this->ui->outputData('update-channels complete', $command);
return true;
}
function doInfo($command, $options, $params)
{
if (sizeof($params) != 1) {
return $this->raiseError("No channel specified");
}
$reg = &$this->config->getRegistry();
$channel = strtolower($params[0]);
if ($reg->channelExists($channel)) {
$chan = $reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $this->raiseError($chan);
}
} else {
if (strpos($channel, '://')) {
$downloader = &$this->getDownloader();
if (!class_exists('System')) {
require_once 'System.php';
}
$tmpdir = System::mktemp(array('-d'));
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$loc = $downloader->downloadHttp($channel, $this->ui, $tmpdir);
PEAR::staticPopErrorHandling();
if (PEAR::isError($loc)) {
return $this->raiseError('Cannot open "' . $channel . '"');
} else {
$contents = implode('', file($loc));
}
} else {
$fp = @fopen($params[0], 'r');
if (!$fp) {
if (@file_exists($params[0])) {
return $this->raiseError('Cannot open "' . $params[0] . '"');
} else {
return $this->raiseError('Unknown channel "' . $channel . '"');
}
}
$contents = '';
while (!feof($fp)) {
$contents .= fread($fp, 1024);
}
fclose($fp);
}
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$chan = new PEAR_ChannelFile;
$chan->fromXmlString($contents);
$chan->validate();
if ($errs = $chan->getErrors(true)) {
foreach ($errs as $err) {
$this->ui->outputData($err['level'] . ': ' . $err['message']);
}
return $this->raiseError('Channel file "' . $params[0] . '" is not valid');
}
}
if ($chan) {
$channel = $chan->getName();
$caption = 'Channel ' . $channel . ' Information:';
$data1 = array(
'caption' => $caption,
'border' => true);
$data1['data']['server'] = array('Name and Server', $chan->getName());
if ($chan->getAlias() != $chan->getName()) {
$data1['data']['alias'] = array('Alias', $chan->getAlias());
}
$data1['data']['summary'] = array('Summary', $chan->getSummary());
$validate = $chan->getValidationPackage();
$data1['data']['vpackage'] = array('Validation Package Name', $validate['_content']);
$data1['data']['vpackageversion'] =
array('Validation Package Version', $validate['attribs']['version']);
$d = array();
$d['main'] = $data1;
$data['data'] = array();
$data['caption'] = 'Server Capabilities';
$data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
$capabilities = $chan->getFunctions('xmlrpc');
$soaps = $chan->getFunctions('soap');
if ($capabilities || $soaps || $chan->supportsREST()) {
if ($capabilities) {
if (!isset($capabilities[0])) {
$capabilities = array($capabilities);
}
foreach ($capabilities as $protocol) {
$data['data'][] = array('xmlrpc', $protocol['attribs']['version'],
$protocol['_content']);
}
}
if ($soaps) {
if (!isset($soaps[0])) {
$soaps = array($soaps);
}
foreach ($soaps as $protocol) {
$data['data'][] = array('soap', $protocol['attribs']['version'],
$protocol['_content']);
}
}
if ($chan->supportsREST()) {
$funcs = $chan->getFunctions('rest');
if (!isset($funcs[0])) {
$funcs = array($funcs);
}
foreach ($funcs as $protocol) {
$data['data'][] = array('rest', $protocol['attribs']['type'],
$protocol['_content']);
}
}
} else {
$data['data'][] = array('No supported protocols');
}
$d['protocols'] = $data;
$data['data'] = array();
$mirrors = $chan->getMirrors();
if ($mirrors) {
$data['caption'] = 'Channel ' . $channel . ' Mirrors:';
unset($data['headline']);
foreach ($mirrors as $mirror) {
$data['data'][] = array($mirror['attribs']['host']);
$d['mirrors'] = $data;
}
foreach ($mirrors as $mirror) {
$data['data'] = array();
$data['caption'] = 'Mirror ' . $mirror['attribs']['host'] . ' Capabilities';
$data['headline'] = array('Type', 'Version/REST type', 'Function Name/REST base');
$capabilities = $chan->getFunctions('xmlrpc', $mirror['attribs']['host']);
$soaps = $chan->getFunctions('soap', $mirror['attribs']['host']);
if ($capabilities || $soaps || $chan->supportsREST($mirror['attribs']['host'])) {
if ($capabilities) {
if (!isset($capabilities[0])) {
$capabilities = array($capabilities);
}
foreach ($capabilities as $protocol) {
$data['data'][] = array('xmlrpc', $protocol['attribs']['version'],
$protocol['_content']);
}
}
if ($soaps) {
if (!isset($soaps[0])) {
$soaps = array($soaps);
}
foreach ($soaps as $protocol) {
$data['data'][] = array('soap', $protocol['attribs']['version'],
$protocol['_content']);
}
}
if ($chan->supportsREST($mirror['attribs']['host'])) {
$funcs = $chan->getFunctions('rest', $mirror['attribs']['host']);
if (!isset($funcs[0])) {
$funcs = array($funcs);
}
foreach ($funcs as $protocol) {
$data['data'][] = array('rest', $protocol['attribs']['type'],
$protocol['_content']);
}
}
} else {
$data['data'][] = array('No supported protocols');
}
$d['mirrorprotocols'] = $data;
}
}
$this->ui->outputData($d, 'channel-info');
} else {
return $this->raiseError('Serious error: Channel "' . $params[0] .
'" has a corrupted registry entry');
}
}
// }}}
function doDelete($command, $options, $params)
{
if (sizeof($params) != 1) {
return $this->raiseError('channel-delete: no channel specified');
}
$reg = &$this->config->getRegistry();
if (!$reg->channelExists($params[0])) {
return $this->raiseError('channel-delete: channel "' . $params[0] . '" does not exist');
}
$channel = $reg->channelName($params[0]);
if ($channel == 'pear.php.net') {
return $this->raiseError('Cannot delete the pear.php.net channel');
}
if ($channel == 'pecl.php.net') {
return $this->raiseError('Cannot delete the pecl.php.net channel');
}
if ($channel == '__uri') {
return $this->raiseError('Cannot delete the __uri pseudo-channel');
}
if (PEAR::isError($err = $reg->listPackages($channel))) {
return $err;
}
if (count($err)) {
return $this->raiseError('Channel "' . $channel .
'" has installed packages, cannot delete');
}
if (!$reg->deleteChannel($channel)) {
return $this->raiseError('Channel "' . $channel . '" deletion failed');
} else {
$this->config->deleteChannel($channel);
$this->ui->outputData('Channel "' . $channel . '" deleted', $command);
}
}
function doAdd($command, $options, $params)
{
if (sizeof($params) != 1) {
return $this->raiseError('channel-add: no channel file specified');
}
if (strpos($params[0], '://')) {
$downloader = &$this->getDownloader();
if (!class_exists('System')) {
require_once 'System.php';
}
$tmpdir = System::mktemp(array('-d'));
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$loc = $downloader->downloadHttp($params[0], $this->ui, $tmpdir, null, false);
PEAR::staticPopErrorHandling();
if (PEAR::isError($loc)) {
return $this->raiseError('channel-add: Cannot open "' . $params[0] . '"');
} else {
list($loc, $lastmodified) = $loc;
$contents = implode('', file($loc));
}
} else {
$lastmodified = false;
$fp = @fopen($params[0], 'r');
if (!$fp) {
return $this->raiseError('channel-add: cannot open "' . $params[0] . '"');
}
$contents = '';
while (!feof($fp)) {
$contents .= fread($fp, 1024);
}
fclose($fp);
}
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$channel = new PEAR_ChannelFile;
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$result = $channel->fromXmlString($contents);
PEAR::staticPopErrorHandling();
if (!$result) {
$exit = false;
if (count($errors = $channel->getErrors(true))) {
foreach ($errors as $error) {
$this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
if (!$exit) {
$exit = $error['level'] == 'error' ? true : false;
}
}
if ($exit) {
return $this->raiseError('channel-add: invalid channel.xml file');
}
}
}
$reg = &$this->config->getRegistry();
if ($reg->channelExists($channel->getName())) {
return $this->raiseError('channel-add: Channel "' . $channel->getName() .
'" exists, use channel-update to update entry');
}
$ret = $reg->addChannel($channel, $lastmodified);
if (PEAR::isError($ret)) {
return $ret;
}
if (!$ret) {
return $this->raiseError('channel-add: adding Channel "' . $channel->getName() .
'" to registry failed');
}
$this->config->setChannels($reg->listChannels());
$this->config->writeConfigFile();
$this->ui->outputData('Adding Channel "' . $channel->getName() . '" succeeded', $command);
}
function doUpdate($command, $options, $params)
{
if (!class_exists('System')) {
require_once 'System.php';
}
$tmpdir = System::mktemp(array('-d'));
$reg = &$this->config->getRegistry();
if (sizeof($params) != 1) {
return $this->raiseError("No channel file specified");
}
$lastmodified = false;
if ((!file_exists($params[0]) || is_dir($params[0]))
&& $reg->channelExists(strtolower($params[0]))) {
$c = $reg->getChannel(strtolower($params[0]));
if (PEAR::isError($c)) {
return $this->raiseError($c);
}
$this->ui->outputData('Retrieving channel.xml from remote server');
$dl = &$this->getDownloader(array());
// if force is specified, use a timestamp of "1" to force retrieval
$lastmodified = isset($options['force']) ? false : $c->lastModified();
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$contents = $dl->downloadHttp('http://' . $c->getName() . '/channel.xml',
$this->ui, $tmpdir, null, $lastmodified);
PEAR::staticPopErrorHandling();
if (PEAR::isError($contents)) {
return $this->raiseError('Cannot retrieve channel.xml for channel "' .
$c->getName() . '"');
}
list($contents, $lastmodified) = $contents;
if (!$contents) {
$this->ui->outputData("Channel $params[0] channel.xml is up to date");
return;
}
$contents = implode('', file($contents));
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$channel = new PEAR_ChannelFile;
$channel->fromXmlString($contents);
if (!$channel->getErrors()) {
// security check: is the downloaded file for the channel we got it from?
if (strtolower($channel->getName()) != strtolower($c->getName())) {
if (isset($options['force'])) {
$this->ui->log(0, 'WARNING: downloaded channel definition file' .
' for channel "' . $channel->getName() . '" from channel "' .
strtolower($c->getName()) . '"');
} else {
return $this->raiseError('ERROR: downloaded channel definition file' .
' for channel "' . $channel->getName() . '" from channel "' .
strtolower($c->getName()) . '"');
}
}
}
} else {
if (strpos($params[0], '://')) {
$dl = &$this->getDownloader();
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$loc = $dl->downloadHttp($params[0],
$this->ui, $tmpdir, null, $lastmodified);
PEAR::staticPopErrorHandling();
if (PEAR::isError($loc)) {
return $this->raiseError("Cannot open " . $params[0]);
} else {
list($loc, $lastmodified) = $loc;
$contents = implode('', file($loc));
}
} else {
$fp = @fopen($params[0], 'r');
if (!$fp) {
return $this->raiseError("Cannot open " . $params[0]);
}
$contents = '';
while (!feof($fp)) {
$contents .= fread($fp, 1024);
}
fclose($fp);
}
if (!class_exists('PEAR_ChannelFile')) {
require_once 'PEAR/ChannelFile.php';
}
$channel = new PEAR_ChannelFile;
$channel->fromXmlString($contents);
}
$exit = false;
if (count($errors = $channel->getErrors(true))) {
foreach ($errors as $error) {
$this->ui->outputData(ucfirst($error['level'] . ': ' . $error['message']));
if (!$exit) {
$exit = $error['level'] == 'error' ? true : false;
}
}
if ($exit) {
return $this->raiseError('Invalid channel.xml file');
}
}
if (!$reg->channelExists($channel->getName())) {
return $this->raiseError('Error: Channel "' . $channel->getName() .
'" does not exist, use channel-add to add an entry');
}
$ret = $reg->updateChannel($channel, $lastmodified);
if (PEAR::isError($ret)) {
return $ret;
}
if (!$ret) {
return $this->raiseError('Updating Channel "' . $channel->getName() .
'" in registry failed');
}
$this->config->setChannels($reg->listChannels());
$this->config->writeConfigFile();
$this->ui->outputData('Update of Channel "' . $channel->getName() . '" succeeded');
}
function &getDownloader()
{
if (!class_exists('PEAR_Downloader')) {
require_once 'PEAR/Downloader.php';
}
$a = new PEAR_Downloader($this->ui, array(), $this->config);
return $a;
}
function doAlias($command, $options, $params)
{
$reg = &$this->config->getRegistry();
if (sizeof($params) == 1) {
return $this->raiseError('No channel alias specified');
}
if (sizeof($params) != 2) {
return $this->raiseError(
'Invalid format, correct is: channel-alias channel alias');
}
if (!$reg->channelExists($params[0], true)) {
if ($reg->isAlias($params[0])) {
$extra = ' (use "channel-alias ' . $reg->channelName($params[0]) . ' ' .
strtolower($params[1]) . '")';
} else {
$extra = '';
}
return $this->raiseError('"' . $params[0] . '" is not a valid channel' . $extra);
}
if ($reg->isAlias($params[1])) {
return $this->raiseError('Channel "' . $reg->channelName($params[1]) . '" is ' .
'already aliased to "' . strtolower($params[1]) . '", cannot re-alias');
}
$chan = &$reg->getChannel($params[0]);
if (PEAR::isError($chan)) {
return $this->raiseError('Corrupt registry? Error retrieving channel "' . $params[0] .
'" information (' . $chan->getMessage() . ')');
}
// make it a local alias
if (!$chan->setAlias(strtolower($params[1]), true)) {
return $this->raiseError('Alias "' . strtolower($params[1]) .
'" is not a valid channel alias');
}
$reg->updateChannel($chan);
$this->ui->outputData('Channel "' . $chan->getName() . '" aliased successfully to "' .
strtolower($params[1]) . '"');
}
function doDiscover($command, $options, $params)
{
$reg = &$this->config->getRegistry();
if (sizeof($params) != 1) {
return $this->raiseError("No channel server specified");
}
if ($reg->channelExists($params[0])) {
if ($reg->isAlias($params[0])) {
return $this->raiseError("A channel alias named \"$params[0]\" " .
'already exists, aliasing channel "' . $reg->channelName($params[0])
. '"');
} else {
return $this->raiseError("Channel \"$params[0]\" is already initialized");
}
}
$this->pushErrorHandling(PEAR_ERROR_RETURN);
$err = $this->doAdd($command, $options, array('http://' . $params[0] . '/channel.xml'));
$this->popErrorHandling();
if (PEAR::isError($err)) {
return $this->raiseError("Discovery of channel \"$params[0]\" failed (" .
$err->getMessage() . ')');
}
$this->ui->outputData("Discovery of channel \"$params[0]\" succeeded", $command);
}
}
?>

View File

@ -0,0 +1,93 @@
<commands version="1.0">
<list-channels>
<summary>List Available Channels</summary>
<function>doList</function>
<shortcut>lc</shortcut>
<options />
<doc>
List all available channels for installation.
</doc>
</list-channels>
<update-channels>
<summary>Update the Channel List</summary>
<function>doUpdateAll</function>
<shortcut>uc</shortcut>
<options />
<doc>
List all installed packages in all channels.
</doc>
</update-channels>
<channel-delete>
<summary>Remove a Channel From the List</summary>
<function>doDelete</function>
<shortcut>cde</shortcut>
<options />
<doc>&lt;channel name&gt;
Delete a channel from the registry. You may not
remove any channel that has installed packages.
</doc>
</channel-delete>
<channel-add>
<summary>Add a Channel</summary>
<function>doAdd</function>
<shortcut>ca</shortcut>
<options />
<doc>&lt;channel.xml&gt;
Add a private channel to the channel list. Note that all
public channels should be synced using &quot;update-channels&quot;.
Parameter may be either a local file or remote URL to a
channel.xml.
</doc>
</channel-add>
<channel-update>
<summary>Update an Existing Channel</summary>
<function>doUpdate</function>
<shortcut>cu</shortcut>
<options>
<force>
<shortopt>f</shortopt>
<doc>will force download of new channel.xml if an existing channel name is used</doc>
</force>
<channel>
<shortopt>c</shortopt>
<arg>CHANNEL</arg>
<doc>will force download of new channel.xml if an existing channel name is used</doc>
</channel>
</options>
<doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
Update a channel in the channel list directly. Note that all
public channels can be synced using &quot;update-channels&quot;.
Parameter may be a local or remote channel.xml, or the name of
an existing channel.
</doc>
</channel-update>
<channel-info>
<summary>Retrieve Information on a Channel</summary>
<function>doInfo</function>
<shortcut>ci</shortcut>
<options />
<doc>&lt;package&gt;
List the files in an installed package.
</doc>
</channel-info>
<channel-alias>
<summary>Specify an alias to a channel name</summary>
<function>doAlias</function>
<shortcut>cha</shortcut>
<options />
<doc>&lt;channel&gt; &lt;alias&gt;
Specify a specific alias to use for a channel name.
The alias may not be an existing channel name or
alias.
</doc>
</channel-alias>
<channel-discover>
<summary>Initialize a Channel from its server</summary>
<function>doDiscover</function>
<shortcut>di</shortcut>
<options />
<doc>[&lt;channel.xml&gt;|&lt;channel name&gt;]
Initialize a Channel from its server and create the local channel.xml.
</doc>
</channel-discover>
</commands>

View File

@ -0,0 +1,279 @@
<?php
/**
* PEAR_Command_Common base class
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: Common.php,v 1.32.2.1 2006/06/08 22:27:11 pajoye Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR.php';
/**
* PEAR commands base class
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.4.11
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Command_Common extends PEAR
{
// {{{ properties
/**
* PEAR_Config object used to pass user system and configuration
* on when executing commands
*
* @var PEAR_Config
*/
var $config;
/**
* @var PEAR_Registry
* @access protected
*/
var $_registry;
/**
* User Interface object, for all interaction with the user.
* @var object
*/
var $ui;
var $_deps_rel_trans = array(
'lt' => '<',
'le' => '<=',
'eq' => '=',
'ne' => '!=',
'gt' => '>',
'ge' => '>=',
'has' => '=='
);
var $_deps_type_trans = array(
'pkg' => 'package',
'ext' => 'extension',
'php' => 'PHP',
'prog' => 'external program',
'ldlib' => 'external library for linking',
'rtlib' => 'external runtime library',
'os' => 'operating system',
'websrv' => 'web server',
'sapi' => 'SAPI backend'
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Common constructor.
*
* @access public
*/
function PEAR_Command_Common(&$ui, &$config)
{
parent::PEAR();
$this->config = &$config;
$this->ui = &$ui;
}
// }}}
// {{{ getCommands()
/**
* Return a list of all the commands defined by this class.
* @return array list of commands
* @access public
*/
function getCommands()
{
$ret = array();
foreach (array_keys($this->commands) as $command) {
$ret[$command] = $this->commands[$command]['summary'];
}
return $ret;
}
// }}}
// {{{ getShortcuts()
/**
* Return a list of all the command shortcuts defined by this class.
* @return array shortcut => command
* @access public
*/
function getShortcuts()
{
$ret = array();
foreach (array_keys($this->commands) as $command) {
if (isset($this->commands[$command]['shortcut'])) {
$ret[$this->commands[$command]['shortcut']] = $command;
}
}
return $ret;
}
// }}}
// {{{ getOptions()
function getOptions($command)
{
$shortcuts = $this->getShortcuts();
if (isset($shortcuts[$command])) {
$command = $shortcuts[$command];
}
return @$this->commands[$command]['options'];
}
// }}}
// {{{ getGetoptArgs()
function getGetoptArgs($command, &$short_args, &$long_args)
{
$short_args = "";
$long_args = array();
if (empty($this->commands[$command]) || empty($this->commands[$command]['options'])) {
return;
}
reset($this->commands[$command]['options']);
while (list($option, $info) = each($this->commands[$command]['options'])) {
$larg = $sarg = '';
if (isset($info['arg'])) {
if ($info['arg']{0} == '(') {
$larg = '==';
$sarg = '::';
$arg = substr($info['arg'], 1, -1);
} else {
$larg = '=';
$sarg = ':';
$arg = $info['arg'];
}
}
if (isset($info['shortopt'])) {
$short_args .= $info['shortopt'] . $sarg;
}
$long_args[] = $option . $larg;
}
}
// }}}
// {{{ getHelp()
/**
* Returns the help message for the given command
*
* @param string $command The command
* @return mixed A fail string if the command does not have help or
* a two elements array containing [0]=>help string,
* [1]=> help string for the accepted cmd args
*/
function getHelp($command)
{
$config = &PEAR_Config::singleton();
$help = @$this->commands[$command]['doc'];
if (empty($help)) {
// XXX (cox) Fallback to summary if there is no doc (show both?)
if (!$help = @$this->commands[$command]['summary']) {
return "No help for command \"$command\"";
}
}
if (preg_match_all('/{config\s+([^\}]+)}/e', $help, $matches)) {
foreach($matches[0] as $k => $v) {
$help = preg_replace("/$v/", $config->get($matches[1][$k]), $help);
}
}
return array($help, $this->getHelpArgs($command));
}
// }}}
// {{{ getHelpArgs()
/**
* Returns the help for the accepted arguments of a command
*
* @param string $command
* @return string The help string
*/
function getHelpArgs($command)
{
if (isset($this->commands[$command]['options']) &&
count($this->commands[$command]['options']))
{
$help = "Options:\n";
foreach ($this->commands[$command]['options'] as $k => $v) {
if (isset($v['arg'])) {
if ($v['arg']{0} == '(') {
$arg = substr($v['arg'], 1, -1);
$sapp = " [$arg]";
$lapp = "[=$arg]";
} else {
$sapp = " $v[arg]";
$lapp = "=$v[arg]";
}
} else {
$sapp = $lapp = "";
}
if (isset($v['shortopt'])) {
$s = $v['shortopt'];
@$help .= " -$s$sapp, --$k$lapp\n";
} else {
@$help .= " --$k$lapp\n";
}
$p = " ";
$doc = rtrim(str_replace("\n", "\n$p", $v['doc']));
$help .= " $doc\n";
}
return $help;
}
return null;
}
// }}}
// {{{ run()
function run($command, $options, $params)
{
if (empty($this->commands[$command]['function'])) {
// look for shortcuts
foreach (array_keys($this->commands) as $cmd) {
if (isset($this->commands[$cmd]['shortcut']) && $this->commands[$cmd]['shortcut'] == $command) {
if (empty($this->commands[$cmd]['function'])) {
return $this->raiseError("unknown command `$command'");
} else {
$func = $this->commands[$cmd]['function'];
}
$command = $cmd;
break;
}
}
} else {
$func = $this->commands[$command]['function'];
}
return $this->$func($command, $options, $params);
}
// }}}
}
?>

View File

@ -0,0 +1,418 @@
<?php
/**
* PEAR_Command_Config (config-show, config-get, config-set, config-help, config-create commands)
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: Config.php,v 1.51.2.1 2006/06/04 12:11:39 pajoye Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for managing configuration data.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.4.11
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Command_Config extends PEAR_Command_Common
{
// {{{ properties
var $commands = array(
'config-show' => array(
'summary' => 'Show All Settings',
'function' => 'doConfigShow',
'shortcut' => 'csh',
'options' => array(
'channel' => array(
'shortopt' => 'c',
'doc' => 'show configuration variables for another channel',
'arg' => 'CHAN',
),
),
'doc' => '[layer]
Displays all configuration values. An optional argument
may be used to tell which configuration layer to display. Valid
configuration layers are "user", "system" and "default". To display
configurations for different channels, set the default_channel
configuration variable and run config-show again.
',
),
'config-get' => array(
'summary' => 'Show One Setting',
'function' => 'doConfigGet',
'shortcut' => 'cg',
'options' => array(
'channel' => array(
'shortopt' => 'c',
'doc' => 'show configuration variables for another channel',
'arg' => 'CHAN',
),
),
'doc' => '<parameter> [layer]
Displays the value of one configuration parameter. The
first argument is the name of the parameter, an optional second argument
may be used to tell which configuration layer to look in. Valid configuration
layers are "user", "system" and "default". If no layer is specified, a value
will be picked from the first layer that defines the parameter, in the order
just specified. The configuration value will be retrieved for the channel
specified by the default_channel configuration variable.
',
),
'config-set' => array(
'summary' => 'Change Setting',
'function' => 'doConfigSet',
'shortcut' => 'cs',
'options' => array(
'channel' => array(
'shortopt' => 'c',
'doc' => 'show configuration variables for another channel',
'arg' => 'CHAN',
),
),
'doc' => '<parameter> <value> [layer]
Sets the value of one configuration parameter. The first argument is
the name of the parameter, the second argument is the new value. Some
parameters are subject to validation, and the command will fail with
an error message if the new value does not make sense. An optional
third argument may be used to specify in which layer to set the
configuration parameter. The default layer is "user". The
configuration value will be set for the current channel, which
is controlled by the default_channel configuration variable.
',
),
'config-help' => array(
'summary' => 'Show Information About Setting',
'function' => 'doConfigHelp',
'shortcut' => 'ch',
'options' => array(),
'doc' => '[parameter]
Displays help for a configuration parameter. Without arguments it
displays help for all configuration parameters.
',
),
'config-create' => array(
'summary' => 'Create a Default configuration file',
'function' => 'doConfigCreate',
'shortcut' => 'coc',
'options' => array(
'windows' => array(
'shortopt' => 'w',
'doc' => 'create a config file for a windows install',
),
),
'doc' => '<root path> <filename>
Create a default configuration file with all directory configuration
variables set to subdirectories of <root path>, and save it as <filename>.
This is useful especially for creating a configuration file for a remote
PEAR installation (using the --remoteconfig option of install, upgrade,
and uninstall).
',
),
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Config constructor.
*
* @access public
*/
function PEAR_Command_Config(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
// }}}
// {{{ doConfigShow()
function doConfigShow($command, $options, $params)
{
if (is_array($params)) {
$layer = isset($params[0]) ? $params[0] : NULL;
} else {
$layer = NULL;
}
// $params[0] -> the layer
if ($error = $this->_checkLayer($layer)) {
return $this->raiseError("config-show:$error");
}
$keys = $this->config->getKeys();
sort($keys);
$channel = isset($options['channel']) ? $options['channel'] :
$this->config->get('default_channel');
$reg = &$this->config->getRegistry();
if (!$reg->channelExists($channel)) {
return $this->raiseError('Channel "' . $channel . '" does not exist');
}
$data = array('caption' => 'Configuration (channel ' . $channel . '):');
foreach ($keys as $key) {
$type = $this->config->getType($key);
$value = $this->config->get($key, $layer, $channel);
if ($type == 'password' && $value) {
$value = '********';
}
if ($value === false) {
$value = 'false';
} elseif ($value === true) {
$value = 'true';
}
$data['data'][$this->config->getGroup($key)][] = array($this->config->getPrompt($key) , $key, $value);
}
foreach ($this->config->getLayers() as $layer) {
$data['data']['Config Files'][] = array(ucfirst($layer) . ' Configuration File', 'Filename' , $this->config->getConfFile($layer));
}
$this->ui->outputData($data, $command);
return true;
}
// }}}
// {{{ doConfigGet()
function doConfigGet($command, $options, $params)
{
if (!is_array($params)) {
$args_cnt = 0;
} else {
$args_cnt = count($params);
}
switch ($args_cnt) {
case 1:
$config_key = $params[0];
$layer = NULL;
break;
case 2:
$config_key = $params[0];
$layer = $params[1];
if ($error = $this->_checkLayer($layer)) {
return $this->raiseError("config-get:$error");
}
break;
case 0:
default:
return $this->raiseError("config-get expects 1 or 2 parameters");
}
$channel = isset($options['channel']) ? $options['channel'] : $this->config->get('default_channel');
$reg = &$this->config->getRegistry();
if (!$reg->channelExists($channel)) {
return $this->raiseError('Channel "' . $channel . '" does not exist');
}
$this->ui->outputData($this->config->get($config_key, $layer, $channel), $command);
return true;
}
// }}}
// {{{ doConfigSet()
function doConfigSet($command, $options, $params)
{
// $param[0] -> a parameter to set
// $param[1] -> the value for the parameter
// $param[2] -> the layer
$failmsg = '';
if (sizeof($params) < 2 || sizeof($params) > 3) {
$failmsg .= "config-set expects 2 or 3 parameters";
return PEAR::raiseError($failmsg);
}
if (isset($params[2]) && $error = $this->_checkLayer($params[2])) {
$failmsg .= $error;
return PEAR::raiseError("config-set:$failmsg");
}
$channel = isset($options['channel']) ? $options['channel'] :
$this->config->get('default_channel');
$reg = &$this->config->getRegistry();
if (!$reg->channelExists($channel)) {
return $this->raiseError('Channel "' . $channel . '" does not exist');
}
if ($params[0] == 'default_channel') {
if (!$reg->channelExists($params[1])) {
return $this->raiseError('Channel "' . $params[1] . '" does not exist');
}
}
if (count($params) == 2) {
array_push($params, 'user');
$layer = 'user';
} else {
$layer = $params[2];
}
array_push($params, $channel);
if (!call_user_func_array(array(&$this->config, 'set'), $params))
{
array_pop($params);
$failmsg = "config-set (" . implode(", ", $params) . ") failed, channel $channel";
} else {
$this->config->store($layer);
}
if ($failmsg) {
return $this->raiseError($failmsg);
}
$this->ui->outputData('config-set succeeded', $command);
return true;
}
// }}}
// {{{ doConfigHelp()
function doConfigHelp($command, $options, $params)
{
if (empty($params)) {
$params = $this->config->getKeys();
}
$data['caption'] = "Config help" . ((count($params) == 1) ? " for $params[0]" : '');
$data['headline'] = array('Name', 'Type', 'Description');
$data['border'] = true;
foreach ($params as $name) {
$type = $this->config->getType($name);
$docs = $this->config->getDocs($name);
if ($type == 'set') {
$docs = rtrim($docs) . "\nValid set: " .
implode(' ', $this->config->getSetValues($name));
}
$data['data'][] = array($name, $type, $docs);
}
$this->ui->outputData($data, $command);
}
// }}}
// {{{ doConfigCreate()
function doConfigCreate($command, $options, $params)
{
if (count($params) != 2) {
return PEAR::raiseError('config-create: must have 2 parameters, root path and ' .
'filename to save as');
}
$root = $params[0];
// Clean up the DIRECTORY_SEPARATOR mess
$ds2 = DIRECTORY_SEPARATOR . DIRECTORY_SEPARATOR;
$root = preg_replace(array('!\\\\+!', '!/+!', "!$ds2+!"),
array('/', '/', '/'),
$root);
if ($root{0} != '/') {
if (isset($options['windows'])) {
if (!preg_match('/^[A-Za-z]:/', $root)) {
return PEAR::raiseError('Root directory must be an absolute path beginning ' .
'with "\\" or "C:\\", was: "' . $root . '"');
}
} else {
return PEAR::raiseError('Root directory must be an absolute path beginning ' .
'with "/", was: "' . $root . '"');
}
}
$windows = isset($options['windows']);
if ($windows) {
$root = str_replace('/', '\\', $root);
}
if (!file_exists($params[1])) {
if (!@touch($params[1])) {
return PEAR::raiseError('Could not create "' . $params[1] . '"');
}
}
$params[1] = realpath($params[1]);
$config = &new PEAR_Config($params[1], '#no#system#config#', false, false);
if ($root{strlen($root) - 1} == '/') {
$root = substr($root, 0, strlen($root) - 1);
}
$config->noRegistry();
$config->set('php_dir', $windows ? "$root\\pear\\php" : "$root/pear/php", 'user');
$config->set('data_dir', $windows ? "$root\\pear\\data" : "$root/pear/data");
$config->set('ext_dir', $windows ? "$root\\pear\\ext" : "$root/pear/ext");
$config->set('doc_dir', $windows ? "$root\\pear\\docs" : "$root/pear/docs");
$config->set('test_dir', $windows ? "$root\\pear\\tests" : "$root/pear/tests");
$config->set('cache_dir', $windows ? "$root\\pear\\cache" : "$root/pear/cache");
$config->set('bin_dir', $windows ? "$root\\pear" : "$root/pear");
$config->writeConfigFile();
$this->_showConfig($config);
$this->ui->outputData('Successfully created default configuration file "' . $params[1] . '"',
$command);
}
// }}}
function _showConfig(&$config)
{
$params = array('user');
$keys = $config->getKeys();
sort($keys);
$channel = 'pear.php.net';
$data = array('caption' => 'Configuration (channel ' . $channel . '):');
foreach ($keys as $key) {
$type = $config->getType($key);
$value = $config->get($key, 'user', $channel);
if ($type == 'password' && $value) {
$value = '********';
}
if ($value === false) {
$value = 'false';
} elseif ($value === true) {
$value = 'true';
}
$data['data'][$config->getGroup($key)][] =
array($config->getPrompt($key) , $key, $value);
}
foreach ($config->getLayers() as $layer) {
$data['data']['Config Files'][] =
array(ucfirst($layer) . ' Configuration File', 'Filename' ,
$config->getConfFile($layer));
}
$this->ui->outputData($data, 'config-show');
return true;
}
// {{{ _checkLayer()
/**
* Checks if a layer is defined or not
*
* @param string $layer The layer to search for
* @return mixed False on no error or the error message
*/
function _checkLayer($layer = null)
{
if (!empty($layer) && $layer != 'default') {
$layers = $this->config->getLayers();
if (!in_array($layer, $layers)) {
return " only the layers: \"" . implode('" or "', $layers) . "\" are supported";
}
}
return false;
}
// }}}
}
?>

View File

@ -0,0 +1,92 @@
<commands version="1.0">
<config-show>
<summary>Show All Settings</summary>
<function>doConfigShow</function>
<shortcut>csh</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>show configuration variables for another channel</doc>
<arg>CHAN</arg>
</channel>
</options>
<doc>[layer]
Displays all configuration values. An optional argument
may be used to tell which configuration layer to display. Valid
configuration layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;. To display
configurations for different channels, set the default_channel
configuration variable and run config-show again.
</doc>
</config-show>
<config-get>
<summary>Show One Setting</summary>
<function>doConfigGet</function>
<shortcut>cg</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>show configuration variables for another channel</doc>
<arg>CHAN</arg>
</channel>
</options>
<doc>&lt;parameter&gt; [layer]
Displays the value of one configuration parameter. The
first argument is the name of the parameter, an optional second argument
may be used to tell which configuration layer to look in. Valid configuration
layers are &quot;user&quot;, &quot;system&quot; and &quot;default&quot;. If no layer is specified, a value
will be picked from the first layer that defines the parameter, in the order
just specified. The configuration value will be retrieved for the channel
specified by the default_channel configuration variable.
</doc>
</config-get>
<config-set>
<summary>Change Setting</summary>
<function>doConfigSet</function>
<shortcut>cs</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>show configuration variables for another channel</doc>
<arg>CHAN</arg>
</channel>
</options>
<doc>&lt;parameter&gt; &lt;value&gt; [layer]
Sets the value of one configuration parameter. The first argument is
the name of the parameter, the second argument is the new value. Some
parameters are subject to validation, and the command will fail with
an error message if the new value does not make sense. An optional
third argument may be used to specify in which layer to set the
configuration parameter. The default layer is &quot;user&quot;. The
configuration value will be set for the current channel, which
is controlled by the default_channel configuration variable.
</doc>
</config-set>
<config-help>
<summary>Show Information About Setting</summary>
<function>doConfigHelp</function>
<shortcut>ch</shortcut>
<options />
<doc>[parameter]
Displays help for a configuration parameter. Without arguments it
displays help for all configuration parameters.
</doc>
</config-help>
<config-create>
<summary>Create a Default configuration file</summary>
<function>doConfigCreate</function>
<shortcut>coc</shortcut>
<options>
<windows>
<shortopt>w</shortopt>
<doc>create a config file for a windows install</doc>
</windows>
</options>
<doc>&lt;root path&gt; &lt;filename&gt;
Create a default configuration file with all directory configuration
variables set to subdirectories of &lt;root path&gt;, and save it as &lt;filename&gt;.
This is useful especially for creating a configuration file for a remote
PEAR installation (using the --remoteconfig option of install, upgrade,
and uninstall).
</doc>
</config-create>
</commands>

View File

@ -0,0 +1,773 @@
<?php
/**
* PEAR_Command_Install (install, upgrade, upgrade-all, uninstall, bundle, run-scripts commands)
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: Install.php,v 1.115 2006/03/02 18:14:13 cellog Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 0.1
*/
/**
* base class
*/
require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for installation or deinstallation/upgrading of
* packages.
*
* @category pear
* @package PEAR
* @author Stig Bakken <ssb@php.net>
* @author Greg Beaver <cellog@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.4.11
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 0.1
*/
class PEAR_Command_Install extends PEAR_Command_Common
{
// {{{ properties
var $commands = array(
'install' => array(
'summary' => 'Install Package',
'function' => 'doInstall',
'shortcut' => 'i',
'options' => array(
'force' => array(
'shortopt' => 'f',
'doc' => 'will overwrite newer installed packages',
),
'loose' => array(
'shortopt' => 'l',
'doc' => 'do not check for recommended dependency version',
),
'nodeps' => array(
'shortopt' => 'n',
'doc' => 'ignore dependencies, install anyway',
),
'register-only' => array(
'shortopt' => 'r',
'doc' => 'do not install files, only register the package as installed',
),
'soft' => array(
'shortopt' => 's',
'doc' => 'soft install, fail silently, or upgrade if already installed',
),
'nobuild' => array(
'shortopt' => 'B',
'doc' => 'don\'t build C extensions',
),
'nocompress' => array(
'shortopt' => 'Z',
'doc' => 'request uncompressed files when downloading',
),
'installroot' => array(
'shortopt' => 'R',
'arg' => 'DIR',
'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
),
'packagingroot' => array(
'shortopt' => 'P',
'arg' => 'DIR',
'doc' => 'root directory used when packaging files, like RPM packaging',
),
'ignore-errors' => array(
'doc' => 'force install even if there were errors',
),
'alldeps' => array(
'shortopt' => 'a',
'doc' => 'install all required and optional dependencies',
),
'onlyreqdeps' => array(
'shortopt' => 'o',
'doc' => 'install all required dependencies',
),
'offline' => array(
'shortopt' => 'O',
'doc' => 'do not attempt to download any urls or contact channels',
),
'pretend' => array(
'shortopt' => 'p',
'doc' => 'Only list the packages that would be downloaded',
),
),
'doc' => '[channel/]<package> ...
Installs one or more PEAR packages. You can specify a package to
install in four ways:
"Package-1.0.tgz" : installs from a local file
"http://example.com/Package-1.0.tgz" : installs from
anywhere on the net.
"package.xml" : installs the package described in
package.xml. Useful for testing, or for wrapping a PEAR package in
another package manager such as RPM.
"Package[-version/state][.tar]" : queries your default channel\'s server
({config master_server}) and downloads the newest package with
the preferred quality/state ({config preferred_state}).
To retrieve Package version 1.1, use "Package-1.1," to retrieve
Package state beta, use "Package-beta." To retrieve an uncompressed
file, append .tar (make sure there is no file by the same name first)
To download a package from another channel, prefix with the channel name like
"channel/Package"
More than one package may be specified at once. It is ok to mix these
four ways of specifying packages.
'),
'upgrade' => array(
'summary' => 'Upgrade Package',
'function' => 'doInstall',
'shortcut' => 'up',
'options' => array(
'force' => array(
'shortopt' => 'f',
'doc' => 'overwrite newer installed packages',
),
'loose' => array(
'shortopt' => 'l',
'doc' => 'do not check for recommended dependency version',
),
'nodeps' => array(
'shortopt' => 'n',
'doc' => 'ignore dependencies, upgrade anyway',
),
'register-only' => array(
'shortopt' => 'r',
'doc' => 'do not install files, only register the package as upgraded',
),
'nobuild' => array(
'shortopt' => 'B',
'doc' => 'don\'t build C extensions',
),
'nocompress' => array(
'shortopt' => 'Z',
'doc' => 'request uncompressed files when downloading',
),
'installroot' => array(
'shortopt' => 'R',
'arg' => 'DIR',
'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
),
'packagingroot' => array(
'shortopt' => 'P',
'arg' => 'DIR',
'doc' => 'root directory used when packaging files, like RPM packaging',
),
'ignore-errors' => array(
'doc' => 'force install even if there were errors',
),
'alldeps' => array(
'shortopt' => 'a',
'doc' => 'install all required and optional dependencies',
),
'onlyreqdeps' => array(
'shortopt' => 'o',
'doc' => 'install all required dependencies',
),
'offline' => array(
'shortopt' => 'O',
'doc' => 'do not attempt to download any urls or contact channels',
),
'pretend' => array(
'shortopt' => 'p',
'doc' => 'Only list the packages that would be downloaded',
),
),
'doc' => '<package> ...
Upgrades one or more PEAR packages. See documentation for the
"install" command for ways to specify a package.
When upgrading, your package will be updated if the provided new
package has a higher version number (use the -f option if you need to
upgrade anyway).
More than one package may be specified at once.
'),
'upgrade-all' => array(
'summary' => 'Upgrade All Packages',
'function' => 'doInstall',
'shortcut' => 'ua',
'options' => array(
'nodeps' => array(
'shortopt' => 'n',
'doc' => 'ignore dependencies, upgrade anyway',
),
'register-only' => array(
'shortopt' => 'r',
'doc' => 'do not install files, only register the package as upgraded',
),
'nobuild' => array(
'shortopt' => 'B',
'doc' => 'don\'t build C extensions',
),
'nocompress' => array(
'shortopt' => 'Z',
'doc' => 'request uncompressed files when downloading',
),
'installroot' => array(
'shortopt' => 'R',
'arg' => 'DIR',
'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT), use packagingroot for RPM',
),
'ignore-errors' => array(
'doc' => 'force install even if there were errors',
),
'loose' => array(
'doc' => 'do not check for recommended dependency version',
),
),
'doc' => '
Upgrades all packages that have a newer release available. Upgrades are
done only if there is a release available of the state specified in
"preferred_state" (currently {config preferred_state}), or a state considered
more stable.
'),
'uninstall' => array(
'summary' => 'Un-install Package',
'function' => 'doUninstall',
'shortcut' => 'un',
'options' => array(
'nodeps' => array(
'shortopt' => 'n',
'doc' => 'ignore dependencies, uninstall anyway',
),
'register-only' => array(
'shortopt' => 'r',
'doc' => 'do not remove files, only register the packages as not installed',
),
'installroot' => array(
'shortopt' => 'R',
'arg' => 'DIR',
'doc' => 'root directory used when installing files (ala PHP\'s INSTALL_ROOT)',
),
'ignore-errors' => array(
'doc' => 'force install even if there were errors',
),
'offline' => array(
'shortopt' => 'O',
'doc' => 'do not attempt to uninstall remotely',
),
),
'doc' => '[channel/]<package> ...
Uninstalls one or more PEAR packages. More than one package may be
specified at once. Prefix with channel name to uninstall from a
channel not in your default channel ({config default_channel})
'),
'bundle' => array(
'summary' => 'Unpacks a Pecl Package',
'function' => 'doBundle',
'shortcut' => 'bun',
'options' => array(
'destination' => array(
'shortopt' => 'd',
'arg' => 'DIR',
'doc' => 'Optional destination directory for unpacking (defaults to current path or "ext" if exists)',
),
'force' => array(
'shortopt' => 'f',
'doc' => 'Force the unpacking even if there were errors in the package',
),
),
'doc' => '<package>
Unpacks a Pecl Package into the selected location. It will download the
package if needed.
'),
'run-scripts' => array(
'summary' => 'Run Post-Install Scripts bundled with a package',
'function' => 'doRunScripts',
'shortcut' => 'rs',
'options' => array(
),
'doc' => '<package>
Run post-installation scripts in package <package>, if any exist.
'),
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Install constructor.
*
* @access public
*/
function PEAR_Command_Install(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
// }}}
/**
* For unit testing purposes
*/
function &getDownloader(&$ui, $options, &$config)
{
if (!class_exists('PEAR_Downloader')) {
require_once 'PEAR/Downloader.php';
}
$a = &new PEAR_Downloader($ui, $options, $config);
return $a;
}
/**
* For unit testing purposes
*/
function &getInstaller(&$ui)
{
if (!class_exists('PEAR_Installer')) {
require_once 'PEAR/Installer.php';
}
$a = &new PEAR_Installer($ui);
return $a;
}
// {{{ doInstall()
function doInstall($command, $options, $params)
{
if (empty($this->installer)) {
$this->installer = &$this->getInstaller($this->ui);
}
if ($command == 'upgrade') {
$options['upgrade'] = true;
}
if (isset($options['installroot']) && isset($options['packagingroot'])) {
return $this->raiseError('ERROR: cannot use both --installroot and --packagingroot');
}
if (isset($options['packagingroot']) && $this->config->get('verbose') > 2) {
$this->ui->outputData('using package root: ' . $options['packagingroot']);
}
$reg = &$this->config->getRegistry();
if ($command == 'upgrade-all') {
$options['upgrade'] = true;
$reg = &$this->config->getRegistry();
$savechannel = $this->config->get('default_channel');
$params = array();
foreach ($reg->listChannels() as $channel) {
if ($channel == '__uri') {
continue;
}
$this->config->set('default_channel', $channel);
$chan = &$reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $this->raiseError($chan);
}
if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
$base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
$dorest = true;
unset($remote);
} else {
$dorest = false;
$remote = &$this->config->getRemote($this->config);
}
$state = $this->config->get('preferred_state');
$installed = array_flip($reg->listPackages($channel));
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
if ($dorest) {
$rest = &$this->config->getREST('1.0', array());
$latest = $rest->listLatestUpgrades($base, $state, $installed, $channel, $reg);
} else {
if (empty($state) || $state == 'any') {
$latest = $remote->call("package.listLatestReleases");
} else {
$latest = $remote->call("package.listLatestReleases", $state);
}
}
PEAR::staticPopErrorHandling();
if (PEAR::isError($latest) || !is_array($latest)) {
continue;
}
foreach ($latest as $package => $info) {
$package = strtolower($package);
if (!isset($installed[$package])) {
// skip packages we don't have installed
continue;
}
$inst_version = $reg->packageInfo($package, 'version', $channel);
if (version_compare("$info[version]", "$inst_version", "le")) {
// installed version is up-to-date
continue;
}
$params[] = $reg->parsedPackageNameToString(array('package' => $package,
'channel' => $channel));
$this->ui->outputData(array('data' => "Will upgrade $package"), $command);
}
}
$this->config->set('default_channel', $savechannel);
}
$this->downloader = &$this->getDownloader($this->ui, $options, $this->config);
$errors = array();
$downloaded = array();
$downloaded = &$this->downloader->download($params);
$errors = $this->downloader->getErrorMsgs();
if (count($errors)) {
foreach ($errors as $error) {
$err['data'][] = array($error);
}
$err['headline'] = 'Install Errors';
$this->ui->outputData($err);
if (!count($downloaded)) {
return $this->raiseError("$command failed");
}
}
$data = array(
'headline' => 'Packages that would be Installed'
);
if (isset($options['pretend'])) {
foreach ($downloaded as $package) {
$data['data'][] = array($reg->parsedPackageNameToString($package->getParsedPackage()));
}
$this->ui->outputData($data, 'pretend');
return true;
}
$this->installer->setOptions($options);
$this->installer->sortPackagesForInstall($downloaded);
if (PEAR::isError($err = $this->installer->setDownloadedPackages($downloaded))) {
$this->raiseError($err->getMessage());
return true;
}
$extrainfo = array();
foreach ($downloaded as $param) {
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$info = $this->installer->install($param, $options);
PEAR::staticPopErrorHandling();
if (PEAR::isError($info)) {
$oldinfo = $info;
$pkg = &$param->getPackageFile();
if ($info->getCode() != PEAR_INSTALLER_NOBINARY) {
if (!($info = $pkg->installBinary($this->installer))) {
$this->ui->outputData('ERROR: ' .$oldinfo->getMessage());
continue;
}
// we just installed a different package than requested,
// let's change the param and info so that the rest of this works
$param = $info[0];
$info = $info[1];
}
}
if (is_array($info)) {
if ($param->getPackageType() == 'extsrc' ||
$param->getPackageType() == 'extbin') {
$pkg = &$param->getPackageFile();
if ($instbin = $pkg->getInstalledBinary()) {
$instpkg = &$reg->getPackage($instbin, $pkg->getChannel());
} else {
$instpkg = &$reg->getPackage($pkg->getPackage(), $pkg->getChannel());
}
foreach ($instpkg->getFilelist() as $name => $atts) {
$pinfo = pathinfo($atts['installed_as']);
if (!isset($pinfo['extension']) ||
in_array($pinfo['extension'], array('c', 'h'))) {
continue; // make sure we don't match php_blah.h
}
if ((strpos($pinfo['basename'], 'php_') === 0 &&
$pinfo['extension'] == 'dll') ||
// most unices
$pinfo['extension'] == 'so' ||
// hp-ux
$pinfo['extension'] == 'sl') {
$extrainfo[] = 'You should add "extension=' . $pinfo['basename']
. '" to php.ini';
break;
}
}
}
if ($this->config->get('verbose') > 0) {
$channel = $param->getChannel();
$label = $reg->parsedPackageNameToString(
array(
'channel' => $channel,
'package' => $param->getPackage(),
'version' => $param->getVersion(),
));
$out = array('data' => "$command ok: $label");
if (isset($info['release_warnings'])) {
$out['release_warnings'] = $info['release_warnings'];
}
$this->ui->outputData($out, $command);
if (!isset($options['register-only']) && !isset($options['offline'])) {
if ($this->config->isDefinedLayer('ftp')) {
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$info = $this->installer->ftpInstall($param);
PEAR::staticPopErrorHandling();
if (PEAR::isError($info)) {
$this->ui->outputData($info->getMessage());
$this->ui->outputData("remote install failed: $label");
} else {
$this->ui->outputData("remote install ok: $label");
}
}
}
}
$deps = $param->getDeps();
if ($deps) {
if (isset($deps['group'])) {
$groups = $deps['group'];
if (!isset($groups[0])) {
$groups = array($groups);
}
foreach ($groups as $group) {
if ($group['attribs']['name'] == 'default') {
// default group is always installed, unless the user
// explicitly chooses to install another group
continue;
}
$this->ui->outputData($param->getPackage() . ': Optional feature ' .
$group['attribs']['name'] . ' available (' .
$group['attribs']['hint'] . ')');
}
$extrainfo[] = 'To install use "pear install ' .
$reg->parsedPackageNameToString(
array('package' => $param->getPackage(),
'channel' => $param->getChannel()), true) .
'#featurename"';
}
}
if (isset($options['installroot'])) {
$reg = &$this->config->getRegistry();
}
$pkg = &$reg->getPackage($param->getPackage(), $param->getChannel());
// $pkg may be NULL if install is a 'fake' install via --packagingroot
if (is_object($pkg)) {
$pkg->setConfig($this->config);
if ($list = $pkg->listPostinstallScripts()) {
$pn = $reg->parsedPackageNameToString(array('channel' =>
$param->getChannel(), 'package' => $param->getPackage()), true);
$extrainfo[] = $pn . ' has post-install scripts:';
foreach ($list as $file) {
$extrainfo[] = $file;
}
$extrainfo[] = 'Use "pear run-scripts ' . $pn . '" to run';
$extrainfo[] = 'DO NOT RUN SCRIPTS FROM UNTRUSTED SOURCES';
}
}
} else {
return $this->raiseError("$command failed");
}
}
if (count($extrainfo)) {
foreach ($extrainfo as $info) {
$this->ui->outputData($info);
}
}
return true;
}
// }}}
// {{{ doUninstall()
function doUninstall($command, $options, $params)
{
if (empty($this->installer)) {
$this->installer = &$this->getInstaller($this->ui);
}
if (isset($options['remoteconfig'])) {
$e = $this->config->readFTPConfigFile($options['remoteconfig']);
if (!PEAR::isError($e)) {
$this->installer->setConfig($this->config);
}
}
if (sizeof($params) < 1) {
return $this->raiseError("Please supply the package(s) you want to uninstall");
}
$reg = &$this->config->getRegistry();
$newparams = array();
$badparams = array();
foreach ($params as $pkg) {
$channel = $this->config->get('default_channel');
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$parsed = $reg->parsePackageName($pkg, $channel);
PEAR::staticPopErrorHandling();
if (!$parsed || PEAR::isError($parsed)) {
$badparams[] = $pkg;
continue;
}
$package = $parsed['package'];
$channel = $parsed['channel'];
$info = &$reg->getPackage($package, $channel);
if ($info === null &&
($channel == 'pear.php.net' || $channel == 'pecl.php.net')) {
// make sure this isn't a package that has flipped from pear to pecl but
// used a package.xml 1.0
$testc = ($channel == 'pear.php.net') ? 'pecl.php.net' : 'pear.php.net';
$info = &$reg->getPackage($package, $testc);
if ($info !== null) {
$channel = $testc;
}
}
if ($info === null) {
$badparams[] = $pkg;
} else {
$newparams[] = &$info;
// check for binary packages (this is an alias for those packages if so)
if ($installedbinary = $info->getInstalledBinary()) {
$this->ui->log('adding binary package ' .
$reg->parsedPackageNameToString(array('channel' => $channel,
'package' => $installedbinary), true));
$newparams[] = &$reg->getPackage($installedbinary, $channel);
}
// add the contents of a dependency group to the list of installed packages
if (isset($parsed['group'])) {
$group = $info->getDependencyGroup($parsed['group']);
if ($group) {
$installed = &$reg->getInstalledGroup($group);
if ($installed) {
foreach ($installed as $i => $p) {
$newparams[] = &$installed[$i];
}
}
}
}
}
}
$err = $this->installer->sortPackagesForUninstall($newparams);
if (PEAR::isError($err)) {
$this->ui->outputData($err->getMessage(), $command);
return true;
}
$params = $newparams;
// twist this to use it to check on whether dependent packages are also being uninstalled
// for circular dependencies like subpackages
$this->installer->setUninstallPackages($newparams);
$params = array_merge($params, $badparams);
foreach ($params as $pkg) {
$this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
if ($err = $this->installer->uninstall($pkg, $options)) {
$this->installer->popErrorHandling();
if (PEAR::isError($err)) {
$this->ui->outputData($err->getMessage(), $command);
continue;
}
$savepkg = $pkg;
if ($this->config->get('verbose') > 0) {
if (is_object($pkg)) {
$pkg = $reg->parsedPackageNameToString($pkg);
}
$this->ui->outputData("uninstall ok: $pkg", $command);
}
if (!isset($options['offline']) && is_object($savepkg) &&
defined('PEAR_REMOTEINSTALL_OK')) {
if ($this->config->isDefinedLayer('ftp')) {
$this->installer->pushErrorHandling(PEAR_ERROR_RETURN);
$info = $this->installer->ftpUninstall($savepkg);
$this->installer->popErrorHandling();
if (PEAR::isError($info)) {
$this->ui->outputData($info->getMessage());
$this->ui->outputData("remote uninstall failed: $pkg");
} else {
$this->ui->outputData("remote uninstall ok: $pkg");
}
}
}
} else {
$this->installer->popErrorHandling();
if (is_object($pkg)) {
$pkg = $reg->parsedPackageNameToString($pkg);
}
return $this->raiseError("uninstall failed: $pkg");
}
}
return true;
}
// }}}
// }}}
// {{{ doBundle()
/*
(cox) It just downloads and untars the package, does not do
any check that the PEAR_Installer::_installFile() does.
*/
function doBundle($command, $options, $params)
{
$downloader = &$this->getDownloader($this->ui, array('force' => true, 'nodeps' => true,
'soft' => true), $this->config);
$reg = &$this->config->getRegistry();
if (sizeof($params) < 1) {
return $this->raiseError("Please supply the package you want to bundle");
}
if (isset($options['destination'])) {
if (!is_dir($options['destination'])) {
System::mkdir('-p ' . $options['destination']);
}
$dest = realpath($options['destination']);
} else {
$pwd = getcwd();
if (is_dir($pwd . DIRECTORY_SEPARATOR . 'ext')) {
$dest = $pwd . DIRECTORY_SEPARATOR . 'ext';
} else {
$dest = $pwd;
}
}
$downloader->setDownloadDir($dest);
$result = &$downloader->download(array($params[0]));
if (PEAR::isError($result)) {
return $result;
}
$pkgfile = &$result[0]->getPackageFile();
$pkgname = $pkgfile->getName();
$pkgversion = $pkgfile->getVersion();
// Unpacking -------------------------------------------------
$dest .= DIRECTORY_SEPARATOR . $pkgname;
$orig = $pkgname . '-' . $pkgversion;
$tar = &new Archive_Tar($pkgfile->getArchiveFile());
if (!@$tar->extractModify($dest, $orig)) {
return $this->raiseError('unable to unpack ' . $pkgfile->getArchiveFile());
}
$this->ui->outputData("Package ready at '$dest'");
// }}}
}
// }}}
function doRunScripts($command, $options, $params)
{
if (!isset($params[0])) {
return $this->raiseError('run-scripts expects 1 parameter: a package name');
}
$reg = &$this->config->getRegistry();
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$parsed = $reg->parsePackageName($params[0], $this->config->get('default_channel'));
PEAR::staticPopErrorHandling();
if (PEAR::isError($parsed)) {
return $this->raiseError($parsed);
}
$package = &$reg->getPackage($parsed['package'], $parsed['channel']);
if (is_object($package)) {
$package->setConfig($this->config);
$package->runPostinstallScripts();
} else {
return $this->raiseError('Could not retrieve package "' . $params[0] . '" from registry');
}
$this->ui->outputData('Install scripts complete', $command);
return true;
}
}
?>

View File

@ -0,0 +1,254 @@
<commands version="1.0">
<install>
<summary>Install Package</summary>
<function>doInstall</function>
<shortcut>i</shortcut>
<options>
<force>
<shortopt>f</shortopt>
<doc>will overwrite newer installed packages</doc>
</force>
<loose>
<shortopt>l</shortopt>
<doc>do not check for recommended dependency version</doc>
</loose>
<nodeps>
<shortopt>n</shortopt>
<doc>ignore dependencies, install anyway</doc>
</nodeps>
<register-only>
<shortopt>r</shortopt>
<doc>do not install files, only register the package as installed</doc>
</register-only>
<soft>
<shortopt>s</shortopt>
<doc>soft install, fail silently, or upgrade if already installed</doc>
</soft>
<nobuild>
<shortopt>B</shortopt>
<doc>don&apos;t build C extensions</doc>
</nobuild>
<nocompress>
<shortopt>Z</shortopt>
<doc>request uncompressed files when downloading</doc>
</nocompress>
<installroot>
<shortopt>R</shortopt>
<arg>DIR</arg>
<doc>root directory used when installing files (ala PHP&apos;s INSTALL_ROOT)</doc>
</installroot>
<ignore-errors>
<doc>force install even if there were errors</doc>
</ignore-errors>
<alldeps>
<shortopt>a</shortopt>
<doc>install all required and optional dependencies</doc>
</alldeps>
<onlyreqdeps>
<shortopt>o</shortopt>
<doc>install all required dependencies</doc>
</onlyreqdeps>
<offline>
<shortopt>O</shortopt>
<doc>do not attempt to download any urls or contact channels</doc>
</offline>
<pretend>
<shortopt>p</shortopt>
<doc>Only list the packages that would be downloaded</doc>
</pretend>
</options>
<doc>[channel/]&lt;package&gt; ...
Installs one or more PEAR packages. You can specify a package to
install in four ways:
&quot;Package-1.0.tgz&quot; : installs from a local file
&quot;http://example.com/Package-1.0.tgz&quot; : installs from
anywhere on the net.
&quot;package.xml&quot; : installs the package described in
package.xml. Useful for testing, or for wrapping a PEAR package in
another package manager such as RPM.
&quot;Package[-version/state][.tar]&quot; : queries your default channel&apos;s server
({config master_server}) and downloads the newest package with
the preferred quality/state ({config preferred_state}).
To retrieve Package version 1.1, use &quot;Package-1.1,&quot; to retrieve
Package state beta, use &quot;Package-beta.&quot; To retrieve an uncompressed
file, append .tar (make sure there is no file by the same name first)
To download a package from another channel, prefix with the channel name like
&quot;channel/Package&quot;
More than one package may be specified at once. It is ok to mix these
four ways of specifying packages.
</doc>
</install>
<upgrade>
<summary>Upgrade Package</summary>
<function>doInstall</function>
<shortcut>up</shortcut>
<options>
<force>
<shortopt>f</shortopt>
<doc>overwrite newer installed packages</doc>
</force>
<loose>
<shortopt>l</shortopt>
<doc>do not check for recommended dependency version</doc>
</loose>
<nodeps>
<shortopt>n</shortopt>
<doc>ignore dependencies, upgrade anyway</doc>
</nodeps>
<register-only>
<shortopt>r</shortopt>
<doc>do not install files, only register the package as upgraded</doc>
</register-only>
<nobuild>
<shortopt>B</shortopt>
<doc>don&apos;t build C extensions</doc>
</nobuild>
<nocompress>
<shortopt>Z</shortopt>
<doc>request uncompressed files when downloading</doc>
</nocompress>
<installroot>
<shortopt>R</shortopt>
<arg>DIR</arg>
<doc>root directory used when installing files (ala PHP&apos;s INSTALL_ROOT)</doc>
</installroot>
<ignore-errors>
<doc>force install even if there were errors</doc>
</ignore-errors>
<alldeps>
<shortopt>a</shortopt>
<doc>install all required and optional dependencies</doc>
</alldeps>
<onlyreqdeps>
<shortopt>o</shortopt>
<doc>install all required dependencies</doc>
</onlyreqdeps>
<offline>
<shortopt>O</shortopt>
<doc>do not attempt to download any urls or contact channels</doc>
</offline>
<pretend>
<shortopt>p</shortopt>
<doc>Only list the packages that would be downloaded</doc>
</pretend>
</options>
<doc>&lt;package&gt; ...
Upgrades one or more PEAR packages. See documentation for the
&quot;install&quot; command for ways to specify a package.
When upgrading, your package will be updated if the provided new
package has a higher version number (use the -f option if you need to
upgrade anyway).
More than one package may be specified at once.
</doc>
</upgrade>
<upgrade-all>
<summary>Upgrade All Packages</summary>
<function>doInstall</function>
<shortcut>ua</shortcut>
<options>
<nodeps>
<shortopt>n</shortopt>
<doc>ignore dependencies, upgrade anyway</doc>
</nodeps>
<register-only>
<shortopt>r</shortopt>
<doc>do not install files, only register the package as upgraded</doc>
</register-only>
<nobuild>
<shortopt>B</shortopt>
<doc>don&apos;t build C extensions</doc>
</nobuild>
<nocompress>
<shortopt>Z</shortopt>
<doc>request uncompressed files when downloading</doc>
</nocompress>
<installroot>
<shortopt>R</shortopt>
<arg>DIR</arg>
<doc>root directory used when installing files (ala PHP&apos;s INSTALL_ROOT)</doc>
</installroot>
<ignore-errors>
<doc>force install even if there were errors</doc>
</ignore-errors>
<loose>
<doc>do not check for recommended dependency version</doc>
</loose>
</options>
<doc>
Upgrades all packages that have a newer release available. Upgrades are
done only if there is a release available of the state specified in
&quot;preferred_state&quot; (currently {config preferred_state}), or a state considered
more stable.
</doc>
</upgrade-all>
<uninstall>
<summary>Un-install Package</summary>
<function>doUninstall</function>
<shortcut>un</shortcut>
<options>
<nodeps>
<shortopt>n</shortopt>
<doc>ignore dependencies, uninstall anyway</doc>
</nodeps>
<register-only>
<shortopt>r</shortopt>
<doc>do not remove files, only register the packages as not installed</doc>
</register-only>
<installroot>
<shortopt>R</shortopt>
<arg>DIR</arg>
<doc>root directory used when installing files (ala PHP&apos;s INSTALL_ROOT)</doc>
</installroot>
<ignore-errors>
<doc>force install even if there were errors</doc>
</ignore-errors>
<offline>
<shortopt>O</shortopt>
<doc>do not attempt to uninstall remotely</doc>
</offline>
</options>
<doc>[channel/]&lt;package&gt; ...
Uninstalls one or more PEAR packages. More than one package may be
specified at once. Prefix with channel name to uninstall from a
channel not in your default channel ({config default_channel})
</doc>
</uninstall>
<bundle>
<summary>Unpacks a Pecl Package</summary>
<function>doBundle</function>
<shortcut>bun</shortcut>
<options>
<destination>
<shortopt>d</shortopt>
<arg>DIR</arg>
<doc>Optional destination directory for unpacking (defaults to current path or &quot;ext&quot; if exists)</doc>
</destination>
<force>
<shortopt>f</shortopt>
<doc>Force the unpacking even if there were errors in the package</doc>
</force>
</options>
<doc>&lt;package&gt;
Unpacks a Pecl Package into the selected location. It will download the
package if needed.
</doc>
</bundle>
<run-scripts>
<summary>Run Post-Install Scripts bundled with a package</summary>
<function>doRunScripts</function>
<shortcut>rs</shortcut>
<options />
<doc>&lt;package&gt;
Run post-installation scripts in package &lt;package&gt;, if any exist.
</doc>
</run-scripts>
</commands>

View File

@ -0,0 +1,153 @@
<?php
/**
* PEAR_Command_Mirror (download-all command)
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Alexander Merz <alexmerz@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: Mirror.php,v 1.18 2006/03/02 18:14:13 cellog Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.2.0
*/
/**
* base class
*/
require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for providing file mirrors
*
* @category pear
* @package PEAR
* @author Alexander Merz <alexmerz@php.net>
* @copyright 1997-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.4.11
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.2.0
*/
class PEAR_Command_Mirror extends PEAR_Command_Common
{
// {{{ properties
var $commands = array(
'download-all' => array(
'summary' => 'Downloads each available package from the default channel',
'function' => 'doDownloadAll',
'shortcut' => 'da',
'options' => array(
'channel' =>
array(
'shortopt' => 'c',
'doc' => 'specify a channel other than the default channel',
'arg' => 'CHAN',
),
),
'doc' => '
Requests a list of available packages from the default channel ({config default_channel})
and downloads them to current working directory. Note: only
packages within preferred_state ({config preferred_state}) will be downloaded'
),
);
// }}}
// {{{ constructor
/**
* PEAR_Command_Mirror constructor.
*
* @access public
* @param object PEAR_Frontend a reference to an frontend
* @param object PEAR_Config a reference to the configuration data
*/
function PEAR_Command_Mirror(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
// }}}
/**
* For unit-testing
*/
function &factory($a)
{
$a = &PEAR_Command::factory($a, $this->config);
return $a;
}
// {{{ doDownloadAll()
/**
* retrieves a list of avaible Packages from master server
* and downloads them
*
* @access public
* @param string $command the command
* @param array $options the command options before the command
* @param array $params the stuff after the command name
* @return bool true if succesful
* @throw PEAR_Error
*/
function doDownloadAll($command, $options, $params)
{
$savechannel = $this->config->get('default_channel');
$reg = &$this->config->getRegistry();
$channel = isset($options['channel']) ? $options['channel'] :
$this->config->get('default_channel');
if (!$reg->channelExists($channel)) {
$this->config->set('default_channel', $savechannel);
return $this->raiseError('Channel "' . $channel . '" does not exist');
}
$this->config->set('default_channel', $channel);
$this->ui->outputData('Using Channel ' . $this->config->get('default_channel'));
$chan = $reg->getChannel($channel);
if (PEAR::isError($chan)) {
return $this->raiseError($chan);
}
if ($chan->supportsREST($this->config->get('preferred_mirror')) &&
$base = $chan->getBaseURL('REST1.0', $this->config->get('preferred_mirror'))) {
$rest = &$this->config->getREST('1.0', array());
$remoteInfo = array_flip($rest->listPackages($base));
} else {
$remote = &$this->config->getRemote();
$stable = ($this->config->get('preferred_state') == 'stable');
$remoteInfo = $remote->call("package.listAll", true, $stable, false);
}
if (PEAR::isError($remoteInfo)) {
return $remoteInfo;
}
$cmd = &$this->factory("download");
if (PEAR::isError($cmd)) {
return $cmd;
}
$this->ui->outputData('Using Preferred State of ' .
$this->config->get('preferred_state'));
$this->ui->outputData('Gathering release information, please wait...');
/**
* Error handling not necessary, because already done by
* the download command
*/
PEAR::staticPushErrorHandling(PEAR_ERROR_RETURN);
$err = $cmd->run('download', array('downloadonly' => true), array_keys($remoteInfo));
PEAR::staticPopErrorHandling();
$this->config->set('default_channel', $savechannel);
if (PEAR::isError($err)) {
$this->ui->outputData($err->getMessage());
}
return true;
}
// }}}
}

View File

@ -0,0 +1,18 @@
<commands version="1.0">
<download-all>
<summary>Downloads each available package from the default channel</summary>
<function>doDownloadAll</function>
<shortcut>da</shortcut>
<options>
<channel>
<shortopt>c</shortopt>
<doc>specify a channel other than the default channel</doc>
<arg>CHAN</arg>
</channel>
</options>
<doc>
Requests a list of available packages from the default channel ({config default_channel})
and downloads them to current working directory. Note: only
packages within preferred_state ({config preferred_state}) will be downloaded</doc>
</download-all>
</commands>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,194 @@
<commands version="1.0">
<package>
<summary>Build Package</summary>
<function>doPackage</function>
<shortcut>p</shortcut>
<options>
<nocompress>
<shortopt>Z</shortopt>
<doc>Do not gzip the package file</doc>
</nocompress>
<showname>
<shortopt>n</shortopt>
<doc>Print the name of the packaged file.</doc>
</showname>
</options>
<doc>[descfile] [descfile2]
Creates a PEAR package from its description file (usually called
package.xml). If a second packagefile is passed in, then
the packager will check to make sure that one is a package.xml
version 1.0, and the other is a package.xml version 2.0. The
package.xml version 1.0 will be saved as &quot;package.xml&quot; in the archive,
and the other as &quot;package2.xml&quot; in the archive&quot;
</doc>
</package>
<package-validate>
<summary>Validate Package Consistency</summary>
<function>doPackageValidate</function>
<shortcut>pv</shortcut>
<options />
<doc>
</doc>
</package-validate>
<cvsdiff>
<summary>Run a &quot;cvs diff&quot; for all files in a package</summary>
<function>doCvsDiff</function>
<shortcut>cd</shortcut>
<options>
<quiet>
<shortopt>q</shortopt>
<doc>Be quiet</doc>
</quiet>
<reallyquiet>
<shortopt>Q</shortopt>
<doc>Be really quiet</doc>
</reallyquiet>
<date>
<shortopt>D</shortopt>
<doc>Diff against revision of DATE</doc>
<arg>DATE</arg>
</date>
<release>
<shortopt>R</shortopt>
<doc>Diff against tag for package release REL</doc>
<arg>REL</arg>
</release>
<revision>
<shortopt>r</shortopt>
<doc>Diff against revision REV</doc>
<arg>REV</arg>
</revision>
<context>
<shortopt>c</shortopt>
<doc>Generate context diff</doc>
</context>
<unified>
<shortopt>u</shortopt>
<doc>Generate unified diff</doc>
</unified>
<ignore-case>
<shortopt>i</shortopt>
<doc>Ignore case, consider upper- and lower-case letters equivalent</doc>
</ignore-case>
<ignore-whitespace>
<shortopt>b</shortopt>
<doc>Ignore changes in amount of white space</doc>
</ignore-whitespace>
<ignore-blank-lines>
<shortopt>B</shortopt>
<doc>Ignore changes that insert or delete blank lines</doc>
</ignore-blank-lines>
<brief>
<doc>Report only whether the files differ, no details</doc>
</brief>
<dry-run>
<shortopt>n</shortopt>
<doc>Don&apos;t do anything, just pretend</doc>
</dry-run>
</options>
<doc>&lt;package.xml&gt;
Compares all the files in a package. Without any options, this
command will compare the current code with the last checked-in code.
Using the -r or -R option you may compare the current code with that
of a specific release.
</doc>
</cvsdiff>
<cvstag>
<summary>Set CVS Release Tag</summary>
<function>doCvsTag</function>
<shortcut>ct</shortcut>
<options>
<quiet>
<shortopt>q</shortopt>
<doc>Be quiet</doc>
</quiet>
<reallyquiet>
<shortopt>Q</shortopt>
<doc>Be really quiet</doc>
</reallyquiet>
<slide>
<shortopt>F</shortopt>
<doc>Move (slide) tag if it exists</doc>
</slide>
<delete>
<shortopt>d</shortopt>
<doc>Remove tag</doc>
</delete>
<dry-run>
<shortopt>n</shortopt>
<doc>Don&apos;t do anything, just pretend</doc>
</dry-run>
</options>
<doc>&lt;package.xml&gt;
Sets a CVS tag on all files in a package. Use this command after you have
packaged a distribution tarball with the &quot;package&quot; command to tag what
revisions of what files were in that release. If need to fix something
after running cvstag once, but before the tarball is released to the public,
use the &quot;slide&quot; option to move the release tag.
</doc>
</cvstag>
<package-dependencies>
<summary>Show package dependencies</summary>
<function>doPackageDependencies</function>
<shortcut>pd</shortcut>
<options />
<doc>
List all dependencies the package has.</doc>
</package-dependencies>
<sign>
<summary>Sign a package distribution file</summary>
<function>doSign</function>
<shortcut>si</shortcut>
<options />
<doc>&lt;package-file&gt;
Signs a package distribution (.tar or .tgz) file with GnuPG.</doc>
</sign>
<makerpm>
<summary>Builds an RPM spec file from a PEAR package</summary>
<function>doMakeRPM</function>
<shortcut>rpm</shortcut>
<options>
<spec-template>
<shortopt>t</shortopt>
<arg>FILE</arg>
<doc>Use FILE as RPM spec file template</doc>
</spec-template>
<rpm-pkgname>
<shortopt>p</shortopt>
<arg>FORMAT</arg>
<doc>Use FORMAT as format string for RPM package name, %s is replaced
by the PEAR package name, defaults to &quot;PEAR::%s&quot;.</doc>
</rpm-pkgname>
</options>
<doc>&lt;package-file&gt;
Creates an RPM .spec file for wrapping a PEAR package inside an RPM
package. Intended to be used from the SPECS directory, with the PEAR
package tarball in the SOURCES directory:
$ pear makerpm ../SOURCES/Net_Socket-1.0.tgz
Wrote RPM spec file PEAR::Net_Geo-1.0.spec
$ rpm -bb PEAR::Net_Socket-1.0.spec
...
Wrote: /usr/src/redhat/RPMS/i386/PEAR::Net_Socket-1.0-1.i386.rpm
</doc>
</makerpm>
<convert>
<summary>Convert a package.xml 1.0 to package.xml 2.0 format</summary>
<function>doConvert</function>
<shortcut>c2</shortcut>
<options>
<flat>
<shortopt>f</shortopt>
<doc>do not beautify the filelist.</doc>
</flat>
</options>
<doc>[descfile] [descfile2]
Converts a package.xml in 1.0 format into a package.xml
in 2.0 format. The new file will be named package2.xml by default,
and package.xml will be used as the old file by default.
This is not the most intelligent conversion, and should only be
used for automated conversion or learning the format.
</doc>
</convert>
</commands>

View File

@ -0,0 +1,376 @@
<?php
/**
* PEAR_Command_Pickle (pickle command)
*
* PHP versions 4 and 5
*
* LICENSE: This source file is subject to version 3.0 of the PHP license
* that is available through the world-wide-web at the following URI:
* http://www.php.net/license/3_0.txt. If you did not receive a copy of
* the PHP License and are unable to obtain it through the web, please
* send a note to license@php.net so we can mail you a copy immediately.
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 2005-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version CVS: $Id: Pickle.php,v 1.5.2.1 2006/05/10 03:25:15 cellog Exp $
* @link http://pear.php.net/package/PEAR
* @since File available since Release 1.4.1
*/
/**
* base class
*/
require_once 'PEAR/Command/Common.php';
/**
* PEAR commands for login/logout
*
* @category pear
* @package PEAR
* @author Greg Beaver <cellog@php.net>
* @copyright 2005-2006 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: 1.4.11
* @link http://pear.php.net/package/PEAR
* @since Class available since Release 1.4.1
*/
class PEAR_Command_Pickle extends PEAR_Command_Common
{
var $commands = array(
'pickle' => array(
'summary' => 'Build PECL Package',
'function' => 'doPackage',
'shortcut' => 'pi',
'options' => array(
'nocompress' => array(
'shortopt' => 'Z',
'doc' => 'Do not gzip the package file'
),
'showname' => array(
'shortopt' => 'n',
'doc' => 'Print the name of the packaged file.',
),
),
'doc' => '[descfile]
Creates a PECL package from its package2.xml file.
An automatic conversion will be made to a package.xml 1.0 and written out to
disk in the current directory as "package.xml". Note that
only simple package.xml 2.0 will be converted. package.xml 2.0 with:
- dependency types other than required/optional PECL package/ext/php/pearinstaller
- more than one extsrcrelease
- extbinrelease, phprelease, or bundle release type
- dependency groups
- ignore tags in release filelist
- tasks other than replace
- custom roles
will cause pickle to fail, and output an error message. If your package2.xml
uses any of these features, you are best off using PEAR_PackageFileManager to
generate both package.xml.
'
),
);
/**
* PEAR_Command_Package constructor.
*
* @access public
*/
function PEAR_Command_Pickle(&$ui, &$config)
{
parent::PEAR_Command_Common($ui, $config);
}
/**
* For unit-testing ease
*
* @return PEAR_Packager
*/
function &getPackager()
{
if (!class_exists('PEAR_Packager')) {
require_once 'PEAR/Packager.php';
}
$a = &new PEAR_Packager;
return $a;
}
/**
* For unit-testing ease
*
* @param PEAR_Config $config
* @param bool $debug
* @param string|null $tmpdir
* @return PEAR_PackageFile
*/
function &getPackageFile($config, $debug = false, $tmpdir = null)
{
if (!class_exists('PEAR_Common')) {
require_once 'PEAR/Common.php';
}
if (!class_exists('PEAR/PackageFile.php')) {
require_once 'PEAR/PackageFile.php';
}
$a = &new PEAR_PackageFile($config, $debug, $tmpdir);
$common = new PEAR_Common;
$common->ui = $this->ui;
$a->setLogger($common);
return $a;
}
function doPackage($command, $options, $params)
{
$this->output = '';
$pkginfofile = isset($params[0]) ? $params[0] : 'package2.xml';
$packager = &$this->getPackager();
if (PEAR::isError($err = $this->_convertPackage($pkginfofile))) {
return $err;
}
$compress = empty($options['nocompress']) ? true : false;
$result = $packager->package($pkginfofile, $compress, 'package.xml');
if (PEAR::isError($result)) {
return $this->raiseError($result);
}
// Don't want output, only the package file name just created
if (isset($options['showname'])) {
$this->ui->outputData($result, $command);
}
return true;
}
function _convertPackage($packagexml)
{
$pkg = &$this->getPackageFile($this->config);
$pf2 = &$pkg->fromPackageFile($packagexml, PEAR_VALIDATE_NORMAL);
if (!is_a($pf2, 'PEAR_PackageFile_v2')) {
return $this->raiseError('Cannot process "' .
$packagexml . '", is not a package.xml 2.0');
}
require_once 'PEAR/PackageFile/v1.php';
$pf = new PEAR_PackageFile_v1;
$pf->setConfig($this->config);
if ($pf2->getPackageType() != 'extsrc') {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", is not an extension source package. Using a PEAR_PackageFileManager-based ' .
'script is an option');
}
if (is_array($pf2->getUsesRole())) {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", contains custom roles. Using a PEAR_PackageFileManager-based script or ' .
'the convert command is an option');
}
if (is_array($pf2->getUsesTask())) {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", contains custom tasks. Using a PEAR_PackageFileManager-based script or ' .
'the convert command is an option');
}
$deps = $pf2->getDependencies();
if (isset($deps['group'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", contains dependency groups. Using a PEAR_PackageFileManager-based script ' .
'or the convert command is an option');
}
if (isset($deps['required']['subpackage']) ||
isset($deps['optional']['subpackage'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", contains subpackage dependencies. Using a PEAR_PackageFileManager-based '.
'script is an option');
}
if (isset($deps['required']['os'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", contains os dependencies. Using a PEAR_PackageFileManager-based '.
'script is an option');
}
if (isset($deps['required']['arch'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", contains arch dependencies. Using a PEAR_PackageFileManager-based '.
'script is an option');
}
$pf->setPackage($pf2->getPackage());
$pf->setSummary($pf2->getSummary());
$pf->setDescription($pf2->getDescription());
foreach ($pf2->getMaintainers() as $maintainer) {
$pf->addMaintainer($maintainer['role'], $maintainer['handle'],
$maintainer['name'], $maintainer['email']);
}
$pf->setVersion($pf2->getVersion());
$pf->setDate($pf2->getDate());
$pf->setLicense($pf2->getLicense());
$pf->setState($pf2->getState());
$pf->setNotes($pf2->getNotes());
$pf->addPhpDep($deps['required']['php']['min'], 'ge');
if (isset($deps['required']['php']['max'])) {
$pf->addPhpDep($deps['required']['php']['max'], 'le');
}
if (isset($deps['required']['package'])) {
if (!isset($deps['required']['package'][0])) {
$deps['required']['package'] = array($deps['required']['package']);
}
foreach ($deps['required']['package'] as $dep) {
if (!isset($dep['channel'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
' contains uri-based dependency on a package. Using a ' .
'PEAR_PackageFileManager-based script is an option');
}
if ($dep['channel'] != 'pear.php.net' && $dep['channel'] != 'pecl.php.net') {
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
' contains dependency on a non-standard channel package. Using a ' .
'PEAR_PackageFileManager-based script is an option');
}
if (isset($dep['conflicts'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
' contains conflicts dependency. Using a ' .
'PEAR_PackageFileManager-based script is an option');
}
if (isset($dep['exclude'])) {
$this->ui->outputData('WARNING: exclude tags are ignored in conversion');
}
if (isset($dep['min'])) {
$pf->addPackageDep($dep['name'], $dep['min'], 'ge');
}
if (isset($dep['max'])) {
$pf->addPackageDep($dep['name'], $dep['max'], 'le');
}
}
}
if (isset($deps['required']['extension'])) {
if (!isset($deps['required']['extension'][0])) {
$deps['required']['extension'] = array($deps['required']['extension']);
}
foreach ($deps['required']['extension'] as $dep) {
if (isset($dep['conflicts'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
' contains conflicts dependency. Using a ' .
'PEAR_PackageFileManager-based script is an option');
}
if (isset($dep['exclude'])) {
$this->ui->outputData('WARNING: exclude tags are ignored in conversion');
}
if (isset($dep['min'])) {
$pf->addExtensionDep($dep['name'], $dep['min'], 'ge');
}
if (isset($dep['max'])) {
$pf->addExtensionDep($dep['name'], $dep['max'], 'le');
}
}
}
if (isset($deps['optional']['package'])) {
if (!isset($deps['optional']['package'][0])) {
$deps['optional']['package'] = array($deps['optional']['package']);
}
foreach ($deps['optional']['package'] as $dep) {
if (!isset($dep['channel'])) {
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
' contains uri-based dependency on a package. Using a ' .
'PEAR_PackageFileManager-based script is an option');
}
if ($dep['channel'] != 'pear.php.net' && $dep['channel'] != 'pecl.php.net') {
return $this->raiseError('Cannot safely convert "' . $packagexml . '"' .
' contains dependency on a non-standard channel package. Using a ' .
'PEAR_PackageFileManager-based script is an option');
}
if (isset($dep['exclude'])) {
$this->ui->outputData('WARNING: exclude tags are ignored in conversion');
}
if (isset($dep['min'])) {
$pf->addPackageDep($dep['name'], $dep['min'], 'ge', 'yes');
}
if (isset($dep['max'])) {
$pf->addPackageDep($dep['name'], $dep['max'], 'le', 'yes');
}
}
}
if (isset($deps['optional']['extension'])) {
if (!isset($deps['optional']['extension'][0])) {
$deps['optional']['extension'] = array($deps['optional']['extension']);
}
foreach ($deps['optional']['extension'] as $dep) {
if (isset($dep['exclude'])) {
$this->ui->outputData('WARNING: exclude tags are ignored in conversion');
}
if (isset($dep['min'])) {
$pf->addExtensionDep($dep['name'], $dep['min'], 'ge', 'yes');
}
if (isset($dep['max'])) {
$pf->addExtensionDep($dep['name'], $dep['max'], 'le', 'yes');
}
}
}
$contents = $pf2->getContents();
$release = $pf2->getReleases();
if (isset($releases[0])) {
return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
. 'multiple extsrcrelease tags. Using a PEAR_PackageFileManager-based script ' .
'or the convert command is an option');
}
if ($configoptions = $pf2->getConfigureOptions()) {
foreach ($configoptions as $option) {
$pf->addConfigureOption($option['name'], $option['prompt'],
isset($option['default']) ? $option['default'] : false);
}
}
if (isset($release['filelist']['ignore'])) {
return $this->raiseError('Cannot safely process "' . $packagexml . '" contains '
. 'ignore tags. Using a PEAR_PackageFileManager-based script or the convert' .
' command is an option');
}
if (isset($release['filelist']['install']) &&
!isset($release['filelist']['install'][0])) {
$release['filelist']['install'] = array($release['filelist']['install']);
}
if (isset($contents['dir']['attribs']['baseinstalldir'])) {
$baseinstalldir = $contents['dir']['attribs']['baseinstalldir'];
} else {
$baseinstalldir = false;
}
if (!isset($contents['dir']['file'][0])) {
$contents['dir']['file'] = array($contents['dir']['file']);
}
foreach ($contents['dir']['file'] as $file) {
if ($baseinstalldir && !isset($file['attribs']['baseinstalldir'])) {
$file['attribs']['baseinstalldir'] = $baseinstalldir;
}
$processFile = $file;
unset($processFile['attribs']);
if (count($processFile)) {
foreach ($processFile as $name => $task) {
if ($name != $pf2->getTasksNs() . ':replace') {
return $this->raiseError('Cannot safely process "' . $packagexml .
'" contains tasks other than replace. Using a ' .
'PEAR_PackageFileManager-based script is an option.');
}
$file['attribs']['replace'][] = $task;
}
}
if (!in_array($file['attribs']['role'], PEAR_Common::getFileRoles())) {
return $this->raiseError('Cannot safely convert "' . $packagexml .
'", contains custom roles. Using a PEAR_PackageFileManager-based script ' .
'or the convert command is an option');
}
if (isset($release['filelist']['install'])) {
foreach ($release['filelist']['install'] as $installas) {
if ($installas['attribs']['name'] == $file['attribs']['name']) {
$file['attribs']['install-as'] = $installas['attribs']['as'];
}
}
}
$pf->addFile('/', $file['attribs']['name'], $file['attribs']);
}
if ($pf2->getChangeLog()) {
$this->ui->outputData('WARNING: changelog is not translated to package.xml ' .
'1.0, use PEAR_PackageFileManager-based script if you need changelog-' .
'translation for package.xml 1.0');
}
$gen = &$pf->getDefaultGenerator();
$gen->toPackageFile('.');
}
}
?>

Some files were not shown because too many files have changed in this diff Show More