-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.jscsrc b/.jscsrc
new file mode 100644
index 0000000000..d2b6bc8860
--- /dev/null
+++ b/.jscsrc
@@ -0,0 +1,8 @@
+{
+ "preset": "crockford",
+
+ "requireCamelCaseOrUpperCaseIdentifiers": null,
+ "disallowQuotedKeysInObjects": null,
+ "requireMultipleVarDecl": null,
+ "disallowDanglingUnderscores": null
+}
diff --git a/.jshintrc b/.jshintrc
new file mode 100644
index 0000000000..e1fea28309
--- /dev/null
+++ b/.jshintrc
@@ -0,0 +1,22 @@
+{
+ "browser": true,
+ "esnext": true,
+ "expr": true,
+ "bitwise": true,
+ "camelcase": false,
+ "curly": true,
+ "eqeqeq": true,
+ "immed": true,
+ "indent": 4,
+ "jquery": true,
+ "latedef": true,
+ "newcap": true,
+ "noarg": true,
+ "node": true,
+ "nonbsp": true,
+ "quotmark": "single",
+ "strict": false,
+ "sub": false,
+ "unused": false,
+ "trailing": true
+}
diff --git a/.project b/.project
old mode 100644
new mode 100755
index 8e56b007dc..8496df2095
--- a/.project
+++ b/.project
@@ -1,6 +1,6 @@
- osqa
+ askbot
diff --git a/.pydevproject b/.pydevproject
old mode 100644
new mode 100755
index f7f3fd1ac8..2ba60488c7
--- a/.pydevproject
+++ b/.pydevproject
@@ -5,6 +5,6 @@
Defaultpython 2.6
-/osqa
+/askbot
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000..6a295432eb
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,11 @@
+language: python
+python:
+ - "2.7"
+install:
+ - python setup.py -q develop
+ - askbot-setup -n . -e2 -d data.db
+ - pip install -q -U git+git://github.com/coffin/coffin.git@master git+git://github.com/saltduck/django-followit.git@support_django1.6
+before_script:
+ - python manage.py syncdb --migrate --noinput -v0
+script:
+ - python manage.py test askbot
diff --git a/.tx/config b/.tx/config
new file mode 100644
index 0000000000..07617e7c42
--- /dev/null
+++ b/.tx/config
@@ -0,0 +1,12 @@
+[main]
+host = https://www.transifex.com
+
+[askbot.askbot-translation-part1-main]
+file_filter = askbot/locale//LC_MESSAGES/django.po
+source_file = askbot/locale/en/LC_MESSAGES/django.po
+source_lang = en
+
+[askbot.askbot-translation-part2-js]
+file_filter = askbot/locale//LC_MESSAGES/djangojs.po
+source_file = askbot/locale/en/LC_MESSAGES/djangojs.po
+source_lang = en
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000000..c4c443d72e
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,36 @@
+==============================
+Contributors to Askbot Project
+==============================
+
+This is the list of contributors to the code of Askbot project.
+The list is probably incomplete, apologies for any omissions.
+Thanks for all your help
+
+Programming and documentation
+-----------------------------
+* Mike Chen & Sailing Cai - original authors of CNPROG forum
+* Evgeny Fadeev - founder of askbot
+* `Adolfo Fitoria `_
+* Andy Knotts
+* Benoit Lavine (with Windriver Software, Inc.)
+* Jeff Madynski
+* Andrei Mamoutkine
+* Ramiro Morales (with Machinalis)
+* `NoahY `_
+* `Gael Pasgrimaud `_ (bearstech)
+* Alex Robbins (celery support)
+* `Tomasz Szynalski `_
+
+Translations
+------------
+* Mike Chen, Sailing Cai, suyu8776 - Chinese
+* Bruno Sarlo, Adolfo Fitoria - Spanish
+* Evgeny Kalinin - Russian
+* Evgeny Fadeev - English
+* Oktay Yildiz, Onur Mat, Cemre - Turkish
+* Jérôme Blondon (bearstech) - French
+* Pekka Gaiser - German
+* Pekka Järvinen - Finnish
+* Adi Robian - Romanian
+* Dario Ghilardi, Federico Poloni - Italian
+
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000000..94a9ed024d
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc.
+ 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.
+
+
+ Copyright (C)
+
+ 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 .
+
+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:
+
+ Copyright (C)
+ 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
+.
+
+ 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
+.
diff --git a/HOW_TO_DEBUG b/HOW_TO_DEBUG
deleted file mode 100644
index ba36198a9f..0000000000
--- a/HOW_TO_DEBUG
+++ /dev/null
@@ -1,39 +0,0 @@
-1) LOGGING
-Please remember that log files may contain plaintext passwords, etc.
-
-Please do not add print statements - at least do not commit them to git
-because in some environments printing to stdout causes errors
-
-Instead use python logging this way:
---------------------------------
-#somewere on top of file
-import logging
-
-#anywhere below
-logging.debug('this maybe works')
-logging.error('have big error!')
-#or even
-logging.debug('') #this will add time, line number, function and file record
-#sometimes useful record for call tracing on its own
-#etc - take a look at http://docs.python.org/library/logging.html
--------------------------------
-
-in OSQA logging is currently set up in settings_local.py.dist
-please update it if you need - in older revs logging strings have less info
-
-messages of interest can be grepped out of the log file by module/file/function name
-e.g. to take out all django_authopenid logs run:
->grep 'osqa\/django_authopenid' log/django.osqa.log | sed 's/^.*MSG: //'
-in the example above 'sed' call truncates out a long prefix
-and makes output look more meaningful
-
-2) DJANGO DEBUG TOOLBAR
-osqa works with django debug toolbar
-if debugging under apache server, check
-that debug toolbar media is loaded correctly
-if toolbar is enabled but you do not see it, possibly some Alias statement
-in apache config is wrong in your VirtualHost or elsewhere
-
-3) If you discover new debugging techniques, please add here.
-Possible areas to improve - at this point there is no SQL query logging,
-as well as request data and http header.
diff --git a/INSTALL b/INSTALL
deleted file mode 100644
index bd3ac60d59..0000000000
--- a/INSTALL
+++ /dev/null
@@ -1,314 +0,0 @@
-CONTENTS
-------------------
-A. PREREQUISITES
-B. INSTALLATION
- 1. Settings file
- 2. Database
- 3. Running OSQA in the development server
- 4. Installation under Apache/WSGI
- 5. Full text search
- 6. Email subscriptions
- 7. Sitemap
- 8. Miscellaneous
-C. CONFIGURATION PARAMETERS (settings_local.py)
-D. CUSTOMIZATION
-
-
-A. PREREQUISITES
------------------------------------------------
-0. We recommend you to use python-setuptools to install pre-requirement libraries.
-If you haven't installed it, please try to install it first.
-e.g, sudo apt-get install python-setuptools
-
-1. Python2.5/2.6, MySQL, Django v1.0/1.1
-Note: email subscription sender job requires Django 1.1, everything else works with 1.0
-Make sure mysql for python provider has been installed.
-sudo easy_install mysql-python
-
-2. Python-openid v2.2
-http://openidenabled.com/python-openid/
-sudo easy_install python-openid
-
-4. html5lib
-http://code.google.com/p/html5lib/
-Used for HTML sanitizer
-sudo easy_install html5lib
-
-5. Markdown2
-http://code.google.com/p/python-markdown2/
-sudo easy_install markdown2
-
-6. Django Debug Toolbar
-http://github.com/robhudson/django-debug-toolbar/tree/master
-
-7. djangosphinx (optional - for full text questions+answer+tag)
-http://github.com/dcramer/django-sphinx/tree/master/djangosphinx
-
-8. sphinx search engine (optional, works together with djangosphinx)
-http://sphinxsearch.com/downloads.html
-
-9. recaptcha_django
-http://code.google.com/p/recaptcha-django/
-
-10. python recaptcha module
-http://code.google.com/p/recaptcha/
-Notice that you will need to register with recaptcha.net and receive
-recaptcha public and private keys that need to be saved in your
-settings_local.py file
-
-NOTES: django_authopenid is included into OSQA code
-and is significantly modified. http://code.google.com/p/django-authopenid/
-no need to install this library
-
-B. INSTALLATION
------------------------------------------------
-0. Make sure you have all above python libraries installed.
-
- make osqa installation server-readable on Linux command might be:
- chown -R yourlogin:apache /path/to/OSQA
-
- directories templates/upfiles and log must be server writable
-
- on Linux type chmod
- chmod -R g+w /path/to/OSQA/upfiles
- chmod -R g+w /path/to/log
-
- above it is assumed that webserver runs under group named "apache"
-
-1. Settings file
-
-Copy settings_local.py.dist to settings_local.py and
-update all your settings. Check settings.py and update
-it as well if necessory.
-Section C explains configuration paramaters.
-
-2. Database
-
-Prepare your database by using the same database/account
-configuration from above.
-e.g,
-create database osqa DEFAULT CHARACTER SET UTF8 COLLATE utf8_general_ci;
-grant all on osqa.* to 'osqa'@'localhost';
-And then run "python manage.py syncdb" to synchronize your database.
-
-3. Running OSQA on the development server
-
-Run "python manage.py runserver" to startup django
-development environment.
-(Under Linux you can use command "python manage.py runserver `hostname -i`:8000",
-where you can use any other available number for the port)
-
-you might want to have DEBUG=True in the beginning of settings.py
-when using the test server
-
-4. Installation under Apache/WSGI
-
-4.1 Prepare wsgi script
-
-Make a file readable by your webserver with the following content:
-
----------
-import os
-import sys
-
-sys.path.insert(0,'/one/level/above') #insert to make sure that forum will be found
-sys.path.append('/one/level/above/OSQA') #maybe this is not necessary
-os.environ['DJANGO_SETTINGS_MODULE'] = 'OSQA.settings'
-import django.core.handlers.wsgi
-application = django.core.handlers.wsgi.WSGIHandler()
------------
-
-insert method is used for path because if the forum directory name
-is by accident the same as some other python module
-you wull see strange errors - forum won't be found even though
-it's in the python path. for example using name "test" is
-not a good idea - as there is a module with such name
-
-
-4.2 Configure webserver
-Settings below are not perfect but may be a good starting point
-
----------
-WSGISocketPrefix /path/to/socket/sock #must be readable and writable by apache
-WSGIPythonHome /usr/local #must be readable by apache
-WSGIPythonEggs /var/python/eggs #must be readable and writable by apache
-
-#NOTE: all urs below will need to be adjusted if
-#settings.FORUM_SCRIPT_ALIAS !='' (e.g. = 'forum/')
-#this allows "rooting" forum at http://example.com/forum, if you like
-
- ServerAdmin forum@example.com
- DocumentRoot /path/to/osqa-site
- ServerName example.com
-
- #run mod_wsgi process for django in daemon mode
- #this allows avoiding confused timezone settings when
- #another application runs in the same virtual host
- WSGIDaemonProcess OSQA
- WSGIProcessGroup OSQA
-
- #force all content to be served as static files
- #otherwise django will be crunching images through itself wasting time
- Alias /m/ /path/to/osqa-site/forum/skins/
- Alias /upfiles/ /path/to/osqa-site/forum/upfiles/
-
- Order deny,allow
- Allow from all
-
-
- #this is your wsgi script described in the prev section
- WSGIScriptAlias / /path/to/osqa-site/osqa.wsgi
-
- #this will force admin interface to work only
- #through https (optional)
- #"nimda" is the secret spelling of "admin" ;)
-
- RewriteEngine on
- RewriteRule /nimda(.*)$ https://example.com/nimda$1 [L,R=301]
-
- CustomLog /var/log/httpd/OSQA/access_log common
- ErrorLog /var/log/httpd/OSQA/error_log
-
-#(optional) run admin interface under https
-
- ServerAdmin forum@example.com
- DocumentRoot /path/to/osqa-site
- ServerName example.com
- SSLEngine on
- SSLCertificateFile /path/to/ssl-certificate/server.crt
- SSLCertificateKeyFile /path/to/ssl-certificate/server.key
- WSGIScriptAlias / /path/to/osqa-site/osqa.wsgi
- CustomLog /var/log/httpd/OSQA/access_log common
- ErrorLog /var/log/httpd/OSQA/error_log
- DirectoryIndex index.html
-
--------------
-
-5. Full text search (using sphinx search)
-
- Currently full text search works only with sphinx search engine
- And builtin PostgreSQL (postgres only >= 8.3???)
-
- 5.1 Instructions for Sphinx search setup
- Sphinx at this time supports only MySQL and PostgreSQL databases
- to enable this, install sphinx search engine and djangosphinx
-
- configure sphinx, sample configuration can be found in
- sphinx/sphinx.conf file usually goes somewhere in /etc tree
-
- build osqa index first time manually
-
- % indexer --config /path/to/sphinx.conf --index osqa
-
- setup cron job to rebuild index periodically with command
- your crontab entry may be something like
-
- 0 9,15,21 * * * /usr/local/bin/indexer --config /etc/sphinx/sphinx.conf --all --rotate >/dev/null 2>&1
- adjust it as necessary this one will reindex three times a day at 9am 3pm and 9pm
-
- if your forum grows very big ( good luck with that :) you'll
- need to two search indices one diff index and one main
- please refer to online sphinx search documentation for the information
- on the subject http://sphinxsearch.com/docs/
-
- in settings_local.py set
- USE_SPHINX_SEARCH=True
- adjust other settings that have SPHINX_* prefix accordingly
- remember that there must be trailing comma in parentheses for
- SHPINX_SEARCH_INDICES tuple - particlarly with just one item!
-
- in settings.py look for INSTALLED_APPS
- and uncomment #'djangosphinx',
-
-
-6. Email subscriptions
-
- This function at the moment requires Django 1.1
-
- edit paths in the file cron/send_email_alerts
- set up a cron job to call cron/send_email_alerts once or twice a day
- subscription sender may be tested manually in shell
- by calling cron/send_email_alerts
-
-7. Sitemap
-Sitemap will be available at /sitemap.xml
-e.g yoursite.com/forum/sitemap.xml
-
-google will be pinged each time question, answer or
-comment is saved or a question deleted
-
-for this to be useful - do register you sitemap with Google at
-https://www.google.com/webmasters/tools/
-
-8. Miscellaneous
-
-There are some demo scripts under sql_scripts folder,
-including badges and test accounts for CNProg.com. You
-don't need them to run your sample.
-
-C. CONFIGURATION PARAMETERS
-
-#the only parameter that needs to be touched in settings.py is
-DEBUG=False #set to True to enable debug mode
-
-#all forum parameters are set in file settings_local.py
-
-LOG_FILENAME = 'osqa.log' #where logging messages should go
-DATABASE_NAME = 'osqa' # Or path to database file if using sqlite3.
-DATABASE_USER = '' # Not used with sqlite3.
-DATABASE_PASSWORD = '' # Not used with sqlite3.
-DATABASE_ENGINE = 'mysql' #mysql, etc
-SERVER_EMAIL = ''
-DEFAULT_FROM_EMAIL = ''
-EMAIL_HOST_USER = ''
-EMAIL_HOST_PASSWORD = '' #not necessary if mailserver is run on local machine
-EMAIL_SUBJECT_PREFIX = '[OSQA] '
-EMAIL_HOST='osqa.com'
-EMAIL_PORT='25'
-EMAIL_USE_TLS=False
-TIME_ZONE = 'America/Tijuana'
-APP_TITLE = u'OSQA Q&A Forum' #title of your forum
-APP_KEYWORDS = u'OSQA,forum,community' #keywords for search engines
-APP_DESCRIPTION = u'Ask and answer questions.' #site description for searche engines
-APP_INTRO = u'
Ask and answer questions, make the world better!
' #slogan that goes to front page in logged out mode
-APP_COPYRIGHT = '' #copyright message
-
-#if you set FORUM_SCRIPT_ALIAS= 'forum/'
-#then OSQA will run at url http://example.com/forum
-#FORUM_SCRIPT_ALIAS cannot have leading slash, otherwise it can be set to anything
-FORUM_SCRIPT_ALIAS = '' #no leading slash, default = '' empty string
-
-LANGUAGE_CODE = 'en' #forum language (see language instructions on the wiki)
-EMAIL_VALIDATION = 'off' #string - on|off
-MIN_USERNAME_LENGTH = 1
-EMAIL_UNIQUE = False #if True, email addresses must be unique in all accounts
-APP_URL = 'http://osqa.com' #used by email notif system and RSS
-GOOGLE_SITEMAP_CODE = '' #code for google site crawler (look up google webmaster tools)
-GOOGLE_ANALYTICS_KEY = '' #key to enable google analytics on this site
-BOOKS_ON = False #if True - books tab will be on
-WIKI_ON = True #if False - community wiki feature is disabled
-
-#experimental - allow password login through external site
-#must implement django_authopenid/external_login.py
-#included prototype external_login works with Mediawiki
-USE_EXTERNAL_LEGACY_LOGIN = True #if false OSQA uses it's own login/password
-EXTERNAL_LEGACY_LOGIN_HOST = 'login.osqa.com'
-EXTERNAL_LEGACY_LOGIN_PORT = 80
-EXTERNAL_LEGACY_LOGIN_PROVIDER_NAME = 'OSQA'
-
-FEEDBACK_SITE_URL = None #None or url
-LOGIN_URL = '/%s%s%s' % (FORUM_SCRIPT_ALIAS,'account/','signin/')
-
-DJANGO_VERSION = 1.1 #must be either 1.0 or 1.1
-RESOURCE_REVISION=4 #increment when you update media files - clients will be forced to load new version
-
-D. Customization
-
-Other than settings_local.py the following will most likely need customization:
-* locale/*/django.po - language files that may also contain your site-specific messages
- if you want to start with english messages file - look for words like "forum" and
- "OSQA" in the msgstr lines
-* templates/header.html and templates/footer.html may contain extra links
-* templates/about.html - a place to explain for is your forum for
-* templates/faq.html - put answers to users frequent questions
-* templates/content/style/style.css - modify style sheet to add disctinctive look to your forum
diff --git a/INSTALL.pip b/INSTALL.pip
deleted file mode 100644
index 92b1c7fa20..0000000000
--- a/INSTALL.pip
+++ /dev/null
@@ -1,31 +0,0 @@
-* Install virtualenv and pip:
- easy_install virtualenv
- easy_install pip
-
-* Install MySQL:
- sudo apt-get install mysql-client mysql-server
-
-* Install sphinxsearch. See:
- [optional]
- http://sphinxsearch.com/downloads.html
- http://www.hackido.com/2009/01/install-sphinx-search-on-ubuntu.html
- git://github.com/johnl/deb-sphinx-search.git
-
-* Install a virtual environment OUTSIDE of this directory:
- pip install -E ~/env -r osqa-requirements.txt
-[there is discussion on the pinax forums about what it should be outside
-the source directory]
-
-* Notice that you will need to register with recaptcha.net and receive
- recaptcha public and private keys that need to be saved in your
- settings_local.py file
-
-* Start your environment:
- source ~/env/bin/activate
-
-* Install mysql-python into your virtualenv, because we can't
-automagically install it with pip:
- easy_install --prefix ~/env/ mysql-python
-
-For more information about why pip can't automatically install the
-MySQL driver, see this message: http://groups.google.com/group/python-virtualenv/msg/ea988085951c92b3
diff --git a/INSTALL.webfaction b/INSTALL.webfaction
deleted file mode 100644
index 401971a09e..0000000000
--- a/INSTALL.webfaction
+++ /dev/null
@@ -1,346 +0,0 @@
-Detailed instructions for installing OSQA on WebFaction
-
-Adapted from http://code.pinaxproject.com/wiki/DetailedPinaxWebfaction/
-
-Please email turian at gmail with any updates or corrections.
-
-
-Installing OSQA on Webfaction
-------------------------------------
-
-Details the steps for setting up OSQA on a Webfaction shared-hosting
-account, including email setup, using Apache2, mod_wsgi, psycopg2.
-
-If you want to search-and-replace through this file, you will need to replace:
- osqa_server [name of Webfaction application, which will be in ~/webapps/]
- osqa_static [name of Webfaction application for static media serving]
- DOMAIN.com [domain name for OSQA site]
- PORT [port number assigned by WebFaction to your mod_wsgi application]
- SITENAME [name you give the OSQA site, which will contain the apache logs]
- MYOSQA [name of the OSQA project]
- MAILBOX_USERNAME [username you give the email address]
- MAILBOX_PASSWORD [password that webfaction gives to this email username]
- OSQADATABASE_NAME [username you give the database]
- OSQADATABASE_PASSWORD [password that webfaction gives to this database]
- ~/envs/osqa [directory for the OSQA python environment, grep for 'env']
- USERNAME [your WebFaction username]
-
-Some things I'm not sure about:
-
-Here's what I don't know how to do:
- * Set up a nginx server for static media.
- * Configure sphinx search
- * Use PostgreSQL, not MySQL: http://osqa.net/question/13/can-i-use-osqa-with-postgresql
-
-
-Webfaction Control Panel
---------------------------
-
-(Note: if you sign up and pick django it will create the application
-for you, website/subdomain and associate the two for you.)
-
- If necessary, add or create any domains or subdomains you may need.
-
- https://panel.webfaction.com/domain/list/
-
- Let's call the domain DOMAIN.com.
-
- Create a new Webfaction application with a "Type:" of "mod_wsgi
- 2.5/Python2.5", naming it "osqa_server". (These instructions
- might also work with mod_wsgi 2.0, if you like.)
-
- https://panel.webfaction.com/app_/list
-
- Note the port number assigned to the mod_wsgi application. Call
- it PORT.
-
- Create a new Webfaction website which will associate the subdomain
- with the new osqa_server application. Give it name SITENAME, at least one
- domain, and set it to use the osqa_server application for the site's
- root location, "/".
-
- https://panel.webfaction.com/site/list
-
- You will need to create a database, typically one for each project
- you create. Change the type to PostgreSql and modify the name (it
- defaults to your webfaction account name) by adding an underscore
- and a project-specific identifier such as "_osqa". Before
- leaving this section of the control panel, you may wish to change
- the password.
-
- https://panel.webfaction.com/database/create
-
- Call these OSQADATABASE_NAME and OSQADATABASE_PASSWORD.
-
- Save the database password for later.
-
- [The following I haven't figured out yet]
- You will probably want to add a static media server. This is a
- Webfaction application. I created one of type "Static only (no
- .htaccess)" and with the name of "osqa_static".
-
- https://panel.webfaction.com/app_/create
-
- To configure email, you need an email mailbox. Add one here. Note
- that your mailbox password shouldn't be the same password you use
- to SSH to webfaction.
-
- https://panel.webfaction.com/mailbox/list
-
- Save the mail password for later.
- We will call the username and password MAILBOX_USERNAME and
- MAILBOX_PASSWORD, respectively.
- You might also consider adding an email address like admin@DOMAIN.com,
- here:
-
- https://panel.webfaction.com/email/list
-
-
-OSQA Software
---------------
-
- Log onto webfaction and get the code. I use my fork because I have
- a simple pip installation:
- git://github.com/turian/osqa.git
- In my situation, I keep source code in ~/utils/src, create
- virtual environments in ~/envs/osqa, and create Pinax projects in
- ~/webapps/osqa_server/projects.
-
- You will need pip + virtualenv installed:
-
- easy_install --prefix=~/utils/ pip
- easy_install --prefix=~/utils/ virtualenv
-
- cd ~/utils/src/
- git clone git://github.com/turian/osqa.git
- cd osqa
-
- # We need python2.5 to be compatible with WSGI
- python2.5 ~/utils/bin/pip install -E ~/envs/osqa -r osqa-requirements.txt
- source ~/envs/osqa/bin/activate
-
- # [Optional] If you want a MySQL database
- easy_install-2.5 --prefix ~/envs/osqa/ mysql-python
-
-Additional Software
--------------------
-
- [Note that PostgreSQL installation doesn't work for me.]
-
- You will need to install psycopg2 separately for PostgreSQL.
- Psycopg2 requires a little fiddling. Continuing to
- work in the ~/utils/src/ directory:
-
- cd ~/utils/src/
- wget http://initd.org/pub/software/psycopg/psycopg2-2.0.13.tar.gz
- tar zxf psycopg2-2.0.13.tar.gz
- cd psycopg2-2.0.13
- nano setup.cfg
-
- # edit the line reading "#pg_config=" so that it reads:
- "pg_config=/usr/local/pgsql/bin/pg_config"
-
- python2.5 setup.py build
- python2.5 setup.py install
-
-
-Create a Project
-----------------
-
- In Pinax, you clone a project from OSQA.
- However, OSQA we just copy it.
-
- cd ~/webapps/osqa_server
- mkdir projects
- cd projects
- cp -R ~/utils/src/osqa MYOSQA
- cd MYOSQA
- export OSQAPROJECT=`pwd`
-
- Make some directories, as described in the OSQA INSTALL file:
- [okay I haven't actually done this yet]
-
-# mkdir -p $OSQASITE/upfiles/
-# mkdir -p $OSQALOG
-# sudo chown -R `whoami`:www-data $OSQASITE
-# sudo chown -R `whoami`:www-data $OSQALOG
-# chmod -R g+w $OSQASITE/upfiles
-# chmod -R g+w $OSQALOG
-
-
- Edit the settings files:
-
- cd $OSQAPROJECT
- cp settings_local.py.dist settings_local.py
- vi settings_local.py settings.py
-
- Pay attention to the following settings:
-
- DATABASE_ENGINE = 'mysql'
- DATABASE_NAME = 'OSQADATABASE_NAME'
- DATABASE_USER = 'OSQADATABASE_NAME'
- DATABASE_PASSWORD = 'OSQADATABASE_PASSWORD'
-
- EMAIL_HOST='smtp.webfaction.com'
- EMAIL_HOST_USER='MAILBOX_USERNAME'
- EMAIL_HOST_PASSWORD='MAILBOX_PASSWORD'
- EMAIL_PORT='25'
- DEFAULT_FROM_EMAIL = 'MAILBOX_USERNAME@DOMAIN.com'
- SERVER_EMAIL = 'MAILBOX_USERNAME@DOMAIN.com'
- # The following setting might not be necessary, it's used in Pinax tho
- CONTACT_EMAIL = "MAILBOX_USERNAME@DOMAIN.com"
-
- APP_URL = 'http://DOMAIN.com' #used by email notif system and RSS
-
- [Later on, the install instructions should talk about]
- SERVE_MEDIA = False # [Not present, not ready yet]
-
- Create a directory for logs:
-
- cd $OSQAPROJECT
- mkdir log
-
- Modify mail cron scripts "cron/send_email_alerts" as follows:
- [Pinax has cron/emit_notices.sh, cron/retry_deferred.sh,
- cron/send_mail.sh, are these also necessary?]
-
- #!/bin/sh
-
- WORKON_HOME=~/envs/osqa
- PROJECT_ROOT=~/webapps/osqa_server/projects/MYOSQA/
-
- # activate virtual environment
- . $WORKON_HOME/bin/activate
-
- cd $PROJECT_ROOT
- python manage.py send_email_alerts >> $PROJECT_ROOT/log/cron_mail.log 2>&1
-
- Use command "crontab -e" to add this script to your cron file, to run twice a day::
-
- 1 0,12 * * * ~/webapps/osqa_server/projects/MYOSQA/cron/send_email_alerts
-
- [Configure sphinx]
-
- Create the database tables, indices, and so forth:
-
- python manage.py syncdb
-
- [Ignore the following static media steps, I haven't tried them]
- Build media directory links within the project and create symbolic
- links on the static media server.
- python manage.py build_media -all
- mkdir ~/webapps/OSQA_STATIC/MYOSQA
- ln -sd ~/webapps/osqa_server/projects/MYOSQA/site_media ~/webapps/OSQA_STATIC/MYOSQA/site_media
-
-
- Set up the badges:
-
- 1. You should run the SQL commands in:
-
- sql_scripts/badges.sql
-
- 2. Edit paths in the file `cron/multi_award_badges`. (This
- file doesn't yet exist in the git repositories, so just
- copy `cron/send_email_alerts` and make sure the command
- `multi_award_badges` is executed.)
-
- 3. Run `cron/multi_award_badges` to make sure it works okay.
-
- 4. Use `crontab -e` to call `cron/multi_award_badges` maybe
- four times an hour.
-
- 4,19,34,49 * * * * ~/webapps/osqa_server/projects/MYOSQA/cron/multi_award_badges
-
- 5. Repeat steps 1-4 for `cron/once_award_badges`.
-
-
-Configure Apache2
-----------------
-
- Edit ~/webapps/osqa_server/apache2/conf/httpd.conf as follows::
-
- ServerAdmin "MAILBOX_USERNAME@DOMAIN.com"
- ServerRoot "/home/USERNAME/webapps/osqa_server/apache2"
- ServerName DOMAIN.com
-
- LoadModule dir_module modules/mod_dir.so
- LoadModule env_module modules/mod_env.so
- #LoadModule setenvif_module modules/mod_setenvif.so
- LoadModule log_config_module modules/mod_log_config.so
- LoadModule mime_module modules/mod_mime.so
- LoadModule rewrite_module modules/mod_rewrite.so
- LoadModule wsgi_module modules/mod_wsgi.so
-
- KeepAlive Off
- Listen PORT
- LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
- CustomLog /home/USERNAME/logs/user/access_osqa_server_log combined
- ErrorLog /home/USERNAME/logs/user/error_osqa_server_log
- ServerLimit 2
-
- #SetEnvIf X-Forwarded-SSL on HTTPS=1
-
- WSGIPythonPath /home/USERNAME/envs/osqa/lib/python2.5/site-packages/
- WSGIScriptAlias / /home/USERNAME/webapps/osqa_server/projects/MYOSQA/osqa.wsgi
-
- LoadModule alias_module modules/mod_alias.so
- WSGIDaemonProcess osqaWSGI user=USERNAME group=USERNAME threads=25 python-path=/home/USERNAME/envs/osqa/lib/python2.5/site-packages
- WSGIProcessGroup osqaWSGI
-
- NameVirtualHost 127.0.0.1:PORT
-
- #ErrorLog "logs/MYOSQA_2009_05_06.log"
- SetHandler none
- #Alias /site_media /home/USERNAME/webapps/static/MYOSQA/site_media
-
- #force all content to be served as static files
- #otherwise django will be crunching images through itself wasting time
- Alias /content/ /home/USERNAME/webapps/osqa_server/projects/MYOSQA/templates/content/
- Alias /forum/admin/media/ /home/turian/envs/osqa/lib/python2.5/site-packages/django/contrib/admin/media/
- #AliasMatch /([^/]*\.css) /home/USERNAME/webapps/osqa_server/projects/MYOSQA/templates/content/style/$1
-
- # Order deny,allow
- # Allow from all
-
-
- If you want virtual hosts of the admin interface under HTTPS, please
- look at OSQA's install file.
-
- Create osqa.wsgi and edit it:
- cp osqa.wsgi.dist osqa.wsgi
-
- Edit ~/webapps/osqa_server/projects/MYOSQA/deploy/osqa.wsgi as follows::
-
- import os
- import sys
-
- # redirect sys.stdout to sys.stderr for bad libraries like geopy that uses
- # print statements for optional import exceptions.
- sys.stdout = sys.stderr
-
- from os.path import abspath, dirname, join
- from site import addsitedir
-
- # add the virtual environment site-packages to the path
- from site import addsitedir
- addsitedir('/home/USERNAME/envs/osqa/lib/python2.5/site-packages')
-
- sys.path.insert(0, abspath(join(dirname(__file__), "../")))
- sys.path.append(abspath(dirname(__file__)))
-
- from django.conf import settings
- os.environ["DJANGO_SETTINGS_MODULE"] = "MYOSQA.settings"
-
- #print sys.path
-
- from django.core.handlers.wsgi import WSGIHandler
- application = WSGIHandler()
-
-And then you're up and running with:
-
- ~/webapps/osqa_server/apache2/bin/stop
- ~/webapps/osqa_server/apache2/bin/start
-
-You should log in to the admin interface (http://DOMAIN.com/admin/),
-and go to "Sites > Sites", and change the domain name that is used in
-all emails.
diff --git a/LICENSE b/LICENSE
index 803781c551..a27b35fd2d 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,10 @@
-Copyright (C) 2009. Chen Gang
+Askbot - Django Q&A forum application.
+Copyright (C) 2009. Chen Gang and Sailing Cai.
+2009-2011 Evgeny Fadeev and individual contributors of Askbot project (see AUTHORS).
+All rights reserved.
+
+LICENSE
+=======
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
@@ -12,3 +18,32 @@ 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 .
+
+
+TRADEMARKS
+==========
+Some of the files in askbot/media/images/jquery-openid/ are protected
+trademarks. Licenses for those follow here:
+
+
+Fedora
+------
+
+Limited permission to use and redistribute the Fedora logo is permitted
+with the following restrictions:
+
+* The Fedora logo must not be modified in any way.
+* The Fedora logo must only be used to refer to the Fedora OpenID provider.
+
+In all other regards, the Fedora Trademark Guidelines apply to the
+Fedora logo:
+
+https://fedoraproject.org/wiki/Legal:Trademark_guidelines
+
+Fedora®, the Fedora word design, the Infinity design logo, Fedora Remix,
+and the Fedora Remix word design, either separately or in combination,
+are hereinafter referred to as "Fedora Trademarks" and are trademarks of
+Red Hat, Inc. Except as provided in this license, you may not use the
+Fedora Trademarks in any other manner that might cause confusion in the
+marketplace, or imply endorsement of Fedora or Red Hat, Inc for any
+products or services.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000000..3df8a0db93
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,35 @@
+include ez_setup.py
+include tox.ini
+include LICENSE
+include AUTHORS
+include COPYING
+include README.rst
+include askbot_requirements.txt
+recursive-include askbot *
+recursive-exclude askbot *.pyc
+recursive-exclude .git
+prune dist
+prune tmp
+prune build
+prune static
+prune django
+prune lamson
+exclude db
+exclude lint
+exclude settings.py
+exclude manage.py
+exclude __init__.py
+exclude urls.py
+exclude rebuild-locales.pl
+exclude askbot/upfiles/*.*
+exclude askbot/upfiles/avatars/*
+recursive-exclude askbot/doc/build/*
+recursive-exclude avatar *
+recursive-exclude adzone *
+recursive-exclude custom_settings *
+recursive-exclude custom *
+recursive-exclude follow *
+recursive-exclude categories *
+recursive-exclude follow *
+recursive-exclude env *
+recursive-exclude .tox
diff --git a/PENDING b/PENDING
deleted file mode 100644
index 2931303c59..0000000000
--- a/PENDING
+++ /dev/null
@@ -1,28 +0,0 @@
-There are two kinds of things that can be done:
-refactorings (think of jogging in the morning, going to a spa, well make the code better :)
-new features (go to law school, get a job, do something real)
-Just a joke - pick yourself a task and work on it.
-
-==Refactoring==
-* validate HTML
-* set up loading of default settings from inside the /forum dir
-* automatic dependency checking for modules
-* propose how to rename directory forum --> osqa
- without breaking things and keeping name of the project root
- named the same way - osqa
-
-==New features==
-Whoever wants - pick a feature from the WISH_LIST
-add it here and start working on it
-If you are not starting immediately - leave it on the wishlist :)
-
-==Notes==
-1)after this is done most new suggested features
- may be worked on easily since most of them
- only require editing view functions and templates
-
- However, anyone can work on new features anyway - you'll
- just have to probably copy-paste your code into
- the branch undergoing refactoring which involves
- splitting the files. Auto merging across split points
- is harder or impossible.
diff --git a/README b/README
deleted file mode 100644
index e9411648c0..0000000000
--- a/README
+++ /dev/null
@@ -1,10 +0,0 @@
-This is OSQA project - open source Q&A system
-
-Project Q&A site - http://meta.osqa.net
-Homepage - http://www.osqa.net
-MASTER devel. code - http://github.com/OSQA/osqa/
-Bug tracking - http://jira.osqa.net (bugs can be also at http://meta.osqa.net too)
-Wiki - http://wiki.osqa.net
-
-OSQA is based on the CNPROG project, originally created by Mike Chen and Sailing Cai.
-
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000000..8ffd9f735a
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,46 @@
+===================
+Askbot - Q&A forum
+===================
+
+This is Askbot project - open source Q&A system, like StackOverflow, Yahoo Answers and some others.
+Askbot is based on code of CNPROG, originally created by Mike Chen
+and Sailing Cai and some code written for OSQA.
+
+Demos and hosting are available at http://askbot.com.
+
+Branch `0.7.x` - is the latest version supporting Django 1.5
+
+Branch `0.8.x` - transitional version for the upgrade of the database to Django 1.7
+
+Branch `master` supports Django 1.7
+
+How to contribute
+=================
+
+**Translators: DO NOT use git to contribute translations!!!** instead - translate at https://www.transifex.com/projects/p/askbot/.
+
+All documentation is in the directory askbot/doc
+
+To contribute code, please fork and make pull requests.
+
+If you are planning to add a new feature, please bring it up for discussion at our forum
+(http://askbot.org/en/questions/) and mention that you are willing to develop this feature.
+
+We will merge obvious bug fixes without questions, for more complex fixes
+please add a test case that fails before and passes after applying your fix.
+
+**Notes on using git for Askbot.** Please use topic branches only - one per feature or bugfix.
+Do not add multiple features and fixes into the same branch -
+those are much harder to understand and merge.
+
+Follow https://help.github.com/articles/fork-a-repo to to learn how to use
+`fetch` and `push` as well as other help on using git.
+
+License, copyright and trademarks
+=================================
+Askbot software is licensed under GPL, version 3.
+
+Copyright Askbot S.p.A and the project contributors, 2010-2015.
+
+"Askbot" is a trademark and service mark registered in the United States, number 4323777.
+
diff --git a/ROADMAP.rst b/ROADMAP.rst
deleted file mode 100644
index 42f2e8c6ed..0000000000
--- a/ROADMAP.rst
+++ /dev/null
@@ -1,32 +0,0 @@
-This document is a map for our activities down the road - therefore ROADMAP.
-ROADMAP does not specify deadlines - those belong to the PENDING file
-
-Intro
-=========
-ROADMAP aims to streamline activities of the OSQA open source project and
-to minimize ad-hoc approaches of "big-picture" level.
-
-With one exception: under extreme time pressure improvised approaches are perfectly acceptable.
-
-Items in this document must be discussed in public via dev@osqa.net
-
-Architecture
-=============
-
-Sub-systems
------------------
-* authentication system
-* Q&A system
-
-Authentication system
--------------------------
-* MUST authenticate people visiting the website via web browsers.
-* Upon successful authentication must associates the visitor with
- his/her Django system user account
-* MUST allow multiple methods of authentication to the same account
-* MUST support a method to recover lost authentication link by email
-* MAY offer an option to "soft-validate" user's email (send a link
- with a special key, so that user clicks and we know that email is valid)
- "soft" - meaning that lack of validation won't block people
- from using the site
-
diff --git a/WISH_LIST b/WISH_LIST
deleted file mode 100644
index 3df3c3075f..0000000000
--- a/WISH_LIST
+++ /dev/null
@@ -1,24 +0,0 @@
-* The wonder bar (integrated the search / ask functionality)
-* The authentication system ???
-* allow multiple logins to the same account
-* allow multiple logins to the same account
-* more advanced templating/skinning system
-* per-tag email subscriptions
-* view for personalized news on the site
-* a little flag popping when there are news
-* drill-down mode for navigation by tags
-* improved admin console
-* sort out mess with profile - currently we patch django User
-
-* Some functionality should be moved out of the forums app, in the case
-that the forum app is restricted only to authenticated users:
-
- (r'^%s/$' % _('signin/'), 'django_authopenid.views.signin'),
- url(r'^%s$' % _('about/'), app.about, name='about'),
- url(r'^%s$' % _('faq/'), app.faq, name='faq'),
- url(r'^%s$' % _('privacy/'), app.privacy, name='privacy'),
- url(r'^%s$' % _('logout/'), app.logout, name='logout'),
- url(r'^%s$' % _('feedback/'), app.feedback, name='feedback'),
- (r'^%sfb/' % _('account/'), include('fbconnect.urls')),
- (r'^%s' % _('account/'), include('django_authopenid.urls')),
-
diff --git a/askbot/__init__.py b/askbot/__init__.py
new file mode 100644
index 0000000000..e7f4c0fcee
--- /dev/null
+++ b/askbot/__init__.py
@@ -0,0 +1,106 @@
+"""
+:synopsis: the Django Q&A forum application
+
+Functions in the askbot module perform various
+basic actions on behalf of the forum application
+"""
+import os
+import platform
+
+VERSION = (0, 10, 0)
+
+default_app_config = 'askbot.apps.AskbotConfig'
+
+#keys are module names used by python imports,
+#values - the package qualifier to use for pip
+REQUIREMENTS = {
+ 'akismet': 'akismet',
+ 'avatar': 'django-avatar>=2.0',
+ 'bs4': 'beautifulsoup4',
+ 'coffin': 'Coffin>=0.3,<=0.3.8',
+ 'compressor': 'django-compressor>=1.3,<=1.5',
+ 'django': 'django>=1.7,<1.9',
+ 'django_countries': 'django-countries==3.3',
+ 'djcelery': 'django-celery>=3.0.11',
+ 'djkombu': 'django-kombu==0.9.4',
+ 'followit': 'django-followit==0.2.0',
+ 'html5lib': 'html5lib==0.90',
+ 'jinja2': 'Jinja2>=2.8',
+ 'jsonfield': 'jsonfield',
+ 'jwt': 'pyjwt',
+ 'keyedcache': 'django-keyedcache',
+ 'markdown2': 'markdown2',
+ 'mock': 'mock==1.0.1',
+ 'oauth2': 'oauth2',
+ 'openid': 'python-openid',
+ 'picklefield': 'django-picklefield==0.3.0',
+ 'pystache': 'pystache==0.3.1',
+ 'pytz': 'pytz',
+ 'captcha': 'django-recaptcha>=1.0.3',
+ 'requirements': 'requirements-parser',
+ 'robots': 'django-robots==1.1',
+ 'sanction': 'sanction==0.3.1',
+ 'simplejson': 'simplejson',
+ 'threaded_multihost': 'django-threaded-multihost',
+ 'tinymce': 'django-tinymce==1.5.3',
+ 'unidecode': 'unidecode',
+ #'stopforumspam': 'stopforumspam'
+}
+
+if platform.system() != 'Windows':
+ REQUIREMENTS['lamson'] = 'Lamson'
+
+#necessary for interoperability of django and coffin
+try:
+ from askbot import patches
+ from askbot.deployment.assertions import assert_package_compatibility
+ assert_package_compatibility()
+ patches.patch_django()
+ patches.patch_coffin() # must go after django
+except ImportError:
+ pass
+
+
+def get_install_directory():
+ """returns path to directory
+ where code of the askbot django application
+ is installed
+ """
+ return os.path.dirname(__file__)
+
+
+def get_path_to(relative_path):
+ """returns absolute path to a file
+ relative to ``askbot`` directory
+ ``relative_path`` must use only forward slashes
+ and must not start with a slash
+ """
+ root_dir = get_install_directory()
+ assert(relative_path[0] != 0)
+ path_bits = relative_path.split('/')
+ return os.path.join(root_dir, *path_bits)
+
+
+def get_version():
+ """returns version of the askbot app
+ this version is meaningful for pypi only
+ """
+ return '.'.join([str(subversion) for subversion in VERSION])
+
+
+def get_database_engine_name():
+ """returns name of the database engine,
+ independently of the version of django
+ - for django >=1.2 looks into ``settings.DATABASES['default']``,
+ (i.e. assumes that askbot uses database named 'default')
+ , and for django 1.1 and below returns settings.DATABASE_ENGINE
+ """
+ import django
+ from django.conf import settings as django_settings
+ major_version = django.VERSION[0]
+ minor_version = django.VERSION[1]
+ if major_version == 1:
+ if minor_version > 1:
+ return django_settings.DATABASES['default']['ENGINE']
+ else:
+ return django_settings.DATABASE_ENGINE
diff --git a/askbot/admin.py b/askbot/admin.py
new file mode 100644
index 0000000000..7a43bffc5d
--- /dev/null
+++ b/askbot/admin.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+"""
+:synopsis: connector to standard Django admin interface
+
+To make more models accessible in the Django admin interface, add more classes subclassing ``django.contrib.admin.Model``
+
+Names of the classes must be like `SomeModelAdmin`, where `SomeModel` must
+exactly match name of the model used in the project
+"""
+from django.contrib import admin
+from askbot import models
+
+class AnonymousQuestionAdmin(admin.ModelAdmin):
+ """AnonymousQuestion admin class"""
+
+class TagAdmin(admin.ModelAdmin):
+ """Tag admin class"""
+
+class VoteAdmin(admin.ModelAdmin):
+ """ admin class"""
+
+class FavoriteQuestionAdmin(admin.ModelAdmin):
+ """ admin class"""
+
+class PostRevisionAdmin(admin.ModelAdmin):
+ """ admin class"""
+
+class AwardAdmin(admin.ModelAdmin):
+ """ admin class"""
+
+class ReputeAdmin(admin.ModelAdmin):
+ """ admin class"""
+
+class ActivityAdmin(admin.ModelAdmin):
+ """ admin class"""
+
+class BadgeDataAdmin(admin.ModelAdmin):
+ """admin class for BadgeData"""
+admin.site.register(models.BadgeData)
+
+admin.site.register(models.Post)
+admin.site.register(models.Tag, TagAdmin)
+admin.site.register(models.Vote, VoteAdmin)
+admin.site.register(models.FavoriteQuestion, FavoriteQuestionAdmin)
+admin.site.register(models.PostRevision, PostRevisionAdmin)
+admin.site.register(models.Award, AwardAdmin)
+admin.site.register(models.Repute, ReputeAdmin)
+admin.site.register(models.Activity, ActivityAdmin)
+admin.site.register(models.BulkTagSubscription)
diff --git a/askbot/api.py b/askbot/api.py
new file mode 100644
index 0000000000..c36528cd6a
--- /dev/null
+++ b/askbot/api.py
@@ -0,0 +1,68 @@
+"""place for the API calls into askbot
+at this point most of the useful functions are still
+in the askbot.models module, but
+api must become a place to manupulate the data in the askbot application
+so that other implementations of the data storage could be possible
+"""
+from django.db.models import Q
+from askbot import models
+from askbot import const
+
+def get_info_on_moderation_items(user):
+ """returns a dictionary with
+ counts of new and seen moderation items for a given user
+ if user is not a moderator or admin, returns None
+ """
+ if user.is_anonymous():
+ return None
+ if not(user.is_moderator() or user.is_administrator()):
+ return None
+
+ content_types = (
+ const.TYPE_ACTIVITY_MARK_OFFENSIVE,
+ const.TYPE_ACTIVITY_MODERATED_NEW_POST,
+ const.TYPE_ACTIVITY_MODERATED_POST_EDIT,
+ )
+
+ messages = models.ActivityAuditStatus.objects.filter(
+ activity__activity_type__in = content_types,
+ user = user
+ )
+
+ seen_count = messages.filter(
+ status = models.ActivityAuditStatus.STATUS_SEEN
+ ).count()
+ new_count = messages.filter(
+ status = models.ActivityAuditStatus.STATUS_NEW
+ ).count()
+ return {
+ 'seen_count': seen_count,
+ 'new_count': new_count
+ }
+
+def get_admin(seed_user_id=None):
+ """returns user objects with id == seed_user_id
+ if the user with that id is not an administrator,
+ the function will try to find another admin or moderator
+ who has the smallest user id
+
+ if the user is not found, or there are no moderators/admins
+ User.DoesNotExist will be raised
+
+ The reason this function is here and not on a manager of
+ the user object is because we still patch the django-auth User table
+ and it's probably better not to patch the manager
+ """
+ if seed_user_id:
+ user = models.User.objects.get(id=seed_user_id)#let it raise error here
+ if user.is_administrator() or user.is_moderator():
+ return user
+ try:
+ return models.User.objects.filter(
+ Q(is_superuser=True) | Q(askbot_profile__status__in=('m', 'd'))
+ ).order_by('id')[0]
+ except IndexError:
+ raise models.User.DoesNotExist(
+ """Please add a moderator or an administrator to the forum first
+ there don't seem to be any"""
+ )
diff --git a/askbot/apps.py b/askbot/apps.py
new file mode 100644
index 0000000000..aee575faa6
--- /dev/null
+++ b/askbot/apps.py
@@ -0,0 +1,17 @@
+from django.apps import AppConfig
+from django.contrib.auth import get_user_model
+
+class AskbotConfig(AppConfig):
+ name = 'askbot'
+ verbose_name = 'Askbot Q&A platform'
+
+ def ready(self):
+ from askbot.models import badges
+ try:
+ badges.init_badges()
+ except:
+ pass
+
+ import followit
+ user_model = get_user_model()
+ followit.register(user_model)
diff --git a/askbot/auth.py b/askbot/auth.py
new file mode 100644
index 0000000000..e8f272c70d
--- /dev/null
+++ b/askbot/auth.py
@@ -0,0 +1,433 @@
+"""
+Authorisation related functions.
+
+This entire module will be removed some time in
+the future
+
+Many of these functions are being replaced with assertions:
+User.assert_can...
+"""
+from django.db import transaction
+from django.utils import timezone
+from askbot.models import Repute
+#from askbot.models import Answer
+from askbot import signals
+from askbot.conf import settings as askbot_settings
+
+###########################################
+## actions and reputation changes event
+###########################################
+@transaction.atomic
+def onFlaggedItem(post, user, timestamp=None):
+ if timestamp is None:
+ timestamp = timezone.now()
+
+ post.offensive_flag_count = post.offensive_flag_count + 1
+ post.save()
+
+ flagged_user = post.author
+
+ flagged_user.receive_reputation(
+ askbot_settings.REP_LOSS_FOR_RECEIVING_FLAG
+ )
+ flagged_user.save()
+
+ question = post.thread._question_post()
+
+ reputation = Repute(
+ user=flagged_user,
+ negative=askbot_settings.REP_LOSS_FOR_RECEIVING_FLAG,
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=-4,#todo: clean up magic number
+ reputation=flagged_user.reputation
+ )
+ reputation.save()
+
+ signals.flag_offensive.send(
+ sender=post.__class__,
+ instance=post,
+ mark_by=user
+ )
+
+ if post.post_type == 'comment':
+ #do not hide or delete comments automatically yet,
+ #because there is no .deleted field in the comment model
+ return
+
+ #todo: These should be updated to work on same revisions.
+ if post.offensive_flag_count == askbot_settings.MIN_FLAGS_TO_HIDE_POST:
+ #todo: strange - are we supposed to hide the post here or the name of
+ #setting is incorrect?
+ flagged_user.receive_reputation(
+ askbot_settings.REP_LOSS_FOR_RECEIVING_THREE_FLAGS_PER_REVISION
+ )
+
+ flagged_user.save()
+
+ reputation = Repute(
+ user=flagged_user,
+ negative=\
+ askbot_settings.REP_LOSS_FOR_RECEIVING_THREE_FLAGS_PER_REVISION,
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=-6,
+ reputation=flagged_user.reputation
+ )
+ reputation.save()
+
+ elif post.offensive_flag_count == askbot_settings.MIN_FLAGS_TO_DELETE_POST:
+ flagged_user.receive_reputation(
+ askbot_settings.REP_LOSS_FOR_RECEIVING_FIVE_FLAGS_PER_REVISION
+ )
+
+ flagged_user.save()
+
+ reputation = Repute(
+ user=flagged_user,
+ negative=\
+ askbot_settings.REP_LOSS_FOR_RECEIVING_FIVE_FLAGS_PER_REVISION,
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=-7,
+ reputation=flagged_user.reputation
+ )
+ reputation.save()
+
+ post.deleted = True
+ #post.deleted_at = timestamp
+ #post.deleted_by = Admin
+ post.save()
+
+ signals.after_post_removed.send(
+ sender=post.__class__,
+ instance=post,
+ deleted_by=user,
+ )
+
+
+@transaction.atomic
+def onUnFlaggedItem(post, user, timestamp=None):
+ if timestamp is None:
+ timestamp = timezone.now()
+
+ post.offensive_flag_count = post.offensive_flag_count - 1
+ post.save()
+
+ flagged_user = post.author
+
+ flagged_user.receive_reputation(
+ -askbot_settings.REP_LOSS_FOR_RECEIVING_FLAG #negative of a negative
+ )
+ flagged_user.save()
+
+ question = post.thread._question_post()
+
+ reputation = Repute(
+ user=flagged_user,
+ positive=abs(askbot_settings.REP_LOSS_FOR_RECEIVING_FLAG),
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=-4,#todo: clean up magic number
+ reputation=flagged_user.reputation
+ )
+ reputation.save()
+
+ signals.remove_flag_offensive.send(
+ sender=post.__class__,
+ instance=post,
+ mark_by=user
+ )
+
+ if post.post_type == 'comment':
+ #do not hide or delete comments automatically yet,
+ #because there is no .deleted field in the comment model
+ return
+
+ #todo: These should be updated to work on same revisions.
+ # The post fell below HIDE treshold - unhide it.
+ if post.offensive_flag_count == askbot_settings.MIN_FLAGS_TO_HIDE_POST - 1:
+ #todo: strange - are we supposed to hide the post here or the name of
+ #setting is incorrect?
+ flagged_user.receive_reputation(
+ -askbot_settings.REP_LOSS_FOR_RECEIVING_THREE_FLAGS_PER_REVISION
+ )
+
+ flagged_user.save()
+
+ reputation = Repute(
+ user=flagged_user,
+ positive=\
+ abs(askbot_settings.REP_LOSS_FOR_RECEIVING_THREE_FLAGS_PER_REVISION),
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=-6,
+ reputation=flagged_user.reputation
+ )
+ reputation.save()
+ # The post fell below DELETE treshold, undelete it
+ elif post.offensive_flag_count == askbot_settings.MIN_FLAGS_TO_DELETE_POST-1 :
+ flagged_user.receive_reputation(
+ -askbot_settings.REP_LOSS_FOR_RECEIVING_FIVE_FLAGS_PER_REVISION
+ )
+
+ flagged_user.save()
+
+ reputation = Repute(
+ user=flagged_user,
+ positive =\
+ abs(askbot_settings.REP_LOSS_FOR_RECEIVING_FIVE_FLAGS_PER_REVISION),
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=-7,
+ reputation=flagged_user.reputation
+ )
+ reputation.save()
+
+ post.deleted = False
+ post.save()
+
+ signals.after_post_restored.send(
+ sender=post.__class__,
+ instance=post,
+ restored_by=user,
+ )
+
+
+@transaction.atomic
+def onAnswerAccept(answer, user, timestamp=None):
+ answer.thread.set_accepted_answer(
+ answer=answer,
+ actor=user,
+ timestamp=timestamp
+ )
+ question = answer.thread._question_post()
+
+ if answer.author != user:
+ answer.author.receive_reputation(
+ askbot_settings.REP_GAIN_FOR_RECEIVING_ANSWER_ACCEPTANCE
+ )
+ answer.author.save()
+ reputation = Repute(user=answer.author,
+ positive=abs(askbot_settings.REP_GAIN_FOR_RECEIVING_ANSWER_ACCEPTANCE),
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=2,
+ reputation=answer.author.reputation)
+ reputation.save()
+
+ if answer.author_id == question.author_id and user.pk == question.author_id:
+ #a plug to prevent reputation gaming by posting a question
+ #then answering and accepting as best all by the same person
+ return
+
+ user.receive_reputation(askbot_settings.REP_GAIN_FOR_ACCEPTING_ANSWER)
+ user.save()
+ reputation = Repute(user=user,
+ positive=askbot_settings.REP_GAIN_FOR_ACCEPTING_ANSWER,
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=3,
+ reputation=user.reputation)
+ reputation.save()
+
+@transaction.atomic
+def onAnswerAcceptCanceled(answer, user, timestamp=None):
+ if timestamp is None:
+ timestamp = timezone.now()
+
+ answer.endorsed = False
+ answer.endorsed_by = None
+ answer.endorsed_at = None
+ answer.save()
+
+ answer.thread.accepted_answer = None
+ answer.thread.save()
+
+ question = answer.thread._question_post()
+
+ if user != answer.author:
+ answer.author.receive_reputation(
+ -askbot_settings.REP_GAIN_FOR_RECEIVING_ANSWER_ACCEPTANCE
+ )
+ answer.author.save()
+ reputation = Repute(
+ user=answer.author,
+ negative=\
+ -askbot_settings.REP_GAIN_FOR_RECEIVING_ANSWER_ACCEPTANCE,
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=-2,
+ reputation=answer.author.reputation
+ )
+ reputation.save()
+
+ if answer.author_id == question.author_id and user.pk == question.author_id:
+ #a symmettric measure for the reputation gaming plug
+ #as in the onAnswerAccept function
+ #here it protects the user from uwanted reputation loss
+ return
+
+ user.receive_reputation(
+ -askbot_settings.REP_GAIN_FOR_ACCEPTING_ANSWER,
+ )
+ user.save()
+ reputation = Repute(user=user,
+ negative=-askbot_settings.REP_GAIN_FOR_ACCEPTING_ANSWER,
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=-1,
+ reputation=user.reputation)
+ reputation.save()
+
+@transaction.atomic
+def onUpVoted(vote, post, user, timestamp=None):
+ if timestamp is None:
+ timestamp = timezone.now()
+ vote.save()
+
+ if post.post_type != 'comment':
+ post.vote_up_count = int(post.vote_up_count) + 1
+ post.points = int(post.points) + 1
+ post.save()
+
+ if post.post_type == 'comment':
+ #reputation is not affected by the comment votes
+ return
+
+ if not (post.wiki or post.is_anonymous):
+ author = post.author
+ todays_rep_gain = Repute.objects.get_reputation_by_upvoted_today(author)
+ if todays_rep_gain < askbot_settings.MAX_REP_GAIN_PER_USER_PER_DAY:
+ author.receive_reputation(
+ askbot_settings.REP_GAIN_FOR_RECEIVING_UPVOTE
+ )
+ author.save()
+
+ question = post.thread._question_post() # TODO: this is suboptimal if post is already a question
+
+ reputation = Repute(user=author,
+ positive=askbot_settings.REP_GAIN_FOR_RECEIVING_UPVOTE,
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=1,
+ reputation=author.reputation)
+ reputation.save()
+
+@transaction.atomic
+def onUpVotedCanceled(vote, post, user, timestamp=None):
+ if timestamp is None:
+ timestamp = timezone.now()
+ vote.delete()
+
+ if post.post_type != 'comment':
+ post.vote_up_count = int(post.vote_up_count) - 1
+ if post.vote_up_count < 0:
+ post.vote_up_count = 0
+
+ post.points = int(post.points) - 1
+ post.save()
+
+ if post.post_type == 'comment':
+ #comment votes do not affect reputation
+ return
+
+ if not (post.wiki or post.is_anonymous):
+ author = post.author
+ author.receive_reputation(
+ -askbot_settings.REP_GAIN_FOR_RECEIVING_UPVOTE
+ )
+ author.save()
+
+ question = post.thread._question_post() # TODO: this is suboptimal if post is already a question
+
+ reputation = Repute(
+ user=author,
+ negative=-askbot_settings.REP_GAIN_FOR_RECEIVING_UPVOTE,
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=-8,
+ reputation=author.reputation
+ )
+ reputation.save()
+
+@transaction.atomic
+def onDownVoted(vote, post, user, timestamp=None):
+ if timestamp is None:
+ timestamp = timezone.now()
+ vote.save()
+
+ post.vote_down_count = int(post.vote_down_count) + 1
+ post.points = int(post.points) - 1
+ post.save()
+
+ if not (post.wiki or post.is_anonymous):
+ author = post.author
+ author.receive_reputation(
+ askbot_settings.REP_LOSS_FOR_RECEIVING_DOWNVOTE
+ )
+ author.save()
+
+ question = post.thread._question_post() # TODO: this is suboptimal if post is already a question
+
+ reputation = Repute(user=author,
+ negative=abs(askbot_settings.REP_LOSS_FOR_RECEIVING_DOWNVOTE),
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=-3,
+ reputation=author.reputation)
+ reputation.save()
+
+ user.receive_reputation(
+ askbot_settings.REP_LOSS_FOR_DOWNVOTING,
+ )
+ user.save()
+
+ reputation = Repute(user=user,
+ negative=askbot_settings.REP_LOSS_FOR_DOWNVOTING,
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=-5,
+ reputation=user.reputation)
+ reputation.save()
+
+@transaction.atomic
+def onDownVotedCanceled(vote, post, user, timestamp=None):
+ if timestamp is None:
+ timestamp = timezone.now()
+ vote.delete()
+
+ post.vote_down_count = int(post.vote_down_count) - 1
+ if post.vote_down_count < 0:
+ post.vote_down_count = 0
+ post.points = post.points + 1
+ post.save()
+
+ if not (post.wiki or post.is_anonymous):
+ author = post.author
+ author.receive_reputation(
+ -askbot_settings.REP_LOSS_FOR_RECEIVING_DOWNVOTE
+ )
+ author.save()
+
+ question = post.thread._question_post() # TODO: this is suboptimal if post is already a question
+
+ reputation = Repute(user=author,
+ positive=abs(askbot_settings.REP_LOSS_FOR_RECEIVING_DOWNVOTE),
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=4,
+ reputation=author.reputation
+ )
+ reputation.save()
+
+ user.receive_reputation(-askbot_settings.REP_LOSS_FOR_DOWNVOTING)
+ user.save()
+
+ reputation = Repute(user=user,
+ positive=abs(askbot_settings.REP_LOSS_FOR_DOWNVOTING),
+ question=question,
+ reputed_at=timestamp,
+ reputation_type=5,
+ reputation=user.reputation)
+ reputation.save()
diff --git a/__init__.py b/askbot/bin/__init__.py
similarity index 100%
rename from __init__.py
rename to askbot/bin/__init__.py
diff --git a/askbot/bin/checklocales.py b/askbot/bin/checklocales.py
new file mode 100644
index 0000000000..c195d1b4d0
--- /dev/null
+++ b/askbot/bin/checklocales.py
@@ -0,0 +1,11 @@
+import os
+import subprocess
+
+locales = os.listdir('locale')
+for locale in locales:
+ command = 'msgfmt -c locale/%s/LC_MESSAGES/django.po' % locale
+ subprocess.call(command.split())
+ print command
+ command = 'msgfmt -c locale/%s/LC_MESSAGES/djangojs.po' % locale
+ print command
+ subprocess.call(command.split())
diff --git a/dos2unix.sh b/askbot/bin/dos2unix.sh
similarity index 100%
rename from dos2unix.sh
rename to askbot/bin/dos2unix.sh
diff --git a/askbot/bin/generate_modules.py b/askbot/bin/generate_modules.py
new file mode 100755
index 0000000000..30e2d45d94
--- /dev/null
+++ b/askbot/bin/generate_modules.py
@@ -0,0 +1,316 @@
+# -*- coding: utf-8 -*-
+# Miville
+# Copyright (C) 2008 Société des arts technologiques (SAT)
+# http://www.sat.qc.ca
+# All rights reserved.
+#
+# This file is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 2 of the License, or
+# (at your option) any later version.
+#
+# Miville 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 Miville. If not, see .
+
+"""
+This script parse a directory tree looking for python modules and packages and
+create ReST files appropriately to create code documentation with Sphinx.
+It also create a modules index.
+"""
+
+import os
+import optparse
+
+
+# automodule options
+OPTIONS = ['members',
+ 'undoc-members',
+# 'inherited-members', # disable because there's a bug in sphinx
+ 'show-inheritance']
+
+
+def create_file_name(base, opts):
+ """Create file name from base name, path and suffix"""
+ return os.path.join(opts.destdir, "%s.%s" % (base, opts.suffix))
+
+def write_automodule_directive(module):
+ """Create the automodule directive and add the options"""
+ directive = '.. automodule:: %s\n' % module
+ for option in OPTIONS:
+ directive += ' :%s:\n' % option
+ directive += '\n'
+ return directive
+
+def write_heading(module, kind='Module'):
+ """Create the page heading."""
+ heading = '.. _%s:\n' % module
+ heading += '\n'
+ heading += title_line(module, '=')
+ return heading
+
+def write_sub(module, kind='Module'):
+ """Create the module subtitle"""
+ sub = title_line('The :mod:`%s` %s' % (module, kind), '-')
+ return sub
+
+def title_line(title, char):
+ """ Underline the title with the character pass, with the right length."""
+ return ':mod:`%s`\n%s\n\n' % (title, len(title) * char)
+
+def create_module_content(module):
+ """Build the text of the module file."""
+ text = write_heading(module)
+ #text += write_sub(module)
+ text += write_automodule_directive(module)
+ return text
+
+def is_python_package(path):
+ """returns True if directory is Python package
+ - that is - contains the __index__.py file
+ returns False otherwise
+ """
+ return os.path.isfile(os.path.join(path, '__init__.py'))
+
+def create_package_content(package, py_files, sub_packages):
+ """Build the text of the file"""
+
+ text = write_heading(package, 'Package')
+ text += write_automodule_directive(package)
+
+ #if has py_files or sub_packages
+ # output Package summary:
+ # has #modules, #sub-packages, #members
+
+ #create links to sub-module files
+ if py_files:
+ text += '.. _modules::\n'
+ text += '\n'
+ text += title_line('Modules', '-')
+ text += '\n'
+ for py_file in py_files:
+ if py_file == '__init__.py':
+ #continue, because this file is being created for
+ #__init__.py of the current module
+ continue
+ py_file = os.path.splitext(py_file)[0]
+ text += '* :ref:`%s.%s`\n' % (package, py_file)
+ text += '\n'
+
+ #create links to sub-packages
+ if sub_packages:
+ text += '.. _packages::\n'
+ text += '\n'
+ text += title_line('Subpackages', '-')
+ text += '\n'
+ for sub in sub_packages:
+ #todo - add description here
+ text += '* :ref:`%s.%s`\n' % (package, sub)
+ return text
+ #build toctree for the package page
+ #text += '.. toctree::\n\n'
+ #for sub in subs:
+ # text += ' %s.%s\n' % (package, sub)
+
+def write_file(module_name, text_content, opts):
+ """Saves file for the module uses text_content for content
+ and information within options to determine where to save
+
+ respects options "dry run" and "force"
+ """
+ file_path = create_file_name(module_name, opts)
+ if not opts.force and os.path.isfile(file_path):
+ print 'File %s already exists.' % file_path
+ else:
+ print 'Writing file %s' % file_path
+ # write the file
+ if not opts.dryrun:
+ fd = open(file_path, 'w')
+ fd.write(text_content)
+ fd.close()
+
+
+def check_for_code(module):
+ """
+ Check if there's at least one class or one function in the module.
+ """
+ fd = open(module, 'r')
+ for line in fd:
+ if line.startswith('def ') or line.startswith('class '):
+ fd.close()
+ return True
+ fd.close()
+ return False
+
+def select_public_names(name_list):
+ """goes through the list and discards names
+ that match pattern for hidden and private directory and file names
+ returns the list of those items that pass the "publicity" test
+ """
+ public_names = []
+ for name in name_list:
+ if name.startswith('.') or name.startswith('_'):
+ continue
+ else:
+ public_names.append(name)
+ return public_names
+
+def select_python_packages(package_path, sub_directory_names):
+ """returns list of subdimodule_name directories (only basenames) of package_path
+ which are themselves python packages
+ """
+ python_packages = []
+ for sub_name in sub_directory_names:
+ sub_path = os.path.join(package_path, sub_name)
+ if is_python_package(sub_path):
+ python_packages.append(sub_name)
+ return python_packages
+
+def recurse_tree(path, excludes, opts):
+ """
+ Look for every file in the directory tree and create the corresponding
+ ReST files.
+ """
+ print path
+ base_package_name = None
+ # check if the base directory is a package and get is name
+ if '__init__.py' in os.listdir(path):
+ base_package_name = os.path.basename(path)
+
+ toc = []
+ excludes = format_excludes(path, excludes)
+ tree = os.walk(path, False)
+ for directory, subs, files in tree:
+
+ py_files = select_py_files(files)
+ if len(py_files) < 1:
+ continue
+
+ if is_directory_excluded(directory, excludes):
+ continue
+
+ # TODO: could add check for windows hidden files
+ subs = select_public_names(subs)
+ subs = select_python_packages(directory, subs)
+
+ #calculate dotted python package name - like proj.pack.subpackage
+ package_name = directory.replace(os.path.sep, '.')
+
+ if is_python_package(directory):
+ text = create_package_content(package_name, py_files, subs)
+ write_file(package_name, text, opts)
+ toc.append(os.path.basename(directory))
+
+ for py_file in py_files:
+ if py_file == '__init__.py':
+ continue
+ module_name = os.path.splitext(py_file)[0]
+ module_package_name = package_name + '.' + module_name
+ text = create_module_content(module_package_name)
+ write_file(module_package_name, text, opts)
+ toc.append(module_package_name)
+
+ # create the module's index
+ if not opts.notoc:
+ modules_toc(toc, opts)
+
+def modules_toc(modules, opts, name='modules'):
+ """
+ Create the module's index.
+ """
+ fname = create_file_name(name, opts)
+ if not opts.force and os.path.exists(fname):
+ print "File %s already exists." % name
+ return
+
+ print "Creating module's index modules.txt."
+ text = write_heading(opts.header, 'Modules')
+ text += title_line('Modules:', '-')
+ text += '.. toctree::\n'
+ text += ' :maxdepth: %s\n\n' % opts.maxdepth
+
+ modules.sort()
+ prev_module = ''
+ for module in modules:
+ # look if the module is a subpackage and, if yes, ignore it
+ if module.startswith(prev_module + '.'):
+ continue
+ prev_module = module
+ text += ' %s\n' % module
+
+ # write the file
+ if not opts.dryrun:
+ fd = open(fname, 'w')
+ fd.write(text)
+ fd.close()
+
+def format_excludes(path, excludes):
+ """
+ Format the excluded directory list.
+ (verify that the path is not from the root of the volume or the root of the
+ package)
+ """
+ f_excludes = []
+ for exclude in excludes:
+ #not sure about the "not startswith" part
+ if not os.path.isabs(exclude) and not exclude.startswith(path):
+ exclude = os.path.join(path, exclude)
+ # remove trailing slash
+ f_excludes.append(exclude.rstrip(os.path.sep))
+ return f_excludes
+
+def is_directory_excluded(directory, excludes):
+ """Returns true if directory is in the exclude list
+ otherwise returns false
+ """
+ for exclude in excludes:
+ if directory.startswith(exclude):
+ return True
+ return False
+
+def select_py_files(files):
+ """
+ Return a list with only the python scripts (remove all other files).
+ """
+ py_files = [fich for fich in files if os.path.splitext(fich)[1] == '.py']
+ return py_files
+
+
+def main():
+ """
+ Parse and check the command line arguments
+ """
+ parser = optparse.OptionParser(usage="""usage: %prog [options] [exclude paths, ...]
+
+Note: By default this script will not overwrite already created files.""")
+ parser.add_option("-n", "--doc-header", action="store", dest="header", help="Documentation Header (default=Project)", default="Project")
+ parser.add_option("-d", "--dest-dir", action="store", dest="destdir", help="Output destination directory", default="")
+ parser.add_option("-s", "--suffix", action="store", dest="suffix", help="module suffix (default=txt)", default="txt")
+ parser.add_option("-m", "--maxdepth", action="store", dest="maxdepth", help="Maximum depth of submodules to show in the TOC (default=4)", type="int", default=4)
+ parser.add_option("-r", "--dry-run", action="store_true", dest="dryrun", help="Run the script without creating the files")
+ parser.add_option("-f", "--force", action="store_true", dest="force", help="Overwrite all the files")
+ parser.add_option("-t", "--no-toc", action="store_true", dest="notoc", help="Don't create the table of content file")
+ (opts, args) = parser.parse_args()
+ if len(args) < 1:
+ parser.error("package path is required.")
+ else:
+ if os.path.isdir(args[0]):
+ # check if the output destination is a valid directory
+ if opts.destdir and os.path.isdir(opts.destdir):
+ # if there's some exclude arguments, build the list of excludes
+ excludes = args[1:]
+ recurse_tree(args[0], excludes, opts)
+ else:
+ print '%s is not a valid output destination directory.' % opts.destdir
+ else:
+ print '%s is not a valid directory.' % args
+
+
+
+
+if __name__ == '__main__':
+ main()
diff --git a/askbot/bin/mergelocales.py b/askbot/bin/mergelocales.py
new file mode 100644
index 0000000000..2c49cb254b
--- /dev/null
+++ b/askbot/bin/mergelocales.py
@@ -0,0 +1,61 @@
+import os
+import sys
+import shutil
+import subprocess
+
+DIR1 = sys.argv[1]
+DIR2 = sys.argv[2]
+DEST_DIR = sys.argv[3]
+
+def get_locale_list(path):
+ """return names of directories within a locale dir"""
+ items = os.listdir(path)
+ result = list()
+ for item in items:
+ if os.path.isdir(os.path.join(path, item)):
+ result.append(item)
+ return result
+
+def copy_locale_from(localeno, name = None):
+ """copy entire locale without merging"""
+ if localeno == 1:
+ src = os.path.join(DIR1, name)
+ elif localeno == 2:
+ src = os.path.join(DIR2, name)
+ shutil.copytree(src, os.path.join(DEST_DIR, name))
+
+def merge_locales(name):
+ """runs msgcat command on specified files
+ and a locale name in DIR1 and DIR2"""
+ run_msgcat(name, 'django.po')
+ run_msgcat(name, 'djangojs.po')
+
+def run_msgcat(locale_name, file_name):
+ """run msgcat in locale on file name"""
+ file_path = os.path.join(locale_name, 'LC_MESSAGES', file_name)
+ dest_file = os.path.join(DEST_DIR, file_path)
+ dest_dir = os.path.dirname(dest_file)
+ if not os.path.exists(dest_dir):
+ os.makedirs(os.path.dirname(dest_file))
+ subprocess.call((
+ 'msgcat',
+ os.path.join(DIR1, file_path),
+ os.path.join(DIR2, file_path),
+ '-o',
+ dest_file
+ ))
+
+LOCALE_LIST1 = get_locale_list(DIR1)
+LOCALE_LIST2 = get_locale_list(DIR2)
+
+for locale in LOCALE_LIST1:
+ print locale
+ if locale not in LOCALE_LIST2:
+ copy_locale_from(1, name = locale)
+ else:
+ merge_locales(locale)
+ LOCALE_LIST2.remove(locale)
+
+for locale in LOCALE_LIST2:
+ print locale
+ copy_locale_from(2, name = locale)
diff --git a/askbot/bin/rebuildlocales.py b/askbot/bin/rebuildlocales.py
new file mode 100644
index 0000000000..86840adddd
--- /dev/null
+++ b/askbot/bin/rebuildlocales.py
@@ -0,0 +1,16 @@
+import os
+import subprocess
+
+locales = os.listdir('locale')
+
+def call_command(command):
+ print command
+ subprocess.call(command.split())
+
+for locale in locales:
+ call_command(
+ 'python ../manage.py jinja2_makemessages -l %s -e html,py,txt' % locale
+ )
+ call_command(
+ 'python ../manage.py makemessages -l %s -d djangojs' % locale
+ )
diff --git a/askbot/bin/show_profile_stats.py b/askbot/bin/show_profile_stats.py
new file mode 100644
index 0000000000..1e3322defb
--- /dev/null
+++ b/askbot/bin/show_profile_stats.py
@@ -0,0 +1,13 @@
+"""script for digesting profiling output
+to profile functions, wrap them into decorator @profile('file_name.prof')
+
+source: http://code.djangoproject.com/wiki/ProfilingDjango
+"""
+
+import hotshot.stats
+import sys
+
+stats = hotshot.stats.load(sys.argv[1])
+#stats.strip_dirs()
+stats.sort_stats('time', 'calls')
+stats.print_stats(20)
diff --git a/askbot/bin/test_permission_assertions b/askbot/bin/test_permission_assertions
new file mode 100644
index 0000000000..f690936ef4
--- /dev/null
+++ b/askbot/bin/test_permission_assertions
@@ -0,0 +1,9 @@
+python manage.py test askbot.SeeOffensiveFlagsPermissionAssertionTests \
+ askbot.DeleteAnswerPermissionAssertionTests \
+ askbot.DeleteQuestionPermissionAssertionTests \
+ askbot.CloseQuestionPermissionAssertionTests \
+ askbot.ReopenQuestionPermissionAssertionTests \
+ askbot.FlagOffensivePermissionAssertionTests \
+ askbot.CommentPermissionAssertionTests \
+ askbot.VotePermissionAssertionTests \
+ askbot.UploadPermissionAssertionTests
diff --git a/askbot/conf/README b/askbot/conf/README
new file mode 100644
index 0000000000..4dd623295d
--- /dev/null
+++ b/askbot/conf/README
@@ -0,0 +1,5 @@
+this directory contains
+forum site configurations for livesettings
+
+they need to be imported in models so made this a part of
+models module
diff --git a/askbot/conf/__init__.py b/askbot/conf/__init__.py
new file mode 100644
index 0000000000..f6d457e0f7
--- /dev/null
+++ b/askbot/conf/__init__.py
@@ -0,0 +1,64 @@
+#import these to compile code and install values
+from askbot import const
+import askbot
+import askbot.conf.minimum_reputation
+import askbot.conf.vote_rules
+import askbot.conf.reputation_changes
+import askbot.conf.karma_and_badges_visibility
+import askbot.conf.email
+import askbot.conf.email_text
+import askbot.conf.forum_data_rules
+import askbot.conf.moderation
+import askbot.conf.question_lists
+import askbot.conf.flatpages
+import askbot.conf.site_settings
+import askbot.conf.license
+import askbot.conf.external_keys
+import askbot.conf.ldap
+import askbot.conf.skin_general_settings
+import askbot.conf.sidebar_main
+import askbot.conf.sidebar_question
+import askbot.conf.sidebar_profile
+import askbot.conf.leading_sidebar
+import askbot.conf.spam_and_moderation
+import askbot.conf.user_settings
+import askbot.conf.group_settings
+import askbot.conf.feedback
+import askbot.conf.markup
+import askbot.conf.social_sharing
+import askbot.conf.badges
+import askbot.conf.login_providers
+import askbot.conf.access_control
+import askbot.conf.site_modes
+import askbot.conf.words
+
+#import main settings object
+from askbot.conf.settings_wrapper import settings
+
+from django.conf import settings as django_settings
+def should_show_sort_by_relevance():
+ """True if configuration support sorting
+ questions by search relevance
+ """
+ return ('postgresql_psycopg2' in askbot.get_database_engine_name())
+
+def get_tag_display_filter_strategy_choices():
+ from askbot.conf import settings as askbot_settings
+ if askbot_settings.SUBSCRIBED_TAG_SELECTOR_ENABLED:
+ return const.TAG_DISPLAY_FILTER_STRATEGY_CHOICES
+ else:
+ return const.TAG_DISPLAY_FILTER_STRATEGY_MINIMAL_CHOICES
+
+def get_tag_email_filter_strategy_choices():
+ """returns the set of choices appropriate for the configuration"""
+ from askbot.conf import settings as askbot_settings
+ if askbot_settings.SUBSCRIBED_TAG_SELECTOR_ENABLED:
+ return const.TAG_EMAIL_FILTER_ADVANCED_STRATEGY_CHOICES
+ else:
+ return const.TAG_EMAIL_FILTER_SIMPLE_STRATEGY_CHOICES
+
+def gravatar_enabled():
+ from askbot.conf import settings as askbot_settings
+ if 'avatar' in django_settings.INSTALLED_APPS:
+ return askbot_settings.ENABLE_GRAVATAR
+ return True
diff --git a/askbot/conf/access_control.py b/askbot/conf/access_control.py
new file mode 100644
index 0000000000..60f5c5beb8
--- /dev/null
+++ b/askbot/conf/access_control.py
@@ -0,0 +1,148 @@
+from askbot.conf.settings_wrapper import settings
+from askbot.conf.super_groups import LOGIN_USERS_COMMUNICATION
+from askbot.deps import livesettings
+from askbot.deps.livesettings import BooleanValue
+from askbot.deps.livesettings import StringValue
+from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import string_concat
+
+ACCESS_CONTROL = livesettings.ConfigurationGroup(
+ 'ACCESS_CONTROL',
+ _('Access control settings'),
+ super_group = LOGIN_USERS_COMMUNICATION
+ )
+
+settings.register(
+ BooleanValue(
+ ACCESS_CONTROL,
+ 'READ_ONLY_MODE_ENABLED',
+ default=False,
+ description=_('Make site read-only'),
+ )
+)
+
+settings.register(
+ StringValue(
+ ACCESS_CONTROL,
+ 'READ_ONLY_MESSAGE',
+ default=_(
+ 'The site is temporarily read-only. '
+ 'Only viewing of the content is possible at the moment.'
+ )
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ ACCESS_CONTROL,
+ 'ASKBOT_CLOSED_FORUM_MODE',
+ default=False,
+ description=_('Allow only registered user to access the forum'),
+ )
+)
+
+EMAIL_VALIDATION_CASE_CHOICES = (
+ ('nothing', _('nothing - not required')),
+ ('see-content', _('account registration')),
+ #'post-content', _('posting content'),
+)
+
+settings.register(
+ livesettings.StringValue(
+ ACCESS_CONTROL,
+ 'REQUIRE_VALID_EMAIL_FOR',
+ default='nothing',
+ choices=EMAIL_VALIDATION_CASE_CHOICES,
+ description=_('Require valid email for')
+ )
+)
+
+#todo: move REQUIRE_VALID_EMAIL_FOR to boolean setting
+#settings.register(
+# livesettings.BooleanValue(
+# ACCESS_CONTROL,
+# 'EMAIL_VALIDATION_REQUIRED',
+# default=False,
+# description=_('Require valid email address to register')
+# )
+#)
+def update_email_callback(old, new):
+ if new.strip():
+ settings.update('BLACKLISTED_EMAIL_PATTERNS_MODE', 'disabled')
+ return new
+
+settings.register(
+ livesettings.LongStringValue(
+ ACCESS_CONTROL,
+ 'ALLOWED_EMAILS',
+ default='',
+ description=_('Allowed email addresses'),
+ help_text=string_concat(
+ _('Please use space to separate the entries'),
+ '. ',
+ _('Entry disables blacklisted email patterns')
+ ),
+ update_callback=update_email_callback
+ )
+)
+
+settings.register(
+ livesettings.LongStringValue(
+ ACCESS_CONTROL,
+ 'ALLOWED_EMAIL_DOMAINS',
+ default='',
+ description=_('Allowed email domain names'),
+ help_text=string_concat(
+ _('Please use space to separate the entries, do not use the @ symbol!'),
+ '. ',
+ _('Entry disables blacklisted email patterns')
+ ),
+ update_callback=update_email_callback
+ )
+)
+
+BLACKLISTED_EMAIL_PATTERNS_MODE_CHOICES = (
+ ('disabled', _('disable')),
+ ('medium',
+ string_concat(
+ _('block user registrations'),
+ ', ',
+ _('allow existing users to post')
+ )
+ ),
+ ('strict', _('block completely')),
+)
+
+settings.register(
+ livesettings.StringValue(
+ ACCESS_CONTROL,
+ 'BLACKLISTED_EMAIL_PATTERNS_MODE',
+ default='strict',
+ choices=BLACKLISTED_EMAIL_PATTERNS_MODE_CHOICES,
+ description=_('Blacklisted email address patterns mode'),
+ )
+)
+
+settings.register(
+ livesettings.LongStringValue(
+ ACCESS_CONTROL,
+ 'BLACKLISTED_EMAIL_PATTERNS',
+ default='',
+ description=_('Blacklisted email address patterns'),
+ help_text=string_concat(
+ _('Please use space to separate the entries'),
+ ', ',
+ _('regular expressions are allowed'),
+ '.'
+ )
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ ACCESS_CONTROL,
+ 'ADMIN_INBOX_ACCESS_ENABLED',
+ default=False,
+ description=_("Allow moderators to access other's messages"),
+ )
+)
diff --git a/askbot/conf/badges.py b/askbot/conf/badges.py
new file mode 100644
index 0000000000..9499503ed8
--- /dev/null
+++ b/askbot/conf/badges.py
@@ -0,0 +1,250 @@
+"""
+Settings for reputation changes that apply to
+user in response to various actions by the same
+users or others
+"""
+from askbot.conf.settings_wrapper import settings
+from askbot.conf.super_groups import REP_AND_BADGES
+from askbot.deps.livesettings import ConfigurationGroup
+from askbot.deps.livesettings import IntegerValue
+from askbot.deps.livesettings import BooleanValue
+from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import string_concat
+
+BADGES = ConfigurationGroup(
+ 'BADGES',
+ _('Badge settings'),
+ ordering=2,
+ super_group = REP_AND_BADGES
+ )
+
+def register_badge_settings(badge_slug=None, badge_name=None, params=None):
+ settings.register(
+ BooleanValue(
+ BADGES,
+ badge_slug + '_BADGE_ENABLED',
+ default=True,
+ description=_('Enable "%s" badge') % badge_name
+ )
+ )
+ if params is None:
+ return
+
+ for param_slug, param_data in params.items():
+ param_description = param_data[0]
+ param_default = param_data[1]
+ settings.register(
+ IntegerValue(
+ BADGES,
+ badge_slug + '_BADGE_' + param_slug,
+ description=string_concat(badge_name, ': ', param_description),
+ default=param_default
+ )
+ )
+
+register_badge_settings(
+ 'ASSOCIATE_EDITOR',
+ _('Associate Editor'),
+ params={
+ 'MIN_EDITS': (_('minimum number of edits'), 20)
+ }
+)
+
+register_badge_settings('AUTOBIOGRAPHER', _('Autobiographer'))
+
+register_badge_settings('CITIZEN_PATROL', _('Citizen Patrol'))
+
+register_badge_settings(
+ 'CIVIC_DUTY',
+ _('Civic Duty'),
+ params={
+ 'MIN_VOTES': (_('minimum votes'), 100)
+ }
+)
+
+register_badge_settings('CLEANUP', _('Cleanup'))
+
+register_badge_settings(
+ 'COMMENTATOR',
+ _('Commentator'),
+ params={
+ 'MIN_COMMENTS': (_('minimum comments'), 10)
+ }
+)
+
+register_badge_settings('CRITIC', _('Critic'))
+
+register_badge_settings(
+ 'DISCIPLINED',
+ _('Disciplined'),
+ params={
+ 'MIN_UPVOTES': (_('minimum upvotes for deleted post'), 3)
+ }
+)
+
+register_badge_settings('EDITOR', _('Editor'))
+
+register_badge_settings(
+ 'ENLIGHTENED',
+ _('Enlightened Duty'),
+ params={
+ 'MIN_UPVOTES': (_('minimum upvotes'), 3)
+ }
+)
+
+register_badge_settings(
+ 'ENTHUSIAST',
+ _('Enthusiast'),
+ params={
+ 'MIN_DAYS': (_('minimum days'), 5)
+ }
+)
+
+register_badge_settings('EXPERT', _('Expert'))
+
+register_badge_settings(
+ 'FAMOUS_QUESTION',
+ _('Famous Question') ,
+ params={
+ 'MIN_VIEWS': (_('minimum views'), 50)
+ }
+)
+
+register_badge_settings(
+ 'FAVORITE_QUESTION',
+ _('Favorite Question'),
+ params={
+ 'MIN_STARS': (_('minimum followers'), 3)
+ }
+)
+
+register_badge_settings(
+ 'GOOD_ANSWER',
+ _('Good Answer'),
+ params={
+ 'MIN_UPVOTES': (_('minimum upvotes for the answer'), 3)
+ }
+)
+
+register_badge_settings(
+ 'GOOD_QUESTION',
+ _('Good Question'),
+ params={
+ 'MIN_UPVOTES': (_('minimum upvotes for the question'), 3)
+ }
+)
+
+register_badge_settings(
+ 'GREAT_ANSWER',
+ _('Great Answer'),
+ params={
+ 'MIN_UPVOTES': (_('minimum upvotes for the answer'), 5)
+ }
+)
+
+register_badge_settings(
+ 'GREAT_QUESTION',
+ _('Great Question'),
+ params={
+ 'MIN_UPVOTES': (_('minimum upvotes for the question'), 5)
+ }
+)
+
+register_badge_settings(
+ 'GURU',
+ _('Guru'),
+ params={
+ 'MIN_UPVOTES': (_('minimum upvotes'), 5)
+ }
+)
+
+register_badge_settings(
+ 'NECROMANCER',
+ _('Necromancer'),
+ params={
+ 'MIN_UPVOTES': (_('minimum upvotes'), 1),
+ 'MIN_DELAY': (_('minimum delay in days'), 30)
+ }
+)
+
+register_badge_settings(
+ 'NICE_QUESTION',
+ _('Nice Question'),
+ params={
+ 'MIN_UPVOTES': (_('minimum upvotes for the question'), 2)
+ }
+)
+
+register_badge_settings(
+ 'NICE_ANSWER',
+ _('Nice Answer'),
+ params={
+ 'MIN_UPVOTES': (_('minimum upvotes for the answer'), 2)
+ }
+)
+
+register_badge_settings(
+ 'NOTABLE_QUESTION',
+ _('Notable Question'),
+ params={
+ 'MIN_VIEWS': (_('minimum views'), 25)
+ }
+)
+
+register_badge_settings('ORGANIZER', _('Organizer'))
+
+register_badge_settings(
+ 'PEER_PRESSURE',
+ _('Peer pressure'),
+ params={
+ 'MIN_DOWNVOTES': (_('minimum downvotes for deleted post'), 3)
+ }
+)
+
+register_badge_settings(
+ 'POPULAR_QUESTION',
+ _('Popular Question'),
+ params={
+ 'MIN_VIEWS': (_('minimum views'), 15)
+ }
+)
+
+register_badge_settings('PUNDIT', _('Pundit'))
+
+register_badge_settings('SCHOLAR', _('Scholar'))
+
+register_badge_settings(
+ 'SELF_LEARNER',
+ _('Self-Learner'),
+ params={
+ 'MIN_UPVOTES': (_('minimum answer upvotes'), 1)
+ }
+)
+
+register_badge_settings(
+ 'STELLAR_QUESTION',
+ _('Stellar Question'),
+ params={
+ 'MIN_STARS': (_('minimum followers'), 5)
+ }
+)
+
+register_badge_settings('STUDENT', _('Student'))
+
+register_badge_settings('SUPPORTER', _('Supporter'))
+
+register_badge_settings(
+ 'TAXONOMIST',
+ _('Taxonomist'),
+ params={
+ 'MIN_USE_COUNT': (_('minimum tag use count'), 5)
+ }
+)
+
+register_badge_settings(
+ 'TEACHER',
+ _('Teacher'),
+ params={
+ 'MIN_UPVOTES': (_('minimum upvotes for the answer'), 1)
+ }
+)
diff --git a/askbot/conf/email.py b/askbot/conf/email.py
new file mode 100644
index 0000000000..1e66643490
--- /dev/null
+++ b/askbot/conf/email.py
@@ -0,0 +1,436 @@
+"""
+Email related settings
+"""
+from askbot.conf.settings_wrapper import settings
+from askbot.conf.super_groups import LOGIN_USERS_COMMUNICATION
+from askbot.deps import livesettings
+from askbot import const
+from django.utils.translation import ugettext_lazy as _
+from django.utils.translation import string_concat
+from django.conf import settings as django_settings
+
+EMAIL_SUBJECT_PREFIX = getattr(django_settings, 'EMAIL_SUBJECT_PREFIX', '')
+
+EMAIL = livesettings.ConfigurationGroup(
+ 'EMAIL',
+ _('Email and email alert settings'),
+ super_group = LOGIN_USERS_COMMUNICATION
+ )
+
+settings.register(
+ livesettings.StringValue(
+ EMAIL,
+ 'EMAIL_SUBJECT_PREFIX',
+ default = EMAIL_SUBJECT_PREFIX,
+ description = _('Prefix for the email subject line'),
+ help_text = _(
+ 'This setting takes default from the django setting'
+ 'EMAIL_SUBJECT_PREFIX. A value entered here will override'
+ 'the default.'
+ )
+ )
+)
+
+def get_default_admin_email():
+ try:
+ return django_settings.ADMINS[0][1]
+ except:
+ return ''
+
+settings.register(
+ livesettings.StringValue(
+ EMAIL,
+ 'ADMIN_EMAIL',
+ default=get_default_admin_email(),
+ description=_('Site administrator email address')
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'ENABLE_EMAIL_ALERTS',
+ default=True,
+ description=_('Enable email alerts'),
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'INSTANT_EMAIL_ALERT_ENABLED',
+ description=_('Enable instant email alerts'),
+ default=True
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'WELCOME_EMAIL_ENABLED',
+ description=_('Enable welcome email'),
+ default=True
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'REJECTED_POST_EMAIL_ENABLED',
+ description=_('Enable rejected post alert'),
+ help_text=_('Also, premoderation mode must be enabled'),
+ default=True
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'APPROVED_POST_NOTIFICATION_ENABLED',
+ description=_('Enable approved post alert'),
+ help_text=_('Also, premoderation mode must be enabled'),
+ default=True
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'BATCH_EMAIL_ALERT_ENABLED',
+ description=_('Enable batch email alert'),
+ default=True
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'GROUP_MESSAGING_EMAIL_ALERT_ENABLED',
+ description=_('Enable private messaging alerts'),
+ default=True
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'MODERATION_QUEUE_NOTIFICATION_ENABLED',
+ description=_('Enable moderation queue alerts'),
+ default=True
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'HTML_EMAIL_ENABLED',
+ default=True,
+ description=_('Enable HTML-formatted email'),
+ help_text=_('May not be supported by some email clients')
+ )
+)
+
+settings.register(
+ livesettings.IntegerValue(
+ EMAIL,
+ 'MAX_ALERTS_PER_EMAIL',
+ default=7,
+ description=_('Maximum number of news entries in an email alert')
+ )
+)
+
+settings.register(
+ livesettings.StringValue(
+ EMAIL,
+ 'DEFAULT_NOTIFICATION_DELIVERY_SCHEDULE_Q_ALL',
+ default='w',
+ choices=const.NOTIFICATION_DELIVERY_SCHEDULE_CHOICES,
+ description=_('Default notification frequency all questions'),
+ help_text=_(
+ 'Option to define frequency of emailed updates for: '
+ 'all questions.'
+ )
+ )
+)
+
+settings.register(
+ livesettings.StringValue(
+ EMAIL,
+ 'DEFAULT_NOTIFICATION_DELIVERY_SCHEDULE_Q_ASK',
+ default='i',
+ choices=const.NOTIFICATION_DELIVERY_SCHEDULE_CHOICES,
+ description=_('Default notification frequency questions asked by the user'),
+ help_text=_(
+ 'Option to define frequency of emailed updates for: '
+ 'Question asked by the user.'
+ )
+ )
+)
+
+settings.register(
+ livesettings.StringValue(
+ EMAIL,
+ 'DEFAULT_NOTIFICATION_DELIVERY_SCHEDULE_Q_ANS',
+ default='d',
+ choices=const.NOTIFICATION_DELIVERY_SCHEDULE_CHOICES,
+ description=_('Default notification frequency questions answered by the user'),
+ help_text=_(
+ 'Option to define frequency of emailed updates for: '
+ 'Question answered by the user.'
+ )
+ )
+)
+
+settings.register(
+ livesettings.StringValue(
+ EMAIL,
+ 'DEFAULT_NOTIFICATION_DELIVERY_SCHEDULE_Q_SEL',
+ default='i',
+ choices=const.NOTIFICATION_DELIVERY_SCHEDULE_CHOICES,
+ description=_('Default notification frequency questions individually \
+ selected by the user'),
+ help_text=_(
+ 'Option to define frequency of emailed updates for: '
+ 'Question individually selected by the user.'
+ )
+ )
+)
+
+settings.register(
+ livesettings.StringValue(
+ EMAIL,
+ 'DEFAULT_NOTIFICATION_DELIVERY_SCHEDULE_M_AND_C',
+ default='i',
+ choices=const.NOTIFICATION_DELIVERY_SCHEDULE_CHOICES,
+ description=_('Default notification frequency for mentions \
+ and comments'),
+ help_text=_(
+ 'Option to define frequency of emailed updates for: '
+ 'Mentions and comments.'
+ )
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'ENABLE_UNANSWERED_REMINDERS',
+ default = False,
+ description = _('Enable reminders about unanswered questions'),
+ help_text = _(
+ 'NOTE: in order to use this feature, it is necessary to '
+ 'run the management command "send_unanswered_question_reminders" '
+ '(for example, via a cron job - with an appropriate frequency) '
+ )
+ )
+)
+
+UNANSWERED_REMINDER_RECIPIENTS_CHOICES = (
+ ('everyone', _('everyone')),
+ ('admins', _('moderators & administrators'))
+)
+
+settings.register(
+ livesettings.StringValue(
+ EMAIL,
+ 'UNANSWERED_REMINDER_RECIPIENTS',
+ default='everyone',
+ choices=UNANSWERED_REMINDER_RECIPIENTS_CHOICES,
+ description=_('Whom to remind about unanswered questions')
+ )
+)
+
+settings.register(
+ livesettings.IntegerValue(
+ EMAIL,
+ 'DAYS_BEFORE_SENDING_UNANSWERED_REMINDER',
+ default = 1,
+ description = _(
+ 'Days before starting to send reminders about unanswered questions'
+ ),
+ )
+)
+
+settings.register(
+ livesettings.IntegerValue(
+ EMAIL,
+ 'UNANSWERED_REMINDER_FREQUENCY',
+ default = 1,
+ description = _(
+ 'How often to send unanswered question reminders '
+ '(in days between the reminders sent).'
+ )
+ )
+)
+
+settings.register(
+ livesettings.IntegerValue(
+ EMAIL,
+ 'MAX_UNANSWERED_REMINDERS',
+ default = 5,
+ description = _(
+ 'Max. number of reminders to send '
+ 'about unanswered questions'
+ )
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'ENABLE_ACCEPT_ANSWER_REMINDERS',
+ default = False,
+ description = _('Enable accept the best answer reminders'),
+ help_text = _(
+ 'NOTE: in order to use this feature, it is necessary to '
+ 'run the management command "send_accept_answer_reminders" '
+ '(for example, via a cron job - with an appropriate frequency) '
+ )
+ )
+)
+
+settings.register(
+ livesettings.IntegerValue(
+ EMAIL,
+ 'DAYS_BEFORE_SENDING_ACCEPT_ANSWER_REMINDER',
+ default = 3,
+ description = _(
+ 'Days before starting to send reminders to accept an answer'
+ ),
+ )
+)
+
+settings.register(
+ livesettings.IntegerValue(
+ EMAIL,
+ 'ACCEPT_ANSWER_REMINDER_FREQUENCY',
+ default = 3,
+ description = _(
+ 'How often to send accept answer reminders '
+ '(in days between the reminders sent).'
+ )
+ )
+)
+
+settings.register(
+ livesettings.IntegerValue(
+ EMAIL,
+ 'MAX_ACCEPT_ANSWER_REMINDERS',
+ default = 5,
+ description = _(
+ 'Max. number of reminders to send '
+ 'to accept the best answer'
+ )
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'BLANK_EMAIL_ALLOWED',
+ default=False,
+ description=_('Allow blank email'),
+ help_text=string_concat(
+ _('DANGER: makes impossible account recovery by email.'),
+ ' ',
+ settings.get_related_settings_info(
+ ('ACCESS_CONTROL', 'REQUIRE_VALID_EMAIL_FOR', True, _('Must be not be required')),
+ )
+ )
+ )
+)
+
+settings.register(
+ livesettings.StringValue(
+ EMAIL,
+ 'ANONYMOUS_USER_EMAIL',
+ default='anonymous@askbot.org',
+ description=_('Fake email for anonymous user'),
+ help_text=_('Use this setting to control gravatar for email-less user')
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'ALLOW_ASKING_BY_EMAIL',
+ default = False,
+ description=_('Allow posting questions by email'),
+ help_text=_(
+ 'Before enabling this setting - please fill out IMAP settings '
+ 'in the settings.py file'
+ )
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'REPLACE_SPACE_WITH_DASH_IN_EMAILED_TAGS',
+ default = True,
+ description = _('Replace space in emailed tags with dash'),
+ help_text = _(
+ 'This setting applies to tags written in the subject line '
+ 'of questions asked by email'
+ )
+ )
+)
+
+settings.register(
+ livesettings.BooleanValue(
+ EMAIL,
+ 'REPLY_BY_EMAIL',
+ default = False,
+ description=_('Enable posting answers and comments by email'),
+ #TODO give a better explanation depending on lamson startup procedure
+ help_text=_(
+ 'To enable this feature make sure lamson is running'
+
+ )
+ )
+)
+
+settings.register(
+ livesettings.StringValue(
+ EMAIL,
+ 'SELF_NOTIFY_EMAILED_POST_AUTHOR_WHEN',
+ description=_(
+ 'Emailed post: when to notify author about publishing'
+ ),
+ choices=const.SELF_NOTIFY_EMAILED_POST_AUTHOR_WHEN_CHOICES,
+ default=const.NEVER
+ )
+)
+
+#not implemented at this point
+#settings.register(
+# livesettings.IntegerValue(
+# EMAIL,
+# 'SELF_NOTIFY_WEB_POST_AUTHOR_WHEN',
+# description = _(
+# 'Web post: when to notify author about publishing'
+# ),
+# choices = const.SELF_NOTIFY_WEB_POST_AUTHOR_WHEN_CHOICES,
+# default = const.NEVER
+# )
+#)
+
+settings.register(
+ livesettings.StringValue(
+ EMAIL,
+ 'REPLY_BY_EMAIL_HOSTNAME',
+ default = "",
+ description=_('Reply by email hostname'),
+ #TODO give a better explanation depending on lamson startup procedure
+
+ )
+)
+
+settings.register(
+ livesettings.IntegerValue(
+ EMAIL,
+ 'MIN_WORDS_FOR_ANSWER_BY_EMAIL',
+ default=14,
+ description=_('Email replies having fewer words than this number will be posted as comments instead of answers')
+ )
+)
diff --git a/askbot/conf/email_text.py b/askbot/conf/email_text.py
new file mode 100644
index 0000000000..30be298292
--- /dev/null
+++ b/askbot/conf/email_text.py
@@ -0,0 +1,50 @@
+from askbot.conf.settings_wrapper import settings
+from askbot.conf.super_groups import LOGIN_USERS_COMMUNICATION
+from askbot.deps import livesettings
+from django.utils.translation import ugettext_lazy as _
+
+EMAIL_TEXT = livesettings.ConfigurationGroup(
+ 'EMAIL_TEXT',
+ _('Email template phrases'),
+ super_group=LOGIN_USERS_COMMUNICATION
+ )
+
+settings.register(
+ livesettings.StringValue(
+ EMAIL_TEXT,
+ 'EMAIL_TEXT_SHORT_WELCOME',
+ description = _('Short welcome message, for subject line'),
+ default = _('Welcome to {{ SITE_NAME }}!'),
+ help_text = _(
+ 'NOTE: All email text settings allow placeholders: {{ USER_NAME }}, {{ SITE_NAME }} and {{ SITE_LINK }}.'
+ )
+ )
+)
+
+settings.register(
+ livesettings.LongStringValue(
+ EMAIL_TEXT,
+ 'EMAIL_TEXT_LONG_WELCOME',
+ description = _('Longer welcome message, for email body'),
+ default = _('
Please visit {{ SITE_NAME }} at {{ SITE_LINK }}, we look forward to your posts.
+{% endblock %}
+{% block relbar2 %}
+{% endblock %}
diff --git a/askbot/doc/source/askbot/static/facebook.png b/askbot/doc/source/askbot/static/facebook.png
new file mode 100644
index 0000000000..77ae358f3b
Binary files /dev/null and b/askbot/doc/source/askbot/static/facebook.png differ
diff --git a/askbot/doc/source/askbot/static/traditional.css b/askbot/doc/source/askbot/static/traditional.css
new file mode 100644
index 0000000000..3fa381cd72
--- /dev/null
+++ b/askbot/doc/source/askbot/static/traditional.css
@@ -0,0 +1,694 @@
+/*
+ * traditional.css
+ * ~~~~~~~~~~~~~~~
+ *
+ * Sphinx stylesheet -- traditional docs.python.org theme.
+ *
+ * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
+ * :license: BSD, see LICENSE for details.
+ *
+ */
+@import url(http://fonts.googleapis.com/css?family=Droid+Sans|Cabin|Cabin+Sketch:700);
+
+body {
+ color: #000;
+ margin: 0;
+ padding: 0;
+ border-color: gray;
+}
+
+/* :::: LAYOUT :::: */
+
+div.documentwrapper {
+ float: left;
+ width: 100%;
+}
+
+div.bodywrapper {
+ margin: 0 230px 0 0;
+}
+
+div.body {
+ background-color: white;
+ padding: 0 20px 30px 0;
+ font-family: "Droid Sans", "Lucida Grande",Verdana,"Bitstream Vera Sans",Arial,sans-serif;
+}
+
+div.sphinxsidebarwrapper {
+ border: 1px solid #777;
+ padding: 10px;
+ margin: 55px 15px 10px 0;
+}
+
+div.sphinxsidebar {
+ float: right;
+ margin-left: -100%;
+ width: 230px;
+ font-family: "Droid Sans", sans-serif;
+}
+
+div.clearer {
+ clear: both;
+}
+
+div.document {
+ width: 960px;
+ margin: auto;
+}
+
+div.footer {
+ clear: both;
+ width: 100%;
+ background-color: #dcdcdc;
+ padding: 9px 0 9px 0;
+ text-align: center;
+ font-family: "Droid Sans", sans-serif;
+}
+
+div.related {
+ background-color: #99ccff;
+ color: #333;
+ width: 960px;
+ margin: auto;
+ height: 30px;
+ line-height: 30px;
+ border-bottom: 5px solid white;
+}
+
+div.related h3 {
+ display: none;
+}
+
+div.related ul {
+ margin: 0;
+ padding: 0 0 0 10px;
+ list-style: none;
+}
+
+div.related li {
+ display: inline;
+ font-weight: bold;
+}
+
+div.related li.right {
+ float: right;
+ margin-right: 5px;
+}
+
+/* ::: SIDEBAR :::: */
+div.sphinxsidebar h3,
+div.sphinxsidebar h4{
+ font-family: 'Cabin', cursive;
+}
+
+div.sphinxsidebar h3 {
+ margin: 0;
+}
+
+div.sphinxsidebar h4 {
+ margin: 5px 0 0 0;
+}
+
+
+div.sphinxsidebar p.topless {
+ margin: 5px 10px 10px 10px;
+}
+
+div.sphinxsidebar ul {
+ margin: 10px;
+ margin-left: 15px;
+ padding: 0;
+}
+
+div.sphinxsidebar ul ul {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+div.sphinxsidebar form {
+ margin-top: 10px;
+}
+
+
+/* :::: SEARCH :::: */
+ul.search {
+ margin: 10px 0 0 20px;
+ padding: 0;
+}
+
+ul.search li {
+ padding: 5px 0 5px 20px;
+ background-image: url(file.png);
+ background-repeat: no-repeat;
+ background-position: 0 7px;
+}
+
+ul.search li a {
+ font-weight: bold;
+}
+
+ul.search li div.context {
+ color: #888;
+ margin: 2px 0 0 30px;
+ text-align: left;
+}
+
+ul.keywordmatches li.goodmatch a {
+ font-weight: bold;
+}
+
+/* :::: COMMON FORM STYLES :::: */
+
+div.actions {
+ border-top: 1px solid #aaa;
+ background-color: #ddd;
+ margin: 10px 0 0 -20px;
+ padding: 5px 0 5px 20px;
+}
+
+form dl {
+ color: #333;
+}
+
+form dt {
+ clear: both;
+ float: left;
+ min-width: 110px;
+ margin-right: 10px;
+ padding-top: 2px;
+}
+
+input#homepage {
+ display: none;
+}
+
+div.error {
+ margin: 5px 20px 0 0;
+ padding: 5px;
+ border: 1px solid #d00;
+ /*border: 2px solid #05171e;
+ background-color: #092835;
+ color: white;*/
+ font-weight: bold;
+}
+
+/* :::: INLINE COMMENTS :::: */
+
+div.inlinecommentswrapper {
+ float: right;
+ max-width: 40%;
+}
+
+div.commentmarker {
+ float: right;
+ background-image: url(style/comment.png);
+ background-repeat: no-repeat;
+ width: 25px;
+ height: 25px;
+ text-align: center;
+ padding-top: 3px;
+}
+
+div.nocommentmarker {
+ float: right;
+ background-image: url(style/nocomment.png);
+ background-repeat: no-repeat;
+ width: 25px;
+ height: 25px;
+}
+
+div.inlinecomments {
+ margin-left: 10px;
+ margin-bottom: 5px;
+ background-color: #eee;
+ border: 1px solid #ccc;
+ padding: 5px;
+}
+
+div.inlinecomment {
+ border-top: 1px solid #ccc;
+ padding-top: 5px;
+ margin-top: 5px;
+}
+
+.inlinecomments p {
+ margin: 5px 0 5px 0;
+}
+
+.inlinecomments .head {
+ font-weight: bold;
+}
+
+.inlinecomments .meta {
+ font-style: italic;
+}
+
+
+/* :::: COMMENTS :::: */
+
+div#comments h3 {
+ border-top: 1px solid #aaa;
+ padding: 5px 20px 5px 20px;
+ margin: 20px -20px 20px -20px;
+ background-color: #ddd;
+}
+
+div#comments em.important {
+ color: #d00;
+ font-weight: bold;
+ font-style: normal;
+}*/
+
+/* :::: SUGGEST CHANGES :::: */
+div#suggest-changes-box input, div#suggest-changes-box textarea {
+ border: 1px solid #ccc;
+ background-color: white;
+ color: black;
+}
+
+div#suggest-changes-box textarea {
+ width: 99%;
+ height: 400px;
+}
+
+
+/* :::: PREVIEW :::: */
+div.preview {
+ background-image: url(style/preview.png);
+ padding: 0 20px 20px 20px;
+ margin-bottom: 30px;
+}
+
+
+/* :::: INDEX PAGE :::: */
+
+table.contentstable {
+ width: 90%;
+}
+
+table.contentstable p.biglink {
+ line-height: 150%;
+}
+
+a.biglink {
+ font-size: 1.5em;
+}
+
+span.linkdescr {
+ font-style: italic;
+ padding-top: 5px;
+}
+
+/* :::: GENINDEX STYLES :::: */
+
+table.indextable td {
+ text-align: left;
+ vertical-align: top;
+}
+
+table.indextable dl, table.indextable dd {
+ margin-top: 0;
+ margin-bottom: 0;
+}
+
+table.indextable tr.pcap {
+ height: 10px;
+}
+
+table.indextable tr.cap {
+ margin-top: 10px;
+ background-color: #f2f2f2;
+}
+
+img.toggler {
+ margin-right: 3px;
+ margin-top: 3px;
+ cursor: pointer;
+}
+
+/* :::: GLOBAL STYLES :::: */
+
+p.subhead {
+ font-weight: bold;
+ margin-top: 20px;
+}
+
+a {
+ text-decoration: none;
+ border-bottom: 1px solid #dfdfdf;
+}
+a:link:active { color: #555; }
+a:link:hover { color: #000; }
+a:visited { color: #655; }
+a:link { color: #555; }
+
+div.body h1,
+div.body h2,
+div.body h3,
+div.body h4,
+div.body h5,
+div.body h6 {
+ font-family: 'Cabin', cursive;
+ font-weight: bold;
+}
+
+div.body h1 { font-size: 180%; }
+div.body h2 { font-size: 150%; }
+div.body h3 { font-size: 120%; }
+div.body h4 { font-size: 120%; }
+
+div.body p { font-size: 100%; }
+
+a.headerlink,
+a.headerlink,
+a.headerlink,
+a.headerlink,
+a.headerlink,
+a.headerlink {
+ color: #c60f0f;
+ font-size: 0.8em;
+ padding: 0 4px 0 4px;
+ text-decoration: none;
+ visibility: hidden;
+}
+
+*:hover > a.headerlink,
+*:hover > a.headerlink,
+*:hover > a.headerlink,
+*:hover > a.headerlink,
+*:hover > a.headerlink,
+*:hover > a.headerlink {
+ visibility: visible;
+}
+
+a.headerlink:hover,
+a.headerlink:hover,
+a.headerlink:hover,
+a.headerlink:hover,
+a.headerlink:hover,
+a.headerlink:hover {
+ background-color: #c60f0f;
+ color: white;
+}
+
+div.body p, div.body dd, div.body li {
+ text-align: justify;
+}
+
+div.body td {
+ text-align: left;
+}
+
+ul.fakelist {
+ list-style: none;
+ margin: 10px 0 10px 20px;
+ padding: 0;
+}
+
+/* "Footnotes" heading */
+p.rubric {
+ margin-top: 30px;
+ font-weight: bold;
+}
+
+/* "Topics" */
+
+div.topic {
+ background-color: #eee;
+ border: 1px solid #ccc;
+ padding: 0 7px 0 7px;
+ margin: 10px 0 10px 0;
+}
+
+p.topic-title {
+ font-size: 1.1em;
+ font-weight: bold;
+ margin-top: 10px;
+}
+
+/* Admonitions */
+
+div.admonition {
+ margin-top: 10px;
+ margin-bottom: 10px;
+ padding: 7px;
+}
+
+div.admonition dt {
+ font-weight: bold;
+}
+
+div.admonition dd {
+ margin-bottom: 10px;
+}
+
+div.admonition dl {
+ margin-bottom: 0;
+}
+
+div.admonition p {
+ display: inline;
+}
+
+div.seealso {
+ background-color: #ffc;
+ border: 1px solid #ff6;
+}
+
+div.warning {
+ background-color: #ffe4e4;
+ border: 1px solid #f66;
+}
+
+div.note {
+ background-color: #eee;
+ border: 1px solid #ccc;
+}
+
+p.admonition-title {
+ margin: 0px 10px 5px 0px;
+ font-weight: bold;
+ display: inline;
+}
+
+p.admonition-title:after {
+ content: ":";
+}
+
+div.body p.centered {
+ text-align: center;
+ margin-top: 25px;
+}
+
+table.docutils {
+ border: 0;
+}
+
+table.docutils td, table.docutils th {
+ padding: 0 8px 2px 0;
+ border-top: 0;
+ border-left: 0;
+ border-right: 0;
+ border-bottom: 1px solid #aaa;
+}
+
+table.field-list td, table.field-list th {
+ border: 0 !important;
+}
+
+table.footnote td, table.footnote th {
+ border: 0 !important;
+}
+
+dl {
+ margin-bottom: 15px;
+ clear: both;
+}
+
+dd p {
+ margin-top: 0px;
+}
+
+dd ul, dd table {
+ margin-bottom: 10px;
+}
+
+dd {
+ margin-top: 3px;
+ margin-bottom: 10px;
+ margin-left: 30px;
+}
+
+dl.glossary dt {
+ font-weight: bold;
+ font-size: 1.1em;
+}
+
+.refcount {
+ color: #060;
+}
+
+th {
+ text-align: left;
+ padding-right: 5px;
+}
+
+pre {
+ font-family: monospace;
+ padding: 5px;
+ color: #00008b;
+ border-left: none;
+ border-right: none;
+}
+
+tt {
+ font-family: monospace;
+ background-color: #ecf0f3;
+ padding: 0 1px 0 1px;
+}
+
+tt.descname {
+ background-color: transparent;
+ font-weight: bold;
+ font-size: 1.2em;
+}
+
+tt.descclassname {
+ background-color: transparent;
+}
+
+tt.xref, a tt {
+ background-color: transparent;
+ font-weight: bold;
+}
+
+.footnote:target { background-color: #ffa }
+
+.line-block {
+ display: block;
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+
+.line-block .line-block {
+ margin-top: 0;
+ margin-bottom: 0;
+ margin-left: 1.5em;
+}
+
+h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt {
+ background-color: transparent;
+}
+
+.optional {
+ font-size: 1.3em;
+}
+
+.versionmodified {
+ font-style: italic;
+}
+
+form.comment {
+ margin: 0;
+ padding: 10px 30px 10px 30px;
+ background-color: #eee;
+}
+
+form.comment h3 {
+ background-color: #326591;
+ color: white;
+ margin: -10px -30px 10px -30px;
+ padding: 5px;
+ font-size: 1.4em;
+}
+
+form.comment input,
+form.comment textarea {
+ border: 1px solid #ccc;
+ padding: 2px;
+ font-family: sans-serif;
+ font-size: 13px;
+}
+
+form.comment input[type="text"] {
+ width: 240px;
+}
+
+form.comment textarea {
+ width: 100%;
+ height: 200px;
+ margin-bottom: 10px;
+}
+
+/* :::: PRINT :::: */
+@media print {
+ div.documentwrapper {
+ width: 100%;
+ }
+
+ div.body {
+ margin: 0;
+ }
+
+ div.sphinxsidebar,
+ div.related,
+ div.footer,
+ div#comments div.new-comment-box,
+ #top-link {
+ display: none;
+ }
+}
+
+.viewcode-link {
+ float: right;
+}
+
+.viewcode-back {
+ float: right;
+ font-family: serif;
+}
+
+div.viewcode-block:target {
+ background-color: #f4debf;
+ border-top: 1px solid #ac9;
+ border-bottom: 1px solid #ac9;
+ margin: -1px -10px;
+ padding: 0 10px;
+}
+
+div.ab-proj-header {
+ width: 960px;
+ margin: auto;
+ border-bottom: 2px solid #555;
+ font-family: "Droid Sans", sans-serif;
+}
+
+div.ab-proj-header a,
+div.ab-proj-header a:visited
+{
+ text-decoration: none;
+ color: #333;
+ border: none;
+ font-family: "Droid Sans", sans-serif;
+}
+
+div.logo{
+ font-size: 20px;
+ width: 960px;
+ margin: auto;
+}
+
+div.logo a, div.logo a:visited
+{
+ text-decoration: none;
+ color: #333;
+ border: none;
+ font-family: 'Cabin Sketch', cursive;
+}
+
+div.topnav{
+ float: right;
+ position: relative;
+ right:6px;
+ top:-65px;
+}
diff --git a/askbot/doc/source/askbot/static/twitter.png b/askbot/doc/source/askbot/static/twitter.png
new file mode 100644
index 0000000000..371c9823d6
Binary files /dev/null and b/askbot/doc/source/askbot/static/twitter.png differ
diff --git a/askbot/doc/source/askbot/theme.conf b/askbot/doc/source/askbot/theme.conf
new file mode 100644
index 0000000000..9f67df58ee
--- /dev/null
+++ b/askbot/doc/source/askbot/theme.conf
@@ -0,0 +1,4 @@
+[theme]
+inherit = traditional
+stylesheet = traditional.css
+pygments_style = sphinx
diff --git a/askbot/doc/source/change-password.png b/askbot/doc/source/change-password.png
new file mode 100644
index 0000000000..bb2f5cf0aa
Binary files /dev/null and b/askbot/doc/source/change-password.png differ
diff --git a/askbot/doc/source/changelog.rst b/askbot/doc/source/changelog.rst
new file mode 100644
index 0000000000..533ae81698
--- /dev/null
+++ b/askbot/doc/source/changelog.rst
@@ -0,0 +1,385 @@
+Changes in Askbot
+=================
+
+0.10.0 (Dec 7, 2015)
+--------------------
+* Added management command `askbot_rebuild_avatars`
+* Added option to choose gravatar or default avatar for new users
+* Message on the feedback page is editable
+* Added support for the NoCaptcha recaptcha
+
+0.7.53 (Apr 22, 2015)
+---------------------
+* Use prompt placeholders on all registration forms
+* Disable Google login by default because it is now OAuth2
+
+
+0.7.52 (Apr 19, 2015)
+---------------------
+* Added account recovery form to the "complete registration" page
+ to help prevent accidental creation of duplicate accounts
+* Support migration of Google OpenID accounts to G+
+* Added setting to allow comment updates show on the main page
+* Improved support of uploadable avatars
+* Added authentication via MediaWiki
+* Added option to specify `ASKBOT_QUESTION_TITLE_RENDERER` function
+* Added option to specify `ASKBOT_HTML_MODERATOR` function
+* Allowed reordering badges on the badges page via drag and drop
+* Added option to forbid commenting in closed questions
+* Added separate optional time limits to edit questions and answers
+* Added option to disable comments under questions or answers
+* Added management command `askbot_recount_badges`
+* Allowed adding custom badges via `ASKBOT_CUSTOM_BADGES` setting
+* Allowed enabling and disabling individual badges
+* Added "forbidden phrases" for the content moderation
+ Posts containing these will be rejected outright, without placement
+ on the moderation queue.
+* Added minimum reputation to delete own questions with answers
+* Added optional checkbox "accept terms of service"
+ which being enabled, requires users to read and agree
+ with the terms before signing up.
+* Added terms of service page
+* Allowed reverse ordering of comments
+
+0.7.51 (Dec 15, 2014)
+---------------------
+* Bug fixes
+
+0.7.50 (Nov 1, 2014)
+--------------------
+* Added email alert for moderators `askbot_send_moderation_alerts`
+* Implemented Google Plus login
+* Allowed localized site settings
+* Added management command `askbot_clear_moderation_queue`
+* Admins and Moderators can merge questions.
+* Improved moderation modes: flags, audit, premoderation.
+ Watched user status, IP blocking, mass content removal.
+* Allow bulk deletion of user content simultaneously with blocking
+* Allow custom destination url under the logo
+* Option to allow asking without registration (Egil Moeller)
+* Implemented Mozilla Persona authentication
+* Allowed custom providers of gravatar service (michas2)
+* Allowed configurable custom OpenID login button
+* Allowed custom list of feedback recipients (Keto)
+* Added option to show user's emails to the moderators
+* Added Read-Only mode for the site in the "access control" section.
+* Added `askbot_add_osqa_content` management command.
+* Management command to add data from other Askbot site.
+* Allowed simple overrides of livesettings with `ASKBOT_...` prefixed
+ variables in the `settings.py` file.
+
+0.7.49 (Sep 19, 2013)
+---------------------
+* Support for Solr search backend (Adolfo)
+* Allowed read-only access user groups (Adolfo)
+* Added simple read-only API (Adolfo)
+* Added "admin email" to livesettings (Evgeny)
+* Improved Zendesk import feature `Kevin Porterfield, Shotgun Software_`
+* Added backend support for the tag synonyms `pcompassion https://github.com/pcompassion`_
+* Added management command `apply_hinted_tags` to batch-apply tags from a list (Evgeny)
+* Added hovercard on the user's karma display in the header (Evgeny)
+* Added option to hide ad blocks from logged in users (Evgeny)
+* Applied Askbot templates to the settings control panel (Evgeny)
+* Added option to auto-follow questions by the question posters with default "on" (Evgeny)
+* Support for Django 1.5
+* Auto-tweet option for questions and answers
+* Added Chech and Croatian translations
+* Disable/enable best answer feature
+* Allowed post owners repost answers and comments (this used to be mod-only function).
+* Answer editor is "folded" by default. Editor buttons and options show on click.
+* Management command `askbot_import_jive` to import data from Jive forums.
+* Added possibility to choose editor for comments: plain text, or same as
+ editor used for the questions or answers: WMD or TinyMCE.
+* Added ajax search to the tags page
+* Added a placeholder template for the custom javascript on the question page
+* Allowed to disable the big "ask" button.
+* Some support for the media compression (Tyler Mandry)
+* Allowed to enable and disable question scopes on the main page
+* Added full text support for some languages with Postgresql:
+ Danish, Dutch, English, Finnish, French, German, Hungarian,
+ Italian, Japanese (requires package textsearch_ja), Norwegian,
+ Portugese, Romanian, Russian, Spanish, Swedish, Turkish.
+* repost answer as a comment under the previous (older) answer
+* minor edit option for question and answer, to suppress email alerts
+* allowed tags to be created upon marking them as interesting/ignored/subscribed
+
+0.7.48 (Jan 28, 2013)
+---------------------
+* made "how to ask the question" instructions editable
+* added RSS auto-discovery link
+* added support for multilingual site (experimental)
+* tag subscription manager on the tags page (Adolfo)
+
+0.7.47 (Dec 13, 2012)
+---------------------
+* Bugfix release
+
+0.7.46 (Dec 12, 2012)
+---------------------
+* Bugfix release
+
+0.7.45 (Dec 12, 2012)
+---------------------
+* Feedback sender's email is added to the Reply-To header
+ in the feedback form (Evgeny)
+* Reimplemented search as drop-down (Evgeny)
+* Basic design to work on smartphones (Evgeny)
+* Allowed use of alternative form on the user signup page (Evgeny)
+
+0.7.44 (Nov 11, 2012)
+---------------------
+* Support for django 1.4 (Adolfo)
+* Added option to enable/disable rss feeds (Evgeny)
+* Added minimum reputation to insert links and hotlinked images (Evgeny)
+* Added minimum reputation to suggest links as plain text (Evgeny)
+* Added support of Haystack for search (Adolfo)
+* Added minimum reputation setting to accept any answer as correct (Evgeny)
+* Added "VIP" option to groups - if checked, all posts belong to the group and users of that group in the future will be able to moderate those posts. Moderation features for VIP group are in progress (Evgeny)
+* Added setting `NOTIFICATION_DELAY_TIME` to use with enabled celery daemon (Adolfo)
+* Added setting `ASKBOT_INTERNAL_IPS` - to allow anonymous access to
+ closed sites from dedicated IP addresses (Evgeny)
+* Moved default skin from `askbot/skins/default` to simply `askbot` (Evgeny)
+* Repost comment as answer (Adolfo)
+* Question list widget (Adolfo)
+* Ask a question widget (Adolfo)
+* Embeddable widget generator (Adolfo)
+* Groups are shown in the dropdown menu in the header (Adolfo)
+* Added group moderation requests to the moderators inboxes (Evgeny)
+* Group joining may be open/closed or moderated (Evgeny)
+* Adding "extra options" to the ldap session (Evgeny)
+* Tag moderation (Evgeny)
+* Editable optional three level category selector for the tags (Evgeny)
+* Tag editor adding tags as they are typed (Evgeny)
+* Added optional support for unicode slugs (Evgeny)
+* Allow switching comment with answer and answer with question comment (Adolfo)
+* Allow user names longer than 30 characters (Evgeny)
+* Option to disable feedback form for the anonymos users (Evgeny)
+* Optional restriction to have confirmed email address to join forum (Evgeny)
+* Optional list of allowed email addresses and email domain name for the new users (Evgeny)
+* Optional support for unicode slugs (Evgeny)
+* Optionally allow limiting one answer per question per person (Evgeny)
+* Added management command `build_livesettings_cache` (Adolfo)
+* Administrators can post under fictional user accounts without logging out (jtrain, Evgeny)
+* Welcome email for the case when replying by email is enabled (Evgeny)
+* Detection of email signature based on the response to the welcome email (Evgeny)
+* Hide "website" and "about" section of the blocked user profiles
+ to help prevent user profile spam (Evgeny)
+* Added a function to create a custom user profile tab,
+ the feature requires access to the server (Evgeny)
+* Added optional top banner to the question page (Evgeny)
+* Made "bootstrap mode" default and created instead "large site mode" (Evgeny)
+* Added interesting/ignored/subscribed tags to the user profile page (Paul Backhouse, Evgeny)
+
+0.7.43 (May 14, 2012)
+---------------------
+* User groups (Evgeny)
+* Public/Private/Hidden reputation (Evgeny)
+* Enabling/disabling the badges system (Evgeny)
+* Created a basic post moderation feature (Evgeny)
+* Created a way to specify reasons for rejecting posts in a modal dialog (Evgeny)
+* A number of bug fixes (Adolfo Fitoria, Jim Tittsler,
+ Evgeny Fadeev, Robin Stocker, Radim Řehůřek, Silvio Heuberger)
+
+0.7.41, 0.7.42 (April 21, 2012)
+-------------------------------
+* Bug fixes
+
+0.7.40 (March 29, 2012)
+-----------------------
+* New data models!!! (`Tomasz Zieliński `_)
+* Made email recovery link work when askbot is deployed on subdirectory (Evgeny)
+* Added tests for the CSRF_COOKIE_DOMAIN setting in the startup_procedures (Evgeny)
+* Askbot now respects django's staticfiles app (Radim Řehůřek, Evgeny)
+* Fixed the url translation bug (Evgeny)
+* Added left sidebar option (Evgeny)
+* Added "help" page and links to in the header and the footer (Evgeny)
+* Removed url parameters and the hash fragment from uploaded files -
+ amazon S3 for some reason adds weird expiration parameters (Evgeny)
+* Reduced memory usage in data migrations (Evgeny)
+* Added progress bars to slow data migrations (Evgeny)
+* Added a management command to build_thread_summary_cache (Evgeny)
+* Added a management delete_contextless_badge_award_activities (Evgeny)
+* Fixed a file upload issue in FF and IE found by jerry_gzy (Evgeny)
+* Added test on maximum length of title working for utf-8 text (Evgeny)
+* Added caching and invalidation to the question page (Evgeny)
+* Added a management command delete_contextless_activities (Evgeny)
+* LDAP login configuration (github user `monkut `_)
+* Check order of middleware classes (Daniel Mican)
+* Added "reply by email" function (`Vasil Vangelovski `_)
+* Enabled "ask by email" via Lamson (Evgeny)
+* Tags can be optional (Evgeny)
+* Fixed dependency of Django up to 1.3.1, because settings must be upgraded
+ for Django 1.4 (Evgeny)
+
+0.7.39 (Jan 11, 2012)
+---------------------
+* restored facebook login after FB changed the procedure (Evgeny)
+
+0.7.38 (Jan 11, 2012)
+---------------------
+* xss vulnerability fix, issue found by Radim Řehůřek (Evgeny)
+
+0.7.37 (Jan 8, 2012)
+--------------------
+* added basic slugification treatment to question titles with
+ ``ALLOW_UNICODE_SLUGS = True`` (Evgeny)
+* added verification of the project directory name to
+ make sure it does not contain a `.` (dot) symbol (Evgeny)
+* made askbot compatible with django's `CSRFViewMiddleware`
+ that may be used for other projects (Evgeny)
+* added more rigorous test for the user name to make it slug safe (Evgeny)
+* made setting `ASKBOT_FILE_UPLOAD_DIR` work (Radim Řehůřek)
+* added minimal length of question title ond body
+ text to live settings and allowed body-less questions (Radim Řehůřek, Evgeny)
+* allowed disabling use of gravatar site-wide (Rosandra Cuello Suñol)
+* when internal login app is disabled - links to login/logout/add-remove-login-methods are gone (Evgeny)
+* replaced setting `ASKBOT_FILE_UPLOAD_DIR` with django's `MEDIA_ROOT` (Evgeny)
+* replaced setting `ASKBOT_UPLOADED_FILES_URL` with django's `MEDIA_URL` (Evgeny)
+* allowed changing file storage backend for file uploads by configuration (Evgeny)
+* file uploads to amazon S3 now work with proper configuration (Evgeny)
+
+0.7.36 (Dec 20, 2011)
+---------------------
+* bugfix and made the logo not used by default
+
+0.7.35 (Dec 15, 2011)
+---------------------
+* Removal of offensive flags (`Dejan Noveski `_)
+* Fixes in CSS (`Byron Corrales `_)
+* Update of Catalan locale (Jordi Bofill)
+
+0.7.34 (Dec 10, 2011)
+---------------------
+* Returned support of Django 1.2
+
+0.7.33 (Dec 6, 2011)
+--------------------
+* Made on log in redirect to the forum index page by default
+ and to the question page, if user was reading the question
+ it is still possible to override the ``next`` url parameter
+ or just rely on django's ``LOGIN_REDIRECT_URL`` (Evgeny)
+* Implemented retraction of offensive flags (Dejan Noveski)
+* Made automatic dependency checking more complete (Evgeny)
+
+0.7.32 (Nov 30, 2011)
+---------------------
+* Bugfixes in English locale (Evgeny)
+
+0.7.31 (Nov 29, 2011)
+---------------------
+* Added ``askbot_create_test_fixture`` management command (Dejan Noveski)
+* Integrated new test fixture into the page load test cases (Dejan Noveski)
+* Added an embeddable widget for the questions list matching tags (Daniel Mican, Evgeny Fadeev, Dejan Noveski)
+
+0.7.30 (Nov 28, 2011)
+---------------------
+Note: some of these features were added in one of the three previous versions.
+
+* Context-sensitive RSS url (`Dejan Noveski `_)
+* Implemented new version of skin (Byron Corrales)
+* Show unused vote count (Tomasz Zielinski)
+* Categorized live settings (Evgeny)
+* Merge users management command (Daniel Mican)
+* Added management command ``send_accept_answer_reminders`` (Evgeny)
+* Improved the ``askbot-setup`` script (Adolfo, Evgeny)
+* Merge users management command (Daniel Mican)
+* Anonymous caching of the question page (Vlad Bokov)
+* Fixed sharing button bug, css fixes for new template (Alexander Werner)
+* Added ASKBOT_TRANSLATE_URL setting for url localization(Alexander Werner)
+* Changed javascript translation model, moved from jqueryi18n to django (Rosandra Cuello Suñol)
+* Private forum mode (Vlad Bokov)
+* Improved text search query in Postgresql (Alexander Werner)
+* Take LANGUAGE_CODE from request (Alexander Werner)
+* Added support for LOGIN_REDIRECT_URL to the login app (hjwp, Evgeny)
+* Updated Italian localization (Luca Ferroni)
+* Added Catalan localization (Jordi Bofill)
+* Added management command ``askbot_add_test_content`` (Dejan Noveski)
+* Continued work on refactoring the database schema (Tomasz Zielinski)
+
+0.7.27 - 0.7.29 (Nov 8-28, 2011)
+--------------------------------
+For these versions we did not keep consistent record of features.
+
+0.7.26 (Oct 12, 2011)
+---------------------
+* Added settings for email subscription defaults (Adolfo)
+* Resolved `bug #102`_ - duplicate notifications on posts with mentions (Evegeny)
+* Added color-animated transitions when urls with hash tags are visited (Adolfo)
+* Repository tags will be `automatically added `_ to new releases (Evgeny, suggsted by ajmirsky)
+
+0.7.25 (Oct 5 2011)
+-------------------
+* RSS feed for individual question (Sayan Chowdhury)
+* Allow pre-population of tags via ask a questions link (Adolfo)
+* Make answering own question one click harder (Adolfo)
+* Bootstrap mode (Adolfo, Evgeny)
+* Color-animated urls with the hash fragments (Adolfo)
+
+0.7.24
+------
+* Made it possible to disable the anonymous user greeting alltogether (Raghu Udiyar)
+* Added annotations for the meanings of user levels on the "moderation" page. (Jishnu)
+* Auto-link patterns - e.g. to bug databases - are configurable from settings. (Arun SAG)
+
+0.7.23
+------
+* Greeting for anonymuos users can be changed from live settings (Hrishi)
+* Greeting for anonymous users is shown only once (Rag Sagar)
+* Added support for Akismet spam detection service (Adolfo Fitoria)
+* Added noscript message (Arun SAG)
+* Support for url shortening with TinyUrl on link sharing (Rtnpro)
+* Allowed logging in with password and email in the place of login name (Evgeny)
+* Added config settings allowing adjust license information (Evgeny)
+
+0.7.22
+------
+* Media resource revision is now incremented
+ automatically any time when media is updated (Adolfo Fitoria, Evgeny Fadeev)
+* First user automatically becomes site administrator (Adolfo Fitoria)
+* Avatar displayed on the sidebar can be controlled with livesettings.(Adolfo Fitoria, Evgeny Fadeev)
+* Avatar box in the sidebar is ordered with priority for real faces.(Adolfo Fitoria)
+* Django's createsuperuser now works with askbot (Adolfo Fitoria)
+
+0.7.21
+------
+This version was skipped
+
+0.7.20
+------
+* Added support for login via self-hosted Wordpress site (Adolfo Fitoria)
+* Allowed basic markdown in the comments (Adolfo Fitoria)
+* Added this changelog (Adolfo Fitoria)
+* Added support for threaded emails (Benoit Lavigne)
+* A few more Spanish translation strings (Byron Corrales)
+* Social sharing support on identi.ca (Rantadeep Debnath)
+
+0.7.19
+------
+* Changed the Favorite question function for Follow question.
+* Fixed issues with page load time.
+* Added notify me checkbox to the sidebar.
+* Removed MySql dependency from setup.py
+* Fixed Facebook login.
+* `Fixed "Moderation tab is misaligned" issue reported by methner. `_
+* Fixed bug in follow users and changed the follow button design.
+
+0.7.18
+------
+* `Added multiple capitalization to username mentions(reported by niles) `_
+
+0.7.17
+------
+* Adding test for UserNameField.
+* Adding test for markup functions.
+
+0.7.16
+------
+* Admins can add aministrators too.
+* Added a postgres driver version check in the start procedures due to a bug in psycopg2 2.4.2.
+* New inbox system style (`bug reported by Tomasz P. Szynalski `_).
+
+0.7.15
+------
+* Fixed integration with Django 1.1.
+* Fixed bugs in setup script.
+* Fixed pypi bugs.
diff --git a/askbot/doc/source/conf.py b/askbot/doc/source/conf.py
new file mode 100644
index 0000000000..2869886e86
--- /dev/null
+++ b/askbot/doc/source/conf.py
@@ -0,0 +1,276 @@
+# -*- coding: utf-8 -*-
+#
+# Askbot documentation build configuration file, created by
+# sphinx-quickstart on Wed Jun 16 19:22:51 2010.
+#
+# This file is execfile()d with the current directory set to its containing dir.
+#
+# Note that not all possible configuration values are present in this
+# autogenerated file.
+#
+# All configuration values have a default; values that are commented out
+# serve to show the default.
+
+import sys, os
+
+# If extensions (or modules to document with autodoc) are in another directory,
+# add these directories to sys.path here. If the directory is relative to the
+# documentation root, use os.path.abspath to make it absolute, like shown here.
+#sys.path.append(os.path.abspath('.'))
+def parent_dir(start_path, levels_up = 1):
+ """returns path of a directory
+ levels_up relative to the start_path
+ """
+ if os.path.isfile(start_path):
+ start_path = os.path.dirname(start_path)
+ for i in range(levels_up):
+ start_path = os.path.dirname(start_path)
+ out_path = start_path
+ return out_path
+
+PROJECT_DIR = parent_dir(__file__, 3)
+PROJECT_MODULE = os.path.basename(PROJECT_DIR)
+os.environ['DJANGO_SETTINGS_MODULE'] = PROJECT_MODULE + '.settings'
+
+sys.path.append(PROJECT_DIR)
+#and a parent to project dir
+sys.path.append(parent_dir(__file__, 4))
+sys.path.append(parent_dir(__file__, 2))
+
+# -- General configuration -----------------------------------------------------
+
+# If your documentation needs a minimal Sphinx version, state it here.
+#needs_sphinx = '1.0'
+
+# Add any Sphinx extension module names here, as strings. They can be extensions
+# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
+extensions = ['sphinx.ext.todo', 'sphinx.ext.coverage',]# 'sphinx.ext.viewcode']
+#extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.coverage',]# 'sphinx.ext.viewcode']
+
+# Add any paths that contain templates here, relative to this directory.
+templates_path = ['_templates', 'askbot']
+
+# The suffix of source filenames.
+source_suffix = '.rst'
+
+# The encoding of source files.
+#source_encoding = 'utf-8-sig'
+
+# The master toctree document.
+master_doc = 'index'
+
+# General information about the project.
+project = u'Askbot'
+copyright = u'2011, Askbot Project'
+
+# The version info for the project you're documenting, acts as replacement for
+# |version| and |release|, also used in various other places throughout the
+# built documents.
+# The short X.Y version.
+from askbot import get_version
+version = get_version()
+# The full version, including alpha/beta/rc tags.
+release = get_version()
+
+# The language for content autogenerated by Sphinx. Refer to documentation
+# for a list of supported languages.
+#language = None
+
+# There are two options for replacing |today|: either, you set today to some
+# non-false value, then it is used:
+#today = ''
+# Else, today_fmt is used as the format for a strftime call.
+#today_fmt = '%B %d, %Y'
+
+# List of patterns, relative to source directory, that match files and
+# directories to ignore when looking for source files.
+exclude_patterns = []
+
+# The reST default role (used for this markup: `text`) to use for all documents.
+#default_role = None
+
+# If true, '()' will be appended to :func: etc. cross-reference text.
+#add_function_parentheses = True
+
+# If true, the current module name will be prepended to all description
+# unit titles (such as .. function::).
+#add_module_names = True
+
+# If true, sectionauthor and moduleauthor directives will be shown in the
+# output. They are ignored by default.
+show_authors = True
+
+# The name of the Pygments (syntax highlighting) style to use.
+pygments_style = 'sphinx'
+
+# A list of ignored prefixes for module index sorting.
+modindex_common_prefix = ['askbot.']
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+# The theme to use for HTML and HTML Help pages. See the documentation for
+# a list of builtin themes.
+html_theme = 'askbot'
+#html_theme_options = {
+# 'rightsidebar':'false',
+#}
+
+# Theme options are theme-specific and customize the look and feel of a theme
+# further. For a list of options available for each theme, see the
+# documentation.
+#html_theme_options = {}
+
+# Add any paths that contain custom themes here, relative to this directory.
+html_theme_path = ['.',]
+
+# The name for this set of Sphinx documents. If None, it defaults to
+# " v documentation".
+#html_title = None
+
+# A shorter title for the navigation bar. Default is the same as html_title.
+#html_short_title = None
+
+# The name of an image file (relative to this directory) to place at the top
+# of the sidebar.
+#html_logo = None
+
+# The name of an image file (within the static path) to use as favicon of the
+# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
+# pixels large.
+#html_favicon = None
+
+# Add any paths that contain custom static files (such as style sheets) here,
+# relative to this directory. They are copied after the builtin static files,
+# so a file named "default.css" will overwrite the builtin "default.css".
+html_static_path = ['_static']
+
+# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
+# using the given strftime format.
+#html_last_updated_fmt = '%b %d, %Y'
+
+# If true, SmartyPants will be used to convert quotes and dashes to
+# typographically correct entities.
+#html_use_smartypants = True
+
+# Custom sidebar templates, maps document names to template names.
+#html_sidebars = {}
+
+# Additional templates that should be rendered to pages, maps page names to
+# template names.
+#html_additional_pages = {}
+
+# If false, no module index is generated.
+#html_domain_indices = True
+
+# If false, no index is generated.
+#html_use_index = True
+
+# If true, the index is split into individual pages for each letter.
+#html_split_index = False
+
+# If true, links to the reST sources are added to the pages.
+html_show_sourcelink = False
+
+# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
+#html_show_sphinx = True
+
+# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
+#html_show_copyright = True
+
+# If true, an OpenSearch description file will be output, and all pages will
+# contain a tag referring to it. The value of this option must be the
+# base URL from which the finished HTML is served.
+#html_use_opensearch = ''
+
+# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml").
+#html_file_suffix = ''
+
+# Output file base name for HTML help builder.
+htmlhelp_basename = 'Askbotdoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+# The paper size ('letter' or 'a4').
+#latex_paper_size = 'letter'
+
+# The font size ('10pt', '11pt' or '12pt').
+#latex_font_size = '10pt'
+
+# Grouping the document tree into LaTeX files. List of tuples
+# (source start file, target name, title, author, documentclass [howto/manual]).
+latex_documents = [
+ ('index', 'Askbot.tex', u'Askbot Documentation',
+ u'Evgeny Fadeev', 'manual'),
+]
+
+# The name of an image file (relative to this directory) to place at the top of
+# the title page.
+#latex_logo = None
+
+# For "manual" documents, if this is true, then toplevel headings are parts,
+# not chapters.
+#latex_use_parts = False
+
+# If true, show page references after internal links.
+#latex_show_pagerefs = False
+
+# If true, show URL addresses after external links.
+#latex_show_urls = False
+
+# Additional stuff for the LaTeX preamble.
+#latex_preamble = ''
+
+# Documents to append as an appendix to all manuals.
+#latex_appendices = []
+
+# If false, no module index is generated.
+#latex_domain_indices = True
+
+
+# -- Options for manual page output --------------------------------------------
+
+# One entry per manual page. List of tuples
+# (source start file, name, description, authors, manual section).
+man_pages = [
+ ('index', 'askbot', u'Askbot Documentation',
+ [u'Evgeny Fadeev'], 1)
+]
+
+
+# -- Options for Epub output ---------------------------------------------------
+
+# Bibliographic Dublin Core info.
+epub_title = u'Askbot'
+epub_author = u'Evgeny Fadeev'
+epub_publisher = u'Evgeny Fadeev'
+epub_copyright = u'2010, Evgeny Fadeev'
+
+# The language of the text. It defaults to the language option
+# or en if the language is not set.
+#epub_language = ''
+
+# The scheme of the identifier. Typical schemes are ISBN or URL.
+#epub_scheme = ''
+
+# The unique identifier of the text. This can be a ISBN number
+# or the project homepage.
+#epub_identifier = ''
+
+# A unique identification for the text.
+#epub_uid = ''
+
+# HTML files that should be inserted before the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_pre_files = []
+
+# HTML files shat should be inserted after the pages created by sphinx.
+# The format is a list of tuples containing the path and title.
+#epub_post_files = []
+
+# A list of files that should not be packed into the epub file.
+#epub_exclude_files = []
+
+# The depth of the table of contents in toc.ncx.
+#epub_tocdepth = 3
diff --git a/askbot/doc/source/connect-aol.png b/askbot/doc/source/connect-aol.png
new file mode 100644
index 0000000000..e7961f09a6
Binary files /dev/null and b/askbot/doc/source/connect-aol.png differ
diff --git a/askbot/doc/source/contributors.rst b/askbot/doc/source/contributors.rst
new file mode 100644
index 0000000000..09cea10ac9
--- /dev/null
+++ b/askbot/doc/source/contributors.rst
@@ -0,0 +1,88 @@
+==============================
+Contributors to Askbot Project
+==============================
+
+This is the list of contributors to the code of Askbot project.
+The list is probably incomplete, apologies for any omissions.
+Thanks for all your help
+
+Programming, bug fixes and documentation
+----------------------------------------
+* Mike Chen & Sailing Cai - original authors of CNPROG forum
+* Evgeny Fadeev - founder of askbot
+* `Adolfo Fitoria `_
+* `Tomasz Zielinski `_
+* `Sayan Chowdhury `_
+* Andy Knotts
+* Benoit Lavine (with Windriver Software, Inc.)
+* Jeff Madynski
+* `Jishnu `_
+* `Hrishi `_
+* Andrei Mamoutkine
+* `Daniel Mican `_
+* `Dejan Noveski `_
+* `Vasil Vangelovski `_
+* `Ramiro Morales `_ (with Machinalis)
+* Vladimir Bokov
+* `NoahY `_
+* `Gael Pasgrimaud `_ (bearstech)
+* `Arun SAG `_
+* `Rag Sagar `_
+* `Alex Robbins `_
+* `Tomasz Szynalski `_
+* `Raghu Udiyar `_
+* `Alexander Werner `_
+* Rosandra Cuello Suñol
+* `hjwp `_
+* `Jacob Oscarson `_
+* `Radim Řehůřek `_
+* `monkut `_
+* `Jim Tittsler `_
+* Silvio Heuberger
+* `Alexandros `_
+* `Paul Backhouse `_
+* `jtrain `_
+* Niki Rocco
+* `Tyler Mandry `_
+* `Jorge López Pérez `_
+* `Zafer Cakmak `_
+* `Kevin Porterfield `_
+* `Robert Martin `_
+* `Director `_
+* `Stéphane Klein `_
+* `Andrew Chen `_
+* `Benjamin Abel `_
+* `Pami Ketolainen `_
+* `Hamdi `_
+* `michas2 `_
+* `Francis Devereux `_
+* `Andrew Chen `_
+* `Egil Moeller `_
+* `Jerry Zhenlei Cai `_
+* `Dmitry `_
+* `Ruslan Keba `_
+* `Vanessa Hänni `_
+* `Vadim Sikora `_
+* `Zhe Li `_
+
+Translations
+------------
+Thanks for the help to all translators.
+If you believe you were incorrectly missed out of this list,
+please let us know at support@askbot.com.
+
+* Mike Chen, Sailing Cai, suyu8776 - Chinese
+* Bruno Sarlo, Adolfo Fitoria, Francisco Espinoza - Spanish
+* Evgeny Kalinin, Andrey Komrachkov - Russian
+* Evgeny Fadeev - English
+* Oktay Yildiz, Onur Mat, Cemre - Turkish
+* Jérôme Blondon (bearstech) - French
+* Pekka Gaiser, Edur - German
+* Pekka Järvinen - Finnish
+* Adi Robian - Romanian
+* `Stefano Mancini `_, Dario Ghilardi, Federico Poloni, `Luca Ferroni `_ - Italian
+* Cong It, Nguyen Long, ppranhh - Vietnamese
+* `Jordi Bofill `_ - Catalan
+* Vašek Chalupníček - Chech
+* Dario Kolak - Croatian
+.
diff --git a/askbot/doc/source/create-database.rst b/askbot/doc/source/create-database.rst
new file mode 100644
index 0000000000..9b262af784
--- /dev/null
+++ b/askbot/doc/source/create-database.rst
@@ -0,0 +1,64 @@
+.. _create-database:
+
+==========================
+Create database for Askbot
+==========================
+
+Askbot has been successfully tested with `MySQL` and `PostgreSQL` databases.
+
+PostgreSQL
+----------
+PostgreSQL is the preferred database for Askbot - because it offers great
+full text search functionality and supports transactions at the same time.
+
+To use postgresql - install it (please see documentation elsewhere).
+
+After you have the database inself, add python bindingngs to postgresql::
+
+ pip install psycopg2
+
+To create a database, log in to postgresql as user postgres, create a user (if necessary), create a database, and enable the user account to log in to the database::
+
+ create role someuser with createdb login encrypted password `somepassword`;
+ create database somedb with owner=someuser;
+
+Then edit file ``pg_hba.conf`` within your database installation and add a line as the first non-comment line or near, to make sure that this rule takes precedence::
+
+ local somedb someuser md5
+
+Then restart the database server (probably as root user), the command may be::
+
+ /etc/init.d/postgresql restart
+
+MySQL
+-----
+This section assumes that MySQL is installed and is up and running.
+
+Once you have the database installed (please see manual elsewhere), add python bindings for mysql::
+
+ pip install mysql-python
+
+Database can be prepared via your hosting control panel, if available, or
+can be created manually as shown below (using a high privilege MySQL account):
+
+Log in to mysql::
+
+ mysql -u username -p
+
+Then type these two commands (note that fake `dbname`, `dbuser`, and `dbpassword` are used in this example)::
+
+ create database askbot DEFAULT CHARACTER SET UTF8 COLLATE utf8_general_ci;
+ grant all privileges on dbname.* to dbuser@localhost identified by 'dbpassword';
+
+Again, please remember to create real usernname, database name and password and write them down. These
+credentials will go into the file `settings.py`_ - the main configuration file of the Django application.
+
+.. note::
+
+ Notation `dbuser@hostname` is important for security - normally you want to restrict access to
+ the database to certain hosts only. `localhost` entry ensures that database cannot be accessed
+ from remote hosts at all.
+
+.. _Python: http://www.python.org/download/
+.. _MySQL: http://www.mysql.com/downloads/mysql/#downloads
+.. _settings.py: http://github.com/ASKBOT/askbot-devel/blob/master/askbot/setup_templates/settings.py
diff --git a/askbot/doc/source/cron-jobs.rst b/askbot/doc/source/cron-jobs.rst
new file mode 100644
index 0000000000..db96a532b9
--- /dev/null
+++ b/askbot/doc/source/cron-jobs.rst
@@ -0,0 +1,16 @@
+==========================================
+Automation of maintenance jobs with cron
+==========================================
+
+There are routine tasks that should be performed periodically
+from the command line. They can be automated via cron_ jobs
+
+File askbot_cron_job_ has a sample script that can be run say hourly
+
+The script currently does two things: (1) sends delayed email alerts and
+(2) awards badges. These two actions can be separated into two separate jobs,
+if necessary
+
+.. _cron: http://www.unixgeeks.org/security/newbie/unix/cron-1.html
+.. _askbot_cron_job: http://github.com/ASKBOT/askbot-devel/blob/master/askbot/cron/askbot_cron_job
+
diff --git a/askbot/doc/source/customizing-skin-in-askbot.rst b/askbot/doc/source/customizing-skin-in-askbot.rst
new file mode 100644
index 0000000000..f8cf82a53c
--- /dev/null
+++ b/askbot/doc/source/customizing-skin-in-askbot.rst
@@ -0,0 +1,346 @@
+=====================
+Skin system in Askbot
+=====================
+
+This document aims to help web designers customize skin for their askbot instances.
+
+Askbot has own skinning system, where current skin can be switched on the fly
+in :ref:`live settings `, section "Skin and User Interface Settings".
+Currently, there is only one skin available, called "default".
+
+All (with minor exceptions) templates are written with Jinja2 templating engine,
+very similar to Django, but with advantages
+of better performance and flexibility of coding.
+
+What are skins made of
+======================
+
+Skin is a directory, pointed to by ``ASKBOT_EXTRA_SKINS_DIR``
+parameter of your ``settings.py`` file.
+
+Skin name is the same as the name of its directory,
+here is an example of a skin directory structure::
+
+ myskin/
+ templates/ #all the template files
+ media/ #all the media files
+ style/ #css files
+ images/ #images
+ js/ #javascript files
+
+Some template names and their locations are hardcoded in the
+python code of askbot. In addition, there are templates that are
+included
+
+A skin consists of HTML templates, css and javascript
+and all of these resources are looked up first within currently active skin,
+then in "default".
+
+Name "default" is reserved and should not be used to
+name custom skins.
+
+Current state of skin system
+============================
+
+Default skin is still somewhat in flux.
+In addition to refactorings of HTML,
+skins may receive additional template context variables.
+
+A caveat is that some names of the element selectors might still change so the customization may require some maintenance upon upgrades.
+
+
+Possible approaches to customize skins
+======================================
+
+There are several methods at your disposal,
+would you like to customize askbot's appearance.
+
+.. deprecated:: 0.7.21
+ Whenever you change any media files on disk, it will be necessary
+ to increment "skin media revision number" in the
+ skin settings and restart the app,
+ so that the change goes past the browser caches.
+ This requirement will be removed in the future.
+
+Customization via ``settings`` user interface
+---------------------------------------------
+Some customizations can be done via the :ref:`live settings `,
+section "Skin and User Interface settings":
+
+* change site logo
+* change favicon
+* change password login button, if you use the builtin authentication system
+* select current skin
+* add custom contents to the HTML
+* disable or customize the page footer
+* add custom css
+* add custom javascript
+
+.. note::
+ these settings are stored in the database, therefore
+ remember to back it up. Also, if you change these settings
+ it is not necessary to increment the skin revision number.
+
+Customization via editing ``style/extra.css``
+---------------------------------------------
+In this method you will not need to edit any askbot's files.
+The ``extra.css`` file is not distributed with askbot, but can be
+added by the site administrators wishing to add their own
+css rules to those shipped with askbot.
+
+You can create a new skin in one of the directories reserved for the skins,
+then place all of your custom ``css`` rules
+into a file ``style/extra.css`` within the skin directory or just add
+``extra.css`` to the default skin.
+
+If necessary, add your custom images to ``images/`` within the same skin directory.
+
+Deeper customization by editing default skin
+--------------------------------------------
+Since the default skin still will change (a major redesign is expected),
+the best method for deeper customization
+is via use git revision control on a clone of the askbot
+master repository. It does require some knowledge of git system.
+
+If you plan to do this, firstly, install askbot from the repository.
+In addition, it will help if your copy of askbot code is installed
+in the django project directory (use ``python setup.py develop`` method
+to install askbot in the first place).
+
+Then edit anything in directories ``askbot/templates`` and ``askbot/media``
+and commit to your own repository.
+
+If the askbot app is installed in the `site-packages` or `dist-packages`
+of your sitewide python system, or your virtual environment,
+then it is not very convinient to tweak the skin,
+as the file path may be long and files may be writable only
+by from the root account.
+
+**IMPORTANT:** Do not edit file style.css manually, instead edit the
+source style.less, written in the `lesscss `_ format.
+See also: :ref:`customizing-style-css-file-in-askbot`.
+
+Create a custom skin in a new directory
+---------------------------------------
+This is technically possible, but not advisable
+because a redesign of default skin is pending.
+After the redesign your custom skins may be difficult
+to update.
+
+If you still wish to follow this option,
+name all directories and files the same way as
+in the "default" skin, as some template file names are
+hard-coded in the askbot's python code.
+
+Add setting ``ASKBOT_EXTRA_SKINS_DIR`` to your ``settings.py`` file
+and set its value to the directory with your additional skins.
+
+For example::
+
+ ASKBOT_EXTRA_SKINS_DIR = '/home/myname/my_askbot_themes'
+
+And your directory structure might be::
+
+ /home/myname/my_askbot_themes/
+ /my_theme
+ /templates
+ /media
+
+If you are planning to seriously recode the skin -
+it will be worthwhile learning the ``git`` system
+and just follow the recipe described in the previous section -
+direct editing of the "default" skin.
+Git makes this task quite simple and manageable.
+
+Skin templates
+==============
+
+The first template to look at is `askbot/templates/base.html`, it is quite simple and you can substantially change the appearance by modifying that template in the combination with adding some custom css.
+
+More detailed description of templates will follow.
+
+Page classes
+============
+
+Some pages in askbot have classes assigned to the HTML ```` element,
+to facilitate styling.
+Eventually all more pages will have dedicated class names.
+These are not set in stone yet.
+
++----------------------------+------------------------+
+| page url | class name |
++============================+========================+
+| /questions/ | main-page |
++----------------------------+------------------------+
+| /questions/ask/ | ask-page |
++----------------------------+------------------------+
+| /tags | tags-page |
++----------------------------+------------------------+
+| /question// | question-page |
++----------------------------+------------------------+
+| /questions//revisions | revisions-page |
++----------------------------+------------------------+
+| /questions//edit | question-edit-page |
++----------------------------+------------------------+
+| /answers//revisions | revisions-page |
++----------------------------+------------------------+
+| /users/ | users-page |
++----------------------------+------------------------+
+| /users//slug | user-profile-page |
++----------------------------+------------------------+
+| /users//edit (bug!) | user-profile-edit-page |
++----------------------------+------------------------+
+| /account/signin/ | openid-signin |
++----------------------------+------------------------+
+| /avatar/change/ | avatar-page |
++----------------------------+------------------------+
+| /about/ | meta |
+| /badges/ | |
+| /badges// | |
+| /account/logout/ | |
+| /faq/ | |
+| /feedback/ | |
++----------------------------+------------------------+
+
+Template Distrubution.
+======================
+
+Layouts
+-------
+
+The general template layout is controlled by a few files described below:
+
++------------------------------------+------------------------------------------------------+
+| Template File | Description |
++====================================+======================================================+
+| base.html | This is the base template, a container to call all |
+| | the template files required. |
++------------------------------------+------------------------------------------------------+
+| one_column_body.html | This is a base layout for one column style pages. |
++------------------------------------+------------------------------------------------------+
+| two_column_body.html | This is a base layout for two column style pages. |
++------------------------------------+------------------------------------------------------+
+| widgets/answer_edit_tips.html | Contains text displayed as "Answer Edit Tips" in the |
+| | answer edit page. |
++------------------------------------+------------------------------------------------------+
+| widgets/ask_form.html | Contains the form to ask a question. |
++------------------------------------+------------------------------------------------------+
+| widgets/bottom_scripts.html | Contains javascript calls and some javascript |
+| | functions needed for askbot this is included at the |
+| | bottom of every page. |
++------------------------------------+------------------------------------------------------+
+| widgets/editor_data.html | Contains data necessary for the post editor this is |
+| | included in block endjs. |
++------------------------------------+------------------------------------------------------+
+| widgets/footer.html | Contains the html displayed on the footer. |
++------------------------------------+------------------------------------------------------+
+| widgets/header.html | Contains the header section of the web. Normaly |
+| | includes the site logo and navitation tools. |
++------------------------------------+------------------------------------------------------+
+| widgets/mandatory_tags_js.html | Javascript functions for mandatory tags. |
++------------------------------------+------------------------------------------------------+
+| widgets/paginator.html | Renders the paginator in the main page. |
++------------------------------------+------------------------------------------------------+
+| widgets/question_edit_tips.html | Contains text displayed as "Question Edit Tips" in |
+| | the question edit page. |
++------------------------------------+------------------------------------------------------+
+| widgets/secondary_header.html | Containter for the search bar section. |
++------------------------------------+------------------------------------------------------+
+| widgets/system_messages.html | Containter for notification messages in the top of |
+| | the page. |
++------------------------------------+------------------------------------------------------+
+| widgets/user_navigation.html | User links to login/logout. |
++------------------------------------+------------------------------------------------------+
+
+Widgets
+-------
+
+Widgets are pieces of html code separated to be easily modified, they are located in the
+widgets folder and are called from several places in the templates.
+
++----------------------------+------------------------------+--------------------------------+
+| Widget name | Used in | Description |
++============================+==============================+================================+
+| ask_button.html | widgets/secondary_header.html | Just the "ask a question" |
+| | | button |
++----------------------------+------------------------------+--------------------------------+
+| answer_controls.html | question.html | Answer operation links, edit |
+| | | report as spam and more. |
++----------------------------+------------------------------+--------------------------------+
+| contributors.html | main_page/sidebar.html | Widget to display contributors |
+| | | avatars. |
++----------------------------+------------------------------+--------------------------------+
+| logo.html | widgets/header.html | Contains the site logo. |
++----------------------------+------------------------------+--------------------------------+
+| main_menu.html | widgets/secondary_header.html| Contains the main menu html |
++----------------------------+------------------------------+--------------------------------+
+| meta_nav.html | widgets/header.html | Widget for the me logo. |
++----------------------------+------------------------------+--------------------------------+
+| question_controls.html | question.html | Question operation links, edit |
+| | | report as spam and more. |
++----------------------------+------------------------------+--------------------------------+
+| question_vote_buttons.html | question.html | Vote buttons used in question |
++----------------------------+------------------------------+--------------------------------+
+| related_tags.html | main_page/sidebar.html | Question operation links, edit |
+| | | report as spam and more. |
++----------------------------+------------------------------+--------------------------------+
+| search_bar.html | widgets/secondary_header.html| Contains the search bar. |
++----------------------------+------------------------------+--------------------------------+
+| share_buttons.html | question.html | Widget to show the social |
+| | | sharing buttons. |
++----------------------------+------------------------------+--------------------------------+
+| tag_selector.html | main_page/sidebar.html | Contains the tag selector for |
+| | | search. |
++----------------------------+------------------------------+--------------------------------+
+| user_navigation.html | widgets/header.html | User navigation links like |
+| | | login, logout. |
++----------------------------+------------------------------+--------------------------------+
+
+Template per URL
+----------------
+
+According to the URL some template files are called, the detail on
+which file is called is in the following table.
+
++----------------------------+-----------------------------+--------------------------------+
+| Page url | Template file | Macros used |
++============================+=============================+================================+
+| /questions/ | main_page.html | |
++----------------------------+-----------------------------+--------------------------------+
+| /questions/ask/ | ask.html | |
++----------------------------+-----------------------------+--------------------------------+
+| /tags | tags.html | tag_widget, paginator, |
+| | | tag_cloud |
++----------------------------+-----------------------------+--------------------------------+
+| /question// | question.html | tag_widget, edit_post |
+| | | checkbox_in_div, share |
++----------------------------+-----------------------------+--------------------------------+
+| /questions//revisions | revisions.html | post_contributor_info |
++----------------------------+-----------------------------+--------------------------------+
+| /questions//edit | question-edit.html | tag_autocomplete_js, |
+| | | checkbox_in_div, |
+| | | edit_post |
++----------------------------+-----------------------------+--------------------------------+
+| /answers//revisions | revisions.html | post_contributor_info |
++----------------------------+-----------------------------+--------------------------------+
+| /users/ | users.html | users_list, paginator |
++----------------------------+-----------------------------+--------------------------------+
+| /users//slug | user_profile/user.html | |
++----------------------------+-----------------------------+--------------------------------+
+| /users//edit (bug!) | user_profile/user_edit.html | gravatar |
++----------------------------+-----------------------------+--------------------------------+
+| /account/signin/ | authopenid/signin.html | provider_buttons |
+| | | (from authopenid/macros) |
++----------------------------+-----------------------------+--------------------------------+
+| /avatar/change/ | avatar/change.html | gravatar |
++----------------------------+-----------------------------+--------------------------------+
+| /about/ | about.html | |
++----------------------------+-----------------------------+--------------------------------+
+| /badges/ | badges.html | |
++----------------------------+-----------------------------+--------------------------------+
+| /account/logout/ | authopenid/logout.html | |
++----------------------------+-----------------------------+--------------------------------+
+| /faq/ | faq.html | |
++----------------------------+-----------------------------+--------------------------------+
+| /feedback/ | feedback.html | |
++----------------------------+-----------------------------+--------------------------------+
diff --git a/askbot/doc/source/customizing-style-css-file-in-askbot.rst b/askbot/doc/source/customizing-style-css-file-in-askbot.rst
new file mode 100644
index 0000000000..65b75002a6
--- /dev/null
+++ b/askbot/doc/source/customizing-style-css-file-in-askbot.rst
@@ -0,0 +1,42 @@
+.. _customizing-style-css-file-in-askbot:
+
+====================================
+Customizing style.css file in Askbot
+====================================
+
+File `style.css` is produced by the `lesscss compiler `_ - ``lessc``.
+Secondly, `style.css` is used in production mode - with an entry
+`ASKBOT_CSS_DEVEL = True` in the `settings.py` file.
+When `ASKBOT_CSS_DEVEL` setting is absent or set to ``False``,
+the source `style.less` will be loaded and compiled by the browser.
+A side-effect of that is a possible momentary flash of unstyled content
+and some delay in the page load.
+
+`ASKBOT_CSS_DEVEL = True` is a convenient setting for the designer.
+
+Please find documentation about the lesscss format elsewhere.
+
+.. note::
+ Besides the "official" lesscss compiler, there are other
+ tools that convert .less files into .css: for example a
+ `less compiler from codekit (mac) `_
+ and a `portable SimpLESS compiler `_.
+
+Compiling lesscss files
+=======================
+
+The following command will compile the lesscss source file,
+an option -x will produce compressed css file:
+
+ lessc file.lesscss -x > file.css
+
+Installing lesscss
+==================
+
+Make sure you have recent version of `node.js `_ - latest version preferred.
+More recent versions of node come with the tool called `npm `_,
+for earlier versions ``npm`` will need to be installed manually.
+
+To install lesscss, type:
+
+ sudo npm install less
diff --git a/askbot/doc/source/debugging.rst b/askbot/doc/source/debugging.rst
new file mode 100644
index 0000000000..af865b1216
--- /dev/null
+++ b/askbot/doc/source/debugging.rst
@@ -0,0 +1,88 @@
+.. _debugging:
+
+================================================
+Debugging Askbot (and other Django applications)
+================================================
+
+This document describes techniques that can be used to debug Askbot and other Django projects
+If you discover new debugging techniques, please add here.
+
+.. _runserver:
+Use development server for debugging
+------------------------------------
+
+Django comes with a handy development webserver that can be started with the command::
+
+ python manage.py runserver
+
+With the combination of runserver,
+the :ref:`python debugger `,
+and even inserted "print" statements directly in the code
+it is possible to "look into" the program as it runs.
+
+Inspect the log file
+--------------------
+
+By default askbot will log errors into file `log/askbot.log` within the
+project directory. See what's inside that file.
+
+Note that in the production setups there are many log files - for the
+production webserver, database, etc.
+
+.. _pdb:
+Use Python debugger
+-------------------
+
+In the problematic portion of the code, insert lines::
+
+ import pdb
+ pdb.set_trace()
+
+Then fire up the :ref:`runserver ` and step through the program.
+When you see prompt starting with `(pdb)`
+type `help` and see what options there are.
+
+Use logging in code
+---------------------
+
+Please remember that log files may contain plaintext passwords, etc.
+
+Please do not add print statements - at least do not commit them to git
+because in some environments printing to stdout causes errors
+
+Instead use python logging this way::
+
+ #somewere on top of file
+ import logging
+
+ #anywhere below
+ logging.debug('this maybe works')
+ logging.error('have big error!')
+ #or even
+ logging.debug('') #this will add time, line number, function and file record
+ #sometimes useful record for call tracing on its own
+ #etc - take a look at http://docs.python.org/library/logging.html
+
+in Askbot logging is currently set up in settings.py
+please update it if you need - in older revs logging strings have less info
+
+messages of interest can be grepped out of the log file by module/file/function name
+e.g. to take out all django_authopenid logs run::
+
+ >grep 'askbot\/django_authopenid' log/django.askbot.log | sed 's/^.*MSG: //'
+
+in the example above `sed` call truncates out a long prefix
+and makes output look more meaningful
+
+Using django debug toolbar
+---------------------------
+
+Askbot works with django debug toolbar that displays a lot of useful diagnostics about
+your site.
+
+To enable the toolbar set parameter `DEBUG = True` in the `settings.py` file. Also you will
+need to add your IP address to the tuple `INTERNAL_IPS` in the same `settings.py` file.
+
+If your debugging site runs under apache server, check
+that debug toolbar media is loaded correctly through an `alias` configuration directive in
+the appropriate place of your apache configuration file.
diff --git a/askbot/doc/source/dependencies.rst b/askbot/doc/source/dependencies.rst
new file mode 100644
index 0000000000..3cd992cea2
--- /dev/null
+++ b/askbot/doc/source/dependencies.rst
@@ -0,0 +1,38 @@
+.. _dependencies:
+
+===================
+Askbot Dependencies
+===================
+
+Askbot depends on quite a few other packages. Normally those dependencies will be
+automatically resolved with setuptools (i.e. when you run `easy_install` or `python setup.py install`).
+
+However, if something does not go well - e.g.
+some dependency package site is not accessible, please
+download and install them manually:
+
+* django-1.1.2_
+* django-debug-toolbar_
+* South_
+* recaptcha-client_
+* markdown2_
+* html5lib_
+* python-openid_
+* django-keyedcache_
+* django-threaded-multihost_
+* mysql-python_
+
+If any of the provided links
+do not work please try to look up those packages or notify askbot maintainers at admin@askbot.org.
+
+.. _django-1.1.2: http://www.djangoproject.com/download/1.1.2/tarball/
+.. _django-debug-toolbar: http://github.com/robhudson/django-debug-toolbar
+.. _South: http://www.aeracode.org/releases/south/
+.. _recaptcha-client: http://code.google.com/p/django-recaptcha/
+.. _markdown2: http://code.google.com/p/python-markdown2/
+.. _html5lib: http://code.google.com/p/html5lib/
+.. _python-openid: http://github.com/openid/python-openid
+.. _django-keyedcache: http://bitbucket.org/bkroeze/django-keyedcache/src
+.. _django-threaded-multihost: http://bitbucket.org/bkroeze/django-threaded-multihost/src
+.. _mysql-python: http://sourceforge.net/projects/mysql-python/
+.. _mod_wsgi: http://code.google.com/p/modwsgi/
diff --git a/askbot/doc/source/deployment.rst b/askbot/doc/source/deployment.rst
new file mode 100644
index 0000000000..2d9403d8f6
--- /dev/null
+++ b/askbot/doc/source/deployment.rst
@@ -0,0 +1,129 @@
+.. _deployment:
+
+================
+Deploying Askbot
+================
+
+Deploying askbot (assuming that it is already installed) entails:
+
+* collecting static media files
+* setting correct file access permissions
+* configuring the webserver to work with your application
+
+This document currently explains the configuration under Apache and mod_wsgi_.
+
+Collecting static media files
+-----------------------------
+Static media must be collected into a single location with a command::
+
+ python manage.py collectstatic
+
+There are several options on where to put the static files - the simplest is
+a local directory, but it is also possible to use a dedicated static files
+storage or a CDN, for more information see django documentation about
+serving static files.
+
+Setting up file access permissions
+----------------------------------
+
+Webserver process must be able to write to the following locations within your project::
+
+ log/
+ askbot/upfiles
+
+If you know user name or the group name under which the webserver runs,
+you can make those directories writable by setting the permissons
+accordingly:
+
+For example, if you are using Linux installation of apache webserver running under
+group name 'apache' you could do the following::
+
+ cd /path/to/django-project
+ cd .. #go one level up
+ chown -R yourlogin:apache django-project
+ chmod -R g+w django-project/askbot/upfiles
+ chmod -R g+w django-project/log
+
+If your account somehow limits you from running such commands - please consult your
+system administrator.
+
+Installation under Apache/mod\_wsgi
+------------------------------------
+
+Apache/mod\_wsgi combination is the only type of deployment described in this
+document at the moment. mod_wsgi_ is currently the most resource efficient
+apache handler for the Python web applications.
+
+The main wsgi script is in the file django.wsgi_
+it does not need to be modified
+
+Configure webserver
+~~~~~~~~~~~~~~~~~~~~
+
+Settings below are not perfect but may be a good starting point::
+
+ #NOTE: the directory paths used here may be adjusted
+
+ #the following two directories must be both readable and writable by apache
+ WSGISocketPrefix /path/to/socket/sock
+ WSGIPythonEggs /var/python/eggs
+
+ #the following directory must be readable by apache
+ WSGIPythonHome /usr/local
+
+ #NOTE: all urs below will need to be adjusted if
+ #settings.FORUM_SCRIPT_ALIAS is anything other than empty string (e.g. = 'forum/')
+ #this allows "rooting" forum at http://example.com/forum, if you like
+
+ #replace with 127.0.0.1 with real IP address
+
+ ServerAdmin you@example.com
+ DocumentRoot /path/to/django-project
+ ServerName example.come
+
+ #aliases to serve static media directly
+ #will probably need adjustment
+ Alias /m/ /path/to/django-project/static/
+ Alias /upfiles/ /path/to/django-project/askbot/upfiles/
+
+ Order deny,allow
+ Allow from all
+
+
+ Order deny,allow
+ Allow from all
+
+ #must be a distinct name within your apache configuration
+ WSGIDaemonProcess askbot2
+ WSGIProcessGroup askbot2
+ WSGIScriptAlias / /path/to/django-project/django.wsgi
+ #make all admin stuff except media go through secure connection
+
+ RewriteEngine on
+ RewriteRule /admin(.*)$ https://example.com/admin$1 [L,R=301]
+
+ CustomLog /var/log/httpd/askbot/access_log common
+ ErrorLog /var/log/httpd/askbot/error_log
+ LogLevel debug
+
+ #again, replace the IP address
+
+ ServerAdmin you@example.com
+ DocumentRoot /path/to/django-project
+ ServerName example.com
+
+ RewriteEngine on
+ RewriteRule django.wsgi(.*)$ http://example.com$1 [L,R=301]
+
+ SSLEngine on
+ #your SSL keys
+ SSLCertificateFile /etc/httpd/ssl.crt/server.crt
+ SSLCertificateKeyFile /etc/httpd/ssl.key/server.key
+ Alias /admin/media/ /usr/local/lib/python2.6/site-packages/django/contrib/admin/media/
+ WSGIScriptAlias / /path/to/django-project/django.wsgi
+ CustomLog /var/log/httpd/askbot/access_log common
+ ErrorLog /var/log/httpd/askbot/error_log
+
+
+.. _mod_wsgi: http://code.google.com/p/modwsgi/
+.. _django.wsgi: http://github.com/ASKBOT/askbot-devel/blob/master/askbot/setup_templates/django.wsgi
diff --git a/askbot/doc/source/devel/askbot.admin.rst b/askbot/doc/source/devel/askbot.admin.rst
new file mode 100644
index 0000000000..335ec44407
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.admin.rst
@@ -0,0 +1,10 @@
+.. _askbot.admin:
+
+:mod:`askbot.admin`
+============
+
+.. automodule:: askbot.admin
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.auth.rst b/askbot/doc/source/devel/askbot.auth.rst
new file mode 100644
index 0000000000..90137cb3dd
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.auth.rst
@@ -0,0 +1,10 @@
+.. _askbot.auth:
+
+:mod:`askbot.auth`
+===========
+
+.. automodule:: askbot.auth
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.bin.generate_modules.rst b/askbot/doc/source/devel/askbot.bin.generate_modules.rst
new file mode 100644
index 0000000000..ff5c8c917c
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.bin.generate_modules.rst
@@ -0,0 +1,10 @@
+.. _askbot.bin.generate_modules:
+
+:mod:`askbot.bin.generate_modules`
+===========================
+
+.. automodule:: askbot.bin.generate_modules
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.bin.rst b/askbot/doc/source/devel/askbot.bin.rst
new file mode 100644
index 0000000000..84d99ee77c
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.bin.rst
@@ -0,0 +1,19 @@
+.. _askbot.bin:
+
+:mod:`askbot.bin`
+==========
+
+.. automodule:: askbot.bin
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.bin.generate_modules`
+* :ref:`askbot.bin.show_profile_stats`
+
diff --git a/askbot/doc/source/devel/askbot.bin.show_profile_stats.rst b/askbot/doc/source/devel/askbot.bin.show_profile_stats.rst
new file mode 100644
index 0000000000..53ba36bf62
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.bin.show_profile_stats.rst
@@ -0,0 +1,10 @@
+.. _askbot.bin.show_profile_stats:
+
+:mod:`askbot.bin.show_profile_stats`
+=============================
+
+.. automodule:: askbot.bin.show_profile_stats
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.conf.email.rst b/askbot/doc/source/devel/askbot.conf.email.rst
new file mode 100644
index 0000000000..01dd0693ff
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.conf.email.rst
@@ -0,0 +1,10 @@
+.. _askbot.conf.email:
+
+:mod:`askbot.conf.email`
+=================
+
+.. automodule:: askbot.conf.email
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.conf.external_keys.rst b/askbot/doc/source/devel/askbot.conf.external_keys.rst
new file mode 100644
index 0000000000..8c0d586179
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.conf.external_keys.rst
@@ -0,0 +1,10 @@
+.. _askbot.conf.external_keys:
+
+:mod:`askbot.conf.external_keys`
+=========================
+
+.. automodule:: askbot.conf.external_keys
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.conf.flatpages.rst b/askbot/doc/source/devel/askbot.conf.flatpages.rst
new file mode 100644
index 0000000000..a33b5f64cf
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.conf.flatpages.rst
@@ -0,0 +1,10 @@
+.. _askbot.conf.flatpages:
+
+:mod:`askbot.conf.flatpages`
+=====================
+
+.. automodule:: askbot.conf.flatpages
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.conf.forum_data_rules.rst b/askbot/doc/source/devel/askbot.conf.forum_data_rules.rst
new file mode 100644
index 0000000000..f373c2a0b5
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.conf.forum_data_rules.rst
@@ -0,0 +1,10 @@
+.. _askbot.conf.forum_data_rules:
+
+:mod:`askbot.conf.forum_data_rules`
+============================
+
+.. automodule:: askbot.conf.forum_data_rules
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.conf.minimum_reputation.rst b/askbot/doc/source/devel/askbot.conf.minimum_reputation.rst
new file mode 100644
index 0000000000..17a84e0f21
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.conf.minimum_reputation.rst
@@ -0,0 +1,10 @@
+.. _askbot.conf.minimum_reputation:
+
+:mod:`askbot.conf.minimum_reputation`
+==============================
+
+.. automodule:: askbot.conf.minimum_reputation
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.conf.reputation_changes.rst b/askbot/doc/source/devel/askbot.conf.reputation_changes.rst
new file mode 100644
index 0000000000..0d7879bf40
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.conf.reputation_changes.rst
@@ -0,0 +1,10 @@
+.. _askbot.conf.reputation_changes:
+
+:mod:`askbot.conf.reputation_changes`
+==============================
+
+.. automodule:: askbot.conf.reputation_changes
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.conf.rst b/askbot/doc/source/devel/askbot.conf.rst
new file mode 100644
index 0000000000..3aab757d4a
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.conf.rst
@@ -0,0 +1,29 @@
+.. _askbot.conf:
+
+:mod:`askbot.conf`
+===========
+
+.. automodule:: askbot.conf
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.conf.email`
+* :ref:`askbot.conf.external_keys`
+* :ref:`askbot.conf.flatpages`
+* :ref:`askbot.conf.forum_data_rules`
+* :ref:`askbot.conf.minimum_reputation`
+* :ref:`askbot.conf.reputation_changes`
+* :ref:`askbot.conf.settings_wrapper`
+* :ref:`askbot.conf.site_settings`
+* :ref:`askbot.conf.skin_counter_settings`
+* :ref:`askbot.conf.skin_general_settings`
+* :ref:`askbot.conf.user_settings`
+* :ref:`askbot.conf.vote_rules`
+
diff --git a/askbot/doc/source/devel/askbot.conf.settings_wrapper.rst b/askbot/doc/source/devel/askbot.conf.settings_wrapper.rst
new file mode 100644
index 0000000000..af95d15cc1
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.conf.settings_wrapper.rst
@@ -0,0 +1,10 @@
+.. _askbot.conf.settings_wrapper:
+
+:mod:`askbot.conf.settings_wrapper`
+============================
+
+.. automodule:: askbot.conf.settings_wrapper
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.conf.site_settings.rst b/askbot/doc/source/devel/askbot.conf.site_settings.rst
new file mode 100644
index 0000000000..0cff38e408
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.conf.site_settings.rst
@@ -0,0 +1,10 @@
+.. _askbot.conf.site_settings:
+
+:mod:`askbot.conf.site_settings`
+=========================
+
+.. automodule:: askbot.conf.site_settings
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.conf.skin_counter_settings.rst b/askbot/doc/source/devel/askbot.conf.skin_counter_settings.rst
new file mode 100644
index 0000000000..843a4e5bcf
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.conf.skin_counter_settings.rst
@@ -0,0 +1,10 @@
+.. _askbot.conf.skin_counter_settings:
+
+:mod:`askbot.conf.skin_counter_settings`
+=================================
+
+.. automodule:: askbot.conf.skin_counter_settings
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.conf.skin_general_settings.rst b/askbot/doc/source/devel/askbot.conf.skin_general_settings.rst
new file mode 100644
index 0000000000..e6b7070f71
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.conf.skin_general_settings.rst
@@ -0,0 +1,10 @@
+.. _askbot.conf.skin_general_settings:
+
+:mod:`askbot.conf.skin_general_settings`
+=================================
+
+.. automodule:: askbot.conf.skin_general_settings
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.conf.user_settings.rst b/askbot/doc/source/devel/askbot.conf.user_settings.rst
new file mode 100644
index 0000000000..7a02b95e49
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.conf.user_settings.rst
@@ -0,0 +1,10 @@
+.. _askbot.conf.user_settings:
+
+:mod:`askbot.conf.user_settings`
+=========================
+
+.. automodule:: askbot.conf.user_settings
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.conf.vote_rules.rst b/askbot/doc/source/devel/askbot.conf.vote_rules.rst
new file mode 100644
index 0000000000..613af09861
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.conf.vote_rules.rst
@@ -0,0 +1,10 @@
+.. _askbot.conf.vote_rules:
+
+:mod:`askbot.conf.vote_rules`
+======================
+
+.. automodule:: askbot.conf.vote_rules
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.const.message_keys.rst b/askbot/doc/source/devel/askbot.const.message_keys.rst
new file mode 100644
index 0000000000..29e9b8b121
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.const.message_keys.rst
@@ -0,0 +1,10 @@
+.. _askbot.const.message_keys:
+
+:mod:`askbot.const.message_keys`
+=========================
+
+.. automodule:: askbot.const.message_keys
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.const.rst b/askbot/doc/source/devel/askbot.const.rst
new file mode 100644
index 0000000000..c9e7755830
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.const.rst
@@ -0,0 +1,18 @@
+.. _askbot.const:
+
+:mod:`askbot.const`
+============
+
+.. automodule:: askbot.const
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.const.message_keys`
+
diff --git a/askbot/doc/source/devel/askbot.context.rst b/askbot/doc/source/devel/askbot.context.rst
new file mode 100644
index 0000000000..991e077545
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.context.rst
@@ -0,0 +1,10 @@
+.. _askbot.context:
+
+:mod:`askbot.context`
+==============
+
+.. automodule:: askbot.context
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.deployment.dialogs.rst b/askbot/doc/source/devel/askbot.deployment.dialogs.rst
new file mode 100644
index 0000000000..2389a4754e
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.deployment.dialogs.rst
@@ -0,0 +1,10 @@
+.. _askbot.deployment.dialogs:
+
+:mod:`askbot.deployment.dialogs`
+=========================
+
+.. automodule:: askbot.deployment.dialogs
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.deployment.messages.rst b/askbot/doc/source/devel/askbot.deployment.messages.rst
new file mode 100644
index 0000000000..b4133d8665
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.deployment.messages.rst
@@ -0,0 +1,10 @@
+.. _askbot.deployment.messages:
+
+:mod:`askbot.deployment.messages`
+==========================
+
+.. automodule:: askbot.deployment.messages
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.deployment.path_utils.rst b/askbot/doc/source/devel/askbot.deployment.path_utils.rst
new file mode 100644
index 0000000000..d3fba5a334
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.deployment.path_utils.rst
@@ -0,0 +1,10 @@
+.. _askbot.deployment.path_utils:
+
+:mod:`askbot.deployment.path_utils`
+============================
+
+.. automodule:: askbot.deployment.path_utils
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.deployment.rst b/askbot/doc/source/devel/askbot.deployment.rst
new file mode 100644
index 0000000000..d2b6fe92e9
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.deployment.rst
@@ -0,0 +1,20 @@
+.. _askbot.deployment:
+
+:mod:`askbot.deployment`
+=================
+
+.. automodule:: askbot.deployment
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.deployment.dialogs`
+* :ref:`askbot.deployment.messages`
+* :ref:`askbot.deployment.path_utils`
+
diff --git a/askbot/doc/source/devel/askbot.deps.grapefruit.rst b/askbot/doc/source/devel/askbot.deps.grapefruit.rst
new file mode 100644
index 0000000000..eaa3dbbeba
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.deps.grapefruit.rst
@@ -0,0 +1,10 @@
+.. _askbot.deps.grapefruit:
+
+:mod:`askbot.deps.grapefruit`
+======================
+
+.. automodule:: askbot.deps.grapefruit
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.deps.rst b/askbot/doc/source/devel/askbot.deps.rst
new file mode 100644
index 0000000000..6c0df669ca
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.deps.rst
@@ -0,0 +1,28 @@
+.. _askbot.deps:
+
+:mod:`askbot.deps`
+===========
+
+.. automodule:: askbot.deps
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.deps.grapefruit`
+
+.. _packages::
+
+:mod:`Subpackages`
+-----------
+
+
+* :ref:`askbot.deps.django_authopenid`
+* :ref:`askbot.deps.livesettings`
+* :ref:`askbot.deps.openid`
+* :ref:`askbot.deps.recaptcha_django`
diff --git a/askbot/doc/source/devel/askbot.doc.source.conf.rst b/askbot/doc/source/devel/askbot.doc.source.conf.rst
new file mode 100644
index 0000000000..bf78752b50
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.doc.source.conf.rst
@@ -0,0 +1,10 @@
+.. _askbot.doc.source.conf:
+
+:mod:`askbot.doc.source.conf`
+======================
+
+.. automodule:: askbot.doc.source.conf
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.feed.rst b/askbot/doc/source/devel/askbot.feed.rst
new file mode 100644
index 0000000000..96e944a16f
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.feed.rst
@@ -0,0 +1,10 @@
+.. _askbot.feed:
+
+:mod:`askbot.feed`
+===========
+
+.. automodule:: askbot.feed
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.forms.rst b/askbot/doc/source/devel/askbot.forms.rst
new file mode 100644
index 0000000000..20558ec4a6
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.forms.rst
@@ -0,0 +1,10 @@
+.. _askbot.forms:
+
+:mod:`askbot.forms`
+============
+
+.. automodule:: askbot.forms
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.importers.rst b/askbot/doc/source/devel/askbot.importers.rst
new file mode 100644
index 0000000000..d1c2005330
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.importers.rst
@@ -0,0 +1,24 @@
+.. _askbot.importers:
+
+:mod:`askbot.importers`
+================
+
+.. automodule:: askbot.importers
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+
+.. _packages::
+
+:mod:`Subpackages`
+-----------
+
+
+* :ref:`askbot.importers.stackexchange`
diff --git a/askbot/doc/source/devel/askbot.importers.stackexchange.management.commands.load_stackexchange.rst b/askbot/doc/source/devel/askbot.importers.stackexchange.management.commands.load_stackexchange.rst
new file mode 100644
index 0000000000..56e2c19891
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.importers.stackexchange.management.commands.load_stackexchange.rst
@@ -0,0 +1,10 @@
+.. _askbot.importers.stackexchange.management.commands.load_stackexchange:
+
+:mod:`askbot.importers.stackexchange.management.commands.load_stackexchange`
+=====================================================================
+
+.. automodule:: askbot.importers.stackexchange.management.commands.load_stackexchange
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.importers.stackexchange.management.commands.rst b/askbot/doc/source/devel/askbot.importers.stackexchange.management.commands.rst
new file mode 100644
index 0000000000..c7d5a0e4dc
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.importers.stackexchange.management.commands.rst
@@ -0,0 +1,18 @@
+.. _askbot.importers.stackexchange.management.commands:
+
+:mod:`askbot.importers.stackexchange.management.commands`
+==================================================
+
+.. automodule:: askbot.importers.stackexchange.management.commands
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.importers.stackexchange.management.commands.load_stackexchange`
+
diff --git a/askbot/doc/source/devel/askbot.importers.stackexchange.management.rst b/askbot/doc/source/devel/askbot.importers.stackexchange.management.rst
new file mode 100644
index 0000000000..d399d80918
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.importers.stackexchange.management.rst
@@ -0,0 +1,24 @@
+.. _askbot.importers.stackexchange.management:
+
+:mod:`askbot.importers.stackexchange.management`
+=========================================
+
+.. automodule:: askbot.importers.stackexchange.management
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+
+.. _packages::
+
+:mod:`Subpackages`
+-----------
+
+
+* :ref:`askbot.importers.stackexchange.management.commands`
diff --git a/askbot/doc/source/devel/askbot.importers.stackexchange.models.rst b/askbot/doc/source/devel/askbot.importers.stackexchange.models.rst
new file mode 100644
index 0000000000..62a7770376
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.importers.stackexchange.models.rst
@@ -0,0 +1,10 @@
+.. _askbot.importers.stackexchange.models:
+
+:mod:`askbot.importers.stackexchange.models`
+=====================================
+
+.. automodule:: askbot.importers.stackexchange.models
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.importers.stackexchange.parse_models.rst b/askbot/doc/source/devel/askbot.importers.stackexchange.parse_models.rst
new file mode 100644
index 0000000000..57ffe6c3f5
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.importers.stackexchange.parse_models.rst
@@ -0,0 +1,10 @@
+.. _askbot.importers.stackexchange.parse_models:
+
+:mod:`askbot.importers.stackexchange.parse_models`
+===========================================
+
+.. automodule:: askbot.importers.stackexchange.parse_models
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.importers.stackexchange.rst b/askbot/doc/source/devel/askbot.importers.stackexchange.rst
new file mode 100644
index 0000000000..1a38a17341
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.importers.stackexchange.rst
@@ -0,0 +1,26 @@
+.. _askbot.importers.stackexchange:
+
+:mod:`askbot.importers.stackexchange`
+==============================
+
+.. automodule:: askbot.importers.stackexchange
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.importers.stackexchange.models`
+* :ref:`askbot.importers.stackexchange.parse_models`
+
+.. _packages::
+
+:mod:`Subpackages`
+-----------
+
+
+* :ref:`askbot.importers.stackexchange.management`
diff --git a/askbot/doc/source/devel/askbot.management.commands.add_admin.rst b/askbot/doc/source/devel/askbot.management.commands.add_admin.rst
new file mode 100644
index 0000000000..e4ea3cfeb6
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.add_admin.rst
@@ -0,0 +1,10 @@
+.. _askbot.management.commands.add_admin:
+
+:mod:`askbot.management.commands.add_admin`
+====================================
+
+.. automodule:: askbot.management.commands.add_admin
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.management.commands.base_command.rst b/askbot/doc/source/devel/askbot.management.commands.base_command.rst
new file mode 100644
index 0000000000..85122b162a
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.base_command.rst
@@ -0,0 +1,10 @@
+.. _askbot.management.commands.base_command:
+
+:mod:`askbot.management.commands.base_command`
+=======================================
+
+.. automodule:: askbot.management.commands.base_command
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.management.commands.clean_award_badges.rst b/askbot/doc/source/devel/askbot.management.commands.clean_award_badges.rst
new file mode 100644
index 0000000000..6cc9ad430c
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.clean_award_badges.rst
@@ -0,0 +1,10 @@
+.. _askbot.management.commands.clean_award_badges:
+
+:mod:`askbot.management.commands.clean_award_badges`
+=============================================
+
+.. automodule:: askbot.management.commands.clean_award_badges
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.management.commands.message_to_everyone.rst b/askbot/doc/source/devel/askbot.management.commands.message_to_everyone.rst
new file mode 100644
index 0000000000..398f355029
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.message_to_everyone.rst
@@ -0,0 +1,10 @@
+.. _askbot.management.commands.message_to_everyone:
+
+:mod:`askbot.management.commands.message_to_everyone`
+==============================================
+
+.. automodule:: askbot.management.commands.message_to_everyone
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.management.commands.multi_award_badges.rst b/askbot/doc/source/devel/askbot.management.commands.multi_award_badges.rst
new file mode 100644
index 0000000000..510763f89d
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.multi_award_badges.rst
@@ -0,0 +1,10 @@
+.. _askbot.management.commands.multi_award_badges:
+
+:mod:`askbot.management.commands.multi_award_badges`
+=============================================
+
+.. automodule:: askbot.management.commands.multi_award_badges
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.management.commands.once_award_badges.rst b/askbot/doc/source/devel/askbot.management.commands.once_award_badges.rst
new file mode 100644
index 0000000000..8f270dd645
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.once_award_badges.rst
@@ -0,0 +1,10 @@
+.. _askbot.management.commands.once_award_badges:
+
+:mod:`askbot.management.commands.once_award_badges`
+============================================
+
+.. automodule:: askbot.management.commands.once_award_badges
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.management.commands.pg_base_command.rst b/askbot/doc/source/devel/askbot.management.commands.pg_base_command.rst
new file mode 100644
index 0000000000..76ec282789
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.pg_base_command.rst
@@ -0,0 +1,10 @@
+.. _askbot.management.commands.pg_base_command:
+
+:mod:`askbot.management.commands.pg_base_command`
+==========================================
+
+.. automodule:: askbot.management.commands.pg_base_command
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.management.commands.pg_clean_award_badges.rst b/askbot/doc/source/devel/askbot.management.commands.pg_clean_award_badges.rst
new file mode 100644
index 0000000000..cda44a1c72
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.pg_clean_award_badges.rst
@@ -0,0 +1,10 @@
+.. _askbot.management.commands.pg_clean_award_badges:
+
+:mod:`askbot.management.commands.pg_clean_award_badges`
+================================================
+
+.. automodule:: askbot.management.commands.pg_clean_award_badges
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.management.commands.pg_multi_award_badges.rst b/askbot/doc/source/devel/askbot.management.commands.pg_multi_award_badges.rst
new file mode 100644
index 0000000000..eba77abebb
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.pg_multi_award_badges.rst
@@ -0,0 +1,10 @@
+.. _askbot.management.commands.pg_multi_award_badges:
+
+:mod:`askbot.management.commands.pg_multi_award_badges`
+================================================
+
+.. automodule:: askbot.management.commands.pg_multi_award_badges
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.management.commands.pg_once_award_badges.rst b/askbot/doc/source/devel/askbot.management.commands.pg_once_award_badges.rst
new file mode 100644
index 0000000000..837b92c974
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.pg_once_award_badges.rst
@@ -0,0 +1,10 @@
+.. _askbot.management.commands.pg_once_award_badges:
+
+:mod:`askbot.management.commands.pg_once_award_badges`
+===============================================
+
+.. automodule:: askbot.management.commands.pg_once_award_badges
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.management.commands.remove_admin.rst b/askbot/doc/source/devel/askbot.management.commands.remove_admin.rst
new file mode 100644
index 0000000000..aceef40846
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.remove_admin.rst
@@ -0,0 +1,10 @@
+.. _askbot.management.commands.remove_admin:
+
+:mod:`askbot.management.commands.remove_admin`
+=======================================
+
+.. automodule:: askbot.management.commands.remove_admin
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.management.commands.rst b/askbot/doc/source/devel/askbot.management.commands.rst
new file mode 100644
index 0000000000..e8dbde066c
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.rst
@@ -0,0 +1,31 @@
+.. _askbot.management.commands:
+
+:mod:`askbot.management.commands`
+==========================
+
+.. automodule:: askbot.management.commands
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.management.commands.base_command`
+* :ref:`askbot.management.commands.clean_award_badges`
+* :ref:`askbot.management.commands.message_to_everyone`
+* :ref:`askbot.management.commands.multi_award_badges`
+* :ref:`askbot.management.commands.once_award_badges`
+* :ref:`askbot.management.commands.pg_base_command`
+* :ref:`askbot.management.commands.pg_clean_award_badges`
+* :ref:`askbot.management.commands.pg_multi_award_badges`
+* :ref:`askbot.management.commands.pg_once_award_badges`
+* :ref:`askbot.management.commands.sample_command`
+* :ref:`askbot.management.commands.send_email_alerts`
+* :ref:`askbot.management.commands.subscribe_everyone`
+* :ref:`askbot.management.commands.add_admin`
+* :ref:`askbot.management.commands.remove_admin`
+
diff --git a/askbot/doc/source/devel/askbot.management.commands.sample_command.rst b/askbot/doc/source/devel/askbot.management.commands.sample_command.rst
new file mode 100644
index 0000000000..87cae37f33
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.sample_command.rst
@@ -0,0 +1,10 @@
+.. _askbot.management.commands.sample_command:
+
+:mod:`askbot.management.commands.sample_command`
+=========================================
+
+.. automodule:: askbot.management.commands.sample_command
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.management.commands.send_email_alerts.rst b/askbot/doc/source/devel/askbot.management.commands.send_email_alerts.rst
new file mode 100644
index 0000000000..03319f6156
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.send_email_alerts.rst
@@ -0,0 +1,10 @@
+.. _askbot.management.commands.send_email_alerts:
+
+:mod:`askbot.management.commands.send_email_alerts`
+============================================
+
+.. automodule:: askbot.management.commands.send_email_alerts
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.management.commands.subscribe_everyone.rst b/askbot/doc/source/devel/askbot.management.commands.subscribe_everyone.rst
new file mode 100644
index 0000000000..7527cb8e72
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.commands.subscribe_everyone.rst
@@ -0,0 +1,10 @@
+.. _askbot.management.commands.subscribe_everyone:
+
+:mod:`askbot.management.commands.subscribe_everyone`
+=============================================
+
+.. automodule:: askbot.management.commands.subscribe_everyone
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.management.rst b/askbot/doc/source/devel/askbot.management.rst
new file mode 100644
index 0000000000..0bc0b21bf1
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.management.rst
@@ -0,0 +1,24 @@
+.. _askbot.management:
+
+:mod:`askbot.management`
+=================
+
+.. automodule:: askbot.management
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+
+.. _packages::
+
+:mod:`Subpackages`
+-----------
+
+
+* :ref:`askbot.management.commands`
diff --git a/askbot/doc/source/devel/askbot.middleware.anon_user.rst b/askbot/doc/source/devel/askbot.middleware.anon_user.rst
new file mode 100644
index 0000000000..5dc10faf84
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.middleware.anon_user.rst
@@ -0,0 +1,10 @@
+.. _askbot.middleware.anon_user:
+
+:mod:`askbot.middleware.anon_user`
+===========================
+
+.. automodule:: askbot.middleware.anon_user
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.middleware.cancel.rst b/askbot/doc/source/devel/askbot.middleware.cancel.rst
new file mode 100644
index 0000000000..f00cab026d
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.middleware.cancel.rst
@@ -0,0 +1,10 @@
+.. _askbot.middleware.cancel:
+
+:mod:`askbot.middleware.cancel`
+========================
+
+.. automodule:: askbot.middleware.cancel
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.middleware.pagesize.rst b/askbot/doc/source/devel/askbot.middleware.pagesize.rst
new file mode 100644
index 0000000000..36170298cb
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.middleware.pagesize.rst
@@ -0,0 +1,10 @@
+.. _askbot.middleware.pagesize:
+
+:mod:`askbot.middleware.pagesize`
+==========================
+
+.. automodule:: askbot.middleware.pagesize
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.middleware.rst b/askbot/doc/source/devel/askbot.middleware.rst
new file mode 100644
index 0000000000..ce1551fcd1
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.middleware.rst
@@ -0,0 +1,22 @@
+.. _askbot.middleware:
+
+:mod:`askbot.middleware`
+=================
+
+.. automodule:: askbot.middleware
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.middleware.anon_user`
+* :ref:`askbot.middleware.cancel`
+* :ref:`askbot.middleware.pagesize`
+* :ref:`askbot.middleware.spaceless`
+* :ref:`askbot.middleware.view_log`
+
diff --git a/askbot/doc/source/devel/askbot.middleware.spaceless.rst b/askbot/doc/source/devel/askbot.middleware.spaceless.rst
new file mode 100644
index 0000000000..e75f217fe8
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.middleware.spaceless.rst
@@ -0,0 +1,10 @@
+.. _askbot.middleware.spaceless:
+
+:mod:`askbot.middleware.spaceless`
+===========================
+
+.. automodule:: askbot.middleware.spaceless
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.middleware.view_log.rst b/askbot/doc/source/devel/askbot.middleware.view_log.rst
new file mode 100644
index 0000000000..d0779fc0a3
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.middleware.view_log.rst
@@ -0,0 +1,10 @@
+.. _askbot.middleware.view_log:
+
+:mod:`askbot.middleware.view_log`
+==========================
+
+.. automodule:: askbot.middleware.view_log
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0001_initial.rst b/askbot/doc/source/devel/askbot.migrations.0001_initial.rst
new file mode 100644
index 0000000000..f0a8907d7f
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0001_initial.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0001_initial:
+
+:mod:`askbot.migrations.0001_initial`
+==============================
+
+.. automodule:: askbot.migrations.0001_initial
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0002_auto__add_field_answer_text__chg_field_answer_html__add_field_question.rst b/askbot/doc/source/devel/askbot.migrations.0002_auto__add_field_answer_text__chg_field_answer_html__add_field_question.rst
new file mode 100644
index 0000000000..50cd7f2270
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0002_auto__add_field_answer_text__chg_field_answer_html__add_field_question.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0002_auto__add_field_answer_text__chg_field_answer_html__add_field_question:
+
+:mod:`askbot.migrations.0002_auto__add_field_answer_text__chg_field_answer_html__add_field_question`
+=============================================================================================
+
+.. automodule:: askbot.migrations.0002_auto__add_field_answer_text__chg_field_answer_html__add_field_question
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0003_copy_denorm_text_record_to_posts_for_fulltext_search.rst b/askbot/doc/source/devel/askbot.migrations.0003_copy_denorm_text_record_to_posts_for_fulltext_search.rst
new file mode 100644
index 0000000000..e5c50e9417
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0003_copy_denorm_text_record_to_posts_for_fulltext_search.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0003_copy_denorm_text_record_to_posts_for_fulltext_search:
+
+:mod:`askbot.migrations.0003_copy_denorm_text_record_to_posts_for_fulltext_search`
+===========================================================================
+
+.. automodule:: askbot.migrations.0003_copy_denorm_text_record_to_posts_for_fulltext_search
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0004_install_full_text_indexes_for_mysql.rst b/askbot/doc/source/devel/askbot.migrations.0004_install_full_text_indexes_for_mysql.rst
new file mode 100644
index 0000000000..6a58f82991
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0004_install_full_text_indexes_for_mysql.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0004_install_full_text_indexes_for_mysql:
+
+:mod:`askbot.migrations.0004_install_full_text_indexes_for_mysql`
+==========================================================
+
+.. automodule:: askbot.migrations.0004_install_full_text_indexes_for_mysql
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0005_install_badges.rst b/askbot/doc/source/devel/askbot.migrations.0005_install_badges.rst
new file mode 100644
index 0000000000..763913a032
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0005_install_badges.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0005_install_badges:
+
+:mod:`askbot.migrations.0005_install_badges`
+=====================================
+
+.. automodule:: askbot.migrations.0005_install_badges
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0006_add_subscription_setting_for_comments_and_mentions.rst b/askbot/doc/source/devel/askbot.migrations.0006_add_subscription_setting_for_comments_and_mentions.rst
new file mode 100644
index 0000000000..fc4528fccc
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0006_add_subscription_setting_for_comments_and_mentions.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0006_add_subscription_setting_for_comments_and_mentions:
+
+:mod:`askbot.migrations.0006_add_subscription_setting_for_comments_and_mentions`
+=========================================================================
+
+.. automodule:: askbot.migrations.0006_add_subscription_setting_for_comments_and_mentions
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0007_install_mentions_model.rst b/askbot/doc/source/devel/askbot.migrations.0007_install_mentions_model.rst
new file mode 100644
index 0000000000..f8126b25a1
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0007_install_mentions_model.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0007_install_mentions_model:
+
+:mod:`askbot.migrations.0007_install_mentions_model`
+=============================================
+
+.. automodule:: askbot.migrations.0007_install_mentions_model
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0008_add_html_field_to_comments.rst b/askbot/doc/source/devel/askbot.migrations.0008_add_html_field_to_comments.rst
new file mode 100644
index 0000000000..66194d8a37
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0008_add_html_field_to_comments.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0008_add_html_field_to_comments:
+
+:mod:`askbot.migrations.0008_add_html_field_to_comments`
+=================================================
+
+.. automodule:: askbot.migrations.0008_add_html_field_to_comments
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0009_calculate_html_field_for_comments.rst b/askbot/doc/source/devel/askbot.migrations.0009_calculate_html_field_for_comments.rst
new file mode 100644
index 0000000000..ac7b0454f7
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0009_calculate_html_field_for_comments.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0009_calculate_html_field_for_comments:
+
+:mod:`askbot.migrations.0009_calculate_html_field_for_comments`
+========================================================
+
+.. automodule:: askbot.migrations.0009_calculate_html_field_for_comments
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0010_add_receiving_user_to_activity_model.rst b/askbot/doc/source/devel/askbot.migrations.0010_add_receiving_user_to_activity_model.rst
new file mode 100644
index 0000000000..e57701a68d
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0010_add_receiving_user_to_activity_model.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0010_add_receiving_user_to_activity_model:
+
+:mod:`askbot.migrations.0010_add_receiving_user_to_activity_model`
+===========================================================
+
+.. automodule:: askbot.migrations.0010_add_receiving_user_to_activity_model
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0011_merge_mentions_into_activity.rst b/askbot/doc/source/devel/askbot.migrations.0011_merge_mentions_into_activity.rst
new file mode 100644
index 0000000000..58dd83046c
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0011_merge_mentions_into_activity.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0011_merge_mentions_into_activity:
+
+:mod:`askbot.migrations.0011_merge_mentions_into_activity`
+===================================================
+
+.. automodule:: askbot.migrations.0011_merge_mentions_into_activity
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0012_delete_some_unused_models.rst b/askbot/doc/source/devel/askbot.migrations.0012_delete_some_unused_models.rst
new file mode 100644
index 0000000000..b7c25ed4e1
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0012_delete_some_unused_models.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0012_delete_some_unused_models:
+
+:mod:`askbot.migrations.0012_delete_some_unused_models`
+================================================
+
+.. automodule:: askbot.migrations.0012_delete_some_unused_models
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0013_add_response_count__to_user.rst b/askbot/doc/source/devel/askbot.migrations.0013_add_response_count__to_user.rst
new file mode 100644
index 0000000000..e594d785bf
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0013_add_response_count__to_user.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0013_add_response_count__to_user:
+
+:mod:`askbot.migrations.0013_add_response_count__to_user`
+==================================================
+
+.. automodule:: askbot.migrations.0013_add_response_count__to_user
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0014_rename_schema_from_forum_to_askbot.rst b/askbot/doc/source/devel/askbot.migrations.0014_rename_schema_from_forum_to_askbot.rst
new file mode 100644
index 0000000000..bad3504b8a
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0014_rename_schema_from_forum_to_askbot.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0014_rename_schema_from_forum_to_askbot:
+
+:mod:`askbot.migrations.0014_rename_schema_from_forum_to_askbot`
+=========================================================
+
+.. automodule:: askbot.migrations.0014_rename_schema_from_forum_to_askbot
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0015_rename_forum_contenttypes_to_askbot.rst b/askbot/doc/source/devel/askbot.migrations.0015_rename_forum_contenttypes_to_askbot.rst
new file mode 100644
index 0000000000..632d014477
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0015_rename_forum_contenttypes_to_askbot.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0015_rename_forum_contenttypes_to_askbot:
+
+:mod:`askbot.migrations.0015_rename_forum_contenttypes_to_askbot`
+==========================================================
+
+.. automodule:: askbot.migrations.0015_rename_forum_contenttypes_to_askbot
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0016_auto__del_validationhash.rst b/askbot/doc/source/devel/askbot.migrations.0016_auto__del_validationhash.rst
new file mode 100644
index 0000000000..2b572d8036
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0016_auto__del_validationhash.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0016_auto__del_validationhash:
+
+:mod:`askbot.migrations.0016_auto__del_validationhash`
+===============================================
+
+.. automodule:: askbot.migrations.0016_auto__del_validationhash
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.0017_add_group__moderators.rst b/askbot/doc/source/devel/askbot.migrations.0017_add_group__moderators.rst
new file mode 100644
index 0000000000..d36165ab5b
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.0017_add_group__moderators.rst
@@ -0,0 +1,10 @@
+.. _askbot.migrations.0017_add_group__moderators:
+
+:mod:`askbot.migrations.0017_add_group__moderators`
+============================================
+
+.. automodule:: askbot.migrations.0017_add_group__moderators
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.migrations.rst b/askbot/doc/source/devel/askbot.migrations.rst
new file mode 100644
index 0000000000..bffa748b05
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.migrations.rst
@@ -0,0 +1,34 @@
+.. _askbot.migrations:
+
+:mod:`askbot.migrations`
+=================
+
+.. automodule:: askbot.migrations
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.migrations.0001_initial`
+* :ref:`askbot.migrations.0002_auto__add_field_answer_text__chg_field_answer_html__add_field_question`
+* :ref:`askbot.migrations.0003_copy_denorm_text_record_to_posts_for_fulltext_search`
+* :ref:`askbot.migrations.0004_install_full_text_indexes_for_mysql`
+* :ref:`askbot.migrations.0005_install_badges`
+* :ref:`askbot.migrations.0006_add_subscription_setting_for_comments_and_mentions`
+* :ref:`askbot.migrations.0007_install_mentions_model`
+* :ref:`askbot.migrations.0008_add_html_field_to_comments`
+* :ref:`askbot.migrations.0009_calculate_html_field_for_comments`
+* :ref:`askbot.migrations.0010_add_receiving_user_to_activity_model`
+* :ref:`askbot.migrations.0011_merge_mentions_into_activity`
+* :ref:`askbot.migrations.0012_delete_some_unused_models`
+* :ref:`askbot.migrations.0013_add_response_count__to_user`
+* :ref:`askbot.migrations.0014_rename_schema_from_forum_to_askbot`
+* :ref:`askbot.migrations.0015_rename_forum_contenttypes_to_askbot`
+* :ref:`askbot.migrations.0016_auto__del_validationhash`
+* :ref:`askbot.migrations.0017_add_group__moderators`
+
diff --git a/askbot/doc/source/devel/askbot.models.answer.rst b/askbot/doc/source/devel/askbot.models.answer.rst
new file mode 100644
index 0000000000..e1db344cc6
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.models.answer.rst
@@ -0,0 +1,10 @@
+.. _askbot.models.answer:
+
+:mod:`askbot.models.answer`
+====================
+
+.. automodule:: askbot.models.answer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.models.base.rst b/askbot/doc/source/devel/askbot.models.base.rst
new file mode 100644
index 0000000000..85c2715d8f
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.models.base.rst
@@ -0,0 +1,10 @@
+.. _askbot.models.base:
+
+:mod:`askbot.models.base`
+==================
+
+.. automodule:: askbot.models.base
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.models.content.rst b/askbot/doc/source/devel/askbot.models.content.rst
new file mode 100644
index 0000000000..5d919add9e
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.models.content.rst
@@ -0,0 +1,10 @@
+.. _askbot.models.content:
+
+:mod:`askbot.models.content`
+=====================
+
+.. automodule:: askbot.models.content
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.models.meta.rst b/askbot/doc/source/devel/askbot.models.meta.rst
new file mode 100644
index 0000000000..b048a18011
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.models.meta.rst
@@ -0,0 +1,10 @@
+.. _askbot.models.meta:
+
+:mod:`askbot.models.meta`
+==================
+
+.. automodule:: askbot.models.meta
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.models.question.rst b/askbot/doc/source/devel/askbot.models.question.rst
new file mode 100644
index 0000000000..e7f3ecd308
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.models.question.rst
@@ -0,0 +1,10 @@
+.. _askbot.models.question:
+
+:mod:`askbot.models.question`
+======================
+
+.. automodule:: askbot.models.question
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.models.repute.rst b/askbot/doc/source/devel/askbot.models.repute.rst
new file mode 100644
index 0000000000..d3d69865b9
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.models.repute.rst
@@ -0,0 +1,10 @@
+.. _askbot.models.repute:
+
+:mod:`askbot.models.repute`
+====================
+
+.. automodule:: askbot.models.repute
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.models.rst b/askbot/doc/source/devel/askbot.models.rst
new file mode 100644
index 0000000000..148f2dd545
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.models.rst
@@ -0,0 +1,26 @@
+.. _askbot.models:
+
+:mod:`askbot.models`
+=============
+
+.. automodule:: askbot.models
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.models.answer`
+* :ref:`askbot.models.base`
+* :ref:`askbot.models.content`
+* :ref:`askbot.models.meta`
+* :ref:`askbot.models.question`
+* :ref:`askbot.models.repute`
+* :ref:`askbot.models.signals`
+* :ref:`askbot.models.tag`
+* :ref:`askbot.models.user`
+
diff --git a/askbot/doc/source/devel/askbot.models.signals.rst b/askbot/doc/source/devel/askbot.models.signals.rst
new file mode 100644
index 0000000000..2b57a61ea2
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.models.signals.rst
@@ -0,0 +1,10 @@
+.. _askbot.models.signals:
+
+:mod:`askbot.models.signals`
+=====================
+
+.. automodule:: askbot.models.signals
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.models.tag.rst b/askbot/doc/source/devel/askbot.models.tag.rst
new file mode 100644
index 0000000000..4c7d74f585
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.models.tag.rst
@@ -0,0 +1,10 @@
+.. _askbot.models.tag:
+
+:mod:`askbot.models.tag`
+=================
+
+.. automodule:: askbot.models.tag
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.models.user.rst b/askbot/doc/source/devel/askbot.models.user.rst
new file mode 100644
index 0000000000..ac62f9bc07
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.models.user.rst
@@ -0,0 +1,10 @@
+.. _askbot.models.user:
+
+:mod:`askbot.models.user`
+==================
+
+.. automodule:: askbot.models.user
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.rst b/askbot/doc/source/devel/askbot.rst
new file mode 100644
index 0000000000..df988cdc6a
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.rst
@@ -0,0 +1,48 @@
+.. _askbot:
+
+:mod:`askbot`
+======
+
+.. automodule:: askbot
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.admin`
+* :ref:`askbot.auth`
+* :ref:`askbot.context`
+* :ref:`askbot.feed`
+* :ref:`askbot.forms`
+* :ref:`askbot.sitemap`
+* :ref:`askbot.tests`
+* :ref:`askbot.urls`
+
+.. _packages::
+
+:mod:`Subpackages`
+-----------
+
+
+* :ref:`askbot.bin`
+* :ref:`askbot.conf`
+* :ref:`askbot.const`
+* :ref:`askbot.deployment`
+* :ref:`askbot.importers`
+* :ref:`askbot.management`
+* :ref:`askbot.middleware`
+* :ref:`askbot.migrations`
+* :ref:`askbot.models`
+* :ref:`askbot.search`
+* :ref:`askbot.skins`
+* :ref:`askbot.templatetags`
+* :ref:`askbot.user_messages`
+* :ref:`askbot.utils`
+* :ref:`askbot.views`
+* :ref:`askbot.deps`
+* :ref:`askbot.setup_templates`
diff --git a/askbot/doc/source/devel/askbot.search.indexer.rst b/askbot/doc/source/devel/askbot.search.indexer.rst
new file mode 100644
index 0000000000..dc7cac2102
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.search.indexer.rst
@@ -0,0 +1,10 @@
+.. _askbot.search.indexer:
+
+:mod:`askbot.search.indexer`
+=====================
+
+.. automodule:: askbot.search.indexer
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.search.rst b/askbot/doc/source/devel/askbot.search.rst
new file mode 100644
index 0000000000..cdfa3f6d30
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.search.rst
@@ -0,0 +1,19 @@
+.. _askbot.search:
+
+:mod:`askbot.search`
+=============
+
+.. automodule:: askbot.search
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.search.indexer`
+* :ref:`askbot.search.state_manager`
+
diff --git a/askbot/doc/source/devel/askbot.search.state_manager.rst b/askbot/doc/source/devel/askbot.search.state_manager.rst
new file mode 100644
index 0000000000..a315f954ad
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.search.state_manager.rst
@@ -0,0 +1,10 @@
+.. _askbot.search.state_manager:
+
+:mod:`askbot.search.state_manager`
+===========================
+
+.. automodule:: askbot.search.state_manager
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.setup_templates.manage.rst b/askbot/doc/source/devel/askbot.setup_templates.manage.rst
new file mode 100644
index 0000000000..e9c4775ee2
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.setup_templates.manage.rst
@@ -0,0 +1,10 @@
+.. _askbot.setup_templates.manage:
+
+:mod:`askbot.setup_templates.manage`
+=============================
+
+.. automodule:: askbot.setup_templates.manage
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.setup_templates.rst b/askbot/doc/source/devel/askbot.setup_templates.rst
new file mode 100644
index 0000000000..58d0b704e9
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.setup_templates.rst
@@ -0,0 +1,20 @@
+.. _askbot.setup_templates:
+
+:mod:`askbot.setup_templates`
+======================
+
+.. automodule:: askbot.setup_templates
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.setup_templates.manage`
+* :ref:`askbot.setup_templates.settings`
+* :ref:`askbot.setup_templates.urls`
+
diff --git a/askbot/doc/source/devel/askbot.setup_templates.settings.rst b/askbot/doc/source/devel/askbot.setup_templates.settings.rst
new file mode 100644
index 0000000000..230a1474ab
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.setup_templates.settings.rst
@@ -0,0 +1,10 @@
+.. _askbot.setup_templates.settings:
+
+:mod:`askbot.setup_templates.settings`
+===============================
+
+.. automodule:: askbot.setup_templates.settings
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.setup_templates.urls.rst b/askbot/doc/source/devel/askbot.setup_templates.urls.rst
new file mode 100644
index 0000000000..4844502d27
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.setup_templates.urls.rst
@@ -0,0 +1,10 @@
+.. _askbot.setup_templates.urls:
+
+:mod:`askbot.setup_templates.urls`
+===========================
+
+.. automodule:: askbot.setup_templates.urls
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.sitemap.rst b/askbot/doc/source/devel/askbot.sitemap.rst
new file mode 100644
index 0000000000..373d88c77a
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.sitemap.rst
@@ -0,0 +1,10 @@
+.. _askbot.sitemap:
+
+:mod:`askbot.sitemap`
+==============
+
+.. automodule:: askbot.sitemap
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.skins.loaders.rst b/askbot/doc/source/devel/askbot.skins.loaders.rst
new file mode 100644
index 0000000000..e55c8472e3
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.skins.loaders.rst
@@ -0,0 +1,10 @@
+.. _askbot.skins.loaders:
+
+:mod:`askbot.skins.loaders`
+====================
+
+.. automodule:: askbot.skins.loaders
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.skins.rst b/askbot/doc/source/devel/askbot.skins.rst
new file mode 100644
index 0000000000..ad2b33681a
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.skins.rst
@@ -0,0 +1,19 @@
+.. _askbot.skins:
+
+:mod:`askbot.skins`
+============
+
+.. automodule:: askbot.skins
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.skins.loaders`
+* :ref:`askbot.skins.utils`
+
diff --git a/askbot/doc/source/devel/askbot.skins.utils.rst b/askbot/doc/source/devel/askbot.skins.utils.rst
new file mode 100644
index 0000000000..71a989e5a9
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.skins.utils.rst
@@ -0,0 +1,10 @@
+.. _askbot.skins.utils:
+
+:mod:`askbot.skins.utils`
+==================
+
+.. automodule:: askbot.skins.utils
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.templatetags.extra_filters.rst b/askbot/doc/source/devel/askbot.templatetags.extra_filters.rst
new file mode 100644
index 0000000000..759333938d
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.templatetags.extra_filters.rst
@@ -0,0 +1,10 @@
+.. _askbot.templatetags.extra_filters:
+
+:mod:`askbot.templatetags.extra_filters`
+=================================
+
+.. automodule:: askbot.templatetags.extra_filters
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.templatetags.extra_tags.rst b/askbot/doc/source/devel/askbot.templatetags.extra_tags.rst
new file mode 100644
index 0000000000..c4a2fca381
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.templatetags.extra_tags.rst
@@ -0,0 +1,10 @@
+.. _askbot.templatetags.extra_tags:
+
+:mod:`askbot.templatetags.extra_tags`
+==============================
+
+.. automodule:: askbot.templatetags.extra_tags
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.templatetags.rst b/askbot/doc/source/devel/askbot.templatetags.rst
new file mode 100644
index 0000000000..c38879524b
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.templatetags.rst
@@ -0,0 +1,20 @@
+.. _askbot.templatetags:
+
+:mod:`askbot.templatetags`
+===================
+
+.. automodule:: askbot.templatetags
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.templatetags.extra_filters`
+* :ref:`askbot.templatetags.extra_tags`
+* :ref:`askbot.templatetags.smart_if`
+
diff --git a/askbot/doc/source/devel/askbot.templatetags.smart_if.rst b/askbot/doc/source/devel/askbot.templatetags.smart_if.rst
new file mode 100644
index 0000000000..ea43b691c2
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.templatetags.smart_if.rst
@@ -0,0 +1,10 @@
+.. _askbot.templatetags.smart_if:
+
+:mod:`askbot.templatetags.smart_if`
+============================
+
+.. automodule:: askbot.templatetags.smart_if
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.tests.rst b/askbot/doc/source/devel/askbot.tests.rst
new file mode 100644
index 0000000000..3bf281673a
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.tests.rst
@@ -0,0 +1,10 @@
+.. _askbot.tests:
+
+:mod:`askbot.tests`
+============
+
+.. automodule:: askbot.tests
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.urls.rst b/askbot/doc/source/devel/askbot.urls.rst
new file mode 100644
index 0000000000..17ebd08d2f
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.urls.rst
@@ -0,0 +1,10 @@
+.. _askbot.urls:
+
+:mod:`askbot.urls`
+===========
+
+.. automodule:: askbot.urls
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.user_messages.context_processors.rst b/askbot/doc/source/devel/askbot.user_messages.context_processors.rst
new file mode 100644
index 0000000000..f6499f2ecf
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.user_messages.context_processors.rst
@@ -0,0 +1,10 @@
+.. _askbot.user_messages.context_processors:
+
+:mod:`askbot.user_messages.context_processors`
+=======================================
+
+.. automodule:: askbot.user_messages.context_processors
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.user_messages.rst b/askbot/doc/source/devel/askbot.user_messages.rst
new file mode 100644
index 0000000000..3426b3639d
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.user_messages.rst
@@ -0,0 +1,18 @@
+.. _askbot.user_messages:
+
+:mod:`askbot.user_messages`
+====================
+
+.. automodule:: askbot.user_messages
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.user_messages.context_processors`
+
diff --git a/askbot/doc/source/devel/askbot.utils.cache.rst b/askbot/doc/source/devel/askbot.utils.cache.rst
new file mode 100644
index 0000000000..583c7ec9a3
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.utils.cache.rst
@@ -0,0 +1,10 @@
+.. _askbot.utils.cache:
+
+:mod:`askbot.utils.cache`
+==================
+
+.. automodule:: askbot.utils.cache
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.utils.colors.rst b/askbot/doc/source/devel/askbot.utils.colors.rst
new file mode 100644
index 0000000000..df271c9a0e
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.utils.colors.rst
@@ -0,0 +1,10 @@
+.. _askbot.utils.colors:
+
+:mod:`askbot.utils.colors`
+===================
+
+.. automodule:: askbot.utils.colors
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.utils.decorators.rst b/askbot/doc/source/devel/askbot.utils.decorators.rst
new file mode 100644
index 0000000000..7c7468c18a
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.utils.decorators.rst
@@ -0,0 +1,10 @@
+.. _askbot.utils.decorators:
+
+:mod:`askbot.utils.decorators`
+=======================
+
+.. automodule:: askbot.utils.decorators
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.utils.diff.rst b/askbot/doc/source/devel/askbot.utils.diff.rst
new file mode 100644
index 0000000000..0d3fb71917
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.utils.diff.rst
@@ -0,0 +1,10 @@
+.. _askbot.utils.diff:
+
+:mod:`askbot.utils.diff`
+=================
+
+.. automodule:: askbot.utils.diff
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.utils.email.rst b/askbot/doc/source/devel/askbot.utils.email.rst
new file mode 100644
index 0000000000..02ef238c89
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.utils.email.rst
@@ -0,0 +1,10 @@
+.. _askbot.utils.email:
+
+:mod:`askbot.utils.email`
+==================
+
+.. automodule:: askbot.utils.email
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.utils.forms.rst b/askbot/doc/source/devel/askbot.utils.forms.rst
new file mode 100644
index 0000000000..3e24bad447
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.utils.forms.rst
@@ -0,0 +1,10 @@
+.. _askbot.utils.forms:
+
+:mod:`askbot.utils.forms`
+==================
+
+.. automodule:: askbot.utils.forms
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.utils.functions.rst b/askbot/doc/source/devel/askbot.utils.functions.rst
new file mode 100644
index 0000000000..f1fa1c127c
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.utils.functions.rst
@@ -0,0 +1,10 @@
+.. _askbot.utils.functions:
+
+:mod:`askbot.utils.functions`
+======================
+
+.. automodule:: askbot.utils.functions
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.utils.html.rst b/askbot/doc/source/devel/askbot.utils.html.rst
new file mode 100644
index 0000000000..50ce9854f4
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.utils.html.rst
@@ -0,0 +1,10 @@
+.. _askbot.utils.html:
+
+:mod:`askbot.utils.html`
+=================
+
+.. automodule:: askbot.utils.html
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.utils.lists.rst b/askbot/doc/source/devel/askbot.utils.lists.rst
new file mode 100644
index 0000000000..080e696baf
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.utils.lists.rst
@@ -0,0 +1,10 @@
+.. _askbot.utils.lists:
+
+:mod:`askbot.utils.lists`
+==================
+
+.. automodule:: askbot.utils.lists
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.utils.markup.rst b/askbot/doc/source/devel/askbot.utils.markup.rst
new file mode 100644
index 0000000000..fd4627e50d
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.utils.markup.rst
@@ -0,0 +1,10 @@
+.. _askbot.utils.markup:
+
+:mod:`askbot.utils.markup`
+===================
+
+.. automodule:: askbot.utils.markup
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.utils.rst b/askbot/doc/source/devel/askbot.utils.rst
new file mode 100644
index 0000000000..0ba8ed2580
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.utils.rst
@@ -0,0 +1,27 @@
+.. _askbot.utils:
+
+:mod:`askbot.utils`
+============
+
+.. automodule:: askbot.utils
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.utils.cache`
+* :ref:`askbot.utils.colors`
+* :ref:`askbot.utils.decorators`
+* :ref:`askbot.utils.diff`
+* :ref:`askbot.utils.email`
+* :ref:`askbot.utils.forms`
+* :ref:`askbot.utils.functions`
+* :ref:`askbot.utils.html`
+* :ref:`askbot.utils.lists`
+* :ref:`askbot.utils.markup`
+
diff --git a/askbot/doc/source/devel/askbot.views.commands.rst b/askbot/doc/source/devel/askbot.views.commands.rst
new file mode 100644
index 0000000000..610c32ae9f
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.views.commands.rst
@@ -0,0 +1,10 @@
+.. _askbot.views.commands:
+
+:mod:`askbot.views.commands`
+=====================
+
+.. automodule:: askbot.views.commands
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.views.meta.rst b/askbot/doc/source/devel/askbot.views.meta.rst
new file mode 100644
index 0000000000..493dbfb479
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.views.meta.rst
@@ -0,0 +1,10 @@
+.. _askbot.views.meta:
+
+:mod:`askbot.views.meta`
+=================
+
+.. automodule:: askbot.views.meta
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.views.readers.rst b/askbot/doc/source/devel/askbot.views.readers.rst
new file mode 100644
index 0000000000..f264d1e479
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.views.readers.rst
@@ -0,0 +1,10 @@
+.. _askbot.views.readers:
+
+:mod:`askbot.views.readers`
+====================
+
+.. automodule:: askbot.views.readers
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.views.rst b/askbot/doc/source/devel/askbot.views.rst
new file mode 100644
index 0000000000..e47782d5a8
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.views.rst
@@ -0,0 +1,22 @@
+.. _askbot.views:
+
+:mod:`askbot.views`
+============
+
+.. automodule:: askbot.views
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
+.. _modules::
+
+:mod:`Modules`
+-------
+
+
+* :ref:`askbot.views.commands`
+* :ref:`askbot.views.meta`
+* :ref:`askbot.views.readers`
+* :ref:`askbot.views.users`
+* :ref:`askbot.views.writers`
+
diff --git a/askbot/doc/source/devel/askbot.views.users.rst b/askbot/doc/source/devel/askbot.views.users.rst
new file mode 100644
index 0000000000..fd2d47bf2e
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.views.users.rst
@@ -0,0 +1,10 @@
+.. _askbot.views.users:
+
+:mod:`askbot.views.users`
+==================
+
+.. automodule:: askbot.views.users
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/askbot.views.writers.rst b/askbot/doc/source/devel/askbot.views.writers.rst
new file mode 100644
index 0000000000..5f643f3259
--- /dev/null
+++ b/askbot/doc/source/devel/askbot.views.writers.rst
@@ -0,0 +1,10 @@
+.. _askbot.views.writers:
+
+:mod:`askbot.views.writers`
+====================
+
+.. automodule:: askbot.views.writers
+ :members:
+ :undoc-members:
+ :show-inheritance:
+
diff --git a/askbot/doc/source/devel/modules.rst b/askbot/doc/source/devel/modules.rst
new file mode 100644
index 0000000000..71f888f566
--- /dev/null
+++ b/askbot/doc/source/devel/modules.rst
@@ -0,0 +1,33 @@
+.. _Project:
+
+:mod:`Project`
+=======
+
+:mod:`Modules:`
+--------
+
+.. toctree::
+ :maxdepth: 4
+
+ askbot
+ bin
+ commands
+ commands
+ conf
+ const
+ deployment
+ deps
+ importers
+ management
+ management
+ middleware
+ migrations
+ models
+ search
+ setup_templates
+ skins
+ stackexchange
+ templatetags
+ user_messages
+ utils
+ views
diff --git a/askbot/doc/source/download.rst b/askbot/doc/source/download.rst
new file mode 100644
index 0000000000..d6172fecf9
--- /dev/null
+++ b/askbot/doc/source/download.rst
@@ -0,0 +1,6 @@
+===============
+Download Askbot
+===============
+
+The entire source code for the Askbot Q & A forum can be downloaded
+at the Python Package index
diff --git a/askbot/doc/source/footnotes.rst b/askbot/doc/source/footnotes.rst
new file mode 100644
index 0000000000..f8e96da0b0
--- /dev/null
+++ b/askbot/doc/source/footnotes.rst
@@ -0,0 +1,70 @@
+=========
+Footnotes
+=========
+
+This page summarizes additional information that might be useful
+for deployment of development of ``askbot``.
+
+.. _git:
+
+Git
+===
+
+At askbot we use ``git`` to keep track of the source code,
+and the main repository is hosted at
+`github `_.
+
+With git you can always grab
+the latest code of askbot from the
+latest ``askbot`` code::
+
+ git clone git://github.com/ASKBOT/askbot-devel.git
+
+Do some customization by editing files and then::
+
+ git add
+ git commit -m 'explain why you have changed some files'
+
+Bring updates from the main repo::
+
+ git git fetch origin master:github #.. onto a local branch called github
+ git checkout master
+ git merge github
+
+If all goes well, you are done. Otherwise, you may need to
+`resolve the conflict `_.
+
+Here is a
+`good basic tutorial `_
+about git,
+more comprehensive ones
+`here `_
+and
+`there `_.
+Finally, you also may want to visit the
+official git `reference `_
+and `documentation `_.
+There are `screencasts `_ too.
+
+.. _pip:
+
+Pip
+===
+
+``Pip`` is the best package management tool for python, allows to install and
+unistall python packages, supports installation from source code repositories
+and much more.
+
+For more information about ``pip``,
+including its installation,
+please visit the `pip package page `_
+and the links within.
+
+.. _pip-pypi: http://pypi.python.org/pypi/pip
+.. _git-csm-book: http://book.git-scm.com/
+.. _git-basic-tutorial: http://www.ralfebert.de/tutorials/git/
+.. _git-github-tutorial: http://help.github.com/
+.. _git-docs: http://www.kernel.org/pub/software/scm/git/docs/
+.. _git-reference: http://gitref.org
+.. _git-casts: http://gitcasts.com/
+.. _git-resolve-conflict: http://www.kernel.org/pub/software/scm/git/docs/user-manual.html#resolving-a-merge
diff --git a/askbot/doc/source/git.rst b/askbot/doc/source/git.rst
new file mode 100644
index 0000000000..9719f4bfb8
--- /dev/null
+++ b/askbot/doc/source/git.rst
@@ -0,0 +1,150 @@
+.. _upgrading-with-git:
+
+===============================================
+Upgrading Askbot (and other software) with git
+===============================================
+
+Git makes it easy to upgrade software, especially if your version is customized.
+
+Upgrading with git consists of three steps:
+
+#. preparing your local repository for the merge
+#. bringing the latest version of the code onto your system
+#. merging the latest code with your work
+
+Preparing the local repository for merge
+-----------------------------------------
+
+Before you can merge the new code, your local repository must be "clean" - that is any changes in the working copy - most likely the local directory must be committed to your local repository.
+
+First, see which branch is currently in the working copy and what is its state::
+
+ > git status
+
+If the output says that the branch is clean, then skip the section below.
+
+Commit any modified files to the local repository
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If the local branch does have modifed files,
+any of those files (or even entire directories) must be added to the repository index with command `git add`::
+
+ > git add
+ > git add
+
+If there are several modified files in the same directory, then adding directory will be more convinient.
+
+In Git system index_ is only a part of the repository - it's a record of "scheduled" changes that must be applied in a single batch called "commit_"
+
+After all changed files are added to the index, the index must be committed (really added, if you will) to the repository::
+
+ > git commit -m 'some descriptive message'
+
+Jump into the branch that you want to upgrade
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+If it is the current branch that you want to upgrade, then you are ready for the next step, otherwise switch the branch in the working copy with `git checkout`_ command.
+
+Before checking out a branch see what branches are locally available and which one is the current::
+
+ > git branch
+
+Current branch will be marked with an asterisk.
+
+(Note that adding extra arguments the `git branch`_ command will significantly modify its meaning, for example it can create or delete branches)
+
+Now check out the branch you want to merge the new code into::
+
+ > git checkout
+
+(Example below assumes that branchname is 'master').
+
+Bring the latest code into your repository
+-------------------------------------------
+
+Now to bring in the fresh code from some public repository (for example public "master" branch hosted on github_), run::
+
+ > git fetch origin master:master-github
+
+In the command above (`git fetch`_), `origin` is the name of the repository (also called "remote" repository). By default `origin` repository is the one that you have used to originally clone_ into your system.
+
+The last part of the command `master:master-github` tells that you want to take stuff from branch `master` on the `origin` repository and put it into branch `master-github` on your local repository.
+
+Merge the upgrade into your local repository
+-------------------------------------------------
+
+To merge content of one branch into another, run `git merge`_ command::
+
+ > git merge github-master
+ Auto-merging askbot/models/__init__.py
+ CONFLICT (content): Merge conflict in askbot/models/__init__.py
+ Removing askbot/utils/time.py
+ Auto-merging askbot/views/readers.py
+ Automatic merge failed; fix conflicts and then commit the result.
+
+The command `git merge github-master` means that you indended to merge content
+of your local branch `github-master` into the currently checked out branch.
+
+Often, merge will go smoothly, but if you and someone else have edited the same file approximately on the same place, automatic merge will not work on that file. For example the output above tells that there was a "conflict" in file `askbot/models/__init__.py`.
+
+At any time, e.g. during resolving conflicts you can always check which files still have them with `git status` command::
+
+ > git status
+ askbot/models/__init__.py: needs merge
+ # On branch master
+ # Your branch is ahead of 'origin/master' by 91 commits.
+ #
+ # Changes to be committed:
+ # (use "git reset HEAD ..." to unstage)
+ #
+ # new file: askbot/bin/show_profile_stats.py
+ # modified: askbot/doc/source/index.rst
+ # new file: askbot/locale/fi/LC_MESSAGES/django.mo
+ # modified: askbot/locale/fi/LC_MESSAGES/django.po
+ # new file: askbot/migrations/0016_auto__del_validationhash.py
+ # modified: askbot/models/question.py
+ # modified: askbot/models/user.py
+ # modified: askbot/skins/default/media/js/com.cnprog.i18n.js
+ # modified: askbot/skins/default/media/js/org.askbot.output-words.js
+ # modified: askbot/skins/default/templates/email_base.html
+ # modified: askbot/skins/default/templates/question.html
+ # modified: askbot/skins/default/templates/question_list.html
+ # modified: askbot/skins/default/templates/user_edit.html
+ # modified: askbot/utils/decorators.py
+ # deleted: askbot/utils/time.py
+ # modified: askbot/views/readers.py
+ #
+ # Changed but not updated:
+ # (use "git add ..." to update what will be committed)
+ # (use "git checkout -- ..." to discard changes in working directory)
+ #
+ # unmerged: askbot/models/__init__.py
+
+If you have merge conflicts - resolve them and commit them into the repository.
+
+To resolve conflicts, open the file in question and find lines that start with `<<<`. Conflict areas are demarcated by `<<<`, `====` and `>>>` patterns.
+
+`====` divides the conflicting versions.
+
+When resolving merge conflicts your options are: accept one of the versions or come up with some compromize.
+
+Decide what is the best course of action, fix the code, remove the conflict demarcation lines and add file to the index with `git add`_::
+
+ > git add askbot/models/__init__.py
+
+At this point it is best not to use wholsale add via a directory (like `git add askbot`) - because you don't want to accidentally add other conflicting files into the index.
+
+Once all conflicts are resolved, run the `git commit`_ command::
+
+ > git commit -m 'merged with the public master branch'
+
+.. _index: http://book.git-scm.com/1_the_git_index.html
+.. _`git commit`: http://www.kernel.org/pub/software/scm/git/docs/git-commit.html
+.. _commit: http://www.kernel.org/pub/software/scm/git/docs/git-commit.html
+.. _`git checkout`: http://www.kernel.org/pub/software/scm/git/docs/git-checkout.html
+.. _`git branch`: http://www.kernel.org/pub/software/scm/git/docs/git-branch.html
+.. _`git fetch`: http://www.kernel.org/pub/software/scm/git/docs/git-fetch.html
+.. _`git merge`: http://www.kernel.org/pub/software/scm/git/docs/git-merge.html
+.. _`git add`: http://www.kernel.org/pub/software/scm/git/docs/git-add.html
+.. _clone: http://www.kernel.org/pub/software/scm/git/docs/git-clone.html
+.. _github: http://github.com/ASKBOT/askbot-devel
diff --git a/askbot/doc/source/images/basic-twitter-settings.png b/askbot/doc/source/images/basic-twitter-settings.png
new file mode 100644
index 0000000000..785e5a9df8
Binary files /dev/null and b/askbot/doc/source/images/basic-twitter-settings.png differ
diff --git a/askbot/doc/source/images/enable-auto-tweeting.png b/askbot/doc/source/images/enable-auto-tweeting.png
new file mode 100644
index 0000000000..a761601f45
Binary files /dev/null and b/askbot/doc/source/images/enable-auto-tweeting.png differ
diff --git a/askbot/doc/source/import-data.rst b/askbot/doc/source/import-data.rst
new file mode 100644
index 0000000000..44b902b572
--- /dev/null
+++ b/askbot/doc/source/import-data.rst
@@ -0,0 +1,48 @@
+.. import-data::
+
+===============================
+Import other forums into Askbot
+===============================
+
+Askbot supports importing of data from StackExchange and Zendesk.
+
+.. warning::
+ If your database contains any data prior to importing, please back it up before proceeding.
+
+StackExchange
+=============
+
+Add `askbot.importers.stackexchange` to the list of `INSTALLED_APPS` list in your `settings.py`, then run::
+
+ python manage.py syncdb
+
+Then there will be two ways to import your StackExchange dump:
+
+* via the web at url `/import-data/`, relative to your forum installation
+* using a management command::
+
+ python manage.py load_stackexchange /path/to/your-se-data.zip
+
+
+Zendesk
+=======
+Add `askbot.importers.zendesk` to the list of `INSTALLED_APPS` in the `settings.py`,
+run `python manage.py syncdb`.
+
+Prepare your zendesk files: put all your .xml files into one directory and tar-zip it::
+
+ mkdir somedir
+ mv *.xml somedir #select the zendesk xml files and move them to the directory
+ tar cvfz zendesk.tgz somedir #name of the tgz file is not important
+
+Then run the import script::
+
+ python manage.py import_zendesk zendesk.tgz #file name is the parameter
+
+.. note::
+ It is possible that import script will make some mistakes in determining
+ which post in the group is the question, due to some specifics of zendesk
+ data format. If so, please enable feature
+ "Forum data rules"->"allow switching question with answer"
+ in :ref:`live settings ` and use it in an admin or a moderator
+ account.
diff --git a/askbot/doc/source/index.rst b/askbot/doc/source/index.rst
new file mode 100644
index 0000000000..e3f7ba128e
--- /dev/null
+++ b/askbot/doc/source/index.rst
@@ -0,0 +1,56 @@
+.. _index:
+
+==================
+Documentation Home
+==================
+
+Askbot is an open source Question and Answer (Q&A) forum project inspired by StackOverflow
+and YahooAnswers.
+
+This version of Askbot supports only Django 1.7.
+
+To upgrade, or select version of Askbot working with earlier versions of Django,
+please follow `the instructions`_.
+
+
+It is quick and easy to install and deploy askbot on your site.
+Have questions? - please ask
+at the forum_ or by email at admin@askbot.org
+
+.. toctree::
+ :maxdepth: 1
+
+ Install the software
+ Create the database
+ Create and configure the site files
+ Initialize the database tables
+ Deploy on a webserver
+ Upgrades
+ Import data (StackExchange & ZenDesk)
+ Moderation
+ Appendix A: Maintenance procedures
+ Appendix B: Sending email to askbot
+ Appendix C: Optional modules
+ Appendix D: Api
+ Appendix E: Askbot as reusable Django application
+ Appendix F: Customizing skin in askbot
+ Appendix G: Intranet setup
+ Appendix H: Language support in Askbot
+ Appendix I: Configuration of text search
+ Appendix J: Migration from MySQL to PostgreSQL
+ Footnotes
+ Contributors
+ Changelog
+
+Some background information: Askbot is written in Python on top of the Django platform.
+Code of Askbot grew out of CNPROG project originally written by
+Mike Chen and Sailing Cai.
+
+.. _Python: http://www.python.org/download/
+.. _YahooAnswers: http://answers.yahoo.com/
+.. _StackOverflow: http://stackoverflow.com/
+.. _Django: http://djangoproject.com
+.. _CNPROG: http://cnprog.com
+.. _forum: http://askbot.org
+.. _`development version`: http://github.com/ASKBOT/askbot-devel
+.. _`the instructions`: https://github.com/ASKBOT/askbot-devel/blob/master/askbot/doc/source/upgrade.rst
diff --git a/askbot/doc/source/initial-configuration.rst b/askbot/doc/source/initial-configuration.rst
new file mode 100644
index 0000000000..23c3b5fd48
--- /dev/null
+++ b/askbot/doc/source/initial-configuration.rst
@@ -0,0 +1,106 @@
+.. _compile-time-configuration:
+
+===============================
+Initial Configuration of Askbot
+===============================
+
+While most configuration settings for askbot can be done at any time :ref:`through the web-interface `, some manipulations on the server are still necessary.
+
+
+Installing Askbot as a new Django project (standalone app)
+==========================================================
+
+.. note::
+ Firstly - if you are preparing the project directory manually,
+ make sure that the directory name does not
+ have the `.` - dot - symbol, because it is illegal for Python modules.
+ For example::
+
+ mkdir mydjangosite
+ cd mydjangosite
+
+When installing Askbot for the first time, you will need to initialize the project setup files by typing::
+
+ askbot-setup
+
+and answering the questions. The `askbot-setup` script will ask you where to deploy Askbot. If you are in
+the directory where the Askbot project resides, you can answer `.` (`.` refers to the current directory).
+There may be an error message; ignore it.
+
+After that - run command `collectstatic` - in order to place all the static files (.css and .js)
+into one directory::
+
+ python manage.py collectstatic
+
+Remember to repeat this command any time you upgrade Askbot or other apps installed
+in the same project.
+
+.. note::
+
+ All Django sites have four project-wide files::
+
+ settings.py - the main settings configuration file
+ urls.py - main url configuration
+ __init__.py - often empty but needed for Python
+ manage.py - the hook allowing to run management commands
+
+ `askbot-setup` adds those files to the directory you select (and some more things specific to Askbot).
+
+.. versionadded:: 0.7.24
+ `askbot-setup` also have command line arguments such as folder name(name), database name, database password and database user also added verbosity support.
+ You can also specify a local settings file to append it's contents to the deployment settings file.
+
+ +----------------------------------+------------------------------------------------------------+
+ | Parameter | Purpose |
+ +==================================+============================================================+
+ | -n | Name of the instance, this is the name that the |
+ | | folder will use. |
+ +----------------------------------+------------------------------------------------------------+
+ | -e | Integer values: 1 - postgresql, 2 - sqlite3, 3 - mysql |
+ +----------------------------------+------------------------------------------------------------+
+ | -d | The database name that the instance will use. |
+ +----------------------------------+------------------------------------------------------------+
+ | -u | The database user that the instance will use. |
+ +----------------------------------+------------------------------------------------------------+
+ | -p | The database password for the user. |
+ +----------------------------------+------------------------------------------------------------+
+ | --domain= | Domain name for the application. |
+ +----------------------------------+------------------------------------------------------------+
+ | --append-settings=| Allows to append a setting file content to the |
+ | | settings file, the parameter is the file to use. |
+ +----------------------------------+------------------------------------------------------------+
+
+
+.. note::
+
+ `askbot-setup` command line arguments detail parameter is available when you type: askbot-setup --h.
+
+Note that if you already have a Django site you will not want to use `askbot-setup`, because you don't want to just overwrite your existing settings.py. See below for instructions.
+
+Another thing you have to do if you are creating a brand new Django project is edit the file `settings.py`_. At the very minimum, you will need to provide the correct values to some settings.
+
+All values must be enclosed in single quotes, as shown below::
+
+ DATABASE_ENGINE = '' #e.g. 'mysql'
+ DATABASE_NAME = '' #name of the database you created, e.g. 'askbot'.
+ DATABASE_USER = '' #name of the database user, e.g. 'askbotuser'.
+ DATABASE_PASSWORD = '' #password to the database
+ CSRF_COOKIE_DOMAIN = ''#e.g. 'example.com' or 'askbot.example.com' (localhost/IP address for tests)
+
+.. note::
+
+ The files settings.py_ and urls.py_ may also need to be touched up
+ when you upgrate the software, because new versions may bring
+ new dependencies and add new site urls.
+
+
+Adding Askbot to an existing Django project
+===========================================
+
+If you are adding askbot to an existing Django project, you will need to
+merge settings.py_ and urls.py_ into your project manually. The templates to be used can be found
+in the `askbot/setup_templates` subdirectory.
+
+
+.. _urls.py: http://github.com/ASKBOT/askbot-devel/blob/master/askbot/setup_templates/urls.py
+.. _settings.py: http://github.com/ASKBOT/askbot-devel/blob/master/askbot/setup_templates/settings.py
diff --git a/askbot/doc/source/initialize-database-tables.rst b/askbot/doc/source/initialize-database-tables.rst
new file mode 100644
index 0000000000..a296de3e98
--- /dev/null
+++ b/askbot/doc/source/initialize-database-tables.rst
@@ -0,0 +1,61 @@
+.. _initialize-database-tables:
+
+=======================================================
+Initialization and upgrade of the database for Askbot
+=======================================================
+
+When you install Askbot the first time and any time you upgrade the software, run these two commands::
+
+ python manage.py syncdb
+
+.. versionchanged:: 0.7.21
+ When the script asks you if you want to create a superuser, answer yes if you want to create one. By default Askbot sets admin status(superuser) for the first user created automatically but also supports this form.
+
+.. deprecated:: 0.7.21
+ When the script asks you if you want to create a superuser, answer **no**.
+
+Then run::
+
+ python manage.py migrate askbot
+ python manage.py migrate django_authopenid #embedded login application
+
+.. note::
+
+ When upgrading - do not skip to back up the database before proceeding!!!
+ Things can break and it is better to be safe than sorry. Even better -
+ do run two installations of your project - one for production deployment
+ and the second one - for testing the upgrade. When you are sure that
+ your upgrade works, just switch the testing installation for the former production one.
+
+Now run the Django development server and check that everything works::
+
+ python manage.py runserver `hostname -i`:8000 #or use some other port number > 1024
+
+.. note::
+
+ `hostname -i` is a Unix command returning the IP address of your system, you can also type
+ the IP manually or replace it with word `localhost` if you are installing askbot
+ on a local machine.
+
+Connect to the Django development server with your Web browser. The address is the name
+(or IP address) of your site followed by ":8000" (or whatever port number you chose above).
+Once the fresh copy of Askbot appears in your browser, create a new account at the site.
+This will be your administrator account.
+
+.. deprecated:: 0.7.20
+ Finally, turn the newly added user into a superuser by running::
+
+ python manage.py add_admin 1
+
+.. versionadded:: 0.7.20
+ In the new version of Askbot the first user you create on the site will be added as administrator.
+
+Here number 1 is the numeric id of the first user, enter a different number, if it is indeed different.
+
+Your basic installation is now complete. Many settings can be
+:ref:`changed at runtime ` by following url `/settings`.
+
+If you choose to host a real website, please read
+section :ref:`deployment`.
+
+
diff --git a/askbot/doc/source/install.rst b/askbot/doc/source/install.rst
new file mode 100644
index 0000000000..06576fc81f
--- /dev/null
+++ b/askbot/doc/source/install.rst
@@ -0,0 +1,66 @@
+.. _install:
+
+=================
+Installing Askbot
+=================
+
+The latest stable version of askbot can be installed from the official `Python Package Index (PyPI) `_
+
+There are several methods to install Askbot. The recommended choice of the method depends on whether you are planning to modify the source code and/or templates or not.
+
+Would like to use the package as is?
+====================================
+
+If so - then the best tool for that is `pip`, the second best choice is `easy_install`::
+
+ pip install askbot
+ easy_install askbot #if you prefer easy_install
+
+Both commands automatically install Askbot and the dependency packages. `Pip` is a significant improvement upon `easy_install` and is strongly recommended.
+
+If you do not have either of those tools - download the `askbot archive from PyPI `_, unzip and untar it, then run::
+
+ python setup.py install #this is actually equivalent to running easy_install
+
+Intend to customize the forum?
+==============================
+
+In this case the best option is to clone the code from the development repository::
+
+ git clone git://github.com/ASKBOT/askbot-devel.git
+
+where `` should be some very distinct name.
+
+Then jump into the new directory and run::
+
+ python setup.py develop #the develop option will not install askbot into the python site packages directory
+
+.. note::
+
+ `setup.py` installs the Python modules required by Askbot into the proper directory (e.g.
+ `/usr/bin/python2.6/site-packages`).
+
+How to install into custom directories
+======================================
+
+On the shared hosts and in some other cases it is better to install python packages in some place other than the system package directory. If that's your situation - use the `virtualenv` tool::
+
+ virtualenv /path/to/some/directory
+
+Virtualenv will provide a dedicated `python` interpreter and `pip` just for that isolated environment. Both will be available within directory `/path/to/some/dir/bin`. Please, use them to run operations shown above.
+
+Under windows, please install
+`mysql-python windows binary package `_ manually.
+
+Most likely, by this time you will have askbot software installed. However, in some cases
+one of the dependency packages might fail to install. :ref:`This document ` will help you find those components.
+
+When you have all packages installed,
+please proceed to the :ref:`initial configuration ` section.
+
+.. _Python: http://www.python.org/download/
+.. _askbot: http://pypi.python.org/pypi/askbot
+.. _`easy_install`: http://pypi.python.org/pypi/setuptools
+.. _pypi: http://pypi.python.org/
+
+.. _django.wsgi: http://github.com/ASKBOT/askbot-devel/blob/master/askbot/setup_templates/django.wsgi
diff --git a/askbot/doc/source/intranet-setup.rst b/askbot/doc/source/intranet-setup.rst
new file mode 100644
index 0000000000..2711b37624
--- /dev/null
+++ b/askbot/doc/source/intranet-setup.rst
@@ -0,0 +1,21 @@
+==========================================================
+Setting up Askbot for use on the closed network (Intranet)
+==========================================================
+
+When using Askbot on the Intranet (for example - within your
+Company network), it will be useful to disable references to
+all external resources - such as custom fonts, gravatars.
+
+Please change the following settings in your ``settings.py`` file::
+
+ ASKBOT_USE_LOCAL_FONTS=True
+
+In addition, in the "live settings":
+* disable gravatar in "settings->User settings"
+
+If you would like to password/protect your site
+(achievable via "access control settings" -> "allow only registered users..."),
+and at the same time be able to have some dedicated service
+to read your site without authentication, add
+IP addresses of that service to a tuple ``ASKBOT_INTERNAL_IPS``
+in your ``settings.py`` file.
diff --git a/askbot/doc/source/live-settings.rst b/askbot/doc/source/live-settings.rst
new file mode 100644
index 0000000000..bc0d3d72c6
--- /dev/null
+++ b/askbot/doc/source/live-settings.rst
@@ -0,0 +1,73 @@
+.. _live-settings:
+=============
+Live settings
+=============
+
+Many of the configuration settings in askbot are accessible
+to the site administators via link "settings" in the site header.
+
+Any change to the "live settings" will be reflected on the site
+immediately.
+
+No-one but the site administrators can change those settings.
+
+.. note::
+ Any user can be turned into an administrator via running a command.
+
+ python manage.py add_admin
+
+ At the moment this command is not available from the web-interface
+ but this will be fixed in the future.
+
+.. _live-settings-options:
+Entering live settings in settings.py file
+==========================================
+
+You might want to bypass live settings and enter them directly
+in the ``settings.py`` file.
+
+Currently there are two ways to do this:
+
+1. Simply add variable with the same name as defined in `askbot/conf` files,
+ but prefixed with `ASKBOT_` and the corresponding value.
+ For example, add `ASKBOT_RSS_ENABLED = False` to disable the rss.
+ In `askbot/conf` this value is defined simply as `RSS_ENABLED`.
+
+2. Put settings into the ``LIVESETTINGS_OPTIONS`` dictionary,
+ this way you can assign livesettings values to specific site by ID,
+ which may or may not be useful for the multi-portal (multi-site) askbot setup.
+
+The first method above overrides the second.
+
+Here is a more detailed description on how to use the `LIVESETTINGS_OPTIONS` method:
+
+Having live settings overridden from the ``settings.py`` file may
+somewhat speed up your site
+and
+decrease a chance that the values could be accessed
+by an unauthorized person.
+
+Please see an example below::
+
+ LIVESETTINGS_OPTIONS = {
+ 1: {
+ 'DB' : True,
+ 'SETTINGS': {
+ 'EMAIL': {
+ 'REPLY_BY_EMAIL': True
+ }
+ }
+ }
+
+Firstly, the number "1" is site id. Most
+likely the number should be the same as the value of ``SITE_ID`` setting.
+
+The value for the site id key is a nested dictionary with two keys:
+``'DB'`` (if True - then the rest of settings will be taken from the database)
+and ``'SETTINGS'`` - a dictionary with the actual settings.
+In this example ``'EMAIL'`` is the settings group
+and
+``'REPLY_BY_EMAIL'`` is the setting name, with ``True`` being the value.
+
+Setting group names and setting names can be looked up in files within
+``askbot/conf`` directory.
diff --git a/askbot/doc/source/localization.rst b/askbot/doc/source/localization.rst
new file mode 100644
index 0000000000..fbf51da6d1
--- /dev/null
+++ b/askbot/doc/source/localization.rst
@@ -0,0 +1,81 @@
+.. _localization:
+======================================
+Configuring language support in Askbot
+======================================
+
+There are several things to consider when localizing askbot:
+
+* :ref:`setting the site language `
+* :ref:`translation and display of the urls `
+* :ref:`translation of the strings in the user interface `
+* :ref:`enabling the multilingual setup `
+* :ref:`configuring the language-specific text search `
+
+.. _default-lang:
+
+Setting the site language
+=========================
+
+Specify the language code with the value of `LANGUAGE_CODE` parameter
+in the `settings.py` file::
+
+ LANGUAGE_CODE='es'
+
+.. note::
+ In the :ref:`multi-lingual configuration `
+ this language will be the default and the complete list of
+ language codes and their verbose names
+ is specified with the `LANGUAGES` parameter.
+
+.. _translate-urls:
+
+Translation of the URLs
+=======================
+
+There are also `settings.py` options to translate the urls:
+`ASKBOT_TRANSLATE_URL` and `ALLOW_UNICODE_SLUGS`.
+
+When the `ASKBOT_TRANSLATE_URL` is `True`, most urls will be translated,
+otherwise urls will be in English.
+When the `ALLOW_UNICODE_SLUGS` is `True` the question titles and user names
+will be presented as Unicode, e.g. with the Cyrillic, Chinese
+or Arabic characters, otherwise they will be transliterated into ASCII.
+
+If you are translating URLs (in the transifex you will probably
+find them as strings containing forward slashes) -
+take the following, in order to prevent broken links:
+
+* translation of multiple urls cannot be the same
+ (e.g. /question/ and /questions/ must have different translations)
+* if the same url is present in more than one translation file
+ those translation must be exactly the same
+
+.. _strings:
+
+Translation of strings in Askbot
+================================
+
+Translation of Askbot strings is performed at the `Transifex service `_.
+Please `register there `_ and work on the localization that interests you.
+We periodically update the source language strings on Transifex and pull
+the translations back into the project. Thanks!
+
+If you intend to translate urls - please :ref:`look here `.
+
+Please *do not* translate via github (if you know what it means),
+as it's better to have just one source of strings.
+
+The remaining part will will most likely interest developers,
+therefore here we tell what is specific to Askbot and
+refer the developer to the documentation of tools
+used in Askbot.
+
+Firstly - Askbot uses `Jinja2 `_ templates,
+not the Django templates and an Jinja2 adapter module for Django, called
+`Coffin `_. Please look at how translation
+tags are added to the templates processed by the `coffin` module.
+
+Secondly - instead of the django `makemessages` command - use `jinja2_makemessages`.
+
+Finally - to pull strings from the transifex use the `tx` program from
+`transifex-client pypi package `_.
diff --git a/askbot/doc/source/manage-logins1.png b/askbot/doc/source/manage-logins1.png
new file mode 100644
index 0000000000..e28676a694
Binary files /dev/null and b/askbot/doc/source/manage-logins1.png differ
diff --git a/askbot/doc/source/management-commands.rst b/askbot/doc/source/management-commands.rst
new file mode 100644
index 0000000000..89cdf6bfe5
--- /dev/null
+++ b/askbot/doc/source/management-commands.rst
@@ -0,0 +1,218 @@
+==========================
+Askbot management commands
+==========================
+
+There are a number of command line utilities help the forum administrator
+perform a range of tasks such as add or revoke administration privileges, back up and restore
+the forum data, fix database errors if such occur, etc.
+
+To run these commands there is a general pattern::
+
+ cd project_directory
+ python manage.py some_command [possible arguments and parameters]
+
+I.e. the commands are generally run from the project directory (the same
+one that contains your settings.py file) and they may use additional parameters and options.
+
+Data and User administration commands
+=====================================
+
+The bulk of the management commands fall into this group and will probably be the most frequently used.
+
++---------------------------------+-------------------------------------------------------------+
+| command | purpose |
++=================================+=============================================================+
+| `add_admin ` | Turn user into an administrator |
+| | `` is a numeric user id of the account |
++---------------------------------+-------------------------------------------------------------+
+| `apply_hinted_tags | Apply tags to all questions in batch given the list of tags |
+| --tag-names ` | provided with a file. The file must contain tags - |
+| | one per line. If many tags match - only the most frequent |
+| | will be selected. |
++---------------------------------+-------------------------------------------------------------+
+| `create_tag_synonyms --from | Creates tag synonym record from one name to another, |
+| --to | creates the tag named as given with the value of `--to` |
+| --user-id ` | if not existing, and the tag creator will be user with id |
+| | equal to the value of `--user-id` parameter. |
++---------------------------------+-------------------------------------------------------------+
+| `remove_admin ` | Remove admin status from a user account - the opposite of |
+| | the `add_admin` command |
++---------------------------------+-------------------------------------------------------------+
+| `add_askbot_user --user-name | Create a user account. If password is not given, an |
+| --email [--password]` | unusable password will be set. |
+| | The command does not create associations with |
+| | any of the external login providers. |
++---------------------------------+-------------------------------------------------------------+
+| `askbot_clear_moderation_queue` | Clear all items from the moderation queue |
++---------------------------------+-------------------------------------------------------------+
+| `askbot_award_badges` | Awards badges to users (only some badges are supported) |
++---------------------------------+-------------------------------------------------------------+
+| `askbot_recount_badges` | Fixes badge award counts, use when disabling/enabling badges|
++---------------------------------+-------------------------------------------------------------+
+| `merge_users | Merges user accounts and all related data from one user |
+| ` | to another, the "from user" account is deleted. |
++---------------------------------+-------------------------------------------------------------+
+| `get_tag_stats [-u|-t] [-e]` | Print tag subscription statistics, per tag (option -t) |
+| | or per user (option -u), if option -e is given, empty |
+| | records will be shown too (longer versions of the options |
+| | are: --per-tag-subscription-counts for -t, |
+| | --per-user-tag-subscription-counts for -u, and --print-empty|
+| | for -e). |
++---------------------------------+-------------------------------------------------------------+
+| `rename_tags --from | Rename, merge or split tags. User ID is the id of the user |
+| --to --user-id | who will be assigned as the performer of the retag action. |
+| ` | If more than is in the `--from` or the `--to` parameters |
+| | then that parameter quoted, e.g. `--to "tag1 tag2". |
+| | If user id is not given, the administrator with the smallest|
+| | id number will be automatically assigned. |
++---------------------------------+-------------------------------------------------------------+
+| `rename_tags_id --from | This command is the same as `rename_tags`, but takes the tag|
+| --to | id's as arguments. |
+| --user_id | |
+| ` | |
++---------------------------------+-------------------------------------------------------------+
+| `delete_unused_tags` | Permanently deletes tags that do not appear in any questions|
+| | , including the questions that are themselves |
+| | marked as deleted. |
++---------------------------------+-------------------------------------------------------------+
+| `update_avatar_data` | Set values of avatar types for all users; |
+| | this command may take up to 2s per user, because it makes |
+| | up to one http request per user to gravatar.com. |
+| | This data is used to display preferentially real faces |
+| | on the main page. |
++---------------------------------+-------------------------------------------------------------+
+| `askbot_rebuild_avatars` | Rebuilds avatar urls and creates avatar thumbnails |
++---------------------------------+-------------------------------------------------------------+
+| `build_thread_summary_cache` | Rebuilds cache for the question summary snippet. |
++---------------------------------+-------------------------------------------------------------+
+| `build_livesettings_cache` | Rebuilds cache for the live settings. |
++---------------------------------+-------------------------------------------------------------+
+| `delete_contextless_...` | `delete_contextless_badge_award_activities` |
+| | Deletes Activity objects of type badge award where the |
+| | related context object is lost. |
++---------------------------------+-------------------------------------------------------------+
+| `delete_contextless_activities` | Same as above, but works in a broader sense - when the |
+| | related context object does not exist, but the generic |
+| | foreign key to that object is still present. |
++---------------------------------+-------------------------------------------------------------+
+
+.. _data-import-commands:
+
+Data import commands
+====================
+
+These commands import or add data to the Askbot forum.
+
++---------------------------------+-------------------------------------------------------------+
+| command | purpose |
++=================================+=============================================================+
+| `load_stackexchange ` | Load SackExchange dump into Askbot. It is best to run this |
+| | command on empty database. Also - before running, make sure |
+| | that `askbot.importers.stackexchange` is in the list of |
+| | installed apps within your settings.py file (it might also |
+| | be necessary to run `syncdb` command to initiate the |
+| | SE importer tables). |
++---------------------------------+-------------------------------------------------------------+
+| `askbot_add_xml_content | Add xml Askbot data dumped with the Django command |
+| ` | `dumpdata` |
++---------------------------------+-------------------------------------------------------------+
+| `askbot_add_osqa_content | Add xml OSQA data dumped with the Django command |
+| ` | `export_osqa` |
++---------------------------------+-------------------------------------------------------------+
+| `askbot_import_jive | Import xml Jive data |
++---------------------------------+-------------------------------------------------------------+
+
+.. _email-related-commands:
+
+Email-related commands
+======================
+
+These commands deal with the periodic tasks related to sending and receiving email by askbot.
+A UNIX program called `cron` can run these commands at the specified times
+(please look up futher information about `cron` elsewhere).
+
+Any configurable options, related to these commands are accessible via "Email" section of the
+:ref:`live settings `.
+
++-------------------------------------+-------------------------------------------------------------+
+| command | purpose |
++=====================================+=============================================================+
+| `send_email_alerts` | Dispatches email alerts to the users according to |
+| | their subscription settings. This command does not |
+| | send instant" alerts because those are sent automatically |
+| | and do not require a separate command. |
+| | The most frequent alert setting that can be served by this |
+| | command is "daily", therefore running `send_email_alerts` |
+| | more than twice a day is not necessary. |
++-------------------------------------+-------------------------------------------------------------+
+| `send_unanswered_question_reminders`| Sends periodic reminders about unanswered questions. |
+| | This command may be disabled from the "email" section |
+| | of :ref:`live settings `, as well as |
+| | an initial wait period and the recurrence delay may be set. |
++-------------------------------------+-------------------------------------------------------------+
+| `send_accept_answer_reminders` | Sends periodic reminders about accepting best answers. |
+| | This command may be disabled from the "email" section |
+| | of the live settings, as well as the appropriate delay |
+| | parameters may be set. |
++-------------------------------------+-------------------------------------------------------------+
+| `askbot_send_moderation_alerts` | Sends alerts to moderators when there are items on the |
+| | queue. |
++-------------------------------------+-------------------------------------------------------------+
+
+Data repair commands
+====================
+
+Under certain circumstances (especially when using MySQL database with MyISAM
+storage engine or when venturing to adapt the software to your needs) some
+records in the database tables may become internally inconsistent.
+The commands from this section will help fix those issues.
+
+.. note::
+
+ Data inconsistency in the Askbot project is considered as a critical error and as a matter of
+ the project policy is addressed on the day of reporting. If you discover such issue - please
+ report it at the forum or by email at `admin@askbot.org`
+
++--------------------------------+-------------------------------------------------------------+
+| command | purpose |
++================================+=============================================================+
+| `add_missing_subscriptions` | adds default values of email subscription settings to users |
+| | that lack them |
++--------------------------------+-------------------------------------------------------------+
+| `fix_answer_counts` | recalculates answer counts for all questions |
++--------------------------------+-------------------------------------------------------------+
+| `fix_inbox_counts` | recalculates response counts in the user inboxes |
++--------------------------------+-------------------------------------------------------------+
+| `fix_revisionless_posts` | adds a revision record to posts that lack them |
++--------------------------------+-------------------------------------------------------------+
+| `fix_question_tags` | takes tag names from the record on the question table |
+| | and stores them in the tag table. This defect may show when |
+| | the server process is interrupted after the question was |
+| | saved, but tags were not updated, and the symptom is that |
+| | the question cannot be found via the tag search. |
++--------------------------------+-------------------------------------------------------------+
+
+The above commands are safe to run at any time, also they do not require
+additional parameters. In the future all these will be replaced with just one simple command.
+
+Developer commands
+==================
+
+Besides the commands designed to help run the forum, there are several aiming to help
+the developers of the Askbot project:
+
++--------------------------------+-------------------------------------------------------------+
+| command | purpose |
++================================+=============================================================+
+| `make_docs` | Rebuild HTML documentation for the project |
++--------------------------------+-------------------------------------------------------------+
+| `jinja2_makemessages` | Extract translatable strings into the `.po` files. Works |
+| | exactly the same way as the django `makemessages` command |
+| | but extracts strings from Jinja2 templates that are used |
+| | by the Askbot project. **Note:** the `jinja2_makemessages` |
+| | must be run from the `askbot` app directory, unlike all the |
+| | remaining commands that are expected to be run from the |
+| | site root directory. |
++--------------------------------+-------------------------------------------------------------+
+| `askbot_add_test_content` | Creates content with dummy data for testing |
++--------------------------------+-------------------------------------------------------------+
diff --git a/askbot/doc/source/mathjax.rst b/askbot/doc/source/mathjax.rst
new file mode 100644
index 0000000000..382ef3d42e
--- /dev/null
+++ b/askbot/doc/source/mathjax.rst
@@ -0,0 +1,44 @@
+.. _enable_mathjax:
+
+==========================
+Enabling MathJax in Askbot
+==========================
+
+MathJax_ is a rendering engine for mathematical
+expressions (based on cross-browser javascript code). On a MathJax-enabled site, such as Askbot you can display
+perfectly formatted mathematical formulae.
+
+However, MathJax distribution is very large and is not shipped with Askbot.
+
+To enable MathJax on your site, please do the following:
+
+Decide where you want to store mathjax (e.g. to share it with other applications as well)::
+
+ cd /some/directory
+
+Follow `mathjax installation instructions`_
+
+Edit webserver configuration so that url `http://example.com/mathjax`
+points to that directory and file `MathJax.js` is available at
+`http://example.com/mathjax/MathJax.js`.
+
+For Apache, a following line in the configuration file (maybe within a VirtualHost section) will do::
+
+ Alias /mathjax/ /filesystem/path/to/mathjax/
+
+Finally, enable MathJax in Askbot: "settings" -> "Markup formatting", check "Enable MathJax" and
+enter url `http://example.com/mathjax` (link "settings" is available to site administrators in the upper right corner of the forum pages).
+
+.. note::
+
+ your actual forum site must be served from the **same domain and subdomain**
+ as mathjax. This is **very important** for Firefox and some other browsers adhering
+ to the `same origin policy`_ for the browser cookies. Mathjax does use cookies to
+ store math display settings.
+
+One day enabling MathJax will be even easier, but `some more work`_ needs to be done for this to happen.
+
+.. _MathJax: http://www.mathjax.org/
+.. _`some more work`: http://bugs.askbot.org/issues/27
+.. _`mathjax installation instructions`: http://www.mathjax.org/resources/docs/?installation.html
+.. _`same origin policy`: http://en.wikipedia.org/wiki/Same_origin_policy
diff --git a/askbot/doc/source/moderation.rst b/askbot/doc/source/moderation.rst
new file mode 100644
index 0000000000..9ccaa5b000
--- /dev/null
+++ b/askbot/doc/source/moderation.rst
@@ -0,0 +1,30 @@
+====================
+Moderation in Askbot
+====================
+
+Regular users and forum Moderators can participate
+in the content moderation. Any user with sufficient reputation
+(this reputation threshold can be changed in the settings panel)
+can flag offensive posts.
+
+When a post receives a certain number of flags (adjustable),
+the post is automatically hidden.
+
+In addition users can delete posts, given a minimum reputation
+threshold (also adjustable) is met.
+Moderators can delete any post at any time.
+
+.. note::
+ All the minimum reputation thresholds can be adjusted
+ at the "settings" panel. Only site administrators have
+ access to the settings editor.
+
+Forum moderators can suspend and block users, by going to
+the "moderation" section in the user profile page.
+From the same page moderators can send an email to the user.
+
+Suspended users can only edit own posts, but cannot make new posts.
+Blocked users can only sign in and send feedback to
+the side administrators.
+
+Only site administrators can assign moderator status to any user.
diff --git a/askbot/doc/source/multilingual.rst b/askbot/doc/source/multilingual.rst
new file mode 100644
index 0000000000..75f93f0aee
--- /dev/null
+++ b/askbot/doc/source/multilingual.rst
@@ -0,0 +1,46 @@
+.. _multilingual:
+====================================
+Setting up multilingual Askbot sites
+====================================
+
+Askbot can support multiple languages on a single site, in which case
+urls are modified by a prefix made of a language code, e.g.
+base url /questions/ becomes /de/questions/ for the German localization.
+
+.. note::
+ If you want to learn about configuration of individual languages
+ please look :ref:`here `
+
+In order to enable the multilingual setup add the following to the
+`settings.py` file::
+
+ ASKBOT_MULTILINGUAL=True
+
+Also, activate the django's locale middleware by adding to the
+`MIDDLEWARE_CLASSES` the following entry::
+
+ 'django.middleware.locale.LocaleMiddleware',
+
+There is a standard Django setting `LANGUAGES`, which enables specific languages.
+By default this setting contains very many languages.
+You will likely want to narrow in the `settings.py` file
+the choice of the available languages::
+
+ #it's important to use ugettext_lazy or ugettext_noop
+ #in the settings.py file
+ from django.utils.translation import ugettext_lazy as _
+ LANGUAGES = (
+ ('de', _('German')),
+ ('en', _('English'))
+ )
+
+More on the usage of this setting can be read in the
+`Django documentation `_.
+
+The default language should be specified with the setting `LANGUAGE_CODE`.
+Users will be automatically redirected to the corresponding default language
+page from the non-prefixed urls.
+
+There are a number of `settings.py` options that control the various
+aspects of the site localization - the behaviour of the software depending on the
+currently active language.. Please read more about the :ref:`Localization of Askbot `.
diff --git a/askbot/doc/source/mysql-to-postgres.rst b/askbot/doc/source/mysql-to-postgres.rst
new file mode 100644
index 0000000000..c9c0e47753
--- /dev/null
+++ b/askbot/doc/source/mysql-to-postgres.rst
@@ -0,0 +1,114 @@
+.. _mysql-to-postgres:
+
+===========================================================
+Migrating data from MySQL to Postgresql
+===========================================================
+
+In this document we explain how to migrate from MySQL to Postgresql with different approaches.
+
+Askbot is optimized for Postgresql as search functionality works better with this database engine.
+
+.. note::
+ As a general advice, to reduce the database size - run the **cleanup** management command before starting the migration.
+
+
+Simple Migration of small database
+==================================
+
+If your database is small with few users and questions you can follow this steps:
+
+With MySQL as your database engine in your settings.py file run the following command::
+
+ python manage.py dumpdata > data.json
+
+After that change your database engine to Postgresql in settings.py and do::
+
+ python manage.py syncdb --migrate --noinput #create the database structure
+ python manage.py loaddata data.json
+
+
+.. note::
+ This won't work with large datasets because django will load all your
+ data into memory and you might run out of memory if the site data is too large.
+
+ This process can produce warnings that can be ignored.
+
+
+Data migration with py-mysql2pgsql
+==================================
+
+If the database is large this tool will come handy, to install it run::
+
+ pip install py-mysql2pgsql
+
+Create a configuration file called config.yml with the following contents::
+
+ mysql:
+ hostname: localhost
+ port: 3306
+ username: your_user
+ password: your_password
+ database: your_database
+
+ destination:
+ file:
+ postgres:
+ hostname: localhost
+ port: 5432
+ username: your_user
+ password: your_password
+ database: your_database
+
+Then run::
+
+ py-mysql2pgsql -v -f config.yml
+
+The script will start migrating the data and might take a while, depending on the database size.
+
+After the process is finished there are a couple of things left to do.
+
+Enable Postgresql full text search
+----------------------------------
+
+Askbot relies on special postgresql features for better search, in this case the py-mysql2pgsql tool will not
+add these features, so it requires to be added manually.
+
+To fix it run the command::
+
+ python manage.py init_postgresql_full_text_search
+
+This may also take some time, depending on the database size.
+Test this by running a search query on the askbot site.
+
+..
+ If you have an issue with the above command, it is possible to run the search setup sql script manually:
+ 1. Download `thread_and_post_models_10032013.plsql `_
+ 2. Download `user_profile_search_08312012.plsql `_
+ 3. Apply the scripts to your postgres database::
+ psql your_database < thread_and_post_models_10032013.plsql
+ psql your_database < user_profile_search_08312012.plsql
+
+
+Fixing data types
+-----------------
+
+The py-mysql2pgsql translates datatype a bit different than Django ORM do, to keep the same
+datatypes do the following:
+
+1. Create a new postgresql database and run sync and migrate commands the following way::
+
+ python manage.py syncdb --migrate --noinput --no-initial-data
+
+2. Dump the converted database data with binary format::
+
+ pg_dump --format=c -a database_name > dump_name
+
+3. Restore it into your current Django database::
+
+ pg_restore -a --disable-triggers -d django_database dump_name
+
+
+Links
+=====
+
+* `py-mysql2pgsql `_
diff --git a/askbot/doc/source/optional-modules.rst b/askbot/doc/source/optional-modules.rst
new file mode 100644
index 0000000000..19170b27af
--- /dev/null
+++ b/askbot/doc/source/optional-modules.rst
@@ -0,0 +1,355 @@
+================
+Optional modules
+================
+
+Askbot supports a number of optional modules, enabling certain features, not available
+in askbot by default.
+
+.. _sphinx-search:
+
+Sphinx search
+=============
+Askbot supports Sphinx search - and at this point only for MySQL.
+Tested with sphinx 0.9.8.
+May be a little outdated, please give your feedback if that is the case.
+
+To enable:
+
+* install `sphinx search package `_
+* if necessary to support Chinese language, instead take `sphinx for Chinese `_
+* prepare configuration file by running command ``python manage.py get_askbot_sphinx_config > sphinx.conf``
+* if necessary, modify the ``.conf`` file (may be needed for language other than English
+* place the ``sphinx.conf`` file to an appropriate location, like /etc/sphinx/
+
+Install django-sphinx python module (and follow all instructions)
+
+ pip install django-sphinx
+
+In ``settings.py`` add::
+
+ SPHINX_API_VERSION = 0x113 #according to django sphinx doc
+ USE_SPHINX_SEARCH = True
+ ASKBOT_SPHINX_SEARCH_INDEX = 'askbot'
+
+.. note::
+ Value of SPHINX_API_VERSION may depend on the version of
+ python sphinx api installed with the django-sphinx application,
+ please refer to the django-sphinx documentation.
+
+Initialize the sphinx index (may need to log in as root)::
+
+ indexer askbot --config /etc/sphinx/sphinx.conf
+
+Start the sphinx search daemon::
+
+ /usr/local/bin/searchd --config /etc/sphinx/sphinx.conf &
+
+Also, add the line above to the file /etc/rc.d/rc.local or equivalent to start the daemon
+when the server reboots.
+
+Set up a periodic re-indexing job (using cron)::
+
+ indexer askbot --rotate --config /etc/sphinx/sphinx.conf
+
+Finally, add lin
+
+.. _embedding-video:
+
+Haystack search
+=============
+Askbot supports `Haystack `_, a modular search framework that supports popular search engine backends as
+Solr, Elasticsearch, Whoosh and Xapian.
+
+.. note::
+ Haystack support in Askbot is a new feature,
+ please give us your feedback at ``support@askbot.com``
+ regarding the possible improvements.
+
+To enable:
+
+* add 'haystack' to INSTALLED_APPS
+* add ENABLE_HAYSTACK_SEARCH = True in settings.py
+* Configure your search backend according to your setup following `this guide `_
+
+Solr and Multilingual Support
+-------------------------
+
+There is more documentation about solr and multilingual support please visit :ref:`this link `
+
+Embedding video
+===============
+
+Want to share videos in askbot posts? It is possible, but you will have to install a forked
+version of ``markdown2`` module, here is how::
+
+ pip uninstall markdown2
+ pip install -e git+git://github.com/andryuha/python-markdown2.git#egg=markdown2
+
+Also, for this to work you'll need to have :ref:`pip` and :ref:`git` installed on your system.
+
+Finally, please go to your forum :ref:`live settings ` -->
+"Settings for askbot data entry and display" and check "Enable embedding video".
+
+Limitation: at the moment only YouTube and Veoh are supported.
+
+.. _ldap:
+
+LDAP authentication
+===================
+
+To enable authentication via LDAP
+(Lightweight Directory Access Protocol, see more info elsewhere)
+, first :ref:`install `
+``python-ldap`` package:
+
+ pip install python-ldap
+
+After that, add configuration parameters in :ref:`live settings `,
+section "LDAP settings"
+(url ``/settings/LDAP_SETTINGS``, relative to the forum base url)
+
+.. note::
+ While it is possible to configure LDAP via web interface,
+ it is actually more safe to add them in your ``settings.py`` file in the
+ :ref:`LIVESETTINGS_OPTIONS ` dictionary.
+ Consider that a breach in security of your forum might open
+ malicious access into your LDAP directory.
+
+The parameters are (note that some have pre-set defaults that might work for you)::
+
+* in Login Provider Settings select "enable local login"
+ - this makes login/password form available
+* enable/disable LDAP for password login -
+ must check that, to connect the login/password form to LDAP flow
+* create accounts automatically or not (``LDAP_AUTOCREATE_USERS``)
+* protocol version (``LDAP_PROTOCOL_VERSION``) (version 2 is insecure and deprecated)
+* ldap url (``LDAP_URL``)
+* base distinguished name, 'dn' in LDAP parlance (``LDAP_BASEDN``)
+* user id field name (``LDAP_USERID_FIELD``)
+* email field name (``LDAP_EMAIL_FIELD``)
+* user name filter template (``LDAP_USERNAME_FILTER_TEMPLATE``)
+ must have two string placeholders.
+* given (first) name field (``LDAP_GIVEN_NAME_FIELD``)
+* surname (last name) field (``LDAP_SURNAME_FIELD``)
+* common name field (``LDAP_COMMON_NAME_FIELD``)
+ either given and surname should be used or common name.
+ All three are not necessary - either first two or common.
+ These fields are used to extract users first and last names.
+* Format of common name (``LDAP_COMMON_NAME_FIELD_FORMAT``)
+ values can be only 'first,last' or 'last,first' - used to
+ extract last and first names from common name
+
+There are three more optional parameters that must go to the ``settings.py`` file::
+
+* ``LDAP_LOGIN_DN``
+* ``LDAP_PASSWORD``
+* ``LDAP_EXTRA_OPTIONS``, a list of two-item tuples - of names and values of
+ the options. Option names must be upper case strings all starting with ``OPT_``
+ as described in the `python ldap library documentation `_. An often used option is (`OPT_REFERRALS`, 0).
+* ``LDAP_AUTHENTICATE_FUNCTION`` - dotted python path to optional function that
+ can override the default `ldap_authenticate` function. This function allows to
+ completely customize the LDAP login procedure.
+ To see what is expected of this function (input parameters and the return value) -
+ look at the end of the doc string at
+ `askbot.deps.django_authopenid.ldap_auth.ldap_authenticate_default`.
+ One use case for the custom function is determining to which group
+ a user might belong or check any additional access rules that might be
+ stored in your LDAP directory. Another use case - is the case when
+ the default procedure just does not work for you.
+* ``LDAP_AUTHENICATE_FAILURE_FUNCTION`` - python dotted path to an additional function
+ that may be called after a unsuccessful authentication.
+ This function can be used to set custom error messages to the login form.
+ The function should take two parameters (in the following order): user_info, login_form.
+ user_info - is the same dictionary
+ that is returned by the `ldap_authenticate` function.
+* ``LDAP_CREATE_USER_FUNCTION`` - python dotted path to function that will create
+ the ldap user, should actually return a user association object, like
+ ``askbot.deps.django_authopenid.ldap_auth.ldap_create_user_default``.
+ Function takes return value of the ldap authenticate function as a sole parameter.
+
+
+Use these when you have the "directory master passsword" -
+for a specific user who can access the rest of the directory,
+these were not added to the live settings due to security concerns.
+
+``LDAP_USER`` and ``LDAP_PASSWORD`` will be used only if both are provided!
+
+Since LDAP authentication requires so many parameters,
+you might need to :ref:`debug ` the settings.
+The function to look at is `askbot.deps.django_authopenid.backends.ldap_authenticate`.
+If you have problems with LDAP please contact us at support@askbot.com.
+
+The easiest way to debug - insert ``import pdb; pdb.set_trace()`` line into function
+`askbot.deps.django_authopenid.backends.ldap_authenticate`,
+start the ``runserver`` and step through.
+
+Uploaded avatars
+================
+
+To enable uploadable avatars (in addition to :ref:`gravatars `),
+please install application ``django-avatar``, with the following command::
+
+ pip install django-avatar
+
+Then add ``avatar`` to the list of ``INSTALLED_APPS`` in your ``settings.py`` file
+and run (to install database table used by the avatar app):
+
+ python manage.py syncdb
+
+Also, settings ``MEDIA_ROOT`` and ``MEDIA_URL`` will need to be added to your ``settings.py`` file.
+
+.. note::
+
+ Version of the ``avatar`` application available at pypi may not
+ be up to date, so please take the development version from the
+ github repository
+
+Custom section in the user profile
+==================================
+Sometimes you might want to add a completely custom section
+to the user profile, available via an additional tab.
+
+This is possible by editing the ``settings.py`` file,
+which means that to use this feature you must have sufficient
+access to the webserver file system.
+
+Add a following setting to your ``settings.py``::
+
+ ASKBOT_CUSTOM_USER_PROFILE_TAB = {
+ 'NAME': 'some name',
+ 'SLUG': 'some-name',
+ 'CONTENT_GENERATOR': 'myapp.views.somefunc'
+ }
+
+The value of ``ASKBOT_CUSTOM_USER_PROFILE_TAB['CONTENT_GENERATOR']``
+should be a path to the function that returns the widget content
+as string.
+
+Here is a simple example of the content generator
+implemented as part of the fictional application called ``myapp``::
+
+ from myapp.models import Thing#definition not shown here
+ from django.template.loader import get_template
+ from django.template import Context
+
+ def somefunc(request, profile_owner):
+ """loads things for the ``profile_owner``
+ and returns output rendered as html string
+ """
+ template = get_template('mytemplate.html')
+ things = Thing.objects.filter(user = profile_owner)
+ return template.render(Context({'things': things}))
+
+The function is very similar to the regular
+Django view, but returns a string instead of the ``HttpResponse``
+instance.
+
+Also, the method must accept one additional argument -
+an instance of the ``django.contrib.auth.models.User`` object.
+
+Wordpress Integration
+=====================
+
+To enable authentication for self hosted wordpress sites(wordpress.com blogs will work with openid login). To enable it follow the following steps:
+
+* Check if you have the package `"python_wordpress_xmlrpc `_ from pypi.
+* Go to your wordpress blog admin panel and serch for: Settings->Writing->Remote Publishing then check the box for XML-RPC.
+* Go back to your askbot site settings and click on *Login Provider Settings* and then activate the option *Activate to allow login with self-hosted wordpress site*,
+* Input your blog url to the xmlrpc.php file it will look something like this http://yoursite.com/xmlrpc.php
+* Upload an icon for display in the login area.
+
+After doing this steps you should be able to login with your self hosted wordpress site user/password combination.
+
+
+Celery for background jobs
+==========================
+
+Askbot supports `celery `_ distributed task queue for some task, to enable it follow the following steps:
+
+* Install the following packages: `celery `_, `django-celery `_, `django-kombu `_
+* Set **CELERY_ALWAYS_EAGER** setting value to **False**
+* Run the celery daemon: for this you can use generic init scripts or supervisor, `celery documentation have more information `_
+
+For `supervisor `_: add this sample config file named askbot.conf into /etc/supervisor/conf.d/ directory::
+
+ [program:askbot_celery]
+ command=celeryd --loglevel=INFO
+
+ environment=PYTHONPATH=/path/to/project
+ directory=/path/to/project
+
+ user=nobody
+ numprocs=1
+ stdout_logfile=/var/log/askbot_celery.log
+ stderr_logfile=/var/log/askbot_celery.err
+ autostart=true
+ autorestart=true
+ startsecs=10
+
+Then run **supervisorctl update** and it will be started. For more information about job handling with supervisor please visit `this link `_.
+
+
+Receiving replies for email notifications
+===========================================
+
+Askbot supports posting replies by email. For this feature to work ``Lamson`` and ``django-lamson`` need to be installed on the system. To install all the necessery dependencies execute the following command:
+
+ pip install django-lamson
+
+.. note::
+ On Windows installation of the Lamson module may require
+ additional work. Askbot does not support this feature
+ on Windows automatically.
+
+The lamson daemon needs a folder to store it's mail queue files and a folder to store log files, create the folders folder named ``run`` and ``logs`` within your project folder by executing the following commands:
+
+ mkdir run
+
+ mkdir logs
+
+The minimum settings required to enable this feature are defining the port and binding address for the lamson SMTP daemon and the email handlers within askbot. Edit your settings.py file to include the following::
+
+ LAMSON_RECEIVER_CONFIG = {'host': 'your.ip.address', 'port': 25}
+ LAMSON_HANDLERS = ['askbot.mail.lamson_handlers']
+ LAMSON_ROUTER_DEFAULTS = {'host': '.+'}
+
+In the list of ``installed_apps`` add the app ``django_lamson``.
+
+The ``LAMSON_RECEIVER_CONFIG`` parameter defines the binding address/port for the SMTP daemon. To recieve internet email you will need to bind to your external ip address and port 25. If you just want to test the feature by sending eamil from the same system you could bind to 127.0.0.1 and any higher port.
+
+To run the lamson SMTP daemon you will need to execute the following management command::
+
+ python manage.py lamson_start
+
+To stop the daemon issue the following command::
+
+ python manage.py lamson_stop
+
+Note that in order to be able to bind the daemon to port 25 you will need to execute the command as a superuser.
+
+Within the askbot admin interface there are 4 significant configuration points for this feature.
+
+* In the email section, the "Enable posting answers and comments by email" controls whether the feature is enabled or disabled.
+* The "reply by email hostname" needs to be set to the email hostname where you want to receive the email replies. If for example this is set to "example.com" the users will post replies to addresses such as "4wffsw345wsf@example.com", you need to point the MX DNS record for that domain to the address where you will run the lamson SMTP daemon.
+* The last setting in this section controls the threshold for minimum length of the reply that is posted as an answer to a question. If the user is replying to a notification for a question and the reply body is shorter than this threshold the reply will be posted as a comment to the question.
+* In the karma thresholds section the "Post answers and comments by email" defines the minimum karma for users to be able to post replies by email.
+
+If the system where lamson is hosted also acts as an email server or you simply want some of the emails to be ignored and sent to another server you can define forward rules. Any emails matching these rules will be sent to another smtp server, bypassing the reply by email function. As an example by adding the following in your settings.py file::
+
+ LAMSON_FORWARD = (
+ {
+ 'pattern': '(.*?)@(.subdomain1|subdomain2)\.example.com',
+ 'host': 'localhost',
+ 'port': 8825
+ },
+ {
+ 'pattern': '(info|support)@example.com',
+ 'host': 'localhost',
+ 'port': 8825
+ },
+
+ )
+
+any email that was sent to anyaddress@sobdomain1.example.com or anyaddress@sobdomain2.example.com or info@example.com will be forwarded to the smtp server listening on port 8825. The pattern parameter is treated as a regular expression that is matched against the ``To`` header of the email message and the ``host`` and ``port`` are the host and port of the smtp server that the message should be forwarded to.
+
+If you want to run the lamson daemon on a port other than 25 you can use a mail proxy server such as ``nginx`` that will listen on port 25 and forward any SMTP requests to lamson. Using nginx you can also setup more complex email handling rules, such as for example if the same server where askbot is installed acts as an email server for other domains you can configure nginx to forward any emails directed to your askbot installation to lamson and any other emails to the mail server you're using, such as ``postfix``. For more information on how to use nginx for this please consult the nginx mail module documentation `nginx mail module documentation `_ .
diff --git a/askbot/doc/source/password-signin.png b/askbot/doc/source/password-signin.png
new file mode 100644
index 0000000000..0e9a75f1c5
Binary files /dev/null and b/askbot/doc/source/password-signin.png differ
diff --git a/askbot/doc/source/pw-register.png b/askbot/doc/source/pw-register.png
new file mode 100644
index 0000000000..1e7ecd43a2
Binary files /dev/null and b/askbot/doc/source/pw-register.png differ
diff --git a/askbot/doc/source/recover-account.png b/askbot/doc/source/recover-account.png
new file mode 100644
index 0000000000..8ee05ede80
Binary files /dev/null and b/askbot/doc/source/recover-account.png differ
diff --git a/askbot/doc/source/roadmap.rst b/askbot/doc/source/roadmap.rst
new file mode 100644
index 0000000000..68f7942d53
--- /dev/null
+++ b/askbot/doc/source/roadmap.rst
@@ -0,0 +1,55 @@
+Intro
+=========
+ROADMAP aims to streamline activities of the Askbot open source project and
+to minimize ad-hoc approaches of "big-picture" level.
+
+Askbot is a Question and Answer system for the normal people!
+
+Basic principles of the project
+==================================
+
+We favor plain and minimalistic style of programming, but pay
+ attention to detail - especially details of user experience.
+
+We try do develop using the following workflow:
+
+* specify problem that we try to solve
+* create requirements that will guarantee a solution, once met
+* dream up some implementation ideas (maybe even some sketches on the paper)
+* discuss and decide on the best one
+* write and test code
+
+The process doesn't have to be this formal all the time, but trying to stick
+to some subset of this almost always helps!
+Especially it helps to iron out disagreements between
+individual programmers (which if you are one - you know are qute common).
+
+Ad-hoc programming - i.e. simply go and add code - is not really encouraged.
+This works fine in the one person team or when the team consists of
+best friends, but is almost sure to fail in a heterogenous group.
+
+Architecture and Requirements
+=====================================
+Obviously Django and Python are pre-made choices - so this
+is not going to change any time soon. At this point all of
+the client side Javascript is written using jQuery library.
+
+Our basic principle is that Askbot should be a mashable Q&A component.
+Askbot is an application written in Python/Django. So it should be
+distributable as a Django App alone, but can be deployed as a dedicated site
+with the script "askbot-setup", that also ships with askbot.
+
+If we develop a sub-system that can be used in the broader scope -
+we package it as a separate django application (login system is one example).
+
+We will start using Google Closure library soon!
+
+Skins
+-----------
+Skins eventually must be upgrade-stable - that is people who created custom
+skins should not need to change anything if something changes in the code
+
+Admin interface
+-----------------------
+We use a forked application "livesettings" that ideally should be merged
+back to the original livesettings application.
diff --git a/askbot/doc/source/run-time-configuration.rst b/askbot/doc/source/run-time-configuration.rst
new file mode 100644
index 0000000000..46ec025af6
--- /dev/null
+++ b/askbot/doc/source/run-time-configuration.rst
@@ -0,0 +1,21 @@
+.. _run-time-configuration:
+
+==================================
+Run-time configuration of Askbot
+==================================
+
+Any of this can be done later via url `/settings` at your site - log in as a superuser and explore what is available.
+
+.. note::
+ Probably the first two settings you should update are the Google Site verification Key for the sitemap
+ and (if you want Google search engine crawl your site timely) the Google Analytics Key (if you wish to monitor
+ the site traffic)
+
+Google will be pinged each time question, answer or comment is saved or a question deleted and the
+site verification key is required for this to work. Please obtain the Site Verification Key at the
+`Google Webmasters Tools`_ site.
+
+There are many more settings that can be changed at any time without restarting the site. More
+documentaition on this topic will be added in the near future.
+
+.. _`Google Webmasters Tools`: https://www.google.com/webmasters/tools/
diff --git a/askbot/doc/source/sending-email-to-askbot.rst b/askbot/doc/source/sending-email-to-askbot.rst
new file mode 100644
index 0000000000..b50b8c8e0d
--- /dev/null
+++ b/askbot/doc/source/sending-email-to-askbot.rst
@@ -0,0 +1,33 @@
+=======================
+Sending email to askbot
+=======================
+
+Askbot supports asking questions by email via the IMAP protocol,
+answering by email is not yet supported.
+
+.. note::
+ This feature is still experimental and some emails will not
+ be parsed, please report any issues at the askbot forum.
+
+To enable the feature, please:
+
+* set up an IMAP mailbox called "INBOX"
+* in your ``settings.py`` file fill out values
+ ``IMAP_HOST``, ``IMAP_HOST_USER``, ``IMAP_HOST_PASSWORD``,
+ ``IMAP_PORT`` and ``IMAP_USE_TLS``
+* in the site :ref:`live settings `, enable the
+ feature
+* set up a cron job to periodically run command
+ :ref:`post_emailed_questions `.
+ This command will connect to the inbox, and post questions,
+ based on the incoming messages.
+
+The email address to send the questions will be
+``@``. Also, there is a quite strict
+requirement to the format of incoming messages - described
+in a response to any incorrectly formatted emails.
+
+.. warning::
+ the "INBOX" used to post messages to askbot must be dedicated
+ do not use any other mailbox as all messages
+ are **automatically deleted** after each processing.
diff --git a/askbot/doc/source/settings.rst b/askbot/doc/source/settings.rst
new file mode 100644
index 0000000000..d07e697bb0
--- /dev/null
+++ b/askbot/doc/source/settings.rst
@@ -0,0 +1,14 @@
+=================================
+Settings for ``settings.py`` file
+=================================
+
+* ``ALLOW_UNICODE_SLUGS`` - if ``True``, slugs will use unicode, default - ``False``
+
+There are more settings that are not documented yet,
+but most are described in the ``settings.py`` template:
+
+ askbot/setup_templates/settings.py.mustache
+
+TODO: describe all of them here.
+
+
diff --git a/askbot/doc/source/signin-with-aol.png b/askbot/doc/source/signin-with-aol.png
new file mode 100644
index 0000000000..4f769b77f5
Binary files /dev/null and b/askbot/doc/source/signin-with-aol.png differ
diff --git a/askbot/doc/source/solr.rst b/askbot/doc/source/solr.rst
new file mode 100644
index 0000000000..5d4e464e0c
--- /dev/null
+++ b/askbot/doc/source/solr.rst
@@ -0,0 +1,200 @@
+.. _solr:
+
+===========================================================
+Installing Apache Solr with Apache Tomcat 7 in Ubuntu 12.04
+===========================================================
+
+
+This document describes the process of instalation of Apache Solr search engine in Ubuntu Server 12.04
+for askbot use. To follow this steps you must have already askbot installed and running.
+
+Installation of the required packages
+=====================================
+
+Install packages `tomcat7` and `tomcat7-admin`::
+
+ sudo apt-get install tomcat7 tomcat7-admin
+
+Download Apache Solr from the `official site `_::
+
+ wget http://www.bizdirusa.com/mirrors/apache/lucene/solr/3.6.2/apache-solr-3.6.2.tgz
+
+Install `django-haystack` module in your Python environment::
+
+ pip install django-haystack
+
+Setting up Tomcat
+=================
+
+After installing Tomcat, add users to the Tomcat server.
+Edit `/etc/tomcat7/tomcat-users.xml` and add the following::
+
+
+
+
+
+
+
+
+
+
+Then restart the service::
+
+ service tomcat7 restart
+
+Now you should be able to connect to the web management interface
+via http://youripaddress:8080/manager
+and entering there user name and password.
+
+Installing Solr under Tomcat
+============================
+
+Extract the solr tar archive from the previous download::
+
+ tar -xzf apache-solr-3.6.2.tgz
+
+Copy the `example/` directory from the source to `/opt/solr/`.
+Open the file `/opt/solr/example/solr/conf/solrconfig.xml`
+and Modify the dataDir parameter as::
+
+ ${solr.data.dir:/opt/solr/example/solr/data}
+
+Copy the `.war` file in dist directory to `/opt/solr`::
+
+ cp dist/apache-solr-3.6.2.war /opt/solr
+
+Create `solr.xml` inside of `/etc/tomcat/Catalina/localhost/` with the following contents::
+
+
+
+
+
+
+Restart the tomcat server::
+
+ service tomcat7 restart
+
+Now you should be able to access the "solr" application
+in the Tomcat manager at `/solr/admin`.
+
+Configuring Askbot with Solr
+============================
+
+Open settings.py file and configure the following::
+
+ ENABLE_HAYSTACK_SEARCH = True
+ HAYSTACK_CONNECTIONS = {
+ 'default': {
+ 'ENGINE': 'haystack.backends.solr_backend.SolrEngine',
+ 'URL': 'http://127.0.0.1:8080/solr'
+ }
+ }
+
+After that create the solr schema and store the output to your solr instalation::
+
+ python manage.py build_solr_schema > /opt/solr/example/solr/conf/schema.xml
+
+Restart tomcat server::
+
+ service tomcat7 restart
+
+Build the Index for the first time::
+
+ python manage.py rebuild_index
+
+The output should be something like::
+
+ All documents removed.
+ Indexing 43 people.
+ Indexing 101 posts.
+ Indexing 101 threads.
+
+Now all should be ready,
+just restart the askbot application
+and test the search with haystack and solr.
+
+.. _solr-multilingual:
+
+Multilingual Setup
+==================
+
+.. note::
+ This is experimental feature, currently xml generation works for:
+ English, Spanish, Chinese, Japanese, Korean and French.
+
+Add the following to settings.py::
+
+ HAYSTACK_ROUTERS = ['askbot.search.haystack.routers.LanguageRouter',]
+
+Configure the HAYSTACK_CONNECTIONS settings with the following format for each language::
+
+ HAYSTACK_CONNECTIONS = {
+ 'default': {
+ 'ENGINE': 'haystack.backends.solr_backend.SolrEngine',
+ 'URL': 'http://127.0.0.1:8080/solr'
+ },
+ 'default_': {
+ 'ENGINE': 'haystack.backends.solr_backend.SolrEngine',
+ 'URL': 'http://127.0.0.1:8080/solr/core-'
+ },
+ }
+
+Generate xml files according to language::
+
+ python manage.py askbot_build_solr_schema -l