Public release of subscriberRegistry.
git-svn-id: http://wush.net/svn/range/software/public/subscriberRegistry/trunk@2243 19bc5d8c-e614-43d4-8b26-e1612bc8e597
This commit is contained in:
commit
da6f7ad541
|
@ -0,0 +1,724 @@
|
|||
GNU AFFERO GENERAL PUBLIC LICENSE
|
||||
Version 3, 19 November 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU Affero General Public License is a free, copyleft license for
|
||||
software and other kinds of works, specifically designed to ensure
|
||||
cooperation with the community in the case of network server software.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
our General Public Licenses are intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users.
|
||||
|
||||
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
|
||||
them 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.
|
||||
|
||||
Developers that use our General Public Licenses protect your rights
|
||||
with two steps: (1) assert copyright on the software, and (2) offer
|
||||
you this License which gives you legal permission to copy, distribute
|
||||
and/or modify the software.
|
||||
|
||||
A secondary benefit of defending all users' freedom is that
|
||||
improvements made in alternate versions of the program, if they
|
||||
receive widespread use, become available for other developers to
|
||||
incorporate. Many developers of free software are heartened and
|
||||
encouraged by the resulting cooperation. However, in the case of
|
||||
software used on network servers, this result may fail to come about.
|
||||
The GNU General Public License permits making a modified version and
|
||||
letting the public access it on a server without ever releasing its
|
||||
source code to the public.
|
||||
|
||||
The GNU Affero General Public License is designed specifically to
|
||||
ensure that, in such cases, the modified source code becomes available
|
||||
to the community. It requires the operator of a network server to
|
||||
provide the source code of the modified version running there to the
|
||||
users of that server. Therefore, public use of a modified version, on
|
||||
a publicly accessible server, gives the public access to the source
|
||||
code of the modified version.
|
||||
|
||||
An older license, called the Affero General Public License and
|
||||
published by Affero, was designed to accomplish similar goals. This is
|
||||
a different license, not a version of the Affero GPL, but Affero has
|
||||
released a new version of the Affero GPL which permits relicensing under
|
||||
this license.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU Affero General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey 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;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If 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 convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Remote Network Interaction; Use with the GNU General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, if you modify the
|
||||
Program, your modified version must prominently offer all users
|
||||
interacting with it remotely through a computer network (if your version
|
||||
supports such interaction) an opportunity to receive the Corresponding
|
||||
Source of your version by providing access to the Corresponding Source
|
||||
from a network server at no charge, through some standard or customary
|
||||
means of facilitating copying of software. This Corresponding Source
|
||||
shall include the Corresponding Source for any work covered by version 3
|
||||
of the GNU General Public License that is incorporated pursuant to the
|
||||
following paragraph.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the work with which it is combined will remain governed by version
|
||||
3 of the GNU General Public License.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU Affero 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 that a certain numbered version of the GNU Affero General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU Affero General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU Affero General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
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.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
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.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
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
|
||||
state 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 Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If your software can interact with users remotely through a computer
|
||||
network, you should also make sure that it provides a way for users to
|
||||
get its source. For example, if your program is a web application, its
|
||||
interface could display a "Source" link that leads users to an archive
|
||||
of the code. There are many ways you could offer source, and different
|
||||
solutions will be better for different programs; see section 13 for the
|
||||
specific requirements.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
|
||||
|
||||
=========================================================================
|
||||
|
||||
This marks the end of the AGPLv3 text. The following text is appended to the
|
||||
same file for convience but constituting a distinct document, not part of the
|
||||
actual AGPL text and not part of an attempt to create a deriviative work based
|
||||
on the AGPLv3 text.
|
||||
|
||||
=========================================================================
|
||||
|
||||
|
||||
ADDITIONAL TERMS TO THE AGPLv3 LICENSE FOR OPENBTS
|
||||
|
||||
|
||||
Permissive Terms Supplementing the License
|
||||
|
||||
1. Remote Interaction Through IP Networks.
|
||||
|
||||
OpenBTS includes an implementation of the GSM network cellular air interface,
|
||||
as well as other interfaces to IP networks. The interaction of cellular
|
||||
handsets with the OpenBTS software is considered "remote network interaction"
|
||||
for the purposes of the Affero General Public License and cellular users are
|
||||
subject to the source code access requirements of Section 13 of AGPLv3 ("Remote
|
||||
Network Interaction; Use with the GNU General Public License").
|
||||
|
||||
Remote interactions through interfaces other than the GSM air interface are, at
|
||||
your option, exempted from the requirements of Section 13 ("Remote Network
|
||||
Interaction; Use with the GNU General Public License"). This exemption of
|
||||
interfaces other than the GSM air interface from the requirements of Section 13
|
||||
is an additional permission granted to you.
|
||||
|
||||
|
||||
Non-Permissive Terms Supplementing The License
|
||||
|
||||
1. Trademarks.
|
||||
|
||||
"OpenBTS" is a trademark of Kestrel Signal Processing, Inc., registered with
|
||||
the US Patent and Trademark Office. Your use of OpenBTS software under a GPL
|
||||
license does not include the right to use the OpenBTS trademark in commerce.
|
||||
This additional non-permissive term is consistent with Section 7 of the AGPLv3
|
||||
license.
|
||||
|
||||
|
||||
END OF ADDITIONAL TERMS
|
||||
|
||||
|
||||
|
||||
How to comply with Section 13 of the AGPLv3 license.
|
||||
|
||||
The recommended method for compliance with Section 13 of the AGPLv3 license is
|
||||
to deliver a text message to each handset that attaches to the OpenBTS cellular
|
||||
network. At a minimum, that text message should include the string "OpenBTS
|
||||
AGPLv3" and a URL that can be used to access the OpenBTS source code. This
|
||||
message need not be delivered to handsets that are denied registration with the
|
||||
network, since those handsets have been denied service.
|
||||
|
||||
In OpenBTS 2.6, such text messages can be delivered with the "Welcome Message"
|
||||
feature. See the OpenBTS.config.example file for more information on the use of
|
||||
this feature for AGPLv3 compliance.
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
TRUNK=../..
|
||||
COM=$(TRUNK)/CommonLibs/trunk-public-staging
|
||||
SQL=$(TRUNK)/sqlite3/trunk-public-staging
|
||||
#SR=$(TRUNK)/subscriberRegistry/trunk-public-staging
|
||||
LOCALLIBS=$(COM)/Logger.cpp $(COM)/Timeval.cpp $(COM)/Threads.cpp $(COM)/Sockets.cpp $(COM)/Configuration.cpp $(SQL)/sqlite3util.cpp SubscriberRegistry.cpp servershare.cpp
|
||||
LIBS=$(LOCALLIBS) -losipparser2 -losip2 -lc -lpthread -lsqlite3
|
||||
INCLUDES=-I$(COM) -I$(SQL)
|
||||
CPPFLAGS=-g -Wall -Wno-deprecated
|
||||
|
||||
all: srmanager.cgi sipauthserve
|
||||
|
||||
srmanager.cgi: srmanager.cpp $(LOCALLIBS)
|
||||
g++ -o srmanager.cgi $(CPPFLAGS) $(INCLUDES) srmanager.cpp $(LIBS)
|
||||
|
||||
sipauthserve: sipauthserve.cpp $(LOCALLIBS)
|
||||
g++ -o sipauthserve $(CPPFLAGS) $(INCLUDES) sipauthserve.cpp $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -f srmanager.cgi sipauthserve test.SubscriberRegistry/test
|
||||
rm -r -f *.dSYM
|
|
@ -0,0 +1,433 @@
|
|||
/*
|
||||
* Copyright 2011 Kestrel Signal Processing, Inc.
|
||||
* Copyright 2011 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "SubscriberRegistry.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include "sqlite3.h"
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <Configuration.h>
|
||||
|
||||
extern ConfigurationTable gConfig;
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
static const char* createRRLPTable = {
|
||||
"CREATE TABLE IF NOT EXISTS RRLP ("
|
||||
"id INTEGER PRIMARY KEY, "
|
||||
"name VARCHAR(80) not null, "
|
||||
"latitude real not null, "
|
||||
"longitude real not null, "
|
||||
"error real not null, "
|
||||
"time text not null "
|
||||
")"
|
||||
};
|
||||
|
||||
static const char* createDDTable = {
|
||||
"CREATE TABLE IF NOT EXISTS DIALDATA_TABLE ("
|
||||
"id INTEGER PRIMARY KEY, "
|
||||
"exten VARCHAR(40) NOT NULL DEFAULT '', "
|
||||
"dial VARCHAR(128) NOT NULL DEFAULT '' "
|
||||
")"
|
||||
};
|
||||
|
||||
static const char* createSBTable = {
|
||||
"CREATE TABLE IF NOT EXISTS SIP_BUDDIES ("
|
||||
"id integer primary key, "
|
||||
"name VARCHAR(80) not null, "
|
||||
"context VARCHAR(80), "
|
||||
"callingpres VARCHAR(30) DEFAULT 'allowed_not_screened', "
|
||||
"deny VARCHAR(95), "
|
||||
"permit VARCHAR(95), "
|
||||
"secret VARCHAR(80), "
|
||||
"md5secret VARCHAR(80), "
|
||||
"remotesecret VARCHAR(250), "
|
||||
"transport VARCHAR(10), "
|
||||
"host VARCHAR(31) default '' not null, "
|
||||
"nat VARCHAR(5) DEFAULT 'no' not null, "
|
||||
"type VARCHAR(10) DEFAULT 'friend' not null, "
|
||||
"accountcode VARCHAR(20), "
|
||||
"amaflags VARCHAR(13), "
|
||||
"callgroup VARCHAR(10), "
|
||||
"callerid VARCHAR(80), "
|
||||
"defaultip VARCHAR(40) DEFAULT '0.0.0.0', "
|
||||
"dtmfmode VARCHAR(7) DEFAULT 'rfc2833', "
|
||||
"fromuser VARCHAR(80), "
|
||||
"fromdomain VARCHAR(80), "
|
||||
"insecure VARCHAR(4), "
|
||||
"language CHAR(2), "
|
||||
"mailbox VARCHAR(50), "
|
||||
"pickupgroup VARCHAR(10), "
|
||||
"qualify CHAR(3), "
|
||||
"regexten VARCHAR(80), "
|
||||
"rtptimeout CHAR(3), "
|
||||
"rtpholdtimeout CHAR(3), "
|
||||
"setvar VARCHAR(100), "
|
||||
"disallow VARCHAR(100) DEFAULT 'all', "
|
||||
"allow VARCHAR(100) DEFAULT 'gsm' not null, "
|
||||
"fullcontact VARCHAR(80), "
|
||||
"ipaddr VARCHAR(45), "
|
||||
"port int(5) DEFAULT 5062, "
|
||||
"username VARCHAR(80), "
|
||||
"defaultuser VARCHAR(80), "
|
||||
"subscribecontext VARCHAR(80), "
|
||||
"directmedia VARCHAR(3), "
|
||||
"trustrpid VARCHAR(3), "
|
||||
"sendrpid VARCHAR(3), "
|
||||
"progressinband VARCHAR(5), "
|
||||
"promiscredir VARCHAR(3), "
|
||||
"useclientcode VARCHAR(3), "
|
||||
"callcounter VARCHAR(3), "
|
||||
"busylevel int(11), "
|
||||
"allowoverlap VARCHAR(3) DEFAULT 'yes', "
|
||||
"allowsubscribe VARCHAR(3) DEFAULT 'yes', "
|
||||
"allowtransfer VARCHAR(3) DEFAULT 'yes', "
|
||||
"ignoresdpversion VARCHAR(3) DEFAULT 'no', "
|
||||
"template VARCHAR(100), "
|
||||
"videosupport VARCHAR(6) DEFAULT 'no', "
|
||||
"maxcallbitrate int(11), "
|
||||
"rfc2833compensate VARCHAR(3) DEFAULT 'yes', "
|
||||
"'session-timers' VARCHAR(10) DEFAULT 'accept', "
|
||||
"'session-expires' int(6) DEFAULT 1800, "
|
||||
"'session-minse' int(6) DEFAULT 90, "
|
||||
"'session-refresher' VARCHAR(3) DEFAULT 'uas', "
|
||||
"t38pt_usertpsource VARCHAR(3), "
|
||||
"outboundproxy VARCHAR(250), "
|
||||
"callbackextension VARCHAR(250), "
|
||||
"registertrying VARCHAR(3) DEFAULT 'yes', "
|
||||
"timert1 int(6) DEFAULT 500, "
|
||||
"timerb int(9), "
|
||||
"qualifyfreq int(6) DEFAULT 120, "
|
||||
"contactpermit VARCHAR(250), "
|
||||
"contactdeny VARCHAR(250), "
|
||||
"lastms int(11) DEFAULT 0 not null, "
|
||||
"regserver VARCHAR(100), "
|
||||
"regseconds int(11) DEFAULT 0 not null, "
|
||||
"useragent VARCHAR(100), "
|
||||
"cancallforward CHAR(3) DEFAULT 'yes' not null, "
|
||||
"canreinvite CHAR(3) DEFAULT 'yes' not null, "
|
||||
"mask VARCHAR(95), "
|
||||
"musiconhold VARCHAR(100), "
|
||||
"restrictcid CHAR(3), "
|
||||
"calllimit int(5), "
|
||||
"WhiteListFlag timestamp not null default '0', "
|
||||
"WhiteListCode varchar(8) not null default '0', "
|
||||
"rand varchar(33) default '', "
|
||||
"sres varchar(33) default '', "
|
||||
"ki varchar(33) default '', "
|
||||
"kc varchar(33) default '', "
|
||||
"prepaid int(1) DEFAULT 0 not null, "
|
||||
"secondsRemaining int(11) DEFAULT 0 not null, "
|
||||
"RRLPSupported int(1) default 1 not null, "
|
||||
"regTime INTEGER default 0 NOT NULL, " // Unix time of most recent registration
|
||||
"a3_a8 varchar(45) default NULL"
|
||||
")"
|
||||
};
|
||||
|
||||
|
||||
SubscriberRegistry::SubscriberRegistry()
|
||||
{
|
||||
string ldb = gConfig.getStr("SubscriberRegistry.db");
|
||||
int rc = sqlite3_open(ldb.c_str(),&mDB);
|
||||
if (rc) {
|
||||
LOG(EMERG) << "Cannot open SubscriberRegistry database: " << sqlite3_errmsg(mDB);
|
||||
sqlite3_close(mDB);
|
||||
mDB = NULL;
|
||||
return;
|
||||
}
|
||||
if (!sqlite3_command(mDB,createRRLPTable)) {
|
||||
LOG(EMERG) << "Cannot create RRLP table";
|
||||
}
|
||||
if (!sqlite3_command(mDB,createDDTable)) {
|
||||
LOG(EMERG) << "Cannot create DIALDATA_TABLE table";
|
||||
}
|
||||
if (!sqlite3_command(mDB,createSBTable)) {
|
||||
LOG(EMERG) << "Cannot create SIP_BUDDIES table";
|
||||
}
|
||||
if (!getCLIDLocal("IMSI001010000000000")) {
|
||||
// This is a test SIM provided with the BTS.
|
||||
if (addUser("IMSI001010000000000", "2100") != SUCCESS) {
|
||||
LOG(EMERG) << "Cannot insert test SIM";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
SubscriberRegistry::~SubscriberRegistry()
|
||||
{
|
||||
if (mDB) sqlite3_close(mDB);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::sqlLocal(const char *query, char **resultptr)
|
||||
{
|
||||
LOG(INFO) << query;
|
||||
|
||||
if (!resultptr) {
|
||||
if (!sqlite3_command(db(), query)) return FAILURE;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
sqlite3_stmt *stmt;
|
||||
if (sqlite3_prepare_statement(db(), &stmt, query)) {
|
||||
LOG(ERR) << "sqlite3_prepare_statement problem";
|
||||
return FAILURE;
|
||||
}
|
||||
int src = sqlite3_run_query(db(), stmt);
|
||||
if (src != SQLITE_ROW) {
|
||||
sqlite3_finalize(stmt);
|
||||
return FAILURE;
|
||||
}
|
||||
char *column = (char*)sqlite3_column_text(stmt, 0);
|
||||
if (!column) {
|
||||
LOG(ERR) << "Subscriber registry returned a NULL column.";
|
||||
sqlite3_finalize(stmt);
|
||||
return FAILURE;
|
||||
}
|
||||
*resultptr = strdup(column);
|
||||
sqlite3_finalize(stmt);
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *SubscriberRegistry::sqlQuery(const char *unknownColumn, const char *table, const char *knownColumn, const char *knownValue)
|
||||
{
|
||||
char *result = NULL;
|
||||
SubscriberRegistry::Status st;
|
||||
ostringstream os;
|
||||
os << "select " << unknownColumn << " from " << table << " where " << knownColumn << " = \"" << knownValue << "\"";
|
||||
// try to find locally
|
||||
st = sqlLocal(os.str().c_str(), &result);
|
||||
if (st == SUCCESS) {
|
||||
// got it. return it.
|
||||
LOG(INFO) << "result = " << result;
|
||||
return result;
|
||||
}
|
||||
LOG(INFO) << "not found";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::sqlUpdate(const char *stmt)
|
||||
{
|
||||
LOG(INFO) << stmt;
|
||||
SubscriberRegistry::Status st = sqlLocal(stmt, NULL);
|
||||
return st;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *SubscriberRegistry::getIMSI(const char *ISDN)
|
||||
{
|
||||
if (!ISDN) {
|
||||
LOG(WARNING) << "SubscriberRegistry::getIMSI attempting lookup of NULL ISDN";
|
||||
return NULL;
|
||||
}
|
||||
LOG(INFO) << "getIMSI(" << ISDN << ")";
|
||||
return sqlQuery("dial", "dialdata_table", "exten", ISDN);
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *SubscriberRegistry::getCLIDLocal(const char* IMSI)
|
||||
{
|
||||
if (!IMSI) {
|
||||
LOG(WARNING) << "SubscriberRegistry::getCLIDLocal attempting lookup of NULL IMSI";
|
||||
return NULL;
|
||||
}
|
||||
LOG(INFO) << "getCLIDLocal(" << IMSI << ")";
|
||||
return sqlQuery("callerid", "sip_buddies", "name", IMSI);
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *SubscriberRegistry::getCLIDGlobal(const char* IMSI)
|
||||
{
|
||||
if (!IMSI) {
|
||||
LOG(WARNING) << "SubscriberRegistry::getCLIDGlobal attempting lookup of NULL IMSI";
|
||||
return NULL;
|
||||
}
|
||||
LOG(INFO) << "getCLIDGlobal(" << IMSI << ")";
|
||||
return sqlQuery("callerid", "sip_buddies", "name", IMSI);
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *SubscriberRegistry::getRegistrationIP(const char* IMSI)
|
||||
{
|
||||
if (!IMSI) {
|
||||
LOG(WARNING) << "SubscriberRegistry::getRegistrationIP attempting lookup of NULL IMSI";
|
||||
return NULL;
|
||||
}
|
||||
LOG(INFO) << "getRegistrationIP(" << IMSI << ")";
|
||||
return sqlQuery("ipaddr", "sip_buddies", "name", IMSI);
|
||||
}
|
||||
|
||||
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::setRegTime(const char* IMSI)
|
||||
{
|
||||
if (!IMSI) {
|
||||
LOG(WARNING) << "SubscriberRegistry::setRegTime attempting set for NULL IMSI";
|
||||
return FAILURE;
|
||||
}
|
||||
unsigned now = (unsigned)time(NULL);
|
||||
ostringstream os;
|
||||
os << "update sip_buddies set regTime = " << now << " where name = " << '"' << IMSI << '"';
|
||||
return sqlUpdate(os.str().c_str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
SubscriberRegistry::Status SubscriberRegistry::addUser(const char* IMSI, const char* CLID)
|
||||
{
|
||||
if (!IMSI) {
|
||||
LOG(WARNING) << "SubscriberRegistry::addUser attempting add of NULL IMSI";
|
||||
return FAILURE;
|
||||
}
|
||||
if (!CLID) {
|
||||
LOG(WARNING) << "SubscriberRegistry::addUser attempting add of NULL CLID";
|
||||
return FAILURE;
|
||||
}
|
||||
LOG(INFO) << "addUser(" << IMSI << "," << CLID << ")";
|
||||
ostringstream os;
|
||||
os << "insert into sip_buddies (name, username, type, context, host, callerid, canreinvite, allow, dtmfmode, ipaddr, port) values (";
|
||||
os << "\"" << IMSI << "\"";
|
||||
os << ",";
|
||||
os << "\"" << IMSI << "\"";
|
||||
os << ",";
|
||||
os << "\"" << "friend" << "\"";
|
||||
os << ",";
|
||||
os << "\"" << "phones" << "\"";
|
||||
os << ",";
|
||||
os << "\"" << "dynamic" << "\"";
|
||||
os << ",";
|
||||
os << "\"" << CLID << "\"";
|
||||
os << ",";
|
||||
os << "\"" << "no" << "\"";
|
||||
os << ",";
|
||||
os << "\"" << "gsm" << "\"";
|
||||
os << ",";
|
||||
os << "\"" << "info" << "\"";
|
||||
os << ",";
|
||||
os << "\"" << "127.0.0.1" << "\"";
|
||||
os << ",";
|
||||
os << "\"" << "5062" << "\"";
|
||||
os << ")";
|
||||
os << ";";
|
||||
SubscriberRegistry::Status st = sqlUpdate(os.str().c_str());
|
||||
ostringstream os2;
|
||||
os2 << "insert into dialdata_table (exten, dial) values (";
|
||||
os2 << "\"" << CLID << "\"";
|
||||
os2 << ",";
|
||||
os2 << "\"" << IMSI << "\"";
|
||||
os2 << ")";
|
||||
SubscriberRegistry::Status st2 = sqlUpdate(os2.str().c_str());
|
||||
return st == SUCCESS && st2 == SUCCESS ? SUCCESS : FAILURE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
char *SubscriberRegistry::mapCLIDGlobal(const char *local)
|
||||
{
|
||||
if (!local) {
|
||||
LOG(WARNING) << "SubscriberRegistry::mapCLIDGlobal attempting lookup of NULL local";
|
||||
return NULL;
|
||||
}
|
||||
LOG(INFO) << "mapCLIDGlobal(" << local << ")";
|
||||
char *IMSI = getIMSI(local);
|
||||
if (!IMSI) return NULL;
|
||||
char *global = getCLIDGlobal(IMSI);
|
||||
free(IMSI);
|
||||
return global;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void SubscriberRegistry::stringToUint(string strRAND, uint64_t *hRAND, uint64_t *lRAND)
|
||||
{
|
||||
assert(strRAND.size() == 32);
|
||||
string strhRAND = strRAND.substr(0, 16);
|
||||
string strlRAND = strRAND.substr(16, 16);
|
||||
stringstream ssh;
|
||||
ssh << hex << strhRAND;
|
||||
ssh >> *hRAND;
|
||||
stringstream ssl;
|
||||
ssl << hex << strlRAND;
|
||||
ssl >> *lRAND;
|
||||
}
|
||||
|
||||
string SubscriberRegistry::uintToString(uint64_t h, uint64_t l)
|
||||
{
|
||||
ostringstream os1;
|
||||
os1.width(16);
|
||||
os1.fill('0');
|
||||
os1 << hex << h;
|
||||
ostringstream os2;
|
||||
os2.width(16);
|
||||
os2.fill('0');
|
||||
os2 << hex << l;
|
||||
ostringstream os3;
|
||||
os3 << os1.str() << os2.str();
|
||||
return os3.str();
|
||||
}
|
||||
|
||||
string SubscriberRegistry::uintToString(uint32_t x)
|
||||
{
|
||||
ostringstream os;
|
||||
os.width(8);
|
||||
os.fill('0');
|
||||
os << hex << x;
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// vim: ts=4 sw=4
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,164 @@
|
|||
/*
|
||||
* Copyright 2011 Kestrel Signal Processing, Inc.
|
||||
* Copyright 2011 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef SubscriberRegistry_H
|
||||
#define SubscriberRegistry_H
|
||||
|
||||
#include <map>
|
||||
#include <stdlib.h>
|
||||
#include <Logger.h>
|
||||
// #include <Timeval.h>
|
||||
// #include <Threads.h>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "sqlite3.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
class SubscriberRegistry {
|
||||
|
||||
private:
|
||||
|
||||
sqlite3 *mDB; ///< database connection
|
||||
|
||||
|
||||
public:
|
||||
|
||||
SubscriberRegistry();
|
||||
~SubscriberRegistry();
|
||||
|
||||
typedef enum {
|
||||
SUCCESS=0, ///< operation successful
|
||||
FAILURE=1, ///< operation not successful
|
||||
DELAYED=2, ///< operation successful, but effect delayed
|
||||
TRYAGAIN=3 ///< operation not attempted, try again later
|
||||
} Status;
|
||||
|
||||
|
||||
sqlite3 *db()
|
||||
{
|
||||
return mDB;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Resolve an ISDN or other numeric address to an IMSI.
|
||||
@param ISDN Any numeric address, E.164, local extension, etc.
|
||||
@return A C-string to be freed by the caller,
|
||||
NULL if the ISDN cannot be resolved.
|
||||
*/
|
||||
char* getIMSI(const char* ISDN);
|
||||
|
||||
/**
|
||||
Given an IMSI, return the local CLID, which should be a numeric address.
|
||||
@param IMSI The subscriber IMSI.
|
||||
@return A C-string to be freed by the caller,
|
||||
NULL if the IMSI isn't found.
|
||||
*/
|
||||
char* getCLIDLocal(const char* IMSI);
|
||||
|
||||
/**
|
||||
Given an IMSI, return the global CLID, which should be a numeric address.
|
||||
@param IMSI The subscriber IMSI.
|
||||
@return A C-string to be freed by the caller,
|
||||
NULL if the IMSI isn't found.
|
||||
*/
|
||||
char* getCLIDGlobal(const char* IMSI);
|
||||
|
||||
/**
|
||||
Given an IMSI, return the IP address of the most recent registration.
|
||||
@param IMSI The subscriber IMSI
|
||||
@return A C-string to be freed by the caller, "111.222.333.444:port",
|
||||
NULL if the ISMI isn't registered.
|
||||
*/
|
||||
char* getRegistrationIP(const char* IMSI);
|
||||
|
||||
/**
|
||||
Add a new user to the SubscriberRegistry.
|
||||
@param IMSI The user's IMSI or SIP username.
|
||||
@param CLID The user's local CLID.
|
||||
*/
|
||||
Status addUser(const char* IMSI, const char* CLID);
|
||||
|
||||
|
||||
/**
|
||||
Set the current time as the time of the most recent registration for an IMSI.
|
||||
@param IMSI The user's IMSI or SIP username.
|
||||
*/
|
||||
Status setRegTime(const char* IMSI);
|
||||
|
||||
|
||||
char *mapCLIDGlobal(const char *local);
|
||||
|
||||
|
||||
|
||||
void stringToUint(string strRAND, uint64_t *hRAND, uint64_t *lRAND);
|
||||
|
||||
string uintToString(uint64_t h, uint64_t l);
|
||||
|
||||
string uintToString(uint32_t x);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Run sql statments locally.
|
||||
@param stmt The sql statements.
|
||||
@param resultptr Set this to point to the result of executing the statements.
|
||||
*/
|
||||
Status sqlLocal(const char *stmt, char **resultptr);
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Run an sql query (select unknownColumn from table where knownColumn = knownValue).
|
||||
@param unknownColumn The column whose value you want.
|
||||
@param table The table to look in.
|
||||
@param knownColumn The column with the value you know.
|
||||
@param knownValue The known value of knownColumn.
|
||||
*/
|
||||
char *sqlQuery(const char *unknownColumn, const char *table, const char *knownColumn, const char *knownValue);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Run an sql update.
|
||||
@param stmt The update statement.
|
||||
*/
|
||||
Status sqlUpdate(const char *stmt);
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
// vim: ts=4 sw=4
|
|
@ -0,0 +1,6 @@
|
|||
[asterisk]
|
||||
Description=SQLite3 database
|
||||
Driver=SQLite3
|
||||
Database=/var/lib/asterisk/sqlite3dir/sqlite3.db
|
||||
# optional lock timeout in milliseconds
|
||||
Timeout=2000
|
|
@ -0,0 +1,5 @@
|
|||
[SQLite3]
|
||||
Description=SQLite3 ODBC Driver
|
||||
Driver=/usr/local/lib/libsqlite3odbc.so
|
||||
Setup=/usr/local/lib/libsqlite3odbc.so
|
||||
Threading=2
|
|
@ -0,0 +1,95 @@
|
|||
create table dialdata_table (
|
||||
id INTEGER,
|
||||
exten VARCHAR(40) NOT NULL DEFAULT '',
|
||||
dial VARCHAR(128) NOT NULL DEFAULT '',
|
||||
PRIMARY KEY (id)
|
||||
);
|
||||
|
||||
CREATE TABLE 'sip_buddies'
|
||||
(
|
||||
id integer,
|
||||
name VARCHAR(80) not null,
|
||||
context VARCHAR(80),
|
||||
callingpres VARCHAR(30) DEFAULT 'allowed_not_screened',
|
||||
deny VARCHAR(95),
|
||||
permit VARCHAR(95),
|
||||
secret VARCHAR(80),
|
||||
md5secret VARCHAR(80),
|
||||
remotesecret VARCHAR(250),
|
||||
transport VARCHAR(10),
|
||||
host VARCHAR(31) not null,
|
||||
nat VARCHAR(5) DEFAULT 'no' not null,
|
||||
type VARCHAR(10) DEFAULT 'friend' not null,
|
||||
accountcode VARCHAR(20),
|
||||
amaflags VARCHAR(13),
|
||||
callgroup VARCHAR(10),
|
||||
callerid VARCHAR(80),
|
||||
defaultip VARCHAR(40) DEFAULT '0.0.0.0',
|
||||
dtmfmode VARCHAR(7) DEFAULT 'rfc2833',
|
||||
fromuser VARCHAR(80),
|
||||
fromdomain VARCHAR(80),
|
||||
insecure VARCHAR(4),
|
||||
language CHAR(2),
|
||||
mailbox VARCHAR(50),
|
||||
pickupgroup VARCHAR(10),
|
||||
qualify CHAR(3),
|
||||
regexten VARCHAR(80),
|
||||
rtptimeout CHAR(3),
|
||||
rtpholdtimeout CHAR(3),
|
||||
setvar VARCHAR(100),
|
||||
disallow VARCHAR(100) DEFAULT 'all',
|
||||
allow VARCHAR(100) DEFAULT 'ulaw' not null,
|
||||
fullcontact VARCHAR(80),
|
||||
ipaddr VARCHAR(40),
|
||||
port int(5) DEFAULT 0,
|
||||
username VARCHAR(80),
|
||||
defaultuser VARCHAR(80),
|
||||
subscribecontext VARCHAR(80),
|
||||
directmedia VARCHAR(3),
|
||||
trustrpid VARCHAR(3),
|
||||
sendrpid VARCHAR(3),
|
||||
progressinband VARCHAR(5),
|
||||
promiscredir VARCHAR(3),
|
||||
useclientcode VARCHAR(3),
|
||||
callcounter VARCHAR(3),
|
||||
busylevel int(11),
|
||||
allowoverlap VARCHAR(3) DEFAULT 'yes',
|
||||
allowsubscribe VARCHAR(3) DEFAULT 'yes',
|
||||
allowtransfer VARCHAR(3) DEFAULT 'yes',
|
||||
ignoresdpversion VARCHAR(3) DEFAULT 'no',
|
||||
template VARCHAR(100),
|
||||
videosupport VARCHAR(6) DEFAULT 'no',
|
||||
maxcallbitrate int(11),
|
||||
rfc2833compensate VARCHAR(3) DEFAULT 'yes',
|
||||
'session-timers' VARCHAR(10) DEFAULT 'accept',
|
||||
'session-expires' int(6) DEFAULT 1800,
|
||||
'session-minse' int(6) DEFAULT 90,
|
||||
'session-refresher' VARCHAR(3) DEFAULT 'uas',
|
||||
t38pt_usertpsource VARCHAR(3),
|
||||
outboundproxy VARCHAR(250),
|
||||
callbackextension VARCHAR(250),
|
||||
registertrying VARCHAR(3) DEFAULT 'yes',
|
||||
timert1 int(6) DEFAULT 500,
|
||||
timerb int(9),
|
||||
qualifyfreq int(6) DEFAULT 120,
|
||||
contactpermit VARCHAR(250),
|
||||
contactdeny VARCHAR(250),
|
||||
lastms int(11) DEFAULT 0 not null,
|
||||
regserver VARCHAR(100),
|
||||
regseconds int(11) DEFAULT 0 not null,
|
||||
useragent VARCHAR(100),
|
||||
cancallforward CHAR(3) DEFAULT 'yes' not null,
|
||||
canreinvite CHAR(3) DEFAULT 'yes' not null,
|
||||
mask VARCHAR(95),
|
||||
musiconhold VARCHAR(100),
|
||||
restrictcid CHAR(3),
|
||||
calllimit int(5),
|
||||
WhiteListFlag timestamp not null default '0',
|
||||
WhiteListCode varchar(8) not null default '0',
|
||||
rand varchar(33) default '',
|
||||
sres varchar(33) default '',
|
||||
ki varchar(33) default '',
|
||||
kc varchar(33) default '',
|
||||
primary key(id)
|
||||
)
|
||||
;
|
|
@ -0,0 +1,45 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
# this normalizes things that are ok to change, like random numbers (which it numbers
|
||||
# in the order found to keep relative values correct), SRESs (ditto), dates, and PIDs.
|
||||
# And source code line numbers.
|
||||
|
||||
my($hexN) = 1000;
|
||||
my(%mapping);
|
||||
|
||||
sub hexmap {
|
||||
my($in) = @_;
|
||||
my($out) = $mapping{$in};
|
||||
if (!defined($out)) {
|
||||
$out = substr("hexhexhexhexhexhexhexhexhexhexhex", 0, length($in) - 4) . $hexN;
|
||||
$mapping{$in} = $out;
|
||||
$hexN++;
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
sub main {
|
||||
my($first) = 1;
|
||||
while (<>) {
|
||||
# normalize big (random) hex numbers
|
||||
s/\b([0-9a-fA-F]{32})\b/&hexmap($1)/ge; # RAND and Ki size
|
||||
s/\b([0-9a-fA-F]{24})\b/&hexmap($1)/ge; # simout size
|
||||
s/\b([0-9a-fA-F]{8})\b/&hexmap($1)/ge; # SRES size
|
||||
# normalize dates
|
||||
if ($first) {
|
||||
$first = 0;
|
||||
} else {
|
||||
s/[A-Z][a-z][a-z] [A-Z][a-z][a-z] (\d| )\d \d\d:\d\d:\d\d (P[DS]T )?201\d/-DATE-/;
|
||||
}
|
||||
# normalize PIDs
|
||||
s/(subscriberregistry\.[12])\.\d+/$1.-PID-/g;
|
||||
# normalize source code line numbers
|
||||
s/(\.cpp):(\d+):/$1:-0-:/;
|
||||
print;
|
||||
}
|
||||
}
|
||||
|
||||
&main;
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
# A script to restart and just keep sipauthserve running.
|
||||
while true; do killall sipauthserve; sleep 2; ./sipauthserve; done
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* Copyright 2011 Kestrel Signal Processing, Inc.
|
||||
* Copyright 2011 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <cstdlib>
|
||||
#include <Configuration.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "servershare.h"
|
||||
#include "sqlite3.h"
|
||||
#include "Logger.h"
|
||||
#include "SubscriberRegistry.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
extern ConfigurationTable gConfig;
|
||||
|
||||
// just using this for the database access
|
||||
extern SubscriberRegistry gSubscriberRegistry;
|
||||
|
||||
|
||||
|
||||
string imsiGet(string imsi, string key)
|
||||
{
|
||||
string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi;
|
||||
char *value;
|
||||
if (!sqlite3_single_lookup(gSubscriberRegistry.db(), "sip_buddies", "name", name.c_str(), key.c_str(), value)) {
|
||||
return "";
|
||||
}
|
||||
if (!value) { return ""; }
|
||||
string retValue = value;
|
||||
free(value);
|
||||
return retValue;
|
||||
}
|
||||
|
||||
void imsiSet(string imsi, string key, string value)
|
||||
{
|
||||
string name = imsi.substr(0,4) == "IMSI" ? imsi : "IMSI" + imsi;
|
||||
ostringstream os2;
|
||||
os2 << "update sip_buddies set " << key << " = \"" << value << "\" where name = \"" << name << "\"";
|
||||
if (!sqlite3_command(gSubscriberRegistry.db(), os2.str().c_str())) {
|
||||
LOG(ERR) << "sqlite3_command problem";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
string soGenerateIt()
|
||||
{
|
||||
ostringstream os;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
// if rand() is too slow you can call it fewer times
|
||||
os << hex << (rand() & 0xf);
|
||||
}
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// generate a 128' random number
|
||||
string generateRand(string imsi)
|
||||
{
|
||||
string ki = imsiGet(imsi, "ki");
|
||||
string ret;
|
||||
if (ki.length() != 0) {
|
||||
LOG(INFO) << "ki is known";
|
||||
// generate and return rand (clear any cached rand or sres)
|
||||
imsiSet(imsi, "rand", "");
|
||||
imsiSet(imsi, "sres", "");
|
||||
ret = soGenerateIt();
|
||||
} else {
|
||||
string wRand = imsiGet(imsi, "rand");
|
||||
if (wRand.length() != 0) {
|
||||
LOG(INFO) << "ki is unknown, rand is cached";
|
||||
// return cached rand
|
||||
ret = wRand;
|
||||
} else {
|
||||
LOG(INFO) << "ki is unknown, rand is not cached";
|
||||
// generate rand, cache rand, clear sres, and return rand
|
||||
wRand = soGenerateIt();
|
||||
imsiSet(imsi, "rand", wRand);
|
||||
imsiSet(imsi, "sres", "");
|
||||
ret = wRand;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool strEqual(string a, string b)
|
||||
{
|
||||
return 0 == strcasecmp(a.c_str(), b.c_str());
|
||||
}
|
||||
|
||||
void decodeQuery(map<string,string> &args)
|
||||
{
|
||||
string query;
|
||||
// this works for GET or POST.
|
||||
// get the request method
|
||||
char *g = getenv("REQUEST_METHOD");
|
||||
string method = g ? g : "";
|
||||
LOG(INFO) << "REQUEST_METHOD = " << g;
|
||||
// if POST, then read from stdin the number of bytes specified in CONTENT_LENGTH, and that's the query
|
||||
if (method == "POST") {
|
||||
int lth = atoi(getenv("CONTENT_LENGTH"));
|
||||
LOG(INFO) << "CONTENT_LENGTH = " << lth;
|
||||
char *buf = new char[lth+1];
|
||||
cin.get(buf, lth+1);
|
||||
int nread = cin.gcount();
|
||||
if (nread != lth) {
|
||||
LOG(ERR) << "content length changed to " << nread;
|
||||
lth = nread;
|
||||
}
|
||||
query = string(buf, lth);
|
||||
LOG(INFO) << "QUERY = " << query;
|
||||
delete[] buf;
|
||||
// if GET, then the query is in the environment variable QUERY_STRING
|
||||
} else if (method == "GET") {
|
||||
char *q = getenv("QUERY_STRING");
|
||||
query = q ? q : "";
|
||||
LOG(INFO) << "QUERY_STRING = " << q;
|
||||
}
|
||||
if (query.length() != 0) {
|
||||
// fields of http request are separated with "&"
|
||||
vector<string> fields;
|
||||
split('&', query, &fields);
|
||||
vector<string>::iterator it;
|
||||
for (it = fields.begin(); it != fields.end(); it++) {
|
||||
string field = *it;
|
||||
size_t p = field.find('=');
|
||||
string key = field.substr(0, p);
|
||||
string value = field.substr(p+1);
|
||||
p = 0;
|
||||
while (1) {
|
||||
size_t q = value.find('%', p);
|
||||
if (q == string::npos) break;
|
||||
string hex = value.substr(q+1, 2);
|
||||
char s[2];
|
||||
strcpy(s, "x");
|
||||
int i;
|
||||
sscanf(hex.c_str(), "%x", &i);
|
||||
s[0] = i;
|
||||
string hexx = s;
|
||||
value.replace(q, 3, hexx);
|
||||
}
|
||||
args[key] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string join(string separator, vector<string> &strings)
|
||||
{
|
||||
string result("");
|
||||
vector<string>::iterator it;
|
||||
for (it = strings.begin(); it != strings.end(); it++) {
|
||||
if (it != strings.begin()) result.append(separator);
|
||||
result.append(*it);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void split(char separator, string tosplit, vector<string> *fields)
|
||||
{
|
||||
int p = 0;
|
||||
while (1) {
|
||||
size_t q = tosplit.find(separator, p);
|
||||
if (q == string::npos) {
|
||||
fields->push_back(tosplit.substr(p));
|
||||
break;
|
||||
}
|
||||
fields->push_back(tosplit.substr(p, q-p));
|
||||
p = q+1;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright 2011 Kestrel Signal Processing, Inc.
|
||||
* Copyright 2011 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <string>
|
||||
#include "sqlite3.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
/**
|
||||
Get a subscriber's property.
|
||||
@param imsi imsi of the subscriber
|
||||
@param key name of the property
|
||||
*/
|
||||
string imsiGet(string imsi, string key);
|
||||
|
||||
/**
|
||||
Set a subscriber's property.
|
||||
@param imsi imsi of the subscriber
|
||||
@param key name of the property
|
||||
@param value value of the property
|
||||
*/
|
||||
void imsiSet(string imsi, string key, string value);
|
||||
|
||||
/**
|
||||
Generate a 128-bit random number.
|
||||
@param imsi imsi of subscriber the random number is for
|
||||
*/
|
||||
string generateRand(string imsi);
|
||||
|
||||
/**
|
||||
Decode the html query.
|
||||
@param args mapping of query key->value pairs.
|
||||
*/
|
||||
void decodeQuery(map<string,string> &args);
|
||||
|
||||
/**
|
||||
Join the strings in strings, separated by separator
|
||||
@param separator the separator
|
||||
@param strings the strings to join
|
||||
*/
|
||||
string join(string separator, vector<string> &strings);
|
||||
|
||||
/**
|
||||
Split tosplit into strings in fields, using separator
|
||||
@param separator the separator to look for
|
||||
@param tosplit the string to split
|
||||
@param fields the vector result
|
||||
*/
|
||||
void split(char separator, string tosplit, vector<string> *fields);
|
||||
|
||||
/**
|
||||
Open the database whose name is in the config table
|
||||
*/
|
||||
sqlite3 *openDB();
|
|
@ -0,0 +1,27 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Install subscriber registry and assocated files.
|
||||
|
||||
if [ "$USER" != "root" ]; then
|
||||
echo This script must be run as super-user.
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
IPATH=/usr/local/bin
|
||||
cp comp128 $IPATH
|
||||
cp hexmapper $IPATH
|
||||
cp syslogextractor $IPATH
|
||||
|
||||
CGIPATH=/var/cgi-bin
|
||||
cp srmanager.cgi $CGIPATH
|
||||
cp subscriberserver.cgi $CGIPATH
|
||||
|
||||
cp comp128 /OpenBTS
|
||||
cp sipauthserve /OpenBTS
|
||||
cp runloop.sipauthserve.sh /OpenBTS
|
||||
|
||||
# Don't do this. This will be created when the SR starts running.
|
||||
#DBPATH=/var/lib/asterisk/sqlite3dir
|
||||
#sqlite3 $DBPATH/sqlite3.db ".read configFiles/subscriberRegistryInit.sql"
|
||||
#cp configFiles/subscriberRegistryInit.sql $DBPATH
|
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
* Copyright 2011 Kestrel Signal Processing, Inc.
|
||||
* Copyright 2011 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
#include <arpa/inet.h>
|
||||
#include <cstdlib>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <netinet/in.h>
|
||||
#include <osip2/osip.h>
|
||||
#include <osipparser2/osip_message.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <Logger.h>
|
||||
#include <Configuration.h>
|
||||
#include "servershare.h"
|
||||
#include "SubscriberRegistry.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
ConfigurationTable gConfig("/etc/OpenBTS/OpenBTS.db");
|
||||
|
||||
int my_udp_port;
|
||||
|
||||
// just using this for the database access
|
||||
SubscriberRegistry gSubscriberRegistry;
|
||||
|
||||
void prettyPrint(const char *label, osip_message_t *sip)
|
||||
{
|
||||
char *dest=NULL;
|
||||
size_t length=0;
|
||||
int i = osip_message_to_str(sip, &dest, &length);
|
||||
if (i!=0) {
|
||||
LOG(ERR) << "cannot get printable message";
|
||||
} else {
|
||||
LOG(INFO) << label << ":\n" << dest;
|
||||
osip_free(dest);
|
||||
}
|
||||
}
|
||||
|
||||
string imsiFromSip(osip_message_t *sip)
|
||||
{
|
||||
int i;
|
||||
char *dest;
|
||||
osip_uri_t *fromUri = osip_from_get_url(sip->from);
|
||||
if (!fromUri) {
|
||||
LOG(ERR) << "osip_from_get_url problem";
|
||||
return "";
|
||||
}
|
||||
i = osip_uri_to_str(fromUri, &dest);
|
||||
string imsi = dest;
|
||||
osip_free(dest);
|
||||
return imsi;
|
||||
}
|
||||
|
||||
string imsiToSip(osip_message_t *sip)
|
||||
{
|
||||
int i;
|
||||
char *dest;
|
||||
osip_uri_t *toUri = osip_to_get_url(sip->to);
|
||||
if (!toUri) {
|
||||
LOG(ERR) << "osip_to_get_url problem";
|
||||
return "";
|
||||
}
|
||||
i = osip_uri_to_str(toUri, &dest);
|
||||
string imsi = dest;
|
||||
osip_free(dest);
|
||||
return imsi;
|
||||
}
|
||||
|
||||
// is imsi in the database?
|
||||
bool imsiFound(string imsi)
|
||||
{
|
||||
string x = imsiGet(imsi, "id");
|
||||
return x.length() != 0;
|
||||
}
|
||||
|
||||
string imsiClean(string imsi)
|
||||
{
|
||||
// remove leading sip:
|
||||
if (0 == strncasecmp(imsi.c_str(), "sip:", 4)) {
|
||||
imsi = imsi.substr(4);
|
||||
}
|
||||
// remove trailing @...
|
||||
size_t p = imsi.find("@");
|
||||
if (p != string::npos) {
|
||||
imsi = imsi.substr(0, p);
|
||||
}
|
||||
// remove leading IMSI
|
||||
if (0 == strncasecmp(imsi.c_str(), "imsi", 4)) {
|
||||
imsi = imsi.substr(4);
|
||||
}
|
||||
return imsi;
|
||||
}
|
||||
|
||||
|
||||
char *processBuffer(char *buffer)
|
||||
{
|
||||
int i;
|
||||
|
||||
// parse sip message
|
||||
osip_message_t *sip;
|
||||
i=osip_message_init(&sip);
|
||||
if (i!=0) {
|
||||
LOG(ERR) << "cannot allocate";
|
||||
osip_message_free(sip);
|
||||
return NULL;
|
||||
}
|
||||
i=osip_message_parse(sip, buffer, strlen(buffer));
|
||||
if (i!=0) {
|
||||
LOG(ERR) << "cannot parse sip message";
|
||||
osip_message_free(sip);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
prettyPrint("request", sip);
|
||||
|
||||
// response starts as clone of message
|
||||
osip_message_t *response;
|
||||
osip_message_clone(sip, &response);
|
||||
|
||||
osip_from_t * contact_header = (osip_from_t*)osip_list_get(&sip->contacts,0);
|
||||
osip_uri_t* contact_url = contact_header->url;
|
||||
char *remote_host = contact_url->host;
|
||||
|
||||
// return via
|
||||
ostringstream newvia;
|
||||
// newvia << "SIP/2.0/UDP localhost:5063;branch=1;received=string_address@foo.bar";
|
||||
const char *my_ipaddress = "localhost";
|
||||
newvia << "SIP/2.0/UDP " << my_ipaddress << ":" << my_udp_port << ";branch=1;received="
|
||||
<< "string_address@foo.bar"; // << my_network.string_addr((struct sockaddr *)netaddr, netaddrlen, false);
|
||||
osip_message_append_via(response, newvia.str().c_str());
|
||||
|
||||
// no method
|
||||
osip_message_set_method(response, NULL);
|
||||
|
||||
string imsi = imsiClean(imsiFromSip(sip));
|
||||
string imsiTo = imsiClean(imsiToSip(sip));
|
||||
if ((imsi == "EXIT") && (imsiTo == "EXIT")) exit(0); // for testing only
|
||||
if (!imsiFound(imsi)) {
|
||||
LOG(NOTICE) << "imsi unknown";
|
||||
// imsi problem => 404 IMSI Not Found
|
||||
osip_message_set_status_code (response, 404);
|
||||
osip_message_set_reason_phrase (response, osip_strdup("IMSI Not Found"));
|
||||
} else {
|
||||
// sres matches rand => 200 OK
|
||||
osip_message_set_status_code (response, 200);
|
||||
osip_message_set_reason_phrase (response, osip_strdup("OK"));
|
||||
// And register it.
|
||||
LOG(INFO) << "success, registering for IP address " << remote_host;
|
||||
imsiSet(imsi,"ipaddr",remote_host);
|
||||
imsiSet(imsi,"port","5062");
|
||||
}
|
||||
|
||||
prettyPrint("response", response);
|
||||
size_t length = 0;
|
||||
char *dest;
|
||||
int ii = osip_message_to_str(response, &dest, &length);
|
||||
if (ii != 0) {
|
||||
LOG(ERR) << "cannot get printable message";
|
||||
}
|
||||
|
||||
osip_message_free(sip);
|
||||
osip_message_free(response);
|
||||
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
#define BUFLEN 5000
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
sockaddr_in si_me;
|
||||
sockaddr_in si_other;
|
||||
int aSocket;
|
||||
char buf[BUFLEN];
|
||||
|
||||
gLogInit("sipauthserve", gConfig.getStr("Log.Level").c_str(), LOG_LOCAL7);
|
||||
LOG(ALERT) << argv[0] << " (re)starting";
|
||||
srand ( time(NULL) + (int)getpid() );
|
||||
my_udp_port = gConfig.getNum("SubscriberRegistry.Port");
|
||||
|
||||
// init osip lib
|
||||
osip_t *osip;
|
||||
int i=osip_init(&osip);
|
||||
if (i!=0) {
|
||||
LOG(ALERT) << "cannot init sip lib";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((aSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) {
|
||||
LOG(ALERT) << "can't initialize socket";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset((char *) &si_me, 0, sizeof(si_me));
|
||||
si_me.sin_family = AF_INET;
|
||||
si_me.sin_port = htons(my_udp_port);
|
||||
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
if (bind(aSocket, (sockaddr*)&si_me, sizeof(si_me)) == -1) {
|
||||
LOG(ALERT) << "can't bind socket on port " << my_udp_port;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
LOG(NOTICE) << "binding on port " << my_udp_port;
|
||||
|
||||
while (true) {
|
||||
gConfig.purge();
|
||||
socklen_t slen = sizeof(si_other);
|
||||
memset(buf, 0, BUFLEN);
|
||||
if (recvfrom(aSocket, buf, BUFLEN, 0, (sockaddr*)&si_other, &slen) == -1) {
|
||||
LOG(ERR) << "recvfrom problem";
|
||||
continue;
|
||||
}
|
||||
|
||||
LOG(INFO) << " receiving " << buf;
|
||||
|
||||
char *dest = processBuffer(buf);
|
||||
if (dest == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sendto(aSocket, dest, strlen(dest), 0, (sockaddr*)&si_other, sizeof(si_other)) == -1) {
|
||||
LOG(ERR) << "sendto problem";
|
||||
continue;
|
||||
}
|
||||
osip_free(dest);
|
||||
}
|
||||
|
||||
close(aSocket);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,290 @@
|
|||
/*
|
||||
* Copyright 2011 Kestrel Signal Processing, Inc.
|
||||
* Copyright 2011 Range Networks, Inc.
|
||||
*
|
||||
* This software is distributed under the terms of the GNU Affero Public License.
|
||||
* See the COPYING file in the main directory for details.
|
||||
*
|
||||
* This use of this software may be subject to additional restrictions.
|
||||
* See the LEGAL file in the main directory for details.
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published by
|
||||
the Free Software Foundation, either version 3 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 Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <sqlite3.h>
|
||||
#include <time.h>
|
||||
#include "Configuration.h"
|
||||
#include "Logger.h"
|
||||
#include <string.h>
|
||||
#include "servershare.h"
|
||||
#include "SubscriberRegistry.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std;
|
||||
|
||||
ConfigurationTable gConfig("/etc/OpenBTS/OpenBTS.db");
|
||||
map<string,string> gArgs;
|
||||
string gDatabase;
|
||||
string gVisibleSipColumns;
|
||||
string gUrl;
|
||||
string gTitle;
|
||||
string gVisibleExtColumns = "exten dial";
|
||||
|
||||
// just using this for the database access
|
||||
SubscriberRegistry gSubscriberRegistry;
|
||||
|
||||
|
||||
#define NO_BUTTON 0
|
||||
#define UPDATE_BUTTON 1
|
||||
#define ADD_BUTTON 2
|
||||
#define DELETE_BUTTON 4
|
||||
|
||||
// may need some way to add/update a NULL field
|
||||
void tableRow(vector<string> &names, vector<string> &values, int buttons, string id)
|
||||
{
|
||||
cout << "<form name=\"input\" action=\"" << gUrl << "\" method=\"post\">\n";
|
||||
for (size_t i = 0; i < names.size(); i++) {
|
||||
string name = names[i];
|
||||
string value = values.size() == 0 ? "" : values[i];
|
||||
cout << "<input type=\"text\" name=\"" << name << "\" value=\"" << value << "\" />\n";
|
||||
}
|
||||
cout << "<input type=\"hidden\" name=\"id\" value=\"" << id << "\" />\n";
|
||||
if (buttons & UPDATE_BUTTON) {
|
||||
cout << "<input type=\"submit\" name=\"what\" value=\"Update\" />\n";
|
||||
}
|
||||
if (buttons & ADD_BUTTON) {
|
||||
cout << "<input type=\"submit\" name=\"what\" value=\"Add\" />\n";
|
||||
}
|
||||
if (buttons & DELETE_BUTTON) {
|
||||
cout << "<input type=\"submit\" name=\"what\" value=\"Delete\" />\n";
|
||||
}
|
||||
cout << "</form>\n";
|
||||
}
|
||||
|
||||
// make the header a fake form to get the same widths
|
||||
void initTable(vector<string> &cols)
|
||||
{
|
||||
tableRow(cols, cols, NO_BUTTON, "0");
|
||||
}
|
||||
|
||||
void table(const char *tableName, vector<string> &cols, bool addButtonP, const char *note)
|
||||
{
|
||||
cout << "<h4>" << gDatabase << "." << tableName << " (" << note << ")</h4>\n";
|
||||
initTable(cols);
|
||||
ostringstream os;
|
||||
os << "select id," << join(",", cols) << " from " << tableName;
|
||||
sqlite3_stmt *stmt;
|
||||
if (sqlite3_prepare_statement(gSubscriberRegistry.db(), &stmt,os.str().c_str())) {
|
||||
cout << "sqlite3_prepare_statement problem" << endl;
|
||||
return;
|
||||
}
|
||||
int src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
|
||||
while (src == SQLITE_ROW) {
|
||||
vector<string> values;
|
||||
const char *id = (const char*)sqlite3_column_text(stmt, 0);
|
||||
for (int i = 1; i <= (int)cols.size(); i++) {
|
||||
const char *value = (const char*)sqlite3_column_text(stmt, i);
|
||||
values.push_back(value ? value : "-NULL-");
|
||||
}
|
||||
tableRow(cols, values, UPDATE_BUTTON | DELETE_BUTTON, id);
|
||||
src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
if (addButtonP) {
|
||||
vector<string> dummy;
|
||||
tableRow(cols, dummy, ADD_BUTTON, "0");
|
||||
}
|
||||
}
|
||||
|
||||
void getFields(vector<string> *fields, vector<bool> *isSet)
|
||||
{
|
||||
vector<string> vsc;
|
||||
split(' ', gVisibleSipColumns, &vsc);
|
||||
sqlite3_stmt *stmt;
|
||||
const char *cmd = "pragma table_info(sip_buddies)";
|
||||
if (sqlite3_prepare_statement(gSubscriberRegistry.db(), &stmt, cmd)) {
|
||||
LOG(ERR) << "sqlite3_prepare_statement problem - statement: " << cmd;
|
||||
return;
|
||||
}
|
||||
int src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
|
||||
while (src == SQLITE_ROW) {
|
||||
string field = (char*)sqlite3_column_text(stmt, 1);
|
||||
fields->push_back(field);
|
||||
isSet->push_back(find(vsc.begin(), vsc.end(), field) != vsc.end());
|
||||
src = sqlite3_run_query(gSubscriberRegistry.db(), stmt);
|
||||
}
|
||||
sqlite3_finalize(stmt);
|
||||
}
|
||||
|
||||
void mainTables()
|
||||
{
|
||||
cout << "<form name=\"provision\" action=\"" << gUrl << "\" method=\"post\">\n";
|
||||
cout << "Phone Number = ";
|
||||
cout << "<input type=\"text\" name=\"phonenumber\" value=\"\" />\n";
|
||||
cout << "IMSI = ";
|
||||
cout << "<input type=\"text\" name=\"imsi\" value=\"\" />\n";
|
||||
cout << "<input type=\"submit\" name=\"what\" value=\"Provision\" />\n";
|
||||
cout << "</form>\n";
|
||||
cout << "<br><hr><br>\n";
|
||||
|
||||
vector<string> vsc;
|
||||
split(' ', gVisibleSipColumns, &vsc);
|
||||
table("sip_buddies", vsc, false, "scroll down to change which fields of sip_buddies are visible");
|
||||
cout << "<hr>";
|
||||
vector<string> vec;
|
||||
split(' ', gVisibleExtColumns, &vec);
|
||||
table("dialdata_table", vec, true, "");
|
||||
|
||||
cout << "<br><hr><br>\n";
|
||||
cout << "<FORM METHOD=\"LINK\" ACTION=\"" << gUrl << "\"> <INPUT TYPE=\"submit\" VALUE=\"Refresh\"> </FORM>\n";
|
||||
|
||||
cout << "<br><hr><br>\n";
|
||||
cout << "<h4>Selected fields are included in sip_buddies table (submit button at bottom)</h4>\n";
|
||||
cout << "<form method=\"post\" action=\"" << gUrl << "\">\n";
|
||||
vector<string> fields;
|
||||
vector<bool> isSet;
|
||||
getFields(&fields, &isSet);
|
||||
for (int i = 0; i < (int)fields.size(); i++) {
|
||||
string field = fields[i];
|
||||
string checked = isSet[i] ? "checked" : "";
|
||||
cout << "<input type=\"checkbox\" name=\"" << field << "\" value=\"" << field << "\"" << checked << " /> " << field << "<br />\n";
|
||||
}
|
||||
cout << "<br><INPUT TYPE=SUBMIT name=\"what\" VALUE=\"Submit\">\n";
|
||||
cout << "</form>\n";
|
||||
}
|
||||
|
||||
void doCmd(string cmd)
|
||||
{
|
||||
string table;
|
||||
vector<string> cols;
|
||||
if (gArgs.find("dial") == gArgs.end()) {
|
||||
table = "sip_buddies";
|
||||
split(' ', gVisibleSipColumns, &cols);
|
||||
} else {
|
||||
table = "dialdata_table";
|
||||
split(' ', gVisibleExtColumns, &cols);
|
||||
}
|
||||
string id = gArgs["id"];
|
||||
ostringstream os;
|
||||
if (cmd == "add") {
|
||||
string names = join(",", cols);
|
||||
vector<string> values0;
|
||||
vector<string>::iterator it;
|
||||
for (it = cols.begin(); it != cols.end(); it++) {
|
||||
values0.push_back("\"" + gArgs[*it] + "\"");
|
||||
}
|
||||
string values = join(",", values0);
|
||||
os << "insert into " << table << " (" << names << ") values (" << values << ")";
|
||||
} else if (cmd == "delete") {
|
||||
os << "delete from " << table << " where id = " << id;
|
||||
} else if (cmd == "update") {
|
||||
vector<string> sets0;
|
||||
vector<string>::iterator it;
|
||||
for (it = cols.begin(); it != cols.end(); it++) {
|
||||
sets0.push_back(*it + "=\"" + gArgs[*it] + "\"");
|
||||
}
|
||||
string sets = join(",", sets0);
|
||||
os << "update " << table << " set " << sets << " where id = " << id;
|
||||
} else {
|
||||
cout << "internal error<br>\n";
|
||||
}
|
||||
if (!sqlite3_command(gSubscriberRegistry.db(), os.str().c_str())) {
|
||||
cout << "sqlite3_command problem" << endl;
|
||||
return;
|
||||
}
|
||||
mainTables();
|
||||
}
|
||||
|
||||
void initHtml()
|
||||
{
|
||||
cout << "Content-Type: text/html\n\n";
|
||||
cout << "<HTML>\n";
|
||||
cout << "<HEAD>\n";
|
||||
cout << "<TITLE>" << gTitle << "</TITLE>\n";
|
||||
cout << "</HEAD>\n";
|
||||
cout << "<BODY>\n";
|
||||
cout << "<h4>" << gTitle << "</h4>\n";
|
||||
time_t rawtime;
|
||||
time ( &rawtime );
|
||||
struct tm * timeinfo;
|
||||
timeinfo = localtime ( &rawtime );
|
||||
cout << "<h4>" << asctime(timeinfo) << "</h4>\n";
|
||||
}
|
||||
|
||||
void endHtml()
|
||||
{
|
||||
cout << "</BODY>\n";
|
||||
cout << "</HTML>\n";
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
gLogInit("srmanager",gConfig.getStr("Log.Level").c_str(),LOG_LOCAL7);
|
||||
gSubscriberRegistry = SubscriberRegistry();
|
||||
// start the html return
|
||||
initHtml();
|
||||
// read the config file
|
||||
gVisibleSipColumns = gConfig.getStr("SubscriberRegistry.Manager.VisibleColumns");
|
||||
gUrl = argv[0];
|
||||
gTitle = gConfig.getStr("SubscriberRegistry.Manager.Title");
|
||||
// connect to the database
|
||||
gDatabase = gConfig.getStr("SubscriberRegistry.db");
|
||||
// decode the http query
|
||||
decodeQuery(gArgs);
|
||||
// execute command
|
||||
string what = gArgs["what"];
|
||||
if (!what.length() || what == "Main") {
|
||||
mainTables();
|
||||
} else if (what == "Add") {
|
||||
doCmd("add");
|
||||
} else if (what == "Update") {
|
||||
doCmd("update");
|
||||
} else if (what == "Delete") {
|
||||
doCmd("delete");
|
||||
} else if (what == "Provision") {
|
||||
gSubscriberRegistry.addUser(gArgs["imsi"].c_str(), gArgs["phonenumber"].c_str());
|
||||
mainTables();
|
||||
} else if (what == "Submit") {
|
||||
gVisibleSipColumns = "";
|
||||
map<string,string>::iterator it;
|
||||
bool first = true;
|
||||
for (it = gArgs.begin(); it != gArgs.end(); it++) {
|
||||
if (it->first == "what") continue;
|
||||
if (first) {
|
||||
first = false;
|
||||
} else {
|
||||
gVisibleSipColumns += " ";
|
||||
}
|
||||
gVisibleSipColumns += it->first;
|
||||
}
|
||||
if (!gConfig.set("SubscriberRegistry.Manager.VisibleColumns", gVisibleSipColumns)) {
|
||||
LOG(ERR) << "unable to update SubscriberRegistry.Manager.VisibleColumns";
|
||||
}
|
||||
mainTables();
|
||||
} else {
|
||||
cout << "unrecognized what parameter<br>\n";
|
||||
map<string,string>::iterator it;
|
||||
for (it = gArgs.begin(); it != gArgs.end(); it++) {
|
||||
cout << it->first << " -> " << it->second << "<br>\n";
|
||||
}
|
||||
}
|
||||
// finish the html return
|
||||
endHtml();
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
sub poot2 {
|
||||
my($line) = @_;
|
||||
# sip message printing adds the \r stuff. Get rid of it.
|
||||
$line =~ s/\\r//g;
|
||||
print "$line\n";
|
||||
}
|
||||
|
||||
sub poot {
|
||||
my($buf) = @_;
|
||||
# sip message printing comes in one big chunk. Split the lines.
|
||||
my(@buf) = split('\\\\n', $buf);
|
||||
&poot2($_) foreach @buf;
|
||||
}
|
||||
|
||||
sub main {
|
||||
open(IN, "/var/log/OpenBTS.log") || die;
|
||||
my(@out);
|
||||
while (<IN>) {
|
||||
chomp;
|
||||
# Ignore everything before the latest mark.
|
||||
if (/dwb syslog mark/) {
|
||||
@out = ();
|
||||
next;
|
||||
}
|
||||
if (/: INFO (0x[0-9a-fA-F]+|\d+) (.+)/) {
|
||||
# clean out garbage fro INFO lines
|
||||
push(@out, $2);
|
||||
} else {
|
||||
# keep all of other lines. (might be ERR or EMERG, e.g.)
|
||||
push(@out, $_);
|
||||
}
|
||||
}
|
||||
close(IN);
|
||||
poot $_ foreach @out;
|
||||
}
|
||||
|
||||
&main;
|
Loading…
Reference in New Issue