Open Source Billing
21
.htaccess
Normal file
@ -0,0 +1,21 @@
|
||||
# Turn on URL rewriting
|
||||
RewriteEngine On
|
||||
|
||||
# Installation directory
|
||||
RewriteBase /
|
||||
|
||||
# Protect hidden files from being viewed
|
||||
<Files .*>
|
||||
Order Deny,Allow
|
||||
Deny From All
|
||||
</Files>
|
||||
|
||||
# Protect application and system files from being viewed
|
||||
RewriteRule ^(?:application|modules|includes/kohana)\b.* index.php/$0 [L]
|
||||
|
||||
# Allow any files or directories that exist to be displayed directly
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
RewriteCond %{REQUEST_FILENAME} !-d
|
||||
|
||||
# Rewrite all other URLs to index.php/URL
|
||||
RewriteRule .* index.php/$0 [PT]
|
674
LICENSE
Normal file
@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 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 General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is 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. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
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.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
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 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. Use with the GNU Affero General Public License.
|
||||
|
||||
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 Affero 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 special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU 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 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 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 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 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 General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU 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 the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
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 GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
169
application/bootstrap.php
Normal file
@ -0,0 +1,169 @@
|
||||
<?php defined('SYSPATH') or die('No direct script access.');
|
||||
|
||||
// -- Environment setup --------------------------------------------------------
|
||||
|
||||
// Load the core Kohana class
|
||||
require SYSPATH.'classes/Kohana/Core'.EXT;
|
||||
|
||||
if (is_file(APPPATH.'classes/Kohana'.EXT))
|
||||
{
|
||||
// Application extends the core
|
||||
require APPPATH.'classes/Kohana'.EXT;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load empty core extension
|
||||
require SYSPATH.'classes/Kohana'.EXT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the default time zone.
|
||||
*
|
||||
* @link http://kohanaframework.org/guide/using.configuration
|
||||
* @link http://www.php.net/manual/timezones
|
||||
*/
|
||||
date_default_timezone_set('Australia/Melbourne');
|
||||
|
||||
/**
|
||||
* Set the default locale.
|
||||
*
|
||||
* @link http://kohanaframework.org/guide/using.configuration
|
||||
* @link http://www.php.net/manual/function.setlocale
|
||||
*/
|
||||
setlocale(LC_ALL, 'en_US.utf-8');
|
||||
|
||||
/**
|
||||
* Enable the Kohana auto-loader.
|
||||
*
|
||||
* @link http://kohanaframework.org/guide/using.autoloading
|
||||
* @link http://www.php.net/manual/function.spl-autoload-register
|
||||
*/
|
||||
spl_autoload_register(array('Kohana', 'auto_load'));
|
||||
|
||||
/**
|
||||
* Optionally, you can enable a compatibility auto-loader for use with
|
||||
* older modules that have not been updated for PSR-0.
|
||||
*
|
||||
* It is recommended to not enable this unless absolutely necessary.
|
||||
*/
|
||||
//spl_autoload_register(array('Kohana', 'auto_load_lowercase'));
|
||||
|
||||
/**
|
||||
* Enable the Kohana auto-loader for unserialization.
|
||||
*
|
||||
* @link http://www.php.net/manual/function.spl-autoload-call
|
||||
* @link http://www.php.net/manual/var.configuration#unserialize-callback-func
|
||||
*/
|
||||
ini_set('unserialize_callback_func', 'spl_autoload_call');
|
||||
|
||||
// -- Configuration and initialization -----------------------------------------
|
||||
|
||||
/**
|
||||
* Set the default language
|
||||
*/
|
||||
I18n::lang('en-us');
|
||||
|
||||
/**
|
||||
* Set Kohana::$environment if a 'KOHANA_ENV' environment variable has been supplied.
|
||||
*
|
||||
* Note: If you supply an invalid environment name, a PHP warning will be thrown
|
||||
* saying "Couldn't find constant Kohana::<INVALID_ENV_NAME>"
|
||||
*/
|
||||
if (isset($_SERVER['KOHANA_ENV']))
|
||||
{
|
||||
Kohana::$environment = constant('Kohana::'.strtoupper($_SERVER['KOHANA_ENV']));
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize Kohana, setting the default options.
|
||||
*
|
||||
* The following options are available:
|
||||
*
|
||||
* - string base_url path, and optionally domain, of your application NULL
|
||||
* - string index_file name of your index file, usually "index.php" index.php
|
||||
* - string charset internal character set used for input and output utf-8
|
||||
* - string cache_dir set the internal cache directory APPPATH/cache
|
||||
* - integer cache_life lifetime, in seconds, of items cached 60
|
||||
* - boolean errors enable or disable error handling TRUE
|
||||
* - boolean profile enable or disable internal profiling TRUE
|
||||
* - boolean caching enable or disable internal caching FALSE
|
||||
* - boolean expose set the X-Powered-By header FALSE
|
||||
*/
|
||||
Kohana::init(array(
|
||||
'base_url' => '/',
|
||||
'caching' => TRUE,
|
||||
'index_file' => '',
|
||||
));
|
||||
|
||||
/**
|
||||
* Attach the file write to logging. Multiple writers are supported.
|
||||
*/
|
||||
Kohana::$log->attach(new Log_File(APPPATH.'logs'));
|
||||
|
||||
/**
|
||||
* Attach a file reader to config. Multiple readers are supported.
|
||||
*/
|
||||
Kohana::$config->attach(new Config_File);
|
||||
|
||||
/**
|
||||
* Enable modules. Modules are referenced by a relative or absolute path.
|
||||
*/
|
||||
Kohana::modules(array(
|
||||
'lnapp' => MODPATH.'lnApp',
|
||||
'auth' => SMDPATH.'auth', // Basic authentication
|
||||
'cache' => SMDPATH.'cache', // Caching with multiple backends
|
||||
'cron' => SMDPATH.'cron', // Kohana Cron Module
|
||||
// 'codebench' => SMDPATH.'codebench', // Benchmarking tool
|
||||
'database' => SMDPATH.'database', // Database access
|
||||
'gchart' => MODPATH.'gchart', // Google Chart Module
|
||||
// 'image' => SMDPATH.'image', // Image manipulation
|
||||
'khemail' => SMDPATH.'khemail', // Email module for Kohana 3 PHP Framework
|
||||
'minion' => SMDPATH.'minion', // CLI Tasks
|
||||
'orm' => SMDPATH.'orm', // Object Relationship Mapping
|
||||
'pagination' => SMDPATH.'pagination', // Kohana Pagination module for Kohana 3 PHP Framework
|
||||
// 'unittest' => SMDPATH.'unittest', // Unit testing
|
||||
// 'userguide' => SMDPATH.'userguide', // User guide and API documentation
|
||||
'xml' => SMDPATH.'xml', // XML module for Kohana 3 PHP Framework
|
||||
));
|
||||
|
||||
/**
|
||||
* Load our modules defined in the DB
|
||||
*/
|
||||
Kohana::modules(array_merge(Kohana::modules(),Config::modules()));
|
||||
|
||||
/**
|
||||
* Enable specalised interfaces
|
||||
*/
|
||||
Route::set('sections', '<directory>/<controller>(/<action>(/<id>(/<sid>)))',
|
||||
array(
|
||||
'directory' => '('.implode('|',array_values(URL::$method_directory)).')'
|
||||
))
|
||||
->defaults(array(
|
||||
'action' => 'index',
|
||||
));
|
||||
|
||||
// Static file serving (CSS, JS, images)
|
||||
Route::set('default/media', 'media(/<file>)', array('file' => '.+'))
|
||||
->defaults(array(
|
||||
'controller' => 'media',
|
||||
'action' => 'get',
|
||||
));
|
||||
|
||||
/**
|
||||
* Set the routes. Each route must have a minimum of a name, a URI and a set of
|
||||
* defaults for the URI.
|
||||
*/
|
||||
Route::set('default', '(<controller>(/<action>(/<id>)))', array('id'=>'[a-zA-Z0-9_.-]+'))
|
||||
->defaults(array(
|
||||
'controller' => 'welcome',
|
||||
'action' => 'index',
|
||||
));
|
||||
|
||||
/**
|
||||
* If APC is enabled, and we need to clear the cache
|
||||
*/
|
||||
if (file_exists(APPPATH.'cache/CLEAR_APC_CACHE') AND function_exists('apc_clear_cache') AND (PHP_SAPI !== 'cli')) {
|
||||
if (! apc_clear_cache() OR ! unlink(APPPATH.'cache/CLEAR_APC_CACHE'))
|
||||
throw new Kohana_Exception('Unable to clear the APC cache.');
|
||||
}
|
||||
?>
|
2
application/cache/.htaccess
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
order allow,deny
|
||||
deny from all
|
22
application/classes/Auth/ORM.php
Normal file
@ -0,0 +1,22 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's Auth
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Auth_ORM extends Kohana_Auth_ORM {
|
||||
// Override Kohana Auth requirement to have a hash_key
|
||||
public function hash($str) {
|
||||
switch ($this->_config['hash_method']) {
|
||||
case '' : return $str;
|
||||
case 'md5': return md5($str);
|
||||
default: return hash_hmac($this->_config['hash_method'], $str, $this->_config['hash_key']);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
275
application/classes/Auth/OSB.php
Normal file
@ -0,0 +1,275 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Auth driver.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Auth_OSB extends Auth_ORM {
|
||||
/**
|
||||
* OSB authentication is controlled via database queries.
|
||||
*
|
||||
* This method can be used to test two situations:
|
||||
* 1) Is the user logged in? ($role == FALSE)
|
||||
* 2) Can the user run the current controller->action ($role == TRUE)
|
||||
*
|
||||
* @param boolean If authentication should be done for this module:method (ie: controller:action).
|
||||
* @return boolean
|
||||
*/
|
||||
public function logged_in($role=NULL,$debug=NULL) {
|
||||
$status = FALSE;
|
||||
|
||||
// Get the user from the session
|
||||
$uo = $this->get_user();
|
||||
|
||||
// If we are not a valid user object, then we are not logged in
|
||||
if (is_object($uo) AND ($uo instanceof Model_Account) AND $uo->loaded()) {
|
||||
if (Config::sitemode() == Kohana::DEVELOPMENT)
|
||||
SystemMessage::add(array('title'=>'Debug','type'=>'debug','body'=>Debug::vars(array('user'=>$uo->username,'r'=>$role))));
|
||||
|
||||
if (! empty($role)) {
|
||||
// Get the module details
|
||||
$mo = ORM::factory('Module',array('name'=>Request::current()->controller()));
|
||||
if (! $mo->loaded() OR ! $mo->status) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Module is not defined or active in the Database',
|
||||
'type'=>'warning',
|
||||
'body'=>sprintf('Module not defined: %s',Request::current()->controller()),
|
||||
));
|
||||
|
||||
} else {
|
||||
if (Request::current()->directory())
|
||||
$method_name = sprintf('%s_%s',Request::current()->directory(),Request::current()->action());
|
||||
else
|
||||
$method_name = Request::current()->action();
|
||||
|
||||
// Get the method number
|
||||
$mmo = ORM::factory('Module_Method',array('module_id'=>$mo->id,'name'=>$method_name));
|
||||
if (! $mmo->loaded()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Method is not defined or active in the Database',
|
||||
'type'=>'warning',
|
||||
'body'=>sprintf('Method not defined: %s for %s',Request::current()->action(),$mo->name),
|
||||
));
|
||||
|
||||
} else {
|
||||
// If the role has the authorisation to run the method
|
||||
$gmo = ORM::factory('Group_Method')
|
||||
->where('method_id','=',$mmo->id);
|
||||
|
||||
$roles = '';
|
||||
foreach ($gmo->find_all() as $gm) {
|
||||
$roles .= ($roles ? '|' : '').$gm->group->name;
|
||||
|
||||
// $gm->group->id == 0 means all users.
|
||||
if ($gm->group->id == 0 OR $uo->has_any('group',$gm->group->list_childgrps(TRUE))) {
|
||||
$status = TRUE;
|
||||
$roles = '';
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! $status) {
|
||||
if (Config::sitemode() == Kohana::DEVELOPMENT)
|
||||
SystemMessage::add(array(
|
||||
'title'=>'User is not authorised in Database',
|
||||
'type'=>'debug',
|
||||
'body'=>sprintf('Role(s) checked: %s<br/>User: %s</br>Module: %s<br/>Method: %s',$roles,$uo->username,$mo->name,$mmo->name),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Config::sitemode() == Kohana::DEVELOPMENT)
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Debug',
|
||||
'type'=>'debug',
|
||||
'body'=>sprintf('User: <b>%s</b>, Module: <b>%s</b>, Method: <b>%s</b>, Role: <b>%s</b>, Status: <b>%s</b>, Data: <b>%s</b>',
|
||||
$uo->username,Request::current()->controller(),Request::current()->action(),$role,$status,$debug)));
|
||||
|
||||
// There is no role, so the method should be allowed to run as anonymous
|
||||
} else {
|
||||
if (Config::sitemode() == Kohana::DEVELOPMENT)
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Debug',
|
||||
'type'=>'debug',
|
||||
'body'=>sprintf('User: <b>%s</b>, Module: <b>%s</b>, Method: <b>%s</b>, Status: <b>%s</b>, Data: <b>%s</b>',
|
||||
$uo->username,Request::current()->controller(),Request::current()->action(),'No Role Default Access',$debug)));
|
||||
|
||||
$status = TRUE;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (Config::sitemode() == Kohana::DEVELOPMENT)
|
||||
SystemMessage::add(array('title'=>'Debug','type'=>'debug','body'=>'No user logged in'));
|
||||
}
|
||||
|
||||
return $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the currently logged in user from the session.
|
||||
* Returns NULL if no user is currently logged in.
|
||||
*
|
||||
* @param boolean Check token users too
|
||||
* @return mixed
|
||||
*/
|
||||
public function get_user($default=NULL,$tokenuser=TRUE) {
|
||||
// Get the current user
|
||||
$uo = parent::get_user($default);
|
||||
|
||||
// If we are not logged in, see if there is token for the user
|
||||
if (is_null($uo) AND $tokenuser AND ($token=Session::instance()->get('token')) OR (! empty($_REQUEST['token']) AND $token=$_REQUEST['token']))
|
||||
$uo = $this->_get_token_user($token);
|
||||
|
||||
return $uo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user that a token applies to
|
||||
*
|
||||
* This will check that the token is valid (not expired and for the request)
|
||||
*
|
||||
* @param $token The token
|
||||
* @return Model_Account|NULL The user that the token is valid for.
|
||||
*/
|
||||
private function _get_token_user($token) {
|
||||
// This has been implemented, as we sometimes we seem to come here twice
|
||||
static $uo = NULL;
|
||||
|
||||
if (! is_null($uo))
|
||||
return $uo;
|
||||
|
||||
$mmto = ORM::factory('Module_Method_Token',array('token'=>$token));
|
||||
|
||||
// Ignore the token if it doesnt exist.
|
||||
if ($mmto->loaded()) {
|
||||
// Check that the token is for this URI
|
||||
$mo = ORM::factory('Module',array('name'=>Request::current()->controller()));
|
||||
$mmo = ORM::factory('Module_Method',array(
|
||||
'module_id'=>$mo->id,
|
||||
'name'=>Request::current()->directory() ? sprintf('%s_%s',Request::current()->directory(),Request::current()->action()) : Request::current()->action()
|
||||
));
|
||||
|
||||
// Ignore the token if this is not the right method.
|
||||
if ($mmo->id == $mmto->method_id) {
|
||||
if (! is_null($mmto->date_expire) AND $mmto->date_expire < time()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Token Not Valid'),
|
||||
'type'=>'warning',
|
||||
'body'=>_('Token expired')));
|
||||
|
||||
// @todo Log the token deletion
|
||||
Session::instance()->delete('token');
|
||||
$mmto->delete();
|
||||
|
||||
} elseif (! is_null($mmto->uses) AND $mmto->uses < 1) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Token Not Valid'),
|
||||
'type'=>'warning',
|
||||
'body'=>_('Token expired')));
|
||||
|
||||
// @todo Log the token deletion
|
||||
Session::instance()->delete('token');
|
||||
$mmto->delete();
|
||||
|
||||
} else {
|
||||
// If this is a usage count token, reduce the count.
|
||||
if (! is_null($mmto->uses))
|
||||
$mmto->uses -= 1;
|
||||
|
||||
// Record the date this token was used
|
||||
$mmto->date_last = time();
|
||||
$mmto->save();
|
||||
|
||||
Session::instance()->set('token',$token);
|
||||
|
||||
$uo = ORM::factory('Account',$mmto->account_id);
|
||||
$uo->log(sprintf('Token %s used for method %s [%s]',$mmto->token,$mmto->module_method->name(),Request::current()->param('id')));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $uo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs a user in.
|
||||
*
|
||||
* @param string username
|
||||
* @param string password
|
||||
* @param boolean enable autologin
|
||||
* @return boolean
|
||||
*/
|
||||
protected function _login($user,$password,$remember) {
|
||||
if (! is_object($user)) {
|
||||
$username = $user;
|
||||
|
||||
// Load the user
|
||||
$user = ORM::factory('Account');
|
||||
$user->where('username','=',$username)->find();
|
||||
|
||||
// If no user loaded, return
|
||||
if (! $user->loaded())
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Create a hashed password
|
||||
if (is_string($password))
|
||||
$password = $this->hash($password);
|
||||
|
||||
// If the passwords match, perform a login
|
||||
if ($user->status AND $user->has_any('group',ORM::factory('Group',array('name'=>'Registered Users'))->list_childgrps(TRUE)) AND $user->password === $password) {
|
||||
|
||||
// @todo This is not currently used.
|
||||
if ($remember === TRUE) {
|
||||
// Create a new autologin token
|
||||
$token = ORM::factory('User_Token');
|
||||
|
||||
// Set token data
|
||||
$token->user_id = $user->id;
|
||||
$token->expires = time() + $this->_config['lifetime'];
|
||||
$token->save();
|
||||
|
||||
// Set the autologin cookie
|
||||
Cookie::set('authautologin', $token->token, $this->_config['lifetime']);
|
||||
}
|
||||
|
||||
// Record our session ID, we may need to update our DB when we get a new ID
|
||||
$oldsess = session_id();
|
||||
|
||||
// Finish the login
|
||||
$this->complete_login($user);
|
||||
|
||||
// Do we need to update databases with our new sesion ID
|
||||
$sct = Kohana::$config->load('config')->session_change_trigger;
|
||||
if (session_id() != $oldsess AND count($sct))
|
||||
foreach ($sct as $t => $c)
|
||||
if (Config::module_exist($t))
|
||||
foreach (ORM::factory(ucwords($t))->where($c,'=',$oldsess)->find_all() as $o)
|
||||
$o->set('session_id',session_id())
|
||||
->update();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Login failed
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a user is authorised to view an account
|
||||
*
|
||||
* @param Model_Account Account Ojbect to validate if the current user has access
|
||||
* @return boolean TRUE if authorised, FALSE if not.
|
||||
*/
|
||||
public function authorised(Model_Account $ao) {
|
||||
return (($uo = $this->get_user()) AND $uo->loaded() AND ($uo == $ao OR in_array($ao->id,$uo->RTM->customers($uo->RTM))));
|
||||
}
|
||||
}
|
||||
?>
|
139
application/classes/Company.php
Normal file
@ -0,0 +1,139 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class is for access company information.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Company {
|
||||
// Our Company Setup object
|
||||
private $so;
|
||||
|
||||
public function __construct(Model_Setup $so) {
|
||||
$this->so = $so;
|
||||
|
||||
if (! $this->so->loaded())
|
||||
throw new Kohana_Exception(_('Site [:site] not defined in DB?'),array(':site'=>URL::base('http')));
|
||||
|
||||
Kohana::$environment = (int)$this->so->status;
|
||||
}
|
||||
|
||||
public static function instance() {
|
||||
return new Company(ORM::factory('Setup',array('url'=>URL::base('http'))));
|
||||
}
|
||||
|
||||
public function admin() {
|
||||
return $this->so->account->name();
|
||||
}
|
||||
|
||||
public function address($ln='<br/>') {
|
||||
return implode($ln,array($this->street($ln),sprintf('%s, %s %s',$this->city(),$this->state(),$this->pcode())));
|
||||
}
|
||||
|
||||
public function city() {
|
||||
return $this->so->site_details('city');
|
||||
}
|
||||
|
||||
public function contacts() {
|
||||
return 'Tel: '.$this->phone();
|
||||
}
|
||||
|
||||
public function country() {
|
||||
return $this->so->country;
|
||||
}
|
||||
|
||||
public function date_format() {
|
||||
return $this->so->date_format;
|
||||
}
|
||||
|
||||
public function decimals() {
|
||||
return $this->so->decimal_place;
|
||||
}
|
||||
|
||||
public function email() {
|
||||
return $this->so->site_details('email');
|
||||
}
|
||||
|
||||
public function fax() {
|
||||
return $this->so->site_details('fax');
|
||||
}
|
||||
|
||||
public function language() {
|
||||
return $this->so->language->iso;
|
||||
}
|
||||
|
||||
public function logo() {
|
||||
return Config::logo();
|
||||
}
|
||||
|
||||
public function logo_file() {
|
||||
list ($path,$suffix) = explode('.',Config::$logo);
|
||||
|
||||
return ($x=Kohana::find_file(sprintf('media/site/%s',$this->site()),$path,$suffix)) ? $x : Kohana::find_file('media',$path,$suffix);
|
||||
}
|
||||
|
||||
public function name() {
|
||||
return $this->so->site_details('name');
|
||||
}
|
||||
|
||||
public function module_config($item) {
|
||||
return $this->so->module_config($item);
|
||||
}
|
||||
|
||||
public function pcode() {
|
||||
return $this->so->site_details('pcode');
|
||||
}
|
||||
|
||||
public function phone() {
|
||||
return $this->so->site_details('phone');
|
||||
}
|
||||
|
||||
public function site($format=FALSE) {
|
||||
return $format ? sprintf('%02s',$this->so->id) : $this->so->id;
|
||||
}
|
||||
|
||||
public function so() {
|
||||
return $this->so;
|
||||
}
|
||||
|
||||
public function state() {
|
||||
return $this->so->site_details('state');
|
||||
}
|
||||
|
||||
public function street($ln='<br/>') {
|
||||
return $this->so->site_details('address2') ? implode($ln,array($this->so->site_details('address1'),$this->so->site_details('address2'))) : $this->so->site_details('address1');
|
||||
}
|
||||
|
||||
public function sitemode() {
|
||||
return $this->so->status;
|
||||
}
|
||||
|
||||
public function taxid() {
|
||||
// Tax ID details are stored in invoice config
|
||||
$mc = $this->so->module_config('invoice');
|
||||
|
||||
if (empty($mc['TAX_ID_NAME']))
|
||||
return empty($mc['TAX_ID']) ? '' : $mc['TAX_ID'];
|
||||
else
|
||||
return sprintf('%s: %s',$mc['TAX_ID_NAME'],empty($mc['TAX_ID']) ? '' : $mc['TAX_ID']);
|
||||
}
|
||||
|
||||
public function time_format() {
|
||||
return $this->so->time_format;
|
||||
}
|
||||
|
||||
public static function bsb() {
|
||||
// @todo Details should be obtained from DB
|
||||
return Kohana::$config->load('config')->bsb;
|
||||
}
|
||||
|
||||
public static function account() {
|
||||
// @todo Details should be obtained from DB
|
||||
return Kohana::$config->load('config')->accnum;
|
||||
}
|
||||
}
|
||||
?>
|
177
application/classes/Config.php
Normal file
@ -0,0 +1,177 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class extends the core Kohana class by adding some core application
|
||||
* specific functions, and configuration.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Config extends Kohana_Config {
|
||||
// Our default logo, if there is no site logo
|
||||
public static $logo = 'img/logo-small.png';
|
||||
|
||||
/**
|
||||
* @compat Restore KH 3.1 functionality
|
||||
* @var Kohana_Config Singleton static instance
|
||||
*/
|
||||
protected static $_instance;
|
||||
|
||||
/**
|
||||
* Some early initialisation
|
||||
*
|
||||
* At this point, KH hasnt been fully initialised either, so we cant rely on
|
||||
* too many KH functions yet.
|
||||
*
|
||||
* NOTE: Kohana doesnt provide a parent construct for the Kohana_Config class.
|
||||
*/
|
||||
public function __construct() {
|
||||
if (defined('PHPUNITTEST'))
|
||||
$_SERVER['SERVER_NAME'] = PHPUNITTEST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the singleton instance of Config.
|
||||
*
|
||||
* $config = Config::instance();
|
||||
*
|
||||
* @return Config
|
||||
* @compat Restore KH 3.1 functionality
|
||||
*/
|
||||
public static function instance() {
|
||||
if (Config::$_instance === NULL)
|
||||
// Create a new instance
|
||||
Config::$_instance = new Config;
|
||||
|
||||
return Config::$_instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return our caching mechanism
|
||||
*/
|
||||
public static function cachetype() {
|
||||
return is_null(Kohana::$config->load('config')->cache_type) ? 'file' : Kohana::$config->load('config')->cache_type;
|
||||
}
|
||||
|
||||
public static function copywrite() {
|
||||
return '(c) Open Source Billing Development Team';
|
||||
}
|
||||
|
||||
public static function country() {
|
||||
return Company::instance()->country();
|
||||
}
|
||||
|
||||
public static function date($date) {
|
||||
return date(Company::instance()->date_format(),($date ? $date : time()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a date using a site configured format
|
||||
* @note We need this function here, since we call static:: methods, which need to resolve to the child class.
|
||||
*/
|
||||
public static function datetime($date) {
|
||||
return sprintf('%s %s',static::date($date),static::time($date));
|
||||
}
|
||||
|
||||
public static function language() {
|
||||
return Company::instance()->language();
|
||||
}
|
||||
|
||||
/**
|
||||
* The URI to show for the login prompt.
|
||||
* Normally if the user is logged in, we can replace it with something else
|
||||
*/
|
||||
public static function login_uri() {
|
||||
return ($ao = Auth::instance()->get_user() AND is_object($ao)) ? HTML::anchor(URL::link('user','account/edit'),$ao->name()) : HTML::anchor('login',_('Login'));
|
||||
}
|
||||
|
||||
public static function logo() {
|
||||
return HTML::image(static::logo_uri(),array('class'=>'headlogo','alt'=>_('Logo')));
|
||||
}
|
||||
|
||||
public static function logo_uri($protocol=NULL) {
|
||||
list ($path,$suffix) = explode('.',static::$logo);
|
||||
|
||||
return URL::site(Route::get('default/media')->uri(array('file'=>$path.'.'.$suffix),array('alt'=>static::sitename())),$protocol);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a list of all database enabled modules
|
||||
*
|
||||
* Our available modules are defined in the DB (along with method
|
||||
* security).
|
||||
*/
|
||||
public static function modules() {
|
||||
static $result = array();
|
||||
|
||||
if (! count($result)) {
|
||||
// We need to know our site here, so that we can subsequently load our enabled modules.
|
||||
if (PHP_SAPI === 'cli') {
|
||||
if (! $site = Minion_CLI::options('site'))
|
||||
// @todo Need to figure out how to make this CLI error nicer.
|
||||
throw new Minion_Exception_InvalidTask(_('Cant figure out the site, use --site= for CLI'));
|
||||
else
|
||||
$_SERVER['SERVER_NAME'] = $site;
|
||||
}
|
||||
|
||||
foreach (ORM::factory('Module')->list_external() as $mo)
|
||||
$result[$mo->name] = MODPATH.$mo->name;
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function module_config($item) {
|
||||
return Company::instance()->module_config($item);
|
||||
}
|
||||
|
||||
public static function module_exist($module) {
|
||||
return array_key_exists(strtolower($module),static::modules()) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
public static function siteid($format=FALSE) {
|
||||
return Company::instance()->site($format);
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out our site mode (dev,test,prod)
|
||||
*/
|
||||
public static function sitemode() {
|
||||
return Company::instance()->sitemode();
|
||||
}
|
||||
|
||||
public static function sitename() {
|
||||
return Company::instance()->name();
|
||||
}
|
||||
|
||||
/**
|
||||
* See if our emails for the template should be sent to configured admin(s)
|
||||
*
|
||||
* @param string template - Template to test for
|
||||
* @return mixed|array - Email to send test emails to
|
||||
*/
|
||||
public static function testmail($template) {
|
||||
$config = Kohana::$config->load('config')->email_admin_only;
|
||||
|
||||
if (is_null($config) OR ! is_array($config) OR empty($config[$template]))
|
||||
return FALSE;
|
||||
else
|
||||
return $config[$template];
|
||||
}
|
||||
|
||||
public static function theme() {
|
||||
// If we are using user admin pages (and login), we'll choose the admin theme.
|
||||
if (! empty(URL::$method_directory[strtolower(Request::current()->directory())]) OR in_array(strtolower(Request::current()->controller()),array('login')))
|
||||
return 'theme/'.Kohana::$config->load('config')->theme_admin;
|
||||
else
|
||||
return 'theme/'.Kohana::$config->load('config')->theme;
|
||||
}
|
||||
|
||||
public static function time($date) {
|
||||
return date(Company::instance()->time_format(),($date ? $date : time()));
|
||||
}
|
||||
}
|
||||
?>
|
33
application/classes/Controller/Account.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides account management
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Account extends Controller_TemplateDefault {
|
||||
public function action_group() {
|
||||
$output = '';
|
||||
|
||||
$cg = $this->ao->group->find_all();
|
||||
|
||||
foreach ($cg as $go) {
|
||||
$output .= sprintf('Group %s: %s<br/>',$go->id,$go->display('name'));
|
||||
|
||||
foreach ($go->list_childgrps(TRUE) as $cgo)
|
||||
$output .= sprintf('- %s: %s (%s)<br/>',$cgo->id,$cgo->display('name'),$cgo->parent_id);
|
||||
|
||||
$output .= sprintf('END Group %s<br/><br/>',$go->id);
|
||||
}
|
||||
|
||||
Block::add(array(
|
||||
'title'=>'Group Structure',
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
17
application/classes/Controller/Admin/Account.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Admin Account management
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Admin
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Account extends Controller_Account {
|
||||
protected $secure_actions = array(
|
||||
'group'=>FALSE, // @todo Testing
|
||||
);
|
||||
}
|
||||
?>
|
130
application/classes/Controller/Admin/Module.php
Normal file
@ -0,0 +1,130 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides MODULE management
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Admin
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Module extends Controller_Module {
|
||||
protected $secure_actions = array(
|
||||
'add'=>TRUE,
|
||||
'edit'=>TRUE,
|
||||
'list'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Get the list of methods for a class
|
||||
*/
|
||||
protected function _methods($class) {
|
||||
// Get a list of methods this module has
|
||||
$ch = 'Controller_%s';
|
||||
$methods = array();
|
||||
|
||||
// List of classes where all our methods are, including this one.
|
||||
$classes = URL::$method_directory;
|
||||
array_unshift($classes,'');
|
||||
|
||||
foreach ($classes as $c) {
|
||||
$cn = Kohana::classname('Controller_'.$c ? $c.'_'.$class : $class);
|
||||
|
||||
if (class_exists($cn)) {
|
||||
$r = new ReflectionClass($cn);
|
||||
|
||||
foreach ($r->getMethods() as $method)
|
||||
if (preg_match('/^Controller_(.*_)?'.$class.'$/i',$method->class) AND ! preg_match('/^_/',$method->name))
|
||||
array_push($methods,str_replace('action_',($c ? $c.'_' : $c),$method->name));
|
||||
}
|
||||
}
|
||||
|
||||
return $methods;
|
||||
}
|
||||
|
||||
/**
|
||||
* List our installed modules
|
||||
*/
|
||||
public function action_list() {
|
||||
$mo = ORM::factory('Module');
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Defined Modules'),
|
||||
'body'=>Table::display(
|
||||
$mo->find_all(),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('admin','module/edit/')),
|
||||
'name'=>array('label'=>'Name'),
|
||||
'status'=>array('label'=>'Active'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'list',
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a Module Configuration
|
||||
*
|
||||
* @todo Highlight those methods that have security, but the class does not have auth_required set to YES or the method isnt defined in secure_actions
|
||||
*/
|
||||
public function action_edit() {
|
||||
$mid = $this->request->param('id');
|
||||
$mo = ORM::factory('Module',$mid);
|
||||
|
||||
if (! $mo->loaded()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Invalid Module ID'),
|
||||
'type'=>'error',
|
||||
'body'=>sprintf(_('Module with ID %s doesnt appear to exist?'),$mid),
|
||||
));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$output = '';
|
||||
$methods = $this->_methods($mo->name);
|
||||
|
||||
// Show methods defined in the DB already.
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s ',_('Defined Module Methods For'),$mo->display('name')),
|
||||
'body'=>Table::display(
|
||||
$mo->module_method->find_all(),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('admin','module_method/edit/')),
|
||||
'name'=>array('label'=>'Name'),
|
||||
'notes'=>array('label'=>'Notes'),
|
||||
'menu_display'=>array('label'=>'Menu'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'list',
|
||||
)),
|
||||
));
|
||||
|
||||
// Show new methods NOT defined in the DB already.
|
||||
foreach ($mo->module_method->find_all() as $meo)
|
||||
if (($method = array_search($meo->name,$methods)) !== false)
|
||||
unset($methods[$method]);
|
||||
|
||||
if (count($methods))
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s ',_('Undefined Module Methods For'),$mo->display('name')),
|
||||
'body'=>Table::display(
|
||||
$methods,
|
||||
25,
|
||||
array(
|
||||
'__VALUE__'=>array('label'=>'Name','url'=>URL::link('admin','module_method/add/'.$mo->id)),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'list',
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
137
application/classes/Controller/Admin/Module/Method.php
Normal file
@ -0,0 +1,137 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides MODULE management
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Admin
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Module_Method extends Controller_Admin_Module {
|
||||
/**
|
||||
* Add a method to the database
|
||||
*/
|
||||
public function action_add() {
|
||||
$id = $this->request->param('id');
|
||||
$method = $this->request->param('sid');
|
||||
|
||||
$mo = ORM::factory('Module',$id);
|
||||
$mmo = ORM::factory('Module_Method');
|
||||
|
||||
if (! $mo->loaded() OR ! in_array($method,$this->_methods($mo->name)))
|
||||
throw new Kohana_Exception('Method (:method) does not exist in :class',array(':method'=>$method,':class'=>$mo->name));
|
||||
|
||||
$mmo->name = $method;
|
||||
$mmo->module_id = $mo->id;
|
||||
$mmo->values($_POST);
|
||||
|
||||
$output = '';
|
||||
|
||||
if ($_POST AND $mmo->values($_POST)->check()) {
|
||||
$mmo->save();
|
||||
|
||||
if ($mmo->saved()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Method Added'),
|
||||
'type'=>'info',
|
||||
'body'=>sprintf(_('Method %s defined to database'),$mmo->name),
|
||||
));
|
||||
|
||||
HTTP::redirect(URL::link('admin','/module/edit/'.$mo->id));
|
||||
|
||||
} else {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Method Not Saved'),
|
||||
'type'=>'error',
|
||||
'body'=>sprintf(_('Unable to define Method %s to database?'),$mmo->name),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
$output .= View::factory('module/admin/method_add')
|
||||
->set('module',$mo)
|
||||
->set('method',$mmo);
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf(_('Add Method (%s) to Database for (%s)'),strtoupper($mmo->name),strtoupper($mo->name)),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a Module Configuration
|
||||
*
|
||||
* @param int $mid Module ID
|
||||
*/
|
||||
public function action_edit() {
|
||||
$mid = $this->request->param('id');
|
||||
$mmo = ORM::factory('Module_Method',$mid);
|
||||
|
||||
if (! $mmo->loaded()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Invalid Method ID'),
|
||||
'type'=>'error',
|
||||
'body'=>sprintf(_('Method with ID %s doesnt appear to exist?'),$mid),
|
||||
));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$output = '';
|
||||
|
||||
// The groups that can run this method.
|
||||
$groups = ORM::factory('Group');
|
||||
|
||||
if ($_POST) {
|
||||
foreach ($groups->find_all() as $go) {
|
||||
// If the group was defined and no longer
|
||||
if ($mmo->has('group',$go) AND (! isset($_POST['groups']) OR ! in_array($go->id,$_POST['groups']))) {
|
||||
$gm = ORM::factory('Group_Method',array('method_id'=>$mmo->id,'group_id'=>$go->id));
|
||||
|
||||
if (! $gm->delete())
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Unable to DELETE Group Method'),
|
||||
'type'=>'error',
|
||||
'body'=>sprintf(_('Unable to delete Group Method for method %s and group %s'),$mmo->name,$go->name),
|
||||
));
|
||||
|
||||
// If the group was not defined and now is
|
||||
} elseif (! $mmo->has('group',$go) AND isset($_POST['groups']) AND in_array($go->id,$_POST['groups'])) {
|
||||
$gm = ORM::factory('Group_Method')
|
||||
->values(array(
|
||||
'method_id'=>$mmo->id,
|
||||
'group_id'=>$go->id,
|
||||
));
|
||||
|
||||
if (! $gm->check() OR ! $gm->save())
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Unable to SAVE Group Method'),
|
||||
'type'=>'error',
|
||||
'body'=>sprintf(_('Unable to save Group Method for method %s and group %s'),$mmo->name,$go->name),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$output .= Form::open();
|
||||
|
||||
$output .= View::factory('module/admin/method_detail_head');
|
||||
foreach ($groups->find_all() as $go) {
|
||||
$output .= View::factory('module/admin/method_detail_body')
|
||||
->set('group',$go)
|
||||
->set('defined',$mmo->has('group',$go));
|
||||
}
|
||||
$output .= View::factory('module/admin/method_detail_foot');
|
||||
|
||||
$output .= '<div>'.Form::submit('submit',_('Update'),array('class'=>'form_button')).'</div>';
|
||||
$output .= Form::close();
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf(_('%s->%s Method'),strtoupper($mmo->module->name),strtoupper($mmo->name)),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
73
application/classes/Controller/Admin/Setup.php
Normal file
@ -0,0 +1,73 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Siet Configuration Setup
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Admin
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Setup extends Controller_TemplateDefault {
|
||||
protected $secure_actions = array(
|
||||
'edit'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* View/Update the site configuration
|
||||
*/
|
||||
public function action_edit() {
|
||||
$o = Company::instance()->so();
|
||||
$output = '';
|
||||
|
||||
if ($_POST) {
|
||||
// Entry updated
|
||||
if ($o->values($_POST)->check() AND $o->save())
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Site Configuration Recorded',
|
||||
'type'=>'info',
|
||||
'body'=>'Site Config successfully recorded.',
|
||||
));
|
||||
}
|
||||
|
||||
$output .= Form::open();
|
||||
|
||||
// site_details
|
||||
$output .= View::factory($this->viewpath())
|
||||
->set('o',$o);;
|
||||
|
||||
$output .= '<div>'.Form::submit('submit','submit',array('class'=>'form_button')).'</div>';
|
||||
$output .= Form::close();
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Update Site Configuration'),
|
||||
'body'=>$output,
|
||||
));
|
||||
|
||||
// module_config
|
||||
$output = '';
|
||||
$output .= View::factory($this->viewpath().'/module/head');
|
||||
|
||||
foreach ($o->module_config as $mid => $detail) {
|
||||
$mo = ORM::factory('Module',$mid);
|
||||
|
||||
$output .= View::factory($this->viewpath().'/module/body')
|
||||
->set('mo',$mo);
|
||||
|
||||
Script::add(array('type'=>'stdin','data'=>'
|
||||
$(document).ready(function() {
|
||||
$("div[id='.$mo->name.']").load("'.URL::link('admin',$mo->name.'/setup',TRUE).'");
|
||||
});'
|
||||
));
|
||||
}
|
||||
|
||||
$output .= View::factory($this->viewpath().'/module/foot');
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Update Module Specific Configuration'),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
130
application/classes/Controller/Admin/Welcome.php
Normal file
@ -0,0 +1,130 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Admin Main home page
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Admin
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Admin_Welcome extends Controller_Welcome {
|
||||
protected $auth_required = TRUE;
|
||||
public $secure_actions = array(
|
||||
'index'=>TRUE,
|
||||
);
|
||||
|
||||
public function action_index() {
|
||||
$t = time();
|
||||
|
||||
// Show outstanding invoices
|
||||
$o = ORM::factory('Invoice');
|
||||
|
||||
Block_Sub::add(array(
|
||||
'title'=>'Invoices Overdue - No Auto Billing',
|
||||
'body'=>Table::display(
|
||||
$o->list_overdue_billing($t),
|
||||
25,
|
||||
array(
|
||||
'due_date'=>array('label'=>'Due Date'),
|
||||
'account->accnum()'=>array('label'=>'Num'),
|
||||
'account->name()'=>array('label'=>'Account'),
|
||||
'account->display("status")'=>array('label'=>'Active'),
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','invoice/view/')),
|
||||
'total(TRUE)'=>array('label'=>'Total','class'=>'right'),
|
||||
'due(TRUE)'=>array('label'=>'Amount Due','class'=>'right'),
|
||||
),
|
||||
array('page'=>TRUE)),
|
||||
'position'=>1,
|
||||
'order'=>1,
|
||||
));
|
||||
|
||||
Block_Sub::add(array(
|
||||
'title'=>'Invoices Overdue - Auto Billing',
|
||||
'body'=>Table::display(
|
||||
$o->list_overdue_billing($t,TRUE),
|
||||
25,
|
||||
array(
|
||||
'due_date'=>array('label'=>'Due Date'),
|
||||
'account->accnum()'=>array('label'=>'Num'),
|
||||
'account->name()'=>array('label'=>'Account'),
|
||||
'account->display("status")'=>array('label'=>'Active'),
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','invoice/view/')),
|
||||
'total(TRUE)'=>array('label'=>'Total','class'=>'right'),
|
||||
'due(TRUE)'=>array('label'=>'Amount Due','class'=>'right'),
|
||||
),
|
||||
array('page'=>TRUE)),
|
||||
'position'=>2,
|
||||
'order'=>1,
|
||||
));
|
||||
|
||||
Block_Sub::add(array(
|
||||
'title'=>'Invoices Due',
|
||||
'body'=>Table::display(
|
||||
$o->list_due(),
|
||||
25,
|
||||
array(
|
||||
'due_date'=>array('label'=>'Due Date'),
|
||||
'account->accnum()'=>array('label'=>'Num'),
|
||||
'account->name()'=>array('label'),
|
||||
'account->display("status")'=>array('label'=>'Active'),
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('user','invoice/view/')),
|
||||
'total(TRUE)'=>array('label'=>'Total','class'=>'right'),
|
||||
'due(TRUE)'=>array('label'=>'Amount Due','class'=>'right'),
|
||||
),
|
||||
array('show_other'=>'due()')),
|
||||
'position'=>3,
|
||||
'order'=>1,
|
||||
));
|
||||
|
||||
// Show un-applied payments
|
||||
Block_Sub::add(array(
|
||||
'title'=>'Unapplied Payments',
|
||||
'body'=>Table::display(
|
||||
ORM::factory('Payment')->list_unapplied(),
|
||||
25,
|
||||
array(
|
||||
'date_payment'=>array('label'=>'Pay Date'),
|
||||
'account->accnum()'=>array('label'=>'Num'),
|
||||
'account->name()'=>array('label'=>'Account'),
|
||||
'account->display("status")'=>array('label'=>'Active'),
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('admin','payment/view/')),
|
||||
'total_amt'=>array('label'=>'Total','class'=>'right'),
|
||||
'balance(TRUE)'=>array('label'=>'Balance','class'=>'right'),
|
||||
),
|
||||
array('show_other'=>'balance()')),
|
||||
'position'=>1,
|
||||
'order'=>2,
|
||||
));
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s %s',$this->ao->accnum(),$this->ao->first_name,$this->ao->last_name),
|
||||
'subtitle'=>_('Administrator Overview'),
|
||||
'body'=>(string)Block_Sub::factory(),
|
||||
));
|
||||
|
||||
// We are a site administrator
|
||||
$output = '';
|
||||
if ($this->ao->rtm_id == NULL) {
|
||||
$rtmo = ORM::factory('RTM',array('account_id','=',$this->ao->id))->find();
|
||||
|
||||
// Quick validation, if we are an admin, we should have an entry in the RTM table.
|
||||
if (! $rtmo->loaded())
|
||||
throw new Kohana_Exception('User :aid not set up properly',array(':aid'=>$this->ao->id));
|
||||
|
||||
$output = View::factory('welcome/admin')
|
||||
->set('o',$rtmo);
|
||||
|
||||
} else {
|
||||
$rtmo = ORM::factory('RTM',$this->ao->rtm_id);
|
||||
}
|
||||
|
||||
if ($output)
|
||||
Block::add(array(
|
||||
'title'=>sprintf('Reseller %s',$this->ao->display('company')),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
36
application/classes/Controller/Debug.php
Normal file
@ -0,0 +1,36 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Debug extends Controller_TemplateDefault {
|
||||
public function before() {
|
||||
if (! in_array(Config::sitemode(),array(Kohana::DEVELOPMENT,Kohana::TESTING)))
|
||||
HTTP::redirect();
|
||||
|
||||
parent::before();
|
||||
}
|
||||
|
||||
public function action_site() {
|
||||
$output = '';
|
||||
|
||||
$output .= debug::vars(array(
|
||||
'm'=>__METHOD__,
|
||||
'site'=>Config::site(),
|
||||
'siteID'=>Company::instance()->site(),
|
||||
'siteMode'=>Config::sitemodeverbose(),
|
||||
'modules'=>Config::appmodules(),
|
||||
));
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Site debug'),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
92
application/classes/Controller/Login.php
Normal file
@ -0,0 +1,92 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides login capability
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
* @also [logout]
|
||||
*/
|
||||
class Controller_Login extends lnApp_Controller_Login {
|
||||
/**
|
||||
* Enable site registration
|
||||
*
|
||||
* @todo Needs to be written
|
||||
*/
|
||||
public function action_register() {
|
||||
// If user already signed-in
|
||||
if (Auth::instance()->logged_in())
|
||||
HTTP::redirect('welcome/index');
|
||||
|
||||
HTTP::redirect('login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable user password reset
|
||||
*/
|
||||
public function action_reset() {
|
||||
// Minutes to keep our token
|
||||
$token_expire = 15;
|
||||
|
||||
// If user already signed-in
|
||||
if (Auth::instance()->logged_in())
|
||||
HTTP::redirect('welcome/index');
|
||||
|
||||
// If the user posted their details to reset their password
|
||||
if ($_POST) {
|
||||
// If the username is correct, create a method token
|
||||
if (! empty($_POST['username']) AND ($ao=ORM::factory('Account',array('username'=>$_POST['username']))) AND $ao->loaded()) {
|
||||
$mmto = ORM::factory('Module_Method_Token')
|
||||
->method(array('account','user_resetpassword'))
|
||||
->account($ao)
|
||||
->uses(2)
|
||||
->expire(time()+$token_expire*60);
|
||||
|
||||
if ($mmto->generate()) {
|
||||
// Send our email with the token
|
||||
// @todo Need to provide an option if Email_Template is not installed/activited.
|
||||
// @todo Need to provide an option if account_reset_password template doesnt exist.
|
||||
$et = Email_Template::instance('account_reset_password');
|
||||
$et->to = array('account'=>array($mmto->account_id));
|
||||
$et->variables = array(
|
||||
'SITE'=>URL::base(TRUE,TRUE),
|
||||
'SITE_ADMIN'=>Company::instance()->admin(),
|
||||
'SITE_NAME'=>Company::instance()->name(),
|
||||
'TOKEN'=>$mmto->token,
|
||||
'TOKEN_EXPIRE_MIN'=>$token_expire,
|
||||
'USER_NAME'=>sprintf('%s %s',$mmto->account->first_name,$mmto->account->last_name),
|
||||
);
|
||||
$et->send();
|
||||
|
||||
// Log the password reset
|
||||
$ao->log('Password reset token sent');
|
||||
}
|
||||
|
||||
// Redirect to our password reset, the Auth will validate the token.
|
||||
} elseif (! empty($_REQUEST['token'])) {
|
||||
HTTP::redirect(URL::link('user','account/resetpassword?token='.$_REQUEST['token']));
|
||||
}
|
||||
|
||||
// Show our token screen even if the email was invalid.
|
||||
if (isset($_POST['username']))
|
||||
Block::add(array(
|
||||
'title'=>_('Reset your password'),
|
||||
'body'=>View::factory('login_reset_sent'),
|
||||
'style'=>array('css/login.css'=>'screen'),
|
||||
));
|
||||
else
|
||||
HTTP::redirect('login');
|
||||
|
||||
} else {
|
||||
Block::add(array(
|
||||
'title'=>_('Reset your password'),
|
||||
'body'=>View::factory('login_reset'),
|
||||
'style'=>array('css/login.css'=>'screen'),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
14
application/classes/Controller/Module.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides MODULE management
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Module extends Controller_TemplateDefault {
|
||||
}
|
||||
?>
|
81
application/classes/Controller/Reseller/Account.php
Normal file
@ -0,0 +1,81 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Reseller Account management
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Reseller
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Reseller_Account extends Controller_Account {
|
||||
protected $secure_actions = array(
|
||||
'ajaxlist'=>TRUE,
|
||||
'list'=>TRUE,
|
||||
'listlog'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Used by AJAX calls to find accounts
|
||||
* @note list_autocomplete() will limit to authorised accounts
|
||||
*/
|
||||
public function action_ajaxlist() {
|
||||
$result = array();
|
||||
|
||||
if (isset($_REQUEST['term']) AND trim($_REQUEST['term']))
|
||||
$result += ORM::factory('Account')->list_autocomplete($_REQUEST['term']);
|
||||
|
||||
$this->auto_render = FALSE;
|
||||
$this->response->headers('Content-Type','application/json');
|
||||
$this->response->body(json_encode(array_values($result)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of accounts
|
||||
*/
|
||||
public function action_list() {
|
||||
Block::add(array(
|
||||
'title'=>_('Customer List'),
|
||||
'body'=>Table::display(
|
||||
$this->filter(ORM::factory('Account')->list_active(),$this->ao->RTM->customers($this->ao->RTM),'sortkey(TRUE)','id'),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID','url'=>URL::link('reseller','invoice/list/')),
|
||||
'accnum()'=>array('label'=>'Num'),
|
||||
'name(TRUE)'=>array('label'=>'Account'),
|
||||
'email'=>array('label'=>'Email'),
|
||||
'invoices_due_total(NULL,TRUE)'=>array('label'=>'Invoices','class'=>'right'),
|
||||
'services_count(TRUE)'=>array('label'=>'Services','class'=>'right'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
'type'=>'select',
|
||||
'form'=>URL::link('reseller','invoice/list'),
|
||||
)),
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a list of account logins
|
||||
*/
|
||||
public function action_listlog() {
|
||||
Block::add(array(
|
||||
'title'=>_('Account Login Log'),
|
||||
'body'=>Table::display(
|
||||
$this->filter(ORM::factory('Account_Log')->find_all(),$this->ao->RTM->customers($this->ao->RTM),NULL,'account_id'),
|
||||
25,
|
||||
array(
|
||||
'id'=>array('label'=>'ID'),
|
||||
'date_orig'=>array('label'=>'Date'),
|
||||
'account->name()'=>array('label'=>'Account'),
|
||||
'ip'=>array('label'=>'IP Address'),
|
||||
'details'=>array('label'=>'Details'),
|
||||
),
|
||||
array(
|
||||
'page'=>TRUE,
|
||||
)),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
25
application/classes/Controller/Reseller/Welcome.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* lnApp Main home page
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Reseller
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Reseller_Welcome extends Controller_Welcome {
|
||||
protected $auth_required = TRUE;
|
||||
protected $secure_actions = array(
|
||||
'index'=>TRUE,
|
||||
);
|
||||
|
||||
public function action_index() {
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s',$this->ao->accnum(),$this->ao->name(TRUE)),
|
||||
'body'=>View::factory('welcome/reseller'),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
134
application/classes/Controller/TemplateDefault.php
Normal file
@ -0,0 +1,134 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides the default template controller for rendering pages.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_TemplateDefault extends lnApp_Controller_TemplateDefault {
|
||||
protected $auth_required = TRUE;
|
||||
|
||||
// Our acccount object
|
||||
protected $ao;
|
||||
|
||||
public function __construct(Request $request, Response $response) {
|
||||
if (Config::theme())
|
||||
$this->template = Config::theme().'/page';
|
||||
|
||||
return parent::__construct($request,$response);
|
||||
}
|
||||
|
||||
protected function _headimages() {
|
||||
// This is where we should be able to change our country
|
||||
// @todo To implement
|
||||
$co = Config::country();
|
||||
HeadImages::add(array(
|
||||
'img'=>sprintf('img/country/%s.png',strtolower($co->two_code)),
|
||||
'attrs'=>array('onclick'=>"target='_blank';",'title'=>$co->display('name'))
|
||||
));
|
||||
|
||||
return HeadImages::factory();
|
||||
}
|
||||
|
||||
protected function _left() {
|
||||
if ($this->template->left)
|
||||
return $this->template->left;
|
||||
|
||||
elseif (Auth::instance()->logged_in(NULL,get_class($this).'|'.__METHOD__))
|
||||
return Controller_Tree::js();
|
||||
}
|
||||
|
||||
protected function _right() {
|
||||
return ($this->template->right) ? $this->template->right : '';
|
||||
}
|
||||
|
||||
public function before() {
|
||||
// If our action doesnt exist, no point processing any further.
|
||||
if (! method_exists($this,'action_'.Request::current()->action()))
|
||||
return;
|
||||
|
||||
if ($this->auth_required) {
|
||||
if (! count($this->secure_actions) OR (! isset($this->secure_actions[Request::current()->action()])))
|
||||
throw new Kohana_Exception('Class has no security defined :class, or no security configured for :method',array(':class'=>get_class($this),':method'=>Request::current()->action()));
|
||||
|
||||
$this->ao = Auth::instance()->get_user();
|
||||
|
||||
if (! is_null($this->ao) AND (is_string($this->ao) OR ! $this->ao->loaded()))
|
||||
throw HTTP_Exception::factory(501,'Account doesnt exist :account ?',array(':account'=>(is_string($this->ao) OR is_null($this->ao)) ? $this->ao : Auth::instance()->get_user()->id));
|
||||
}
|
||||
|
||||
parent::before();
|
||||
}
|
||||
|
||||
public function after() {
|
||||
$dc = Kohana::$config->load('config','user_default_method');
|
||||
$m = sprintf('%s/%s',Request::current()->directory(),Request::current()->controller());
|
||||
|
||||
BreadCrumb::URL(Request::current()->directory(),sprintf('%s/%s',Request::current()->directory(),$dc),FALSE);
|
||||
BreadCrumb::URL($m,method_exists($this,'action_menu') ? $m.'/menu' : sprintf('%s/%s',Request::current()->directory(),$dc),FALSE);
|
||||
|
||||
parent::after();
|
||||
}
|
||||
|
||||
/**
|
||||
* This will filter a search query to only return those accounts for a reseller
|
||||
*/
|
||||
protected function filter($o,$af,$sort=NULL,$afid=NULL) {
|
||||
$result = array();
|
||||
|
||||
foreach ($o as $x) {
|
||||
if (! is_null($afid) AND isset($x->$afid)) {
|
||||
if ((is_array($af) AND in_array($x->$afid,$af)) OR ($x->$afid == $af))
|
||||
array_push($result,$x);
|
||||
|
||||
} elseif (method_exists($x,'list_reseller')) {
|
||||
if (in_array($af,$x->list_reseller()))
|
||||
array_push($result,$x);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if ($sort)
|
||||
Sort::MAsort($result,$sort);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function setup(array $config_items=array()) {
|
||||
$module = Request::current()->controller();
|
||||
|
||||
if ($_POST AND isset($_POST['module_config'][$module]))
|
||||
Config::instance()->module_config($module,$_POST['module_config'][$module])->save();
|
||||
|
||||
if ($config_items) {
|
||||
$output = '';
|
||||
$mc = Config::instance()->module_config($module);
|
||||
|
||||
$output .= Form::open();
|
||||
$output .= View::factory('setup/admin/module/head');
|
||||
|
||||
foreach ($config_items as $k=>$v)
|
||||
$output .= View::factory('setup/admin/module/body')
|
||||
->set('module',$module)
|
||||
->set('mc',$mc)
|
||||
->set('key',$k)
|
||||
->set('info',$v)
|
||||
->set('val',isset($mc[$k]) ? $mc[$k] : '');
|
||||
|
||||
$output .= View::factory('setup/admin/module/foot');
|
||||
|
||||
$output .= Form::submit('submit',_('Submit'),array('class'=>'form_button'));
|
||||
$output .= Form::close();
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s',strtoupper($module),_('Configuration')),
|
||||
'body'=>$output,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
23
application/classes/Controller/TemplateDefault/Admin.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* lnApp User Main home page controller
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Admin
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_TemplateDefault_Admin extends Controller_TemplateDefault_User {
|
||||
public function after() {
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Retire this class extension',
|
||||
'type'=>'info',
|
||||
'body'=>__METHOD__,
|
||||
));
|
||||
|
||||
return parent::after();
|
||||
}
|
||||
}
|
||||
?>
|
23
application/classes/Controller/TemplateDefault/Affiliate.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB User Main home page controller
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/Affiliate
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_TemplateDefault_Affiliate extends Controller_TemplateDefault_User {
|
||||
public function after() {
|
||||
SystemMessage::add(array(
|
||||
'title'=>'Retire this class extension',
|
||||
'type'=>'info',
|
||||
'body'=>__METHOD__,
|
||||
));
|
||||
|
||||
return parent::after();
|
||||
}
|
||||
}
|
||||
?>
|
14
application/classes/Controller/TemplateDefault/User.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* lnApp User Main home page controller
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/User
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_TemplateDefault_User extends Controller_TemplateDefault {
|
||||
}
|
||||
?>
|
131
application/classes/Controller/Tree.php
Normal file
@ -0,0 +1,131 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class extends renders OSB menu tree.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Tree extends lnApp_Controller_Tree {
|
||||
protected $auth_required = TRUE;
|
||||
|
||||
/**
|
||||
* Draw the Tree Menu
|
||||
*
|
||||
* The incoming ID is either a Branch B_x or a Node N_x
|
||||
* Where X is actually the module.
|
||||
*
|
||||
* @param array $data Tree data passed in by inherited methods
|
||||
*/
|
||||
public function action_json(array $data=array()) {
|
||||
// Get the user details
|
||||
$id = (is_null($this->request->param('id')) AND isset($_REQUEST['id'])) ? substr($_REQUEST['id'],2) : $this->request->param('id');
|
||||
$user = Auth::instance()->get_user();
|
||||
|
||||
if ($user) {
|
||||
if (! $id) {
|
||||
$modules = array();
|
||||
foreach ($user->groups() as $go)
|
||||
foreach ($go->list_parentgrps(TRUE) as $cgo)
|
||||
foreach ($cgo->module_method->find_all() as $mmo)
|
||||
if ($mmo->menu_display AND empty($modules[$mmo->module_id]))
|
||||
$modules[$mmo->module_id] = $mmo->module;
|
||||
|
||||
Sort::MAsort($modules,'name');
|
||||
|
||||
foreach ($modules as $id => $mo)
|
||||
if (! $mo->parent_id)
|
||||
array_push($data,array('id'=>$id,'name'=>$mo->name,'state'=>'closed'));
|
||||
|
||||
} else {
|
||||
$idx = NULL;
|
||||
if (preg_match('/_/',$id))
|
||||
list($id,$idx) = explode('_',$id,2);
|
||||
|
||||
$mo = ORM::factory('Module',$id);
|
||||
|
||||
$methods = array();
|
||||
if ($mo->loaded()) {
|
||||
foreach ($mo->module_method->find_all() as $mmo)
|
||||
if ($mmo->menu_display)
|
||||
foreach ($mmo->group->find_all() as $gmo)
|
||||
if ($user->has_any('group',$gmo->list_childgrps(TRUE)))
|
||||
$methods[$mmo->id] = $mmo;
|
||||
|
||||
Sort::MASort($modules,'name');
|
||||
|
||||
$subdata = array();
|
||||
foreach ($methods as $id => $mmo) {
|
||||
if (preg_match('/_/',$mmo->name)) {
|
||||
list($mode,$action) = explode('_',$mmo->name);
|
||||
|
||||
$url = URL::link($mode,$mmo->module->name.'/'.$action,TRUE);
|
||||
|
||||
} else {
|
||||
$url = URL::site($mmo->module->name.'/'.$mmo->name);
|
||||
}
|
||||
|
||||
// We can split our menus into sub menus using the _ char.
|
||||
if (preg_match('/_/',$mmo->name)) {
|
||||
list($sub,$name) = explode('_',$mmo->name,2);
|
||||
$subdata[$sub][$name]['name'] = preg_replace('/^(.*: )/','',$mmo->notes);
|
||||
$subdata[$sub][$name]['id'] = sprintf('%s_%s',$mmo->module_id,$id);
|
||||
$subdata[$sub][$name]['href'] = (empty($details['page']) ? $url : $details['page']);
|
||||
|
||||
} else {
|
||||
// We dont want to show these items again, if we can through on a submenu
|
||||
if (! $idx)
|
||||
array_push($data,array(
|
||||
'id'=>sprintf('%s_%s',$mmo->module_id,$id),
|
||||
'name'=>$mmo->name,
|
||||
'state'=>'none',
|
||||
'attr_id'=>sprintf('%s_%s',$mmo->module->name,$id),
|
||||
'attr_href'=>(empty($details['page']) ? $url : $details['page'])
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// If our sub menus only have 1 branch, then we'll display it as normal.
|
||||
if (count($subdata) == 1) {
|
||||
$sk = array_keys($subdata);
|
||||
$idx = array_shift($sk);
|
||||
}
|
||||
|
||||
if ($idx)
|
||||
foreach ($subdata[$idx] as $k=>$v) {
|
||||
array_push($data,array(
|
||||
'id'=>$v['id'],
|
||||
'name'=>$v['name'],
|
||||
'state'=>'none',
|
||||
'attr_id'=>$v['id'],
|
||||
'attr_href'=>$v['href']
|
||||
));
|
||||
}
|
||||
|
||||
else
|
||||
foreach ($subdata as $t=>$x)
|
||||
array_push($data,array('id'=>$mmo->module_id.'_'.$t,'name'=>$t,'state'=>'closed'));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$this->output = array();
|
||||
|
||||
foreach ($data as $branch) {
|
||||
array_push($this->output,array(
|
||||
'attr'=>array('id'=>sprintf('B_%s',$branch['id'])),
|
||||
'state'=>$branch['state'],
|
||||
'data'=>array('title'=>$branch['name']),
|
||||
'attr'=>array('id'=>sprintf('N_%s',$branch['id']),'href'=>empty($branch['attr_href']) ? URL::site(sprintf('%s/menu',$branch['name'])) : $branch['attr_href']),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return parent::action_json($data);
|
||||
}
|
||||
}
|
||||
?>
|
104
application/classes/Controller/User/Account.php
Normal file
@ -0,0 +1,104 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides User Account Update functions
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/User
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_User_Account extends Controller_Account {
|
||||
protected $secure_actions = array(
|
||||
'edit'=>TRUE,
|
||||
'resetpassword'=>TRUE,
|
||||
);
|
||||
|
||||
/**
|
||||
* Enable User to Edit their Account Details
|
||||
*/
|
||||
public function action_edit() {
|
||||
// Store our new values
|
||||
$this->ao->values($_POST);
|
||||
|
||||
// Run validation and save
|
||||
if ($this->ao->changed())
|
||||
if ($this->ao->check()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Record updated'),
|
||||
'type'=>'info',
|
||||
'body'=>_('Your account record has been updated.')
|
||||
));
|
||||
|
||||
$this->ao->save();
|
||||
|
||||
} else {
|
||||
$output = '';
|
||||
foreach ($this->ao->validation()->errors('forms/login') as $field => $error)
|
||||
$output .= sprintf('<li><b>%s</b> %s</li>',$field,$error);
|
||||
|
||||
if ($output)
|
||||
$output = sprintf('<ul>%s</ul>',$output);
|
||||
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Record NOT updated'),
|
||||
'type'=>'error',
|
||||
'body'=>_('Your updates didnt pass validation.').'<br/>'.$output,
|
||||
));
|
||||
}
|
||||
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s - %s',_('Account Edit'),$this->ao->accnum(),$this->ao->name(TRUE)),
|
||||
'body'=>View::factory($this->viewpath())
|
||||
->set('record',$this->ao),
|
||||
));
|
||||
}
|
||||
|
||||
public function action_resetpassword() {
|
||||
// @todo Fix this next logic, since matches_ifset is not being called when the value is on the form, but empty
|
||||
if (empty($_POST['password_confirm']))
|
||||
$_POST['password_confirm'] = ' ';
|
||||
|
||||
// Store our new values
|
||||
$this->ao->values($_POST);
|
||||
|
||||
// Run validation and save
|
||||
if ($this->ao->changed())
|
||||
if ($this->ao->check()) {
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Record updated'),
|
||||
'type'=>'info',
|
||||
'body'=>_('Your account record has been updated.')
|
||||
));
|
||||
|
||||
$this->ao->save();
|
||||
|
||||
// Log the password reset
|
||||
$this->ao->log('Password reset');
|
||||
|
||||
HTTP::redirect('login');
|
||||
|
||||
} else {
|
||||
$output = '';
|
||||
foreach ($this->ao->validation()->errors('forms/login') as $field => $error)
|
||||
$output .= sprintf('<li><b>%s</b> %s</li>',$field,$error);
|
||||
|
||||
if ($output)
|
||||
$output = sprintf('<ul>%s</ul>',$output);
|
||||
|
||||
SystemMessage::add(array(
|
||||
'title'=>_('Record NOT updated'),
|
||||
'type'=>'error',
|
||||
'body'=>_('Your updates didnt pass validation.').'<br/>'.$output,
|
||||
));
|
||||
}
|
||||
|
||||
Block::add(array(
|
||||
'title'=>_('Password Reset'),
|
||||
'body'=>View::factory($this->viewpath())
|
||||
->set('record',$this->ao),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
25
application/classes/Controller/User/Welcome.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* lnApp Main home page
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers/User
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_User_Welcome extends Controller_Welcome {
|
||||
protected $auth_required = TRUE;
|
||||
protected $secure_actions = array(
|
||||
'index'=>TRUE,
|
||||
);
|
||||
|
||||
public function action_index() {
|
||||
Block::add(array(
|
||||
'title'=>sprintf('%s: %s',$this->ao->accnum(),$this->ao->name(TRUE)),
|
||||
'body'=>View::factory('welcome/user'),
|
||||
));
|
||||
}
|
||||
}
|
||||
?>
|
29
application/classes/Controller/Welcome.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Main home page
|
||||
*
|
||||
* @package OSB
|
||||
* @category Controllers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Controller_Welcome extends Controller_TemplateDefault {
|
||||
protected $auth_required = FALSE;
|
||||
|
||||
public function action_index() {
|
||||
if (! Kohana::$config->load('config')->appname)
|
||||
HTTP::redirect('guide/app');
|
||||
|
||||
// @todo This should be in the DB or something.
|
||||
HTTP::redirect('product/categorys');
|
||||
}
|
||||
|
||||
public function action_breadcrumb() {
|
||||
$this->auto_render = FALSE;
|
||||
|
||||
$this->response->body(Session::instance()->get_once('breadcrumb'));
|
||||
}
|
||||
}
|
||||
?>
|
15
application/classes/Cookie.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's Cookie
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Cookie extends Kohana_Cookie {
|
||||
public static $salt = 'OSB';
|
||||
}
|
||||
?>
|
19
application/classes/Country.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides Country routines
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Country {
|
||||
public static function icon($cid) {
|
||||
$co = ORM::factory('Country',$cid);
|
||||
|
||||
return HTML::image(sprintf('media/img/country/%s.png',strtolower($co->two_code)),array('alt'=>$co->currency()->symbol));
|
||||
}
|
||||
}
|
||||
?>
|
21
application/classes/Currency.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class is for all page attributes.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Currency {
|
||||
public static function display($amount) {
|
||||
return Num::format($amount,Company::instance()->decimals(),TRUE);
|
||||
}
|
||||
|
||||
public static function round($amount) {
|
||||
return Num::round($amount,Company::instance()->decimals());
|
||||
}
|
||||
}
|
||||
?>
|
35
application/classes/DB.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's DB
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class DB extends Kohana_DB {
|
||||
// Add the site_id to the delete query
|
||||
public static function delete($table = NULL)
|
||||
{
|
||||
$db = new Database_Query_Builder_Delete($table);
|
||||
|
||||
if (! in_array($table,ORM::$no_site_id_tables))
|
||||
return $db->where($table.'.site_id','=',Company::instance()->site());
|
||||
else
|
||||
return $db;
|
||||
}
|
||||
|
||||
// Add the site_id to the update query
|
||||
final public static function update($table = NULL)
|
||||
{
|
||||
$db = new Database_Query_Builder_Update($table);
|
||||
|
||||
if (! in_array($table,ORM::$no_site_id_tables))
|
||||
return $db->where($table.'.site_id','=',Company::instance()->site());
|
||||
else
|
||||
return $db;
|
||||
}
|
||||
}
|
||||
?>
|
19
application/classes/Database/Mysql.php
Normal file
@ -0,0 +1,19 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* MySQL database connection.
|
||||
*
|
||||
* Modified for OSB, so that ORM can use enhanced SQL queries. This has been
|
||||
* achieved by simply removing the identifier backtick.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Database_MySQL extends Kohana_Database_MySQL {
|
||||
// MySQL uses a backtick for identifiers
|
||||
protected $_identifier = '';
|
||||
}
|
||||
?>
|
52
application/classes/Editor.php
Normal file
@ -0,0 +1,52 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class is for rendering the tinyMCE editor
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Editor {
|
||||
private static $added = FALSE;
|
||||
|
||||
public static function add() {
|
||||
if (static::$added)
|
||||
return;
|
||||
|
||||
static::$added = TRUE;
|
||||
|
||||
Script::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'js/jquery-1.4.2.js',
|
||||
));
|
||||
Script::add(array(
|
||||
'type'=>'file',
|
||||
'data'=>'js/tiny_mce/tiny_mce.js',
|
||||
));
|
||||
Script::add(array(
|
||||
'type'=>'stdin',
|
||||
'data'=>'
|
||||
tinyMCE.init({
|
||||
mode : "specific_textareas",
|
||||
editor_selector : "mceEditor",
|
||||
theme : "advanced",
|
||||
plugins : "table,save,advhr,advimage,advlink,emotions,iespell,insertdatetime,preview,media,searchreplace,print",
|
||||
theme_advanced_buttons1_add : "fontselect,fontsizeselect",
|
||||
theme_advanced_buttons2_add : "separator,insertdate,inserttime,preview,separator,forecolor,backcolor",
|
||||
theme_advanced_buttons2_add_before: "cut,copy,paste,separator,search,replace,separator",
|
||||
theme_advanced_buttons3_add_before : "tablecontrols,separator",
|
||||
theme_advanced_buttons3_add : "iespell,media,advhr",
|
||||
theme_advanced_toolbar_location : "bottom",
|
||||
theme_advanced_toolbar_align : "center",
|
||||
plugin_insertdate_dateFormat : "%Y-%m-%d",
|
||||
plugin_insertdate_timeFormat : "%H:%M:%S",
|
||||
extended_valid_elements : "a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]",
|
||||
relative_urls: "true",
|
||||
width : "100%"
|
||||
});'));
|
||||
}
|
||||
}
|
||||
?>
|
18
application/classes/Form.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's Form
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Form extends Kohana_Form {
|
||||
// Enable 3.0 features, default to current URI for empty Form::open()
|
||||
public static function open($action = NULL, array $attributes = NULL) {
|
||||
return parent::open(is_null($action) ? Request::detect_uri() : $action,$attributes);
|
||||
}
|
||||
}
|
||||
?>
|
25
application/classes/HTTP/Exception/404.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's 404 Exception
|
||||
*
|
||||
* @package OSB
|
||||
* @category Exceptions
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class HTTP_Exception_404 extends Kohana_HTTP_Exception_404 {
|
||||
public function get_response() {
|
||||
$response = Response::factory();
|
||||
$response->status($this->_code);
|
||||
|
||||
$view = View::factory('errors/404');
|
||||
$view->message = $this->getMessage();
|
||||
|
||||
$response->body($view->render());
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
?>
|
34
application/classes/HTTP/Exception/501.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class provides a custom 501 Exception to catch OSB specific errors.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Exceptions
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class HTTP_Exception_501 extends Kohana_HTTP_Exception {
|
||||
protected $_code = 501;
|
||||
|
||||
public function __construct($message='',array $variables=NULL,$code=0) {
|
||||
parent::__construct($message,$variables,$code);
|
||||
|
||||
$response = Response::factory();
|
||||
$response->status($this->_code);
|
||||
|
||||
// @todo This is not working as cleanly as I would like - ie: we shouldnt need to publish the headers ourselves?
|
||||
header(':', true, 501);
|
||||
|
||||
if (Kohana::$config->load('debug')->show_errors)
|
||||
$response->body(View::factory('errors/501')->set('message',$this->getMessage())->render());
|
||||
else
|
||||
$response->body('Dang, something went wrong, tell us how we got here...');
|
||||
|
||||
echo $response->render();
|
||||
|
||||
exit (501);
|
||||
}
|
||||
}
|
||||
?>
|
56
application/classes/Kohana.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's Core
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class Kohana extends Kohana_Core {
|
||||
/**
|
||||
* @compat Restore KH 3.1 functionality
|
||||
* @var boolean True if Kohana is running from the command line
|
||||
*/
|
||||
public static $is_cli = FALSE;
|
||||
|
||||
/**
|
||||
* @compat Restore KH 3.1 functionality
|
||||
*/
|
||||
public static function init(array $settings = NULL) {
|
||||
parent::init($settings);
|
||||
|
||||
// Determine if we are running in a command line environment
|
||||
Kohana::$is_cli = (PHP_SAPI === 'cli');
|
||||
}
|
||||
|
||||
/**
|
||||
* Override Kohana's shutdown_handler()
|
||||
*
|
||||
* When set up for multi-site, we need to disable Kohana's caching
|
||||
* unless each site has exactly the same modules enabled.
|
||||
* This is because Kohana::$file is cached with the enabled modules
|
||||
* and is not OSB multi-site aware.
|
||||
*/
|
||||
public static function shutdown_handler() {
|
||||
// If caching isnt enabled, we can skip this anyway
|
||||
if (! Kohana::$caching)
|
||||
return parent::shutdown_handler();
|
||||
|
||||
Kohana::$caching = FALSE;
|
||||
$result = parent::shutdown_handler();
|
||||
Kohana::$caching = TRUE;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Work out our Class Name as per Kohana's standards
|
||||
*/
|
||||
public static function classname($name) {
|
||||
return str_replace(' ','_',ucwords(strtolower(str_replace('_',' ',$name))));
|
||||
}
|
||||
}
|
||||
?>
|
64
application/classes/Kohana/Exception.php
Normal file
@ -0,0 +1,64 @@
|
||||
<?php defined('SYSPATH') OR die('No direct access');
|
||||
/**
|
||||
* Kohana exception class. Translates exceptions using the [I18n] class.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Kohana_Exception extends Kohana_Kohana_Exception {
|
||||
/**
|
||||
* Logs an exception in the database. If that fails fall back to Kohana's Logging.
|
||||
*
|
||||
* @uses Kohana_Exception::text
|
||||
* @param Exception $e
|
||||
* @param int $level
|
||||
* @return void
|
||||
*/
|
||||
public static function log(Exception $e,$level=Log::EMERGENCY) {
|
||||
try {
|
||||
$eo = ORM::factory('Log_Error');
|
||||
$eo->message = Kohana_Exception::text($e);
|
||||
$eo->account_id = Auth::instance()->get_user()->id;
|
||||
$eo->module = (Request::current()->directory() ? Request::current()->directory().'_' : '').Request::current()->controller();
|
||||
$eo->method = Request::current()->action();
|
||||
$eo->save();
|
||||
|
||||
} catch (Exception $x) {
|
||||
return parent::log($e,$level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Redirect errors to the main page after showing a system message.
|
||||
* The error should be logged in the DB.
|
||||
*
|
||||
* @param Exception $e
|
||||
* @return Response
|
||||
*/
|
||||
public static function response(Exception $e) {
|
||||
try {
|
||||
if (Kohana::$config->load('debug')->show_errors) {
|
||||
return parent::response($e);
|
||||
} else {
|
||||
SystemMessage::add(array(
|
||||
'title'=>'An Error Occured.',
|
||||
'type'=>'error',
|
||||
'body'=>'Dont panic, its been logged.',
|
||||
));
|
||||
|
||||
// We'll redirect to the main page.
|
||||
$response = Response::factory();
|
||||
$response->status(302);
|
||||
$response->headers('Location',URL::site());
|
||||
return $response;
|
||||
}
|
||||
|
||||
} catch (Exception $x) {
|
||||
return parent::response($e);
|
||||
}
|
||||
}
|
||||
}
|
||||
?>
|
17
application/classes/Minion/Task.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's Minion CLI Module
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class Minion_Task extends Kohana_Minion_Task {
|
||||
protected $_options = array(
|
||||
'site'=>NULL,
|
||||
);
|
||||
}
|
||||
?>
|
194
application/classes/Model/Account.php
Normal file
@ -0,0 +1,194 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This Model manages both the accounts that users use to login to the system, as well as the account where services are owned.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Account extends Model_Auth_UserDefault {
|
||||
// Relationships
|
||||
protected $_has_many = array(
|
||||
'user_tokens' => array('model' => 'user_token'),
|
||||
'email_log' => array('far_key'=>'id'),
|
||||
'group' => array('through' => 'account_group'),
|
||||
'invoice' => array('far_key'=>'id'),
|
||||
'payment'=>array('far_key'=>'id'),
|
||||
'service' => array('far_key'=>'id'),
|
||||
);
|
||||
|
||||
protected $_has_one = array(
|
||||
'country'=>array('foreign_key'=>'id'),
|
||||
'currency'=>array('foreign_key'=>'id'),
|
||||
'language'=>array('foreign_key'=>'id'),
|
||||
'RTM'=>array('far_key'=>'id'),
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'date_orig'=>array(
|
||||
array('Config::date',array(':value')),
|
||||
),
|
||||
'date_last'=>array(
|
||||
array('Config::date',array(':value')),
|
||||
),
|
||||
'status'=>array(
|
||||
array('StaticList_YesNo::display',array(':value')),
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Our account number format
|
||||
*/
|
||||
public function accnum() {
|
||||
return sprintf('%s-%04s',Company::instance()->site(TRUE),$this->id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the groups that an account belongs to
|
||||
*/
|
||||
public function groups() {
|
||||
return $this->group->where_active()->find_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of all invoices for this account
|
||||
*/
|
||||
public function invoices($processed=FALSE) {
|
||||
$o = $this->invoice;
|
||||
|
||||
return $processed ? $o->find_all() : $o->where_unprocessed()->find_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of due invoices for this account
|
||||
*
|
||||
* @param int Date (in secs) to only retrieve invoices prior to this date
|
||||
*/
|
||||
public function invoices_due($date=NULL) {
|
||||
$result = array();
|
||||
|
||||
foreach ($this->invoices() as $io)
|
||||
if ((is_null($date) OR $io->date_orig < $date) AND $io->due())
|
||||
$result[$io->id] = $io;
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate the total of invoices due for this account
|
||||
*/
|
||||
public function invoices_due_total($date=NULL,$format=FALSE) {
|
||||
$result = 0;
|
||||
|
||||
foreach ($this->invoices_due($date) as $io)
|
||||
$result += $io->due();
|
||||
|
||||
return $format ? Currency::display($result) : $result;
|
||||
}
|
||||
|
||||
public function log($message) {
|
||||
// Log the logout
|
||||
$alo = ORM::factory('Account_Log');
|
||||
$alo->account_id = $this->id;
|
||||
$alo->ip = Request::$client_ip;
|
||||
$alo->details = $message;
|
||||
$alo->save();
|
||||
|
||||
return $alo->saved();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an account name
|
||||
*/
|
||||
public function name($withcompany=FALSE) {
|
||||
if ($withcompany)
|
||||
return sprintf('%s %s%s',$this->first_name,$this->last_name,$this->company ? sprintf(' (%s)',$this->company) : '');
|
||||
else
|
||||
return sprintf('%s %s',$this->first_name,$this->last_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* List all the services for this account
|
||||
*/
|
||||
public function services($active=TRUE) {
|
||||
$o = $this->service;
|
||||
|
||||
return $active ? $o->where_active()->find_all() : $o->find_all();
|
||||
}
|
||||
|
||||
public function services_count($active=TRUE,$afid=NULL) {
|
||||
return $this->services($active)->count();
|
||||
}
|
||||
|
||||
/**
|
||||
* The key we use to sort entries of this model type
|
||||
*/
|
||||
public function sortkey($withcompany=FALSE) {
|
||||
$sk = '';
|
||||
|
||||
if ($withcompany AND $this->company)
|
||||
$sk .= $this->company.' ';
|
||||
|
||||
return $sk.sprintf('%s %s',$this->last_name,$this->first_name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for accounts matching a term
|
||||
*/
|
||||
public function list_autocomplete($term,$index='id',array $limit=array()) {
|
||||
$result = array();
|
||||
$ao = Auth::instance()->get_user();
|
||||
|
||||
$this->clear();
|
||||
$this->where_active();
|
||||
$value = 'name(TRUE)';
|
||||
|
||||
// Build our where clause
|
||||
// First Name, Last name
|
||||
if (preg_match('/\ /',$term)) {
|
||||
list($fn,$ln) = explode(' ',$term,2);
|
||||
|
||||
$this->where_open()
|
||||
->where('first_name','like','%'.$fn.'%')
|
||||
->and_where('last_name','like','%'.$ln.'%')
|
||||
->where_close()
|
||||
->or_where('company','like','%'.$term.'%');
|
||||
|
||||
} elseif (is_numeric($term)) {
|
||||
$this->where('id','like','%'.$term.'%');
|
||||
|
||||
} elseif (preg_match('/\@/',$term)) {
|
||||
$this->where('email','like','%'.$term.'%');
|
||||
$value = 'email';
|
||||
|
||||
} else {
|
||||
$this->where_open()
|
||||
->where('company','like','%'.$term.'%')
|
||||
->or_where('first_name','like','%'.$term.'%')
|
||||
->or_where('last_name','like','%'.$term.'%')
|
||||
->or_where('email','like','%'.$term.'%')
|
||||
->where_close();
|
||||
}
|
||||
|
||||
foreach ($limit as $w) {
|
||||
list($k,$s,$v) = $w;
|
||||
|
||||
$this->and_where($k,$s,$v);
|
||||
}
|
||||
|
||||
// Restrict results to authorised accounts
|
||||
$this->and_where('id','IN',$ao->RTM->customers($ao->RTM));
|
||||
|
||||
foreach ($this->find_all() as $o)
|
||||
$result[$o->$index] = array(
|
||||
'value'=>$o->$index,
|
||||
'label'=>sprintf('ACC %s: %s',$o->id,Table::resolve($o,$value)),
|
||||
);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
?>
|
27
application/classes/Model/Account/Log.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class supports Account Login Logging
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Account_Log extends ORM_OSB {
|
||||
protected $_belongs_to = array(
|
||||
'account'=>array(),
|
||||
);
|
||||
|
||||
protected $_sorting = array(
|
||||
'id'=>'DESC',
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'date_orig'=>array(
|
||||
array('Config::datetime',array(':value')),
|
||||
),
|
||||
);
|
||||
}
|
||||
?>
|
14
application/classes/Model/Affiliate.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Affiliate
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Affiliate extends ORM_OSB {
|
||||
}
|
||||
?>
|
13
application/classes/Model/Auth/RoleDefault.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Auth_RoleDefault extends Model_Auth_Role {
|
||||
}
|
||||
?>
|
76
application/classes/Model/Auth/UserDefault.php
Normal file
@ -0,0 +1,76 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Auth_UserDefault extends Model_Auth_User {
|
||||
// Validation rules
|
||||
public function rules() {
|
||||
return array(
|
||||
'username' => array(
|
||||
array('not_empty'),
|
||||
array('min_length', array(':value', 4)),
|
||||
array('max_length', array(':value', 32)),
|
||||
),
|
||||
'password' => array(
|
||||
array('not_empty'),
|
||||
array('min_length', array(':value', 5)),
|
||||
array('max_length', array(':value', 32)),
|
||||
),
|
||||
'email' => array(
|
||||
array('not_empty'),
|
||||
array('min_length', array(':value', 4)),
|
||||
array('max_length', array(':value', 127)),
|
||||
array('email'),
|
||||
),
|
||||
// @todo To test
|
||||
'password_confirm' => array(
|
||||
array('matches_ifset', array(':validation', 'password', 'password_confirm')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Validation callbacks
|
||||
// @todo _callbacks no longer used
|
||||
protected $_callbacks = array(
|
||||
'username' => array('username_available'),
|
||||
'email' => array('email_available'),
|
||||
);
|
||||
|
||||
// Columns to ignore
|
||||
protected $_ignored_columns = array('password_confirm');
|
||||
|
||||
/*
|
||||
* Complete our login
|
||||
*
|
||||
* For some database logins, we may not want to record the user last login
|
||||
* details in the repository, so we just override that parent function
|
||||
* here.
|
||||
*
|
||||
* We can also do some other post-login actions here.
|
||||
* @todo Maybe we can do our session update here.
|
||||
*/
|
||||
public function complete_login() {
|
||||
return $this->log('Logged In');
|
||||
}
|
||||
|
||||
/**
|
||||
* Debug function to see that has() finds
|
||||
* @todo This function could be removed
|
||||
*/
|
||||
public function has_list($alias, $model) {
|
||||
// Return list of matches
|
||||
return DB::select()
|
||||
->from($this->_has_many[$alias]['through'])
|
||||
->where($this->_has_many[$alias]['foreign_key'], '=', $this->pk())
|
||||
->where($this->_has_many[$alias]['far_key'], '=', $model->pk())
|
||||
->execute($this->_db)
|
||||
->as_array();
|
||||
}
|
||||
}
|
||||
?>
|
17
application/classes/Model/Country.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Country Model
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Country extends ORM_OSB {
|
||||
public function currency() {
|
||||
return ORM::factory('Currency')->where('country_id','=',$this->id)->find();
|
||||
}
|
||||
}
|
||||
?>
|
14
application/classes/Model/Currency.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Currency Model
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Currency extends ORM_OSB {
|
||||
}
|
||||
?>
|
84
application/classes/Model/Group.php
Normal file
@ -0,0 +1,84 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Group extends Model_Auth_RoleDefault {
|
||||
// Relationships
|
||||
protected $_has_many = array(
|
||||
'account'=>array('through'=>'account_group'),
|
||||
'module_method'=>array('through'=>'group_method','far_key'=>'method_id'),
|
||||
);
|
||||
|
||||
protected $_sorting = array(
|
||||
'name'=>'ASC',
|
||||
);
|
||||
|
||||
// Validation rules
|
||||
protected $_rules = array(
|
||||
'name' => array(
|
||||
'not_empty' => NULL,
|
||||
'min_length' => array(4),
|
||||
'max_length' => array(32),
|
||||
),
|
||||
'description' => array(
|
||||
'max_length' => array(255),
|
||||
),
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'status'=>array(
|
||||
array('StaticList_YesNo::display',array(':value')),
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* This function will, given a group, list all of the children that
|
||||
* are also related to this group, in the group heirarchy.
|
||||
*/
|
||||
public function list_childgrps($incParent=FALSE) {
|
||||
$result = array();
|
||||
|
||||
if (! $this->loaded())
|
||||
return $result;
|
||||
|
||||
foreach (ORM::factory('Group')->where_active()->and_where('parent_id','=',$this)->find_all() as $go) {
|
||||
array_push($result,$go);
|
||||
|
||||
$result = array_merge($result,$go->list_childgrps());
|
||||
}
|
||||
|
||||
if ($incParent)
|
||||
array_push($result,$this);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will, given a group, list all of the parent that
|
||||
* are also related to this group, in the group heirarchy.
|
||||
*/
|
||||
public function list_parentgrps($incParent=FALSE) {
|
||||
$result = array();
|
||||
|
||||
if (! $this->loaded())
|
||||
return $result;
|
||||
|
||||
foreach (ORM::factory('Group')->where_active()->and_where('id','=',$this->parent_id)->find_all() as $go) {
|
||||
array_push($result,$go);
|
||||
|
||||
$result = array_merge($result,$go->list_parentgrps());
|
||||
}
|
||||
|
||||
if ($incParent)
|
||||
array_push($result,$this);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
?>
|
25
application/classes/Model/Group/Method.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Application Module Method Model
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Group_Method extends ORM_OSB {
|
||||
// Relationships
|
||||
protected $_has_one = array(
|
||||
'record_id'=>array(),
|
||||
);
|
||||
protected $_belongs_to = array(
|
||||
'group'=>array(),
|
||||
);
|
||||
|
||||
// This module doesnt keep track of column updates automatically
|
||||
protected $_created_column = FALSE;
|
||||
protected $_updated_column = FALSE;
|
||||
}
|
||||
?>
|
15
application/classes/Model/Language.php
Normal file
@ -0,0 +1,15 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Language Model
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Language extends ORM_OSB {
|
||||
protected $_form = array('id'=>'id','value'=>'name');
|
||||
}
|
||||
?>
|
14
application/classes/Model/Log/Error.php
Normal file
@ -0,0 +1,14 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* Log errors in the database.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Log_Error extends ORM_OSB {
|
||||
}
|
||||
?>
|
51
application/classes/Model/Module.php
Normal file
@ -0,0 +1,51 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Application Module Model
|
||||
*
|
||||
* This module must remain in applications/ as it is used very early in the
|
||||
* OSB initialisation.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Module extends ORM_OSB {
|
||||
// Relationships
|
||||
protected $_has_many = array(
|
||||
'module_method'=>array('far_key'=>'id'),
|
||||
);
|
||||
protected $_has_one = array(
|
||||
'record_id'=>array('model'=>'Record_ID','far_key'=>'id'),
|
||||
);
|
||||
|
||||
protected $_sorting = array(
|
||||
'status'=>'DESC',
|
||||
'name'=>'ASC',
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'name'=>array(
|
||||
array('strtoupper',array(':value')),
|
||||
),
|
||||
'status'=>array(
|
||||
array('StaticList_YesNo::display',array(':value')),
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Return an instance of this Module's Model
|
||||
*
|
||||
* @param $id PK of Model
|
||||
*/
|
||||
public function instance($id=NULL) {
|
||||
return ORM::factory(ucwords($this->name),$id);
|
||||
}
|
||||
|
||||
public function list_external() {
|
||||
return $this->_where_active()->where('external','=',TRUE)->find_all();
|
||||
}
|
||||
}
|
||||
?>
|
43
application/classes/Model/Module/Method.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Application Module Method Model
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Module_Method extends ORM_OSB {
|
||||
// Relationships
|
||||
protected $_belongs_to = array(
|
||||
'module'=>array(),
|
||||
);
|
||||
protected $_has_one = array(
|
||||
'record_id'=>array(),
|
||||
);
|
||||
protected $_has_many = array(
|
||||
'group'=>array('through'=>'group_method','foreign_key'=>'method_id')
|
||||
);
|
||||
|
||||
protected $_sorting = array(
|
||||
'name'=>'ASC',
|
||||
);
|
||||
|
||||
protected $_display_filters = array(
|
||||
'menu_display'=>array(
|
||||
array('StaticList_YesNo::display',array(':value')),
|
||||
),
|
||||
);
|
||||
|
||||
// This module doesnt keep track of column updates automatically
|
||||
protected $_created_column = FALSE;
|
||||
protected $_updated_column = FALSE;
|
||||
|
||||
// Return the method name.
|
||||
public function name() {
|
||||
return sprintf('%s::%s',$this->module->name,$this->name);
|
||||
}
|
||||
}
|
||||
?>
|
112
application/classes/Model/Module/Method/Token.php
Normal file
@ -0,0 +1,112 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Application Module Method Token Model
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Module_Method_Token extends ORM_OSB {
|
||||
// Relationships
|
||||
protected $_belongs_to = array(
|
||||
'account'=>array(),
|
||||
'module_method'=>array('foreign_key'=>'method_id'),
|
||||
);
|
||||
protected $_has_one = array(
|
||||
'record_id'=>array(),
|
||||
);
|
||||
|
||||
// This module doesnt keep track of column updates automatically
|
||||
protected $_update_column = FALSE;
|
||||
|
||||
public function method(array $modmeth) {
|
||||
list($module,$method) = $modmeth;
|
||||
|
||||
if (! $method instanceof Model_Module_Method) {
|
||||
if (is_numeric($module))
|
||||
$mo = ORM::factory('Module',$module);
|
||||
elseif (is_string($module))
|
||||
$mo = ORM::factory('Module',array('name'=>$module));
|
||||
elseif (! $module instanceof Model_Module)
|
||||
throw new Kohana_Exception('Unknown module :module',array(':module'=>serialize($module)));
|
||||
else
|
||||
$mo = $module;
|
||||
|
||||
if (! $mo->loaded())
|
||||
throw new Kohana_Exception('Unknown module :module - not loaded?',array(':module'=>$mo->id));
|
||||
|
||||
if (is_numeric($method))
|
||||
$mmo = ORM::factory('Module_Method',$method);
|
||||
elseif (is_string($method))
|
||||
$mmo = ORM::factory('Module_Method',array('name'=>$method,'module_id'=>$mo->id));
|
||||
else
|
||||
throw new Kohana_Exception('Unknown method :method',array(':method'=>serialize($method)));
|
||||
} else
|
||||
$mmo = $method;
|
||||
|
||||
if (! $mmo->loaded())
|
||||
throw new Kohana_Exception('Unknown method :method - not loaded?',array(':method'=>$mmo->id));
|
||||
|
||||
$this->method_id = $mmo->id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function account($account) {
|
||||
if (! $account instanceof Model_Account) {
|
||||
if (is_numeric($account))
|
||||
$ao = ORM::factory('Account',$account);
|
||||
else
|
||||
throw new Kohana_Exception('Unknown account :account',array(':account'=>serialize($account)));
|
||||
} else
|
||||
$ao = $account;
|
||||
|
||||
$this->account_id = $ao->id;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function uses($uses) {
|
||||
$this->uses = $uses;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function expire($expire) {
|
||||
$this->date_expire = $expire;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
// @todo Login Reset: When called within a timelimit (so existing token already exists), is returning true but password reset emails have blanks where the tokens are
|
||||
public function generate() {
|
||||
if (! $this->account_id OR ! $this->method_id OR ! ($this->date_expire OR $this->uses))
|
||||
return NULL;
|
||||
|
||||
// Check we dont already have a valid token
|
||||
$mmto = ORM::factory('Module_Method_Token')
|
||||
->where('account_id','=',$this->account_id)
|
||||
->where('method_id','=',$this->method_id)
|
||||
->find();
|
||||
|
||||
if ($mmto->loaded()) {
|
||||
// Check that the token is still good
|
||||
if ((is_null($mmto->date_expire) OR $mmto->date_expire > time()) AND (is_null($mmto->uses) OR $mmto->uses > 0)) {
|
||||
$this->token = $mmto->token;
|
||||
return $this->token;
|
||||
|
||||
// Token expired
|
||||
} else
|
||||
$mmto->delete();
|
||||
}
|
||||
|
||||
$this->token = md5(sprintf('%s:%s:%s',$this->account_id,$this->method_id,time()));
|
||||
$this->save();
|
||||
|
||||
return $this->saved() ? $this->token : NULL;
|
||||
}
|
||||
}
|
||||
?>
|
42
application/classes/Model/RTM.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Route to Market
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_RTM extends ORM_OSB {
|
||||
protected $_belongs_to = array(
|
||||
'account' => array(),
|
||||
);
|
||||
|
||||
protected $_has_many = array(
|
||||
'customer' => array('model'=>'account','far_key'=>'id','foreign_key'=>'rtm_id'),
|
||||
'agent' => array('model'=>'rtm','far_key'=>'id','foreign_key'=>'parent_id'),
|
||||
);
|
||||
|
||||
public function customers(Model_RTM $rtmo) {
|
||||
$result = array();
|
||||
|
||||
foreach ($rtmo->agents_direct() as $artmo)
|
||||
$result = $result+$rtmo->customers($artmo);
|
||||
|
||||
foreach ($rtmo->customers_direct() as $ao)
|
||||
array_push($result,$ao);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function agents_direct() {
|
||||
return $this->agent->find_all();
|
||||
}
|
||||
|
||||
public function customers_direct() {
|
||||
return $this->customer->find_all();
|
||||
}
|
||||
}
|
||||
?>
|
42
application/classes/Model/Record/ID.php
Normal file
@ -0,0 +1,42 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
* @todo Rename to Record/ID.php
|
||||
*/
|
||||
class Model_Record_ID extends ORM_OSB {
|
||||
protected $_primary_key = 'module_id';
|
||||
|
||||
// This module doesnt keep track of column updates automatically
|
||||
protected $_created_column = FALSE;
|
||||
protected $_updated_column = FALSE;
|
||||
|
||||
// @todo we need $mid here, since if there is no record, we cant figure out the module that called us.
|
||||
public function next_id($mid) {
|
||||
if (is_null($this->id)) {
|
||||
$this->module_id = $mid;
|
||||
|
||||
// We'll get the next ID as the MAX(id) of the table
|
||||
$mo = ORM::factory('Module',$mid);
|
||||
|
||||
$max = DB::select(array('MAX(id)','id'))
|
||||
->from($mo->name)
|
||||
->where('site_id','=',Company::instance()->site());
|
||||
|
||||
$this->id = $max->execute()->get('id');
|
||||
}
|
||||
|
||||
$this->id++;
|
||||
|
||||
if (! $this->save())
|
||||
throw new Koahan_Exception(_('Unable to increase ID for :table'),array(':table'=>$mid));
|
||||
|
||||
return $this->id;
|
||||
}
|
||||
}
|
||||
?>
|
83
application/classes/Model/Setup.php
Normal file
@ -0,0 +1,83 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Setup Model
|
||||
*
|
||||
* This module must remain in applications/ as it is used very early in the
|
||||
* OSB initialisation.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Models
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Model_Setup extends ORM_OSB {
|
||||
// Setup doesnt use the update column
|
||||
protected $_updated_column = FALSE;
|
||||
|
||||
protected $_has_one = array(
|
||||
'account'=>array('foreign_key'=>'id','far_key'=>'admin_id'),
|
||||
'country'=>array('foreign_key'=>'id','far_key'=>'country_id'),
|
||||
'language'=>array('foreign_key'=>'id','far_key'=>'language_id'),
|
||||
);
|
||||
|
||||
public function rules() {
|
||||
$r = parent::rules();
|
||||
|
||||
// This module doesnt use site_id.
|
||||
unset($r['site_id']);
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get/Set Module Configuration
|
||||
*
|
||||
* @param $key Module name.
|
||||
* @param $value Values to store. If NULL, retrieves the value stored, otherwise stores value.
|
||||
*/
|
||||
public function module_config($key,array $value=NULL) {
|
||||
// If we are not loaded, we dont have any config.
|
||||
if (! $this->loaded() OR (is_null($value) AND ! $this->module_config))
|
||||
return array();
|
||||
|
||||
$mo = ORM::factory('Module')->where('name','=',$key)->find();
|
||||
|
||||
if (! $mo->loaded())
|
||||
throw new Kohana_Exception('Unknown module :name',array(':name'=>$key));
|
||||
|
||||
$mc = $this->module_config ? $this->module_config : array();
|
||||
|
||||
// If $value is NULL, we are a getter
|
||||
if ($value === NULL)
|
||||
return empty($mc[$mo->id]) ? array() : $mc[$mo->id];
|
||||
|
||||
// Store new value
|
||||
$mc[$mo->id] = $value;
|
||||
$this->module_config = $mc;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get/Set our Site Configuration from the DB
|
||||
*
|
||||
* @param $key Key
|
||||
* @param $value Values to store. If NULL, retrieves the value stored, otherwise stores value.
|
||||
*/
|
||||
public function site_details($key,array $value=NULL) {
|
||||
if (! in_array($key,array('name','address1','address2','city','state','pcode','phone','fax','email')))
|
||||
throw new Kohana_Exception('Unknown Site Configuration Key :key',array(':key'=>$key));
|
||||
|
||||
// If $value is NULL, we are a getter
|
||||
if ($value === NULL)
|
||||
return empty($this->site_details[$key]) ? '' : $this->site_details[$key];
|
||||
|
||||
// Store new value
|
||||
$sc[$key] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
||||
?>
|
125
application/classes/ORM.php
Normal file
@ -0,0 +1,125 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's ORM
|
||||
*
|
||||
* This file contains enhancements for Kohana, that should be considered upstream and maybe havent been yet.
|
||||
* It also contains some functionality for OSB, which cannot be covered in ORM_OSB.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class ORM extends Kohana_ORM {
|
||||
protected $_table_names_plural = FALSE;
|
||||
protected $_model_names_plural = FALSE;
|
||||
private $_object_formated = array();
|
||||
private $_formated = FALSE;
|
||||
// Our filters used to display values in a friendly format
|
||||
protected $_display_filters = array();
|
||||
|
||||
/**
|
||||
* Format fields for display purposes
|
||||
*
|
||||
* @param string column name
|
||||
* @return mixed
|
||||
*/
|
||||
private function _format() {
|
||||
foreach ($this->_display_filters as $column => $formats)
|
||||
$this->_object_formated[$column] = $this->run_filter($column,$this->__get($column),array($column=>$formats));
|
||||
|
||||
$this->_formated = TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a formated columns, as per the model definition
|
||||
*/
|
||||
public function display($column) {
|
||||
// Trigger a load of the record.
|
||||
$value = $this->__get($column);
|
||||
|
||||
// If some of our fields need to be formated for display purposes.
|
||||
if (! $this->_formated AND $this->_display_filters)
|
||||
$this->_format();
|
||||
|
||||
if (isset($this->_object_formated[$column]))
|
||||
return $this->_object_formated[$column];
|
||||
else
|
||||
return HTML::nbsp($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override KH's ORM count_relations() function, to include our site_id in the query.
|
||||
*
|
||||
* This is a copy of KH's ORM count_relations() function, with the addition of a where
|
||||
* clause to include the site id.
|
||||
*/
|
||||
public function count_relations($alias, $far_keys = NULL)
|
||||
{
|
||||
if ($far_keys === NULL)
|
||||
{
|
||||
return (int) DB::select(array(DB::expr('COUNT(*)'), 'records_found'))
|
||||
->from($this->_has_many[$alias]['through'])
|
||||
->where($this->_has_many[$alias]['foreign_key'], '=', $this->pk())
|
||||
->where('site_id', '=', Company::instance()->site())
|
||||
->execute($this->_db)->get('records_found');
|
||||
}
|
||||
|
||||
$far_keys = ($far_keys instanceof ORM) ? $far_keys->pk() : $far_keys;
|
||||
|
||||
// We need an array to simplify the logic
|
||||
$far_keys = (array) $far_keys;
|
||||
|
||||
// Nothing to check if the model isn't loaded or we don't have any far_keys
|
||||
if ( ! $far_keys OR ! $this->_loaded)
|
||||
return 0;
|
||||
|
||||
$count = (int) DB::select(array(DB::expr('COUNT(*)'), 'records_found'))
|
||||
->from($this->_has_many[$alias]['through'])
|
||||
->where($this->_has_many[$alias]['foreign_key'], '=', $this->pk())
|
||||
->where($this->_has_many[$alias]['far_key'], 'IN', $far_keys)
|
||||
->where('site_id', '=', Company::instance()->site())
|
||||
->execute($this->_db)->get('records_found');
|
||||
|
||||
// Rows found need to match the rows searched
|
||||
return (int) $count;
|
||||
}
|
||||
|
||||
/** OSB SPECIFIC ENHANCEMENTS **/
|
||||
|
||||
// Tables that do not have a site_id column
|
||||
public static $no_site_id_tables = array('setup','country','currency','language','tax');
|
||||
|
||||
/**
|
||||
* Add our OSB site_id to each SELECT query
|
||||
* @see parent::__build()
|
||||
*/
|
||||
final protected function _build($type) {
|
||||
// Exclude tables without site ID's
|
||||
if (! in_array($this->_table_name,ORM::$no_site_id_tables))
|
||||
$this->where($this->_object_name.'.site_id','=',Company::instance()->site());
|
||||
|
||||
return parent::_build($type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Function help to find records that are active
|
||||
*/
|
||||
public function list_active() {
|
||||
return $this->_where_active()->find_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Function help to find records that are active
|
||||
*/
|
||||
protected function _where_active() {
|
||||
return $this->where('status','=',TRUE);
|
||||
}
|
||||
|
||||
public function where_active() {
|
||||
return $this->_where_active();
|
||||
}
|
||||
}
|
||||
?>
|
228
application/classes/ORM/OSB.php
Normal file
@ -0,0 +1,228 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class extends Kohana's [ORM] class to create defaults for OSB.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class ORM_OSB extends ORM {
|
||||
/**
|
||||
* @var string Database to connect to
|
||||
*/
|
||||
protected $_db = 'default';
|
||||
|
||||
protected $_created_column = array('column'=>'date_orig','format'=>TRUE);
|
||||
protected $_updated_column = array('column'=>'date_last','format'=>TRUE);
|
||||
|
||||
// Our attribute values that need to be stored as serialized
|
||||
protected $_serialize_column = array();
|
||||
|
||||
// Our attributes used in forms.
|
||||
protected $_form = array();
|
||||
|
||||
// Rules to assist with site ID and getting next record ID for inserts.
|
||||
public function rules() {
|
||||
return array(
|
||||
'id'=>array(
|
||||
array('ORM_OSB::get_next_id',array(':model',':field')),
|
||||
),
|
||||
'site_id'=>array(
|
||||
array('ORM_OSB::set_site_id',array(':model',':field')),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Auto process some data as it comes from the database
|
||||
* @see parent::__get()
|
||||
*/
|
||||
public function __get($column) {
|
||||
if (array_key_exists($column,$this->_table_columns)) {
|
||||
// If the column is a blob, we'll decode it automatically
|
||||
if (
|
||||
$this->_table_columns[$column]['data_type'] == 'blob'
|
||||
AND ! is_null($this->_object[$column])
|
||||
AND ! isset($this->_changed[$column])
|
||||
AND (! isset($this->_table_columns[$column]['auto_convert']) OR ! $this->_table_columns[$column]['auto_convert'])
|
||||
) {
|
||||
|
||||
// In case our blob hasnt been saved as one.
|
||||
try {
|
||||
$this->_object[$column] = $this->blob($this->_object[$column]);
|
||||
}
|
||||
catch(Exception $e) {
|
||||
// @todo Log this exception
|
||||
echo Kohana_Exception::text($e), "\n";
|
||||
echo debug_print_backtrace();
|
||||
}
|
||||
|
||||
$this->_table_columns[$column]['auto_convert'] = TRUE;
|
||||
}
|
||||
|
||||
// If the column is a serialized object, we'll unserialize it.
|
||||
if (
|
||||
in_array($column,$this->_serialize_column)
|
||||
AND is_string($this->_object[$column])
|
||||
AND ! is_null($this->_object[$column])
|
||||
AND ! isset($this->_changed[$column])
|
||||
AND (! isset($this->_table_columns[$column]['unserialized']) OR ! $this->_table_columns[$column]['unserialized'])
|
||||
) {
|
||||
|
||||
// In case our object hasnt been saved as serialized.
|
||||
try {
|
||||
$this->_object[$column] = unserialize($this->_object[$column]);
|
||||
}
|
||||
catch(Exception $e) {
|
||||
// @todo Log this exception
|
||||
echo Kohana_Exception::text($e), "\n";
|
||||
echo debug_print_backtrace();
|
||||
}
|
||||
|
||||
$this->_table_columns[$column]['unserialized'] = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return parent::__get($column);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function will enhance the [Validate::filter], since it always passes
|
||||
* the value as the first argument and sometimes functions need that to not
|
||||
* be the first argument.
|
||||
*
|
||||
* Currently this implements:
|
||||
* [date()][date-ref]
|
||||
*
|
||||
* [date-ref]: http://www.php.net/date
|
||||
*
|
||||
* This function will throw an exception if called without a function
|
||||
* defined.
|
||||
*
|
||||
* @param mixed $val Value to be processed
|
||||
* @param string $func Name of function to call
|
||||
* @param string $arg Other arguments for the function
|
||||
* @todo This has probably changed in KH 3.1
|
||||
*/
|
||||
final public static function x_filters($val,$func,$arg) {
|
||||
switch ($func) {
|
||||
case 'date':
|
||||
return date($arg,$val);
|
||||
default:
|
||||
throw new Exception(sprintf(_('Unknown function: %s (%s,%s)'),$func,$arg,$val));
|
||||
}
|
||||
}
|
||||
|
||||
final public static function xform($table,$blank=FALSE) {
|
||||
return ORM::factory($table)->formselect($blank);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve and Store DB BLOB data.
|
||||
*/
|
||||
private function blob($data,$set=FALSE) {
|
||||
try {
|
||||
return $set ? gzcompress(serialize($data)) : unserialize(gzuncompress($data));
|
||||
|
||||
// Maybe the data isnt compressed?
|
||||
} catch (Exception $e) {
|
||||
return $set ? serialize($data) : unserialize($data);
|
||||
}
|
||||
}
|
||||
|
||||
public function config($key) {
|
||||
$mc = Config::instance()->module_config($this->_object_name);
|
||||
|
||||
return empty($mc[$key]) ? '' : $mc[$key];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Next record id
|
||||
*
|
||||
* @param array Validate object
|
||||
* @param string Primary Key
|
||||
*/
|
||||
final public static function get_next_id($model,$field) {
|
||||
if (! is_null($model->$field))
|
||||
return TRUE;
|
||||
|
||||
$model->_changed[$field] = $field;
|
||||
|
||||
$ido = ORM::factory('Module')
|
||||
->where('name','=',$model->_table_name)
|
||||
->find();
|
||||
|
||||
if (! $ido->loaded())
|
||||
throw new Kohana_Exception('Problem getting record_id for :table',array(':table'=>$model->_table_name));
|
||||
|
||||
$model->$field = $ido->record_id->next_id($ido->id);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the site ID attribute for each row update
|
||||
*/
|
||||
final public static function set_site_id($model,$field) {
|
||||
if (! is_null($model->$field))
|
||||
return TRUE;
|
||||
|
||||
$model->_changed[$field] = $field;
|
||||
$model->$field = Company::instance()->site();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
public function xformselect($blank) {
|
||||
$result = array();
|
||||
|
||||
if ($blank)
|
||||
$result[] = '';
|
||||
|
||||
foreach ($this->find_all() as $o)
|
||||
$result[$o->{$this->_form['id']}] = $o->{$this->_form['value']};
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function keyget($column,$key=NULL) {
|
||||
if (is_null($key) OR ! is_array($this->$column))
|
||||
return $this->$column;
|
||||
else
|
||||
return array_key_exists($key,$this->$column) ? $this->{$column}[$key] : NULL;
|
||||
}
|
||||
|
||||
final public function mid() {
|
||||
return ORM::factory('Module',array('name'=>$this->_table_name));
|
||||
}
|
||||
|
||||
public function save(Validation $validation = NULL) {
|
||||
// Find any fields that have changed, and process them.
|
||||
if ($this->_changed)
|
||||
foreach ($this->_changed as $c)
|
||||
// Any fields that are blobs, and encode them.
|
||||
if ($this->_table_columns[$c]['data_type'] == 'blob') {
|
||||
$this->_object[$c] = $this->blob($this->_object[$c],TRUE);
|
||||
|
||||
// We need to reset our auto_convert flag
|
||||
if (isset($this->_table_columns[$c]['auto_convert']))
|
||||
$this->_table_columns[$c]['auto_convert'] = FALSE;
|
||||
|
||||
// Any fields that should be seriailzed, we'll do that.
|
||||
} elseif (is_array($this->_object[$c]) AND in_array($c,$this->_serialize_column)) {
|
||||
$this->_object[$c] = serialize($this->_object[$c]);
|
||||
}
|
||||
|
||||
return parent::save($validation);
|
||||
}
|
||||
|
||||
public function list_count($active=TRUE) {
|
||||
$x=($active ? $this->_where_active() : $this);
|
||||
|
||||
return $x->find_all()->count();
|
||||
}
|
||||
}
|
||||
?>
|
129
application/classes/Period.php
Normal file
@ -0,0 +1,129 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class is for calculating date periods.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Period {
|
||||
/**
|
||||
* Calculate both the start and end dates for a billing period
|
||||
* and the pro-rata percentage.
|
||||
*
|
||||
* See [StaticList_RecurSchedule]
|
||||
*
|
||||
* @param StaticList_RecurSchedule Period Type [StaticList_RecurSchedule]
|
||||
* @param int Starting date if recurring must start on a day of the month
|
||||
* @param datetime Date to start calculating from, otherwise now() is used
|
||||
* @param boolean Show dates in 'Y-m-d' format
|
||||
* @return array
|
||||
*/
|
||||
public static function details($type,$weekday=NULL,$start=NULL,$df=FALSE,$strict=FALSE) {
|
||||
// Round the time integer to a whole day.
|
||||
if (is_null($start))
|
||||
$start = strtotime('today');
|
||||
else
|
||||
$start = strtotime(date('Y-m-d',$start));
|
||||
|
||||
$inc_months = $used_months = 0;
|
||||
|
||||
switch ($type) {
|
||||
// Weekly
|
||||
case 0:
|
||||
if ($strict)
|
||||
throw new Kohana_Exception('Strict doesnt work here');
|
||||
|
||||
$period_start = is_null($weekday) ? $start : $start+86400*($weekday-date('w',$start));
|
||||
$period_end = $period_start+(86400*7);
|
||||
|
||||
break;
|
||||
|
||||
// Monthly
|
||||
case 1:
|
||||
// NOTE: Strict doesnt do anything here.
|
||||
$inc_months = 1;
|
||||
break;
|
||||
|
||||
// Quarterly
|
||||
case 2:
|
||||
$inc_months = 3;
|
||||
break;
|
||||
|
||||
// Half Yearly
|
||||
case 3:
|
||||
$inc_months = 6;
|
||||
break;
|
||||
|
||||
// Yearly
|
||||
case 4:
|
||||
$inc_months = 12;
|
||||
break;
|
||||
|
||||
// Biennial
|
||||
case 5:
|
||||
$inc_months = 24;
|
||||
break;
|
||||
|
||||
// Triennial
|
||||
case 6:
|
||||
if ($strict)
|
||||
throw new Kohana_Exception('Strict not implemented here');
|
||||
|
||||
$inc_months = 36;
|
||||
break;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Workout the period start day
|
||||
if (is_null($weekday))
|
||||
$weekday = $strict ? 1 : date('d',$start);
|
||||
|
||||
// We only work our used_months for periods monthly or more.
|
||||
if ($inc_months) {
|
||||
if ($strict)
|
||||
$used_months = $inc_months-(($inc_months-(date('n',$start)%$inc_months))%$inc_months+1);
|
||||
|
||||
$d = mktime(0,0,0,date('m',$start)-$used_months,$weekday,date('y',$start));
|
||||
if ($d <= $start)
|
||||
$period_start = $d;
|
||||
else
|
||||
$period_start = mktime(0,0,0,date('m',$d)-1-$used_months,$weekday,date('y',$d));
|
||||
|
||||
// Workout the period end
|
||||
$period_end = mktime(0,0,0,date('m',$period_start)+$inc_months,$weekday,date('y',$period_start));
|
||||
}
|
||||
|
||||
$total_time = $period_end-$period_start;
|
||||
$remain_time = $period_end-$start;
|
||||
$used_time = $start-$period_start;
|
||||
|
||||
// Change our end date to the day before
|
||||
$period_end -= 86400;
|
||||
|
||||
$result = array(
|
||||
'start'=>$period_start,
|
||||
'start_time'=>$start,
|
||||
'date'=>$start,
|
||||
'end'=>$period_end,
|
||||
'end_time'=>$period_end,
|
||||
'weekday'=>$weekday,
|
||||
'prorata'=>round($remain_time/$total_time,4),
|
||||
'total_time'=>sprintf('%3.1f',$total_time/86400),
|
||||
'remain_time'=>sprintf('%3.1f',$remain_time/86400),
|
||||
'used_time'=>sprintf('%3.1f',$used_time/86400),
|
||||
);
|
||||
|
||||
if ($df)
|
||||
foreach (array('start','date','end') as $key)
|
||||
$result[$key] = Config::date($result[$key]);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
?>
|
31
application/classes/Request.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* Request. Uses the [Route] class to determine what
|
||||
* [Controller] to send the request to.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Request extends Kohana_Request {
|
||||
/**
|
||||
* Sets and gets the directory for the controller.
|
||||
*
|
||||
* We override the Kohana version, so that we can have short directory URLs.
|
||||
* eg: admin=>a,reseller=>r.
|
||||
*
|
||||
* @param string $directory Directory to execute the controller from
|
||||
* @return mixed
|
||||
*/
|
||||
public function directory($directory = NULL) {
|
||||
// If $directory is NULL, we are a getter and see if we need to expand the directory
|
||||
if ($directory === NULL AND $this->_directory)
|
||||
$this->_directory = URL::dir($this->_directory);
|
||||
|
||||
return parent::directory($directory);
|
||||
}
|
||||
}
|
||||
?>
|
18
application/classes/Response.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's Response
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Response extends Kohana_Response {
|
||||
// Append to the body.
|
||||
public function bodyadd($content) {
|
||||
$this->_body .= (string) $content;
|
||||
}
|
||||
}
|
||||
?>
|
71
application/classes/StaticList.php
Normal file
@ -0,0 +1,71 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders standard lists and their values
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class StaticList {
|
||||
// This is our list of items that will be rendered
|
||||
protected $list = array();
|
||||
|
||||
/**
|
||||
* Each static list type must provide the table function that contains
|
||||
* the table of list and values.
|
||||
*/
|
||||
abstract protected function table();
|
||||
|
||||
public static function factory() {
|
||||
throw new Kohana_Exception(':class is calling :method, when it should have its own method',
|
||||
array(':class'=>get_called_class(),':method'=>__METHOD__));
|
||||
}
|
||||
|
||||
/**
|
||||
* Display a static name for a value
|
||||
*
|
||||
* @param key $id value to render
|
||||
* @see _display()
|
||||
*/
|
||||
public static function display($value) {
|
||||
return static::_display($value);
|
||||
}
|
||||
|
||||
// Due to static scope, sometimes we need to call this function from the child class.
|
||||
protected static function _display($id) {
|
||||
$table = static::factory()->table();
|
||||
|
||||
if (! $table)
|
||||
return 'No Table';
|
||||
elseif (empty($table[$id]))
|
||||
return sprintf('No Value (%s)',$id);
|
||||
else
|
||||
return $table[$id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Lists our available keys
|
||||
*/
|
||||
public static function keys() {
|
||||
return array_keys(static::factory()->table());
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders form input
|
||||
*
|
||||
* @param string Form name to render
|
||||
* @param string Default value to populate in the Form input.
|
||||
*/
|
||||
public static function form($name,$default='',$addblank=FALSE) {
|
||||
$table = static::factory()->table();
|
||||
|
||||
if ($addblank)
|
||||
$table = array_merge(array(''=>' '),$table);
|
||||
|
||||
return Form::Select($name,$table,$default);
|
||||
}
|
||||
}
|
||||
?>
|
93
application/classes/StaticList/Module.php
Normal file
@ -0,0 +1,93 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders responses and forms based on the values from a module.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class StaticList_Module extends StaticList {
|
||||
protected static $record = array();
|
||||
|
||||
/**
|
||||
* Display a static name for a value
|
||||
*/
|
||||
public static function display($id) {
|
||||
// Override our argument list as defined in parent
|
||||
list($table,$key,$skey,$value) = func_get_args();
|
||||
$db = DB::select($key)->from($table)->where($skey,'=',$value)->execute();
|
||||
|
||||
if ($db->count() !== 1)
|
||||
return sprintf('No Value (%s)',$value);
|
||||
else
|
||||
return $db->get($key);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is to return the cached value of the current active record
|
||||
* This is so that a follow up call to get an attribute of a value retrieved
|
||||
* can reuse the active record values.
|
||||
* This gets over a limitation where the query to form() to get a default
|
||||
* no longer exists (or is invalid) and you want other attributes of the
|
||||
* remaining active record, which may not be the default record.
|
||||
*/
|
||||
public static function record($table,$attribute,$skey,$value) {
|
||||
if (empty(static::$record[$table]))
|
||||
return static::display($table,$attribute,$skey,$value);
|
||||
else
|
||||
return static::$record[$table][$attribute];
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders form input
|
||||
*/
|
||||
public static function form($name,$default='',$addblank=FALSE) {
|
||||
// Override our argument list as defined in parent
|
||||
list($name,$table,$default,$key,$value,$where,$addblank,$attributes) = func_get_args();
|
||||
|
||||
$db = DB::select()->from($table);
|
||||
|
||||
foreach ($where as $k=>$v) {
|
||||
list ($op,$v) = explode(':',$v);
|
||||
$db->where($k,$op,$v);
|
||||
}
|
||||
|
||||
$db = $db->execute();
|
||||
|
||||
// If we only have one record, dont make a select list
|
||||
if ($db->count() == 1) {
|
||||
static::$record[$table] = $db->as_array();
|
||||
static::$record[$table] = array_shift(static::$record[$table]);
|
||||
|
||||
return Form::hidden($name,$db->get($key)).$db->get($value);
|
||||
}
|
||||
|
||||
// Else we return a select list
|
||||
$x = array();
|
||||
if ($addblank)
|
||||
$x[] = '';
|
||||
|
||||
foreach ($db as $record) {
|
||||
$x[$record[$key]] = $record[$value];
|
||||
|
||||
// Save our static record, in case we reference this item again.
|
||||
if ($record[$key] == $default)
|
||||
static::$record[$table] = $record;
|
||||
}
|
||||
|
||||
return Form::select($name,$x,$default,$attributes);
|
||||
}
|
||||
|
||||
protected function table($module=NULL) {
|
||||
if (is_null($module))
|
||||
throw new Kohana_Exception('Module is a required attribute.');
|
||||
}
|
||||
|
||||
public static function factory() {
|
||||
return new StaticList_Module;
|
||||
}
|
||||
}
|
||||
?>
|
29
application/classes/StaticList/PriceType.php
Normal file
@ -0,0 +1,29 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Price Type responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class StaticList_PriceType extends StaticList {
|
||||
protected function table() {
|
||||
return array(
|
||||
0=>_('One-time Charge'),
|
||||
1=>_('Recurring Membership/Subscription'),
|
||||
2=>_('Trial for Membership/Subscription')
|
||||
);
|
||||
}
|
||||
|
||||
public static function factory() {
|
||||
return new StaticList_PriceType;
|
||||
}
|
||||
|
||||
public static function display($value) {
|
||||
return static::_display($value);
|
||||
}
|
||||
}
|
||||
?>
|
55
application/classes/StaticList/RecurSchedule.php
Normal file
@ -0,0 +1,55 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Recurring Schedule Times on responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class StaticList_RecurSchedule extends StaticList {
|
||||
protected function table() {
|
||||
return array(
|
||||
0=>_('Weekly'),
|
||||
1=>_('Monthly'),
|
||||
2=>_('Quarterly'),
|
||||
3=>_('Semi-Annually'),
|
||||
4=>_('Annually'),
|
||||
5=>_('Two years'),
|
||||
6=>_('Three Years')
|
||||
);
|
||||
}
|
||||
|
||||
public static function factory() {
|
||||
return new StaticList_RecurSchedule;
|
||||
}
|
||||
|
||||
public static function display($value) {
|
||||
return static::_display($value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the price display for a product
|
||||
*
|
||||
* @uses product
|
||||
*/
|
||||
public static function form($name,$product='',$default='',$addblank=FALSE) {
|
||||
if (empty($product))
|
||||
throw new Kohana_Exception('Product is a required field for :method',array(':method'=>__METHOD__));
|
||||
|
||||
$x = '';
|
||||
$table = static::factory()->table();
|
||||
|
||||
foreach ($product->get_price_array() as $term => $price) {
|
||||
$x[$term] = sprintf('%s %s',Currency::display(Tax::add($price['price_base'])),$table[$term]);
|
||||
|
||||
if ($price['price_setup'] > 0)
|
||||
$x[$term] .= sprintf(' + %s %s',Currency::display(Tax::add($price['price_setup'])),_('Setup'));
|
||||
}
|
||||
|
||||
return Form::select($name,$x,$default);
|
||||
}
|
||||
}
|
||||
?>
|
28
application/classes/StaticList/RecurType.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Recurring Schedule Types on responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class StaticList_RecurType extends StaticList {
|
||||
protected function table() {
|
||||
return array(
|
||||
0=>_('Bill on Aniversary Date of Subscription'),
|
||||
1=>_('Bill on Fixed Schedule'),
|
||||
);
|
||||
}
|
||||
|
||||
public static function factory() {
|
||||
return new StaticList_RecurType;
|
||||
}
|
||||
|
||||
public static function display($value) {
|
||||
return static::_display($value);
|
||||
}
|
||||
}
|
||||
?>
|
33
application/classes/StaticList/SweepType.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Charge Sweep Types on responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class StaticList_SweepType extends StaticList {
|
||||
protected function table() {
|
||||
return array(
|
||||
0=>_('Daily'),
|
||||
1=>_('Weekly'),
|
||||
2=>_('Monthly'),
|
||||
3=>_('Quarterly'),
|
||||
4=>_('Semi-Annually'),
|
||||
5=>_('Annually'),
|
||||
6=>_('Service Rebill'),
|
||||
);
|
||||
}
|
||||
|
||||
public static function factory() {
|
||||
return new StaticList_SweepType;
|
||||
}
|
||||
|
||||
public static function display($value) {
|
||||
return static::_display($value);
|
||||
}
|
||||
}
|
||||
?>
|
28
application/classes/StaticList/Title.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Person Title responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class StaticList_Title extends StaticList {
|
||||
protected function table() {
|
||||
return array(
|
||||
'mr'=>_('Mr'),
|
||||
'ms'=>_('Ms'),
|
||||
'mrs'=>_('Mrs'),
|
||||
'miss'=>_('Miss'),
|
||||
'dr'=>_('Dr'),
|
||||
'prof'=>_('Prof')
|
||||
);
|
||||
}
|
||||
|
||||
public static function factory() {
|
||||
return new StaticList_Title;
|
||||
}
|
||||
}
|
||||
?>
|
28
application/classes/StaticList/YesNo.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This is class renders Yes/No responses and forms.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class StaticList_YesNo extends StaticList {
|
||||
protected function table() {
|
||||
return array(
|
||||
0=>_('No'),
|
||||
1=>_('Yes'),
|
||||
);
|
||||
}
|
||||
|
||||
public static function factory() {
|
||||
return new StaticList_YesNo;
|
||||
}
|
||||
|
||||
public static function display($value) {
|
||||
return static::_display($value);
|
||||
}
|
||||
}
|
||||
?>
|
20
application/classes/Task.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class extends Minions Tasks to require the site option
|
||||
*
|
||||
* @package OSB
|
||||
* @category Helpers
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class Task extends Minion_Task {
|
||||
protected $_options = array(
|
||||
'site'=>NULL,
|
||||
'id'=>NULL,
|
||||
'force'=>FALSE,
|
||||
'verbose'=>FALSE,
|
||||
);
|
||||
}
|
||||
?>
|
33
application/classes/Task/Account/Complete.php
Normal file
@ -0,0 +1,33 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* Mark all accounts that have no outstanding invoices and active services as disabled.
|
||||
*
|
||||
* @package Account
|
||||
* @category Tasks
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class Task_Account_Complete extends Task {
|
||||
protected function _execute(array $params) {
|
||||
$c = 0;
|
||||
|
||||
$o = ORM::factory('Account')
|
||||
->where_active();
|
||||
|
||||
foreach ($o->find_all() as $ao) {
|
||||
if (count($ao->invoice->where_unprocessed()->find_all()) == 0 AND count($ao->service->where_active()->find_all()) == 0)
|
||||
// @todo Cant update status=0, problem with sessions in CLI
|
||||
echo $ao->id.',';
|
||||
|
||||
$ao->save();
|
||||
|
||||
if ($ao->saved())
|
||||
$c++;
|
||||
}
|
||||
|
||||
printf('%s services updated',$c);
|
||||
}
|
||||
}
|
||||
?>
|
54
application/classes/URL.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class overrides Kohana's URL
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class URL extends Kohana_URL {
|
||||
// Our method paths for different functions
|
||||
public static $method_directory = array(
|
||||
'admin'=>'a',
|
||||
'affiliate'=>'affiliate', // @todo To retire
|
||||
'reseller'=>'r',
|
||||
'task'=>'task',
|
||||
'user'=>'u',
|
||||
);
|
||||
|
||||
/**
|
||||
* Wrapper to provide a URL::site() link based on function
|
||||
*/
|
||||
public static function link($dir,$src,$site=FALSE) {
|
||||
if (! $dir)
|
||||
return $src;
|
||||
|
||||
if (! array_key_exists($dir,URL::$method_directory))
|
||||
throw new Kohana_Exception('Unknown directory :dir for :src',array(':dir'=>$dir,':src'=>$src));
|
||||
|
||||
$x = URL::$method_directory[$dir].'/'.$src;
|
||||
|
||||
return $site ? URL::site($x) : $x;
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to reveal the real directory for a URL
|
||||
*/
|
||||
public static function dir($dir) {
|
||||
// Quick check if we can do something here
|
||||
if (! in_array(strtolower($dir),URL::$method_directory))
|
||||
return $dir;
|
||||
|
||||
// OK, we can, find it.
|
||||
foreach (URL::$method_directory as $k=>$v)
|
||||
if (strtolower($dir) == $v)
|
||||
return ucfirst($k);
|
||||
|
||||
// If we get here, we didnt have anything.
|
||||
return $dir;
|
||||
}
|
||||
}
|
||||
?>
|
27
application/classes/Valid.php
Normal file
@ -0,0 +1,27 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* Array and variable validation.
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
abstract class Valid extends Kohana_Valid {
|
||||
/**
|
||||
* Checks if a field matches the value of another field, if it is set.
|
||||
* Field is ignored if it is blank.
|
||||
*
|
||||
* @param array array of values
|
||||
* @param string field name
|
||||
* @param string field name to match
|
||||
* @return boolean
|
||||
*/
|
||||
public static function matches_ifset($array, $field, $match)
|
||||
{
|
||||
return isset($array[$match]) ? ($array[$field] === $array[$match]) : TRUE;
|
||||
}
|
||||
}
|
||||
?>
|
44
application/classes/XML.php
Normal file
@ -0,0 +1,44 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* This class extends the Kohana XML
|
||||
*
|
||||
* @package OSB
|
||||
* @category Modifications
|
||||
* @author Deon George
|
||||
* @copyright (c) 2009-2013 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
class XML extends XML_Core {
|
||||
/**
|
||||
* Collapse an XML object into a simple array
|
||||
*/
|
||||
public function collapse(XML $xml=NULL) {
|
||||
if (is_null($xml))
|
||||
$xml = $this;
|
||||
$result = array();
|
||||
|
||||
foreach ($xml->as_array() as $j=>$k) {
|
||||
$v = $xml->$j->value();
|
||||
|
||||
if (count($k) > 1) {
|
||||
foreach ($xml->get($j,1) as $k)
|
||||
if (isset($k['name'][0]))
|
||||
$result[$j][$k['name'][0]] = (isset($k['value'][0]) ? $k['value'][0] : '');
|
||||
else
|
||||
$result[$j][] = $k;
|
||||
|
||||
} elseif (! is_null($v))
|
||||
$result[$j] = $v;
|
||||
else {
|
||||
$result[$j] = $this->collapse($xml->$j);
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('name',$result) AND array_key_exists('value',$result))
|
||||
$result = array($result['name']=>$result['value']);
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
?>
|
18
application/config/auth.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Configuration - Authentication
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Authentication
|
||||
* @category Configuration
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
|
||||
return array(
|
||||
'driver' => 'OSB',
|
||||
'hash_method' => 'md5',
|
||||
);
|
||||
?>
|
32
application/config/cache.php
Normal file
@ -0,0 +1,32 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Configuration - Cache Driver
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Cache
|
||||
* @category Configuration
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
|
||||
return array(
|
||||
'apc' => array(
|
||||
'driver' => 'apc',
|
||||
'default_expire' => 3600,
|
||||
),
|
||||
|
||||
'file' => array(
|
||||
'driver' => 'file',
|
||||
'cache_dir' => Kohana::$cache_dir ? Kohana::$cache_dir : APPPATH.'cache/',
|
||||
'default_expire' => 3600,
|
||||
'ignore_on_delete' => array(
|
||||
'.gitignore',
|
||||
'.git',
|
||||
'.htaccess',
|
||||
'.svn'
|
||||
)
|
||||
),
|
||||
);
|
||||
?>
|
31
application/config/config.php
Normal file
@ -0,0 +1,31 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Configuration - System Default Configurable Items.
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage System
|
||||
* @category Configuration
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
|
||||
return array(
|
||||
'appname' => 'OS Billing', // Our application name, as shown in the title bar of pages
|
||||
'cache_type' => 'file',
|
||||
'email_from' => array('noreply@graytech.net.au'=>'Graytech Hosting'),
|
||||
'email_admin_only'=> array(
|
||||
// 'adsl_traffic_notice'=>array('deon@leenooks.vpn'=>'Deon George'),
|
||||
),
|
||||
'method_security' => TRUE, // Enables Method Security. Setting to false means any method can be run without authentication
|
||||
'session_change_trigger'=>array( // Updates to tables to make when our session ID is changed
|
||||
'Cart'=>'session_id',
|
||||
),
|
||||
'bsb' => '633-000', // @todo This should come from the DB
|
||||
'accnum' => '120 440 821', // @todo This should come from the DB
|
||||
'theme' => 'yaml', // @todo This should be in the DB
|
||||
'theme_admin' => 'yaml', // @todo This should be in the DB
|
||||
'tmpdir' => '/tmp',
|
||||
);
|
||||
?>
|
43
application/config/database.php
Normal file
@ -0,0 +1,43 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Configuration - Database Driver
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Database
|
||||
* @category Configuration
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
|
||||
return array
|
||||
(
|
||||
'default' => array
|
||||
(
|
||||
'type' => 'mysql',
|
||||
'connection' => array(
|
||||
/**
|
||||
* The following options are available for MySQL:
|
||||
*
|
||||
* string hostname server hostname, or socket
|
||||
* string database database name
|
||||
* string username database username
|
||||
* string password database password
|
||||
* boolean persistent use persistent connections?
|
||||
*
|
||||
* Ports and sockets may be appended to the hostname.
|
||||
*/
|
||||
'hostname' => 'localhost',
|
||||
'username' => 'username',
|
||||
'password' => 'password',
|
||||
'persistent' => FALSE,
|
||||
'database' => 'database',
|
||||
),
|
||||
'table_prefix' => 'ab_',
|
||||
'charset' => 'utf8',
|
||||
'caching' => FALSE,
|
||||
'profiling' => TRUE,
|
||||
),
|
||||
);
|
||||
?>
|
25
application/config/debug.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Configuration - Debug Settings
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Debug
|
||||
* @category Configuration
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
|
||||
return array
|
||||
(
|
||||
'ajax'=>FALSE, // AJAX actions can only be run by ajax calls if set to FALSE
|
||||
'etag'=>FALSE, // Force generating ETAGS
|
||||
'checkout_notify'=>FALSE, // Test mode to test a particular checkout_notify item
|
||||
'invoice'=>0, // Number of invoices to generate in a pass
|
||||
'site'=>FALSE, // Glogal site debug
|
||||
'show_errors'=>FALSE, // Show errors instead of logging in the DB.
|
||||
'show_inactive'=>FALSE, // Show Inactive Items
|
||||
'task_sim'=>FALSE, // Simulate running tasks
|
||||
);
|
||||
?>
|
17
application/config/invoice.php
Normal file
@ -0,0 +1,17 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Configuration - Invoice Driver
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Invoice
|
||||
* @category Configuration
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
|
||||
return array(
|
||||
'driver' => 'default',
|
||||
);
|
||||
?>
|
278
application/config/openssl.cnf
Normal file
@ -0,0 +1,278 @@
|
||||
# OpenSSL example configuration file.
|
||||
|
||||
# Extra OBJECT IDENTIFIER info:
|
||||
#oid_file = $ENV::HOME/.oid
|
||||
oid_section = new_oids
|
||||
|
||||
# To use this configuration file with the "-extfile" option of the
|
||||
# "openssl x509" utility, name here the section containing the
|
||||
# X.509v3 extensions to use:
|
||||
# extensions =
|
||||
# (Alternatively, use a configuration file that has only
|
||||
# X.509v3 extensions in its main [= default] section.)
|
||||
|
||||
[ new_oids ]
|
||||
|
||||
# We can add new OIDs in here for use by 'ca' and 'req'.
|
||||
# Add a simple OID like this:
|
||||
# testoid1=1.2.3.4
|
||||
# Or use config file substitution like this:
|
||||
# testoid2=${testoid1}.5.6
|
||||
|
||||
####################################################################
|
||||
[ ca ]
|
||||
default_ca = CA_default # The default ca section
|
||||
|
||||
####################################################################
|
||||
[ CA_default ]
|
||||
|
||||
dir = modules/ssl/config# Where everything is kept
|
||||
certs = $dir # Where the issued certs are kept
|
||||
crl_dir = $dir # Where the issued crl are kept
|
||||
database = $dir/index.txt # database index file.
|
||||
new_certs_dir = $dir # default place for new certs.
|
||||
|
||||
certificate = $dir/ca.crt # The CA certificate
|
||||
serial = $dir/serial # The current serial number
|
||||
crl = $dir/crl.pem # The current CRL
|
||||
private_key = $dir/ca.key # The private key
|
||||
RANDFILE = $dir/.rand # private random number file
|
||||
|
||||
x509_extensions = usr_cert # The extentions to add to the cert
|
||||
|
||||
# Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs
|
||||
# so this is commented out by default to leave a V1 CRL.
|
||||
crl_extensions = crl_ext
|
||||
|
||||
default_days = 375 # how long to certify for
|
||||
default_crl_days = 30 # how long before next CRL
|
||||
default_md = sha1 # which md to use.
|
||||
preserve = no # keep passed DN ordering
|
||||
|
||||
# A few difference way of specifying how similar the request should look
|
||||
# For type CA, the listed attributes must be the same, and the optional
|
||||
# and supplied fields are just that :-)
|
||||
policy = policy_match
|
||||
|
||||
# For the CA policy
|
||||
[ policy_match ]
|
||||
countryName = match
|
||||
stateOrProvinceName = supplied
|
||||
organizationName = supplied
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
[ policy_o ]
|
||||
countryName = match
|
||||
stateOrProvinceName = supplied
|
||||
organizationName = supplied
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
[ policy_ou ]
|
||||
countryName = match
|
||||
stateOrProvinceName = match
|
||||
organizationName = match
|
||||
organizationalUnitName = supplied
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
# For the 'anything' policy
|
||||
# At this point in time, you must list all acceptable 'object'
|
||||
# types.
|
||||
[ policy_anything ]
|
||||
countryName = optional
|
||||
stateOrProvinceName = optional
|
||||
localityName = optional
|
||||
organizationName = optional
|
||||
organizationalUnitName = optional
|
||||
commonName = supplied
|
||||
emailAddress = optional
|
||||
|
||||
####################################################################
|
||||
[ req ]
|
||||
default_bits = 1024
|
||||
default_keyfile = privkey.pem
|
||||
distinguished_name = req_distinguished_name
|
||||
attributes = req_attributes
|
||||
x509_extensions = v3_ca # The extentions to add to the self signed cert
|
||||
|
||||
# Passwords for private keys if not present they will be prompted for
|
||||
# input_password = secret
|
||||
# output_password = secret
|
||||
|
||||
# This sets a mask for permitted string types. There are several options.
|
||||
# default: PrintableString, T61String, BMPString.
|
||||
# pkix : PrintableString, BMPString.
|
||||
# utf8only: only UTF8Strings.
|
||||
# nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings).
|
||||
# MASK:XXXX a literal mask value.
|
||||
# WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings
|
||||
# so use this option with caution!
|
||||
string_mask = nombstr
|
||||
|
||||
req_extensions = v3_req # The extensions to add to a certificate request
|
||||
|
||||
[ req_distinguished_name ]
|
||||
countryName = Country Name (2 letter code)
|
||||
countryName_default = AU
|
||||
countryName_min = 2
|
||||
countryName_max = 2
|
||||
|
||||
stateOrProvinceName = State or Province Name (full name)
|
||||
stateOrProvinceName_default = VIC
|
||||
|
||||
localityName = Locality Name (eg, city)
|
||||
localityName_default = Bendigo
|
||||
|
||||
0.organizationName = Organization Name (eg, company)
|
||||
#0.organizationName_default = $ENV::KEY_ORG
|
||||
|
||||
# we can do this but it is not needed normally :-)
|
||||
#1.organizationName = Second Organization Name (eg, company)
|
||||
#1.organizationName_default = World Wide Web Pty Ltd
|
||||
|
||||
organizationalUnitName = Organizational Unit Name (eg, section)
|
||||
#organizationalUnitName_default = $ENV::KEY_OU
|
||||
#organizationalUnitName_default =
|
||||
|
||||
commonName = Common Name (eg, your name or your server\'s hostname)
|
||||
#commonName_default = $ENV::KEY_CN
|
||||
commonName_max = 64
|
||||
|
||||
#emailAddress = Email Address
|
||||
#emailAddress_default = $ENV::KEY_EMAIL
|
||||
#emailAddress_max = 40
|
||||
|
||||
# SET-ex3 = SET extension number 3
|
||||
|
||||
[ req_attributes ]
|
||||
challengePassword = A challenge password
|
||||
challengePassword_min = 4
|
||||
challengePassword_max = 20
|
||||
|
||||
# unstructuredName = An optional company name
|
||||
|
||||
[ usr_cert ]
|
||||
|
||||
# These extensions are added when 'ca' signs a request.
|
||||
|
||||
# This goes against PKIX guidelines but some CAs do it and some software
|
||||
# requires this to avoid interpreting an end user certificate as a CA.
|
||||
|
||||
#basicConstraints = CA:FALSE
|
||||
|
||||
# Here are some examples of the usage of nsCertType. If it is omitted
|
||||
# the certificate can be used for anything *except* object signing.
|
||||
|
||||
# This is OK for an SSL server.
|
||||
# nsCertType = server
|
||||
|
||||
# For an object signing certificate this would be used.
|
||||
# nsCertType = objsign
|
||||
|
||||
# For normal client use this is typical
|
||||
# nsCertType = client, email
|
||||
|
||||
# and for everything including object signing:
|
||||
# nsCertType = client, email, objsign
|
||||
|
||||
# This is typical in keyUsage for a client certificate.
|
||||
# keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
|
||||
# PKIX recommendations harmless if included in all certificates.
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid,issuer:always
|
||||
|
||||
# This stuff is for subjectAltName and issuerAltname.
|
||||
# Import the email address.
|
||||
# subjectAltName=email:copy
|
||||
|
||||
# Copy subject details
|
||||
issuerAltName = issuer:copy,URI:https://www.graytech.net.au
|
||||
authorityInfoAccess = OCSP;URI:https://www.graytech.net.au/ssl/ocsp,caIssuers;URI:https://www.graytech.net.au/ssl/ca
|
||||
crlDistributionPoints = URI:https://www.graytech.net.au/ssl/crl
|
||||
|
||||
## Should add --extensions client to client certs
|
||||
[ client ]
|
||||
|
||||
nsCertType = client,email,objsign
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid,issuer:always
|
||||
issuerAltName = issuer:copy,URI:https://www.graytech.net.au
|
||||
authorityInfoAccess = OCSP;URI:https://www.graytech.net.au/ssl/ocsp,caIssuers;URI:https://www.graytech.net.au/ssl/ca
|
||||
crlDistributionPoints = URI:https://www.graytech.net.au/ssl/crl
|
||||
|
||||
## Should add --extensions server to server certs
|
||||
[ server ]
|
||||
|
||||
nsCertType = server
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid,issuer:always
|
||||
issuerAltName = issuer:copy,URI:https://www.graytech.net.au
|
||||
authorityInfoAccess = OCSP;URI:https://www.graytech.net.au/ssl/ocsp,caIssuers;URI:https://www.graytech.net.au/ssl/ca
|
||||
crlDistributionPoints = URI:https://www.graytech.net.au/ssl/crl
|
||||
|
||||
[ v3_req ]
|
||||
|
||||
# Extensions to add to a certificate request
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
|
||||
|
||||
[ v3_ca ]
|
||||
basicConstraints = critical,CA:true,pathlen:0
|
||||
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid:always,issuer:always
|
||||
keyUsage = cRLSign, keyCertSign
|
||||
nsCertType = sslCA, emailCA
|
||||
|
||||
issuerAltName = issuer:copy,URI:https://www.graytech.net.au
|
||||
authorityInfoAccess = OCSP;URI:https://www.graytech.net.au/ssl/ocsp,caIssuers;URI:https://www.graytech.net.au/ssl/ca
|
||||
crlDistributionPoints = URI:https://www.graytech.net.au/ssl/crl
|
||||
|
||||
[ v3_ca_ou ]
|
||||
basicConstraints = critical,CA:true,pathlen:0
|
||||
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid:always,issuer:always
|
||||
keyUsage = cRLSign, keyCertSign
|
||||
nsCertType = sslCA, emailCA
|
||||
|
||||
issuerAltName = issuer:copy,URI:https://www.graytech.net.au
|
||||
authorityInfoAccess = OCSP;URI:https://www.graytech.net.au/ssl/ocsp,caIssuers;URI:https://www.graytech.net.au/ssl/ca
|
||||
crlDistributionPoints = URI:https://www.graytech.net.au/ssl/crl
|
||||
|
||||
[ v3_ca_o ]
|
||||
basicConstraints = critical,CA:true,pathlen:1
|
||||
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid:always,issuer:always
|
||||
keyUsage = cRLSign, keyCertSign
|
||||
nsCertType = sslCA, emailCA
|
||||
|
||||
issuerAltName = issuer:copy,URI:https://www.graytech.net.au
|
||||
authorityInfoAccess = OCSP;URI:https://www.graytech.net.au/ssl/ocsp,caIssuers;URI:https://www.graytech.net.au/ssl/ca
|
||||
crlDistributionPoints = URI:https://www.graytech.net.au/ssl/crl
|
||||
|
||||
[ v3_ca_ca ]
|
||||
basicConstraints = critical,CA:true,pathlen:2
|
||||
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid:always,issuer:always
|
||||
keyUsage = cRLSign, keyCertSign
|
||||
nsCertType = sslCA, emailCA
|
||||
|
||||
issuerAltName = issuer:copy,URI:https://www.graytech.net.au
|
||||
authorityInfoAccess = OCSP;URI:https://www.graytech.net.au/ssl/ocsp,caIssuers;URI:https://www.graytech.net.au/ssl/ca
|
||||
crlDistributionPoints = URI:https://www.graytech.net.au/ssl/crl
|
||||
|
||||
[ crl_ext ]
|
||||
|
||||
# CRL extensions.
|
||||
# Only issuerAltName and authorityKeyIdentifier make any sense in a CRL.
|
||||
|
||||
# issuerAltName=issuer:copy
|
||||
authorityKeyIdentifier = keyid:always,issuer:always
|
24
application/config/pagination.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Configuration - Pagination Driver
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage Pagination
|
||||
* @category Configuration
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
|
||||
return array(
|
||||
'default' => array(
|
||||
'current_page' => array('source' => 'query_string', 'key' => 'page'),
|
||||
'total_items' => 0,
|
||||
'items_per_page' => 20,
|
||||
'view' => 'pagination/floating',
|
||||
'auto_hide' => TRUE,
|
||||
'first_page_in_url' => FALSE,
|
||||
),
|
||||
);
|
||||
?>
|
18
application/config/pwgen.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
/**
|
||||
* OSB Configuration - PWGen Configuration
|
||||
*
|
||||
* @package OSB
|
||||
* @subpackage PWGen
|
||||
* @category PWGen
|
||||
* @author Deon George
|
||||
* @copyright (c) 2010 Open Source Billing
|
||||
* @license http://dev.osbill.net/license.html
|
||||
*/
|
||||
|
||||
return array(
|
||||
'host' => '127.0.0.1',
|
||||
'port' => '129',
|
||||
);
|
||||
?>
|
46
application/config/userguide.php
Normal file
@ -0,0 +1,46 @@
|
||||
<?php defined('SYSPATH') or die('No direct access allowed.');
|
||||
|
||||
return array
|
||||
(
|
||||
// Enable the API browser. TRUE or FALSE
|
||||
'api_browser' => TRUE,
|
||||
|
||||
// Enable these packages in the API browser. TRUE for all packages, or a string of comma seperated packages, using 'None' for a class with no @package
|
||||
// Example: 'api_packages' => 'Kohana,Kohana/Database,Kohana/ORM,None',
|
||||
'api_packages' => TRUE,
|
||||
|
||||
// Enables Disqus comments on the API and User Guide pages
|
||||
'show_comments' => Kohana::$environment === Kohana::PRODUCTION,
|
||||
|
||||
// Leave this alone
|
||||
'modules' => array(
|
||||
|
||||
'kohana' => array('enabled'=>FALSE),
|
||||
'auth' => array('enabled'=>FALSE),
|
||||
'cache' => array('enabled'=>FALSE),
|
||||
'database' => array('enabled'=>FALSE),
|
||||
'minion' => array('enabled'=>FALSE),
|
||||
'orm' => array('enabled'=>FALSE),
|
||||
'pagination' => array('enabled'=>FALSE),
|
||||
// This should be the path to this modules userguide pages, without the 'guide/'. Ex: '/guide/modulename/' would be 'modulename'
|
||||
'userguide' => array(
|
||||
|
||||
// Whether this modules userguide pages should be shown
|
||||
'enabled' => TRUE,
|
||||
|
||||
// The name that should show up on the userguide index page
|
||||
'name' => 'Userguide',
|
||||
|
||||
// A short description of this module, shown on the index page
|
||||
'description' => 'Documentation viewer and api generation.',
|
||||
|
||||
// Copyright message, shown in the footer for this module
|
||||
'copyright' => '© 2008–2012 Kohana Team',
|
||||
)
|
||||
),
|
||||
|
||||
// Set transparent class name segments
|
||||
'transparent_prefixes' => array(
|
||||
'Kohana' => TRUE,
|
||||
)
|
||||
);
|
2
application/i18n/.htaccess
Normal file
@ -0,0 +1,2 @@
|
||||
order allow,deny
|
||||
deny from all
|
232
application/media/css/dhtml.calendar.css
Normal file
@ -0,0 +1,232 @@
|
||||
/* The main calendar widget. DIV containing a table. */
|
||||
|
||||
div.calendar { position: relative; }
|
||||
|
||||
.calendar, .calendar table {
|
||||
border: 1px solid #556;
|
||||
font-size: 11px;
|
||||
color: #000;
|
||||
cursor: default;
|
||||
background: #eef;
|
||||
font-family: tahoma,verdana,sans-serif;
|
||||
}
|
||||
|
||||
/* Header part -- contains navigation buttons and day names. */
|
||||
|
||||
.calendar .button { /* "<<", "<", ">", ">>" buttons have this class */
|
||||
text-align: center; /* They are the navigation buttons */
|
||||
padding: 2px; /* Make the buttons seem like they're pressing */
|
||||
}
|
||||
|
||||
.calendar .nav {
|
||||
background: #778 url(dhtml.menuarrow.gif) no-repeat 100% 100%;
|
||||
}
|
||||
|
||||
.calendar thead .title { /* This holds the current "month, year" */
|
||||
font-weight: bold; /* Pressing it will take you to the current date */
|
||||
text-align: center;
|
||||
background: #fff;
|
||||
color: #000;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.calendar thead .headrow { /* Row <TR> containing navigation buttons */
|
||||
background: #778;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.calendar thead .daynames { /* Row <TR> containing the day names */
|
||||
background: #bdf;
|
||||
}
|
||||
|
||||
.calendar thead .name { /* Cells <TD> containing the day names */
|
||||
border-bottom: 1px solid #556;
|
||||
padding: 2px;
|
||||
text-align: center;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.calendar thead .weekend { /* How a weekend day name shows in header */
|
||||
color: #a66;
|
||||
}
|
||||
|
||||
.calendar thead .hilite { /* How do the buttons in header appear when hover */
|
||||
background-color: #aaf;
|
||||
color: #000;
|
||||
border: 1px solid #04f;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.calendar thead .active { /* Active (pressed) buttons in header */
|
||||
background-color: #77c;
|
||||
padding: 2px 0px 0px 2px;
|
||||
}
|
||||
|
||||
/* The body part -- contains all the days in month. */
|
||||
|
||||
.calendar tbody .day { /* Cells <TD> containing month days dates */
|
||||
width: 2em;
|
||||
color: #456;
|
||||
text-align: right;
|
||||
padding: 2px 4px 2px 2px;
|
||||
}
|
||||
.calendar tbody .day.othermonth {
|
||||
font-size: 80%;
|
||||
color: #bbb;
|
||||
}
|
||||
.calendar tbody .day.othermonth.oweekend {
|
||||
color: #fbb;
|
||||
}
|
||||
|
||||
.calendar table .wn {
|
||||
padding: 2px 3px 2px 2px;
|
||||
border-right: 1px solid #000;
|
||||
background: #bdf;
|
||||
}
|
||||
|
||||
.calendar tbody .rowhilite td {
|
||||
background: #def;
|
||||
}
|
||||
|
||||
.calendar tbody .rowhilite td.wn {
|
||||
background: #eef;
|
||||
}
|
||||
|
||||
.calendar tbody td.hilite { /* Hovered cells <TD> */
|
||||
background: #def;
|
||||
padding: 1px 3px 1px 1px;
|
||||
border: 1px solid #bbb;
|
||||
}
|
||||
|
||||
.calendar tbody td.active { /* Active (pressed) cells <TD> */
|
||||
background: #cde;
|
||||
padding: 2px 2px 0px 2px;
|
||||
}
|
||||
|
||||
.calendar tbody td.selected { /* Cell showing today date */
|
||||
font-weight: bold;
|
||||
border: 1px solid #000;
|
||||
padding: 1px 3px 1px 1px;
|
||||
background: #fff;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.calendar tbody td.weekend { /* Cells showing weekend days */
|
||||
color: #a66;
|
||||
}
|
||||
|
||||
.calendar tbody td.today { /* Cell showing selected date */
|
||||
font-weight: bold;
|
||||
color: #00f;
|
||||
}
|
||||
|
||||
.calendar tbody .disabled { color: #999; }
|
||||
|
||||
.calendar tbody .emptycell { /* Empty cells (the best is to hide them) */
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.calendar tbody .emptyrow { /* Empty row (some months need less than 6 rows) */
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* The footer part -- status bar and "Close" button */
|
||||
|
||||
.calendar tfoot .footrow { /* The <TR> in footer (only one right now) */
|
||||
text-align: center;
|
||||
background: #556;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.calendar tfoot .ttip { /* Tooltip (status bar) cell <TD> */
|
||||
background: #fff;
|
||||
color: #445;
|
||||
border-top: 1px solid #556;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.calendar tfoot .hilite { /* Hover style for buttons in footer */
|
||||
background: #aaf;
|
||||
border: 1px solid #04f;
|
||||
color: #000;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.calendar tfoot .active { /* Active (pressed) style for buttons in footer */
|
||||
background: #77c;
|
||||
padding: 2px 0px 0px 2px;
|
||||
}
|
||||
|
||||
/* Combo boxes (menus that display months/years for direct selection) */
|
||||
|
||||
.calendar .combo {
|
||||
position: absolute;
|
||||
display: none;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
width: 4em;
|
||||
cursor: default;
|
||||
border: 1px solid #655;
|
||||
background: #def;
|
||||
color: #000;
|
||||
font-size: 90%;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.calendar .combo .label,
|
||||
.calendar .combo .label-IEfix {
|
||||
text-align: center;
|
||||
padding: 1px;
|
||||
}
|
||||
|
||||
.calendar .combo .label-IEfix {
|
||||
width: 4em;
|
||||
}
|
||||
|
||||
.calendar .combo .hilite {
|
||||
background: #acf;
|
||||
}
|
||||
|
||||
.calendar .combo .active {
|
||||
border-top: 1px solid #46a;
|
||||
border-bottom: 1px solid #46a;
|
||||
background: #eef;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.calendar td.time {
|
||||
border-top: 1px solid #000;
|
||||
padding: 1px 0px;
|
||||
text-align: center;
|
||||
background-color: #f4f0e8;
|
||||
}
|
||||
|
||||
.calendar td.time .hour,
|
||||
.calendar td.time .minute,
|
||||
.calendar td.time .ampm {
|
||||
padding: 0px 3px 0px 4px;
|
||||
border: 1px solid #889;
|
||||
font-weight: bold;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.calendar td.time .ampm {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.calendar td.time .colon {
|
||||
padding: 0px 2px 0px 3px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.calendar td.time span.hilite {
|
||||
border-color: #000;
|
||||
background-color: #667;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.calendar td.time span.active {
|
||||
border-color: #f00;
|
||||
background-color: #000;
|
||||
color: #0f0;
|
||||
}
|
BIN
application/media/css/dhtml.menuarrow.gif
Normal file
After Width: | Height: | Size: 68 B |
102
application/media/css/html5reset-1.6.1.css
Normal file
@ -0,0 +1,102 @@
|
||||
/*
|
||||
html5doctor.com Reset Stylesheet
|
||||
v1.6.1
|
||||
Last Updated: 2010-09-17
|
||||
Author: Richard Clark - http://richclarkdesign.com
|
||||
Twitter: @rich_clark
|
||||
*/
|
||||
|
||||
html, body, div, span, object, iframe,
|
||||
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||
abbr, address, cite, code,
|
||||
del, dfn, em, img, ins, kbd, q, samp,
|
||||
small, strong, sub, sup, var,
|
||||
b, i,
|
||||
dl, dt, dd, ol, ul, li,
|
||||
fieldset, form, label, legend,
|
||||
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||
article, aside, canvas, details, figcaption, figure,
|
||||
footer, header, hgroup, menu, nav, section, summary,
|
||||
time, mark, audio, video {
|
||||
margin:0;
|
||||
padding:0;
|
||||
border:0;
|
||||
outline:0;
|
||||
font-size:100%;
|
||||
vertical-align:baseline;
|
||||
background:transparent;
|
||||
}
|
||||
|
||||
body {
|
||||
line-height:1;
|
||||
}
|
||||
|
||||
article,aside,details,figcaption,figure,
|
||||
footer,header,hgroup,menu,nav,section {
|
||||
display:block;
|
||||
}
|
||||
|
||||
nav ul {
|
||||
list-style:none;
|
||||
}
|
||||
|
||||
blockquote, q {
|
||||
quotes:none;
|
||||
}
|
||||
|
||||
blockquote:before, blockquote:after,
|
||||
q:before, q:after {
|
||||
content:'';
|
||||
content:none;
|
||||
}
|
||||
|
||||
a {
|
||||
margin:0;
|
||||
padding:0;
|
||||
font-size:100%;
|
||||
vertical-align:baseline;
|
||||
background:transparent;
|
||||
}
|
||||
|
||||
/* change colours to suit your needs */
|
||||
ins {
|
||||
background-color:#ff9;
|
||||
color:#000;
|
||||
text-decoration:none;
|
||||
}
|
||||
|
||||
/* change colours to suit your needs */
|
||||
mark {
|
||||
background-color:#ff9;
|
||||
color:#000;
|
||||
font-style:italic;
|
||||
font-weight:bold;
|
||||
}
|
||||
|
||||
del {
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
abbr[title], dfn[title] {
|
||||
border-bottom:1px dotted;
|
||||
cursor:help;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse:collapse;
|
||||
border-spacing:0;
|
||||
}
|
||||
|
||||
/* change border colour to suit your needs */
|
||||
hr {
|
||||
display:block;
|
||||
height:1px;
|
||||
border:0;
|
||||
border-top:1px solid #cccccc;
|
||||
margin:1em 0;
|
||||
padding:0;
|
||||
}
|
||||
|
||||
input, select {
|
||||
vertical-align:middle;
|
||||
}
|
92
application/media/css/jquery.gritter.css
Normal file
@ -0,0 +1,92 @@
|
||||
/* ie6 trash */
|
||||
* html #gritter-notice-wrapper {
|
||||
position:absolute;
|
||||
}
|
||||
* html .gritter-top {
|
||||
margin-bottom:-10px;
|
||||
}
|
||||
* html .gritter-item {
|
||||
padding-bottom:0;
|
||||
}
|
||||
* html .gritter-bottom {
|
||||
margin-bottom:0;
|
||||
}
|
||||
* html .gritter-close {
|
||||
background:url(../img/jquery.gritter-close-ie6.gif);
|
||||
width:22px;
|
||||
height:22px;
|
||||
top:7px;
|
||||
left:7px;
|
||||
}
|
||||
|
||||
/* the norm */
|
||||
#gritter-notice-wrapper {
|
||||
position:fixed;
|
||||
top:20px;
|
||||
right:20px;
|
||||
width:301px;
|
||||
z-index:9999;
|
||||
}
|
||||
.gritter-item-wrapper {
|
||||
position:relative;
|
||||
margin:0 0 10px 0;
|
||||
}
|
||||
.gritter-top {
|
||||
background:url(../img/jquery.gritter.png) no-repeat left -30px;
|
||||
height:10px;
|
||||
}
|
||||
.hover .gritter-top {
|
||||
background-position:right -30px;
|
||||
}
|
||||
.gritter-bottom {
|
||||
background:url(../img/jquery.gritter.png) no-repeat left bottom;
|
||||
height:8px;
|
||||
margin:0;
|
||||
}
|
||||
.hover .gritter-bottom {
|
||||
background-position: bottom right;
|
||||
}
|
||||
.gritter-item {
|
||||
display:block;
|
||||
background:url(../img/jquery.gritter.png) no-repeat left -40px;
|
||||
color:#eee;
|
||||
padding:2px 11px 8px 11px;
|
||||
font-size: 11px;
|
||||
font-family:verdana;
|
||||
}
|
||||
.hover .gritter-item {
|
||||
background-position:right -40px;
|
||||
}
|
||||
.gritter-item p {
|
||||
padding:0;
|
||||
margin:0;
|
||||
}
|
||||
.gritter-close {
|
||||
position:absolute;
|
||||
top:5px;
|
||||
left:3px;
|
||||
background:url(../img/jquery.gritter.png) no-repeat left top;
|
||||
cursor:pointer;
|
||||
width:30px;
|
||||
height:30px;
|
||||
}
|
||||
.gritter-title {
|
||||
font-size:14px;
|
||||
font-weight:bold;
|
||||
padding:0 0 7px 0;
|
||||
display:block;
|
||||
text-shadow:1px 1px #000; /* Not supported by IE :( */
|
||||
}
|
||||
.gritter-image {
|
||||
width:24px;
|
||||
height:24px;
|
||||
float:left;
|
||||
}
|
||||
.gritter-with-image,
|
||||
.gritter-without-image {
|
||||
padding:0 0 0px 0;
|
||||
}
|
||||
.gritter-with-image {
|
||||
width:250px;
|
||||
float:right;
|
||||
}
|
44
application/media/css/login.css
Normal file
@ -0,0 +1,44 @@
|
||||
/** Login Style Sheet **/
|
||||
|
||||
table.login {
|
||||
width: 5%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background-color: #FBFBFB;
|
||||
border: 1px solid #A0A0A0;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#login-uid {
|
||||
background: url('../img/login.user.png') no-repeat 0 1px;
|
||||
background-color: #FAFAFF;
|
||||
color: #000000;
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
#login-uid:focus {
|
||||
background-color: #F0F0FF;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
#login-uid:disabled {
|
||||
background-color: #DDDDFF;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
#login-pwd {
|
||||
background: url('../img/dialog-password.png') no-repeat 0 1px;
|
||||
background-color: #FAFAFF;
|
||||
color: #000000;
|
||||
padding-left: 24px;
|
||||
}
|
||||
|
||||
#login-pwd:focus {
|
||||
background-color: #F0F0FF;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
#login-pwd:disabled {
|
||||
background-color: #DDDDFF;
|
||||
color: #000000;
|
||||
}
|
BIN
application/media/img/address-book-new-big.png
Normal file
After Width: | Height: | Size: 3.7 KiB |
BIN
application/media/img/address-book-new.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
application/media/img/ajax-progress.gif
Normal file
After Width: | Height: | Size: 7.5 KiB |
BIN
application/media/img/bug-big.png
Normal file
After Width: | Height: | Size: 928 B |
BIN
application/media/img/calendar.png
Normal file
After Width: | Height: | Size: 478 B |
BIN
application/media/img/country/au.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
application/media/img/dialog-error-big.png
Normal file
After Width: | Height: | Size: 2.3 KiB |
BIN
application/media/img/dialog-error.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
application/media/img/dialog-information-big.png
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
application/media/img/dialog-information.png
Normal file
After Width: | Height: | Size: 1.2 KiB |