Compare commits
388 Commits
release-1_
...
master
Author | SHA1 | Date |
---|---|---|
bagyenda | 73955b34cf | |
bagyenda | cb989364b8 | |
bagyenda | be8dc0ee28 | |
bagyenda | 5208b4311f | |
bagyenda | 628fc0c744 | |
bagyenda | 58ebfcc0fd | |
bagyenda | 1eb8f06cb6 | |
bagyenda | 3cd18abe87 | |
bagyenda | 61ff6817fa | |
bagyenda | 5cd58210fe | |
bagyenda | 0d2974bd27 | |
bagyenda | f67330f9e0 | |
bagyenda | e7b5faee07 | |
bagyenda | 11c50d6217 | |
bagyenda | 044e3ebbe6 | |
bagyenda | 265c827fe1 | |
bagyenda | dc3ad6068d | |
bagyenda | d155bd57d4 | |
bagyenda | 8efe4605bc | |
bagyenda | 1e14a17e39 | |
bagyenda | 6a34ce5ca2 | |
bagyenda | 9a7952d200 | |
bagyenda | fae80063f8 | |
bagyenda | fd2ff89411 | |
bagyenda | 919aef48d5 | |
bagyenda | 442846f4c0 | |
bagyenda | 7c1654c5dd | |
bagyenda | fedce613cf | |
bagyenda | 67d8049f1b | |
bagyenda | eba4e9e09d | |
bagyenda | cdabed7443 | |
bagyenda | 18dd46568f | |
bagyenda | e64d8d322d | |
bagyenda | 17a2cbfc90 | |
bagyenda | 2891e9bb27 | |
matlads | f65646e1b8 | |
matlads | 6a459a63f6 | |
bagyenda | 7c777cd10f | |
bagyenda | e104515d9b | |
bagyenda | 6cb349ec90 | |
bagyenda | ea9506fde2 | |
bagyenda | 821f4f32bf | |
matlads | bcfb4ea87b | |
bagyenda | 83d5d370b3 | |
bagyenda | 60be3311ca | |
bagyenda | fd2ed9038f | |
bagyenda | 20ae441d94 | |
bagyenda | bf5c6e2c6c | |
bagyenda | 92563ae701 | |
bagyenda | f23dfb66b9 | |
bagyenda | 6e23d68a16 | |
bagyenda | 8c51f383d7 | |
bagyenda | 3223e679cb | |
bagyenda | 9693113f21 | |
bagyenda | e6de3e5b31 | |
bagyenda | 79cd5a1c7b | |
bagyenda | ab8828922d | |
bagyenda | 4f185a7032 | |
bagyenda | 760b8d734e | |
bagyenda | 09e891bcc9 | |
bagyenda | 48bc07ef14 | |
bagyenda | 41fba4873d | |
bagyenda | 8ba2b9b126 | |
bagyenda | 7206e8b20d | |
bagyenda | 00bdd513fe | |
bagyenda | 18cd80e632 | |
bagyenda | adc01f651f | |
bagyenda | 8e72d4ca3b | |
bagyenda | 83a824759b | |
bagyenda | a7be9632e7 | |
bagyenda | e499aa8131 | |
bagyenda | 0ee33f2da1 | |
bagyenda | 3d663b90a9 | |
bagyenda | 6b35184a7e | |
bagyenda | 1db281efec | |
bagyenda | 5fcfe061af | |
bagyenda | e35d2ffa26 | |
bagyenda | 790e15eb20 | |
bagyenda | 53b7e978e4 | |
bagyenda | b2ba6dfdb5 | |
bagyenda | 828a78bcf3 | |
bagyenda | 1e761682a5 | |
bagyenda | a15d86fa74 | |
bagyenda | 5000597c67 | |
bagyenda | abb7b6d2d1 | |
bagyenda | a721364402 | |
bagyenda | cda686d77a | |
bagyenda | d27f4c0f8a | |
bagyenda | 462972c4a3 | |
bagyenda | 9a0785830c | |
bagyenda | c2887c0857 | |
bagyenda | b00dcbe383 | |
bagyenda | af393b2afe | |
bagyenda | c96438a274 | |
bagyenda | d98f7906b6 | |
bagyenda | c2c0ce7fe3 | |
bagyenda | 25d8d878c7 | |
bagyenda | 2aed655a12 | |
bagyenda | e402334756 | |
bagyenda | 7d69e70dc3 | |
bagyenda | d62e733178 | |
bagyenda | 037183a65a | |
bagyenda | 76cb3e6f5b | |
bagyenda | 591c61f094 | |
bagyenda | 967898a995 | |
bagyenda | 2544b6d718 | |
bagyenda | 0e5dad042b | |
bagyenda | 28231a7d7e | |
bagyenda | ec32ce868e | |
bagyenda | b8ea7dac27 | |
bagyenda | cb2e860093 | |
bagyenda | 5247c97695 | |
bagyenda | 1a1b8ba5e5 | |
bagyenda | e60ed679b4 | |
bagyenda | 8b05add577 | |
bagyenda | be5d0a6bc9 | |
bagyenda | e090e6795e | |
bagyenda | d93be7fce5 | |
bagyenda | f10b0e4e41 | |
bagyenda | b064ee14f0 | |
bagyenda | b579472a52 | |
bagyenda | 3db2d7db6c | |
bagyenda | 8aa1a1a0be | |
bagyenda | bc1a24200e | |
bagyenda | 6c5759f1e9 | |
bagyenda | fcebda1812 | |
bagyenda | e370a86566 | |
bagyenda | 39f5cccee4 | |
bagyenda | 00198c858a | |
bagyenda | c26a3d3e24 | |
bagyenda | 5cd0188e94 | |
bagyenda | bb16c3299a | |
bagyenda | 9490de2bc8 | |
bagyenda | 09bb2abe14 | |
bagyenda | 4a2ad20874 | |
bagyenda | 445723dc0f | |
bagyenda | a1fa945c5f | |
bagyenda | c0e677a7a5 | |
bagyenda | 3e3b9b2b2b | |
bagyenda | 0dfdfdc305 | |
bagyenda | b480d170a5 | |
bagyenda | 069455ec3d | |
bagyenda | 04037fbb64 | |
bagyenda | 335682874b | |
bagyenda | b82e3f2723 | |
bagyenda | 671a62699d | |
bagyenda | 5afec26e5d | |
bagyenda | f55d24567f | |
bagyenda | 30973cf9e5 | |
bagyenda | 02a5ede686 | |
bagyenda | 6263d512b8 | |
bagyenda | 1a3aa4c9aa | |
bagyenda | 30d9e2c0d4 | |
bagyenda | 526ec741fb | |
bagyenda | 2236d0e9e5 | |
bagyenda | b7bd482849 | |
bagyenda | c6591fc15b | |
bagyenda | bf9218da78 | |
bagyenda | fb68ed198e | |
bagyenda | 9b99b14955 | |
bagyenda | 2ff5dabb9e | |
bagyenda | b477dd843c | |
bagyenda | 3b1371f55f | |
bagyenda | f7bc48d88d | |
bagyenda | 85babd8de0 | |
bagyenda | 3f4df1cdc7 | |
bagyenda | 80682bbcb3 | |
bagyenda | 49ae1c2a69 | |
bagyenda | 13e9649091 | |
bagyenda | d63cc82ea8 | |
bagyenda | f654396ea5 | |
bagyenda | 7c7de0e22d | |
bagyenda | 06e4a94eb0 | |
bagyenda | 590444539c | |
bagyenda | b99cbd96fa | |
bagyenda | fe4c53f2be | |
bagyenda | 0cb6626339 | |
bagyenda | f7fa35d3ea | |
bagyenda | 4cdb712d76 | |
bagyenda | 5b5fa1fd7b | |
bagyenda | 6445ca1403 | |
bagyenda | ce84ac2e7b | |
bagyenda | 505e998657 | |
bagyenda | 47172dbb5f | |
bagyenda | 173be8807a | |
bagyenda | 769690693d | |
bagyenda | 55f9ee3766 | |
bagyenda | 82d5a85805 | |
bagyenda | 371438118b | |
bagyenda | 23df285f45 | |
bagyenda | dc10393106 | |
bagyenda | 4658ce6b10 | |
bagyenda | 6eb3e6629c | |
bagyenda | 6b472bf22b | |
bagyenda | 4eb54ddffa | |
bagyenda | 483c6d658d | |
bagyenda | 7264d4f88d | |
bagyenda | 9bf11ffd57 | |
bagyenda | d9be1198a5 | |
bagyenda | fbbec2877b | |
bagyenda | e1c18c07a4 | |
bagyenda | b31790def4 | |
bagyenda | 0fb93b3c90 | |
bagyenda | f69e38cd85 | |
bagyenda | 72ea4e45f0 | |
bagyenda | 232351d5ce | |
bagyenda | cf2f4e7d8e | |
bagyenda | e78739a3a1 | |
bagyenda | ee5c86878d | |
bagyenda | 2179aa0b3c | |
bagyenda | be411e731b | |
bagyenda | 59e844d16c | |
bagyenda | 3ebb5316c1 | |
bagyenda | cd52c8f1ee | |
bagyenda | 9748e88621 | |
bagyenda | fcad678f3c | |
bagyenda | 5d01704548 | |
bagyenda | a49d02b4e8 | |
bagyenda | 15888c94ca | |
bagyenda | b36fe80262 | |
bagyenda | 421c6f6856 | |
bagyenda | d06fa69106 | |
bagyenda | 6cad727c78 | |
bagyenda | d0714028b5 | |
bagyenda | cade2f51a9 | |
bagyenda | 2bee4e49db | |
bagyenda | c58cfafec5 | |
bagyenda | a69feb2eb9 | |
bagyenda | d05d46cc9f | |
bagyenda | 18dcdf7052 | |
bagyenda | 650c1c8318 | |
bagyenda | fc552034da | |
bagyenda | 7137d5bd5d | |
bagyenda | 0cb610d5bd | |
bagyenda | 15f61ba8d5 | |
bagyenda | a87514cc02 | |
bagyenda | 281b7c220b | |
bagyenda | c845a51c10 | |
bagyenda | e76995ab27 | |
bagyenda | 970badf660 | |
bagyenda | 195b7888b9 | |
bagyenda | 30ed2d83f6 | |
bagyenda | d2c8efd1aa | |
bagyenda | 5a5e6603ef | |
bagyenda | fcdd5c442b | |
bagyenda | 3059138928 | |
bagyenda | e1f24fdeee | |
bagyenda | 4308cb1446 | |
bagyenda | 9640be11c8 | |
bagyenda | e48246fa63 | |
bagyenda | 45c6276727 | |
bagyenda | 61d76e1a14 | |
bagyenda | 4208985069 | |
bagyenda | 4ebf96552e | |
bagyenda | 3789d199a7 | |
bagyenda | 89a6e5007d | |
bagyenda | aea228ecc2 | |
bagyenda | b3f9f30919 | |
bagyenda | 21f1188c4e | |
bagyenda | 382c48bb69 | |
bagyenda | 4c5a8389c0 | |
bagyenda | 8438ca779d | |
bagyenda | 9cbf72f5f1 | |
bagyenda | 8124439d44 | |
bagyenda | d7d97c695d | |
bagyenda | 96811a10b7 | |
bagyenda | 67cdf0f387 | |
bagyenda | d973e24c53 | |
bagyenda | 99318916ea | |
bagyenda | f7da8933d8 | |
bagyenda | b3da1b4ead | |
bagyenda | 27d9e7f6ec | |
bagyenda | 8ef3978cab | |
bagyenda | 7c31b97523 | |
bagyenda | 26b0508487 | |
bagyenda | 3d59903562 | |
bagyenda | cc3a502516 | |
bagyenda | e6a0b2d72c | |
bagyenda | 5e84205190 | |
bagyenda | eef103ae02 | |
bagyenda | 7cb159ae13 | |
bagyenda | 3a83c61050 | |
bagyenda | 83312fbf45 | |
bagyenda | f0a3e8a350 | |
bagyenda | 7eec5761a1 | |
bagyenda | 098ffba5cf | |
bagyenda | 824581609c | |
bagyenda | eef6e9b967 | |
bagyenda | 824b57f35f | |
bagyenda | 71c19b6b30 | |
bagyenda | 26adfda0db | |
bagyenda | 81adc79a47 | |
bagyenda | 64722b0299 | |
bagyenda | a2c99daca6 | |
bagyenda | 7430986871 | |
bagyenda | 5271c532c8 | |
bagyenda | e84a8c67ab | |
bagyenda | 561dafdca7 | |
bagyenda | b5aa2c8e63 | |
bagyenda | e3aabcccfe | |
bagyenda | c3a4ddcf67 | |
bagyenda | e59b517fb8 | |
bagyenda | 65c185e3eb | |
bagyenda | c49a4bbe57 | |
bagyenda | 27547cb49b | |
bagyenda | b1df15b16d | |
bagyenda | 3c990ad7cf | |
bagyenda | a22898306a | |
bagyenda | 89c9b8eddb | |
bagyenda | d6292f03d9 | |
bagyenda | a8c3ddccf7 | |
bagyenda | eb1a689a8a | |
bagyenda | 5af2e53f30 | |
bagyenda | 825102fc0a | |
bagyenda | 7a0d166d21 | |
bagyenda | 2255fe303b | |
bagyenda | 222cf4487a | |
bagyenda | fd2d1fbc79 | |
bagyenda | 869a6d3eed | |
bagyenda | bc7049dbd6 | |
bagyenda | a21f21d5d6 | |
bagyenda | de6ded80a9 | |
bagyenda | 14e44ea421 | |
bagyenda | 1b9c2dc2ad | |
bagyenda | c057093761 | |
bagyenda | 7ad9569dce | |
bagyenda | 6ca83011c9 | |
bagyenda | 1075745c33 | |
bagyenda | 99ad888a54 | |
bagyenda | 5eec86d69e | |
bagyenda | 65a82a7175 | |
bagyenda | 00c7e34515 | |
bagyenda | 8ece099c13 | |
bagyenda | f34daaa335 | |
bagyenda | 6e363677a0 | |
bagyenda | c6b75666ab | |
bagyenda | 0b22c99c69 | |
bagyenda | 8e6ecf8a5c | |
bagyenda | ea98a5da35 | |
bagyenda | 89fbf157c8 | |
bagyenda | 63b90a7845 | |
bagyenda | f2d45f4164 | |
bagyenda | c3feca09ff | |
bagyenda | 26cf73882b | |
bagyenda | caa71ca8ca | |
bagyenda | c73765c7a9 | |
bagyenda | 64c2ffe8ed | |
bagyenda | 356905c4b6 | |
bagyenda | 491a6173a8 | |
bagyenda | 3e010fccd4 | |
bagyenda | e652be1d62 | |
bagyenda | 96708be15c | |
bagyenda | c42ddb8aa5 | |
bagyenda | bbeb0c91e3 | |
bagyenda | 88de7ef670 | |
bagyenda | 79b19bac64 | |
bagyenda | 7fd8045dd4 | |
bagyenda | 4d625f2375 | |
bagyenda | e656ec81a7 | |
bagyenda | 1e21db8592 | |
bagyenda | b2f178153c | |
bagyenda | d48ac96cd7 | |
bagyenda | f8c0ef9a7b | |
bagyenda | 9e59d79de5 | |
bagyenda | 1bd576132d | |
bagyenda | cfa26d3c75 | |
bagyenda | feeb8ab13c | |
bagyenda | 0ccc7938d0 | |
bagyenda | fcebfd2ea1 | |
bagyenda | 3e6f552a5f | |
bagyenda | 11574bb88e | |
bagyenda | 0f38817669 | |
bagyenda | 50fd9b03aa | |
bagyenda | bc4ef69c40 | |
bagyenda | 142c9f8342 | |
bagyenda | ea8bce278a | |
bagyenda | ca05acedc9 | |
bagyenda | e92035851f | |
bagyenda | aa1708af9a | |
bagyenda | ddcd63dfa2 | |
bagyenda | ef53251db3 | |
bagyenda | dfc9f52994 | |
menulis | 53c8b46e57 | |
bagyenda | 83d1c98991 | |
bagyenda | dde519afc2 | |
bagyenda | 2a25a4cd3e | |
bagyenda | fa8e2b7f02 | |
bagyenda | 6972fad0fe |
|
@ -4,6 +4,7 @@
|
|||
*.patch
|
||||
*.lo
|
||||
*.o
|
||||
.gdb_history
|
||||
mpeg2dec-*.tar.gz
|
||||
Makefile
|
||||
Makefile.in
|
||||
|
@ -16,3 +17,9 @@ config.cache
|
|||
libtool
|
||||
config.status
|
||||
gmon.out
|
||||
autom4te.cache
|
||||
mbuni-config.h
|
||||
mbuni-config.h.in
|
||||
.cproject
|
||||
.project
|
||||
stamp-h1
|
||||
|
|
|
@ -0,0 +1,340 @@
|
|||
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) <year> <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) year 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.
|
1020
mbuni/ChangeLog
1020
mbuni/ChangeLog
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,8 @@
|
|||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004 Free
|
||||
Software Foundation, Inc.
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||
2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
@ -10,7 +10,10 @@ unlimited permission to copy, distribute and modify it.
|
|||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
|
@ -23,9 +26,9 @@ debugging `configure').
|
|||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. (Caching is
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.)
|
||||
cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
|
@ -35,20 +38,17 @@ some point `config.cache' contains results you don't want to keep, you
|
|||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You only need
|
||||
`configure.ac' if you want to change it or regenerate `configure' using
|
||||
a newer version of `autoconf'.
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./bootstrap' followed by `./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
Running `configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
|
@ -78,7 +78,7 @@ details on some of the pertinent environment variables.
|
|||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
|
@ -87,31 +87,29 @@ Compiling For Multiple Architectures
|
|||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
If you have to use a `make' that does not support the `VPATH'
|
||||
variable, you have to compile the package for one architecture at a
|
||||
time in the source code directory. After you have installed the
|
||||
package for one architecture, use `make distclean' before reconfiguring
|
||||
for another architecture.
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' will install the package's files in
|
||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||
installation prefix other than `/usr/local' by giving `configure' the
|
||||
option `--prefix=PREFIX'.
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
give `configure' the option `--exec-prefix=PREFIX', the package will
|
||||
use PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files will still use the regular prefix.
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
|
@ -159,7 +157,7 @@ where SYSTEM can have one of these forms:
|
|||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
|
@ -189,9 +187,14 @@ them in the `configure' command line, using `VAR=value'. For example:
|
|||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
will cause the specified gcc to be used as the C compiler (unless it is
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
SUBDIRS = autotools doc misc-patches mmlib mmsc mmsbox
|
||||
SUBDIRS = autotools doc mmlib mmsc mmsbox extras
|
||||
|
||||
EXTRA_DIST = GnuLICENSE KannelLICENSE bootstrap Notes todo
|
||||
EXTRA_DIST = VERSION GnuLICENSE KannelLICENSE bootstrap Notes
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
cvs
|
||||
$Date$
|
||||
|
||||
This file contains the version number of Mbuni, which must be on the first line. Second line is the date
|
||||
|
|
@ -4,7 +4,11 @@ set -e
|
|||
|
||||
# Check for automake
|
||||
amvers="no"
|
||||
if automake-1.9 --version >/dev/null 2>&1; then
|
||||
if automake-1.11 --version >/dev/null 2>&1; then
|
||||
amvers="-1.11"
|
||||
elif automake-1.10 --version >/dev/null 2>&1; then
|
||||
amvers="-1.10"
|
||||
elif automake-1.9 --version >/dev/null 2>&1; then
|
||||
amvers="-1.9"
|
||||
elif automake-1.8 --version >/dev/null 2>&1; then
|
||||
amvers="-1.8"
|
||||
|
|
|
@ -1,35 +1,51 @@
|
|||
dnl Mbuni - Open Source MMS Gateway
|
||||
dnl
|
||||
dnl Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
dnl Copyright (C) 2003 - 2011, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
dnl
|
||||
dnl Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
dnl
|
||||
dnl This program is free software, distributed under the terms of
|
||||
dnl the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
dnl
|
||||
AC_PREREQ(2.59)
|
||||
AC_PREREQ(2.61)
|
||||
|
||||
AC_INIT([mbuni],[cvs],[devel@mbuni.org])
|
||||
|
||||
dnl Set version
|
||||
|
||||
AC_MSG_CHECKING([Retrieving Mbuni version])
|
||||
M_VERSION=`head -n 1 VERSION`
|
||||
if test "x$M_VERSION" = "xcvs"; then
|
||||
CVS_DATE=`head -1 ChangeLog | cut -f 1 -d ' ' | sed 's/-//g'`
|
||||
M_VERSION="$M_VERSION-$CVS_DATE"
|
||||
fi
|
||||
|
||||
AC_MSG_RESULT([$M_VERSION])
|
||||
|
||||
AC_CONFIG_SRCDIR([mmlib/mms_util.c])
|
||||
AC_CONFIG_AUX_DIR(autotools)
|
||||
AM_INIT_AUTOMAKE([mbuni],[1.0.0-cvs])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AM_INIT_AUTOMAKE([mbuni],[$M_VERSION])
|
||||
AC_CONFIG_HEADERS([mbuni-config.h])
|
||||
AM_MAINTAINER_MODE
|
||||
AC_CANONICAL_HOST
|
||||
|
||||
dnl Checks for programs.
|
||||
AC_PROG_CC
|
||||
AC_PROG_LIBTOOL
|
||||
AC_PROG_RANLIB
|
||||
|
||||
dnl add mmlib to the include path
|
||||
INCLUDES='-I$(top_srcdir)/mmlib -I$(top_builddir)/mmlib'
|
||||
INCLUDES='-I$(top_srcdir)/mmlib -I$(top_builddir)/mmsc -I$(top_srcdir)/mmsc -I$(top_builddir)/mmsbox -I$(top_srcdir)/mmlib -I$(top_builddir)/mmsbox'
|
||||
AC_SUBST([INCLUDES])
|
||||
|
||||
|
||||
dnl Checks for libraries.
|
||||
AC_CHECK_LIB([dl], [dlsym])
|
||||
dnl AC_CHECK_LIB([iconv], [libiconv], [LIBS="$LIBS -liconv"])
|
||||
AC_CHECK_LIB([pthread], [pthread_create])
|
||||
dnl AC_CHECK_LIB([xml2], [xmlStrcasecmp], [],
|
||||
dnl AC_MSG_ERROR([LibXML2 is required]))
|
||||
AC_CHECK_FUNCS([backtrace])
|
||||
|
||||
dnl Checks for header files.
|
||||
AC_HEADER_DIRENT
|
||||
|
@ -53,23 +69,31 @@ AC_CHECK_FUNCS([floor localtime_r memset sqrt strerror strrchr strtol])
|
|||
|
||||
dnl Change a few things (a la kannel config)
|
||||
EXE_EXT=""
|
||||
LIB_EXT="a"
|
||||
case "$host" in
|
||||
*-sun-solaris*)
|
||||
CFLAGS="$CFLAGS -DSunOS=1"
|
||||
*-sun-solaris* | *SunOS* | *-pc-solaris*)
|
||||
CFLAGS="$CFLAGS -DSunOS=1 -D_POSIX_PTHREAD_SEMANTICS -D_REENTRANT"
|
||||
;;
|
||||
*-cygwin*)
|
||||
EXE_EXT=".exe"
|
||||
;;
|
||||
*apple-darwin*)
|
||||
CFLAGS="$CFLAGS -DDARWIN=1"
|
||||
CFLAGS="$CFLAGS -DDARWIN=1 -O4 -Wall -D_REENTRANT=1"
|
||||
LIB_EXT="dylib"
|
||||
allow_undefined_flag='-flat_namespace -undefined suppress'
|
||||
;;
|
||||
*-linux-*)
|
||||
CFLAGS="$CFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE"
|
||||
*-linux*)
|
||||
CFLAGS="$CFLAGS -D_XOPEN_SOURCE=600 -D_BSD_SOURCE -O4 -Wall -D_REENTRANT=1"
|
||||
LDFLAGS="$LDFLAGS -rdynamic"
|
||||
;;
|
||||
*-*-openbsd* | *-*-freebsd*)
|
||||
*-*-openbsd*)
|
||||
CFLAGS="$CFLAGS -pthread"
|
||||
AC_CHECK_LIB(c_r, pthread_exit, [LIBS="$LIBS -lc_r -lkse"; pthread="yes"])
|
||||
AC_CHECK_LIB(c_r, pthread_exit, [LIBS="$LIBS -lc_r -lpthread"; pthread="yes"])
|
||||
;;
|
||||
*-*-freebsd*)
|
||||
LDFLAGS="$LDFLAGS -export-dynamic"
|
||||
CFLAGS="$CFLAGS -DFREEBSD=1 -pthread"
|
||||
AC_CHECK_LIB(c_r, pthread_exit, [LIBS="$LIBS -lc_r -lpthread"; pthread="yes"])
|
||||
;;
|
||||
esac
|
||||
|
||||
|
@ -81,6 +105,15 @@ AC_ARG_WITH(libs,
|
|||
[ --with-libs=FLAGS use FLAGS for extra libraries],
|
||||
LIBS="$LIBS $withval")
|
||||
|
||||
dnl Check for large file handling
|
||||
AC_SYS_LARGEFILE(CFLAGS)
|
||||
if test "${ac_cv_sys_file_offset_bits}" != no ; then
|
||||
CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=${ac_cv_sys_file_offset_bits}"
|
||||
fi
|
||||
if test "${ac_cv_sys_large_files}" != "no" ; then
|
||||
CFLAGS="$CFLAGS -D_LARGE_FILES=${ac_cv_sys_large_files}"
|
||||
fi
|
||||
|
||||
dnl implement SSL stuff.
|
||||
|
||||
dnl Implement the --with-ssl option.
|
||||
|
@ -116,7 +149,7 @@ if test "$ssl" = "yes" ; then
|
|||
dnl test only if --with-ssl has not been used
|
||||
if test "x$ssllib" = "x" && test "x$sslinc" = "x"; then
|
||||
for loc in /usr/lib /usr/local/ssl/lib /usr/local/openssl/lib; do
|
||||
if test -f "$loc/libssl.a"; then
|
||||
if test -f "$loc/libssl.$LIB_EXT"; then
|
||||
ssllib="$loc"
|
||||
fi
|
||||
done
|
||||
|
@ -225,8 +258,9 @@ else
|
|||
AC_MSG_RESULT([$gw_version])
|
||||
AC_MSG_CHECKING([Kannel libs])
|
||||
if ! $GW_CONFIG --libs &>/dev/null ; then
|
||||
LDFLAGS="$LDFLAGS `$GW_CONFIG --libs`"
|
||||
gw_libdir=`$GW_CONFIG --libs`
|
||||
LDFLAGS="$LDFLAGS $gw_libdir"
|
||||
LIBS="$LIBS $gw_libdir"
|
||||
AC_MSG_RESULT([$gw_libdir])
|
||||
fi
|
||||
AC_MSG_CHECKING([Kannel includes])
|
||||
|
@ -240,18 +274,105 @@ fi
|
|||
AC_CHECK_LIB([gwlib], [cfg_create], [], AC_MSG_ERROR([Kannel gwlib is required!]))
|
||||
AC_CHECK_LIB([wap], [wsp_headers_pack], [], AC_MSG_ERROR([Kannel WAP lib is required!]))
|
||||
|
||||
dnl Implement the --with-pgsql-dir option.
|
||||
pgsqlloc="/usr/local/pgsql"
|
||||
AC_ARG_WITH(pgsql-dir,
|
||||
[ --with-pgsql-dir=DIR where to look for PostgreSQL libs and header files
|
||||
DIR points to the installation [/usr/local/pgsql] ],
|
||||
[
|
||||
pgsqlloc=""
|
||||
if test -d "$withval" ; then
|
||||
pgsqlloc="$withval"
|
||||
fi
|
||||
])
|
||||
|
||||
AC_PATH_PROG(PGSQL_CONFIG, pg_config, no, [$pgsqlloc/bin:$pgsqlloc:/usr/lib/postgresql/bin:${PATH}])
|
||||
dnl check for PgSQL >= 7.2 style pg_config information
|
||||
if test "$PGSQL_CONFIG" = "no"; then
|
||||
found=""
|
||||
for loc in $pgsqlloc /usr /usr/local ; do
|
||||
if test "x$found" = "x" ; then
|
||||
AC_MSG_CHECKING([for PostgresSQL include files in])
|
||||
AC_MSG_RESULT($loc)
|
||||
AC_CHECK_FILE("$loc/include/postgresql/libpq-fe.h",
|
||||
[CFLAGS="$CFLAGS -I$loc/include/postgresql"; LIBS="-L$loc/lib/postgresql -lpq $LIBS"]; found=1,
|
||||
[AC_CHECK_FILE("$loc/include/pgsql/libpq-fe.h",
|
||||
[CFLAGS="$CFLAGS -I$loc/include/pgsql"; LIBS=" -L$loc/lib/pgsql $LIBS -lpq"]; found=1,
|
||||
[AC_CHECK_FILE("$loc/pgsql/include/libpq-fe.h",
|
||||
[CFLAGS="-I$loc/pgsql/include $CFLAGS"; LIBS="-L$loc/pgsql/lib $LIBS -lpq"]; found=1,
|
||||
)]
|
||||
)]
|
||||
)
|
||||
fi
|
||||
done
|
||||
|
||||
else
|
||||
dnl pg_config found
|
||||
AC_MSG_CHECKING([PostgreSQL version])
|
||||
pgsql_version=`$PGSQL_CONFIG --version`
|
||||
AC_MSG_RESULT([$pgsql_version])
|
||||
AC_MSG_CHECKING([PostgreSQL libs])
|
||||
if $PGSQL_CONFIG --libdir &>/dev/null ; then
|
||||
LIBS="-L`$PGSQL_CONFIG --libdir` $LIBS -lpq "
|
||||
pg_libdir="`$PGSQL_CONFIG --libdir`"
|
||||
AC_MSG_RESULT([$pg_libdir])
|
||||
fi
|
||||
AC_MSG_CHECKING([PostgreSQL includes])
|
||||
if $PGSQL_CONFIG --includedir &>/dev/null ; then
|
||||
CFLAGS="-I`$PGSQL_CONFIG --includedir` $CFLAGS"
|
||||
pg_incdir=`$PGSQL_CONFIG --includedir`
|
||||
AC_MSG_RESULT([$pg_incdir])
|
||||
fi
|
||||
fi
|
||||
# set HAVE_LIBpq if we have libpq
|
||||
AC_CHECK_LIB([pq], [PQexec], [has_pgsql=true])
|
||||
|
||||
AM_CONDITIONAL([BUILD_PGSQLQ], [test x$has_pgsql = xtrue])
|
||||
|
||||
# Look for curl lib
|
||||
AC_PATH_PROG(CURL_CONFIG, curl-config, no, [${PATH}])
|
||||
if test "$CURL_CONFIG" != "no"; then
|
||||
dnl curl-config found
|
||||
AC_MSG_CHECKING([curl lib version])
|
||||
curl_version=`$CURL_CONFIG --version`
|
||||
AC_MSG_RESULT([$curl_version])
|
||||
AC_MSG_CHECKING([curl libs])
|
||||
if $CURL_CONFIG --libs &>/dev/null ; then
|
||||
curl_libs=`$CURL_CONFIG --libs`
|
||||
AC_MSG_RESULT([$curl_libs])
|
||||
LIBS="$LIBS $curl_libs"
|
||||
fi
|
||||
AC_MSG_CHECKING([curl includes])
|
||||
if $CURL_CONFIG --cflags &>/dev/null ; then
|
||||
curl_cflags=`$CURL_CONFIG --cflags`
|
||||
CFLAGS="$curl_cflags $CFLAGS"
|
||||
AC_MSG_RESULT([$curl_cflags])
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CHECK_LIB([curl], [curl_global_init], [
|
||||
CFLAGS="-DHAVE_LIBCURL=1 $CFLAGS";
|
||||
has_libcurl=true
|
||||
])
|
||||
|
||||
AM_CONDITIONAL([BUILD_MMSBOXMM1], [test x$has_libcurl = xtrue])
|
||||
|
||||
dnl Add mbuni version to Cflags
|
||||
# CFLAGS="$CFLAGS -DMBUNI_VERSION=\"$M_VERSION\""
|
||||
AC_DEFINE_UNQUOTED(MBUNI_VERSION, "$M_VERSION", "Mbuni Version")
|
||||
|
||||
dnl May be we need to check for media conversion tools (imagemagick, etc)?
|
||||
|
||||
|
||||
AC_CONFIG_FILES([Makefile autotools/Makefile doc/Makefile doc/examples/Makefile doc/images/Makefile misc-patches/Makefile mmlib/Makefile mmsc/Makefile mmsbox/Makefile])
|
||||
AC_CONFIG_FILES([Makefile autotools/Makefile doc/Makefile doc/examples/Makefile doc/images/Makefile mmlib/Makefile mmsc/Makefile mmsbox/Makefile extras/Makefile extras/pgsql-queue/Makefile extras/mmsbox-mm1/Makefile])
|
||||
|
||||
AC_OUTPUT
|
||||
|
||||
cat<<X
|
||||
License:
|
||||
Mbuni - Open Source MMS Gateway - http://www.mbuni.org/
|
||||
Mbuni (version $M_VERSION) - Open Source MMS Gateway - http://www.mbuni.org/
|
||||
|
||||
Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
Copyright (C) 2003 - 2011, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
|
||||
This program is free software, distributed under the terms of
|
||||
the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
#!/bin/sh
|
||||
|
||||
MBUNI=/usr/local/mbuni
|
||||
BINDIR=$MBUNI/bin
|
||||
PIDFILES=$MBUNI/run
|
||||
CONF=$MBUNI/etc/mmsc.conf
|
||||
|
||||
MP=mmsproxy
|
||||
MR=mmsrelay
|
||||
|
||||
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$MBUNI/lib/mbuni
|
||||
|
||||
export LD_LIBRARY_PATH
|
||||
|
||||
test -x $BINDIR/$MP && test -x $BINDIR/$MR || exit 0
|
||||
|
||||
case "$1" in
|
||||
start)
|
||||
echo -n "Starting MMSC: mmsproxy"
|
||||
$BINDIR/$MP --daemonize --parachute --pid-file $PIDFILES/$MP.pid -- $CONF
|
||||
sleep 1
|
||||
echo -n " mmsrelay"
|
||||
$BINDIR/$MR --daemonize --parachute --pid-file $PIDFILES/$MR.pid -- $CONF
|
||||
echo "."
|
||||
;;
|
||||
|
||||
stop)
|
||||
echo -n "Stopping MMSC: mmsrelay"
|
||||
kill `cat $PIDFILES/$MR.pid`
|
||||
sleep 1
|
||||
echo -n " mmsproxy"
|
||||
kill `cat $PIDFILES/$MP.pid`
|
||||
echo "."
|
||||
;;
|
||||
|
||||
reload)
|
||||
# We don't have support for this yet.
|
||||
exit 1
|
||||
;;
|
||||
|
||||
restart|force-reload)
|
||||
$0 stop
|
||||
sleep 1
|
||||
$0 start
|
||||
;;
|
||||
|
||||
*)
|
||||
echo "Usage: $0 {start|stop|reload|restart|force-reload}"
|
||||
exit 1
|
||||
|
||||
esac
|
||||
|
||||
exit 0
|
|
@ -1 +1,2 @@
|
|||
SUBDIRS = examples images
|
||||
EXTRA_DIST = userguide.shtml
|
||||
|
|
|
@ -1 +1 @@
|
|||
EXTRA_DIST = mmsc.conf
|
||||
EXTRA_DIST = mmsc.conf mmsbox.conf
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
group = core
|
||||
log-file = /var/log/mmsbox.log
|
||||
access-log = /var/log/mmsbox-access.log
|
||||
log-level = 0
|
||||
|
||||
group = mbuni
|
||||
storage-directory = /var/spool/mbuni
|
||||
max-send-threads = 5
|
||||
maximum-send-attempts = 50
|
||||
default-message-expiry = 360000
|
||||
queue-run-interval = 5
|
||||
send-attempt-back-off = 300
|
||||
sendmms-port = 10001
|
||||
|
||||
group = mmsc
|
||||
id = local
|
||||
mmsc-url = http://mbuni:test@localhost:1982/soap
|
||||
incoming-username = user
|
||||
incoming-password = pass
|
||||
incoming-port = 12345
|
||||
type = soap
|
||||
|
||||
# Sample conf for MMSBox using a modem (MM1)
|
||||
group = mmsc
|
||||
id = modem
|
||||
type = mm1
|
||||
mm1-sms-on-command = lynx -dump 'http://localhost:13000/start-smsc?password=bar&smsc=nokia-modem'
|
||||
mm1-sms-off-command = lynx -dump 'http://localhost:13000/stop-smsc?password=bar&smsc=nokia-modem'
|
||||
mm1-msisdn = "100"
|
||||
mm1-http-proxy = 10.11.12.13:8080
|
||||
incoming-port = 13014
|
||||
mmsc-url = http://net.mmsc/servlets/mms
|
||||
mm1-gprs-on-command = /usr/local/sbin/start-net-gprs
|
||||
mm1-gprs-pid-command = "cat /var/run/ppp-net.pid|head -1"
|
||||
|
||||
group = mms-service
|
||||
name = me
|
||||
post-url = http://localhost/~bagyenda/test-mbuni.php
|
||||
catch-all = true
|
||||
http-post-parameters = fx=true&images[]=%i&text[]=%t&skip=1
|
||||
accept-x-mbuni-headers = true
|
||||
pass-thro-headers = X-NOKIA-MMSC-Charging,X-NOKIA-MMSC-Charged-Party
|
||||
keyword = test
|
||||
omit-empty = no
|
||||
suppress-reply = true
|
||||
service-code = regular
|
||||
|
||||
group = mms-service
|
||||
name = fullmessage
|
||||
get-url = http://localhost/images/apache_pb.gif
|
||||
# http-post-parameters = fx=true&image=%i&text=%t
|
||||
accept-x-mbuni-headers = true
|
||||
keyword = thixs
|
||||
|
||||
group = send-mms-user
|
||||
username = tester
|
||||
password = foobar
|
||||
faked-sender = 100
|
||||
|
|
@ -1,21 +1,24 @@
|
|||
group = core
|
||||
log-file = /tmp/log/mbuni.log
|
||||
access-log = /tmp/log/access.log
|
||||
log-file = /tmp/log/mbuni-mmsc.log
|
||||
access-log = /tmp/log/mmsc-access.log
|
||||
log-level = 0
|
||||
|
||||
group = mbuni
|
||||
name = "My MMSC"
|
||||
hostname = ds.co.ug
|
||||
host-alias = mmsc
|
||||
local-mmsc-domains = dsmagic.com
|
||||
local-prefixes = 037;+25637;25637
|
||||
storage-directory = /tmp/spool
|
||||
max-send-threads = 5
|
||||
send-mail-prog = /usr/sbin/sendmail -f '%f' '%t'
|
||||
unified-prefix = "+25637,037,37"
|
||||
maximum-send-attempts = 50
|
||||
mm1-maximum-notify-attempts = 1
|
||||
default-message-expiry = 360000
|
||||
queue-run-interval = 0.1
|
||||
max-message-expiry = 720000
|
||||
mmsc-services = Relay,MM1
|
||||
queue-run-interval = 5
|
||||
mm1-queue-run-interval = 300
|
||||
send-attempt-back-off = 300
|
||||
sendsms-url = http://localhost:13013/cgi-bin/sendsms
|
||||
sendsms-username = tester
|
||||
|
@ -31,59 +34,20 @@ billing-module-parameters = "/tmp/log/cdr.log"
|
|||
content-adaptation = true
|
||||
notify-unprovisioned = yes
|
||||
mms-notify-text = "You have received a multimedia message from %S, go to XXX to view it"
|
||||
mm-box-host = local.ds.co.ug
|
||||
mms-notify-unprovisioned-text = "This is a test"
|
||||
mms-to-email-txt = "This is a multimedia message (HTML suppressed)"
|
||||
mms-to-email-html = "This is a multimedia message powered by <emph>Digital Solutions</emph>"
|
||||
mms-to-email-default-subject = "This is a multimedia message"
|
||||
mms-message-too-large-txt = "You have received a multimedia message from %S that is too large for your phone. Go to xxx to view it"
|
||||
sendmms-port = 10001
|
||||
|
||||
group = send-mms-user
|
||||
username = tester
|
||||
password = foobar
|
||||
# faked-sender = 100
|
||||
|
||||
group = send-mms-user
|
||||
username = binary
|
||||
password = "user"
|
||||
faked-sender = 111
|
||||
|
||||
group = mmsc
|
||||
id = testone
|
||||
mmsc-url = http://mbuni:test@192.168.129.52:8080/eaif
|
||||
# mmsc-url = http://localhost:8080/vasp/servlet/messagerouter
|
||||
incoming-username = user
|
||||
incoming-password = pass
|
||||
incoming-port = 10002
|
||||
type = eaif
|
||||
|
||||
group = mms-service
|
||||
name = me
|
||||
file = /tmp/start.smil
|
||||
catch-all = true
|
||||
# http-post-parameters = fx=true&images.=%i&text.=%t
|
||||
accept-x-mbuni-headers = true
|
||||
keyword = test
|
||||
|
||||
group = mms-service
|
||||
name = fullmessage
|
||||
get-url = http://localhost/~bagyenda/images/apache_pb.gif
|
||||
# http-post-parameters = fx=true&image=%i&text=%t
|
||||
accept-x-mbuni-headers = true
|
||||
keyword = thixs
|
||||
|
||||
strip-prefixes = "1;2"
|
||||
|
||||
group = mms-vasp
|
||||
vasp-id = newscorp
|
||||
type = soap
|
||||
short-code = 111
|
||||
vasp-username = newscorp
|
||||
vasp-password = news123
|
||||
vasp-url = http://localhost:23535/
|
||||
mmsc-username = user
|
||||
mmsc-password = secret
|
||||
mms-to-email-handler = true
|
||||
mms-to-local-copy-handler = true
|
||||
vasp-username = mbuni
|
||||
vasp-password = test
|
||||
vasp-url = http://user:pass@localhost:12345/
|
||||
|
||||
group = mmsproxy
|
||||
name = "A test mms proxy"
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,7 @@
|
|||
if BUILD_PGSQLQ
|
||||
X = pgsql-queue
|
||||
endif
|
||||
if BUILD_MMSBOXMM1
|
||||
Y = mmsbox-mm1
|
||||
endif
|
||||
SUBDIRS = $(X) $(Y)
|
|
@ -0,0 +1,3 @@
|
|||
lib_LTLIBRARIES = libmmsbox_mm1.la
|
||||
libmmsbox_mm1_la_SOURCES = mmsbox_mm1.c
|
||||
libmmsbox_mm1_la_LDFLAGS = -module
|
|
@ -0,0 +1,761 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* Mbuni MmsBox MM1 Component - Send & Receive MMS using a GPRS/EDGE/3G modem
|
||||
*
|
||||
* Copyright (C) 2007-2009, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include "mmsbox_mmsc.h"
|
||||
#include "mmsbox_cfg.h"
|
||||
#include "mmsbox.h"
|
||||
#include "mms_util.h"
|
||||
|
||||
typedef struct {
|
||||
Octstr *mmsc_url; /* mmsc-url. */
|
||||
Octstr *msisdn; /* my msisdn. */
|
||||
Octstr *proxy; /* form is host:port. */
|
||||
Octstr *gprs_on; /* Command to start GPRS link. Must not exit. */
|
||||
Octstr *gprs_off; /* Command to stop GPRS link. */
|
||||
Octstr *gprs_pid; /* command to call to get PID of GPRS for stopping GPRS link (i.e. pppd). */
|
||||
Octstr *smsc_on; /* command to start smsc connection */
|
||||
Octstr *smsc_off; /* commadn to stop smsc connection */
|
||||
int port; /* port for incoming messages. */
|
||||
Octstr *interface; /* specific interface to listen on. */
|
||||
|
||||
Octstr *unified_prefix; /* copies from above, do not edit! */
|
||||
List *strip_prefixes;
|
||||
|
||||
/* internal data. */
|
||||
MmscGrp *info;
|
||||
MmsQueueHandlerFuncs *qfs;
|
||||
List *requests; /* list of requests. */
|
||||
long h_tid, d_tid; /* thread IDs. */
|
||||
|
||||
int sender_alive;
|
||||
|
||||
} MM1Settings;
|
||||
|
||||
typedef struct {
|
||||
enum {MM1_GET, MM1_PUSH} type;
|
||||
int waiter_exists; /* set to true if after handling, should signal and NOT destroy struct.*/
|
||||
pthread_cond_t cond;
|
||||
pthread_mutex_t mutex;
|
||||
union {
|
||||
MmsMsg *m; /* for push. */
|
||||
Octstr *url; /* for get */
|
||||
} u;
|
||||
void *result; /* set to the result for a PUSH */
|
||||
Octstr *error;
|
||||
} MM1Request;
|
||||
|
||||
static void stop_gprs(Octstr *cmd);
|
||||
static void handle_notify(MM1Settings *mm1);
|
||||
static void handle_mm1(MM1Settings *mm1);
|
||||
static int open_mm1(MmscGrp *mmc, MmsQueueHandlerFuncs *qfs,
|
||||
Octstr *unified_prefix, List *strip_prefixes,
|
||||
void **data)
|
||||
{
|
||||
Octstr *x, *y;
|
||||
List *l;
|
||||
Octstr *mmsc_url = NULL;
|
||||
Octstr *proxy = NULL;
|
||||
Octstr *gprs_on = NULL;
|
||||
Octstr *gprs_off = NULL;
|
||||
Octstr *gprs_pid = NULL;
|
||||
Octstr *smsc_on = NULL;
|
||||
Octstr *smsc_off = NULL;
|
||||
int port = 80;
|
||||
Octstr *interface = NULL;
|
||||
Octstr *msisdn = NULL;
|
||||
|
||||
MM1Settings *mm1;
|
||||
|
||||
/* parse the settings. */
|
||||
|
||||
x = octstr_duplicate(mmc->settings);
|
||||
l = octstr_split(x, octstr_imm(";"));
|
||||
octstr_destroy(x);
|
||||
if (l)
|
||||
while ((y = gwlist_extract_first(l)) != NULL) {
|
||||
int i = octstr_search_char(y, '=', 0);
|
||||
Octstr *item = (i>=0) ? octstr_copy(y, 0, i) : NULL;
|
||||
Octstr *value = (i>=0) ? octstr_copy(y, i+1, octstr_len(y)) : NULL;
|
||||
|
||||
if (item == NULL)
|
||||
octstr_destroy(value);
|
||||
else if (octstr_str_case_compare(item, "mmsc-url") == 0)
|
||||
mmsc_url = value;
|
||||
else if (octstr_str_case_compare(item, "proxy") == 0)
|
||||
proxy = value;
|
||||
else if (octstr_str_case_compare(item, "gprs-on") == 0)
|
||||
gprs_on = value;
|
||||
else if (octstr_str_case_compare(item, "gprs-off") == 0)
|
||||
gprs_off = value;
|
||||
else if (octstr_str_case_compare(item, "gprs-pid") == 0)
|
||||
gprs_pid = value;
|
||||
else if (octstr_str_case_compare(item, "port") == 0) {
|
||||
port = value ? atoi(octstr_get_cstr(value)) : 80;
|
||||
if (http_open_port(port, 0) != 0)
|
||||
mms_warning(0, "mmsbox-mm1", NULL, "failed to open incoming notifications port %d: %s",
|
||||
port, strerror(errno));
|
||||
}else if (octstr_str_case_compare(item, "http-interface") == 0)
|
||||
interface = value;
|
||||
else if (octstr_str_case_compare(item, "smsc-on") == 0)
|
||||
smsc_on = value;
|
||||
else if (octstr_str_case_compare(item, "smsc-off") == 0)
|
||||
smsc_off = value;
|
||||
else if (octstr_str_case_compare(item, "msisdn") == 0)
|
||||
msisdn = value;
|
||||
else {
|
||||
mms_error(0, "mmsbox-mm1", NULL, "unknown/unsupported option: %s", octstr_get_cstr(item));
|
||||
octstr_destroy(value);
|
||||
}
|
||||
octstr_destroy(item);
|
||||
octstr_destroy(y);
|
||||
}
|
||||
else {
|
||||
mms_error(0, "mmsbox-mm1", NULL, "failed to parse settings string: %s", octstr_get_cstr(mmc->settings));
|
||||
return -1;
|
||||
}
|
||||
|
||||
gwlist_destroy(l, NULL);
|
||||
|
||||
mm1 = gw_malloc(sizeof *mm1);
|
||||
mm1->mmsc_url = mmsc_url;
|
||||
mm1->proxy = proxy;
|
||||
mm1->gprs_on = gprs_on;
|
||||
mm1->gprs_off = gprs_off;
|
||||
mm1->gprs_pid = gprs_pid;
|
||||
mm1->smsc_on = smsc_on;
|
||||
mm1->smsc_off = smsc_off;
|
||||
mm1->port = port;
|
||||
mm1->interface = interface;
|
||||
mm1->msisdn = msisdn;
|
||||
|
||||
mm1->unified_prefix = unified_prefix;
|
||||
mm1->strip_prefixes = strip_prefixes;
|
||||
|
||||
mm1->qfs = qfs;
|
||||
mm1->info = mmc;
|
||||
mm1->requests = gwlist_create();
|
||||
mm1->sender_alive = 0;
|
||||
gwlist_add_producer(mm1->requests); /* so that when first listener starts, knows there is a consumer. */
|
||||
mm1->h_tid = gwthread_create((gwthread_func_t *)handle_notify, mm1);
|
||||
mm1->d_tid = gwthread_create((gwthread_func_t *)handle_mm1, mm1);
|
||||
|
||||
*data = mm1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void handle_notify(MM1Settings *mm1)
|
||||
{
|
||||
HTTPClient *client = NULL;
|
||||
Octstr *ip = NULL, *url = NULL;
|
||||
Octstr *body = NULL;
|
||||
List *cgivars = NULL, *h = NULL;
|
||||
|
||||
while ((client = http_accept_request(mm1->port, &ip, &url, &h, &body, &cgivars)) != NULL) {
|
||||
List *cgivar_ctypes = NULL;
|
||||
Octstr *text, *rb = NULL, *s = NULL, *loc = NULL;
|
||||
MmsMsg *m = NULL;
|
||||
int hdrlen, status = HTTP_ACCEPTED, mtype;
|
||||
List *mh = NULL, *to = gwlist_create(), *rh = http_create_empty_headers();
|
||||
time_t expiryt = -1, deliveryt = -1;
|
||||
Octstr *from = NULL, *subject = NULL, *otransid = NULL, *mmc_id = NULL;
|
||||
Octstr *qdir;
|
||||
|
||||
|
||||
|
||||
parse_cgivars(h, body, &cgivars, &cgivar_ctypes);
|
||||
text = http_cgi_variable(cgivars, "text");
|
||||
|
||||
if (!text) {
|
||||
rb = octstr_imm("mmsbox-mm1: missing 'text' CGI parameter!");
|
||||
status = HTTP_NOT_FOUND;
|
||||
goto loop;
|
||||
}
|
||||
/* now parse the MMS, determine what kind it is,
|
||||
queue the fetch request or deal with it directly.
|
||||
*/
|
||||
hdrlen = octstr_get_char(text, 2);
|
||||
if ((s = octstr_copy(text, 3 + hdrlen, octstr_len(text))) != NULL)
|
||||
m = mms_frombinary(s, mm1->msisdn);
|
||||
else
|
||||
m = NULL;
|
||||
|
||||
if (m == NULL) {
|
||||
rb = octstr_imm("mmsbox-mm1: mal-formed mms packet on interface!");
|
||||
status = HTTP_FORBIDDEN;
|
||||
goto loop;
|
||||
} else
|
||||
mms_msgdump(m, 1);
|
||||
|
||||
/* rest of this copied largely from EAIF code. */
|
||||
mh = mms_message_headers(m);
|
||||
mtype = mms_messagetype(m);
|
||||
mms_collect_envdata_from_msgheaders(mh, &to, &subject,
|
||||
&otransid, &expiryt, &deliveryt,
|
||||
DEFAULT_EXPIRE, -1,
|
||||
octstr_get_cstr(mm1->unified_prefix),
|
||||
mm1->strip_prefixes);
|
||||
from = http_header_value(mh, octstr_imm("From"));
|
||||
|
||||
qdir = get_mmsbox_queue_dir(from, to, mm1->info, &mmc_id); /* get routing info. */
|
||||
switch (mtype) {
|
||||
Octstr *qf;
|
||||
Octstr *dlr_url, *status_value, *msgid;
|
||||
List *rqh;
|
||||
case MMS_MSGTYPE_DELIVERY_IND: /* notification of a delivery. */
|
||||
case MMS_MSGTYPE_READ_ORIG_IND: /* message read. */
|
||||
msgid = http_header_value(mh, octstr_imm("Message-ID"));
|
||||
status_value = http_header_value(mh,
|
||||
(mtype == MMS_MSGTYPE_DELIVERY_IND) ?
|
||||
octstr_imm("X-Mms-Status") :
|
||||
octstr_imm("X-Mms-Read-Status"));
|
||||
|
||||
rqh = http_create_empty_headers();
|
||||
|
||||
dlr_url = mmsbox_get_report_info(m, mm1->info, mmc_id,
|
||||
(mtype == MMS_MSGTYPE_DELIVERY_IND) ?
|
||||
"delivery-report" : "read-report",
|
||||
status_value, rqh, NULL, 0, msgid);
|
||||
|
||||
qf = mm1->qfs->mms_queue_add(from, to, NULL,
|
||||
mm1->info->id, mmc_id,
|
||||
0, time(NULL) + default_msgexpiry, m, NULL,
|
||||
NULL, NULL,
|
||||
dlr_url, NULL,
|
||||
rqh,
|
||||
0,
|
||||
octstr_get_cstr(qdir),
|
||||
"MM7/MM1-IN",
|
||||
octstr_imm(MM_NAME));
|
||||
if (qf)
|
||||
/* Log to access log */
|
||||
mms_log((mtype == MMS_MSGTYPE_DELIVERY_IND) ? "Received DLR" : "Received RR",
|
||||
from, to, -1, msgid, status_value, mm1->info->id,
|
||||
"MMSBox", octstr_imm("MM1"), NULL);
|
||||
else
|
||||
status = HTTP_INTERNAL_SERVER_ERROR;
|
||||
octstr_destroy(qf);
|
||||
octstr_destroy(msgid);
|
||||
octstr_destroy(dlr_url);
|
||||
octstr_destroy(status_value);
|
||||
http_destroy_headers(rqh);
|
||||
break;
|
||||
|
||||
case MMS_MSGTYPE_NOTIFICATION_IND: /* notification of an incoming message. */
|
||||
if ((loc = http_header_value(mh, octstr_imm("X-Mms-Content-Location"))) != NULL) {
|
||||
MM1Request *r = gw_malloc(sizeof *r);
|
||||
|
||||
memset(r, 0, sizeof *r);
|
||||
r->type = MM1_GET;
|
||||
r->u.url = loc;
|
||||
r->waiter_exists = 0;
|
||||
loc = NULL;
|
||||
|
||||
gwlist_produce(mm1->requests, r);
|
||||
} else
|
||||
rb = octstr_format("mmsbox-mm1: notification with content-location??");
|
||||
break;
|
||||
default:
|
||||
rb = octstr_format("mmsbox-mm1: unexpected message type: %s",
|
||||
mms_message_type_to_cstr(mtype));
|
||||
status = HTTP_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
loop:
|
||||
/* send reply. */
|
||||
http_header_add(rh, "Content-Type", "text/plain");
|
||||
http_send_reply(client, status, rh, rb ? rb : octstr_imm(""));
|
||||
|
||||
octstr_destroy(s);
|
||||
octstr_destroy(ip);
|
||||
octstr_destroy(url);
|
||||
octstr_destroy(loc);
|
||||
octstr_destroy(mmc_id);
|
||||
octstr_destroy(from);
|
||||
octstr_destroy(subject);
|
||||
octstr_destroy(otransid);
|
||||
octstr_destroy(body);
|
||||
octstr_destroy(rb);
|
||||
|
||||
gwlist_destroy(to, (void *)octstr_destroy);
|
||||
http_destroy_headers(h);
|
||||
http_destroy_headers(rh);
|
||||
http_destroy_headers(mh);
|
||||
http_destroy_cgiargs(cgivars);
|
||||
http_destroy_cgiargs(cgivar_ctypes);
|
||||
mms_destroy(m);
|
||||
}
|
||||
|
||||
mms_info(0, "mmsbox-mm1", NULL, "handle_notify exits");
|
||||
gwlist_remove_producer(mm1->requests); /* cause consumers to shut down. */
|
||||
}
|
||||
|
||||
|
||||
static Octstr *send_msg(void *data, Octstr *from, Octstr *to,
|
||||
Octstr *transid,
|
||||
Octstr *linkedid, char *vasid, Octstr *service_code,
|
||||
MmsMsg *m, List *hdrs, Octstr **err, int *retry)
|
||||
{
|
||||
MM1Request *r = gw_malloc(sizeof *r);
|
||||
MM1Settings *s = data;
|
||||
Octstr *id;
|
||||
|
||||
gw_assert(data);
|
||||
gw_assert(m);
|
||||
|
||||
if (!s->sender_alive) {
|
||||
*err = octstr_imm("internal error, mm1 notify not started!");
|
||||
*retry = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Remove the from address first of all, replace the to address as well */
|
||||
mms_replace_header_value(m, "From", "#insert");
|
||||
mms_replace_header_value(m, "To", octstr_get_cstr(to));
|
||||
mms_remove_headers(m, "Message-ID");
|
||||
|
||||
r->u.m = m;
|
||||
pthread_cond_init(&r->cond, NULL);
|
||||
pthread_mutex_init(&r->mutex, NULL);
|
||||
r->waiter_exists = 1;
|
||||
r->type = MM1_PUSH;
|
||||
r->result = NULL;
|
||||
r->error = NULL;
|
||||
|
||||
pthread_mutex_lock(&r->mutex); /* at pickup, must grab mutex before signalling. otherwise race condition.*/
|
||||
|
||||
gwlist_produce(s->requests, r);
|
||||
|
||||
pthread_cond_wait(&r->cond, &r->mutex);
|
||||
|
||||
*err = r->error;
|
||||
|
||||
id = r->result;
|
||||
mms_info(0, "mmsbox-mm1", NULL, "sent message, type=%s, result=%s",
|
||||
mms_message_type_to_cstr(mms_messagetype(m)), r->error ? octstr_get_cstr(r->error) : "(none)");
|
||||
/* destroy the structure. */
|
||||
if(r->error && (octstr_compare(r->error, octstr_imm("Error-service-denied")) == 0 ||
|
||||
octstr_compare(r->error, octstr_imm("Error-permanent-failure")) == 0))
|
||||
*retry = 0;
|
||||
else
|
||||
*retry = 1;
|
||||
|
||||
pthread_cond_destroy(&r->cond);
|
||||
pthread_mutex_destroy(&r->mutex);
|
||||
gw_free(r);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
static long start_gprs(Octstr *cmd, Octstr *pid_cmd);
|
||||
static Octstr *fetch_content(Octstr *url, Octstr *proxy, Octstr *body, int *hstatus);
|
||||
static void handle_mm1(MM1Settings *mm1)
|
||||
{
|
||||
/* stop smsc, start GPRS, transact, stop GPRS, start SMSC. And so on. */
|
||||
MM1Request *r;
|
||||
|
||||
mms_info(0, "mmsbox-mm1", NULL, "handle_mm1 started");
|
||||
mm1->sender_alive++;
|
||||
while ((r = gwlist_consume(mm1->requests)) != NULL) {
|
||||
long n, pid = -1;
|
||||
if (mm1->smsc_off) {
|
||||
n = system(octstr_get_cstr(mm1->smsc_off));
|
||||
gwthread_sleep(5); /* allow it to die. */
|
||||
}
|
||||
if (mm1->gprs_on)
|
||||
pid = start_gprs(mm1->gprs_on, mm1->gprs_pid);
|
||||
|
||||
if (pid < 0) {
|
||||
mms_warning(0, "mmsbox-mm1", NULL,
|
||||
"Failed to start GPRS connection. waiting...");
|
||||
gwthread_sleep(2);
|
||||
goto kill_gprs;
|
||||
} else
|
||||
mms_info(0, "mmsbox-mm1", NULL, "start_gprs returned PID: %ld", pid);
|
||||
|
||||
do {
|
||||
Octstr *body;
|
||||
Octstr *url;
|
||||
int hstatus = 0;
|
||||
Octstr *ms;
|
||||
MmsMsg *m;
|
||||
int msize;
|
||||
|
||||
if (r->waiter_exists)
|
||||
pthread_mutex_lock(&r->mutex); /* grab lock to avoid race condition */
|
||||
|
||||
body = (r->type == MM1_PUSH) ? mms_tobinary(r->u.m) : NULL;
|
||||
url = (r->type == MM1_PUSH) ? mm1->mmsc_url : r->u.url;
|
||||
ms = fetch_content(url, mm1->proxy, body, &hstatus);
|
||||
msize = ms ? octstr_len(ms) : 0;
|
||||
m = (hstatus == 0 && ms) ? mms_frombinary(ms, mm1->msisdn) : NULL;
|
||||
|
||||
if (r->type == MM1_GET) {
|
||||
if (m == NULL)
|
||||
mms_error(0, "mmsbox-mm1", NULL, "failed to fetch mms from URL: %s!",
|
||||
octstr_get_cstr(url));
|
||||
else {
|
||||
List *mh = mms_message_headers(m), *to = gwlist_create();
|
||||
Octstr *subject = NULL, *otransid = NULL, *msgid = NULL, *value;
|
||||
Octstr *hfrom = mh ? http_header_value(mh, octstr_imm("From")) : octstr_imm("anon@anon");
|
||||
Octstr *qf = NULL, *qdir = NULL, *mmc_id = NULL;
|
||||
time_t expiryt = -1, deliveryt = -1;
|
||||
int dlr;
|
||||
|
||||
/* we assume it is a true message (send_req|retrieve_conf) */
|
||||
mms_collect_envdata_from_msgheaders(mh, &to, &subject,
|
||||
&otransid, &expiryt, &deliveryt,
|
||||
DEFAULT_EXPIRE, -1,
|
||||
octstr_get_cstr(mm1->unified_prefix),
|
||||
mm1->strip_prefixes);
|
||||
|
||||
msgid = http_header_value(mh, octstr_imm("Message-ID"));
|
||||
value = http_header_value(mh, octstr_imm("X-Mms-Delivery-Report"));
|
||||
if (value &&
|
||||
octstr_case_compare(value, octstr_imm("Yes")) == 0)
|
||||
dlr = 1;
|
||||
else
|
||||
dlr = 0;
|
||||
octstr_destroy(value);
|
||||
|
||||
if (deliveryt < 0)
|
||||
deliveryt = time(NULL);
|
||||
|
||||
if (expiryt < 0)
|
||||
expiryt = time(NULL) + DEFAULT_EXPIRE;
|
||||
|
||||
if (hfrom == NULL)
|
||||
hfrom = http_header_value(mh, octstr_imm("From"));
|
||||
|
||||
mms_remove_headers(m, "Bcc");
|
||||
mms_remove_headers(m, "X-Mms-Delivery-Time");
|
||||
mms_remove_headers(m, "X-Mms-Expiry");
|
||||
mms_remove_headers(m, "X-Mms-Sender-Visibility");
|
||||
|
||||
qdir = get_mmsbox_queue_dir(hfrom, to, mm1->info, &mmc_id); /* get routing info. */
|
||||
/* Save it, put message id in header, return. */
|
||||
qf = qfs->mms_queue_add(hfrom, to, subject,
|
||||
mm1->info->id, mmc_id,
|
||||
deliveryt, expiryt, m, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
dlr,
|
||||
octstr_get_cstr(qdir),
|
||||
"MM7/MM1-IN",
|
||||
octstr_imm(MM_NAME));
|
||||
|
||||
if (qf)
|
||||
/* Log to access log */
|
||||
mms_log("Received", hfrom, to, msize,
|
||||
msgid, NULL, mm1->info->id, "MMSBox",octstr_imm("MM1"), NULL);
|
||||
else
|
||||
mms_error(0, "mmsbox-mm1", NULL, "failed to create queue entry for URL %s",
|
||||
octstr_get_cstr(url));
|
||||
|
||||
if (otransid) { /* tell mmsc that we fetched fine. */
|
||||
int _status;
|
||||
MmsMsg *mresp = mms_notifyresp_ind(octstr_get_cstr(otransid),
|
||||
mms_message_enc(m), "Retrieved", 1);
|
||||
Octstr *sm = mms_tobinary(mresp);
|
||||
Octstr *_x = fetch_content(mm1->mmsc_url, mm1->proxy,
|
||||
sm, &_status);
|
||||
|
||||
octstr_destroy(_x);
|
||||
octstr_destroy(sm);
|
||||
mms_destroy(mresp);
|
||||
}
|
||||
gwlist_destroy(to, (gwlist_item_destructor_t *)octstr_destroy);
|
||||
octstr_destroy(hfrom);
|
||||
octstr_destroy(subject);
|
||||
octstr_destroy(otransid);
|
||||
octstr_destroy(msgid);
|
||||
octstr_destroy(qf);
|
||||
octstr_destroy(mmc_id);
|
||||
|
||||
http_destroy_headers(mh);
|
||||
}
|
||||
|
||||
} else if (r->type == MM1_PUSH) {
|
||||
/* we expect a send-conf. */
|
||||
if (ms) {
|
||||
octstr_dump(ms, 0);
|
||||
|
||||
mms_msgdump(m, 1);
|
||||
} else
|
||||
mms_warning(0, "mmsbox-mm1", NULL,"No send-conf returned by operator");
|
||||
|
||||
if (m == NULL ||
|
||||
(r->result = mms_get_header_value(m, octstr_imm("Message-ID"))) == NULL ||
|
||||
octstr_compare(mms_get_header_value(m, octstr_imm("X-Mms-Response-Status")),
|
||||
octstr_imm("Ok")) != 0
|
||||
) {
|
||||
Octstr *err = m ? mms_get_header_value(m, octstr_imm("X-Mms-Response-Text")) : NULL;
|
||||
Octstr *status = m ? mms_get_header_value(m, octstr_imm("X-Mms-Response-Status")) : NULL;
|
||||
if(status && (octstr_compare(status, octstr_imm("Error-service-denied")) == 0 ||
|
||||
octstr_compare(status, octstr_imm("Error-permanent-failure")) == 0)) {
|
||||
r->error = octstr_duplicate(status);
|
||||
}
|
||||
r->result = NULL; /* indicate failure to bearerbox */
|
||||
mms_error(0, "mmsbox-mm1", NULL, "Sending failed: %s, %s!",
|
||||
err ? octstr_get_cstr(err) : "(none)",
|
||||
status ? octstr_get_cstr(status) : "(none)");
|
||||
octstr_destroy(err);
|
||||
octstr_destroy(status);
|
||||
}
|
||||
} else
|
||||
mms_error(0, "mmsbox-mm1", NULL, "unknown type: %d", r->type);
|
||||
|
||||
if (r->waiter_exists) {
|
||||
pthread_mutex_unlock(&r->mutex);
|
||||
pthread_cond_signal(&r->cond);
|
||||
} else /* no waiter, so we free it ourselves. */
|
||||
gw_free(r);
|
||||
|
||||
octstr_destroy(body);
|
||||
octstr_destroy(ms);
|
||||
mms_destroy(m);
|
||||
r = NULL;
|
||||
pid_t wp;
|
||||
int st;
|
||||
wp = waitpid(pid, &st, WNOHANG);
|
||||
if(wp == pid && WIFEXITED(st)) {
|
||||
mms_info(0, "mmsbox-mm1", NULL, "GPRS pid (%d) appears to be dead - quitting loop", pid);
|
||||
goto after_gprs_dead;
|
||||
}
|
||||
gwthread_sleep(2); /* according to Piotr Isajew, this makes life better */
|
||||
} while (gwlist_len(mm1->requests) > 0 &&
|
||||
(r = gwlist_consume(mm1->requests)) != NULL);
|
||||
|
||||
kill_gprs:
|
||||
if(r != NULL) {
|
||||
if(r->waiter_exists) {
|
||||
pthread_mutex_unlock(&r->mutex);
|
||||
pthread_cond_signal(&r->cond);
|
||||
} else{
|
||||
gw_free(r);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (mm1->gprs_off) {
|
||||
stop_gprs(mm1->gprs_off);
|
||||
} else if (pid > 0) { /* stop GPRS, restart SMSC connection. */
|
||||
int xkill, status;
|
||||
pid_t wpid;
|
||||
do {
|
||||
xkill = kill(pid, SIGTERM);
|
||||
mms_info(0, "mmsbox-mm1", NULL, "GPRS turned off returned: %d", xkill);
|
||||
if (xkill < 0 && errno == ESRCH)
|
||||
break;
|
||||
wpid = waitpid(pid, &status, 0);
|
||||
if (wpid == pid && WIFEXITED(status))
|
||||
break;
|
||||
else if (wpid < 0 && errno == ECHILD)
|
||||
break;
|
||||
} while (1);
|
||||
gwthread_sleep(2);
|
||||
}
|
||||
after_gprs_dead:
|
||||
if (mm1->smsc_on) {
|
||||
system(octstr_get_cstr(mm1->smsc_on));
|
||||
gwthread_sleep(5);
|
||||
mms_info(0, "mmsbox-mm1", NULL, "SMSC turned on");
|
||||
}
|
||||
|
||||
}
|
||||
mm1->sender_alive--;
|
||||
mms_info(0, "mmsbox-mm1", NULL, "handle_mm1 exits");
|
||||
}
|
||||
|
||||
static int close_mm1(void *data)
|
||||
{
|
||||
MM1Settings *s = data;
|
||||
|
||||
/* close the port, and all will die. */
|
||||
http_close_port(s->port);
|
||||
gwthread_sleep(2);
|
||||
gwthread_join(s->h_tid);
|
||||
gwthread_sleep(2);
|
||||
gwthread_join(s->d_tid);
|
||||
|
||||
octstr_destroy(s->mmsc_url);
|
||||
octstr_destroy(s->msisdn);
|
||||
octstr_destroy(s->proxy);
|
||||
octstr_destroy(s->gprs_on);
|
||||
octstr_destroy(s->gprs_off);
|
||||
octstr_destroy(s->gprs_pid);
|
||||
octstr_destroy(s->smsc_on);
|
||||
octstr_destroy(s->smsc_off);
|
||||
octstr_destroy(s->interface);
|
||||
|
||||
gwlist_destroy(s->requests, NULL);
|
||||
|
||||
gw_free(s);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
MmsBoxMmscFuncs mmsc_funcs = {
|
||||
open_mm1,
|
||||
close_mm1,
|
||||
send_msg
|
||||
};
|
||||
|
||||
|
||||
#include <curl/curl.h>
|
||||
|
||||
|
||||
static int write_octstr_data(void *buffer, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
Octstr *out = userp;
|
||||
|
||||
octstr_append_data(out, buffer, size*nmemb);
|
||||
mms_info(0, "mmsbox-mm1", NULL, "write_data called with nmemn=%ld, size=%ld",
|
||||
nmemb, size);
|
||||
return size*nmemb;
|
||||
}
|
||||
|
||||
static Octstr *fetch_content(Octstr *url, Octstr *proxy, Octstr *body, int *hstatus)
|
||||
{
|
||||
CURL *cl;
|
||||
struct curl_slist *h = NULL;
|
||||
char errbuf[512];
|
||||
static int curl_inited = 0;
|
||||
Octstr *s = octstr_create("");
|
||||
|
||||
if (curl_inited == 0) {
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
curl_inited = 1;
|
||||
}
|
||||
|
||||
cl = curl_easy_init();
|
||||
curl_easy_setopt(cl, CURLOPT_URL, octstr_get_cstr(url));
|
||||
if (proxy && octstr_len(proxy) > 0)
|
||||
curl_easy_setopt(cl, CURLOPT_PROXY, octstr_get_cstr(proxy));
|
||||
curl_easy_setopt(cl, CURLOPT_WRITEFUNCTION, write_octstr_data);
|
||||
curl_easy_setopt(cl, CURLOPT_WRITEDATA, s);
|
||||
curl_easy_setopt(cl, CURLOPT_NOSIGNAL, 1L);
|
||||
curl_easy_setopt(cl, CURLOPT_TIMEOUT, 120L);
|
||||
curl_easy_setopt(cl, CURLOPT_FORBID_REUSE, 1L);
|
||||
curl_easy_setopt(cl, CURLOPT_CONNECTTIMEOUT, 40L);
|
||||
|
||||
h = curl_slist_append(h, "Accept: */*");
|
||||
if (body) { /* POST. */
|
||||
h = curl_slist_append(h, "Content-Type: application/vnd.wap.mms-message");
|
||||
h = curl_slist_append(h, "User-Agent: Mozilla/5.0 (SymbianOS/9.4;U;"
|
||||
"Series60/5.0 Nokia5800d-1/52.50.2008.24;"
|
||||
"Profile/MIDP-2.1Configuration/CLDC-1.1 ) "
|
||||
"AppleWebKit/413 (KHTML, like Gecko) "
|
||||
"Safari/413");
|
||||
curl_easy_setopt(cl, CURLOPT_POSTFIELDS, octstr_get_cstr(body));
|
||||
curl_easy_setopt(cl, CURLOPT_POSTFIELDSIZE, octstr_len(body));
|
||||
}
|
||||
|
||||
|
||||
curl_easy_setopt(cl, CURLOPT_HTTPHEADER, h);
|
||||
curl_easy_setopt(cl, CURLOPT_ERRORBUFFER, errbuf);
|
||||
|
||||
*hstatus = curl_easy_perform(cl); /* post away! */
|
||||
if (*hstatus != 0)
|
||||
mms_error(0, "mmsbox-mm1", NULL, "failed to fetch/post content to host %s [proxy: %s] [http_status=%d] : %.256s",
|
||||
octstr_get_cstr(url), octstr_len(proxy) > 0 ? octstr_get_cstr(proxy) : "n/a",
|
||||
*hstatus, errbuf);
|
||||
|
||||
curl_slist_free_all(h); /* free the header list */
|
||||
curl_easy_setopt(cl, CURLOPT_NOSIGNAL, 0L);
|
||||
curl_easy_cleanup(cl);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
static void stop_gprs(Octstr *cmd)
|
||||
{
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
/* in child */
|
||||
List *l = octstr_split_words(cmd);
|
||||
int i, n = gwlist_len(l);
|
||||
char **args = gw_malloc((n+1) * sizeof *args);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
Octstr *x = gwlist_get(l, i);
|
||||
args[i] = octstr_get_cstr(x);
|
||||
printf("arg %d: %s\n", i, args[i]);
|
||||
}
|
||||
args[i] = NULL;
|
||||
printf("Not reached: %d!", execvp(args[0], args));
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_GPRS_WAIT 80
|
||||
#define GPRS_POLL 5
|
||||
static long start_gprs(Octstr *cmd, Octstr *pid_cmd)
|
||||
{
|
||||
pid_t pid = fork();
|
||||
|
||||
if (pid > 0) { /* parent. */
|
||||
int ct = 0;
|
||||
do {
|
||||
FILE *f;
|
||||
long xpid = -1, cpid;
|
||||
int status;
|
||||
gwthread_sleep(GPRS_POLL); /* wait a little. */
|
||||
if ((f = popen(octstr_get_cstr(pid_cmd), "r")) != NULL) {
|
||||
fscanf(f, "%ld", &xpid);
|
||||
pclose(f);
|
||||
if (xpid >= 0)
|
||||
return xpid;
|
||||
}
|
||||
cpid = waitpid(pid, &status, WNOHANG); /* also wait for the child. */
|
||||
mms_info(0, "mmsbox-mm1", NULL, "waiting for connection: %d, pid=%ld cpid=%ld, ifexited=%d, exitstatus=%d",
|
||||
ct, (long)pid, cpid, WIFEXITED(status), WEXITSTATUS(status));
|
||||
if (cpid == pid &&
|
||||
WIFEXITED(status))
|
||||
return -1;
|
||||
} while (GPRS_POLL*ct++ < MAX_GPRS_WAIT);
|
||||
/* Timed out, but still need to wait for child pid, as
|
||||
start-gprs script is still running and we don't need a
|
||||
zombie */
|
||||
pid_t rpid;
|
||||
int st;
|
||||
|
||||
rpid = waitpid(pid, &st, 0);
|
||||
mms_info(0, "mmsbox-mm1", NULL, "pid %d terminated", pid);
|
||||
return -1;
|
||||
} else if (pid == 0) { /* child. */
|
||||
List *l = octstr_split_words(cmd);
|
||||
int i, n = gwlist_len(l);
|
||||
char **args = gw_malloc((n+1) * sizeof *args);
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
Octstr *x = gwlist_get(l, i);
|
||||
args[i] = octstr_get_cstr(x);
|
||||
printf("arg %d: %s\n", i, args[i]);
|
||||
}
|
||||
args[i] = NULL;
|
||||
printf("Not reached: %d!", execvp(args[0], args));
|
||||
} else
|
||||
mms_error(0, "mmsbox-mm1", NULL, "failed to start process!");
|
||||
return -1;
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
EXTRA_DIST = tables.sql
|
||||
lib_LTLIBRARIES = libmms_pgsql_queue.la
|
||||
libmms_pgsql_queue_la_SOURCES = mms_pgsql_queue.c
|
||||
libmms_pgsql_queue_la_LDFLAGS = -module
|
|
@ -0,0 +1,16 @@
|
|||
This module provides Queue management for mbuni using PostgreSQL as the storage engine.
|
||||
To use it, you need only add two lines to the mbuni config 'mbuni' group:
|
||||
|
||||
queue-manager-module = "/path_to/libmms_pgsql_queue.so"
|
||||
queue-module-init-data = "host=dbhost user=db_user password=dbpassword dbname=dbname"
|
||||
|
||||
Make sure the database you are trying to connect to has already been created
|
||||
and the relevant tables created using the supplied file "tables.sql".
|
||||
|
||||
Some notes:
|
||||
- Mbuni will open number_of_db_connections connections to the database at startup.
|
||||
Ensure your PostgreSQL installation limits are not exceeded. DB connections will
|
||||
be shared by all parts of Mbuni, which means that in high traffic situations,
|
||||
you may experience mbuni component slow-down as all db connections might be in use.
|
||||
- Vacuum your DB often, since a lot of rows are updated/deleted during operation.
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,52 @@
|
|||
-- Table structure for PostgreSQL MMS storage engine
|
||||
-- (c) 2007 Digital Solutions
|
||||
-- Licence: See http://mbuni.org/license.shtml
|
||||
-- Author: P. A. Bagyenda <bagyenda@dsmagic.com>
|
||||
-- Requires: PostgresQL v8.2 and above
|
||||
|
||||
-- Master messages table
|
||||
CREATE TABLE mms_messages (
|
||||
id bigserial PRIMARY KEY,
|
||||
qdir varchar(256) NOT NULL,
|
||||
qfname varchar(256) NOT NULL,
|
||||
sender varchar(256) NOT NULL,
|
||||
created timestamp with time zone NOT NULL DEFAULT current_timestamp,
|
||||
last_try timestamp with time zone NOT NULL DEFAULT '-infinity',
|
||||
send_time timestamp with time zone NOT NULL DEFAULT '-infinity',
|
||||
expire_date timestamp with time zone NOT NULL,
|
||||
num_attempts int NOT NULL DEFAULT 0,
|
||||
|
||||
data bytea NOT NULL DEFAULT '',
|
||||
UNIQUE(qdir, qfname)
|
||||
);
|
||||
|
||||
CREATE index mm_idx1 on mms_messages(qdir); -- because we use it for lookups.
|
||||
CREATE index mm_idx2 on mms_messages(send_time);
|
||||
CREATE index mm_idx3 on mms_messages(qfname);
|
||||
|
||||
-- create a view for message lookup
|
||||
CREATE VIEW mms_messages_view AS SELECT
|
||||
*,
|
||||
EXTRACT(EPOCH FROM created) AS cdate,
|
||||
EXTRACT(EPOCH FROM last_try) AS lastt,
|
||||
EXTRACT(EPOCH FROM send_time) AS sendt,
|
||||
EXTRACT(EPOCH FROM expire_date) AS edate FROM mms_messages;
|
||||
|
||||
-- Table for envelope headers.
|
||||
CREATE TABLE mms_message_headers (
|
||||
id bigserial PRIMARY KEY,
|
||||
qid bigint REFERENCES mms_messages ON UPDATE CASCADE ON DELETE CASCADE,
|
||||
|
||||
item varchar(64) NOT NULL,
|
||||
value text NOT NULL
|
||||
);
|
||||
|
||||
-- When messages are deleted from the queue, they are moved to the achived_XXX tables.
|
||||
-- archive tables are exact copies of old ones, field for field.
|
||||
-- DBA should clear these tables as needed
|
||||
CREATE TABLE archived_mms_messages (LIKE mms_messages INCLUDING DEFAULTS INCLUDING CONSTRAINTS);
|
||||
CREATE TABLE archived_mms_message_headers (LIKE mms_message_headers INCLUDING DEFAULTS INCLUDING CONSTRAINTS);
|
||||
|
||||
ALTER table archived_mms_messages add unique(id);
|
||||
ALTER table archived_mms_message_headers add foreign key (qid)
|
||||
references archived_mms_messages (id);
|
|
@ -1 +0,0 @@
|
|||
EXTRA_DIST = mbuni-kannel-patch-full
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
|||
noinst_LTLIBRARIES = libmms.la
|
||||
libmms_la_SOURCES = mms_mmbox.c mms_msg.c mms_queue.c mms_strings.c mms_uaprof.c mms_util.c mms_mm7soap.c mms_cfg.c
|
||||
lib_LTLIBRARIES = libmms.la
|
||||
libmms_la_SOURCES = charmibenum.def mms_eventlogger.c mms_mmbox.c mms_msg.c mms_queue.c mms_strings.c mms_uaprof.c mms_util.c mms_mm7soap.c mms_cfg.c
|
||||
|
||||
EXTRA_DIST=mms_strings.def mms_mm7soap.h mms_mmbox.h mms_msg.h mms_queue.h mms_strings.h mms_uaprof.h mms_util.h mms_cfg.h mms_cfg.def
|
||||
EXTRA_DIST=mms_strings.def mms_eventlogger.h mms_mm7soap.h mms_mmbox.h mms_msg.h mms_queue.h mms_strings.h mms_uaprof.h mms_util.h mms_cfg.h mms_cfg.def mms_cfg-impl.h
|
||||
|
|
|
@ -0,0 +1,340 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* Charset MIBenum assignments - pre-processor magic.
|
||||
*
|
||||
* Copyright (C) 2003 - , Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
|
||||
#if !defined(CharMIBEnum)
|
||||
#error "Required macro CharMIBEnum is missing."
|
||||
#endif
|
||||
|
||||
CharMIBEnum(3,ASCII)
|
||||
CharMIBEnum(3,ANSI_X3.4-1968)
|
||||
CharMIBEnum(3,ANSI_X3.4-1986)
|
||||
CharMIBEnum(3,CP367)
|
||||
CharMIBEnum(3,IBM367)
|
||||
CharMIBEnum(3,ISO-IR-6)
|
||||
CharMIBEnum(3,ISO646-US)
|
||||
CharMIBEnum(3,ISO_646.IRV:1991)
|
||||
CharMIBEnum(3,US)
|
||||
CharMIBEnum(3,US-ASCII)
|
||||
CharMIBEnum(3,CSASCII)
|
||||
CharMIBEnum(4,CP819)
|
||||
CharMIBEnum(4,IBM819)
|
||||
CharMIBEnum(4,ISO-8859-1)
|
||||
CharMIBEnum(4,ISO-IR-100)
|
||||
CharMIBEnum(4,ISO8859-1)
|
||||
CharMIBEnum(4,ISO_8859-1)
|
||||
CharMIBEnum(4,ISO_8859-1:1987)
|
||||
CharMIBEnum(4,L1)
|
||||
CharMIBEnum(4,LATIN1)
|
||||
CharMIBEnum(4,CSISOLATIN1)
|
||||
CharMIBEnum(5,ISO-8859-2)
|
||||
CharMIBEnum(5,ISO-IR-101)
|
||||
CharMIBEnum(5,ISO8859-2)
|
||||
CharMIBEnum(5,ISO_8859-2)
|
||||
CharMIBEnum(5,ISO_8859-2:1987)
|
||||
CharMIBEnum(5,L2)
|
||||
CharMIBEnum(5,LATIN2)
|
||||
CharMIBEnum(5,CSISOLATIN2)
|
||||
CharMIBEnum(6,ISO-8859-3)
|
||||
CharMIBEnum(6,ISO-IR-109)
|
||||
CharMIBEnum(6,ISO8859-3)
|
||||
CharMIBEnum(6,ISO_8859-3)
|
||||
CharMIBEnum(6,ISO_8859-3:1988)
|
||||
CharMIBEnum(6,L3)
|
||||
CharMIBEnum(6,LATIN3)
|
||||
CharMIBEnum(6,CSISOLATIN3)
|
||||
CharMIBEnum(7,ISO-8859-4)
|
||||
CharMIBEnum(7,ISO-IR-110)
|
||||
CharMIBEnum(7,ISO8859-4)
|
||||
CharMIBEnum(7,ISO_8859-4)
|
||||
CharMIBEnum(7,ISO_8859-4:1988)
|
||||
CharMIBEnum(7,L4)
|
||||
CharMIBEnum(7,LATIN4)
|
||||
CharMIBEnum(7,CSISOLATIN4)
|
||||
CharMIBEnum(8,CYRILLIC)
|
||||
CharMIBEnum(8,ISO-8859-5)
|
||||
CharMIBEnum(8,ISO-IR-144)
|
||||
CharMIBEnum(8,ISO8859-5)
|
||||
CharMIBEnum(8,ISO_8859-5)
|
||||
CharMIBEnum(8,ISO_8859-5:1988)
|
||||
CharMIBEnum(8,CSISOLATINCYRILLIC)
|
||||
CharMIBEnum(9,ARABIC)
|
||||
CharMIBEnum(9,ASMO-708)
|
||||
CharMIBEnum(9,ECMA-114)
|
||||
CharMIBEnum(9,ISO-8859-6)
|
||||
CharMIBEnum(9,ISO-IR-127)
|
||||
CharMIBEnum(9,ISO8859-6)
|
||||
CharMIBEnum(9,ISO_8859-6)
|
||||
CharMIBEnum(9,ISO_8859-6:1987)
|
||||
CharMIBEnum(9,CSISOLATINARABIC)
|
||||
CharMIBEnum(10,ECMA-118)
|
||||
CharMIBEnum(10,ELOT_928)
|
||||
CharMIBEnum(10,GREEK)
|
||||
CharMIBEnum(10,GREEK8)
|
||||
CharMIBEnum(10,ISO-8859-7)
|
||||
CharMIBEnum(10,ISO-IR-126)
|
||||
CharMIBEnum(10,ISO8859-7)
|
||||
CharMIBEnum(10,ISO_8859-7)
|
||||
CharMIBEnum(10,ISO_8859-7:1987)
|
||||
CharMIBEnum(10,ISO_8859-7:2003)
|
||||
CharMIBEnum(10,CSISOLATINGREEK)
|
||||
CharMIBEnum(11,HEBREW)
|
||||
CharMIBEnum(11,ISO-8859-8)
|
||||
CharMIBEnum(11,ISO-IR-138)
|
||||
CharMIBEnum(11,ISO8859-8)
|
||||
CharMIBEnum(11,ISO_8859-8)
|
||||
CharMIBEnum(11,ISO_8859-8:1988)
|
||||
CharMIBEnum(11,CSISOLATINHEBREW)
|
||||
CharMIBEnum(12,ISO-8859-9)
|
||||
CharMIBEnum(12,ISO-IR-148)
|
||||
CharMIBEnum(12,ISO8859-9)
|
||||
CharMIBEnum(12,ISO_8859-9)
|
||||
CharMIBEnum(12,ISO_8859-9:1989)
|
||||
CharMIBEnum(12,L5)
|
||||
CharMIBEnum(12,LATIN5)
|
||||
CharMIBEnum(12,CSISOLATIN5)
|
||||
CharMIBEnum(13,ISO-8859-10)
|
||||
CharMIBEnum(13,ISO-IR-157)
|
||||
CharMIBEnum(13,ISO8859-10)
|
||||
CharMIBEnum(13,ISO_8859-10)
|
||||
CharMIBEnum(13,ISO_8859-10:1992)
|
||||
CharMIBEnum(13,L6)
|
||||
CharMIBEnum(13,LATIN6)
|
||||
CharMIBEnum(13,CSISOLATIN6)
|
||||
CharMIBEnum(15,JISX0201-1976)
|
||||
CharMIBEnum(15,JIS_X0201)
|
||||
CharMIBEnum(15,X0201)
|
||||
CharMIBEnum(15,CSHALFWIDTHKATAKANA)
|
||||
CharMIBEnum(17,MS_KANJI)
|
||||
CharMIBEnum(17,SHIFT-JIS)
|
||||
CharMIBEnum(17,SHIFT_JIS)
|
||||
CharMIBEnum(17,SJIS)
|
||||
CharMIBEnum(17,CSSHIFTJIS)
|
||||
CharMIBEnum(17,SHIFT_JIS-2004)
|
||||
CharMIBEnum(17,SHIFT_JISX0213)
|
||||
CharMIBEnum(18,EUC-JP)
|
||||
CharMIBEnum(18,EUCJP)
|
||||
CharMIBEnum(18,EXTENDED_UNIX_CODE_PACKED_FORMAT_FOR_JAPANESE)
|
||||
CharMIBEnum(18,CSEUCPKDFMTJAPANESE)
|
||||
CharMIBEnum(36,ISO-IR-149)
|
||||
CharMIBEnum(36,KOREAN)
|
||||
CharMIBEnum(36,KSC_5601)
|
||||
CharMIBEnum(36,KS_C_5601-1987)
|
||||
CharMIBEnum(36,KS_C_5601-1989)
|
||||
CharMIBEnum(36,CSKSC56011987)
|
||||
CharMIBEnum(37,ISO-2022-KR)
|
||||
CharMIBEnum(37,CSISO2022KR)
|
||||
CharMIBEnum(38,EUC-KR)
|
||||
CharMIBEnum(38,EUCKR)
|
||||
CharMIBEnum(38,CSEUCKR)
|
||||
CharMIBEnum(39,ISO-2022-JP)
|
||||
CharMIBEnum(39,CSISO2022JP)
|
||||
CharMIBEnum(39,ISO-2022-JP-1)
|
||||
CharMIBEnum(39,ISO-2022-JP-2)
|
||||
CharMIBEnum(39,CSISO2022JP2)
|
||||
CharMIBEnum(39,ISO-2022-JP-2004)
|
||||
CharMIBEnum(39,ISO-2022-JP-3)
|
||||
CharMIBEnum(40,ISO-2022-JP-2)
|
||||
CharMIBEnum(40,CSISO2022JP2)
|
||||
CharMIBEnum(40,ISO-2022-JP-2004)
|
||||
CharMIBEnum(40,ISO-2022-JP-3)
|
||||
CharMIBEnum(42,ISO-IR-14)
|
||||
CharMIBEnum(42,ISO646-JP)
|
||||
CharMIBEnum(42,JIS_C6220-1969-RO)
|
||||
CharMIBEnum(42,JP)
|
||||
CharMIBEnum(42,CSISO14JISC6220RO)
|
||||
CharMIBEnum(56,CN)
|
||||
CharMIBEnum(56,GB_1988-80)
|
||||
CharMIBEnum(56,ISO-IR-57)
|
||||
CharMIBEnum(56,ISO646-CN)
|
||||
CharMIBEnum(56,CSISO57GB1988)
|
||||
CharMIBEnum(57,CHINESE)
|
||||
CharMIBEnum(57,GB_2312-80)
|
||||
CharMIBEnum(57,ISO-IR-58)
|
||||
CharMIBEnum(57,CSISO58GB231280)
|
||||
CharMIBEnum(63,ISO-IR-87)
|
||||
CharMIBEnum(63,JIS0208)
|
||||
CharMIBEnum(63,JIS_C6226-1983)
|
||||
CharMIBEnum(63,JIS_X0208)
|
||||
CharMIBEnum(63,JIS_X0208-1983)
|
||||
CharMIBEnum(63,JIS_X0208-1990)
|
||||
CharMIBEnum(63,X0208)
|
||||
CharMIBEnum(63,CSISO87JISX0208)
|
||||
CharMIBEnum(98,ISO-IR-159)
|
||||
CharMIBEnum(98,JIS_X0212)
|
||||
CharMIBEnum(98,JIS_X0212-1990)
|
||||
CharMIBEnum(98,JIS_X0212.1990-0)
|
||||
CharMIBEnum(98,X0212)
|
||||
CharMIBEnum(98,CSISO159JISX02121990)
|
||||
CharMIBEnum(103,UNICODE-1-1-UTF-7)
|
||||
CharMIBEnum(103,UTF-7)
|
||||
CharMIBEnum(103,CSUNICODE11UTF7)
|
||||
CharMIBEnum(104,ISO-2022-CN)
|
||||
CharMIBEnum(104,CSISO2022CN)
|
||||
CharMIBEnum(104,ISO-2022-CN-EXT)
|
||||
CharMIBEnum(105,ISO-2022-CN-EXT)
|
||||
CharMIBEnum(106,UTF-8)
|
||||
CharMIBEnum(106,UTF-8-MAC)
|
||||
CharMIBEnum(106,UTF8-MAC)
|
||||
CharMIBEnum(109,ISO-8859-13)
|
||||
CharMIBEnum(109,ISO-IR-179)
|
||||
CharMIBEnum(109,ISO8859-13)
|
||||
CharMIBEnum(109,ISO_8859-13)
|
||||
CharMIBEnum(109,L7)
|
||||
CharMIBEnum(109,LATIN7)
|
||||
CharMIBEnum(110,ISO-8859-14)
|
||||
CharMIBEnum(110,ISO-CELTIC)
|
||||
CharMIBEnum(110,ISO-IR-199)
|
||||
CharMIBEnum(110,ISO8859-14)
|
||||
CharMIBEnum(110,ISO_8859-14)
|
||||
CharMIBEnum(110,ISO_8859-14:1998)
|
||||
CharMIBEnum(110,L8)
|
||||
CharMIBEnum(110,LATIN8)
|
||||
CharMIBEnum(111,ISO-8859-15)
|
||||
CharMIBEnum(111,ISO-IR-203)
|
||||
CharMIBEnum(111,ISO8859-15)
|
||||
CharMIBEnum(111,ISO_8859-15)
|
||||
CharMIBEnum(111,ISO_8859-15:1998)
|
||||
CharMIBEnum(111,LATIN-9)
|
||||
CharMIBEnum(112,ISO-8859-16)
|
||||
CharMIBEnum(112,ISO-IR-226)
|
||||
CharMIBEnum(112,ISO8859-16)
|
||||
CharMIBEnum(112,ISO_8859-16)
|
||||
CharMIBEnum(112,ISO_8859-16:2001)
|
||||
CharMIBEnum(112,L10)
|
||||
CharMIBEnum(112,LATIN10)
|
||||
CharMIBEnum(113,GBK)
|
||||
CharMIBEnum(114,GB18030)
|
||||
CharMIBEnum(1000,ISO-10646-UCS-2)
|
||||
CharMIBEnum(1000,UCS-2)
|
||||
CharMIBEnum(1000,CSUNICODE)
|
||||
CharMIBEnum(1001,ISO-10646-UCS-4)
|
||||
CharMIBEnum(1001,UCS-4)
|
||||
CharMIBEnum(1001,CSUCS4)
|
||||
CharMIBEnum(1010,UCS-2BE)
|
||||
CharMIBEnum(1010,UNICODE-1-1)
|
||||
CharMIBEnum(1010,UNICODEBIG)
|
||||
CharMIBEnum(1010,CSUNICODE11)
|
||||
CharMIBEnum(1010,UNICODE-1-1-UTF-7)
|
||||
CharMIBEnum(1010,UTF-7)
|
||||
CharMIBEnum(1010,CSUNICODE11UTF7)
|
||||
CharMIBEnum(1012,UNICODE-1-1-UTF-7)
|
||||
CharMIBEnum(1012,UTF-7)
|
||||
CharMIBEnum(1012,CSUNICODE11UTF7)
|
||||
CharMIBEnum(1013,UTF-16BE)
|
||||
CharMIBEnum(1014,UTF-16LE)
|
||||
CharMIBEnum(1015,UTF-16)
|
||||
CharMIBEnum(1015,UTF-16BE)
|
||||
CharMIBEnum(1015,UTF-16LE)
|
||||
CharMIBEnum(1017,UTF-32)
|
||||
CharMIBEnum(1017,UTF-32BE)
|
||||
CharMIBEnum(1017,UTF-32LE)
|
||||
CharMIBEnum(1018,UTF-32BE)
|
||||
CharMIBEnum(1019,UTF-32LE)
|
||||
CharMIBEnum(2004,HP-ROMAN8)
|
||||
CharMIBEnum(2004,R8)
|
||||
CharMIBEnum(2004,ROMAN8)
|
||||
CharMIBEnum(2004,CSHPROMAN8)
|
||||
CharMIBEnum(2009,850)
|
||||
CharMIBEnum(2009,CP850)
|
||||
CharMIBEnum(2009,IBM850)
|
||||
CharMIBEnum(2009,CSPC850MULTILINGUAL)
|
||||
CharMIBEnum(2013,862)
|
||||
CharMIBEnum(2013,CP862)
|
||||
CharMIBEnum(2013,IBM862)
|
||||
CharMIBEnum(2013,CSPC862LATINHEBREW)
|
||||
CharMIBEnum(2025,CHINESE)
|
||||
CharMIBEnum(2025,GB_2312-80)
|
||||
CharMIBEnum(2025,ISO-IR-58)
|
||||
CharMIBEnum(2025,CSISO58GB231280)
|
||||
CharMIBEnum(2025,CN-GB)
|
||||
CharMIBEnum(2025,EUC-CN)
|
||||
CharMIBEnum(2025,EUCCN)
|
||||
CharMIBEnum(2025,GB2312)
|
||||
CharMIBEnum(2025,CSGB2312)
|
||||
CharMIBEnum(2026,BIG-5)
|
||||
CharMIBEnum(2026,BIG-FIVE)
|
||||
CharMIBEnum(2026,BIG5)
|
||||
CharMIBEnum(2026,BIGFIVE)
|
||||
CharMIBEnum(2026,CN-BIG5)
|
||||
CharMIBEnum(2026,CSBIG5)
|
||||
CharMIBEnum(2026,BIG5-HKSCS:1999)
|
||||
CharMIBEnum(2026,BIG5-HKSCS:2001)
|
||||
CharMIBEnum(2026,BIG5-HKSCS)
|
||||
CharMIBEnum(2026,BIG5-HKSCS:2004)
|
||||
CharMIBEnum(2026,BIG5HKSCS)
|
||||
CharMIBEnum(2026,BIG5-2003)
|
||||
CharMIBEnum(2027,MAC)
|
||||
CharMIBEnum(2027,MACINTOSH)
|
||||
CharMIBEnum(2027,MACROMAN)
|
||||
CharMIBEnum(2027,CSMACINTOSH)
|
||||
CharMIBEnum(2082,VISCII)
|
||||
CharMIBEnum(2082,VISCII1.1-1)
|
||||
CharMIBEnum(2082,CSVISCII)
|
||||
CharMIBEnum(2084,KOI8-R)
|
||||
CharMIBEnum(2084,CSKOI8R)
|
||||
CharMIBEnum(2084,KOI8-RU)
|
||||
CharMIBEnum(2085,HZ)
|
||||
CharMIBEnum(2085,HZ-GB-2312)
|
||||
CharMIBEnum(2086,866)
|
||||
CharMIBEnum(2086,CP866)
|
||||
CharMIBEnum(2086,IBM866)
|
||||
CharMIBEnum(2086,CSIBM866)
|
||||
CharMIBEnum(2088,KOI8-U)
|
||||
CharMIBEnum(2101,BIG5-HKSCS:1999)
|
||||
CharMIBEnum(2101,BIG5-HKSCS:2001)
|
||||
CharMIBEnum(2101,BIG5-HKSCS)
|
||||
CharMIBEnum(2101,BIG5-HKSCS:2004)
|
||||
CharMIBEnum(2101,BIG5HKSCS)
|
||||
CharMIBEnum(2103,CP154)
|
||||
CharMIBEnum(2103,CYRILLIC-ASIAN)
|
||||
CharMIBEnum(2103,PT154)
|
||||
CharMIBEnum(2103,PTCP154)
|
||||
CharMIBEnum(2103,CSPTCP154)
|
||||
CharMIBEnum(2109,CP874)
|
||||
CharMIBEnum(2109,WINDOWS-874)
|
||||
CharMIBEnum(2250,CP1250)
|
||||
CharMIBEnum(2250,MS-EE)
|
||||
CharMIBEnum(2250,WINDOWS-1250)
|
||||
CharMIBEnum(2251,CP1251)
|
||||
CharMIBEnum(2251,MS-CYRL)
|
||||
CharMIBEnum(2251,WINDOWS-1251)
|
||||
CharMIBEnum(2252,CP1252)
|
||||
CharMIBEnum(2252,MS-ANSI)
|
||||
CharMIBEnum(2252,WINDOWS-1252)
|
||||
CharMIBEnum(2253,CP1253)
|
||||
CharMIBEnum(2253,MS-GREEK)
|
||||
CharMIBEnum(2253,WINDOWS-1253)
|
||||
CharMIBEnum(2254,CP1254)
|
||||
CharMIBEnum(2254,MS-TURK)
|
||||
CharMIBEnum(2254,WINDOWS-1254)
|
||||
CharMIBEnum(2255,CP1255)
|
||||
CharMIBEnum(2255,MS-HEBR)
|
||||
CharMIBEnum(2255,WINDOWS-1255)
|
||||
CharMIBEnum(2256,CP1256)
|
||||
CharMIBEnum(2256,MS-ARAB)
|
||||
CharMIBEnum(2256,WINDOWS-1256)
|
||||
CharMIBEnum(2257,CP1257)
|
||||
CharMIBEnum(2257,WINBALTRIM)
|
||||
CharMIBEnum(2257,WINDOWS-1257)
|
||||
CharMIBEnum(2258,CP1258)
|
||||
CharMIBEnum(2258,WINDOWS-1258)
|
||||
CharMIBEnum(2259,ISO-IR-166)
|
||||
CharMIBEnum(2259,TIS-620)
|
||||
CharMIBEnum(2259,TIS620)
|
||||
CharMIBEnum(2259,TIS620-0)
|
||||
CharMIBEnum(2259,TIS620.2529-1)
|
||||
CharMIBEnum(2259,TIS620.2533-0)
|
||||
CharMIBEnum(2259,TIS620.2533-1)
|
||||
|
||||
#undef CharMIBEnum
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* config file functions (when conf is loaded from another source)
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#ifndef __MMS_CFG_IMPL__INCLUDED__
|
||||
#define __MMS_CFG_IMPL__INCLUDED__
|
||||
#include "mms_cfg.h"
|
||||
|
||||
typedef struct mCfgImpl mCfgImpl; /* Implementation-specific struct for config info. */
|
||||
|
||||
/* each implementation must export struct, symbol 'cfg_funcs'. */
|
||||
typedef struct mCfgImpFuncs {
|
||||
mCfgImpl *(*read)(Octstr *init_param);
|
||||
void (*destroy)(mCfgImpl *);
|
||||
mCfgGrp *(*cfg_get_single)(mCfgImpl *cfg, Octstr *name);
|
||||
List *(*get_multi)(mCfgImpl *cfg,Octstr *name); /* List of mCfgGrp */
|
||||
mCfgGrp *(*get_multi_by_field)(mCfgImpl *cfg, Octstr *name, Octstr *field, Octstr *value);
|
||||
Octstr *(*get)(mCfgImpl *cfg, mCfgGrp *grp, Octstr *name);
|
||||
Octstr *(*get_grp_name)(mCfgImpl *, mCfgGrp *);
|
||||
void (*destroy_grp)(mCfgImpl *cfg, mCfgGrp *);
|
||||
} mCfgImpFuncs;
|
||||
|
||||
|
||||
#endif
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* MMS Config file reader functions
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -16,7 +16,8 @@
|
|||
#include <errno.h>
|
||||
|
||||
#include "mms_cfg.h"
|
||||
|
||||
#include "mms_cfg-impl.h"
|
||||
#include "mms_util.h"
|
||||
|
||||
/* config file representation.
|
||||
* 'grps' var is indexed by group name.
|
||||
|
@ -26,9 +27,12 @@
|
|||
struct mCfg {
|
||||
Octstr *file;
|
||||
Dict *grps;
|
||||
|
||||
mCfgImpl *xcfg; /* If set, then this is the real source of conf info. */
|
||||
mCfgImpFuncs *cfg_funcs; /* Config funcs or NULL */
|
||||
};
|
||||
|
||||
struct mCfgGrp {
|
||||
struct mCfgGrp { /* when using file-based, this is our implementation of a group. */
|
||||
Octstr *name;
|
||||
Dict *fields;
|
||||
};
|
||||
|
@ -43,7 +47,7 @@ static void fixup_value(Octstr *value, int lineno)
|
|||
if (octstr_get_char(value, 0) != '"')
|
||||
return;
|
||||
if (octstr_get_char(value, octstr_len(value) - 1) != '"')
|
||||
error(0, "Missing enclosing '\"' at line %d in conf file", lineno);
|
||||
mms_error(0, "mms_cfg", NULL, "Missing enclosing '\"' at line %d in conf file", lineno);
|
||||
|
||||
octstr_delete(value, 0,1); /* strip quotes. */
|
||||
octstr_delete(value, octstr_len(value) - 1, 1);
|
||||
|
@ -83,9 +87,9 @@ static int is_multigroup(Octstr *grpname)
|
|||
{
|
||||
#define OCTSTR(x)
|
||||
#define SINGLE_GROUP(name, fields) \
|
||||
if (octstr_case_compare(grpname, octstr_imm(#name)) == 0) return 0;
|
||||
if (octstr_str_case_compare(grpname, #name) == 0) return 0;
|
||||
#define MULTI_GROUP(name, fields) \
|
||||
if (octstr_case_compare(grpname, octstr_imm(#name)) == 0) return 1;
|
||||
if (octstr_str_case_compare(grpname, #name) == 0) return 1;
|
||||
#include "mms_cfg.def"
|
||||
|
||||
return -1;
|
||||
|
@ -94,9 +98,9 @@ static int is_multigroup(Octstr *grpname)
|
|||
static int valid_in_group(Octstr *grp, Octstr *field)
|
||||
{
|
||||
/* first validate whether field is permitted in the group. */
|
||||
#define OCTSTR(parm) else if (octstr_case_compare(field,octstr_imm(#parm)) == 0) return 1;
|
||||
#define OCTSTR(parm) else if (octstr_str_case_compare(field,#parm) == 0) return 1;
|
||||
#define SINGLE_GROUP(grpname, fields) \
|
||||
else if (octstr_case_compare(grp, octstr_imm(#grpname)) == 0) { \
|
||||
else if (octstr_str_case_compare(grp, #grpname) == 0) { \
|
||||
if (0) (void)0; \
|
||||
fields \
|
||||
}
|
||||
|
@ -112,13 +116,26 @@ static int valid_in_group(Octstr *grp, Octstr *field)
|
|||
static void check_and_add_field(mCfgGrp *grp, Octstr *field, Octstr *value, int lineno)
|
||||
{
|
||||
if (!valid_in_group(grp->name, field))
|
||||
info(0, "field `%s' is not expected within group `%s' at line %d in conf file - skipped",
|
||||
mms_info(0, "mms_cfg", NULL, "field `%s' is not expected within group `%s' at line %d in conf file - skipped",
|
||||
octstr_get_cstr(field), octstr_get_cstr(grp->name), lineno);
|
||||
else if (dict_put_once(grp->fields, field, octstr_duplicate(value)) == 0)
|
||||
panic(0, "Duplicate field `%s' at line %d in conf file",
|
||||
mms_error(0, "mms_cfg", NULL, "Duplicate field `%s' at line %d in conf file, ignored",
|
||||
octstr_get_cstr(field), lineno);
|
||||
}
|
||||
|
||||
static mCfg *make_cfg(Octstr *file)
|
||||
{
|
||||
mCfg *cfg;
|
||||
|
||||
cfg = gw_malloc(sizeof *cfg);
|
||||
cfg->file = file ? octstr_duplicate(file) : NULL;
|
||||
cfg->grps = dict_create(7, NULL);
|
||||
|
||||
cfg->xcfg = NULL;
|
||||
cfg->cfg_funcs = NULL;
|
||||
return cfg;
|
||||
}
|
||||
|
||||
mCfg *mms_cfg_read(Octstr *file)
|
||||
{
|
||||
Octstr *sf;
|
||||
|
@ -131,17 +148,15 @@ mCfg *mms_cfg_read(Octstr *file)
|
|||
gw_assert(file);
|
||||
|
||||
if ((sf = octstr_read_file(octstr_get_cstr(file))) == NULL) {
|
||||
error(errno, "failed to read config from `%s'", octstr_get_cstr(file));
|
||||
mms_error(errno, "mms_cfg", NULL, "failed to read config from `%s'", octstr_get_cstr(file));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cfg = gw_malloc(sizeof *cfg);
|
||||
cfg->file = octstr_duplicate(file);
|
||||
cfg->grps = dict_create(7, NULL);
|
||||
cfg = make_cfg(file);
|
||||
|
||||
lines = octstr_split(sf, octstr_imm("\n"));
|
||||
for (i = 0, n = list_len(lines); i < n; i++) {
|
||||
Octstr *current = list_get(lines,i);
|
||||
for (i = 0, n = gwlist_len(lines); i < n; i++) {
|
||||
Octstr *current = gwlist_get(lines,i);
|
||||
int pos;
|
||||
|
||||
octstr_strip_blanks(current);
|
||||
|
@ -161,16 +176,16 @@ mCfg *mms_cfg_read(Octstr *file)
|
|||
octstr_strip_blanks(field);
|
||||
fixup_value(value, i+1);
|
||||
#if 0
|
||||
info(0, "field/value: [%s - %s]", octstr_get_cstr(field),
|
||||
mms_info(0, "mms_cfg", NULL, "field/value: [%s - %s]", octstr_get_cstr(field),
|
||||
octstr_get_cstr(value));
|
||||
#endif
|
||||
|
||||
if (octstr_case_compare(field, octstr_imm("group")) == 0)
|
||||
if (octstr_str_case_compare(field, "group") == 0)
|
||||
if (grp == NULL) { /* grp name. */
|
||||
int ismulti = is_multigroup(value);
|
||||
|
||||
if (ismulti < 0) {
|
||||
info(0, "Skipping unknown group `%s' at line %d of conf file",
|
||||
mms_info(0, "mms_cfg", NULL, "Skipping unknown group `%s' at line %d of conf file",
|
||||
octstr_get_cstr(value), i+1);
|
||||
skip = 1;
|
||||
} else {
|
||||
|
@ -182,10 +197,10 @@ mCfg *mms_cfg_read(Octstr *file)
|
|||
List *l = dict_get(cfg->grps, value);
|
||||
|
||||
if (l == NULL) {
|
||||
l = list_create();
|
||||
l = gwlist_create();
|
||||
dict_put(cfg->grps, value, l);
|
||||
}
|
||||
list_append(l, grp);
|
||||
gwlist_append(l, grp);
|
||||
} else if (dict_put_once(cfg->grps, value, grp) == 0)
|
||||
panic(0, "Group `%s' [at line %d] cannot appear more "
|
||||
"than once in config!",
|
||||
|
@ -207,8 +222,45 @@ mCfg *mms_cfg_read(Octstr *file)
|
|||
panic(0, "mal-formed entry in conf file at line %d!", i+1);
|
||||
}
|
||||
|
||||
list_destroy(lines, (list_item_destructor_t *)octstr_destroy);
|
||||
gwlist_destroy(lines, (gwlist_item_destructor_t *)octstr_destroy);
|
||||
octstr_destroy(sf);
|
||||
|
||||
/* Now check if config-source is set, use that. */
|
||||
if ((grp = mms_cfg_get_single(cfg, octstr_imm("config-source"))) != NULL) {
|
||||
Octstr *init = mms_cfg_get(cfg, grp, octstr_imm("config-library-init-param"));
|
||||
cfg->cfg_funcs = _mms_load_module(cfg, grp, "config-library", "cfg_funcs", NULL);
|
||||
|
||||
if (cfg->cfg_funcs == NULL ||
|
||||
cfg->cfg_funcs->read == NULL ||
|
||||
(cfg->xcfg = cfg->cfg_funcs->read(init)) == NULL) {
|
||||
mms_error(0, "mms_cfg", NULL, "Failed to load cfg reader library from conf!");
|
||||
mms_cfg_destroy(cfg);
|
||||
cfg = NULL;
|
||||
}
|
||||
|
||||
octstr_destroy(init);
|
||||
}
|
||||
|
||||
return cfg;
|
||||
}
|
||||
|
||||
mCfg *mms_cfg_read2(mCfgImpFuncs *cfgfuncs, Octstr *init)
|
||||
{
|
||||
mCfg *cfg;
|
||||
|
||||
gw_assert(cfgfuncs);
|
||||
|
||||
cfg = make_cfg(NULL);
|
||||
|
||||
|
||||
cfg->cfg_funcs = cfgfuncs;
|
||||
|
||||
if (cfg->cfg_funcs->read == NULL ||
|
||||
(cfg->xcfg = cfg->cfg_funcs->read(init)) == NULL) {
|
||||
mms_error(0, "mms_cfg", NULL, "Failed to load cfg reader: read failed in cfg_read2!");
|
||||
mms_cfg_destroy(cfg);
|
||||
cfg = NULL;
|
||||
}
|
||||
return cfg;
|
||||
}
|
||||
|
||||
|
@ -226,20 +278,26 @@ void mms_cfg_destroy(mCfg *cfg)
|
|||
|
||||
gw_assert(cfg);
|
||||
|
||||
for (i = 0, l = dict_keys(cfg->grps), n = list_len(l); i < n; i++) {
|
||||
Octstr *grpname = list_get(l, i);
|
||||
for (i = 0, l = dict_keys(cfg->grps), n = gwlist_len(l); i < n; i++) {
|
||||
Octstr *grpname = gwlist_get(l, i);
|
||||
void *val = dict_get(cfg->grps, grpname);
|
||||
if (is_multigroup(grpname)) {
|
||||
if (is_multigroup(grpname)) { /* item is a list. */
|
||||
List *gl = val;
|
||||
int j, m = list_len(gl);
|
||||
int j, m = gwlist_len(gl);
|
||||
for (j = 0; j < m; j++)
|
||||
mGrp_destroy(list_get(gl, j));
|
||||
mGrp_destroy(gwlist_get(gl, j));
|
||||
gwlist_destroy(gl, NULL);
|
||||
} else
|
||||
mGrp_destroy(val);
|
||||
}
|
||||
list_destroy(l, (list_item_destructor_t *)octstr_destroy);
|
||||
gwlist_destroy(l, (gwlist_item_destructor_t *)octstr_destroy);
|
||||
dict_destroy(cfg->grps);
|
||||
octstr_destroy(cfg->file);
|
||||
|
||||
if (cfg->xcfg && cfg->cfg_funcs &&
|
||||
cfg->cfg_funcs->destroy)
|
||||
cfg->cfg_funcs->destroy(cfg->xcfg);
|
||||
|
||||
gw_free(cfg);
|
||||
}
|
||||
|
||||
|
@ -248,46 +306,94 @@ mCfgGrp *mms_cfg_get_single(mCfg *cfg, Octstr *name)
|
|||
gw_assert(name);
|
||||
gw_assert(is_multigroup(name) == 0);
|
||||
|
||||
if (cfg->xcfg == NULL)
|
||||
return dict_get(cfg->grps, name);
|
||||
else
|
||||
return cfg->cfg_funcs->cfg_get_single(cfg->xcfg, name);
|
||||
}
|
||||
|
||||
List *mms_cfg_get_multi(mCfg *cfg, Octstr *name)
|
||||
{
|
||||
List *l = NULL, *r;
|
||||
int i;
|
||||
|
||||
gw_assert(name);
|
||||
gw_assert(is_multigroup(name) == 1);
|
||||
|
||||
if (cfg->xcfg == NULL) {
|
||||
List *l = NULL, *r;
|
||||
int i;
|
||||
r = dict_get(cfg->grps, name);
|
||||
|
||||
if (r)
|
||||
for (i = 0, l = list_create(); i < list_len(r); i++)
|
||||
list_append(l, list_get(r,i));
|
||||
for (i = 0, l = gwlist_create(); i < gwlist_len(r); i++)
|
||||
gwlist_append(l, gwlist_get(r,i));
|
||||
return l;
|
||||
} else
|
||||
return cfg->cfg_funcs->get_multi(cfg->xcfg, name);
|
||||
}
|
||||
|
||||
Octstr *mms_cfg_get(mCfgGrp *grp, Octstr *name)
|
||||
void mms_cfg_destroy_grp(mCfg *cfg, mCfgGrp *grp)
|
||||
{
|
||||
gw_assert(cfg);
|
||||
if (cfg->xcfg == NULL || cfg->cfg_funcs == NULL || cfg->cfg_funcs->destroy_grp == NULL)
|
||||
return;
|
||||
else
|
||||
cfg->cfg_funcs->destroy_grp(cfg->xcfg, grp);
|
||||
}
|
||||
|
||||
mCfgGrp *mms_get_multi_by_field(mCfg *cfg, Octstr *name, Octstr *field, Octstr *value)
|
||||
{
|
||||
|
||||
gw_assert(name);
|
||||
gw_assert(is_multigroup(name) == 1);
|
||||
|
||||
if (!valid_in_group(name, field))
|
||||
panic(0, "Request for invalid field/variable `%s' in group `%s', unexpected!",
|
||||
octstr_get_cstr(field), octstr_get_cstr(name));
|
||||
|
||||
if (cfg->xcfg == NULL) {
|
||||
mCfgGrp *grp;
|
||||
Octstr *val;
|
||||
List *r;
|
||||
int i;
|
||||
r = dict_get(cfg->grps, name);
|
||||
if (r)
|
||||
for (i = 0; i < gwlist_len(r); i++)
|
||||
if ((grp = gwlist_get(r, i)) != NULL &&
|
||||
(val = dict_get(grp->fields, field)) != NULL &&
|
||||
octstr_compare(val, value) == 0)
|
||||
return grp;
|
||||
return NULL;
|
||||
} else
|
||||
return cfg->cfg_funcs->get_multi_by_field(cfg->xcfg, name, field, value);
|
||||
|
||||
}
|
||||
|
||||
Octstr *mms_cfg_get(mCfg *cfg, mCfgGrp *grp, Octstr *name)
|
||||
{
|
||||
Octstr *val;
|
||||
Octstr *grp_name = cfg->xcfg ? cfg->cfg_funcs->get_grp_name(cfg->xcfg, grp) :
|
||||
octstr_duplicate(grp->name);
|
||||
|
||||
gw_assert(grp);
|
||||
|
||||
if (!valid_in_group(grp->name, name))
|
||||
if (!valid_in_group(grp_name, name))
|
||||
panic(0, "Request for invalid field/variable `%s' in group `%s', unexpected!",
|
||||
octstr_get_cstr(name), octstr_get_cstr(grp->name));
|
||||
octstr_get_cstr(name), octstr_get_cstr(grp_name));
|
||||
|
||||
octstr_destroy(grp_name);
|
||||
if (cfg->xcfg == NULL) {
|
||||
gw_assert(grp);
|
||||
val = dict_get(grp->fields, name);
|
||||
|
||||
if (!val)
|
||||
return NULL;
|
||||
else
|
||||
return octstr_duplicate(val);
|
||||
val = octstr_duplicate(val);
|
||||
} else {
|
||||
val = cfg->cfg_funcs->get(cfg->xcfg, grp, name);
|
||||
if (val)
|
||||
fixup_value(val, 0);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
int mms_cfg_get_int(mCfgGrp *grp, Octstr *name, long *n)
|
||||
int mms_cfg_get_int(mCfg *cfg, mCfgGrp *grp, Octstr *name, long *n)
|
||||
{
|
||||
Octstr *val = mms_cfg_get(grp, name);
|
||||
Octstr *val = mms_cfg_get(cfg, grp, name);
|
||||
int ret;
|
||||
if (!val)
|
||||
return -1;
|
||||
|
@ -297,24 +403,28 @@ int mms_cfg_get_int(mCfgGrp *grp, Octstr *name, long *n)
|
|||
}
|
||||
|
||||
|
||||
int mms_cfg_get_bool(mCfgGrp *grp, Octstr *name, int *bool)
|
||||
int mms_cfg_get_bool(mCfg *cfg, mCfgGrp *grp, Octstr *name, int *bool)
|
||||
{
|
||||
Octstr *val = mms_cfg_get(grp, name);
|
||||
Octstr *val = mms_cfg_get(cfg, grp, name);
|
||||
int ret = 0;
|
||||
if (!val)
|
||||
return -1;
|
||||
|
||||
if (octstr_case_compare(val, octstr_imm("yes")) == 0 ||
|
||||
octstr_case_compare(val, octstr_imm("true")) == 0 ||
|
||||
octstr_case_compare(val, octstr_imm("1")) == 0)
|
||||
if (octstr_str_case_compare(val, "yes") == 0 ||
|
||||
octstr_str_case_compare(val, "true") == 0 ||
|
||||
octstr_str_case_compare(val, "1") == 0)
|
||||
*bool = 1;
|
||||
else if (octstr_case_compare(val, octstr_imm("no")) == 0 ||
|
||||
octstr_case_compare(val, octstr_imm("false")) == 0 ||
|
||||
octstr_case_compare(val, octstr_imm("0")) == 0)
|
||||
else if (octstr_str_case_compare(val, "no") == 0 ||
|
||||
octstr_str_case_compare(val, "false") == 0 ||
|
||||
octstr_str_case_compare(val, "0") == 0)
|
||||
*bool = 0;
|
||||
else {
|
||||
error(0, "Unable to convert value `%s' to boolean for field `%s' in group `%s'",
|
||||
octstr_get_cstr(val), octstr_get_cstr(name), octstr_get_cstr(grp->name));
|
||||
Octstr *grp_name = cfg->xcfg ? cfg->cfg_funcs->get_grp_name(cfg->xcfg, grp) :
|
||||
octstr_duplicate(grp->name);
|
||||
|
||||
mms_error(0, "mms_cfg", NULL, "Unable to convert value `%s' to boolean for field `%s' in group `%s'",
|
||||
octstr_get_cstr(val), octstr_get_cstr(name), octstr_get_cstr(grp_name));
|
||||
octstr_destroy(grp_name);
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
|
@ -322,9 +432,9 @@ int mms_cfg_get_bool(mCfgGrp *grp, Octstr *name, int *bool)
|
|||
return ret;
|
||||
}
|
||||
|
||||
List *mms_cfg_get_list(mCfgGrp *grp, Octstr *name)
|
||||
List *mms_cfg_get_list(mCfg *cfg, mCfgGrp *grp, Octstr *name)
|
||||
{
|
||||
Octstr *val = mms_cfg_get(grp, name);
|
||||
Octstr *val = mms_cfg_get(cfg, grp, name);
|
||||
List *l;
|
||||
|
||||
if (val == NULL)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* MMS Config structure definitions
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 20058 Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -23,6 +23,16 @@
|
|||
#error MULTI_GROUP not defined.
|
||||
#endif
|
||||
|
||||
/* config-source: If it exists, the rest of the conf file is
|
||||
* ignored. Instead, use the provided lib as the reader of the
|
||||
* config info. (See mms_cfg-impl.h for details)
|
||||
*/
|
||||
|
||||
SINGLE_GROUP(config-source,
|
||||
OCTSTR(config-library)
|
||||
OCTSTR(config-library-init-param)
|
||||
)
|
||||
|
||||
SINGLE_GROUP(core,
|
||||
OCTSTR(log-file)
|
||||
OCTSTR(log-level)
|
||||
|
@ -36,22 +46,28 @@ SINGLE_GROUP(core,
|
|||
OCTSTR(ssl-server-cert-file)
|
||||
OCTSTR(ssl-server-key-file)
|
||||
OCTSTR(ssl-trusted-ca-file)
|
||||
|
||||
OCTSTR(http-interface-name)
|
||||
)
|
||||
|
||||
SINGLE_GROUP(mbuni,
|
||||
OCTSTR(name)
|
||||
OCTSTR(hostname)
|
||||
OCTSTR(host-alias)
|
||||
OCTSTR(local-mmsc-domains)
|
||||
OCTSTR(local-prefixes)
|
||||
OCTSTR(storage-directory)
|
||||
OCTSTR(queue-manager-module)
|
||||
OCTSTR(queue-module-init-data)
|
||||
OCTSTR(max-send-threads)
|
||||
OCTSTR(send-mail-prog)
|
||||
OCTSTR(unified-prefix)
|
||||
OCTSTR(strip-prefixes)
|
||||
OCTSTR(maximum-send-attempts)
|
||||
OCTSTR(mm1-maximum-notify-attempts)
|
||||
OCTSTR(mmsbox-maximum-request-attempts)
|
||||
OCTSTR(default-message-expiry)
|
||||
OCTSTR(max-message-expiry)
|
||||
OCTSTR(queue-run-interval)
|
||||
OCTSTR(mm1-queue-run-interval)
|
||||
OCTSTR(send-attempt-back-off)
|
||||
OCTSTR(sendsms-url)
|
||||
OCTSTR(sendsms-username)
|
||||
|
@ -59,6 +75,7 @@ SINGLE_GROUP(mbuni,
|
|||
OCTSTR(sendsms-global-sender)
|
||||
OCTSTR(mms-port)
|
||||
OCTSTR(mm7-port)
|
||||
OCTSTR(mm4-port)
|
||||
OCTSTR(allow-ip)
|
||||
OCTSTR(deny-ip)
|
||||
OCTSTR(email2mms-relay-hosts)
|
||||
|
@ -73,18 +90,40 @@ SINGLE_GROUP(mbuni,
|
|||
OCTSTR(notify-unprovisioned)
|
||||
OCTSTR(mms-notify-text)
|
||||
OCTSTR(mms-notify-unprovisioned-text)
|
||||
OCTSTR(mm-box-host)
|
||||
OCTSTR(mms-to-email-txt)
|
||||
OCTSTR(mms-to-email-html)
|
||||
OCTSTR(mms-to-email-default-subject)
|
||||
OCTSTR(mms-message-too-large-txt)
|
||||
OCTSTR(mms-client-msisdn-header)
|
||||
OCTSTR(mms-client-ip-header)
|
||||
OCTSTR(allow-ip-type)
|
||||
OCTSTR(optimize-notification-size)
|
||||
OCTSTR(content-adaptation)
|
||||
|
||||
OCTSTR(send-dlr-on-fetch)
|
||||
OCTSTR(sendmms-port)
|
||||
OCTSTR(sendmms-port-ssl)
|
||||
|
||||
OCTSTR(mmsbox-mt-filter-library)
|
||||
OCTSTR(mmsbox-mt-always-multipart)
|
||||
|
||||
OCTSTR(mmsbox-admin-port)
|
||||
OCTSTR(mmsc-admin-port)
|
||||
OCTSTR(admin-port-ssl)
|
||||
OCTSTR(admin-password)
|
||||
|
||||
OCTSTR(admin-allow-ip)
|
||||
OCTSTR(admin-deny-ip)
|
||||
|
||||
OCTSTR(event-logger-module)
|
||||
OCTSTR(event-logger-module-parameters)
|
||||
|
||||
OCTSTR(mm5-module)
|
||||
OCTSTR(mm5-module-parameters)
|
||||
|
||||
OCTSTR(mmsbox-cdr-module)
|
||||
OCTSTR(mmsbox-cdr-module-parameters)
|
||||
OCTSTR(mmsc-services)
|
||||
OCTSTR(smtp-relay)
|
||||
)
|
||||
|
||||
MULTI_GROUP(mmsproxy,
|
||||
|
@ -92,19 +131,27 @@ MULTI_GROUP(mmsproxy,
|
|||
OCTSTR(host)
|
||||
OCTSTR(allowed-prefix)
|
||||
OCTSTR(denied-prefix)
|
||||
OCTSTR(send-mail-prog)
|
||||
OCTSTR(confirmed-delivery)
|
||||
OCTSTR(unified-prefix)
|
||||
OCTSTR(strip-prefixes)
|
||||
)
|
||||
|
||||
MULTI_GROUP(mms-vasp,
|
||||
OCTSTR(vasp-id)
|
||||
OCTSTR(type)
|
||||
OCTSTR(mm7-version)
|
||||
OCTSTR(mm7-soap-xmlns)
|
||||
OCTSTR(use-mm7-soap-namespace-prefix)
|
||||
OCTSTR(short-code)
|
||||
OCTSTR(short-codes)
|
||||
OCTSTR(vasp-username)
|
||||
OCTSTR(vasp-password)
|
||||
OCTSTR(vasp-url)
|
||||
OCTSTR(mms-to-email-handler)
|
||||
OCTSTR(mms-to-local-copy-handler)
|
||||
OCTSTR(mmsc-username)
|
||||
OCTSTR(mmsc-password)
|
||||
OCTSTR(send-uaprof)
|
||||
OCTSTR(throughput)
|
||||
)
|
||||
|
||||
MULTI_GROUP(send-mms-user,
|
||||
|
@ -113,10 +160,13 @@ MULTI_GROUP(send-mms-user,
|
|||
OCTSTR(faked-sender)
|
||||
OCTSTR(delivery-report-url)
|
||||
OCTSTR(read-report-url)
|
||||
OCTSTR(mmsc)
|
||||
)
|
||||
|
||||
MULTI_GROUP(mmsc,
|
||||
OCTSTR(id)
|
||||
OCTSTR(group-id)
|
||||
OCTSTR(vasp-id)
|
||||
OCTSTR(mmsc-url)
|
||||
OCTSTR(incoming-username)
|
||||
OCTSTR(incoming-password)
|
||||
|
@ -125,9 +175,40 @@ MULTI_GROUP(mmsc,
|
|||
OCTSTR(deny-ip)
|
||||
OCTSTR(allowed-prefix)
|
||||
OCTSTR(denied-prefix)
|
||||
OCTSTR(denied-sender-prefix)
|
||||
OCTSTR(allowed-sender-prefix)
|
||||
OCTSTR(incoming-port-ssl)
|
||||
OCTSTR(max-throughput)
|
||||
OCTSTR(type)
|
||||
OCTSTR(allow-adaptations)
|
||||
OCTSTR(mm7-version)
|
||||
OCTSTR(mm7-soap-xmlns)
|
||||
OCTSTR(use-mm7-soap-namespace-prefix)
|
||||
OCTSTR(mm7-mt-filter-params)
|
||||
OCTSTR(reroute)
|
||||
OCTSTR(reroute-mmsc-id)
|
||||
OCTSTR(reroute-add-sender-to-subject)
|
||||
OCTSTR(mmsc-library)
|
||||
OCTSTR(custom-settings)
|
||||
OCTSTR(no-sender-address)
|
||||
|
||||
OCTSTR(default-vasid)
|
||||
OCTSTR(maximum-request-size)
|
||||
OCTSTR(strip-domain)
|
||||
|
||||
OCTSTR(max-recipients)
|
||||
|
||||
OCTSTR(strip-prefixes)
|
||||
OCTSTR(retry-statuses)
|
||||
OCTSTR(mm1-http-proxy)
|
||||
OCTSTR(mm1-gprs-on-command)
|
||||
OCTSTR(mm1-gprs-off-command)
|
||||
OCTSTR(mm1-gprs-pid-command)
|
||||
OCTSTR(mm1-sms-on-command)
|
||||
OCTSTR(mm1-sms-off-command)
|
||||
OCTSTR(mm1-msisdn)
|
||||
OCTSTR(mm1-ua-string)
|
||||
OCTSTR(carrier-id-header)
|
||||
)
|
||||
|
||||
MULTI_GROUP(mms-service,
|
||||
|
@ -140,13 +221,19 @@ MULTI_GROUP(mms-service,
|
|||
OCTSTR(faked-sender)
|
||||
OCTSTR(catch-all)
|
||||
OCTSTR(omit-empty)
|
||||
OCTSTR(suppress-reply)
|
||||
OCTSTR(accept-x-mbuni-headers)
|
||||
OCTSTR(pass-thro-headers)
|
||||
OCTSTR(assume-plain-text)
|
||||
OCTSTR(accepted-mmscs)
|
||||
OCTSTR(denied-mmscs)
|
||||
OCTSTR(denied-receiver-prefix)
|
||||
OCTSTR(allowed-receiver-prefix)
|
||||
OCTSTR(keyword)
|
||||
OCTSTR(aliases)
|
||||
OCTSTR(http-post-parameters)
|
||||
OCTSTR(service-code)
|
||||
OCTSTR(extra-reply-content-header)
|
||||
)
|
||||
#undef OCTSTR
|
||||
#undef SINGLE_GROUP
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* config file functions
|
||||
*
|
||||
* Copyright (C) 2003 - 2006, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -16,15 +16,18 @@
|
|||
#include "gwlib/gwlib.h"
|
||||
#include "gwlib/mime.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "mbuni-config.h"
|
||||
|
||||
typedef struct mCfg mCfg; /* config file structure. */
|
||||
typedef struct mCfgGrp mCfgGrp; /* A config group. */
|
||||
|
||||
struct mCfgImpFuncs; /* Defined in mms_cfg-impl.h */
|
||||
|
||||
/* Read a config file, return the structure. */
|
||||
mCfg *mms_cfg_read(Octstr *file);
|
||||
|
||||
/* Read conf from a module */
|
||||
mCfg *mms_cfg_read2(struct mCfgImpFuncs *cfgfuncs, Octstr *init);
|
||||
|
||||
/* Destroy it all . */
|
||||
void mms_cfg_destroy(mCfg *cfg);
|
||||
|
||||
|
@ -34,22 +37,29 @@ mCfgGrp *mms_cfg_get_single(mCfg *cfg, Octstr *name);
|
|||
/* Get a multiple groups all of same name. */
|
||||
List *mms_cfg_get_multi(mCfg *cfg,Octstr *name);
|
||||
|
||||
mCfgGrp *mms_get_multi_by_field(mCfg *cfg, Octstr *name, Octstr *field, Octstr *value);
|
||||
|
||||
/* Destroy a group object after user -- call this to cleanup memory used by group object
|
||||
* always!
|
||||
*/
|
||||
void mms_cfg_destroy_grp(mCfg *, mCfgGrp *);
|
||||
|
||||
/* Get a string field value from a group. */
|
||||
Octstr *mms_cfg_get(mCfgGrp *grp, Octstr *name);
|
||||
Octstr *mms_cfg_get(mCfg *cfg, mCfgGrp *grp, Octstr *name);
|
||||
|
||||
|
||||
/* Get an integer field value from a group.
|
||||
* returns 0 on success, -1 on error.
|
||||
*/
|
||||
int mms_cfg_get_int(mCfgGrp *grp, Octstr *name, long *n);
|
||||
int mms_cfg_get_int(mCfg *cfg, mCfgGrp *grp, Octstr *name, long *n);
|
||||
|
||||
/* Get a boolean field value from a group.
|
||||
* returns 0 on success, -1 on error
|
||||
*/
|
||||
int mms_cfg_get_bool(mCfgGrp *grp, Octstr *name, int *bool);
|
||||
int mms_cfg_get_bool(mCfg *cfg, mCfgGrp *grp, Octstr *name, int *val);
|
||||
|
||||
/* Get a field value from a group. */
|
||||
List *mms_cfg_get_list(mCfgGrp *grp, Octstr *name);
|
||||
List *mms_cfg_get_list(mCfg *cfg, mCfgGrp *grp, Octstr *name);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,147 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* Event logger module
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#include "mms_eventlogger.h"
|
||||
#include "mms_util.h"
|
||||
|
||||
static Octstr *shell_cmd;
|
||||
|
||||
/* So that below compiles fine. */
|
||||
#undef error
|
||||
#undef warning
|
||||
#undef info
|
||||
static void default_logger(enum mbuni_event_type_t type, const char *subtype, int err, const char *file,
|
||||
int line,
|
||||
const char *function,
|
||||
const char *interface, Octstr *id,
|
||||
Octstr *msg)
|
||||
{
|
||||
void (*f)(int, const char *,...);
|
||||
switch(type) {
|
||||
case MBUNI_INFO:
|
||||
f = info;
|
||||
break;
|
||||
case MBUNI_WARNING:
|
||||
f = warning;
|
||||
break;
|
||||
default: /* including error. */
|
||||
f = error;
|
||||
break;
|
||||
}
|
||||
|
||||
f(err, "%s:%d <%s> [%s] [%s] %s",
|
||||
file, line, function,
|
||||
interface ? interface : "n/a",
|
||||
id ? octstr_get_cstr(id) : "n/a",
|
||||
octstr_get_cstr(msg));
|
||||
}
|
||||
|
||||
|
||||
static void shell_logger(enum mbuni_event_type_t type, const char *subtype, int err, const char *file,
|
||||
int line, const char *function,
|
||||
const char *interface, Octstr *id,
|
||||
Octstr *msg)
|
||||
{
|
||||
char *xtype;
|
||||
Octstr *cmd, *xid = octstr_duplicate(id);
|
||||
|
||||
gw_assert(shell_cmd);
|
||||
|
||||
switch(type) {
|
||||
case MBUNI_INFO:
|
||||
xtype = "INFO";
|
||||
break;
|
||||
case MBUNI_WARNING:
|
||||
xtype = "WARNING";
|
||||
break;
|
||||
|
||||
default: /* including error. */
|
||||
xtype = "ERROR";
|
||||
break;
|
||||
}
|
||||
|
||||
escape_shell_chars(msg);
|
||||
escape_shell_chars(id);
|
||||
|
||||
|
||||
cmd = octstr_format("%S '%s' '%s' %d '%s' '%s' %d '%S' '%S'",
|
||||
shell_cmd, xtype, subtype ? subtype : "", err, interface ? interface : "", file, line, xid ? xid : octstr_imm(""), msg);
|
||||
system(octstr_get_cstr(cmd));
|
||||
|
||||
octstr_destroy(cmd);
|
||||
octstr_destroy(xid);
|
||||
}
|
||||
|
||||
static int init_default_logger(Octstr *param)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int init_shell_logger(Octstr *cmd)
|
||||
{
|
||||
shell_cmd = octstr_duplicate(cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int cleanup_shell_logger(void)
|
||||
{
|
||||
octstr_destroy(shell_cmd);
|
||||
shell_cmd = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static MmsEventLoggerFuncs default_handler = {init_default_logger, default_logger}, *log_handler = &default_handler;
|
||||
|
||||
MmsEventLoggerFuncs shell_event_logger = {
|
||||
init_shell_logger,
|
||||
shell_logger,
|
||||
cleanup_shell_logger
|
||||
};
|
||||
|
||||
int mms_event_logger_init(MmsEventLoggerFuncs *funcs, Octstr *init_param)
|
||||
{
|
||||
if (funcs && (funcs->init == NULL ||
|
||||
funcs->init(init_param) == 0)) {
|
||||
log_handler = funcs;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern void mms_event_logger(enum mbuni_event_type_t type, const char *subtype, int err, const char *file,
|
||||
int line, const char *function, char *interface, Octstr *id,
|
||||
char *fmt,...)
|
||||
{
|
||||
Octstr *x;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
x = octstr_format_valist(fmt, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
log_handler->log_event(type,subtype, err, file, line, function, interface, id, x);
|
||||
|
||||
octstr_destroy(x);
|
||||
}
|
||||
|
||||
void mms_event_logger_cleanup(void)
|
||||
{
|
||||
if (log_handler->cleanup)
|
||||
log_handler->cleanup();
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* Event logger module
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#ifndef __MMS_EVENTLOGGER__INCLUDED__
|
||||
#define __MMS_EVENTLOGGER__INCLUDED__
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "gwlib/gwlib.h"
|
||||
|
||||
typedef enum mbuni_event_type_t {MBUNI_ERROR, MBUNI_INFO, MBUNI_WARNING} mbuni_event_type_t;
|
||||
typedef struct MmsEventLoggerFuncs {
|
||||
int (*init)(Octstr *init_param);
|
||||
void (*log_event)(enum mbuni_event_type_t type, const char *subtype, int err, const char *file,
|
||||
int line,
|
||||
const char *function,
|
||||
const char *interface, Octstr *id,
|
||||
Octstr *msg);
|
||||
int (*cleanup)(void);
|
||||
} MmsEventLoggerFuncs;
|
||||
/* A module should expose a module of the above type with name: logger */
|
||||
|
||||
extern int mms_event_logger_init(MmsEventLoggerFuncs *funcs, Octstr *init_param);
|
||||
/* logger function:
|
||||
* - interface is one of MM1, MM4, etc.
|
||||
* - id is an id for the interface element (e.g. mmsc id)
|
||||
*/
|
||||
extern void mms_event_logger_cleanup(void);
|
||||
extern void mms_event_logger(enum mbuni_event_type_t type, const char *subtype,
|
||||
int err, const char *file,
|
||||
int line, const char *function,
|
||||
char *interface, Octstr *id,
|
||||
char *fmt,...);
|
||||
|
||||
#define mms_error(err,intf,id,fmt,...) mms_event_logger(MBUNI_ERROR, NULL, (err), __FILE__, __LINE__,__FUNCTION__,(intf), (id),(fmt),##__VA_ARGS__)
|
||||
#define mms_info(err,intf,id,fmt,...) mms_event_logger(MBUNI_INFO, NULL, (err), __FILE__, __LINE__,__FUNCTION__,(intf), (id),(fmt),##__VA_ARGS__)
|
||||
#define mms_warning(err,intf,id,fmt,...) mms_event_logger(MBUNI_WARNING, NULL, (err), __FILE__, __LINE__,__FUNCTION__,(intf), (id),(fmt),##__VA_ARGS__)
|
||||
|
||||
#define mms_error_ex(subtype,err,intf,id,fmt,...) mms_event_logger(MBUNI_ERROR, (subtype), (err), __FILE__, __LINE__,__FUNCTION__,(intf), (id),(fmt),##__VA_ARGS__)
|
||||
#define mms_info_ex(subtype,err,intf,id,fmt,...) mms_event_logger(MBUNI_INFO, (subtype), (err), __FILE__, __LINE__,__FUNCTION__,(intf), (id),(fmt),##__VA_ARGS__)
|
||||
#define mms_warning_ex(subtype,err,intf,id,fmt,...) mms_event_logger(MBUNI_WARNING, (subtype), (err), __FILE__, __LINE__,__FUNCTION__,(intf), (id),(fmt),##__VA_ARGS__)
|
||||
|
||||
|
||||
extern MmsEventLoggerFuncs shell_event_logger; /* For logging using a shell command. */
|
||||
|
||||
/* Stop all from using gwlib info, error and warning functions */
|
||||
#define error use_mms_error_instead
|
||||
#define warning use_mms_warning_instead
|
||||
#define info use_mms_info_instead
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* MM7/SOAP message encoder/decoder and helper functions
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -16,17 +16,34 @@
|
|||
|
||||
#define MM7_SOAP_OK 1000
|
||||
#define MM7_SOAP_FORMAT_CORRUPT 2007
|
||||
#define MM7_SOAP_COMMAND_REJECTED 3005
|
||||
#define MM7_SOAP_UNSUPPORTED_OPERATION 4003
|
||||
#define MM7_SOAP_STATUS_OK(e) ((e) / 1000 == 1)
|
||||
#define MM7_DEFAULT_VERSION "5.3.0"
|
||||
#define MM7_SOAP_STATUS_OK(e) (((e) / 1000) == 1)
|
||||
#define MM7_SOAP_CLIENT_ERROR(e) (((e) / 1000) == 2)
|
||||
|
||||
#if 0
|
||||
#define MM7_DEFAULT_VERSION MMS_3GPP_VERSION
|
||||
#define MM7_VERSION "5.3.0"
|
||||
#endif
|
||||
|
||||
#define DEFAULT_MM7_VERSION MAKE_VERSION(5,3,0)
|
||||
|
||||
typedef struct MSoapMsg_t MSoapMsg_t;
|
||||
|
||||
typedef struct MM7Version_t {
|
||||
int major, minor1, minor2; /* e.g. 5.1.0. */
|
||||
int use_mm7_namespace; /* whether to put in the namespace prefix. */
|
||||
char xmlns[128];
|
||||
} MM7Version_t;
|
||||
|
||||
/* Parse SOAP message given http headers and body. */
|
||||
extern MSoapMsg_t *mm7_parse_soap(List *headers, Octstr *body);
|
||||
|
||||
/* Convert message type to mm7 type code */
|
||||
extern int mm7_msgtype_to_soaptype(int mtype, int isclientside);
|
||||
|
||||
/* Convert SOAP message to http headers and body. */
|
||||
extern int mm7_soapmsg_to_httpmsg(MSoapMsg_t *m, List **hdrs, Octstr **body);
|
||||
extern int mm7_soapmsg_to_httpmsg(MSoapMsg_t *m, MM7Version_t *ver, List **hdrs, Octstr **body);
|
||||
|
||||
/* Convert SOAP message to an MMS message. */
|
||||
extern MmsMsg *mm7_soap_to_mmsmsg(MSoapMsg_t *m, Octstr *from);
|
||||
|
@ -44,7 +61,9 @@ extern int mm7_get_envelope(MSoapMsg_t *m, Octstr **sender,
|
|||
List **to, Octstr **subject,
|
||||
Octstr **vasid,
|
||||
time_t *expiry_t,
|
||||
time_t *delivery_t);
|
||||
time_t *delivery_t,
|
||||
Octstr **uaprof,
|
||||
time_t *uaprof_tstamp);
|
||||
|
||||
/* Delete the thingie... */
|
||||
extern void mm7_soap_destroy(MSoapMsg_t *m);
|
||||
|
@ -54,8 +73,14 @@ MSoapMsg_t *mm7_mmsmsg_to_soap(MmsMsg *msg, Octstr *from, List *xto,
|
|||
Octstr *transid, Octstr *srvcode,
|
||||
Octstr *linkedid,
|
||||
int isclientside,
|
||||
char *vaspid, char *vasid);
|
||||
MSoapMsg_t *mm7_make_resp(MSoapMsg_t *mreq, int status, Octstr *msgid);
|
||||
char *vaspid, char *vasid,
|
||||
Octstr *uaprof,
|
||||
time_t uaprof_tstamp,
|
||||
List *extra_hdrs);
|
||||
MSoapMsg_t *mm7_make_resp(MSoapMsg_t *mreq, int status, Octstr *msgid, int isclientside);
|
||||
/* Return the header value for some header. */
|
||||
Octstr *mm7_soap_header_value(MSoapMsg_t *m, Octstr *header);
|
||||
|
||||
/* Return (a copy of) all the headers */
|
||||
List *mm7_soap_headers(MSoapMsg_t *m);
|
||||
#endif
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Mbuni MMBox implementation
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/file.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
@ -91,7 +92,7 @@ static Octstr *user_mmbox_dir(char *mmbox_root, char *userid)
|
|||
if (mkdir(fbuf,
|
||||
S_IRWXU|S_IRWXG) < 0 &&
|
||||
errno != EEXIST) {
|
||||
error(0, "mmbox: failed to create dir [%s] "
|
||||
mms_error(0, "mmbox", NULL, "Failed to create dir [%s] "
|
||||
"while initialising mmbox for %s: %s!",
|
||||
fbuf, userid, strerror(errno));
|
||||
return NULL;
|
||||
|
@ -105,7 +106,7 @@ static Octstr *user_mmbox_dir(char *mmbox_root, char *userid)
|
|||
if (mkdir(octstr_get_cstr(s),
|
||||
S_IRWXU|S_IRWXG) < 0 &&
|
||||
errno != EEXIST) {
|
||||
error(0, "mmbox: failed to create dir [%s] "
|
||||
mms_error(0, "mmbox", NULL, "Failed to create dir [%s] "
|
||||
"while initialising mmbox for %s: %s!",
|
||||
octstr_get_cstr(s), userid, strerror(errno));
|
||||
octstr_destroy(s);
|
||||
|
@ -139,7 +140,7 @@ static int mkdf(char df[64], char *mmbox_home)
|
|||
if (mkdir(octstr_get_cstr(tmp),
|
||||
S_IRWXU|S_IRWXG) < 0 &&
|
||||
errno != EEXIST) {
|
||||
error(0, "mmbox.mkdf: failed to create dir [%s] "
|
||||
mms_error(0, "mmbox", NULL, "failed to create dir [%s] "
|
||||
" in mmbox home %s: %s!",
|
||||
octstr_get_cstr(tmp), mmbox_home, strerror(errno));
|
||||
octstr_destroy(tmp);
|
||||
|
@ -158,7 +159,7 @@ static int mkdf(char df[64], char *mmbox_home)
|
|||
if (mkdir(octstr_get_cstr(tmp),
|
||||
S_IRWXU|S_IRWXG) < 0 &&
|
||||
errno != EEXIST) {
|
||||
error(0, "mmbox.mkdf: failed to create dir [%s] "
|
||||
mms_error(0, "mmbox", NULL, "Failed to create dir [%s] "
|
||||
" in mmbox home %s: %s!",
|
||||
octstr_get_cstr(tmp), mmbox_home, strerror(errno));
|
||||
octstr_destroy(tmp);
|
||||
|
@ -177,7 +178,7 @@ static int mkdf(char df[64], char *mmbox_home)
|
|||
if (fd >= 0 &&
|
||||
mm_lockfile(fd,ctmp,1) != 0) {
|
||||
unlink(ctmp);
|
||||
close(fd);
|
||||
unlock_and_close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
octstr_destroy(tmp);
|
||||
|
@ -197,11 +198,11 @@ static int open_mmbox_index(char *mmbox_dir, int shouldblock)
|
|||
i = 0;
|
||||
do
|
||||
if ((fd = open(fbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)) < 0) {
|
||||
error(0, "Failed to open mmbox index file [%s], error: %s!",
|
||||
mms_error(0, "mmbox", NULL, "Failed to open mmbox index file [%s], error: %s!",
|
||||
fbuf, strerror(errno));
|
||||
break;
|
||||
} else if (mm_lockfile(fd, fbuf, shouldblock) != 0) {
|
||||
close(fd);
|
||||
unlock_and_close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
while (i++ < MAXTRIES && fd < 0);
|
||||
|
@ -215,8 +216,8 @@ static Octstr *linearise_string_list(List *l, char *sep)
|
|||
|
||||
Octstr *s = octstr_create("");
|
||||
|
||||
for (i = 0, n = list_len(l); i < n; i++) {
|
||||
Octstr *p = list_get(l,i);
|
||||
for (i = 0, n = gwlist_len(l); i < n; i++) {
|
||||
Octstr *p = gwlist_get(l,i);
|
||||
if (p)
|
||||
octstr_format_append(s, "%s%S", (i == 0) ? "" : sep, p);
|
||||
}
|
||||
|
@ -227,10 +228,10 @@ static List *parse_string_list(char *buf)
|
|||
{
|
||||
int i = 0;
|
||||
char sbuf[128], *p = buf;
|
||||
List *l = list_create();
|
||||
List *l = gwlist_create();
|
||||
|
||||
while (sscanf(p, "%s%n", sbuf, &i) > 0) {
|
||||
list_append(l, octstr_create(sbuf));
|
||||
gwlist_append(l, octstr_create(sbuf));
|
||||
p += i;
|
||||
}
|
||||
|
||||
|
@ -263,15 +264,15 @@ static int update_mmbox_index(int fd, char *mmbox_dir, int cmd,
|
|||
tempfd = open(fbuf,
|
||||
O_RDWR|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
|
||||
if (tempfd < 0 ) {
|
||||
error(0, "mmbox.update_index: Failed to open temp file %s: error = %s\n",
|
||||
mms_error(0, "mmbox", NULL,"Failed to open temp file %s: error = %s\n",
|
||||
fbuf, strerror(errno));
|
||||
|
||||
goto done;
|
||||
} else if (mm_lockfile(tempfd, fbuf, 0) != 0) { /* Lock it. */
|
||||
error(0, "mmbox.update_index: Failed lock temp file %s: error = %s\n",
|
||||
mms_error(0, "mmbox", NULL,"Failed lock temp file %s: error = %s\n",
|
||||
fbuf, strerror(errno));
|
||||
|
||||
close(tempfd);
|
||||
unlock_and_close(tempfd);
|
||||
tempfd = -1;
|
||||
goto done;
|
||||
|
||||
|
@ -279,11 +280,11 @@ static int update_mmbox_index(int fd, char *mmbox_dir, int cmd,
|
|||
fp = fdopen(fd, "r");
|
||||
|
||||
if (!fp) {
|
||||
error(0, "mmbox.update_index: Failed fdopen on tempfd, file %s: error = %s\n",
|
||||
mms_error(0, "mmbox", NULL,"Failed fdopen on tempfd, file %s: error = %s\n",
|
||||
|
||||
fbuf, strerror(errno));
|
||||
|
||||
close(tempfd);
|
||||
unlock_and_close(tempfd);
|
||||
tempfd = -1;
|
||||
goto done;
|
||||
}
|
||||
|
@ -341,19 +342,19 @@ static int update_mmbox_index(int fd, char *mmbox_dir, int cmd,
|
|||
|
||||
static List *make_mm_flags(List *oflags, List *flag_cmds)
|
||||
{
|
||||
List *l = oflags ? oflags : list_create();
|
||||
List *l = oflags ? oflags : gwlist_create();
|
||||
int i, n;
|
||||
|
||||
for (i = 0, n = list_len(l); i < n; i++) { /* cleanup list. */
|
||||
Octstr *x = list_get(l,i);
|
||||
for (i = 0, n = gwlist_len(l); i < n; i++) { /* cleanup list. */
|
||||
Octstr *x = gwlist_get(l,i);
|
||||
int ch = octstr_get_char(x, 0);
|
||||
|
||||
if (ch == '+' || ch == '-' || ch == '/')
|
||||
octstr_delete(x,0,1);
|
||||
}
|
||||
|
||||
for (i = 0, n = (flag_cmds ? list_len(flag_cmds) : 0); i<n; i++) {
|
||||
Octstr *x = list_get(flag_cmds,i);
|
||||
for (i = 0, n = (flag_cmds ? gwlist_len(flag_cmds) : 0); i<n; i++) {
|
||||
Octstr *x = gwlist_get(flag_cmds,i);
|
||||
int ch = octstr_get_char(x, 0);
|
||||
char *s = octstr_get_cstr(x);
|
||||
int j, m, cmd;
|
||||
|
@ -365,17 +366,17 @@ static List *make_mm_flags(List *oflags, List *flag_cmds)
|
|||
cmd = '+';
|
||||
|
||||
/* Find it in original. If existent, remove it. */
|
||||
for (j = 0, m = list_len(l); j < m; j++)
|
||||
if (octstr_str_compare(list_get(l,j),s) == 0) {
|
||||
Octstr *y = list_get(l,j);
|
||||
list_delete(l,j,1);
|
||||
for (j = 0, m = gwlist_len(l); j < m; j++)
|
||||
if (octstr_str_compare(gwlist_get(l,j),s) == 0) {
|
||||
Octstr *y = gwlist_get(l,j);
|
||||
gwlist_delete(l,j,1);
|
||||
octstr_destroy(y);
|
||||
j--;
|
||||
m--;
|
||||
}
|
||||
|
||||
if (cmd == '+' || cmd == '/')
|
||||
list_append(l, octstr_create(s));
|
||||
gwlist_append(l, octstr_create(s));
|
||||
}
|
||||
|
||||
|
||||
|
@ -400,7 +401,7 @@ Octstr *mms_mmbox_addmsg(char *mmbox_root, char *user, MmsMsg *msg, List *flag_c
|
|||
goto done;
|
||||
|
||||
if ((dfd = mkdf(df, octstr_get_cstr(home))) < 0) {
|
||||
error(0, "mmbox_add: failed to create data file, home=%s - %s!",
|
||||
mms_error(0, "mmbox", NULL, "failed to create data file, home=%s - %s!",
|
||||
octstr_get_cstr(home), strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
@ -433,18 +434,14 @@ Octstr *mms_mmbox_addmsg(char *mmbox_root, char *user, MmsMsg *msg, List *flag_c
|
|||
octstr_replace(sdf, octstr_imm("/"), octstr_imm("-"));
|
||||
done:
|
||||
if (dfd > 0)
|
||||
close(dfd);
|
||||
unlock_and_close(dfd);
|
||||
if (ifd > 0)
|
||||
close(ifd);
|
||||
unlock_and_close(ifd);
|
||||
|
||||
if (s)
|
||||
octstr_destroy(s);
|
||||
if (home)
|
||||
octstr_destroy(home);
|
||||
if (state)
|
||||
octstr_destroy(state);
|
||||
if (flags)
|
||||
list_destroy(flags, (list_item_destructor_t *)octstr_destroy);
|
||||
gwlist_destroy(flags, (gwlist_item_destructor_t *)octstr_destroy);
|
||||
|
||||
return sdf;
|
||||
}
|
||||
|
@ -478,7 +475,7 @@ int mms_mmbox_modmsg(char *mmbox_root, char *user, Octstr *msgref,
|
|||
s = octstr_read_file(octstr_get_cstr(fname));
|
||||
|
||||
if ( s == NULL || octstr_len(s) == 0) {
|
||||
error(0, "mmbox.mod: failed to read data file [%s] - %s!",
|
||||
mms_error(0, "mmbox", NULL, "Failed to read data file [%s] - %s!",
|
||||
octstr_get_cstr(fname), strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
@ -486,7 +483,7 @@ int mms_mmbox_modmsg(char *mmbox_root, char *user, Octstr *msgref,
|
|||
m = mms_frombinary(s, octstr_imm("anon@anon"));
|
||||
|
||||
if (!m) {
|
||||
error(0, "mmbox.mod: failed to read data file [%s]!",
|
||||
mms_error(0, "mmbox", NULL, "Failed to read data file [%s]!",
|
||||
octstr_get_cstr(fname));
|
||||
goto done;
|
||||
}
|
||||
|
@ -519,7 +516,7 @@ int mms_mmbox_modmsg(char *mmbox_root, char *user, Octstr *msgref,
|
|||
|
||||
if ((nifd = update_mmbox_index(ifd, octstr_get_cstr(home), ITEM_MOD, sdf, nstate, flags, msize)) < 0) {
|
||||
/* Not good, we wrote but could not update the index file. scream. */
|
||||
error(0, "mmbox.mod: failed to update index file, home is %s!",
|
||||
mms_error(0, "mmbox", NULL, "Failed to update index file, home is %s!",
|
||||
octstr_get_cstr(home));
|
||||
goto done;
|
||||
}
|
||||
|
@ -546,7 +543,7 @@ int mms_mmbox_modmsg(char *mmbox_root, char *user, Octstr *msgref,
|
|||
if (nstate)
|
||||
octstr_destroy(nstate);
|
||||
if (flags)
|
||||
list_destroy(flags, (list_item_destructor_t *)octstr_destroy);
|
||||
gwlist_destroy(flags, (gwlist_item_destructor_t *)octstr_destroy);
|
||||
if (m)
|
||||
mms_destroy(m);
|
||||
return res;
|
||||
|
@ -577,7 +574,7 @@ int mms_mmbox_delmsg(char *mmbox_root, char *user, Octstr *msgref)
|
|||
|
||||
if ((nifd = update_mmbox_index(ifd, octstr_get_cstr(home), ITEM_DEL, sdf, NULL, NULL,0)) < 0) {
|
||||
|
||||
error(0, "mmbox.del: failed to update index file, home is %s!",
|
||||
mms_error(0, "mmbox", NULL,"Failed to update index file, home is %s!",
|
||||
octstr_get_cstr(home));
|
||||
goto done;
|
||||
}
|
||||
|
@ -604,8 +601,8 @@ static int string_in_list(Octstr *s, List *l)
|
|||
{
|
||||
int i, n;
|
||||
|
||||
for (i = 0, n = list_len(l); i<n; i++) {
|
||||
Octstr *x = list_get(l,i);
|
||||
for (i = 0, n = gwlist_len(l); i<n; i++) {
|
||||
Octstr *x = gwlist_get(l,i);
|
||||
char *p = octstr_get_cstr(x);
|
||||
|
||||
if (p[0] == '+' ||
|
||||
|
@ -653,51 +650,51 @@ List *mms_mmbox_search(char *mmbox_root, char *user,
|
|||
|
||||
if ((tmpfd = dup(ifd)) < 0 ||
|
||||
(fp = fdopen(tmpfd, "r")) == NULL) {
|
||||
error(0, "mmbox.search_index: %s Failed to dup descriptor for index "
|
||||
"file, fp = %d: error = %s\n", octstr_get_cstr(home),
|
||||
(int)fp, strerror(errno));
|
||||
mms_error(0, "mmbox", NULL, "%s Failed to dup descriptor for index "
|
||||
"file, fp = %p: error = %s\n", octstr_get_cstr(home),
|
||||
fp, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
||||
flags = make_mm_flags(NULL, flag_cmds);
|
||||
|
||||
ct = 1;
|
||||
dflist = list_create();
|
||||
dflist = gwlist_create();
|
||||
while (fgets(linbuf, sizeof linbuf, fp) != NULL) {
|
||||
char idx[128], xstate[32];
|
||||
List *xflags = NULL;
|
||||
int i, size;
|
||||
|
||||
int match = (!state && (!msgrefs || list_len(msgrefs) == 0) && (!xflags || list_len(xflags) == 0));
|
||||
int match = (!state && (!msgrefs || gwlist_len(msgrefs) == 0) && (!xflags || gwlist_len(xflags) == 0));
|
||||
|
||||
sscanf(linbuf, "%s %s %d%n", idx, xstate, &size, &i);
|
||||
|
||||
/* search: by id list if given, by states if given, by flags if given */
|
||||
if (!match && state && list_search(state, xstate,
|
||||
(list_item_matches_t *)_x_octstr_str_compare) != NULL)
|
||||
if (!match && state && gwlist_search(state, xstate,
|
||||
(gwlist_item_matches_t *)_x_octstr_str_compare) != NULL)
|
||||
match = 1;
|
||||
|
||||
/* For the rest we only match if nothing else matched. Save time */
|
||||
replace_slash(idx);
|
||||
if (!match && msgrefs &&
|
||||
list_search(msgrefs, idx,
|
||||
(list_item_matches_t *)_x_octstr_str_compare) != NULL)
|
||||
gwlist_search(msgrefs, idx,
|
||||
(gwlist_item_matches_t *)_x_octstr_str_compare) != NULL)
|
||||
match = 1;
|
||||
|
||||
if (!match &&
|
||||
flag_cmds &&
|
||||
((xflags = parse_string_list(linbuf + i)) != NULL &&
|
||||
list_search(xflags, flags, (list_item_matches_t *)string_in_list) != NULL))
|
||||
gwlist_search(xflags, flags, (gwlist_item_matches_t *)string_in_list) != NULL))
|
||||
match = 1;
|
||||
|
||||
if (match && ct >= start && list_len(dflist) <= limit) {
|
||||
if (match && ct >= start && gwlist_len(dflist) <= limit) {
|
||||
Octstr *x = octstr_create(idx);
|
||||
/* octstr_replace(x, octstr_imm("/"), octstr_imm("-")); */
|
||||
list_append(dflist, x);
|
||||
gwlist_append(dflist, x);
|
||||
}
|
||||
ct++;
|
||||
if (xflags)
|
||||
list_destroy(xflags, (list_item_destructor_t *)octstr_destroy);
|
||||
gwlist_destroy(xflags, (gwlist_item_destructor_t *)octstr_destroy);
|
||||
}
|
||||
|
||||
done:
|
||||
|
@ -710,7 +707,7 @@ List *mms_mmbox_search(char *mmbox_root, char *user,
|
|||
close(ifd);
|
||||
|
||||
if (flags)
|
||||
list_destroy(flags, (list_item_destructor_t *)octstr_destroy);
|
||||
gwlist_destroy(flags, (gwlist_item_destructor_t *)octstr_destroy);
|
||||
|
||||
if (home)
|
||||
octstr_destroy(home);
|
||||
|
@ -779,9 +776,9 @@ int mms_mmbox_count(char *mmbox_root, char *user, unsigned long *msgcount, unsi
|
|||
|
||||
if ((tmpfd = dup(ifd)) < 0 ||
|
||||
(fp = fdopen(tmpfd, "r")) == NULL) {
|
||||
error(0, "mmbox.count: %s Failed to dup descriptor for index "
|
||||
"file, fp = %d: error = %s\n", octstr_get_cstr(home),
|
||||
(int)fp, strerror(errno));
|
||||
mms_error(0, "mmbox", NULL, "%s Failed to dup descriptor for index "
|
||||
"file, fp = %p: error = %s\n", octstr_get_cstr(home),
|
||||
fp, strerror(errno));
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Mbuni MMBox implementation
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* MMS message encoder/decoder and helper functions
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -24,7 +24,9 @@ typedef struct MmsMsg MmsMsg; /* Opaque type. */
|
|||
|
||||
typedef MmsMsg *MmsMsgGetFunc_t(void *p1, void *p2, Octstr *msgref, unsigned long *msize);
|
||||
|
||||
extern int mms_validate_address(Octstr *s);
|
||||
enum AddressType_t {MMS_UNKNOWN_ADDRESS=-1, MMS_EMAIL_ADDRESS, MMS_IPV4_ADDRESS, MMS_IPV6_ADDRESS, MMS_NUMBER_ADDRESS};
|
||||
extern int mms_validate_address_real(Octstr *s, enum AddressType_t *address_type);
|
||||
#define mms_validate_address(s) mms_validate_address_real((s), NULL)
|
||||
|
||||
/*
|
||||
* mms_frombinary: Parse MMS binary representation, return a Message or NULL.
|
||||
|
@ -32,7 +34,9 @@ extern int mms_validate_address(Octstr *s);
|
|||
* Takes from param which is put in if insert-address is requested.
|
||||
* NOTE: function may modify 'msg' argument as it parses.
|
||||
*/
|
||||
extern MmsMsg *mms_frombinary(Octstr *msg, Octstr *from);
|
||||
extern MmsMsg *mms_frombinary_ex(Octstr *msg, Octstr *from, char *unified_prefix, List *strip_prefixes);
|
||||
|
||||
#define mms_frombinary(msg, from) mms_frombinary_ex((msg), (from), NULL, NULL)
|
||||
|
||||
/*
|
||||
* mms_tobinary: Return binary encoded Mms message
|
||||
|
@ -57,7 +61,8 @@ extern void mms_msgdump(MmsMsg *m, int headers_only);
|
|||
extern void mms_destroy(MmsMsg *msg);
|
||||
|
||||
/* Make a delivery report message. */
|
||||
extern MmsMsg *mms_deliveryreport(Octstr *msgid, Octstr *to, time_t date, Octstr *status);
|
||||
extern MmsMsg *mms_deliveryreport(Octstr *msgid, Octstr *from,
|
||||
Octstr *to, time_t date, Octstr *status);
|
||||
|
||||
MmsMsg *mms_readreport(Octstr *msgid, Octstr *from, Octstr *to, time_t date, Octstr *status);
|
||||
|
||||
|
@ -65,14 +70,17 @@ MmsMsg *mms_readreport(Octstr *msgid, Octstr *from, Octstr *to, time_t date, Oct
|
|||
extern List *mms_message_headers(MmsMsg *msg);
|
||||
|
||||
/* Make a notification message out of this one and the url given. */
|
||||
extern MmsMsg *mms_notification(MmsMsg *msg, unsigned int msize,
|
||||
extern MmsMsg *mms_notification(Octstr *from, Octstr *subject,
|
||||
Octstr *mclass, unsigned int msize,
|
||||
Octstr *url,
|
||||
Octstr *transactionid, time_t expiryt, int optimizesize);
|
||||
|
||||
MmsMsg *mms_notifyresp_ind(char *transid, int menc, char *status, int report_allowed);
|
||||
MmsMsg *mms_retrieveconf(MmsMsg *msg, Octstr *transactionid, char *err, char *errtxt, Octstr *opt_from, int menc);
|
||||
int mms_remove_headers(MmsMsg *m, char *name);
|
||||
MmsMsg *mms_sendconf(char *errstr, char *msgid, char *transid, int isforward, int menc);
|
||||
|
||||
|
||||
Octstr *mms_get_header_value(MmsMsg *msg, Octstr *header);
|
||||
|
||||
/* Returns a list of values for the header given. */
|
||||
|
@ -118,4 +126,22 @@ int mms_clearbody(MmsMsg *msg);
|
|||
* Use function with extreme caution! It should be for testing only really!!!!
|
||||
*/
|
||||
int mms_putbody(MmsMsg *msg, void *body, int ismultipart);
|
||||
|
||||
/* Convert a retrieve_conf message to a send_req messagre
|
||||
* checked runtime error to pass anything but a send_req/retrieve_conf.
|
||||
* returns 0 on success.
|
||||
*/
|
||||
int mms_make_sendreq(MmsMsg *retrieveconf);
|
||||
|
||||
/* Compute message size -- not altogether efficiently */
|
||||
int mms_msgsize(MmsMsg *m);
|
||||
|
||||
/* MM4 stuff */
|
||||
enum MM4_types_t {MM4_FORWARD_REQ = 0, MM4_FORWARD_RES, MM4_READ_REPLY_REPORT_REQ,
|
||||
MM4_READ_REPLY_REPORT_RES, MM4_DELIVERY_REPORT_REQ, MM4_DELIVERY_REPORT_RES};
|
||||
extern struct MM4_types_map_t {
|
||||
char *mm4str;
|
||||
int mm1_type;
|
||||
} mm4_types[];
|
||||
|
||||
#endif
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Queue management functions
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -14,6 +14,8 @@
|
|||
#ifndef _MMS_QUEUE_INCLUDED__
|
||||
#define _MMS_QUEUE_INCLUDED__
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "mms_msg.h"
|
||||
#include "mms_util.h"
|
||||
|
||||
|
@ -25,6 +27,7 @@ typedef struct MmsEnvelopeTo {
|
|||
* Flags below for details.
|
||||
*/
|
||||
enum {SFailed=0, SSuccess, SDefered, SUnknown} flag;
|
||||
void *_x; /* Used by client modules */
|
||||
} MmsEnvelopeTo;
|
||||
|
||||
typedef struct MmsEnvelope {
|
||||
|
@ -32,14 +35,16 @@ typedef struct MmsEnvelope {
|
|||
Octstr *msgId; /* message id (for reference). */
|
||||
Octstr *token; /* User level token, may be null. */
|
||||
Octstr *from; /* from address. */
|
||||
Octstr *mclass; /* Message class. */
|
||||
|
||||
Octstr *vaspid; /* VASPID (if any) */
|
||||
Octstr *vasid; /* VASID (if any) */
|
||||
|
||||
Octstr *url1; /* Generic URLs (2) associated with message. */
|
||||
Octstr *url2;
|
||||
List *hdrs; /* Generic list of headers associated with message. */
|
||||
|
||||
List *to; /* List of recipients: MmsEnvelopeTo */
|
||||
List *to; /* List of recipients: MmsEnvelopeTo (if process=0 then already sent to)*/
|
||||
|
||||
Octstr *subject; /* Message subject (if any). */
|
||||
|
||||
|
@ -64,48 +69,60 @@ typedef struct MmsEnvelope {
|
|||
Octstr *fromproxy; /* Which proxy sent us this message.*/
|
||||
Octstr *viaproxy; /* Which proxy must we send this message through. */
|
||||
|
||||
void *_x; /* Generic storage field used by module clients. */
|
||||
char src_interface[16]; /* source interface of this message. */
|
||||
char _extra_space; /* A bit of sugar, just in case... */
|
||||
|
||||
/* DO NOT MODIFY ANYTHING BEYOND THIS POINT. */
|
||||
struct { /* Name of the queue file, pointer to it (locked). DO NOT USE THESE! */
|
||||
char name[QFNAMEMAX]; /* Name of the file. */
|
||||
char dir[QFNAMEMAX]; /* Directory in which file is .*/
|
||||
char subdir[64]; /* and the sub-directory. */
|
||||
char _pad[16];
|
||||
int fd;
|
||||
} qf;
|
||||
void *_x; /* Generic storage field used by module clients. */
|
||||
void *qfs_data; /* Queue handler module structure -- allocated for you by queue_create
|
||||
* function.
|
||||
*/
|
||||
char xqfname[64+QFNAMEMAX]; /* The full ID for the queue. Use this. */
|
||||
} MmsEnvelope;
|
||||
|
||||
/* Given a queue directory, initialise it. Must be called at least once on each queue dir. */
|
||||
int mms_init_queuedir(Octstr *qdir);
|
||||
typedef struct MmsQueueHandlerFuncs {
|
||||
/* Initialise queue module. Must be called at least once on each queue dir.
|
||||
* max_concurrent is a best guess as to number of concurrent queue requests
|
||||
*/
|
||||
int (*mms_init_queue_module)(Octstr *init_data, char *top_storage_dir, int max_concurrent);
|
||||
|
||||
/* initialise a queue directory. There can be multiple directories,
|
||||
* upperlevel decides what a directory is.
|
||||
* module returns a directory string.
|
||||
*/
|
||||
Octstr *(*mms_init_queue_dir)(char *qdir, int *error);
|
||||
|
||||
/* cleanup module, e.g. on exit. */
|
||||
int (*mms_cleanup_queue_module)(void);
|
||||
/*
|
||||
* Add a message to the queue, returns 0 on success -1 otherwise (error is logged).
|
||||
* 'to' is a list of Octstr * *.
|
||||
* Returns a queue file name.
|
||||
*/
|
||||
extern Octstr *mms_queue_add(Octstr *from, List *to,
|
||||
Octstr *(*mms_queue_add)(Octstr *from, List *to,
|
||||
Octstr *subject,
|
||||
Octstr *fromproxy, Octstr *viaproxy,
|
||||
time_t senddate, time_t expirydate, MmsMsg *m, Octstr *token,
|
||||
time_t senddate, time_t expirydate, MmsMsg *m,
|
||||
Octstr *token,
|
||||
Octstr *vaspid, Octstr *vasid,
|
||||
Octstr *url1, Octstr *url2,
|
||||
List *hdrs,
|
||||
int dlr,
|
||||
char *directory, Octstr *mmscname);
|
||||
char *directory, char *src_interface,
|
||||
Octstr *mmscname);
|
||||
|
||||
/*
|
||||
* Update queue status. Returns -1 on error, 0 if queue is updated fine and
|
||||
* envelope is still valid, 1 if envelope is no longer valid (no more recipients.)
|
||||
*/
|
||||
extern int mms_queue_update(MmsEnvelope *e);
|
||||
int (*mms_queue_update)(MmsEnvelope *e);
|
||||
|
||||
/*
|
||||
* Get the message associated with this queue entry.
|
||||
*/
|
||||
extern MmsMsg *mms_queue_getdata(MmsEnvelope *e);
|
||||
MmsMsg *(*mms_queue_getdata)(MmsEnvelope *e);
|
||||
|
||||
/* Replace data for this queue item -- used by mm7 interface. */
|
||||
int mms_queue_replacedata(MmsEnvelope *e, MmsMsg *m);
|
||||
int (*mms_queue_replacedata)(MmsEnvelope *e, MmsMsg *m);
|
||||
|
||||
/*
|
||||
* Reads queue, returns up to lim queue entries that are ready for processing. send 0 for no limit.
|
||||
|
@ -119,7 +136,7 @@ int mms_queue_replacedata(MmsEnvelope *e, MmsMsg *m);
|
|||
* - If should block is 1, then does a potentially blocking attempt to lock the file.
|
||||
*/
|
||||
|
||||
MmsEnvelope *mms_queue_readenvelope(char *qf, char *dir, int shouldblock);
|
||||
MmsEnvelope *(*mms_queue_readenvelope)(char *qf, char *dir, int shouldblock);
|
||||
|
||||
/*
|
||||
* Run the queue in the given directory. For each envelope that is due for sending, call
|
||||
|
@ -128,12 +145,43 @@ MmsEnvelope *mms_queue_readenvelope(char *qf, char *dir, int shouldblock);
|
|||
* if deliver() returns 1, it has deleted envelope.
|
||||
* Also if rstop becomes true, queue run must stop.
|
||||
*/
|
||||
void mms_queue_run(char *dir,
|
||||
void (*mms_queue_run)(char *dir,
|
||||
int (*deliver)(MmsEnvelope *),
|
||||
double sleepsecs,
|
||||
int num_threads,
|
||||
int *rstop);
|
||||
volatile sig_atomic_t *rstop);
|
||||
|
||||
/* Get rid of memory used by this. Typically does internal cleanup then calls
|
||||
* the general structure free-ing function below.
|
||||
*/
|
||||
int (*mms_queue_free_env)(MmsEnvelope *e);
|
||||
} MmsQueueHandlerFuncs;
|
||||
|
||||
/* Module must export this symbol:
|
||||
* extern MmsQueueHandlerFuncs qfuncs;
|
||||
*/
|
||||
|
||||
extern MmsQueueHandlerFuncs default_qfuncs; /* default queue handler module, file-based */
|
||||
/* Utility functions, generally defined. */
|
||||
/* Creates the queue envelope object, returns it. Returns the binary MMS in 'binary_mms' if NOT NULL */
|
||||
MmsEnvelope *mms_queue_create_envelope(Octstr *from, List *to,
|
||||
Octstr *subject,
|
||||
Octstr *fromproxy, Octstr *viaproxy,
|
||||
time_t senddate, time_t expirydate,
|
||||
Octstr *token,
|
||||
Octstr *vaspid, Octstr *vasid,
|
||||
Octstr *url1, Octstr *url2,
|
||||
List *hdrs,
|
||||
int dlr,
|
||||
Octstr *mmscname,
|
||||
MmsMsg *m,
|
||||
char *xqfname,
|
||||
char *src_interface,
|
||||
int extra_space,
|
||||
Octstr **binary_mms);
|
||||
/* Get rid of memory used by this. */
|
||||
extern int mms_queue_free_env(MmsEnvelope *e);
|
||||
void mms_queue_free_envelope(MmsEnvelope *e);
|
||||
|
||||
/* utility function for 'cleaning up' addresses. */
|
||||
Octstr *copy_and_clean_address(Octstr *addr);
|
||||
#endif
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* MMS strings module
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -107,7 +107,7 @@ static Octstr *number_to_string(long number, struct table *table)
|
|||
return octstr_duplicate(table->strings[i]);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
return octstr_imm("");
|
||||
}
|
||||
|
||||
static unsigned char *number_to_cstr(long number, struct table *table)
|
||||
|
|
|
@ -293,6 +293,7 @@ VNSTRING(MM7_5, "StatusText",MM7_TAG_StatusText)
|
|||
VNSTRING(MM7_5, "Subject",MM7_TAG_Subject)
|
||||
VNSTRING(MM7_5, "SubmitReq",MM7_TAG_SubmitReq)
|
||||
VNSTRING(MM7_5, "SubmitRsp",MM7_TAG_SubmitRsp)
|
||||
|
||||
VNSTRING(MM7_5, "TimeStamp",MM7_TAG_TimeStamp)
|
||||
VNSTRING(MM7_5, "To",MM7_TAG_To)
|
||||
VNSTRING(MM7_5, "TransactionID",MM7_TAG_TransactionID)
|
||||
|
@ -307,6 +308,9 @@ VNSTRING(MM7_5, "MessageType",MM7_TAG_MessageType)
|
|||
VNSTRING(MM7_5, "replyChargingSize", MM7_TAG_replyChargingSize)
|
||||
VNSTRING(MM7_5, "replyDeadline", MM7_TAG_replyDeadline)
|
||||
VNSTRING(MM7_5, "DeliveryReport", MM7_TAG_DeliveryReport)
|
||||
VNSTRING(MM7_5, "allowAdaptations", MM7_TAG_allowAdaptations)
|
||||
VNSTRING(MM7_5, "DistributionIndicator",MM7_TAG_distributionIndicator)
|
||||
VNSTRING(MM7_5, "UACapabilities",MM7_TAG_UACapabilities)
|
||||
)
|
||||
|
||||
NUMBERED(soap_status,
|
||||
|
@ -324,6 +328,7 @@ ASSIGN("Server Error", 3000)
|
|||
ASSIGN("Not Possible", 3001)
|
||||
ASSIGN("Message rejected", 3002)
|
||||
ASSIGN("Multiple addresses not supported", 3003)
|
||||
ASSIGN("Command Rejected", 3005)
|
||||
ASSIGN("General service error", 4000)
|
||||
ASSIGN("Improper identification", 4001)
|
||||
ASSIGN("Unsupported version", 4002)
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* MMS strings module
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* User-Agent profiles handling, content adaptation.
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -56,21 +56,21 @@ static unsigned long hash_key(Octstr *s)
|
|||
static void destroy_uaprof(MmsUaProfile *prof)
|
||||
{
|
||||
if (prof->versions)
|
||||
list_destroy(prof->versions,
|
||||
(list_item_destructor_t *)octstr_destroy);
|
||||
gwlist_destroy(prof->versions,
|
||||
(gwlist_item_destructor_t *)octstr_destroy);
|
||||
|
||||
if (prof->ccppaccept.content) {
|
||||
list_destroy(prof->ccppaccept.content, (list_item_destructor_t *)octstr_destroy);
|
||||
list_destroy(prof->ccppaccept._hash, NULL);
|
||||
gwlist_destroy(prof->ccppaccept.content, (gwlist_item_destructor_t *)octstr_destroy);
|
||||
gwlist_destroy(prof->ccppaccept._hash, NULL);
|
||||
}
|
||||
|
||||
if (prof->ccppaccept.charset) {
|
||||
list_destroy(prof->ccppaccept.charset, (list_item_destructor_t *)octstr_destroy);
|
||||
list_destroy(prof->ccppaccept._chash, NULL);
|
||||
gwlist_destroy(prof->ccppaccept.charset, (gwlist_item_destructor_t *)octstr_destroy);
|
||||
gwlist_destroy(prof->ccppaccept._chash, NULL);
|
||||
} if (prof->ccppaccept.lang)
|
||||
list_destroy(prof->ccppaccept.lang, (list_item_destructor_t *)octstr_destroy);
|
||||
gwlist_destroy(prof->ccppaccept.lang, (gwlist_item_destructor_t *)octstr_destroy);
|
||||
if (prof->ccppaccept.enc)
|
||||
list_destroy(prof->ccppaccept.enc, (list_item_destructor_t *)octstr_destroy);
|
||||
gwlist_destroy(prof->ccppaccept.enc, (gwlist_item_destructor_t *)octstr_destroy);
|
||||
|
||||
gw_free(prof);
|
||||
}
|
||||
|
@ -88,37 +88,37 @@ static void dump_profile(MmsUaProfile *prof, Octstr *name)
|
|||
|
||||
s = octstr_create("");
|
||||
if (prof->ccppaccept.content)
|
||||
for (i=0; i<list_len(prof->ccppaccept.content); i++)
|
||||
octstr_format_append(s, "%S, ", list_get(prof->ccppaccept.content,i));
|
||||
for (i=0; i<gwlist_len(prof->ccppaccept.content); i++)
|
||||
octstr_format_append(s, "%S, ", gwlist_get(prof->ccppaccept.content,i));
|
||||
debug("mms.uaprof", 0, "Accept content: %s", octstr_get_cstr(s));
|
||||
octstr_destroy(s);
|
||||
|
||||
|
||||
s = octstr_create("");
|
||||
if (prof->ccppaccept.enc)
|
||||
for (i=0; i<list_len(prof->ccppaccept.enc); i++)
|
||||
octstr_format_append(s, "%S, ", list_get(prof->ccppaccept.enc,i));
|
||||
for (i=0; i<gwlist_len(prof->ccppaccept.enc); i++)
|
||||
octstr_format_append(s, "%S, ", gwlist_get(prof->ccppaccept.enc,i));
|
||||
debug("mms.uaprof", 0, "Accept encodings: %s", octstr_get_cstr(s));
|
||||
octstr_destroy(s);
|
||||
|
||||
s = octstr_create("");
|
||||
if (prof->ccppaccept.lang)
|
||||
for (i=0; i<list_len(prof->ccppaccept.lang); i++)
|
||||
octstr_format_append(s, "%S, ", list_get(prof->ccppaccept.lang,i));
|
||||
for (i=0; i<gwlist_len(prof->ccppaccept.lang); i++)
|
||||
octstr_format_append(s, "%S, ", gwlist_get(prof->ccppaccept.lang,i));
|
||||
debug("mms.uaprof", 0, "Accept language: %s", octstr_get_cstr(s));
|
||||
octstr_destroy(s);
|
||||
|
||||
s = octstr_create("");
|
||||
if (prof->ccppaccept.charset)
|
||||
for (i=0; i<list_len(prof->ccppaccept.charset); i++)
|
||||
octstr_format_append(s, "%S, ", list_get(prof->ccppaccept.charset,i));
|
||||
for (i=0; i<gwlist_len(prof->ccppaccept.charset); i++)
|
||||
octstr_format_append(s, "%S, ", gwlist_get(prof->ccppaccept.charset,i));
|
||||
debug("mms.uaprof", 0, "Accept charset: %s", octstr_get_cstr(s));
|
||||
octstr_destroy(s);
|
||||
|
||||
s = octstr_create("");
|
||||
if (prof->versions)
|
||||
for (i=0; i<list_len(prof->versions); i++)
|
||||
octstr_format_append(s, "%S, ", list_get(prof->versions,i));
|
||||
for (i=0; i<gwlist_len(prof->versions); i++)
|
||||
octstr_format_append(s, "%S, ", gwlist_get(prof->versions,i));
|
||||
debug("mms.uaprof", 0, "Mms Version: %s", octstr_get_cstr(s));
|
||||
octstr_destroy(s);
|
||||
|
||||
|
@ -192,19 +192,19 @@ MmsUaProfile *mms_make_ua_profile(List *req_headers)
|
|||
prof->maxres.x = 640;
|
||||
prof->maxres.y = 480;
|
||||
prof->maxmsgsize = 100*1024;
|
||||
prof->versions = list_create();
|
||||
prof->versions = gwlist_create();
|
||||
|
||||
|
||||
list_append(prof->versions, octstr_imm("1.0")); /* Assume 1.0 for now. */
|
||||
gwlist_append(prof->versions, octstr_imm("1.0")); /* Assume 1.0 for now. */
|
||||
|
||||
/* Get accepted charsets. */
|
||||
s = http_header_value(req_headers, octstr_imm("Accept-Charset"));
|
||||
|
||||
if (s && (l = http_header_split_value(s)) != NULL) {
|
||||
prof->ccppaccept.charset = l;
|
||||
prof->ccppaccept._chash = list_create();
|
||||
for (i = 0, n = list_len(l); i<n; i++)
|
||||
list_append(prof->ccppaccept._chash, (void *)hash_key(list_get(l, i)));
|
||||
prof->ccppaccept._chash = gwlist_create();
|
||||
for (i = 0, n = gwlist_len(l); i<n; i++)
|
||||
gwlist_append(prof->ccppaccept._chash, (void *)hash_key(gwlist_get(l, i)));
|
||||
}
|
||||
if (s) octstr_destroy(s);
|
||||
|
||||
|
@ -229,16 +229,16 @@ MmsUaProfile *mms_make_ua_profile(List *req_headers)
|
|||
s = http_header_value(req_headers, octstr_imm("Accept"));
|
||||
if (s && (l = http_header_split_value(s)) != NULL) {
|
||||
prof->ccppaccept.content = l;
|
||||
prof->ccppaccept._hash = list_create();
|
||||
prof->ccppaccept._hash = gwlist_create();
|
||||
|
||||
for (i = 0, n = l ? list_len(l) : 0; i<n; i++) {
|
||||
Octstr *x = list_get(l, i);
|
||||
for (i = 0, n = l ? gwlist_len(l) : 0; i<n; i++) {
|
||||
Octstr *x = gwlist_get(l, i);
|
||||
if (octstr_str_compare(x, "*/*") == 0)
|
||||
prof->ccppaccept.all = 1;
|
||||
else if (octstr_case_compare(x, octstr_imm(PRES_TYPE)) == 0)
|
||||
prof->ccppaccept.presentation = 1;
|
||||
|
||||
list_append(prof->ccppaccept._hash, (void *)hash_key(x));
|
||||
gwlist_append(prof->ccppaccept._hash, (void *)hash_key(x));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,11 +246,11 @@ MmsUaProfile *mms_make_ua_profile(List *req_headers)
|
|||
|
||||
/* Put it in with the UA string as the key. */
|
||||
if (dict_put_once(profile_dict, ua, prof) != 1)
|
||||
warning(0, "mms_uaprof: Duplicate cache entry(%s)?\n",
|
||||
mms_warning(0, "mms_uaprof", NULL, "Duplicate cache entry(%s)?\n",
|
||||
octstr_get_cstr(ua));
|
||||
|
||||
/* Done. Dump it while debugging. */
|
||||
done:
|
||||
done:
|
||||
|
||||
#if 1
|
||||
dump_profile(prof, ua ? ua : octstr_imm("<from http headers>"));
|
||||
|
@ -295,12 +295,12 @@ static MmsUaProfile *parse_uaprofile(Octstr *xml)
|
|||
|
||||
/* If there is a Bag, get the list. */
|
||||
if ((rdfnode = find_node(xnode->xmlChildrenNode, "Bag", NULL,0,1)) != NULL) {
|
||||
l = list_create();
|
||||
l = gwlist_create();
|
||||
for (lnode = rdfnode->xmlChildrenNode; lnode; lnode = lnode->next)
|
||||
if (xmlStrcasecmp(lnode->name, (const xmlChar *)"li") == 0) {
|
||||
unsigned char *t = xmlNodeListGetString(doc, lnode->xmlChildrenNode,1);
|
||||
if (t) {
|
||||
list_append(l, octstr_create((char *)t));
|
||||
gwlist_append(l, octstr_create((char *)t));
|
||||
xmlFree(t);
|
||||
}
|
||||
}
|
||||
|
@ -315,38 +315,44 @@ static MmsUaProfile *parse_uaprofile(Octstr *xml)
|
|||
xmlStrcasecmp(xname, (const xmlChar *)"MmsCcppAccept-CharSet") == 0) {/* Cranky old ones! */
|
||||
int i, n;
|
||||
prof->ccppaccept.charset = l;
|
||||
prof->ccppaccept._chash = list_create();
|
||||
for (i = 0, n = list_len(l); i<n; i++)
|
||||
list_append(prof->ccppaccept._chash, (void *)hash_key(list_get(l, i)));
|
||||
} else if (xmlStrcasecmp(xname, (const xmlChar *)"MmsCcppAcceptLanguage") == 0)
|
||||
l = NULL; /* Avoid deletion below */
|
||||
prof->ccppaccept._chash = gwlist_create();
|
||||
for (i = 0, n = gwlist_len(l); i<n; i++)
|
||||
gwlist_append(prof->ccppaccept._chash, (void *)hash_key(gwlist_get(l, i)));
|
||||
} else if (xmlStrcasecmp(xname, (const xmlChar *)"MmsCcppAcceptLanguage") == 0) {
|
||||
prof->ccppaccept.lang = l;
|
||||
else if (xmlStrcasecmp(xname, (const xmlChar *)"MmsCcppAcceptEncoding") == 0)
|
||||
l = NULL; /* Avoid deletion below */
|
||||
} else if (xmlStrcasecmp(xname, (const xmlChar *)"MmsCcppAcceptEncoding") == 0) {
|
||||
prof->ccppaccept.enc = l;
|
||||
else if (xmlStrcasecmp(xname, (const xmlChar *)"MmsVersion") == 0) {
|
||||
if (!l && childtext) { /* SonyEriccson uses old format! */
|
||||
l = list_create();
|
||||
list_append(l, octstr_create((char *)childtext));
|
||||
l = NULL; /* Avoid deletion below */
|
||||
} else if (xmlStrcasecmp(xname, (const xmlChar *)"MmsVersion") == 0) {
|
||||
if (l == NULL && childtext) { /* SonyEriccson uses old format! */
|
||||
l = gwlist_create();
|
||||
gwlist_append(l, octstr_create((char *)childtext));
|
||||
}
|
||||
prof->versions = l;
|
||||
l = NULL; /* Avoid deletion below */
|
||||
} else if (xmlStrcasecmp(xname, (const xmlChar *)"MmsCcppAccept") == 0) {
|
||||
int i, n;
|
||||
prof->ccppaccept.content = l;
|
||||
prof->ccppaccept._hash = list_create();
|
||||
prof->ccppaccept._hash = gwlist_create();
|
||||
|
||||
for (i = 0, n = l ? list_len(l) : 0; i<n; i++) {
|
||||
Octstr *x = list_get(l, i);
|
||||
for (i = 0, n = l ? gwlist_len(l) : 0; i<n; i++) {
|
||||
Octstr *x = gwlist_get(l, i);
|
||||
if (octstr_str_compare(x, "*/*") == 0)
|
||||
prof->ccppaccept.all = 1;
|
||||
else if (octstr_case_compare(x, octstr_imm(PRES_TYPE)) == 0)
|
||||
prof->ccppaccept.presentation = 1;
|
||||
|
||||
list_append(prof->ccppaccept._hash, (void *)hash_key(x));
|
||||
gwlist_append(prof->ccppaccept._hash, (void *)hash_key(x));
|
||||
}
|
||||
l = NULL; /* Avoid deletion below */
|
||||
}
|
||||
if (childtext) xmlFree(childtext);
|
||||
gwlist_destroy(l, (void *)octstr_destroy);
|
||||
}
|
||||
|
||||
done:
|
||||
done:
|
||||
if (doc) xmlFreeDoc(doc);
|
||||
return prof;
|
||||
}
|
||||
|
@ -370,7 +376,7 @@ static int mms_load_ua_profile_cache(char *dir)
|
|||
dirp = opendir(dir);
|
||||
|
||||
if (!dirp) {
|
||||
error(0, "mms_uaprof: Failed to open UA prof cache directory %s",
|
||||
mms_error(0, "mms_uaprof", NULL, "Failed to open UA prof cache directory %s",
|
||||
dir);
|
||||
return -1;
|
||||
}
|
||||
|
@ -391,14 +397,14 @@ static int mms_load_ua_profile_cache(char *dir)
|
|||
xml = octstr_read_file(octstr_get_cstr(fname));
|
||||
octstr_destroy(fname);
|
||||
if (!xml) {
|
||||
error(0, "mms_uaprof: Failed to read UA prof doc %s in %s (%s)\n",
|
||||
mms_error(0, "mms_uaprof", NULL, "Failed to read UA prof doc %s in %s (%s)\n",
|
||||
dp->d_name, dir, strerror(errno));
|
||||
continue;
|
||||
}
|
||||
|
||||
prof = parse_uaprofile(xml);
|
||||
if (!prof) {
|
||||
error(0, "mms_uaprof: Failed to parse UA prof doc %s in %s\n", dp->d_name, dir);
|
||||
mms_error(0, "mms_uaprof", NULL, "Failed to parse UA prof doc %s in %s\n", dp->d_name, dir);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
|
@ -406,7 +412,7 @@ static int mms_load_ua_profile_cache(char *dir)
|
|||
octstr_convert_range(key, 0, octstr_len(key), unreplace_slash);
|
||||
|
||||
if (dict_put_once(profile_dict, key, prof) != 1)
|
||||
warning(0, "mms_uaprof: Duplicate cache entry(%s)?\n",
|
||||
mms_warning(0, "mms_uaprof", NULL, "Duplicate cache entry(%s)?\n",
|
||||
octstr_get_cstr(key));
|
||||
#if 1
|
||||
dump_profile(prof, key);
|
||||
|
@ -423,7 +429,7 @@ static int mms_load_ua_profile_cache(char *dir)
|
|||
|
||||
static MmsUaProfile *profile_fetch(Octstr *profile_url)
|
||||
{
|
||||
Octstr *final_url = NULL, *body = NULL;
|
||||
Octstr *body = NULL;
|
||||
List *h, *rh = NULL;
|
||||
int status;
|
||||
MmsUaProfile *prof;
|
||||
|
@ -438,14 +444,14 @@ static MmsUaProfile *profile_fetch(Octstr *profile_url)
|
|||
h = http_create_empty_headers();
|
||||
http_header_add(h, "User-Agent", MM_NAME "/" MMSC_VERSION);
|
||||
|
||||
status = http_get_real(HTTP_METHOD_GET, profile_url, h, &final_url, &rh, &body);
|
||||
if (status == HTTP_OK) {
|
||||
status = mms_url_fetch_content(HTTP_METHOD_GET, profile_url, h, NULL, &rh, &body);
|
||||
if (http_status_class(status) == HTTP_STATUS_SUCCESSFUL) {
|
||||
prof = parse_uaprofile(body);
|
||||
|
||||
debug("mms.uaprof", 0, "Fetcher got %s", octstr_get_cstr(profile_url));
|
||||
if (prof) {
|
||||
if (dict_put_once(profile_dict, profile_url, prof) != 1)
|
||||
warning(0, "mms_uaprof: Duplicate ua profile fetched? (%s)?\n",
|
||||
mms_warning(0, "mms_uaprof", NULL, "Duplicate ua profile fetched? (%s)?\n",
|
||||
octstr_get_cstr(profile_url));
|
||||
else {
|
||||
Octstr *fname;
|
||||
|
@ -460,21 +466,20 @@ static MmsUaProfile *profile_fetch(Octstr *profile_url)
|
|||
octstr_print(f, body);
|
||||
fclose(f);
|
||||
} else
|
||||
error(0, "mms_uaprof: Failed to save profile data to cache file %s->%s\n",
|
||||
mms_error(0, "mms_uaprof", NULL, "Failed to save profile data to cache file %s->%s\n",
|
||||
octstr_get_cstr(fname), strerror(errno));
|
||||
octstr_destroy(fname);
|
||||
}
|
||||
} else
|
||||
error(0, "mms_uaprof: Failed to parse UA prof url=%s\n",
|
||||
mms_error(0, "mms_uaprof", NULL, "Failed to parse UA prof url=%s\n",
|
||||
octstr_get_cstr(profile_url));
|
||||
} else
|
||||
prof = NULL;
|
||||
|
||||
if (body) octstr_destroy(body);
|
||||
octstr_destroy(body);
|
||||
|
||||
if (h) http_destroy_headers(h);
|
||||
if (rh) http_destroy_headers(rh);
|
||||
if (final_url) octstr_destroy(final_url);
|
||||
|
||||
return prof;
|
||||
}
|
||||
|
@ -494,16 +499,17 @@ int mms_start_profile_engine(char *cache_dir)
|
|||
init_format_table();
|
||||
mms_load_ua_profile_cache(cache_dir);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mms_stop_profile_engine(void)
|
||||
{
|
||||
/* This will cause thread to stop and also destroy dict. */
|
||||
if (profile_dir)
|
||||
|
||||
octstr_destroy(profile_dir);
|
||||
|
||||
dict_destroy(profile_dict);
|
||||
|
||||
profile_dict = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
@ -568,6 +574,8 @@ struct {
|
|||
"sox -t wav - -t raw -s -w -c 1 -r 8000 - lowpass 3700 | amrencoder MR122 - -", "amr",0, TAUDIO},
|
||||
{"audio/amr-wb", 0, "amrdecoder - - | sox -t raw -s -w -c 1 -r 8000 - -t wav -",
|
||||
"sox -t wav - -t raw -s -w -c 1 -r 8000 - lowpass 3700 | amrencoder MR122 - -", "amr",0, TAUDIO},
|
||||
|
||||
{"audio/au", 0,"sox -t au -s - -t wav -","lame - -","mp3",0,TAUDIO},
|
||||
#if 0
|
||||
{"audio/midi", 0, "cat", "cat", "mid",0, TAUDIO},
|
||||
{"audio/sp-midi", 0, "cat", "cat", "mid",0, TAUDIO},
|
||||
|
@ -591,12 +599,19 @@ static void init_format_table(void)
|
|||
/* Removes an object by making it text/plain. For now not configurable. */
|
||||
static void remove_object(MIMEEntity *m, Octstr *ctype)
|
||||
{
|
||||
http_header_remove_all(m->headers, "Content-Type");
|
||||
List *h = mime_entity_headers(m);
|
||||
Octstr *s = octstr_format("Unsupported object (content type %S) removed", ctype);
|
||||
|
||||
http_header_add(m->headers, "Content-Type", "text/plain");
|
||||
http_header_remove_all(h, "Content-Type");
|
||||
http_header_add(h, "Content-Type", "text/plain");
|
||||
|
||||
octstr_destroy(m->body);
|
||||
m->body = octstr_format("Unsupported object (content type %S) removed", ctype);
|
||||
mime_replace_headers(m, h);
|
||||
http_destroy_headers(h);
|
||||
|
||||
while (mime_entity_num_parts(m) > 0) /* Delete all parts, if any. */
|
||||
mime_entity_remove_part(m, 0);
|
||||
mime_entity_set_body(m, s);
|
||||
octstr_destroy(s);
|
||||
}
|
||||
|
||||
static void mktmpfname(char fname[])
|
||||
|
@ -627,7 +642,7 @@ static Octstr *mknewname(Octstr *oldname, char *ext)
|
|||
static void replace_ctype(List *headers, char *newcontent_type, List *params_h)
|
||||
{
|
||||
Octstr *ct;
|
||||
if (list_len(params_h) > 0) {
|
||||
if (gwlist_len(params_h) > 0) {
|
||||
Octstr *tmp = make_value_parameters(params_h);
|
||||
ct = octstr_format("%s; %S", newcontent_type, tmp);
|
||||
octstr_destroy(tmp);
|
||||
|
@ -645,9 +660,9 @@ static void replace_body(MIMEEntity *msg, Octstr *newbody, List *params_h,
|
|||
{
|
||||
Octstr *part_name;
|
||||
Octstr *new_partname = NULL;
|
||||
List *h = mime_entity_headers(msg);
|
||||
|
||||
octstr_destroy(msg->body); /* Replace the body. */
|
||||
msg->body = newbody;
|
||||
mime_entity_set_body(msg, newbody); /* Replace the body. */
|
||||
|
||||
if ((part_name = http_header_value(params_h, octstr_imm("name"))) != NULL) {
|
||||
Octstr *tmp = mknewname(part_name, file_ext);
|
||||
|
@ -658,16 +673,17 @@ static void replace_body(MIMEEntity *msg, Octstr *newbody, List *params_h,
|
|||
new_partname = tmp;
|
||||
}
|
||||
|
||||
replace_ctype(msg->headers, newcontent_type, params_h);
|
||||
replace_ctype(h, newcontent_type, params_h);
|
||||
|
||||
if (add_disposition_header) {
|
||||
Octstr *tmp = octstr_format("inline; filename=\"%S\"",
|
||||
new_partname ? new_partname : octstr_imm("any"));
|
||||
http_header_add(msg->headers, "Content-Disposition", octstr_get_cstr(tmp));
|
||||
http_header_add(h, "Content-Disposition", octstr_get_cstr(tmp));
|
||||
octstr_destroy(tmp);
|
||||
}
|
||||
|
||||
if (new_partname) octstr_destroy(new_partname);
|
||||
mime_replace_headers(msg,h);
|
||||
http_destroy_headers(h);
|
||||
octstr_destroy(new_partname);
|
||||
}
|
||||
|
||||
/* Modify the message based on the user agent profile data. Return 1 if was supported, 0
|
||||
|
@ -688,14 +704,15 @@ static int modify_msg(MIMEEntity *msg, MmsUaProfile *prof)
|
|||
FILE *pf;
|
||||
char tmpf[40], tmpf2[40];
|
||||
Octstr *cmd = NULL;
|
||||
List *h = NULL;
|
||||
|
||||
if (!msg) return 0;
|
||||
|
||||
tmpf[0] = tmpf2[0] = 0; /* Clear .*/
|
||||
|
||||
/* Get the content type, hash it. */
|
||||
|
||||
get_content_type(msg->headers, &content_type, ¶ms);
|
||||
h = mime_entity_headers(msg);
|
||||
get_content_type(h, &content_type, ¶ms);
|
||||
params_h = get_value_parameters(params);
|
||||
|
||||
#if 0
|
||||
|
@ -704,13 +721,14 @@ static int modify_msg(MIMEEntity *msg, MmsUaProfile *prof)
|
|||
http_header_dump(params_h);
|
||||
#endif
|
||||
|
||||
if (msg->multiparts && list_len(msg->multiparts) > 0) {
|
||||
if ((n = mime_entity_num_parts(msg)) > 0) {
|
||||
Octstr *startp = http_header_value(params_h, octstr_imm("start"));
|
||||
int sflag = 0;
|
||||
|
||||
for (i = 0, n = list_len(msg->multiparts); i<n; i++) {
|
||||
MIMEEntity *x = list_get(msg->multiparts,i);
|
||||
Octstr *cid = http_header_value(x->headers, octstr_imm("Content-ID"));
|
||||
for (i = 0; i<n; i++) {
|
||||
MIMEEntity *x = mime_entity_get_part(msg,i);
|
||||
List *hx = mime_entity_headers(x);
|
||||
Octstr *cid = _x_get_content_id(hx);
|
||||
int sup;
|
||||
|
||||
debug("MMS uaprof: cid =###", 0, "%s", cid ? octstr_get_cstr(cid) : "NULL");
|
||||
|
@ -718,9 +736,13 @@ static int modify_msg(MIMEEntity *msg, MmsUaProfile *prof)
|
|||
sup = modify_msg(x, prof);
|
||||
|
||||
if (!sup && /* not supported and is the presentation part, set flag */
|
||||
cid && octstr_compare(cid, startp) == 0)
|
||||
cid && startp && octstr_compare(cid, startp) == 0)
|
||||
sflag = 1;
|
||||
if (cid) octstr_destroy(cid);
|
||||
octstr_destroy(cid);
|
||||
|
||||
mime_entity_replace_part(msg, i, x); /* Put back changed one */
|
||||
http_destroy_headers(hx);
|
||||
mime_entity_destroy(x);
|
||||
}
|
||||
|
||||
/* If no start param but content type is other than multipart/mixed OR
|
||||
|
@ -738,10 +760,10 @@ static int modify_msg(MIMEEntity *msg, MmsUaProfile *prof)
|
|||
http_header_remove_all(params_h, "start");
|
||||
http_header_remove_all(params_h, "type");
|
||||
|
||||
replace_ctype(msg->headers, "multipart/mixed", params_h);
|
||||
replace_ctype(h, "multipart/mixed", params_h);
|
||||
}
|
||||
|
||||
if (startp) octstr_destroy(startp);
|
||||
octstr_destroy(startp);
|
||||
|
||||
supported = 1;
|
||||
goto done;
|
||||
|
@ -765,25 +787,25 @@ static int modify_msg(MIMEEntity *msg, MmsUaProfile *prof)
|
|||
|
||||
if (charset == NULL ||
|
||||
octstr_str_compare(charset, "unknown") == 0) {
|
||||
if (charset) octstr_destroy(charset);
|
||||
octstr_destroy(charset);
|
||||
charset = octstr_imm(DEFAULT_CHARSET);
|
||||
}
|
||||
|
||||
n = prof->ccppaccept.charset ? list_len(prof->ccppaccept.charset) : 0;
|
||||
n = prof->ccppaccept.charset ? gwlist_len(prof->ccppaccept.charset) : 0;
|
||||
|
||||
/* Is this character set supported? If so do nothing. */
|
||||
for (i = 0; i<n; i++)
|
||||
if (octstr_case_compare(list_get(prof->ccppaccept.charset,i), charset) == 0) {
|
||||
if (octstr_case_compare(gwlist_get(prof->ccppaccept.charset,i), charset) == 0) {
|
||||
csupport = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!csupport)
|
||||
for (i = 0; i<n; i++) {
|
||||
Octstr *ncharset = list_get(prof->ccppaccept.charset,i); /* Don't free this! */
|
||||
Octstr *ncharset = gwlist_get(prof->ccppaccept.charset,i); /* Don't free this! */
|
||||
Octstr *ct;
|
||||
|
||||
if (charset_convert(msg->body, octstr_get_cstr(charset),
|
||||
Octstr *s = mime_entity_body(msg);
|
||||
if (charset_convert(s, octstr_get_cstr(charset),
|
||||
octstr_get_cstr(ncharset)) != -1) { /* using libiconv...*/
|
||||
Octstr *tmp;
|
||||
|
||||
|
@ -793,12 +815,15 @@ static int modify_msg(MIMEEntity *msg, MmsUaProfile *prof)
|
|||
|
||||
ct = octstr_format("%S; %S", content_type, tmp);
|
||||
octstr_destroy(tmp);
|
||||
http_header_remove_all(msg->headers, "Content-Type");
|
||||
http_header_add(msg->headers, "Content-Type", octstr_get_cstr(ct));
|
||||
http_header_remove_all(h, "Content-Type");
|
||||
http_header_add(h, "Content-Type", octstr_get_cstr(ct));
|
||||
octstr_destroy(ct);
|
||||
|
||||
mime_entity_set_body(msg,s); /* replace with new body. */
|
||||
octstr_destroy(s);
|
||||
break; /* We succeeded in converting it so we shd go away. */
|
||||
}
|
||||
} else
|
||||
octstr_destroy(s);
|
||||
}
|
||||
|
||||
octstr_destroy(charset);
|
||||
|
@ -811,10 +836,10 @@ static int modify_msg(MIMEEntity *msg, MmsUaProfile *prof)
|
|||
if (prof->ccppaccept.all) /* Check if it accepts all content types. */
|
||||
supported = 1;
|
||||
else
|
||||
for (i = 0, n = prof->ccppaccept.content ? list_len(prof->ccppaccept.content) : 0;
|
||||
for (i = 0, n = gwlist_len(prof->ccppaccept.content);
|
||||
i<n; i++)
|
||||
if ((unsigned long)list_get(prof->ccppaccept._hash,i) == chash &&
|
||||
octstr_case_compare(list_get(prof->ccppaccept.content,i),content_type) == 0) {
|
||||
if ((unsigned long)gwlist_get(prof->ccppaccept._hash,i) == chash &&
|
||||
octstr_case_compare(gwlist_get(prof->ccppaccept.content,i),content_type) == 0) {
|
||||
supported = 1;
|
||||
break;
|
||||
}
|
||||
|
@ -847,10 +872,10 @@ static int modify_msg(MIMEEntity *msg, MmsUaProfile *prof)
|
|||
oindex = -1;
|
||||
for (i = 0; i < NELEMS(cformats); i++)
|
||||
if (cformats[i].fromstandard_cmd) /* Check only ones we can convert from. */
|
||||
for (j = 0, m = list_len(prof->ccppaccept.content); j<m; j++)
|
||||
if ((unsigned long)list_get(prof->ccppaccept._hash,j) == cformats[i].chash &&
|
||||
for (j = 0, m = gwlist_len(prof->ccppaccept.content); j<m; j++)
|
||||
if ((unsigned long)gwlist_get(prof->ccppaccept._hash,j) == cformats[i].chash &&
|
||||
cformats[i].t == type && /* Convert to like type ! */
|
||||
octstr_case_compare(list_get(prof->ccppaccept.content,j),
|
||||
octstr_case_compare(gwlist_get(prof->ccppaccept.content,j),
|
||||
octstr_imm(cformats[i].content_type)) == 0){
|
||||
oindex = i;
|
||||
i = NELEMS(cformats); /* So the other loop breaks too. */
|
||||
|
@ -858,18 +883,16 @@ static int modify_msg(MIMEEntity *msg, MmsUaProfile *prof)
|
|||
}
|
||||
|
||||
|
||||
if (iindex < 0 || oindex < 0) { /* We don't know how to convert this one fully, so... */
|
||||
if (!supported)
|
||||
remove_object(msg, content_type);
|
||||
goto done;
|
||||
}
|
||||
if (iindex < 0 || oindex < 0) /* We don't know how to convert this one fully, so... */
|
||||
goto done2; /* go away, don't even replace headers. */
|
||||
|
||||
|
||||
/* Whatever we have (audio or image) we know how to convert it fully, so ... */
|
||||
mktmpfname(tmpf);
|
||||
if (type == TIMAGE) {
|
||||
FILE *pf;
|
||||
long x = 640, y = 480;
|
||||
Octstr *icmd;
|
||||
Octstr *icmd, *s;
|
||||
char *selector;
|
||||
|
||||
mktmpfname(tmpf2);
|
||||
|
@ -877,9 +900,11 @@ static int modify_msg(MIMEEntity *msg, MmsUaProfile *prof)
|
|||
if (!pf)
|
||||
goto done;
|
||||
|
||||
n = octstr_print(pf, msg->body);
|
||||
s = mime_entity_body(msg);
|
||||
n = octstr_print(pf, s);
|
||||
m = fclose(pf);
|
||||
|
||||
octstr_destroy(s);
|
||||
if (n < 0 || m != 0)
|
||||
goto done; /* error .*/
|
||||
|
||||
|
@ -911,14 +936,17 @@ static int modify_msg(MIMEEntity *msg, MmsUaProfile *prof)
|
|||
selector = "-[0]";
|
||||
else
|
||||
selector = "-";
|
||||
/* We have an unsupported image now. time to convert it. */
|
||||
/* We have an unsupported image now, or a supported one that must be scaled.
|
||||
* time to convert it.
|
||||
*/
|
||||
if (icmd) {
|
||||
cmd = octstr_format("%S | " IMGCONVERTCMD,
|
||||
cmd = (supported) ? octstr_format("%S > %s", icmd, tmpf) :
|
||||
octstr_format("%S | " IMGCONVERTCMD,
|
||||
icmd, cformats[iindex].file_ext, selector,
|
||||
cformats[oindex].file_ext, tmpf);
|
||||
octstr_destroy(icmd);
|
||||
} else
|
||||
cmd = octstr_format("cat %S | " IMGCONVERTCMD,
|
||||
} else /* Image format MUST be unsupported */
|
||||
cmd = octstr_format("cat %s | " IMGCONVERTCMD,
|
||||
tmpf2, cformats[iindex].file_ext, selector,
|
||||
cformats[oindex].file_ext, tmpf);
|
||||
|
||||
|
@ -935,32 +963,37 @@ static int modify_msg(MIMEEntity *msg, MmsUaProfile *prof)
|
|||
if (!pf)
|
||||
goto done;
|
||||
|
||||
if (send_data) /* If this is not set then write the content... */
|
||||
n = octstr_print(pf, msg->body);
|
||||
else
|
||||
if (send_data) { /* If this is not set then write the content... */
|
||||
Octstr *sx = mime_entity_body(msg);
|
||||
n = octstr_print(pf, sx);
|
||||
octstr_destroy(sx);
|
||||
} else
|
||||
n = 0;
|
||||
m = pclose(pf);
|
||||
|
||||
if (n < 0 || m != 0)
|
||||
goto done; /* Error -- finish up. */
|
||||
|
||||
s = octstr_read_file(tmpf);
|
||||
if (s)
|
||||
if ((s = octstr_read_file(tmpf)) != NULL) {
|
||||
replace_body(msg, s, params_h,
|
||||
cformats[oindex].content_type,
|
||||
cformats[oindex].file_ext,0);
|
||||
else
|
||||
supported == 1 ? cformats[iindex].content_type : cformats[oindex].content_type,
|
||||
supported == 1 ? cformats[iindex].file_ext : cformats[oindex].file_ext,0);
|
||||
octstr_destroy(s);
|
||||
supported = 1;
|
||||
goto done2; /* we are done, don't even change headers. */
|
||||
} else /* failed to convert, hence unsupported. */
|
||||
goto done;
|
||||
|
||||
supported = 1; /* Means we have sorted it out. */
|
||||
|
||||
done:
|
||||
done:
|
||||
if (h)
|
||||
mime_replace_headers(msg,h);
|
||||
done2:
|
||||
if (!supported)
|
||||
remove_object(msg, content_type);
|
||||
|
||||
if (content_type)
|
||||
if (h)
|
||||
http_destroy_headers(h);
|
||||
|
||||
octstr_destroy(content_type);
|
||||
if (params)
|
||||
octstr_destroy(params);
|
||||
if (params_h)
|
||||
http_destroy_headers(params_h);
|
||||
|
@ -970,7 +1003,6 @@ static int modify_msg(MIMEEntity *msg, MmsUaProfile *prof)
|
|||
if (tmpf2[0])
|
||||
unlink(tmpf2);
|
||||
|
||||
if (cmd)
|
||||
octstr_destroy(cmd);
|
||||
return supported;
|
||||
}
|
||||
|
@ -1023,66 +1055,71 @@ static int format_special(MIMEEntity *m,
|
|||
char tmpf[40];
|
||||
Octstr *cmd = NULL;
|
||||
List *params_h;
|
||||
List *headers;
|
||||
|
||||
tmpf[0] = 0;
|
||||
get_content_type(m->headers, &content_type, ¶ms);
|
||||
headers = mime_entity_headers(m);
|
||||
get_content_type(headers, &content_type, ¶ms);
|
||||
params_h = get_value_parameters(params);
|
||||
|
||||
if (m->multiparts && list_len(m->multiparts) > 0) {
|
||||
MIMEEntity *pres = NULL;
|
||||
if ((n = mime_entity_num_parts(m)) > 0) {
|
||||
int presindex = -1;
|
||||
Octstr *presbody;
|
||||
Octstr *presbody = NULL;
|
||||
Octstr *start = http_header_value(params_h, octstr_imm("start"));
|
||||
|
||||
for (i = 0, n = list_len(m->multiparts); i<n; i++) {/* format sub-parts,
|
||||
* find presentation part too
|
||||
*/
|
||||
MIMEEntity *x = list_get(m->multiparts,i);
|
||||
for (i = 0; i<n; i++) {/* format sub-parts, find presentation part too */
|
||||
MIMEEntity *x = mime_entity_get_part(m,i);
|
||||
Octstr *ctype = NULL, *charset = NULL;
|
||||
Octstr *cid = http_header_value(x->headers, octstr_imm("Content-ID"));
|
||||
List *hx = mime_entity_headers(x);
|
||||
Octstr *cid = _x_get_content_id(hx);
|
||||
|
||||
http_header_get_content_type(x->headers, &ctype, &charset);
|
||||
http_header_get_content_type(hx, &ctype, &charset);
|
||||
|
||||
/* Find presentation part: If we have start param, and it matches
|
||||
* this one, and this one is SMIL, then...
|
||||
*/
|
||||
if (start && cid && octstr_compare(cid, start) == 0 &&
|
||||
octstr_case_compare(ctype, octstr_imm(PRES_TYPE)) == 0) {
|
||||
pres = x;
|
||||
octstr_case_compare(ctype, octstr_imm(PRES_TYPE)) == 0)
|
||||
presindex = i;
|
||||
}
|
||||
|
||||
if (ctype) octstr_destroy(ctype);
|
||||
if (charset) octstr_destroy(charset);
|
||||
if (cid) octstr_destroy(cid);
|
||||
|
||||
octstr_destroy(ctype);
|
||||
octstr_destroy(charset);
|
||||
octstr_destroy(cid);
|
||||
|
||||
format_special(x, trans_smil, txtmsg, htmlmsg, counter);
|
||||
mime_entity_replace_part(m, i, x);
|
||||
|
||||
http_destroy_headers(hx);
|
||||
mime_entity_destroy(x);
|
||||
}
|
||||
|
||||
if (start) octstr_destroy(start);
|
||||
octstr_destroy(start);
|
||||
|
||||
if (trans_smil && pres) { /* Reformat. */
|
||||
MIMEEntity *x;
|
||||
if (trans_smil && presindex >= 0) { /* Reformat. */
|
||||
MIMEEntity *x, *pres;
|
||||
Octstr *btxt = octstr_create("");
|
||||
List *h = NULL, *h2 = NULL;
|
||||
Octstr *tmp;
|
||||
|
||||
/* Remove type & start param from top level. */
|
||||
http_header_remove_all(params_h, "type");
|
||||
http_header_remove_all(params_h, "start");
|
||||
replace_ctype(m->headers, "multipart/related", params_h);
|
||||
|
||||
replace_ctype(headers, "multipart/related", params_h);
|
||||
|
||||
/* Put content ids on all siblings, and build html. */
|
||||
for (i = 0, n = list_len(m->multiparts); i<n; i++) {
|
||||
MIMEEntity *x = list_get(m->multiparts,i);
|
||||
for (i = 0, n = mime_entity_num_parts(m); i<n; i++) {
|
||||
MIMEEntity *x = mime_entity_get_part(m,i);
|
||||
List *hx = NULL;
|
||||
Octstr *cid, *pname;
|
||||
Octstr *ctype = NULL, *cparams = NULL;
|
||||
Octstr *y, *loc, *cidurl;
|
||||
List *cparamsl;
|
||||
|
||||
if (x == pres) continue; /* Skip the presentation param. */
|
||||
if (i == presindex) goto loop; /* Skip the presentation param. */
|
||||
|
||||
hx = mime_entity_headers(x);
|
||||
cid = _x_get_content_id(hx);
|
||||
|
||||
cid = http_header_value(x->headers, octstr_imm("Content-ID"));
|
||||
if (cid == NULL) {
|
||||
time_t t = time(NULL);
|
||||
char ch[2];
|
||||
|
@ -1091,17 +1128,23 @@ static int format_special(MIMEEntity *m,
|
|||
ch[1] = 0;
|
||||
|
||||
cid = octstr_format("<item-%s-%d-%d>", ch, *counter, (t%99989));
|
||||
http_header_add(x->headers, "Content-ID", octstr_get_cstr(cid));
|
||||
http_header_add(hx, "Content-ID", octstr_get_cstr(cid));
|
||||
|
||||
++*counter;
|
||||
} else if (octstr_get_char(cid, 0) != '<') { /* fix up for badly behaved clients. */
|
||||
octstr_insert_char(cid, 0, '<');
|
||||
octstr_append_char(cid, '>');
|
||||
http_header_remove_all(hx, "Content-ID");
|
||||
http_header_add(hx, "Content-ID", octstr_get_cstr(cid));
|
||||
}
|
||||
|
||||
y = octstr_copy(cid, 1, octstr_len(cid) - 2);
|
||||
loc = http_header_value(x->headers, octstr_imm("Content-Location"));
|
||||
loc = http_header_value(hx, octstr_imm("Content-Location"));
|
||||
|
||||
cidurl = octstr_duplicate(y);
|
||||
octstr_url_encode(cidurl);
|
||||
|
||||
get_content_type(x->headers, &ctype, &cparams); /* Get type of object. */
|
||||
get_content_type(hx, &ctype, &cparams); /* Get type of object. */
|
||||
|
||||
if (cparams) { /* Get its name. */
|
||||
if ((cparamsl = get_value_parameters(cparams)) != NULL) {
|
||||
|
@ -1116,10 +1159,12 @@ static int format_special(MIMEEntity *m,
|
|||
if (octstr_case_search(ctype, octstr_imm("image/"), 0) == 0)
|
||||
octstr_format_append(btxt,
|
||||
"\n<img src=\"cid:%S\" border=0 alt=\"%S\"><br><br>\n",
|
||||
cidurl, pname);
|
||||
else if (octstr_case_search(ctype, octstr_imm("text/"), 0) == 0)
|
||||
octstr_format_append(btxt, "%S<br><br>\n",
|
||||
x->body ? x->body : octstr_imm(""));
|
||||
cidurl, pname ? pname : octstr_imm("image"));
|
||||
else if (octstr_case_search(ctype, octstr_imm("text/"), 0) == 0) {
|
||||
Octstr *s = mime_entity_body(x);
|
||||
octstr_format_append(btxt, "%S<br><br>\n", s);
|
||||
octstr_destroy(s);
|
||||
}
|
||||
#if 0
|
||||
else if (octstr_case_search(ctype, octstr_imm("audio/"), 0) == 0)
|
||||
octstr_format_append(btxt,
|
||||
|
@ -1129,63 +1174,91 @@ static int format_special(MIMEEntity *m,
|
|||
else
|
||||
octstr_format_append(btxt,
|
||||
"<a type=\"%S\" href=\"cid:%S\">%S</a><br><br>\n",
|
||||
ctype, cidurl, pname);
|
||||
ctype, cidurl, pname ? pname : octstr_imm(""));
|
||||
|
||||
http_header_remove_all(x->headers, "Content-Location");
|
||||
http_header_remove_all(hx, "Content-Location");
|
||||
|
||||
if (y) octstr_destroy(y);
|
||||
if (loc) octstr_destroy(loc);
|
||||
if (ctype) octstr_destroy(ctype);
|
||||
if (cidurl) octstr_destroy(cidurl);
|
||||
if (pname) octstr_destroy(pname);
|
||||
mime_replace_headers(x, hx); /* put back headers, replace part in main...*/
|
||||
mime_entity_replace_part(m, i, x);
|
||||
|
||||
http_destroy_headers(hx);
|
||||
|
||||
octstr_destroy(y);
|
||||
octstr_destroy(loc);
|
||||
octstr_destroy(ctype);
|
||||
octstr_destroy(cidurl);
|
||||
octstr_destroy(pname);
|
||||
|
||||
octstr_destroy(cid);
|
||||
|
||||
loop:
|
||||
mime_entity_destroy(x);
|
||||
}
|
||||
|
||||
pres = mime_entity_get_part(m,presindex);
|
||||
presbody = mime_entity_body(pres);
|
||||
h = mime_entity_headers(pres);
|
||||
|
||||
http_header_remove_all(pres->headers, "Content-Type");
|
||||
http_header_add(pres->headers, "Content-Type", "multipart/alternative");
|
||||
|
||||
presbody = pres->body;
|
||||
pres->body = NULL;
|
||||
if (!pres->multiparts)
|
||||
pres->multiparts = list_create();
|
||||
http_header_remove_all(h, "Content-Type");
|
||||
http_header_add(h, "Content-Type", "multipart/alternative");
|
||||
|
||||
mime_replace_headers(pres,h);
|
||||
http_destroy_headers(h);
|
||||
|
||||
/* first the text part ... */
|
||||
x = mime_entity_create();
|
||||
http_header_add(x->headers, "Content-Type", "text/plain");
|
||||
x->body = octstr_create(txtmsg ? txtmsg : "");
|
||||
list_append(pres->multiparts, x);
|
||||
h2 = http_create_empty_headers();
|
||||
http_header_add(h2, "Content-Type", "text/plain");
|
||||
tmp = octstr_create(txtmsg ? txtmsg : "");
|
||||
|
||||
mime_replace_headers(x, h2);
|
||||
mime_entity_set_body(x,tmp);
|
||||
|
||||
mime_entity_add_part(pres, x);
|
||||
|
||||
http_destroy_headers(h2);
|
||||
octstr_destroy(tmp);
|
||||
mime_entity_destroy(x);
|
||||
|
||||
/* Lets also leave the pres part in there, just in case somebody knows how to handle it... */
|
||||
x = mime_entity_create();
|
||||
http_header_add(x->headers, "Content-Type", PRES_TYPE);
|
||||
x->body = presbody;
|
||||
list_append(pres->multiparts, x);
|
||||
h2 = http_create_empty_headers();
|
||||
http_header_add(h2, "Content-Type", PRES_TYPE);
|
||||
mime_replace_headers(x, h2);
|
||||
mime_entity_set_body(x, presbody);
|
||||
mime_entity_add_part(pres, x);
|
||||
|
||||
http_destroy_headers(h2);
|
||||
mime_entity_destroy(x);
|
||||
|
||||
|
||||
/* then the html part. */
|
||||
x = mime_entity_create();
|
||||
http_header_add(x->headers, "Content-Type", "text/html");
|
||||
x->body = octstr_format("<html><body><center>%s<hr><br>%S<hr></center></body></html>\n",
|
||||
h2 = http_create_empty_headers();
|
||||
http_header_add(h2, "Content-Type", "text/html");
|
||||
tmp = octstr_format("<html><body><center>%s<hr><br>%S<hr></center></body></html>\n",
|
||||
htmlmsg ? htmlmsg : "", btxt);
|
||||
list_append(pres->multiparts, x);
|
||||
|
||||
list_delete(m->multiparts, presindex, 1); /* Put it at the beginning. */
|
||||
list_insert(m->multiparts, 0, pres);
|
||||
#if 0
|
||||
http_header_remove_all(pres->headers, "Content-ID"); /* Not needed anymore. */
|
||||
#endif
|
||||
mime_replace_headers(x, h2);
|
||||
mime_entity_set_body(x,tmp);
|
||||
|
||||
mime_entity_add_part(pres, x);
|
||||
|
||||
http_destroy_headers(h2);
|
||||
octstr_destroy(tmp);
|
||||
mime_entity_destroy(x);
|
||||
|
||||
|
||||
mime_entity_replace_part(m, presindex, pres);
|
||||
mime_entity_destroy(pres);
|
||||
|
||||
octstr_destroy(presbody);
|
||||
octstr_destroy(btxt);
|
||||
|
||||
|
||||
}
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (octstr_case_search(content_type, octstr_imm("image/"), 0) == 0)
|
||||
type = TIMAGE;
|
||||
else if (octstr_case_search(content_type, octstr_imm("audio/"), 0) == 0)
|
||||
|
@ -1233,22 +1306,26 @@ static int format_special(MIMEEntity *m,
|
|||
|
||||
if (!pf)
|
||||
goto done;
|
||||
n = octstr_print(pf, m->body);
|
||||
s = mime_entity_body(m);
|
||||
n = octstr_print(pf, s);
|
||||
octstr_destroy(s);
|
||||
|
||||
o = pclose(pf);
|
||||
|
||||
if (n < 0 || o != 0)
|
||||
goto done; /* Error -- finish up. */
|
||||
|
||||
s = octstr_read_file(tmpf);
|
||||
if (s)
|
||||
if ((s = octstr_read_file(tmpf)) != NULL) {
|
||||
replace_body(m, s, params_h,
|
||||
cformats[ipref].content_type,
|
||||
cformats[ipref].file_ext,1);
|
||||
else
|
||||
octstr_destroy(s);
|
||||
} else
|
||||
goto done;
|
||||
|
||||
} else if (type == TTEXT) {/* change to default charset. */
|
||||
Octstr *charset = http_header_value(params_h, octstr_imm("charset"));
|
||||
Octstr *s;
|
||||
if (charset == NULL ||
|
||||
octstr_case_compare(charset, octstr_imm("unknown")) == 0 ||
|
||||
octstr_case_compare(charset, octstr_imm(DEFAULT_CHARSET)) == 0) {
|
||||
|
@ -1256,7 +1333,8 @@ static int format_special(MIMEEntity *m,
|
|||
goto done; /* Nothing more to do here. */
|
||||
}
|
||||
|
||||
if (charset_convert(m->body, octstr_get_cstr(charset),
|
||||
s = mime_entity_body(m);
|
||||
if (charset_convert(s, octstr_get_cstr(charset),
|
||||
DEFAULT_CHARSET) != -1) { /* using libiconv...*/
|
||||
Octstr *tmp, *ct;
|
||||
|
||||
|
@ -1266,23 +1344,25 @@ static int format_special(MIMEEntity *m,
|
|||
|
||||
ct = octstr_format("%S; %S", content_type, tmp);
|
||||
octstr_destroy(tmp);
|
||||
http_header_remove_all(m->headers, "Content-Type");
|
||||
http_header_add(m->headers, "Content-Type", octstr_get_cstr(ct));
|
||||
http_header_remove_all(headers, "Content-Type");
|
||||
http_header_add(headers, "Content-Type", octstr_get_cstr(ct));
|
||||
octstr_destroy(ct);
|
||||
|
||||
mime_entity_set_body(m, s);
|
||||
} /* Else goto done. */
|
||||
|
||||
octstr_destroy(s);
|
||||
} /* Else do nothing. */
|
||||
|
||||
done:
|
||||
|
||||
if (headers) {
|
||||
mime_replace_headers(m, headers);
|
||||
http_destroy_headers(headers);
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
if (content_type)
|
||||
octstr_destroy(content_type);
|
||||
octstr_destroy(params);
|
||||
if (params_h)
|
||||
http_destroy_headers(params_h);
|
||||
if (cmd)
|
||||
octstr_destroy(cmd);
|
||||
|
||||
if (tmpf[0])
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* User-Agent profiles handling, content adaptation.
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Misc. functions
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -15,51 +15,69 @@
|
|||
|
||||
#include "gwlib/gwlib.h"
|
||||
#include "gwlib/mime.h"
|
||||
#include "gwlib/regex.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "mbuni-config.h"
|
||||
#include "mms_strings.h"
|
||||
#include "mms_msg.h"
|
||||
#include "mms_mm7soap.h"
|
||||
#include "mms_cfg.h"
|
||||
#include "mms_mmbox.h"
|
||||
#include "mms_eventlogger.h"
|
||||
|
||||
/* supported 3GPP MMS version */
|
||||
#define MAKE_VERSION(a,b,c) ((a)<<16 | (b)<<8 | (c))
|
||||
|
||||
#define MAJOR_VERSION(v) (((v)>>16)&0xF)
|
||||
#define MINOR1_VERSION(v) (((v)>>8)&0xF)
|
||||
#define MINOR2_VERSION(v) ((v)&0xF)
|
||||
|
||||
#define MMS_3GPP_VERSION MAKE_VERSION(5,5,0)
|
||||
|
||||
/* Send errors */
|
||||
#define MMS_SEND_OK 0
|
||||
#define MMS_SEND_QUEUED 1
|
||||
#define MMS_SEND_ERROR_TRANSIENT -1
|
||||
#define MMS_SEND_ERROR_FATAL -2
|
||||
|
||||
#define SEND_ERROR_STR(e) ((e) == MMS_SEND_OK ? "Sent" : (e) == MMS_SEND_ERROR_TRANSIENT ? "Retry later" : "Failed")
|
||||
/* Aging of old (internal) records... */
|
||||
#define DEFAULT_DELETE_AGE 10*60
|
||||
|
||||
#define SEND_ERROR_STR(e) ((e) == MMS_SEND_OK ? "Sent" : \
|
||||
(e) == MMS_SEND_ERROR_TRANSIENT ? "Retry later" : \
|
||||
((e) == MMS_SEND_QUEUED ? "Queued" : "Failed"))
|
||||
/* Useful headers. */
|
||||
#define XMSISDN_HEADER "X-WAP-Network-Client-MSISDN"
|
||||
#define XIP_HEADER "X-WAP-Network-Client-IP"
|
||||
#define MM_NAME "Mbuni"
|
||||
|
||||
#define EAIF_VERSION "3.0"
|
||||
#define EAIF_VERSION "%d.%d"
|
||||
|
||||
/* used by mmbox and queue code -- directory stuff. */
|
||||
#define _TT "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
#define _TTSIZE (-1 + sizeof _TT)
|
||||
|
||||
#define MBUNI_MULTIPART_TYPE "application/vnd.mbuni.url-list"
|
||||
|
||||
/* Global variables and shared code used by all modules. */
|
||||
|
||||
#define MMSC_VERSION VERSION
|
||||
#define MMSC_VERSION MBUNI_VERSION
|
||||
#define MMS_NAME PACKAGE
|
||||
|
||||
#define DRM_CONTENT_TYPE(ctype) ((ctype) && octstr_case_search(ctype, octstr_imm("application/vnd.oma.drm"), 0) == 0)
|
||||
|
||||
/* Message location flags: Used to distinguish fetch-urls */
|
||||
enum mms_loc_t {MMS_LOC_MMBOX = 1, MMS_LOC_MQUEUE=2};
|
||||
|
||||
|
||||
extern int mms_load_core_settings(mCfgGrp *cgrp);
|
||||
extern int mms_load_core_settings(mCfg *cfg, mCfgGrp *cgrp);
|
||||
|
||||
extern Octstr *mms_maketransid(char *qf, Octstr *mmscname);
|
||||
|
||||
extern Octstr *mms_make_msgid(char *qf, Octstr *mmscname);
|
||||
|
||||
extern Octstr *mms_getqf_fromtransid(Octstr *transid);
|
||||
|
||||
extern int mms_decodefetchurl(Octstr *fetch_url,
|
||||
Octstr **qf, Octstr **token, int *loc);
|
||||
|
||||
Octstr *mms_find_sender_ip(List *request_hdrs, Octstr *ip_header, Octstr *ip, int *isv6);
|
||||
extern Octstr *mms_getqf_from_msgid(Octstr *msgid);
|
||||
|
||||
extern Octstr *mms_isodate(time_t t);
|
||||
void mms_lib_init(void);
|
||||
|
@ -75,27 +93,39 @@ List *get_value_parameters(Octstr *params);
|
|||
|
||||
Octstr *make_value_parameters(List *params);
|
||||
|
||||
/* Get parameter from http header value and strip it */
|
||||
Octstr *get_stripped_param_value(Octstr *value, Octstr *param);
|
||||
|
||||
/* Where value is comma-separated, make separate header items. */
|
||||
void unpack_mimeheaders(MIMEEntity *m);
|
||||
|
||||
/* Where element has base64 encoding, decode. */
|
||||
void unbase64_mimeparts(MIMEEntity *m);
|
||||
|
||||
/* Where element contains binary data, encode it base64. */
|
||||
void base64_mimeparts(MIMEEntity *m);
|
||||
/* Where element contains binary data, encode it base64. Set all = 1 to ignore whether body is binary
|
||||
* and should be coded.
|
||||
*/
|
||||
void base64_mimeparts(MIMEEntity *m, int all);
|
||||
|
||||
void notify_prov_server(char *cmd, char *from, char *event, char *arg);
|
||||
int mms_ind_send(Octstr *prov_cmd, Octstr *to);
|
||||
|
||||
/* Send this message to email recipient: Returns 0 on success 1 or 2 on profile error
|
||||
* (negate to get right one), -ve on some other error
|
||||
*/
|
||||
int mms_sendtoemail(Octstr *from, Octstr *to,
|
||||
int mms_sendtoemail(Octstr *from, List *lto,
|
||||
Octstr *subject, Octstr *msgid,
|
||||
MmsMsg *msg, int dlr, Octstr **error,
|
||||
char *sendmail_cmd, Octstr *myhostname,
|
||||
int trans_msg,
|
||||
int trans_smil, char *txt, char *html, int append_hostname);
|
||||
int trans_smil, char *txt, char *html, int mm4,
|
||||
char *transid, List *extra_headers,
|
||||
Octstr *relay_host, int relay_port);
|
||||
|
||||
/* Send directly to email. */
|
||||
int mm_send_to_email(Octstr *to, Octstr *from, Octstr *subject,
|
||||
Octstr *msgid,
|
||||
MIMEEntity *m, int append_hostname, Octstr **error,
|
||||
char *sendmail_cmd, Octstr *myhostname,
|
||||
Octstr *relay_host, int relay_port);
|
||||
|
||||
/* log to access log. */
|
||||
void mms_log(char *logmsg, Octstr *from, List *to,
|
||||
|
@ -118,28 +148,41 @@ void mms_log2(char *logmsg, Octstr *from, Octstr *to,
|
|||
*/
|
||||
int mm_lockfile(int fd, char *fname, int shouldblock);
|
||||
|
||||
/* This should be elsewhere, but it isn't, so we do it here... */
|
||||
extern MIMEEntity *mime_entity_duplicate(MIMEEntity *m);
|
||||
|
||||
/* Returns true if the character is printable or space */
|
||||
int _mms_gw_isprint(int c);
|
||||
|
||||
int lockfile(int fd, int shouldblock);
|
||||
/*
|
||||
* unlock_and_fclose/unlock_and_close are wrappers around fclose/close
|
||||
* needed to maintain the state of the global list on Solaris.
|
||||
*/
|
||||
int unlock_and_fclose(FILE *fp);
|
||||
int unlock_and_close(int fd);
|
||||
|
||||
/* Special form of cfg_get which returns zero-length string when there is nothing. */
|
||||
Octstr *_mms_cfg_getx(mCfgGrp *grp, Octstr *item);
|
||||
Octstr *_mms_cfg_getx(mCfg *cfg, mCfgGrp *grp, Octstr *item);
|
||||
|
||||
/* Get envelope data from message headers. */
|
||||
void mms_collect_envdata_from_msgheaders(List *mh, List **xto,
|
||||
Octstr **subject,
|
||||
Octstr **otransid, time_t *expiryt,
|
||||
time_t *deliveryt, long default_msgexpiry);
|
||||
time_t *deliveryt, long default_msgexpiry,
|
||||
long max_msgexpiry,
|
||||
char *unified_prefix, List *strip_prefixes);
|
||||
|
||||
/* Simple hash function */
|
||||
unsigned long _mshash(char *s);
|
||||
|
||||
/* Tell us whether address is a phone number. */
|
||||
int isphonenum(Octstr *s);
|
||||
/* Fixup an address: Add type, etc. */
|
||||
void _mms_fixup_address(Octstr *address);
|
||||
int isphonenum_ex(Octstr *s, int offset);
|
||||
|
||||
/* Fixup an address: Normalize number (if prefix given), Add type (if keep_suffix is set), etc. */
|
||||
void _mms_fixup_address(Octstr **address, char *unified_prefix, List *strip_prefixes, int keep_suffix);
|
||||
|
||||
/* normalize a phone number: Strip any prefixes, then normalize. */
|
||||
void mms_normalize_phonenum(Octstr **num, char *unified_prefix, List *strip_prefixes);
|
||||
|
||||
/* Check that host is one of hosts in semi-colon separated list in host_list */
|
||||
int is_allowed_host(Octstr *host, Octstr *host_list);
|
||||
|
@ -147,8 +190,138 @@ int is_allowed_host(Octstr *host, Octstr *host_list);
|
|||
/* escape (backlash) special shell characters. */
|
||||
void escape_shell_chars(Octstr *str);
|
||||
|
||||
/* Parse CGI variables out of a HTTP POST request.
|
||||
* This function understands both standard POST and enctype multipart/form-data
|
||||
* For the latter it puts the content type of each of the variables found into
|
||||
* cgivars_ctypes (as HTTPCGIVars where name is the field name and value is the content type)
|
||||
* cgivars argument is the cgivars as passed to us by http_accept_request. For GET
|
||||
* HTTP requests this is returned unchanged, otherwise it is augmented with the
|
||||
* variables found.
|
||||
*/
|
||||
int parse_cgivars(List *request_headers, Octstr *request_body,
|
||||
List **cgivars, List **cgivar_ctypes);
|
||||
|
||||
/* get content-ID header, fix: WAP decoder may leave " at beginning */
|
||||
Octstr *_x_get_content_id(List *headers);
|
||||
|
||||
/* Remove the boundary element from a list of headers. */
|
||||
void strip_boundary_element(List *headers, char *s);
|
||||
|
||||
/* Fetch a URL. If necessary, authenticate, etc. also understands data: url scheme. */
|
||||
int mms_url_fetch_content(int method, Octstr *url, List *request_headers,
|
||||
Octstr *body, List **reply_headers, Octstr **reply_body);
|
||||
|
||||
/* check that the token is valid. */
|
||||
int mms_is_token(Octstr *token);
|
||||
|
||||
/* try to guess content type from file name extension. */
|
||||
Octstr *filename2content_type(char *fname);
|
||||
|
||||
/* try to give a good extension name based on the url or content type. */
|
||||
char *make_file_ext(Octstr *url, Octstr *ctype, char fext[5]);
|
||||
|
||||
/* return true if node has a child... */
|
||||
int has_node_children(xmlNodePtr node);
|
||||
|
||||
/* strip non-essential headers from top-level */
|
||||
void strip_non_essential_headers(MIMEEntity *mime);
|
||||
|
||||
/* Get phone number out of mms formatted one, and unify. */
|
||||
Octstr *extract_phonenum(Octstr *num, Octstr *unified_prefix);
|
||||
|
||||
/* strip quotes off a quoted string. */
|
||||
void strip_quoted_string(Octstr *s);
|
||||
|
||||
/* Remove quotes from string */
|
||||
void strip_quotes(Octstr *s);
|
||||
|
||||
/* Make a mime entity representing a multipart/form-data HTTP request. */
|
||||
MIMEEntity *make_multipart_formdata(void);
|
||||
|
||||
/* Add a form field to the multipart/form-data entity. */
|
||||
void add_multipart_form_field(MIMEEntity *multipart, char *field_name,
|
||||
char *ctype, char *content_loc,
|
||||
Octstr *data);
|
||||
|
||||
/* Build a multipart message from a list of URLs. Fetch each one and add. Result is a multipart/mixed message. */
|
||||
MIMEEntity *multipart_from_urls(List *url_list);
|
||||
|
||||
/* load a shared object, then load a symbol from it. */
|
||||
void *_mms_load_module(mCfg *cfg, mCfgGrp *grp, char *config_key, char *symbolname,
|
||||
void *shell_builtin);
|
||||
|
||||
/* Clean addresses by type: remove prefixes, etc. */
|
||||
void fixup_address_type(List *headers, char *hdr,
|
||||
char *unified_prefix,
|
||||
List *strip_prefixes);
|
||||
|
||||
/* Convert charset mib enum to charset and vice versa */
|
||||
extern const char *mibenum_to_charset(int val);
|
||||
extern int charset_to_mibenum(char *charset);
|
||||
Octstr *pack_rfc2047_text(Octstr *in, int charset_mib_enum);
|
||||
Octstr *parse_rfc2047_text(Octstr *in, int *mibenum);
|
||||
|
||||
/* Utility func */
|
||||
void mygw_free(void *);
|
||||
|
||||
/* Authenticate using HTTP Basic auth */
|
||||
int http_auth_check(char *user, char *pass, List *headers, int *has_auth_hdr);
|
||||
|
||||
/* Add @host to an mms address */
|
||||
void addmmscname(Octstr *address, char *myhostname);
|
||||
|
||||
/* Get (copy of) keyword from mime thingie */
|
||||
Octstr *get_keyword_from_mime(MIMEEntity *me);
|
||||
|
||||
enum _xurltype {FILE_TYPE, URL_TYPE};
|
||||
void get_content_from_sendmms_request(Octstr *body, List *headers, List *cgivars, List *cgivar_ctypes,
|
||||
List **rh, Octstr **ctype, Octstr **data,
|
||||
Octstr **rb,
|
||||
Octstr **base_url, Octstr **data_url);
|
||||
|
||||
MmsMsg *make_msg_from_sendmms_request(Octstr *from, List *to,
|
||||
Octstr *msgId,
|
||||
Octstr *subject,
|
||||
Octstr *data, Octstr *ctype,
|
||||
List *reply_headers,
|
||||
Octstr *msg_url,
|
||||
Octstr *base_url, int type,
|
||||
Octstr *mmc,
|
||||
Octstr *svc_name,
|
||||
time_t expiryt,
|
||||
int do_multipart,
|
||||
int do_rr,
|
||||
int do_dlr,
|
||||
Octstr *allow_adaptations,
|
||||
int (*filter)(MIMEEntity **msg, Octstr *loc_url, Octstr *mmc_id),
|
||||
Octstr **err);
|
||||
#define US_ASCII_MIB_VAL 3
|
||||
#define UTF8_MIB_VAL 106
|
||||
|
||||
#define MAXQTRIES 100
|
||||
#define BACKOFF_FACTOR 5*60 /* In seconds */
|
||||
#define QUEUERUN_INTERVAL 15*60 /* 15 minutes. */
|
||||
#define QUEUERUN_INTERVAL 1*60 /* 1 minutes. */
|
||||
#define DEFAULT_EXPIRE 3600*24*7 /* One week */
|
||||
|
||||
#define DEFAULT_SIMUL_RCPTS 10
|
||||
|
||||
#define HTTP_REPLACE_HEADER(hdr, hname, value) do { \
|
||||
http_header_remove_all((hdr), (hname)); \
|
||||
http_header_add((hdr), (hname), (value)); \
|
||||
} while (0)
|
||||
|
||||
List *gwlist_create_ex_real(const char *file, const char *func, int line,...);
|
||||
|
||||
#define gwlist_create_ex(...) gwlist_create_ex_real(__FILE__,__FUNCTION__,__LINE__, __VA_ARGS__, NULL)
|
||||
|
||||
#define LINEARISE_STR_LIST(res,lst,sep) do { \
|
||||
Octstr *__res; \
|
||||
int __i; \
|
||||
for (__res = octstr_create(""), __i = 0; __i < gwlist_len(lst); __i++) \
|
||||
octstr_format_append(__res, "%s%S", \
|
||||
octstr_len(__res) == 0 ? "" : (sep), gwlist_get((lst), __i)); \
|
||||
(res) = __res; \
|
||||
} while (0)
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
libmms = $(top_builddir)/mmlib/libmms.la
|
||||
|
||||
lib_LTLIBRARIES = libmmsbox.la
|
||||
libmmsbox_la_SOURCES = mmsbox_cdr.c mmsbox_cfg.h mmsbox_cfg.c dlr.c bearerbox.c mmsbox_resolve.c mmsbox_resolve_shell.c
|
||||
bin_PROGRAMS = mmsbox
|
||||
mmsbox_SOURCES = mmsbox.c mmsbox_cfg.c dlr.c bearerbox.c
|
||||
mmsbox_LDADD = $(libmms)
|
||||
mmsbox_SOURCES = mmsbox.c mmsbox.h
|
||||
mmsbox_LDADD = libmmsbox.la $(libmms)
|
||||
|
||||
EXTRA_DIST = mmsbox_cfg.h mmsbox.h
|
||||
EXTRA_DIST = mmsbox_cdr.h mmsbox_cfg.h mmsbox.h mmsbox_mt_filter.h mmsbox_resolve_shell.h mmsbox_resolve.h mmsbox_mmsc.h
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* MMSBox Dlr: Dlr storage for MMSBox
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -17,6 +17,10 @@
|
|||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#ifdef SunOS
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
@ -24,7 +28,7 @@
|
|||
#include "mms_queue.h"
|
||||
|
||||
#define MAXTRIES 10
|
||||
static int dlr_entry_fname(char *msgid, char *rtype, Octstr *mmc_id, Octstr **efname)
|
||||
static int dlr_entry_fname(char *msgid, char *rtype, Octstr *mmc_gid, Octstr **efname)
|
||||
{
|
||||
char d1[2], d2[3], fbuf[512], *p;
|
||||
unsigned long h = _mshash(msgid);
|
||||
|
@ -43,17 +47,17 @@ static int dlr_entry_fname(char *msgid, char *rtype, Octstr *mmc_id, Octstr **ef
|
|||
d2[2] = '\0';
|
||||
|
||||
/* Try and create the next level dir (first level was created by root_init) */
|
||||
sprintf(fbuf, "%s/%s/%s", octstr_get_cstr(dlr_dir), d1, d2);
|
||||
sprintf(fbuf, "%.128s/%s/%s", octstr_get_cstr(dlr_dir), d1, d2);
|
||||
if (mkdir(fbuf,
|
||||
S_IRWXU|S_IRWXG) < 0 &&
|
||||
errno != EEXIST) {
|
||||
error(0, "mmsbox: failed to create dir [%s] "
|
||||
mms_error(0, "mmsbox", NULL, "failed to create dir [%s] "
|
||||
"while initialising dlr dir for %s: %s!",
|
||||
fbuf, msgid, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
t = octstr_format("%S-%s_%s", mmc_id, msgid, rtype); /* Put mmc id into name. */
|
||||
t = octstr_format("%S-%s_%s", mmc_gid, msgid, rtype); /* Put mmc id into name. */
|
||||
|
||||
octstr_replace(t, octstr_imm("/"), octstr_imm("$")); /* XXX safe in all cases?? */
|
||||
s = octstr_format("%s/%S", fbuf, t);
|
||||
|
@ -64,11 +68,11 @@ static int dlr_entry_fname(char *msgid, char *rtype, Octstr *mmc_id, Octstr **ef
|
|||
i = 0;
|
||||
do
|
||||
if ((fd = open(p, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)) < 0) {
|
||||
error(0, "Failed to open DLR URL store file [%s], error: %s!",
|
||||
mms_error(0, "mmsbox", NULL, "Failed to open DLR URL store file [%s], error: %s!",
|
||||
p, strerror(errno));
|
||||
break;
|
||||
} else if (mm_lockfile(fd, p, 1) != 0) {
|
||||
close(fd);
|
||||
unlock_and_close(fd);
|
||||
fd = -1;
|
||||
}
|
||||
while (i++ < MAXTRIES && fd < 0);
|
||||
|
@ -81,42 +85,53 @@ static int dlr_entry_fname(char *msgid, char *rtype, Octstr *mmc_id, Octstr **ef
|
|||
return fd;
|
||||
}
|
||||
|
||||
void mms_dlr_url_put(Octstr *msgid, char *rtype, Octstr *mmc_id, Octstr *dlr_url)
|
||||
void mms_dlr_url_put(Octstr *msgid, char *rtype, Octstr *mmc_gid, Octstr *dlr_url, Octstr *transid)
|
||||
{
|
||||
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_id, NULL);
|
||||
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_gid, NULL);
|
||||
|
||||
if (fd >= 0) {
|
||||
octstr_write_data(dlr_url, fd, 0);
|
||||
close(fd);
|
||||
Octstr *x = octstr_format("%S %S", transid ? transid : octstr_imm("x"), dlr_url); /* better have no spaces in transid! */
|
||||
octstr_write_data(x, fd, 0);
|
||||
unlock_and_close(fd);
|
||||
octstr_destroy(x);
|
||||
}
|
||||
}
|
||||
|
||||
Octstr *mms_dlr_url_get(Octstr *msgid, char *rtype, Octstr *mmc_id)
|
||||
int mms_dlr_url_get(Octstr *msgid, char *rtype, Octstr *mmc_gid, Octstr **dlr_url, Octstr **transid)
|
||||
{
|
||||
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_id, NULL);
|
||||
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_gid, NULL);
|
||||
FILE *f;
|
||||
|
||||
if (fd >= 0 && (f = fdopen(fd, "r+")) != NULL) {
|
||||
Octstr *s = octstr_read_pipe(f);
|
||||
int i, ret;
|
||||
|
||||
fclose(f);
|
||||
unlock_and_fclose(f);
|
||||
if (s && octstr_len(s) == 0) {
|
||||
octstr_destroy(s);
|
||||
return NULL;
|
||||
ret = -1;
|
||||
} else if ((i = octstr_search_char(s, ' ', 0)) >= 0) {
|
||||
*transid = octstr_copy(s, 0, i);
|
||||
*dlr_url = octstr_copy(s, i+1, octstr_len(s));
|
||||
ret = 0;
|
||||
} else
|
||||
return s;
|
||||
ret = -1;
|
||||
octstr_destroy(s);
|
||||
return ret;
|
||||
} else if (fd >= 0)
|
||||
close(fd);
|
||||
return NULL;
|
||||
unlock_and_close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void mms_dlr_url_remove(Octstr *msgid, char *rtype, Octstr *mmc_id)
|
||||
void mms_dlr_url_remove(Octstr *msgid, char *rtype, Octstr *mmc_gid)
|
||||
{
|
||||
Octstr *fname = NULL;
|
||||
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_id, &fname);
|
||||
int fd = dlr_entry_fname(octstr_get_cstr(msgid), rtype, mmc_gid, &fname);
|
||||
|
||||
if (fname)
|
||||
if (fname) {
|
||||
unlink(octstr_get_cstr(fname));
|
||||
octstr_destroy(fname);
|
||||
}
|
||||
if (fd >= 0)
|
||||
close(fd);
|
||||
unlock_and_close(fd);
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* MMSBOX CFG: MMC configuration and misc. functions
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -14,14 +14,19 @@
|
|||
#define __MMSBOX_INCLUDED__
|
||||
#include "mmsbox_cfg.h"
|
||||
|
||||
extern int rstop;
|
||||
void mms_dlr_url_put(Octstr *msgid, char *rtype, Octstr *mmc_id, Octstr *dlr_url);
|
||||
Octstr *mms_dlr_url_get(Octstr *msgid, char *rtype, Octstr *mmc_id);
|
||||
void mms_dlr_url_remove(Octstr *msgid, char *rtype, Octstr *mmc_id);
|
||||
void mmsc_receive_func(MmscGrp *m);
|
||||
void mmsbox_outgoing_queue_runner(int *rstop);
|
||||
void mms_dlr_url_put(Octstr *msgid, char *rtype, Octstr *mmc_gid, Octstr *dlr_url, Octstr *transid);
|
||||
int mms_dlr_url_get(Octstr *msgid, char *rtype, Octstr *mmc_gid, Octstr **dlr_url, Octstr **transid);
|
||||
void mms_dlr_url_remove(Octstr *msgid, char *rtype, Octstr *mmc_gid);
|
||||
|
||||
/* Fetch content given method. also understands data: url scheme. */
|
||||
int mmsbox_url_fetch_content(int method, Octstr *url, List *request_headers,
|
||||
Octstr *body, List **reply_headers, Octstr **reply_body);
|
||||
Octstr *mmsbox_get_report_info(MmsMsg *m, MmscGrp *mmsc, Octstr *out_mmc_id,
|
||||
char *report_type,
|
||||
Octstr *status, List *qhdr, Octstr *uaprof,
|
||||
time_t uaprof_tstamp,
|
||||
Octstr *msgid);
|
||||
void mmsc_receive_func(MmscGrp *m);
|
||||
void mmsbox_outgoing_queue_runner(volatile sig_atomic_t *rstop);
|
||||
void mm4_receive_func(int *sock);
|
||||
void handle_mm1_mt_requests(MmscGrp *m); /* MM1 loop */
|
||||
/* Just a convenience, should go away in future! */
|
||||
#define mmsbox_url_fetch_content mms_url_fetch_content
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* Mbuni MMSBOX base CDR handler module (writes to a CVS file)
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mmsbox_cdr.h"
|
||||
#include "mmsbox_cfg.h"
|
||||
|
||||
static FILE *cdr_file;
|
||||
static List *req_list;
|
||||
static long th_id;
|
||||
|
||||
|
||||
#define CBUFSIZE 256
|
||||
typedef struct MmsBoxCdrStruct {
|
||||
time_t sdate;
|
||||
char from[CBUFSIZE];
|
||||
char to[CBUFSIZE];
|
||||
#if 0
|
||||
char src_ip[CBUFSIZE/4];
|
||||
char dest_ip[CBUFSIZE/4];
|
||||
#endif
|
||||
char msgid[CBUFSIZE];
|
||||
char mmsc_id[CBUFSIZE];
|
||||
|
||||
char src_int[CBUFSIZE/4];
|
||||
char dst_int[CBUFSIZE/4];
|
||||
|
||||
unsigned long msg_size;
|
||||
|
||||
char msgtype[CBUFSIZE/8];
|
||||
char prio[CBUFSIZE/8];
|
||||
char mclass[CBUFSIZE/8];
|
||||
char status[CBUFSIZE/8];
|
||||
unsigned char dlr;
|
||||
unsigned char rr;
|
||||
} MmsBoxCdrStruct;
|
||||
|
||||
|
||||
static void cdr_logger_func(void)
|
||||
{
|
||||
|
||||
MmsBoxCdrStruct *cdr;
|
||||
hmon->register_thread("cdr_logger");
|
||||
while ((cdr = gwlist_consume(req_list)) != NULL) {
|
||||
char buf[CBUFSIZE];
|
||||
struct tm tm;
|
||||
|
||||
localtime_r(&cdr->sdate, &tm);
|
||||
gw_strftime(buf, sizeof buf, "%Y-%m-%d %H:%M:%S", &tm);
|
||||
fprintf(cdr_file, "%s", buf);
|
||||
|
||||
/* Print rest of fields one by one. */
|
||||
#define PRINTF_STR_FIELD(fld) fprintf(cdr_file, "\t%.*s", (int)(sizeof cdr->fld), cdr->fld)
|
||||
|
||||
PRINTF_STR_FIELD(src_int);
|
||||
PRINTF_STR_FIELD(dst_int);
|
||||
PRINTF_STR_FIELD(from);
|
||||
PRINTF_STR_FIELD(to);
|
||||
PRINTF_STR_FIELD(msgid);
|
||||
PRINTF_STR_FIELD(mmsc_id);
|
||||
PRINTF_STR_FIELD(msgtype);
|
||||
PRINTF_STR_FIELD(prio);
|
||||
PRINTF_STR_FIELD(mclass);
|
||||
PRINTF_STR_FIELD(status);
|
||||
|
||||
fprintf(cdr_file, "\t%ld\t%s\t%s\n",
|
||||
(long)cdr->msg_size,
|
||||
cdr->dlr ? "Yes" : "No",
|
||||
cdr->rr ? "Yes" : "No");
|
||||
|
||||
fflush(cdr_file);
|
||||
|
||||
gw_free(cdr);
|
||||
}
|
||||
hmon->unregister_thread("cdr_logger");
|
||||
}
|
||||
|
||||
static int cdr_module_init(char *settings)
|
||||
{
|
||||
cdr_file = fopen(settings, "a"); /* Settings is interpreted as a file name. */
|
||||
if (cdr_file) {
|
||||
req_list = gwlist_create();
|
||||
|
||||
gwlist_add_producer(req_list);
|
||||
|
||||
th_id = gwthread_create((void *)cdr_logger_func, NULL);
|
||||
return 0;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int module_fini(void)
|
||||
{
|
||||
gw_assert(req_list);
|
||||
gw_assert(cdr_file);
|
||||
|
||||
gwlist_remove_producer(req_list);
|
||||
|
||||
if (th_id >= 0)
|
||||
gwthread_join(th_id);
|
||||
gwlist_destroy(req_list, NULL); /* there shouldn't be any requests waiting */
|
||||
|
||||
if (cdr_file)
|
||||
fclose(cdr_file);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* utility function. */
|
||||
static void fill_cdr_struct(MmsBoxCdrStruct *cdr,
|
||||
time_t sdate, char *from, char *to, char *msgid,
|
||||
char *mmsc_id, char *src_int, char *dst_int,
|
||||
#if 0
|
||||
char *src_ip, char *dst_ip,
|
||||
#endif
|
||||
unsigned long msg_size,
|
||||
char *msgtype, char *prio, char *mclass,
|
||||
char *status,
|
||||
int dlr, int rr)
|
||||
{
|
||||
memset(cdr, 0, sizeof cdr[0]);
|
||||
|
||||
cdr->sdate = sdate;
|
||||
|
||||
#define COPY_CDR_FIELD(fld) if (fld) strncpy(cdr->fld, fld, sizeof cdr->fld)
|
||||
|
||||
COPY_CDR_FIELD(from);
|
||||
COPY_CDR_FIELD(to);
|
||||
COPY_CDR_FIELD(msgid);
|
||||
COPY_CDR_FIELD(mmsc_id);
|
||||
COPY_CDR_FIELD(src_int);
|
||||
COPY_CDR_FIELD(dst_int);
|
||||
COPY_CDR_FIELD(msgtype);
|
||||
COPY_CDR_FIELD(prio);
|
||||
COPY_CDR_FIELD(mclass);
|
||||
COPY_CDR_FIELD(status);
|
||||
|
||||
cdr->dlr = dlr;
|
||||
cdr->rr = rr;
|
||||
cdr->msg_size = msg_size;
|
||||
}
|
||||
|
||||
static int cdr_module_logcdr(time_t sdate, char *from, char *to, char *msgid,
|
||||
char *mmsc_id, char *src_int, char *dst_int,
|
||||
#if 0
|
||||
char *src_ip, char *dst_ip,
|
||||
#endif
|
||||
unsigned long msg_size,
|
||||
char *msgtype, char *prio, char *mclass,
|
||||
char *status,
|
||||
int dlr, int rr)
|
||||
{
|
||||
MmsBoxCdrStruct *xcdr = gw_malloc(sizeof xcdr[0]);
|
||||
|
||||
gw_assert(req_list);
|
||||
|
||||
|
||||
fill_cdr_struct(xcdr, sdate, from, to, msgid, mmsc_id, src_int, dst_int,
|
||||
#if 0
|
||||
src_ip, dst_ip,
|
||||
#endif
|
||||
msg_size, msgtype, prio, mclass, status, dlr, rr);
|
||||
|
||||
gwlist_produce(req_list, xcdr);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
MmsBoxCdrFuncStruct mmsbox_cdrfuncs = {
|
||||
cdr_module_init,
|
||||
cdr_module_logcdr,
|
||||
module_fini
|
||||
};
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* Mbuni billing integration interface
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
|
||||
#ifndef __MMSBOX_CDR_INCLUDED__
|
||||
#define __MMSBOX_CDR_INCLUDED__
|
||||
|
||||
|
||||
#include <time.h>
|
||||
#include "gwlib/gwlib.h"
|
||||
|
||||
/* MMSBOX CDR module. This file provides prototypes for all CDR functions.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
typedef struct MmsBoxCdrFuncStruct {
|
||||
/* This function is called once to initialise the module. Return 0 on success */
|
||||
int (*init)(char *settings);
|
||||
|
||||
/* This function logs a cdr to wherever it is logging to. */
|
||||
int (*logcdr)(time_t sdate, char *from, char *to, char *msgid,
|
||||
char *mmsc_id, char *src_int, char *dst_int,
|
||||
#if 0
|
||||
char *src_ip, char *dst_ip,
|
||||
#endif
|
||||
unsigned long msg_size,
|
||||
char *msgtype, char *prio, char *mclass,
|
||||
char *status,
|
||||
int dlr, int rr);
|
||||
|
||||
int (*cleanup)(void);
|
||||
} MmsBoxCdrFuncStruct;
|
||||
|
||||
extern MmsBoxCdrFuncStruct mmsbox_cdrfuncs; /* The module must expose a symbol 'cdr_funcs' */
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* MMSBOX CFG: MMC configuration and misc. functions
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -13,38 +13,137 @@
|
|||
#ifndef __MMSBOX_CFG_INCLUDED__
|
||||
#define __MMSBOX_CFG_INCLUDED__
|
||||
#include "mms_util.h"
|
||||
#include "mmsbox_mt_filter.h"
|
||||
#include "mms_queue.h"
|
||||
#include "mmsbox_resolve.h"
|
||||
|
||||
#include "mmsbox_mmsc.h"
|
||||
#include "mmsbox_cdr.h"
|
||||
#include "mms_cfg.h"
|
||||
|
||||
/* Alarm callback mechanism */
|
||||
enum MmsBoxAlarms {
|
||||
MMSBOX_ALARM_HTTP_DOWN = 0,
|
||||
MMSBOX_ALARM_FILE_WRITE_ERROR,
|
||||
MMSBOX_ALARM_SOCKET_CONNECT_FAILED,
|
||||
MMSBOX_ALARM_QUEUE_WRITE_ERROR,
|
||||
MMSBOX_ALARM_STORAGE_API_ERROR,
|
||||
MMSBOX_ALARM_MM7_PARSING_FAILURE,
|
||||
MMSBOX_ALARM_MM7_NON_200_RESULT,
|
||||
MMSBOX_ALARM_RETRIEVE_MMS_ERROR,
|
||||
MMSBOX_ALARM_MM4_PARSING_FAILURE,
|
||||
MMSBOX_ALARM_MM1_ADDRESS_RESOLUTION_ERROR,
|
||||
MMSBOX_ALARM_MAX_ALARM /* Must be last one */
|
||||
};
|
||||
|
||||
typedef struct MmscGrp {
|
||||
Octstr *id; /* MMSC id (for logging). */
|
||||
Octstr *group_id; /* GROUP MMSC id (used for qf). */
|
||||
Octstr *vasp_id; /* vasp id for SOAP mmsc */
|
||||
Octstr *mmsc_url; /* URL at which MMSC can be reached. */
|
||||
struct {
|
||||
Octstr *user, *pass;
|
||||
Octstr *allow_ip;
|
||||
Octstr *deny_ip;
|
||||
long port;
|
||||
int ssl;
|
||||
} incoming; /* user, pass, port (and whether SSL) that MMSC uses to connect to us. */
|
||||
Octstr *allowed_prefix, *denied_prefix;
|
||||
enum {UNKNOWN_MMSC, SOAP_MMSC, EAIF_MMSC} type; /* type of connection. */
|
||||
long throughput; /* Max send rate. */
|
||||
Octstr *allowed_sender_prefix, *denied_sender_prefix;
|
||||
Octstr *carrier_id_header; /* http header that has carrier id */
|
||||
enum {UNKNOWN_MMSC = -1, CUSTOM_MMSC, SOAP_MMSC, EAIF_MMSC, MM4_MMSC, HTTP_MMSC, MM1_MMSC} type; /* type of connection. */
|
||||
double throughput; /* Max send rate. */
|
||||
int allow_adaptations; /* turns ON/OFF allow-adaptations in MM7 SOAP XML */
|
||||
long threadid; /* handler thread. */
|
||||
|
||||
int reroute; /* whether messages from this mmsc are re-routed outwards. */
|
||||
Octstr *reroute_mmsc_id;
|
||||
int no_senderaddress; /* used by SOAP interface: Don't add a sender address. */
|
||||
int reroute_mod_subject; /* Set to true if we'll change subject line on reroute. */
|
||||
MM7Version_t ver; /* supported MM7/SOAP version. */
|
||||
int use_mt_filter; /* whether to use MT filter on this connection. */
|
||||
Mutex *mutex;
|
||||
|
||||
Octstr *default_vasid; /* default vasid for mm7/soap */
|
||||
|
||||
MmsBoxMmscFuncs *fns; /* pointer to functions for handling this mmsc connection type */
|
||||
Octstr *settings; /* settings for the above module. */
|
||||
void *data; /* data for above module. */
|
||||
int started; /* Whether it is active */
|
||||
unsigned long mt_pdus; /* number of MT PDUs since start. */
|
||||
unsigned long mo_pdus; /* number of MO PDUs since start. */
|
||||
unsigned long mt_errors; /* number of MT errors since start */
|
||||
unsigned long mo_errors; /* number of MO errors since start */
|
||||
|
||||
time_t last_pdu; /* time of last PDU */
|
||||
time_t start_time; /* when was this connection started */
|
||||
|
||||
time_t last_alarm[MMSBOX_ALARM_MAX_ALARM];
|
||||
int use_count; /* use counter. */
|
||||
time_t delete_after; /* used to control deletion of object -- not very clean, but... */
|
||||
|
||||
long max_pkt_size;
|
||||
|
||||
int strip_domain; /* MM4 only */
|
||||
|
||||
long max_recipients; /* Max recpients per transaction */
|
||||
|
||||
List *strip_prefixes; /* List of prefixes to be stripped before sending out*/
|
||||
|
||||
List *retry_statuses; /* List of HTTP/MM7 statuses we do retry on, MM7 statuses are checked only on HTTP 200 - they do not overlap*/
|
||||
|
||||
struct MM1Info_t { /* Stuff used only by the MM1 MMSC */
|
||||
Octstr *proxy; /* Proxy within the operator network, form of host:port */
|
||||
Octstr *gprs_on; /* Command to start GPRS link. Must not exit. */
|
||||
Octstr *gprs_off; /* Command to stop GPRS link. */
|
||||
Octstr *gprs_pid; /* command to call to get PID of GPRS for stopping GPRS link (i.e. pppd). */
|
||||
Octstr *smsc_on; /* command to start smsc connection */
|
||||
Octstr *smsc_off; /* commadn to stop smsc connection */
|
||||
Octstr *msisdn; /* Our msisdn */
|
||||
Octstr *ua; /* User agent string, if given */
|
||||
List *requests; /* list of requests. */
|
||||
long d_tid;/* thread ID for mm1 handler. */
|
||||
|
||||
int sender_alive;
|
||||
} mm1;
|
||||
} MmscGrp;
|
||||
|
||||
#define DEFAULT_MAX_PKT_SIZE 1024*1024
|
||||
|
||||
#define MMSBOX_MMSC_MARK_INUSE(mmc) do {\
|
||||
mutex_lock((mmc)->mutex); \
|
||||
(mmc)->use_count++; \
|
||||
mutex_unlock(mmc->mutex); \
|
||||
} while (0)
|
||||
|
||||
#define MMSBOX_MMSC_UNMARK_INUSE(mmc) do {\
|
||||
mutex_lock((mmc)->mutex); \
|
||||
(mmc)->use_count--; \
|
||||
mutex_unlock(mmc->mutex); \
|
||||
} while (0)
|
||||
|
||||
|
||||
typedef struct MmsServiceUrlParam {
|
||||
Octstr *name;
|
||||
enum {NO_PART, AUDIO_PART, IMAGE_PART, VIDEO_PART,
|
||||
TEXT_PART, SMIL_PART , OTHER_PART,
|
||||
ANY_PART, WHOLE_BINARY} type;
|
||||
ANY_PART, WHOLE_BINARY, KEYWORD_PART,
|
||||
|
||||
RCPT_PART, FROM_PART, SUBJECT_PART, MMSCID_PART,
|
||||
MSGTYPE_PART, MSGID_PART} type;
|
||||
Octstr *value; /* for generic value (type == NO_PART),
|
||||
* or for value that follows spec (e.g. %Tisatest is allowed) */
|
||||
* or for value that follows spec (e.g. %Tisatest is allowed)
|
||||
*/
|
||||
} MmsServiceUrlParam;
|
||||
|
||||
typedef struct MmsService {
|
||||
Octstr *name; /* name of service. */
|
||||
int isdefault;
|
||||
int omitempty;
|
||||
int noreply;
|
||||
int accept_x_headers;
|
||||
List *passthro_headers;
|
||||
|
||||
int assume_plain_text;
|
||||
List *keywords; /* List of keywords matched. */
|
||||
enum {TRANS_TYPE_GET_URL, TRANS_TYPE_POST_URL, TRANS_TYPE_FILE, TRANS_TYPE_EXEC,
|
||||
|
@ -55,21 +154,27 @@ typedef struct MmsService {
|
|||
Octstr *faked_sender;
|
||||
List *allowed_mmscs; /* List of MMSCs allowed to access this service (by ID). */
|
||||
List *denied_mmscs; /* List of MMSCs allowed to access this service (by ID). */
|
||||
Octstr *service_code; /* Service code (MM7/SOAP only) */
|
||||
|
||||
Octstr *allowed_receiver_prefix, *denied_receiver_prefix;
|
||||
Octstr *special_header; /* To be added to each content element. */
|
||||
} MmsService;
|
||||
|
||||
typedef struct SendMmsUser {
|
||||
Octstr *user, *pass;
|
||||
Octstr *faked_sender;
|
||||
Octstr *dlr_url, *rr_url;
|
||||
Octstr *dlr_url, *rr_url, *mmsc;
|
||||
} SendMmsUser;
|
||||
|
||||
/* Basic settings for the mmsbox. */
|
||||
extern List *sendmms_users; /* list of SendMmsUser structs */
|
||||
extern List *mms_services; /* list of MMS Services */
|
||||
extern List *mmscs; /* MMSC list. Perhaps turn into a Dict instead? */
|
||||
extern Octstr *incoming_qdir, *outgoing_qdir, *dlr_dir;
|
||||
extern Octstr *unified_prefix;
|
||||
extern long mmsbox_maxsendattempts, mmsbox_send_back_off;
|
||||
extern Octstr *sendmail_cmd;
|
||||
extern Octstr *myhostname;
|
||||
extern List *strip_prefixes;
|
||||
extern long svc_maxsendattempts, maxsendattempts, mmsbox_send_back_off, default_msgexpiry, max_msgexpiry;
|
||||
extern long maxthreads;
|
||||
extern double queue_interval;
|
||||
extern struct SendMmsPortInfo {
|
||||
|
@ -78,6 +183,117 @@ extern struct SendMmsPortInfo {
|
|||
Octstr *deny_ip;
|
||||
} sendmms_port;
|
||||
|
||||
extern struct MmsBoxMTfilter *mt_filter;
|
||||
extern MmsQueueHandlerFuncs *qfs;
|
||||
extern int mt_multipart;
|
||||
|
||||
extern int mms_load_mmsbox_settings(mCfg *cfg, gwthread_func_t *mmsc_handler_func);
|
||||
extern MmsBoxResolverFuncStruct *rfs; /* resolver functions. */
|
||||
extern void *rfs_data;
|
||||
extern Octstr *rfs_settings;
|
||||
|
||||
extern struct SMTPRelay {
|
||||
Octstr *host;
|
||||
int port;
|
||||
} smtp_relay;
|
||||
|
||||
extern MmsBoxCdrFuncStruct *cdrfs;
|
||||
|
||||
|
||||
extern struct MmsBoxHealthMonitors {
|
||||
void (*register_thread)( char *name); /* Called by each thread to register itself with the health monitor */
|
||||
void (*unregister_thread)(char *name); /* Called by each thread to unregister itself with the health monitor */
|
||||
void (*register_port)(short port); /* Called to register each port on which we listen */
|
||||
void (*unregister_port)(short port); /* Called to unregister each port on which we listen */
|
||||
} *hmon; /* This should be set if you want to do any thread and port monitoring */
|
||||
|
||||
/* mmsbox_event_cb: Called with each mmsc event.
|
||||
* mmsc - mmsc ID
|
||||
* mm7_pkt_type - MM7 packet type (using MM7/SOAP codes)
|
||||
* mm7_ver - value for SOAP or EAIF only
|
||||
* status - 0 for Ok, -1 if failed (e.g. for submitack
|
||||
* msg_size - size of mms
|
||||
* num_retries - number of retries so far
|
||||
* from - sender (can be NULL)
|
||||
* to - recipient (can be NULL)
|
||||
* transid - transaction ID
|
||||
* message_id - Message ID (for submitack, deliverreq, deliveryreport or readreport)
|
||||
* hdrs - List of envelope headers
|
||||
* value - value associated with pkt type: e.g. for deliveryreport, report type
|
||||
*/
|
||||
extern void (*mmsbox_event_cb)(Octstr *mmsc, int mm7_pkt_type,
|
||||
int is_mm4,
|
||||
Octstr *mm7_ver, int status,
|
||||
int msg_size, int num_retries,
|
||||
Octstr *from, Octstr *to, Octstr *message_id, Octstr *transid,
|
||||
List *hdrs, Octstr *value);
|
||||
|
||||
/* mmsbox_alarm_cb: Called when an alarm is raised or cleared
|
||||
* mmsc - MMSC ID
|
||||
* alarm - alarm type
|
||||
* alarm_state - 0 = alarm cleared, 1 = alarm raised
|
||||
* lev = severity level, 1 = warning, 2 = minor, 3 = major, 4+ = critical
|
||||
*/
|
||||
extern void (*mmsbox_alarm_cb)(Octstr*mmsc, enum MmsBoxAlarms alarm, int alarm_state, int lev);
|
||||
|
||||
#define MMSC_ISSUE_ALARM(mmc,alarm,lev) do { \
|
||||
MmscGrp *_mmc = (mmc); \
|
||||
if (_mmc) \
|
||||
_mmc->last_alarm[(alarm)] = time(NULL); \
|
||||
mmsbox_alarm_cb(_mmc ? _mmc->id : NULL, (alarm), 1, (lev)); \
|
||||
} while (0)
|
||||
#define MMSC_CLEAR_ALARM(mmc,alarm) do { \
|
||||
MmscGrp *_mmc = (mmc); \
|
||||
if (_mmc && _mmc->last_alarm[(alarm)] > 0 ) { \
|
||||
mmsbox_alarm_cb(_mmc->id, (alarm), 0, 0); \
|
||||
_mmc->last_alarm[(alarm)] = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
extern int mms_load_mmsbox_settings(struct mCfgImpFuncs *cfg_funcs, Octstr *init,
|
||||
gwthread_func_t *mmsc_handler_func,
|
||||
MmsQueueHandlerFuncs *,
|
||||
MmsEventLoggerFuncs *);
|
||||
extern void mmsbox_settings_cleanup(void);
|
||||
extern MmscGrp *get_handler_mmc(Octstr *id, Octstr *to, Octstr *from);
|
||||
extern void return_mmsc_conn(MmscGrp *m);
|
||||
|
||||
extern Octstr *get_mmsbox_queue_dir(Octstr *from, List *to, MmscGrp *m, Octstr **mmc_id);
|
||||
#if 0
|
||||
MmscGrp *start_mmsc_from_conf(mCfg *cfg, mCfgGrp *x, List *errors, List *warnings);
|
||||
#endif
|
||||
int mmsbox_stop_mmsc(Octstr *mmc);
|
||||
|
||||
int mmsbox_start_mmsc(Octstr *mmc_id);
|
||||
|
||||
MmscGrp *mmsbox_get_mmsc_by_url(Octstr *mmc_url);
|
||||
void mmsbox_stop_all_mmsc_conn(void);
|
||||
typedef struct MmsBoxHTTPClientInfo {
|
||||
HTTPClient *client;
|
||||
Octstr *ua;
|
||||
Octstr *ip;
|
||||
List *headers;
|
||||
Octstr *url;
|
||||
Octstr *body;
|
||||
List *cgivars;
|
||||
MmscGrp *m;
|
||||
} MmsBoxHTTPClientInfo;
|
||||
void free_mmsbox_http_clientInfo(MmsBoxHTTPClientInfo *h, int freeh);
|
||||
/* parse service url params in list of MmsServiceUrlParm structs */
|
||||
List *parse_service_url_params(Octstr *input, Octstr *id);
|
||||
|
||||
#define add_all_matching_parts(a,b,c,d,e,f,g) add_all_matching_parts_real((a),(b),(c),(d),(e),(f),(g),NULL,NULL,NULL,NULL,-1,NULL)
|
||||
|
||||
void add_all_matching_parts_real(MIMEEntity *plist, MmsServiceUrlParam *pm,
|
||||
Octstr *keyword,
|
||||
MIMEEntity *me,
|
||||
MmsMsg *msg, int lev, int count,
|
||||
Octstr *from, List *lto, char *subject,
|
||||
char *mmsc_id, int mtype, Octstr *msgid);
|
||||
|
||||
MIMEEntity *mmsbox_add_service_url_params(List *params,
|
||||
Octstr *from, List *lto, char *subject,
|
||||
char *mmsc_id, int mtype, Octstr *msgid,
|
||||
MmsMsg *m);
|
||||
|
||||
extern volatile sig_atomic_t rstop;
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* MMSBOX Custom MMSC types: MMC function definitions
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#ifndef __MMSBOX_MMSC_CFG_INCLUDED__
|
||||
#define __MMSBOX_MMSC_CFG_INCLUDED__
|
||||
#include "mms_util.h"
|
||||
#include "mms_queue.h"
|
||||
struct MmscGrp; /* so we compile. */
|
||||
typedef struct MmsBoxMmscFuncs {
|
||||
/* start_conn: called once with the module settings, ID of the connection
|
||||
* and a pointer where to store module specific info.
|
||||
* should return 0 on success, -1 on error.
|
||||
*/
|
||||
int (*start_conn)(struct MmscGrp *mmc, MmsQueueHandlerFuncs *qfs,
|
||||
Octstr *unified_prefix, List *strip_prefixes,
|
||||
void **data);
|
||||
|
||||
/* stop_conn: Called to stop the MMC connection. */
|
||||
int (*stop_conn)(void *data);
|
||||
|
||||
/* send_msg: called to send a message. Should msg ID if any. On error,
|
||||
* retry can be set to 1 for sending to be retried later.
|
||||
* Should set err to the error message (if any).
|
||||
*/
|
||||
Octstr *(*send_msg)(void *data, Octstr *from, Octstr *to,
|
||||
Octstr *transid,
|
||||
Octstr *linkedid, char *vasid, Octstr *service_code,
|
||||
MmsMsg *m, List *hdrs, Octstr **err, int *retry);
|
||||
|
||||
} MmsBoxMmscFuncs;
|
||||
|
||||
extern MmsBoxMmscFuncs mmsc_funcs; /* lib should expose this structure. */
|
||||
#endif
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* Empty wrapper library
|
||||
*
|
||||
* Copyright (C) 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is proprietary software, refer to licence holder for details
|
||||
*/
|
||||
#include <sys/file.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/wait.h>
|
||||
#include <errno.h>
|
||||
#include <dlfcn.h>
|
||||
#include <strings.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include "mmsbox_mt_filter.h"
|
||||
|
||||
static int myinit(Octstr *mmc_url, Octstr *mmc_id, Octstr *startup_params)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int myfilter(MIMEEntity **msg, Octstr *loc_url, Octstr *mmc_id)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void myclose(Octstr *mmc_id)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
struct MmsBoxMTfilter mmsbox_mt_filter = {
|
||||
.name = "Empty Wrapper",
|
||||
.init = myinit,
|
||||
.filter = myfilter,
|
||||
.destroy = myclose
|
||||
};
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* MMSBOX MT MMS filter: Optional filter for MT messages
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#ifndef __MMSMT_FILTER_INCLUDED__
|
||||
#define __MMSMT_FILTER_INCLUDED__
|
||||
#include "mms_util.h"
|
||||
|
||||
struct MmsBoxMTfilter {
|
||||
/* name of filter. */
|
||||
char *name;
|
||||
/* Init: called once for each mmc to determine if to use filter on MT MMS via the particular MMC. Returns 1
|
||||
* on success, error otherwise
|
||||
*/
|
||||
int (*init)(Octstr *mmc_url, Octstr *mmc_id, Octstr *startup_params);
|
||||
|
||||
/* filter: Filter/transform the message. Return 0 on success. May modify the message itself of course */
|
||||
int (*filter)(MIMEEntity **msg, Octstr *loc_url, Octstr *mmc_id);
|
||||
|
||||
/* destroy this mmc's settings in filter. */
|
||||
void (*destroy)(Octstr *mmc_id);
|
||||
};
|
||||
|
||||
/* Each module must export this symbol, a pointer to the structure.
|
||||
* WARNING: Ensure your module is thread-safe
|
||||
*/
|
||||
extern struct MmsBoxMTfilter mmsbox_mt_filter;
|
||||
#endif
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* Resolving MSISDNs to local/remote MMSBox MMSC - interface
|
||||
*
|
||||
* Copyright (C) 2003 - 2007, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "mmsbox_resolve.h"
|
||||
#include "mmsbox_cfg.h"
|
||||
|
||||
static void *_resolvermodule_init(char *settings)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _resolvermodule_fini(void *module_data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Octstr *_resolve(Octstr * pfrom, Octstr *pto, char *in_mmsc,
|
||||
void *module_data, void *settings_p)
|
||||
{
|
||||
/* route normally to mms-service. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The function itself. */
|
||||
MmsBoxResolverFuncStruct mmsbox_resolvefuncs = {
|
||||
_resolvermodule_init,
|
||||
_resolve,
|
||||
_resolvermodule_fini
|
||||
};
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* Resolving MSISDNs to local/remote MMSBox MMSC - interface
|
||||
*
|
||||
* Copyright (C) 2003 - 2007, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#ifndef __MMSBOX_RESOLVE_INCLUDED__
|
||||
#define __MMSBOX_RESOLVE_INCLUDED__
|
||||
|
||||
#include <time.h>
|
||||
#include "gwlib/gwlib.h"
|
||||
|
||||
/* Resolver module. This file provides prototypes for all resolver functions.
|
||||
* the module is loaded once and _init is called once at load.
|
||||
* _resolve is called for each incoming message to determine how to route it.
|
||||
*/
|
||||
|
||||
typedef struct MmsBoxResolverFuncStruct {
|
||||
/* This function is called once to initialise the resolver module. Return a generic object,
|
||||
* which is passed with each resolution request..
|
||||
*/
|
||||
void *(*mmsbox_resolvermodule_init)(char *settings);
|
||||
|
||||
/* Looks up the sender and receiver msisdns and returns the ID of the MMC connection through which
|
||||
* the received message should be sent.
|
||||
* Note: This function may modify sender and/or receive to match prefered usage.
|
||||
* Return NULL or the empty string to send the message to a service (normal behavior)
|
||||
*/
|
||||
Octstr *(*mmsbox_resolve)(Octstr *pfrom, Octstr *pto, char *from_mmsc,
|
||||
void *module_data, void *settings);
|
||||
|
||||
int (*mmsbox_resolvermodule_fini)(void *module_data);
|
||||
} MmsBoxResolverFuncStruct;
|
||||
|
||||
extern MmsBoxResolverFuncStruct mmsbox_resolvefuncs; /* The module must expose this symbol. */
|
||||
|
||||
#endif
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* Resolving MSISDNs to local/remote MMSCs - calling shell scripts
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "mmsbox_resolve.h"
|
||||
#include "mms_util.h"
|
||||
|
||||
static Octstr *script = NULL;
|
||||
|
||||
static void *_shell_resolvermodule_init(char *settings)
|
||||
{
|
||||
script = octstr_imm(settings);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _shell_resolvermodule_fini(void *module_data)
|
||||
{
|
||||
octstr_destroy(script);
|
||||
script = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static Octstr *_shell_resolve(Octstr *pfrom, Octstr *pto, char *in_mmc, void *module_data, void *settings_p)
|
||||
{
|
||||
Octstr *s;
|
||||
FILE *fp;
|
||||
char buf[4096];
|
||||
|
||||
if (script == NULL || octstr_len(script) == 0)
|
||||
return 0;
|
||||
|
||||
s = octstr_format("%s '%s' '%s' '%s'",
|
||||
octstr_get_cstr(script), octstr_get_cstr(pfrom), octstr_get_cstr(pto),
|
||||
in_mmc);
|
||||
|
||||
mms_info(0, "mmsbox", NULL, "Preparing to call resolver as: %s", octstr_get_cstr(s));
|
||||
fp = popen(octstr_get_cstr(s), "r");
|
||||
octstr_destroy(s);
|
||||
|
||||
fgets(buf, sizeof buf, fp);
|
||||
s = octstr_create(buf);
|
||||
octstr_strip_crlfs(s);
|
||||
|
||||
pclose(fp);
|
||||
|
||||
mms_info(0, "mmsbox", NULL, "Resolver returned: %s", octstr_get_cstr(s));
|
||||
if (octstr_len(s) == 0) {
|
||||
octstr_destroy(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* The function struct itself. */
|
||||
MmsBoxResolverFuncStruct mmsbox_resolvefuncs_shell = {
|
||||
_shell_resolvermodule_init,
|
||||
_shell_resolve,
|
||||
_shell_resolvermodule_fini
|
||||
};
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* Resolving MSISDNs to local/remote MMSCs - interface (shell)
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#ifndef __MMSBOX_RESOLVE_SHELL_INCLUDED__
|
||||
#define __MMSBOX_RESOLVE_SHELL_INCLUDED__
|
||||
|
||||
#include <time.h>
|
||||
#include "gwlib/gwlib.h"
|
||||
#include "mmsbox_resolve.h"
|
||||
|
||||
extern MmsBoxResolverFuncStruct mmsbox_resolvefuncs_shell;
|
||||
|
||||
#endif
|
|
@ -1,19 +1,13 @@
|
|||
libmms = $(top_builddir)/mmlib/libmms.la
|
||||
libmmsc = libmmsc.la
|
||||
libmmsc = libmmsc.a
|
||||
|
||||
noinst_LTLIBRARIES = libmmsc.la
|
||||
libmmsc_la_SOURCES = mmsc_cfg.c mms_detokenize.c mms_resolve.c mms_billing.c
|
||||
noinst_LIBRARIES = libmmsc.a
|
||||
libmmsc_a_SOURCES = mmsc_cfg.c mms_detokenize.c mms_resolve.c mms_billing.c mms_detokenize_shell.c mms_resolve_shell.c mms_billing_shell.c mmsc_mm5.c
|
||||
|
||||
bin_PROGRAMS = mmsrelay mmsproxy mmsfromemail mmssend
|
||||
mmsrelay_SOURCES = mmsglobalsender.c mmsmobilesender.c mmsrelay.c
|
||||
mmsrelay_LDADD = $(libmmsc) $(libmms)
|
||||
mmsproxy_LDADD = $(libmmsc) $(libmms)
|
||||
bin_PROGRAMS = mmsc mmsfromemail mmssend
|
||||
mmsc_SOURCES = mmsc.c mmsglobalsender.c mmsmobilesender.c mmsrelay.c mmsproxy.c
|
||||
mmsc_LDADD = $(libmmsc) $(libmms)
|
||||
mmsfromemail_LDADD = $(libmmsc) $(libmms)
|
||||
mmssend_LDADD = $(libmmsc) $(libmms)
|
||||
|
||||
pkglib_LTLIBRARIES = libmmsc_billing_shell.la libmmsc_resolve_shell.la libmmsc_detokenize_shell.la
|
||||
libmmsc_billing_shell_la_SOURCES = mms_billing_shell.c
|
||||
libmmsc_resolve_shell_la_SOURCES = mms_resolve_shell.c
|
||||
libmmsc_detokenize_shell_la_SOURCES = mms_detokenize_shell.c
|
||||
|
||||
EXTRA_DIST = mms_billing.h mmsc_cfg.h mms_detokenize.h mmsrelay.h mms_resolve.h
|
||||
EXTRA_DIST = mmsc.h mms_billing.h mms_detokenize_shell.h mms_billing_shell.h mms_resolve_shell.h mmsc_cfg.h mms_detokenize.h mms_resolve.h mmsc_mm5.h
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Mbuni sample billing handler module
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -33,7 +33,7 @@ static int mms_billingmodule_fini(void *module_data)
|
|||
return module_data ? fclose(module_data) : -1;
|
||||
}
|
||||
|
||||
static int mms_billmsg(Octstr *from, List *to, unsigned long msg_size, Octstr *vaspid, void *module_data)
|
||||
static int mms_billmsg(Octstr *from, List *to, unsigned long msg_size, Octstr *vaspid, Octstr *msgid, void *module_data)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -46,8 +46,11 @@ static int mms_logcdr(MmsCdrStruct *cdr)
|
|||
|
||||
localtime_r(&cdr->sdate, &tm);
|
||||
gw_strftime(buf, sizeof buf, "%Y-%m-%d %H:%M:%S", &tm);
|
||||
fprintf(cdr->module_data, "%s\t%.128s\t%.256s\t%.256s\t%ld\n",
|
||||
buf, cdr->from, cdr->to, cdr->msgid, cdr->msg_size);
|
||||
fprintf(cdr->module_data, "%s\t%.128s\t%.128s\t%.128s\t%.256s\t%.256s\t%ld\n",
|
||||
buf,
|
||||
cdr->src_interface[0] ? cdr->src_interface : "MM2",
|
||||
cdr->dst_interface[0] ? cdr->dst_interface : "MM2",
|
||||
cdr->from, cdr->to, cdr->msgid, cdr->msg_size);
|
||||
fflush(cdr->module_data);
|
||||
} else
|
||||
return -1;
|
||||
|
@ -55,6 +58,26 @@ static int mms_logcdr(MmsCdrStruct *cdr)
|
|||
return 0;
|
||||
}
|
||||
|
||||
MmsCdrStruct *make_cdr_struct(void *module_data, time_t sdate, char *from, char *to, char *msgid,
|
||||
char *vaspid, char *src_int, char *dst_int, unsigned long msg_size)
|
||||
{
|
||||
|
||||
MmsCdrStruct *cdr = gw_malloc(sizeof *cdr);
|
||||
|
||||
cdr->module_data = module_data;
|
||||
cdr->sdate = sdate;
|
||||
strncpy(cdr->from, from ? from : "", sizeof cdr->from);
|
||||
strncpy(cdr->to, to ? to : "", sizeof cdr->to);
|
||||
strncpy(cdr->msgid, msgid ? msgid : "", sizeof cdr->msgid);
|
||||
strncpy(cdr->vaspid, vaspid ? vaspid : "", sizeof cdr->vaspid);
|
||||
strncpy(cdr->src_interface, src_int ? src_int : "MM2", sizeof cdr->src_interface);
|
||||
strncpy(cdr->dst_interface, dst_int ? dst_int : "MM2", sizeof cdr->dst_interface);
|
||||
|
||||
cdr->msg_size = msg_size;
|
||||
|
||||
return cdr;
|
||||
}
|
||||
|
||||
/* The function itself. */
|
||||
MmsBillingFuncStruct mms_billfuncs = {
|
||||
mms_billingmodule_init,
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Mbuni billing integration interface
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -31,6 +31,8 @@ typedef struct MmsCdrStruct {
|
|||
char to[CBUFSIZE];
|
||||
char msgid[CBUFSIZE];
|
||||
char vaspid[CBUFSIZE];
|
||||
char src_interface[CBUFSIZE];
|
||||
char dst_interface[CBUFSIZE];
|
||||
unsigned long msg_size;
|
||||
} MmsCdrStruct;
|
||||
|
||||
|
@ -47,11 +49,14 @@ typedef struct MmsBillingFuncStruct {
|
|||
/* Bills a message. Returns >= 0 if billed ok, -1 if message should be rejected,
|
||||
* -2 on internal (temporary) error.
|
||||
*/
|
||||
int (*mms_billmsg)(Octstr *from, List *to, unsigned long msg_size, Octstr *vaspid, void *module_data);
|
||||
int (*mms_billmsg)(Octstr *from, List *to, unsigned long msg_size, Octstr *vaspid, Octstr *msgid, void *module_data);
|
||||
|
||||
int (*mms_billingmodule_fini)(void *module_data);
|
||||
} MmsBillingFuncStruct;
|
||||
|
||||
extern MmsBillingFuncStruct mms_billfuncs; /* The module must expose this symbol. */
|
||||
|
||||
/* utility function. */
|
||||
MmsCdrStruct *make_cdr_struct(void *module_data, time_t sdate, char *from, char *to, char *msgid,
|
||||
char *vaspid, char *src_int, char *dst_int, unsigned long msg_size);
|
||||
#endif
|
||||
|
|
|
@ -12,6 +12,13 @@
|
|||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#ifndef DARWIN
|
||||
#ifndef FREEBSD
|
||||
#include <wait.h>
|
||||
#endif
|
||||
#endif
|
||||
#include <sys/wait.h>
|
||||
|
||||
|
||||
#include "mms_billing.h"
|
||||
|
||||
|
@ -33,15 +40,16 @@ static int mms_billingmodule_fini(void *module_data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mms_billmsg(Octstr *from, List *to, unsigned long msg_size, Octstr *vaspid, void *module_data)
|
||||
static int mms_billmsg(Octstr *from, List *to, unsigned long msg_size, Octstr *vaspid, Octstr *msgid, void *module_data)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (script == NULL || octstr_len(script) == 0)
|
||||
return 0;
|
||||
for (i=0;i<list_len(to);i++) {
|
||||
for (i=0;i<gwlist_len(to);i++) {
|
||||
Octstr *s;
|
||||
s = octstr_format("%s '%s' '%s'", octstr_get_cstr(script), octstr_get_cstr(from), octstr_get_cstr(list_get(to, i)));
|
||||
s = octstr_format("%s '%s' '%s' '%S'", octstr_get_cstr(script), octstr_get_cstr(from),
|
||||
octstr_get_cstr(gwlist_get(to, i)), msgid);
|
||||
if (s) {
|
||||
int ret = system(octstr_get_cstr(s));
|
||||
octstr_destroy(s);
|
||||
|
@ -60,7 +68,7 @@ static int mms_logcdr(MmsCdrStruct *cdr)
|
|||
}
|
||||
|
||||
/* The function itself. */
|
||||
MmsBillingFuncStruct mms_billfuncs = {
|
||||
MmsBillingFuncStruct mms_billfuncs_shell = {
|
||||
mms_billingmodule_init,
|
||||
mms_logcdr,
|
||||
mms_billmsg,
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* Mbuni billing integration interface (shell)
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
|
||||
#ifndef __MMS_BILLING_SHELL_INCLUDED__
|
||||
#define __MMS_BILLING_SHELL_INCLUDED__
|
||||
|
||||
|
||||
#include <time.h>
|
||||
#include "gwlib/gwlib.h"
|
||||
#include "mms_billing.h"
|
||||
|
||||
extern MmsBillingFuncStruct mms_billfuncs_shell;
|
||||
|
||||
#endif
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Mbuni MSISDN mapper sample
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Mbuni MSISDN mapper interface
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
|
|
@ -21,7 +21,7 @@ Octstr *script;
|
|||
static int mms_detokenizer_init(char *settings)
|
||||
{
|
||||
script = octstr_create(settings);
|
||||
info(0, "Detokenizer script set to \"%s\"", settings);
|
||||
mms_info(0, "mms_detokenizer", NULL, "Detokenizer script set to \"%s\"", settings);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -35,17 +35,29 @@ static int mms_detokenizer_fini(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static Octstr *mms_detokenize(Octstr * token, Octstr *request_ip)
|
||||
static Octstr *mms_detokenize(Octstr *token, Octstr *request_ip)
|
||||
{
|
||||
Octstr *cmd = NULL, *msisdn = NULL;
|
||||
Octstr *tmp1, *tmp2;
|
||||
FILE *fp;
|
||||
char buf[4096];
|
||||
|
||||
if (script == NULL || octstr_len(script) == 0)
|
||||
return NULL;
|
||||
|
||||
cmd = octstr_format("%s '%s'", octstr_get_cstr(script), octstr_get_cstr(token));
|
||||
info(0, "Calling \"%s\"", octstr_get_cstr(cmd));
|
||||
tmp1 = octstr_duplicate(token ? token : octstr_imm("x"));
|
||||
tmp2 = octstr_duplicate(request_ip ? request_ip : octstr_imm("x"));
|
||||
|
||||
escape_shell_chars(tmp1);
|
||||
escape_shell_chars(tmp2);
|
||||
|
||||
cmd = octstr_format("%s %s %s",
|
||||
octstr_get_cstr(script),
|
||||
octstr_get_cstr(tmp1),
|
||||
octstr_get_cstr(tmp2));
|
||||
octstr_destroy(tmp1);
|
||||
octstr_destroy(tmp2);
|
||||
mms_info(0, "mms_detokenizer", NULL, "Calling \"%s\"", octstr_get_cstr(cmd));
|
||||
if ((fp = popen(octstr_get_cstr(cmd), "r"))) {
|
||||
if (fgets(buf, sizeof buf, fp) != NULL) {
|
||||
msisdn = octstr_create(buf);
|
||||
|
@ -53,7 +65,7 @@ static Octstr *mms_detokenize(Octstr * token, Octstr *request_ip)
|
|||
}
|
||||
pclose(fp);
|
||||
}
|
||||
info(0, "%s \"%s\", returned msisdn = %s",
|
||||
mms_info(0, "mms_detokenizer", NULL, "%s \"%s\", returned msisdn = %s",
|
||||
fp ? "Called" : "Failed to call",
|
||||
octstr_get_cstr(cmd),
|
||||
msisdn ? octstr_get_cstr(msisdn) : "null");
|
||||
|
@ -68,7 +80,7 @@ static Octstr *mms_gettoken(Octstr *msisdn)
|
|||
}
|
||||
|
||||
/* The function itself. */
|
||||
MmsDetokenizerFuncStruct mms_detokenizefuncs = {
|
||||
MmsDetokenizerFuncStruct mms_detokenizefuncs_shell = {
|
||||
mms_detokenizer_init,
|
||||
mms_detokenize,
|
||||
mms_gettoken,
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* Mbuni MSISDN mapper interface (shell)
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#ifndef __MMS_DETOKENIZE_SHELL_INCLUDED__
|
||||
#define __MMS_DETOKENIZE_SHELL_INCLUDED__
|
||||
|
||||
#include <time.h>
|
||||
#include "gwlib/gwlib.h"
|
||||
#include "mms_detokenize.h"
|
||||
|
||||
extern MmsDetokenizerFuncStruct mms_detokenizefuncs_shell;
|
||||
|
||||
#endif
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Resolving MSISDNs to local/remote MMSCs
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -25,7 +25,8 @@ static int mms_resolvermodule_fini(void *module_data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static Octstr *mms_resolve(Octstr * phonenum, void *module_data, void *settings_p, void *proxyrelays_p)
|
||||
static Octstr *mms_resolve(Octstr * phonenum, char *src_int, char *src_id,
|
||||
void *module_data, void *settings_p, void *proxyrelays_p)
|
||||
{
|
||||
/* Most custom implementations of this library will probably just ignore the two last arguments,
|
||||
* but this one needs them
|
||||
|
@ -36,13 +37,13 @@ static Octstr *mms_resolve(Octstr * phonenum, void *module_data, void *settings_
|
|||
int j, m;
|
||||
|
||||
if (does_prefix_match(settings->local_prefix, phonenum)) {
|
||||
return settings->hostname;
|
||||
} else if (proxyrelays && list_len(proxyrelays) > 0) /* Step through proxies. */
|
||||
for (j = 0, m = list_len(proxyrelays); j < m; j++) {
|
||||
MmsProxyRelay *mp = list_get(proxyrelays, j);
|
||||
return settings->hostname ? octstr_duplicate(settings->hostname) : NULL;
|
||||
} else if (proxyrelays && gwlist_len(proxyrelays) > 0) /* Step through proxies. */
|
||||
for (j = 0, m = gwlist_len(proxyrelays); j < m; j++) {
|
||||
MmsProxyRelay *mp = gwlist_get(proxyrelays, j);
|
||||
if (does_prefix_match(mp->allowed_prefix, phonenum) &&
|
||||
!does_prefix_match(mp->denied_prefix, phonenum)) {
|
||||
return mp->host;
|
||||
return octstr_duplicate(mp->host);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Resolving MSISDNs to local/remote MMSCs - interface
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -33,9 +33,11 @@ typedef struct MmsResolverFuncStruct {
|
|||
*
|
||||
* Return NULL on error, otherwise an Octstr
|
||||
*/
|
||||
Octstr *(*mms_resolve)(Octstr * phonenum, void *module_data, void *settings, void *proxyrelays);
|
||||
Octstr *(*mms_resolve)(Octstr *phonenum, char *src_int, char *src_id,
|
||||
void *module_data, void *settings, void *proxyrelays);
|
||||
|
||||
int (*mms_resolvermodule_fini)(void *module_data);
|
||||
|
||||
} MmsResolverFuncStruct;
|
||||
|
||||
extern MmsResolverFuncStruct mms_resolvefuncs; /* The module must expose this symbol. */
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Resolving MSISDNs to local/remote MMSCs - calling shell scripts
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -28,7 +28,8 @@ static int mms_resolvermodule_fini(void *module_data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static Octstr *mms_resolve(Octstr * phonenum, void *module_data, void *settings_p, void *proxyrelays_p)
|
||||
static Octstr *mms_resolve(Octstr *phonenum, char *src_int, char *src_id,
|
||||
void *module_data, void *settings_p, void *proxyrelays_p)
|
||||
{
|
||||
Octstr *s;
|
||||
FILE *fp;
|
||||
|
@ -37,21 +38,28 @@ static Octstr *mms_resolve(Octstr * phonenum, void *module_data, void *settings_
|
|||
if (script == NULL || octstr_len(script) == 0)
|
||||
return 0;
|
||||
|
||||
s = octstr_format("%s '%s' ", octstr_get_cstr(phonenum));
|
||||
s = octstr_format("%s '%s' '%s' '%s'",
|
||||
octstr_get_cstr(script), octstr_get_cstr(phonenum) ,
|
||||
src_int ? src_int : "", src_id ? src_id : "");
|
||||
fp = popen(octstr_get_cstr(s), "r");
|
||||
octstr_destroy(s);
|
||||
|
||||
fgets(buf, 4096, fp);
|
||||
fgets(buf, sizeof buf, fp);
|
||||
s = octstr_create(buf);
|
||||
octstr_strip_crlfs(s);
|
||||
|
||||
pclose(fp);
|
||||
|
||||
if (octstr_len(s) == 0) {
|
||||
octstr_destroy(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
/* The function itself. */
|
||||
MmsResolverFuncStruct mms_resolvefuncs = {
|
||||
MmsResolverFuncStruct mms_resolvefuncs_shell = {
|
||||
mms_resolvermodule_init,
|
||||
mms_resolve,
|
||||
mms_resolvermodule_fini
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* Resolving MSISDNs to local/remote MMSCs - interface (shell)
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#ifndef __MMS_RESOLVE_SHELL_INCLUDED__
|
||||
#define __MMS_RESOLVE_SHELL_INCLUDED__
|
||||
|
||||
#include <time.h>
|
||||
#include "gwlib/gwlib.h"
|
||||
#include "mms_resolve.h"
|
||||
|
||||
extern MmsResolverFuncStruct mms_resolvefuncs_shell;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* MMSC: Full MMSC startup
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#include <signal.h>
|
||||
#include "mmsc.h"
|
||||
#include "mms_uaprof.h"
|
||||
|
||||
MmscSettings *settings;
|
||||
List *proxyrelays;
|
||||
|
||||
static void quit_now(int notused)
|
||||
{
|
||||
stop_mmsrelay();
|
||||
stop_mmsproxy();
|
||||
}
|
||||
|
||||
/* manage the SIGHUP signal */
|
||||
static void relog_now(int notused)
|
||||
{
|
||||
mms_warning(0, "mmsc", NULL, "SIGHUP received, catching and re-opening logs");
|
||||
log_reopen();
|
||||
alog_reopen();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int cfidx;
|
||||
Octstr *fname;
|
||||
long r_thread = 0;
|
||||
|
||||
mms_lib_init();
|
||||
|
||||
srandom(time(NULL));
|
||||
|
||||
cfidx = get_and_set_debugs(argc, argv, NULL);
|
||||
|
||||
if (argv[cfidx] == NULL)
|
||||
fname = octstr_imm("mbuni.conf");
|
||||
else
|
||||
fname = octstr_create(argv[cfidx]);
|
||||
|
||||
|
||||
mms_info(0, "mmsc", NULL, "----------------------------------------");
|
||||
mms_info(0, "mmsc", NULL," " MM_NAME " MMSC version %s starting", MMSC_VERSION);
|
||||
|
||||
|
||||
settings = mms_load_mmsc_settings(fname,&proxyrelays, 0);
|
||||
|
||||
octstr_destroy(fname);
|
||||
if (!settings)
|
||||
panic(0, "No MMSC configuration!");
|
||||
|
||||
#ifdef SA_RESTART
|
||||
{
|
||||
struct sigaction nact;
|
||||
|
||||
memset(&nact, 0, sizeof(nact));
|
||||
nact.sa_handler = relog_now;
|
||||
nact.sa_flags = SA_RESTART;
|
||||
sigaction(SIGHUP, &nact, (struct sigaction *)0);
|
||||
}
|
||||
#else
|
||||
signal(SIGHUP, relog_now);
|
||||
#endif
|
||||
signal(SIGTERM, quit_now);
|
||||
signal(SIGINT, quit_now);
|
||||
signal(SIGPIPE,SIG_IGN); /* Ignore pipe errors. They kill us sometimes for no reason*/
|
||||
|
||||
|
||||
mms_info(0, "mmsc", NULL," " MM_NAME " MMSC services:%s%s%s%s",
|
||||
(settings->svc_list & SvcMM1) ? " MM1" : "",
|
||||
(settings->svc_list & SvcMM7) ? " MM7" : "",
|
||||
(settings->svc_list & SvcRelay) ? " Relay" : "",
|
||||
(settings->svc_list & (SvcMM1 | SvcMM7 | SvcRelay)) ? "" : " None");
|
||||
mms_info(0, "mmsc", NULL, "----------------------------------------");
|
||||
|
||||
if ((r_thread = gwthread_create((gwthread_func_t *)mmsrelay, NULL)) < 0)
|
||||
panic(0, "Failed to start MMSC Relay component!");
|
||||
|
||||
if (mmsproxy() < 0)
|
||||
panic(0, "Failed to start MMSC Relay component!");
|
||||
|
||||
/* We are done. Cleanup. */
|
||||
gwthread_join(r_thread);
|
||||
|
||||
mms_info(0, "mmsc", NULL, "MMSC shutdown commenced.");
|
||||
|
||||
gwthread_sleep(2); /* Wait for them to die. */
|
||||
mms_info(0, "mmsc", NULL, "Final cleanup...");
|
||||
mms_cleanup_mmsc_settings(settings); /* Stop settings stuff and so on. */
|
||||
|
||||
mms_info(0, "mmsc", NULL,"Shutdown complete...");
|
||||
mms_lib_shutdown();
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* MMSC: Full MMSC startup
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#ifndef __MBUNI_MMSC_INCLUDED__
|
||||
#define __MBUNI_MMSC_INCLUDED__
|
||||
#include "mmsc_cfg.h"
|
||||
|
||||
int mmsproxy(void);
|
||||
void stop_mmsproxy(void);
|
||||
|
||||
int mmsrelay(void);
|
||||
int stop_mmsrelay(void);
|
||||
|
||||
|
||||
extern void mbuni_global_queue_runner(volatile sig_atomic_t *stopflag);
|
||||
extern void mbuni_mm1_queue_runner(volatile sig_atomic_t *stopflag);
|
||||
extern MmscSettings *settings;
|
||||
extern List *proxyrelays;
|
||||
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* MMSC CFG: MMC configuration and misc. functions
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -13,41 +13,68 @@
|
|||
#ifndef __MMSC_CFG__
|
||||
#define __MMSC_CFG__
|
||||
#include "mms_util.h"
|
||||
#include "mms_resolve.h"
|
||||
#include "mms_billing.h"
|
||||
#include "mms_detokenize.h"
|
||||
#include "mms_resolve_shell.h"
|
||||
#include "mms_billing_shell.h"
|
||||
#include "mms_detokenize_shell.h"
|
||||
#include "mms_queue.h"
|
||||
#include "mmsc_mm5.h"
|
||||
|
||||
typedef struct MmsProxyRelay {
|
||||
Octstr *host;
|
||||
Octstr *name;
|
||||
Octstr *allowed_prefix;
|
||||
Octstr *denied_prefix;
|
||||
|
||||
Octstr *unified_prefix;
|
||||
List *strip_prefixes;
|
||||
|
||||
int confirmed_mm4;
|
||||
Octstr *sendmail;
|
||||
} MmsProxyRelay;
|
||||
|
||||
typedef struct MmsVasp {
|
||||
Octstr *id;
|
||||
long short_code;
|
||||
long *short_codes; /* array of short codes. */
|
||||
int num_short_codes; /* number of short codes above. */
|
||||
enum {SOAP_VASP, EAIF_VASP, NONE_VASP} type;
|
||||
Octstr *vasp_username, *vasp_password;
|
||||
Octstr *vasp_url;
|
||||
Octstr *mmsc_username, *mmsc_password;
|
||||
enum {UAProf_None, UAProf_URL, UAProf_UA} send_uaprof;
|
||||
MM7Version_t ver;
|
||||
double throughput;
|
||||
|
||||
time_t delete_after; /* Set, when thingie should be deleted. */
|
||||
struct {
|
||||
unsigned long mo_pdus, mt_pdus;
|
||||
unsigned long mo_errors, mt_errors;
|
||||
time_t start_time, last_pdu;
|
||||
} stats;
|
||||
} MmsVasp;
|
||||
|
||||
typedef struct MmscSettings {
|
||||
Octstr *system_user;
|
||||
Octstr *name, *hostname, *host_alias;
|
||||
List *local_domains;
|
||||
Octstr *unified_prefix, *local_prefix;
|
||||
|
||||
List *strip_prefixes;
|
||||
|
||||
Octstr *sendmail;
|
||||
Octstr *global_queuedir, *mm1_queuedir, *mm4_queuedir;
|
||||
|
||||
Octstr *smtp_relay;
|
||||
int smtp_port;
|
||||
|
||||
Octstr *global_queuedir, *mm1_queuedir;
|
||||
Octstr *mmbox_rootdir;
|
||||
|
||||
MmsQueueHandlerFuncs *qfs;
|
||||
|
||||
Octstr *ua_profile_cache_dir;
|
||||
|
||||
long maxthreads;
|
||||
long maxsendattempts;
|
||||
long maxsendattempts, mm1_maxsendattempts;
|
||||
long default_msgexpiry;
|
||||
double queue_interval;
|
||||
long max_msgexpiry;
|
||||
double queue_interval, mm1_queue_interval;
|
||||
long send_back_off;
|
||||
|
||||
long port, mm7port;
|
||||
|
@ -77,6 +104,7 @@ typedef struct MmscSettings {
|
|||
|
||||
int optimize_notification_size;
|
||||
int content_adaptation;
|
||||
int dlr_on_fetch;
|
||||
|
||||
Octstr *prov_notify;
|
||||
|
||||
|
@ -88,27 +116,57 @@ typedef struct MmscSettings {
|
|||
|
||||
Octstr *mms_email_txt;
|
||||
Octstr *mms_email_html;
|
||||
Octstr *wap_gw_msisdn_header;
|
||||
Octstr *wap_gw_ip_header;
|
||||
Octstr *mms_email_subject;
|
||||
List *wap_gw_msisdn_header;
|
||||
List *wap_gw_ip_header;
|
||||
|
||||
List *vasp_list; /* of MmsVasp * */
|
||||
Dict *vasp_list; /* of MmsVasp *, indexed by ID */
|
||||
|
||||
List *vasp_del_list; /* stuff to be deleted! */
|
||||
|
||||
MmsVasp *mms2email, *mms2mobile;
|
||||
|
||||
MmscMM5FuncStruct *mm5; /* If we have loaded an mm5 module, this is it. */
|
||||
|
||||
/* Stuff for the admin interface. */
|
||||
long admin_port;
|
||||
Octstr *admin_allow_ip, *admin_deny_ip;
|
||||
Octstr *admin_pass;
|
||||
long admin_thread;
|
||||
|
||||
unsigned int svc_list; /* List of started services */
|
||||
mCfg *cfg; /* have a pointer to it. */
|
||||
} MmscSettings;
|
||||
|
||||
/* Returns mmsc settings. */
|
||||
MmscSettings *mms_load_mmsc_settings(mCfg *cfg, List **proxyrelays);
|
||||
enum {SvcMM1=1, SvcMM7=2, SvcRelay=4}; /* List of started services */
|
||||
|
||||
/* Returns mmsc settings. */
|
||||
MmscSettings *mms_load_mmsc_settings(Octstr *fname, List **proxyrelays, int skip_admin_port);
|
||||
MmsVasp *mmsc_load_vasp_from_conf(MmscSettings *m, mCfgGrp *grp,
|
||||
List *errors, List *warnings);
|
||||
int mmsc_unload_vasp(MmscSettings *m, Octstr *id);
|
||||
/* do final cleanup. */
|
||||
void mms_cleanup_mmsc_settings(MmscSettings *settings);
|
||||
/* Returns list of MmsProxyRelay */
|
||||
extern List *mms_proxy_relays(mCfg *cfg);
|
||||
extern List *mms_proxy_relays(mCfg *cfg, Octstr *myhostname);
|
||||
|
||||
extern Octstr *mms_makefetchurl(char *qf, Octstr *token, int loc,
|
||||
Octstr *to,
|
||||
MmscSettings *settings);
|
||||
|
||||
Octstr *mms_find_sender_msisdn(Octstr *send_url, List *request_hdrs,
|
||||
Octstr *msisdn_header,
|
||||
Octstr *requestip_header,
|
||||
Octstr *mms_find_sender_msisdn(Octstr *send_url,
|
||||
Octstr *ip,
|
||||
List *request_hdrs,
|
||||
List *msisdn_header,
|
||||
List *requestip_header,
|
||||
MmsDetokenizerFuncStruct *detokenizerfuncs);
|
||||
|
||||
extern int mms_decodefetchurl(Octstr *fetch_url,
|
||||
Octstr **qf, Octstr **token, int *loc);
|
||||
Octstr *mms_find_sender_ip(List *request_hdrs, List *ip_header, Octstr *ip, int *isv6);
|
||||
|
||||
void notify_prov_server(char *cmd, char *from, char *event, char *arg, Octstr *msgid,
|
||||
Octstr *ua, Octstr *uaprof);
|
||||
int mms_ind_send(Octstr *prov_cmd, Octstr *to);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* MM5 interface, query/save mapping from msisdn to uaprof string/url
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "mmsc_mm5.h"
|
||||
#include "mms_util.h"
|
||||
|
||||
static char cmd[1024] = "true";
|
||||
static int mm5_shell_init(char *shell_cmd)
|
||||
{
|
||||
strncpy(cmd, shell_cmd, sizeof cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mm5_shell_update(char *phonenum, char *uaprof_url, char *ua_string)
|
||||
{
|
||||
Octstr *x;
|
||||
Octstr *y;
|
||||
Octstr *z;
|
||||
Octstr *s;
|
||||
|
||||
if (phonenum == NULL)
|
||||
return;
|
||||
|
||||
x = uaprof_url ? octstr_create(uaprof_url) : octstr_imm("");
|
||||
y = ua_string ? octstr_create(ua_string) : octstr_imm("");
|
||||
z = octstr_create(phonenum);
|
||||
|
||||
escape_shell_chars(x);
|
||||
escape_shell_chars(y);
|
||||
escape_shell_chars(z);
|
||||
s = octstr_format("%s '%S' '%S' '%S'", cmd, z, x, y);
|
||||
|
||||
system(octstr_get_cstr(s));
|
||||
|
||||
octstr_destroy(s);
|
||||
octstr_destroy(x);
|
||||
octstr_destroy(y);
|
||||
octstr_destroy(z);
|
||||
}
|
||||
|
||||
|
||||
static int mm5_shell_query(char *phonenum, char uaprof_url[], char *ua_string,
|
||||
int buflen)
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[4096], *p;
|
||||
int ret;
|
||||
|
||||
Octstr *z;
|
||||
Octstr *s;
|
||||
|
||||
if (phonenum == NULL)
|
||||
return -1;
|
||||
|
||||
z = octstr_create(phonenum);
|
||||
escape_shell_chars(z);
|
||||
|
||||
s = octstr_format("%s '%S'", cmd, z);
|
||||
if ((fp = popen(octstr_get_cstr(s), "r")) != NULL) {
|
||||
|
||||
if (uaprof_url) {
|
||||
uaprof_url[0] = 0;
|
||||
p = fgets(buf, sizeof buf, fp);
|
||||
if (p)
|
||||
strncpy(uaprof_url, p, buflen);
|
||||
}
|
||||
|
||||
if (ua_string) {
|
||||
ua_string[0] = 0;
|
||||
p = fgets(buf, sizeof buf, fp);
|
||||
if (p)
|
||||
strncpy(ua_string, p, buflen);
|
||||
}
|
||||
pclose(fp);
|
||||
ret = 0;
|
||||
} else
|
||||
ret = -1;
|
||||
octstr_destroy(s);
|
||||
octstr_destroy(z);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static void shell_cleanup(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
MmscMM5FuncStruct _x = {
|
||||
mm5_shell_init,
|
||||
mm5_shell_update,
|
||||
mm5_shell_query,
|
||||
|
||||
shell_cleanup
|
||||
}, *shell_mm5 = &_x;
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* MM5 interface, query/save mapping from msisdn to uaprof string/url
|
||||
*
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#ifndef __MMS_MM5_INCLUDED__
|
||||
#define __MMS_MM5_INCLUDED__
|
||||
|
||||
#include <time.h>
|
||||
#include "gwlib/gwlib.h"
|
||||
|
||||
/* mm5 module. This file provides prototypes for all mm5 interface functions.
|
||||
*
|
||||
*/
|
||||
|
||||
typedef struct MmscMM5FuncStruct {
|
||||
/* This function is called once to initialise the mm5 interface module. Return a generic object,
|
||||
* which is passed with each request.
|
||||
*/
|
||||
int (*init)(char *settings);
|
||||
|
||||
/* Save the UaProf URL and UserAgent string for given phone number. */
|
||||
void (*update)(char *phonenum,
|
||||
char *uaprof_url, char *ua_string);
|
||||
|
||||
/* Query for the uaprof and ua string. Return them in the buffers provided.
|
||||
* return 0 on success, -1 on error.
|
||||
*/
|
||||
int (*query)(char *phonenum, char uaprof_url[], char *ua_string,
|
||||
int buflen);
|
||||
|
||||
void (*cleanup)(void);
|
||||
} MmscMM5FuncStruct;
|
||||
|
||||
/* Any module must export a symbol of the above type, with name 'mm5_funcs' */
|
||||
extern MmscMM5FuncStruct *shell_mm5; /* Handler when using shell script. */
|
||||
|
||||
#endif
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* Email2MMS and MM4 (incoming) interface
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -23,28 +23,37 @@ static Octstr *xproxy;
|
|||
|
||||
enum {TPLMN, TEMAIL, TOTHER} ttype;
|
||||
|
||||
/* above indexed by types! */
|
||||
|
||||
static int find_own(int i, int argc, char *argv[]);
|
||||
|
||||
static void fixup_recipient(void);
|
||||
static void fixup_recipient(Octstr **host);
|
||||
static void fixup_sender(void);
|
||||
static void fixup_addresses(List *headers);
|
||||
|
||||
static void send_mm4_res(int mtype, Octstr *to, Octstr *sender,
|
||||
Octstr *transid, char *status, Octstr *msgid,
|
||||
Octstr *sendmail_cmd);
|
||||
|
||||
static mCfg *cfg;
|
||||
static List *proxyrelays;
|
||||
static int no_strip = 0, strip_type = 0;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int cfidx;
|
||||
Octstr *fname;
|
||||
|
||||
MIMEEntity *mm;
|
||||
MmsMsg *msg;
|
||||
|
||||
Octstr *email;
|
||||
Octstr *home_mmsc = NULL;
|
||||
Octstr *email, *me, *rstatus, *fname;
|
||||
Octstr *home_mmsc = NULL, *rhost = NULL;
|
||||
List *headers, *h2;
|
||||
Octstr *mm4_type = NULL, *transid, *ack, *msgid, *orig_sys;
|
||||
Octstr *newmsgid = NULL;
|
||||
|
||||
int mtype = -1, mm1_type = -1, cfidx, i;
|
||||
char *err = NULL;
|
||||
|
||||
mms_lib_init();
|
||||
|
||||
srandom(time(NULL));
|
||||
|
||||
cfidx = get_and_set_debugs(argc, argv, find_own);
|
||||
|
||||
if (argv[cfidx] == NULL)
|
||||
|
@ -52,42 +61,36 @@ int main(int argc, char *argv[])
|
|||
else
|
||||
fname = octstr_create(argv[cfidx]);
|
||||
|
||||
cfg = mms_cfg_read(fname);
|
||||
|
||||
if (cfg == NULL)
|
||||
panic(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
|
||||
|
||||
octstr_destroy(fname);
|
||||
|
||||
info(0, "----------------------------------------");
|
||||
info(0, " MMSC Email2MMS Tool version %s starting", MMSC_VERSION);
|
||||
mms_info(0, "mmsfromemail", NULL, "----------------------------------------");
|
||||
mms_info(0, "mmsfromemail", NULL, " MMSC Email2MMS/MM4 Incoming Tool version %s starting", MMSC_VERSION);
|
||||
|
||||
/* Load settings. */
|
||||
settings = mms_load_mmsc_settings(cfg, &proxyrelays);
|
||||
|
||||
mms_cfg_destroy(cfg);
|
||||
|
||||
settings = mms_load_mmsc_settings(fname, &proxyrelays,1);
|
||||
if (!settings)
|
||||
panic(0, "No global MMSC configuration!");
|
||||
panic(0, "No global MMSC configuration, or failed to read conf from <%s>!", octstr_get_cstr(fname));
|
||||
|
||||
if (!xto || !xfrom)
|
||||
panic(0, "usage: %s -f from -t to!", argv[0]);
|
||||
octstr_destroy(fname);
|
||||
if (!xto || !xfrom) {
|
||||
mms_error(0, "mmsfromemail", NULL, "usage: %s -f from -t to!", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* normalize recipient address, then if phone number,
|
||||
* check whether we are allowed to process.
|
||||
*/
|
||||
fixup_recipient();
|
||||
fixup_recipient(&rhost);
|
||||
fixup_sender();
|
||||
|
||||
if (xto && ttype == TPLMN) /* Get the home mmsc domain for this recipient. */
|
||||
home_mmsc = settings->mms_resolvefuncs->mms_resolve(xto,
|
||||
"MM4", xproxy ? octstr_get_cstr(xproxy) : NULL,
|
||||
settings->mms_resolver_module_data,
|
||||
settings, proxyrelays);
|
||||
if (!xto ||
|
||||
(ttype == TPLMN && (!home_mmsc ||
|
||||
!is_allowed_host(home_mmsc,
|
||||
settings->email2mmsrelay_hosts)))) {
|
||||
error(0, " Not allowed to send to this recipient %s, resolved mmsc=%s!",
|
||||
mms_error(0, "mmsfromemail", NULL, " Not allowed to send to this recipient %s, resolved mmsc=%s!",
|
||||
xto ? octstr_get_cstr(xto) : "(null)",
|
||||
home_mmsc ? octstr_get_cstr(home_mmsc) : "(null)");
|
||||
mms_lib_shutdown();
|
||||
|
@ -98,13 +101,13 @@ int main(int argc, char *argv[])
|
|||
email = octstr_read_pipe(stdin);
|
||||
|
||||
if (!email || octstr_len(email) == 0) {
|
||||
error(0, "Empty email message!");
|
||||
mms_error(0, "mmsfromeail", NULL, "Empty email message!");
|
||||
mms_lib_shutdown();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((mm = mime_octstr_to_entity(email)) == NULL) {
|
||||
error(0, "Unable to decode mime entity!");
|
||||
mms_error(0, "mmsfromeail", NULL, "Unable to decode mime entity!");
|
||||
mms_lib_shutdown();
|
||||
return -1;
|
||||
}
|
||||
|
@ -115,37 +118,145 @@ int main(int argc, char *argv[])
|
|||
unpack_mimeheaders(mm);
|
||||
|
||||
/* Delete some headers... */
|
||||
http_header_remove_all(mm->headers, "Received");
|
||||
http_header_remove_all(mm->headers, "X-MimeOLE");
|
||||
http_header_remove_all(mm->headers, "X-Mailer");
|
||||
headers = mime_entity_headers(mm);
|
||||
http_header_remove_all(headers, "Received");
|
||||
http_header_remove_all(headers, "X-MimeOLE");
|
||||
http_header_remove_all(headers, "X-Mailer");
|
||||
|
||||
/* Now convert from mime to MMS message. */
|
||||
msg = mms_frommime(mm);
|
||||
mime_entity_destroy(mm);
|
||||
/* rebuild headers, removing nasty looking ones. */
|
||||
h2 = http_create_empty_headers();
|
||||
for (i = 0; i<gwlist_len(headers); i++) {
|
||||
Octstr *name = NULL, *value = NULL;
|
||||
http_header_get(headers, i, &name, &value);
|
||||
|
||||
if (!msg) {
|
||||
error(0, "Unable to create MM!");
|
||||
if (!name ||
|
||||
octstr_case_search(name, octstr_imm("spam"), 0) >= 0 ||
|
||||
octstr_case_search(name, octstr_imm("mailscanner"), 0) >= 0)
|
||||
goto loop;
|
||||
|
||||
http_header_add(h2, octstr_get_cstr(name), octstr_get_cstr(value));
|
||||
loop:
|
||||
octstr_destroy(name);
|
||||
octstr_destroy(value);
|
||||
}
|
||||
http_destroy_headers(headers);
|
||||
headers = h2;
|
||||
/* Look for MM4 headers... */
|
||||
mm4_type = http_header_value(headers, octstr_imm("X-Mms-Message-Type"));
|
||||
ack = http_header_value(headers, octstr_imm("X-Mms-Ack-Request"));
|
||||
rstatus = http_header_value(headers, octstr_imm("X-Mms-Request-Status-Code"));
|
||||
|
||||
if ((transid = http_header_value(headers, octstr_imm("X-Mms-Transaction-ID"))) == NULL)
|
||||
transid = octstr_create("001");
|
||||
/* get originator system. */
|
||||
if ((orig_sys = http_header_value(headers, octstr_imm("X-Mms-Originator-System"))) == NULL)
|
||||
orig_sys = http_header_value(headers, octstr_imm("Sender"));
|
||||
|
||||
if (xproxy == NULL && orig_sys != NULL) { /* Copy proxy address from originator system. */
|
||||
int i = octstr_search_char(orig_sys, '@', 0);
|
||||
if (i >= 0)
|
||||
xproxy = octstr_copy(orig_sys, i+1, octstr_len(orig_sys));
|
||||
}
|
||||
|
||||
if ((msgid = http_header_value(headers, octstr_imm("X-Mms-Message-ID"))) == NULL)
|
||||
msgid = http_header_value(headers, octstr_imm("Message-ID"));
|
||||
|
||||
strip_quoted_string(msgid);
|
||||
strip_quoted_string(transid);
|
||||
|
||||
|
||||
mms_info(0, "MM4", NULL, "Received [message type: %s] [transaction id: %s] [origin: %s] [msgid: %s]",
|
||||
mm4_type ? octstr_get_cstr(mm4_type) : "",
|
||||
transid ? octstr_get_cstr(transid) : "",
|
||||
orig_sys ? octstr_get_cstr(orig_sys) : "",
|
||||
msgid ? octstr_get_cstr(msgid) : "");
|
||||
|
||||
/* ... and remove non-essential ones */
|
||||
http_header_remove_all(headers, "X-Mms-3GPP-MMS-Version");
|
||||
http_header_remove_all(headers, "MIME-Version");
|
||||
http_header_remove_all(headers, "X-Mms-Message-ID");
|
||||
http_header_remove_all(headers, "Message-ID");
|
||||
http_header_remove_all(headers, "X-Mms-Ack-Request");
|
||||
http_header_remove_all(headers, "X-Mms-Originator-System");
|
||||
|
||||
http_header_remove_all(headers, "Sender");
|
||||
|
||||
/* msgid was there, put it back in proper form. */
|
||||
if (msgid)
|
||||
http_header_add(headers, "Message-ID", octstr_get_cstr(msgid));
|
||||
|
||||
fixup_addresses(headers);
|
||||
|
||||
if (mm4_type) {
|
||||
unsigned char *x = NULL;
|
||||
Octstr *y;
|
||||
int i;
|
||||
|
||||
http_header_remove_all(headers, "X-Mms-Message-Type");
|
||||
for (i = 0; mm4_types[i].mm4str; i++)
|
||||
if (octstr_str_case_compare(mm4_type, mm4_types[i].mm4str) == 0) {
|
||||
mtype = i;
|
||||
mm1_type = mm4_types[i].mm1_type;
|
||||
x = mms_message_type_to_cstr(mm1_type);
|
||||
break;
|
||||
}
|
||||
|
||||
if (x) {
|
||||
http_header_add(headers, "X-Mms-Message-Type", (char *)x);
|
||||
if (orig_sys == NULL) /* Make it up! */
|
||||
orig_sys = octstr_format("system-user@%S",
|
||||
xproxy ? xproxy : octstr_imm("unknown"));
|
||||
} else {
|
||||
octstr_destroy(mm4_type);
|
||||
mm4_type = NULL; /* So that we assume normal message below. */
|
||||
}
|
||||
|
||||
if ((y = http_header_value(headers, octstr_imm("X-Mms-MM-Status-Code"))) != NULL) {
|
||||
/* This field is different on MM1. */
|
||||
http_header_remove_all(headers, "X-Mms-MM-Status-Code");
|
||||
http_header_add(headers, "X-Mms-Status", octstr_get_cstr(y));
|
||||
octstr_destroy(y);
|
||||
}
|
||||
}
|
||||
|
||||
if (mm4_type == NULL && mtype < 0) { /* else assume a normal send message. */
|
||||
http_header_add(headers, "X-Mms-Message-Type", "m-send-req");
|
||||
mm1_type = MMS_MSGTYPE_SEND_REQ;
|
||||
mtype = MM4_FORWARD_REQ;
|
||||
}
|
||||
|
||||
mime_replace_headers(mm, headers);
|
||||
http_destroy_headers(headers);
|
||||
|
||||
/* Now convert from mime to MMS message, if we should */
|
||||
if (mm1_type >= 0) {
|
||||
if ((msg = mms_frommime(mm)) == NULL) {
|
||||
mms_error(0, "mmsfromeail", NULL, "Unable to create MM!");
|
||||
mms_lib_shutdown();
|
||||
return -1;
|
||||
}
|
||||
} else
|
||||
msg = NULL;
|
||||
mime_entity_destroy(mm);
|
||||
me = octstr_format("system-user@%S", settings->hostname);
|
||||
|
||||
switch(mms_messagetype(msg)) {
|
||||
case MMS_MSGTYPE_SEND_REQ:
|
||||
if (ttype != TPLMN)
|
||||
error(0, "Not allowed to send to non-phone recipient, to=%s!", octstr_get_cstr(xto));
|
||||
else {
|
||||
List *lto = list_create();
|
||||
switch(mtype) {
|
||||
case MM4_FORWARD_REQ:
|
||||
if (ttype != TPLMN && settings->mms2email == NULL) {
|
||||
err = "Error-service-denied";
|
||||
mms_error(0, "MM4", NULL, "Not allowed to send to non-phone recipient, to=%s!", octstr_get_cstr(xto));
|
||||
} else {
|
||||
List *lto = gwlist_create();
|
||||
Octstr *qf;
|
||||
Octstr *msgid = mms_get_header_value(msg, octstr_imm("Message-ID"));
|
||||
Octstr *transid = mms_get_header_value(msg, octstr_imm("X-Mms-Transaction-ID"));
|
||||
Octstr *dreport = mms_get_header_value(msg,
|
||||
octstr_imm("X-Mms-Delivery-Report"));
|
||||
char *err;
|
||||
Octstr *rto;
|
||||
Octstr *dreport = mms_get_header_value(msg, octstr_imm("X-Mms-Delivery-Report"));
|
||||
|
||||
int dlr;
|
||||
|
||||
if (ttype == TPLMN)
|
||||
octstr_format_append(xto, "/TYPE=PLMN");
|
||||
list_append(lto, xto);
|
||||
else
|
||||
octstr_format_append(xto, "@%S", rhost);
|
||||
gwlist_append(lto, xto);
|
||||
|
||||
if (dreport &&
|
||||
octstr_case_compare(dreport, octstr_imm("Yes")) == 0)
|
||||
|
@ -153,16 +264,23 @@ int main(int argc, char *argv[])
|
|||
else
|
||||
dlr = 0;
|
||||
|
||||
qf = mms_queue_add(xfrom, lto, NULL, xproxy, NULL,
|
||||
qf = settings->qfs->mms_queue_add(xfrom, lto, NULL, xproxy, NULL,
|
||||
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
dlr,
|
||||
octstr_get_cstr(settings->global_queuedir),
|
||||
mm4_type ? "MM4" : "MM3",
|
||||
settings->host_alias);
|
||||
if (qf) {
|
||||
|
||||
info(0, "Email2MMS Queued message to %s from %s (via %s) => %s",
|
||||
newmsgid = msgid ? octstr_duplicate(msgid) :
|
||||
qf ? mms_make_msgid(octstr_get_cstr(qf),
|
||||
settings->host_alias) : NULL;
|
||||
|
||||
if (qf) {
|
||||
mms_info(0, "mmsfromemail", NULL, "%s Queued message to %s from %s (via %s) => %s",
|
||||
mm4_type ? "MM4 Incoming" : "Email2MMS",
|
||||
octstr_get_cstr(xto), octstr_get_cstr(xfrom),
|
||||
xproxy ? octstr_get_cstr(xproxy) : "(None)", octstr_get_cstr(qf));
|
||||
octstr_destroy(qf);
|
||||
|
@ -170,154 +288,210 @@ int main(int argc, char *argv[])
|
|||
/* Queue our response to the chap. */
|
||||
err = "Ok";
|
||||
} else
|
||||
err = "Error-transient-failure";
|
||||
if (xproxy) {
|
||||
MmsMsg *mresp;
|
||||
List *xlto;
|
||||
mresp = mms_sendconf(err, octstr_get_cstr(msgid),
|
||||
transid ? octstr_get_cstr(transid) : "001",
|
||||
0,MS_1_1);
|
||||
|
||||
rto = octstr_format("system-user@%S", xproxy);
|
||||
xlto = list_create();
|
||||
list_append(xlto, rto);
|
||||
|
||||
qf = mms_queue_add(settings->system_user, xlto, NULL,
|
||||
xproxy, NULL,
|
||||
0, time(NULL) + settings->default_msgexpiry,
|
||||
mresp, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
0,
|
||||
octstr_get_cstr(settings->global_queuedir),
|
||||
settings->host_alias);
|
||||
|
||||
list_destroy(xlto, (list_item_destructor_t *)octstr_destroy);
|
||||
mms_destroy(mresp);
|
||||
octstr_destroy(qf);
|
||||
}
|
||||
|
||||
err = "Error-network-problem";
|
||||
mms_log("Received", xfrom, lto,
|
||||
-1, msgid, NULL, xproxy, xproxy ? "MM4" : "MM3", NULL,NULL);
|
||||
-1, msgid, NULL, xproxy, mm4_type ? "MM4" : "MM3", NULL,NULL);
|
||||
|
||||
list_destroy(lto,NULL);
|
||||
octstr_destroy(transid);
|
||||
octstr_destroy(msgid);
|
||||
gwlist_destroy(lto,NULL);
|
||||
if (dreport)
|
||||
octstr_destroy(dreport);
|
||||
|
||||
}
|
||||
break;
|
||||
case MM4_DELIVERY_REPORT_REQ:
|
||||
if (ttype != TPLMN && settings->mms2email == NULL) { /* We only send to phones from this interface */
|
||||
mms_error(0, "MM4", NULL, "Not allowed to send to %s!", octstr_get_cstr(xto));
|
||||
err = "Error-service-denied";
|
||||
} else {
|
||||
List *lto = gwlist_create();
|
||||
Octstr *qf;
|
||||
|
||||
case MMS_MSGTYPE_SEND_CONF:
|
||||
{
|
||||
Octstr *transid = mms_get_header_value(msg, octstr_imm("X-Mms-Transaction-ID"));
|
||||
Octstr *qf = mms_getqf_fromtransid(transid);
|
||||
|
||||
octstr_destroy(transid);
|
||||
if (ttype == TPLMN)
|
||||
octstr_format_append(xto, "/TYPE=PLMN");
|
||||
else
|
||||
octstr_format_append(xto, "@%S", rhost);
|
||||
gwlist_append(lto, xto);
|
||||
qf = settings->qfs->mms_queue_add(xfrom, lto, NULL,
|
||||
xproxy, NULL,
|
||||
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
0,
|
||||
octstr_get_cstr(settings->global_queuedir),
|
||||
"MM4",
|
||||
settings->host_alias);
|
||||
gwlist_destroy(lto, NULL);
|
||||
if (qf) {
|
||||
MmsEnvelope *e = mms_queue_readenvelope(octstr_get_cstr(qf),
|
||||
octstr_get_cstr(settings->mm4_queuedir),
|
||||
mms_info(0, "MM4", xproxy,"Queued DLR from proxy %s to %s from %s => %s",
|
||||
octstr_get_cstr(xproxy), octstr_get_cstr(xto), octstr_get_cstr(xfrom),
|
||||
octstr_get_cstr(qf));
|
||||
octstr_destroy(qf);
|
||||
err = "Ok";
|
||||
} else
|
||||
err = "Error-network-problem";
|
||||
newmsgid = msgid ? octstr_duplicate(msgid) : NULL; /* report old msg id */
|
||||
}
|
||||
break;
|
||||
|
||||
case MM4_READ_REPLY_REPORT_REQ:
|
||||
if (ttype != TPLMN && settings->mms2email == NULL) { /* We only send to phones from this interface */
|
||||
mms_error(0, "MM4", NULL, "Not allowed to send to %s!", octstr_get_cstr(xto));
|
||||
err = "Error-service-denied";
|
||||
} else {
|
||||
List *lto = gwlist_create();
|
||||
Octstr *qf;
|
||||
|
||||
if (ttype == TPLMN)
|
||||
octstr_format_append(xto, "/TYPE=PLMN");
|
||||
else
|
||||
octstr_format_append(xto, "@%S", rhost);
|
||||
|
||||
gwlist_append(lto, xto);
|
||||
qf = settings->qfs->mms_queue_add(xfrom, lto, NULL,
|
||||
xproxy, NULL,
|
||||
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
0,
|
||||
octstr_get_cstr(settings->global_queuedir),
|
||||
"MM4",
|
||||
settings->host_alias);
|
||||
gwlist_destroy(lto, NULL);
|
||||
if (qf) {
|
||||
mms_info(0, "MM4", xproxy, "Queued read report from proxy %s to %s from %s => %s",
|
||||
octstr_get_cstr(xproxy), octstr_get_cstr(xto), octstr_get_cstr(xfrom),
|
||||
octstr_get_cstr(qf));
|
||||
octstr_destroy(qf);
|
||||
err = "Ok";
|
||||
} else
|
||||
err = "Error-network-problem";
|
||||
}
|
||||
break;
|
||||
case MM4_FORWARD_RES:
|
||||
case MM4_READ_REPLY_REPORT_RES:
|
||||
case MM4_DELIVERY_REPORT_RES: /* remove corresponding queue entry. */
|
||||
{
|
||||
Octstr *qf, *o_to;
|
||||
int i;
|
||||
|
||||
/* Pull the number out of the fake transaction ID */
|
||||
if ((i = octstr_search_char(transid, '-',0)) > 0) {
|
||||
o_to = octstr_copy(transid, 0, i);
|
||||
#if 0
|
||||
_mms_fixup_address(o_to, settings->unified_prefix ? octstr_get_cstr(settings->unified_prefix) : NULL);
|
||||
#else
|
||||
mms_normalize_phonenum(&o_to,
|
||||
octstr_get_cstr(settings->unified_prefix),
|
||||
settings->strip_prefixes);
|
||||
|
||||
#endif
|
||||
octstr_delete(transid, 0, i+1);
|
||||
} else
|
||||
o_to = NULL;
|
||||
qf = mms_getqf_fromtransid(transid);
|
||||
if (qf) {
|
||||
MmsEnvelope *e;
|
||||
octstr_strip_blanks(qf);
|
||||
strip_quotes(qf);
|
||||
octstr_strip_blanks(o_to);
|
||||
strip_quotes(o_to);
|
||||
e = settings->qfs->mms_queue_readenvelope(octstr_get_cstr(qf),
|
||||
octstr_get_cstr(settings->global_queuedir),
|
||||
1);
|
||||
if (!e)
|
||||
warning(0, "Received confirm MMS but cannot find message %s [%s] in queue!",
|
||||
mms_warning(0, "MM4", xproxy, "MM4 Received %s from %s but cannot find queue entry for transaction %s [%s]!",
|
||||
mm4_types[mtype].mm4str,
|
||||
octstr_get_cstr(xproxy),
|
||||
octstr_get_cstr(transid),
|
||||
octstr_get_cstr(qf));
|
||||
else {
|
||||
MmsEnvelopeTo *t;
|
||||
int i, n;
|
||||
int processed = 0;
|
||||
|
||||
for (i = 0, n = list_len(e->to); i<n; i++)
|
||||
if ((t = list_get(e->to, i)) != NULL)
|
||||
for (i = 0, n = gwlist_len(e->to); i<n; i++)
|
||||
if ((t = gwlist_get(e->to, i)) != NULL &&
|
||||
(o_to == NULL || octstr_case_compare(o_to, t->rcpt) == 0)) {
|
||||
t->process = 0; /* Should make it go away. */
|
||||
mms_queue_update(e);
|
||||
info(0, "Email2MMS received send conf from proxy %s to %s from %s => %s",
|
||||
octstr_get_cstr(xproxy), octstr_get_cstr(xto),
|
||||
processed = 1;
|
||||
}
|
||||
/* write CDR if it is a forward confirmation */
|
||||
if (processed && mtype == MM4_FORWARD_RES &&
|
||||
rstatus && octstr_str_case_compare(rstatus, "Ok") == 0) {
|
||||
MmsCdrStruct *cdr = make_cdr_struct(settings->mms_bill_module_data,
|
||||
e->created, octstr_get_cstr(e->from),
|
||||
o_to ? octstr_get_cstr(o_to) : "",
|
||||
e->msgId ? octstr_get_cstr(e->msgId) : "",
|
||||
e->vaspid ? octstr_get_cstr(e->vaspid) : "",
|
||||
e->src_interface,
|
||||
"MM4", e->msize);
|
||||
settings->mms_billfuncs->mms_logcdr(cdr);
|
||||
|
||||
gw_free(cdr);
|
||||
}
|
||||
|
||||
mms_info(0, "MM4", xproxy, "Received %s from proxy %s to %s from %s => %s, status: [%s, %s]",
|
||||
mm4_types[mtype].mm4str,
|
||||
octstr_get_cstr(xproxy), o_to ? octstr_get_cstr(o_to) : octstr_get_cstr(xto),
|
||||
octstr_get_cstr(xfrom),
|
||||
octstr_get_cstr(qf));
|
||||
octstr_get_cstr(qf),
|
||||
rstatus ? octstr_get_cstr(rstatus) : "",
|
||||
processed ? "Sender number matched in queue file" : "Sender number not matched in queue file");
|
||||
|
||||
if (settings->qfs->mms_queue_update(e) != 1)
|
||||
settings->qfs->mms_queue_free_env(e);
|
||||
}
|
||||
|
||||
} else
|
||||
warning(0, "Received confirm MMS but cannot find message %s in queue!",
|
||||
mms_warning(0, "MM4", xproxy, "Received %s but cannot find message %s in queue!",
|
||||
mm4_types[mtype].mm4str,
|
||||
octstr_get_cstr(transid));
|
||||
|
||||
octstr_destroy(o_to);
|
||||
|
||||
}
|
||||
break;
|
||||
case MMS_MSGTYPE_DELIVERY_IND:
|
||||
if (ttype != TPLMN) /* We only send to phones from this interface */
|
||||
error(0, "Not allowed to send to %s!", octstr_get_cstr(xto));
|
||||
else {
|
||||
List *lto = list_create();
|
||||
Octstr *qf;
|
||||
|
||||
|
||||
octstr_format_append(xto, "/TYPE=PLMN");
|
||||
list_append(lto, xto);
|
||||
qf = mms_queue_add(xfrom, lto, NULL,
|
||||
xproxy, NULL,
|
||||
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
0,
|
||||
octstr_get_cstr(settings->global_queuedir),
|
||||
settings->host_alias);
|
||||
list_destroy(lto, NULL);
|
||||
if (qf) {
|
||||
info(0, "Email2MMS Queued DLR from proxy %s to %s from %s => %s",
|
||||
octstr_get_cstr(xproxy), octstr_get_cstr(xto), octstr_get_cstr(xfrom),
|
||||
octstr_get_cstr(qf));
|
||||
|
||||
octstr_destroy(qf);
|
||||
}
|
||||
|
||||
list_destroy(lto, NULL);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMS_MSGTYPE_READ_REC_IND:
|
||||
|
||||
mms_convert_readrec2readorig(msg);
|
||||
|
||||
/* Fall through. */
|
||||
case MMS_MSGTYPE_READ_ORIG_IND:
|
||||
if (ttype != TPLMN) /* We only send to phones from this interface */
|
||||
error(0, "Not allowed to send to %s!", octstr_get_cstr(xto));
|
||||
else {
|
||||
List *lto = list_create();
|
||||
Octstr *qf;
|
||||
|
||||
octstr_format_append(xto, "/TYPE=PLMN");
|
||||
list_append(lto, xto);
|
||||
qf = mms_queue_add(xfrom, lto, NULL,
|
||||
xproxy, NULL,
|
||||
0, time(NULL) + settings->default_msgexpiry, msg, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
0,
|
||||
octstr_get_cstr(settings->global_queuedir),
|
||||
settings->host_alias);
|
||||
list_destroy(lto, NULL);
|
||||
if (qf) {
|
||||
info(0, "Email2MMS Queued read report from proxy %s to %s from %s => %s",
|
||||
octstr_get_cstr(xproxy), octstr_get_cstr(xto), octstr_get_cstr(xfrom),
|
||||
octstr_get_cstr(qf));
|
||||
|
||||
octstr_destroy(qf);
|
||||
}
|
||||
|
||||
|
||||
list_destroy(lto, NULL);
|
||||
}
|
||||
default:
|
||||
{
|
||||
int x = mms_messagetype(msg);
|
||||
warning(0, "Unexpected message type: %d=>%s",
|
||||
x,
|
||||
mms_message_type_to_cstr(x));
|
||||
mms_warning(0, "MM4", xproxy, "Unexpected message type: %s",
|
||||
mm4_type ? octstr_get_cstr(mm4_type) : "not given!");
|
||||
break;
|
||||
}
|
||||
|
||||
/* respond to the sender as necessary. */
|
||||
if (mm4_type &&
|
||||
err &&
|
||||
ack && octstr_str_case_compare(ack, "Yes") == 0) {
|
||||
int i, n;
|
||||
Octstr *sendmail_cmd = settings->sendmail;
|
||||
/* try and find proxy and it's send command. */
|
||||
if (xproxy)
|
||||
for (i = 0, n = gwlist_len(proxyrelays); i<n; i++) {
|
||||
MmsProxyRelay *mp = gwlist_get(proxyrelays, i);
|
||||
if (mp && octstr_case_compare(xproxy, mp->host) == 0 &&
|
||||
mp->sendmail) {
|
||||
sendmail_cmd = mp->sendmail;
|
||||
break;
|
||||
}
|
||||
}
|
||||
send_mm4_res(mtype+1, orig_sys, me, transid, err, newmsgid, sendmail_cmd);
|
||||
}
|
||||
octstr_destroy(mm4_type);
|
||||
octstr_destroy(transid);
|
||||
octstr_destroy(orig_sys);
|
||||
octstr_destroy(msgid);
|
||||
octstr_destroy(newmsgid);
|
||||
octstr_destroy(rstatus);
|
||||
octstr_destroy(xto);
|
||||
octstr_destroy(xfrom);
|
||||
octstr_destroy(xproxy);
|
||||
octstr_destroy(me);
|
||||
|
||||
octstr_destroy(rhost);
|
||||
|
||||
mms_destroy(msg);
|
||||
mms_cleanup_mmsc_settings(settings);
|
||||
mms_lib_shutdown();
|
||||
|
||||
return 0;
|
||||
|
@ -339,60 +513,139 @@ static int find_own(int i, int argc, char *argv[])
|
|||
return 1;
|
||||
} else
|
||||
return -1;
|
||||
else if (argv[i][1] == 'p') /* Proxy name if any. */
|
||||
else if (argv[i][1] == 's') /* Proxy name if any. */
|
||||
if (i + 1 < argc) {
|
||||
xproxy = octstr_create(argv[i+1]);
|
||||
return 1;
|
||||
} else
|
||||
return -1;
|
||||
else
|
||||
else if (argv[i][1] == 'n') {
|
||||
no_strip = 1;
|
||||
return 0;
|
||||
} else if (argv[i][1] == 'x') {
|
||||
strip_type = 1;
|
||||
return 0;
|
||||
} else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static void fixup_recipient(void)
|
||||
static void fixup_recipient(Octstr **host)
|
||||
{
|
||||
int i;
|
||||
Octstr *typ = NULL;
|
||||
|
||||
|
||||
if (!xto) xto = octstr_imm("");
|
||||
i = octstr_search_char(xto, '@', 0);
|
||||
if (i>0)
|
||||
if (!xto) return;
|
||||
|
||||
i = octstr_search_char(xto, '@', 0); /* Remove '@' */
|
||||
if (i>0) {
|
||||
*host = octstr_copy(xto, i+1, octstr_len(xto));
|
||||
octstr_delete(xto, i, octstr_len(xto));
|
||||
} else
|
||||
*host = octstr_create("localhost");
|
||||
|
||||
i = octstr_search(xto, octstr_imm("/TYPE="), 0);
|
||||
if (i > 0) {
|
||||
typ = octstr_copy(xto, i+1, octstr_len(xto));
|
||||
octstr_delete(xto, i, octstr_len(xto));
|
||||
}
|
||||
|
||||
/* XXX may be we should use fixup function in mmlib/mms_util.c ?? */
|
||||
if (isphonenum(xto) &&
|
||||
(!typ || octstr_str_compare(typ, "TYPE=PLMN") == 0)) { /* A phone number. */
|
||||
#if 0
|
||||
normalize_number(octstr_get_cstr(settings->unified_prefix), &xto);
|
||||
#else
|
||||
|
||||
mms_normalize_phonenum(&xto,
|
||||
octstr_get_cstr(settings->unified_prefix),
|
||||
settings->strip_prefixes);
|
||||
#endif
|
||||
ttype = TPLMN;
|
||||
} else { /* For now everything else is email. */
|
||||
ttype = TEMAIL;
|
||||
}
|
||||
|
||||
octstr_destroy(typ);
|
||||
}
|
||||
|
||||
static void fixup_sender(void)
|
||||
{
|
||||
int i;
|
||||
int i, isphone = 1;
|
||||
|
||||
/* Find the TYPE=xxx element. If it is there, it is a number. Strip the @ */
|
||||
|
||||
if (!xfrom) xfrom = octstr_imm("");
|
||||
i = octstr_search_char(xfrom, '@', 0);
|
||||
if (i>0)
|
||||
return;
|
||||
if (!xfrom) return;
|
||||
|
||||
i = octstr_search(xfrom, octstr_imm("/TYPE="), 0);
|
||||
if (i > 0)
|
||||
return;
|
||||
|
||||
if (isphonenum(xfrom))
|
||||
i = octstr_case_search(xfrom, octstr_imm("/TYPE="), 0);
|
||||
if (i>0) {
|
||||
int j = octstr_search_char(xfrom, '@', 0);
|
||||
if (j > i) { /* we have @, remove it */
|
||||
if (xproxy == NULL)
|
||||
xproxy = octstr_copy(xfrom, j+1, octstr_len(xfrom));
|
||||
octstr_delete(xfrom, j, octstr_len(xfrom));
|
||||
}
|
||||
if (strip_type)
|
||||
octstr_delete(xfrom, i, octstr_len(xfrom));
|
||||
} else if (isphonenum(xfrom)) { /* Add the TYPE element if missing. */
|
||||
if (!strip_type)
|
||||
octstr_append(xfrom, octstr_imm("/TYPE=PLMN"));
|
||||
else
|
||||
octstr_append(xfrom, octstr_imm("@unknown"));
|
||||
} else {
|
||||
i = octstr_search_char(xfrom, '@', 0);
|
||||
if (i<0)
|
||||
octstr_format_append(xfrom, "@unknown");
|
||||
else if (xproxy == NULL)
|
||||
xproxy = octstr_copy(xfrom, i+1, octstr_len(xfrom));
|
||||
isphone = 0;
|
||||
}
|
||||
/* clean the number. */
|
||||
_mms_fixup_address(&xfrom,
|
||||
octstr_get_cstr(settings->unified_prefix),
|
||||
settings->strip_prefixes, strip_type ? 0 : 1);
|
||||
|
||||
if (no_strip && isphone && xproxy)
|
||||
octstr_format_append(xfrom, "@%S", xproxy);
|
||||
}
|
||||
|
||||
|
||||
static void fixup_addresses(List *headers)
|
||||
{
|
||||
fixup_address_type(headers, "To",
|
||||
octstr_get_cstr(settings->unified_prefix), settings->strip_prefixes);
|
||||
fixup_address_type(headers, "From",
|
||||
octstr_get_cstr(settings->unified_prefix), settings->strip_prefixes);
|
||||
}
|
||||
|
||||
static void send_mm4_res(int mtype, Octstr *to, Octstr *sender, Octstr *transid, char *status, Octstr *msgid,
|
||||
Octstr *sendmail_cmd)
|
||||
{
|
||||
char tmp[32];
|
||||
List *h = http_create_empty_headers();
|
||||
MIMEEntity *m = mime_entity_create();
|
||||
Octstr *err = NULL;
|
||||
/* Make headers */
|
||||
sprintf(tmp, "%d.%d.%d",
|
||||
MAJOR_VERSION(MMS_3GPP_VERSION),
|
||||
MINOR1_VERSION(MMS_3GPP_VERSION),
|
||||
MINOR2_VERSION(MMS_3GPP_VERSION));
|
||||
|
||||
http_header_add(h, "X-Mms-3GPP-MMS-Version", tmp);
|
||||
http_header_add(h, "X-Mms-Transaction-ID", octstr_get_cstr(transid));
|
||||
http_header_add(h, "X-Mms-Message-Type", mm4_types[mtype].mm4str);
|
||||
if (msgid)
|
||||
http_header_add(h, "X-Mms-Message-ID", octstr_get_cstr(msgid));
|
||||
http_header_add(h, "X-Mms-Request-Status-Code", status);
|
||||
http_header_add(h, "Sender", octstr_get_cstr(sender));
|
||||
http_header_add(h, "To", octstr_get_cstr(to));
|
||||
|
||||
mime_replace_headers(m, h);
|
||||
http_destroy_headers(h);
|
||||
|
||||
mm_send_to_email(to, sender, octstr_imm(""), msgid, m, 0, &err, octstr_get_cstr(sendmail_cmd),
|
||||
settings->hostname, settings->smtp_relay, settings->smtp_port);
|
||||
if (err) {
|
||||
mms_warning(0, "MM4", NULL, "send.RES reported: %s!", octstr_get_cstr(err));
|
||||
octstr_destroy(err);
|
||||
}
|
||||
mime_entity_destroy(m);
|
||||
}
|
||||
|
|
|
@ -3,27 +3,24 @@
|
|||
*
|
||||
* MMS Global Queue Runner, routes messages generally.
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
|
||||
#include "mmsrelay.h"
|
||||
#include <unistd.h>
|
||||
#include "mmsc.h"
|
||||
|
||||
#define NMAX 256
|
||||
static char mobile_qdir[NMAX];
|
||||
static char mm4_qdir[NMAX];
|
||||
static char sendmail_cmd[NMAX];
|
||||
|
||||
|
||||
/* Set the queue directory for messages going to mobile. */
|
||||
static int mms_setmobile_queuedir(char *mqdir);
|
||||
|
||||
/* Set the queue directory for messages going to remote proxies. */
|
||||
static int mms_setmm4_queuedir(char *mqdir);
|
||||
|
||||
/* Send command for sending mail. It will be called as <sendmail> <to> with
|
||||
* headers and message on stdin.
|
||||
|
@ -47,17 +44,22 @@ static int mms_sendtomobile(Octstr *from, Octstr *to,
|
|||
*/
|
||||
static int mms_sendtoproxy(Octstr *from, Octstr *to,
|
||||
Octstr *subject, Octstr *proxy,
|
||||
Octstr *msgid, time_t expires, MmsMsg *m, int dlr, Octstr **error);
|
||||
char *transid,
|
||||
Octstr *msgid, time_t expires, MmsMsg *msg,
|
||||
int dlr, Octstr *proxy_sendmail_cmd, List *extra_headers, Octstr **error);
|
||||
|
||||
static int mms_sendtovasp(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
|
||||
List *qh,
|
||||
MmsMsg *m, Octstr **error);
|
||||
|
||||
static int _x_octstr_int_compare(int n, Octstr *s);
|
||||
static int match_short_codes(Octstr *phonenum, long short_codes[], int num_codes);
|
||||
|
||||
#if 0
|
||||
/* Send errors */
|
||||
#define MMS_SEND_OK 0
|
||||
#define MMS_SEND_ERROR_TRANSIENT -1
|
||||
#define MMS_SEND_ERROR_FATAL -2
|
||||
|
||||
#endif
|
||||
|
||||
#define NMAX 256
|
||||
static char qdir[NMAX];
|
||||
|
@ -68,31 +70,37 @@ static int sendMsg(MmsEnvelope *e)
|
|||
{
|
||||
int i, n;
|
||||
MmsMsg *msg = NULL;
|
||||
|
||||
time_t tstart = time(NULL);
|
||||
|
||||
if (e->msgtype == MMS_MSGTYPE_SEND_REQ &&
|
||||
!e->bill.billed) { /* Attempt to bill if not already billed */
|
||||
List *l = list_create();
|
||||
List *l = gwlist_create();
|
||||
double amt;
|
||||
|
||||
for (i = 0, n = list_len(e->to); i < n; i++) {
|
||||
MmsEnvelopeTo *to = list_get(e->to, i);
|
||||
list_append(l, to->rcpt);
|
||||
for (i = 0, n = gwlist_len(e->to); i < n; i++) {
|
||||
MmsEnvelopeTo *to = gwlist_get(e->to, i);
|
||||
Octstr *s = octstr_duplicate(to->rcpt);
|
||||
|
||||
_mms_fixup_address(&s,
|
||||
octstr_get_cstr(settings->unified_prefix),
|
||||
settings->strip_prefixes, 1);
|
||||
gwlist_append(l, s);
|
||||
}
|
||||
|
||||
amt = settings->mms_billfuncs->mms_billmsg(e->from, l,
|
||||
e->msize,
|
||||
e->vaspid,
|
||||
e->msgId,
|
||||
settings->mms_bill_module_data);
|
||||
list_destroy(l, NULL);
|
||||
gwlist_destroy(l, (void *)octstr_destroy);
|
||||
|
||||
info(0, "Global Queue MMS Bill: From %s, to_count=%ld, msgid=%s, msgsize=%ld: returned=%.2f",
|
||||
octstr_get_cstr(e->from), list_len(e->to), e->msgId ? octstr_get_cstr(e->msgId) : "",
|
||||
mms_info(0, "MM2", NULL, "Global Queue MMS Bill: From %s, to_count=%ld, msgid=%s, msgsize=%ld: returned=%.2f",
|
||||
octstr_get_cstr(e->from), gwlist_len(e->to), e->msgId ? octstr_get_cstr(e->msgId) : "",
|
||||
e->msize, amt);
|
||||
|
||||
if (amt == -1) { /* Delete message. */
|
||||
for (i = 0, n = list_len(e->to); i < n; i++) {
|
||||
MmsEnvelopeTo *to = list_get(e->to, i);
|
||||
for (i = 0, n = gwlist_len(e->to); i < n; i++) {
|
||||
MmsEnvelopeTo *to = gwlist_get(e->to, i);
|
||||
to->process = 0;
|
||||
}
|
||||
} else if (amt >= 0) {
|
||||
|
@ -101,7 +109,7 @@ static int sendMsg(MmsEnvelope *e)
|
|||
}
|
||||
|
||||
if (amt >= -1)
|
||||
if (mms_queue_update(e) == 1) /* Write queue just in case we crash. */
|
||||
if (settings->qfs->mms_queue_update(e) == 1) /* Write queue just in case we crash. */
|
||||
e = NULL;
|
||||
|
||||
if (e == NULL ||
|
||||
|
@ -111,18 +119,18 @@ static int sendMsg(MmsEnvelope *e)
|
|||
|
||||
|
||||
|
||||
msg = mms_queue_getdata(e);
|
||||
msg = settings->qfs->mms_queue_getdata(e);
|
||||
#if 0
|
||||
if (msg) mms_msgdump(msg,1);
|
||||
#endif
|
||||
|
||||
|
||||
for (i = 0, n = list_len(e->to); i < n; i++) {
|
||||
for (i = 0, n = gwlist_len(e->to); i < n; i++) {
|
||||
Octstr *err = NULL;
|
||||
int res = MMS_SEND_OK, m;
|
||||
MmsEnvelopeTo *to = list_get(e->to, i);
|
||||
MmsEnvelopeTo *to = gwlist_get(e->to, i);
|
||||
time_t tnow = time(NULL);
|
||||
|
||||
char *dst_int = "NONE";
|
||||
|
||||
if (!to || !to->process) /* Already processed. */
|
||||
continue;
|
||||
|
@ -147,26 +155,53 @@ static int sendMsg(MmsEnvelope *e)
|
|||
*/
|
||||
|
||||
if (octstr_search_char(to->rcpt, '@', 0) > 0) {
|
||||
if (settings->mms2email)
|
||||
int j = octstr_case_search(e->from, octstr_imm("/TYPE=PLMN"), 0);
|
||||
int k = octstr_case_search(e->from, octstr_imm("/TYPE=IPv"), 0);
|
||||
int len = octstr_len(e->from);
|
||||
Octstr *pfrom;
|
||||
|
||||
dst_int = "MM3";
|
||||
|
||||
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len)
|
||||
pfrom = octstr_copy(e->from, 0, j);
|
||||
else if (k > 0 && k + sizeof "/TYPE=IPv" == len)
|
||||
pfrom = octstr_copy(e->from, 0, k);
|
||||
else
|
||||
pfrom = octstr_duplicate(e->from);
|
||||
|
||||
if (octstr_search_char(e->from, '@', 0) < 0)
|
||||
octstr_format_append(pfrom,"@%S", settings->hostname);
|
||||
|
||||
if (settings->mms2email && /* send, but don't loop back on it */
|
||||
!(strcmp(e->src_interface, "MM7") == 0 &&
|
||||
e->vaspid && settings->mms2email->id &&
|
||||
octstr_compare(e->vaspid, settings->mms2email->id) == 0))
|
||||
res = mms_sendtovasp(settings->mms2email,
|
||||
e->from, to->rcpt,
|
||||
e->msgId,
|
||||
e->hdrs,
|
||||
msg, &err);
|
||||
else
|
||||
res = mms_sendtoemail(e->from, to->rcpt,
|
||||
e->subject,
|
||||
e->msgId, msg, e->dlr, &err, sendmail_cmd,
|
||||
else {
|
||||
List *lto = gwlist_create_ex(to->rcpt);
|
||||
res = mms_sendtoemail(pfrom, lto,
|
||||
e->subject ? e->subject : settings->mms_email_subject,
|
||||
e->msgId, msg, 0, &err, sendmail_cmd,
|
||||
settings->hostname, 1, 1,
|
||||
octstr_get_cstr(settings->mms_email_txt),
|
||||
octstr_get_cstr(settings->mms_email_html), 1);
|
||||
octstr_get_cstr(settings->mms_email_html), 0, e->xqfname,
|
||||
e->hdrs, settings->smtp_relay, settings->smtp_port);
|
||||
gwlist_destroy(lto, NULL);
|
||||
}
|
||||
if (res == MMS_SEND_QUEUED)
|
||||
res = MMS_SEND_OK; /* queued to email treated same as sent.
|
||||
* XXX - this means DLR requests for emailed messages not supported!
|
||||
*/
|
||||
if (res == MMS_SEND_OK)
|
||||
mms_log2("Sent", e->from, to->rcpt,
|
||||
-1, e->msgId, NULL, NULL, "MM3", NULL,NULL);
|
||||
} else if (e->viaproxy && octstr_len(e->viaproxy) > 0)
|
||||
res = mms_sendtoproxy(e->from,
|
||||
to->rcpt, e->subject, e->viaproxy,
|
||||
e->msgId, e->expiryt, msg, e->dlr, &err);
|
||||
else {
|
||||
if (pfrom != e->from)
|
||||
octstr_destroy(pfrom);
|
||||
} else {
|
||||
int j = octstr_case_search(to->rcpt, octstr_imm("/TYPE=PLMN"), 0);
|
||||
int k = octstr_case_search(to->rcpt, octstr_imm("/TYPE=IPv"), 0);
|
||||
int len = octstr_len(to->rcpt);
|
||||
|
@ -174,18 +209,20 @@ static int sendMsg(MmsEnvelope *e)
|
|||
Octstr *mmsc;
|
||||
int sent = 0;
|
||||
MmsVasp *vasp;
|
||||
List *vlist;
|
||||
|
||||
/* If it is an IP, send to mobile handler, else if number, look for recipient. */
|
||||
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len)
|
||||
phonenum = octstr_copy(to->rcpt, 0, j);
|
||||
else if (k > 0 && k + sizeof "/TYPE=IPv" == len) {
|
||||
if (settings->mms2mobile) { /* Send a copy to this VASP. */
|
||||
if (settings->mms2mobile && e->msgtype == MMS_MSGTYPE_SEND_REQ) { /* Send a copy to this VASP. */
|
||||
Octstr *xerr = NULL;
|
||||
int res = mms_sendtovasp(settings->mms2mobile,
|
||||
e->from, to->rcpt,
|
||||
e->msgId,
|
||||
e->hdrs,
|
||||
msg, &err);
|
||||
info(0, "%s Global Queue MMS Send: Local Msg copy to VASP (%s) - "
|
||||
mms_info(0, "MM7", settings->mms2mobile->id, "%s Global Queue MMS Send: Local Msg copy to VASP (%s) - "
|
||||
"From %s, to %s, msgsize=%ld: err=%s",
|
||||
SEND_ERROR_STR(res),
|
||||
octstr_get_cstr(settings->mms2mobile->id),
|
||||
|
@ -197,6 +234,7 @@ static int sendMsg(MmsEnvelope *e)
|
|||
res = mms_sendtomobile(e->from,
|
||||
to->rcpt, e->subject, e->fromproxy,
|
||||
e->msgId, e->expiryt, msg, e->dlr, &err);
|
||||
dst_int = "MM1";
|
||||
sent = 1;
|
||||
goto done;
|
||||
} else {
|
||||
|
@ -207,52 +245,124 @@ static int sendMsg(MmsEnvelope *e)
|
|||
goto done;
|
||||
}
|
||||
|
||||
/* Normalise the number, then see if we can resolve home MMSC for this recipient. */
|
||||
normalize_number(octstr_get_cstr(settings->unified_prefix), &phonenum);
|
||||
/* Search VASP list, see what you can find... */
|
||||
vlist = dict_keys(settings->vasp_list);
|
||||
for (j = 0, m = gwlist_len(vlist); j < m; j++)
|
||||
if ((vasp = dict_get(settings->vasp_list, gwlist_get(vlist, j))) != NULL &&
|
||||
match_short_codes(phonenum, vasp->short_codes, vasp->num_short_codes)) {
|
||||
res = mms_sendtovasp(vasp, e->from, to->rcpt,
|
||||
e->msgId,
|
||||
e->hdrs,
|
||||
msg, &err);
|
||||
dst_int = "MM7";
|
||||
sent = 1;
|
||||
break;
|
||||
}
|
||||
gwlist_destroy(vlist, (void *)octstr_destroy);
|
||||
|
||||
if (sent != 1) { /* Not yet, sent, find the receiver MMSC. */
|
||||
/* Normalise the number, then see if we can resolve home MMSC for this recipient. */
|
||||
#if 0
|
||||
normalize_number(octstr_get_cstr(settings->unified_prefix), &phonenum);
|
||||
#else
|
||||
mms_normalize_phonenum(&phonenum,
|
||||
octstr_get_cstr(settings->unified_prefix),
|
||||
settings->strip_prefixes);
|
||||
#endif
|
||||
if ((mmsc = settings->mms_resolvefuncs->mms_resolve(phonenum,
|
||||
e->src_interface,
|
||||
e->vaspid ? octstr_get_cstr(e->vaspid) : NULL,
|
||||
settings->mms_resolver_module_data,
|
||||
settings, proxyrelays))) {
|
||||
info(0, "mmsc for \"%s\" resolved to: \"%s\"",
|
||||
mms_info(0, "MM2", NULL, "mmsc for \"%s\" resolved to: \"%s\"",
|
||||
octstr_get_cstr(phonenum), octstr_get_cstr(mmsc));
|
||||
|
||||
/* If resolved to my hostname, then this is local. */
|
||||
if (octstr_compare(mmsc, settings->hostname) == 0) {
|
||||
res =
|
||||
mms_sendtomobile(e->from, to->rcpt,
|
||||
if (settings->mms2mobile &&
|
||||
e->msgtype == MMS_MSGTYPE_SEND_REQ) { /* Send a copy to this VASP. */
|
||||
Octstr *xerr = NULL;
|
||||
int res = mms_sendtovasp(settings->mms2mobile,
|
||||
e->from, to->rcpt,
|
||||
e->msgId,
|
||||
e->hdrs,
|
||||
msg, &err);
|
||||
mms_info(0, "MM2", NULL, "%s Global Queue MMS Send: Local Msg copy to VASP (%s) - "
|
||||
"From %s, to %s, msgsize=%ld: err=%s",
|
||||
SEND_ERROR_STR(res),
|
||||
octstr_get_cstr(settings->mms2mobile->id),
|
||||
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
|
||||
xerr ? octstr_get_cstr(xerr) : "(null)");
|
||||
if (xerr)
|
||||
octstr_destroy(xerr);
|
||||
}
|
||||
|
||||
res = mms_sendtomobile(e->from, to->rcpt,
|
||||
e->subject, e->fromproxy,
|
||||
e->msgId, e->expiryt, msg, e->dlr,
|
||||
&err);
|
||||
dst_int = "MM1";
|
||||
sent = 1;
|
||||
} else if (proxyrelays && list_len(proxyrelays) > 0) /* Step through proxies. */
|
||||
for (j = 0, m = list_len(proxyrelays); j<m; j++) {
|
||||
MmsProxyRelay *mp = list_get(proxyrelays, j);
|
||||
} else {
|
||||
|
||||
if (!octstr_compare(mp->host, mmsc)) {
|
||||
res = mms_sendtoproxy(e->from, to->rcpt,
|
||||
/* else, step through proxies, look for one that matches. */
|
||||
for (j = 0, m = proxyrelays ? gwlist_len(proxyrelays) : 0; j<m; j++) {
|
||||
MmsProxyRelay *mp = gwlist_get(proxyrelays, j);
|
||||
|
||||
if (octstr_compare(mp->host, mmsc) == 0) {
|
||||
Octstr *xtransid = mms_maketransid(e->xqfname,
|
||||
settings->host_alias);
|
||||
Octstr *xfrom = e->from ? octstr_duplicate(e->from) : octstr_create("anon@anon");
|
||||
Octstr *xto = octstr_duplicate(to->rcpt);
|
||||
|
||||
_mms_fixup_address(&xfrom,
|
||||
mp->unified_prefix ? octstr_get_cstr(mp->unified_prefix) : NULL,
|
||||
mp->strip_prefixes, 1);
|
||||
|
||||
_mms_fixup_address(&xto,
|
||||
mp->unified_prefix ? octstr_get_cstr(mp->unified_prefix) : NULL,
|
||||
mp->strip_prefixes, 1);
|
||||
res = mms_sendtoproxy(xfrom, xto,
|
||||
e->subject, mp->host,
|
||||
octstr_get_cstr(xtransid),
|
||||
e->msgId, e->expiryt, msg,
|
||||
e->dlr, &err);
|
||||
mp->confirmed_mm4, mp->sendmail, e->hdrs, &err);
|
||||
dst_int = "MM4";
|
||||
sent = 1;
|
||||
octstr_destroy(xtransid);
|
||||
octstr_destroy(xfrom);
|
||||
octstr_destroy(xto);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else /* Search VASP list, see what you can find... */
|
||||
for (j = 0, m = list_len(settings->vasp_list); j < m; j++)
|
||||
if ((vasp = list_get(settings->vasp_list, j)) != NULL &&
|
||||
_x_octstr_int_compare(vasp->short_code, phonenum) == 0) {
|
||||
|
||||
if (sent != 1) { /* try mm7 delivery. Again. */
|
||||
List *vlist = dict_keys(settings->vasp_list);
|
||||
Octstr *vid;
|
||||
for (j = 0, m = gwlist_len(vlist); j < m; j++)
|
||||
if ((vid = gwlist_get(vlist, j)) != NULL &&
|
||||
(vasp = dict_get(settings->vasp_list, vid)) != NULL &&
|
||||
vasp->id &&
|
||||
octstr_compare(vasp->id, mmsc) == 0) {
|
||||
res = mms_sendtovasp(vasp, e->from, to->rcpt,
|
||||
e->msgId,
|
||||
e->hdrs,
|
||||
msg, &err);
|
||||
dst_int = "MM7";
|
||||
sent = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
gwlist_destroy(vlist, (void *)octstr_destroy);
|
||||
}
|
||||
}
|
||||
octstr_destroy(mmsc);
|
||||
}
|
||||
}
|
||||
if (!sent) {
|
||||
res = MMS_SEND_ERROR_FATAL;
|
||||
err = octstr_format("MMSC error: Don't know how to deliver to %S !", to->rcpt);
|
||||
|
||||
}
|
||||
if (phonenum) octstr_destroy(phonenum);
|
||||
octstr_destroy(phonenum);
|
||||
}
|
||||
|
||||
done:
|
||||
|
@ -262,26 +372,35 @@ static int sendMsg(MmsEnvelope *e)
|
|||
|
||||
if (e->dlr) {
|
||||
Octstr *qfs;
|
||||
MmsMsg *m = mms_deliveryreport(e->msgId, to->rcpt, tnow,
|
||||
(e->expiryt != 0 && e->expiryt < tnow) ?
|
||||
octstr_imm("Expired") : octstr_imm("Rejected"));
|
||||
char *mstatus;
|
||||
MmsMsg *m;
|
||||
List *l;
|
||||
|
||||
if (res == MMS_SEND_QUEUED)
|
||||
mstatus = "Forwarded";
|
||||
else if (e->expiryt != 0 && e->expiryt < tnow)
|
||||
mstatus = "Expired";
|
||||
else
|
||||
mstatus = "Rejected";
|
||||
m = mms_deliveryreport(e->msgId, to->rcpt, e->from, tnow, octstr_imm(mstatus));
|
||||
|
||||
List *l = list_create();
|
||||
l = gwlist_create();
|
||||
|
||||
list_append(l, octstr_duplicate(e->from));
|
||||
gwlist_append(l, octstr_duplicate(e->from));
|
||||
|
||||
/* Add to queue, switch via proxy to be from proxy. */
|
||||
qfs = mms_queue_add(settings->system_user, l,
|
||||
qfs = settings->qfs->mms_queue_add(to->rcpt, l,
|
||||
err, NULL, e->fromproxy,
|
||||
tnow, tnow+settings->default_msgexpiry, m, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
0,
|
||||
qdir,
|
||||
"MM2",
|
||||
settings->host_alias);
|
||||
octstr_destroy(qfs);
|
||||
list_destroy(l, NULL);
|
||||
gwlist_destroy(l, NULL);
|
||||
|
||||
mms_destroy(m);
|
||||
}
|
||||
|
@ -290,35 +409,46 @@ static int sendMsg(MmsEnvelope *e)
|
|||
}
|
||||
|
||||
/* Write to log */
|
||||
info(0, "%s Global Queue MMS Send: From %s, to %s, msgsize=%ld: err=%s",
|
||||
if (res == MMS_SEND_ERROR_FATAL ||
|
||||
(res == MMS_SEND_ERROR_TRANSIENT && err != NULL))
|
||||
mms_error(0, "MM2", NULL, "%s Global Queue MMS Send [%.128s]: From %s, to %s, msgsize=%ld: %s. ",
|
||||
SEND_ERROR_STR(res),
|
||||
e->xqfname,
|
||||
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
|
||||
err ? octstr_get_cstr(err) : "(null)");
|
||||
err ? octstr_get_cstr(err) : "n/a");
|
||||
else
|
||||
mms_info(0, "MM2", NULL, "%s Global Queue MMS Send [%.128s]: From %s, to %s, msgsize=%ld: %s.",
|
||||
SEND_ERROR_STR(res),
|
||||
e->xqfname,
|
||||
octstr_get_cstr(e->from), octstr_get_cstr(to->rcpt), e->msize,
|
||||
err ? octstr_get_cstr(err) : "n/a");
|
||||
|
||||
if (res == MMS_SEND_OK) { /* Do CDR writing. */
|
||||
MmsCdrStruct *cdr = gw_malloc(sizeof *cdr);
|
||||
if (res == MMS_SEND_OK &&
|
||||
(e->msgtype == MMS_MSGTYPE_SEND_REQ ||
|
||||
e->msgtype == MMS_MSGTYPE_RETRIEVE_CONF)) { /* Do CDR writing. */
|
||||
MmsCdrStruct *cdr = make_cdr_struct(settings->mms_bill_module_data,
|
||||
e->created,
|
||||
octstr_get_cstr(e->from),
|
||||
octstr_get_cstr(to->rcpt),
|
||||
e->msgId ? octstr_get_cstr(e->msgId) : "",
|
||||
e->vaspid ? octstr_get_cstr(e->vaspid) : "",
|
||||
e->src_interface,
|
||||
dst_int,
|
||||
e->msize);
|
||||
|
||||
cdr->module_data = settings->mms_bill_module_data;
|
||||
cdr->sdate = e->created;
|
||||
strncpy(cdr->from, octstr_get_cstr(e->from), sizeof cdr->from);
|
||||
strncpy(cdr->to, octstr_get_cstr(to->rcpt), sizeof cdr->to);
|
||||
strncpy(cdr->msgid, e->msgId ? octstr_get_cstr(e->msgId) : "", sizeof cdr->msgid);
|
||||
strncpy(cdr->vaspid, e->vaspid ? octstr_get_cstr(e->vaspid) : "", sizeof cdr->vaspid);
|
||||
cdr->msg_size = e->msize;
|
||||
|
||||
list_produce(cdr_list, cdr); /* Put it on list so sending thread sends it. */
|
||||
gwlist_produce(cdr_list, cdr); /* Put it on list so sending thread sends it. */
|
||||
}
|
||||
|
||||
octstr_destroy(err);
|
||||
/* Update queue entry so that we know which ones have been processed. */
|
||||
e->lasttry = tnow;
|
||||
if (mms_queue_update(e) == 1) {
|
||||
if (settings->qfs->mms_queue_update(e) == 1) {
|
||||
e = NULL;
|
||||
break; /* Queue entry gone. */
|
||||
}
|
||||
}
|
||||
|
||||
done2:
|
||||
if (msg)
|
||||
|
||||
mms_destroy(msg);
|
||||
|
||||
if (e) { /* Update the queue if it is still valid (e.g. recipients not handled) XXX can this happen here??... */
|
||||
|
@ -326,9 +456,12 @@ static int sendMsg(MmsEnvelope *e)
|
|||
e->attempts++; /* Update count of number of delivery attempts. */
|
||||
e->sendt = e->lasttry + settings->send_back_off * e->attempts;
|
||||
|
||||
if (mms_queue_update(e) != 1)
|
||||
mms_queue_free_env(e);
|
||||
if (settings->qfs->mms_queue_update(e) != 1)
|
||||
settings->qfs->mms_queue_free_env(e);
|
||||
}
|
||||
|
||||
mms_info(0, "MMSC.global", NULL, "Processed in %d secs", (int)(time(NULL) - tstart)); /* report processing time. */
|
||||
|
||||
return 1; /* Always deletes the queue entry. */
|
||||
}
|
||||
|
||||
|
@ -337,18 +470,17 @@ static void cdr_thread(void *unused)
|
|||
{
|
||||
MmsCdrStruct *cdr;
|
||||
|
||||
while ((cdr = list_consume(cdr_list)) != NULL) {
|
||||
while ((cdr = gwlist_consume(cdr_list)) != NULL) {
|
||||
settings->mms_billfuncs->mms_logcdr(cdr);
|
||||
/* We should probably write to log here... */
|
||||
gw_free(cdr);
|
||||
}
|
||||
}
|
||||
|
||||
void mbuni_global_queue_runner(int *rstop)
|
||||
void mbuni_global_queue_runner(volatile sig_atomic_t *rstop)
|
||||
{
|
||||
|
||||
long cdr_thid;
|
||||
mms_setmobile_queuedir(octstr_get_cstr(settings->mm1_queuedir));
|
||||
mms_setmm4_queuedir(octstr_get_cstr(settings->mm4_queuedir));
|
||||
|
||||
mms_setsendmail_cmd(octstr_get_cstr(settings->sendmail));
|
||||
|
||||
|
@ -356,15 +488,19 @@ void mbuni_global_queue_runner(int *rstop)
|
|||
|
||||
|
||||
/* Start the thread for CDR */
|
||||
cdr_list = list_create();
|
||||
list_add_producer(cdr_list);
|
||||
gwthread_create(cdr_thread, NULL);
|
||||
cdr_list = gwlist_create();
|
||||
gwlist_add_producer(cdr_list);
|
||||
cdr_thid = gwthread_create(cdr_thread, NULL);
|
||||
|
||||
|
||||
mms_queue_run(qdir, sendMsg, settings->queue_interval, settings->maxthreads, rstop);
|
||||
settings->qfs->mms_queue_run(qdir, sendMsg, settings->queue_interval, settings->maxthreads, rstop);
|
||||
/* When it ends, wait a little for other stuff to stop... */
|
||||
sleep(2);
|
||||
list_remove_producer(cdr_list); /* Stop CDR thread. */
|
||||
gwlist_remove_producer(cdr_list); /* Stop CDR thread. */
|
||||
|
||||
if (cdr_thid >= 0)
|
||||
gwthread_join(cdr_thid);
|
||||
gwthread_sleep(2);
|
||||
gwlist_destroy(cdr_list, NULL);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -377,11 +513,6 @@ static int mms_setmobile_queuedir(char *mqdir)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int mms_setmm4_queuedir(char *mqdir)
|
||||
{
|
||||
strncpy(mm4_qdir, mqdir, sizeof mm4_qdir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mms_setsendmail_cmd(char *sendmail)
|
||||
{
|
||||
|
@ -399,11 +530,11 @@ int mms_sendtomobile(Octstr *from, Octstr *to,
|
|||
Octstr *msgid, time_t expires, MmsMsg *m, int dlr, Octstr **error)
|
||||
{
|
||||
|
||||
Octstr *ret, *x;
|
||||
List *l = list_create();
|
||||
Octstr *ret = NULL, *x;
|
||||
List *l = gwlist_create();
|
||||
char tokenstr[128];
|
||||
|
||||
list_append(l, to);
|
||||
gwlist_append(l, to);
|
||||
|
||||
/* We generate a special token that will be added to message ID to make
|
||||
* stealing messages a bit harder.
|
||||
|
@ -413,18 +544,23 @@ int mms_sendtomobile(Octstr *from, Octstr *to,
|
|||
random() % 100);
|
||||
|
||||
x = octstr_create(tokenstr);
|
||||
|
||||
ret = mms_queue_add(from, l, subject, fromproxy, NULL, 0, expires, m,
|
||||
if (m)
|
||||
ret = settings->qfs->mms_queue_add(from, l, subject, fromproxy, NULL, 0, expires, m,
|
||||
x, NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
dlr, mobile_qdir,
|
||||
"MM2",
|
||||
settings->host_alias);
|
||||
else
|
||||
*error = octstr_format("GlobalSend: Failed to send to %S, Message format is corrupt!", to);
|
||||
|
||||
octstr_destroy(x);
|
||||
|
||||
list_destroy(l, NULL);
|
||||
gwlist_destroy(l, NULL);
|
||||
octstr_destroy(ret);
|
||||
if (ret == NULL)
|
||||
return MMS_SEND_ERROR_TRANSIENT;
|
||||
return (m) ? MMS_SEND_ERROR_TRANSIENT : MMS_SEND_ERROR_FATAL;
|
||||
else
|
||||
return MMS_SEND_OK;
|
||||
}
|
||||
|
@ -436,14 +572,15 @@ int mms_sendtomobile(Octstr *from, Octstr *to,
|
|||
*/
|
||||
static int mms_sendtoproxy(Octstr *from, Octstr *to,
|
||||
Octstr *subject, Octstr *proxy,
|
||||
Octstr *msgid, time_t expires, MmsMsg *msg, int dlr, Octstr **error)
|
||||
char *transid,
|
||||
Octstr *msgid, time_t expires, MmsMsg *msg,
|
||||
int dlr, Octstr *proxy_sendmail_cmd, List *extra_headers, Octstr **error)
|
||||
{
|
||||
|
||||
Octstr *pto;
|
||||
|
||||
|
||||
int x;
|
||||
|
||||
Octstr *pto, *pfrom;
|
||||
List *lto;
|
||||
int x = MMS_SEND_ERROR_FATAL;
|
||||
Octstr *xtransid; /* We make a fake transaction ID that includes 'to' field. */
|
||||
|
||||
if (!to ||
|
||||
octstr_search_char(to, '@', 0) >= 0) {
|
||||
|
@ -451,37 +588,37 @@ static int mms_sendtoproxy(Octstr *from, Octstr *to,
|
|||
return MMS_SEND_ERROR_FATAL;
|
||||
}
|
||||
|
||||
if (mms_messagetype(msg) == MMS_MSGTYPE_SEND_REQ) { /* Only queue these ones for future response. */
|
||||
List *l = list_create();
|
||||
Octstr *ret;
|
||||
list_append(l, to);
|
||||
ret = mms_queue_add(from, l, subject, NULL, proxy, 0, expires, msg,NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
dlr, mm4_qdir,
|
||||
settings->host_alias);
|
||||
list_destroy(l, NULL);
|
||||
|
||||
if (ret == NULL) {
|
||||
*error = octstr_format("MM4: Failed to queue message to %S for future tracking. ", to);
|
||||
return MMS_SEND_ERROR_TRANSIENT;
|
||||
if (!msg) {
|
||||
*error = octstr_format("GlobalSend: Failed to send to %S, Message format is corrupt!", to);
|
||||
return MMS_SEND_ERROR_FATAL;
|
||||
}
|
||||
octstr_destroy(ret);
|
||||
}
|
||||
|
||||
|
||||
pto = octstr_format("%S@%S", to, proxy);
|
||||
if (octstr_search_char(from, '@', 0) < 0)
|
||||
pfrom = octstr_format("%S@%S", from, settings->hostname);
|
||||
else
|
||||
pfrom = from;
|
||||
|
||||
xtransid = octstr_format("%S-%s", to,transid);
|
||||
lto = gwlist_create_ex(pto);
|
||||
x = mms_sendtoemail(from, lto,
|
||||
subject ? subject : settings->mms_email_subject,
|
||||
msgid, msg, dlr,
|
||||
error, proxy_sendmail_cmd ? octstr_get_cstr(proxy_sendmail_cmd) : sendmail_cmd,
|
||||
settings->hostname, 0, 0,NULL,NULL,1, octstr_get_cstr(xtransid), extra_headers,
|
||||
settings->smtp_relay, settings->smtp_port);
|
||||
octstr_destroy(xtransid);
|
||||
|
||||
x = mms_sendtoemail(from, pto, subject, msgid, msg, 0,
|
||||
error, sendmail_cmd,
|
||||
settings->hostname, 0, 0,NULL,NULL,0);
|
||||
if (x == MMS_SEND_QUEUED && !dlr) /* No confirmed sending, and message was queued successfully... */
|
||||
x = MMS_SEND_OK; /* we assume fully sent! */
|
||||
|
||||
mms_log2("Sent", from, to,
|
||||
if (x >= 0) /* no error. */
|
||||
mms_log2(x == MMS_SEND_OK ? "Sent" : "Queued", from, pto,
|
||||
-1, msgid, NULL, proxy, "MM4", NULL,NULL);
|
||||
|
||||
octstr_destroy(pto);
|
||||
|
||||
if (pfrom != from)
|
||||
octstr_destroy(pfrom);
|
||||
gwlist_destroy(lto, NULL);
|
||||
return x;
|
||||
}
|
||||
|
||||
|
@ -494,49 +631,54 @@ static int _x_octstr_int_compare(int n, Octstr *s)
|
|||
}
|
||||
|
||||
static int mm7soap_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
|
||||
MmsMsg *m, Octstr **error)
|
||||
List *qh,
|
||||
MmsMsg *m, Octstr **error, int *got_conn_error)
|
||||
{
|
||||
int ret = MMS_SEND_ERROR_TRANSIENT;
|
||||
int mtype = mms_messagetype(m);
|
||||
int hstatus = HTTP_OK, tstatus;
|
||||
List *xto = list_create();
|
||||
List *xto = gwlist_create();
|
||||
MSoapMsg_t *mreq = NULL, *mresp = NULL;
|
||||
List *rh = NULL, *ph = NULL;
|
||||
Octstr *body = NULL, *rbody = NULL, *url = NULL;
|
||||
HTTPCaller *caller = http_caller_create();
|
||||
void *xx;
|
||||
Octstr *s;
|
||||
Octstr *body = NULL, *rbody = NULL;
|
||||
Octstr *uaprof = NULL, *s;
|
||||
time_t tstamp;
|
||||
|
||||
info(0, "MMS Relay: Send[soap] to VASP[%s], msg type [%s], from %s, to %s",
|
||||
mms_info(0, "MM7", vasp->id, "MMS Relay: Send[soap] to VASP[%s], msg_type=[%s], from=[%s], to=[%s]",
|
||||
vasp ? octstr_get_cstr(vasp->id) : "",
|
||||
mms_message_type_to_cstr(mtype), octstr_get_cstr(from), octstr_get_cstr(to));
|
||||
|
||||
list_append(xto, to);
|
||||
gwlist_append(xto, to);
|
||||
|
||||
if (vasp->send_uaprof == UAProf_URL)
|
||||
uaprof = http_header_value(qh, octstr_imm("X-Mbuni-Profile-Url"));
|
||||
else if (vasp->send_uaprof == UAProf_UA)
|
||||
uaprof = http_header_value(qh, octstr_imm("X-Mbuni-User-Agent"));
|
||||
|
||||
if ((s = http_header_value(qh, octstr_imm("X-Mbuni-Timestamp"))) != NULL) {
|
||||
tstamp = strtoul(octstr_get_cstr(s), NULL, 10);
|
||||
octstr_destroy(s);
|
||||
} else
|
||||
tstamp = 0;
|
||||
|
||||
if ((mreq = mm7_mmsmsg_to_soap(m, from, xto, msgId, settings->host_alias,
|
||||
msgId,
|
||||
0, NULL, NULL)) == NULL) {
|
||||
0, NULL, NULL, uaprof, tstamp, NULL)) == NULL) {
|
||||
*error = octstr_format("Failed to convert Msg[%s] 2 SOAP message!",
|
||||
mms_message_type_to_cstr(mtype));
|
||||
goto done1;
|
||||
}
|
||||
|
||||
if (mm7_soapmsg_to_httpmsg(mreq, &rh, &body) < 0) {
|
||||
if (mm7_soapmsg_to_httpmsg(mreq, &vasp->ver, &rh, &body) < 0) {
|
||||
*error = octstr_format("Failed to convert SOAP message 2 HTTP Msg!");
|
||||
goto done1;
|
||||
}
|
||||
|
||||
if (vasp->mmsc_username)
|
||||
http_add_basic_auth(rh, vasp->mmsc_username,
|
||||
vasp->mmsc_password ? vasp->mmsc_password : octstr_imm(""));
|
||||
|
||||
http_start_request(caller, HTTP_METHOD_POST, vasp->vasp_url, rh, body, 1, NULL, NULL);
|
||||
|
||||
if ((xx = http_receive_result(caller, &hstatus, &url, &ph, &rbody)) == NULL ||
|
||||
hstatus != HTTP_OK) {
|
||||
*error = octstr_format("Failed to contact VASP[url=%s] => HTTP returned status = %d, id=%s !",
|
||||
octstr_get_cstr(vasp->vasp_url), hstatus, xx ? "Ok" : "not OK");
|
||||
hstatus = mms_url_fetch_content(HTTP_METHOD_POST, vasp->vasp_url, rh, body, &ph, &rbody);
|
||||
*got_conn_error = (hstatus < 0);
|
||||
if (http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) {
|
||||
*error = octstr_format("Failed to contact VASP[url=%s] => HTTP returned status = %d!",
|
||||
octstr_get_cstr(vasp->vasp_url), hstatus);
|
||||
goto done1;
|
||||
}
|
||||
|
||||
|
@ -557,7 +699,7 @@ static int mm7soap_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
|
|||
if (!MM7_SOAP_STATUS_OK(tstatus)) {
|
||||
Octstr *detail = mm7_soap_header_value(mresp, octstr_imm("Details"));
|
||||
ret = MMS_SEND_ERROR_FATAL;
|
||||
info(0, "Send to VASP[%s], failed, code=[%d=>%s], detail=%s",
|
||||
mms_info(0, "MM7", vasp->id, "Send to VASP[%s], failed, code=[%d=>%s], detail=%s",
|
||||
vasp ? octstr_get_cstr(vasp->id) : "",
|
||||
tstatus, mms_soap_status_to_cstr(tstatus),
|
||||
detail ? octstr_get_cstr(detail) : "");
|
||||
|
@ -572,44 +714,37 @@ static int mm7soap_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgId,
|
|||
} else
|
||||
ret = MMS_SEND_OK;
|
||||
|
||||
info(0, "Sent to VASP[%s], code=[%d=>%s]", octstr_get_cstr(vasp->id),
|
||||
mms_info(0, "MM7", vasp->id, "Sent to VASP[%s], code=[%d=>%s]", octstr_get_cstr(vasp->id),
|
||||
tstatus, mms_soap_status_to_cstr(tstatus));
|
||||
done1:
|
||||
|
||||
if (mreq)
|
||||
|
||||
mm7_soap_destroy(mreq);
|
||||
if (mresp)
|
||||
mm7_soap_destroy(mresp);
|
||||
if (rh)
|
||||
http_destroy_headers(rh);
|
||||
if (body)
|
||||
|
||||
octstr_destroy(body);
|
||||
if (ph)
|
||||
http_destroy_headers(ph);
|
||||
if (rbody)
|
||||
|
||||
octstr_destroy(rbody);
|
||||
if (url)
|
||||
octstr_destroy(url);
|
||||
http_caller_destroy(caller);
|
||||
list_destroy(xto, NULL);
|
||||
octstr_destroy(uaprof);
|
||||
gwlist_destroy(xto, NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mm7eaif_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgid,
|
||||
MmsMsg *m, Octstr **error)
|
||||
MmsMsg *m, Octstr **error, int *got_conn_error)
|
||||
{
|
||||
int ret = MMS_SEND_ERROR_TRANSIENT;
|
||||
int mtype = mms_messagetype(m);
|
||||
int hstatus = HTTP_OK;
|
||||
List *rh = http_create_empty_headers(), *ph = NULL;
|
||||
Octstr *body = NULL, *rbody = NULL, *url = NULL;
|
||||
HTTPCaller *caller = http_caller_create();
|
||||
void *xx;
|
||||
Octstr *body = NULL, *rbody = NULL, *url = NULL, *xver;
|
||||
char *msgtype;
|
||||
|
||||
|
||||
info(0, "MMS Relay: Send [eaif] to VASP[%s], msg type [%s], from %s, to %s",
|
||||
mms_info(0, "MM7", vasp->id, "MMS Relay: Send [eaif] to VASP[%s], msg_type=[%s], from=[%s], to=[%s]",
|
||||
vasp ? octstr_get_cstr(vasp->id) : "",
|
||||
mms_message_type_to_cstr(mtype), octstr_get_cstr(from), octstr_get_cstr(to));
|
||||
|
||||
|
@ -617,34 +752,37 @@ static int mm7eaif_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgid,
|
|||
http_header_add(rh, "X-NOKIA-MMSC-From", octstr_get_cstr(from));
|
||||
if (msgid)
|
||||
http_header_add(rh, "X-NOKIA-MMSC-Message-Id", octstr_get_cstr(msgid));
|
||||
http_header_add(rh, "X-NOKIA-MMSC-Version", EAIF_VERSION);
|
||||
|
||||
if (mtype == MMS_MSGTYPE_SEND_REQ)
|
||||
xver = octstr_format(EAIF_VERSION, vasp->ver.major, vasp->ver.minor1);
|
||||
http_header_add(rh, "X-NOKIA-MMSC-Version", octstr_get_cstr(xver));
|
||||
octstr_destroy(xver);
|
||||
|
||||
if (mtype == MMS_MSGTYPE_SEND_REQ ||
|
||||
mtype == MMS_MSGTYPE_RETRIEVE_CONF) {
|
||||
msgtype = "MultiMediaMessage";
|
||||
else if (mtype == MMS_MSGTYPE_DELIVERY_IND)
|
||||
|
||||
mms_make_sendreq(m); /* ensure it is a sendreq. */
|
||||
|
||||
} else if (mtype == MMS_MSGTYPE_DELIVERY_IND)
|
||||
msgtype = "DeliveryReport";
|
||||
else
|
||||
msgtype = "ReadReply";
|
||||
http_header_add(rh, "X-NOKIA-MMSC-Message-Type", msgtype);
|
||||
http_header_add(rh, "Content-Type", "application/vnd.wap.mms-message");
|
||||
|
||||
if (vasp->mmsc_username)
|
||||
http_add_basic_auth(rh, vasp->mmsc_username,
|
||||
vasp->mmsc_password ? vasp->mmsc_password : octstr_imm(""));
|
||||
|
||||
body = mms_tobinary(m);
|
||||
http_start_request(caller, HTTP_METHOD_POST, vasp->vasp_url, rh, body, 1, NULL, NULL);
|
||||
|
||||
if ((xx = http_receive_result(caller, &hstatus, &url, &ph, &rbody)) == NULL ||
|
||||
http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) {
|
||||
*error = octstr_format("Failed to contact VASP[url=%s] => HTTP returned status = %d, id=%s !",
|
||||
octstr_get_cstr(vasp->vasp_url), hstatus, xx ? "Ok" : "not OK");
|
||||
hstatus = mms_url_fetch_content(HTTP_METHOD_POST, vasp->vasp_url, rh, body, &ph, &rbody);
|
||||
if (http_status_class(hstatus) != HTTP_STATUS_SUCCESSFUL) {
|
||||
*error = octstr_format("Failed to contact VASP[url=%s] => HTTP returned status = %d!",
|
||||
octstr_get_cstr(vasp->vasp_url), hstatus);
|
||||
} else
|
||||
info(0, "Sent to VASP[%s], code=[%d]", octstr_get_cstr(vasp->id), hstatus);
|
||||
mms_info(0, "MM7", vasp->id, "Sent to VASP[%s], code=[%d]", octstr_get_cstr(vasp->id), hstatus);
|
||||
|
||||
if (hstatus < 0)
|
||||
if (hstatus < 0) {
|
||||
ret = MMS_SEND_ERROR_TRANSIENT;
|
||||
else {
|
||||
*got_conn_error = (hstatus < 0);
|
||||
} else {
|
||||
hstatus = http_status_class(hstatus);
|
||||
if (hstatus == HTTP_STATUS_CLIENT_ERROR)
|
||||
ret = MMS_SEND_ERROR_TRANSIENT;
|
||||
|
@ -654,31 +792,50 @@ static int mm7eaif_send(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgid,
|
|||
ret = MMS_SEND_OK;
|
||||
}
|
||||
|
||||
if (rh)
|
||||
|
||||
http_destroy_headers(rh);
|
||||
if (body)
|
||||
octstr_destroy(body);
|
||||
if (ph)
|
||||
http_destroy_headers(ph);
|
||||
if (rbody)
|
||||
octstr_destroy(rbody);
|
||||
if (url)
|
||||
octstr_destroy(url);
|
||||
http_caller_destroy(caller);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mms_sendtovasp(MmsVasp *vasp, Octstr *from, Octstr *to, Octstr *msgid,
|
||||
List *qh,
|
||||
MmsMsg *m, Octstr **err)
|
||||
{
|
||||
if (vasp->type == SOAP_VASP)
|
||||
return mm7soap_send(vasp, from, to, msgid, m, err);
|
||||
int ret, conn_err = 0;
|
||||
if (m == NULL) {
|
||||
*err = octstr_format("GlobalSend: Failed to send to %S, Message format is corrupt!", to);
|
||||
ret = MMS_SEND_ERROR_FATAL;
|
||||
} else if (vasp->type == SOAP_VASP)
|
||||
ret = mm7soap_send(vasp, from, to, msgid, qh, m, err, &conn_err);
|
||||
else if (vasp->type == EAIF_VASP)
|
||||
return mm7eaif_send(vasp, from, to, msgid, m, err);
|
||||
ret = mm7eaif_send(vasp, from, to, msgid, m, err, &conn_err);
|
||||
else {
|
||||
error(0, "Vasp[%s] of unknown type, can't send!",
|
||||
mms_error(0, "MM7", vasp->id, "Vasp[%s] of unknown type, can't send!",
|
||||
vasp->id ? octstr_get_cstr(vasp->id) : "");
|
||||
return MMS_SEND_ERROR_FATAL;
|
||||
ret = MMS_SEND_ERROR_FATAL;
|
||||
}
|
||||
|
||||
if (ret < 0) /* failed. */
|
||||
vasp->stats.mt_errors++;
|
||||
|
||||
if (!conn_err) {
|
||||
vasp->stats.mt_pdus++;
|
||||
vasp->stats.last_pdu = time(NULL);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int match_short_codes(Octstr *phonenum, long short_codes[], int num_codes)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i<num_codes;i++)
|
||||
if (_x_octstr_int_compare(short_codes[i], phonenum) == 0)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -4,76 +4,58 @@
|
|||
* MMS client sender: notifications/reports to clients via WAP Push,
|
||||
* manages out-going messages.
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#include "mmsrelay.h"
|
||||
#include "mmsc.h"
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <strings.h>
|
||||
|
||||
#define WAPPUSH_PORT 2948
|
||||
|
||||
|
||||
static HTTPCaller *httpcaller;
|
||||
static MmsEnvelope edummy;
|
||||
|
||||
|
||||
static MmsEnvelope *update_env_success(MmsEnvelope *env, MmsEnvelopeTo *xto)
|
||||
static MmsEnvelope *update_env(MmsEnvelope *e, MmsEnvelopeTo *xto, int success)
|
||||
{
|
||||
time_t tnow = time(NULL);
|
||||
|
||||
if (xto && !(env->msgtype == MMS_MSGTYPE_SEND_REQ ||
|
||||
env->msgtype == MMS_MSGTYPE_RETRIEVE_CONF))
|
||||
xto->process = 0; /* No more processing. */
|
||||
else {
|
||||
env->lasttry = tnow;
|
||||
env->attempts++;
|
||||
env->sendt = env->lasttry + settings->send_back_off * env->attempts;
|
||||
}
|
||||
if (success && xto &&
|
||||
e->msgtype != MMS_MSGTYPE_SEND_REQ &&
|
||||
e->msgtype != MMS_MSGTYPE_RETRIEVE_CONF)
|
||||
xto->process = 0; /* No more processing, unless it is a SEND/RETRIEVE */
|
||||
|
||||
if (mms_queue_update(env) == 1)
|
||||
env = NULL;
|
||||
return env;
|
||||
e->lasttry = tnow;
|
||||
e->attempts++;
|
||||
e->sendt = tnow + settings->send_back_off * e->attempts;
|
||||
|
||||
if (settings->qfs->mms_queue_update(e) == 1)
|
||||
e = NULL;
|
||||
|
||||
return e;
|
||||
}
|
||||
|
||||
static MmsEnvelope *update_env_failed(MmsEnvelope *env)
|
||||
{
|
||||
time_t tnow = time(NULL);
|
||||
if (env && env != &edummy) {
|
||||
env->sendt = tnow + settings->send_back_off;
|
||||
env->lasttry = tnow;
|
||||
|
||||
if (mms_queue_update(env) == 1)
|
||||
env = NULL;
|
||||
}
|
||||
return env;
|
||||
}
|
||||
|
||||
static void start_push(Octstr *rcpt_to, int isphonenum, MmsEnvelope *e, MmsMsg *msg)
|
||||
static void do_mm1_push(Octstr *rcpt_to, int isphonenum, MmsEnvelope *e, MmsMsg *msg)
|
||||
{
|
||||
List *pheaders;
|
||||
static unsigned char ct; /* Transaction counter -- do we need it? */
|
||||
Octstr *to = NULL;
|
||||
|
||||
Octstr *pduhdr = octstr_create("");
|
||||
|
||||
Octstr *s = NULL;
|
||||
|
||||
|
||||
info(0, "mms2mobile.startpush: notification to %s\n", octstr_get_cstr(rcpt_to));
|
||||
|
||||
if (!rcpt_to) {
|
||||
error(0, "mobilesender: Queue entry %s has no recipient address!", e->xqfname);
|
||||
mms_error(0, "MM1", NULL, "mobilesender: Queue entry %s has no recipient address!", e->xqfname);
|
||||
goto done;
|
||||
} else
|
||||
to = octstr_duplicate(rcpt_to);
|
||||
|
||||
|
||||
ct++;
|
||||
octstr_append_char(pduhdr, ct);
|
||||
octstr_append_char(pduhdr, 0x06); /* Pushd id */
|
||||
octstr_append_char(pduhdr, ct); /* Pushd id */
|
||||
octstr_append_char(pduhdr, 0x06); /* PUSH */
|
||||
|
||||
|
||||
#if 1
|
||||
|
@ -81,44 +63,50 @@ static void start_push(Octstr *rcpt_to, int isphonenum, MmsEnvelope *e, MmsMsg *
|
|||
octstr_append_char(pduhdr, 0xbe); /* content type. */
|
||||
#else
|
||||
octstr_append_char(pduhdr,
|
||||
1 + 1 + sizeof "application/vnd.wap.mms-message"); /*header length. */
|
||||
1 + 1 + strlen("application/vnd.wap.mms-message") + 1); /*header length. */
|
||||
octstr_append_cstr(pduhdr, "application/vnd.wap.mms-message");
|
||||
octstr_append_char(pduhdr, 0x0); /* string terminator. */
|
||||
#endif
|
||||
octstr_append_char(pduhdr, 0xaf); /* charset. */
|
||||
octstr_append_char(pduhdr, 0xaf); /* push application ID header and value follows. */
|
||||
octstr_append_char(pduhdr, 0x84); /* ... */
|
||||
|
||||
s = mms_tobinary(msg);
|
||||
|
||||
if (isphonenum) {
|
||||
Octstr *url;
|
||||
|
||||
octstr_url_encode(to);
|
||||
octstr_url_encode(s);
|
||||
#if 0
|
||||
octstr_dump(pduhdr, 0);
|
||||
#endif
|
||||
|
||||
octstr_url_encode(pduhdr);
|
||||
|
||||
url = octstr_format("%S&text=%S%S&to=%S&udh=%%06%%05%%04%%0B%%84%%23%%F0",
|
||||
Octstr *url = octstr_format("%S&text=%E%E&to=%E&udh=%%06%%05%%04%%0B%%84%%23%%F0",
|
||||
settings->sendsms_url, pduhdr, s, to);
|
||||
int status;
|
||||
List *rph = NULL;
|
||||
Octstr *rbody = NULL;
|
||||
MmsEnvelopeTo *xto = gwlist_get(e->to, 0);
|
||||
|
||||
pheaders = http_create_empty_headers();
|
||||
http_header_add(pheaders, "Connection", "close");
|
||||
http_header_add(pheaders, "User-Agent", MM_NAME "/" MMSC_VERSION);
|
||||
|
||||
http_start_request(httpcaller, HTTP_METHOD_GET, url,
|
||||
pheaders, NULL, 0, e, NULL);
|
||||
if ((status = mms_url_fetch_content(HTTP_METHOD_GET, url, pheaders, NULL, &rph, &rbody)) < 0 ||
|
||||
http_status_class(status) != HTTP_STATUS_SUCCESSFUL) {
|
||||
|
||||
mms_error(0, "MM1", NULL, " Push[%s] from %s, to %s, failed, HTTP code => %d", e->xqfname,
|
||||
octstr_get_cstr(e->from), octstr_get_cstr(to), status);
|
||||
|
||||
e = update_env(e,xto,0);
|
||||
} else { /* Successful push. */
|
||||
|
||||
mms_log2("Notify", octstr_imm("system"), to,
|
||||
-1, e ? e->msgId : NULL, NULL, NULL, "MM1", NULL,NULL);
|
||||
e = update_env(e, xto, 1);
|
||||
}
|
||||
|
||||
http_destroy_headers(pheaders);
|
||||
http_destroy_headers(rph);
|
||||
octstr_destroy(rbody);
|
||||
octstr_destroy(url);
|
||||
} else { /* An IP Address: Send packet, forget. */
|
||||
Octstr *addr = udp_create_address(to, WAPPUSH_PORT);
|
||||
int sock = udp_client_socket();
|
||||
MmsEnvelopeTo *xto = gwlist_get(e->to,0);
|
||||
|
||||
if (sock > 0) {
|
||||
MmsEnvelopeTo *xto = list_get(e->to,0);
|
||||
octstr_append(pduhdr, s);
|
||||
#if 0
|
||||
octstr_dump(pduhdr, 0);
|
||||
|
@ -128,100 +116,28 @@ static void start_push(Octstr *rcpt_to, int isphonenum, MmsEnvelope *e, MmsMsg *
|
|||
mms_log2("Notify", octstr_imm("system"), to,
|
||||
-1, e ? e->msgId : NULL,
|
||||
NULL, NULL, "MM1", NULL,NULL);
|
||||
e = update_env_success(e, xto);
|
||||
e = update_env(e, xto, 1);
|
||||
} else {
|
||||
e = update_env_failed(e);
|
||||
error(0, "push to %s:%d failed, no reason found", octstr_get_cstr(to), WAPPUSH_PORT);
|
||||
e = update_env(e, xto, 0);
|
||||
mms_error(0, "MM1", NULL, "push to %s:%d failed: %s",
|
||||
octstr_get_cstr(to), WAPPUSH_PORT, strerror(errno));
|
||||
}
|
||||
octstr_destroy(addr);
|
||||
if (e)
|
||||
mms_queue_free_env(e);
|
||||
}
|
||||
done:
|
||||
if (to) octstr_destroy(to);
|
||||
if (pduhdr) octstr_destroy(pduhdr);
|
||||
if (s) octstr_destroy(s);
|
||||
}
|
||||
octstr_destroy(to);
|
||||
octstr_destroy(pduhdr);
|
||||
octstr_destroy(s);
|
||||
|
||||
|
||||
static int receive_push_reply(HTTPCaller *caller)
|
||||
{
|
||||
int http_status;
|
||||
List *reply_headers;
|
||||
Octstr *final_url, *reply_body;
|
||||
|
||||
MmsEnvelope *env;
|
||||
|
||||
http_status = HTTP_UNAUTHORIZED;
|
||||
|
||||
while ((env = http_receive_result(caller, &http_status, &final_url, &reply_headers,
|
||||
&reply_body)) != NULL) {
|
||||
MmsEnvelopeTo *xto = NULL;
|
||||
Octstr *to = NULL;
|
||||
|
||||
if (http_status == -1 || final_url == NULL) {
|
||||
error(0, "push failed, no reason found");
|
||||
goto push_failed;
|
||||
}
|
||||
|
||||
if (env == &edummy) /* Skip this one it is a dummy. */
|
||||
goto push_free_env;
|
||||
xto = list_get(env->to, 0);
|
||||
if (xto)
|
||||
to = xto->rcpt;
|
||||
else {
|
||||
error(0, "mobilesender: Queue entry %s has no recipient address!", env->xqfname);
|
||||
goto push_failed;
|
||||
}
|
||||
|
||||
info(0, "send2mobile.push_reply[%s]: From %s, to %s => %d",
|
||||
env->xqfname,
|
||||
octstr_get_cstr(env->from), octstr_get_cstr(to), http_status);
|
||||
|
||||
if (http_status == HTTP_UNAUTHORIZED ||
|
||||
http_status == HTTP_NOT_FOUND ||
|
||||
http_status == HTTP_FORBIDDEN) { /* This is a temporary system error
|
||||
* do not increase attempts, count,
|
||||
* merely reschedule
|
||||
* for a minute or so later.
|
||||
*/
|
||||
|
||||
error(0, "Deffered notification, WAP Push failed for "
|
||||
"msgid %s to %s, http error: %d!", octstr_get_cstr(env->msgId),
|
||||
octstr_get_cstr(to), http_status);
|
||||
goto push_failed;
|
||||
}
|
||||
|
||||
|
||||
debug("mobilesender.push", 0, "Push reply headers were");
|
||||
http_header_dump(reply_headers);
|
||||
|
||||
mms_log2("Notify", octstr_imm("system"), to,
|
||||
-1, env ? env->msgId : NULL, NULL, NULL, "MM1", NULL,NULL);
|
||||
|
||||
if ((env = update_env_success(env, xto)) != NULL)
|
||||
goto push_free_env;
|
||||
|
||||
/* Fall through. */
|
||||
push_failed:
|
||||
octstr_destroy(final_url);
|
||||
octstr_destroy(reply_body);
|
||||
http_destroy_headers(reply_headers);
|
||||
|
||||
env = update_env_failed(env);
|
||||
push_free_env:
|
||||
if (env && env != &edummy)
|
||||
mms_queue_free_env(env);
|
||||
}
|
||||
|
||||
return 0;
|
||||
if (e)
|
||||
settings->qfs->mms_queue_free_env(e);
|
||||
}
|
||||
|
||||
static int sendNotify(MmsEnvelope *e)
|
||||
{
|
||||
Octstr *to;
|
||||
MmsMsg *msg, *smsg = NULL;
|
||||
MmsEnvelopeTo *xto = list_get(e->to, 0);
|
||||
MmsMsg *smsg = NULL;
|
||||
MmsEnvelopeTo *xto = gwlist_get(e->to, 0);
|
||||
Octstr *err = NULL;
|
||||
time_t tnow = time(NULL);
|
||||
int j, k, len;
|
||||
|
@ -232,19 +148,22 @@ static int sendNotify(MmsEnvelope *e)
|
|||
char *prov_notify_event = NULL;
|
||||
char *rtype = NULL;
|
||||
|
||||
#if 0 /* ... because we don't want fetched messages sticking around in queue forever */
|
||||
|
||||
if (e->lastaccess != 0) { /* This message has been fetched at least once, no more signals. */
|
||||
e->sendt = e->expiryt + 3600*24*30*12;
|
||||
return mms_queue_update(e);
|
||||
|
||||
mms_info(0, "MM1", NULL, "Message [ID: %s] fetched/touched at least once. Skipping",
|
||||
e->xqfname);
|
||||
return settings->qfs->mms_queue_update(e);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!xto) {
|
||||
error(0, "mobilesender: Queue entry %s with no recipients!",
|
||||
mms_error(0, "MM1", NULL, "mobilesender: Queue entry %s with no recipients!",
|
||||
e->xqfname);
|
||||
return 0;
|
||||
}
|
||||
|
||||
msg = mms_queue_getdata(e);
|
||||
to = octstr_duplicate(xto->rcpt);
|
||||
expiryt = e->expiryt;
|
||||
msgId = e->msgId ? octstr_duplicate(e->msgId) : NULL;
|
||||
|
@ -252,31 +171,50 @@ static int sendNotify(MmsEnvelope *e)
|
|||
fromproxy = e->fromproxy ? octstr_duplicate(e->fromproxy) : NULL;
|
||||
msize = e->msize;
|
||||
dlr = e->dlr;
|
||||
mtype = e->msgtype;
|
||||
|
||||
if (e->expiryt != 0 && /* Handle message expiry. */
|
||||
e->expiryt < tnow) {
|
||||
err = octstr_format("MMSC error: Message expired while sending to %S!", to);
|
||||
err = octstr_format("MM1 error: Message expired while sending to %S!", to);
|
||||
res = MMS_SEND_ERROR_FATAL;
|
||||
prov_notify_event = "failedfetch";
|
||||
rtype = "Expired";
|
||||
goto done;
|
||||
} else if (e->attempts >= settings->maxsendattempts) {
|
||||
err = octstr_format("MMSC error: Failed to deliver to %S after %ld attempts!",
|
||||
to, e->attempts);
|
||||
res = MMS_SEND_ERROR_FATAL;
|
||||
} else if (e->attempts >= settings->mm1_maxsendattempts) {
|
||||
err = octstr_format("MM1: Maximum delivery attempts [%d] to %S reached. Delivery suspended!",
|
||||
e->attempts, to);
|
||||
res = MMS_SEND_OK;
|
||||
|
||||
e->sendt = e->expiryt + 1; /* no retry until expiry */
|
||||
if (settings->qfs->mms_queue_update(e) != 1)
|
||||
settings->qfs->mms_queue_free_env(e);
|
||||
e = NULL;
|
||||
goto done;
|
||||
|
||||
} else if (e->lastaccess != 0) {
|
||||
e->sendt = e->expiryt + 1;
|
||||
res = MMS_SEND_OK;
|
||||
err = octstr_create("Skipped");
|
||||
|
||||
mms_info(0, "MM1", NULL, "Message [ID: %s] fetched/touched at least once. Skipping",
|
||||
e->xqfname);
|
||||
if (settings->qfs->mms_queue_update(e) != 1)
|
||||
settings->qfs->mms_queue_free_env(e);
|
||||
e = NULL;
|
||||
|
||||
prov_notify_event = "failedfetch";
|
||||
rtype = "Expired";
|
||||
goto done;
|
||||
}
|
||||
|
||||
|
||||
j = octstr_case_search(to, octstr_imm("/TYPE=PLMN"), 0);
|
||||
k = octstr_case_search(to, octstr_imm("/TYPE=IPv"), 0);
|
||||
len = octstr_len(to);
|
||||
|
||||
if (j > 0 && j - 1 + sizeof "/TYPE=PLMN" == len) { /* A proper number. */
|
||||
phonenum = octstr_copy(to, 0, j);
|
||||
normalize_number(octstr_get_cstr(settings->unified_prefix), &phonenum);
|
||||
mms_normalize_phonenum(&phonenum,
|
||||
octstr_get_cstr(settings->unified_prefix),
|
||||
settings->strip_prefixes);
|
||||
} else if (k > 0 && k + sizeof "/TYPE=IPv" == len)
|
||||
rcpt_ip = octstr_copy(to, 0, k);
|
||||
else {
|
||||
|
@ -286,7 +224,6 @@ static int sendNotify(MmsEnvelope *e)
|
|||
goto done;
|
||||
}
|
||||
|
||||
mtype = mms_messagetype(msg);
|
||||
|
||||
/* For phone, getting here means the message can be delivered. So:
|
||||
* - Check whether the recipient is provisioned, if not, wait (script called will queue creation req)
|
||||
|
@ -317,41 +254,45 @@ static int sendNotify(MmsEnvelope *e)
|
|||
e->lasttry = tnow;
|
||||
e->sendt = e->lasttry + settings->send_back_off * (1 + e->attempts);
|
||||
|
||||
if (mms_queue_update(e) == 1)
|
||||
if (settings->qfs->mms_queue_update(e) == 1)
|
||||
e = NULL; /* Queue entry gone. */
|
||||
else
|
||||
mms_queue_free_env(e);
|
||||
settings->qfs->mms_queue_free_env(e);
|
||||
goto done;
|
||||
} else if (send_ind == 0) { /* provisioned but does not support */
|
||||
Octstr *s = octstr_format(octstr_get_cstr(settings->mms_notify_txt),
|
||||
from);
|
||||
if (s && octstr_len(s) > 0) { /* Only send if the string was set. */
|
||||
List *pheaders;
|
||||
Octstr *sto = octstr_duplicate(phonenum);
|
||||
if (settings->notify_unprovisioned && s && octstr_len(s) > 0) { /* Only send if the string was set. */
|
||||
List *pheaders = http_create_empty_headers(), *rph = NULL;
|
||||
Octstr *rbody = NULL;
|
||||
int status;
|
||||
|
||||
octstr_url_encode(s);
|
||||
octstr_url_encode(sto);
|
||||
url = octstr_format("%S&text=%E&to=%E",settings->sendsms_url,s, phonenum);
|
||||
|
||||
url = octstr_format("%S&text=%S&to=%S",settings->sendsms_url,s, sto);
|
||||
pheaders = http_create_empty_headers();
|
||||
http_header_add(pheaders, "Connection", "close");
|
||||
http_header_add(pheaders, "User-Agent", MM_NAME "/" VERSION);
|
||||
|
||||
http_start_request(httpcaller, HTTP_METHOD_GET, url,
|
||||
pheaders, NULL, 0, &edummy, NULL);
|
||||
if ((status = mms_url_fetch_content(HTTP_METHOD_GET, url,
|
||||
pheaders, NULL, &rph, &rbody)) <0 ||
|
||||
http_status_class(status) != HTTP_STATUS_SUCCESSFUL)
|
||||
mms_error(0, "MM1", NULL, "Notify unprovisioned url fetch failed => %d", status);
|
||||
|
||||
http_destroy_headers(pheaders);
|
||||
http_destroy_headers(rph);
|
||||
octstr_destroy(url);
|
||||
octstr_destroy(sto);
|
||||
} else if (s)
|
||||
octstr_destroy(rbody);
|
||||
|
||||
}
|
||||
|
||||
octstr_destroy(s);
|
||||
res = MMS_SEND_OK;
|
||||
err = octstr_imm("No MMS Ind support, sent SMS instead");
|
||||
|
||||
xto->process = 0; /* No more processing. */
|
||||
if (mms_queue_update(e) == 1)
|
||||
if (settings->qfs->mms_queue_update(e) == 1)
|
||||
e = NULL;
|
||||
else
|
||||
mms_queue_free_env(e);
|
||||
settings->qfs->mms_queue_free_env(e);
|
||||
goto done;
|
||||
|
||||
}
|
||||
|
@ -359,11 +300,13 @@ static int sendNotify(MmsEnvelope *e)
|
|||
|
||||
/* To get here means we can send Ind. */
|
||||
url = mms_makefetchurl(e->xqfname, e->token, MMS_LOC_MQUEUE,
|
||||
to,
|
||||
phonenum ? phonenum : to,
|
||||
settings);
|
||||
mms_info(0, "MM1", NULL, "Preparing to notify client to fetch message at URL: %s",
|
||||
octstr_get_cstr(url));
|
||||
transid = mms_maketransid(e->xqfname, settings->host_alias);
|
||||
|
||||
smsg = mms_notification(msg, e->msize, url, transid,
|
||||
smsg = mms_notification(e->from, e->subject, e->mclass, e->msize, url, transid,
|
||||
e->expiryt ? e->expiryt :
|
||||
tnow + settings->default_msgexpiry,
|
||||
settings->optimize_notification_size);
|
||||
|
@ -371,69 +314,69 @@ static int sendNotify(MmsEnvelope *e)
|
|||
octstr_destroy(url);
|
||||
} else if (mtype == MMS_MSGTYPE_DELIVERY_IND ||
|
||||
mtype == MMS_MSGTYPE_READ_ORIG_IND)
|
||||
smsg = msg;
|
||||
smsg = settings->qfs->mms_queue_getdata(e);
|
||||
else {
|
||||
error(0, "Unexpected message type %s for %s found in MT queue!",
|
||||
mms_error(0, "MM1", NULL, "Unexpected message type [%s] for [%s] found in MT queue!",
|
||||
mms_message_type_to_cstr(mtype), octstr_get_cstr(to));
|
||||
res = MMS_SEND_ERROR_FATAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (smsg)
|
||||
start_push(phonenum ? phonenum : rcpt_ip,
|
||||
if (smsg) {
|
||||
do_mm1_push(phonenum ? phonenum : rcpt_ip,
|
||||
phonenum ? 1 : 0,
|
||||
e, smsg); /* Send the message.
|
||||
* Don't touch 'e' after this point!
|
||||
* It may be freed by receive thread.
|
||||
*/
|
||||
e, smsg); /* Don't touch 'e' after this point. It is gone */
|
||||
e = NULL;
|
||||
}
|
||||
|
||||
if (smsg != msg && smsg)
|
||||
if (smsg)
|
||||
mms_destroy(smsg);
|
||||
|
||||
done:
|
||||
if (err != NULL &&
|
||||
res != MMS_SEND_ERROR_TRANSIENT) { /* If there was a report request and this is a legit error
|
||||
if (e != NULL &&
|
||||
err != NULL &&
|
||||
res != MMS_SEND_ERROR_TRANSIENT && dlr) { /* If there was a report request and this is a legit error
|
||||
* queue it.
|
||||
*/
|
||||
|
||||
if (dlr) {
|
||||
MmsMsg *m = mms_deliveryreport(msgId, to, tnow,
|
||||
MmsMsg *m = mms_deliveryreport(msgId, to, e->from, tnow,
|
||||
rtype ? octstr_imm(rtype) :
|
||||
octstr_imm("Indeterminate"));
|
||||
|
||||
List *l = list_create();
|
||||
List *l = gwlist_create();
|
||||
Octstr *res;
|
||||
list_append(l, from);
|
||||
gwlist_append(l, from);
|
||||
|
||||
/* Add to queue, switch via proxy to be from proxy. */
|
||||
res = mms_queue_add(settings->system_user, l, err,
|
||||
res = settings->qfs->mms_queue_add(to ? to : settings->system_user, l, err,
|
||||
NULL, fromproxy,
|
||||
tnow, tnow+settings->default_msgexpiry, m, NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
NULL,
|
||||
0,
|
||||
octstr_get_cstr(settings->mm1_queuedir),
|
||||
octstr_get_cstr(settings->global_queuedir),
|
||||
"MM2",
|
||||
settings->host_alias);
|
||||
list_destroy(l, NULL);
|
||||
gwlist_destroy(l, NULL);
|
||||
mms_destroy(m);
|
||||
octstr_destroy(res);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Write to log */
|
||||
info(0, "%s Mobile Queue MMS Send Notify: From=%s, to=%s, msgsize=%d, reason=%s",
|
||||
mms_info(0, "MM1", NULL, "%s Mobile Queue MMS Send Notify: From=%s, to=%s, msgsize=%d, reason=%s. Processed in %d secs",
|
||||
SEND_ERROR_STR(res),
|
||||
octstr_get_cstr(from), octstr_get_cstr(to), msize,
|
||||
err ? octstr_get_cstr(err) : "");
|
||||
err ? octstr_get_cstr(err) : "",
|
||||
(int)(time(NULL) - tnow));
|
||||
|
||||
|
||||
if (res == MMS_SEND_ERROR_FATAL) {
|
||||
if (xto && e) {
|
||||
if (res == MMS_SEND_ERROR_FATAL)
|
||||
xto->process = 0; /* No more attempts to deliver, delete this. */
|
||||
if (mms_queue_update(e) == 1)
|
||||
if (settings->qfs->mms_queue_update(e) == 1)
|
||||
e = NULL; /* Queue entry gone. */
|
||||
else
|
||||
mms_queue_free_env(e);
|
||||
settings->qfs->mms_queue_free_env(e);
|
||||
} /* Else queue will be updated/freed elsewhere. */
|
||||
|
||||
|
||||
|
@ -441,37 +384,26 @@ static int sendNotify(MmsEnvelope *e)
|
|||
notify_prov_server(octstr_get_cstr(settings->prov_notify),
|
||||
to ? octstr_get_cstr(to) : "unknown",
|
||||
prov_notify_event,
|
||||
rtype ? rtype : "");
|
||||
rtype ? rtype : "",
|
||||
e ? e->msgId : NULL, NULL, NULL);
|
||||
|
||||
if (msg) mms_destroy(msg);
|
||||
if (phonenum)
|
||||
octstr_destroy(phonenum);
|
||||
if (rcpt_ip)
|
||||
|
||||
octstr_destroy(rcpt_ip);
|
||||
octstr_destroy(to);
|
||||
if (msgId) octstr_destroy(msgId);
|
||||
if (fromproxy) octstr_destroy(fromproxy);
|
||||
octstr_destroy(msgId);
|
||||
octstr_destroy(fromproxy);
|
||||
octstr_destroy(from);
|
||||
if (err) octstr_destroy(err);
|
||||
octstr_destroy(err);
|
||||
|
||||
return 1;
|
||||
return 1; /* Tell caller we dealt with envelope */
|
||||
}
|
||||
|
||||
void mbuni_mm1_queue_runner(int *rstop)
|
||||
void mbuni_mm1_queue_runner(volatile sig_atomic_t *rstop)
|
||||
{
|
||||
httpcaller = http_caller_create();
|
||||
if (gwthread_create((gwthread_func_t *)receive_push_reply, httpcaller) < 0) { /* Listener thread. */
|
||||
error(0, "Mobile sender: Failed to create push reply thread: %d: %s!",
|
||||
errno, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
mms_queue_run(octstr_get_cstr(settings->mm1_queuedir),
|
||||
sendNotify, settings->queue_interval, settings->maxthreads, rstop);
|
||||
sleep(2); /* Wait for it to die. */
|
||||
http_caller_signal_shutdown(httpcaller);
|
||||
sleep(2);
|
||||
http_caller_destroy(httpcaller);
|
||||
settings->qfs->mms_queue_run(octstr_get_cstr(settings->mm1_queuedir),
|
||||
sendNotify, settings->mm1_queue_interval, settings->maxthreads, rstop);
|
||||
gwthread_sleep(2); /* Wait for it to die. */
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -10,85 +10,45 @@
|
|||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#include "mmsrelay.h"
|
||||
|
||||
static mCfg *cfg;
|
||||
MmscSettings *settings;
|
||||
List *proxyrelays;
|
||||
#include "mmsc.h"
|
||||
|
||||
|
||||
static int rstop = 0; /* Set to 1 to stop relay. */
|
||||
static void quit_now(int notused)
|
||||
static long qthread = -1;
|
||||
|
||||
static volatile sig_atomic_t rstop = 0; /* Set to 1 to stop relay. */
|
||||
|
||||
int mmsrelay()
|
||||
{
|
||||
rstop = 1;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int cfidx;
|
||||
Octstr *fname;
|
||||
|
||||
long qthread = 0;
|
||||
|
||||
mms_lib_init();
|
||||
|
||||
srandom(time(NULL));
|
||||
|
||||
cfidx = get_and_set_debugs(argc, argv, NULL);
|
||||
|
||||
if (argv[cfidx] == NULL)
|
||||
fname = octstr_imm("mbuni.conf");
|
||||
else
|
||||
fname = octstr_create(argv[cfidx]);
|
||||
|
||||
cfg = mms_cfg_read(fname);
|
||||
|
||||
if (cfg == NULL)
|
||||
panic(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
|
||||
|
||||
octstr_destroy(fname);
|
||||
|
||||
info(0, "----------------------------------------");
|
||||
info(0, " " MM_NAME " MMSC Relay version %s starting", MMSC_VERSION);
|
||||
|
||||
|
||||
settings = mms_load_mmsc_settings(cfg,&proxyrelays);
|
||||
|
||||
mms_cfg_destroy(cfg);
|
||||
|
||||
if (!settings)
|
||||
panic(0, "No global MMSC configuration!");
|
||||
|
||||
#if 0
|
||||
mms_start_profile_engine(octstr_get_cstr(settings->ua_profile_cache_dir));
|
||||
#endif
|
||||
|
||||
signal(SIGHUP, quit_now);
|
||||
signal(SIGTERM, quit_now);
|
||||
signal(SIGPIPE,SIG_IGN); /* Ignore pipe errors. They kill us sometimes for nothing*/
|
||||
|
||||
if (!(settings->svc_list & (SvcMM1 | SvcRelay))) {
|
||||
mms_info(0, "mmsrelay", NULL, " " MM_NAME " MMSC Relay version %s, no services to be started.", MMSC_VERSION);
|
||||
return 0;
|
||||
} else
|
||||
mms_info(0, "mmsrelay", NULL, " " MM_NAME " MMSC Relay version %s starting", MMSC_VERSION);
|
||||
|
||||
/* Start global queue runner. */
|
||||
info(0, "Starting Global Queue Runner...");
|
||||
qthread = gwthread_create((gwthread_func_t *)mbuni_global_queue_runner, &rstop);
|
||||
|
||||
if (settings->svc_list & SvcRelay) {
|
||||
mms_info(0, "mmsrelay", NULL, "Starting Global Queue Runner...");
|
||||
qthread = gwthread_create((gwthread_func_t *)mbuni_global_queue_runner, (void *)&rstop);
|
||||
}
|
||||
|
||||
if (settings->svc_list & SvcMM1) {
|
||||
/* Start the local queue runner. */
|
||||
info(0, "Starting Local Queue Runner...");
|
||||
mms_info(0, "mmsrelay", NULL,"Starting Local Queue Runner...");
|
||||
mbuni_mm1_queue_runner(&rstop);
|
||||
}
|
||||
|
||||
|
||||
if (qthread >= 0)
|
||||
gwthread_join(qthread); /* Wait for it to die... */
|
||||
mms_info(0, "mmsrelay", NULL, "MMSC Relay MM1 queue runner terminates...");
|
||||
return 0;
|
||||
|
||||
sleep(2);
|
||||
/* It terminates, so start dying... */
|
||||
mms_stop_profile_engine(); /* Stop profile stuff. */
|
||||
}
|
||||
|
||||
sleep(2); /* Wait for them to die. */
|
||||
mms_lib_shutdown();
|
||||
int stop_mmsrelay(void)
|
||||
{
|
||||
rstop = 1;
|
||||
mms_info(0, "mmsrelay", NULL, "Mmsrelay: Queue runners shutdown, cleanup commenced...");
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef __MMSRELAY_INCLUDED__
|
||||
#define __MMSRELAY_INCLUDED__
|
||||
/*
|
||||
* Mbuni - Open Source MMS Gateway
|
||||
*
|
||||
* MMS Relay, implements message routing
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
* This program is free software, distributed under the terms of
|
||||
* the GNU General Public License, with a few exceptions granted (see LICENSE)
|
||||
*/
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include "mms_queue.h"
|
||||
#include "mms_uaprof.h"
|
||||
#include "mmsc_cfg.h"
|
||||
#include "mms_mm7soap.h"
|
||||
|
||||
extern void mbuni_global_queue_runner(int *stopflag);
|
||||
extern void mbuni_mm1_queue_runner(int *stopflag);
|
||||
extern MmscSettings *settings;
|
||||
extern List *proxyrelays;
|
||||
#endif
|
|
@ -3,7 +3,7 @@
|
|||
*
|
||||
* MMS send: Inject message into queue for delivery.
|
||||
*
|
||||
* Copyright (C) 2003 - 2005, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
* Copyright (C) 2003 - 2008, Digital Solutions Ltd. - http://www.dsmagic.com
|
||||
*
|
||||
* Paul Bagyenda <bagyenda@dsmagic.com>
|
||||
*
|
||||
|
@ -20,21 +20,17 @@
|
|||
|
||||
|
||||
static Octstr *from;
|
||||
static Octstr *binfo;
|
||||
static List *to;
|
||||
static Octstr *data;
|
||||
static MmsMsg *m;
|
||||
static int savetommbox;
|
||||
Octstr *mmbox;
|
||||
|
||||
static MmscSettings *settings;
|
||||
|
||||
static int dlr;
|
||||
static int find_own(int i, int argc, char *argv[])
|
||||
{
|
||||
|
||||
if (argv[i][1] == 'f')
|
||||
if (i + 1 < argc) {
|
||||
from = octstr_create(argv[i+1]);
|
||||
_mms_fixup_address(from);
|
||||
return 1;
|
||||
} else
|
||||
return -1;
|
||||
|
@ -43,15 +39,9 @@ static int find_own(int i, int argc, char *argv[])
|
|||
return 0;
|
||||
} else if (argv[i][1] == 't')
|
||||
if (i + 1 < argc) {
|
||||
int j, m;
|
||||
List *l = octstr_split(octstr_create(argv[i+1]),
|
||||
octstr_imm(":"));
|
||||
for (j = 0, m = list_len(l); j < m; j++) {
|
||||
Octstr *x = list_get(l, j);
|
||||
_mms_fixup_address(x);
|
||||
list_append(to, x);
|
||||
}
|
||||
list_destroy(l, NULL);
|
||||
Octstr *x = octstr_create(argv[i+1]);
|
||||
to = octstr_split(x, octstr_imm(":"));
|
||||
octstr_destroy(x);
|
||||
return 1;
|
||||
} else
|
||||
return -1;
|
||||
|
@ -61,14 +51,23 @@ static int find_own(int i, int argc, char *argv[])
|
|||
return 1;
|
||||
} else
|
||||
return -1;
|
||||
|
||||
else if (argv[i][1] == 'r') {
|
||||
dlr = 1;
|
||||
return 0;
|
||||
} else if (argv[i][1] == 'B')
|
||||
if (i + 1 < argc) {
|
||||
binfo = octstr_create(argv[i+1]);
|
||||
return 1;
|
||||
} else
|
||||
return -1;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static mCfg *cfg;
|
||||
|
||||
static MmscSettings *settings;
|
||||
static List *proxyrelays;
|
||||
static MmsMsg *m;
|
||||
Octstr *mmbox;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
@ -77,12 +76,12 @@ int main(int argc, char *argv[])
|
|||
int cfidx;
|
||||
int msize;
|
||||
|
||||
List *h = NULL;
|
||||
|
||||
if (argc < 2)
|
||||
return -1;
|
||||
|
||||
mms_lib_init();
|
||||
to = list_create();
|
||||
srandom(time(NULL));
|
||||
|
||||
cfidx = get_and_set_debugs(argc, argv, find_own);
|
||||
|
||||
|
@ -91,30 +90,39 @@ int main(int argc, char *argv[])
|
|||
else
|
||||
fname = octstr_create(argv[cfidx]);
|
||||
|
||||
cfg = mms_cfg_read(fname);
|
||||
|
||||
if (cfg == NULL)
|
||||
panic(0, "Couldn't read configuration from '%s'.", octstr_get_cstr(fname));
|
||||
|
||||
octstr_destroy(fname);
|
||||
|
||||
info(0, "----------------------------------------");
|
||||
info(0, " MMSC Message sender runner version %s starting", MMSC_VERSION);
|
||||
mms_info(0, "mmssend", NULL, "----------------------------------------");
|
||||
mms_info(0, "mmssend", NULL, " MMSC Message sender runner version %s starting", MMSC_VERSION);
|
||||
|
||||
|
||||
/* Load settings. */
|
||||
settings = mms_load_mmsc_settings(cfg, &proxyrelays);
|
||||
|
||||
mms_cfg_destroy(cfg);
|
||||
settings = mms_load_mmsc_settings(fname, &proxyrelays,1);
|
||||
|
||||
if (!settings)
|
||||
panic(0, "No global MMSC configuration!");
|
||||
panic(0, "No global MMSC configuration, or failed to read conf from <%s>!", octstr_get_cstr(fname));
|
||||
|
||||
octstr_destroy(fname);
|
||||
if (from == NULL ||
|
||||
to == NULL) {
|
||||
error(0, "Sender and recipient addresses required!\n");
|
||||
mms_error(0, "mmssend", NULL, "Sender and recipient addresses required!\n");
|
||||
exit(-1);
|
||||
} else { /* fix up 'to' list */
|
||||
List *l = gwlist_create();
|
||||
Octstr *x;
|
||||
while ((x = gwlist_extract_first(to)) != NULL) {
|
||||
octstr_strip_blanks(x);
|
||||
_mms_fixup_address(&x,
|
||||
settings->unified_prefix ? octstr_get_cstr(settings->unified_prefix) : NULL,
|
||||
settings->strip_prefixes, 1);
|
||||
gwlist_append(l, x);
|
||||
}
|
||||
gwlist_destroy(to, NULL);
|
||||
to = l;
|
||||
}
|
||||
|
||||
/* fix from address. */
|
||||
_mms_fixup_address(&from,
|
||||
settings->unified_prefix ? octstr_get_cstr(settings->unified_prefix) : NULL,
|
||||
settings->strip_prefixes, 1);
|
||||
|
||||
#if 0
|
||||
mms_start_profile_engine(octstr_get_cstr(settings->ua_profile_cache_dir));
|
||||
|
@ -130,7 +138,9 @@ int main(int argc, char *argv[])
|
|||
mime_entity_destroy(mime);
|
||||
}
|
||||
} else
|
||||
m = mms_frombinary(data, from ? from : octstr_imm("anon@anon"));
|
||||
m = mms_frombinary_ex(data, from ? from : octstr_imm("anon@anon"),
|
||||
octstr_get_cstr(settings->unified_prefix),
|
||||
settings->strip_prefixes);
|
||||
if (m)
|
||||
mms_msgdump(m,1);
|
||||
msize = octstr_len(data);
|
||||
|
@ -140,24 +150,38 @@ int main(int argc, char *argv[])
|
|||
if (!m)
|
||||
panic(0, "No Message supplied, or failed to decode binary data!");
|
||||
|
||||
s = mms_queue_add(from, to, NULL, NULL, NULL, time(NULL),
|
||||
|
||||
h = http_create_empty_headers();
|
||||
http_header_add(h, "X-Mbuni-Tool", "mmssend");
|
||||
http_header_add(h, "X-Mbuni-CalledFrom", "Terminal");
|
||||
|
||||
if (binfo) {
|
||||
mms_info(0, "add.info", NULL, "Adding extra headers billing info `X-Mms-Binfo' :");
|
||||
http_header_add(h, "X-Mms-Binfo", octstr_get_cstr(binfo));
|
||||
}
|
||||
s = settings->qfs->mms_queue_add(from, to, NULL, NULL, NULL, time(NULL),
|
||||
time(NULL) + settings->default_msgexpiry, m,
|
||||
NULL,
|
||||
NULL, NULL,
|
||||
NULL, NULL,
|
||||
0,
|
||||
h,
|
||||
dlr,
|
||||
octstr_get_cstr(settings->global_queuedir),
|
||||
"MM3",
|
||||
settings->host_alias);
|
||||
|
||||
if (savetommbox)
|
||||
mmbox = mms_mmbox_addmsg(octstr_get_cstr(settings->mmbox_rootdir),
|
||||
octstr_get_cstr(from), m, NULL, octstr_imm("Sent"));
|
||||
|
||||
mms_log("Received", from, to, msize, s, NULL, NULL, "mmssend",NULL,NULL);
|
||||
mms_log("Received", from, to, msize, s, NULL, NULL, "MM3",NULL,NULL);
|
||||
|
||||
printf("Queued: %s, mmbox=%s\n",
|
||||
octstr_get_cstr(s), mmbox ? octstr_get_cstr(mmbox) : "");
|
||||
octstr_destroy(s);
|
||||
|
||||
http_destroy_headers(h);
|
||||
mms_cleanup_mmsc_settings(settings);
|
||||
mms_lib_shutdown();
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -3,6 +3,4 @@
|
|||
- Need to parameterise some values: response messages (say on failed content adaptation)
|
||||
- Test suite
|
||||
- Correct handling of unrecognised mms headers. spec says pass them un-changed.
|
||||
- Queue module needs to be de-coupled slightly from storage, so that mmsproxy can run on a separate box
|
||||
but be able to initiate queue writes/reads over network. Hence pieces can run on separate boxes
|
||||
(with mmsrelay providing network service for queue functions)
|
||||
- Generalise billing interface
|
||||
|
|
Loading…
Reference in New Issue