[
  {
    "path": ".gitignore",
    "content": "*.log\n*.pyc\n*~\nbuild/\nlocalsettings.py\n.svn/\n.svn/*\ndata.db\n*.wpr\nfacebook.py\n"
  },
  {
    "path": "AUTHORS",
    "content": "AUTHORS\n\nShabda Raaj <shabda at uswaretech dot com>\nLakshman Prasad <lakshman at agiliq dot com>\nAshok Raavi <ashok at agiliq dot com>\n\nCONTRIBUTORS\n\noliland <oliland at oliland-desktop.(none)>\nBenny Daon <bennydaon at gmail dot com>\nPeter Sidebotham <peter.sidebotham at studioidm dot net>\nclay <clay at pen.(none)>\nKen Sternberg <sternberg at speakeasy dot net>\nOliver Kingshott <oliland at olivaio.(none)>\ntwidi <s.angel at twidi dot com>\nAitzol Naberan <aitzol at arno.(none)>\ncyrildoussin <cdoussin at gmail dot com>\nzay2 <alan.kesselmann at gmail dot com>\nPhui Hock <phuihock at gmail dot com>\nDavid Michon <davidmichon at ip-187-90-50-54.user.vivozap.com dot br>\nJustin Wong <stryderjzw at gmail dot com>\nRodrigo Chacon <rochacon at gmail dot com>\nDidier Rano <didier.rano at gmail dot com>\nDavid Michon <davidmichon at ip-187-90-56-229.user.vivozap.com dot br>\nJosu Azpillaga <josu at josu-laptop.(none)>\nHel <helenst at gmail dot com>\nJaved Khan <javed at agiliq dot com>\nRoman Vorushin <roman.vorushin at gmail dot com>\n"
  },
  {
    "path": "LICENSE",
    "content": "This work is dual licensed under GPLv3 and BSD license.\n\nBSD\n-------\n\nCopyright (c) 2009-2010, Agiliq Solutions\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\nRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\nRedistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\nNeither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\nGPLv3\n-----------\n\nCopyright (c) 2010, Agiliq Solutions\nAll rights reserved.\n\n                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n                            Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n                       TERMS AND CONDITIONS\n\n  0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n  1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n  2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n  3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n  4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n  5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\n    a) The work must carry prominent notices stating that you modified\n    it, and giving a relevant date.\n\n    b) The work must carry prominent notices stating that it is\n    released under this License and any conditions added under section\n    7.  This requirement modifies the requirement in section 4 to\n    \"keep intact all notices\".\n\n    c) You must license the entire work, as a whole, under this\n    License to anyone who comes into possession of a copy.  This\n    License will therefore apply, along with any applicable section 7\n    additional terms, to the whole of the work, and all its parts,\n    regardless of how they are packaged.  This License gives no\n    permission to license the work in any other way, but it does not\n    invalidate such permission if you have separately received it.\n\n    d) If the work has interactive user interfaces, each must display\n    Appropriate Legal Notices; however, if the Program has interactive\n    interfaces that do not display Appropriate Legal Notices, your\n    work need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n  6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\n    a) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by the\n    Corresponding Source fixed on a durable physical medium\n    customarily used for software interchange.\n\n    b) Convey the object code in, or embodied in, a physical product\n    (including a physical distribution medium), accompanied by a\n    written offer, valid for at least three years and valid for as\n    long as you offer spare parts or customer support for that product\n    model, to give anyone who possesses the object code either (1) a\n    copy of the Corresponding Source for all the software in the\n    product that is covered by this License, on a durable physical\n    medium customarily used for software interchange, for a price no\n    more than your reasonable cost of physically performing this\n    conveying of source, or (2) access to copy the\n    Corresponding Source from a network server at no charge.\n\n    c) Convey individual copies of the object code with a copy of the\n    written offer to provide the Corresponding Source.  This\n    alternative is allowed only occasionally and noncommercially, and\n    only if you received the object code with such an offer, in accord\n    with subsection 6b.\n\n    d) Convey the object code by offering access from a designated\n    place (gratis or for a charge), and offer equivalent access to the\n    Corresponding Source in the same way through the same place at no\n    further charge.  You need not require recipients to copy the\n    Corresponding Source along with the object code.  If the place to\n    copy the object code is a network server, the Corresponding Source\n    may be on a different server (operated by you or a third party)\n    that supports equivalent copying facilities, provided you maintain\n    clear directions next to the object code saying where to find the\n    Corresponding Source.  Regardless of what server hosts the\n    Corresponding Source, you remain obligated to ensure that it is\n    available for as long as needed to satisfy these requirements.\n\n    e) Convey the object code using peer-to-peer transmission, provided\n    you inform other peers where the object code and Corresponding\n    Source of the work are being offered to the general public at no\n    charge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n  7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\n    a) Disclaiming warranty or limiting liability differently from the\n    terms of sections 15 and 16 of this License; or\n\n    b) Requiring preservation of specified reasonable legal notices or\n    author attributions in that material or in the Appropriate Legal\n    Notices displayed by works containing it; or\n\n    c) Prohibiting misrepresentation of the origin of that material, or\n    requiring that modified versions of such material be marked in\n    reasonable ways as different from the original version; or\n\n    d) Limiting the use for publicity purposes of names of licensors or\n    authors of the material; or\n\n    e) Declining to grant rights under trademark law for use of some\n    trade names, trademarks, or service marks; or\n\n    f) Requiring indemnification of licensors and authors of that\n    material by anyone who conveys the material (or modified versions of\n    it) with contractual assumptions of liability to the recipient, for\n    any liability that these contractual assumptions directly impose on\n    those licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n  8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n  9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n  10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n  11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n  12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n  13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n  14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n  15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n  16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n  17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\n                     END OF TERMS AND CONDITIONS\n\n            How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nstate the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software: you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation, either version 3 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program.  If not, see <http://www.gnu.org/licenses/>.\n\nAlso add information on how to contact you by electronic and paper mail.\n\n  If the program does terminal interaction, make it output a short\nnotice like this when it starts in an interactive mode:\n\n    <program>  Copyright (C) <year>  <name of author>\n    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, your program's commands\nmight be different; for a GUI interface, you would use an \"about box\".\n\n  You should also get your employer (if you work as a programmer) or school,\nif any, to sign a \"copyright disclaimer\" for the program, if necessary.\nFor more information on this, and how to apply and follow the GNU GPL, see\n<http://www.gnu.org/licenses/>.\n\n  The GNU General Public License does not permit incorporating your program\ninto proprietary programs.  If your program is a subroutine library, you\nmay consider it more useful to permit linking proprietary applications with\nthe library.  If this is what you want to do, use the GNU Lesser General\nPublic License instead of this License.  But first, please read\n<http://www.gnu.org/philosophy/why-not-lgpl.html>.\n"
  },
  {
    "path": "README.rst",
    "content": "WARNING: This app is not maintained anymore\n-------------------------------------------------\nThis repo is here for archive purposes, but unmaintained. There are much better social auth libraries.\n\n* https://github.com/omab/django-social-auth/ \n* https://github.com/pennersr/django-allauth\n\n\n\nWhat it does.\n--------------\n\n#. Allow logging in via various providers.\n#. Import contacts from various third party sites, to find out which of your\n   friends already use our service.\n\nLogging In\n----------\n\nThis is a application to enable authentication via various third party sites.\nIn particular it allows logging in via\n\n#. Twitter\n#. Gmail\n#. Facebook\n#. Yahoo(Essentially openid)\n#. OpenId\n#. Github\n#. Foursquare\n\nLibs you need to install\nSee requirements.txt\nuse `pip install -r requirements.txt` to install all dependencies at once\nNote that you will probably require git and mercurial installed for pip to\nfetch the requirements.\n\nThe API Keys are available from\n\n* http://www.facebook.com/developers/createapp.php \n* https://developer.yahoo.com/dashboard/createKey.html\n* https://www.google.com/accounts/ManageDomains\n* http://twitter.com/oauth_clients \n* https://github.com/settings/applications/new\n* https://developer.foursquare.com/overview/auth.html\n\nHow it works.\n--------------\n\n* **Openid**: Users need to provide their openid providers. Talk to the providers and\n  login.\n* **Yahoo**: Yahoo is an openid provider. Talk to Yahoo endpoints. (Endpoint: http://yahoo.com)\n* **Google**: Google is a provider. Talk to them. (Endpoint: https://www.google.com/accounts/o8/id)\n* **Facebook**: Facebook connect provides authentication framework.\n* **Twitter**: We use Twitter Oauth for authentication. In theory, Oauth shouldn't be\n  used for authentication. (It is an autorisation framework, not an authentication one),\n  In practice it works pretty well. Once you have an access_token, and a name, essentially\n  authenticated.\n* **Github**:We use Github Oauth for authentication. As like Twitter, it works\n  pretty well.\n* **Foursquare**:We use Oauth2.0 for authenticating via foursquare.\n\nReferences\n----------\n\n#. http://openid.net/developers/\n#. http://developer.yahoo.com/openid/\n#. http://code.google.com/apis/accounts/docs/OpenID.html\n#. http://apiwiki.twitter.com/OAuth-FAQ\n#. http://developers.facebook.com/connect.php\n#. http://develop.github.com/p/oauth.html\n#. https://developer.foursquare.com/overview/auth.html\n\nLimitations\n------------\n\nAs with all APIs, we are limited by the amount of data which the API provider\nprovides us. For example, both Yahoo and Google provide extremely limited data\nabout the autheticated subscriber. Twitter and Facebook provide a lot of details,\nbut not the email. Different Openid providers are free to provide [different\namounts of data](http://openid.net/specs/openid-simple-registration-extension-1_0.html).\n\nHow it works.\n--------------\n\n#. For all providers(except Facebook) there are two urls and views. (start and done)\n#. Start sets up the required tokens, and redirects and hands off to the correct\n   provider.\n#. Provider handles authentication on their ends, and hands off to Us, providing\n   authorization tokens.\n#. In done, we check if the user with these details already exists, if yes, we\n   log them in. Otherwise we create a new user, and log them in.\n\nFor all of these, we use standard django authenication system, with custom\nauth_backends, hence all existing views, and decorators as login_required\nwill work as expected.\n\nUrls\n-----\n\n* /login/ Login page. Has all the login options\n* /openid_login/ AND /openid_login/done/\n* /yahoo_login/ AND /yahoo_login/done/\n* /gmail_login/ AND /gmail_login/done/\n* /twitter_login/ AND /twitter_login/done/\n* /facebook_login/done/ We dont have a start url here, as the starting tokens are\n  set in a popup.\n* /github_login/ AND /github_login/done/\n* /foursquare_login/ AND /foursquare_login/done/\n\nImplementation\n---------------\n\n#. Install required libraries.\n#. Get tokens and populate in localsettings.py\n#. Set the token callback urls correctly at Twitter, Facebook, Github and Foursquare.\n#. Set the authentication_backends to the providers you are using.\n"
  },
  {
    "path": "example_project/LICENSE",
    "content": "This work is dual licensed under\n\n(new)\n\nCopyright (c) 2009, Shabda Raaj and Contributors\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n    * Redistributions of source code must retain the above copyright\n      notice, this list of conditions and the following disclaimer.\n    * Redistributions in binary form must reproduce the above copyright\n      notice, this list of conditions and the following disclaimer in the\n      documentation and/or other materials provided with the distribution.\n    * Neither the name of the <organization> nor the\n      names of its contributors may be used to endorse or promote products\n      derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY <copyright holder> ''AS IS'' AND ANY\nEXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n(To keep the older one around if in some remote chance you prefer this.)\n\nCopyright (c) 2009 by Shabda Raaj and Contributors\n* Usware Technologies\n* www.uswaretech.com\n\"Building Amazing Webapps\"\n\nAll Rights Reserved\nModified ATTRIBUTION ASSURANCE LICENSE (adapted from the original BSD license)\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the conditions below are met.\nThese conditions require a modest attribution to Author (the\n\"Shabda Raaj\"), who hopes that its promotional value may help justify the\nthousands of dollars in otherwise billable time invested in writing\nthis and other freely available, open-source software.\n\n1. Redistributions of source code, in whole or part and with or without\nmodification (the \"Code\"), must display this GPG-signed\ntext in verifiable form.\n2. Redistributions of the Code in binary form must be accompanied by\nthis GPG-signed text in any documentation and, each time the resulting\nexecutable program or a program dependent thereon is launched, a\nmodest display (e.g., splash screen or banner text) of the Shabda Raaj's\nattribution information, which includes:\n(a) Name (\"Shabda Raaj\"),\n(b) Identification (\"Usware Technologies\"), and\n(c) URL (\"http://uswaretech.com\").\n3. Neither the name nor any trademark of the Shabda Raaj may be used to\nendorse or promote products derived from this software without specific\nprior written permission.\n4. Users are entirely responsible, to the exclusion of the Shabda Raaj and\nany other persons, for compliance with (1) regulations set by owners or\nadministrators of employed equipment, (2) licensing terms of any other\nsoftware, and (3) local regulations regarding use, including those\nregarding import, export, and use of encryption software.\n\nTHIS FREE SOFTWARE IS PROVIDED BY THE AUTHOR \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\nLIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO\nEVENT SHALL THE AUTHOR OR ANY CONTRIBUTOR BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\nCONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nEFFECTS OF UNAUTHORIZED OR MALICIOUS NETWORK ACCESS;\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED\nAND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT\nLIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN\nIF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nThis work builds upon the work of many others. No ownership of their\nwork is claimed or implied. They retain the ownership of their work,\nincluded here for convenience.  On being bought to my notice, mentions\nwould be gratefully provided.\n"
  },
  {
    "path": "example_project/__init__.py",
    "content": ""
  },
  {
    "path": "example_project/commentor/__init__.py",
    "content": ""
  },
  {
    "path": "example_project/commentor/models.py",
    "content": "from django.db import models\n\nclass Comment(models.Model):\n    comment = models.TextField()\n"
  },
  {
    "path": "example_project/commentor/templates/commentor/index.html",
    "content": "{% extends 'base.html' %}\n\n{% block main_content %}\n\nEnter Comment\n\n{% if user.is_authenticated %}\n\n<p>You are currently logged in as <strong>{{ user.username }}</strong></p>\n\n<form action=\".\"  method=\"post\">\n    {{ form }}\n    <input type=\"submit\" name=\"comment_submit\" value=\"Comment\" />\n</form>\n<a href=\"{% url socialauth_social_logout %}\">Logout</a>\n{% else %}\n\n<a href=\"{% url socialauth_login_page %}\">Login</a>\n\n{% endif %}\n\n\n{% for comment in comments %}\n\n<p>\n    {{ comment.comment }}\n</p>\n\n{% endfor %}\n\n{% endblock %}"
  },
  {
    "path": "example_project/commentor/tests.py",
    "content": "\"\"\"\nThis file demonstrates two different styles of tests (one doctest and one\nunittest). These will both pass when you run \"manage.py test\".\n\nReplace these with more appropriate tests for your application.\n\"\"\"\n\nfrom django.test import TestCase\n\nclass SimpleTest(TestCase):\n    def test_basic_addition(self):\n        \"\"\"\n        Tests that 1 + 1 always equals 2.\n        \"\"\"\n        self.failUnlessEqual(1 + 1, 2)\n\n__test__ = {\"doctest\": \"\"\"\nAnother way to test that 1 + 1 is equal to 2.\n\n>>> 1 + 1 == 2\nTrue\n\"\"\"}\n\n"
  },
  {
    "path": "example_project/commentor/urls.py",
    "content": ""
  },
  {
    "path": "example_project/commentor/views.py",
    "content": "from django.contrib.auth.decorators import login_required\nfrom django.http import HttpResponseRedirect\nfrom commentor.models import Comment\nfrom django.template import RequestContext\nfrom django import forms\nfrom django.shortcuts import render_to_response\n\n@login_required\ndef leave_comment(request):\n    form = CommentForm()\n    if request.POST:\n        form = CommentForm(data = request.POST)\n        if form.is_valid():\n            form.save()\n            return HttpResponseRedirect('.')\n        \n    payload = {'form':form, 'comments':Comment.objects.all()}\n    return render_to_response('commentor/index.html', payload, RequestContext(request))\n    \nclass CommentForm(forms.ModelForm):\n    class Meta:\n        model = Comment"
  },
  {
    "path": "example_project/example/README",
    "content": "This is an example app using socialauth as authentication backend\nWe use modified django comments app to allow users to login via socialauth and post comments\n\nTo use this app in your project:\n\n1. Copy example and example_comments dirs to your project dir\n2. Add     \n     'example',\n     'example_comments',\n   to your INSTALLED_APPS\n3. Add \n    (r'^comments/post/', 'example_comments.views.post_comment'),\n    (r'comments/', include('django.contrib.comments.urls')),\n   to your urlpatterns\n4. Add\n     COMMENTS_APP = 'example_comments'\n   to your settings\n"
  },
  {
    "path": "example_project/example/__init__.py",
    "content": ""
  },
  {
    "path": "example_project/example/admin.py",
    "content": "from models import Post\nfrom django.contrib import admin\n\nadmin.site.register(Post)\n\n"
  },
  {
    "path": "example_project/example/models.py",
    "content": "from django.db import models\nfrom django.contrib.auth.models import User\n# Create your models here.\n\nclass Post(models.Model):\n    author = models.ForeignKey(User)\n    date = models.DateTimeField()\n    title = models.CharField(max_length=100)\n    post = models.TextField()\n\n    def __unicode__(self):\n        return  self.title\n"
  },
  {
    "path": "example_project/example/templates/comments/example/form.html",
    "content": "{% load comments i18n %}\n\n<form action=\"{% comment_form_target %}\" method=\"post\">{% csrf_token %}\n  {% if next %}<input type=\"hidden\" name=\"next\" value=\"{{ next }}\" />{% endif %}\n  {% for field in form %}\n    {% if field.is_hidden %}\n      {{ field }}\n    {% else %}\n      {% if field.errors %}{{ field.errors }}{% endif %}\n      <p\n        {% if field.errors %} class=\"error\"{% endif %}\n        {% ifequal field.name \"honeypot\" %} style=\"display:none;\"{% endifequal %}>\n        {{ field.label_tag }} {{ field }}\n      </p>\n    {% endif %}\n  {% endfor %}\n    <input type=\"hidden\" name=\"next\" id=\"next\" value=\"{{request.path}}\">\n  <p class=\"submit\">\n    <input type=\"submit\" name=\"post\" class=\"submit-post\" value=\"{% trans \"Post\" %}\" />\n    <input type=\"submit\" name=\"preview\" class=\"submit-preview\" value=\"{% trans \"Preview\" %}\" />\n  </p>\n</form>\n"
  },
  {
    "path": "example_project/example/templates/comments/example/list.html",
    "content": "<dl id=\"comments\">\n  {% for comment in comment_list %}\n    <dd>\n        <p>{{ comment.comment }}</p>\n    </dd>\n    <dt id=\"c{{ comment.id }}\">\n        on {{ comment.submit_date|date }} at {{ comment.submit_date|time }} by {{ comment.name }}\n    </dt>    \n  {% endfor %}\n</dl>\n"
  },
  {
    "path": "example_project/example/templates/example/post_detail.html",
    "content": "{% load comments socialauth_tags %}\n\n<h2> {{ post }}</h2>\n<p>{{ post.post }}</p>\n  <br /> \n    posted by {{ post.author }} on {{ post.date|date }} at {{ post.date|time }}\n  <br />\n  <br />\n  Comments:\n  <br />\n    {% render_comment_list for post %}\n  <br />\n    {% if request.user.username %}\n        Comment as {% get_calculated_username request.user %} \n        (<a href=\"{% url socialauth_social_logout %}?next={{ request.path }}\">Not {% get_calculated_username request.user %}?</a>)\n        {% render_comment_form for post %}\n    {% else %}\n        <a href='{% url socialauth_login_page %}?next={{ request.path }}'>Login to comment</a>\n    {% endif %}\n"
  },
  {
    "path": "example_project/example/templates/example/post_list.html",
    "content": "{% load comments %}\n{{ latest }}\n{% if object_list %}\n    {% for post in object_list %}\n      <h2>{{ post }}</h2>\n      <p>{{ post.post }}</p>\n      {% get_comment_count for post as comment_count %}\n      <b>{{ post.author }}</b> wrote {{ post.post|wordcount }} words on {{ post.date|date }} at {{ post.date|time }}\n      <br />\n      <a href='{{ post.id }}'>\n          {{ comment_count }} comments\n      </a>\n    {% endfor %}\n{% else %}\n    <a href=\"/admin/example/post/add/\">Add a new blog post</a>\n{% endif %}\n"
  },
  {
    "path": "example_project/example/tests.py",
    "content": "\"\"\"\nThis file demonstrates two different styles of tests (one doctest and one\nunittest). These will both pass when you run \"manage.py test\".\n\nReplace these with more appropriate tests for your application.\n\"\"\"\n\nfrom django.test import TestCase\n\nclass SimpleTest(TestCase):\n    def test_basic_addition(self):\n        \"\"\"\n        Tests that 1 + 1 always equals 2.\n        \"\"\"\n        self.failUnlessEqual(1 + 1, 2)\n\n__test__ = {\"doctest\": \"\"\"\nAnother way to test that 1 + 1 is equal to 2.\n\n>>> 1 + 1 == 2\nTrue\n\"\"\"}\n\n"
  },
  {
    "path": "example_project/example/urls.py",
    "content": "from django.conf.urls.defaults import *\nfrom models import Post\n\nurlpatterns = patterns('',\n    url(r'^(?P<post_id>\\d+)$', 'example.views.post_detail'),\n    url(r'^$', 'django.views.generic.list_detail.object_list',\n        { 'queryset' : Post.objects.all() }\n    ),\n)\n"
  },
  {
    "path": "example_project/example/views.py",
    "content": "# Create your views here.\nfrom django.shortcuts import render_to_response, get_object_or_404\nfrom django.http import HttpResponseRedirect\nfrom django.contrib.comments.models import Comment\nfrom models import Post\nfrom django.template import RequestContext\n\ndef comment_posted(request):\n    comment_id = request.GET['c']\n    post_id = Comment.objects.get(id=comment_id).content_object.id\n    return HttpResponseRedirect('/blog/'+str(post_id))\n\ndef post_detail(request, post_id):\n    post = get_object_or_404(Post, pk=post_id)\n    return render_to_response('example/post_detail.html', {'post': post}, context_instance=RequestContext(request))\n"
  },
  {
    "path": "example_project/example_comments/__init__.py",
    "content": "from django import forms\nfrom django.utils.translation import ugettext_lazy as _\nfrom django.contrib.comments.forms import CommentDetailsForm\n\nclass CommentForm(CommentDetailsForm):\n    name          = forms.CharField(widget=forms.HiddenInput, required=False)\n    email         = forms.EmailField(widget=forms.HiddenInput, required=False)\n    url           = forms.URLField(widget=forms.HiddenInput, required=False)\n\n\ndef get_form():\n    return CommentForm\n"
  },
  {
    "path": "example_project/example_comments/models.py",
    "content": "from django.db import models\n\n# Create your models here.\n"
  },
  {
    "path": "example_project/example_comments/tests.py",
    "content": "\"\"\"\nThis file demonstrates two different styles of tests (one doctest and one\nunittest). These will both pass when you run \"manage.py test\".\n\nReplace these with more appropriate tests for your application.\n\"\"\"\n\nfrom django.test import TestCase\n\nclass SimpleTest(TestCase):\n    def test_basic_addition(self):\n        \"\"\"\n        Tests that 1 + 1 always equals 2.\n        \"\"\"\n        self.failUnlessEqual(1 + 1, 2)\n\n__test__ = {\"doctest\": \"\"\"\nAnother way to test that 1 + 1 is equal to 2.\n\n>>> 1 + 1 == 2\nTrue\n\"\"\"}\n\n"
  },
  {
    "path": "example_project/example_comments/views.py",
    "content": "# Create your views here.\n\nfrom django.contrib.auth.decorators import login_required\nfrom django.contrib.comments.views.comments import post_comment as old_post_comment\n\n@login_required\ndef post_comment(request):\n        return old_post_comment(request)\n"
  },
  {
    "path": "example_project/localsettings.example.py",
    "content": "OPENID_REDIRECT_NEXT = '/accounts/openid/done/'\n\nOPENID_SREG = {\"requred\": \"nickname, email, fullname\",\n               \"optional\":\"postcode, country\",\n               \"policy_url\": \"\"}\n\n#example should be something more like the real thing, i think\nOPENID_AX = [{\"type_uri\": \"http://axschema.org/contact/email\",\n              \"count\": 1,\n              \"required\": True,\n              \"alias\": \"email\"},\n             {\"type_uri\": \"http://axschema.org/schema/fullname\",\n              \"count\":1 ,\n              \"required\": False,\n              \"alias\": \"fname\"}]\n\nOPENID_AX_PROVIDER_MAP = {'Google': {'email': 'http://axschema.org/contact/email',\n                                     'firstname': 'http://axschema.org/namePerson/first',\n                                     'lastname': 'http://axschema.org/namePerson/last'},\n                          'Default': {'email': 'http://axschema.org/contact/email',\n                                      'fullname': 'http://axschema.org/namePerson',\n                                      'nickname': 'http://axschema.org/namePerson/friendly'}\n                          }\n\nTWITTER_CONSUMER_KEY = ''\nTWITTER_CONSUMER_SECRET = ''\n\nFACEBOOK_APP_ID = ''\nFACEBOOK_API_KEY = ''\nFACEBOOK_SECRET_KEY = ''\n\nLINKEDIN_CONSUMER_KEY = ''\nLINKEDIN_CONSUMER_SECRET = ''\n\nGITHUB_CLIENT_ID = ''\nGITHUB_CLIENT_SECRET = ''\n\nFOURSQUARE_CONSUMER_KEY = ''\nFOURSQUARE_CONSUMER_SECRET = ''\nFOURSQUARE_REGISTERED_REDIRECT_URI = ''\n\n## if any of this information is desired for your app\nFACEBOOK_EXTENDED_PERMISSIONS = (\n    #'publish_stream',\n    #'create_event',\n    #'rsvp_event',\n    #'sms',\n    #'offline_access',\n    #'email',\n    #'read_stream',\n    #'user_about_me',\n    #'user_activites',\n    #'user_birthday',\n    #'user_education_history',\n    #'user_events',\n    #'user_groups',\n    #'user_hometown',\n    #'user_interests',\n    #'user_likes',\n    #'user_location',\n    #'user_notes',\n    #'user_online_presence',\n    #'user_photo_video_tags',\n    #'user_photos',\n    #'user_relationships',\n    #'user_religion_politics',\n    #'user_status',\n    #'user_videos',\n    #'user_website',\n    #'user_work_history',\n    #'read_friendlists',\n    #'read_requests',\n    #'friend_about_me',\n    #'friend_activites',\n    #'friend_birthday',\n    #'friend_education_history',\n    #'friend_events',\n    #'friend_groups',\n    #'friend_hometown',\n    #'friend_interests',\n    #'friend_likes',\n    #'friend_location',\n    #'friend_notes',\n    #'friend_online_presence',\n    #'friend_photo_video_tags',\n    #'friend_photos',\n    #'friend_relationships',\n    #'friend_religion_politics',\n    #'friend_status',\n    #'friend_videos',\n    #'friend_website',\n    #'friend_work_history',\n)\n\n\nAUTHENTICATION_BACKENDS = (\n    'django.contrib.auth.backends.ModelBackend',\n    'socialauth.auth_backends.OpenIdBackend',\n    'socialauth.auth_backends.TwitterBackend',\n    'socialauth.auth_backends.FacebookBackend',\n    'socialauth.auth_backends.LinkedInBackend',\n    'socialauth.auth_backends.GithubBackend',\n    'socialauth.auth_backends.FoursquareBackend',\n)\n"
  },
  {
    "path": "example_project/manage.py",
    "content": "#!/usr/bin/env python\nfrom django.core.management import execute_manager\ntry:\n    import settings # Assumed to be in the same directory.\nexcept ImportError:\n    import sys\n    sys.stderr.write(\"Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\\nYou'll have to run django-admin.py, passing it your settings module.\\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\\n\" % __file__)\n    sys.exit(1)\n\nif __name__ == \"__main__\":\n    execute_manager(settings)\n"
  },
  {
    "path": "example_project/media/css/openid.css",
    "content": "#openid_form {\n\twidth: 400px;\t\n}\n#openid_form legend {\n\tfont-weight: bold;\n}\n#openid_choice {\n\tdisplay: none;\n}\n#openid_input_area {\n\tclear: both;\n\tpadding: 10px;\n}\n#openid_btns, #openid_btns br {\n\tclear: both;\n}\n#openid_highlight {\n\tpadding: 3px;\n\tbackground-color: #FFFCC9;\n\tfloat: left;\n}\n.openid_large_btn {\n\twidth: 100px;\n\theight: 60px;\n\tborder: 1px solid #DDD;\n\tmargin: 3px;\n\tfloat: left;\n}\n.openid_small_btn {\n\twidth: 24px;\n\theight: 24px;\n\tborder: 1px solid #DDD;\n\tmargin: 3px;\n\tfloat: left;\n}\t\na.openid_large_btn:focus {\n\toutline: none;\n}\na.openid_large_btn:focus{\n-moz-outline-style: none;\n}\n.openid_selected {\n\tborder: 4px solid #DDD;\n}\t"
  },
  {
    "path": "example_project/media/css/socialauth.css",
    "content": "body {\n    margin-left: auto;\n    margin-right: auto;\n    width: 950px;\n}\n#openid_choice{\n\tmargin-top:10px;\n\tdisplay: none;\n}\n#openid_input_area{\n\tpadding-top:10px;\n\tclear: both;\n}\n#openid_username{\n\tmargin-right:5px;\n}\n#openid_btns, #openid_btns br{\n\tclear: both;\n}\n#openid_btns #facebook{\n\theight: 60px;\n\twidth: 110px;\n\tfloat: left;\n\tmargin-top: 3px;\n\tdisplay: table-cell;\n    text-align: center;\n    vertical-align: middle;\n\tborder: 1px solid #ccc;\n}\n#openid_highlight{\n\tpadding: 3px;\n\tbackground-color: #FFFCC9;\n\tfloat: left;\n}\n.openid_large_btn{\n\twidth: 100px;\n\theight: 60px;\n\tborder: 1px solid #DDD;\n\tmargin: 3px;\n\tfloat: left;\n}\n.openid_small_btn{\n\twidth: 24px;\n\theight: 24px;\n\tborder: 1px solid #DDD;\n\tmargin: 3px;\n\tfloat: left;\n}\na.openid_large_btn:focus{\n\toutline: none;\n}\na.openid_large_btn:focus{\n\t-moz-outline-style: none;\n}\n.openid_selected{\n\tborder: 4px solid #DDD;\n}\n.linkedin{\n\tbackground: #FFF url(/site_media/images/linkedin.jpg) no-repeat center center;\n}\n.yahoo{\n\tbackground: #FFF url(/site_media/images/yahoo.gif) no-repeat center center;\n}\n.google{\n\tbackground: #FFF url(/site_media/images/google.png) no-repeat center center;\n}\n.openid{\n\tbackground: #FFF url(/site_media/images/openid.png) no-repeat center center;\n}\n.twitter{\n\tbackground: #FFF url(/site_media/images/twitter.png) no-repeat center center;\n}\n\n"
  },
  {
    "path": "example_project/media/js/openid-jquery.js",
    "content": "/*\nSimple OpenID Plugin\nhttp://code.google.com/p/openid-selector/\n\nThis code is licenced under the New BSD License.\n*/\n\nvar providers_large = {\n    google: {\n        name: 'Google',\n        url: 'https://www.google.com/accounts/o8/id'\n    },\n    yahoo: {\n        name: 'Yahoo',      \n        url: 'https://me.yahoo.com/'\n    },    \n    aol: {\n        name: 'AOL',     \n        label: 'Enter your AOL screenname.',\n        url: 'http://openid.aol.com/{username}/'\n    },\n    openid: {\n        name: 'OpenID',     \n        label: 'Enter your OpenID.',\n        url: null\n    }\n};\nvar providers_small = {\n    myopenid: {\n        name: 'MyOpenID',\n        label: 'Enter your MyOpenID username.',\n        url: 'http://{username}.myopenid.com/'\n    },\n    livejournal: {\n        name: 'LiveJournal',\n        label: 'Enter your Livejournal username.',\n        url: 'http://{username}.livejournal.com/'\n    },\n    flickr: {\n        name: 'Flickr',        \n        label: 'Enter your Flickr username.',\n        url: 'http://flickr.com/photos/{username}/'\n    },\n    technorati: {\n        name: 'Technorati',\n        label: 'Enter your Technorati username.',\n        url: 'http://technorati.com/people/technorati/{username}/'\n    },\n    wordpress: {\n        name: 'Wordpress',\n        label: 'Enter your Wordpress.com username.',\n        url: 'http://{username}.wordpress.com/'\n    },\n    blogger: {\n        name: 'Blogger',\n        label: 'Your Blogger account',\n        url: 'http://{username}.blogspot.com/'\n    },\n    verisign: {\n        name: 'Verisign',\n        label: 'Your Verisign username',\n        url: 'http://{username}.pip.verisignlabs.com/'\n    },\n    vidoop: {\n        name: 'Vidoop',\n        label: 'Your Vidoop username',\n        url: 'http://{username}.myvidoop.com/'\n    },\n    verisign: {\n        name: 'Verisign',\n        label: 'Your Verisign username',\n        url: 'http://{username}.pip.verisignlabs.com/'\n    },\n    claimid: {\n        name: 'ClaimID',\n        label: 'Your ClaimID username',\n        url: 'http://claimid.com/{username}'\n    }\n};\nvar providers = $.extend({}, providers_large, providers_small);\n\nvar openid = {\n\n\tcookie_expires: 6*30,\t// 6 months.\n\tcookie_name: 'openid_provider',\n\tcookie_path: '/',\n\t\n\timg_path: '/site_media/images/',\n\t\n\tinput_id: null,\n\tprovider_url: null,\n\t\n    init: function(input_id) {\n        \n        var openid_btns = $('#openid_btns');\n        \n        this.input_id = input_id;\n        \n        $('#openid_choice').show();\n        $('#openid_input_area').empty();\n        // add box for each provider\n        for (id in providers_large) {\n        \n           \topenid_btns.append(this.getBoxHTML(providers_large[id], 'large', '.gif'));\n        }\n        if (providers_small) {\n        \topenid_btns.append('<br/>');\n        \t\n\t        for (id in providers_small) {\n\t        \n\t           \topenid_btns.append(this.getBoxHTML(providers_small[id], 'small', '.ico'));\n\t        }\n        }\n        \n        $('#openid_form').submit(this.submit);\n        \n        var box_id = this.readCookie();\n        if (box_id) {\n        \tthis.signin(box_id, true);\n        }  \n    },\n    getBoxHTML: function(provider, box_size, image_ext) {\n            \n        var box_id = provider[\"name\"].toLowerCase();\n        return '<a title=\"'+provider[\"name\"]+'\" href=\"javascript: openid.signin(\\''+ box_id +'\\');\"' +\n        \t\t' style=\"background: #FFF url(' + this.img_path + box_id + image_ext+') no-repeat center center\" ' + \n        \t\t'class=\"' + box_id + ' openid_' + box_size + '_btn\"></a>';    \n    \n    },\n    /* Provider image click */\n    signin: function(box_id, onload) {\n    \n    \tvar provider = providers[box_id];\n  \t\tif (! provider) {\n  \t\t\treturn;\n  \t\t}\n\t\t\n\t\tthis.highlight(box_id);\n\t\tthis.setCookie(box_id);\n\t\t\n\t\t// prompt user for input?\n\t\tif (provider['label']) {\n\t\t\t\n\t\t\tthis.useInputBox(provider);\n\t\t\tthis.provider_url = provider['url'];\n\t\t\t\n\t\t} else {\n\t\t\t\n\t\t\tthis.setOpenIdUrl(provider['url']);\n\t\t\tif (! onload) {\n\t\t\t\t$('#openid_form').submit();\n\t\t\t}\t\n\t\t}\n    },\n    /* Sign-in button click */\n    submit: function() {\n        \n    \tvar url = openid.provider_url; \n    \tif (url) {\n    \t\turl = url.replace('{username}', $('#openid_username').val());\n    \t\topenid.setOpenIdUrl(url);\n    \t}\n    \treturn true;\n    },\n    setOpenIdUrl: function (url) {\n    \n    \tvar hidden = $('#'+this.input_id);\n    \tif (hidden.length > 0) {\n    \t\thidden.value = url;\n    \t} else {\n    \t\t$('#openid_form').append('<input type=\"hidden\" id=\"' + this.input_id + '\" name=\"' + this.input_id + '\" value=\"'+url+'\"/>');\n    \t}\n    },\n    highlight: function (box_id) {\n    \t\n    \t// remove previous highlight.\n    \tvar highlight = $('#openid_highlight');\n    \tif (highlight) {\n    \t\thighlight.replaceWith($('#openid_highlight a')[0]);\n    \t}\n    \t// add new highlight.\n    \t$('.'+box_id).wrap('<div id=\"openid_highlight\"></div>');\n    },\n    setCookie: function (value) {\n    \n\t\tvar date = new Date();\n\t\tdate.setTime(date.getTime()+(this.cookie_expires*24*60*60*1000));\n\t\tvar expires = \"; expires=\"+date.toGMTString();\n\t\t\n\t\tdocument.cookie = this.cookie_name+\"=\"+value+expires+\"; path=\" + this.cookie_path;\n    },\n    readCookie: function () {\n\t\tvar nameEQ = this.cookie_name + \"=\";\n\t\tvar ca = document.cookie.split(';');\n\t\tfor(var i=0;i < ca.length;i++) {\n\t\t\tvar c = ca[i];\n\t\t\twhile (c.charAt(0)==' ') c = c.substring(1,c.length);\n\t\t\tif (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);\n\t\t}\n\t\treturn null;\n    },\n    useInputBox: function (provider) {\n   \t\n\t\tvar input_area = $('#openid_input_area');\n\t\t\n\t\tvar html = '';\n\t\tvar id = 'openid_username';\n\t\tvar value = '';\n\t\tvar label = provider['label'];\n\t\tvar style = '';\n\t\t\n\t\tif (label) {\n\t\t\thtml = '<p>' + label + '</p>';\n\t\t}\n\t\tif (provider['name'] == 'OpenID') {\n\t\t\tid = this.input_id;\n\t\t\tvalue = 'http://';\n\t\t\tstyle = 'background:#FFF url('+this.img_path+'openid-inputicon.gif) no-repeat scroll 0 50%; padding-left:18px;';\n\t\t}\n\t\thtml += '<input id=\"'+id+'\" type=\"text\" style=\"'+style+'\" name=\"'+id+'\" value=\"'+value+'\" />' + \n\t\t\t\t\t'<input id=\"openid_submit\" type=\"submit\" value=\"Sign-In\"/>';\n\t\t\n\t\tinput_area.empty();\n\t\tinput_area.append(html);\n\n\t\t$('#'+id).focus();\n    }\n};\n"
  },
  {
    "path": "example_project/settings.py",
    "content": "# Django settings for socialauthdemo project.\n\nDEBUG = True\nTEMPLATE_DEBUG = DEBUG\n\nADMINS = (\n    # ('Your Name', 'your_email@domain.com'),\n)\n\nMANAGERS = ADMINS\n\nDATABASE_ENGINE = 'sqlite3'           # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.\nDATABASE_NAME = 'data.db'              # Or path to database file if using sqlite3.\nDATABASE_USER = ''             # Not used with sqlite3.\nDATABASE_PASSWORD = ''         # Not used with sqlite3.\nDATABASE_HOST = ''             # Set to empty string for localhost. Not used with sqlite3.\nDATABASE_PORT = ''             # Set to empty string for default. Not used with sqlite3.\n\n# Local time zone for this installation. Choices can be found here:\n# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name\n# although not all choices may be available on all operating systems.\n# If running in a Windows environment this must be set to the same as your\n# system time zone.\nTIME_ZONE = 'America/Chicago'\n\n# Language code for this installation. All choices can be found here:\n# http://www.i18nguy.com/unicode/language-identifiers.html\nLANGUAGE_CODE = 'en-us'\n\nSITE_ID = 1\n\n# If you set this to False, Django will make some optimizations so as not\n# to load the internationalization machinery.\nUSE_I18N = True\n\n# Absolute path to the directory that holds media.\n# Example: \"/home/media/media.lawrence.com/\"\nMEDIA_ROOT = ''\n\n# URL that handles the media served from MEDIA_ROOT. Make sure to use a\n# trailing slash if there is a path component (optional in other cases).\n# Examples: \"http://media.lawrence.com\", \"http://example.com/media/\"\nMEDIA_URL = ''\n\n# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a\n# trailing slash.\n# Examples: \"http://foo.com/media/\", \"/media/\".\nADMIN_MEDIA_PREFIX = '/media/'\n\n# Make this unique, and don't share it with anybody.\nSECRET_KEY = 'tnrm*t2b80nu51mgz3kc2%_v6bv8e)8rup$03m)dp7xb0)m8t9'\n\n# List of callables that know how to import templates from various sources.\nTEMPLATE_LOADERS = (\n    'django.template.loaders.filesystem.load_template_source',\n    'django.template.loaders.app_directories.load_template_source',\n#     'django.template.loaders.eggs.load_template_source',\n)\n\nMIDDLEWARE_CLASSES = (\n    'django.middleware.common.CommonMiddleware',\n    'django.contrib.sessions.middleware.SessionMiddleware',\n    'django.contrib.auth.middleware.AuthenticationMiddleware',\n    'openid_consumer.middleware.OpenIDMiddleware',\n    'django.middleware.csrf.CsrfViewMiddleware',\n    #'socialauth.middleware.FacebookConnectMiddleware'\n)\n\nTEMPLATE_CONTEXT_PROCESSORS = (\n    \"socialauth.context_processors.facebook_api_key\",\n    'django.core.context_processors.media',\n    \"django.contrib.auth.context_processors.auth\",\n    \"django.core.context_processors.request\",\n)\n\nROOT_URLCONF = 'urls'\n\nTEMPLATE_DIRS = (\n    # Put strings here, like \"/home/html/django_templates\" or \"C:/www/django/templates\".\n    # Always use forward slashes, even on Windows.\n    # Don't forget to use absolute paths, not relative paths.\n)\n\nINSTALLED_APPS = (\n    'django.contrib.auth',\n    'django.contrib.contenttypes',\n    'django.contrib.sessions',\n    'django.contrib.sites',\n    'django.contrib.admin',\n    'django.contrib.comments',\n    'socialauth',\n    'openid_consumer',\n    'commentor',\n    'example',\n    'example_comments',\n)\n\nCOMMENTS_APP = 'example_comments'\n\nLOGIN_REDIRECT_URL = '/'\n\nLOGOUT_REDIRECT_URL = '/'\n\ntry:\n    from localsettings import *\nexcept ImportError:\n    pass\n\nimport os\nMEDIA_ROOT = os.path.normpath(os.path.join(os.path.dirname(os.path.abspath(__file__)), 'media'))\nMEDIA_URL = '/site_media/'\n\nSITE_NAME = 'foobar'\n"
  },
  {
    "path": "example_project/urls.py",
    "content": "from django.conf.urls.defaults import *\nfrom commentor.views import leave_comment\n\nfrom django.contrib import admin\nadmin.autodiscover()\n\nurlpatterns = patterns('',\n    (r'^blog/', include('example.urls')),\n    (r'^accounts/', include('socialauth.urls')),\n    (r'^admin/', admin.site.urls), \n    #(r'^$', leave_comment), \n    (r'^$', 'socialauth.views.signin_complete'),\n    (r'^comments/post/', 'example_comments.views.post_comment'),\n    (r'comments/', include('django.contrib.comments.urls')),\n)\n\nfrom django.conf import settings\nif settings.DEBUG:\n    \n    urlpatterns += patterns('',\n        # This is for the CSS and static files:\n        (r'^site_media/(?P<path>.*)$', 'django.views.static.serve',\n         {'document_root': settings.MEDIA_ROOT}),\n    )\n    \n"
  },
  {
    "path": "ez_setup.py",
    "content": "#!python\n\"\"\"Bootstrap setuptools installation\n\nIf you want to use setuptools in your package's setup.py, just include this\nfile in the same directory with it, and add this to the top of your setup.py::\n\n    from ez_setup import use_setuptools\n    use_setuptools()\n\nIf you want to require a specific version of setuptools, set a download\nmirror, or use an alternate download directory, you can do so by supplying\nthe appropriate options to ``use_setuptools()``.\n\nThis file can also be run as a script to install or upgrade setuptools.\n\"\"\"\nimport sys\nDEFAULT_VERSION = \"0.6c9\"\nDEFAULT_URL     = \"http://pypi.python.org/packages/%s/s/setuptools/\" % sys.version[:3]\n\nmd5_data = {\n    'setuptools-0.6b1-py2.3.egg': '8822caf901250d848b996b7f25c6e6ca',\n    'setuptools-0.6b1-py2.4.egg': 'b79a8a403e4502fbb85ee3f1941735cb',\n    'setuptools-0.6b2-py2.3.egg': '5657759d8a6d8fc44070a9d07272d99b',\n    'setuptools-0.6b2-py2.4.egg': '4996a8d169d2be661fa32a6e52e4f82a',\n    'setuptools-0.6b3-py2.3.egg': 'bb31c0fc7399a63579975cad9f5a0618',\n    'setuptools-0.6b3-py2.4.egg': '38a8c6b3d6ecd22247f179f7da669fac',\n    'setuptools-0.6b4-py2.3.egg': '62045a24ed4e1ebc77fe039aa4e6f7e5',\n    'setuptools-0.6b4-py2.4.egg': '4cb2a185d228dacffb2d17f103b3b1c4',\n    'setuptools-0.6c1-py2.3.egg': 'b3f2b5539d65cb7f74ad79127f1a908c',\n    'setuptools-0.6c1-py2.4.egg': 'b45adeda0667d2d2ffe14009364f2a4b',\n    'setuptools-0.6c2-py2.3.egg': 'f0064bf6aa2b7d0f3ba0b43f20817c27',\n    'setuptools-0.6c2-py2.4.egg': '616192eec35f47e8ea16cd6a122b7277',\n    'setuptools-0.6c3-py2.3.egg': 'f181fa125dfe85a259c9cd6f1d7b78fa',\n    'setuptools-0.6c3-py2.4.egg': 'e0ed74682c998bfb73bf803a50e7b71e',\n    'setuptools-0.6c3-py2.5.egg': 'abef16fdd61955514841c7c6bd98965e',\n    'setuptools-0.6c4-py2.3.egg': 'b0b9131acab32022bfac7f44c5d7971f',\n    'setuptools-0.6c4-py2.4.egg': '2a1f9656d4fbf3c97bf946c0a124e6e2',\n    'setuptools-0.6c4-py2.5.egg': '8f5a052e32cdb9c72bcf4b5526f28afc',\n    'setuptools-0.6c5-py2.3.egg': 'ee9fd80965da04f2f3e6b3576e9d8167',\n    'setuptools-0.6c5-py2.4.egg': 'afe2adf1c01701ee841761f5bcd8aa64',\n    'setuptools-0.6c5-py2.5.egg': 'a8d3f61494ccaa8714dfed37bccd3d5d',\n    'setuptools-0.6c6-py2.3.egg': '35686b78116a668847237b69d549ec20',\n    'setuptools-0.6c6-py2.4.egg': '3c56af57be3225019260a644430065ab',\n    'setuptools-0.6c6-py2.5.egg': 'b2f8a7520709a5b34f80946de5f02f53',\n    'setuptools-0.6c7-py2.3.egg': '209fdf9adc3a615e5115b725658e13e2',\n    'setuptools-0.6c7-py2.4.egg': '5a8f954807d46a0fb67cf1f26c55a82e',\n    'setuptools-0.6c7-py2.5.egg': '45d2ad28f9750e7434111fde831e8372',\n    'setuptools-0.6c8-py2.3.egg': '50759d29b349db8cfd807ba8303f1902',\n    'setuptools-0.6c8-py2.4.egg': 'cba38d74f7d483c06e9daa6070cce6de',\n    'setuptools-0.6c8-py2.5.egg': '1721747ee329dc150590a58b3e1ac95b',\n    'setuptools-0.6c9-py2.3.egg': 'a83c4020414807b496e4cfbe08507c03',\n    'setuptools-0.6c9-py2.4.egg': '260a2be2e5388d66bdaee06abec6342a',\n    'setuptools-0.6c9-py2.5.egg': 'fe67c3e5a17b12c0e7c541b7ea43a8e6',\n    'setuptools-0.6c9-py2.6.egg': 'ca37b1ff16fa2ede6e19383e7b59245a',\n}\n\nimport sys, os\ntry: from hashlib import md5\nexcept ImportError: from md5 import md5\n\ndef _validate_md5(egg_name, data):\n    if egg_name in md5_data:\n        digest = md5(data).hexdigest()\n        if digest != md5_data[egg_name]:\n            print >>sys.stderr, (\n                \"md5 validation of %s failed!  (Possible download problem?)\"\n                % egg_name\n            )\n            sys.exit(2)\n    return data\n\ndef use_setuptools(\n    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,\n    download_delay=15\n):\n    \"\"\"Automatically find/download setuptools and make it available on sys.path\n\n    `version` should be a valid setuptools version number that is available\n    as an egg for download under the `download_base` URL (which should end with\n    a '/').  `to_dir` is the directory where setuptools will be downloaded, if\n    it is not already available.  If `download_delay` is specified, it should\n    be the number of seconds that will be paused before initiating a download,\n    should one be required.  If an older version of setuptools is installed,\n    this routine will print a message to ``sys.stderr`` and raise SystemExit in\n    an attempt to abort the calling script.\n    \"\"\"\n    was_imported = 'pkg_resources' in sys.modules or 'setuptools' in sys.modules\n    def do_download():\n        egg = download_setuptools(version, download_base, to_dir, download_delay)\n        sys.path.insert(0, egg)\n        import setuptools; setuptools.bootstrap_install_from = egg\n    try:\n        import pkg_resources\n    except ImportError:\n        return do_download()       \n    try:\n        pkg_resources.require(\"setuptools>=\"+version); return\n    except pkg_resources.VersionConflict, e:\n        if was_imported:\n            print >>sys.stderr, (\n            \"The required version of setuptools (>=%s) is not available, and\\n\"\n            \"can't be installed while this script is running. Please install\\n\"\n            \" a more recent version first, using 'easy_install -U setuptools'.\"\n            \"\\n\\n(Currently using %r)\"\n            ) % (version, e.args[0])\n            sys.exit(2)\n        else:\n            del pkg_resources, sys.modules['pkg_resources']    # reload ok\n            return do_download()\n    except pkg_resources.DistributionNotFound:\n        return do_download()\n\n\n\ndef download_setuptools(\n    version=DEFAULT_VERSION, download_base=DEFAULT_URL, to_dir=os.curdir,\n    delay = 15\n):\n    \"\"\"Download setuptools from a specified location and return its filename\n\n    `version` should be a valid setuptools version number that is available\n    as an egg for download under the `download_base` URL (which should end\n    with a '/'). `to_dir` is the directory where the egg will be downloaded.\n    `delay` is the number of seconds to pause before an actual download attempt.\n    \"\"\"\n    import urllib2, shutil\n    egg_name = \"setuptools-%s-py%s.egg\" % (version,sys.version[:3])\n    url = download_base + egg_name\n    saveto = os.path.join(to_dir, egg_name)\n    src = dst = None\n    if not os.path.exists(saveto):  # Avoid repeated downloads\n        try:\n            from distutils import log\n            if delay:\n                log.warn(\"\"\"\n---------------------------------------------------------------------------\nThis script requires setuptools version %s to run (even to display\nhelp).  I will attempt to download it for you (from\n%s), but\nyou may need to enable firewall access for this script first.\nI will start the download in %d seconds.\n\n(Note: if this machine does not have network access, please obtain the file\n\n   %s\n\nand place it in this directory before rerunning this script.)\n---------------------------------------------------------------------------\"\"\",\n                    version, download_base, delay, url\n                ); from time import sleep; sleep(delay)\n            log.warn(\"Downloading %s\", url)\n            src = urllib2.urlopen(url)\n            # Read/write all in one block, so we don't create a corrupt file\n            # if the download is interrupted.\n            data = _validate_md5(egg_name, src.read())\n            dst = open(saveto,\"wb\"); dst.write(data)\n        finally:\n            if src: src.close()\n            if dst: dst.close()\n    return os.path.realpath(saveto)\n\n\ndef main(argv, version=DEFAULT_VERSION):\n    \"\"\"Install or upgrade setuptools and EasyInstall\"\"\"\n    try:\n        import setuptools\n    except ImportError:\n        egg = None\n        try:\n            egg = download_setuptools(version, delay=0)\n            sys.path.insert(0,egg)\n            from setuptools.command.easy_install import main\n            return main(list(argv)+[egg])   # we're done here\n        finally:\n            if egg and os.path.exists(egg):\n                os.unlink(egg)\n    else:\n        if setuptools.__version__ == '0.0.1':\n            print >>sys.stderr, (\n            \"You have an obsolete version of setuptools installed.  Please\\n\"\n            \"remove it from your system entirely before rerunning this script.\"\n            )\n            sys.exit(2)\n\n    req = \"setuptools>=\"+version\n    import pkg_resources\n    try:\n        pkg_resources.require(req)\n    except pkg_resources.VersionConflict:\n        try:\n            from setuptools.command.easy_install import main\n        except ImportError:\n            from easy_install import main\n        main(list(argv)+[download_setuptools(delay=0)])\n        sys.exit(0) # try to force an exit\n    else:\n        if argv:\n            from setuptools.command.easy_install import main\n            main(argv)\n        else:\n            print \"Setuptools version\",version,\"or greater has been installed.\"\n            print '(Run \"ez_setup.py -U setuptools\" to reinstall or upgrade.)'\n\n\n\ndef update_md5(filenames):\n    \"\"\"Update our built-in md5 registry\"\"\"\n\n    import re\n\n    for name in filenames:\n        base = os.path.basename(name)\n        f = open(name,'rb')\n        md5_data[base] = md5(f.read()).hexdigest()\n        f.close()\n\n    data = [\"    %r: %r,\\n\" % it for it in md5_data.items()]\n    data.sort()\n    repl = \"\".join(data)\n\n    import inspect\n    srcfile = inspect.getsourcefile(sys.modules[__name__])\n    f = open(srcfile, 'rb'); src = f.read(); f.close()\n\n    match = re.search(\"\\nmd5_data = {\\n([^}]+)}\", src)\n    if not match:\n        print >>sys.stderr, \"Internal error!\"\n        sys.exit(2)\n\n    src = src[:match.start(1)] + repl + src[match.end(1):]\n    f = open(srcfile,'w')\n    f.write(src)\n    f.close()\n\n\nif __name__=='__main__':\n    if len(sys.argv)>2 and sys.argv[1]=='--md5update':\n        update_md5(sys.argv[2:])\n    else:\n        main(sys.argv[1:])\n\n\n\n\n\n\n"
  },
  {
    "path": "openid_consumer/__init__.py",
    "content": ""
  },
  {
    "path": "openid_consumer/locale/en/LC_MESSAGES/django.po",
    "content": "# English language file for django-openid-consumer package\n# Copyright (C) 2008 Matjaž Črnko\n# This file is distributed under the same license as the django-openid-consumer package.\n# Matjaž Črnko <matjaz.crnko@gmail.com>, 2008.\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version: 0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2008-08-07 13:23+0200\\n\"\n\"PO-Revision-Date: 2008-8-1 21:02+0100\\n\"\n\"Last-Translator: Matjaž Črnko <matjaz.crnko@gmail.com>\\n\"\n\"Language-Team: none\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: views.py:91\nmsgid \"i-names are not supported\"\nmsgstr \"i-names are not supported\"\n\n#: views.py:97\nmsgid \"The OpenID was invalid\"\nmsgstr \"The OpenID was invalid\"\n\n#: views.py:128\nmsgid \"The request was cancelled\"\nmsgstr \"The request was cancelled\"\n\n#: views.py:132\nmsgid \"Setup needed\"\nmsgstr \"Setup needed\"\n\n#~ msgid \"OpenID failed\"\n#~ msgstr \"OpenID failed\"\n\n#~ msgid \"Sign in with your OpenID\"\n#~ msgstr \"Sign in with your OpenID\"\n\n#~ msgid \"Sign in\"\n#~ msgstr \"Sign in\"\n"
  },
  {
    "path": "openid_consumer/locale/sl/LC_MESSAGES/django.po",
    "content": "# Slovenski prevod django-openid-consumer paketa\n# Copyright (C) 2008 Matjaž Črnko\n# This file is distributed under the same license as the django-openid-consumer package.\n# Matjaž Črnko <matjaz.crnko@gmail.com>, 2008.\n#, fuzzy\nmsgid \"\"\nmsgstr \"\"\n\"Project-Id-Version:  0.1\\n\"\n\"Report-Msgid-Bugs-To: \\n\"\n\"POT-Creation-Date: 2008-08-07 13:23+0200\\n\"\n\"PO-Revision-Date: 2008-8-1 21:02+0100\\n\"\n\"Last-Translator: Matjaž Črnko <matjaz.crnko@gmail.com>\\n\"\n\"Language-Team: none\\n\"\n\"MIME-Version: 1.0\\n\"\n\"Content-Type: text/plain; charset=UTF-8\\n\"\n\"Content-Transfer-Encoding: 8bit\\n\"\n\n#: views.py:91\nmsgid \"i-names are not supported\"\nmsgstr \"i-name ni podprt\"\n\n#: views.py:97\nmsgid \"The OpenID was invalid\"\nmsgstr \"OpenID je neveljaven\"\n\n#: views.py:128\nmsgid \"The request was cancelled\"\nmsgstr \"Povezava je bila prekinjena\"\n\n#: views.py:132\nmsgid \"Setup needed\"\nmsgstr \"Postavitev potrebna\"\n\n#~ msgid \"OpenID failed\"\n#~ msgstr \"Napaka pri prijavi z OpenID\"\n\n#~ msgid \"Sign in with your OpenID\"\n#~ msgstr \"Prijavite se z OpenID\"\n\n#~ msgid \"Sign in\"\n#~ msgstr \"Prijava\"\n"
  },
  {
    "path": "openid_consumer/middleware.py",
    "content": "class OpenIDMiddleware(object):\n    \"\"\"\n    Populate request.openid and request.openids with their openid. This comes \n    either from their cookie or from their session, depending on the presence \n    of OPENID_USE_SESSIONS.\n    \"\"\"\n    def process_request(self, request):\n        request.openids = request.session.get('openids', [])\n        if request.openids:\n            request.openid = request.openids[-1] # Last authenticated OpenID\n        else:\n            request.openid = None\n"
  },
  {
    "path": "openid_consumer/models.py",
    "content": "from django.db import models\n\nclass Nonce(models.Model):\n    server_url = models.URLField()\n    timestamp  = models.IntegerField()\n    salt       = models.CharField( max_length=50 )\n\n    def __unicode__(self):\n        return \"Nonce: %s\" % self.nonce\n\nclass Association(models.Model):\n    server_url = models.TextField(max_length=2047)\n    handle = models.CharField(max_length=255)\n    secret = models.TextField(max_length=255) # Stored base64 encoded\n    issued = models.IntegerField()\n    lifetime = models.IntegerField()\n    assoc_type = models.TextField(max_length=64)\n\n    def __unicode__(self):\n        return \"Association: %s, %s\" % (self.server_url, self.handle)\n"
  },
  {
    "path": "openid_consumer/templates/openid_consumer/failure.html",
    "content": "{% extends 'openid_consumer/openid_consumer_base.html' %}\n{% load i18n %}\n\n\n{% block title %}\n\n{{ block.super }} - {% trans \"OpenID failed\" %}\n\n{% endblock %}\n\n{% block main_content %}\n\n<h1>{% trans \"OpenID failed\" %}:</h1>\n\n<p>{{ message|escape }}</p>\n\n<br /><br /><br /><br />\n\n\n{% endblock %}\n\n\n\n{#\n{% load i18n %}\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<head>\n<title>{% trans \"OpenID failed\" %}</title>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n</head>\n\n<body>\n<h1>{% trans \"OpenID failed\" %}:</h1>\n\n<p>{{ message|escape }}</p>\n</body>\n</html>\n#}\n"
  },
  {
    "path": "openid_consumer/templates/openid_consumer/openid_consumer_base.html",
    "content": "{% extends 'socialauth/base.html' %}\n"
  },
  {
    "path": "openid_consumer/templates/openid_consumer/signin.html",
    "content": "{% extends 'openid_consumer/openid_consumer_base.html' %}\n{% load i18n %}\n\n{% block title %}\n\n{{ block.super }} - Sign in with your OpenID\n\n{% endblock %}\n\n{% block main_content %}\n\n<h1>{% trans \"Sign in with your OpenID\" %}</h1>\n\n<form action=\"{{ action }}\" method=\"post\">\n<p><input class=\"openid\" type=\"text\" name=\"openid_url\"> <input type=\"submit\" value=\"{% trans \"Sign in\" %}\"></p>\n</form>\n\n<br /><br /><br /><br />\n\n\n{% endblock %}\n\n\n{#\n<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01//EN\" \"http://www.w3.org/TR/html4/strict.dtd\">\n<head>\n<title>{% trans \"Sign in with your OpenID\" %}</title>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n</head>\n\n<body>\n</body>\n</html>\n#}\n"
  },
  {
    "path": "openid_consumer/util.py",
    "content": "import openid\nif openid.__version__ < '2.1.0':\n    from openid.sreg import SRegResponse\nelse:\n    from openid.extensions.sreg import SRegResponse\n    from openid.extensions.ax import FetchResponse as AXFetchResponse\n    try:\n        from openid.extensions.pape import Response as PapeResponse\n    except ImportError:\n        from openid.extensions import pape as openid_pape\n        PapeResponse = openid_pape.Response\n\nfrom openid.store import nonce as oid_nonce\nfrom openid.store.interface import OpenIDStore\nfrom openid.association import Association as OIDAssociation\nfrom openid.yadis import xri\n\nimport time, base64, hashlib\n\nfrom django.conf import settings\nfrom models import Association, Nonce\n\nclass OpenID:\n    def __init__(self, openid, issued,\n                  attrs=None, sreg=None, pape=None, ax=None):\n        self.openid = openid\n        self.issued = issued\n        self.attrs = attrs or {}\n        self.sreg = sreg or {}\n        self.pape = pape or {}\n        self.ax = ax or {}\n        self.is_iname = (xri.identifierScheme(openid) == 'XRI')\n    \n    def __repr__(self):\n        return '<OpenID: %s>' % self.openid\n    \n    def __str__(self):\n        return self.openid\n\nclass DjangoOpenIDStore(OpenIDStore):\n    def __init__(self):\n        self.max_nonce_age = 6 * 60 * 60 # Six hours\n    \n    def storeAssociation(self, server_url, association):\n        assoc = Association(\n            server_url = server_url,\n            handle = association.handle,\n            secret = base64.encodestring(association.secret),\n            issued = association.issued,\n            lifetime = association.issued,\n            assoc_type = association.assoc_type\n        )\n        assoc.save()\n    \n    def getAssociation(self, server_url, handle=None):\n        assocs = []\n        if handle is not None:\n            assocs = Association.objects.filter(\n                server_url = server_url, handle = handle\n            )\n        else:\n            assocs = Association.objects.filter(\n                server_url = server_url\n            )\n        if not assocs:\n            return None\n        associations = []\n        for assoc in assocs:\n            association = OIDAssociation(\n                assoc.handle, base64.decodestring(assoc.secret), assoc.issued,\n                assoc.lifetime, assoc.assoc_type\n            )\n            if association.getExpiresIn() == 0:\n                self.removeAssociation(server_url, assoc.handle)\n            else:\n                associations.append((association.issued, association))\n        if not associations:\n            return None\n        return associations[-1][1]\n    \n    def removeAssociation(self, server_url, handle):\n        assocs = list(Association.objects.filter(\n            server_url = server_url, handle = handle\n        ))\n        assocs_exist = len(assocs) > 0\n        for assoc in assocs:\n            assoc.delete()\n        return assocs_exist\n    \n    def storeNonce(self, nonce):\n        nonce, created = Nonce.objects.get_or_create(\n            nonce = nonce, defaults={'expires': int(time.time())}\n        )\n    \n    def useNonce(self, server_url, timestamp, salt):\n        if abs(timestamp - time.time()) > oid_nonce.SKEW:\n            return False\n        \n        try:\n            nonce = Nonce(server_url=server_url,\n                          timestamp=timestamp,\n                          salt=salt)\n            nonce.save()\n        except:\n            raise\n        else:\n            return 1\n    \n    def getAuthKey(self):\n        # Use first AUTH_KEY_LEN characters of md5 hash of SECRET_KEY\n        return hashlib.md5(settings.SECRET_KEY).hexdigest()[:self.AUTH_KEY_LEN]\n\ndef from_openid_response(openid_response):\n    issued = int(time.time())\n\n    openid = OpenID(openid_response.identity_url, issued,\n                    openid_response.signed_fields)\n\n    if getattr(settings, 'OPENID_PAPE', False):\n        openid.pape = PapeResponse.fromSuccessResponse(openid_response)\n\n    if getattr(settings, 'OPENID_SREG', False):\n        openid.sreg = SRegResponse.fromSuccessResponse(openid_response)\n\n    if getattr(settings, 'OPENID_AX', False):\n        openid.ax = AXFetchResponse.fromSuccessResponse(openid_response)\n\n    return openid\n"
  },
  {
    "path": "openid_consumer/views.py",
    "content": "from django.http import HttpResponse, HttpResponseRedirect\nfrom django.shortcuts import render_to_response as render\nfrom django.template import RequestContext\nfrom django.conf import settings\nfrom django.utils.translation import ugettext_lazy as _\n\nimport re, time, urllib\n\nimport openid   \nif openid.__version__ < '2.0.0':\n    raise ImportError, 'You need python-openid 2.0.0 or newer'\nelif openid.__version__ < '2.1.0':\n    from openid.sreg import SRegRequest\nelse: \n    from openid.extensions.sreg import SRegRequest\n    try:\n        from openid.extensions.pape import Request as PapeRequest\n    except ImportError:\n        from openid.extensions import pape as openid_pape\n        PapeRequest =  openid_pape.Request\n    from openid.extensions.ax import FetchRequest as AXFetchRequest\n    from openid.extensions.ax import AttrInfo\n\nfrom openid.consumer.consumer import Consumer, \\\n    SUCCESS, CANCEL, FAILURE, SETUP_NEEDED\nfrom openid.consumer.discover import DiscoveryFailure\nfrom openid.yadis import xri\n\nfrom util import OpenID, DjangoOpenIDStore, from_openid_response\nfrom middleware import OpenIDMiddleware\n\nfrom django.utils.html import escape\n\ndef get_url_host(request):\n    if request.is_secure():\n        protocol = 'https'\n    else:\n        protocol = 'http'\n    host = escape(request.get_host())\n    return '%s://%s' % (protocol, host)\n\ndef get_full_url(request):\n    return get_url_host(request) + request.get_full_path()\n\t\t\nnext_url_re = re.compile('^/[-\\w/]+$')\n\ndef is_valid_next_url(next):\n    # When we allow this:\n    #   /openid/?next=/welcome/\n    # For security reasons we want to restrict the next= bit to being a local \n    # path, not a complete URL.\n    return bool(next_url_re.match(next))\n\ndef begin(request, redirect_to=None, on_failure=None, user_url=None,\n          template_name='openid_consumer/signin.html'):\n    on_failure = on_failure or default_on_failure\n    trust_root = getattr(\n        settings, 'OPENID_TRUST_ROOT', get_url_host(request) + '/'\n    )\n    \n    \n    # foo derbis.\n    redirect_to = redirect_to or getattr(\n        settings, 'OPENID_REDIRECT_TO',\n        # If not explicitly set, assume current URL with complete/ appended\n        get_full_url(request).split('?')[0] + 'complete/'\n    )\n    # In case they were lazy...\n    if not (\n            redirect_to.startswith('http://')\n        or\n            redirect_to.startswith('https://')):\n        redirect_to =  get_url_host(request) + redirect_to\n    \n    if request.GET.get('next') and is_valid_next_url(request.GET['next']):\n        if '?' in redirect_to:\n            join = '&'\n        else:\n            join = '?'\n        redirect_to += join + urllib.urlencode({\n            'next': request.GET['next']\n        })\n    if not user_url:\n        user_url = request.REQUEST.get('openid_url', None)\n\n    if not user_url:\n        request_path = request.path\n        if request.GET.get('next'):\n            request_path += '?' + urllib.urlencode({\n                'next': request.GET['next']\n            })\n        \n        return render(template_name, {\n            'action': request_path,\n        }, RequestContext(request))\n    \n    if xri.identifierScheme(user_url) == 'XRI' and getattr(\n        settings, 'OPENID_DISALLOW_INAMES', False\n        ):\n        return on_failure(request, _('i-names are not supported'))\n    \n    consumer = Consumer(request.session, DjangoOpenIDStore())\n\n    try:\n        auth_request = consumer.begin(user_url)\n    except DiscoveryFailure:\n        return on_failure(request, _('The OpenID was invalid'))\n    \n    sreg = getattr(settings, 'OPENID_SREG', False)\n    \n    if sreg:\n        s = SRegRequest()        \n        for sarg in sreg:\n            if sarg.lower().lstrip() == \"policy_url\":\n                s.policy_url = sreg[sarg]\n            else:\n                for v in sreg[sarg].split(','):\n                    s.requestField(field_name=v.lower().lstrip(),\n                                   required=(sarg.lower().lstrip() ==\n                                             \"required\"))\n        auth_request.addExtension(s)\n    \n    pape = getattr(settings, 'OPENID_PAPE', False)\n\n    if pape:\n        if openid.__version__ <= '2.0.0' and openid.__version__ >= '2.1.0':\n            raise (ImportError, \n                   'For pape extension you need python-openid 2.1.0 or newer')\n        p = PapeRequest()\n        for parg in pape:\n            if parg.lower().strip() == 'policy_list':\n                for v in pape[parg].split(','):\n                    p.addPolicyURI(v)\n            elif parg.lower().strip() == 'max_auth_age':\n                p.max_auth_age = pape[parg]\n        auth_request.addExtension(p)\n    \n    OPENID_AX_PROVIDER_MAP = getattr(settings, 'OPENID_AX_PROVIDER_MAP', {})\n    \n    openid_provider = ('Google' if \n                       'google' in request.session.get('openid_provider', '')\n                       else 'Default')\n    ax = OPENID_AX_PROVIDER_MAP.get(openid_provider)\n    \n    if ax:\n        axr = AXFetchRequest()\n        for attr_name, attr_url in ax.items():\n            # axr.add(AttrInfo(i['type_uri'], \n            #    i['count'], i['required'], \n            #    i['alias']))\n            \n            # setting all as required attrs\n            axr.add(AttrInfo(attr_url, required=True))\n        auth_request.addExtension(axr)\n    \n    redirect_url = auth_request.redirectURL(trust_root, redirect_to)\n    \n    return HttpResponseRedirect(redirect_url)\n\ndef complete(request, on_success=None, on_failure=None, \n             failure_template='openid_consumer/failure.html'):\n    \n    on_success = on_success or default_on_success\n    on_failure = on_failure or default_on_failure\n    \n    consumer = Consumer(request.session, DjangoOpenIDStore())\n    #dummydebug\n    #for r in request.GET.items():\n    #    print r\n\n    # JanRain library raises a warning if passed unicode objects as the keys,\n    # so we convert to bytestrings before passing to the library\n    query_dict = dict([\n        (k.encode('utf8'),\n         v.encode('utf8')) for k, v in request.REQUEST.items()\n    ])\n\n    url = get_url_host(request) + request.path\n    openid_response = consumer.complete(query_dict, url)\n    if openid_response.status == SUCCESS:\n        return on_success(request,\n                          openid_response.identity_url,\n                          openid_response)\n    elif openid_response.status == CANCEL:\n        return on_failure(request, \n                          _('The request was cancelled'), failure_template)\n    elif openid_response.status == FAILURE:\n        return on_failure(request, openid_response.message, failure_template)\n    elif openid_response.status == SETUP_NEEDED:\n        return on_failure(request, _('Setup needed'), failure_template)\n    else:\n        assert False, \"Bad openid status: %s\" % openid_response.status\n\ndef default_on_success(request, identity_url, openid_response):\n    if 'openids' not in request.session.keys():\n        request.session['openids'] = []\n    \n    # Eliminate any duplicates\n    request.session['openids'] = [\n        o for o in request.session['openids'] if o.openid != identity_url\n    ]\n    request.session['openids'].append(from_openid_response(openid_response))\n    \n    # Set up request.openids and request.openid, reusing middleware logic\n    OpenIDMiddleware().process_request(request)\n    \n    next = request.GET.get('next', '').strip()\n    if not next or not is_valid_next_url(next):\n        next = getattr(settings, 'OPENID_REDIRECT_NEXT', '/')\n    \n    return HttpResponseRedirect(next)\n\ndef default_on_failure(request, message,\n                       template_name='openid_consumer/failure.html'):\n    return render(template_name, {\n        'message': message\n    }, \t\tRequestContext(request))\n\ndef signout(request):\n    request.session['openids'] = []\n    next = request.GET.get('next', '/')\n    if not is_valid_next_url(next):\n        next = '/'\n    return HttpResponseRedirect(next)\n"
  },
  {
    "path": "requirements.txt",
    "content": "python-openid>=2.0.0\noauth>=1.0.0\nfacebook-sdk\nhg+https://pylinkedin.googlecode.com/hg/pylinkedin>=0.1\n"
  },
  {
    "path": "setup.py",
    "content": "import ez_setup\nez_setup.use_setuptools()\nfrom setuptools import setup, find_packages\n\nsetup(\n    name = \"django-socialauth\",\n    version = \"0.1.2c\",\n    packages = ['socialauth',\n                'socialauth/lib',\n                'socialauth/templatetags',\n                'openid_consumer'],\n    package_data = { 'socialauth': [ 'templates/*.html',\n                                     'templates/socialauth/*.html',\n                                     'templates/socialauth/*.htm',\n                                     'templates/openid/*.html'],\n                     'openid_consumer': ['locale/*/LC_MESSAGES/*.po']\n                     },\n    zip_safe = False,\n    author = \"Agiliq Solutions\",\n    author_email = \"info@uswaretech.com\",\n    description = \"Allows logging via Facebook, Yahoo, Gmail, Twitter and Openid \",\n    url = \"http://agiliq.com/\",\n)\n"
  },
  {
    "path": "socialauth/__init__.py",
    "content": ""
  },
  {
    "path": "socialauth/admin.py",
    "content": "from socialauth.models import AuthMeta, OpenidProfile, TwitterUserProfile, \\\nFacebookUserProfile, LinkedInUserProfile, GithubUserProfile, FoursquareUserProfile\n\nfrom django.contrib import admin\n\nadmin.site.register(AuthMeta)\nadmin.site.register(OpenidProfile)\nadmin.site.register(TwitterUserProfile)\nadmin.site.register(FacebookUserProfile)\nadmin.site.register(LinkedInUserProfile)\nadmin.site.register(GithubUserProfile)\nadmin.site.register(FoursquareUserProfile)\n"
  },
  {
    "path": "socialauth/auth_backends.py",
    "content": "from django.contrib.auth.models import User\nfrom django.contrib.sites.models import Site\nfrom django.core.urlresolvers import reverse\nfrom django.conf import settings\nimport facebook\n\nimport urllib\nfrom socialauth.lib import oauthtwitter2 as oauthtwitter\nfrom socialauth.models import OpenidProfile as UserAssociation, \\\nTwitterUserProfile, FacebookUserProfile, LinkedInUserProfile, AuthMeta, GithubUserProfile, FoursquareUserProfile\nfrom socialauth.lib.linkedin import *\n\nimport random\nfrom cgi import parse_qs\n\nTWITTER_CONSUMER_KEY = getattr(settings, 'TWITTER_CONSUMER_KEY', '')\nTWITTER_CONSUMER_SECRET = getattr(settings, 'TWITTER_CONSUMER_SECRET', '')\n\nFACEBOOK_APP_ID = getattr(settings, 'FACEBOOK_APP_ID', '')\nFACEBOOK_API_KEY = getattr(settings, 'FACEBOOK_API_KEY', '')\nFACEBOOK_SECRET_KEY = getattr(settings, 'FACEBOOK_SECRET_KEY', '')\n\n# Linkedin\nLINKEDIN_CONSUMER_KEY = getattr(settings, 'LINKEDIN_CONSUMER_KEY', '')\nLINKEDIN_CONSUMER_SECRET = getattr(settings, 'LINKEDIN_CONSUMER_SECRET', '')\n\n# OpenId setting map\n\nOPENID_AX_PROVIDER_MAP = getattr(settings, 'OPENID_AX_PROVIDER_MAP', {})\n\nclass OpenIdBackend:\n    supports_object_permissions = False\n    supports_anonymous_user = False\n    supports_inactive_user = False\n\n    def authenticate(self, openid_key, request, provider, user=None):\n        try:\n            assoc = UserAssociation.objects.get(openid_key=openid_key)\n            return assoc.user\n        except UserAssociation.DoesNotExist:\n            #fetch if openid provider provides any simple registration fields\n            nickname = None\n            email = None\n            firstname = None\n            lastname = None\n            \n            if request.openid and request.openid.sreg:\n                email = request.openid.sreg.get('email')\n                nickname = request.openid.sreg.get('nickname')\n                firstname, lastname = (request.openid.sreg\n                                       .get('fullname', ' ')\n                                       .split(' ', 1))\n            elif request.openid and request.openid.ax:\n                email = \\\n                    (request.openid.ax\n                     .getSingle('http://axschema.org/contact/email'))\n                if 'google' in provider:\n                    ax_schema = OPENID_AX_PROVIDER_MAP['Google']\n                    firstname = (request.openid.ax\n                                 .getSingle(ax_schema['firstname']))\n                    lastname = (request.openid.ax\n                                .getSingle(ax_schema['lastname']))\n                    nickname = email.split('@')[0]\n                else:\n                    ax_schema = OPENID_AX_PROVIDER_MAP['Default']\n                    try:\n                         #should be replaced by correct schema\n                        nickname = (request.openid.ax\n                                    .getSingle(ax_schema['nickname']))\n                        (firstname, \n                            lastname) = (request.openid.ax\n                                         .getSingle(ax_schema['fullname'])\n                                         .split(' ', 1))\n                    except:\n                        pass\n\n            if nickname is None :\n                nickname =  ''.join(\n                                    [random\n                                     .choice('abcdefghijklmnopqrstuvwxyz')\n                                     for i in xrange(10)])\n            \n            name_count = (User.objects\n                          .filter(username__startswith=nickname)\n                          .count())\n            if name_count:\n                username = '%s%d' % (nickname, name_count + 1)\n            else:\n                username = '%s' % (nickname)\n                \n            if email is None :\n                valid_username = False\n                email =  \"%s@socialauth\" % (username)\n            else:\n                valid_username = True\n            \n            if not user:\n                user = User.objects.create_user(username, email)\n                \n            user.first_name = firstname\n            user.last_name = lastname\n            user.save()\n    \n            #create openid association\n            assoc = UserAssociation()\n            assoc.openid_key = openid_key\n            assoc.user = user\n            if email:\n                assoc.email = email\n            if nickname:\n                assoc.nickname = nickname\n            if valid_username:\n                assoc.is_username_valid = True\n            assoc.save()\n            \n            #Create AuthMeta\n            # auth_meta = \n            #             AuthMeta(user=user, \n            #                        provider=provider, \n            #                        provider_model='OpenidProfile', \n            #                        provider_id=assoc.pk)\n            auth_meta = AuthMeta(user=user, provider=provider)\n            auth_meta.save()\n            return user\n        \n    def GooglesAX(self,openid_response):\n        email = (openid_response.ax\n                 .getSingle('http://axschema.org/contact/email'))\n        firstname = (openid_response.ax\n                     .getSingle('http://axschema.org/namePerson/first'))\n        lastname = (openid_response.ax\n                    .getSingle('http://axschema.org/namePerson/last'))\n        # country = \n        #    (openid_response.ax\n        #        .getSingle('http://axschema.org/contact/country/home'))\n        # language = \n        #    openid_response.ax.getSingle('http://axschema.org/pref/language')\n        return locals()\n  \n    def get_user(self, user_id):\n        try:\n            user = User.objects.get(pk=user_id)\n            return user\n        except User.DoesNotExist:\n            return None\n\nclass LinkedInBackend:\n    \"\"\"LinkedInBackend for authentication\"\"\"\n    def authenticate(self, linkedin_access_token, user=None):\n        linkedin = LinkedIn(LINKEDIN_CONSUMER_KEY, LINKEDIN_CONSUMER_SECRET)\n        # get their profile\n        \n        profile = (ProfileApi(linkedin)\n                   .getMyProfile(access_token=linkedin_access_token))\n\n        try:\n            user_profile = (LinkedInUserProfile.objects\n                            .get(linkedin_uid=profile.id))\n            user = user_profile.user\n            return user\n        except LinkedInUserProfile.DoesNotExist:\n            # Create a new user\n            username = 'LI:%s' % profile.id\n\n            if not user:\n                user = User(username=username)\n                user.first_name, user.last_name = (profile.firstname\n                                                   , profile.lastname)\n                user.email = '%s@socialauth' % (username)\n                user.save()\n                \n            userprofile = LinkedInUserProfile(user=user, \n                                              linkedin_uid=profile.id)\n            userprofile.save()\n            \n            auth_meta = AuthMeta(user=user, provider='LinkedIn').save()\n            return user\n\n    def get_user(self, user_id):\n        try:\n            return User.objects.get(pk=user_id)\n        except:\n            return None\n\nclass TwitterBackend:\n    \"\"\"TwitterBackend for authentication\"\"\"\n    def authenticate(self, twitter_access_token, user=None):\n        '''\n            authenticates the token by requesting user information\n            from twitter\n        '''\n        # twitter = oauthtwitter.OAuthApi(TWITTER_CONSUMER_KEY,\n        #                                  TWITTER_CONSUMER_SECRET,\n        #                                  twitter_access_token)\n        twitter = oauthtwitter.TwitterOAuthClient(\n                                            settings.TWITTER_CONSUMER_KEY,\n                                            settings.TWITTER_CONSUMER_SECRET)\n        try:\n            userinfo = twitter.get_user_info(twitter_access_token)\n        except:\n            # If we cannot get the user information, \n            # user cannot be authenticated\n            raise\n\n        screen_name = userinfo.screen_name\n        twitter_id = userinfo.id\n        \n        try:\n            user_profile = (TwitterUserProfile.objects\n                            .get(screen_name=screen_name))\n            \n            # Update Twitter Profile\n            user_profile.url = userinfo.url\n            user_profile.location = userinfo.location\n            user_profile.description = userinfo.description\n            user_profile.profile_image_url = userinfo.profile_image_url\n            user_profile.save()\n            \n            user = user_profile.user\n            return user\n        except TwitterUserProfile.DoesNotExist:\n            # Create new user\n            if not user:\n                same_name_count = (User.objects\n                                   .filter(username__startswith=screen_name)\n                                   .count())\n                if same_name_count:\n                    username = '%s%s' % (screen_name, same_name_count + 1)\n                else:\n                    username = screen_name\n                user = User(username=username)\n                name_data = userinfo.name.split()\n                try:\n                    first_name, last_name = (name_data[0], \n                                            ' '.join(name_data[1:]))\n                except:\n                    first_name, last_name =  screen_name, ''\n                user.first_name, user.last_name = first_name, last_name\n                #user.email = screen_name + \"@socialauth\"\n                #user.email = '%s@example.twitter.com'%(userinfo.screen_name)\n                user.save()\n                \n            user_profile = TwitterUserProfile(user=user, \n                                              screen_name=screen_name)\n            user_profile.access_token = str(twitter_access_token)\n            user_profile.url = userinfo.url\n            user_profile.location = userinfo.location\n            user_profile.description = userinfo.description\n            user_profile.profile_image_url = userinfo.profile_image_url\n            user_profile.save()\n            \n            auth_meta = AuthMeta(user=user, provider='Twitter').save()\n                \n            return user\n\n    def get_user(self, user_id):\n        try:\n            return User.objects.get(pk=user_id)\n        except:\n            return None\n        \nclass FacebookBackend:\n    def authenticate(self, request, user=None):\n        cookie = facebook.get_user_from_cookie(request.COOKIES,\n                                               FACEBOOK_APP_ID,\n                                               FACEBOOK_SECRET_KEY)\n        if cookie:\n            uid = cookie['uid']\n            access_token = cookie['access_token']\n        else:\n            # if cookie does not exist\n            # assume logging in normal way\n            params = {}\n            params[\"client_id\"] = FACEBOOK_APP_ID\n            params[\"client_secret\"] = FACEBOOK_SECRET_KEY\n            params[\"redirect_uri\"] = '%s://%s%s' % (\n                         'https' if request.is_secure() else 'http',\n                         Site.objects.get_current().domain,\n                         reverse(\"socialauth_facebook_login_done\"))\n            params[\"code\"] = request.GET.get('code', '')\n\n            url = (\"https://graph.facebook.com/oauth/access_token?\"\n                   + urllib.urlencode(params))\n            from cgi import parse_qs\n            userdata = urllib.urlopen(url).read()\n            res_parse_qs = parse_qs(userdata)\n            # Could be a bot query\n            if not res_parse_qs.has_key('access_token'):\n                return None\n                \n            access_token = res_parse_qs['access_token'][-1]\n            \n            graph = facebook.GraphAPI(access_token)\n            uid = graph.get_object('me')['id']\n            \n        try:\n            fb_user = FacebookUserProfile.objects.get(facebook_uid=uid)\n            return fb_user.user\n\n        except FacebookUserProfile.DoesNotExist:\n            \n            # create new FacebookUserProfile\n            graph = facebook.GraphAPI(access_token) \n            fb_data = graph.get_object(\"me\")\n\n            if not fb_data:\n                return None\n\n            username = uid\n            if not user:\n                user = User.objects.create(username=username)\n                user.first_name = fb_data['first_name']\n                user.last_name = fb_data['last_name']\n                user.save()\n                \n            fb_profile = FacebookUserProfile(facebook_uid=uid, user=user)\n            fb_profile.save()\n            \n            auth_meta = AuthMeta(user=user, provider='Facebook').save()\n                \n            return user\n\n    \n    def get_user(self, user_id):\n        try:\n            return User.objects.get(pk=user_id)\n        except:\n            return None\n\nclass GithubBackend:\n    def authenticate(self, github_access_token, user=None):\n        response_qs = parse_qs(github_access_token)\n        github_access_token = response_qs['access_token'][0]\n        try:\n            github_user = GithubUserProfile.objects.get(access_token=github_access_token)\n            return github_user.user\n        except GithubUserProfile.DoesNotExist:\n            github_user_count = GithubUserProfile.objects.all().count()\n            username = \"GithubUser:\" + str(github_user_count+1)\n            user = User(username=username)\n            user.save()\n            github_user = GithubUserProfile(user=user, access_token=github_access_token)\n            github_user.save()\n            AuthMeta(user=user, provider='Github').save() \n            return github_user.user\n\n    def get_user(self, user_id):\n        try:\n            return User.objects.get(pk=user_id)\n        except:\n            return None\n\nclass FoursquareBackend:\n    def authenticate(self, foursquare_access_token):\n        try:\n            foursquare_profile = FoursquareUserProfile.objects.get(access_token=foursquare_access_token)\n            return foursquare_profile.user \n        except FoursquareUserProfile.DoesNotExist:\n            foursquare_user_count = FoursquareUserProfile.objects.all().count()\n            username = \"FoursquareUser:\" + str(foursquare_user_count+1)\n            user = User(username=username)\n            user.save()\n            foursquare_user = FoursquareUserProfile(user=user, access_token=foursquare_access_token)\n            foursquare_user.save()\n            AuthMeta(user=user, provider='Foursquare').save()\n            return foursquare_user.user \n\n    def get_user(self, user_id):\n        try:\n            return User.objects.get(pk=user_id)\n        except:\n            return None\n"
  },
  {
    "path": "socialauth/context_processors.py",
    "content": "from django.conf import settings\n\n\ndef facebook_api_key(request):\n    FACEBOOK_APP_ID = getattr(settings, 'FACEBOOK_APP_ID', '')\n    FACEBOOK_API_KEY = getattr(settings, 'FACEBOOK_API_KEY', '')\n    FACEBOOK_EXTENDED_PERMISSIONS = getattr(settings, \n                                            'FACEBOOK_EXTENDED_PERMISSIONS',\n                                            '')\n    \n    if FACEBOOK_APP_ID:\n        return {'FACEBOOK_APP_ID': FACEBOOK_APP_ID,\n                'FACEBOOK_API_KEY': FACEBOOK_API_KEY, \n                'login_button_perms': ','.join(FACEBOOK_EXTENDED_PERMISSIONS)}\n    else:\n        return {}\n"
  },
  {
    "path": "socialauth/forms.py",
    "content": "from django import forms\nfrom django.conf import settings\n\nfrom socialauth.models import AuthMeta\n\n\nALLOW_MULTIPLE_USERNAME_EDITS = getattr(settings,\n                                        'ALLOW_MULTIPLE_USERNAME_EDITS',\n                                        False)\n\nclass EditProfileForm(forms.Form):\n    email = forms.EmailField()\n    password = forms.CharField(max_length=100, widget=forms.PasswordInput,\n                               required=False,\n                               help_text='If you give a password, you can \\\n                               login via a login form as well.')\n    password2 = forms.CharField(max_length=100, widget=forms.PasswordInput,\n                                required=False,\n                                label='Repeat password')\n    first_name = forms.CharField(max_length=100, required=False)\n    last_name = forms.CharField(max_length=100, required=False)\n    \n    def __init__(self, user=None, *args, **kwargs):\n        super(EditProfileForm, self).__init__(*args, **kwargs)\n        self.user = user\n        if self.user:\n            self.initial = {'email': user.email,  \\\n                            'first_name':user.first_name,\n                            'last_name':user.last_name}\n            \n    def clean(self):\n        cleaned_data = self.cleaned_data\n        if 'password' in cleaned_data or 'password2' in cleaned_data:\n            if 'password' in cleaned_data and 'password2' in cleaned_data:\n                if cleaned_data['password'] != cleaned_data['password2']:\n                    raise forms.ValidationError('The passwords do not match.')\n            else:\n                raise forms.ValidationError('Either ener both or None of the\\\n                                            password fields')\n\n        return cleaned_data\n        \n    def save(self):\n        user = self.user\n        user.email = self.cleaned_data['email']\n        user.first_name = self.cleaned_data['first_name']\n        user.last_name = self.cleaned_data['last_name']\n        if ('password' in self.cleaned_data \n            and \n            'password2' in self.cleaned_data):\n            user.set_password(self.cleaned_data['password'])\n        user.save()\n        try:\n            authmeta = user.authmeta\n            authmeta.is_email_filled = True\n            authmeta.is_profile_modified = True\n            authmeta.save()\n        except AuthMeta.DoesNotExist:\n            pass\n        return user\n        \n        \n"
  },
  {
    "path": "socialauth/lib/__init__.py",
    "content": ""
  },
  {
    "path": "socialauth/lib/foursquare.py",
    "content": "from oauth import oauth\nfrom django.conf import settings\nimport httplib\n\nFOURSQUARE_AUTHENTICATION_URL = 'https://foursquare.com/oauth2/authenticate'\nFOURSQUARE_ACCESS_TOKEN_URL = 'https://foursquare.com/oauth2/access_token'\nFOURSQUARE_CONSUMER_KEY = getattr(settings, 'FOURSQUARE_CONSUMER_KEY')\nFOURSQUARE_CONSUMER_SECRET = getattr(settings, 'FOURSQUARE_CONSUMER_SECRET')\nREGISTERED_REDIRECT_URI = getattr(settings, 'FOURSQUARE_REGISTERED_REDIRECT_URI')\n\ndef get_http_connection():\n    return httplib.HTTPSConnection('foursquare.com')\n\ndef get_response_body(oauth_request):\n    http_conn = get_http_connection()\n    http_conn.request('GET', oauth_request.to_url())\n    response = http_conn.getresponse().read()\n    return response\n    \n\nclass FourSquareClient(object):\n    def __init__(self):\n        self.consumer = oauth.OAuthConsumer(FOURSQUARE_CONSUMER_KEY, FOURSQUARE_CONSUMER_SECRET)\n\n    def get_authentication_url(self):\n        parameters = {}\n        parameters['client_id'] = FOURSQUARE_CONSUMER_KEY \n        parameters['response_type'] = 'code'\n        parameters['redirect_uri'] = REGISTERED_REDIRECT_URI\n        oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.consumer, http_url=FOURSQUARE_AUTHENTICATION_URL, parameters=parameters)\n        return oauth_request.to_url()\n\n    def get_access_token(self, foursquare_code):\n        parameters = {}\n        parameters['client_id'] = FOURSQUARE_CONSUMER_KEY\n        parameters['client_secret'] = FOURSQUARE_CONSUMER_SECRET\n        parameters['grant_type'] = 'authorization_code' \n        parameters['redirect_uri'] = REGISTERED_REDIRECT_URI\n        parameters['code'] = foursquare_code\n        oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.consumer, http_url=FOURSQUARE_ACCESS_TOKEN_URL, parameters=parameters)\n        access_token_response = get_response_body(oauth_request) \n        return access_token_response\n"
  },
  {
    "path": "socialauth/lib/github.py",
    "content": "from django.conf import settings \nfrom oauth.oauth import OAuthConsumer, OAuthRequest \nimport httplib\n\nGITHUB_CLIENT_ID = getattr(settings, 'GITHUB_CLIENT_ID')\nGITHUB_CLIENT_SECRET = getattr(settings, 'GITHUB_CLIENT_SECRET')\nGITHUB_AUTHORIZE_URL = 'https://github.com/login/oauth/authorize'\nGITHUB_ACCESS_TOKEN_URL = 'https://github.com/login/oauth/access_token'\n\ndef get_response_from_url(to_url):\n    conn = httplib.HTTPSConnection('github.com')\n    conn.request('GET', to_url)\n    return conn.getresponse().read()\n\nclass GithubClient(object):\n    def __init__(self):\n        self.consumer = OAuthConsumer(GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET)\n\n    def get_authorize_url(self):\n        parameters = {'client_id':GITHUB_CLIENT_ID}\n        oauth_request = OAuthRequest.from_consumer_and_token(self.consumer, http_url=GITHUB_AUTHORIZE_URL, parameters=parameters)\n        return oauth_request.to_url()\n\n    def get_access_token(self, code):\n        parameters = {}\n        parameters['client_id'] = GITHUB_CLIENT_ID\n        parameters['client_secret'] = GITHUB_CLIENT_SECRET\n        parameters['code'] = code\n        oauth_request = OAuthRequest.from_consumer_and_token(self.consumer, http_url=GITHUB_ACCESS_TOKEN_URL, parameters=parameters)\n        access_token = get_response_from_url(oauth_request.to_url())       \n        return access_token\n"
  },
  {
    "path": "socialauth/lib/linkedin.py",
    "content": "\"\"\"\nLinkedIn OAuth Api Access \nVersion: 0.01\nLicense: MIT\nAuthor: Max Lynch <max@mendotasoft.com>\nWebsite: http://mendotasoft.com, http://maxlynch.com\nDate Release: 11/23/2009\n\nEnjoy!\n\"\"\"\n\nimport hashlib\nimport urllib2\nimport httplib\n\nimport time\n\nfrom xml.dom.minidom import parseString\n\nimport oauth.oauth as oauth\n\nclass LinkedIn():\n    LI_SERVER = \"api.linkedin.com\"\n    LI_API_URL = \"https://api.linkedin.com\"\n\n    REQUEST_TOKEN_URL = LI_API_URL + \"/uas/oauth/requestToken\"\n    AUTHORIZE_URL = LI_API_URL + \"/uas/oauth/authorize\"\n    ACCESS_TOKEN_URL = LI_API_URL + \"/uas/oauth/accessToken\"\n\n\n\n    def __init__(self, api_key, secret_key):\n        self.api_key = api_key\n        self.secret_key = secret_key\n\n        self.connection = httplib.HTTPSConnection(self.LI_SERVER)\n        self.consumer = oauth.OAuthConsumer(api_key, secret_key)\n        self.sig_method = oauth.OAuthSignatureMethod_HMAC_SHA1()\n\n        self.status_api = StatusApi(self)\n        self.connections_api = ConnectionsApi(self)\n\n    def getRequestToken(self, callback):\n        \"\"\"\n        Get a request token from linkedin\n        \"\"\"\n        oauth_consumer_key = self.api_key\n\n        oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.consumer,\n                        callback=callback,\n                        http_url = self.REQUEST_TOKEN_URL)\n        oauth_request.sign_request(self.sig_method, self.consumer, None)\n\n\n        self.connection.request(oauth_request.http_method,\n                        self.REQUEST_TOKEN_URL, headers = oauth_request.to_header())\n        response = self.connection.getresponse().read()\n        \n        token = oauth.OAuthToken.from_string(response)\n        return token\n\n    def getAuthorizeUrl(self, token):\n        \"\"\"\n        Get the URL that we can redirect the user to for authorization of our\n        application.\n        \"\"\"\n        oauth_request = oauth.OAuthRequest.from_token_and_callback(token=token, http_url = self.AUTHORIZE_URL)\n        return oauth_request.to_url()\n\n    def getAccessToken(self, token, verifier):\n        \"\"\"\n        Using the verifier we obtained through the user's authorization of\n        our application, get an access code.\n\n        Note: token is the request token returned from the call to getRequestToken\n\n        @return an OAuthToken object with the access token.  Use it like this:\n                token.key -> Key\n                token.secret -> Secret Key\n        \"\"\"\n        token.verifier = verifier\n        oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.consumer, token=token, verifier=verifier, http_url=self.ACCESS_TOKEN_URL)\n        oauth_request.sign_request(self.sig_method, self.consumer, token)\n        \n        # self.connection.request(oauth_request.http_method, self.ACCESS_TOKEN_URL, headers=oauth_request.to_header()) \n        self.connection.request(oauth_request.http_method, oauth_request.to_url()) \n        response = self.connection.getresponse().read()\n        return oauth.OAuthToken.from_string(response)\n\n    \"\"\"\n    More functionality coming soon...\n    \"\"\"\n\nclass LinkedInApi():\n    def __init__(self, linkedin):\n        self.linkedin = linkedin\n\n    def doApiRequest(self, url, access_token):\n        oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.linkedin.consumer, token=access_token, http_url=url)\n        oauth_request.sign_request(self.linkedin.sig_method, self.linkedin.consumer, access_token)\n        self.linkedin.connection.request(oauth_request.http_method, url, headers=oauth_request.to_header())\n        return self.linkedin.connection.getresponse().read()\n\n\nclass StatusApi(LinkedInApi):\n    STATUS_SELF_URL = LinkedIn.LI_API_URL + \"/v1/people/~:(current-status)\"\n    \n    def __init__(self, linkedin):\n        LinkedInApi.__init__(self, linkedin)\n    \n    def getMyStatus(self, access_token):\n        return self.doApiRequest(self.STATUS_SELF_URL, access_token)\n\nclass ProfileApi(LinkedInApi):\n    \"\"\"\n    Get a LinkedIn Profile\n    \"\"\"\n    PROFILE_SELF = LinkedIn.LI_API_URL + r\"/v1/people/~:(id,first-name,last-name,headline,industry,picture-url,site-standard-profile-request)\"\n    \n    def __init__(self, linkedin):\n        LinkedInApi.__init__(self, linkedin)\n\n    def getMyProfile(self, access_token):\n        xml = self.doApiRequest(self.PROFILE_SELF, access_token)\n        dom = parseString(xml)\n        personDom = dom.getElementsByTagName('person')\n\n        p = personDom[0]\n\n        fn=ln=picurl=headline=company=industry=profurl=\"\"\n\n        try:\n            id = p.getElementsByTagName('id')[0].firstChild.nodeValue\n            fn = p.getElementsByTagName('first-name')[0].firstChild.nodeValue\n            ln = p.getElementsByTagName('last-name')[0].firstChild.nodeValue\n            picurl = p.getElementsByTagName('picture-url')[0].firstChild.nodeValue\n\n            headline = p.getElementsByTagName('headline')[0].firstChild.nodeValue\n            if ' at ' in headline:\n                company = headline.split(' at ')[1]\n            industry = p.getElementsByTagName('industry')[0].firstChild.nodeValue\n            #location = p.getElementsByTagName('industry')[0].firstChild.nodeValue\n            profurl = p.getElementsByTagName('url')[0].firstChild.nodeValue\n        except:\n            pass\n\n        person = Person()\n        person.id = id\n        person.firstname = fn\n        person.lastname = ln\n        person.headline = headline\n        person.company = company\n        person.industry = industry\n        person.picture_url = picurl\n        person.profile_url = profurl\n\n        return person\n\nclass ConnectionsApi(LinkedInApi):\n    \"\"\"\n    How to get all of a user's connections:\n\n            Note: This should happen after the linkedin redirect.  verifier is passed\n            by LinkedIn back to your redirect page\n\n            li = LinkedIn(LINKEDIN_CONSUMER_KEY, LINKEDIN_CONSUMER_SECRET)\n\n            tokenObj = oauth.OAuthToken(requestTokenKey, requestTokenSecret)\n            access_token = li.getAccessToken(tokenObj, verifier)\n\n            connections = li.connections_api.getMyConnections(access_token)\n\n            for c in connections:\n                    # Access c.firstname, c.lastname, etc.\n    \"\"\"\n\n    CONNECTIONS_SELF = LinkedIn.LI_API_URL + \"/v1/people/~/connections\"\n    def __init__(self, linkedin):\n        LinkedInApi.__init__(self, linkedin)\n        \n    def getMyConnections(self, access_token):\n        xml = self.doApiRequest(self.CONNECTIONS_SELF, access_token)\n        dom = parseString(xml)\n        peopleDom = dom.getElementsByTagName('person')\n\n        people = []\n\n        for p in peopleDom:\n            try:\n                fn = p.getElementsByTagName('first-name')[0].firstChild.nodeValue\n                ln = p.getElementsByTagName('last-name')[0].firstChild.nodeValue\n                headline = p.getElementsByTagName('headline')[0].firstChild.nodeValue\n                company = headline.split(' at ')[1]\n                industry = p.getElementsByTagName('industry')[0].firstChild.nodeValue\n                #location = p.getElementsByTagName('industry')[0].firstChild.nodeValue\n                person = Person()\n                person.firstname = fn\n                person.lastname = ln\n                person.headline = headline\n                person.company = company\n                person.industry = industry\n                people.append(person)\n            except:\n                continue\n        return people\n\nclass Person():\n    id = \"\"\n    firstname = \"\"\n    lastname = \"\"\n    headline = \"\"\n    company = \"\"\n    location = None\n    industry = \"\"\n    picture_url = \"\"\n    profile_url = \"\"\n\n    def __str__(self):\n        return \"%s %s working at %s\" % (self.firstname, self.lastname, self.company)\n\nclass Location():\n    name = \"\"\n    country = \"\"\n"
  },
  {
    "path": "socialauth/lib/oauth1.py",
    "content": "\"\"\"\nThe MIT License\n\nCopyright (c) 2007 Leah Culver\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\"\"\"\n\nimport cgi\nimport urllib\nimport time\nimport random\nimport urlparse\nimport hmac\nimport binascii\n\n\nVERSION = '1.0' # Hi Blaine!\nHTTP_METHOD = 'GET'\nSIGNATURE_METHOD = 'PLAINTEXT'\n\n\nclass OAuthError(RuntimeError):\n    \"\"\"Generic exception class.\"\"\"\n    def __init__(self, message='OAuth error occured.'):\n        self.message = message\n\ndef build_authenticate_header(realm=''):\n    \"\"\"Optional WWW-Authenticate header (401 error)\"\"\"\n    return {'WWW-Authenticate': 'OAuth realm=\"%s\"' % realm}\n\ndef escape(s):\n    \"\"\"Escape a URL including any /.\"\"\"\n    return urllib.quote(s, safe='~')\n\ndef _utf8_str(s):\n    \"\"\"Convert unicode to utf-8.\"\"\"\n    if isinstance(s, unicode):\n        return s.encode(\"utf-8\")\n    else:\n        return str(s)\n\ndef generate_timestamp():\n    \"\"\"Get seconds since epoch (UTC).\"\"\"\n    return int(time.time())\n\ndef generate_nonce(length=8):\n    \"\"\"Generate pseudorandom number.\"\"\"\n    return ''.join([str(random.randint(0, 9)) for i in range(length)])\n\ndef generate_verifier(length=8):\n    \"\"\"Generate pseudorandom number.\"\"\"\n    return ''.join([str(random.randint(0, 9)) for i in range(length)])\n\n\nclass OAuthConsumer(object):\n    \"\"\"Consumer of OAuth authentication.\n\n    OAuthConsumer is a data type that represents the identity of the Consumer\n    via its shared secret with the Service Provider.\n\n    \"\"\"\n    key = None\n    secret = None\n\n    def __init__(self, key, secret):\n        self.key = key\n        self.secret = secret\n\n\nclass OAuthToken(object):\n    \"\"\"OAuthToken is a data type that represents an End User via either an access\n    or request token.\n    \n    key -- the token\n    secret -- the token secret\n\n    \"\"\"\n    key = None\n    secret = None\n    callback = None\n    callback_confirmed = None\n    verifier = None\n\n    def __init__(self, key, secret):\n        self.key = key\n        self.secret = secret\n\n    def set_callback(self, callback):\n        self.callback = callback\n        self.callback_confirmed = 'true'\n\n    def set_verifier(self, verifier=None):\n        if verifier is not None:\n            self.verifier = verifier\n        else:\n            self.verifier = generate_verifier()\n\n    def get_callback_url(self):\n        if self.callback and self.verifier:\n            # Append the oauth_verifier.\n            parts = urlparse.urlparse(self.callback)\n            scheme, netloc, path, params, query, fragment = parts[:6]\n            if query:\n                query = '%s&oauth_verifier=%s' % (query, self.verifier)\n            else:\n                query = 'oauth_verifier=%s' % self.verifier\n            return urlparse.urlunparse((scheme, netloc, path, params,\n                query, fragment))\n        return self.callback\n\n    def to_string(self):\n        data = {\n            'oauth_token': self.key,\n            'oauth_token_secret': self.secret,\n        }\n        if self.callback_confirmed is not None:\n            data['oauth_callback_confirmed'] = self.callback_confirmed\n        return urllib.urlencode(data)\n \n    def from_string(s):\n        \"\"\" Returns a token from something like:\n        oauth_token_secret=xxx&oauth_token=xxx\n        \"\"\"\n        params = cgi.parse_qs(s, keep_blank_values=False)\n        key = params['oauth_token'][0]\n        secret = params['oauth_token_secret'][0]\n        token = OAuthToken(key, secret)\n        try:\n            token.callback_confirmed = params['oauth_callback_confirmed'][0]\n        except KeyError:\n            pass # 1.0, no callback confirmed.\n        return token\n    from_string = staticmethod(from_string)\n\n    def __str__(self):\n        return self.to_string()\n\n\nclass OAuthRequest(object):\n    \"\"\"OAuthRequest represents the request and can be serialized.\n\n    OAuth parameters:\n        - oauth_consumer_key \n        - oauth_token\n        - oauth_signature_method\n        - oauth_signature \n        - oauth_timestamp \n        - oauth_nonce\n        - oauth_version\n        - oauth_verifier\n        ... any additional parameters, as defined by the Service Provider.\n    \"\"\"\n    parameters = None # OAuth parameters.\n    http_method = HTTP_METHOD\n    http_url = None\n    version = VERSION\n\n    def __init__(self, http_method=HTTP_METHOD, http_url=None, parameters=None):\n        self.http_method = http_method\n        self.http_url = http_url\n        self.parameters = parameters or {}\n\n    def set_parameter(self, parameter, value):\n        self.parameters[parameter] = value\n\n    def get_parameter(self, parameter):\n        try:\n            return self.parameters[parameter]\n        except:\n            raise OAuthError('Parameter not found: %s' % parameter)\n\n    def _get_timestamp_nonce(self):\n        return self.get_parameter('oauth_timestamp'), self.get_parameter(\n            'oauth_nonce')\n\n    def get_nonoauth_parameters(self):\n        \"\"\"Get any non-OAuth parameters.\"\"\"\n        parameters = {}\n        for k, v in self.parameters.iteritems():\n            # Ignore oauth parameters.\n            if k.find('oauth_') < 0:\n                parameters[k] = v\n        return parameters\n\n    def to_header(self, realm=''):\n        \"\"\"Serialize as a header for an HTTPAuth request.\"\"\"\n        auth_header = 'OAuth realm=\"%s\"' % realm\n        # Add the oauth parameters.\n        if self.parameters:\n            for k, v in self.parameters.iteritems():\n                if k[:6] == 'oauth_':\n                    auth_header += ', %s=\"%s\"' % (k, escape(str(v)))\n        return {'Authorization': auth_header}\n\n    def to_postdata(self):\n        \"\"\"Serialize as post data for a POST request.\"\"\"\n        return '&'.join(['%s=%s' % (escape(str(k)), escape(str(v))) \\\n            for k, v in self.parameters.iteritems()])\n\n    def to_url(self):\n        \"\"\"Serialize as a URL for a GET request.\"\"\"\n        return '%s?%s' % (self.get_normalized_http_url(), self.to_postdata())\n\n    def get_normalized_parameters(self):\n        \"\"\"Return a string that contains the parameters that must be signed.\"\"\"\n        params = self.parameters\n        try:\n            # Exclude the signature if it exists.\n            del params['oauth_signature']\n        except:\n            pass\n        # Escape key values before sorting.\n        key_values = [(escape(_utf8_str(k)), escape(_utf8_str(v))) \\\n            for k,v in params.items()]\n        # Sort lexicographically, first after key, then after value.\n        key_values.sort()\n        # Combine key value pairs into a string.\n        return '&'.join(['%s=%s' % (k, v) for k, v in key_values])\n\n    def get_normalized_http_method(self):\n        \"\"\"Uppercases the http method.\"\"\"\n        return self.http_method.upper()\n\n    def get_normalized_http_url(self):\n        \"\"\"Parses the URL and rebuilds it to be scheme://host/path.\"\"\"\n        parts = urlparse.urlparse(self.http_url)\n        scheme, netloc, path = parts[:3]\n        # Exclude default port numbers.\n        if scheme == 'http' and netloc[-3:] == ':80':\n            netloc = netloc[:-3]\n        elif scheme == 'https' and netloc[-4:] == ':443':\n            netloc = netloc[:-4]\n        return '%s://%s%s' % (scheme, netloc, path)\n\n    def sign_request(self, signature_method, consumer, token):\n        \"\"\"Set the signature parameter to the result of build_signature.\"\"\"\n        # Set the signature method.\n        self.set_parameter('oauth_signature_method',\n            signature_method.get_name())\n        # Set the signature.\n        self.set_parameter('oauth_signature',\n            self.build_signature(signature_method, consumer, token))\n\n    def build_signature(self, signature_method, consumer, token):\n        \"\"\"Calls the build signature method within the signature method.\"\"\"\n        return signature_method.build_signature(self, consumer, token)\n\n    def from_request(http_method, http_url, headers=None, parameters=None,\n            query_string=None):\n        \"\"\"Combines multiple parameter sources.\"\"\"\n        if parameters is None:\n            parameters = {}\n\n        # Headers\n        if headers and 'Authorization' in headers:\n            auth_header = headers['Authorization']\n            # Check that the authorization header is OAuth.\n            if auth_header[:6] == 'OAuth ':\n                auth_header = auth_header[6:]\n                try:\n                    # Get the parameters from the header.\n                    header_params = OAuthRequest._split_header(auth_header)\n                    parameters.update(header_params)\n                except:\n                    raise OAuthError('Unable to parse OAuth parameters from '\n                        'Authorization header.')\n\n        # GET or POST query string.\n        if query_string:\n            query_params = OAuthRequest._split_url_string(query_string)\n            parameters.update(query_params)\n\n        # URL parameters.\n        param_str = urlparse.urlparse(http_url)[4] # query\n        url_params = OAuthRequest._split_url_string(param_str)\n        parameters.update(url_params)\n\n        if parameters:\n            return OAuthRequest(http_method, http_url, parameters)\n\n        return None\n    from_request = staticmethod(from_request)\n\n    def from_consumer_and_token(oauth_consumer, token=None,\n            callback=None, verifier=None, http_method=HTTP_METHOD,\n            http_url=None, parameters=None):\n        if not parameters:\n            parameters = {}\n\n        defaults = {\n            'oauth_consumer_key': oauth_consumer.key,\n            'oauth_timestamp': generate_timestamp(),\n            'oauth_nonce': generate_nonce(),\n            'oauth_version': OAuthRequest.version,\n        }\n\n        defaults.update(parameters)\n        parameters = defaults\n\n        if token:\n            parameters['oauth_token'] = token.key\n            if token.callback:\n                parameters['oauth_callback'] = token.callback\n            # 1.0a support for verifier.\n            if verifier:\n                parameters['oauth_verifier'] = verifier\n        elif callback:\n            # 1.0a support for callback in the request token request.\n            parameters['oauth_callback'] = callback\n\n        return OAuthRequest(http_method, http_url, parameters)\n    from_consumer_and_token = staticmethod(from_consumer_and_token)\n\n    def from_token_and_callback(token, callback=None, http_method=HTTP_METHOD,\n            http_url=None, parameters=None):\n        if not parameters:\n            parameters = {}\n\n        parameters['oauth_token'] = token.key\n\n        if callback:\n            parameters['oauth_callback'] = callback\n\n        return OAuthRequest(http_method, http_url, parameters)\n    from_token_and_callback = staticmethod(from_token_and_callback)\n\n    def _split_header(header):\n        \"\"\"Turn Authorization: header into parameters.\"\"\"\n        params = {}\n        parts = header.split(',')\n        for param in parts:\n            # Ignore realm parameter.\n            if param.find('realm') > -1:\n                continue\n            # Remove whitespace.\n            param = param.strip()\n            # Split key-value.\n            param_parts = param.split('=', 1)\n            # Remove quotes and unescape the value.\n            params[param_parts[0]] = urllib.unquote(param_parts[1].strip('\\\"'))\n        return params\n    _split_header = staticmethod(_split_header)\n\n    def _split_url_string(param_str):\n        \"\"\"Turn URL string into parameters.\"\"\"\n        parameters = cgi.parse_qs(param_str, keep_blank_values=False)\n        for k, v in parameters.iteritems():\n            parameters[k] = urllib.unquote(v[0])\n        return parameters\n    _split_url_string = staticmethod(_split_url_string)\n\nclass OAuthServer(object):\n    \"\"\"A worker to check the validity of a request against a data store.\"\"\"\n    timestamp_threshold = 300 # In seconds, five minutes.\n    version = VERSION\n    signature_methods = None\n    data_store = None\n\n    def __init__(self, data_store=None, signature_methods=None):\n        self.data_store = data_store\n        self.signature_methods = signature_methods or {}\n\n    def set_data_store(self, data_store):\n        self.data_store = data_store\n\n    def get_data_store(self):\n        return self.data_store\n\n    def add_signature_method(self, signature_method):\n        self.signature_methods[signature_method.get_name()] = signature_method\n        return self.signature_methods\n\n    def fetch_request_token(self, oauth_request):\n        \"\"\"Processes a request_token request and returns the\n        request token on success.\n        \"\"\"\n        try:\n            # Get the request token for authorization.\n            token = self._get_token(oauth_request, 'request')\n        except OAuthError:\n            # No token required for the initial token request.\n            version = self._get_version(oauth_request)\n            consumer = self._get_consumer(oauth_request)\n            try:\n                callback = self.get_callback(oauth_request)\n            except OAuthError:\n                callback = None # 1.0, no callback specified.\n            self._check_signature(oauth_request, consumer, None)\n            # Fetch a new token.\n            token = self.data_store.fetch_request_token(consumer, callback)\n        return token\n\n    def fetch_access_token(self, oauth_request):\n        \"\"\"Processes an access_token request and returns the\n        access token on success.\n        \"\"\"\n        version = self._get_version(oauth_request)\n        consumer = self._get_consumer(oauth_request)\n        try:\n            verifier = self._get_verifier(oauth_request)\n        except OAuthError:\n            verifier = None\n        # Get the request token.\n        token = self._get_token(oauth_request, 'request')\n        self._check_signature(oauth_request, consumer, token)\n        new_token = self.data_store.fetch_access_token(consumer, token, verifier)\n        return new_token\n\n    def verify_request(self, oauth_request):\n        \"\"\"Verifies an api call and checks all the parameters.\"\"\"\n        # -> consumer and token\n        version = self._get_version(oauth_request)\n        consumer = self._get_consumer(oauth_request)\n        # Get the access token.\n        token = self._get_token(oauth_request, 'access')\n        self._check_signature(oauth_request, consumer, token)\n        parameters = oauth_request.get_nonoauth_parameters()\n        return consumer, token, parameters\n\n    def authorize_token(self, token, user):\n        \"\"\"Authorize a request token.\"\"\"\n        return self.data_store.authorize_request_token(token, user)\n\n    def get_callback(self, oauth_request):\n        \"\"\"Get the callback URL.\"\"\"\n        return oauth_request.get_parameter('oauth_callback')\n \n    def build_authenticate_header(self, realm=''):\n        \"\"\"Optional support for the authenticate header.\"\"\"\n        return {'WWW-Authenticate': 'OAuth realm=\"%s\"' % realm}\n\n    def _get_version(self, oauth_request):\n        \"\"\"Verify the correct version request for this server.\"\"\"\n        try:\n            version = oauth_request.get_parameter('oauth_version')\n        except:\n            version = VERSION\n        if version and version != self.version:\n            raise OAuthError('OAuth version %s not supported.' % str(version))\n        return version\n\n    def _get_signature_method(self, oauth_request):\n        \"\"\"Figure out the signature with some defaults.\"\"\"\n        try:\n            signature_method = oauth_request.get_parameter(\n                'oauth_signature_method')\n        except:\n            signature_method = SIGNATURE_METHOD\n        try:\n            # Get the signature method object.\n            signature_method = self.signature_methods[signature_method]\n        except:\n            signature_method_names = ', '.join(self.signature_methods.keys())\n            raise OAuthError('Signature method %s not supported try one of the '\n                'following: %s' % (signature_method, signature_method_names))\n\n        return signature_method\n\n    def _get_consumer(self, oauth_request):\n        consumer_key = oauth_request.get_parameter('oauth_consumer_key')\n        consumer = self.data_store.lookup_consumer(consumer_key)\n        if not consumer:\n            raise OAuthError('Invalid consumer.')\n        return consumer\n\n    def _get_token(self, oauth_request, token_type='access'):\n        \"\"\"Try to find the token for the provided request token key.\"\"\"\n        token_field = oauth_request.get_parameter('oauth_token')\n        token = self.data_store.lookup_token(token_type, token_field)\n        if not token:\n            raise OAuthError('Invalid %s token: %s' % (token_type, token_field))\n        return token\n    \n    def _get_verifier(self, oauth_request):\n        return oauth_request.get_parameter('oauth_verifier')\n\n    def _check_signature(self, oauth_request, consumer, token):\n        timestamp, nonce = oauth_request._get_timestamp_nonce()\n        self._check_timestamp(timestamp)\n        self._check_nonce(consumer, token, nonce)\n        signature_method = self._get_signature_method(oauth_request)\n        try:\n            signature = oauth_request.get_parameter('oauth_signature')\n        except:\n            raise OAuthError('Missing signature.')\n        # Validate the signature.\n        valid_sig = signature_method.check_signature(oauth_request, consumer,\n            token, signature)\n        if not valid_sig:\n            key, base = signature_method.build_signature_base_string(\n                oauth_request, consumer, token)\n            raise OAuthError('Invalid signature. Expected signature base '\n                'string: %s' % base)\n        built = signature_method.build_signature(oauth_request, consumer, token)\n\n    def _check_timestamp(self, timestamp):\n        \"\"\"Verify that timestamp is recentish.\"\"\"\n        timestamp = int(timestamp)\n        now = int(time.time())\n        lapsed = abs(now - timestamp)\n        if lapsed > self.timestamp_threshold:\n            raise OAuthError('Expired timestamp: given %d and now %s has a '\n                'greater difference than threshold %d' %\n                (timestamp, now, self.timestamp_threshold))\n\n    def _check_nonce(self, consumer, token, nonce):\n        \"\"\"Verify that the nonce is uniqueish.\"\"\"\n        nonce = self.data_store.lookup_nonce(consumer, token, nonce)\n        if nonce:\n            raise OAuthError('Nonce already used: %s' % str(nonce))\n\n\nclass OAuthClient(object):\n    \"\"\"OAuthClient is a worker to attempt to execute a request.\"\"\"\n    consumer = None\n    token = None\n\n    def __init__(self, oauth_consumer, oauth_token):\n        self.consumer = oauth_consumer\n        self.token = oauth_token\n\n    def get_consumer(self):\n        return self.consumer\n\n    def get_token(self):\n        return self.token\n\n    def fetch_request_token(self, oauth_request):\n        \"\"\"-> OAuthToken.\"\"\"\n        raise NotImplementedError\n\n    def fetch_access_token(self, oauth_request):\n        \"\"\"-> OAuthToken.\"\"\"\n        raise NotImplementedError\n\n    def access_resource(self, oauth_request):\n        \"\"\"-> Some protected resource.\"\"\"\n        raise NotImplementedError\n\n\nclass OAuthDataStore(object):\n    \"\"\"A database abstraction used to lookup consumers and tokens.\"\"\"\n\n    def lookup_consumer(self, key):\n        \"\"\"-> OAuthConsumer.\"\"\"\n        raise NotImplementedError\n\n    def lookup_token(self, oauth_consumer, token_type, token_token):\n        \"\"\"-> OAuthToken.\"\"\"\n        raise NotImplementedError\n\n    def lookup_nonce(self, oauth_consumer, oauth_token, nonce):\n        \"\"\"-> OAuthToken.\"\"\"\n        raise NotImplementedError\n\n    def fetch_request_token(self, oauth_consumer, oauth_callback):\n        \"\"\"-> OAuthToken.\"\"\"\n        raise NotImplementedError\n\n    def fetch_access_token(self, oauth_consumer, oauth_token, oauth_verifier):\n        \"\"\"-> OAuthToken.\"\"\"\n        raise NotImplementedError\n\n    def authorize_request_token(self, oauth_token, user):\n        \"\"\"-> OAuthToken.\"\"\"\n        raise NotImplementedError\n\n\nclass OAuthSignatureMethod(object):\n    \"\"\"A strategy class that implements a signature method.\"\"\"\n    def get_name(self):\n        \"\"\"-> str.\"\"\"\n        raise NotImplementedError\n\n    def build_signature_base_string(self, oauth_request, oauth_consumer, oauth_token):\n        \"\"\"-> str key, str raw.\"\"\"\n        raise NotImplementedError\n\n    def build_signature(self, oauth_request, oauth_consumer, oauth_token):\n        \"\"\"-> str.\"\"\"\n        raise NotImplementedError\n\n    def check_signature(self, oauth_request, consumer, token, signature):\n        built = self.build_signature(oauth_request, consumer, token)\n        return built == signature\n\n\nclass OAuthSignatureMethod_HMAC_SHA1(OAuthSignatureMethod):\n\n    def get_name(self):\n        return 'HMAC-SHA1'\n        \n    def build_signature_base_string(self, oauth_request, consumer, token):\n        sig = (\n            escape(oauth_request.get_normalized_http_method()),\n            escape(oauth_request.get_normalized_http_url()),\n            escape(oauth_request.get_normalized_parameters()),\n        )\n\n        key = '%s&' % escape(consumer.secret)\n        if token:\n            key += escape(token.secret)\n        raw = '&'.join(sig)\n        return key, raw\n\n    def build_signature(self, oauth_request, consumer, token):\n        \"\"\"Builds the base signature string.\"\"\"\n        key, raw = self.build_signature_base_string(oauth_request, consumer,\n            token)\n\n        # HMAC object.\n        try:\n            import hashlib # 2.5\n            hashed = hmac.new(key, raw, hashlib.sha1)\n        except:\n            import sha # Deprecated\n            hashed = hmac.new(key, raw, sha)\n\n        # Calculate the digest base 64.\n        return binascii.b2a_base64(hashed.digest())[:-1]\n\n\nclass OAuthSignatureMethod_PLAINTEXT(OAuthSignatureMethod):\n\n    def get_name(self):\n        return 'PLAINTEXT'\n\n    def build_signature_base_string(self, oauth_request, consumer, token):\n        \"\"\"Concatenates the consumer key and secret.\"\"\"\n        sig = '%s&' % escape(consumer.secret)\n        if token:\n            sig = sig + escape(token.secret)\n        return sig, sig\n\n    def build_signature(self, oauth_request, consumer, token):\n        key, raw = self.build_signature_base_string(oauth_request, consumer,\n            token)\n        return key"
  },
  {
    "path": "socialauth/lib/oauth2.py",
    "content": "\"\"\"\nThe MIT License\n\nCopyright (c) 2007 Leah Culver\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\"\"\"\n\nimport cgi\nimport urllib\nimport time\nimport random\nimport urlparse\nimport hmac\nimport binascii\n\n\nVERSION = '1.0' # Hi Blaine!\nHTTP_METHOD = 'GET'\nSIGNATURE_METHOD = 'PLAINTEXT'\n\n\nclass OAuthError(RuntimeError):\n    \"\"\"Generic exception class.\"\"\"\n    def __init__(self, message='OAuth error occured.'):\n        self.message = message\n\ndef build_authenticate_header(realm=''):\n    \"\"\"Optional WWW-Authenticate header (401 error)\"\"\"\n    return {'WWW-Authenticate': 'OAuth realm=\"%s\"' % realm}\n\ndef escape(s):\n    \"\"\"Escape a URL including any /.\"\"\"\n    return urllib.quote(s, safe='~')\n\ndef _utf8_str(s):\n    \"\"\"Convert unicode to utf-8.\"\"\"\n    if isinstance(s, unicode):\n        return s.encode(\"utf-8\")\n    else:\n        return str(s)\n\ndef generate_timestamp():\n    \"\"\"Get seconds since epoch (UTC).\"\"\"\n    return int(time.time())\n\ndef generate_nonce(length=8):\n    \"\"\"Generate pseudorandom number.\"\"\"\n    return ''.join([str(random.randint(0, 9)) for i in range(length)])\n\n\nclass OAuthConsumer(object):\n    \"\"\"Consumer of OAuth authentication.\n\n    OAuthConsumer is a data type that represents the identity of the Consumer\n    via its shared secret with the Service Provider.\n\n    \"\"\"\n    key = None\n    secret = None\n\n    def __init__(self, key, secret):\n        self.key = key\n        self.secret = secret\n\n   \nclass OAuthToken(object):\n    \"\"\"OAuthToken is a data type that represents an End User via either an access\n    or request token.\n    \n    key -- the token\n    secret -- the token secret\n\n    \"\"\"\n    key = None\n    secret = None\n\n    def __init__(self, key, secret):\n        self.key = key\n        self.secret = secret\n\n    def to_string(self):\n        return urllib.urlencode({'oauth_token': self.key,\n            'oauth_token_secret': self.secret})\n \n    def from_string(s):\n        \"\"\" Returns a token from something like:\n        oauth_token_secret=xxx&oauth_token=xxx\n        \"\"\"\n        params = cgi.parse_qs(s, keep_blank_values=False)\n        key = params['oauth_token'][0]\n        secret = params['oauth_token_secret'][0]\n        return OAuthToken(key, secret)\n    from_string = staticmethod(from_string)\n\n    def __str__(self):\n        return self.to_string()\n\n\nclass OAuthRequest(object):\n    \"\"\"OAuthRequest represents the request and can be serialized.\n\n    OAuth parameters:\n        - oauth_consumer_key \n        - oauth_token\n        - oauth_signature_method\n        - oauth_signature \n        - oauth_timestamp \n        - oauth_nonce\n        - oauth_version\n        ... any additional parameters, as defined by the Service Provider.\n    \"\"\"\n    parameters = None # OAuth parameters.\n    http_method = HTTP_METHOD\n    http_url = None\n    version = VERSION\n\n    def __init__(self, http_method=HTTP_METHOD, http_url=None, parameters=None):\n        self.http_method = http_method\n        self.http_url = http_url\n        self.parameters = parameters or {}\n\n    def set_parameter(self, parameter, value):\n        self.parameters[parameter] = value\n\n    def get_parameter(self, parameter):\n        try:\n            return self.parameters[parameter]\n        except:\n            raise OAuthError('Parameter not found: %s' % parameter)\n\n    def _get_timestamp_nonce(self):\n        return self.get_parameter('oauth_timestamp'), self.get_parameter(\n            'oauth_nonce')\n\n    def get_nonoauth_parameters(self):\n        \"\"\"Get any non-OAuth parameters.\"\"\"\n        parameters = {}\n        for k, v in self.parameters.iteritems():\n            # Ignore oauth parameters.\n            if k.find('oauth_') < 0:\n                parameters[k] = v\n        return parameters\n\n    def to_header(self, realm=''):\n        \"\"\"Serialize as a header for an HTTPAuth request.\"\"\"\n        auth_header = 'OAuth realm=\"%s\"' % realm\n        # Add the oauth parameters.\n        if self.parameters:\n            for k, v in self.parameters.iteritems():\n                if k[:6] == 'oauth_':\n                    auth_header += ', %s=\"%s\"' % (k, escape(str(v)))\n        return {'Authorization': auth_header}\n\n    def to_postdata(self):\n        \"\"\"Serialize as post data for a POST request.\"\"\"\n        return '&'.join(['%s=%s' % (escape(str(k)), escape(str(v))) \\\n            for k, v in self.parameters.iteritems()])\n\n    def to_url(self):\n        \"\"\"Serialize as a URL for a GET request.\"\"\"\n        return '%s?%s' % (self.get_normalized_http_url(), self.to_postdata())\n\n    def get_normalized_parameters(self):\n        \"\"\"Return a string that contains the parameters that must be signed.\"\"\"\n        params = self.parameters\n        try:\n            # Exclude the signature if it exists.\n            del params['oauth_signature']\n        except:\n            pass\n        # Escape key values before sorting.\n        key_values = [(escape(_utf8_str(k)), escape(_utf8_str(v))) \\\n            for k,v in params.items()]\n        # Sort lexicographically, first after key, then after value.\n        key_values.sort()\n        # Combine key value pairs into a string.\n        return '&'.join(['%s=%s' % (k, v) for k, v in key_values])\n\n    def get_normalized_http_method(self):\n        \"\"\"Uppercases the http method.\"\"\"\n        return self.http_method.upper()\n\n    def get_normalized_http_url(self):\n        \"\"\"Parses the URL and rebuilds it to be scheme://host/path.\"\"\"\n        parts = urlparse.urlparse(self.http_url)\n        scheme, netloc, path = parts[:3]\n        # Exclude default port numbers.\n        if scheme == 'http' and netloc[-3:] == ':80':\n            netloc = netloc[:-3]\n        elif scheme == 'https' and netloc[-4:] == ':443':\n            netloc = netloc[:-4]\n        return '%s://%s%s' % (scheme, netloc, path)\n\n    def sign_request(self, signature_method, consumer, token):\n        \"\"\"Set the signature parameter to the result of build_signature.\"\"\"\n        # Set the signature method.\n        self.set_parameter('oauth_signature_method',\n            signature_method.get_name())\n        # Set the signature.\n        self.set_parameter('oauth_signature',\n            self.build_signature(signature_method, consumer, token))\n\n    def build_signature(self, signature_method, consumer, token):\n        \"\"\"Calls the build signature method within the signature method.\"\"\"\n        return signature_method.build_signature(self, consumer, token)\n\n    def from_request(http_method, http_url, headers=None, parameters=None,\n            query_string=None):\n        \"\"\"Combines multiple parameter sources.\"\"\"\n        if parameters is None:\n            parameters = {}\n\n        # Headers\n        if headers and 'Authorization' in headers:\n            auth_header = headers['Authorization']\n            # Check that the authorization header is OAuth.\n            if auth_header.index('OAuth') > -1:\n                auth_header = auth_header.lstrip('OAuth ')\n                try:\n                    # Get the parameters from the header.\n                    header_params = OAuthRequest._split_header(auth_header)\n                    parameters.update(header_params)\n                except:\n                    raise OAuthError('Unable to parse OAuth parameters from '\n                        'Authorization header.')\n\n        # GET or POST query string.\n        if query_string:\n            query_params = OAuthRequest._split_url_string(query_string)\n            parameters.update(query_params)\n\n        # URL parameters.\n        param_str = urlparse.urlparse(http_url)[4] # query\n        url_params = OAuthRequest._split_url_string(param_str)\n        parameters.update(url_params)\n\n        if parameters:\n            return OAuthRequest(http_method, http_url, parameters)\n\n        return None\n    from_request = staticmethod(from_request)\n\n    def from_consumer_and_token(oauth_consumer, token=None,\n            http_method=HTTP_METHOD, http_url=None, parameters=None):\n        if not parameters:\n            parameters = {}\n\n        defaults = {\n            'oauth_consumer_key': oauth_consumer.key,\n            'oauth_timestamp': generate_timestamp(),\n            'oauth_nonce': generate_nonce(),\n            'oauth_version': OAuthRequest.version,\n        }\n\n        defaults.update(parameters)\n        parameters = defaults\n\n        if token:\n            parameters['oauth_token'] = token.key\n\n        return OAuthRequest(http_method, http_url, parameters)\n    from_consumer_and_token = staticmethod(from_consumer_and_token)\n\n    def from_token_and_callback(token, callback=None, http_method=HTTP_METHOD,\n            http_url=None, parameters=None):\n        if not parameters:\n            parameters = {}\n\n        parameters['oauth_token'] = token.key\n\n        if callback:\n            parameters['oauth_callback'] = callback\n\n        return OAuthRequest(http_method, http_url, parameters)\n    from_token_and_callback = staticmethod(from_token_and_callback)\n\n    def _split_header(header):\n        \"\"\"Turn Authorization: header into parameters.\"\"\"\n        params = {}\n        parts = header.split(',')\n        for param in parts:\n            # Ignore realm parameter.\n            if param.find('realm') > -1:\n                continue\n            # Remove whitespace.\n            param = param.strip()\n            # Split key-value.\n            param_parts = param.split('=', 1)\n            # Remove quotes and unescape the value.\n            params[param_parts[0]] = urllib.unquote(param_parts[1].strip('\\\"'))\n        return params\n    _split_header = staticmethod(_split_header)\n\n    def _split_url_string(param_str):\n        \"\"\"Turn URL string into parameters.\"\"\"\n        parameters = cgi.parse_qs(param_str, keep_blank_values=False)\n        for k, v in parameters.iteritems():\n            parameters[k] = urllib.unquote(v[0])\n        return parameters\n    _split_url_string = staticmethod(_split_url_string)\n\nclass OAuthServer(object):\n    \"\"\"A worker to check the validity of a request against a data store.\"\"\"\n    timestamp_threshold = 300 # In seconds, five minutes.\n    version = VERSION\n    signature_methods = None\n    data_store = None\n\n    def __init__(self, data_store=None, signature_methods=None):\n        self.data_store = data_store\n        self.signature_methods = signature_methods or {}\n\n    def set_data_store(self, data_store):\n        self.data_store = data_store\n\n    def get_data_store(self):\n        return self.data_store\n\n    def add_signature_method(self, signature_method):\n        self.signature_methods[signature_method.get_name()] = signature_method\n        return self.signature_methods\n\n    def fetch_request_token(self, oauth_request):\n        \"\"\"Processes a request_token request and returns the\n        request token on success.\n        \"\"\"\n        try:\n            # Get the request token for authorization.\n            token = self._get_token(oauth_request, 'request')\n        except OAuthError:\n            # No token required for the initial token request.\n            version = self._get_version(oauth_request)\n            consumer = self._get_consumer(oauth_request)\n            self._check_signature(oauth_request, consumer, None)\n            # Fetch a new token.\n            token = self.data_store.fetch_request_token(consumer)\n        return token\n\n    def fetch_access_token(self, oauth_request):\n        \"\"\"Processes an access_token request and returns the\n        access token on success.\n        \"\"\"\n        version = self._get_version(oauth_request)\n        consumer = self._get_consumer(oauth_request)\n        # Get the request token.\n        token = self._get_token(oauth_request, 'request')\n        self._check_signature(oauth_request, consumer, token)\n        new_token = self.data_store.fetch_access_token(consumer, token)\n        return new_token\n\n    def verify_request(self, oauth_request):\n        \"\"\"Verifies an api call and checks all the parameters.\"\"\"\n        # -> consumer and token\n        version = self._get_version(oauth_request)\n        consumer = self._get_consumer(oauth_request)\n        # Get the access token.\n        token = self._get_token(oauth_request, 'access')\n        self._check_signature(oauth_request, consumer, token)\n        parameters = oauth_request.get_nonoauth_parameters()\n        return consumer, token, parameters\n\n    def authorize_token(self, token, user):\n        \"\"\"Authorize a request token.\"\"\"\n        return self.data_store.authorize_request_token(token, user)\n\n    def get_callback(self, oauth_request):\n        \"\"\"Get the callback URL.\"\"\"\n        return oauth_request.get_parameter('oauth_callback')\n \n    def build_authenticate_header(self, realm=''):\n        \"\"\"Optional support for the authenticate header.\"\"\"\n        return {'WWW-Authenticate': 'OAuth realm=\"%s\"' % realm}\n\n    def _get_version(self, oauth_request):\n        \"\"\"Verify the correct version request for this server.\"\"\"\n        try:\n            version = oauth_request.get_parameter('oauth_version')\n        except:\n            version = VERSION\n        if version and version != self.version:\n            raise OAuthError('OAuth version %s not supported.' % str(version))\n        return version\n\n    def _get_signature_method(self, oauth_request):\n        \"\"\"Figure out the signature with some defaults.\"\"\"\n        try:\n            signature_method = oauth_request.get_parameter(\n                'oauth_signature_method')\n        except:\n            signature_method = SIGNATURE_METHOD\n        try:\n            # Get the signature method object.\n            signature_method = self.signature_methods[signature_method]\n        except:\n            signature_method_names = ', '.join(self.signature_methods.keys())\n            raise OAuthError('Signature method %s not supported try one of the '\n                'following: %s' % (signature_method, signature_method_names))\n\n        return signature_method\n\n    def _get_consumer(self, oauth_request):\n        consumer_key = oauth_request.get_parameter('oauth_consumer_key')\n        consumer = self.data_store.lookup_consumer(consumer_key)\n        if not consumer:\n            raise OAuthError('Invalid consumer.')\n        return consumer\n\n    def _get_token(self, oauth_request, token_type='access'):\n        \"\"\"Try to find the token for the provided request token key.\"\"\"\n        token_field = oauth_request.get_parameter('oauth_token')\n        token = self.data_store.lookup_token(token_type, token_field)\n        if not token:\n            raise OAuthError('Invalid %s token: %s' % (token_type, token_field))\n        return token\n\n    def _check_signature(self, oauth_request, consumer, token):\n        timestamp, nonce = oauth_request._get_timestamp_nonce()\n        self._check_timestamp(timestamp)\n        self._check_nonce(consumer, token, nonce)\n        signature_method = self._get_signature_method(oauth_request)\n        try:\n            signature = oauth_request.get_parameter('oauth_signature')\n        except:\n            raise OAuthError('Missing signature.')\n        # Validate the signature.\n        valid_sig = signature_method.check_signature(oauth_request, consumer,\n            token, signature)\n        if not valid_sig:\n            key, base = signature_method.build_signature_base_string(\n                oauth_request, consumer, token)\n            raise OAuthError('Invalid signature. Expected signature base '\n                'string: %s' % base)\n        built = signature_method.build_signature(oauth_request, consumer, token)\n\n    def _check_timestamp(self, timestamp):\n        \"\"\"Verify that timestamp is recentish.\"\"\"\n        timestamp = int(timestamp)\n        now = int(time.time())\n        lapsed = now - timestamp\n        if lapsed > self.timestamp_threshold:\n            raise OAuthError('Expired timestamp: given %d and now %s has a '\n                'greater difference than threshold %d' %\n                (timestamp, now, self.timestamp_threshold))\n\n    def _check_nonce(self, consumer, token, nonce):\n        \"\"\"Verify that the nonce is uniqueish.\"\"\"\n        nonce = self.data_store.lookup_nonce(consumer, token, nonce)\n        if nonce:\n            raise OAuthError('Nonce already used: %s' % str(nonce))\n\n\nclass OAuthClient(object):\n    \"\"\"OAuthClient is a worker to attempt to execute a request.\"\"\"\n    consumer = None\n    token = None\n\n    def __init__(self, oauth_consumer, oauth_token):\n        self.consumer = oauth_consumer\n        self.token = oauth_token\n\n    def get_consumer(self):\n        return self.consumer\n\n    def get_token(self):\n        return self.token\n\n    def fetch_request_token(self, oauth_request):\n        \"\"\"-> OAuthToken.\"\"\"\n        raise NotImplementedError\n\n    def fetch_access_token(self, oauth_request):\n        \"\"\"-> OAuthToken.\"\"\"\n        raise NotImplementedError\n\n    def access_resource(self, oauth_request):\n        \"\"\"-> Some protected resource.\"\"\"\n        raise NotImplementedError\n\n\nclass OAuthDataStore(object):\n    \"\"\"A database abstraction used to lookup consumers and tokens.\"\"\"\n\n    def lookup_consumer(self, key):\n        \"\"\"-> OAuthConsumer.\"\"\"\n        raise NotImplementedError\n\n    def lookup_token(self, oauth_consumer, token_type, token_token):\n        \"\"\"-> OAuthToken.\"\"\"\n        raise NotImplementedError\n\n    def lookup_nonce(self, oauth_consumer, oauth_token, nonce):\n        \"\"\"-> OAuthToken.\"\"\"\n        raise NotImplementedError\n\n    def fetch_request_token(self, oauth_consumer):\n        \"\"\"-> OAuthToken.\"\"\"\n        raise NotImplementedError\n\n    def fetch_access_token(self, oauth_consumer, oauth_token):\n        \"\"\"-> OAuthToken.\"\"\"\n        raise NotImplementedError\n\n    def authorize_request_token(self, oauth_token, user):\n        \"\"\"-> OAuthToken.\"\"\"\n        raise NotImplementedError\n\n\nclass OAuthSignatureMethod(object):\n    \"\"\"A strategy class that implements a signature method.\"\"\"\n    def get_name(self):\n        \"\"\"-> str.\"\"\"\n        raise NotImplementedError\n\n    def build_signature_base_string(self, oauth_request, oauth_consumer, oauth_token):\n        \"\"\"-> str key, str raw.\"\"\"\n        raise NotImplementedError\n\n    def build_signature(self, oauth_request, oauth_consumer, oauth_token):\n        \"\"\"-> str.\"\"\"\n        raise NotImplementedError\n\n    def check_signature(self, oauth_request, consumer, token, signature):\n        built = self.build_signature(oauth_request, consumer, token)\n        return built == signature\n\n\nclass OAuthSignatureMethod_HMAC_SHA1(OAuthSignatureMethod):\n\n    def get_name(self):\n        return 'HMAC-SHA1'\n        \n    def build_signature_base_string(self, oauth_request, consumer, token):\n        sig = (\n            escape(oauth_request.get_normalized_http_method()),\n            escape(oauth_request.get_normalized_http_url()),\n            escape(oauth_request.get_normalized_parameters()),\n        )\n\n        key = '%s&' % escape(consumer.secret)\n        if token:\n            key += escape(token.secret)\n        raw = '&'.join(sig)\n        return key, raw\n\n    def build_signature(self, oauth_request, consumer, token):\n        \"\"\"Builds the base signature string.\"\"\"\n        key, raw = self.build_signature_base_string(oauth_request, consumer,\n            token)\n\n        # HMAC object.\n        try:\n            import hashlib # 2.5\n            hashed = hmac.new(key, raw, hashlib.sha1)\n        except:\n            import sha # Deprecated\n            hashed = hmac.new(key, raw, sha)\n\n        # Calculate the digest base 64.\n        return binascii.b2a_base64(hashed.digest())[:-1]\n\n\nclass OAuthSignatureMethod_PLAINTEXT(OAuthSignatureMethod):\n\n    def get_name(self):\n        return 'PLAINTEXT'\n\n    def build_signature_base_string(self, oauth_request, consumer, token):\n        \"\"\"Concatenates the consumer key and secret.\"\"\"\n        sig = '%s&' % escape(consumer.secret)\n        if token:\n            sig = sig + escape(token.secret)\n        return sig, sig\n\n    def build_signature(self, oauth_request, consumer, token):\n        key, raw = self.build_signature_base_string(oauth_request, consumer,\n            token)\n        return key"
  },
  {
    "path": "socialauth/lib/oauthgoogle.py",
    "content": "import httplib\nimport urllib2\nimport urllib\nimport time\nimport oauth2 as oauth\n\nfrom django.conf import settings\n\n\n\nREQUEST_TOKEN_URL = 'https://www.google.com/accounts/OAuthGetRequestToken'\nACCESS_TOKEN_URL = 'https://www.google.com/accounts/OAuthGetAccessToken'\nAUTHORIZATION_URL = 'https://www.google.com/accounts/OAuthAuthorizeToken'\n\n\nclass GoogleOAuthClient(oauth.OAuthClient):\n\n    def __init__(self, consumer_key, consumer_secret, request_token_url=REQUEST_TOKEN_URL, access_token_url=ACCESS_TOKEN_URL, authorization_url=AUTHORIZATION_URL):\n        self.consumer_key = consumer_key\n        self.consumer_secret = consumer_secret\n        self.request_token_url = request_token_url\n        self.access_token_url = access_token_url\n        self.authorization_url = authorization_url\n        self.consumer = oauth.OAuthConsumer(consumer_key, consumer_secret)\n        self.signature_method = oauth.OAuthSignatureMethod_HMAC_SHA1()\n\n    def fetch_request_token(self, **kwargs):\n        if not 'scope' in kwargs:\n            kwargs['scope'] = 'http://www.google.com/m8/feeds'\n        oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.consumer, http_url=self.request_token_url, parameters=kwargs)\n        oauth_request.sign_request(self.signature_method, self.consumer, None)\n        params = oauth_request.parameters\n        data = urllib.urlencode(params)\n        full_url='%s?%s'%(self.request_token_url, data)\n        response = urllib2.urlopen(full_url)\n        return oauth.OAuthToken.from_string(response.read())\n    \n    def authorize_token_url(self, token, callback_url=None,):\n        if not callback_url:\n            callback_url = CALLBACK_URL\n        oauth_request = oauth.OAuthRequest.from_token_and_callback(token=token, callback=callback_url, http_url=self.authorization_url,)\n        params = oauth_request.parameters\n        data = urllib.urlencode(params)\n        full_url='%s?%s'%(self.authorization_url, data)\n        return full_url\n        # response = urllib2.urlopen(full_url)\n        # return oauth.OAuthToken.from_string(response.read())\n\n    def fetch_access_token(self, token):\n        oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.consumer, token=token, http_url=self.access_token_url)\n        oauth_request.sign_request(self.signature_method, self.consumer, token)\n        params = oauth_request.parameters\n        data = urllib.urlencode(params)\n        full_url='%s?%s'%(self.access_token_url, data)\n        response = urllib2.urlopen(full_url)\n        return oauth.OAuthToken.from_string(response.read())\n\n\n    def access_resource(self, url, token, **kwargs):\n        oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.consumer, token=token, http_url=url, parameters=kwargs)\n        oauth_request.sign_request(self.signature_method, self.consumer, token)\n        params = oauth_request.parameters\n        data = urllib.urlencode(params)\n        full_url='%s?%s'%(url, data)\n        #print full_url\n        response = urllib2.urlopen(full_url)\n        return response\n\ndef run_example():\n\n    # setup\n    print '** OAuth Python Library Example **'\n    client = GoogleOAuthClient(CONSUMER_KEY, CONSUMER_SECRET)\n    pause()\n\n    # get request token\n    print '* Obtain a request token ...'\n    pause()\n    \n    print 'REQUEST (via headers)'\n    print 'parameters: %s' % str(oauth_request.parameters)\n    pause()\n    token = client.fetch_request_token(oauth_request)\n    print 'GOT'\n    print 'key: %s' % str(token.key)\n    print 'secret: %s' % str(token.secret)\n    pause()\n\n    print '* Authorize the request token ...'\n    pause()\n    \n    print 'REQUEST (via url query string)'\n    print 'parameters: %s' % str(oauth_request.parameters)\n    pause()\n    # this will actually occur only on some callback\n    url = client.authorize_token(oauth_request, get_url_only=True)\n    print 'GOT'\n    print url\n    pause()\n\n    # get access token\n    print '* Obtain an access token ...'\n    pause()\n    print 'REQUEST (via headers)'\n    print 'parameters: %s' % str(oauth_request.parameters)\n    pause()\n    token = client.fetch_access_token(oauth_request)\n    print 'GOT'\n    print 'key: %s' % str(token.key)\n    print 'secret: %s' % str(token.secret)\n    pause()\n\n    # access some protected resources\n    print '* Access protected resources ...'\n    pause()\n    parameters = {'file': 'vacation.jpg', 'size': 'original', 'oauth_callback': CALLBACK_URL} # resource specific params\n    print 'REQUEST (via post body)'\n    print 'parameters: %s' % str(oauth_request.parameters)\n    pause()\n    params = client.access_resource(oauth_request)\n    print 'GOT'\n    print 'non-oauth parameters: %s' % params\n    pause()\n\ndef pause():\n    print ''\n    time.sleep(1)\n\nif __name__ == '__main__':\n    run_example()\n    print 'Done.'"
  },
  {
    "path": "socialauth/lib/oauthtwitter.py",
    "content": "#!/usr/bin/env python\n# \n# Copyright under GPLv3\n\n'''A class the inherits everything from python-twitter and allows oauth based access\n\nRequires:\n  python-twitter\n  simplejson\n  oauth\n'''\n\n__author__ = \"Hameedullah Khan <hameed@hameedkhan.net>\"\n__version__ = \"0.1\"\n\n\nfrom twitter import Api, User\ntry:\n    import json as simplejson\nexcept:\n    from django.utils import simplejson\n\nfrom oauth import oauth\n\n\n\n# Taken from oauth implementation at: http://github.com/harperreed/twitteroauth-python/tree/master\nREQUEST_TOKEN_URL = 'https://twitter.com/oauth/request_token'\nACCESS_TOKEN_URL = 'https://twitter.com/oauth/access_token'\nAUTHORIZATION_URL = 'http://twitter.com/oauth/authorize'\nSIGNIN_URL = 'http://twitter.com/oauth/authenticate'\n\n\nclass OAuthApi(Api):\n    def __init__(self, consumer_key, consumer_secret, access_token=None):\n        if access_token:\n            Api.__init__(self,access_token.key, access_token.secret)\n        else:\n            Api.__init__(self)\n        self._Consumer = oauth.OAuthConsumer(consumer_key, consumer_secret)\n        self._signature_method = oauth.OAuthSignatureMethod_HMAC_SHA1()\n        self._access_token = access_token\n\n\n    def _GetOpener(self):\n        opener = self._urllib.build_opener()\n        return opener\n\n    def _FetchUrl(self,\n                    url,\n                    post_data=None,\n                    parameters=None,\n                    no_cache=None):\n        '''Fetch a URL, optionally caching for a specified time.\n    \n        Args:\n          url: The URL to retrieve\n          post_data: \n            A dict of (str, unicode) key/value pairs.  If set, POST will be used.\n          parameters:\n            A dict whose key/value pairs should encoded and added \n            to the query string. [OPTIONAL]\n          no_cache: If true, overrides the cache on the current request\n    \n        Returns:\n          A string containing the body of the response.\n        '''\n        # Build the extra parameters dict\n        extra_params = {}\n        try:\n            if self._default_params:\n                extra_params.update(self._default_params)\n        except AttributeError:\n            pass\n        if parameters:\n            extra_params.update(parameters)\n    \n        # Add key/value parameters to the query string of the url\n        #url = self._BuildUrl(url, extra_params=extra_params)\n    \n        if post_data:\n            http_method = \"POST\"\n            extra_params.update(post_data)\n        else:\n            http_method = \"GET\"\n        \n        req = self._makeOAuthRequest(url, parameters=extra_params, \n                                                    http_method=http_method)\n        self._signRequest(req, self._signature_method)\n\n        \n        # Get a url opener that can handle Oauth basic auth\n        opener = self._GetOpener()\n        \n        #encoded_post_data = self._EncodePostData(post_data)\n\n        if post_data:\n            encoded_post_data = req.to_postdata()\n            url = req.get_normalized_http_url()\n        else:\n            url = req.to_url()\n            encoded_post_data = \"\"\n            \n        no_cache=True\n        # Open and return the URL immediately if we're not going to cache\n        # OR we are posting data\n        if encoded_post_data or no_cache:\n            if encoded_post_data:\n                url_data = opener.open(url, encoded_post_data).read()\n            else:\n                url_data = opener.open(url).read()\n            opener.close()\n        else:\n            # Unique keys are a combination of the url and the username\n            if self._username:\n                key = self._username + ':' + url\n            else:\n                key = url\n    \n            # See if it has been cached before\n            last_cached = self._cache.GetCachedTime(key)\n    \n            # If the cached version is outdated then fetch another and store it\n            if not last_cached or time.time() >= last_cached + self._cache_timeout:\n                url_data = opener.open(url).read()\n                opener.close()\n                self._cache.Set(key, url_data)\n            else:\n                url_data = self._cache.Get(key)\n    \n        # Always return the latest version\n        return url_data\n    \n    def _makeOAuthRequest(self, url, token=None,\n                                        parameters=None, http_method=\"GET\"):\n        '''Make a OAuth request from url and parameters\n        \n        Args:\n          url: The Url to use for creating OAuth Request\n          parameters:\n             The URL parameters\n          http_method:\n             The HTTP method to use\n        Returns:\n          A OAauthRequest object\n        '''\n        if not token:\n            token = self._access_token\n        request = oauth.OAuthRequest.from_consumer_and_token(\n                            self._Consumer, token=token, \n                            http_url=url, parameters=parameters, \n                            http_method=http_method)\n        return request\n\n    def _signRequest(self, req, signature_method=oauth.OAuthSignatureMethod_HMAC_SHA1()):\n        '''Sign a request\n        \n        Reminder: Created this function so incase\n        if I need to add anything to request before signing\n        \n        Args:\n          req: The OAuth request created via _makeOAuthRequest\n          signate_method:\n             The oauth signature method to use\n        '''\n        req.sign_request(signature_method, self._Consumer, self._access_token)\n    \n\n    def getAuthorizationURL(self, token, url=AUTHORIZATION_URL, callback_url = None):\n        '''Create a signed authorization URL\n        \n        Returns:\n          A signed OAuthRequest authorization URL \n        '''\n        if callback_url:\n            parameters= {'oauth_callback':callback_url}\n        else:\n            parameters= {}\n        req = self._makeOAuthRequest(url, token=token, parameters=parameters)\n        self._signRequest(req)\n        return req.to_url()\n\n    def getSigninURL(self, token, url=SIGNIN_URL, callback_url = None):\n        '''Create a signed Sign-in URL\n        \n        Returns:\n          A signed OAuthRequest Sign-in URL \n        '''\n        \n        signin_url = self.getAuthorizationURL(token, url, callback_url)\n        return signin_url\n    \n    def getAccessToken(self, url=ACCESS_TOKEN_URL):\n        token = self._FetchUrl(url, no_cache=True)\n        return oauth.OAuthToken.from_string(token) \n\n    def getRequestToken(self, url=REQUEST_TOKEN_URL):\n        '''Get a Request Token from Twitter\n        \n        Returns:\n          A OAuthToken object containing a request token\n        '''\n        resp = self._FetchUrl(url, no_cache=True)\n        token = oauth.OAuthToken.from_string(resp)\n        return token\n    \n    def GetUserInfo(self, url='https://twitter.com/account/verify_credentials.json'):\n        '''Get user information from twitter\n        \n        Returns:\n          Returns the twitter.User object\n        '''\n        json = self._FetchUrl(url)\n        data = simplejson.loads(json)\n        self._CheckForTwitterError(data)\n        return User.NewFromJsonDict(data)\n        \n"
  },
  {
    "path": "socialauth/lib/oauthtwitter2.py",
    "content": "import time\nfrom urllib2 import Request, urlopen\n\nimport oauth1 as oauth\nfrom twitter import User\n\nfrom django.utils import simplejson as json\n\nTWITTER_URL = 'twitter.com'\nREQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token'\nACCESS_TOKEN_URL = 'https://api.twitter.com/oauth/access_token'\nAUTHORIZATION_URL = 'https://api.twitter.com/oauth/authorize'\nTWITTER_CREDENTIALS_URL = 'https://api.twitter.com/1/account/verify_credentials.json'\n\n\ndef oauth_response(req):\n    response = urlopen(Request(req.http_url, headers=req.to_header()))\n    return response.read()\n\n\nclass TwitterOAuthClient(oauth.OAuthClient):\n    def __init__(self, consumer_key, consumer_secret, request_token_url=REQUEST_TOKEN_URL, access_token_url=ACCESS_TOKEN_URL, authorization_url=AUTHORIZATION_URL):\n        self.consumer_secret = consumer_secret\n        self.consumer_key = consumer_key\n        self.consumer = oauth.OAuthConsumer(consumer_key, consumer_secret)\n        self.signature_method = oauth.OAuthSignatureMethod_HMAC_SHA1()\n        self.request_token_url = request_token_url\n        self.access_token_url = access_token_url\n        self.authorization_url = authorization_url\n\n    def fetch_request_token(self, callback):\n        oauth_request = oauth.OAuthRequest.from_consumer_and_token(\n            self.consumer,\n            http_url=self.request_token_url,\n            callback=callback\n        )\n        oauth_request.sign_request(self.signature_method, self.consumer, None)\n        return oauth.OAuthToken.from_string(oauth_response(oauth_request))\n\n    def authorize_token_url(self, token, callback_url=None):\n        oauth_request = oauth.OAuthRequest.from_consumer_and_token(\n            self.consumer,\n            token=token,\n            http_url=self.authorization_url,\n            callback=callback_url\n        )\n        oauth_request.sign_request(self.signature_method, self.consumer, token)\n        return oauth_request.to_url()\n\n    def fetch_access_token(self, token, verifier):\n        oauth_request = oauth.OAuthRequest.from_consumer_and_token(\n            self.consumer,\n            token=token,\n            verifier=verifier,\n            http_url=self.access_token_url\n        )\n        oauth_request.http_method = 'POST'\n        oauth_request.sign_request(self.signature_method, self.consumer, token)\n        return oauth.OAuthToken.from_string(oauth_response(oauth_request))\n\n    def get_user_info(self, token):\n        try:\n            oauth_request = oauth.OAuthRequest.from_consumer_and_token(\n                self.consumer,\n                token=token,\n                http_url=TWITTER_CREDENTIALS_URL\n            )\n            oauth_request.sign_request(self.signature_method, self.consumer, token)\n            return User.NewFromJsonDict(json.loads(oauth_response(oauth_request)))\n        except:\n            pass\n        return None\n\n    def access_resource(self, oauth_request):\n        # via post body\n        # -> some protected resources\n        headers = {'Content-Type': 'application/x-www-form-urlencoded'}\n        connection = get_connection()\n        body = oauth_request.to_postdata()\n        connection.request('POST', RESOURCE_URL, body=body, headers=headers)\n        response = connection.getresponse().read()\n        connection.close()\n        return response\n\n\ndef run_example():\n\n    # setup\n    print '** OAuth Python Library Example **'\n    consumer_key = raw_input('Twitter Consumer Key:').strip()\n    consumer_secret = raw_input('Twitter Consumer Secret:').strip()\n    callback = 'http://example.com/newaccounts/login/done/'\n\n    client = TwitterOAuthClient(consumer_key, consumer_secret)\n\n    pause()\n\n    # get request token\n    print '* Obtain a request token ...'\n    pause()\n\n    token = client.fetch_request_token(callback)\n    print 'GOT'\n    print 'key: %s' % str(token.key)\n    print 'secret: %s' % str(token.secret)\n    pause()\n\n    print '* Authorize the request token ...'\n    pause()\n    # this will actually occur only on some callback\n    url = client.authorize_token_url(token)\n    print 'GOT'\n    print url\n    pause()\n\n    # get access token\n    print '* Obtain an access token ...'\n    pause()\n\n    access_token = client.fetch_access_token(token)\n    print 'GOT'\n    print 'key: %s' % str(access_token.key)\n    print 'secret: %s' % str(access_token.secret)\n    pause()\n\n    # access some protected resources\n    print '* Access protected resources ...'\n    pause()\n    parameters = {\n        'file': 'vacation.jpg',\n        'size': 'original',\n        'oauth_callback': callback,\n    }  # resource specific params\n    oauth_request = oauth.OAuthRequest.from_consumer_and_token(\n        client.consumer,\n        token=token,\n        http_method='POST',\n        http_url=RESOURCE_URL,\n        parameters=parameters\n    )\n    oauth_request.sign_request(client.signature_method, client.consumer, token)\n    print 'REQUEST (via post body)'\n    print 'parameters: %s' % str(oauth_request.parameters)\n    pause()\n    params = client.access_resource(oauth_request)\n    print 'GOT'\n    print 'non-oauth parameters: %s' % params\n    pause()\n\n\ndef pause():\n    print ''\n    time.sleep(1)\n\nif __name__ == '__main__':\n    run_example()\n    print 'Done.'\n"
  },
  {
    "path": "socialauth/lib/oauthyahoo.py",
    "content": "import httplib\nimport urllib2\nimport urllib\nimport time\nimport oauth.oauth as oauth\n\nfrom django.conf import settings\n\n\n\nREQUEST_TOKEN_URL = 'https://api.login.yahoo.com/oauth/v2/get_request_token'\nACCESS_TOKEN_URL = 'https://api.login.yahoo.com/oauth/v2/get_token'\nAUTHORIZATION_URL = 'https://api.login.yahoo.com/oauth/v2/request_auth'\n\n\nclass YahooOAuthClient(oauth.OAuthClient):\n\n    def __init__(self, consumer_key, consumer_secret, request_token_url=REQUEST_TOKEN_URL, access_token_url=ACCESS_TOKEN_URL, authorization_url=AUTHORIZATION_URL):\n        self.consumer_key = consumer_key\n        self.consumer_secret = consumer_secret\n        self.request_token_url = request_token_url\n        self.access_token_url = access_token_url\n        self.authorization_url = authorization_url\n        self.consumer = oauth.OAuthConsumer(consumer_key, consumer_secret)\n        self.signature_method = oauth.OAuthSignatureMethod_HMAC_SHA1()\n\n    def fetch_request_token(self, **kwargs):\n        oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.consumer, http_url=self.request_token_url, parameters=kwargs)\n        oauth_request.sign_request(self.signature_method, self.consumer, None)\n        params = oauth_request.parameters\n        data = urllib.urlencode(params)\n        full_url='%s?%s'%(self.request_token_url, data)\n        response = urllib2.urlopen(full_url)\n        return oauth.OAuthToken.from_string(response.read())\n    \n    def authorize_token_url(self, token, callback_url=None):\n        oauth_request = oauth.OAuthRequest.from_token_and_callback(token=token, callback=callback_url, http_url=self.authorization_url)\n        params = oauth_request.parameters\n        data = urllib.urlencode(params)\n        full_url='%s?%s'%(self.authorization_url, data)\n        return full_url\n        response = urllib2.urlopen(full_url)\n        return oauth.OAuthToken.from_string(response.read())\n\n    def fetch_access_token(self, token, **kwargs):\n        oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.consumer, token=token, http_url=self.access_token_url, parameters = kwargs)\n        oauth_request.sign_request(self.signature_method, self.consumer, token)\n        params = oauth_request.parameters\n        data = urllib.urlencode(params)\n        full_url='%s?%s'%(self.access_token_url, data)\n        response = urllib2.urlopen(full_url)\n        return response\n        #return oauth.OAuthToken.from_string(response.read())\n\n\n    def access_resource(self, url, token, **kwargs):\n        oauth_request = oauth.OAuthRequest.from_consumer_and_token(self.consumer, token=token, http_url=url, parameters = kwargs)\n        oauth_request.sign_request(self.signature_method, self.consumer, token)\n        params = oauth_request.parameters\n        data = urllib.urlencode(params)\n        full_url='%s?%s'%(url, data)\n        response = urllib2.urlopen(full_url)\n        return response\n\ndef run_example():\n\n    # setup\n    print '** OAuth Python Library Example **'\n    client = GoogleOAuthClient(CONSUMER_KEY, CONSUMER_SECRET)\n    pause()\n\n    # get request token\n    print '* Obtain a request token ...'\n    pause()\n    \n    print 'REQUEST (via headers)'\n    print 'parameters: %s' % str(oauth_request.parameters)\n    pause()\n    token = client.fetch_request_token(oauth_request)\n    print 'GOT'\n    print 'key: %s' % str(token.key)\n    print 'secret: %s' % str(token.secret)\n    pause()\n\n    print '* Authorize the request token ...'\n    pause()\n    \n    print 'REQUEST (via url query string)'\n    print 'parameters: %s' % str(oauth_request.parameters)\n    pause()\n    # this will actually occur only on some callback\n    url = client.authorize_token(oauth_request, get_url_only=True)\n    print 'GOT'\n    print url\n    pause()\n\n    # get access token\n    print '* Obtain an access token ...'\n    pause()\n    print 'REQUEST (via headers)'\n    print 'parameters: %s' % str(oauth_request.parameters)\n    pause()\n    token = client.fetch_access_token(oauth_request)\n    print 'GOT'\n    print 'key: %s' % str(token.key)\n    print 'secret: %s' % str(token.secret)\n    pause()\n\n    # access some protected resources\n    print '* Access protected resources ...'\n    pause()\n    parameters = {'file': 'vacation.jpg', 'size': 'original', 'oauth_callback': CALLBACK_URL} # resource specific params\n    print 'REQUEST (via post body)'\n    print 'parameters: %s' % str(oauth_request.parameters)\n    pause()\n    params = client.access_resource(oauth_request)\n    print 'GOT'\n    print 'non-oauth parameters: %s' % params\n    pause()\n\ndef pause():\n    print ''\n    time.sleep(1)\n\nif __name__ == '__main__':\n    run_example()\n    print 'Done.'"
  },
  {
    "path": "socialauth/lib/twitter.py",
    "content": "#!/usr/bin/python2.4\n#\n# Copyright 2007 Google Inc. All Rights Reserved.\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     http://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n'''A library that provides a python interface to the Twitter API'''\n\n__author__ = 'dewitt@google.com'\n__version__ = '0.6-devel'\n\n\nimport base64\nimport calendar\nimport os\nimport rfc822\ntry:\n    import json as simplejson\nexcept:\n    from django.utils import simplejson\nimport sys\nimport tempfile\nimport textwrap\nimport time\nimport urllib\nimport urllib2\nimport urlparse\n\ntry:\n  from hashlib import md5\nexcept ImportError:\n  from md5 import md5\n\n\nCHARACTER_LIMIT = 140\n\n\nclass TwitterError(Exception):\n  '''Base class for Twitter errors'''\n  \n  @property\n  def message(self):\n    '''Returns the first argument used to construct this error.'''\n    return self.args[0]\n\n\nclass Status(object):\n  '''A class representing the Status structure used by the twitter API.\n\n  The Status structure exposes the following properties:\n\n    status.created_at\n    status.created_at_in_seconds # read only\n    status.favorited\n    status.in_reply_to_screen_name\n    status.in_reply_to_user_id\n    status.in_reply_to_status_id\n    status.truncated\n    status.source\n    status.id\n    status.text\n    status.relative_created_at # read only\n    status.user\n  '''\n  def __init__(self,\n               created_at=None,\n               favorited=None,\n               id=None,\n               text=None,\n               user=None,\n               in_reply_to_screen_name=None,\n               in_reply_to_user_id=None,\n               in_reply_to_status_id=None,\n               truncated=None,\n               source=None,\n               now=None):\n    '''An object to hold a Twitter status message.\n\n    This class is normally instantiated by the twitter.Api class and\n    returned in a sequence.\n\n    Note: Dates are posted in the form \"Sat Jan 27 04:17:38 +0000 2007\"\n\n    Args:\n      created_at: The time this status message was posted\n      favorited: Whether this is a favorite of the authenticated user\n      id: The unique id of this status message\n      text: The text of this status message\n      relative_created_at:\n        A human readable string representing the posting time\n      user:\n        A twitter.User instance representing the person posting the message\n      now:\n        The current time, if the client choses to set it.  Defaults to the\n        wall clock time.\n    '''\n    self.created_at = created_at\n    self.favorited = favorited\n    self.id = id\n    self.text = text\n    self.user = user\n    self.now = now\n    self.in_reply_to_screen_name = in_reply_to_screen_name\n    self.in_reply_to_user_id = in_reply_to_user_id\n    self.in_reply_to_status_id = in_reply_to_status_id\n    self.truncated = truncated\n    self.source = source\n\n  def GetCreatedAt(self):\n    '''Get the time this status message was posted.\n\n    Returns:\n      The time this status message was posted\n    '''\n    return self._created_at\n\n  def SetCreatedAt(self, created_at):\n    '''Set the time this status message was posted.\n\n    Args:\n      created_at: The time this status message was created\n    '''\n    self._created_at = created_at\n\n  created_at = property(GetCreatedAt, SetCreatedAt,\n                        doc='The time this status message was posted.')\n\n  def GetCreatedAtInSeconds(self):\n    '''Get the time this status message was posted, in seconds since the epoch.\n\n    Returns:\n      The time this status message was posted, in seconds since the epoch.\n    '''\n    return calendar.timegm(rfc822.parsedate(self.created_at))\n\n  created_at_in_seconds = property(GetCreatedAtInSeconds,\n                                   doc=\"The time this status message was \"\n                                       \"posted, in seconds since the epoch\")\n\n  def GetFavorited(self):\n    '''Get the favorited setting of this status message.\n\n    Returns:\n      True if this status message is favorited; False otherwise\n    '''\n    return self._favorited\n\n  def SetFavorited(self, favorited):\n    '''Set the favorited state of this status message.\n\n    Args:\n      favorited: boolean True/False favorited state of this status message\n    '''\n    self._favorited = favorited\n\n  favorited = property(GetFavorited, SetFavorited,\n                       doc='The favorited state of this status message.')\n\n  def GetId(self):\n    '''Get the unique id of this status message.\n\n    Returns:\n      The unique id of this status message\n    '''\n    return self._id\n\n  def SetId(self, id):\n    '''Set the unique id of this status message.\n\n    Args:\n      id: The unique id of this status message\n    '''\n    self._id = id\n\n  id = property(GetId, SetId,\n                doc='The unique id of this status message.')\n\n  def GetInReplyToScreenName(self):\n    return self._in_reply_to_screen_name\n\n  def SetInReplyToScreenName(self, in_reply_to_screen_name):\n    self._in_reply_to_screen_name = in_reply_to_screen_name\n\n  in_reply_to_screen_name = property(GetInReplyToScreenName, SetInReplyToScreenName,\n                doc='')\n\n  def GetInReplyToUserId(self):\n    return self._in_reply_to_user_id\n\n  def SetInReplyToUserId(self, in_reply_to_user_id):\n    self._in_reply_to_user_id = in_reply_to_user_id\n\n  in_reply_to_user_id = property(GetInReplyToUserId, SetInReplyToUserId,\n                doc='')\n\n  def GetInReplyToStatusId(self):\n    return self._in_reply_to_status_id\n\n  def SetInReplyToStatusId(self, in_reply_to_status_id):\n    self._in_reply_to_status_id = in_reply_to_status_id\n\n  in_reply_to_status_id = property(GetInReplyToStatusId, SetInReplyToStatusId,\n                doc='')\n\n  def GetTruncated(self):\n    return self._truncated\n\n  def SetTruncated(self, truncated):\n    self._truncated = truncated\n\n  truncated = property(GetTruncated, SetTruncated,\n                doc='')\n\n  def GetSource(self):\n    return self._source\n\n  def SetSource(self, source):\n    self._source = source\n\n  source = property(GetSource, SetSource,\n                doc='')\n\n  def GetText(self):\n    '''Get the text of this status message.\n\n    Returns:\n      The text of this status message.\n    '''\n    return self._text\n\n  def SetText(self, text):\n    '''Set the text of this status message.\n\n    Args:\n      text: The text of this status message\n    '''\n    self._text = text\n\n  text = property(GetText, SetText,\n                  doc='The text of this status message')\n\n  def GetRelativeCreatedAt(self):\n    '''Get a human redable string representing the posting time\n\n    Returns:\n      A human readable string representing the posting time\n    '''\n    fudge = 1.25\n    delta  = long(self.now) - long(self.created_at_in_seconds)\n\n    if delta < (1 * fudge):\n      return 'about a second ago'\n    elif delta < (60 * (1/fudge)):\n      return 'about %d seconds ago' % (delta)\n    elif delta < (60 * fudge):\n      return 'about a minute ago'\n    elif delta < (60 * 60 * (1/fudge)):\n      return 'about %d minutes ago' % (delta / 60)\n    elif delta < (60 * 60 * fudge):\n      return 'about an hour ago'\n    elif delta < (60 * 60 * 24 * (1/fudge)):\n      return 'about %d hours ago' % (delta / (60 * 60))\n    elif delta < (60 * 60 * 24 * fudge):\n      return 'about a day ago'\n    else:\n      return 'about %d days ago' % (delta / (60 * 60 * 24))\n\n  relative_created_at = property(GetRelativeCreatedAt,\n                                 doc='Get a human readable string representing'\n                                     'the posting time')\n\n  def GetUser(self):\n    '''Get a twitter.User reprenting the entity posting this status message.\n\n    Returns:\n      A twitter.User reprenting the entity posting this status message\n    '''\n    return self._user\n\n  def SetUser(self, user):\n    '''Set a twitter.User reprenting the entity posting this status message.\n\n    Args:\n      user: A twitter.User reprenting the entity posting this status message\n    '''\n    self._user = user\n\n  user = property(GetUser, SetUser,\n                  doc='A twitter.User reprenting the entity posting this '\n                      'status message')\n\n  def GetNow(self):\n    '''Get the wallclock time for this status message.\n\n    Used to calculate relative_created_at.  Defaults to the time\n    the object was instantiated.\n\n    Returns:\n      Whatever the status instance believes the current time to be,\n      in seconds since the epoch.\n    '''\n    if self._now is None:\n      self._now = time.time()\n    return self._now\n\n  def SetNow(self, now):\n    '''Set the wallclock time for this status message.\n\n    Used to calculate relative_created_at.  Defaults to the time\n    the object was instantiated.\n\n    Args:\n      now: The wallclock time for this instance.\n    '''\n    self._now = now\n\n  now = property(GetNow, SetNow,\n                 doc='The wallclock time for this status instance.')\n\n\n  def __ne__(self, other):\n    return not self.__eq__(other)\n\n  def __eq__(self, other):\n    try:\n      return other and \\\n             self.created_at == other.created_at and \\\n             self.id == other.id and \\\n             self.text == other.text and \\\n             self.user == other.user and \\\n             self.in_reply_to_screen_name == other.in_reply_to_screen_name and \\\n             self.in_reply_to_user_id == other.in_reply_to_user_id and \\\n             self.in_reply_to_status_id == other.in_reply_to_status_id and \\\n             self.truncated == other.truncated and \\\n             self.favorited == other.favorited and \\\n             self.source == other.source\n    except AttributeError:\n      return False\n\n  def __str__(self):\n    '''A string representation of this twitter.Status instance.\n\n    The return value is the same as the JSON string representation.\n\n    Returns:\n      A string representation of this twitter.Status instance.\n    '''\n    return self.AsJsonString()\n\n  def AsJsonString(self):\n    '''A JSON string representation of this twitter.Status instance.\n\n    Returns:\n      A JSON string representation of this twitter.Status instance\n   '''\n    return simplejson.dumps(self.AsDict(), sort_keys=True)\n\n  def AsDict(self):\n    '''A dict representation of this twitter.Status instance.\n\n    The return value uses the same key names as the JSON representation.\n\n    Return:\n      A dict representing this twitter.Status instance\n    '''\n    data = {}\n    if self.created_at:\n      data['created_at'] = self.created_at\n    if self.favorited:\n      data['favorited'] = self.favorited\n    if self.id:\n      data['id'] = self.id\n    if self.text:\n      data['text'] = self.text\n    if self.user:\n      data['user'] = self.user.AsDict()\n    if self.in_reply_to_screen_name:\n      data['in_reply_to_screen_name'] = self.in_reply_to_screen_name\n    if self.in_reply_to_user_id:\n      data['in_reply_to_user_id'] = self.in_reply_to_user_id\n    if self.in_reply_to_status_id:\n      data['in_reply_to_status_id'] = self.in_reply_to_status_id\n    if self.truncated is not None:\n      data['truncated'] = self.truncated\n    if self.favorited is not None:\n      data['favorited'] = self.favorited\n    if self.source:\n      data['source'] = self.source\n    return data\n\n  @staticmethod\n  def NewFromJsonDict(data):\n    '''Create a new instance based on a JSON dict.\n\n    Args:\n      data: A JSON dict, as converted from the JSON in the twitter API\n    Returns:\n      A twitter.Status instance\n    '''\n    if 'user' in data:\n      user = User.NewFromJsonDict(data['user'])\n    else:\n      user = None\n    return Status(created_at=data.get('created_at', None),\n                  favorited=data.get('favorited', None),\n                  id=data.get('id', None),\n                  text=data.get('text', None),\n                  in_reply_to_screen_name=data.get('in_reply_to_screen_name', None),\n                  in_reply_to_user_id=data.get('in_reply_to_user_id', None),\n                  in_reply_to_status_id=data.get('in_reply_to_status_id', None),\n                  truncated=data.get('truncated', None),\n                  source=data.get('source', None),\n                  user=user)\n\n\nclass User(object):\n  '''A class representing the User structure used by the twitter API.\n\n  The User structure exposes the following properties:\n\n    user.id\n    user.name\n    user.screen_name\n    user.location\n    user.description\n    user.profile_image_url\n    user.profile_background_tile\n    user.profile_background_image_url\n    user.profile_sidebar_fill_color\n    user.profile_background_color\n    user.profile_link_color\n    user.profile_text_color\n    user.protected\n    user.utc_offset\n    user.time_zone\n    user.url\n    user.status\n    user.statuses_count\n    user.followers_count\n    user.friends_count\n    user.favourites_count\n  '''\n  def __init__(self,\n               id=None,\n               name=None,\n               screen_name=None,\n               location=None,\n               description=None,\n               profile_image_url=None,\n               profile_background_tile=None,\n               profile_background_image_url=None,\n               profile_sidebar_fill_color=None,\n               profile_background_color=None,\n               profile_link_color=None,\n               profile_text_color=None,\n               protected=None,\n               utc_offset=None,\n               time_zone=None,\n               followers_count=None,\n               friends_count=None,\n               statuses_count=None,\n               favourites_count=None,\n               url=None,\n               status=None):\n    self.id = id\n    self.name = name\n    self.screen_name = screen_name\n    self.location = location\n    self.description = description\n    self.profile_image_url = profile_image_url\n    self.profile_background_tile = profile_background_tile\n    self.profile_background_image_url = profile_background_image_url\n    self.profile_sidebar_fill_color = profile_sidebar_fill_color\n    self.profile_background_color = profile_background_color\n    self.profile_link_color = profile_link_color\n    self.profile_text_color = profile_text_color\n    self.protected = protected\n    self.utc_offset = utc_offset\n    self.time_zone = time_zone\n    self.followers_count = followers_count\n    self.friends_count = friends_count\n    self.statuses_count = statuses_count\n    self.favourites_count = favourites_count\n    self.url = url\n    self.status = status\n\n\n  def GetId(self):\n    '''Get the unique id of this user.\n\n    Returns:\n      The unique id of this user\n    '''\n    return self._id\n\n  def SetId(self, id):\n    '''Set the unique id of this user.\n\n    Args:\n      id: The unique id of this user.\n    '''\n    self._id = id\n\n  id = property(GetId, SetId,\n                doc='The unique id of this user.')\n\n  def GetName(self):\n    '''Get the real name of this user.\n\n    Returns:\n      The real name of this user\n    '''\n    return self._name\n\n  def SetName(self, name):\n    '''Set the real name of this user.\n\n    Args:\n      name: The real name of this user\n    '''\n    self._name = name\n\n  name = property(GetName, SetName,\n                  doc='The real name of this user.')\n\n  def GetScreenName(self):\n    '''Get the short username of this user.\n\n    Returns:\n      The short username of this user\n    '''\n    return self._screen_name\n\n  def SetScreenName(self, screen_name):\n    '''Set the short username of this user.\n\n    Args:\n      screen_name: the short username of this user\n    '''\n    self._screen_name = screen_name\n\n  screen_name = property(GetScreenName, SetScreenName,\n                         doc='The short username of this user.')\n\n  def GetLocation(self):\n    '''Get the geographic location of this user.\n\n    Returns:\n      The geographic location of this user\n    '''\n    return self._location\n\n  def SetLocation(self, location):\n    '''Set the geographic location of this user.\n\n    Args:\n      location: The geographic location of this user\n    '''\n    self._location = location\n\n  location = property(GetLocation, SetLocation,\n                      doc='The geographic location of this user.')\n\n  def GetDescription(self):\n    '''Get the short text description of this user.\n\n    Returns:\n      The short text description of this user\n    '''\n    return self._description\n\n  def SetDescription(self, description):\n    '''Set the short text description of this user.\n\n    Args:\n      description: The short text description of this user\n    '''\n    self._description = description\n\n  description = property(GetDescription, SetDescription,\n                         doc='The short text description of this user.')\n\n  def GetUrl(self):\n    '''Get the homepage url of this user.\n\n    Returns:\n      The homepage url of this user\n    '''\n    return self._url\n\n  def SetUrl(self, url):\n    '''Set the homepage url of this user.\n\n    Args:\n      url: The homepage url of this user\n    '''\n    self._url = url\n\n  url = property(GetUrl, SetUrl,\n                 doc='The homepage url of this user.')\n\n  def GetProfileImageUrl(self):\n    '''Get the url of the thumbnail of this user.\n\n    Returns:\n      The url of the thumbnail of this user\n    '''\n    return self._profile_image_url\n\n  def SetProfileImageUrl(self, profile_image_url):\n    '''Set the url of the thumbnail of this user.\n\n    Args:\n      profile_image_url: The url of the thumbnail of this user\n    '''\n    self._profile_image_url = profile_image_url\n\n  profile_image_url= property(GetProfileImageUrl, SetProfileImageUrl,\n                              doc='The url of the thumbnail of this user.')\n\n  def GetProfileBackgroundTile(self):\n    '''Boolean for whether to tile the profile background image.\n\n    Returns:\n      True if the background is to be tiled, False if not, None if unset.\n    '''\n    return self._profile_background_tile\n\n  def SetProfileBackgroundTile(self, profile_background_tile):\n    '''Set the boolean flag for whether to tile the profile background image.\n\n    Args:\n      profile_background_tile: Boolean flag for whether to tile or not.\n    '''\n    self._profile_background_tile = profile_background_tile\n\n  profile_background_tile = property(GetProfileBackgroundTile, SetProfileBackgroundTile,\n                                     doc='Boolean for whether to tile the background image.')\n\n  def GetProfileBackgroundImageUrl(self):\n    return self._profile_background_image_url\n\n  def SetProfileBackgroundImageUrl(self, profile_background_image_url):\n    self._profile_background_image_url = profile_background_image_url\n\n  profile_background_image_url = property(GetProfileBackgroundImageUrl, SetProfileBackgroundImageUrl,\n                                          doc='The url of the profile background of this user.')\n\n  def GetProfileSidebarFillColor(self):\n    return self._profile_sidebar_fill_color\n\n  def SetProfileSidebarFillColor(self, profile_sidebar_fill_color):\n    self._profile_sidebar_fill_color = profile_sidebar_fill_color\n\n  profile_sidebar_fill_color = property(GetProfileSidebarFillColor, SetProfileSidebarFillColor)\n\n  def GetProfileBackgroundColor(self):\n    return self._profile_background_color\n\n  def SetProfileBackgroundColor(self, profile_background_color):\n    self._profile_background_color = profile_background_color\n\n  profile_background_color = property(GetProfileBackgroundColor, SetProfileBackgroundColor)\n\n  def GetProfileLinkColor(self):\n    return self._profile_link_color\n\n  def SetProfileLinkColor(self, profile_link_color):\n    self._profile_link_color = profile_link_color\n\n  profile_link_color = property(GetProfileLinkColor, SetProfileLinkColor)\n\n  def GetProfileTextColor(self):\n    return self._profile_text_color\n\n  def SetProfileTextColor(self, profile_text_color):\n    self._profile_text_color = profile_text_color\n\n  profile_text_color = property(GetProfileTextColor, SetProfileTextColor)\n\n  def GetProtected(self):\n    return self._protected\n\n  def SetProtected(self, protected):\n    self._protected = protected\n\n  protected = property(GetProtected, SetProtected)\n\n  def GetUtcOffset(self):\n    return self._utc_offset\n\n  def SetUtcOffset(self, utc_offset):\n    self._utc_offset = utc_offset\n\n  utc_offset = property(GetUtcOffset, SetUtcOffset)\n\n  def GetTimeZone(self):\n    '''Returns the current time zone string for the user.\n\n    Returns:\n      The descriptive time zone string for the user.\n    '''\n    return self._time_zone\n\n  def SetTimeZone(self, time_zone):\n    '''Sets the user's time zone string.\n\n    Args:\n      time_zone: The descriptive time zone to assign for the user.\n    '''\n    self._time_zone = time_zone\n\n  time_zone = property(GetTimeZone, SetTimeZone)\n\n  def GetStatus(self):\n    '''Get the latest twitter.Status of this user.\n\n    Returns:\n      The latest twitter.Status of this user\n    '''\n    return self._status\n\n  def SetStatus(self, status):\n    '''Set the latest twitter.Status of this user.\n\n    Args:\n      status: The latest twitter.Status of this user\n    '''\n    self._status = status\n\n  status = property(GetStatus, SetStatus,\n                  doc='The latest twitter.Status of this user.')\n\n  def GetFriendsCount(self):\n    '''Get the friend count for this user.\n    \n    Returns:\n      The number of users this user has befriended.\n    '''\n    return self._friends_count\n\n  def SetFriendsCount(self, count):\n    '''Set the friend count for this user.\n\n    Args:\n      count: The number of users this user has befriended.\n    '''\n    self._friends_count = count\n\n  friends_count = property(GetFriendsCount, SetFriendsCount,\n                  doc='The number of friends for this user.')\n\n  def GetFollowersCount(self):\n    '''Get the follower count for this user.\n    \n    Returns:\n      The number of users following this user.\n    '''\n    return self._followers_count\n\n  def SetFollowersCount(self, count):\n    '''Set the follower count for this user.\n\n    Args:\n      count: The number of users following this user.\n    '''\n    self._followers_count = count\n\n  followers_count = property(GetFollowersCount, SetFollowersCount,\n                  doc='The number of users following this user.')\n\n  def GetStatusesCount(self):\n    '''Get the number of status updates for this user.\n    \n    Returns:\n      The number of status updates for this user.\n    '''\n    return self._statuses_count\n\n  def SetStatusesCount(self, count):\n    '''Set the status update count for this user.\n\n    Args:\n      count: The number of updates for this user.\n    '''\n    self._statuses_count = count\n\n  statuses_count = property(GetStatusesCount, SetStatusesCount,\n                  doc='The number of updates for this user.')\n\n  def GetFavouritesCount(self):\n    '''Get the number of favourites for this user.\n    \n    Returns:\n      The number of favourites for this user.\n    '''\n    return self._favourites_count\n\n  def SetFavouritesCount(self, count):\n    '''Set the favourite count for this user.\n\n    Args:\n      count: The number of favourites for this user.\n    '''\n    self._favourites_count = count\n\n  favourites_count = property(GetFavouritesCount, SetFavouritesCount,\n                  doc='The number of favourites for this user.')\n\n  def __ne__(self, other):\n    return not self.__eq__(other)\n\n  def __eq__(self, other):\n    try:\n      return other and \\\n             self.id == other.id and \\\n             self.name == other.name and \\\n             self.screen_name == other.screen_name and \\\n             self.location == other.location and \\\n             self.description == other.description and \\\n             self.profile_image_url == other.profile_image_url and \\\n             self.profile_background_tile == other.profile_background_tile and \\\n             self.profile_background_image_url == other.profile_background_image_url and \\\n             self.profile_sidebar_fill_color == other.profile_sidebar_fill_color and \\\n             self.profile_background_color == other.profile_background_color and \\\n             self.profile_link_color == other.profile_link_color and \\\n             self.profile_text_color == other.profile_text_color and \\\n             self.protected == other.protected and \\\n             self.utc_offset == other.utc_offset and \\\n             self.time_zone == other.time_zone and \\\n             self.url == other.url and \\\n             self.statuses_count == other.statuses_count and \\\n             self.followers_count == other.followers_count and \\\n             self.favourites_count == other.favourites_count and \\\n             self.friends_count == other.friends_count and \\\n             self.status == other.status\n    except AttributeError:\n      return False\n\n  def __str__(self):\n    '''A string representation of this twitter.User instance.\n\n    The return value is the same as the JSON string representation.\n\n    Returns:\n      A string representation of this twitter.User instance.\n    '''\n    return self.AsJsonString()\n\n  def AsJsonString(self):\n    '''A JSON string representation of this twitter.User instance.\n\n    Returns:\n      A JSON string representation of this twitter.User instance\n   '''\n    return simplejson.dumps(self.AsDict(), sort_keys=True)\n\n  def AsDict(self):\n    '''A dict representation of this twitter.User instance.\n\n    The return value uses the same key names as the JSON representation.\n\n    Return:\n      A dict representing this twitter.User instance\n    '''\n    data = {}\n    if self.id:\n      data['id'] = self.id\n    if self.name:\n      data['name'] = self.name\n    if self.screen_name:\n      data['screen_name'] = self.screen_name\n    if self.location:\n      data['location'] = self.location\n    if self.description:\n      data['description'] = self.description\n    if self.profile_image_url:\n      data['profile_image_url'] = self.profile_image_url\n    if self.profile_background_tile is not None:\n      data['profile_background_tile'] = self.profile_background_tile\n    if self.profile_background_image_url:\n      data['profile_sidebar_fill_color'] = self.profile_background_image_url\n    if self.profile_background_color:\n      data['profile_background_color'] = self.profile_background_color\n    if self.profile_link_color:\n      data['profile_link_color'] = self.profile_link_color\n    if self.profile_text_color:\n      data['profile_text_color'] = self.profile_text_color\n    if self.protected is not None:\n      data['protected'] = self.protected\n    if self.utc_offset:\n      data['utc_offset'] = self.utc_offset\n    if self.time_zone:\n      data['time_zone'] = self.time_zone\n    if self.url:\n      data['url'] = self.url\n    if self.status:\n      data['status'] = self.status.AsDict()\n    if self.friends_count:\n      data['friends_count'] = self.friends_count\n    if self.followers_count:\n      data['followers_count'] = self.followers_count\n    if self.statuses_count:\n      data['statuses_count'] = self.statuses_count\n    if self.favourites_count:\n      data['favourites_count'] = self.favourites_count\n    return data\n\n  @staticmethod\n  def NewFromJsonDict(data):\n    '''Create a new instance based on a JSON dict.\n\n    Args:\n      data: A JSON dict, as converted from the JSON in the twitter API\n    Returns:\n      A twitter.User instance\n    '''\n    if 'status' in data:\n      status = Status.NewFromJsonDict(data['status'])\n    else:\n      status = None\n    return User(id=data.get('id', None),\n                name=data.get('name', None),\n                screen_name=data.get('screen_name', None),\n                location=data.get('location', None),\n                description=data.get('description', None),\n                statuses_count=data.get('statuses_count', None),\n                followers_count=data.get('followers_count', None),\n                favourites_count=data.get('favourites_count', None),\n                friends_count=data.get('friends_count', None),\n                profile_image_url=data.get('profile_image_url', None),\n                profile_background_tile = data.get('profile_background_tile', None),\n                profile_background_image_url = data.get('profile_background_image_url', None),\n                profile_sidebar_fill_color = data.get('profile_sidebar_fill_color', None),\n                profile_background_color = data.get('profile_background_color', None),\n                profile_link_color = data.get('profile_link_color', None),\n                profile_text_color = data.get('profile_text_color', None),\n                protected = data.get('protected', None),\n                utc_offset = data.get('utc_offset', None),\n                time_zone = data.get('time_zone', None),\n                url=data.get('url', None),\n                status=status)\n\nclass DirectMessage(object):\n  '''A class representing the DirectMessage structure used by the twitter API.\n\n  The DirectMessage structure exposes the following properties:\n\n    direct_message.id\n    direct_message.created_at\n    direct_message.created_at_in_seconds # read only\n    direct_message.sender_id\n    direct_message.sender_screen_name\n    direct_message.recipient_id\n    direct_message.recipient_screen_name\n    direct_message.text\n  '''\n\n  def __init__(self,\n               id=None,\n               created_at=None,\n               sender_id=None,\n               sender_screen_name=None,\n               recipient_id=None,\n               recipient_screen_name=None,\n               text=None):\n    '''An object to hold a Twitter direct message.\n\n    This class is normally instantiated by the twitter.Api class and\n    returned in a sequence.\n\n    Note: Dates are posted in the form \"Sat Jan 27 04:17:38 +0000 2007\"\n\n    Args:\n      id: The unique id of this direct message\n      created_at: The time this direct message was posted\n      sender_id: The id of the twitter user that sent this message\n      sender_screen_name: The name of the twitter user that sent this message\n      recipient_id: The id of the twitter that received this message\n      recipient_screen_name: The name of the twitter that received this message\n      text: The text of this direct message\n    '''\n    self.id = id\n    self.created_at = created_at\n    self.sender_id = sender_id\n    self.sender_screen_name = sender_screen_name\n    self.recipient_id = recipient_id\n    self.recipient_screen_name = recipient_screen_name\n    self.text = text\n\n  def GetId(self):\n    '''Get the unique id of this direct message.\n\n    Returns:\n      The unique id of this direct message\n    '''\n    return self._id\n\n  def SetId(self, id):\n    '''Set the unique id of this direct message.\n\n    Args:\n      id: The unique id of this direct message\n    '''\n    self._id = id\n\n  id = property(GetId, SetId,\n                doc='The unique id of this direct message.')\n\n  def GetCreatedAt(self):\n    '''Get the time this direct message was posted.\n\n    Returns:\n      The time this direct message was posted\n    '''\n    return self._created_at\n\n  def SetCreatedAt(self, created_at):\n    '''Set the time this direct message was posted.\n\n    Args:\n      created_at: The time this direct message was created\n    '''\n    self._created_at = created_at\n\n  created_at = property(GetCreatedAt, SetCreatedAt,\n                        doc='The time this direct message was posted.')\n\n  def GetCreatedAtInSeconds(self):\n    '''Get the time this direct message was posted, in seconds since the epoch.\n\n    Returns:\n      The time this direct message was posted, in seconds since the epoch.\n    '''\n    return calendar.timegm(rfc822.parsedate(self.created_at))\n\n  created_at_in_seconds = property(GetCreatedAtInSeconds,\n                                   doc=\"The time this direct message was \"\n                                       \"posted, in seconds since the epoch\")\n\n  def GetSenderId(self):\n    '''Get the unique sender id of this direct message.\n\n    Returns:\n      The unique sender id of this direct message\n    '''\n    return self._sender_id\n\n  def SetSenderId(self, sender_id):\n    '''Set the unique sender id of this direct message.\n\n    Args:\n      sender id: The unique sender id of this direct message\n    '''\n    self._sender_id = sender_id\n\n  sender_id = property(GetSenderId, SetSenderId,\n                doc='The unique sender id of this direct message.')\n\n  def GetSenderScreenName(self):\n    '''Get the unique sender screen name of this direct message.\n\n    Returns:\n      The unique sender screen name of this direct message\n    '''\n    return self._sender_screen_name\n\n  def SetSenderScreenName(self, sender_screen_name):\n    '''Set the unique sender screen name of this direct message.\n\n    Args:\n      sender_screen_name: The unique sender screen name of this direct message\n    '''\n    self._sender_screen_name = sender_screen_name\n\n  sender_screen_name = property(GetSenderScreenName, SetSenderScreenName,\n                doc='The unique sender screen name of this direct message.')\n\n  def GetRecipientId(self):\n    '''Get the unique recipient id of this direct message.\n\n    Returns:\n      The unique recipient id of this direct message\n    '''\n    return self._recipient_id\n\n  def SetRecipientId(self, recipient_id):\n    '''Set the unique recipient id of this direct message.\n\n    Args:\n      recipient id: The unique recipient id of this direct message\n    '''\n    self._recipient_id = recipient_id\n\n  recipient_id = property(GetRecipientId, SetRecipientId,\n                doc='The unique recipient id of this direct message.')\n\n  def GetRecipientScreenName(self):\n    '''Get the unique recipient screen name of this direct message.\n\n    Returns:\n      The unique recipient screen name of this direct message\n    '''\n    return self._recipient_screen_name\n\n  def SetRecipientScreenName(self, recipient_screen_name):\n    '''Set the unique recipient screen name of this direct message.\n\n    Args:\n      recipient_screen_name: The unique recipient screen name of this direct message\n    '''\n    self._recipient_screen_name = recipient_screen_name\n\n  recipient_screen_name = property(GetRecipientScreenName, SetRecipientScreenName,\n                doc='The unique recipient screen name of this direct message.')\n\n  def GetText(self):\n    '''Get the text of this direct message.\n\n    Returns:\n      The text of this direct message.\n    '''\n    return self._text\n\n  def SetText(self, text):\n    '''Set the text of this direct message.\n\n    Args:\n      text: The text of this direct message\n    '''\n    self._text = text\n\n  text = property(GetText, SetText,\n                  doc='The text of this direct message')\n\n  def __ne__(self, other):\n    return not self.__eq__(other)\n\n  def __eq__(self, other):\n    try:\n      return other and \\\n          self.id == other.id and \\\n          self.created_at == other.created_at and \\\n          self.sender_id == other.sender_id and \\\n          self.sender_screen_name == other.sender_screen_name and \\\n          self.recipient_id == other.recipient_id and \\\n          self.recipient_screen_name == other.recipient_screen_name and \\\n          self.text == other.text\n    except AttributeError:\n      return False\n\n  def __str__(self):\n    '''A string representation of this twitter.DirectMessage instance.\n\n    The return value is the same as the JSON string representation.\n\n    Returns:\n      A string representation of this twitter.DirectMessage instance.\n    '''\n    return self.AsJsonString()\n\n  def AsJsonString(self):\n    '''A JSON string representation of this twitter.DirectMessage instance.\n\n    Returns:\n      A JSON string representation of this twitter.DirectMessage instance\n   '''\n    return simplejson.dumps(self.AsDict(), sort_keys=True)\n\n  def AsDict(self):\n    '''A dict representation of this twitter.DirectMessage instance.\n\n    The return value uses the same key names as the JSON representation.\n\n    Return:\n      A dict representing this twitter.DirectMessage instance\n    '''\n    data = {}\n    if self.id:\n      data['id'] = self.id\n    if self.created_at:\n      data['created_at'] = self.created_at\n    if self.sender_id:\n      data['sender_id'] = self.sender_id\n    if self.sender_screen_name:\n      data['sender_screen_name'] = self.sender_screen_name\n    if self.recipient_id:\n      data['recipient_id'] = self.recipient_id\n    if self.recipient_screen_name:\n      data['recipient_screen_name'] = self.recipient_screen_name\n    if self.text:\n      data['text'] = self.text\n    return data\n\n  @staticmethod\n  def NewFromJsonDict(data):\n    '''Create a new instance based on a JSON dict.\n\n    Args:\n      data: A JSON dict, as converted from the JSON in the twitter API\n    Returns:\n      A twitter.DirectMessage instance\n    '''\n    return DirectMessage(created_at=data.get('created_at', None),\n                         recipient_id=data.get('recipient_id', None),\n                         sender_id=data.get('sender_id', None),\n                         text=data.get('text', None),\n                         sender_screen_name=data.get('sender_screen_name', None),\n                         id=data.get('id', None),\n                         recipient_screen_name=data.get('recipient_screen_name', None))\n\nclass Api(object):\n  '''A python interface into the Twitter API\n\n  By default, the Api caches results for 1 minute.\n\n  Example usage:\n\n    To create an instance of the twitter.Api class, with no authentication:\n\n      >>> import twitter\n      >>> api = twitter.Api()\n\n    To fetch the most recently posted public twitter status messages:\n\n      >>> statuses = api.GetPublicTimeline()\n      >>> print [s.user.name for s in statuses]\n      [u'DeWitt', u'Kesuke Miyagi', u'ev', u'Buzz Andersen', u'Biz Stone'] #...\n\n    To fetch a single user's public status messages, where \"user\" is either\n    a Twitter \"short name\" or their user id.\n\n      >>> statuses = api.GetUserTimeline(user)\n      >>> print [s.text for s in statuses]\n\n    To use authentication, instantiate the twitter.Api class with a\n    username and password:\n\n      >>> api = twitter.Api(username='twitter user', password='twitter pass')\n\n    To fetch your friends (after being authenticated):\n\n      >>> users = api.GetFriends()\n      >>> print [u.name for u in users]\n\n    To post a twitter status message (after being authenticated):\n\n      >>> status = api.PostUpdate('I love python-twitter!')\n      >>> print status.text\n      I love python-twitter!\n\n    There are many other methods, including:\n\n      >>> api.PostUpdates(status)\n      >>> api.PostDirectMessage(user, text)\n      >>> api.GetUser(user)\n      >>> api.GetReplies()\n      >>> api.GetUserTimeline(user)\n      >>> api.GetStatus(id)\n      >>> api.DestroyStatus(id)\n      >>> api.GetFriendsTimeline(user)\n      >>> api.GetFriends(user)\n      >>> api.GetFollowers()\n      >>> api.GetFeatured()\n      >>> api.GetDirectMessages()\n      >>> api.PostDirectMessage(user, text)\n      >>> api.DestroyDirectMessage(id)\n      >>> api.DestroyFriendship(user)\n      >>> api.CreateFriendship(user)\n      >>> api.GetUserByEmail(email)\n  '''\n\n  DEFAULT_CACHE_TIMEOUT = 60 # cache for 1 minute\n\n  _API_REALM = 'Twitter API'\n\n  def __init__(self,\n               username=None,\n               password=None,\n               input_encoding=None,\n               request_headers=None):\n    '''Instantiate a new twitter.Api object.\n\n    Args:\n      username: The username of the twitter account.  [optional]\n      password: The password for the twitter account. [optional]\n      input_encoding: The encoding used to encode input strings. [optional]\n      request_header: A dictionary of additional HTTP request headers. [optional]\n    '''\n    self._cache = _FileCache()\n    self._urllib = urllib2\n    self._cache_timeout = Api.DEFAULT_CACHE_TIMEOUT\n    self._InitializeRequestHeaders(request_headers)\n    self._InitializeUserAgent()\n    self._InitializeDefaultParameters()\n    self._input_encoding = input_encoding\n    self.SetCredentials(username, password)\n\n  def GetPublicTimeline(self, since_id=None):\n    '''Fetch the sequnce of public twitter.Status message for all users.\n\n    Args:\n      since_id:\n        Returns only public statuses with an ID greater than (that is,\n        more recent than) the specified ID. [Optional]\n\n    Returns:\n      An sequence of twitter.Status instances, one for each message\n    '''\n    parameters = {}\n    if since_id:\n      parameters['since_id'] = since_id\n    url = 'http://twitter.com/statuses/public_timeline.json'\n    json = self._FetchUrl(url,  parameters=parameters)\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return [Status.NewFromJsonDict(x) for x in data]\n\n  def GetFriendsTimeline(self,\n                         user=None,\n                         count=None,\n                         since=None, \n                         since_id=None):\n    '''Fetch the sequence of twitter.Status messages for a user's friends\n\n    The twitter.Api instance must be authenticated if the user is private.\n\n    Args:\n      user:\n        Specifies the ID or screen name of the user for whom to return\n        the friends_timeline.  If unspecified, the username and password\n        must be set in the twitter.Api instance.  [Optional]\n      count: \n        Specifies the number of statuses to retrieve. May not be\n        greater than 200. [Optional]\n      since:\n        Narrows the returned results to just those statuses created\n        after the specified HTTP-formatted date. [Optional]\n      since_id:\n        Returns only public statuses with an ID greater than (that is,\n        more recent than) the specified ID. [Optional]\n\n    Returns:\n      A sequence of twitter.Status instances, one for each message\n    '''\n    if user:\n      url = 'http://twitter.com/statuses/friends_timeline/%s.json' % user\n    elif not user and not self._username:\n      raise TwitterError(\"User must be specified if API is not authenticated.\")\n    else:\n      url = 'http://twitter.com/statuses/friends_timeline.json'\n    parameters = {}\n    if count is not None:\n      try:\n        if int(count) > 200:\n          raise TwitterError(\"'count' may not be greater than 200\")\n      except ValueError:\n        raise TwitterError(\"'count' must be an integer\")\n      parameters['count'] = count\n    if since:\n      parameters['since'] = since\n    if since_id:\n      parameters['since_id'] = since_id\n    json = self._FetchUrl(url, parameters=parameters)\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return [Status.NewFromJsonDict(x) for x in data]\n\n  def GetUserTimeline(self, user=None, count=None, since=None, since_id=None):\n    '''Fetch the sequence of public twitter.Status messages for a single user.\n\n    The twitter.Api instance must be authenticated if the user is private.\n\n    Args:\n      user:\n        either the username (short_name) or id of the user to retrieve.  If\n        not specified, then the current authenticated user is used. [optional]\n      count: the number of status messages to retrieve [optional]\n      since:\n        Narrows the returned results to just those statuses created\n        after the specified HTTP-formatted date. [optional]\n      since_id:\n        Returns only public statuses with an ID greater than (that is,\n        more recent than) the specified ID. [Optional]\n\n    Returns:\n      A sequence of twitter.Status instances, one for each message up to count\n    '''\n    try:\n      if count:\n        int(count)\n    except:\n      raise TwitterError(\"Count must be an integer\")\n    parameters = {}\n    if count:\n      parameters['count'] = count\n    if since:\n      parameters['since'] = since\n    if since_id:\n      parameters['since_id'] = since_id\n    if user:\n      url = 'http://twitter.com/statuses/user_timeline/%s.json' % user\n    elif not user and not self._username:\n      raise TwitterError(\"User must be specified if API is not authenticated.\")\n    else:\n      url = 'http://twitter.com/statuses/user_timeline.json'\n    json = self._FetchUrl(url, parameters=parameters)\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return [Status.NewFromJsonDict(x) for x in data]\n\n  def GetStatus(self, id):\n    '''Returns a single status message.\n\n    The twitter.Api instance must be authenticated if the status message is private.\n\n    Args:\n      id: The numerical ID of the status you're trying to retrieve.\n\n    Returns:\n      A twitter.Status instance representing that status message\n    '''\n    try:\n      if id:\n        long(id)\n    except:\n      raise TwitterError(\"id must be an long integer\")\n    url = 'http://twitter.com/statuses/show/%s.json' % id\n    json = self._FetchUrl(url)\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return Status.NewFromJsonDict(data)\n\n  def DestroyStatus(self, id):\n    '''Destroys the status specified by the required ID parameter.\n\n    The twitter.Api instance must be authenticated and thee\n    authenticating user must be the author of the specified status.\n\n    Args:\n      id: The numerical ID of the status you're trying to destroy.\n\n    Returns:\n      A twitter.Status instance representing the destroyed status message\n    '''\n    try:\n      if id:\n        long(id)\n    except:\n      raise TwitterError(\"id must be an integer\")\n    url = 'http://twitter.com/statuses/destroy/%s.json' % id\n    json = self._FetchUrl(url, post_data={})\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return Status.NewFromJsonDict(data)\n\n  def PostUpdate(self, status, in_reply_to_status_id=None):\n    '''Post a twitter status message from the authenticated user.\n\n    The twitter.Api instance must be authenticated.\n\n    Args:\n      status:\n        The message text to be posted.  Must be less than or equal to\n        140 characters.\n      in_reply_to_status_id:\n        The ID of an existing status that the status to be posted is\n        in reply to.  This implicitly sets the in_reply_to_user_id\n        attribute of the resulting status to the user ID of the\n        message being replied to.  Invalid/missing status IDs will be\n        ignored. [Optional]\n    Returns:\n      A twitter.Status instance representing the message posted.\n    '''\n    if not self._username:\n      raise TwitterError(\"The twitter.Api instance must be authenticated.\")\n\n    url = 'http://twitter.com/statuses/update.json'\n\n    if len(status) > CHARACTER_LIMIT:\n      raise TwitterError(\"Text must be less than or equal to %d characters. \"\n                         \"Consider using PostUpdates.\" % CHARACTER_LIMIT)\n\n    data = {'status': status}\n    if in_reply_to_status_id:\n      data['in_reply_to_status_id'] = in_reply_to_status_id\n    json = self._FetchUrl(url, post_data=data)\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return Status.NewFromJsonDict(data)\n\n  def PostUpdates(self, status, continuation=None, **kwargs):\n    '''Post one or more twitter status messages from the authenticated user.\n\n    Unlike api.PostUpdate, this method will post multiple status updates\n    if the message is longer than 140 characters.\n\n    The twitter.Api instance must be authenticated.\n\n    Args:\n      status:\n        The message text to be posted.  May be longer than 140 characters.\n      continuation:\n        The character string, if any, to be appended to all but the\n        last message.  Note that Twitter strips trailing '...' strings\n        from messages.  Consider using the unicode \\u2026 character\n        (horizontal ellipsis) instead. [Defaults to None]\n      **kwargs:\n        See api.PostUpdate for a list of accepted parameters.\n    Returns:\n      A of list twitter.Status instance representing the messages posted.\n    '''\n    results = list()\n    if continuation is None:\n      continuation = ''\n    line_length = CHARACTER_LIMIT - len(continuation)\n    lines = textwrap.wrap(status, line_length)\n    for line in lines[0:-1]:\n      results.append(self.PostUpdate(line + continuation, **kwargs))\n    results.append(self.PostUpdate(lines[-1], **kwargs))\n    return results\n\n  def GetReplies(self, since=None, since_id=None, page=None): \n    '''Get a sequence of status messages representing the 20 most recent\n    replies (status updates prefixed with @username) to the authenticating\n    user.\n\n    Args:\n      page: \n      since:\n        Narrows the returned results to just those statuses created\n        after the specified HTTP-formatted date. [optional]\n      since_id:\n        Returns only public statuses with an ID greater than (that is,\n        more recent than) the specified ID. [Optional]\n\n    Returns:\n      A sequence of twitter.Status instances, one for each reply to the user.\n    '''\n    url = 'http://twitter.com/statuses/replies.json'\n    if not self._username:\n      raise TwitterError(\"The twitter.Api instance must be authenticated.\")\n    parameters = {}\n    if since:\n      parameters['since'] = since\n    if since_id:\n      parameters['since_id'] = since_id\n    if page:\n      parameters['page'] = page\n    json = self._FetchUrl(url, parameters=parameters)\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return [Status.NewFromJsonDict(x) for x in data]\n\n  def GetFriends(self, user=None, page=None):\n    '''Fetch the sequence of twitter.User instances, one for each friend.\n\n    Args:\n      user: the username or id of the user whose friends you are fetching.  If\n      not specified, defaults to the authenticated user. [optional]\n\n    The twitter.Api instance must be authenticated.\n\n    Returns:\n      A sequence of twitter.User instances, one for each friend\n    '''\n    if not self._username:\n      raise TwitterError(\"twitter.Api instance must be authenticated\")\n    if user:\n      url = 'http://twitter.com/statuses/friends/%s.json' % user \n    else:\n      url = 'http://twitter.com/statuses/friends.json'\n    parameters = {}\n    if page:\n      parameters['page'] = page\n    json = self._FetchUrl(url, parameters=parameters)\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return [User.NewFromJsonDict(x) for x in data]\n\n  def GetFollowers(self, page=None):\n    '''Fetch the sequence of twitter.User instances, one for each follower\n\n    The twitter.Api instance must be authenticated.\n\n    Returns:\n      A sequence of twitter.User instances, one for each follower\n    '''\n    if not self._username:\n      raise TwitterError(\"twitter.Api instance must be authenticated\")\n    url = 'http://twitter.com/statuses/followers.json'\n    parameters = {}\n    if page:\n      parameters['page'] = page\n    json = self._FetchUrl(url, parameters=parameters)\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return [User.NewFromJsonDict(x) for x in data]\n\n  def GetFeatured(self):\n    '''Fetch the sequence of twitter.User instances featured on twitter.com\n\n    The twitter.Api instance must be authenticated.\n\n    Returns:\n      A sequence of twitter.User instances\n    '''\n    url = 'http://twitter.com/statuses/featured.json'\n    json = self._FetchUrl(url)\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return [User.NewFromJsonDict(x) for x in data]\n\n  def GetUser(self, user):\n    '''Returns a single user.\n\n    The twitter.Api instance must be authenticated.\n\n    Args:\n      user: The username or id of the user to retrieve.\n\n    Returns:\n      A twitter.User instance representing that user\n    '''\n    url = 'http://twitter.com/users/show/%s.json' % user\n    json = self._FetchUrl(url)\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return User.NewFromJsonDict(data)\n\n  def GetDirectMessages(self, since=None, since_id=None, page=None):\n    '''Returns a list of the direct messages sent to the authenticating user.\n\n    The twitter.Api instance must be authenticated.\n\n    Args:\n      since:\n        Narrows the returned results to just those statuses created\n        after the specified HTTP-formatted date. [optional]\n      since_id:\n        Returns only public statuses with an ID greater than (that is,\n        more recent than) the specified ID. [Optional]\n\n    Returns:\n      A sequence of twitter.DirectMessage instances\n    '''\n    url = 'http://twitter.com/direct_messages.json'\n    if not self._username:\n      raise TwitterError(\"The twitter.Api instance must be authenticated.\")\n    parameters = {}\n    if since:\n      parameters['since'] = since\n    if since_id:\n      parameters['since_id'] = since_id\n    if page:\n      parameters['page'] = page \n    json = self._FetchUrl(url, parameters=parameters)\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return [DirectMessage.NewFromJsonDict(x) for x in data]\n\n  def PostDirectMessage(self, user, text):\n    '''Post a twitter direct message from the authenticated user\n\n    The twitter.Api instance must be authenticated.\n\n    Args:\n      user: The ID or screen name of the recipient user.\n      text: The message text to be posted.  Must be less than 140 characters.\n\n    Returns:\n      A twitter.DirectMessage instance representing the message posted\n    '''\n    if not self._username:\n      raise TwitterError(\"The twitter.Api instance must be authenticated.\")\n    url = 'http://twitter.com/direct_messages/new.json'\n    data = {'text': text, 'user': user}\n    json = self._FetchUrl(url, post_data=data)\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return DirectMessage.NewFromJsonDict(data)\n\n  def DestroyDirectMessage(self, id):\n    '''Destroys the direct message specified in the required ID parameter.\n\n    The twitter.Api instance must be authenticated, and the\n    authenticating user must be the recipient of the specified direct\n    message.\n\n    Args:\n      id: The id of the direct message to be destroyed\n\n    Returns:\n      A twitter.DirectMessage instance representing the message destroyed\n    '''\n    url = 'http://twitter.com/direct_messages/destroy/%s.json' % id\n    json = self._FetchUrl(url, post_data={})\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return DirectMessage.NewFromJsonDict(data)\n\n  def CreateFriendship(self, user):\n    '''Befriends the user specified in the user parameter as the authenticating user.\n\n    The twitter.Api instance must be authenticated.\n\n    Args:\n      The ID or screen name of the user to befriend.\n    Returns:\n      A twitter.User instance representing the befriended user.\n    '''\n    url = 'http://twitter.com/friendships/create/%s.json' % user\n    json = self._FetchUrl(url, post_data={})\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return User.NewFromJsonDict(data)\n\n  def DestroyFriendship(self, user):\n    '''Discontinues friendship with the user specified in the user parameter.\n\n    The twitter.Api instance must be authenticated.\n\n    Args:\n      The ID or screen name of the user  with whom to discontinue friendship.\n    Returns:\n      A twitter.User instance representing the discontinued friend.\n    '''\n    url = 'http://twitter.com/friendships/destroy/%s.json' % user\n    json = self._FetchUrl(url, post_data={})\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return User.NewFromJsonDict(data)\n\n  def CreateFavorite(self, status):\n    '''Favorites the status specified in the status parameter as the authenticating user.\n    Returns the favorite status when successful.\n\n    The twitter.Api instance must be authenticated.\n\n    Args:\n      The twitter.Status instance to mark as a favorite.\n    Returns:\n      A twitter.Status instance representing the newly-marked favorite.\n    '''\n    url = 'http://twitter.com/favorites/create/%s.json' % status.id\n    json = self._FetchUrl(url, post_data={})\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return Status.NewFromJsonDict(data)\n\n  def DestroyFavorite(self, status):\n    '''Un-favorites the status specified in the ID parameter as the authenticating user.\n    Returns the un-favorited status in the requested format when successful.\n\n    The twitter.Api instance must be authenticated.\n\n    Args:\n      The twitter.Status to unmark as a favorite.\n    Returns:\n      A twitter.Status instance representing the newly-unmarked favorite.\n    '''\n    url = 'http://twitter.com/favorites/destroy/%s.json' % status.id\n    json = self._FetchUrl(url, post_data={})\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return Status.NewFromJsonDict(data)\n\n  def GetUserByEmail(self, email):\n    '''Returns a single user by email address.\n\n    Args:\n      email: The email of the user to retrieve.\n    Returns:\n      A twitter.User instance representing that user\n    '''\n    url = 'http://twitter.com/users/show.json?email=%s' % email\n    json = self._FetchUrl(url)\n    data = simplejson.loads(json)\n    self._CheckForTwitterError(data)\n    return User.NewFromJsonDict(data)\n\n  def SetCredentials(self, username, password):\n    '''Set the username and password for this instance\n\n    Args:\n      username: The twitter username.\n      password: The twitter password.\n    '''\n    self._username = username\n    self._password = password\n\n  def ClearCredentials(self):\n    '''Clear the username and password for this instance\n    '''\n    self._username = None\n    self._password = None\n\n  def SetCache(self, cache):\n    '''Override the default cache.  Set to None to prevent caching.\n\n    Args:\n      cache: an instance that supports the same API as the  twitter._FileCache\n    '''\n    self._cache = cache\n\n  def SetUrllib(self, urllib):\n    '''Override the default urllib implementation.\n\n    Args:\n      urllib: an instance that supports the same API as the urllib2 module\n    '''\n    self._urllib = urllib\n\n  def SetCacheTimeout(self, cache_timeout):\n    '''Override the default cache timeout.\n\n    Args:\n      cache_timeout: time, in seconds, that responses should be reused.\n    '''\n    self._cache_timeout = cache_timeout\n\n  def SetUserAgent(self, user_agent):\n    '''Override the default user agent\n\n    Args:\n      user_agent: a string that should be send to the server as the User-agent\n    '''\n    self._request_headers['User-Agent'] = user_agent\n\n  def SetXTwitterHeaders(self, client, url, version):\n    '''Set the X-Twitter HTTP headers that will be sent to the server.\n\n    Args:\n      client:\n         The client name as a string.  Will be sent to the server as\n         the 'X-Twitter-Client' header.\n      url:\n         The URL of the meta.xml as a string.  Will be sent to the server\n         as the 'X-Twitter-Client-URL' header.\n      version:\n         The client version as a string.  Will be sent to the server\n         as the 'X-Twitter-Client-Version' header.\n    '''\n    self._request_headers['X-Twitter-Client'] = client\n    self._request_headers['X-Twitter-Client-URL'] = url\n    self._request_headers['X-Twitter-Client-Version'] = version\n\n  def SetSource(self, source):\n    '''Suggest the \"from source\" value to be displayed on the Twitter web site.\n\n    The value of the 'source' parameter must be first recognized by\n    the Twitter server.  New source values are authorized on a case by\n    case basis by the Twitter development team.\n\n    Args:\n      source:\n        The source name as a string.  Will be sent to the server as\n        the 'source' parameter.\n    '''\n    self._default_params['source'] = source\n\n  def _BuildUrl(self, url, path_elements=None, extra_params=None):\n    # Break url into consituent parts\n    (scheme, netloc, path, params, query, fragment) = urlparse.urlparse(url)\n\n    # Add any additional path elements to the path\n    if path_elements:\n      # Filter out the path elements that have a value of None\n      p = [i for i in path_elements if i]\n      if not path.endswith('/'):\n        path += '/'\n      path += '/'.join(p)\n\n    # Add any additional query parameters to the query string\n    if extra_params and len(extra_params) > 0:\n      extra_query = self._EncodeParameters(extra_params)\n      # Add it to the existing query\n      if query:\n        query += '&' + extra_query\n      else:\n        query = extra_query\n\n    # Return the rebuilt URL\n    return urlparse.urlunparse((scheme, netloc, path, params, query, fragment))\n\n  def _InitializeRequestHeaders(self, request_headers):\n    if request_headers:\n      self._request_headers = request_headers\n    else:\n      self._request_headers = {}\n\n  def _InitializeUserAgent(self):\n    user_agent = 'Python-urllib/%s (python-twitter/%s)' % \\\n                 (self._urllib.__version__, __version__)\n    self.SetUserAgent(user_agent)\n\n  def _InitializeDefaultParameters(self):\n    self._default_params = {}\n\n  def _AddAuthorizationHeader(self, username, password):\n    if username and password:\n      basic_auth = base64.encodestring('%s:%s' % (username, password))[:-1]\n      self._request_headers['Authorization'] = 'Basic %s' % basic_auth\n\n  def _RemoveAuthorizationHeader(self):\n    if self._request_headers and 'Authorization' in self._request_headers:\n      del self._request_headers['Authorization']\n\n  def _GetOpener(self, url, username=None, password=None):\n    if username and password:\n      self._AddAuthorizationHeader(username, password)\n      handler = self._urllib.HTTPBasicAuthHandler()\n      (scheme, netloc, path, params, query, fragment) = urlparse.urlparse(url)\n      handler.add_password(Api._API_REALM, netloc, username, password)\n      opener = self._urllib.build_opener(handler)\n    else:\n      opener = self._urllib.build_opener()\n    opener.addheaders = self._request_headers.items()\n    return opener\n\n  def _Encode(self, s):\n    if self._input_encoding:\n      return unicode(s, self._input_encoding).encode('utf-8')\n    else:\n      return unicode(s).encode('utf-8')\n\n  def _EncodeParameters(self, parameters):\n    '''Return a string in key=value&key=value form\n\n    Values of None are not included in the output string.\n\n    Args:\n      parameters:\n        A dict of (key, value) tuples, where value is encoded as\n        specified by self._encoding\n    Returns:\n      A URL-encoded string in \"key=value&key=value\" form\n    '''\n    if parameters is None:\n      return None\n    else:\n      return urllib.urlencode(dict([(k, self._Encode(v)) for k, v in parameters.items() if v is not None]))\n\n  def _EncodePostData(self, post_data):\n    '''Return a string in key=value&key=value form\n\n    Values are assumed to be encoded in the format specified by self._encoding,\n    and are subsequently URL encoded.\n\n    Args:\n      post_data:\n        A dict of (key, value) tuples, where value is encoded as\n        specified by self._encoding\n    Returns:\n      A URL-encoded string in \"key=value&key=value\" form\n    '''\n    if post_data is None:\n      return None\n    else:\n      return urllib.urlencode(dict([(k, self._Encode(v)) for k, v in post_data.items()]))\n\n  def _CheckForTwitterError(self, data):\n    \"\"\"Raises a TwitterError if twitter returns an error message.\n\n    Args:\n      data: A python dict created from the Twitter json response\n    Raises:\n      TwitterError wrapping the twitter error message if one exists.\n    \"\"\"\n    # Twitter errors are relatively unlikely, so it is faster\n    # to check first, rather than try and catch the exception\n    if 'error' in data:\n      raise TwitterError(data['error'])\n\n  def _FetchUrl(self,\n                url,\n                post_data=None,\n                parameters=None,\n                no_cache=None):\n    '''Fetch a URL, optionally caching for a specified time.\n\n    Args:\n      url: The URL to retrieve\n      post_data: \n        A dict of (str, unicode) key/value pairs.  If set, POST will be used.\n      parameters:\n        A dict whose key/value pairs should encoded and added \n        to the query string. [OPTIONAL]\n      no_cache: If true, overrides the cache on the current request\n\n    Returns:\n      A string containing the body of the response.\n    '''\n    # Build the extra parameters dict\n    extra_params = {}\n    if self._default_params:\n      extra_params.update(self._default_params)\n    if parameters:\n      extra_params.update(parameters)\n\n    # Add key/value parameters to the query string of the url\n    url = self._BuildUrl(url, extra_params=extra_params)\n\n    # Get a url opener that can handle basic auth\n    opener = self._GetOpener(url, username=self._username, password=self._password)\n\n    encoded_post_data = self._EncodePostData(post_data)\n\n    # Open and return the URL immediately if we're not going to cache\n    if encoded_post_data or no_cache or not self._cache or not self._cache_timeout:\n      url_data = opener.open(url, encoded_post_data).read()\n      opener.close()\n    else:\n      # Unique keys are a combination of the url and the username\n      if self._username:\n        key = self._username + ':' + url\n      else:\n        key = url\n\n      # See if it has been cached before\n      last_cached = self._cache.GetCachedTime(key)\n\n      # If the cached version is outdated then fetch another and store it\n      if not last_cached or time.time() >= last_cached + self._cache_timeout:\n        url_data = opener.open(url, encoded_post_data).read()\n        opener.close()\n        self._cache.Set(key, url_data)\n      else:\n        url_data = self._cache.Get(key)\n\n    # Always return the latest version\n    return url_data\n\n\nclass _FileCacheError(Exception):\n  '''Base exception class for FileCache related errors'''\n\nclass _FileCache(object):\n\n  DEPTH = 3\n\n  def __init__(self,root_directory=None):\n    self._InitializeRootDirectory(root_directory)\n\n  def Get(self,key):\n    path = self._GetPath(key)\n    if os.path.exists(path):\n      return open(path).read()\n    else:\n      return None\n\n  def Set(self,key,data):\n    path = self._GetPath(key)\n    directory = os.path.dirname(path)\n    if not os.path.exists(directory):\n      os.makedirs(directory)\n    if not os.path.isdir(directory):\n      raise _FileCacheError('%s exists but is not a directory' % directory)\n    temp_fd, temp_path = tempfile.mkstemp()\n    temp_fp = os.fdopen(temp_fd, 'w')\n    temp_fp.write(data)\n    temp_fp.close()\n    if not path.startswith(self._root_directory):\n      raise _FileCacheError('%s does not appear to live under %s' %\n                            (path, self._root_directory))\n    if os.path.exists(path):\n      os.remove(path)\n    os.rename(temp_path, path)\n\n  def Remove(self,key):\n    path = self._GetPath(key)\n    if not path.startswith(self._root_directory):\n      raise _FileCacheError('%s does not appear to live under %s' %\n                            (path, self._root_directory ))\n    if os.path.exists(path):\n      os.remove(path)\n\n  def GetCachedTime(self,key):\n    path = self._GetPath(key)\n    if os.path.exists(path):\n      return os.path.getmtime(path)\n    else:\n      return None\n\n  def _GetUsername(self):\n    '''Attempt to find the username in a cross-platform fashion.'''\n    try:\n      return os.getenv('USER') or \\\n             os.getenv('LOGNAME') or \\\n             os.getenv('USERNAME') or \\\n             os.getlogin() or \\\n             'nobody'\n    except (IOError, OSError), e:\n      return 'nobody'\n\n  def _GetTmpCachePath(self):\n    username = self._GetUsername()\n    cache_directory = 'python.cache_' + username\n    return os.path.join(tempfile.gettempdir(), cache_directory)\n\n  def _InitializeRootDirectory(self, root_directory):\n    if not root_directory:\n      root_directory = self._GetTmpCachePath()\n    root_directory = os.path.abspath(root_directory)\n    if not os.path.exists(root_directory):\n      os.mkdir(root_directory)\n    if not os.path.isdir(root_directory):\n      raise _FileCacheError('%s exists but is not a directory' %\n                            root_directory)\n    self._root_directory = root_directory\n\n  def _GetPath(self,key):\n    try:\n        hashed_key = md5(key).hexdigest()\n    except TypeError:\n        hashed_key = md5.new(key).hexdigest()\n        \n    return os.path.join(self._root_directory,\n                        self._GetPrefix(hashed_key),\n                        hashed_key)\n\n  def _GetPrefix(self,hashed_key):\n    return os.path.sep.join(hashed_key[0:_FileCache.DEPTH])\n"
  },
  {
    "path": "socialauth/models.py",
    "content": "from django.db import models\nfrom django.contrib.auth.models import User\n\nclass AuthMeta(models.Model):\n    \"\"\"Metadata for Authentication\"\"\"\n    def __unicode__(self):\n        return '%s - %s' % (self.user, self.provider)\n    \n    user = models.ForeignKey(User)\n    provider = models.CharField(max_length=200)\n    is_email_filled = models.BooleanField(default=False)\n    is_profile_modified = models.BooleanField(default=False)\n\nclass OpenidProfile(models.Model):\n    \"\"\"A class associating an User to a Openid\"\"\"\n    openid_key = models.CharField(max_length=200, unique=True, db_index=True)\n    \n    user = models.ForeignKey(User, related_name='openid_profiles')\n    is_username_valid = models.BooleanField(default=False)\n    #Values which we get from openid.sreg\n    email = models.EmailField()\n    nickname = models.CharField(max_length=100)\n    \n    \n    def __unicode__(self):\n        return unicode(self.openid_key)\n    \n    def __repr__(self):\n        return unicode(self.openid_key)\n    \nclass LinkedInUserProfile(models.Model):\n    \"\"\"\n    For users who login via Linkedin.\n    \"\"\"\n    linkedin_uid = models.CharField(max_length=50,\n                                    unique=True,\n                                    db_index=True)\n\n    user = models.ForeignKey(User, related_name='linkedin_profiles')\n    headline = models.CharField(max_length=120, blank=True, null=True)\n    company = models.CharField(max_length=255, blank=True, null=True)\n    location = models.TextField(blank=True, null=True)\n    industry = models.CharField(max_length=255, blank=True, null=True)\n    profile_image_url = models.URLField(blank=True, null=True)\n    url = models.URLField(blank=True, null=True)\n    access_token = models.CharField(max_length=255,\n                                    blank=True,\n                                    null=True,\n                                    editable=False)\n\n    def __unicode__(self):\n        return \"%s's profile\" % self.user\n\nclass TwitterUserProfile(models.Model):\n    \"\"\"\n    For users who login via Twitter.\n    \"\"\"\n    screen_name = models.CharField(max_length=200,\n                                   unique=True,\n                                   db_index=True)\n    \n    user = models.ForeignKey(User, related_name='twitter_profiles')\n    access_token = models.CharField(max_length=255,\n                                    blank=True,\n                                    null=True,\n                                    editable=False)\n    profile_image_url = models.URLField(blank=True, null=True)\n    location = models.TextField(blank=True, null=True)\n    url = models.URLField(blank=True, null=True)\n    description = models.CharField(max_length=160, blank=True, null=True)\n\n    def __unicode__(self):\n        return \"%s's profile\" % self.user\n        \n\nclass FacebookUserProfile(models.Model):\n    \"\"\"\n    For users who login via Facebook.\n    \"\"\"\n    facebook_uid = models.CharField(max_length=20,\n                                    unique=True,\n                                    db_index=True)\n    \n    user = models.ForeignKey(User, related_name='facebook_profiles')\n    profile_image_url = models.URLField(blank=True, null=True)\n    profile_image_url_big = models.URLField(blank=True, null=True)\n    profile_image_url_small = models.URLField(blank=True, null=True)\n    location = models.TextField(blank=True, null=True)\n    url = models.URLField(blank=True, null=True)\n    about_me = models.CharField(max_length=160, blank=True, null=True)\n    \n    def __unicode__(self):\n        return \"%s's profile\" % self.user\n\nclass GithubUserProfile(models.Model):\n    user = models.ForeignKey(User)\n    access_token = models.CharField(max_length=100, blank=True, null=True, editable=False)\n\n    def __unicode__(self):\n        return \"%s's profile\" % self.user\n\nclass FoursquareUserProfile(models.Model):\n    user = models.ForeignKey(User)\n    access_token = models.CharField(max_length=255, blank=True, null=True, editable=False)\n\n    def __unicode__(self):\n        return \"%s's profile\" % self.user\n"
  },
  {
    "path": "socialauth/templates/openid/index.html",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\"   \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\n<head>\n\t<title>JQuery Simple OpenID Selector Demo</title>\n\t\n\t<!-- Simple OpenID Selector -->\n\t<link rel=\"stylesheet\" href=\"{{ MEDIA_URL }}css/openid.css\" />\n\t<script type=\"text/javascript\" src=\"{{ MEDIA_URL }}js/jquery-1.2.6.min.js\"></script>\n\t<script type=\"text/javascript\" src=\"{{ MEDIA_URL }}js/openid-jquery.js\"></script>\n\t<script type=\"text/javascript\">\n\t\t$(document).ready(function() {\n\t\t    openid.init('openid_identifier');\n\t\t});\n\t</script>\n\t<!-- /Simple OpenID Selector -->\n\t\n\t<style type=\"text/css\">\n\t\t/* Basic page formatting. */\n\t\tbody {\n\t\t\tfont-family:\"Helvetica Neue\", Helvetica, Arial, sans-serif;\n\t\t}\n\t</style>\n</head>\n\n<body>\n\n<h2>JQuery Simple OpenID Selector Demo</h2>\n<p>This is a simple example to show how you can include the Javascript into your page.</p>\n<br/>\n\n<!-- Simple OpenID Selector -->\n<form action=\"{% url socialauth_openid_login %}\" method=\"get\" id=\"openid_form\">\n\t<input type=\"hidden\" name=\"action\" value=\"verify\" />\n\n\t<fieldset>\n    \t\t<legend>Sign-in or Create New Account</legend>\n    \t\t\n    \t\t<div id=\"openid_choice\">\n\t    \t\t<p>Please click your account provider:</p>\n\t    \t\t<div id=\"openid_btns\"></div>\n\t\t\t</div>\n\t\t\t\n\t\t\t<div id=\"openid_input_area\">\n\t\t\t\t<input id=\"openid_identifier\" name=\"openid_identifier\" type=\"text\" value=\"http://\" />\n\t\t\t\t<input id=\"openid_submit\" type=\"submit\" value=\"Sign-In\"/>\n\t\t\t</div>\n\t\t\t<noscript>\n\t\t\t<p>OpenID is service that allows you to log-on to many different websites using a single indentity.\n\t\t\tFind out <a href=\"http://openid.net/what/\">more about OpenID</a> and <a href=\"http://openid.net/get/\">how to get an OpenID enabled account</a>.</p>\n\t\t\t</noscript>\n\t</fieldset>\n</form>\n<!-- /Simple OpenID Selector -->\n\n</body>\n</html>\n"
  },
  {
    "path": "socialauth/templates/socialauth/base.html",
    "content": "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n{% block html_declare %}\n<html lang=\"en\">\n{% endblock %}\n\n<head>\n    <title>{% if user.is_authenticated %}Hello {{ user }}{% else %}Please login{% endif %}</title>\n    <link rel=\"stylesheet\" type=\"text/css\" media=\"screen\"  href=\"{{ MEDIA_URL }}css/socialauth.css\" />\n    {% block extra_head %}\n    {% endblock %}\n</head>\n\n<body>\n    <h1>social-auth</h1>\n\t\t{% if FACEBOOK_APP_ID %}\n\t\t  <div id=\"fb-root\"></div>\n\t\t  <script>\n\t\t  window.fbAsyncInit = function() {\n\t\t\tFB.init({appId: '{{ FACEBOOK_APP_ID }}', status: true, cookie: true, xfbml: true});\n\t\t\tFB.Event.subscribe('auth.sessionChange', function(response) {\n\t\t\t  if (response.session) {\n\t\t\t\t  window.location = '{% url socialauth_facebook_login_done %}';\n\t\t\t  } else {\n\t\t\t\t  //window.location = '{% url socialauth_social_logout %}';\n\t\t\t  }\n\t\t\t});\n\t\t  };\n\t\t  (function() {\n\t\t\tvar e = document.createElement('script');\n\t\t\te.type = 'text/javascript';\n\t\t\te.src = document.location.protocol +\n\t\t\t  '//connect.facebook.net/en_US/all.js';\n\t\t\te.async = true;\n\t\t\tdocument.getElementById('fb-root').appendChild(e);\n\t\t  }());\n\t\t  </script>    \n\t\t{% endif %}    \n    {% block extra_body %}\n    {% endblock %}\n    \n    {% block main_content %}\n    {% endblock %}\n    \n    {% block content %}\n    {% endblock %}\n    <!-- Insert your content here -->\n</body>\n</html>\n"
  },
  {
    "path": "socialauth/templates/socialauth/editprofile.html",
    "content": "{% extends 'socialauth/socialauth_base.html' %}\n\n\n\n\n{% block content %}\n\n<form action=\".\" method=\"post\">\n    <table>\n    {{ edit_form }}\n    </table>\n    <input type=\"submit\" name=\"edit profile\" value=\"edit profile\" />\n</form>\n\n\n{% endblock %}\n"
  },
  {
    "path": "socialauth/templates/socialauth/login_page.html",
    "content": "{% extends 'socialauth/base.html' %}\n\n{% block html_declare %}\n<html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:fb=\"http://www.facebook.com/2008/fbml\">\n{% endblock %}\n\n{% block extra_head %}\n  <!-- Simple OpenID Selector -->\n  <link rel=\"stylesheet\" href=\"{{ MEDIA_URL }}css/openid.css\" />\n  <!--<script src=\"http://static.ak.connect.facebook.com/js/api_lib/v0.4/FeatureLoader.js.php\" type=\"text/javascript\"></script>-->\n  <script type=\"text/javascript\" src=\"{{ MEDIA_URL }}js/jquery-1.2.6.min.js\"></script>\n  <script type=\"text/javascript\" src=\"{{ MEDIA_URL }}js/openid-jquery.js\"></script>\n  <script type=\"text/javascript\">\n\t$(document).ready(function() {\n\t  openid.init('openid_identifier');\n\t});\n\t//function facebook_onlogin(){\n    //  window.location = \"{% url socialauth_facebook_login_done %}\"\n\t//}\n  </script>\n  <!-- /Simple OpenID Selector -->\n{% endblock %}\n\n{% block extra_body %}\n{{ block.super }}\n\n{% endblock %}\n\n{% block main_content %}\n{% if user.is_authenticated %}\n  <p>You are already logged in. <a href=\"{% url socialauth_social_logout %}\">Logout</a>?</p>\n{% else %}\n<div id=\"login\">\n\n<form action=\"{% url socialauth_openid_login %}\" method=\"get\" id=\"openid_form\">\n  <input type=\"hidden\" name=\"action\" value=\"verify\" />\n  \n  <fieldset>\n\t<legend>Sign-in or Create New Account via these openid providers</legend>\n\t\n\t<div id=\"openid_choice\">\n\t  <p>Please click your account provider:</p>\n\t\n\t  <div id=\"openid_btns\">\n\t    {% if FACEBOOK_APP_ID %}\n\t\t  <div id=\"facebook\">\n\t\t\t<p><fb:login-button perms=\"{{ login_button_perms }}\"></fb:login-button></p>\n\t\t  </div>\t  \n\t\t{% endif %}\n\t\t\n\t\t<div id=\"linkedin\">\n\t\t  <a href=\"{% url socialauth_linkedin_login %}?next={{ next }}\" id=\"linkedin_login_link\" class=\"openid_large_btn linkedin\"></a>\n\t\t</div>\n\t  \n\t\t<div id=\"twitter\">\n\t\t  <a href=\"{% url socialauth_twitter_login %}?next={{ next }}\" id=\"twitter_login_link\" class=\"openid_large_btn twitter\"></a>\n\t\t</div>\n\t  \n\t\t<!--<div id=\"yahoo\">\n\t\t  <a href=\"{% url socialauth_yahoo_login %}\" id=\"yahoo_login_link\" class=\"openid_large_btn yahoo\"></a>\n\t\t</div>-->\n\t  </div>\n\n      <input type=\"hidden\" name=\"openid_next\" value=\"{{ next }}\">\n\t\n\t  <div id=\"openid_input_area\">\n\t\t<input id=\"openid_identifier\" name=\"openid_identifier\" type=\"text\" value=\"http://\" />\n\t\t<input id=\"openid_submit\" type=\"submit\" value=\"Sign-In\"/>\n\t  </div>\n\t</div>\n\t\n\t<noscript>\n\t  <p>\n\t\tOpenID is service that allows you to log-on to many different websites using a single indentity. Find out \n\t\t<a href=\"http://openid.net/what/\">more about OpenID</a> and \n\t\t<a href=\"http://openid.net/get/\">how to get an OpenID enabled account</a>.\n\t  </p>\n\t</noscript>\n\t\n  </fieldset>\n  \n</form>\n\n\n\n    \n    \n    <br />\n    <br />\n    <br />\n    \n</div>\n{% endif %}\n{% endblock %}\n"
  },
  {
    "path": "socialauth/templates/socialauth/signin_complete.html",
    "content": "{% extends 'socialauth/base.html' %}\n\n{% block main_content %}\n\nYou have signed in.<br/>\n<a onclick=\"FB.logout(); window.location='{% url socialauth_social_logout %}';\" href=\"#\">Logout</a>\n\n{% endblock %}\n"
  },
  {
    "path": "socialauth/templates/socialauth/socialauth_base.html",
    "content": "{% extends \"socialauth/base.html\" %}\n{% block head %}\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01//EN\">\n{% block html_declare %}\n<html lang=\"en\">\n{% endblock %}\n{% endblock %}\n\n{% block content %}\n<head>\n    <title>{% if user.is_authenticated %}Hello {{ user }}{% else %}Please login{% endif %}</title>\n    {% block extra_head %}\n    {% endblock %}\n</head>\n<body>\n    {% block extra_body %}\n    {% endblock %}\n    \n    {% block main_content %}\n    {% endblock %}\n    <!-- Insert your content here -->\n</body>\n</html>\n{% endblock %}\n"
  },
  {
    "path": "socialauth/templates/socialauth/xd_receiver.htm",
    "content": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\"> <html xmlns=\"http://www.w3.org/1999/xhtml\" > <body> <script src=\"http://static.ak.connect.facebook.com/js/api_lib/v0.4/XdCommReceiver.js\" type=\"text/javascript\"></script> </body> </html>"
  },
  {
    "path": "socialauth/templatetags/__init__.py",
    "content": ""
  },
  {
    "path": "socialauth/templatetags/socialauth_tags.py",
    "content": "from django import  template\n\nregister = template.Library()\n\n@register.simple_tag\ndef get_calculated_username(user):\n    if hasattr(user, 'openidprofile_set') and user.openidprofile_set.filter().count():\n        if user.openidprofile_set.filter(is_username_valid = True).count():\n            return user.openidprofile_set.filter(is_username_valid = True)[0].user.username\n        else:\n            from django.core.urlresolvers import  reverse\n            editprof_url = reverse('socialauth_editprofile')\n            return u'Anonymous User. <a href=\"%s\">Add name</a>'%editprof_url\n    else:\n        return user.username\n"
  },
  {
    "path": "socialauth/test_data.py.example",
    "content": "test_base_url = \"http://nothing.uswaretech.net:8000/\"\ntwitter_username = \"socialauthtest2\"\ntwitter_password = \"\"\nmyopenid_url = \"http://socialauthtest2.myopenid.com/\"\nmyopenid_password = \"\""
  },
  {
    "path": "socialauth/tests.py",
    "content": "from selenium import selenium\nimport unittest\nfrom django.contrib.auth.models import User\n\nfrom test_data import *\n\nclass TwitterTester(unittest.TestCase):\n    def setUp(self):\n        self.verificationErrors = []\n        self.selenium = selenium(\"localhost\", 4444, \"*chrome\", test_base_url)\n        self.selenium.start()\n    \n    def testTwitter(self):\n        sel = self.selenium\n        #Test that a user is created after \n        #    logging in via Twitter for the first time.\n        initial_user_count = User.objects.count()\n        sel.open(\"/accounts/login/\")\n        sel.click(\"link=Login via twitter\")\n        sel.wait_for_page_to_load(\"30000\")\n        try:\n            sel.click(\"link=Sign out\")\n            sel.wait_for_page_to_load(\"30000\")\n        except:\n            pass\n        sel.type(\"username_or_email\", twitter_username)\n        sel.type(\"session[password]\", twitter_password)\n        sel.click(\"allow\")\n        sel.wait_for_page_to_load(\"30000\")\n        sel.open(\"/accounts/login/\")\n        sel.open(\"/accounts/edit/profile/\")\n        self.assertEqual(initial_user_count + 1, User.objects.count())\n        \n    \n    def tearDown(self):\n        self.selenium.stop()\n        self.assertEqual([], self.verificationErrors)\n        \n\nclass OpenIdTester(unittest.TestCase):\n    def setUp(self):\n        self.verificationErrors = []\n        self.selenium = selenium(\"localhost\", 4444, \"*chrome\", test_base_url)\n        self.selenium.start()\n    \n    def testOpenId(self):\n        initial_user_count = User.objects.count()\n        sel = self.selenium\n        sel.open(\"/accounts/login/\")\n        sel.click(\"openid_login_link\")\n        sel.wait_for_page_to_load(\"30000\")\n        sel.type(\"openid_url\", myopenid_url)\n        sel.click(\"//input[@value='Sign in']\")\n        sel.wait_for_page_to_load(\"30000\")\n        try:\n            sel.type(\"password\", myopenid_password)\n            sel.click(\"signin_button\")\n            sel.wait_for_page_to_load(\"30000\")\n        except:\n            sel.click(\"continue-button\")\n        sel.wait_for_page_to_load(\"30000\")\n        sel.open(\"/accounts/login/\")\n        self.assertEqual(initial_user_count + 1, User.objects.count())\n    \n    def tearDown(self):\n        self.selenium.stop()\n        self.assertEqual([], self.verificationErrors)\n\nif __name__ == \"__main__\":\n    unittest.main()\n\n\n\nif __name__ == \"__main__\":\n    unittest.main()\n"
  },
  {
    "path": "socialauth/urls.py",
    "content": "from django.conf.urls.defaults import *\nfrom openid_consumer.views import complete, signout\nfrom django.views.generic.base import TemplateView\n\n#Login Views\nurlpatterns = patterns('socialauth.views',\n    url(r'^facebook_login/xd_receiver.htm$', TemplateView.as_view(template_name='socialauth/xd_receiver.htm'), name='socialauth_xd_receiver'),\n    url(r'^facebook_login/$', 'facebook_login', name='socialauth_facebook_login'),\n    url(r'^facebook_login/done/$', 'facebook_login_done', name='socialauth_facebook_login_done'),\n    url(r'^login/$', 'login_page', name='socialauth_login_page'),\n    url(r'^openid_login/$', 'openid_login_page', name='socialauth_openid_login_page'),\n    url(r'^twitter_login/$', 'twitter_login', name='socialauth_twitter_login'),\n    url(r'^twitter_login/done/$', 'twitter_login_done', name='socialauth_twitter_login_done'),\n    url(r'^linkedin_login/$', 'linkedin_login', name='socialauth_linkedin_login'),\n    url(r'^linkedin_login/done/$', 'linkedin_login_done', name='socialauth_linkedin_login_done'),\n    url(r'^yahoo_login/$', 'yahoo_login', name='socialauth_yahoo_login'),\n    url(r'^yahoo_login/complete/$', complete, name='socialauth_yahoo_complete'),\n    url(r'^gmail_login/$', 'gmail_login', name='socialauth_google_login'),\n    url(r'^gmail_login/complete/$', complete, name='socialauth_google_complete'),\n    url(r'^openid/$', 'openid_login', name='socialauth_openid_login'),\n    url(r'^openid/complete/$', complete, name='socialauth_openid_complete'),\n    url(r'^openid/signout/$', signout, name='openid_signout'),\n    url(r'^openid/done/$', 'openid_done', name='openid_openid_done'),\n    url(r'^github_login/$', 'github_login', name='github_login'),\n    url(r'github_login/done/$', 'github_login_done', name='github_login_done'),\n    url(r'^foursquare_login/$', 'foursquare_login', name='foursquare_login'),\n    url(r'^foursquare_login/done/$', 'foursquare_login_done', name='foursquare_login_done'),\n)\n\n#Other views.\nurlpatterns += patterns('socialauth.views',\n    url(r'^$', 'login_page', name='socialauth_index'),\n    url(r'^done/$', 'signin_complete', name='socialauth_signin_complete'),\n    url(r'^edit/profile/$', 'editprofile',  name='socialauth_editprofile'),\n    url(r'^logout/$', 'social_logout',  name='socialauth_social_logout'),\n)\n\n"
  },
  {
    "path": "socialauth/views.py",
    "content": "import logging\nimport urllib\nfrom oauth import oauth\n\nfrom django.shortcuts import render_to_response\nfrom django.template import RequestContext\nfrom django.contrib.auth import authenticate, login\nfrom django.http import HttpResponseRedirect\nfrom django.core.urlresolvers import reverse\nfrom django.conf import settings\nfrom django.contrib.auth.decorators import login_required\nfrom django.contrib.auth.views import logout\n\nfrom socialauth.models import AuthMeta\nfrom socialauth.forms import EditProfileForm\n\nfrom openid_consumer.views import begin\nfrom socialauth.lib import oauthtwitter2 as oauthtwitter\n\nfrom socialauth.lib.linkedin import *\nfrom socialauth.lib.github import GithubClient\nfrom socialauth.lib import foursquare\n\nLINKEDIN_CONSUMER_KEY = getattr(settings, 'LINKEDIN_CONSUMER_KEY', '')\nLINKEDIN_CONSUMER_SECRET = getattr(settings, 'LINKEDIN_CONSUMER_SECRET', '')\n\nADD_LOGIN_REDIRECT_URL = getattr(settings, 'ADD_LOGIN_REDIRECT_URL', '')\nLOGIN_REDIRECT_URL = getattr(settings, 'LOGIN_REDIRECT_URL', '')\nLOGIN_URL = getattr(settings, 'LOGIN_URL', '')\n\nTWITTER_CONSUMER_KEY = getattr(settings, 'TWITTER_CONSUMER_KEY', '')\nTWITTER_CONSUMER_SECRET = getattr(settings, 'TWITTER_CONSUMER_SECRET', '')\n\nFACEBOOK_APP_ID = getattr(settings, 'FACEBOOK_APP_ID', '')\nFACEBOOK_API_KEY = getattr(settings, 'FACEBOOK_API_KEY', '')\nFACEBOOK_SECRET_KEY = getattr(settings, 'FACEBOOK_SECRET_KEY', '')\n\n\n\ndef del_dict_key(src_dict, key):\n    if key in src_dict:\n        del src_dict[key]\n\ndef login_page(request):\n    return render_to_response('socialauth/login_page.html', \n                              {'next': request.GET.get('next', LOGIN_REDIRECT_URL)}, \n                              context_instance=RequestContext(request))\n\ndef linkedin_login(request):\n    linkedin = LinkedIn(LINKEDIN_CONSUMER_KEY, LINKEDIN_CONSUMER_SECRET)\n    request_token = linkedin.getRequestToken(callback=request.build_absolute_uri(reverse('socialauth_linkedin_login_done')))\n    request.session['linkedin_request_token'] = request_token\n    signin_url = linkedin.getAuthorizeUrl(request_token)\n    return HttpResponseRedirect(signin_url)\n\ndef linkedin_login_done(request):\n    request_token = request.session.get('linkedin_request_token', None)\n\n    # If there is no request_token for session\n    # Means we didn't redirect user to linkedin\n    if not request_token:\n        # Send them to the login page\n        return HttpResponseRedirect(reverse(\"socialauth_login_page\"))\n    try:\n        linkedin = LinkedIn(settings.LINKEDIN_CONSUMER_KEY, settings.LINKEDIN_CONSUMER_SECRET)\n        verifier = request.GET.get('oauth_verifier', None)\n        access_token = linkedin.getAccessToken(request_token,verifier)\n\n        request.session['access_token'] = access_token\n        user = authenticate(linkedin_access_token=access_token)\n    except:\n        user = None\n\n    # if user is authenticated then login user\n    if user:\n        login(request, user)\n    else:\n        # We were not able to authenticate user\n        # Redirect to login page\n        del_dict_key(request.session, 'access_token')\n        del_dict_key(request.session, 'request_token')\n        return HttpResponseRedirect(reverse('socialauth_login_page'))\n\n    # authentication was successful, user is now logged in\n    return HttpResponseRedirect(LOGIN_REDIRECT_URL)\n\ndef twitter_login(request):\n    next = request.GET.get('next', None)\n    if next:\n        request.session['twitter_login_next'] = next\n    \n    twitter = oauthtwitter.TwitterOAuthClient(settings.TWITTER_CONSUMER_KEY, settings.TWITTER_CONSUMER_SECRET)\n    request_token = twitter.fetch_request_token(callback=request.build_absolute_uri(reverse('socialauth_twitter_login_done')))\n    request.session['request_token'] = request_token.to_string()\n    signin_url = twitter.authorize_token_url(request_token)\n    return HttpResponseRedirect(signin_url)\n\ndef twitter_login_done(request):\n    request_token = request.session.get('request_token', None)\n    verifier = request.GET.get('oauth_verifier', None)\n    denied = request.GET.get('denied', None)\n    \n    # If we've been denied, put them back to the signin page\n    # They probably meant to sign in with facebook >:D\n    if denied:\n        return HttpResponseRedirect(reverse(\"socialauth_login_page\"))\n\n    # If there is no request_token for session,\n    # Means we didn't redirect user to twitter\n    if not request_token:\n        # Redirect the user to the login page,\n        return HttpResponseRedirect(reverse(\"socialauth_login_page\"))\n\n    token = oauth.OAuthToken.from_string(request_token)\n\n    # If the token from session and token from twitter does not match\n    # means something bad happened to tokens\n    if token.key != request.GET.get('oauth_token', 'no-token'):\n        del_dict_key(request.session, 'request_token')\n        # Redirect the user to the login page\n        return HttpResponseRedirect(reverse(\"socialauth_login_page\"))\n\n    try:\n        twitter = oauthtwitter.TwitterOAuthClient(settings.TWITTER_CONSUMER_KEY, settings.TWITTER_CONSUMER_SECRET)\n        access_token = twitter.fetch_access_token(token, verifier)\n\n        request.session['access_token'] = access_token.to_string()\n        user = authenticate(twitter_access_token=access_token)\n    except:\n        user = None\n  \n    # if user is authenticated then login user\n    if user:\n        login(request, user)\n    else:\n        # We were not able to authenticate user\n        # Redirect to login page\n        del_dict_key(request.session, 'access_token')\n        del_dict_key(request.session, 'request_token')\n        return HttpResponseRedirect(reverse('socialauth_login_page'))\n\n    # authentication was successful, use is now logged in\n    next = request.session.get('twitter_login_next', None)\n    if next:\n        del_dict_key(request.session, 'twitter_login_next')\n        return HttpResponseRedirect(next)\n    else:\n        return HttpResponseRedirect(LOGIN_REDIRECT_URL)\n\ndef openid_login(request):\n    if 'openid_next' in request.GET:\n        request.session['openid_next'] = request.GET.get('openid_next')\n    if 'openid_identifier' in request.GET:\n        user_url = request.GET.get('openid_identifier')\n        request.session['openid_provider'] = user_url\n        return begin(request, user_url=user_url)\n    else:\n        request.session['openid_provider'] = 'Openid'\n        return begin(request)\n\ndef gmail_login(request):\n    request.session['openid_provider'] = 'Google'\n    return begin(request, user_url='https://www.google.com/accounts/o8/id')\n\ndef gmail_login_complete(request):\n    pass\n\n\ndef yahoo_login(request):\n    request.session['openid_provider'] = 'Yahoo'\n    return begin(request, user_url='https://me.yahoo.com/')\n\ndef openid_done(request, provider=None):\n    \"\"\"\n    When the request reaches here, the user has completed the Openid\n    authentication flow. He has authorised us to login via Openid, so\n    request.openid is populated.\n    After coming here, we want to check if we are seeing this openid first time.\n    If we are, we will create a new Django user for this Openid, else login the\n    existing openid.\n    \"\"\"\n    \n    if not provider:\n        provider = request.session.get('openid_provider', '')\n    if hasattr(request,'openid') and request.openid:\n        #check for already existing associations\n        openid_key = str(request.openid)\n    \n        #authenticate and login\n        try:\n            user = authenticate(openid_key=openid_key, request=request, provider=provider)\n        except:\n            user = None\n        \n        if user:\n            login(request, user)\n            if 'openid_next' in request.session :\n                openid_next = request.session.get('openid_next')\n                if len(openid_next.strip()) >  0 :\n                    return HttpResponseRedirect(openid_next)\n            return HttpResponseRedirect(LOGIN_REDIRECT_URL)\n            # redirect_url = reverse('socialauth_editprofile')\n            # return HttpResponseRedirect(redirect_url)\n        else:\n            return HttpResponseRedirect(LOGIN_URL)\n    else:\n        return HttpResponseRedirect(LOGIN_URL)\n\ndef facebook_login(request):\n    \"\"\"\n    Facebook login page\n    \"\"\"\n    next = request.GET.get('next', None)\n    if next:\n        request.session['facebook_login_next'] = next\n    \n    if request.REQUEST.get(\"device\"):\n        device = request.REQUEST.get(\"device\")\n    else:\n        device = \"user-agent\"\n\n    params = {}\n    params[\"client_id\"] = FACEBOOK_APP_ID\n    params[\"redirect_uri\"] = request.build_absolute_uri(reverse(\"socialauth_facebook_login_done\"))\n\n    url = \"https://graph.facebook.com/oauth/authorize?\"+urllib.urlencode(params)\n\n    return HttpResponseRedirect(url)\n\ndef facebook_login_done(request):\n    user = authenticate(request=request)\n\n    if not user:\n        request.COOKIES.pop(FACEBOOK_API_KEY + '_session_key', None)\n        request.COOKIES.pop(FACEBOOK_API_KEY + '_user', None)\n\n        # TODO: maybe the project has its own login page?\n        logging.debug(\"SOCIALAUTH: Couldn't authenticate user with Django, redirecting to Login page\")\n        return HttpResponseRedirect(reverse('socialauth_login_page'))\n\n    login(request, user)\n    \n    logging.debug(\"SOCIALAUTH: Successfully logged in with Facebook!\")\n    \n    next = request.GET.get('next')\n    if not next:\n        next = request.session.get('facebook_login_next')\n        del_dict_key(request.session, 'facebook_login_next')\n    \n    if next:\n        return HttpResponseRedirect(next)\n    else:\n        return HttpResponseRedirect(LOGIN_REDIRECT_URL)\n\ndef openid_login_page(request):\n    return render_to_response('openid/index.html', context_instance=RequestContext(request))\n\n@login_required\ndef signin_complete(request):\n    return render_to_response('socialauth/signin_complete.html', context_instance=RequestContext(request))\n\n@login_required\ndef editprofile(request):\n    if request.method == 'POST':\n        edit_form = EditProfileForm(user=request.user, data=request.POST)\n        if edit_form.is_valid():\n            user = edit_form.save()\n            try:\n                user.authmeta.is_profile_modified = True\n                user.authmeta.save()\n            except AuthMeta.DoesNotExist:\n                pass\n            if hasattr(user,'openidprofile_set') and user.openidprofile_set.count():\n                openid_profile = user.openidprofile_set.all()[0]\n                openid_profile.is_valid_username = True\n                openid_profile.save()\n            try:\n                #If there is a profile. notify that we have set the username\n                profile = user.get_profile()\n                profile.is_valid_username = True\n                profile.save()\n            except:\n                pass\n            request.user.message_set.create(message='Your profile has been updated.')\n            return HttpResponseRedirect('.')\n    if request.method == 'GET':\n        edit_form = EditProfileForm(user=request.user)\n\n    payload = {'edit_form':edit_form}\n    return render_to_response('socialauth/editprofile.html', payload, RequestContext(request))\n\ndef social_logout(request):\n    # Todo\n    # still need to handle FB cookies, session etc.\n\n    # let the openid_consumer app handle openid-related cleanup\n    from openid_consumer.views import signout as oid_signout\n    oid_signout(request)\n\n    # normal logout\n    logout_response = logout(request)\n\n    if 'next' in request.GET:\n        response = HttpResponseRedirect(request.GET.get('next'))\n    elif getattr(settings, 'LOGOUT_REDIRECT_URL', None):\n        response = HttpResponseRedirect(settings.LOGOUT_REDIRECT_URL)\n    else:\n        response = logout_response\n\n    # Delete the facebook cookie\n    response.delete_cookie(\"fbs_\" + FACEBOOK_APP_ID)\n\n    return response\n\ndef github_login(request):\n    github_client = GithubClient()\n    authorize_url = github_client.get_authorize_url()  \n    return HttpResponseRedirect(authorize_url)\n\ndef github_login_done(request):\n    try:\n        code = request.GET['code']\n    except:\n        \"\"\"Either github did not respond properly\n        or someone is playing with this url\"\"\"\n        return HttpResponseRedirect(LOGIN_URL)\n    github_client = GithubClient()\n    access_token = github_client.get_access_token(code)\n    try:\n        user = authenticate(github_access_token=access_token)\n    except:\n        user = None\n    if user:\n        login(request, user)\n        return HttpResponseRedirect(LOGIN_REDIRECT_URL)\n    return HttpResponseRedirect(LOGIN_URL) \n\ndef foursquare_login(request):\n    foursquare_client = foursquare.FourSquareClient()\n    return HttpResponseRedirect(foursquare_client.get_authentication_url())\n\ndef foursquare_login_done(request):\n    try:\n        code = request.GET.get('code')\n    except:\n        \"\"\"Some error ocurred.\n        Rediect to login page\"\"\"\n        return HttpResponseRedirect(LOGIN_URL)\n    request.session['foursquare_code'] = code\n    foursquare_client = foursquare.FourSquareClient()\n    access_token_response = foursquare_client.get_access_token(request.session['foursquare_code'])\n    import json\n    access_token = json.loads(access_token_response)['access_token'] \n    try:\n        user = authenticate(foursquare_access_token=access_token)\n    except:\n        user=None\n    if user:\n        login(request, user)\n        return HttpResponseRedirect(LOGIN_REDIRECT_URL)\n    return HttpResponseRedirect(LOGIN_URL) \n"
  }
]