/* 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
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) 19yy <name of author>
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
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) 19yy name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Library General
Public License instead of this License. */
#include "httpd.h"
#include "http_config.h"
#include "http_request.h"
#include "http_protocol.h"
#include "http_core.h"
#include "http_log.h"
#include <time.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include "adml.h"
#if _TPE_CM > 0
#include "lib/credit-mutuel/include/cm-mac.h" /* TPE du credit mutuel */
#endif
/* Le debut et fin de tag ne peuvent faire que 2 caracteres precisement */
#define DEBUT_TAG "<*"
#define FIN_TAG "*>"
#define FALSE 0
#define TRUE 1
#define FORMAT_DATE_DEFAUT "%A, %d-%b-%Y %H:%M:%S %Z"
#define CONFIG_MODE_SERVER 1
#define CONFIG_MODE_DIRECTORY 2
#define CONFIG_MODE_COMBO 3 /* Shouldn't ever happen. */
/*--------------------------------------------------------------------------*/
/* Declarations de la structure de donnees. */
/*--------------------------------------------------------------------------*/
#define N_FORM 6 /* Nombre de structure Form */
#define N_VAR 6 /* Nombre de structure Var */
#define N_MYSQL 6 /* Nombre de structure Form */
#define N_WHILE 21 /* Nombre de boucle imbrique maximum */
#define N_DATE 6 /* Nombre de structure date */
#define N_UPLOAD 11 /* Nombre maximum de fichier Upload */
#define N_SOCKET 6 /* Nombre maximum de structure socket (la derniere socket n'est utiliser qu'en interne pour les includes par exemple) */
#if _XML_EXPAT > 0
#define N_XML 6 /* Nombre de structure XML */
#endif
#define TAILLE_BUFFER 1024 /* Taille du buffer a alloue dans conf->buffer a la creation du processus */
static const long unsigned int crc32table[] = {
0x00000000,0x04C11DB7,0x09823B6E,0x0D4326D9,0x130476DC,0x17C56B6B,0x1A864DB2,0x1E475005,
0x2608EDB8,0x22C9F00F,0x2F8AD6D6,0x2B4BCB61,0x350C9B64,0x31CD86D3,0x3C8EA00A,0x384FBDBD,
0x4C11DB70,0x48D0C6C7,0x4593E01E,0x4152FDA9,0x5F15ADAC,0x5BD4B01B,0x569796C2,0x52568B75,
0x6A1936C8,0x6ED82B7F,0x639B0DA6,0x675A1011,0x791D4014,0x7DDC5DA3,0x709F7B7A,0x745E66CD,
0x9823B6E0,0x9CE2AB57,0x91A18D8E,0x95609039,0x8B27C03C,0x8FE6DD8B,0x82A5FB52,0x8664E6E5,
0xBE2B5B58,0xBAEA46EF,0xB7A96036,0xB3687D81,0xAD2F2D84,0xA9EE3033,0xA4AD16EA,0xA06C0B5D,
0xD4326D90,0xD0F37027,0xDDB056FE,0xD9714B49,0xC7361B4C,0xC3F706FB,0xCEB42022,0xCA753D95,
0xF23A8028,0xF6FB9D9F,0xFBB8BB46,0xFF79A6F1,0xE13EF6F4,0xE5FFEB43,0xE8BCCD9A,0xEC7DD02D,
0x34867077,0x30476DC0,0x3D044B19,0x39C556AE,0x278206AB,0x23431B1C,0x2E003DC5,0x2AC12072,
0x128E9DCF,0x164F8078,0x1B0CA6A1,0x1FCDBB16,0x018AEB13,0x054BF6A4,0x0808D07D,0x0CC9CDCA,
0x7897AB07,0x7C56B6B0,0x71159069,0x75D48DDE,0x6B93DDDB,0x6F52C06C,0x6211E6B5,0x66D0FB02,
0x5E9F46BF,0x5A5E5B08,0x571D7DD1,0x53DC6066,0x4D9B3063,0x495A2DD4,0x44190B0D,0x40D816BA,
0xACA5C697,0xA864DB20,0xA527FDF9,0xA1E6E04E,0xBFA1B04B,0xBB60ADFC,0xB6238B25,0xB2E29692,
0x8AAD2B2F,0x8E6C3698,0x832F1041,0x87EE0DF6,0x99A95DF3,0x9D684044,0x902B669D,0x94EA7B2A,
0xE0B41DE7,0xE4750050,0xE9362689,0xEDF73B3E,0xF3B06B3B,0xF771768C,0xFA325055,0xFEF34DE2,
0xC6BCF05F,0xC27DEDE8,0xCF3ECB31,0xCBFFD686,0xD5B88683,0xD1799B34,0xDC3ABDED,0xD8FBA05A,
0x690CE0EE,0x6DCDFD59,0x608EDB80,0x644FC637,0x7A089632,0x7EC98B85,0x738AAD5C,0x774BB0EB,
0x4F040D56,0x4BC510E1,0x46863638,0x42472B8F,0x5C007B8A,0x58C1663D,0x558240E4,0x51435D53,
0x251D3B9E,0x21DC2629,0x2C9F00F0,0x285E1D47,0x36194D42,0x32D850F5,0x3F9B762C,0x3B5A6B9B,
0x0315D626,0x07D4CB91,0x0A97ED48,0x0E56F0FF,0x1011A0FA,0x14D0BD4D,0x19939B94,0x1D528623,
0xF12F560E,0xF5EE4BB9,0xF8AD6D60,0xFC6C70D7,0xE22B20D2,0xE6EA3D65,0xEBA91BBC,0xEF68060B,
0xD727BBB6,0xD3E6A601,0xDEA580D8,0xDA649D6F,0xC423CD6A,0xC0E2D0DD,0xCDA1F604,0xC960EBB3,
0xBD3E8D7E,0xB9FF90C9,0xB4BCB610,0xB07DABA7,0xAE3AFBA2,0xAAFBE615,0xA7B8C0CC,0xA379DD7B,
0x9B3660C6,0x9FF77D71,0x92B45BA8,0x9675461F,0x8832161A,0x8CF30BAD,0x81B02D74,0x857130C3,
0x5D8A9099,0x594B8D2E,0x5408ABF7,0x50C9B640,0x4E8EE645,0x4A4FFBF2,0x470CDD2B,0x43CDC09C,
0x7B827D21,0x7F436096,0x7200464F,0x76C15BF8,0x68860BFD,0x6C47164A,0x61043093,0x65C52D24,
0x119B4BE9,0x155A565E,0x18197087,0x1CD86D30,0x029F3D35,0x065E2082,0x0B1D065B,0x0FDC1BEC,
0x3793A651,0x3352BBE6,0x3E119D3F,0x3AD08088,0x2497D08D,0x2056CD3A,0x2D15EBE3,0x29D4F654,
0xC5A92679,0xC1683BCE,0xCC2B1D17,0xC8EA00A0,0xD6AD50A5,0xD26C4D12,0xDF2F6BCB,0xDBEE767C,
0xE3A1CBC1,0xE760D676,0xEA23F0AF,0xEEE2ED18,0xF0A5BD1D,0xF464A0AA,0xF9278673,0xFDE69BC4,
0x89B8FD09,0x8D79E0BE,0x803AC667,0x84FBDBD0,0x9ABC8BD5,0x9E7D9662,0x933EB0BB,0x97FFAD0C,
0xAFB010B1,0xAB710D06,0xA6322BDF,0xA2F33668,0xBCB4666D,0xB8757BDA,0xB5365D03,0xB1F740B4
};
static char base64table[] = {
'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', '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', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/', '\0'
};
static char base64pad = '=';
static unsigned char hexa[] = "0123456789ABCDEF";
static const char *code_html[] = {"nbsp","iexcl","cent","pound","curren","yen","brkbar",
"sect","uml","copy","ordf","laquo","not","shy","reg","macr","deg","plusm",
"sup2","sup3","acute","micro","para","middot","cedil","sup1","ordm","raquo",
"frac14","frac12","frac34","iquest","Agrave","Aacute","Acirc","Atilde","Auml",
"Aring","AElig","Ccedil","Egrave","Eacute","Ecirc","Euml","Igrave","Iacute",
"Icirc","Iuml","Dstrok","Ntilde","Ograve","Oacute","Ocirc","Otilde","Ouml",
"times","Oslash","Ugrave","Uacute","Ucirc","Uuml","Yacute","THORN","szlig",
"agrave","aacute","acirc","atilde","auml","aring","aelig","ccedil","egrave",
"eacute","ecirc","euml","igrave","iacute","icirc","iuml","eth","ntilde",
"ograve","oacute","ocirc","otilde","ouml","divide","oslash","ugrave","uacute",
"ucirc","uuml","yacute","thorn","yuml", NULL};
static int jour_dans_mois[2][13] = {
{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
{0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};
static const char *jour[6][7] = {
{"Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi"}, /* -- Francais -- */
{"Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"},
{"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"}, /* -- Anglais -- */
{"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"},
{"Sontag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"}, /* -- Allemand -- */
{"Son", "Mon", "Die", "Mit", "Don", "Fre", "Sam"}
};
static const char *mois[6][12] = {
{"Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Aout", "Septembre", "Octobre", "Novembre", "Décembre"}, /* -- francais -- */
{"Jan", "Fév", "Mar", "Avr", "Mai", "Jun", "Jui", "Aou", "Sep", "Oct", "Nov", "Déc"},
{"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"}, /* -- Anglais -- */
{"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"},
{"Januar", "Februar", "Marz", "April", "Mai", "Juny", "July", "August", "September", "October", "November", "December"}, /* -- Allemand -- */
{"Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}
};
#define JEUDI 4 /* pour reformation */
#define SAMEDI 6 /* le 1 Jan 1 est un Samedi */
#define FIRST_MISSING_DAY 639787 /* 3 Sep 1752 */
#define NUMBER_MISSING_DAYS 11 /* 11 day correction */
/* annee bissextile - 0: pas bissextile, 1: annee bisextile */
#define annee_bissex(annee) \
((annee) <= 1752 ? !((annee) % 4) : \
(!((annee) % 4) && ((annee) % 100)) || !((annee) % 400))
/* nombre de siecles depuis 1700, non inclut */
#define siecles_depuis_1700(annee) \
((annee) > 1700 ? (annee) / 100 - 17 : 0)
/* nombre de 4 siecles depuis 1700 */
#define quatre_siecles_depuis_1700(annee) \
((annee) > 1600 ? ((annee) - 1600) / 400 : 0)
/* nombre d'annee bissextile entre l'annee 1 et cette annee, non inclut */
#define nombre_annee_bissex(annee) \
((annee) / 4 - siecles_depuis_1700(annee) + quatre_siecles_depuis_1700(annee))
#define if_sortie (conf->ifwhile[conf->nwhile].sortie && conf->show)
/* ---------- Structure pour Upload ---------- */
typedef struct adml_upload {
char *remote_filename;
char *filename;
char *content_type;
char *name;
char *data;
char *save; /* NULL si pas sauvegarde et nom du fichier de la derniere sauvegarde sinon */
unsigned long int taille;
} adml_upload;
/* ---------- Structure pour Mime ---------- */
typedef struct adml_mime {
char *buffer;
unsigned long int taille;
unsigned long int position;
const char *boundary;
char *content_type;
char *content_disposition;
char *content_transfer_encoding;
char *data;
unsigned long int taille_data;
int fin; /* Afin de renvoyer un TRUE si le boundary de fin a ete trouve et FALSE si non */
} adml_mime;
/* ---------- Structure pour Form ---------- */
typedef struct adml_form {
table *tab; /* Table pour la liste de champs */
int pos; /* Position courante sur la liste de champs */
} adml_form;
/* ---------- Structure pour Var ---------- */
typedef struct adml_var {
table *tab; /* Table pour la liste de champs */
int pos; /* Position courante sur la liste de champs */
} adml_var;
/* ---------- Structure pour Cookies ---------- */
typedef struct adml_cookies {
table *tab; /* Table pour la liste de champs */
int pos; /* Position courante sur la liste de champs */
} adml_cookies;
enum socket_flag { NONE=0, NOWAIT=1, FORK=2, NOHANDLE=4 };
/* ---------- Structure pour les Sockets ---------- */
typedef struct adml_socket {
BUFF *f;
int fd;
int port;
pool *p;
const char *host;
const char *service;
int last_excess;
char *last_pos;
char eom;
table *headers;
char *buffer;
int taille_buffer, taille_buffer_max;
size_t recv_buffer_size;
} adml_socket;
/* ---------- Structure pour le SMTP ---------- */
typedef struct adml_smtp {
adml_socket sock; /* structure socket pour les envois de E-Mail */
int code_retour;
int etrn;
int dsn;
int bit8mime;
} adml_smtp;
/* ---------- Structure pour Mysql ---------- */
typedef struct adml_mysql {
int fconnect, fbase, fquery, ferror;
int numligne, numcolonne;
MYSQL mysql; /* Socket */
MYSQL_RES *res; /* Structure */
MYSQL_ROW row; /* champs */
MYSQL_FIELD *field; /* champs */
} adml_mysql;
/* ---------- Structure pour les boucles While ---------- */
typedef struct adml_while {
int type, tour, limite, num;
int sortie, execute;
int position; /* Afin de memorise la position dans le fichier en cour du debut du contenu de la boucle */
int ligne; /* Afin de memoriser le numero de ligne au debut de la boucle de facon que la boucle ne genere pas d'erreur sur les numeros de lignes */
array_header *arr; /* Afin de memoriser si besoin est un pointeur vers un array */
} adml_while;
#if _XML_EXPAT > 0
/* ---------- Structure pour les boucles While ---------- */
typedef struct adml_xml {
int depth;
XML_Parser parser;
} adml_xml;
#endif
/* ---------- Structure Generale ---------- */
typedef struct adml_cfg {
const char *filename; /* Pour memoriser le nom du fichier include en cour ou NULL si on est dans le fichier principal ou "-VaR!" si ont est dans une variable */
char *fichier; /* Pour le fichier principal */
int ligne; /* Numero et position de ligne courante du fichier en cour (utile pour les erreurs) */
int taille_fichier; /* Taille du fichier */
table *tag; /* afin de decortiquer un tag proprietaire */
table *include; /* afin de memoriser les fichiers includes */
char *tag_nom; /* Nom du tag */
char *tag_valeur; /* Valeur du tag */
int debut_tag; /* Pointe sur le premier caractere du tag courrant */
int fin_tag; /* Pointe sur le dernier caractere du tag courrant */
int pos_fichier; /* Position du pointeur d'analyse du fichier */
pool *pool_tag; /* pool pour l'analyse des tags (Initialiser a chaque debut de TAG) */
pool *pool_session; /* pool pour la creation des structures form par exemple (initialise a chaque session) */
char *temp, *temp1; /* Pour usage temporaire */
const char *ctemp; /* Pour usage temporaire */
long engine; /* Pour la commande : ModelEngine on|off */
double calcul; /* Principalement pour la fonction calcul afin qu'elle puissent passer des resultat en numerique */
adml_form form[N_FORM]; /* Structures Form */
adml_var var[N_VAR]; /* Structures Var */
int form_def; /* Numero de structure par defaut de Form */
int var_def; /* Numero de structure par defaut de Var */
adml_mysql base_mysql[N_MYSQL]; /* Structure mysql */
int mysql_def; /* Numero de structure par defaut de Mysql */
adml_socket sock[N_SOCKET + 1]; /* structures socket */
adml_smtp smtp; /* structure socket pour les envois de E-Mail */
char *mysql_host; /* Pour la config par defaut */
char *mysql_user; /* Pour la config par defaut */
char *mysql_passwd; /* Pour la config par defaut */
char *mysql_base; /* Pour la config par defaut */
int nwhile; /* Pour connaitre le niveau d'imbriction */
adml_while ifwhile[N_WHILE]; /* Pour les boucle While et les IF */
time_t secs[N_DATE]; /* structure Date */
int notagbr; /* SI il est a TRUE, alors les retour chariot juste apres un TAG proprietaire sont supprimmer */
const char *unique_id; /* Identificateur unique pour la session en cour et ses sous-requetes */
char *boundary; /* Pour stocker le boundary du multipart/form-data */
adml_upload upload[N_UPLOAD]; /* Structure pour stocker les uploads */
int nupload; /* Afin de savoir combien de upload sont stocker dans la structure upload */
int upload_num; /* position courante dans la structure upload */
request_rec *rr; /* Afin de realiser une sous-requete */
request_rec *r; /* Afin de garder la trace dans la structure de la requete */
int header, noheader; /* header=TRUE si le Header est deja envoye et noheader=TRUE si le header ne doit pas etre envoye */
int exit; /* TRUE si une commande EXIT a ete utilise (donc sortie de la page) */
char buffer[TAILLE_BUFFER + 1]; /* Buffer de taille TAILLE_BUFFER alloue a la creation du processus */
adml_cookies cookies; /* Structure devant contenir la liste des cookies */
int headers_in_num; /* Position courante dans la table des headers_in */
const char *auth_user, *auth_passwd, *auth_type; /* Pour l'entete Authorization: (si user == NULL, c'est qu'il n'y a rien) */
int show; /* Pour le tag Show= On ou Off */
#if _XML_EXPAT > 0
adml_xml xml[N_XML]; /* Structure XML */
#endif
} adml_cfg;
typedef struct adml_calcul {
int type;
char *chaine;
double valeur;
} adml_calcul;
/*
* Let's set up a module-local static cell to point to the accreting callback
* trace. As each API callback is made to us, we'll tack on the particulars
* to whatever we've already recorded. To avoid massive memory bloat as
* directories are walked again and again, we record the routine/environment
* the first time (non-request context only), and ignore subsequent calls for
* the same routine/environment.
*/
static const char *trace = NULL;
/* Declaration du module */
module adml_module;
static char *int_to_hex(pool *p, long unsigned int val, int digit, char *result);
static int add_form(table *form, const char *nom, const char *valeur, int type);
static void decode_classique(adml_cfg *conf, int num, char *chaine, int type, int copie);
static double calc(adml_cfg *conf, const char *chaine);
static char *interp(adml_cfg *conf, const char *chaine);
static void analyse_page(request_rec *r, char *fichier);
static int recup(request_rec *r);
static void recup_cookies(adml_cfg *conf);
static int testlog(adml_cfg *conf, const char *chaine);
static int isnum(const char *chaine);
/*--------------------------------------------------------------------------*/
/* Prend en compte les parametres de type FLAG (on/off) */
/*--------------------------------------------------------------------------*/
static const char *handle_FLAG(cmd_parms *cmd, adml_cfg *conf, int val)
{
int i = (int)cmd->info; /* recupere le parametre supplementaire */
switch(i)
{
case 0: /* Commande : AdmlEngine on|off */
conf->engine = val;
break;
}
return NULL;
}
/*--------------------------------------------------------------------------*/
/* Prend en compte les parametres avec 1 argument */
/*--------------------------------------------------------------------------*/
static const char *handle_TAKE1(cmd_parms *cmd, adml_cfg *conf, char *argument)
{
int i = (int)cmd->info; /* recupere le parametre supplementaire */
switch(i)
{
case 0: /* Commande : MysqlHost */
conf->mysql_host = argument;
break;
case 1: /* Commande : MysqlUser */
conf->mysql_user = argument;
break;
case 2: /* Commande : MysqlPassword */
conf->mysql_passwd = argument;
break;
case 3: /* Commande : MysqlBase */
conf->mysql_base = argument;
break;
}
return NULL;
}
/*--------------------------------------------------------------------------*/
/* Encodage Base64 */
/*--------------------------------------------------------------------------*/
static unsigned char *base64encode(pool *p, const unsigned char *chaine, int taille, int *res_taille)
{
const unsigned char *ptr = chaine;
int i = 0;
unsigned char *result = (unsigned char *)ap_palloc(p, ((taille + 3 - taille % 3) * 4 / 3 + 1) * sizeof(char)); /* Alloue la zone memoire necessaire a l'encodage */
/* keep going until we have less than 24 bits */
while (taille > 2)
{
result[i++] = base64table[ptr[0] >> 2];
result[i++] = base64table[((ptr[0] & 0x03) << 4) + (ptr[1] >> 4)];
result[i++] = base64table[((ptr[1] & 0x0f) << 2) + (ptr[2] >> 6)];
result[i++] = base64table[ptr[2] & 0x3f];
ptr += 3;
taille -= 3;
}
/* now deal with the tail end of things */
if (taille != 0)
{
result[i++] = base64table[ptr[0] >> 2];
if (taille > 1)
{
result[i++] = base64table[((ptr[0] & 0x03) << 4) + (ptr[1] >> 4)];
result[i++] = base64table[(ptr[1] & 0x0f) << 2];
result[i++] = base64pad;
}
else
{
result[i++] = base64table[(ptr[0] & 0x03) << 4];
result[i++] = base64pad;
result[i++] = base64pad;
}
}
if(res_taille) *res_taille = i; /* retourne la taille si le pointeur res_taille n'est pas NULL */
result[i] = '\0'; /* Fin de chaine */
return(result);
}
/*--------------------------------------------------------------------------*/
/* Decodage Base64 */
/* Retourne la chaine decoder ou NULL si pas possible ou erreur */
/*--------------------------------------------------------------------------*/
static unsigned char *base64decode(pool *p, const unsigned char *chaine, int taille, int *res_taille)
{
const unsigned char *ptr = chaine;
int ch, i = 0, j = 0;
unsigned char *result = (unsigned char *)ap_palloc(p, (taille / 4 * 3 + 1) * sizeof(char)); /* alloue la zone memoire necessaire au decodage */
if (result == NULL) return(NULL);
while ((ch = *ptr++) != '\0') /* Boucle pour traitement de conversion */
{
if (ch == base64pad) break;
ch = (int)strchr(base64table, ch);
if (ch == 0) return(NULL);
ch -= (int)base64table;
switch(i % 4)
{
case 0:
result[j] = ch << 2;
break;
case 1:
result[j++] |= ch >> 4;
result[j] = (ch & 0x0f) << 4;
break;
case 2:
result[j++] |= ch >>2;
result[j] = (ch & 0x03) << 6;
break;
case 3:
result[j++] |= ch;
break;
}
i++;
}
if (ch == base64pad) /* Si c'est la fin de la chaine encode */
{
switch(i % 4)
{
case 0:
case 1:
return(NULL);
case 2:
j++;
case 3:
result[j++] = 0;
}
}
if(res_taille) *res_taille = j; /* retourne la taille du resultat si res_taille est different de NULL */
result[j] = '\0'; /* fin de chaine */
return(result);
}
/*--------------------------------------------------------------------------*/
/* Si quot = TRUE, alors prend en compte les guillemets dans la chaine */
/* Retourne NULL si pas trouve et le mot si trouve */
/* Type : 0 = renvoi un char avec le mot recuperer ou NULL si pas trouve */
/* 1 = renvoi un int avec TRUE si le mot existe ou FALSE sinon */
/* 2 = retoune un int avec le nombre de mots de la chaine */
/* ret est le pointeur de la variable a retourner pour le int */
/*--------------------------------------------------------------------------*/
static void *recupmots(pool *p, const char *chaine, int num, int min, int max, int quot, int type, int *ret)
{
int guil = FALSE; /* Pas encore de guillemet d'ouvert */
int flag = FALSE; /* Ont est pas encore dans un mot */
int pos, z = 0, x = -1;
if (min < 1) min = 1; /* La taille minimum ne doit pas etre inferieur a 1 */
if (max < 0) max = 0; /* La taille maximum ne doit pas etre negative */
if (num > 0) /* C'est pas la peine de chercher si num < 1 */
{
while(chaine[++x] != '\0')
{
if (flag) /* Je suis dans un mot */
{
if ((!guil && (chaine[x] < 48 || (chaine[x] >57 && chaine[x] < 64))) || (guil && chaine[x] == '\"')) /* Fin du mot */
{
flag = FALSE;
guil = FALSE;
if ((x-pos >= min || min < 1) && (x-pos <= max || max < 1)) z++; /* Mot suivant seulement si il a le nombre de caractere correct */
if (type != 2 && z == num) break; /* Le mot est trouver */
}
}
else if ((chaine[x] > 47 && chaine[x] < 58) || chaine[x] > 63 || (chaine[x] == '\"' && quot)) /* J'entre dans un nouveau mot */
{
flag = TRUE;
pos = x; /* debut du mot suivant */
if (chaine[x] == '\"') /* Si un guillemet a ete ouvert */
{
if (strchr(&chaine[x+1], '\"') == NULL) flag = FALSE; /* Si il n'y a pas d'autre guillemet plus loin pour ferme alors ignore le guillemet */
else
{
guil = TRUE;
pos++; /* saute le guillemet */
}
}
}
}
if (flag && x-pos > 0 && (x-pos >= min || min < 1) && (x-pos <= max || max < 1)) z++; /* Si il y a un dernier mot a prendre en compte */
if (z > 0 && z == num) /* Si ont a trouve */
{
if (type == 0) return(ap_pstrndup(p, &chaine[pos], x - pos));
else if (type == 1)
{
*ret = TRUE;
return(ret);
}
}
else if (type == 2)
{
*ret = z; /* Nombre de mots trouve */
return(ret);
}
}
/* Si pas trouve */
if (type == 0) return(NULL);
else
{
if (type == 1) *ret = FALSE;
else if (type == 2) *ret = 0;
return(ret);
}
}
/*--------------------------------------------------------------------------*/
/* Meme Fonction que l'API Apache mais avec difference Maj/Min ou non */
/* Si minmaj = TRUE, alors ne tient pas compte des Maj/min */
/*--------------------------------------------------------------------------*/
void adml_table_merge(table *t, const char *key, const char *val, int minmaj)
{
array_header *arr = ap_table_elts(t);
table_entry *elts = (table_entry *) arr->elts;
int i;
for (i = 0; i < arr->nelts; ++i)
{
if ((minmaj && !strcasecmp(elts[i].key, key)) || (!minmaj && !strcmp(elts[i].key, key)))
{
elts[i].val = ap_pstrcat(arr->pool, elts[i].val, ", ", val, NULL);
return;
}
}
if (&arr->nelts == &arr->nalloc) fprintf(stderr, "adml_table_merge: table created by X hit limit of %u\n", arr->nalloc);
elts = (table_entry *) ap_push_array(arr);
elts->key = ap_pstrdup(arr->pool, key);
elts->val = ap_pstrdup(arr->pool, val);
}
/*--------------------------------------------------------------------------*/
/* Meme Fonction que l'API Apache mais avec difference Maj/Min ou non */
/* Si minmaj = TRUE, alors ne tient pas compte des Maj/min */
/*--------------------------------------------------------------------------*/
void adml_table_set(table *t, const char *key, const char *val, int minmaj)
{
register int i, j, k;
array_header *arr = ap_table_elts(t);
table_entry *elts = (table_entry *) arr->elts;
int done = 0;
for (i = 0; i < arr->nelts; )
{
if ((minmaj && !strcasecmp(elts[i].key, key)) || (!minmaj && !strcmp(elts[i].key, key)))
{
if (!done)
{
elts[i].val = ap_pstrdup(arr->pool, val);
done = 1;
++i;
}
else /* delete an extraneous element */
{
for (j = i, k = i + 1; k < arr->nelts; ++j, ++k)
{
elts[j].key = elts[k].key;
elts[j].val = elts[k].val;
}
--arr->nelts;
}
}
else ++i;
}
if (!done)
{
if (&arr->nelts == &arr->nalloc) fprintf(stderr, "adml_table_add: table created by X hit limit of %u\n", arr->nalloc);
elts = (table_entry *) ap_push_array(arr);
elts->key = ap_pstrdup(arr->pool, key);
elts->val = ap_pstrdup(arr->pool, val);
}
}
/*--------------------------------------------------------------------------*/
/* Type = 0:normal 1:is 2:name 3:len 4:pos 5:bool 6:int 7:num */
/* min_maj = TRUE alors ne tient pas compte de la difference Min/Maj */
/* pos = position courante */
/* nbr = selectionne le nbr champ correspondant */
/*--------------------------------------------------------------------------*/
static char *cherche_table(adml_cfg *conf, table *tab, int pos, int nbr, const char *chaine, int type, int min_maj)
{
array_header *arr = ap_table_elts(tab);
table_entry *elts = (table_entry *) arr->elts;
int y, w, z = -1, i;
char *result = "", *ptr;
if (chaine == NULL) return(NULL);
if (!strcasecmp(chaine, "_nbr")) result = ap_psprintf(conf->pool_tag, "%d", arr->nelts); /* Nombre de champs dans la structure */
else if (!strncasecmp(chaine, "_pos", 4)) result = ap_psprintf(conf->pool_tag, "%d", pos); /* position courante */
else
{
if (chaine[0] != '#') /* Recherche en nom */
{
for(y=0, w=0; y < arr->nelts; y++)
{
if ((min_maj && !ap_strcasecmp_match(elts[y].key, chaine)) || (!min_maj && !ap_strcmp_match(elts[y].key, chaine)))
{
if (++w == nbr) /* Pour le deuxieme parametre (nbr de champ) */
{
z = y;
break;
}
}
}
}
else if (!strcmp(chaine, "#")) /* Position courante */
{
if (pos >= 0 && pos < arr->nelts) z = pos; /* Trouver */
}
else if (isnum(&chaine[1]) && strlen(&chaine[1]) > 0) /* Recherche avec le numero du champ */
{
i = atoi(&chaine[1]);
if (i >= 0 && i < arr->nelts) z = i; /* Trouver */
}
if (z < 0)
{
if (type == 1 || (type > 4 && type < 9)) result = "0"; /* Pour le IS, IF, Bool, Int et Num */
}
else
{
if (type == 1) result = "1"; /* Pour le IS ou IF */
else if (type == 2) result = elts[z].key; /* Renvoi le nom du champ */
else if (type == 3) result = ap_psprintf(conf->pool_tag, "%lu", (unsigned long int)strlen(elts[z].val)); /* Renvoi la taille du champ */
else if (type == 4) result = ap_psprintf(conf->pool_tag, "%d", z); /* Renvoi la position du champ */
else if (type == 5) /* Type BOOL */
{
if (atoi(elts[z].val)) result = "1"; /* VRAI */
else result = "0"; /* FAUX */
}
else if (type == 6) /* TYPE INT */
{
result = ap_pstrdup(conf->pool_tag, elts[z].val);
if ((ptr = strchr(result, ',')) != NULL) ptr[0] = '.'; /* Remplacer la virgule par un point pour que atof() convertisse correctement */
result = ap_psprintf(conf->pool_tag, "%0.0lf", atof(result));
}
else result = elts[z].val; /* Renvoi la valeur du champ correspondant au numero */
}
}
return(result);
}
/*--------------------------------------------------------------------------*/
/* GET_PORT */
/*--------------------------------------------------------------------------*/
static int get_port(const char *service)
{
struct servent *servent;
if (!service || !strlen(service)) return(-1); /* Le service n'existe pas */
if (!isdigit(*service))
{
if ((servent = getservbyname((char *)service, "tcp")) == 0) return(-1); /* Err */
}
else
{
if ((servent = getservbyport(atoi(service), "tcp")) == 0) return(htons(atoi(service)));
}
return(servent->s_port);
}
/*--------------------------------------------------------------------------*/
/* GET_IP */
/*--------------------------------------------------------------------------*/
static unsigned long get_ip(const char *host)
{
struct hostent *hostent;
struct in_addr *addr;
unsigned long addr1;
if (!host || !strlen(host)) return(-1); /* pas de host */
if (!isdigit(*host))
{
if ((hostent = gethostbyname((char *)host)) == 0) return(-1);
}
else
{
addr1 = inet_addr((char *)host);
return(addr1);
}
addr = (struct in_addr *) *(hostent->h_addr_list);
return(addr[0].s_addr);
}
/*--------------------------------------------------------------------------*/
/* Ferme une connection socket */
/*--------------------------------------------------------------------------*/
static int socket_close(adml_socket *sock)
{
if (sock->fd > -1)
{
ap_bclose(sock->f); /* Ferme le flux */
shutdown(sock->fd, 2);
if (!sock->p) ap_pclosesocket(sock->p, sock->fd);
sock->fd = -1;
}
return(TRUE);
}
/*--------------------------------------------------------------------------*/
/* */
/*--------------------------------------------------------------------------*/
static int socket_wait(adml_socket *sock, long seconds, long microseconds, int type)
{
int nbytes;
const char *src;
struct timeval timeval = {seconds, microseconds};
fd_set read_fds;
fd_set error_fds;
fd_set write_fds;
if (sock->fd < 0) return(0); /* Pas de socket connecter */
if ((type&1) && (sock->last_excess > 0))
{
nbytes = sock->last_excess;
src = sock->last_pos;
while (nbytes-- > 0)
{
if (*src++ == sock->eom) return(1);
}
}
FD_ZERO(&read_fds);
FD_SET(sock->fd, &read_fds);
return(select(FD_SETSIZE, (type&1?&read_fds:0), (type&2?&write_fds:0), (type&4?&error_fds:0), (seconds < 0 ? 0 : &timeval)));
}
/*--------------------------------------------------------------------------*/
/* Ecriture de donnees vers une socket */
/*--------------------------------------------------------------------------*/
static int socket_write(adml_socket *sock, const char *buffer, int nbytes)
{
const char *ptr = buffer;
int len;
int wbytes = 0;
loop_write:
if ((len = send(sock->fd, ptr, nbytes, 0)) < 0)
{
if ((errno != EWOULDBLOCK) && (errno != EINTR)) return(-errno);
}
wbytes += len;
if (len < nbytes)
{
ptr += len;
nbytes -= len;
socket_wait(sock, -1, 0, 2); /* Wait for socket to be writable */
goto loop_write;
}
return(wbytes);
}
/*--------------------------------------------------------------------------*/
/* Lecture de donnees en provenance d'une socket */
/*--------------------------------------------------------------------------*/
static int socket_readmsg(request_rec *r, adml_socket *sock, char *buffer, int nbytes)
{
int len;
ap_hard_timeout("ADML Socket Reading...", r);
len = ap_bgets(buffer, nbytes, sock->f);
if (len == -1 || len == 0)
{
/* ap_bclose(sock->f); */
ap_kill_timeout(r);
buffer[0] = 0; /* Fin de chaine */
return(len);
}
ap_kill_timeout(r);
buffer[len] = 0; /* Fin de chaine */
return(len);
}
/*--------------------------------------------------------------------------*/
/* Lecture de donnees en provenance d'une socket */
/*--------------------------------------------------------------------------*/
static int socket_read(request_rec *r, pool *p, adml_socket *sock)
{
char *ptr, *buffer;
int len;
int nbytes = 1024;
buffer = ap_palloc(p, nbytes+1);
loop_read:
if ((len = recv(sock->fd, buffer, nbytes, 0)) < 0)
{
if (errno == EINTR) goto loop_read;
else if (errno == EWOULDBLOCK) return(0);
else return(-errno); /* Erreur */
}
ap_rprintf(r, " [%s] ", buffer);
return(len);
}
/*--------------------------------------------------------------------------*/
/* Recupere une ligne dans le buffer socket */
/* Jusqu'au <LF> en eliminant l'eventuel <CR> precedent le <LF> */
/*--------------------------------------------------------------------------*/
static char *socket_gets(adml_cfg *conf, adml_socket *sock)
{
int z, y;
char *temp;
z = 0;
while((y = socket_readmsg(conf->r, sock, conf->buffer, TAILLE_BUFFER)) > 0)
{
if ((z + y) >= sock->taille_buffer_max) /* Si l'emplacement est trop petit */
{
sock->taille_buffer_max += TAILLE_BUFFER;
temp = ap_palloc(sock->p, sizeof(char) * (sock->taille_buffer_max + 1));
memcpy(temp, sock->buffer, sizeof(char) * z);
sock->buffer = temp;
}
memcpy(&sock->buffer[z], conf->buffer, sizeof(char) * y);
z += y;
sock->buffer[z] = '\0'; /* Fin de ligne */
if ((temp = strchr(sock->buffer, '\n')) != NULL) /* Si ont rencontre un caractere de retour chariot */
{
temp[0] = '\0'; /* Fin de ligne */
break;
}
}
return(sock->buffer);
}
/*--------------------------------------------------------------------------*/
/* Envoi une requete SMTP et recupere la reponse dans la structure SMTP */
/*--------------------------------------------------------------------------*/
static int smtp_retour(adml_cfg *conf)
{
char car;
conf->smtp.code_retour = 0;
smtp_req_goto:
socket_gets(conf, &conf->smtp.sock); /* Lecture d'une ligne dans le buffer socket SMTP */
if (conf->smtp.sock.buffer[3] == '-') goto smtp_req_goto;
if (strlen(conf->smtp.sock.buffer) > 3)
{
car = conf->smtp.sock.buffer[3];
conf->smtp.sock.buffer[3] = '\0';
conf->smtp.code_retour = atoi(conf->smtp.sock.buffer);
conf->smtp.sock.buffer[3] = car;
}
if (conf->smtp.code_retour == 250)
{
if (!strncasecmp(&conf->smtp.sock.buffer[4], "ETRN", 4)) conf->smtp.etrn = TRUE;
else if (!strncasecmp(&conf->smtp.sock.buffer[4], "DSN", 3)) conf->smtp.dsn = TRUE;
else if (!strncasecmp(&conf->smtp.sock.buffer[4], "8BITMIME", 8)) conf->smtp.bit8mime = TRUE;
}
return(conf->smtp.code_retour);
}
/*--------------------------------------------------------------------------*/
/* Realise une connection socket */
/*--------------------------------------------------------------------------*/
static int socket_connect(adml_socket *sock, const char *host, const char *service)
{
struct linger linger;
int flag, i;
struct sockaddr_in remote;
socket_close(sock); /* ferme la socket existante (au cas ou) */
ap_clear_pool(sock->p); /* Effacer le contenu du pool (donnees de la precedente socket) */
ap_make_table(sock->p, 1); /* creation de la table des headers */
sock->taille_buffer = sock->taille_buffer_max = 0;
sock->buffer = "";
sock->f = ap_bcreate(sock->p, B_RDWR | B_SOCKET); /* cree un flux tamponne dans le pool p en lecture et ecriture */
if ((sock->fd = ap_psocket(sock->p, PF_INET, SOCK_STREAM, 0)) == -1)
{
/* Erreur ERRNO (erreur de connection) */
return(-1);
}
linger.l_onoff = 1; /* Specifit que l_linger definit le temp pendant lequel des données non transmise essayeront de l'etre lors d'un close */
linger.l_linger = 5;
setsockopt(sock->fd, SOL_SOCKET, SO_LINGER, (char *)&linger, sizeof(linger));
/* Permet de tester qu'une connection sur laquelle aucun transfert n'a ete realise depuis longtemp est encore active et la ferme eventuellement */
flag = 1;
setsockopt(sock->fd, SOL_SOCKET, SO_KEEPALIVE, (char *)&flag, sizeof(int));
ap_bpushfd(sock->f, sock->fd, sock->fd); /* Definit les descripteur de fichier en lecture et ecriture d'un flux */
/*
setsockopt(sock->fd, SOL_SOCKET, SO_RCVBUF, (const char *)&sock->recv_buffer_size, sizeof(int));
*/
remote.sin_family = PF_INET;
remote.sin_port = get_port(service);
remote.sin_addr.s_addr = get_ip(host);
sock->port = ntohs(remote.sin_port);
do
{
i = connect(sock->fd, (struct sockaddr *)&remote, sizeof(remote));
/*
if (i == SOCKET_ERROR) errno = WSAGetLastError();
*/
} while (i == -1 && errno == EINTR);
if (i == -1)
{
/* Erreur socket */
return(-errno);
}
/*
ioctl(sock->fd, FIONBIO, 1);
ap_bnonblock(sock->f, B_RD);
*/
sock->host = ap_pstrdup(sock->p, host); /* Conserve l'adresse host */
sock->service = ap_pstrdup(sock->p, service); /* Conserve le service */
return(sock->fd);
}
/*--------------------------------------------------------------------------*/
/* Imprime un caractere vers le client */
/*--------------------------------------------------------------------------*/
static int imprime_char(adml_cfg *conf, int c)
{
if (if_sortie && (conf->noheader || conf->header || c > 32))
{
if (!conf->header && !conf->noheader)
{
conf->r->content_type = "text/html"; /* Definit le content_type */
ap_send_http_header(conf->r);
conf->header = TRUE;
}
return(ap_rputc(c, conf->r));
}
return(0);
}
/*--------------------------------------------------------------------------*/
/* Imprime vers le client */
/*--------------------------------------------------------------------------*/
static int imprime(adml_cfg *conf, const char *fmt, ...)
{
va_list vlist;
int n;
if (if_sortie)
{
if (conf->r->connection->aborted) return(-1);
va_start(vlist, fmt);
if (!conf->header && !conf->noheader)
{
conf->r->content_type = "text/html"; /* Definit le content_type */
ap_send_http_header(conf->r);
conf->header = TRUE;
}
n = ap_vbprintf(conf->r->connection->client, fmt, vlist);
va_end(vlist);
if (n < 0)
{
if (!conf->r->connection->aborted)
{
ap_log_rerror(APLOG_MARK, APLOG_INFO, conf->r, "client stopped connection before adml imprime() completed");
ap_bsetflag(conf->r->connection->client, B_EOUT, 1);
conf->r->connection->aborted = 1;
}
return(-1);
}
do
{
if (conf->r->sent_bodyct) ap_bgetopt(conf->r->connection->client, BO_BYTECT, &conf->r->bytes_sent);
} while (0);
ap_rflush(conf->r); /* Vide le tampon vers le client (pour debugage) */
return(n);
}
return(0);
}
/*--------------------------------------------------------------------------*/
/* Retire les anti-slash d'une chaine */
/*--------------------------------------------------------------------------*/
static char *unescape_backslash(char *chaine)
{
int x, y = 0, taille, flag = FALSE;
if (chaine == NULL) return(NULL);
taille = strlen(chaine);
for (x = 0; x < taille; x++)
{
if (flag)
{
if (chaine[x] == 'r') chaine[y++] = '\r';
else if (chaine[x] == 'n') chaine[y++] = '\n';
flag = FALSE;
}
else if (chaine[x] == '\\') flag = TRUE;
else chaine[y++] = chaine[x];
}
chaine[y] = '\0';
return(chaine);
}
/*--------------------------------------------------------------------------*/
/* Calcul le CRC32 d'une chaine */
/*--------------------------------------------------------------------------*/
static long unsigned int calcul_crc32(const char *chaine)
{
int i, taille;
long unsigned int crc32 = 0;
if (chaine == NULL) return(0);
taille = strlen(chaine);
for (i = 0; i < taille; i++) crc32 = (crc32 >> 8) ^ crc32table[(crc32 ^ chaine[i]) & 0xFF];
return(crc32);
}
/*--------------------------------------------------------------------------*/
/* Remplace une ou plusieurs occurance d'une sous-chaine dans une chaine */
/*--------------------------------------------------------------------------*/
static char *strrep(pool *p, char *chaine, const char *ch1, const char *ch2, int nbr, int minmaj)
{
int x = -1, y = 0, n = 0, trep, comptage = 0, len;
char *result;
if ((len = strlen(ch1)) < 1 || nbr == 0) return(chaine); /* aucun traitement */
if ((trep = strlen(ch2)) > len) /* si la chaine de remplacement est plus grande que la sous-chaine a remplacer */
{
while(chaine[++x] != '\0') /* boucle permettant de connaitre le nombre d'occurance afin de calculer la taille de la nouvelle zone memoire a allouer */
{
if ((minmaj && !strncasecmp(&chaine[x], ch1, len)) || (!minmaj && !strncmp(&chaine[x], ch1, len)))
{
if (++n == nbr || nbr < 0)
{
x += len - 1;
comptage++; /* Compte le nombre d'occurance */
}
}
}
if (comptage < 1) return(chaine); /* s'il y a pas d'occurance de bonne */
result = ap_palloc(p, (strlen(chaine) + (trep * comptage) - (len * comptage) + 1) * sizeof(char)); /* Allocation d'une nouvelle zone memoire */
}
else result = chaine;
x = -1; n = 0; y = 0;
while(chaine[++x] != '\0') /* Boucle de traitement */
{
if ((minmaj && !strncasecmp(&chaine[x], ch1, len)) || (!minmaj && !strncmp(&chaine[x], ch1, len)))
{
if (++n == nbr || nbr < 0)
{
x += len - 1; /* saute l'occurance */
strncpy(&result[y], ch2, trep); /* remplace l'occurance */
y += trep;
}
else result[y++] = chaine[x];
}
else result[y++] = chaine[x];
}
result[y++] = '\0';
return(result);
}
/*--------------------------------------------------------------------------*/
/* Supprim une ou plusieurs occurance d'une sous-chaine dans une chaine */
/*--------------------------------------------------------------------------*/
static char *strsup(char *chaine, const char *sup, int nbr, int minmaj)
{
int x = -1, y = 0, n = 0, len;
if ((len = strlen(sup)) < 1 || nbr == 0) return(chaine); /* aucun traitement */
while(chaine[++x] != '\0')
{
if ((minmaj && !strncasecmp(&chaine[x], sup, len)) || (!minmaj && !strncmp(&chaine[x], sup, len)))
{
if (++n == nbr || nbr < 0) x += len - 1;
else chaine[y++] = chaine[x];
}
else chaine[y++] = chaine[x];
}
chaine[y++] = '\0';
return(chaine);
}
/*--------------------------------------------------------------------------*/
/* Encode en CRC32 Hexadecimal une chaine */
/*--------------------------------------------------------------------------*/
static char *encode_crc32(pool *p, const char *data, const char *key)
{
long unsigned int crc32;
int i, tdata, tkey, k = 0, j = 0;
char *result;
char hex_temp[9];
if (data == NULL) data = "";
tdata = strlen(data); /* recupere la taille de la chaine a encoder */
crc32 = calcul_crc32(data); /* Recupere le CRC32 */
if (key == NULL) key = int_to_hex(p, crc32, 8, NULL); /* Si key == NULL alors prend le crc32 en hexa comme cles */
tkey = strlen(key); /* recupere la taille de la cles */
result = ap_pcalloc(p, ((tdata * 2) + tkey + 1) * sizeof(char)); /* Alloue l'emplacement memoire */
for (i = 0; i < tdata; i++)
{
strcpy(&result[k], int_to_hex(p, data[i] ^ key[j], 2, hex_temp));
k += 2;
if (++j >= tkey) j = 0; /* Boucle sur la cles */
}
strcpy(&result[k], int_to_hex(p, crc32, 8, hex_temp)); /* Ajoute le CRC32 en hexa a la fin de la chaine */
return(result);
}
/*--------------------------------------------------------------------------*/
/* Decode en CRC32 Hexadecimal une chaine */
/*--------------------------------------------------------------------------*/
static char *decode_crc32(pool *p, const char *data, const char *key)
{
register char digit;
int i, tdata, tkey, x = 0, j = 0;
char *result;
if (data == NULL) data = "";
if ((tdata = strlen(data)) < 9) return(NULL); /* Erreur */
result = ap_pcalloc(p, ((tdata + 2) / 2) * sizeof(char)); /* Alloue l'emplacement memoire */
tdata -= 8;
if (key == NULL) key = &data[tdata]; /* Si key == NULL alors prend le crc32 comme cles */
tkey = strlen(key);
for (i = 0; i < tdata; i++)
{
digit = (data[i] >= 'A' ? ((data[i] & 0xdf) - 'A')+10 : (data[i] - '0'));
i++;
digit *= 16;
digit += (data[i] >= 'A' ? ((data[i] & 0xdf) - 'A')+10 : (data[i] - '0'));
result[x++] = (digit ^ key[j]);
if (++j >= tkey) j=0; /* Boucle sur la cles */
}
if (strcasecmp(&data[tdata], int_to_hex(p, calcul_crc32(result), 8, NULL))) return(NULL); /* Erreur de CRC */
return(result); /* Retourne le resultat du decodage */
}
/*--------------------------------------------------------------------------*/
/* Fonction TRIM (elimine les caractere car devant et derriere) */
/*--------------------------------------------------------------------------*/
static char *trim(char *chaine, const char car)
{
char *ptr;
int x = -1;
if (chaine == NULL) return(NULL);
if (strlen(chaine) > 0)
{
while(chaine[++x] == car);
ptr = &chaine[x]; /* Recupere le debut de la chaine */
x = strlen(ptr);
while(ptr[--x] == car);
ptr[++x] = '\0'; /* Fin de chaine */
return(ptr); /* Retourne le pointeur vers la nouvelle chaine */
}
return(chaine);
}
/*--------------------------------------------------------------------------*/
/* Algorithme Soundex */
/*--------------------------------------------------------------------------*/
static char *calcul_soundex(pool *p, const char *chaine, int langue)
{
int i, small, len, code, last;
char *soundex;
char table_soundex[2][26] = {
{0, '1', '2', '3', 0, '9', '7', 0, 0, '7', '2', '4', '5', '5', 0, '1', '2', '6', '8', '3', 0, '9', 0, '8', 0, '8'}, /* Francais */
{0, '1', '2', '3', 0, '1', '2', 0, 0, '2', '2', '4', '5', '5', 0, '1', '2', '6', '2', '3', 0, '1', 0, '2', 0, '2'}, /* Anglais */
};
if (langue < 0 || langue > 1) langue = 0;
soundex = ap_palloc(p, 5); /* Alloue de la memoire pour le resultat */
len = strlen(chaine);
last = -1;
for (i = 0, small = 0; i < len && small < 4; i++)
{
code = chaine[i];
if (code == 224 || code == 225 || code == 226 || code == 227) code = 'A';
else if (code == 232 || code == 233 || code == 234 || code == 'e') code = 'E';
else if (code == 236 || code == 237 || code == 238) code = 'I';
else if (code == 242 || code == 243 || code == 244 || code == 245) code = 'O';
else if (code == 249 || code == 250 || code == 251) code = 'U';
else if (code == 231) code = 'C';
else if (code == 241) code = 'N';
else code = toupper(chaine[i]); /* Convertit en majuscule pour que les calculs soit correct */
if (code >= 'A' && code <= 'Z')
{
if (small == 0)
{
soundex[small++] = code;
last = table_soundex[langue][code - 'A'];
}
else
{
code = table_soundex[langue][code - 'A'];
if (code != last)
{
if (code != 0) soundex[small++] = code;
last = code;
}
}
}
}
while(small < 4) soundex[small++] = '0';
soundex[small] = '\0';
return(soundex);
}
/*--------------------------------------------------------------------------*/
/* 0 = Visa ; 1 = Mastercard ; 2 = American Express ; 3 = Novus */
/*--------------------------------------------------------------------------*/
static int verif_cb(pool *p, int type, const char *numero)
{
int cb[2][16],i=0,x=0;
char *nbr;
if (numero == NULL) return(FALSE);
i = -1;
while(numero[++i] != '\0' && x < 16 && i < 20)
{
if ((numero[i] >= '0') && (numero[i] <= '9'))
{
cb[0][x] = (int)numero[i] -48;
if ((cb[1][x] = cb[0][x] *2) > 9) cb[1][x] -= 9;
x++;
}
}
if (x == 13 && type == 0) i = cb[0][0] + cb[1][1] + cb[0][2] + cb[1][3] + cb[0][4] + cb[1][5] + cb[0][6] + cb[1][7] + cb[0][8] + cb[1][9] + cb[0][10] + cb[1][11] + cb[0][12];
else if (x == 16 && (type == 0 || type == 1 || type == 3)) i = cb[1][0] + cb[0][1] + cb[1][2] + cb[0][3] + cb[1][4] + cb[0][5] + cb[1][6] + cb[0][7] + cb[1][8] + cb[0][9] + cb[1][10] + cb[0][11] + cb[1][12] + cb[0][13] + cb[1][14] + cb[0][15];
else if (x == 15 && type == 2) i = cb[0][0] + cb[1][1] + cb[0][2] + cb[1][3] + cb[0][4] + cb[1][5] + cb[0][6] + cb[1][7] + cb[0][8] + cb[1][9] + cb[0][10] + cb[1][11] + cb[0][12] + cb[1][13] + cb[0][14];
else return(FALSE);
nbr = ap_psprintf(p, "%d", i);
if (nbr[1] == '0') return(TRUE);
return(FALSE);
}
/*--------------------------------------------------------------------------*/
/* ISEMAIL (verifie si la chaine est une adresse E-Mail */
/*--------------------------------------------------------------------------*/
static int isemail(const char *chaine)
{
register int x;
if (chaine == NULL) return(FALSE);
x = strlen(chaine) - 1;
if (x < 5) return(FALSE); /* 6-1 est la plus petite adresse possible */
if (strchr(chaine, '@') == NULL) return(FALSE); /* Il faut obligatoirement un '@' */
if (chaine[x] == '@' || chaine[x] < 65 || chaine[0] < 48 || (chaine[0] > 57 && chaine[0] < 65)) return(FALSE); /* Il ne peut pas y avoir un de ces caractere a la fin et au debut */
if (strchr(strchr(chaine, '@'), '.') == NULL) return(FALSE); /* Il faut qu'il y est au moins un '.' derriere le '@' */
return(TRUE);
}
/*--------------------------------------------------------------------------*/
/* Fonction ifvide */
/* Renvoi TRUE si la chaine est vide et FALSE sinon */
/*--------------------------------------------------------------------------*/
static int ifvide(const char *chaine)
{
register x = -1;
if (chaine == NULL) return(TRUE);
while(chaine[++x] != '\0')
{
if (chaine[x] > 32) return(FALSE); /* A trouve des caractere valides */
}
return(TRUE);
}
/*--------------------------------------------------------------------------*/
/* Renvoi le numero du jour de l'annee */
/*--------------------------------------------------------------------------*/
static int jour_annee(int jour, int mois, int annee)
{
int v, w;
v = annee_bissex(annee);
for (w = 1; w < mois; w++) jour += jour_dans_mois[v][w];
return(jour); /* Retourne le numero du jour de l'annee */
}
/*--------------------------------------------------------------------------*/
/* Renvoi le numero du jour de la semaine (dimanche = 1, lundi = 2, etc... */
/*--------------------------------------------------------------------------*/
static int jour_semaine(int jour, int mois, int annee)
{
long temp;
int resultat;
temp = (long)(annee - 1) * 365 + nombre_annee_bissex(annee - 1) + jour_annee(jour, mois, annee);
if (temp < FIRST_MISSING_DAY) resultat = (temp -1 + SAMEDI) % 7;
else if (temp >= (FIRST_MISSING_DAY + NUMBER_MISSING_DAYS)) resultat = ((temp - 1 + SAMEDI) - NUMBER_MISSING_DAYS) % 7;
else resultat = JEUDI;
return (resultat);
}
/*--------------------------------------------------------------------------*/
/* Renvoi FALSE (0) si la chaine ne peut pas etre une valeur numerique */
/* Renvoi TRUE (1) si la chaine est conforme au type numerique (double) */
/*--------------------------------------------------------------------------*/
static int isnum(const char *chaine)
{
int x = -1, deb = FALSE, signe = FALSE, fin = FALSE, virg = FALSE, expo = FALSE, expsi = FALSE, chif = FALSE;
while (chaine[++x] != '\0')
{
if (deb)
{
if (!fin)
{
if (chaine[x] < 33 || chaine[x] == 127) fin = TRUE;
else if (chaine[x] == ',' || chaine[x] == '.')
{
if (!virg && !expo && isdigit(chaine[x-1])) virg = TRUE;
else return(FALSE);
}
else if (chaine[x] == '+' || chaine[x] == '-')
{
if (!expo) return(FALSE);
else if (!expsi && (chaine[x-1] == 'e' || chaine[x-1] == 'E')) expsi = TRUE;
else return(FALSE);
}
else if (chaine[x] == 'e' || chaine[x] == 'E')
{
if (!expo && isdigit(chaine[x-1])) expo = TRUE;
else return(FALSE);
}
else if (!isdigit((int)chaine[x])) return(FALSE);
else chif = TRUE;
}
else if (chaine[x] > 32 && chaine[x] != 127) return(FALSE);
}
else if (chaine[x] == '+' || chaine[x] == '-') deb = signe = TRUE;
else if (chaine[x] > 32 && chaine[x] != 127)
{
if (!isdigit((int)chaine[x])) return(FALSE);
deb = chif = TRUE;
}
}
if (!chif) return(FALSE);
return(TRUE);
}
/*--------------------------------------------------------------------------*/
/* Val = valeur numerique a convertir (32 bits maximum en unsigned) */
/* Digit = nbr de digit pour le retour (entre 0 et 8 maximum) */
/* Renvoi dans Chaine la valeur en Hexa qui ne depassera pas */
/* le nombre de digit prevu */
/* Si result != NULL, alors ce sert de cette variable pour le calcul */
/*--------------------------------------------------------------------------*/
static char *int_to_hex(pool *p, long unsigned int val, int digit, char *result)
{
const unsigned char hexa[] = "0123456789ABCDEF";
int i=0,j=0;
long unsigned int quot, quot1, reste;
char *temp;
if (result == NULL) temp = ap_palloc(p, 9 * sizeof(char)); /* Alloue un emplacement memoire pour le resultat */
else temp = result;
quot1 = val;
for (i = 7; i>=0; i--)
{
quot = quot1 / 16;
reste = quot1 - (quot*16);
temp[i] = hexa[reste];
quot1 = quot;
if (j == 0 && quot <= 0) j = i;
}
temp[8] = '\0';
if (digit > 0 && digit < 9) return(&temp[8-digit]);
return(&temp[j]);
}
/*--------------------------------------------------------------------------*/
/* ListFields */
/*--------------------------------------------------------------------------*/
static int md_mysql_listfields(adml_mysql *base_mysql, const char *ftable, const char *wild)
{
if (!base_mysql->fconnect) return(FALSE);
base_mysql->fquery = base_mysql->ferror = FALSE;
if ((base_mysql->res = mysql_list_fields(&base_mysql->mysql, ftable, wild)))
{
base_mysql->row = mysql_fetch_row(base_mysql->res);
base_mysql->numligne = base_mysql->numcolonne = 0;
return(base_mysql->fquery = TRUE);
}
return(FALSE);
}
/*--------------------------------------------------------------------------*/
/* ListTables */
/*--------------------------------------------------------------------------*/
static int md_mysql_listtables(adml_mysql *base_mysql, const char *wild)
{
if (!base_mysql->fconnect) return(FALSE);
base_mysql->fquery = base_mysql->ferror = FALSE;
if ((base_mysql->res = mysql_list_tables(&base_mysql->mysql, wild)))
{
base_mysql->row = mysql_fetch_row(base_mysql->res);
base_mysql->numligne = base_mysql->numcolonne = 0;
return(base_mysql->fquery = TRUE);
}
return(FALSE);
}
/*--------------------------------------------------------------------------*/
/* ListDbs */
/*--------------------------------------------------------------------------*/
static int md_mysql_listdbs(adml_mysql *base_mysql, const char *wild)
{
if (!base_mysql->fconnect) return(FALSE);
base_mysql->fquery = base_mysql->ferror = FALSE;
if ((base_mysql->res = mysql_list_dbs(&base_mysql->mysql, wild)))
{
base_mysql->row = mysql_fetch_row(base_mysql->res);
base_mysql->numligne = base_mysql->numcolonne = 0;
return(base_mysql->fquery = TRUE);
}
return(FALSE);
}
/*--------------------------------------------------------------------------*/
/* FreeResult */
/*--------------------------------------------------------------------------*/
static void md_mysql_freeresult(adml_mysql *base_mysql)
{
if (base_mysql->fconnect) return;
base_mysql->fquery = base_mysql->ferror = FALSE;
mysql_free_result(base_mysql->res);
}
/*--------------------------------------------------------------------------*/
/* Recharge la table des utilisateurs (Grants) */
/*--------------------------------------------------------------------------*/
static int md_mysql_reload(adml_mysql *base_mysql)
{
if (base_mysql->fconnect)
{
if (mysql_reload(&base_mysql->mysql) == 0) return(TRUE);
}
base_mysql->ferror = TRUE;
return(FALSE);
}
/*--------------------------------------------------------------------------*/
/* AddDataSeek */
/*--------------------------------------------------------------------------*/
static int md_mysql_add_dataseek(adml_mysql *base_mysql, int num)
{
int x;
x = base_mysql->numligne; /* Sauvegarde la position actuelle */
base_mysql->numligne += num;
if ((base_mysql->numligne >= 0) && (base_mysql->numligne < mysql_num_rows(base_mysql->res)))
{
/*
if ((base_mysql->row = mysql_fetch_row(base_mysql->res))) return(TRUE);
*/
mysql_data_seek(base_mysql->res, base_mysql->numligne);
base_mysql->row = mysql_fetch_row(base_mysql->res);
return(TRUE);
}
base_mysql->numligne = x;
return(FALSE);
}
/*--------------------------------------------------------------------------*/
/* AddFieldSeek */
/*--------------------------------------------------------------------------*/
static int md_mysql_add_fieldseek(adml_mysql *base_mysql, int num)
{
int x;
x = base_mysql->numcolonne; /* Sauvegarde la position actuelle */
base_mysql->numcolonne += num;
if ((base_mysql->numcolonne >= 0) && (base_mysql->numcolonne < mysql_num_fields(base_mysql->res)))
{
/*
if ((base_mysql->row = mysql_fetch_row(base_mysql->res))) return(TRUE);
*/
mysql_field_seek(base_mysql->res, base_mysql->numcolonne);
return(TRUE);
}
base_mysql->numcolonne = x;
return(FALSE);
}
/*--------------------------------------------------------------------------*/
/* Recupere la liste des processus lance sur le serveur */
/*--------------------------------------------------------------------------*/
static int md_mysql_processes(adml_mysql *base_mysql)
{
if (!base_mysql->fconnect) return(FALSE);
if ((base_mysql->res = mysql_list_processes(&base_mysql->mysql)))
{
base_mysql->row = mysql_fetch_row(base_mysql->res);
base_mysql->numligne = base_mysql->numcolonne = 0;
base_mysql->ferror = FALSE;
return(base_mysql->fquery = TRUE);
}
base_mysql->ferror = TRUE;
return(base_mysql->fquery = FALSE);
}
/*--------------------------------------------------------------------------*/
/* DataSeek */
/*--------------------------------------------------------------------------*/
static int md_mysql_dataseek(adml_mysql *base_mysql, uint offset)
{
if (!base_mysql->fquery) return(FALSE);
if (offset >= 0 && offset < mysql_num_rows(base_mysql->res))
{
mysql_data_seek(base_mysql->res, offset);
base_mysql->row = mysql_fetch_row(base_mysql->res);
base_mysql->numligne = offset;
base_mysql->numcolonne = 0;
return(TRUE);
}
else base_mysql->numligne = mysql_num_rows(base_mysql->res);
return(FALSE);
}
/*--------------------------------------------------------------------------*/
/* FieldSeek */
/*--------------------------------------------------------------------------*/
static int md_mysql_fieldseek(adml_mysql *base_mysql, int numfield)
{
if (!base_mysql->fquery) return(FALSE);
if (numfield >= 0 && numfield < mysql_num_fields(base_mysql->res))
{
mysql_field_seek(base_mysql->res, numfield);
base_mysql->field = mysql_fetch_field(base_mysql->res);
base_mysql->numcolonne = numfield;
return(TRUE);
}
else base_mysql->numcolonne = mysql_num_fields(base_mysql->res);
return(FALSE);
}
/*--------------------------------------------------------------------------*/
/* envoi le nombre de Rows de la requete */
/*--------------------------------------------------------------------------*/
static int md_mysql_nbrfields(adml_mysql *base_mysql)
{
if (!base_mysql->fquery) return(0);
return(mysql_num_fields(base_mysql->res));
}
/*--------------------------------------------------------------------------*/
/* envoi le nombre de Rows de la requete */
/*--------------------------------------------------------------------------*/
static int md_mysql_nbrrows(adml_mysql *base_mysql)
{
if (!base_mysql->fquery) return(0);
return(mysql_num_rows(base_mysql->res));
}
/*--------------------------------------------------------------------------*/
/* Recuperation du message d'erreur s'il y en a un */
/*--------------------------------------------------------------------------*/
static char *md_mysql_error(adml_mysql *base_mysql)
{
if (base_mysql->ferror)
{
if (mysql_error(&base_mysql->mysql) == NULL) return(""); /* Il ne faut pas renvoyer un NULL */
else return(mysql_error(&base_mysql->mysql));
}
else return(""); /* Renvoi une chaine vide s'il n'y a pas d'erreur */
}
/*--------------------------------------------------------------------------*/
/* Deconnection a une base de donnees Mysql */
/*--------------------------------------------------------------------------*/
static void md_mysql_close(adml_mysql *base_mysql)
{
if (base_mysql->fconnect) mysql_close(&base_mysql->mysql);
base_mysql->fconnect = base_mysql->fbase = base_mysql->fquery = base_mysql->ferror = FALSE;
}
/*--------------------------------------------------------------------------*/
/* Connection a une base de donnees Mysql */
/*--------------------------------------------------------------------------*/
static int md_mysql_connect(adml_mysql *base_mysql, const char *host, const char *login, const char *passwd)
{
md_mysql_close(base_mysql); /* Fermeture au cas ou */
if (!(mysql_connect(&base_mysql->mysql, host, login, passwd))) base_mysql->ferror = TRUE;
else base_mysql->fconnect = TRUE;
return(base_mysql->fconnect);
}
/*--------------------------------------------------------------------------*/
/* Selection d'une base de donnees Mysql */
/*--------------------------------------------------------------------------*/
static int md_mysql_select(adml_mysql *base_mysql, const char *base)
{
const char *labase;
base_mysql->fquery = base_mysql->ferror = FALSE;
if (!base_mysql->fconnect) return(FALSE);
if (base == NULL) labase = "";
else labase = base;
if (mysql_select_db(&base_mysql->mysql, labase))
{
base_mysql->ferror = TRUE;
return(base_mysql->fbase = FALSE);
}
return(base_mysql->fbase = TRUE);
}
/*--------------------------------------------------------------------------*/
/* Lance une requete SQL */
/*--------------------------------------------------------------------------*/
static int md_mysql_query(adml_mysql *base_mysql, const char *req)
{
const char *lareq;
base_mysql->fquery = FALSE;
if (!base_mysql->fconnect) return(base_mysql->ferror = FALSE);
else base_mysql->ferror = TRUE;
if (req == NULL) lareq = "";
else lareq = req;
if (!mysql_query(&base_mysql->mysql, lareq))
{
if (strstr(lareq, "INSERT") || strstr(lareq, "UPDATE") || strstr(lareq, "DELETE"))
{
base_mysql->ferror = FALSE;
return(TRUE); // Ne positionne pas le fquery afin de ne pas pouvoir visualiser le nombre de Rows, etc... */
}
base_mysql->res = mysql_store_result(&base_mysql->mysql);
if (base_mysql->res)
{
base_mysql->row = mysql_fetch_row(base_mysql->res);
base_mysql->numligne = 0; // Se positionne sur la premiere ligne
base_mysql->numcolonne = 0; // et sur la premiere colonne
base_mysql->ferror = FALSE;
return(base_mysql->fquery = TRUE);
}
}
return(FALSE);
}
/*--------------------------------------------------------------------------*/
/* Execution des fonctions */
/*--------------------------------------------------------------------------*/
static char *exec_fonction(adml_cfg *conf, const char *chaine1, const char *chaine2)
{
#define N_TAG_PARAM 25
char *ch1, *ch2, *param[N_TAG_PARAM], *ptr, *temp;
unsigned char car;
int x=-1, y, z, w, v, i, pos=0, nparam=0, flag;
array_header *arr;
table_entry *elts;
struct tm *temps;
div_t divis;
time_t timestamp;
unsigned char tr[256];
struct in_addr addr;
ch1 = (chaine1 != NULL) ? interp(conf ,chaine1) : ""; /* Interpretation */
param[0] = "";
while(ch1[++x] != '\0' && nparam < 20)
{
if (nparam > 0)
{
if (ch1[x] == ',' || ch1[x] == ')')
{
if (x - pos > 0) param[nparam] = ap_pstrndup(conf->pool_tag,&ch1[pos],x-pos);
else param[nparam] = "";
if (ch1[x] == ')') break;
pos = x+1;
nparam++;
}
}
else if (ch1[x] == '(')
{
param[nparam++] = ap_pstrndup(conf->pool_tag,ch1,x); /* Recupere le nom de la fonction */
pos = x+1;
}
}
if (nparam < 1) param[0] = ch1; /* Recupere le nom de la fonction (dans le cas ou il n'y a pas de parametre) */
if (chaine2 == NULL) ch2 = ""; /* Chaine vide */
else
{
if (strcasecmp(param[0], "nointerp")) ch2 = interp(conf ,chaine2); /* Interprete si ce n'est pas la fonction NOINTERP */
else ch2 = ap_pstrdup(conf->pool_tag, chaine2); /* N'interprete pas */
}
ch1 = "";
pos = 0; v = 0; w = 0; x = 0; y = 0; z = 0;
flag = FALSE;
/*---------------------------------------------------------------------*/
/* NOINTERP */
/*---------------------------------------------------------------------*/
if (!strcasecmp(param[0],"nointerp"))
{
ch1 = ch2; /* Pas d'interpretation */
}
/*---------------------------------------------------------------------*/
/* CONV... */
/*---------------------------------------------------------------------*/
#define TAILLE_SUP_CONV 128
#define TAILLE_LINK_MAX 100
else if (!strncasecmp(param[0],"conv",4) || !strncasecmp(param[0], "link", 4) || !strncasecmp(param[0], "upper", 5) || !strncasecmp(param[0], "strupper", 8) || !strncasecmp(param[0], "strlower", 8)
|| !strncasecmp(param[0], "lower", 5) || !strncasecmp(param[0], "encod", 5) || !strcasecmp(param[0], "html") || !strcasecmp(param[0], "br")
|| !strcasecmp(param[0], "notag") || !strcasecmp(param[0], "eschtml") || !strcasecmp(param[0], "nohtml") || !strncasecmp(param[0], "mysqlesc", 8)
|| !strcasecmp(param[0], "escmysql") || !strcasecmp(param[0], "nospc") || !strncasecmp(param[0], "testli", 6))
{
ptr = NULL;
if (!strncasecmp(param[0], "link", 4) || !strncasecmp(param[0], "testli", 6))
{
if (nparam > 0) ptr = param[1];
if (!strncasecmp(param[0], "testli", 6)) v = 8192; /* TESTLI... */
else v = 1; /* LINK */
}
else
{
v = 0;
for (x = 0; x <=nparam; x++)
{
if (!(v&1) && (!strncasecmp(param[x], "link", 4))) v += 1;
else if (!(v&2) && (!strncasecmp(param[x], "upper", 5) || !strncasecmp(param[x], "strupper", 8))) v += 2;
else if (!(v&4) && (!strncasecmp(param[x], "lower", 5) || !strncasecmp(param[x], "strlower", 8))) v += 4;
else if (!(v&8) && !strncasecmp(param[x], "encod", 5)) v += 8;
else if (!(v&16) && !strcasecmp(param[x], "html")) v += 16;
else if (!(v&32) && !strcasecmp(param[x], "br")) v += 32;
else if (!(v&64) && (!strcasecmp(param[x], "notag") || !strcasecmp(param[x], "nohtml") || !strcasecmp(param[x], "eschtml"))) v += 64;
else if (!(v&128) && (!strncasecmp(param[x], "mysqlesc", 8) || !strcasecmp(param[x], "escmysql"))) v += 128;
else if (!(v&256) && !strcasecmp(param[x], "trim")) v += 256;
else if (!(v&512) && !strcasecmp(param[x], "nospc")) v += 512;
else if (!(v&8192) && !strncasecmp(param[x], "testli", 6)) v += 8192;
else if (!(v&1024) && !(v&2048) && !(v&4096))
{
if (!(v&1024) && !strcasecmp(param[x], "targtop"))
{
ptr = "_top";
v += 1024;
}
else if (!(v&2048) && !strcasecmp(param[x], "targparent"))
{
ptr = "_parent";
v += 2048;
}
else if (!(v&4096) && (!strcasecmp(param[x], "targblank") || !strcasecmp(param[x], "targnew")))
{
ptr = "_blank";
v += 4096;
}
}
}
}
if (v&2 && v&4) v -= 6; /* Supprime MAJ et MIN s'il sont tous les deux actifs */
ch1 = ap_palloc(conf->pool_tag, sizeof(char) * (y = (x = strlen(ch2)) + TAILLE_SUP_CONV)); /* Calcul la taille de ch2 (x) et alloue une zone memoire de depart (y) */
for (pos = 0, w = 0; pos < x; pos++) /* Parcour la chaine ch2 */
{
/* ---------- NOSPC et le cotes gauche de TRIM ---------- */
if ((!(v&512) || ch2[pos] != ' ') && (!(v&256) || ch2[pos] != ' ' || flag))
{
flag = TRUE;
/* ---------- BR ---------- */
if ((v&32) && !(v&8) && (ch2[pos] == '\n' || ch2[pos] == '\r'))
{
if (ch2[pos] == '\n')
{
strcpy(&ch1[w], "<BR>");
w +=4;
}
}
/* ---------- LINK... ---------- */
else if (((v&1) || (v&8192)) && !(v&8) && (!strncasecmp(&ch2[pos], "http://", 7) || !strncasecmp(&ch2[pos], "mailto:", 7)))
{
z = pos + 6; /* saute l'entete http:// ou mailto: */
while((car = ch2[++z]) != '\0' && (unsigned char)car > 44 && car != ';' && (z < pos + TAILLE_LINK_MAX));
if (z < (pos + TAILLE_LINK_MAX)) /* Verifie si le lien n'est pas trop long */
{
if (!(v&8192) || strncasecmp(&ch2[pos], "mailto:", 7) || isemail(ap_pstrndup(conf->pool_tag, &ch2[pos+7], z - pos - 7))) /* Verifie si l'email a une syntaxe correct si TESTLINK */
{
if (ptr != NULL) i = strlen(ptr); /* Recupere la taille du target */
else i = 0; /* Pas de target */
if (w + ((z - pos) * 2) + 40 + i > y) /* Realloue un nouvel emplacement memoire plus grand */
{
conf->temp = ap_palloc(conf->pool_tag, sizeof(char) * (y += TAILLE_SUP_CONV + ((z - pos) * 2) + 40));
memcpy(conf->temp, ch1, w); /* recopie la chaine */
ch1 = conf->temp;
}
strcpy(&ch1[w], "<A ");
w += 3;
if (ptr != NULL) /* Si il y a un target */
{
strcpy(&ch1[w], "TARGET=\"");
w += 8;
strcpy(&ch1[w], ptr); /* Place le nom du target */
w += i;
strcpy(&ch1[w], "\" ");
w += 2;
}
i = z - pos; /* Calcul la taille */
strcpy(&ch1[w], "HREF=\"");
w += 6;
strncpy(&ch1[w], ap_pstrndup(conf->pool_tag, &ch2[pos], i), i);
w += i;
strcpy(&ch1[w], "\">");
w += 2;
if (!strncasecmp(&ch2[pos], "mailto:", 7))
{
i -= 7; /* Retire le mailto: */
strncpy(&ch1[w], &ch2[pos + 7], i);
}
else strncpy(&ch1[w], &ch2[pos], i);
w += i;
strcpy(&ch1[w], "</A>");
w += 4;
pos = z - 1; /* Nouvelle position */
}
else goto CONV_GOTO; /* Finalement, ce n'est pas un lien */
}
else goto CONV_GOTO; /* Finalement, ce n'est pas un lien */
}
else
{
CONV_GOTO:
/* ---------- UPPER... ---------- */
if (v&2 && islower(ch2[pos]))
{
ch2[pos] = toupper(ch2[pos]);
}
/* ---------- LOWER... ---------- */
else if (v&4 && isupper(ch2[pos]))
{
ch2[pos] = tolower(ch2[pos]);
}
if ((v&8) || (v&128))
{
/* ---------- ENCODED... ---------- */
if (v&8 && (ch2[pos] == '\'' || ch2[pos] == '\0' || ch2[pos] == ' ' || ch2[pos] == '|' || ch2[pos] == '=' || ch2[pos] == '+' || ch2[pos] == '&' || ch2[pos] == '\n' || ch2[pos] == '\r' || ch2[pos] == '%' || ch2[pos] == '\\' || ch2[pos] == '/' || ch2[pos] == '?'))
{
if (ch2[pos] == ' ') ch1[w++] = '+';
else if (ch2[pos] == '\'') ch1[w++] = ch2[pos]; /* Recopie le caractere sans traitement */
else
{
ch1[w++] = '%';
divis = div((unsigned int)ch2[pos], 16);
ch1[w++] = hexa[divis.quot];
ch1[w++] = hexa[divis.rem];
}
}
/* ---------- MYSQLESC ou ESCMYSQL ---------- */
else if (ch2[pos] == '\0' || ch2[pos] == '\n' || ch2[pos] == '\r' || ch2[pos] == '\\' || ch2[pos] == '\'')
{
ch1[w++] = '\\';
if (ch2[pos] == '\0') ch1[w++] = '0';
else if (ch2[pos] == '\n') ch1[w++] = 'n';
else if (ch2[pos] == '\r') ch1[w++] = 'r';
else if (ch2[pos] == '\\') ch1[w++] = '\\';
else if (ch2[pos] == '\'') ch1[w++] = '\'';
}
/* ---------- Recopie le caractere sans traitement ---------- */
else ch1[w++] = ch2[pos];
}
else
{
/* ---------- NOTAG ou ESCHTML ---------- */
if (v&64 && (ch2[pos] == '<' || ch2[pos] == '>' || ch2[pos] == '&' || ch2[pos] == '\"'))
{
if (ch2[pos] == '<')
{
strcpy(&ch1[w], "<");
w += 4;
}
else if (ch2[pos] == '>')
{
strcpy(&ch1[w], ">");
w += 4;
}
else if (ch2[pos] == '&')
{
strcpy(&ch1[w], "&");
w += 5;
}
else if (ch2[pos] == '\"')
{
strcpy(&ch1[w], """);
w += 6;
}
}
/* ---------- HTML... ---------- */
else if (v&16)
{
if ((unsigned char)ch2[pos] >= 160 && (unsigned char)ch2[pos] < 256)
{
z = (unsigned char)ch2[pos];
ch1[w++] = '&';
strcpy(&ch1[w], code_html[z - 160]);
w += strlen(code_html[z - 160]);
ch1[w++] = ';';
}
else if (ch2[pos] == '&')
{
strcpy(&ch1[w], "&");
w += 5;
}
else ch1[w++] = ch2[pos]; /* Recopie le caractere sans traitement */
}
/* ---------- Recopie le caractere sans traitement ---------- */
else ch1[w++] = ch2[pos];
}
}
}
if (w + 15 > y) /* Realloue un nouvel emplacement memoire plus grand */
{
conf->temp = ap_palloc(conf->pool_tag, sizeof(char) * (y += TAILLE_SUP_CONV));
memcpy(conf->temp, ch1, w); /* recopie la chaine */
ch1 = conf->temp;
}
}
/* ---------- TRIM partie droite ---------- */
if (v&256)
{
while(ch1[--w] == ' '); /* Retire les espaces en fin de chaine */
w++;
}
ch1[w] = '\0'; /* Place le fin de chaine */
}
/*---------------------------------------------------------------------*/
/* TRIM...(car) */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0],"trim"))
{
if (nparam > 0) car = param[1][0];
else car = ' '; /* Par defaut */
ch1 = trim(ch2, car);
}
/*---------------------------------------------------------------------*/
/* BOOL... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0],"bool",4))
{
if (!strcasecmp(ch2, "true")) ch1 = "1"; /* TRUE */
else ch1 = "0"; /* FALSE */
}
/*---------------------------------------------------------------------*/
/* TRUE */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0],"true")) ch1 = "1";
/*---------------------------------------------------------------------*/
/* FALSE */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0],"false")) ch1 = "0";
/*---------------------------------------------------------------------*/
/* UUENCOD... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0],"uuencod", 7)) ch1 = ap_uuencode(conf->pool_tag, ch2);
/*---------------------------------------------------------------------*/
/* UUDECOD... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0],"uudecod", 7)) ch1 = ap_uudecode(conf->pool_tag, ch2);
/*---------------------------------------------------------------------*/
/* WORD...(n,n,n) et QWORD...(n,n,n) */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "word", 4) || !strncasecmp(param[0], "qword", 5))
{
if (nparam > 0) y = atoi(param[1]); /* Numero du mot a recuperer */
if (nparam > 1) w = atoi(param[2]); /* Taille minimum du mot */
if (nparam > 2) v = atoi(param[3]); /* Taille maximum du mot */
if (!strncasecmp(param[0], "q", 1)) flag = TRUE; /* S'il faut prendre en compte les guillemets */
if ((temp = (char *)recupmots(conf->pool_tag, ch2, y, w, v, flag, 0, NULL)) != NULL) ch1 = temp;
}
/*---------------------------------------------------------------------*/
/* ELT(x,x,...),n
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0],"elt"))
{
if (nparam > 0)
{
x = atoi(ch2) + 1;
if (x < 1 || x > nparam) x = 1; /* Verifie que l'on ne soit pas hors-zone */
ch1 = param[x]; // Sort l'element selectionne
}
else
{
/* WARNING: aucun parametre a la fonction */
}
}
/*---------------------------------------------------------------------*/
/* NUM(precision,largeur,type) et CALC(precision,largeur,type) */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0],"num") || !strcasecmp(param[0], "calc"))
{
if (nparam > 2)
{
if (strcmp(param[3], "-") && strcmp(param[3], "+") && strcmp(param[3], "0")) param[3] = "0";
}
else param[3] = "0";
if (nparam > 1) x = atoi(param[2]); /* Largeur */
else x = 0;
if (nparam > 0) z = atoi(param[1]); /* Precision (nombre de decimal) */
else z = 6;
ch1 = ap_psprintf(conf->pool_tag, "%%%s%d.%dlf", param[3], x, z);
if (!strcasecmp(param[0], "num")) /* Fonction NUM */
{
if ((ptr = strchr(ch2, ',')) != NULL) ptr[0] = '.'; /* Remplacer la virgule par un point pour que atof() convertisse correctement */
ch1 = ap_psprintf(conf->pool_tag, ch1, atof(ch2));
if (ptr != NULL) ptr[0] = ','; /* Remettre la virgule */
}
else /* Fonction CALC */
{
ch1 = ap_psprintf(conf->pool_tag, ch1, calc(conf, ch2));
}
}
/*---------------------------------------------------------------------*/
/* RIGHT(n,n) et LEFT(n,n) */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0],"right") || !strcasecmp(param[0],"left"))
{
if (nparam > 0) /* Il faut au moins 1 parametre */
{
v = strlen(ch2); /* Recupere la taille de la chaine a traiter */
w = (!strcmp(param[1],"*")) ? v : atoi(param[1]); /* Recupere le premier parametre (le nombre de caracteres a prendre) */
if (w < 0) w = 0; /* Interdit les valeurs negatives */
if (nparam > 1) x = atoi(param[2]); /* Recupere le 2eme parametre (le debut a partir du bord) */
x = (x < 0) ? 0 : x; /* Interdit d'etre en negatif */
if (x < v) /* Si le 2eme parametre ne depasse pas la taille de la chaine */
{
if (w > v - x) w = v-x; /* verifie que la longueur ne soit pas trop longue */
if ((!strcasecmp(param[0], "right")) && x > 0) x = v -x -w;
ch1 = ap_pstrndup(conf->pool_tag, &ch2[x], w); /* Recopie le nombre de caracteres demande */
}
}
else ch1 = ch2; /* Recopie la chaine dans son integralite */
}
/*---------------------------------------------------------------------*/
/* HOSTTOIP */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "hosttoip"))
{
if ((long)(addr.s_addr = get_ip(ch2)) > 0) ch1 = inet_ntoa(addr);
}
/*---------------------------------------------------------------------*/
/* SERVICETOPORT */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "servicetoport"))
{
if ((x = get_port(ch2)) > 0) ch1 = ap_psprintf(conf->pool_tag, "%d", ntohs(x));
}
/*---------------------------------------------------------------------*/
/* SOCK... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "sock", 4))
{
x = (nparam > 0) ? atoi(param[1]) : 0; /* numero de structure */
if (x >= 0 && x < N_SOCKET)
{
if (!strncasecmp(param[0], "sock", 4))
{
if (!strcasecmp(ch2, "buffer")) ch1 = ap_pstrdup(conf->pool_tag, conf->sock[x].buffer);
else if (!strncasecmp(ch2, "bufferlen", 9)) ch1 = ap_psprintf(conf->pool_tag, "%d", conf->sock[x].taille_buffer); /* Taille des donnees contenu dans le buffer de la socket */
}
}
}
/*---------------------------------------------------------------------*/
/* UPLOAD... et ISUPLOAD... et IFUPLOAD... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "isupload", 8) || !strncasecmp(param[0], "ifupload", 8) || !strncasecmp(param[0], "upload", 6))
{
v = (nparam > 0) ? atoi(param[1]) : 0;
z = -1;
if (ch2[0] == '_')
{
if (!strcasecmp(ch2, "_nbr")) ch1 = ap_psprintf(conf->pool_tag, "%d", conf->nupload); /* Nombre de champ upload */
else if (!strncasecmp(ch2, "_pos", 4)) ch1 = ap_psprintf(conf->pool_tag, "%d", conf->upload_num); /* Position courante */
}
else
{
if (ch2[0] != '#') /* Recherche en nom */
{
for(y=0, w=0; y < conf->nupload; y++)
{
if (!ap_strcmp_match(conf->upload[y].name, ch2))
{
if (w++ >= v) /* Pour le nbr de champ */
{
z = y;
break;
}
}
}
}
else if (!strcmp(ch2, "#")) /* Position courante */
{
if (conf->upload_num >= 0 && conf->upload_num < conf->nupload) z = conf->upload_num; /* Trouver */
}
else if (isnum(&ch2[1]) && strlen(&ch2[1]) > 0) /* Recherche avec le numero du champ */
{
i = atoi(&ch2[1]);
if (i >= 0 && i < conf->nupload) z = i; /* Trouver */
}
if (z < 0)
{
if (!strncasecmp(param[0], "i", 1)) ch1 = "0"; /* Pour le ISUPLOAD */
}
else
{
if (!strncasecmp(param[0], "i", 1)) /* Pour le ISUPLOAD */
{
if (!strncasecmp(¶m[0][8], "sav", 3))
{
if (!conf->upload[z].save) ch1 = "0"; /* L'upload n'a pas encore ete sauvegarde */
else ch1 = "1"; /* Upload sauvegarder */
}
else ch1 = "1";
}
else if (!strncasecmp(¶m[0][6], "nam", 3) || !strcasecmp(¶m[0][6], "nom")) ch1 = conf->upload[z].name; /* Renvoi le nom du champ upload */
else if (!strncasecmp(¶m[0][6], "file", 4) || !strncasecmp(¶m[0][6], "fic", 3)) ch1 = conf->upload[z].filename; /* Renvoi le nom du fichier */
else if (!strncasecmp(¶m[0][6], "rfile", 5) || !strncasecmp(¶m[0][6], "rfic", 4)) ch1 = conf->upload[z].remote_filename; /* Renvoi le chemin complet du fichier sur la machine remote */
else if (!strncasecmp(¶m[0][6], "typ", 3)) ch1 = conf->upload[z].content_type; /* Renvoi le type des donnees du champ upload */
else if (!strncasecmp(¶m[0][6], "len", 3) || !strncasecmp(¶m[0][6], "taille", 6)) ch1 = ap_psprintf(conf->pool_tag, "%lu", conf->upload[z].taille); /* Renvoi la taille des donnees du champ upload */
else if (!strncasecmp(¶m[0][6], "val", 3)) ch1 = conf->upload[z].data; /* Renvoi les donnees du champ upload */
else if (!strncasecmp(¶m[0][6], "pos", 3)) ch1 = ap_psprintf(conf->pool_tag, "%d", z); /* Renvoi la position du champ upload */
else if (!strncasecmp(¶m[0][6], "ext", 3))
{
if ((temp = strrchr(conf->upload[z].filename, '.')) != NULL) ch1 = ap_pstrdup(conf->pool_tag, temp); /* Retourne l'extension du fichier s'il y en a un */
}
else if (!strncasecmp(¶m[0][6], "sav", 3)) /* renvoi le nom du fichier sauvegarde si l'upload a ete sauver */
{
if (conf->upload[z].save) ch1 = conf->upload[z].save;
}
}
}
}
/*---------------------------------------------------------------------*/
/* HEADER... et ISHEADER... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "isheader", 8) || !strncasecmp(param[0], "ifheader", 8) || !strncasecmp(param[0], "header", 6))
{
v = (nparam > 0) ? atoi(param[1]) : 1;
if (!strncasecmp(param[0], "headerauth", 10) || !strncasecmp(param[0], "isheaderauth", 12) || !strncasecmp(param[0], "ifheaderauth", 12))
{
if (conf->auth_user != NULL)
{
if (!strncasecmp(param[0], "i", 1)) ch1 = "1"; /* Oui, il y a un element d'entete Authorization: */
else if (!strncasecmp(ch2, "user", 4) || !strcasecmp(ch2, "name")) ch1 = ap_pstrdup(conf->pool_tag, conf->auth_user); /* Le USER */
else if (!strncasecmp(ch2, "pass", 4)) ch1 = ap_pstrdup(conf->pool_tag, conf->auth_passwd); /* Le PASSWORD */
else if (!strcasecmp(ch2, "type")) ch1 = ap_pstrdup(conf->pool_tag, conf->auth_type); /* Le TYPE d'authentification */
}
else if (tolower(param[0][0]) == 'i') ch1 = "0"; /* si le nom de la commande commence par un i (pour is ou if) */
}
else
{
if (tolower(param[0][0]) == 'i') i = 1; /* Pour le ISHEADER ou IFHEADER */
else if (!strncasecmp(param[0], "headernam", 9)) i = 2; /* nom du champ */
else if (!strncasecmp(param[0], "headerlen", 9)) i = 3; /* taille du champ */
else if (!strncasecmp(param[0], "headerpos", 9)) i = 4; /* position du champ dans la table */
else i = 0;
ch1 = cherche_table(conf, conf->r->headers_in, conf->headers_in_num, v, ch2, i, TRUE);
}
}
/*---------------------------------------------------------------------*/
/* COOKIE... et ISCOOKIE... */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "iscookie") || !strcasecmp(param[0], "ifcookie") || !strncasecmp(param[0], "cookie", 6))
{
v = (nparam > 0) ? atoi(param[1]) : 1;
if (!strncasecmp(param[0], "i", 1)) i = 1; /* Pour le ISCOOKIE ou IFCOOKIE */
else if (!strncasecmp(param[0], "cookienam", 9)) i = 2; /* nom du champ */
else if (!strncasecmp(param[0], "cookielen", 9)) i = 3; /* taille du champ */
else if (!strncasecmp(param[0], "cookiepos", 9)) i = 4; /* position du champ dans la table */
else i = 0;
ch1 = cherche_table(conf, conf->cookies.tab, conf->cookies.pos, v, ch2, i, FALSE);
}
/*---------------------------------------------------------------------*/
/* FORM... et ISFORM... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "isform", 6) || !strncasecmp(param[0], "ifform", 6) || !strncasecmp(param[0], "form", 4))
{
x = (nparam > 0) ? atoi(param[1]) : conf->form_def; /* numero de structure */
v = (nparam > 1) ? atoi(param[2]) : 1;
if (!strncasecmp(param[0], "i", 1)) i = 1; /* Pour le ISFORM ou IFFORM */
else if (!strncasecmp(param[0], "formnam", 7)) i = 2; /* nom du champ */
else if (!strncasecmp(param[0], "formlen", 7)) i = 3; /* taille du champ */
else if (!strncasecmp(param[0], "formpos", 7)) i = 4; /* position du champ dans la table */
else if (!strncasecmp(param[0], "formbool", 8)) i = 5; /* Retourne un boolean */
else if (!strncasecmp(param[0], "formint", 7)) i = 6; /* Retourne un entier */
else if (!strncasecmp(param[0], "formnum", 7)) i = 7; /* Retourne un Float */
else i = 0;
if (x < N_FORM && x > -1) /* Si le numero de structure est correct */
{
ch1 = cherche_table(conf, conf->form[x].tab, conf->form[x].pos, v, ch2, i, FALSE);
}
else if (i==1 || (i>4 && i<8)) ch1 = "0"; /* Pour le ISFORM, IFFORM, FORMBOOL, FORMNUM et FORMINT */
}
/*---------------------------------------------------------------------*/
/* VAR... et ISVAR... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "isvar", 5) || !strncasecmp(param[0], "ifvar", 5) || !strncasecmp(param[0], "var", 3))
{
x = (nparam > 0) ? atoi(param[1]) : conf->var_def; /* numero de structure */
v = (nparam > 1) ? atoi(param[2]) : 1;
if (!strncasecmp(param[0], "i", 1)) i = 1; /* Pour le ISVAR ou IFVAR */
else if (!strncasecmp(param[0], "varnam", 6)) i = 2; /* nom du champ */
else if (!strncasecmp(param[0], "varlen", 6)) i = 3; /* taille du champ */
else if (!strncasecmp(param[0], "varpos", 6)) i = 4; /* position du champ dans la table */
else if (!strncasecmp(param[0], "varbool", 7)) i = 5; /* Retourne un boolean */
else if (!strncasecmp(param[0], "varint", 6)) i = 6; /* Retourne un entier */
else if (!strncasecmp(param[0], "varnum", 6)) i = 7; /* Retourne un Float */
else i = 0;
if (x < N_VAR && x > -1) /* Si le numero de structure est correct */
{
ch1 = cherche_table(conf, conf->var[x].tab, conf->var[x].pos, v, ch2, i, FALSE);
}
else if (i==1 || (i>4 && i<8)) ch1 = "0"; /* Pour le ISVAR, IFVAR, VARBOOL, VARNUM et VARINT */
}
/*---------------------------------------------------------------------*/
/* IS... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "is", 2))
{
ch1 = "0"; /* Par defaut */
/*---------------------------------------------------------------------*/
/* ISSHOW */
/*---------------------------------------------------------------------*/
if (!strcasecmp(param[0], "isshow"))
{
if (if_sortie) ch1 = "1";
}
/*---------------------------------------------------------------------*/
/* ISEMAIL */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "isemail"))
{
if (isemail(ch2)) ch1 = "1";
}
/*---------------------------------------------------------------------*/
/* ISEMPTY */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "isempty"))
{
if (ifvide(ch2)) ch1 = "1";
}
/*---------------------------------------------------------------------*/
/* ISNUM... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "isnum", 5))
{
if (isnum(ch2)) ch1 = "1";
}
/*---------------------------------------------------------------------*/
/* ISURL */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "isurl"))
{
if (ap_is_url(ch2)) ch1 = "1";
}
/*---------------------------------------------------------------------*/
/* ISCB */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "iscb"))
{
if (nparam > 0)
{
if (!strcasecmp(param[1], "visa")) x = 1;
else if (!strncasecmp(param[1], "master", 6)) x = 1;
else if (!strncasecmp(param[1], "amer", 4)) x = 2;
else if (!strncasecmp(param[1], "novus", 5)) x = 2;
else x = -1;
}
else x = 0; /* Visa si pas de parametre */
if (x > -1)
{
if (verif_cb(conf->pool_tag, x, ch2)) ch1 = "1"; /* VRAI */
}
}
/*---------------------------------------------------------------------*/
/* ISDIR... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "isdir", 5))
{
conf->rr = (request_rec *)ap_sub_req_lookup_uri(ch2, conf->r);
if (S_ISDIR (conf->rr->finfo.st_mode)) /* Oui, c'est un directory */
{
if (nparam > 0)
{
x = strlen(param[1]);
for (i = 0,z = F_OK; i < x; i++)
{
if (param[1][i] == 'r' || param[1][i] == 'R') z |= R_OK;
else if (param[1][i] == 'w' || param[1][i] == 'W') z |= W_OK;
else if (param[1][i] == 'x' || param[1][i] == 'X') z |= X_OK;
}
if (access(conf->rr->filename, z) == 0) ch1 = "1";
}
else ch1 = "1"; /* Le fichier exist */
}
}
/*---------------------------------------------------------------------*/
/* ISFILE */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "isfile"))
{
conf->rr = (request_rec *)ap_sub_req_lookup_uri(ch2, conf->r);
if (S_ISREG(conf->rr->finfo.st_mode)) /* Oui, c'est un fichier */
{
if (nparam > 0)
{
x = strlen(param[1]);
for (i = 0,z = F_OK; i < x; i++)
{
if (param[1][i] == 'r' || param[1][i] == 'R') z |= R_OK;
else if (param[1][i] == 'w' || param[1][i] == 'W') z |= W_OK;
else if (param[1][i] == 'x' || param[1][i] == 'X') z |= X_OK;
}
if (access(conf->rr->filename, z) == 0) ch1 = "1";
}
else ch1 = "1"; /* Le fichier exist */
}
}
/*---------------------------------------------------------------------*/
/* ISLINK */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "islink"))
{
conf->rr = (request_rec *)ap_sub_req_lookup_uri(ch2, conf->r);
if (S_ISLNK(conf->rr->finfo.st_mode)) ch1 = "1"; /* Oui, c'est un lien symbolique */
}
/*---------------------------------------------------------------------*/
/* ISEXEC... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "isexec", 6))
{
conf->rr = (request_rec *)ap_sub_req_lookup_uri(ch2, conf->r);
if (conf->rr->finfo.st_mode)
{
if (access(conf->rr->filename, X_OK) == 0) ch1 = "1";
}
}
/*---------------------------------------------------------------------*/
/* ISREAD... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "isread", 6))
{
conf->rr = (request_rec *)ap_sub_req_lookup_uri(ch2, conf->r);
if (conf->rr->finfo.st_mode)
{
if (access(conf->rr->filename, R_OK) == 0) ch1 = "1";
}
}
/*---------------------------------------------------------------------*/
/* ISWRITE... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "iswrite", 7))
{
conf->rr = (request_rec *)ap_sub_req_lookup_uri(ch2, conf->r);
if (conf->rr->finfo.st_mode)
{
if (access(conf->rr->filename, W_OK) == 0) ch1 = "1";
}
}
/*---------------------------------------------------------------------*/
/* ISMASK... */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "ismask"))
{
if (nparam > 0) /* Il faut au moins 1 parametre */
{
if (ap_checkmask(ch2, param[1])) ch1 = "1"; /* VRAI */
}
}
/*---------------------------------------------------------------------*/
/* ISBISSEX... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "isbissex", 8))
{
if ((x = atoi(ch2)) > 0)
{
if (annee_bissex(x)) ch1 = "1";
}
}
/*---------------------------------------------------------------------*/
/* ISREQPARENT */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "isreqparent"))
{
if (ap_is_initial_req(conf->r)) ch1 = "1";
}
/*---------------------------------------------------------------------*/
/* ISWORD...(n,n,n) et ISQWORD...(n,n,n) */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "isword", 6) || !strncasecmp(param[0], "isqword", 7))
{
if (nparam > 0) y = atoi(param[1]); /* Numero du mot a recuperer */
if (nparam > 1) w = atoi(param[2]); /* Taille minimum du mot */
if (nparam > 2) v = atoi(param[3]); /* Taille maximum du mot */
if (!strncasecmp(param[0], "isq", 3)) flag = TRUE; /* S'il faut prendre en compte les guillemets */
recupmots(conf->pool_tag, ch2, y, w, v, flag, 1, &x);
if (x) ch1 = "1";
}
}
/*---------------------------------------------------------------------*/
/* IF... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "if", 2))
{
/* ---------- IF ---------- */
if (!strcasecmp(param[0], "if"))
{
if (nparam < 1) param[1] = ""; /* Vide si pas de parametres */
if (testlog(conf, ch2)) ch1 = param[1]; /* Si la condition est Vrai */
else if (nparam > 1) ch1 = param[2]; /* Si la condition est fausse */
}
}
/*---------------------------------------------------------------------*/
/* CPAGE(n,n,n) */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "cpage", 5))
{
if (nparam > 0)
{
w = atoi(param[1]); /* Nombre total d'éléments */
v = (nparam > 1) ? atoi(param[2]) : 1; /* Partitionnement : Nombre d'éléments par page */
if (v < 1) v = 1;
if (!strcasecmp(ch2, "npage"))
{
y = w/v;
if (w%v) y++;
ch1 = ap_psprintf(conf->pool_tag, "%d", y);
}
else if (nparam > 2) /* Positionnement : Premier élément de la page */
{
x = atoi(param[3]);
if (x < 0) x = 0;
else if (x > w) x = w;
if (!strcasecmp(ch2, "page")) ch1 = ap_psprintf(conf->pool_tag, "%d", (x / v) + 1);
else if (!strncasecmp(ch2, "prev", 4))
{
if ((x - v) >= 0) ch1 = ap_psprintf(conf->pool_tag, "%d", x - v);
else ch1 = "0";
}
else if (!strcasecmp(ch2, "next"))
{
if (x + v >= w) y = x;
else y = x+v;
ch1 = ap_psprintf(conf->pool_tag, "%d", y);
}
else if (!strcasecmp(ch2, "start")) ch1 = "0";
else if (!strcasecmp(ch2, "end"))
{
y = w/v;
if (w%v) y++;
ch1 = ap_psprintf(conf->pool_tag, "%d", (y-1)*v);
}
else if (!strcasecmp(ch2, "isstart") || !strcasecmp(ch2, "ifstart"))
{
if (x > 0) ch1 = "0";
else ch1 = "1";
}
else if (!strcasecmp(ch2, "isend") || !strcasecmp(ch2, "ifend"))
{
if ((x + v) >= w) ch1 = "1";
else ch1 = "0";
}
}
}
}
/*---------------------------------------------------------------------*/
/* NBRWORD...(n,n) et NBRQWORD...(n,n) */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "nbrword", 7) || !strncasecmp(param[0], "nbrqword", 8))
{
if (nparam > 0) w = atoi(param[1]); /* Taille minimum du mot */
if (nparam > 1) v = atoi(param[2]); /* Taille maximum du mot */
if (!strncasecmp(param[0], "nbrq", 4)) flag = TRUE; /* S'il faut prendre en compte les guillemets */
recupmots(conf->pool_tag, ch2, 1, w, v, flag, 2, &x);
ch1 = ap_psprintf(conf->pool_tag, "%d", x); /* Nombre de mots trouve dans la chaine */
}
/*---------------------------------------------------------------------*/
/* INTERP... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "interp", 6))
{
ch1 = interp(conf, ch2);
}
/*---------------------------------------------------------------------*/
/* HEXTOINT... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0],"hextoint", 8)) ch1 = ap_psprintf(conf->pool_tag, "%lu", strtol(ch2, NULL, 16));
/*---------------------------------------------------------------------*/
/* INTTOHEX...(n) */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0],"inttohex", 8))
{
x = (nparam > 0) ? atoi(param[1]) : 0; /* Pour fixer le nombre de caracteres */
ch1 = int_to_hex(conf->pool_tag, strtol(ch2, NULL, 10), x, NULL);
}
/*---------------------------------------------------------------------*/
/* HEXTOSTR... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0],"hextostr", 8))
{
if ((y = strlen(ch2)-1) > 0)
{
ptr = ap_pcalloc(conf->pool_tag, 3 * sizeof(char)); /* Alloue de la memoire pour stocker 2 caracteres */
ch1 = ap_palloc(conf->pool_tag, (y+3) * sizeof(char)); /* Alloue de la memoire pour le resultat */
for (x = 0, z = 0; x < y; x+=2)
{
if (!isxdigit(ptr[0] = ch2[x]) || !isxdigit(ptr[1] = ch2[x+1])) break; /* Si ce n'est pas une valeur hexa alors stop le traitement */
ch1[z++] = (char)strtol(ptr, NULL, 16);
}
ch1[z] = '\0';
}
}
/*---------------------------------------------------------------------*/
/* ORD */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0],"ord"))
{
if (nparam > 0) y = atoi(param[1]);
else y = 0;
if (y >= 0 && y < strlen(ch2)) ch1 = ap_psprintf(conf->pool_tag, "%u", (unsigned char)ch2[y]);
else ch1 = "0";
}
/*---------------------------------------------------------------------*/
/* CHR */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "chr"))
{
y = atoi(ch2);
if (y > 0 && y < 256) ch1 = ap_psprintf(conf->pool_tag, "%c", (unsigned char)y);
}
/*---------------------------------------------------------------------*/
/* BASETOINT...(n) */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0],"basetoint", 9)) ch1 = ap_psprintf(conf->pool_tag, "%lu", strtol(ch2, NULL, x = (nparam > 0) ? atoi(param[1]) : 0));
/*---------------------------------------------------------------------*/
/* STR... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "str", 3))
{
/*---------------------------------------------------------------------*/
/* STRTOHEX... */
/*---------------------------------------------------------------------*/
if (!strncasecmp(param[0],"strtohex", 8))
{
if ((y = strlen(ch2)) > 0)
{
ch1 = ap_palloc(conf->pool_tag, (y * 2 * sizeof(char))+1); /* Alloue un emplacement memoire pour le resultat */
for (x = 0, z = 0; x < y; x++)
{
ptr = int_to_hex(conf->pool_tag, (long unsigned int)ch2[x], 2, NULL);
ch1[z++] = ptr[0]; /* Recupere le premier caractere */
ch1[z++] = ptr[1]; /* Recupere le deuxieme caractere */
}
ch1[z] = '\0'; /* Fin de chaine */
}
}
/*---------------------------------------------------------------------*/
/* STRREPEAT */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "strrepeat"))
{
x = (nparam > 0) ? atoi(param[1]) : 0;
y = strlen(ch2);
if (x > 0 && y > 0)
{
ptr = ch1 = ap_palloc(conf->pool_tag, (y * x) + 1); /* Allocation de la zone memoire necessaire */
while(x-- > 0)
{
memcpy(ptr, ch2, y);
ptr += y;
}
ptr[0] = 0; /* Fin de chaine */
}
}
/*---------------------------------------------------------------------*/
/* STRLEN... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "strlen", 6)) ch1 = ap_psprintf(conf->pool_tag, "%lu", (long int)strlen(ch2));
/*---------------------------------------------------------------------*/
/* STRREV... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "strrev", 6))
{
x = strlen(ch2) - 1;
for (y = 0; y < x; y++)
{
car = ch2[y];
ch2[y] = ch2[x];
ch2[x--] = car;
}
ch1 = ch2;
}
/*---------------------------------------------------------------------*/
/* STRTR */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "strtr"))
{
if (nparam > 1 && (z = strlen(ch2)) > 0)
{
if ((x = strlen(param[1])) > (y = strlen(param[2]))) x = y; /* Recupere la longueur de From et To */
for (i = 0; i < 256; tr[i] = i++); /* Remplit le tableau ASCII */
for (i = 0; i < x; i++) tr[(unsigned char)param[1][i]] = param[2][i]; /* Modifie le tableau ASCII */
for (i = 0; i < z; i++) ch2[i] = tr[(unsigned char)ch2[i]];
}
ch1 = ch2;
}
/* --------------------------------------------------- */
else if (nparam > 0)
{
/*---------------------------------------------------------------------*/
/* STRCHR */
/*---------------------------------------------------------------------*/
if (!strcasecmp(param[0], "strchr"))
{
if (strlen(param[1]) > 0)
{
if ((temp = strchr(ch2, param[1][0])) != NULL) ch1 = temp;
}
}
/*---------------------------------------------------------------------*/
/* STRRCHR */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "strrchr"))
{
if (strlen(param[1]) > 0)
{
if ((temp = strrchr(ch2, param[1][0])) != NULL) ch1 = temp;
}
}
/*---------------------------------------------------------------------*/
/* STRSTR */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "strstr"))
{
if (strlen(param[1]) > 0)
{
if ((temp = strstr(ch2, param[1])) != NULL) ch1 = temp;
}
}
/*---------------------------------------------------------------------*/
/* STRCUT... et STRCASECUT... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "strcut", 6) || !strncasecmp(param[0], "strcasecut", 10))
{
if (nparam > 1)
{
if (!strcmp(param[2], "*")) x = -1;
else x = atoi(param[2]);
}
else x = -1;
if (!strncasecmp(param[0], "strcut", 6)) ch1 = strsup(ch2, param[1], x, 0);
else ch1 = strsup(ch2, param[1], x, 1);
}
/*---------------------------------------------------------------------*/
/* STRREP... et STRCASEREP... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "strrep", 6) || !strncasecmp(param[0], "strcaserep", 10))
{
if (nparam > 1)
{
if (nparam > 2)
{
if (!strcmp(param[3], "*")) x = -1;
else x = atoi(param[3]);
}
else x = -1;
if (!strncasecmp(param[0], "strrep", 6)) ch1 = strrep(conf->pool_tag, ch2, param[1], param[2], x, 0);
else ch1 = strrep(conf->pool_tag, ch2, param[1], param[2], x, 1);
}
}
/*---------------------------------------------------------------------*/
/* STREND(n) et STRCASEEND(n) */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "strend") || !strcasecmp(param[0], "strcaseend"))
{
if (nparam > 1)
{
if (!strcmp(param[2], "*")) x = -1;
else x = atoi(param[2]);
}
else x = -1;
if ((y = strlen(param[1])) > 0 && x != 0)
{
if (!strcasecmp(param[0], "strcaseend")) z = TRUE; /* Ne fait pas la difference entre Maj/Min */
else z = FALSE;
v = w = 0;
i = -1;
while(ch2[++i] != '\0')
{
if ((z && !strncasecmp(&ch2[i], param[1], y)) || (!z && !strncmp(&ch2[i], param[1], y)))
{
w = i; /* Memorise la position de cette occurence */
if (++v == x) break;
}
}
if (w) ch2[w] = 0; /* Fin de chaine */
}
ch1 = ch2;
}
}
}
/*---------------------------------------------------------------------*/
/* SOUNDEX */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "soundex"))
{
x = 0; /* francais par defaut */
if (nparam > 0) /* Si il y a un parametre (la langue) */
{
if (!strcasecmp(param[1], "en")) x = 1; /* Anglais */
}
ch1 = calcul_soundex(conf->pool_tag, ch2, x);
}
/*---------------------------------------------------------------------*/
/* MD5 */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0],"md5")) ch1 = (char *)ap_md5(conf->pool_tag, (unsigned char *)ch2);
/*---------------------------------------------------------------------*/
/* CRC32... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "crc32", 5))
{
/* ---------- CRC32 ---------- */
if (!strcasecmp(param[0], "crc32")) ch1 = ap_psprintf(conf->pool_tag, "%lu", calcul_crc32(ch2)); /* Calcul le CRC32 de la chaine */
/* ---------- CRC32HEX... ---------- */
else if (!strncasecmp(param[0], "crc32hex", 8)) ch1 = int_to_hex(conf->pool_tag, calcul_crc32(ch2), 8, NULL); /* Calcul le CRC32 de la chaine en hexadecimal */
/* ---------- CRC32ENCOD... ---------- */
else if (!strncasecmp(param[0], "crc32encod", 10))
{
if (nparam < 1) param[1] = NULL;
ch1 = encode_crc32(conf->pool_tag, ch2, param[1]);
}
/* ---------- CRC32DECOD... ---------- */
else if (!strncasecmp(param[0], "crc32decod", 10))
{
if (nparam < 1) param[1] = NULL;
if ((temp = decode_crc32(conf->pool_tag, ch2, param[1])) != NULL) ch1 = temp;
}
/* ---------- CRC32VERIF... ---------- */
else if (!strncasecmp(param[0], "crc32verif", 10))
{
if (nparam < 1) param[1] = NULL;
if ((temp = decode_crc32(conf->pool_tag, ch2, param[1])) != NULL) ch1 = "1";
else ch1 = "0";
}
}
/*---------------------------------------------------------------------*/
/* BASE64ENCOD... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "base64encod", 11)) ch1 = base64encode(conf->pool_tag, ch2, strlen(ch2), NULL);
/*---------------------------------------------------------------------*/
/* BASE64DECOD... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "base64decod", 11))
{
if ((temp = base64decode(conf->pool_tag, ch2, strlen(ch2), NULL)) != NULL) ch1 = temp;
}
/*---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*/
/* CONST... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0],"const", 5))
{
if (!strcasecmp(ch2, "server_built")) ch1 = ap_pstrdup(conf->pool_tag, ap_get_server_built()); /* Renvoi la date et heure de la derniere compilation du serveur */
else if (!strcasecmp(ch2, "remote_user")) ch1 = ap_pstrdup(conf->pool_tag, conf->r->connection->user); /* Renvoi le nom du User authentifie s'il y en a un */
else if (!strcasecmp(ch2, "server_version")) ch1 = ap_pstrdup(conf->pool_tag, ap_get_server_version()); /* Renvoi le numero de version du serveur */
else if (!strcasecmp(ch2, "id") || !strcasecmp(ch2, "unique_id")) ch1 = ap_pstrdup(conf->pool_tag, conf->unique_id); /* Renvoi un numero unique */
else if (!strcasecmp(ch2, "remote_host")) ch1 = ap_pstrdup(conf->pool_tag, ap_get_remote_host(conf->r->connection, conf->r->per_dir_config, REMOTE_NAME)); /* Renvoi le remote_host */
else if (!strcasecmp(ch2, "document_root")) ch1 = ap_pstrdup(conf->pool_tag, ap_document_root(conf->r)); /* Renvoi le document_root */
else if (!strcasecmp(ch2, "server_name")) ch1 = ap_pstrdup(conf->pool_tag, ap_get_server_name(conf->r)); /* Renvoi le server_name */
else if (!strcasecmp(ch2, "document_uri")) ch1 = conf->r->uri; /* Renvoi l'URI du document principal */
else if (!strcasecmp(ch2, "localhost")) ch1 = ap_get_local_host(conf->pool_tag); /* Renvoi le localHost */
else if (!strcasecmp(ch2, "boundary")) ch1 = conf->boundary; /* Renvoi le boundary ou une chaine vide s'il n'y en a pas */
else if (!strcasecmp(ch2, "adml_version")) ch1 = ADML_VERSION; /* Renvoi le numero de version de ADML */
else if (!strcasecmp(ch2, "adml_name")) ch1 = ADML_NOM; /* Renvoi le nom du programme (module) ADML */
else if (!strcasecmp(ch2, "document_name")) /* Renvoi le nom du document principal */
{
if ((ptr = strrchr(conf->r->filename, '/'))) ch1 = ++ptr;
else ch1 = conf->r->uri;
}
else if (!strcasecmp(ch2, "cr")) ch1 = "\r"; /* Renvoi un caractere de fin de ligne */
else if (!strcasecmp(ch2, "lf")) ch1 = "\n"; /* Renvoi un caractere de nouvelle ligne */
else if (!strcasecmp(ch2, "crlf")) ch1 = "\r\n"; /* Renvoi un caractere de fin de ligne et nouvelle ligne */
}
/*---------------------------------------------------------------------*/
/* VAR... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0],"var", 3))
{
if (!strcasecmp(ch2, "ligne") || !strcasecmp(ch2, "line")) ch1 = ap_psprintf(conf->pool_tag, "%d", conf->ligne); /* Renvoi le numero de ligne courante du fichier en cour */
else if (!strcasecmp(ch2, "ifshow"))
{
if (if_sortie) ch1 = "1"; /* Oui! la sortie est autorise */
else ch1 = "0";
}
else if (!strncasecmp(ch2, "ifnoheader", 10))
{
if (conf->noheader) ch1 = "1";
else ch1 = "0";
}
else if (!strncasecmp(ch2, "ifheader", 8))
{
if (conf->header) ch1 = "1";
else ch1 = "0";
}
else if (!strncasecmp(ch2, "ifinc", 5))
{
if (conf->fichier != NULL) ch1 = "1"; /* Oui! ont est dans un Include */
else ch1 = "0";
}
else if (!strcasecmp(ch2, "document_name"))
{
if (conf->filename == NULL) /* Si ont est dans le document principal */
{
if ((ptr = strrchr(conf->r->filename, '/'))) ch1 = ++ptr;
else ch1 = conf->r->uri;
}
else
{
if ((ptr = strrchr(conf->filename, '/'))) ch1 = ++ptr;
else ch1 = ap_pstrdup(conf->pool_tag, conf->filename);
}
}
}
/*---------------------------------------------------------------------*/
/* ENV */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0],"env"))
{
if ((conf->ctemp = ap_table_get(conf->r->subprocess_env, ch2)) != NULL) ch1 = ap_pstrdup(conf->pool_tag, conf->ctemp);
/*
arr = ap_table_elts(r->subprocess_env);
elts = (table_entry *) arr->elts;
for(y=0; y < arr->nelts; y++)
{
if (!strcasecmp(elts[y].key, ch2))
{
ch1 = elts[y].val;
break;
}
}
*/
}
/*---------------------------------------------------------------------*/
/* WHILE */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0],"while"))
{
ch1 = "0"; /* Valeur de retour par defaut */
if (conf->nwhile > 0) /* Si on est dans une boucle ou un if, ... */
{
for (y=conf->nwhile; y > 0; y--)
{
if (conf->ifwhile[y].type > 2) break; /* Recherche une boucle While et ecarte les IF afin de prendre la boucle la plus proche */
}
if (!strcasecmp(ch2, "loop")) ch1 = ap_psprintf(conf->pool_tag, "%d", conf->ifwhile[y].tour); /* Renvoi le nombre de boucle effectue */
else if (!strcasecmp(ch2, "limit")) ch1 = ap_psprintf(conf->pool_tag, "%d", conf->ifwhile[y].limite); /* Renvoi la valeur limit configurer dans le while */
else if (!strncasecmp(ch2, "istop", 5)) /* IsTop : Renvoi 1 (True) si ont est en haut de la boucle et 0 sinon */
{
if (conf->ifwhile[y].tour < 1) ch1="1";
}
else if (!strncasecmp(ch2, "isbot", 5)) /* IsBottom : Renvoi 1 (True) si ont est en bas de la boucle et 0 sinon */
{
if ((conf->ifwhile[y].tour + 1) < conf->ifwhile[y].limite || conf->ifwhile[y].limite < 1)
{
switch(conf->ifwhile[y].type)
{
/* ----- Type If ----- */
case 1: /* Erreur a prevoir */
case 2: /* Idem */
break;
/* ----- Type Mysql / MysqlRows ----- */
case 3: if ((conf->base_mysql[conf->ifwhile[y].num].numligne + 1) >= mysql_num_rows(conf->base_mysql[conf->ifwhile[y].num].res)) ch1="1";
break;
/* ----- Type MysqlFields ----- */
case 4: if ((conf->base_mysql[conf->ifwhile[y].num].numcolonne + 1) >= mysql_num_fields(conf->base_mysql[conf->ifwhile[y].num].res)) ch1="1";
break;
/* ----- Type Upload ----- */
case 5: if (conf->upload_num >= conf->nupload) ch1="1";
break;
/* ----- Type Header ----- */
case 6: if ((conf->headers_in_num + 1) >= conf->ifwhile[y].arr->nelts) ch1="1";
break;
/* ----- Type Form ----- */
case 7: if ((conf->form[conf->ifwhile[y].num].pos + 1) >= conf->ifwhile[y].arr->nelts) ch1="1";
break;
/* ----- Type Cookie ----- */
case 8: if ((conf->cookies.pos + 1) >= conf->ifwhile[y].arr->nelts) ch1="1";
break;
default: break;
}
}
else ch1 = "1"; /* Si ont arrive a la valeur limite du nbr de boucle */
}
}
}
/*---------------------------------------------------------------------*/
/* ESC... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0],"esc", 3))
{
/* ---------- ESCHTML ---------- */
if (!strcasecmp(param[0],"eschtml")) ch1 = ap_escape_html(conf->pool_tag, ch2); /* Retourne l'HTML protege */
}
/*---------------------------------------------------------------------*/
/* BKSL_UNESC... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0],"bksl_unesc", 10))
{
ch1 = unescape_backslash(ch2); /* Convertit les anti-slash quelque choses */
}
/*---------------------------------------------------------------------*/
/* DATE */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0],"date", 4))
{
x = (nparam > 0) ? atoi(param[1]) : 0;
y = 0; /* Francais par defaut */
if (nparam > 1) /* Choix de la langue */
{
if (!strncasecmp(param[2], "a_fr", 3)) y = 1; /* Abreviation Francais */
else if (!strncasecmp(param[2], "en", 2)) y = 2; /* Anglais */
else if (!strncasecmp(param[2], "a_en", 2)) y = 3; /* Abreviation Anglais */
}
if (x < N_DATE && x > -1) /* Si le numero de structure est correct */
{
temps = localtime(&conf->secs[x]);
if (!strcasecmp(ch2, "month")) ch1 = ap_psprintf(conf->pool_tag, "%02.d", temps->tm_mon+1);
else if (!strcasecmp(ch2, "day")) ch1 = ap_psprintf(conf->pool_tag, "%02.d", temps->tm_mday);
else if (!strncasecmp(ch2, "dayweek", 7))
{
/* Afin de conserver une coerrence entre le Francais et l'anglais, la semaine commence a 1 (dimanche) pour toutes les langues */
ch1 = ap_psprintf(conf->pool_tag, "%d", temps->tm_wday+1);
}
else if (!strcasecmp(ch2, "year")) ch1 = ap_psprintf(conf->pool_tag, "%04.d", temps->tm_year+1900);
else if (!strncasecmp(ch2, "hour",4)) ch1 = ap_psprintf(conf->pool_tag, "%02.d", temps->tm_hour);
else if (!strncasecmp(ch2, "min", 3)) ch1 = ap_psprintf(conf->pool_tag, "%02.d", temps->tm_min);
else if (!strncasecmp(ch2, "sec", 3)) ch1 = ap_psprintf(conf->pool_tag, "%02.d", temps->tm_sec);
else if (!strcasecmp(ch2, "dayname")) ch1 = ap_pstrdup(conf->pool_tag, jour[y][temps->tm_wday]);
else if (!strcasecmp(ch2, "monthname")) ch1 = ap_pstrdup(conf->pool_tag, mois[y][temps->tm_mon]);
else if (!strcasecmp(ch2, "yearday")) ch1 = ap_psprintf(conf->pool_tag, "%04.d", jour_annee(temps->tm_mday, temps->tm_mon, temps->tm_year+1900));
/* ---------- TIMESTAMP (Date de la structure) ---------- */
else if (!strncasecmp(ch2, "time", 4)) ch1 = ap_psprintf(conf->pool_tag, "%lu", conf->secs[x]);
/* ---------- CURRENT_TIMESTAMP (date courante au format Unix) ---------- */
else if (!strncasecmp(ch2, "current_time", 12))
{
time(×tamp);
ch1 = ap_psprintf(conf->pool_tag, "%lu", timestamp);
}
}
}
/*---------------------------------------------------------------------*/
/* DAYWEEK... */
/*---------------------------------------------------------------------*/
else if (!strncasecmp(param[0], "dayweek", 7))
{
v = (nparam > 0) ? atoi(param[1]) : 1; /* Jour */
w = (nparam > 1) ? atoi(param[2]) : 1; /* Mois */
x = (nparam > 2) ? atoi(param[3]) : 1; /* Annee */
if (v > 0 && v < 32 && w > 0 && w < 13)
{
if (!strncasecmp(ch2, "num", 3)) y = -1; /* Numerique */
else if (!strncasecmp(ch2, "fr", 3)) y = 0; /* Francais */
else if (!strncasecmp(ch2, "a_fr", 3)) y = 1; /* Abreviation Francais */
else if (!strncasecmp(ch2, "en", 2)) y = 2; /* Anglais */
else if (!strncasecmp(ch2, "a_en", 2)) y = 3; /* Abreviation Anglais */
else y = -10; /* Francais par defaut */
if (y >= 0) ch1 = ap_psprintf(conf->pool_tag, "%s", jour[y][jour_semaine(v, w, x)]);
else if (y == -1) ch1 = ap_psprintf(conf->pool_tag, "%d", jour_semaine(v, w, x)+1);
}
}
/*---------------------------------------------------------------------*/
/* MONTHDAY */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "monthday"))
{
v = (nparam > 0) ? atoi(param[1]) : 1; /* Mois */
if (v > 0 && v < 13 && (w = atoi(ch2)) > 0) ch1 = ap_psprintf(conf->pool_tag, "%d", jour_dans_mois[annee_bissex(w)][v]); /* Renvoi le nombre de jour du mois en question */
}
/*---------------------------------------------------------------------*/
/* YEARDAY */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0], "yearday"))
{
v = (nparam > 0) ? atoi(param[1]) : 0; /* Jour */
w = (nparam > 1) ? atoi(param[2]) : 0; /* Mois */
x = (nparam > 2) ? atoi(param[3]) : 0; /* Annee */
if (v > 0 && v < 32 && w > 0 && w < 13 && x > 0) ch1 = ap_psprintf(conf->pool_tag, "%d", jour_annee(v, w, x));
}
/*---------------------------------------------------------------------*/
/* MYSQL */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0],"mysql"))
{
x = (nparam > 0) ? atoi(param[1]) : conf->mysql_def;
if (x < N_MYSQL && x > -1) /* Si le numero de structure est correct */
{
/* ---------- Si c'est un mot cles ---------- */
if (!strcasecmp(ch2, "_hostinfo")) ch1 = mysql_get_host_info(&conf->base_mysql[x].mysql);
else if (!strcasecmp(ch2, "_clientinfo")) ch1 = mysql_get_client_info();
else if (!strcasecmp(ch2, "_error")) ch1 = md_mysql_error(&conf->base_mysql[x]);
else if (!strncasecmp(ch2, "_iserr", 6) || !strncasecmp(ch2, "_iferr", 6))
{
if (conf->base_mysql[x].ferror) ch1 = "1"; /* Oui, il y a une erreur */
else ch1 = "0"; /* Pas d'erreur */
}
else if (!strncasecmp(ch2, "_isnoerr", 8) || !strncasecmp(ch2, "_ifnoerr", 8))
{
if (conf->base_mysql[x].ferror) ch1 = "0"; /* NON, il y a une erreur */
else ch1 = "1"; /* Oui, il n'y a pas d'erreur */
}
/* ---------- Si une connection est OK ---------- */
else if (conf->base_mysql[x].fconnect)
{
if (!strcasecmp(ch2, "_protoinfo")) ch1 = ap_psprintf(conf->pool_tag, "%d", mysql_get_proto_info(&conf->base_mysql[x].mysql));
else if (!strcasecmp(ch2, "_serverinfo")) ch1 = mysql_get_server_info(&conf->base_mysql->mysql);
else if (!strcasecmp(ch2, "_stat")) ch1 = mysql_stat(&conf->base_mysql[x].mysql);
else if (!strcasecmp(ch2, "_id")) ch1 = ap_psprintf(conf->pool_tag, "%d", mysql_insert_id(&conf->base_mysql[x].mysql));
/* ---------- Si une Requete est OK ---------- */
else if (conf->base_mysql[x].fquery)
{
if (!strcasecmp(ch2, "_dataseek")) ch1 = ap_psprintf(conf->pool_tag, "%d", conf->base_mysql[x].numligne);
else if (!strcasecmp(ch2, "_fieldseek")) ch1 = ap_psprintf(conf->pool_tag, "%d", conf->base_mysql[x].numcolonne);
else if (!strncasecmp(ch2, "_nbrrow", 7) || !strncasecmp(ch2, "_nrow", 5)) ch1 = ap_psprintf(conf->pool_tag, "%d", mysql_num_rows(conf->base_mysql[x].res));
else if (!strncasecmp(ch2, "_nbrfield", 9) || !strncasecmp(ch2, "_nfield", 7)) ch1 = ap_psprintf(conf->pool_tag, "%d", mysql_num_fields(conf->base_mysql[x].res));
/* ---------- */
else if (conf->base_mysql[x].numligne < 0 || conf->base_mysql[x].numligne >= md_mysql_nbrrows(&conf->base_mysql[x])) /* Si ont est hors champs */
{
ch1 = "";
}
else /* Recherche du nom */
{
w = -1; /* Par defaut */
if (ch2[0] != '#') /* Recherche en nom */
{
if ((conf->temp = strchr(ch2, '.')))
{
conf->temp[0] = '\0';
}
z =-1;
while(++z < md_mysql_nbrfields(&conf->base_mysql[x]))
{
if (md_mysql_fieldseek(&conf->base_mysql[x], z))
{
if (conf->temp) /* Controle du nom de la table egalement */
{
if (!strcmp(conf->base_mysql[x].field->name, &conf->temp[1]) && !strcmp(conf->base_mysql[x].field->table, ch2)) break; /* OK! c'est trouve! */
}
else
{
if (!strcmp(ch2, conf->base_mysql[x].field->name)) break; // OK! c'est trouve!
}
}
}
if (z < md_mysql_nbrfields(&conf->base_mysql[x])) w = z; /* Trouver le champ */
}
else if (!strcmp(ch2, "#")) /* Prend le champ courant */
{
if (conf->base_mysql[x].numcolonne >= 0 && conf->base_mysql[x].numcolonne < md_mysql_nbrfields(&conf->base_mysql[x])) w = conf->base_mysql[x].numcolonne; /* Recupere le numero du champ courant */
}
else if (isnum(&ch2[1]) && strlen(&ch2[1]) > 0) /* Recherche avec le numero du champ */
{
z = atoi(&ch2[1]);
if (z >= 0 && z < md_mysql_nbrfields(&conf->base_mysql[x])) w = z; /* le champ numero z existe */
}
if (w > -1) /* Si un champ est a renvoyer */
{
md_mysql_fieldseek(&conf->base_mysql[x], w);
if (nparam > 1)
{
if (!strncasecmp(param[2], "val", 3) || strlen(param[2]) < 1) ch1 = conf->base_mysql[x].row[w]; /* Renvoi la valeur du champ */
else if (!strcasecmp(param[2], "name") || !strcasecmp(param[2], "nom")) ch1 = conf->base_mysql[x].field->name; /* Renvoi le nom du champ */
else if (!strncasecmp(param[2], "table", 5)) ch1 = conf->base_mysql[x].field->table; /* Renvoi le nom de la table */
else if (!strncasecmp(param[2], "def", 3)) ch1 = conf->base_mysql[x].field->def; /* Renvoi la valeur par defaut du champ */
else if (!strcasecmp(param[2], "type")) ch1 = ap_psprintf(conf->pool_tag, "%d", conf->base_mysql[x].field->type); /* Renvoi le numero du type de champ */
/* -------------> a finir (typename et flagname */
else if (!strcasecmp(param[2], "typename") || !strcasecmp(param[2], "typenom")) ch1 = ap_psprintf(conf->pool_tag, "%d", conf->base_mysql[x].field->type); /* Renvoi le nom du type du champ */
else if (!strncasecmp(param[2], "len", 3) || !strcasecmp(param[2], "taille")) ch1 = ap_psprintf(conf->pool_tag, "%u", conf->base_mysql[x].field->length); /* Renvoi la taille du type du champ */
else if (!strncasecmp(param[2], "maxlen", 6)) ch1 = ap_psprintf(conf->pool_tag, "%u", conf->base_mysql[x].field->max_length); /* Renvoi la taille max de selected set du champ */
else if (!strncasecmp(param[2], "flag", 4)) ch1 = ap_psprintf(conf->pool_tag, "%u", conf->base_mysql[x].field->flags); /* Renvoi la valeur de flag du champ */
else if (!strncasecmp(param[2], "dec", 3)) ch1 = ap_psprintf(conf->pool_tag, "%u", conf->base_mysql[x].field->decimals); /* Renvoi le nombre de decimal du champ */
}
else ch1 = conf->base_mysql[x].row[w]; /* Renvoi la valeur du champ */
}
}
}
}
}
}
/*---------------------------------------------------------------------*/
/* FONCTION INCONNU */
/*---------------------------------------------------------------------*/
else if (!strcasecmp(param[0],"right") || !strcasecmp(param[0],"left"))
{
/* A voir (option) */
}
if (ch1 == NULL) ch1 = ""; /* Au cas ou */
return(ch1);
}
/*--------------------------------------------------------------------------*/
/* Analyse une chaine pour les calculs et test logique */
/*--------------------------------------------------------------------------*/
static char *calcul(adml_cfg *conf, const char *chaine)
{
int ncalc = 0;
adml_calcul tabcalc[15];
int pos = 0, taille, parenth = 0, fparenth = 0;
int sous_pos = 0, num = 0, debut, encour = FALSE, fin = -1;
int signe;
char guil = '\0';
char *erreur = NULL, *ptr;
double tempo;
if (chaine == NULL) return(""); /* Renvoi une chaine vide */
if ((taille = strlen(chaine)) < 1) return(""); /* Recupere la taille de la chaine et retourne "" si la chaine est vide */
/*
ap_rprintf(conf->r,"<P><B>DEBUT=[<TT>%s</TT>]</B> :<BR>", chaine);
*/
do
{
if (fparenth > 0) /* Si ont est dans une fonction */
{
if (chaine[pos] == '(') fparenth++;
else if (chaine[pos] == ')') fparenth--;
}
else /* Si ont est pas dans une fonction */
{
if (guil == '\0') /* Si les guillement ne sont pas encore ouvert */
{
if (parenth > 0) /* Si ont est dans une parenthese */
{
if (chaine[pos] == ')')
{
parenth--;
if (parenth < 1)
{
if (pos - sous_pos > 0)
{
signe = 0;
conf->temp = calcul(conf, ap_pstrndup(conf->pool_tag, &chaine[sous_pos], pos - sous_pos)); /* Lance un sous-calcul */
if (!strncmp(conf->temp, "Error:", 6)) return(conf->temp);
else if (!strcmp(conf->temp, "-VaL*")) /* C'est une valeur numerique */
{
tabcalc[ncalc].type = -2;
tabcalc[ncalc].valeur = conf->calcul;
}
else /* si c'est une chaine */
{
tabcalc[ncalc].type = 0;
tabcalc[ncalc].chaine = conf->temp;
}
goto TRAITE_CHAINE;
}
else
{
erreur = "Parenthese vide !";
break;
}
}
}
else if (chaine[pos] == '(')
{
if (chaine[pos - 1] == '$') fparenth++; /* Ont entre dans une fonction */
else parenth++; /* Si c'est une parenthese de priorite */
}
}
else /* Ont est pas dans une parenthese (sous-calcul) */
{
if (chaine[pos] == '(') /* Ouverture de parenthese, donc sous calcul (recursif) */
{
if (chaine[pos - 1] == '$') fparenth++; /* Ont entre dans une fonction */
else /* Si c'est une parenthese de priorite */
{
parenth++;
sous_pos = pos+1; /* Enregistre le debut du sous-calcul */
if (ncalc > 0)
{
if (encour || tabcalc[ncalc-1].type < 1)
{
erreur = "Fonction ou ouverture de parenthese a la suite d'une valeur !";
break;
}
}
}
}
else if (chaine[pos] == ')') /* Fermeture de parenthese alors qu'aucune n'est ouverte */
{
parenth--; /* afin que la valeur soit negatif */
break; /* Quitte la boucle */
}
else if (chaine[pos] == '\"' || chaine[pos] == '\'') /* Ouverture de guillemet */
{
if (encour) /* Si ont est deja en train de recuperer une valeur */
{
erreur = "Probleme lors de l'ouverture d'un guillemet !";
break;
}
guil = chaine[pos];
encour = TRUE;
debut = pos+1; /* Enregistre la position de depart */
}
else
{
signe = 0;
fin = pos;
if (chaine[pos] == '+' || chaine[pos] == '-')
{
if (ncalc > 0)
{
if (tabcalc[ncalc-1].type > 0 && !encour) signe++;
}
else if (!encour) signe++;
if (signe < 1)
{
if (chaine[pos] == '+') signe = 1;
else signe = 2;
}
else
{
fin = -1;
debut = pos;
encour = TRUE; /* Prend ce symbole comme faisant partis d'une valeur */
signe = 0;
}
}
else if (chaine[pos] == '^') signe = 4;
else if (chaine[pos] == '/') signe = 15;
else if (chaine[pos] == '*') signe = 14;
else if (chaine[pos] == '<' || chaine[pos] == '>')
{
if (chaine[pos] == '<') signe = 5;
else signe = 7;
if (chaine[pos+1] == '=')
{
signe++;
pos++;
}
else if (chaine[pos+1] == '>')
{
if (signe == 5) signe = 10;
else signe = 17;
pos++;
}
else if (signe == 5 && chaine[pos+1] == '<')
{
signe = 16;
pos++;
}
}
else if (chaine[pos] == '=')
{
signe = 9;
if (chaine[pos+1] == '=') pos++;
}
else if (chaine[pos] == '!')
{
if (chaine[pos+1] == '=')
{
signe = 10;
pos++;
}
else
{
if (ncalc > 0)
{
if (encour || tabcalc[ncalc-1].type < 1)
{
erreur = "Negation a la suite d'une valeur !";
break;
}
}
signe = 19;
}
}
else if (chaine[pos] == '|')
{
if (chaine[pos+1] == '|')
{
signe = 11;
pos++;
}
else signe = 3;
}
else if (chaine[pos] == '&')
{
if (chaine[pos+1] == '&')
{
signe = 12;
pos++;
}
else signe = 13;
}
else if (chaine[pos] == '%') signe = 18;
else if (chaine[pos] > 32 && chaine[pos] != 127) /* Si c'est un caractere valide */
{
fin = -1;
if (!encour)
{
encour = TRUE;
debut = pos; /* Enregistre la position de depart */
}
}
else if (chaine[pos] == '\0')
{
signe = 100;
/* pos--; */
}
if (fin >= 0 && encour) /* Si un mot est a recuperer */
{
if (fin - debut == 1 && (chaine[debut] == '-' || chaine[debut] == '+'))
{
erreur = "2 symbole se suivent et le deuxieme et trop eloigne d'une valeur pour en faire partie !";
break;
}
tabcalc[ncalc].chaine = interp(conf, ap_pstrndup(conf->pool_tag, &chaine[debut], fin - debut));
if (isnum(tabcalc[ncalc].chaine)) /* Si c'est un type numerique */
{
if ((ptr = strchr(tabcalc[ncalc].chaine, ',')) != NULL) ptr[0] = '.'; /* Remplacer la virgule par un point pour que atof() convertisse correctement */
tabcalc[ncalc].valeur = atof(tabcalc[ncalc].chaine);
if (ptr != NULL) ptr[0] = ','; /* Remettre la virgule */
tabcalc[ncalc].type = -1;
}
else tabcalc[ncalc].type = 0; /* Si c'est un type chaine */
TRAITE_CHAINE:
if (tabcalc[ncalc].type < 0) /* Type numerique */
{
if (ncalc > 0)
{
if (tabcalc[ncalc-1].type < 1)
{
erreur = "Error: 2 valeurs se suivent !";
break;
}
else if (tabcalc[ncalc-1].type == 19) /* Traitement de la negation */
{
tabcalc[--ncalc].type = -2;
if (tabcalc[ncalc+1].valeur) tabcalc[ncalc].valeur = FALSE;
else tabcalc[ncalc].valeur = TRUE;
}
}
/*
ap_rprintf(conf->r," <FONT SIZE=2>[<B>%lf</B>]</FONT>", tabcalc[ncalc].valeur);
*/
}
else if (tabcalc[ncalc].type == 0) /* type chaine */
{
/*
ap_rprintf(conf->r," <FONT SIZE=2>[<B>\"%s\"</B>]</FONT>", tabcalc[ncalc].chaine);
*/
if (ncalc > 0)
{
if (tabcalc[ncalc-1].type < 1)
{
erreur = "Error: 2 valeurs se suivent !";
break;
}
else if(tabcalc[ncalc-1].type == 19) /* Traitement de la negation */
{
erreur = "Negation sur une chaine interdite";
break;
}
}
}
/* --- Traitement du '/', '*', '&', '<<', '>>' et '%' --- */
if (ncalc > 1)
{
if (tabcalc[ncalc-1].type > 12 && tabcalc[ncalc-1].type < 19)
{
if (tabcalc[ncalc-2].type > -1 || tabcalc[ncalc].type > -1)
{
erreur = "operation impossible sur une chaine !";
break;
}
else
{
tempo = tabcalc[ncalc-2].valeur;
/*
ap_rprintf(conf->r," <FONT SIZE=2 COLOR=#FF0000>[A:<B>%lf;%lf=", tempo, tabcalc[ncalc].valeur);
*/
switch(tabcalc[ncalc-1].type)
{
case 13: tabcalc[ncalc-2].valeur = (double)((long int)tempo & (long int)tabcalc[ncalc].valeur);
break;
case 14: tabcalc[ncalc-2].valeur = tempo * tabcalc[ncalc].valeur;
break;
case 15: if (tabcalc[ncalc].valeur == 0)
{
erreur = "Division par 0 interdite !";
}
else tabcalc[ncalc-2].valeur = tempo / tabcalc[ncalc].valeur;
break;
case 16: tabcalc[ncalc-2].valeur = (double)((long int)tempo << (long int)tabcalc[ncalc].valeur);
break;
case 17: tabcalc[ncalc-2].valeur = (double)((long int)tempo >> (long int)tabcalc[ncalc].valeur);
break;
case 18: tabcalc[ncalc-2].valeur = fmod(tempo, tabcalc[ncalc].valeur);
break;
default: break;
}
if (erreur != NULL) break;
tabcalc[ncalc-2].type = -2; /* Valeur numerique comme resultat obligatoirement */
/*
ap_rprintf(conf->r,"%lf</B>]</FONT> ", tabcalc[ncalc-2].valeur);
*/
ncalc -= 2;
}
}
}
ncalc++;
encour = FALSE;
fin = -1;
}
if (signe > 0) /* Si un signe est a recuperer */
{
tabcalc[ncalc].type = signe;
/*
conf->temp = "";
switch(signe)
{
case 1: conf->temp = "+"; break;
case 2: conf->temp = "-"; break;
case 3: conf->temp = "|"; break;
case 4: conf->temp = "^"; break;
case 5: conf->temp = "<"; break;
case 6: conf->temp = "<="; break;
case 7: conf->temp = ">"; break;
case 8: conf->temp = ">="; break;
case 9: conf->temp = "=="; break;
case 10: conf->temp = "!="; break;
case 11: conf->temp = "||"; break;
case 12: conf->temp = "&&"; break;
case 13: conf->temp = "&"; break;
case 14: conf->temp = "*"; break;
case 15: conf->temp = "/"; break;
case 16: conf->temp = "<<"; break;
case 17: conf->temp = ">>"; break;
case 18: conf->temp = "%"; break;
case 19: conf->temp = "!"; break;
case 20: conf->temp = "~"; break;
case 100: conf->temp = "FIN"; break;
default: conf->temp = "INCONNU!"; break;
}
ap_rprintf(conf->r, " <FONT SIZE=2>[<B>%s</B>]</FONT> ", conf->temp);
*/
if (ncalc < 1 && signe != 100)
{
if (signe != 1 && signe != 2 && signe != 19)
{
erreur = "symbole interdit en debut de calcul ou de parenthese !";
break;
}
}
else if (signe != 100)
{
if ((tabcalc[ncalc-1].type > 0 && tabcalc[ncalc].type != 19) || (tabcalc[ncalc-1].type == 19 && tabcalc[ncalc].type == 19))
{
if (tabcalc[ncalc].type == 100) erreur = "1 symbole se trouve seul a la fin";
else erreur = "2 symboles se suivent !";
break;
}
}
/* --- Traitement du '+', '-', '|' et '^' --- */
if (ncalc > 2 && ((signe > 0 && signe < 13) || signe == 100))
{
if (tabcalc[ncalc-2].type > 0 && tabcalc[ncalc-2].type < 5)
{
if ((tabcalc[ncalc-3].type > -1 || tabcalc[ncalc-1].type > -1) && tabcalc[ncalc-2].type != 1)
{
erreur = "operation impossible sur une chaine !";
break;
}
else
{
tempo = tabcalc[ncalc-3].valeur;
/*
if (tabcalc[ncalc-3].type == 0 && tabcalc[ncalc-1].type == 0) ap_rprintf(conf->r," <FONT SIZE=2 COLOR=#FF0000>[B:<B>\"%s\";\"%s\"=", tabcalc[ncalc-3].chaine, tabcalc[ncalc-1].chaine);
else if (tabcalc[ncalc-3].type != 0 && tabcalc[ncalc-1].type == 0) ap_rprintf(conf->r," <FONT SIZE=2 COLOR=#FF0000>[B:<B>%lf;\"%s\"=", tempo, tabcalc[ncalc-1].chaine);
else if (tabcalc[ncalc-3].type == 0 && tabcalc[ncalc-1].type != 0) ap_rprintf(conf->r," <FONT SIZE=2 COLOR=#FF0000>[B:<B>\"%s\";%s=", tabcalc[ncalc-3].chaine, tabcalc[ncalc-1].valeur);
else ap_rprintf(conf->r," <FONT SIZE=2 COLOR=#FF0000>[B:<B>%lf;%lf=", tempo, tabcalc[ncalc-1].valeur);
*/
switch(tabcalc[ncalc-2].type)
{
case 1: if (tabcalc[ncalc-3].type > -1 || tabcalc[ncalc-1].type > -1) /* addition de type chaine */
{
if (tabcalc[ncalc-3].type < -1 || tabcalc[ncalc-1].type < -1)
{
erreur = "Operation impossible entre une chaine et une valeur numerique !";
}
else
{
tabcalc[ncalc-3].type = 0; /* Resultat de type chaine */
tabcalc[ncalc-3].chaine = ap_pstrcat(conf->pool_tag, tabcalc[ncalc-3].chaine, tabcalc[ncalc-1].chaine, NULL); /* Additionne les deux chaines */
}
}
else
{
tabcalc[ncalc-3].type = -2;
tabcalc[ncalc-3].valeur = tempo + tabcalc[ncalc-1].valeur;
}
break;
case 2: tabcalc[ncalc-3].valeur = tempo - tabcalc[ncalc-1].valeur;
break;
case 3: tabcalc[ncalc-3].valeur = (double)((long int)tempo | (long int)tabcalc[ncalc-1].valeur);
break;
case 4: tabcalc[ncalc-3].valeur = (double)((long int)tempo ^ (long int)tabcalc[ncalc-1].valeur);
break;
default:
break;
}
if (erreur != NULL) break;
if (tabcalc[ncalc-2].type != 1) tabcalc[ncalc-3].type = -2; /* Valeur numerique comme resultat sauf pour le plus */
/*
if (tabcalc[ncalc-3].type < 0) ap_rprintf(conf->r,"%lf</B>]</FONT> ", tabcalc[ncalc-3].valeur);
else ap_rprintf(conf->r,"%s</B>]</FONT> ", tabcalc[ncalc-3].chaine);
*/
tabcalc[ncalc-2].type = tabcalc[ncalc].type;
ncalc -= 2;
}
}
}
if (ncalc > 2 && signe > 4 && signe < 11)
{
if (tabcalc[ncalc-2].type > 4 && tabcalc[ncalc-2].type < 11)
{
erreur = "2 signe logique ne peuvent se suivrent !";
break;
}
}
if (ncalc > 2 && (signe == 11 || signe == 12 || signe == 100))
{
if ((signe == 11 || signe == 12 || signe == 100) && ((tabcalc[ncalc-2].type > 4 && tabcalc[ncalc-2].type < 11) || tabcalc[ncalc-2].type == 12))
{
if ((tabcalc[ncalc-3].type > -1 || tabcalc[ncalc-1].type > -1) && tabcalc[ncalc-2].type > 4 && tabcalc[ncalc-2].type < 9)
{
erreur = "operation impossible sur une chaine !";
}
else
{
tempo = tabcalc[ncalc-3].valeur;
tabcalc[ncalc-3].valeur = FALSE; /* resultat du test logique FAUX par defaut */
/*
if (tabcalc[ncalc-3].type == 0 && tabcalc[ncalc-1].type == 0) ap_rprintf(conf->r," <FONT SIZE=2 COLOR=#FF0000>[C:<B>\"%s\";\"%s\"=", tabcalc[ncalc-3].chaine, tabcalc[ncalc-1].chaine);
else if (tabcalc[ncalc-3].type != 0 && tabcalc[ncalc-1].type == 0) ap_rprintf(conf->r," <FONT SIZE=2 COLOR=#FF0000>[C:<B>%lf;\"%s\"=", tempo, tabcalc[ncalc-1].chaine);
else if (tabcalc[ncalc-3].type == 0 && tabcalc[ncalc-1].type != 0) ap_rprintf(conf->r," <FONT SIZE=2 COLOR=#FF0000>[C:<B>\"%s\";%s=", tabcalc[ncalc-3].chaine, tabcalc[ncalc-1].valeur);
else ap_rprintf(conf->r," <FONT SIZE=2 COLOR=#FF0000>[C:<B>%lf;%lf=", tempo, tabcalc[ncalc-1].valeur);
*/
switch(tabcalc[ncalc-2].type)
{
case 5: if (tempo < tabcalc[ncalc-1].valeur) tabcalc[ncalc-3].valeur = TRUE;
break;
case 6: if (tempo <= tabcalc[ncalc-1].valeur) tabcalc[ncalc-3].valeur = TRUE;
break;
case 7: if (tempo > tabcalc[ncalc-1].valeur) tabcalc[ncalc-3].valeur = TRUE;
break;
case 8: if (tempo >= tabcalc[ncalc-1].valeur) tabcalc[ncalc-3].valeur = TRUE;
break;
case 9: if (tabcalc[ncalc-3].type > -1 || tabcalc[ncalc-1].type > -1) /* comparaison de type chaine */
{
if (tabcalc[ncalc-3].type < -1 || tabcalc[ncalc-1].type < -1)
{
erreur = "Operation impossible entre une chaine et une valeur numerique !";
}
else if (!strcmp(tabcalc[ncalc-3].chaine, tabcalc[ncalc-1].chaine)) tabcalc[ncalc-3].valeur = TRUE;
}
else if (tempo == tabcalc[ncalc-1].valeur) tabcalc[ncalc-3].valeur = TRUE;
break;
case 10: if (tabcalc[ncalc-3].type > -1 || tabcalc[ncalc-1].type > -1) /* comparaison de type chaine */
{
if (tabcalc[ncalc-3].type < -1 || tabcalc[ncalc-1].type < -1)
{
erreur = "Operation impossible entre une chaine et une valeur numerique !";
}
else if (strcmp(tabcalc[ncalc-3].chaine, tabcalc[ncalc-1].chaine)) tabcalc[ncalc-3].valeur = TRUE;
}
else if (tempo != tabcalc[ncalc-1].valeur) tabcalc[ncalc-3].valeur = TRUE;
break;
case 12: if (tabcalc[ncalc-3].type == 0) tempo = ifvide(tabcalc[ncalc-3].chaine);
if (tabcalc[ncalc-1].type == 0) tabcalc[ncalc-1].valeur = ifvide(tabcalc[ncalc-1].chaine);
if (tabcalc[ncalc-2].type == 11 && (tempo || tabcalc[ncalc-1].valeur)) tabcalc[ncalc-3].valeur = TRUE;
else if (tabcalc[ncalc-2].type == 12 && (tempo && tabcalc[ncalc-1].valeur)) tabcalc[ncalc-3].valeur = TRUE;
break;
default:
break;
}
if (erreur != NULL) break;
tabcalc[ncalc-3].type = -2; /* Valeur numerique comme resultat obligatoirement */
/*
ap_rprintf(conf->r,"%lf</B>]</FONT> ", tabcalc[ncalc-3].valeur);
*/
tabcalc[ncalc-2].type = tabcalc[ncalc].type;
ncalc -= 2;
}
}
}
DERNIERE_PASSE:
if (ncalc > 2 && (signe == 11 || signe == 100))
{
&n