commit f6d0d043b5701713cb5163e3e1766c38921f09bb Author: Shandem Date: Fri Jun 19 07:39:16 2009 +0000 DO NOT DOWNLOAD. DOWNLOAT LATEST STABLE FROM RELEASE TAB Created 4.1.0 branch [TFS Changeset #55082] diff --git a/IronPython License.Rtf b/IronPython License.Rtf new file mode 100644 index 0000000000..1b76756cbb --- /dev/null +++ b/IronPython License.Rtf @@ -0,0 +1,82 @@ +{\rtf1\ansi\ansicpg1252\uc1\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f36\fswiss\fcharset0\fprq2{\*\panose 020b0604030504040204}Tahoma;} +{\f39\froman\fcharset238\fprq2 Times New Roman CE;}{\f40\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f42\froman\fcharset161\fprq2 Times New Roman Greek;}{\f43\froman\fcharset162\fprq2 Times New Roman Tur;} +{\f44\froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f45\froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f46\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f47\froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\f399\fswiss\fcharset238\fprq2 Tahoma CE;}{\f400\fswiss\fcharset204\fprq2 Tahoma Cyr;}{\f402\fswiss\fcharset161\fprq2 Tahoma Greek;}{\f403\fswiss\fcharset162\fprq2 Tahoma Tur;}{\f404\fswiss\fcharset177\fprq2 Tahoma (Hebrew);} +{\f405\fswiss\fcharset178\fprq2 Tahoma (Arabic);}{\f406\fswiss\fcharset186\fprq2 Tahoma Baltic;}{\f407\fswiss\fcharset163\fprq2 Tahoma (Vietnamese);}{\f408\fswiss\fcharset222\fprq2 Tahoma (Thai);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255; +\red0\green255\blue255;\red0\green255\blue0;\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0; +\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}{\stylesheet{\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 Normal;}{\*\cs10 \additive +\ssemihidden Default Paragraph Font;}{\*\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\trcbpat1\trcfpat1\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv +\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs20\lang1024\langfe1024\cgrid\langnp1024\langfenp1024 \snext11 \ssemihidden Normal Table;}{\s15\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 +\f36\fs16\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \sbasedon0 \snext15 \ssemihidden \styrsid668380 Balloon Text;}}{\*\latentstyles\lsdstimax156\lsdlockeddef0}{\*\listtable{\list\listtemplateid130696116{\listlevel\levelnfc0\levelnfcn0\leveljc0 +\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'00.;}{\levelnumbers\'01;}\fi-360\li720\jclisttab\tx720\lin720 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0 +{\leveltext\'02\'01.;}{\levelnumbers\'01;}\fi-360\li1440\jclisttab\tx1440\lin1440 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'02.;}{\levelnumbers\'01;}\fi-360\li2160 +\jclisttab\tx2160\lin2160 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'03.;}{\levelnumbers\'01;}\fi-360\li2880\jclisttab\tx2880\lin2880 }{\listlevel\levelnfc0\levelnfcn0\leveljc0 +\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'04.;}{\levelnumbers\'01;}\fi-360\li3600\jclisttab\tx3600\lin3600 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0 +{\leveltext\'02\'05.;}{\levelnumbers\'01;}\fi-360\li4320\jclisttab\tx4320\lin4320 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'06.;}{\levelnumbers\'01;}\fi-360\li5040 +\jclisttab\tx5040\lin5040 }{\listlevel\levelnfc0\levelnfcn0\leveljc0\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'07.;}{\levelnumbers\'01;}\fi-360\li5760\jclisttab\tx5760\lin5760 }{\listlevel\levelnfc0\levelnfcn0\leveljc0 +\leveljcn0\levelfollow0\levelstartat1\levelspace0\levelindent0{\leveltext\'02\'08.;}{\levelnumbers\'01;}\fi-360\li6480\jclisttab\tx6480\lin6480 }{\listname ;}\listid723138990}}{\*\listoverridetable{\listoverride\listid723138990\listoverridecount0\ls1}} +{\*\pgptbl {\pgp\ipgp2\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp4\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}{\pgp\ipgp0\itap0\li0\ri0\sb0\sa0}}{\*\rsidtbl \rsid288726\rsid668380\rsid1077358\rsid1250157\rsid1778664 +\rsid2232581\rsid3018318\rsid3766585\rsid4417501\rsid4531485\rsid4807452\rsid5341002\rsid7018004\rsid7880391\rsid10749719\rsid12150908\rsid12939982\rsid13596669\rsid15149892\rsid15551579\rsid16128754\rsid16674677}{\*\generator Microsoft Word 11.0.6359;} +{\info{\title Shared Source License for Software included in Workspaces}{\author suev}{\operator Martin Maly}{\creatim\yr2005\mo3\dy22\hr10\min45}{\revtim\yr2005\mo3\dy22\hr15\min54}{\printim\yr2002\mo9\dy20\hr15\min39}{\version3}{\edmins1}{\nofpages1} +{\nofwords672}{\nofchars3837}{\*\company Microsoft}{\nofcharsws4501}{\vern24703}}\widowctrl\ftnbj\aenddoc\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\hyphcaps0\formshade\horzdoc\dgmargin\dghspace180\dgvspace180\dghorigin1701\dgvorigin1984 +\dghshow1\dgvshow1\jexpand\viewkind5\viewscale100\pgbrdrhead\pgbrdrfoot\splytwnine\ftnlytwnine\htmautsp\nolnhtadjtbl\useltbaln\alntblind\lytcalctblwd\lyttblrtgr\lnbrkrule\nobrkwrptbl\snaptogridincell\allowfieldendsel\wrppunct +\asianbrkrule\nojkernpunct\rsidroot15149892 \fet0\sectd \linex0\endnhere\sectlinegrid360\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3 +\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}} +{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain +\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\b\fs28\insrsid1250157\charrsid1250157 Shared Source License for }{\b\fs28\insrsid16674677 IronPython}{ +\b\fs28\insrsid1250157 +\par }{\b\fs28\insrsid5341002 +\par }{\b\insrsid5341002\charrsid5341002 This license governs use of the accompanying software}{\b\insrsid5341002 (\'93Software\'94)}{\b\insrsid5341002\charrsid5341002 , and your use of the }{\b\insrsid5341002 S}{\b\insrsid5341002\charrsid5341002 +oftware constitutes acceptance of this license. +\par }{\insrsid1250157\charrsid5341002 +\par }{\b\insrsid1250157\charrsid1250157 You }{\b\insrsid5341002 may}{\b\insrsid1250157\charrsid1250157 use }{\b\insrsid5341002 the}{\b\insrsid1250157\charrsid1250157 Software for any }{\b\insrsid1250157 commercial or }{\b\insrsid1250157\charrsid1250157 +noncommercial purpose, including distributing derivative}{\b\insrsid4417501 work}{\b\insrsid1250157\charrsid1250157 s}{\b\insrsid1250157 . +\par }{\insrsid1250157 +\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid1250157 {\insrsid1250157\charrsid1250157 In return, we simply require that you agree: +\par {\listtext\pard\plain\insrsid1250157\charrsid1250157 \hich\af0\dbch\af0\loch\f0 1.\tab}}\pard \ql \fi-360\li720\ri0\widctlpar\jclisttab\tx720\aspalpha\aspnum\faauto\ls1\adjustright\rin0\lin720\itap0\pararsid1250157 {\insrsid1250157\charrsid1250157 +Not to remove any copyright}{\insrsid5341002 or other}{\insrsid1250157\charrsid1250157 notices from the Software. +\par {\listtext\pard\plain\insrsid1250157\charrsid1250157 \hich\af0\dbch\af0\loch\f0 2.\tab}That if you distribute the Software in source code form you do so only under this }{\insrsid5341002 l}{\insrsid1250157\charrsid1250157 +icense (i.e. you must include a complete copy of this }{\insrsid5341002 l}{\insrsid1250157\charrsid1250157 icense with your distribution), and if you distribute the Software solely in object form you only do so under a license that complies with this }{ +\insrsid5341002 l}{\insrsid1250157\charrsid1250157 icense. +\par {\listtext\pard\plain\b\insrsid1250157\charrsid1250157 \hich\af0\dbch\af0\loch\f0 3.\tab}}{\b\insrsid1250157\charrsid1250157 +That the Software comes "as is", with no warranties. None whatsoever. This means no express, implied or statutory warranty, including without limitation, warranties of merchantability or fitness for a particular purpose or any warranty of }{ +\b\insrsid5341002 title or }{\b\insrsid1250157\charrsid1250157 non}{\b\insrsid5341002 -}{\b\insrsid1250157\charrsid1250157 infringement. Also, you must pass this disclaimer on whenever you distribute the Software}{\b\insrsid5341002 or derivative works}{ +\b\insrsid1250157\charrsid1250157 .}{\insrsid1250157\charrsid1250157 +\par {\listtext\pard\plain\b\insrsid1250157\charrsid1250157 \hich\af0\dbch\af0\loch\f0 4.\tab}}{\b\insrsid1250157\charrsid1250157 That neither Microsoft nor }{\b\insrsid1250157 any contributor to the Software}{\b\insrsid1250157\charrsid1250157 + will be liable for any of those types of damages known as}{\b\insrsid5341002 }{\b\insrsid1250157\charrsid1250157 indirect, special, consequential, or incidental related to the Software or this }{\b\insrsid5341002 l}{\b\insrsid1250157\charrsid1250157 +icense, to the maximum extent the law permits, no matter what legal theory it\rquote s based on. Also, you must pass this limitation of liability on whenever you distribute the Software}{\b\insrsid5341002 or derivative works}{ +\b\insrsid1250157\charrsid1250157 .}{\insrsid1250157\charrsid1250157 +\par {\listtext\pard\plain\insrsid1250157\charrsid1250157 \hich\af0\dbch\af0\loch\f0 5.\tab}That if you sue anyone over patents that you think may apply to the Software for a person's use of the Software, your license to the Software ends automatically. + +\par {\listtext\pard\plain\insrsid1250157 \hich\af0\dbch\af0\loch\f0 6.\tab}}{\insrsid1250157 That the patent rights, if any, }{\insrsid288726 granted in this license}{\insrsid1250157\charrsid1250157 only apply to the Software, not to any derivative}{ +\insrsid4417501 work}{\insrsid1250157\charrsid1250157 s you make.}{\insrsid3018318 +\par {\listtext\pard\plain\insrsid3018318\charrsid3018318 \hich\af0\dbch\af0\loch\f0 7.\tab}}{\insrsid3018318\charrsid3018318 That if you are an agency of the U.S. Government, (i) Software provided pursuant to a solicitation issued on or after Dece +mber 1, 1995, is provided with the commercial license rights set forth in this license, and (ii) Software provided pursuant to a solicitation issued prior to December 1, 1995, is provided with \'93Restricted Rights\'94 + as set forth in FAR, 48 C.F.R. 52.227-14 (June 1987) or DFAR, 48 C.F.R. 252.227-7013 (Oct 1988), as applicable.}{\insrsid1250157 +\par {\listtext\pard\plain\insrsid1250157 \hich\af0\dbch\af0\loch\f0 8.\tab}That your rights under this License end automatically if you breach it in any way. +\par {\listtext\pard\plain\insrsid5341002 \hich\af0\dbch\af0\loch\f0 9.\tab}}{\insrsid5341002 That all rights not expressly granted to you in this license are reserved. +\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid1778664 {\insrsid1778664 +\par }{\insrsid12150908 Read below}{\insrsid1778664 for answers to frequently asked questions about this license. +\par }{\insrsid12150908 +\par }\pard \ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0\pararsid12150908 {\b\insrsid12150908\charrsid12150908 Q: Is this license OSI compliant? +\par }{\insrsid12150908 +A: This license has not been submitted to OSI, but it allows developers to take full advantage of a dynamic language on the CLR and to have the freedom to distribute their works for the benefit of the community at large. The license is half of a +page long and very straight forward. We believe it stands up to what developers demand of an "open" license. +\par +\par }{\b\insrsid12150908\charrsid12150908 Q: What copyright rights does the license grant me? +\par }{\insrsid12150908 A: The license grants you a copyright license to make unlimited copies of the Software in sour +ce or object code form, as well as to create Derivative Works (as that term is defined under US copyright law). This means that in addition to making unlimited copies of the Software, you have a copyright license to modify the Software and to use all or p +art of the Software to create a Derivative Work. +\par +\par }{\b\insrsid12150908\charrsid12150908 Q: What patent rights does the license grant me? +\par }{\insrsid12150908 A: This license grants you a patent license to use and distribute the Software under any Microsoft patent claims that read on the Software itself. In other wo +rds, if you create a modified version of the Software, you still retain the patent license to use and distribute the original portions of the Software under the specific Microsoft patent claims that read on the Software, but you do not have a patent licen +s +e as to the new functionality you may have added by modifying the Software. This result is typical of many common open source licenses, including the Common Public License (CPL) and the Mozilla Public License (MPL). In addition, this license grants no rig +h +ts to any Microsoft patents that read on other components or files not included in the Software. This means that no patent license is granted to use or distribute any other software or technology that may be needed to use the Software or was created from +t +he Software (for example, any compiled output of the Software, the combination of the Software with other hardware or other software, or any additional enabling technologies that may be necessary to make or use the Software or any final product that inclu +des the Software).}{\insrsid12150908 +\par }{\insrsid12150908\charrsid1250157 +\par }} \ No newline at end of file diff --git a/License.txt b/License.txt new file mode 100644 index 0000000000..59e4c551d6 --- /dev/null +++ b/License.txt @@ -0,0 +1,221 @@ +umbraco v3 is licensed under the open source license CPL - Common Public License (attached below). Please notice that it's only v3 that uses the CPL. The prior versions (v2.0, v2.1 and v2.1.x) uses GPL. + +Important License Guidelines - How we see and adopt the CPL +- You're free to choose whatever license (both open source and properary licenses) for any umbraco extensions you make as long as these are distributed alone and not bundled with umbraco. +- umbraco may only be distributed as a whole. You may not use part of umbraco to create another stand-alone application, this could be using the UI parts to create another CMS. +- You may not re-brand umbraco +- If in doubt, please contact us (http://umbraco.org) before using our software for other than the original purpose. We have a commercial non-CPL license for those in doubt, wishes not to use CPL licensed software or wishes to build a new product based on parts of umbraco (see http://umbraco.org). + +Common Public License Version 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC +LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM +CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + +a) in the case of the initial Contributor, the initial code and +documentation distributed under this Agreement, and + +b) in the case of each subsequent Contributor: + +i) changes to the Program, and + +ii) additions to the Program; + +where such changes and/or additions to the Program originate from and are +distributed by that particular Contributor. A Contribution 'originates' from a +Contributor if it was added to the Program by such Contributor itself or anyone +acting on such Contributor's behalf. Contributions do not include additions to +the Program which: (i) are separate modules of software distributed in +conjunction with the Program under their own license agreement, and (ii) are not +derivative works of the Program. + +"Contributor" means any person or entity that distributes the Program. + +"Licensed Patents " mean patent claims licensable by a Contributor which are +necessarily infringed by the use or sale of its Contribution alone or when +combined with the Program. + +"Program" means the Contributions distributed in accordance with this Agreement. + +"Recipient" means anyone who receives the Program under this Agreement, +including all Contributors. + +2. GRANT OF RIGHTS + +a) Subject to the terms of this Agreement, each Contributor hereby grants +Recipient a non-exclusive, worldwide, royalty-free copyright license to +reproduce, prepare derivative works of, publicly display, publicly perform, +distribute and sublicense the Contribution of such Contributor, if any, and such +derivative works, in source code and object code form. + +b) Subject to the terms of this Agreement, each Contributor hereby grants +Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed +Patents to make, use, sell, offer to sell, import and otherwise transfer the +Contribution of such Contributor, if any, in source code and object code form. +This patent license shall apply to the combination of the Contribution and the +Program if, at the time the Contribution is added by the Contributor, such +addition of the Contribution causes such combination to be covered by the +Licensed Patents. The patent license shall not apply to any other combinations +which include the Contribution. No hardware per se is licensed hereunder. + +c) Recipient understands that although each Contributor grants the licenses +to its Contributions set forth herein, no assurances are provided by any +Contributor that the Program does not infringe the patent or other intellectual +property rights of any other entity. Each Contributor disclaims any liability to +Recipient for claims brought by any other entity based on infringement of +intellectual property rights or otherwise. As a condition to exercising the +rights and licenses granted hereunder, each Recipient hereby assumes sole +responsibility to secure any other intellectual property rights needed, if any. +For example, if a third party patent license is required to allow Recipient to +distribute the Program, it is Recipient's responsibility to acquire that license +before distributing the Program. + +d) Each Contributor represents that to its knowledge it has sufficient +copyright rights in its Contribution, if any, to grant the copyright license set +forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code form under its +own license agreement, provided that: + +a) it complies with the terms and conditions of this Agreement; and + +b) its license agreement: + +i) effectively disclaims on behalf of all Contributors all warranties and +conditions, express and implied, including warranties or conditions of title and +non-infringement, and implied warranties or conditions of merchantability and +fitness for a particular purpose; + +ii) effectively excludes on behalf of all Contributors all liability for +damages, including direct, indirect, special, incidental and consequential +damages, such as lost profits; + +iii) states that any provisions which differ from this Agreement are offered +by that Contributor alone and not by any other party; and + +iv) states that source code for the Program is available from such +Contributor, and informs licensees how to obtain it in a reasonable manner on or +through a medium customarily used for software exchange. + +When the Program is made available in source code form: + +a) it must be made available under this Agreement; and + +b) a copy of this Agreement must be included with each copy of the Program. + +Contributors may not remove or alter any copyright notices contained within the +Program. + +Each Contributor must identify itself as the originator of its Contribution, if +any, in a manner that reasonably allows subsequent Recipients to identify the +originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with +respect to end users, business partners and the like. While this license is +intended to facilitate the commercial use of the Program, the Contributor who +includes the Program in a commercial product offering should do so in a manner +which does not create potential liability for other Contributors. Therefore, if +a Contributor includes the Program in a commercial product offering, such +Contributor ("Commercial Contributor") hereby agrees to defend and indemnify +every other Contributor ("Indemnified Contributor") against any losses, damages +and costs (collectively "Losses") arising from claims, lawsuits and other legal +actions brought by a third party against the Indemnified Contributor to the +extent caused by the acts or omissions of such Commercial Contributor in +connection with its distribution of the Program in a commercial product +offering. The obligations in this section do not apply to any claims or Losses +relating to any actual or alleged intellectual property infringement. In order +to qualify, an Indemnified Contributor must: a) promptly notify the Commercial +Contributor in writing of such claim, and b) allow the Commercial Contributor to +control, and cooperate with the Commercial Contributor in, the defense and any +related settlement negotiations. The Indemnified Contributor may participate in +any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial product +offering, Product X. That Contributor is then a Commercial Contributor. If that +Commercial Contributor then makes performance claims, or offers warranties +related to Product X, those performance claims and warranties are such +Commercial Contributor's responsibility alone. Under this section, the +Commercial Contributor would have to defend claims against the other +Contributors related to those performance claims and warranties, and if a court +requires any other Contributor to pay any damages as a result, the Commercial +Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each +Recipient is solely responsible for determining the appropriateness of using and +distributing the Program and assumes all risks associated with its exercise of +rights under this Agreement, including but not limited to the risks and costs of +program errors, compliance with applicable laws, damage to or loss of data, +programs or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY +CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), 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 OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS +GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under applicable +law, it shall not affect the validity or enforceability of the remainder of the +terms of this Agreement, and without further action by the parties hereto, such +provision shall be reformed to the minimum extent necessary to make such +provision valid and enforceable. + +If Recipient institutes patent litigation against a Contributor with respect to +a patent applicable to software (including a cross-claim or counterclaim in a +lawsuit), then any patent licenses granted by that Contributor to such Recipient +under this Agreement shall terminate as of the date such litigation is filed. In +addition, if Recipient institutes patent litigation against any entity +(including a cross-claim or counterclaim in a lawsuit) alleging that the Program +itself (excluding combinations of the Program with other software or hardware) +infringes such Recipient's patent(s), then such Recipient's rights granted under +Section 2(b) shall terminate as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it fails to +comply with any of the material terms or conditions of this Agreement and does +not cure such failure in a reasonable period of time after becoming aware of +such noncompliance. If all Recipient's rights under this Agreement terminate, +Recipient agrees to cease use and distribution of the Program as soon as +reasonably practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall continue and +survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in +order to avoid inconsistency the Agreement is copyrighted and may only be +modified in the following manner. The Agreement Steward reserves the right to +publish new versions (including revisions) of this Agreement from time to time. +No one other than the Agreement Steward has the right to modify this Agreement. +IBM is the initial Agreement Steward. IBM may assign the responsibility to serve +as the Agreement Steward to a suitable separate entity. Each new version of the +Agreement will be given a distinguishing version number. The Program (including +Contributions) may always be distributed subject to the version of the Agreement +under which it was received. In addition, after a new version of the Agreement +is published, Contributor may elect to distribute the Program (including its +Contributions) under the new version. Except as expressly stated in Sections +2(a) and 2(b) above, Recipient receives no rights or licenses to the +intellectual property of any Contributor under this Agreement, whether +expressly, by implication, estoppel or otherwise. All rights in the Program not +expressly granted under this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and the +intellectual property laws of the United States of America. No party to this +Agreement will bring a legal action under this Agreement more than one year +after the cause of action arose. Each party waives its rights to a jury trial in +any resulting litigation. diff --git a/aspnet35.config b/aspnet35.config new file mode 100644 index 0000000000..a49064291a --- /dev/null +++ b/aspnet35.config @@ -0,0 +1,215 @@ + + + +
+ + + + +
+ +
+
+
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/build.xml b/build.xml new file mode 100644 index 0000000000..3f35055ac6 --- /dev/null +++ b/build.xml @@ -0,0 +1,6 @@ + + + 4.0 Beta 2 + @assembly@ + @date@ + diff --git a/components/PalmTidy/AssemblyInfo.cs b/components/PalmTidy/AssemblyInfo.cs new file mode 100644 index 0000000000..177a4f0e70 --- /dev/null +++ b/components/PalmTidy/AssemblyInfo.cs @@ -0,0 +1,58 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.0.*")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/components/PalmTidy/tidy.cs b/components/PalmTidy/tidy.cs new file mode 100644 index 0000000000..899c33f785 --- /dev/null +++ b/components/PalmTidy/tidy.cs @@ -0,0 +1,94 @@ +using System; + +using System.Runtime.InteropServices; + + +// GPL Licensed work +// (c) Christian Palm + umbraco crew 2005 +// Kudos to Christian Palm for finally making a +// Tidy solution that just works +// palmdk@gmail.com + +namespace CPalmTidy +{ + /// + /// Summary description for tidy. + /// + public class Tidy + { + public string error; + public string outputFile; + public string inputFile; + public string configFile; + + public Tidy() + { + this.error = ""; + this.outputFile = ""; + this.inputFile = ""; + this.configFile = ""; + } + + public bool Run() + { + int i = CallTidyMain(this.inputFile, this.outputFile, this.configFile); + this.error = i.ToString(); + //this.error = "this.inputFile: " + this.inputFile + "
this.outputFile: " + this.outputFile + "
this.configFile: " + this.configFile; + return true; + } + + [DllImport(@"TidyDll.dll")] + static extern int CallTidyMain( + [MarshalAs(UnmanagedType.LPStr)] string inFileName, + [MarshalAs(UnmanagedType.LPStr)] string outFileName, + [MarshalAs(UnmanagedType.LPStr)] string optionsFileName + ); + + + public string ErrorValue + { + get + { + return this.error; + } + } + + public string ConfigFile + { + get + { + return this.configFile; + } + set + { + this.configFile = value; + } + } + + public string OutputFile + { + get + { + return this.outputFile; + } + set + { + this.outputFile = value; + } + } + + public string InputFile + { + get + { + return this.inputFile; + } + set + { + this.inputFile = value; + } + } + + + } +} diff --git a/components/PalmTidy/umbraco.CPalmTidy.csproj b/components/PalmTidy/umbraco.CPalmTidy.csproj new file mode 100644 index 0000000000..dd1bbddbbb --- /dev/null +++ b/components/PalmTidy/umbraco.CPalmTidy.csproj @@ -0,0 +1,106 @@ + + + Local + 8.0.50727 + 2.0 + {C584F126-315D-4136-A3EA-E87A108D27DA} + Debug + AnyCPU + + + + + umbraco.CPalmTidy + + + JScript + Grid + IE50 + false + Library + umbraco.CPalmTidy + OnBuildSuccess + + + + + + + SAK + SAK + SAK + SAK + 2.0 + + + bin\Debug\ + false + 285212672 + false + + + DEBUG;TRACE + bin\Debug\umbraco.CPalmTidy.XML + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + bin\Release\ + false + 285212672 + false + + + TRACE + + + false + 4096 + false + + + true + false + false + false + 4 + none + prompt + + + + System + + + System.Data + + + System.XML + + + + + Code + + + Code + + + + + + + + + + \ No newline at end of file diff --git a/components/PalmTidy/umbraco.CPalmTidy.csproj.vspscc b/components/PalmTidy/umbraco.CPalmTidy.csproj.vspscc new file mode 100644 index 0000000000..feffdecaa4 --- /dev/null +++ b/components/PalmTidy/umbraco.CPalmTidy.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/components/editorControls/AssemblyInfo.cs b/components/editorControls/AssemblyInfo.cs new file mode 100644 index 0000000000..cced87bf05 --- /dev/null +++ b/components/editorControls/AssemblyInfo.cs @@ -0,0 +1,62 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.0.*")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the "project output directory". The location of the project output +// directory is dependent on whether you are working with a local or web project. +// For local projects, the project output directory is defined as +// \obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// For web projects, the project output directory is defined as +// %HOMEPATH%\VSWebCache\\\obj\. +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/components/editorControls/BaseDataType.cs b/components/editorControls/BaseDataType.cs new file mode 100644 index 0000000000..9fb01a62b3 --- /dev/null +++ b/components/editorControls/BaseDataType.cs @@ -0,0 +1,94 @@ +using System; + +using umbraco.DataLayer; +using umbraco.BusinessLogic; + +namespace umbraco.editorControls +{ + public abstract class BaseDataType + { + private int _datatypedefinitionid; + private string _datafield = ""; + private DBTypes _DBType; + + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + public BaseDataType() + {} + + #region IDataType Members + public abstract Guid Id {get;} + public abstract string DataTypeName{get;} + public abstract interfaces.IDataEditor DataEditor{get;} + public abstract interfaces.IDataPrevalue PrevalueEditor {get;} + public abstract interfaces.IData Data{get;} + + public int DataTypeDefinitionId { + set { + _datatypedefinitionid = value; + } + get { + return _datatypedefinitionid; + } + } + + public DBTypes DBType { + get { + string test= ""; + if (_datafield == "") + test = DataFieldName; + return _DBType; + } + set { + _DBType = value; + SqlHelper.ExecuteNonQuery("update cmsDataType set dbType = '" + value.ToString() + "' where nodeId = @datadefinitionid", + SqlHelper.CreateParameter("@datadefinitionid",_datatypedefinitionid)).ToString(); + + } + } + // Umbraco legacy - get the datafield - the columnname of the cmsPropertyData table + // where to find the data, since it's configurable - there is no way of telling if + // its a bit, nvarchar, ntext or datetime field. + // get it by lookup the value associated to the datatypedefinition id. + public string DataFieldName + { + get { + if (_datafield == "") + { + string dbtypestr = SqlHelper.ExecuteScalar("select dbType from cmsDataType where nodeId = @datadefinitionid", + SqlHelper.CreateParameter("@datadefinitionid",_datatypedefinitionid)); + DBTypes DataTypeSQLType = (DBTypes) Enum.Parse(typeof(DBTypes),dbtypestr,true); + _DBType = DataTypeSQLType; + switch (DataTypeSQLType) + { + case DBTypes.Date : + _datafield = "dataDate"; + break; + case DBTypes.Integer : + _datafield = "DataInt"; + break; + case DBTypes.Ntext : + _datafield = "dataNtext"; + break; + case DBTypes.Nvarchar : + _datafield = "dataNvarchar"; + break; + } + return _datafield; + } + return _datafield; + } + } + #endregion + } + public enum DBTypes + { + Integer, + Date, + Nvarchar, + Ntext + } +} diff --git a/components/editorControls/DefaultData.cs b/components/editorControls/DefaultData.cs new file mode 100644 index 0000000000..f062f439fa --- /dev/null +++ b/components/editorControls/DefaultData.cs @@ -0,0 +1,100 @@ +using System; + +using umbraco.BusinessLogic; +using umbraco.DataLayer; + +namespace umbraco.editorControls +{ + [Obsolete("Use umbraco.cms.businesslogic.datatype.DefaultData instead")] + public class DefaultData : interfaces.IData + { + private int _propertyId; + private object _value; + protected BaseDataType _dataType; + + public static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + public DefaultData(BaseDataType DataType) { + _dataType = DataType; + } + + #region IData Members + + public virtual System.Xml.XmlNode ToXMl(System.Xml.XmlDocument d) + { + if (this._dataType.DBType == DBTypes.Ntext) + return d.CreateCDataSection(this.Value.ToString()); + return d.CreateTextNode(Value.ToString()); + } + + public object Value + { + get + { + return _value; + } + set + { + // Try to set null values if possible + try + { + if (value == null) + SqlHelper.ExecuteNonQuery("update cmsPropertyData set "+ _dataType.DataFieldName +" = NULL where id = " + _propertyId); + else + SqlHelper.ExecuteNonQuery("update cmsPropertyData set "+ _dataType.DataFieldName +" = @value where id = " + _propertyId, SqlHelper.CreateParameter("@value", value) ); + _value = value; + } + catch (Exception e) + { + umbraco.BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Debug, umbraco.BusinessLogic.User.GetUser(0), -1, "Error updating item: " + e.ToString()); + if (value==null) value =""; + SqlHelper.ExecuteNonQuery("update cmsPropertyData set "+ _dataType.DataFieldName +" = @value where id = " + _propertyId, SqlHelper.CreateParameter("@value", value) ); + _value = value; + } + + } + } + + public virtual void MakeNew(int PropertyId) + { + // this default implementation of makenew does not do anything snce + // it uses the default datastorage of umbraco, and the row is already populated by the "property" object + // If the datatype needs to have a default value, inherit this class and override this method. + } + + public void Delete() { + // this default implementation of delete does not do anything snce + // it uses the default datastorage of umbraco, and the row is already deleted by the "property" object + } + + public int PropertyId + { + get { + return _propertyId; + } + set + { + _propertyId = value; + _value = SqlHelper.ExecuteScalar("Select " + _dataType.DataFieldName + " from cmsPropertyData where id = " + value); + } + } + + // TODO: clean up Legacy - these are needed by the wysiwyeditor, in order to feed the richtextholder with version and nodeid + // solution, create a new version of the richtextholder, which does not depend on these. + public Guid Version { + get { + return new Guid(SqlHelper.ExecuteScalar("Select versionId from cmsPropertyData where id = " + PropertyId).ToString()); + } + } + + public int NodeId { + get { + return SqlHelper.ExecuteScalar("Select contentNodeid from cmsPropertyData where id = " + PropertyId); + } + } + #endregion + } +} diff --git a/components/editorControls/DefaultDataKeyValue.cs b/components/editorControls/DefaultDataKeyValue.cs new file mode 100644 index 0000000000..8aee77fb06 --- /dev/null +++ b/components/editorControls/DefaultDataKeyValue.cs @@ -0,0 +1,39 @@ +using System; +using umbraco.DataLayer; + +namespace umbraco.editorControls +{ + /// + /// Summary description for cms.businesslogic.datatype.DefaultDataKeyValue. + /// + public class DefaultDataKeyValue : cms.businesslogic.datatype.DefaultData + { + public DefaultDataKeyValue(cms.businesslogic.datatype.BaseDataType DataType) : base(DataType) + {} + /// + /// Ov + /// + /// + /// + + public override System.Xml.XmlNode ToXMl(System.Xml.XmlDocument d) + { + // Get the value from + string v = ""; + try + { + IRecordsReader dr = SqlHelper.ExecuteReader("Select [value] from cmsDataTypeprevalues where id in (" + Value.ToString() +")"); + + while (dr.Read()) { + if (v.Length == 0) + v += dr.GetString("value"); + else + v += "," + dr.GetString("value"); + } + dr.Close(); + } + catch {} + return d.CreateCDataSection(v); + } + } +} diff --git a/components/editorControls/DefaultPrevalueEditor.cs b/components/editorControls/DefaultPrevalueEditor.cs new file mode 100644 index 0000000000..7a6c17cffd --- /dev/null +++ b/components/editorControls/DefaultPrevalueEditor.cs @@ -0,0 +1,215 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +using umbraco.interfaces; +using umbraco.BusinessLogic; +using umbraco.DataLayer; + +namespace umbraco.editorControls +{ + public class DefaultPrevalueEditor : PlaceHolder, IDataPrevalue + { + // UI controls + private TextBox _textbox; + private DropDownList _dropdownlist; + + // referenced datatype + private cms.businesslogic.datatype.BaseDataType _datatype; + private BaseDataType _datatypeOld; + + private bool _isEnsured = false; + private string _prevalue; + private bool _displayTextBox; + + public static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + /// + /// The default editor for editing the build-in pre values in umbraco + /// + /// The DataType to be parsed + /// Whether to use the default text box + public DefaultPrevalueEditor(cms.businesslogic.datatype.BaseDataType DataType, bool DisplayTextBox) + { + // state it knows its datatypedefinitionid + _displayTextBox = DisplayTextBox; + _datatype = DataType; + setupChildControls(); + } + + /// + /// For backwards compatibility, should be replaced in your extension with the constructor that + /// uses the BaseDataType from the cms.businesslogic.datatype namespace + /// + /// The DataType to be parsed (note: the BaseDataType from editorControls is obsolete) + /// Whether to use the default text box + public DefaultPrevalueEditor(BaseDataType DataType, bool DisplayTextBox) + { + // state it knows its datatypedefinitionid + _displayTextBox = DisplayTextBox; + _datatypeOld = DataType; + setupChildControls(); + } + + private void setupChildControls() + { + _dropdownlist = new DropDownList(); + _dropdownlist.ID = "dbtype"; + + _textbox = new TextBox(); + _textbox.ID = "prevalues"; + _textbox.Visible = _displayTextBox; + + // put the childcontrols in context - ensuring that + // the viewstate is persisted etc. + Controls.Add(_textbox); + Controls.Add(_dropdownlist); + + _dropdownlist.Items.Add(DBTypes.Date.ToString()); + _dropdownlist.Items.Add(DBTypes.Integer.ToString()); + _dropdownlist.Items.Add(DBTypes.Ntext.ToString()); + _dropdownlist.Items.Add(DBTypes.Nvarchar.ToString()); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + if (!Page.IsPostBack) + { + if (_datatype != null) + _dropdownlist.SelectedValue = _datatype.DBType.ToString(); + else + _dropdownlist.SelectedValue = _datatypeOld.DBType.ToString(); + + _textbox.Text = Prevalue; + } + } + + public string Prevalue + { + get + { + ensurePrevalue(); + if (_prevalue == null) { + int defId; + if (_datatype != null) + defId = _datatype.DataTypeDefinitionId; + else if (_datatypeOld != null) + defId = _datatypeOld.DataTypeDefinitionId; + else + throw new ArgumentException("Datatype is not initialized"); + + _prevalue = + SqlHelper.ExecuteScalar("Select [value] from cmsDataTypePreValues where DataTypeNodeId = " + defId); + } + return _prevalue; + } + set + { + int defId; + if (_datatype != null) + defId = _datatype.DataTypeDefinitionId; + else if (_datatypeOld != null) + defId = _datatypeOld.DataTypeDefinitionId; + else + throw new ArgumentException("Datatype is not initialized"); + + _prevalue = value; + ensurePrevalue(); + IParameter[] SqlParams = new IParameter[] + { + SqlHelper.CreateParameter("@value", _textbox.Text), + SqlHelper.CreateParameter("@dtdefid", defId) + }; + // update prevalue + SqlHelper.ExecuteNonQuery("update cmsDataTypePreValues set [value] = @value where datatypeNodeId = @dtdefid", SqlParams); + } + } + + private void ensurePrevalue() + { + if (!_isEnsured) + { + + int defId; + if (_datatype != null) + defId = _datatype.DataTypeDefinitionId; + else if (_datatypeOld != null) + defId = _datatypeOld.DataTypeDefinitionId; + else + throw new ArgumentException("Datatype is not initialized"); + + + bool hasPrevalue = (SqlHelper.ExecuteScalar("select count(id) from cmsDataTypePreValues where dataTypeNodeId = " + defId) > 0); + IParameter[] SqlParams = new IParameter[] + { + SqlHelper.CreateParameter("@value", _textbox.Text), + SqlHelper.CreateParameter("@dtdefid", defId) + }; + if (!hasPrevalue) + { + SqlHelper.ExecuteNonQuery("insert into cmsDataTypePreValues (datatypenodeid,[value],sortorder,alias) values (@dtdefid,@value,0,'')", + SqlParams); + } + _isEnsured = true; + } + } + + public Control Editor + { + get { return this; } + } + + public void Save() + { + // save the prevalue data and get on with you life ;) + if (_datatype != null) + _datatype.DBType = (cms.businesslogic.datatype.DBTypes)Enum.Parse(typeof (cms.businesslogic.datatype.DBTypes), _dropdownlist.SelectedValue, true); + else if (_datatypeOld != null) + _datatypeOld.DBType = (DBTypes)Enum.Parse(typeof (DBTypes), _dropdownlist.SelectedValue, true); + + + if (_displayTextBox) + { + // If the prevalue editor has an prevalue textbox - save the textbox value as the prevalue + Prevalue = _textbox.Text; + } + } + + protected override void Render(HtmlTextWriter writer) + { + writer.Write("
" + ui.Text("dataBaseDatatype") + "
"); + _dropdownlist.RenderControl(writer); + writer.Write("
"); + + + if (_displayTextBox) { + writer.Write("
" + ui.Text("prevalue") + "
"); + _textbox.RenderControl(writer); + writer.Write("
"); + } + + /* + writer.WriteLine("
"); + writer.WriteLine("Database datatype"); + _dropdownlist.RenderControl(writer); + writer.Write(""); + if (_displayTextBox) + writer.WriteLine("Prevalue: "); + _textbox.RenderControl(writer); + writer.WriteLine(""); + writer.Write("
"); + */ + + } + + public static string GetPrevalueFromId(int Id) + { + return SqlHelper.ExecuteScalar("Select [value] from cmsDataTypePreValues where id = @id", + SqlHelper.CreateParameter("@id", Id)); + } + } +} \ No newline at end of file diff --git a/components/editorControls/KeyValuePrevalueEditor.cs b/components/editorControls/KeyValuePrevalueEditor.cs new file mode 100644 index 0000000000..376738a335 --- /dev/null +++ b/components/editorControls/KeyValuePrevalueEditor.cs @@ -0,0 +1,152 @@ +using System; +using System.Collections; +using System.Web.UI; +using System.Web.UI.WebControls; + +using umbraco.BusinessLogic; +using umbraco.DataLayer; + +namespace umbraco.editorControls +{ + /// + /// Summary description for KeyValuePrevalueEditor. + /// + public class KeyValuePrevalueEditor : System.Web.UI.WebControls.PlaceHolder, interfaces.IDataPrevalue + { + + // UI controls + public System.Web.UI.WebControls.DropDownList _dropdownlist; + public TextBox _textbox; + public umbraco.uicontrols.PropertyPanel pp1 = new umbraco.uicontrols.PropertyPanel(); + public umbraco.uicontrols.PropertyPanel pp2 = new umbraco.uicontrols.PropertyPanel(); + + private Hashtable DeleteButtons = new Hashtable(); + + // referenced datatype + private cms.businesslogic.datatype.BaseDataType _datatype; + + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + public KeyValuePrevalueEditor(cms.businesslogic.datatype.BaseDataType DataType) + { + // state it knows its datatypedefinitionid + _datatype = DataType; + + setupChildControls(); + + // Bootstrap delete. + if (System.Web.HttpContext.Current.Request["delete"] != null) { + DeletePrevalue(int.Parse(System.Web.HttpContext.Current.Request["delete"])); + } + + } + + private void DeletePrevalue(int id) { + SqlHelper.ExecuteNonQuery("delete from cmsDataTypePreValues where id = " + id); + } + + private void setupChildControls() + { + _dropdownlist = new DropDownList(); + _dropdownlist.ID = "dbtype"; + + _textbox = new TextBox(); + _textbox.ID = "AddValue"; + + // put the childcontrols in context - ensuring that + // the viewstate is persisted etc. + this.Controls.Add(_dropdownlist); + this.Controls.Add(_textbox); + + _dropdownlist.Items.Add(DBTypes.Date.ToString()); + _dropdownlist.Items.Add(DBTypes.Integer.ToString()); + _dropdownlist.Items.Add(DBTypes.Ntext.ToString()); + _dropdownlist.Items.Add(DBTypes.Nvarchar.ToString()); + } + + protected override void OnInit(EventArgs e) { + base.OnInit(e); + + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad (e); + + if (!Page.IsPostBack) + { + _dropdownlist.SelectedValue = _datatype.DBType.ToString(); + + } + + + } + + public Control Editor + { + get + { + return this; + } + } + + public void Save() + { + _datatype.DBType = (cms.businesslogic.datatype.DBTypes)Enum.Parse(typeof(cms.businesslogic.datatype.DBTypes), _dropdownlist.SelectedValue, true); + // If the add new prevalue textbox is filled out - add the value to the collection. + if (_textbox.Text != "") + { + IParameter[] SqlParams = new IParameter[] { + SqlHelper.CreateParameter("@value",_textbox.Text), + SqlHelper.CreateParameter("@dtdefid",_datatype.DataTypeDefinitionId)}; + SqlHelper.ExecuteNonQuery("insert into cmsDataTypePreValues (datatypenodeid,[value],sortorder,alias) values (@dtdefid,@value,0,'')",SqlParams); + _textbox.Text = ""; + + ScriptManager.GetCurrent(Page).SetFocus(_textbox); + } + } + + protected override void Render(HtmlTextWriter writer) + { + writer.Write("
" + ui.Text("dataBaseDatatype") + "
"); + _dropdownlist.RenderControl(writer); + writer.Write("
"); + + SortedList _prevalues = Prevalues; + if (_prevalues.Count > 0) { + writer.Write("
"); + writer.Write(""); + + foreach (object key in _prevalues.Keys) { + writer.Write(""); + } + writer.Write("
TextValue
" + _prevalues[key].ToString() + " " + key + "" + ui.Text("delete") + "

"); + } + + writer.Write("
" + ui.Text("addPrevalue") + "
"); + _textbox.RenderControl(writer); + writer.Write("
"); + + + + } + + public SortedList Prevalues { + get + { + SortedList retval = new SortedList(); + IRecordsReader dr = SqlHelper.ExecuteReader( + "Select id, [value] from cmsDataTypePreValues where DataTypeNodeId = " + + _datatype.DataTypeDefinitionId + " order by sortorder"); + + while (dr.Read()) + retval.Add(dr.GetInt("id"), dr.GetString("value")); + dr.Close(); + return retval; + } + } + } +} diff --git a/components/editorControls/checkboxlist/CheckBoxDataType.cs b/components/editorControls/checkboxlist/CheckBoxDataType.cs new file mode 100644 index 0000000000..cfa8f9161e --- /dev/null +++ b/components/editorControls/checkboxlist/CheckBoxDataType.cs @@ -0,0 +1,49 @@ +using System; + +namespace umbraco.editorControls.checkboxlist +{ + public class checkboxListDataType : cms.businesslogic.datatype.BaseDataType, interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private KeyValuePrevalueEditor _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new checkboxlistEditor(Data,((KeyValuePrevalueEditor)PrevalueEditor).Prevalues); + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new DefaultDataKeyValue(this); + return _baseData; + } + } + + public override string DataTypeName + {get {return "Checkbox list";}} + + public override Guid Id + { + get {return new Guid("b4471851-82b6-4c75-afa4-39fa9c6a75e9");} + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new KeyValuePrevalueEditor(this); + return _prevalueeditor; + } + } + } +} \ No newline at end of file diff --git a/components/editorControls/checkboxlist/checkboxList.cs b/components/editorControls/checkboxlist/checkboxList.cs new file mode 100644 index 0000000000..0e155fdb11 --- /dev/null +++ b/components/editorControls/checkboxlist/checkboxList.cs @@ -0,0 +1,68 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.ComponentModel; +using System.Collections; + +namespace umbraco.editorControls.checkboxlist +{ + public class checkboxlistEditor : System.Web.UI.WebControls.CheckBoxList, interfaces.IDataEditor + { + private String _text; + + interfaces.IData _data; + SortedList _prevalues; + public checkboxlistEditor(interfaces.IData Data,SortedList Prevalues) + { + _data = Data; + _prevalues = Prevalues; + } + + public Control Editor { get {return this;}} + + public virtual bool TreatAsRichTextEditor + { + get {return false;} + } + public virtual bool ShowLabel + { + get {return true;} + } + + public void Save() + { + _text = ""; + foreach(ListItem li in base.Items) + { + if (li.Selected) + { + _text += li.Value + ","; + } + } + + if (_text.Length > 0) + _text = _text.Substring(0, _text.Length-1); + _data.Value = _text; + + + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + + if (_data != null && _data.Value != null && _data.Value.ToString() != "") + _text = _data.Value.ToString(); + + foreach(object key in _prevalues.Keys) + { + ListItem li = new ListItem(_prevalues[key].ToString(),key.ToString()); + + if ((","+_text+",").IndexOf(","+li.Value.ToString()+",") > -1) + li.Selected = true; + + Items.Add(li); + } + } + } +} diff --git a/components/editorControls/colorpicker/ColorPickerDataType.cs b/components/editorControls/colorpicker/ColorPickerDataType.cs new file mode 100644 index 0000000000..608e75b945 --- /dev/null +++ b/components/editorControls/colorpicker/ColorPickerDataType.cs @@ -0,0 +1,54 @@ +using System; + +namespace umbraco.editorControls.colorpicker +{ + /// + /// Summary description for ColorPickerDataType. + /// + public class ColorPickerDataType : cms.businesslogic.datatype.BaseDataType, interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private KeyValuePrevalueEditor _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + { + _Editor = new colorPicker(Data,((KeyValuePrevalueEditor)PrevalueEditor).Prevalues); + } + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + public override string DataTypeName + { + get {return "Color Picker";} + } + public override Guid Id + { + get {return new Guid("F8D60F68-EC59-4974-B43B-C46EB5677985");} + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new KeyValuePrevalueEditor(this); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/colorpicker/colorPicker.cs b/components/editorControls/colorpicker/colorPicker.cs new file mode 100644 index 0000000000..ba344e9944 --- /dev/null +++ b/components/editorControls/colorpicker/colorPicker.cs @@ -0,0 +1,87 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.ComponentModel; +using System.Collections; + +namespace umbraco.editorControls +{ + /// + /// Summary description for colorPicker. + /// + [DefaultProperty("Value"), + ValidationProperty("Value"), + ToolboxData("<{0}:colorPicker runat=server>")] + public class colorPicker : System.Web.UI.WebControls.HiddenField, interfaces.IDataEditor + { + private interfaces.IData _data; + private SortedList _prevalues; + + public colorPicker(interfaces.IData Data, SortedList Prevalues) + { + _data = Data; + _prevalues = Prevalues; + } + private ArrayList _colors = new ArrayList(); + + public Control Editor { get { return this; } } + + public colorPicker() + { + } + + public virtual bool TreatAsRichTextEditor + { + get { return false; } + } + public bool ShowLabel + { + get { return true; } + } + + public void Save() + { + _data.Value = this.Value; + } + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + if (_data != null && _data.Value != null) + this.Value = _data.Value.ToString(); + + _colors.Add(new ListItem("")); + + try + { + foreach (string val in _prevalues.Values) + { + _colors.Add(new ListItem(val)); + } + } + catch { } + } + + protected override void Render(HtmlTextWriter writer) + { + string _bgColor = this.Value; + if (_bgColor == "") + _bgColor = "FFF"; + + base.Render(writer); + writer.WriteLine("
  - "); + + foreach (object color in _colors) + { + string colorValue = color.ToString(); + if (colorValue == "") + colorValue = "FFF"; + + writer.WriteLine(""); + } + + writer.WriteLine("
"); + } + } +} diff --git a/components/editorControls/datefieldmultiple/DataTypeDatefieldMultiple.cs b/components/editorControls/datefieldmultiple/DataTypeDatefieldMultiple.cs new file mode 100644 index 0000000000..f2e2d04bcf --- /dev/null +++ b/components/editorControls/datefieldmultiple/DataTypeDatefieldMultiple.cs @@ -0,0 +1,43 @@ +using System; + +namespace umbraco.editorControls.datefieldmultiple +{ + /// + /// Summary description for DataTypeDatefieldMultiple. + /// + public class DataTypeDatefieldMultiple : datepicker.DateDataType + { + private interfaces.IDataEditor _Editor; + + public override Guid Id + { + get + { + return new Guid("B6FB1622-AFA5-4BBF-A3CC-D9672A442222"); + } + } + + public override string DataTypeName + { + get + { + return "Date/Time"; + } + } + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + { + dateField df = new dateField(Data); + df.ShowTime = true; + _Editor = df; + } + + return _Editor; + } + } + + } +} diff --git a/components/editorControls/datepicker/DateData.cs b/components/editorControls/datepicker/DateData.cs new file mode 100644 index 0000000000..ca34f5b343 --- /dev/null +++ b/components/editorControls/datepicker/DateData.cs @@ -0,0 +1,35 @@ +using System; + +namespace umbraco.editorControls.datepicker +{ + /// + /// Summary description for DateData. + /// + public class DateData : cms.businesslogic.datatype.DefaultData + { + public DateData(cms.businesslogic.datatype.BaseDataType DataType) : base(DataType) {} + + public override System.Xml.XmlNode ToXMl(System.Xml.XmlDocument d) + { + if (Value.ToString() != "") + return d.CreateTextNode(((DateTime) Value).ToString("s")); + else + return d.CreateTextNode(""); + } + + public override void MakeNew(int PropertyId) + { + this.PropertyId = PropertyId; + try + { +// Changed, do not insert todays date as default! +// System.Data.SqlTypes.SqlDateTime sqlDate = new System.Data.SqlTypes.SqlDateTime(DateTime.Now); +// this.Value = sqlDate; + } + catch + { + this.Value = ""; + } + } + } +} diff --git a/components/editorControls/datepicker/DateDataType.cs b/components/editorControls/datepicker/DateDataType.cs new file mode 100644 index 0000000000..f7d94f0519 --- /dev/null +++ b/components/editorControls/datepicker/DateDataType.cs @@ -0,0 +1,59 @@ +using System; + +namespace umbraco.editorControls.datepicker +{ + /// + /// Summary description for DateDataType. + /// + public class DateDataType : cms.businesslogic.datatype.BaseDataType,interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + { + dateField df = new dateField(Data); + df.ShowTime = false; + _Editor = df; + } + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new DateData(this); + return _baseData; + } + } + + + public override string DataTypeName + { + get {return "Date";} + } + + public override Guid Id + { + get {return new Guid("23e93522-3200-44e2-9f29-e61a6fcbb79a");} + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new DefaultPrevalueEditor(this,false); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/datepicker/dateField.cs b/components/editorControls/datepicker/dateField.cs new file mode 100644 index 0000000000..0cd06c7408 --- /dev/null +++ b/components/editorControls/datepicker/dateField.cs @@ -0,0 +1,68 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.ComponentModel; +using System.Collections; +using System.Globalization; + +namespace umbraco.editorControls +{ + /// + /// Summary description for dateField. + /// + [DefaultProperty("Text"), + ToolboxData("<{0}:dateField runat=server>")] + public class dateField : controls.datePicker, interfaces.IDataEditor + { + + interfaces.IData _data; + + public dateField(interfaces.IData Data) { + _data = Data; + } + + public virtual bool TreatAsRichTextEditor + { + get {return false;} + } + public bool ShowLabel + { + get {return true;} + } + + public Control Editor { + get {return this;} + } + + public void Save() + { + try + { + if (this.Text == String.Empty) + throw new FormatException(); + + DateTime date = DateTime.Parse(this.Text); + this.Text = date.ToString("yyyy-MM-dd") + " " + date.ToLongTimeString(); + _data.Value = date; + } + catch { + this.Text = ""; + _data.Value = null; + } + } + + protected override void OnInit(EventArgs e) + { + //base.ShowTime = false; + base.CustomMinutes = "00, 05, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55"; + + if (_data != null && _data.Value != null && _data.Value.ToString() != "") + this.Text = _data.Value.ToString(); + else { + base.EmptyDateAsDefault = true; + this.Text = ""; + } + base.OnInit(e); + } + } +} diff --git a/components/editorControls/dictionaryPicker/dictionaryPicker.cs b/components/editorControls/dictionaryPicker/dictionaryPicker.cs new file mode 100644 index 0000000000..6dbc1f31ed --- /dev/null +++ b/components/editorControls/dictionaryPicker/dictionaryPicker.cs @@ -0,0 +1,119 @@ +using System; +using System.Collections; +using System.Web.UI.WebControls; + +namespace umbraco.editorControls.dictionaryPicker +{ + /// + /// Summary description for dictionaryPicker. + /// + public class dictionaryPicker : System.Web.UI.WebControls.CheckBoxList, interfaces.IDataEditor + { + private interfaces.IData _data; + private SortedList _prevalues; + private string _text; + + public dictionaryPicker(interfaces.IData Data, SortedList Prevalues) + { + _data = Data; + _prevalues = Prevalues; + } + #region IDataEditor Members + public override String Text + { + get + { + if (_data != null && _data.Value != null) + return _data.Value.ToString(); + else + return ""; + + + } + set {_text = value;} + } + + public bool ShowLabel + { + get + { + // TODO: Add dictionaryPicker.ShowLabel getter implementation + return true; + } + } + + public System.Web.UI.Control Editor + { + get + { + return this; + } + } + + public void Save() + { + _text = ""; + foreach(ListItem li in base.Items) + { + if (li.Selected) + { + _text += li.Value + ","; + } + } + + if (_text.Length > 0) + _text = _text.Substring(0, _text.Length-1); + _data.Value = _text; + } + + public bool TreatAsRichTextEditor + { + get + { + // TODO: Add dictionaryPicker.TreatAsRichTextEditor getter implementation + return false; + } + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + + if (_prevalues.Keys.Count > 0) + { + // Find associated domain + int languageId = 0; + cms.businesslogic.web.Domain[] domains = library.GetCurrentDomains(((umbraco.cms.businesslogic.datatype.DefaultData)_data).NodeId); + if (domains != null) + if (domains.Length > -1) + languageId = domains[0].Language.id; + + + string key = _prevalues.GetByIndex(0).ToString(); + addDictionaries("", key, languageId); + } + } + + private void addDictionaries(string indent, string key, int language) + { + cms.businesslogic.Dictionary.DictionaryItem di = new cms.businesslogic.Dictionary.DictionaryItem(key); + + foreach(cms.businesslogic.Dictionary.DictionaryItem item in di.Children) + { + ListItem li; + if (language != 0) + li = new ListItem(indent + " " + item.Value(language), item.key); + else + li = new ListItem(indent + " " + item.Value(), item.key); + + if ((","+Text+",").IndexOf(","+li.Value.ToString()+",") > -1 && !Page.IsPostBack) + li.Selected = true; + this.Items.Add(li); + addDictionaries(indent + "--", item.key, language); + } + } + + + #endregion + } +} diff --git a/components/editorControls/dictionaryPicker/dictionaryPickerDataType.cs b/components/editorControls/dictionaryPicker/dictionaryPickerDataType.cs new file mode 100644 index 0000000000..fc2035f0b0 --- /dev/null +++ b/components/editorControls/dictionaryPicker/dictionaryPickerDataType.cs @@ -0,0 +1,74 @@ +using System; + +namespace umbraco.editorControls.dictionaryPicker +{ + /// + /// Summary description for dictionaryPickerDataType. + /// + public class dictionaryPickerDataType : cms.businesslogic.datatype.BaseDataType, interfaces.IDataType + { + + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + + public dictionaryPickerDataType() + { + // + // TODO: Add constructor logic here + // + } + #region IDataType Members + + public override umbraco.interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + + public override Guid Id + { + get + { + // TODO: Add dictionaryPickerDataType.Id getter implementation + return new Guid ("17B70066-F764-407d-AB05-3717F1E1C513"); + } + } + + public override umbraco.interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new dictionaryPicker(Data, ((KeyValuePrevalueEditor)PrevalueEditor).Prevalues); + return _Editor; + } + } + + + public override string DataTypeName + { + get + { + // TODO: Add dictionaryPickerDataType.DataTypeName getter implementation + return "Dictionary Picker"; + } + } + + public override umbraco.interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new KeyValuePrevalueEditor(this); + return _prevalueeditor; + } + } + + #endregion + } +} diff --git a/components/editorControls/dropdownlist/DropDownDataType.cs b/components/editorControls/dropdownlist/DropDownDataType.cs new file mode 100644 index 0000000000..fedc2abb5f --- /dev/null +++ b/components/editorControls/dropdownlist/DropDownDataType.cs @@ -0,0 +1,55 @@ +using System; + +namespace umbraco.editorControls.dropdownlist +{ + /// + /// Summary description for ColorPickerDataType. + /// + public class DropdownListDataType : cms.businesslogic.datatype.BaseDataType, interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private KeyValuePrevalueEditor _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + { + _Editor = new dropdown(Data,((KeyValuePrevalueEditor)PrevalueEditor).Prevalues); + } + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new DefaultDataKeyValue(this); + return _baseData; + } + } + public override string DataTypeName + { + get {return "Dropdown list";} + } + + public override Guid Id + { + get {return new Guid("a74ea9c9-8e18-4d2a-8cf6-73c6206c5da6");} + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new KeyValuePrevalueEditor(this); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/dropdownlist/dropDownKeysDataType.cs b/components/editorControls/dropdownlist/dropDownKeysDataType.cs new file mode 100644 index 0000000000..4806538d2f --- /dev/null +++ b/components/editorControls/dropdownlist/dropDownKeysDataType.cs @@ -0,0 +1,55 @@ +using System; + +namespace umbraco.editorControls.dropdownlist +{ + /// + /// Summary description for ColorPickerDataType. + /// + public class DropdownListKeysDataType : cms.businesslogic.datatype.BaseDataType, interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private KeyValuePrevalueEditor _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + { + _Editor = new dropdown(Data,((KeyValuePrevalueEditor)PrevalueEditor).Prevalues); + } + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + public override string DataTypeName + { + get {return "Dropdown list, publishing keys";} + } + + public override Guid Id + { + get {return new Guid("a74ea9e1-8e18-4d2a-8cf6-73c6206c5da6");} + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new KeyValuePrevalueEditor(this); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/dropdownlist/dropdown.cs b/components/editorControls/dropdownlist/dropdown.cs new file mode 100644 index 0000000000..fc9c7490fe --- /dev/null +++ b/components/editorControls/dropdownlist/dropdown.cs @@ -0,0 +1,54 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.ComponentModel; +using System.Collections; + +namespace umbraco.editorControls +{ + public class dropdown : System.Web.UI.WebControls.DropDownList, interfaces.IDataEditor + { + private interfaces.IData _data; + private SortedList _prevalues; + + public dropdown(interfaces.IData Data, SortedList Prevalues) + { + _data = Data; + _prevalues = Prevalues; + } + + public Control Editor { + get {return this;} + } + + public virtual bool TreatAsRichTextEditor + { + get {return false;} + } + public virtual bool ShowLabel + { + get {return true;} + } + + public void Save() + { + string tmpVal = ""; + if (this.SelectedIndex > 0) + tmpVal = this.SelectedValue; + _data.Value = tmpVal; + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + foreach (object key in _prevalues.Keys) + { + this.Items.Add(new ListItem(_prevalues[key].ToString(),key.ToString())); + } + base.Items.Insert(0, new ListItem(ui.Text("choose") + "...","")); + + if (_data != null && _data.Value != null) + this.SelectedValue = _data.Value.ToString(); + } + } +} \ No newline at end of file diff --git a/components/editorControls/folderbrowser/DataTypeFolderbrowser.cs b/components/editorControls/folderbrowser/DataTypeFolderbrowser.cs new file mode 100644 index 0000000000..3bd72f959c --- /dev/null +++ b/components/editorControls/folderbrowser/DataTypeFolderbrowser.cs @@ -0,0 +1,63 @@ +using System; + +namespace umbraco.editorControls.folderbrowser +{ + /// + /// Summary description for DataTypeFolderbrowser. + /// + /// + /// Summary description for DataTypeUploadField. + /// + public class DataTypeFolderBrowser: cms.businesslogic.datatype.BaseDataType,interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private cms.businesslogic.datatype.DefaultData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new folderBrowser((umbraco.cms.businesslogic.datatype.DefaultData)Data); + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + + public override Guid Id + { + get + { + return new Guid ("CCCD4AE9-F399-4ED2-8038-2E88D19E810C"); + } + } + + public override string DataTypeName + { + get + { + return "Folder browser"; + } + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new DefaultPrevalueEditor(this,false); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/folderbrowser/folderBrowser.cs b/components/editorControls/folderbrowser/folderBrowser.cs new file mode 100644 index 0000000000..7056e08c25 --- /dev/null +++ b/components/editorControls/folderbrowser/folderBrowser.cs @@ -0,0 +1,70 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.ComponentModel; +using System.IO; + +namespace umbraco.editorControls +{ + /// + /// Summary description for folderBrowser. + /// + public class folderBrowser : System.Web.UI.WebControls.WebControl, interfaces.IDataEditor + { + private cms.businesslogic.datatype.DefaultData _data; + public folderBrowser(umbraco.cms.businesslogic.datatype.DefaultData Data) + {_data = Data;} + + public Control Editor {get{return this;}} + + #region IDataField Members + + + public virtual bool TreatAsRichTextEditor + { + get {return false;} + } + public bool ShowLabel + { + get + { + return true; + } + } + + + + + public void Save() + { + + } + + protected override void Render(HtmlTextWriter writer) + { + uploadfield.DataTypeUploadField uft = new uploadfield.DataTypeUploadField(); + + cms.businesslogic.Content c = cms.businesslogic.media.Media.GetContentFromVersion(_data.Version); + foreach (BusinessLogic.console.IconI cc in c.Children) + { + cms.businesslogic.media.Media m = new cms.businesslogic.media.Media(cc.UniqueId); + foreach (cms.businesslogic.property.Property p in m.getProperties) + { + if (p.PropertyType.DataTypeDefinition.DataType.Id == uft.Id && p.Value.ToString() != "") + { + // Check for thumbnail! + string fileNameOrg = p.Value.ToString(); + string ext = fileNameOrg.Substring(fileNameOrg.LastIndexOf(".")+1, fileNameOrg.Length-fileNameOrg.LastIndexOf(".")-1); + string fileNameThumb = umbraco.GlobalSettings.Path + "/.." + fileNameOrg.Replace("."+ext, "_thumb.jpg"); + if (File.Exists(System.Web.HttpContext.Current.Server.MapPath(fileNameThumb))) + { + writer.WriteLine("\""   "); + } + } + } + } + base.Render (writer); + } + #endregion + } +} diff --git a/components/editorControls/label/DataTypeNoEdit.cs b/components/editorControls/label/DataTypeNoEdit.cs new file mode 100644 index 0000000000..bda9ecaefd --- /dev/null +++ b/components/editorControls/label/DataTypeNoEdit.cs @@ -0,0 +1,52 @@ +using System; + +namespace umbraco.editorControls.label +{ + /// + /// Summary description for DataTypeNoEdit. + /// + public class DataTypeNoEdit : cms.businesslogic.datatype.BaseDataType,interfaces.IDataType + { + + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + + public override string DataTypeName {get {return "No edit";}} + public override Guid Id {get {return new Guid("6c738306-4c17-4d88-b9bd-6546f3771597");}} + + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new noEdit(Data); + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new DefaultPrevalueEditor(this,false); + return _prevalueeditor; + } + } + + + + } +} diff --git a/components/editorControls/label/noEdit.cs b/components/editorControls/label/noEdit.cs new file mode 100644 index 0000000000..9c791c32c5 --- /dev/null +++ b/components/editorControls/label/noEdit.cs @@ -0,0 +1,47 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +namespace umbraco.editorControls +{ + public class noEdit : System.Web.UI.WebControls.Label, interfaces.IDataEditor + { + private interfaces.IData _data; + private bool labelRefreshed = false; + + public noEdit(interfaces.IData Data) { + _data = Data; + } + public virtual bool TreatAsRichTextEditor + { + get {return false;} + } + public bool ShowLabel {get {return true;}} + + public void Save() + { + // Uncommented this as a label should *never* update itself via ui +// _data.Value = this.Text; + } + + public void RefreshLabel(string content) + { + Text = content; + labelRefreshed = true; + } + + public Control Editor {get {return this;}} + + protected override void OnInit(EventArgs e) + { + if (!labelRefreshed && (_data != null && _data.Value != null)) + Text = _data.Value.ToString(); + + base.OnInit(e); + } + + //public override string Text { + // get {return _data.Value.ToString();} + //} + } +} \ No newline at end of file diff --git a/components/editorControls/listbox/ListBoxDataType.cs b/components/editorControls/listbox/ListBoxDataType.cs new file mode 100644 index 0000000000..8d5fd3c687 --- /dev/null +++ b/components/editorControls/listbox/ListBoxDataType.cs @@ -0,0 +1,55 @@ +using System; + +namespace umbraco.editorControls.listbox +{ + /// + /// Summary description for ColorPickerDataType. + /// + public class ListBoxDataType : cms.businesslogic.datatype.BaseDataType, interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private KeyValuePrevalueEditor _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + { + _Editor = new dropdownMultiple(Data,((KeyValuePrevalueEditor)PrevalueEditor).Prevalues); + } + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new DefaultDataKeyValue(this); + return _baseData; + } + } + + public override string DataTypeName + { + get {return "Dropdown list multiple";} + } + + public override Guid Id + { + get {return new Guid("928639ED-9C73-4028-920C-1E55DBB68783");} + } + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new KeyValuePrevalueEditor(this); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/listbox/ListBoxKeysDataType.cs b/components/editorControls/listbox/ListBoxKeysDataType.cs new file mode 100644 index 0000000000..5fcda7395a --- /dev/null +++ b/components/editorControls/listbox/ListBoxKeysDataType.cs @@ -0,0 +1,55 @@ +using System; + +namespace umbraco.editorControls.listbox +{ + /// + /// Summary description for ColorPickerDataType. + /// + public class ListBoxKeysDataType : cms.businesslogic.datatype.BaseDataType, interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private KeyValuePrevalueEditor _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + { + _Editor = new dropdownMultiple(Data,((KeyValuePrevalueEditor)PrevalueEditor).Prevalues); + } + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + + public override string DataTypeName + { + get {return "Dropdown list multiple, publish keys";} + } + + public override Guid Id + { + get {return new Guid("928639AA-9C73-4028-920C-1E55DBB68783");} + } + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new KeyValuePrevalueEditor(this); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/listbox/dropdownMultiple.cs b/components/editorControls/listbox/dropdownMultiple.cs new file mode 100644 index 0000000000..4dfb0cd0cb --- /dev/null +++ b/components/editorControls/listbox/dropdownMultiple.cs @@ -0,0 +1,83 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.ComponentModel; +using System.Collections; + +namespace umbraco.editorControls +{ + /// + /// Summary description for dropdownMultiple. + /// + public class dropdownMultiple : System.Web.UI.WebControls.ListBox, interfaces.IDataEditor + { + private String _text; + + interfaces.IData _data; + SortedList _prevalues; + public dropdownMultiple(interfaces.IData Data,SortedList Prevalues) + { + _data = Data; + _prevalues = Prevalues; + } + + public Control Editor { get {return this;}} + + public virtual bool TreatAsRichTextEditor + { + get {return false;} + } + public virtual bool ShowLabel + { + get {return true;} + } + + //public override String Text + //{ + // get { + + // return _data.Value.ToString(); + + // } + // set {_text = value;} + //} + + public void Save() + { + _text = ""; + foreach(ListItem li in base.Items) + { + if (li.Selected) + { + _text += li.Value + ","; + } + } + + if (_text.Length > 0) + _text = _text.Substring(0, _text.Length-1); + _data.Value = _text; + + + } + + protected override void OnInit(EventArgs e) + { + base.SelectionMode = System.Web.UI.WebControls.ListSelectionMode.Multiple; + + if (_data != null && _data.Value != null) + _text = _data.Value.ToString(); + + base.OnInit(e); + + foreach (object key in _prevalues.Keys) + { + ListItem li = new ListItem(_prevalues[key].ToString(),key.ToString()); + + if ((","+_text+",").IndexOf(","+li.Value.ToString()+",") > -1) + li.Selected = true; + + Items.Add(li); + } + } + } +} diff --git a/components/editorControls/mediapicker/MediaPickerDataType.cs b/components/editorControls/mediapicker/MediaPickerDataType.cs new file mode 100644 index 0000000000..f746d6fe7b --- /dev/null +++ b/components/editorControls/mediapicker/MediaPickerDataType.cs @@ -0,0 +1,59 @@ +using System; + +namespace umbraco.editorControls.mediapicker +{ + /// + /// Summary description for MemberPickerDataType. + /// + public class MemberPickerDataType : cms.businesslogic.datatype.BaseDataType,interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new mediaChooser(Data); + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + + + public override Guid Id + { + get + { + return new Guid ("EAD69342-F06D-4253-83AC-28000225583B"); + } + } + public override string DataTypeName + { + get + { + return "Media Picker"; + } + } + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new DefaultPrevalueEditor(this,false); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/mediapicker/mediaChooser.cs b/components/editorControls/mediapicker/mediaChooser.cs new file mode 100644 index 0000000000..5c9328b8a1 --- /dev/null +++ b/components/editorControls/mediapicker/mediaChooser.cs @@ -0,0 +1,125 @@ +using System; +using System.Web.UI; +using umbraco.cms.businesslogic.datatype; +using umbraco.cms.presentation.Trees; +namespace umbraco.editorControls +{ + /// + /// Summary description for mediaChooser. + /// + [ClientDependency(1, ClientDependencyType.Css, "js/submodal/submodal.css", true)] + [ClientDependency(1, ClientDependencyType.Javascript, "js/submodal/common.js", true)] + [ClientDependency(2, ClientDependencyType.Javascript, "js/submodal/submodal.js", true, "initPopUp")] + [ClientDependency(3, ClientDependencyType.Javascript, "webservices/legacyAjaxCalls.asmx/js", true)] + [ValidationProperty("Value")] + public class mediaChooser : System.Web.UI.WebControls.HiddenField, interfaces.IDataEditor + { + interfaces.IData _data; + public mediaChooser(interfaces.IData Data) + { + _data = Data; + } + + public System.Web.UI.Control Editor { get { return this; } } + #region IDataField Members + + //private string _text; + + public virtual bool TreatAsRichTextEditor + { + get { return false; } + } + + public bool ShowLabel + { + get + { + return true; + } + } + + public void Save() + { + if (base.Value.Trim() != "") + _data.Value = base.Value; + else + _data.Value = null; + } + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + if (_data != null && _data.Value != null && !String.IsNullOrEmpty(_data.Value.ToString())) + { + base.Value = _data.Value.ToString(); + } + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + + base.Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "subModal", ""); + + // We need to make sure we have a reference to the legacy ajax calls in the scriptmanager + presentation.webservices.ajaxHelpers.EnsureLegacyCalls(base.Page); + + } + + protected override void Render(System.Web.UI.HtmlTextWriter writer) + { + + string tempTitle = ""; + string deleteLink = "   " + ui.Text("delete") + "   "; + try + { + if (base.Value != "") + { + tempTitle = new cms.businesslogic.CMSNode(int.Parse(base.Value)).Text; + } + } + catch { } + + string strScript = "function " + this.ClientID + "_chooseId() {" + + "\nshowPopWin('" + TreeService.GetPickerUrl(true,"media","media") + "', 300, 400, " + ClientID + "_saveId)" + + // "\nvar treePicker = window.showModalDialog(, 'treePicker', 'dialogWidth=350px;dialogHeight=300px;scrollbars=no;center=yes;border=thin;help=no;status=no') " + + "\n}" + + "\nfunction " + ClientID + "_saveId(treePicker) {" + + "\nsetTimeout('" + ClientID + "_saveIdDo(' + treePicker + ')', 200);" + + "\n}" + + "\nfunction " + ClientID + "_saveIdDo(treePicker) {" + + "\nif (treePicker != undefined) {" + + "\ndocument.getElementById(\"" + this.ClientID + "\").value = treePicker;" + + "\nif (treePicker > 0) {" + + "\numbraco.presentation.webservices.legacyAjaxCalls.GetNodeName(treePicker, " + this.ClientID + "_updateContentTitle" + ");" + + "\n} " + + "\n}" + + "\n} " + + "\nfunction " + this.ClientID + "_updateContentTitle(retVal) {" + + "\ndocument.getElementById(\"" + this.ClientID + "_title\").innerHTML = \"\" + retVal + \"" + deleteLink.Replace("\"", "\\\"") + "\";" + + "\n}" + + "\nfunction " + this.ClientID + "_clear() {" + + "\ndocument.getElementById(\"" + this.ClientID + "_title\").innerHTML = \"\";" + + "\ndocument.getElementById(\"" + this.ClientID + "\").value = \"\";" + + "\n}"; + + try + { + if (ScriptManager.GetCurrent(Page).IsInAsyncPostBack) + ScriptManager.RegisterClientScriptBlock(this, this.GetType(), this.ClientID + "_chooseId", strScript, true); + else + Page.ClientScript.RegisterStartupScript(this.GetType(), this.ClientID + "_chooseId", strScript, true); + } + catch + { + Page.ClientScript.RegisterStartupScript(this.GetType(), this.ClientID + "_chooseId", strScript, true); + } + // Clear remove link if text if empty + if (base.Value == "") + deleteLink = ""; + writer.WriteLine("" + tempTitle + "" + deleteLink + "" + ui.Text("choose") + "...   ");//   "); + base.Render(writer); + } + #endregion + } +} diff --git a/components/editorControls/memberpicker/MemberPickerDataType.cs b/components/editorControls/memberpicker/MemberPickerDataType.cs new file mode 100644 index 0000000000..37cf84bc75 --- /dev/null +++ b/components/editorControls/memberpicker/MemberPickerDataType.cs @@ -0,0 +1,53 @@ +using System; + +namespace umbraco.editorControls.memberpicker +{ + /// + /// Summary description for MemberPickerDataType. + /// + public class MemberPickerDataType : cms.businesslogic.datatype.BaseDataType,interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new memberPicker(Data); + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + public override string DataTypeName + { + get {return "Member Picker";} + } + + public override Guid Id + { + get {return new Guid("39F533E4-0551-4505-A64B-E0425C5CE775");} + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new DefaultPrevalueEditor(this,false); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/memberpicker/memberPicker.cs b/components/editorControls/memberpicker/memberPicker.cs new file mode 100644 index 0000000000..e43ea3e1fb --- /dev/null +++ b/components/editorControls/memberpicker/memberPicker.cs @@ -0,0 +1,87 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.ComponentModel; +using System.Data; + +using umbraco.BusinessLogic; +using umbraco.DataLayer; + +namespace umbraco.editorControls +{ + /// + /// Summary description for memberPicker. + /// + public class memberPicker : System.Web.UI.WebControls.DropDownList, interfaces.IDataEditor + { + + //private String _text; + + interfaces.IData _data; + public memberPicker(interfaces.IData Data) + { + _data = Data; + } + + public virtual bool TreatAsRichTextEditor + { + get {return false;} + } + public virtual bool ShowLabel + { + get {return true;} + } + + public Control Editor { + get {return this;} + } + + //public override string Text + //{ + // get + // { + // if (!Page.IsPostBack) + // { + // _text = _data.Value.ToString(); + // } + // return _text; + // } + //} + public void Save() + { + _data.Value = base.SelectedValue; + + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + IRecordsReader dropdownData = Application.SqlHelper.ExecuteReader("select id, text from umbracoNode where nodeObjectType = '39EB0F98-B348-42A1-8662-E7EB18487560' order by text"); + base.DataValueField = "id"; + base.DataTextField = "text"; + base.DataSource = dropdownData; + base.DataBind(); + base.Items.Insert(0, new ListItem(ui.Text("choose") + "...","")); + + base.SelectedValue = _data.Value.ToString(); + + // Iterate on the control items and mark fields by match them with the Text property! + //foreach(ListItem li in base.Items) + //{ + // if ((","+base.SelectedValue+",").IndexOf(","+li.Value.ToString()+",") > -1) + // li.Selected = true; + //} + + dropdownData.Close(); + } + + /// + /// Render this control to the output parameter specified. + /// + /// The HTML writer to write out to + protected override void Render(HtmlTextWriter output) + { + base.Render(output); + } + } +} diff --git a/components/editorControls/numberfield/DataInteger.cs b/components/editorControls/numberfield/DataInteger.cs new file mode 100644 index 0000000000..2144be1ec0 --- /dev/null +++ b/components/editorControls/numberfield/DataInteger.cs @@ -0,0 +1,19 @@ +using System; + +namespace umbraco.editorControls.numberfield +{ + /// + /// Summary description for DataInteger. + /// + public class DataInteger : cms.businesslogic.datatype.DefaultData + { + public DataInteger(cms.businesslogic.datatype.BaseDataType DataType) : base(DataType) {} + + public override void MakeNew(int PropertyId) { + this.PropertyId = PropertyId; + string defaultValue = ((DefaultPrevalueEditor) _dataType.PrevalueEditor).Prevalue; + if (defaultValue.Trim() != "") + this.Value = defaultValue; + } + } +} diff --git a/components/editorControls/numberfield/DataTypeInteger.cs b/components/editorControls/numberfield/DataTypeInteger.cs new file mode 100644 index 0000000000..cbf4dac99c --- /dev/null +++ b/components/editorControls/numberfield/DataTypeInteger.cs @@ -0,0 +1,55 @@ +using System; + +namespace umbraco.editorControls.numberfield +{ + /// + /// Summary description for IDataTypenteger. + /// + public class IDataTypenteger : cms.businesslogic.datatype.BaseDataType,interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + + public override string DataTypeName + { + get {return "Integer";} + } + + public override Guid Id + { + get {return new Guid("1413afcb-d19a-4173-8e9a-68288d2a73b8");} + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new DefaultPrevalueEditor(this,true); + return _prevalueeditor; + } + } + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new numberField(Data); + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new DataInteger(this); + return _baseData; + } + } + + } +} diff --git a/components/editorControls/numberfield/numberField.cs b/components/editorControls/numberfield/numberField.cs new file mode 100644 index 0000000000..0d2651baec --- /dev/null +++ b/components/editorControls/numberfield/numberField.cs @@ -0,0 +1,62 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.ComponentModel; + +namespace umbraco.editorControls +{ + public class numberField : System.Web.UI.WebControls.TextBox, interfaces.IDataEditor + { + private interfaces.IData _data; + public numberField(interfaces.IData Data) { + _data = Data; + } + + + public Control Editor { + get{return this;} + + } + public virtual bool TreatAsRichTextEditor + { + get {return false;} + } + public bool ShowLabel + { + get {return true;} + } + + public void Save() + { + if (Text.Trim() != "") + _data.Value = Text; + else + _data.Value = null; + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + CssClass = "umbEditorNumberField"; + // load data + if (_data != null && _data.Value != null) + this.Text = _data.Value.ToString(); + } + + public override string Text + { + get { return base.Text; } + set { + try { + if (value != null) + base.Text = Convert.ToInt32(value).ToString(); + } + catch { + base.Text = ""; + System.Web.HttpContext.Current.Trace.Warn("Numberfield", "Value has to be an integer (" + value + ")"); + } + } + } + + } +} diff --git a/components/editorControls/pagepicker/PagePickerDataType.cs b/components/editorControls/pagepicker/PagePickerDataType.cs new file mode 100644 index 0000000000..18632cb13e --- /dev/null +++ b/components/editorControls/pagepicker/PagePickerDataType.cs @@ -0,0 +1,62 @@ +using System; + +namespace umbraco.editorControls.pagepicker +{ + /// + /// Summary description for PagePickerDataType. + /// + public class PagePickerDataType : cms.businesslogic.datatype.BaseDataType, interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new pagePicker(Data); + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + + + public override Guid Id + { + get + { + return new Guid ("158AA029-24ED-4948-939E-C3DA209E5FBA"); + } + } + + public override string DataTypeName + { + get + { + // TODO: Add mediaChooser.ControlName getter implementation + return "Content Picker"; + } + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new DefaultPrevalueEditor(this,false); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/pagepicker/pagePicker.cs b/components/editorControls/pagepicker/pagePicker.cs new file mode 100644 index 0000000000..ed93854e08 --- /dev/null +++ b/components/editorControls/pagepicker/pagePicker.cs @@ -0,0 +1,120 @@ +using System; +using System.Web.UI; +using umbraco.cms.businesslogic.datatype; +using umbraco.cms.presentation.Trees; +namespace umbraco.editorControls +{ + /// + /// Summary description for pagePicker. + /// + [ClientDependency(1, ClientDependencyType.Css, "js/submodal/submodal.css", true)] + [ClientDependency(1, ClientDependencyType.Javascript, "js/submodal/common.js", true)] + [ClientDependency(2, ClientDependencyType.Javascript, "js/submodal/submodal.js", true, "initPopUp")] + [ClientDependency(3, ClientDependencyType.Javascript, "webservices/legacyAjaxCalls.asmx/js", true)] + [ValidationProperty("Value")] + public class pagePicker : System.Web.UI.WebControls.HiddenField, interfaces.IDataEditor + { + interfaces.IData _data; + public pagePicker(interfaces.IData Data) + { + _data = Data; + } + #region IDataField Members + + //private string _text; + + + public System.Web.UI.Control Editor { get { return this; } } + + public virtual bool TreatAsRichTextEditor + { + get { return false; } + } + public bool ShowLabel + { + get + { + return true; + } + } + + public void Save() + { + //_text = helper.Request(this.ClientID); + if (base.Value.Trim() != "") + _data.Value = base.Value.Trim(); + else + _data.Value = null; + } + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + base.Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "subModal", ""); + + // We need to make sure we have a reference to the legacy ajax calls in the scriptmanager + presentation.webservices.ajaxHelpers.EnsureLegacyCalls(base.Page); + + if (_data != null && _data.Value != null) + base.Value = _data.Value.ToString(); + } + + + protected override void Render(System.Web.UI.HtmlTextWriter writer) + { + + string tempTitle = ""; + string deleteLink = "   " + ui.Text("delete") + "   "; + try + { + if (base.Value.Trim() != "") + { + tempTitle = new cms.businesslogic.CMSNode(int.Parse(base.Value.Trim())).Text; + } + } + catch { } + + string strScript = "function " + this.ClientID + "_chooseId() {" + + "\nshowPopWin('" + TreeService.GetPickerUrl(true,"content","content") + "', 300, 400, " + ClientID + "_saveId);" + + //"\nvar treePicker = window.showModalDialog(, 'treePicker', 'dialogWidth=350px;dialogHeight=300px;scrollbars=no;center=yes;border=thin;help=no;status=no') " + + "\n}" + + "\nfunction " + ClientID + "_saveId(treePicker) {" + + "\nsetTimeout('" + ClientID + "_saveIdDo(' + treePicker + ')', 200);" + + "\n}" + + "\nfunction " + ClientID + "_saveIdDo(treePicker) {" + + "\nif (treePicker != undefined) {" + + "\ndocument.getElementById(\"" + this.ClientID + "\").value = treePicker;" + + "\nif (treePicker > 0) {" + + "\numbraco.presentation.webservices.legacyAjaxCalls.GetNodeName(treePicker, " + this.ClientID + "_updateContentTitle" + ");" + + "\n} " + + "\n}" + + "\n} " + + "\nfunction " + this.ClientID + "_updateContentTitle(retVal) {" + + "\ndocument.getElementById(\"" + this.ClientID + "_title\").innerHTML = \"\" + retVal + \"" + deleteLink.Replace("\"", "\\\"") + "\";" + + "\n}" + + "\nfunction " + this.ClientID + "_clear() {" + + "\ndocument.getElementById(\"" + this.ClientID + "_title\").innerHTML = \"\";" + + "\ndocument.getElementById(\"" + this.ClientID + "\").value = \"\";" + + "\n}"; + + try + { + if (ScriptManager.GetCurrent(Page).IsInAsyncPostBack) + ScriptManager.RegisterClientScriptBlock(this, this.GetType(), this.ClientID + "_chooseId", strScript, true); + else + Page.ClientScript.RegisterStartupScript(this.GetType(), this.ClientID + "_chooseId", strScript, true); + } + catch + { + Page.ClientScript.RegisterStartupScript(this.GetType(), this.ClientID + "_chooseId", strScript, true); + } + // Clear remove link if text if empty + if (base.Value.Trim() == "") + deleteLink = ""; + writer.WriteLine("" + tempTitle + "" + deleteLink + "" + ui.Text("choose") + "...   ");//"); + base.Render(writer); + } + #endregion + } +} diff --git a/components/editorControls/radiobuttonlist/RadioButtonListDataType.cs b/components/editorControls/radiobuttonlist/RadioButtonListDataType.cs new file mode 100644 index 0000000000..736b49b328 --- /dev/null +++ b/components/editorControls/radiobuttonlist/RadioButtonListDataType.cs @@ -0,0 +1,54 @@ +using System; + +namespace umbraco.editorControls.radiobuttonlist +{ + /// + /// Summary description for ColorPickerDataType. + /// + public class RadioButtonListDataType : cms.businesslogic.datatype.BaseDataType, interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private KeyValuePrevalueEditor _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + { + _Editor = new radiobox(Data,((KeyValuePrevalueEditor)PrevalueEditor).Prevalues); + } + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + public override string DataTypeName + { + get {return "Radiobutton list";} + } + public override Guid Id + { + get {return new Guid("A52C7C1C-C330-476E-8605-D63D3B84B6A6");} + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new KeyValuePrevalueEditor(this); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/radiobuttonlist/radiobox.cs b/components/editorControls/radiobuttonlist/radiobox.cs new file mode 100644 index 0000000000..0e30add344 --- /dev/null +++ b/components/editorControls/radiobuttonlist/radiobox.cs @@ -0,0 +1,54 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.ComponentModel; +using System.Collections; +namespace umbraco.editorControls +{ + public class radiobox : System.Web.UI.WebControls.RadioButtonList, interfaces.IDataEditor + { + private interfaces.IData _data; + private SortedList _prevalues; + + public radiobox(interfaces.IData Data, SortedList Prevalues) + { + _data = Data; + _prevalues = Prevalues; + } + + public Control Editor + { + get {return this;} + } + + public virtual bool TreatAsRichTextEditor + { + get {return false;} + } + public virtual bool ShowLabel + { + get {return true;} + } + + public void Save() + { + string tmpVal = ""; + tmpVal = this.SelectedValue; + _data.Value = tmpVal; + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + foreach (object key in _prevalues.Keys) + { + this.Items.Add(new ListItem(_prevalues[key].ToString(),key.ToString())); + } + + try { + if (_data != null && _data.Value != null) + this.SelectedValue = _data.Value.ToString(); + } catch {} + } + } +} diff --git a/components/editorControls/relatedlinks/PagePickerDataExtractor.cs b/components/editorControls/relatedlinks/PagePickerDataExtractor.cs new file mode 100644 index 0000000000..3d3d4ec766 --- /dev/null +++ b/components/editorControls/relatedlinks/PagePickerDataExtractor.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Text; +using umbraco.interfaces; + +namespace umbraco.editorControls.relatedlinks +{ + /// + /// Allows for the extraction of the link ID for the selected node of the + /// PagePicker (aka content picker) class for integration of the PagePicker + /// in another datatype. + /// This class replaces the database linkup that normally holds the data and + /// stores the data locally in memory and allows for easy access to the + /// data (after the IDataEditor has performed a save()). + /// This class was not designed for, but might work equally well for other datatypes. + /// + class PagePickerDataExtractor : IData + { + private object _value; + + public PagePickerDataExtractor() { } + public PagePickerDataExtractor(object o) + { + Value = o; + } + + #region IData Members + + public void Delete() + { + throw new NotImplementedException(); + } + + public void MakeNew(int PropertyId) + { + throw new NotImplementedException(); + } + + public int PropertyId + { + set { throw new NotImplementedException(); } + } + + public System.Xml.XmlNode ToXMl(System.Xml.XmlDocument d) + { + throw new NotImplementedException(); + } + + public object Value + { + get + { + return _value; + } + set + { + _value = value; + } + } + + #endregion + } +} diff --git a/components/editorControls/relatedlinks/RelatedLinksData.cs b/components/editorControls/relatedlinks/RelatedLinksData.cs new file mode 100644 index 0000000000..89287bcdb4 --- /dev/null +++ b/components/editorControls/relatedlinks/RelatedLinksData.cs @@ -0,0 +1,25 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using System.Xml; + +namespace umbraco.editorControls.relatedlinks +{ + public class RelatedLinksData : umbraco.cms.businesslogic.datatype.DefaultData + { + public RelatedLinksData(umbraco.cms.businesslogic.datatype.BaseDataType DataType) : base(DataType) { } + + public override System.Xml.XmlNode ToXMl(System.Xml.XmlDocument data) + { + if (this.Value != null && !String.IsNullOrEmpty(this.Value.ToString())) { + XmlDocument xd = new XmlDocument(); + xd.LoadXml(this.Value.ToString()); + return data.ImportNode(xd.DocumentElement, true); + } else { + return base.ToXMl(data); + } + } + + } +} diff --git a/components/editorControls/relatedlinks/RelatedLinksDataEditor.cs b/components/editorControls/relatedlinks/RelatedLinksDataEditor.cs new file mode 100644 index 0000000000..db8b5ce776 --- /dev/null +++ b/components/editorControls/relatedlinks/RelatedLinksDataEditor.cs @@ -0,0 +1,325 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web.UI; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; +using System.Web.UI.WebControls.WebParts; +using System.Xml; +using umbraco.interfaces; +using umbraco.editorControls; +using umbraco.cms.businesslogic; +using umbraco.cms.businesslogic.datatype; + +namespace umbraco.editorControls.relatedlinks +{ + [ValidationProperty("IsValid")] + public class RelatedLinksDataEditor : UpdatePanel, IDataEditor + { + private umbraco.interfaces.IData _data; + string _configuration; + + private ListBox _listboxLinks; + private Button _buttonUp; + private Button _buttonDown; + private Button _buttonDelete; + private TextBox _textboxLinkTitle; + private CheckBox _checkNewWindow; + private TextBox _textBoxExtUrl; + private Button _buttonAddExtUrl; + private Button _buttonAddIntUrlCP; + private XmlDocument _xml; + + private pagePicker _pagePicker; + private PagePickerDataExtractor _pagePickerExtractor; + + public RelatedLinksDataEditor(umbraco.interfaces.IData Data, string Configuration) + { + _data = Data; + _configuration = Configuration; + } + + public virtual bool TreatAsRichTextEditor + { + get { return false; } + } + + /// + /// Internal logic for validation controls to detect whether or not it's valid (has to be public though) + /// + /// Am I valid? + public string IsValid + { + get { + if (_listboxLinks != null) { + if (_listboxLinks.Items.Count > 0) + return "Valid"; + } + return ""; + } + } + + public bool ShowLabel + { + get { return true; } + } + + public Control Editor { get { return this; } } + + //Creates and saves a xml format of the content of the _listboxLinks + // + // + // + // + //We could adapt the global xml at every adjustment, but this implementation is easier + // (and possibly more efficient). + public void Save() + { + XmlDocument doc = createBaseXmlDocument(); + XmlNode root = doc.DocumentElement; + foreach (ListItem item in _listboxLinks.Items) + { + string value = item.Value; + + XmlNode newNode = doc.CreateElement("link"); + + XmlNode titleAttr = doc.CreateNode(XmlNodeType.Attribute, "title", null); + titleAttr.Value = item.Text; + newNode.Attributes.SetNamedItem(titleAttr); + + XmlNode linkAttr = doc.CreateNode(XmlNodeType.Attribute, "link", null); + linkAttr.Value = value.Substring(2); + newNode.Attributes.SetNamedItem(linkAttr); + + XmlNode typeAttr = doc.CreateNode(XmlNodeType.Attribute, "type", null); + if (value.Substring(0, 1).Equals("i")) + typeAttr.Value = "internal"; + else + typeAttr.Value = "external"; + newNode.Attributes.SetNamedItem(typeAttr); + + XmlNode windowAttr = doc.CreateNode(XmlNodeType.Attribute, "newwindow", null); + if (value.Substring(1, 1).Equals("n")) + windowAttr.Value = "1"; + else + windowAttr.Value = "0"; + newNode.Attributes.SetNamedItem(windowAttr); + + root.AppendChild(newNode); + } + + this._data.Value = doc.InnerXml; + } + + //Draws the controls, only gets called for the first drawing of the page, not for each postback + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + try + { + _xml = new XmlDocument(); + _xml.LoadXml(_data.Value.ToString()); + + } + catch + { + _xml = createBaseXmlDocument(); + } + + _listboxLinks = new ListBox(); + _listboxLinks.ID = "links" + base.ID; + _listboxLinks.Width = 400; + _listboxLinks.Height = 140; + foreach (XmlNode node in _xml.DocumentElement.ChildNodes) + { + string text = node.Attributes["title"].Value.ToString(); + string value = (node.Attributes["type"].Value.ToString().Equals("internal") ? "i" : "e") + + (node.Attributes["newwindow"].Value.ToString().Equals("1") ? "n" : "o") + + node.Attributes["link"].Value.ToString(); + _listboxLinks.Items.Add(new ListItem(text, value)); + } + + _buttonUp = new Button(); + _buttonUp.ID = "btnUp" + base.ID; + _buttonUp.Text = umbraco.ui.GetText("relatedlinks", "modeUp"); + _buttonUp.Width = 80; + _buttonUp.Click += new EventHandler(this.buttonUp_Click); + + + _buttonDown = new Button(); + _buttonDown.ID = "btnDown" + base.ID; + _buttonDown.Attributes.Add("style", "margin-top: 5px;"); + _buttonDown.Text = umbraco.ui.GetText("relatedlinks", "modeDown"); + _buttonDown.Width = 80; + _buttonDown.Click += new EventHandler(this.buttonDown_Click); + + _buttonDelete = new Button(); + _buttonDelete.ID = "btnDel" + base.ID; + _buttonDelete.Text = umbraco.ui.GetText("relatedlinks", "removeLink"); + _buttonDelete.Width = 80; + _buttonDelete.Click += new EventHandler(this.buttonDel_Click); + + _textboxLinkTitle = new TextBox(); + _textboxLinkTitle.Width = 400; + _textboxLinkTitle.ID = "linktitle" + base.ID; + + _checkNewWindow = new CheckBox(); + _checkNewWindow.ID = "checkNewWindow" + base.ID; + _checkNewWindow.Checked = false; + _checkNewWindow.Text = umbraco.ui.GetText("relatedlinks", "newWindow"); + + _textBoxExtUrl = new TextBox(); + _textBoxExtUrl.Width = 400; + _textBoxExtUrl.ID = "exturl" + base.ID; + + _buttonAddExtUrl = new Button(); + _buttonAddExtUrl.ID = "btnAddExtUrl" + base.ID; + _buttonAddExtUrl.Text = umbraco.ui.GetText("relatedlinks", "addlink"); + _buttonAddExtUrl.Width = 80; + _buttonAddExtUrl.Click += new EventHandler(this.buttonAddExt_Click); + + _buttonAddIntUrlCP = new Button(); + _buttonAddIntUrlCP.ID = "btnAddIntUrl" + base.ID; + _buttonAddIntUrlCP.Text = umbraco.ui.GetText("relatedlinks", "addlink"); + _buttonAddIntUrlCP.Width = 80; + _buttonAddIntUrlCP.Click += new EventHandler(this.buttonAddIntCP_Click); + + _pagePickerExtractor = new PagePickerDataExtractor(); + _pagePicker = new pagePicker(_pagePickerExtractor); + _pagePicker.ID = "pagePicker" + base.ID; + + ContentTemplateContainer.Controls.Add(new LiteralControl("
")); + ContentTemplateContainer.Controls.Add(_listboxLinks); + ContentTemplateContainer.Controls.Add(new LiteralControl("")); + ContentTemplateContainer.Controls.Add(_buttonUp); + ContentTemplateContainer.Controls.Add(new LiteralControl("
")); + ContentTemplateContainer.Controls.Add(_buttonDown); + ContentTemplateContainer.Controls.Add(new LiteralControl("
")); + ContentTemplateContainer.Controls.Add(_buttonDelete); + ContentTemplateContainer.Controls.Add(new LiteralControl("
")); + ContentTemplateContainer.Controls.Add(new LiteralControl("
")); + + // Add related links container + ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("{1}", ClientID, umbraco.ui.GetText("relatedlinks", "addInternal")))); + ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format(" | {1}", ClientID, umbraco.ui.GetText("relatedlinks", "addExternal")))); + + // All urls + ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("
", ClientID))); + ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("", ClientID, GlobalSettings.Path))); + ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("{0}:
", umbraco.ui.GetText("relatedlinks", "caption")))); + ContentTemplateContainer.Controls.Add(_textboxLinkTitle); + ContentTemplateContainer.Controls.Add(new LiteralControl("
")); + ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("
", ClientID))); + ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("{0}:
", umbraco.ui.GetText("relatedlinks", "linkurl")))); + ContentTemplateContainer.Controls.Add(_textBoxExtUrl); + ContentTemplateContainer.Controls.Add(new LiteralControl("
")); + + ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("
", ClientID))); + ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("{0}:
", umbraco.ui.GetText("relatedlinks", "internalPage")))); + ContentTemplateContainer.Controls.Add(_pagePicker); + ContentTemplateContainer.Controls.Add(new LiteralControl("
")); + + ContentTemplateContainer.Controls.Add(new LiteralControl("
")); + ContentTemplateContainer.Controls.Add(_checkNewWindow); + ContentTemplateContainer.Controls.Add(new LiteralControl("
")); + + ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("
", ClientID))); + ContentTemplateContainer.Controls.Add(_buttonAddIntUrlCP); + ContentTemplateContainer.Controls.Add(new LiteralControl("
")); + + ContentTemplateContainer.Controls.Add(new LiteralControl(String.Format("
", ClientID))); + ContentTemplateContainer.Controls.Add(_buttonAddExtUrl); + ContentTemplateContainer.Controls.Add(new LiteralControl("
")); + + ContentTemplateContainer.Controls.Add(new LiteralControl("
")); + + ContentTemplateContainer.Controls.Add(new LiteralControl("
")); + + resetInputMedia(); + } + + + private XmlDocument createBaseXmlDocument() + { + XmlDocument doc = new XmlDocument(); + XmlNode root = doc.CreateElement("links"); + doc.AppendChild(root); + return doc; + } + + private void buttonUp_Click(Object o, EventArgs ea) + { + int index = _listboxLinks.SelectedIndex; + if (index > 0) //not the first item + { + ListItem temp = _listboxLinks.SelectedItem; + _listboxLinks.Items.RemoveAt(index); + _listboxLinks.Items.Insert(index - 1, temp); + _listboxLinks.SelectedIndex = index - 1; + } + } + + private void buttonDown_Click(Object o, EventArgs ea) + { + int index = _listboxLinks.SelectedIndex; + if (index > -1 && index < _listboxLinks.Items.Count - 1) //not the last item + { + ListItem temp = _listboxLinks.SelectedItem; + _listboxLinks.Items.RemoveAt(index); + _listboxLinks.Items.Insert(index + 1, temp); + _listboxLinks.SelectedIndex = index + 1; + } + } + + private void buttonDel_Click(Object o, EventArgs ea) + { + int index = _listboxLinks.SelectedIndex; + if (index > -1) + { + _listboxLinks.Items.RemoveAt(index); + } + } + + private void buttonAddExt_Click(Object o, EventArgs ea) + { + string url = _textBoxExtUrl.Text.Trim(); + if (url.Length > 0 && _textboxLinkTitle.Text.Length > 0) + { + // use default HTTP protocol if no protocol was specified + if (!(url.Contains("://"))) + { + url = "http://" + url; + } + + string value = "e" + (_checkNewWindow.Checked ? "n" : "o") + url; + _listboxLinks.Items.Add(new ListItem(_textboxLinkTitle.Text, value)); + resetInputMedia(); + } + } + + private void buttonAddIntCP_Click(Object o, EventArgs ea) + { + _pagePicker.Save(); + if (!String.IsNullOrEmpty(_textboxLinkTitle.Text) + && _pagePickerExtractor.Value != null + && _pagePickerExtractor.Value.ToString() != "") + { + string value = "i" + (_checkNewWindow.Checked ? "n" : "o") + _pagePickerExtractor.Value.ToString(); + _listboxLinks.Items.Add(new ListItem(_textboxLinkTitle.Text, value)); + resetInputMedia(); + ScriptManager.RegisterClientScriptBlock(_pagePicker, _pagePicker.GetType(), "clearPagePicker", _pagePicker.ClientID + "_clear();", true); + } + } + + private void resetInputMedia() + { + _textBoxExtUrl.Text = "http://"; + _textboxLinkTitle.Text = ""; + _pagePickerExtractor.Value = ""; + + } + + } + +} diff --git a/components/editorControls/relatedlinks/RelatedLinksDataType.cs b/components/editorControls/relatedlinks/RelatedLinksDataType.cs new file mode 100644 index 0000000000..011a848dfb --- /dev/null +++ b/components/editorControls/relatedlinks/RelatedLinksDataType.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace umbraco.editorControls.relatedlinks +{ + public class RelatedLinksDataType : umbraco.cms.businesslogic.datatype.BaseDataType, umbraco.interfaces.IDataType + { + private umbraco.interfaces.IDataEditor _Editor; + private umbraco.interfaces.IData _baseData; + private RelatedLinksPrevalueEditor _prevalueeditor; + + public override umbraco.interfaces.IDataEditor DataEditor + { + get + { + + if (_Editor == null) + _Editor = new RelatedLinksDataEditor(Data, ((RelatedLinksPrevalueEditor)PrevalueEditor).Configuration); + return _Editor; + } + } + + public override umbraco.interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new RelatedLinksData(this); + return _baseData; + } + } + public override Guid Id + { + get { return new Guid("71b8ad1a-8dc2-425c-b6b8-faa158075e63"); } + } + + public override string DataTypeName + { + get { return "Related Links"; } + } + + public override umbraco.interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new RelatedLinksPrevalueEditor(this); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/relatedlinks/RelatedLinksPrevalueEditor.cs b/components/editorControls/relatedlinks/RelatedLinksPrevalueEditor.cs new file mode 100644 index 0000000000..4fcb1ffeb4 --- /dev/null +++ b/components/editorControls/relatedlinks/RelatedLinksPrevalueEditor.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web.UI; +using System.Web.UI.HtmlControls; +using System.Web.UI.WebControls; +using System.Web.UI.WebControls.WebParts; +using umbraco.BusinessLogic; +using umbraco.editorControls; + +namespace umbraco.editorControls.relatedlinks +{ + public class RelatedLinksPrevalueEditor : System.Web.UI.WebControls.PlaceHolder, umbraco.interfaces.IDataPrevalue + { + #region IDataPrevalue Members + + // referenced datatype + private umbraco.cms.businesslogic.datatype.BaseDataType _datatype; + + //private DropDownList _dropdownlist; + //private CheckBox _showUrls; + + public RelatedLinksPrevalueEditor(umbraco.cms.businesslogic.datatype.BaseDataType DataType) + { + + _datatype = DataType; + setupChildControls(); + + } + + private void setupChildControls() + { + //_dropdownlist = new DropDownList(); + //_dropdownlist.ID = "dbtype"; + ////_dropdownlist.Items.Add(DBTypes.Date.ToString()); + ////_dropdownlist.Items.Add(DBTypes.Integer.ToString()); + //_dropdownlist.Items.Add(DBTypes.Ntext.ToString()); + //_dropdownlist.Items.Add(DBTypes.Nvarchar.ToString()); + + ////_checkboxShowGrandChildren = new CheckBox(); + ////_checkboxShowGrandChildren.ID = "showurls"; + + + //Controls.Add(_dropdownlist); + //Controls.Add(_showUrls); + } + + + + public Control Editor + { + get + { + return this; + } + } + + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + //if (!Page.IsPostBack) + //{ + // string[] config = Configuration.Split("|".ToCharArray()); + // if (config.Length > 1) + // { + // //_showUrls.Checked = Convert.ToBoolean(config[0]); + + // } + // _dropdownlist.SelectedValue = _datatype.DBType.ToString(); + //} + } + + public void Save() + { + _datatype.DBType = (umbraco.cms.businesslogic.datatype.DBTypes)Enum.Parse(typeof(umbraco.cms.businesslogic.datatype.DBTypes), DBTypes.Ntext.ToString(), true); + + + } + + protected override void Render(HtmlTextWriter writer) + { + //writer.WriteLine(""); + //writer.WriteLine(""); + + //writer.Write("
Database datatype:"); + //_dropdownlist.RenderControl(writer); + //writer.Write("
"); + } + + public string Configuration + { + get + { + return ""; + + } + } + + #endregion + } +} diff --git a/components/editorControls/simpleEditor/simpleEditor.cs b/components/editorControls/simpleEditor/simpleEditor.cs new file mode 100644 index 0000000000..fad6b948ff --- /dev/null +++ b/components/editorControls/simpleEditor/simpleEditor.cs @@ -0,0 +1,103 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.ComponentModel; +using System.Collections; + +namespace umbraco.editorControls.simpleEditor +{ + /// + /// Summary description for simpleEditor. + /// + public class SimpleEditor : System.Web.UI.WebControls.TextBox, interfaces.IDataEditor + { + private interfaces.IData _data; + + + + public SimpleEditor(interfaces.IData Data) + { + _data = Data; + + } + + public virtual bool TreatAsRichTextEditor + { + get {return false;} + } + + public bool ShowLabel + { + get {return true;} + } + + public Control Editor {get{return this;}} + + public void Save() + { + _data.Value = this.Text; + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + base.TextMode = System.Web.UI.WebControls.TextBoxMode.MultiLine; + base.Rows = 8; + if (this.CssClass == "") + this.CssClass = "umbEditorTextField"; + if (_data != null && _data.Value != null) + Text = _data.Value.ToString(); + + + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad (e); + string script = "function insertLink(element) {"+ + "var theLink = prompt('Enter URL for link here:','http://');" + + "insertTag(element, 'a', ' href=\"' + theLink + '\"')}"; + script += @" + function insertTag(element, tag, param) { + start = '<' + tag + param + '>'; + eind = ''; + /* element = document.getElementById(element); */ + if (document.selection) { + element.focus(); + sel = document.selection.createRange(); + sel.text = start + sel.text + eind; + } else if (element.selectionStart || element.selectionStart == '0') { + element.focus(); + var startPos = element.selectionStart; + var endPos = element.selectionEnd; + element.value = element.value.substring(0, startPos) + start + element.value.substring(startPos, endPos) + eind + element.value.substring(endPos, element.value.length); + } else { + element.value += start + eind; + } + } + "; + + Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "simpleEditorJs", + script, true); + + } + + protected override void Render(HtmlTextWriter output) + { + output.WriteLine("
"); + + output.WriteLine( "

" + + "" + + "" + + "" + + "" + + "" + + " " + + "" + + "" + + "

"); + base.Render(output); + output.WriteLine("
"); + } + } +} \ No newline at end of file diff --git a/components/editorControls/simpleEditor/simpleEditorDataType.cs b/components/editorControls/simpleEditor/simpleEditorDataType.cs new file mode 100644 index 0000000000..e3c9452116 --- /dev/null +++ b/components/editorControls/simpleEditor/simpleEditorDataType.cs @@ -0,0 +1,53 @@ +using System; + +namespace umbraco.editorControls.simpleEditor +{ + /// + /// Summary description for simpleEditorDataType. + /// + public class simpleEditorDataType : cms.businesslogic.datatype.BaseDataType,interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new SimpleEditor(Data); + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + public override Guid Id + { + get {return new Guid("60B7DABF-99CD-41eb-B8E9-4D2E669BBDE9");} + } + + public override string DataTypeName + { + get {return "UltraSimpleEditor";} + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new DefaultPrevalueEditor(this,false); + return _prevalueeditor; + } + } + } +} \ No newline at end of file diff --git a/components/editorControls/tags/DataEditor.cs b/components/editorControls/tags/DataEditor.cs new file mode 100644 index 0000000000..d8b0ab3bf6 --- /dev/null +++ b/components/editorControls/tags/DataEditor.cs @@ -0,0 +1,321 @@ +using System; +using System.Configuration; +using System.Collections; +using System.Web.UI; +using System.Web.UI.WebControls; +using umbraco.BusinessLogic; +using umbraco.DataLayer; +using umbraco.presentation.nodeFactory; + +namespace umbraco.editorControls.tags { + public class DataEditor : System.Web.UI.UpdatePanel, umbraco.interfaces.IDataEditor, umbraco.interfaces.IUseTags { + #region IDataEditor Members + + umbraco.interfaces.IData _data; + string _group = ""; + + public DataEditor(umbraco.interfaces.IData Data, SortedList Prevalues) { + _data = Data; + + if(Prevalues["group"] != null) + _group = Prevalues["group"].ToString(); + } + + public CheckBoxList tagCheckList = new CheckBoxList(); + public TextBox tagBox = new TextBox(); + + + public static ISqlHelper SqlHelper + { + get + { + return Application.SqlHelper; + } + } + + public Control Editor { get { return this; } } + + public void Save() { + + CheckBoxList items = tagCheckList; + string nodeId = umbraco.helper.Request("id"); + int tagId = 0; + + string allTags = ""; + + + //first clear out all items associated with this ID... + SqlHelper.ExecuteNonQuery("DELETE FROM cmsTagRelationship WHERE (nodeId = @nodeId) AND EXISTS (SELECT id FROM cmsTags WHERE (cmsTagRelationship.tagId = id) AND ([group] = @group));", + SqlHelper.CreateParameter("@nodeId", nodeId), + SqlHelper.CreateParameter("@group", _group)); + + //and now we add them again... + foreach (ListItem li in items.Items) { + if (li.Selected) { + + if (li.Value == "0") { + + tagId = saveTag(li.Text); + li.Value = tagId.ToString(); + + } else { + int.TryParse(li.Value, out tagId); + } + + if (tagId > 0) { + + SqlHelper.ExecuteNonQuery("INSERT INTO cmsTagRelationShip(nodeId,tagId) VALUES (@nodeId, @tagId)", + SqlHelper.CreateParameter("@nodeId", nodeId), + SqlHelper.CreateParameter("@tagId", tagId) + ); + + tagId = 0; + allTags += "," + li.Text; + } + } + } + //and just in case, we'll save the tags as plain text on the node itself... + _data.Value = allTags.Trim().Trim(','); + } + + public bool ShowLabel { + get { return true; } + } + + public bool TreatAsRichTextEditor { + get { return false; } + } + + public void tagBoxTextChange(object sender, EventArgs e) { + try { + CheckBoxList items = tagCheckList; + + string[] tags = tagBox.Text.Trim().Trim(',').Split(','); + + + for (int i = 0; i < tags.Length; i++) { + //if not found we'll get zero and handle that onsave instead... + int id = getTagId(tags[i], _group); + + //we don't want 2 of a kind... + if (items.Items.FindByText(tags[i].Trim()) == null) { + ListItem li = new ListItem(tags[i], id.ToString()); + li.Selected = true; + items.Items.Add(li); + } + } + + //reset the textbox + tagBox.Text = ""; + + ScriptManager.GetCurrent(Page).SetFocus(tagBox); + + } + catch (Exception ex) { + Log.Add(LogTypes.Debug, -1, ex.ToString()); + } + } + + private int saveTag(string tag) + { + SqlHelper.ExecuteNonQuery("INSERT INTO cmsTags(tag,[group]) VALUES (@tag,@group)", + SqlHelper.CreateParameter("@tag", tag.Trim()), + SqlHelper.CreateParameter("@group", _group)); + return getTagId(tag, _group); + } + + public int getTagId(string tag, string group) + { + int retval = 0; + try + { + string sql = "SELECT id FROM cmsTags where tag=@tag AND [group]=@group;"; + object result = SqlHelper.ExecuteScalar(sql, + SqlHelper.CreateParameter("@tag", tag), + SqlHelper.CreateParameter("@group", _group)); + + if (result != null) + retval = int.Parse(result.ToString()); + } + catch (Exception ex) + { + umbraco.BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Error, -1, ex.ToString()); + } + + return retval; + } + + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + string _alias = ((umbraco.cms.businesslogic.datatype.DefaultData)_data).PropertyId.ToString(); + + + string tagCss = @""; + + Page.ClientScript.RegisterClientScriptBlock(tagCss.GetType(), "umbracoTagCss", tagCss); + + //making sure that we have a ID for context + string pageId = umbraco.helper.Request("id"); + + if( string.IsNullOrEmpty(pageId.Trim())) + { + Node currentNode = Node.GetCurrent(); + if(currentNode != null) + { + pageId = currentNode.Id.ToString(); + } + } + + + tagBox.ID = "tagBox_" + _alias; + tagBox.AutoPostBack = true; + tagBox.AutoCompleteType = AutoCompleteType.Disabled; + tagBox.TextChanged += new System.EventHandler(this.tagBoxTextChange); + tagBox.CssClass = "umbEditorTextField"; + + Button tagButton = new Button(); + tagButton.Click += new System.EventHandler(this.tagBoxTextChange); + tagButton.Text = "tag"; + + AjaxControlToolkit.AutoCompleteExtender tagList = new AjaxControlToolkit.AutoCompleteExtender(); + tagList.TargetControlID = "tagBox_" + _alias; + tagList.ServiceMethod = "getTagList"; + + tagList.ServicePath = ConfigurationManager.AppSettings["umbracoPath"] + "/webservices/tagService.asmx"; + tagList.MinimumPrefixLength=2; + tagList.CompletionInterval=1000; + tagList.EnableCaching=true; + tagList.CompletionSetCount=20; + tagList.CompletionListCssClass="autocomplete_completionListElement"; + tagList.CompletionListItemCssClass="autocomplete_listItem"; + tagList.CompletionListHighlightedItemCssClass = "autocomplete_highlightedListItem"; + tagList.DelimiterCharacters=";, :"; + tagList.UseContextKey = true; + tagList.ContextKey = pageId + "|" + _group; + + + tagCheckList.ID = "tagCheckList_" + _alias; + + //fetch the current tags + IRecordsReader rr = SqlHelper.ExecuteReader( + @"SELECT * FROM cmsTags + INNER JOIN cmsTagRelationship ON cmsTagRelationShip.tagId = cmsTags.id + WHERE cmsTags.[group] = @group AND cmsTagRelationship.nodeid = @nodeid", + SqlHelper.CreateParameter("@group", _group), + SqlHelper.CreateParameter("@nodeid", pageId)); + + while (rr.Read()) + { + ListItem li = new ListItem( rr.GetString("tag"), rr.GetInt("id").ToString()); + li.Selected = true; + tagCheckList.Items.Add(li); + } + rr.Close(); + + this.ContentTemplateContainer.Controls.Add(tagBox); + this.ContentTemplateContainer.Controls.Add(tagButton); + this.ContentTemplateContainer.Controls.Add(tagCheckList); + this.ContentTemplateContainer.Controls.Add(tagList); + } + + #endregion + + #region IUseTags Members + + public string Group + { + get { return _group; } + } + + #endregion + + #region IUseTags Members + + + public void RemoveTag(int nodeId, string tag) + { + library.RemoveTagFromNode(nodeId, tag, _group); + } + + public System.Collections.Generic.List GetTagsFromNode(int nodeId) + { + return library.GetTagsFromNodeAsITags(nodeId); + } + + public System.Collections.Generic.List GetAllTags() + { + return library.GetTagsFromGroupAsITags(_group); + } + + #endregion + + #region IUseTags Members + + + public void AddTag(string tag) + { + library.AddTag(tag, _group); + } + + public void AddTagToNode(int nodeId, string tag) + { + library.addTagsToNode(nodeId, tag, _group); + } + + #endregion + + #region IUseTags Members + + + public void RemoveTagsFromNode(int nodeId) + { + foreach (umbraco.interfaces.ITag t in library.GetTagsFromNodeAsITags(nodeId)) + library.RemoveTagFromNode(nodeId, t.TagCaption, t.Group); + } + + #endregion + } +} diff --git a/components/editorControls/tags/DataType.cs b/components/editorControls/tags/DataType.cs new file mode 100644 index 0000000000..35a64b98fc --- /dev/null +++ b/components/editorControls/tags/DataType.cs @@ -0,0 +1,58 @@ +using System; +using umbraco.interfaces; +using datatype = umbraco.cms.businesslogic.datatype; + +namespace umbraco.editorControls.tags +{ + public class DataType : datatype.BaseDataType, IDataType + { + #region IDataType Members + + private IDataEditor _Editor; + private IData _baseData; + private IDataPrevalue _prevalueeditor; + + public override IData Data + { + get { + if (_baseData == null) + _baseData = new datatype.DefaultData(this); + return _baseData; + } + } + + public override IDataEditor DataEditor + { + get + { + if (_Editor == null) + { + _Editor = new DataEditor(Data, ((PrevalueEditor)PrevalueEditor).Prevalues); + } + return _Editor; + } + } + + public override string DataTypeName + { + get { return "Tags"; } + } + + public override Guid Id + { + get { return new Guid("4023e540-92f5-11dd-ad8b-0800200c9a66"); } + } + + public override IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new PrevalueEditor(this); + return _prevalueeditor; + } + } + + #endregion + } +} diff --git a/components/editorControls/tags/PrevalueEditor.cs b/components/editorControls/tags/PrevalueEditor.cs new file mode 100644 index 0000000000..6436d98523 --- /dev/null +++ b/components/editorControls/tags/PrevalueEditor.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections; +using System.Web.UI; +using System.Web.UI.WebControls; +using umbraco.BusinessLogic; +using umbraco.DataLayer; +using umbraco.interfaces; +using datatype = umbraco.cms.businesslogic.datatype; + + +namespace umbraco.editorControls.tags +{ + public class PrevalueEditor : PlaceHolder, IDataPrevalue + { + private TextBox _group; + + public static ISqlHelper SqlHelper + { + get + { + return Application.SqlHelper; + } + } + + // referenced datatype + private datatype.BaseDataType _datatype; + + public PrevalueEditor(datatype.BaseDataType DataType) + { + _datatype = DataType; + setupChildControls(); + + } + + public Control Editor + { + get + { + return this; + } + } + + public void Save() + { + //clear all datatype data first... + SqlHelper.ExecuteNonQuery("delete from cmsDataTypePrevalues where datatypeNodeId = " + _datatype.DataTypeDefinitionId); + + //Save datatype + _datatype.DBType = datatype.DBTypes.Ntext; + + // Save path and control type.. + SqlHelper.ExecuteNonQuery("insert into cmsDataTypePrevalues (datatypenodeid,[value],sortorder,alias) values (@dtdefid,@value,0,@alias)", + SqlHelper.CreateParameter("@value", _group.Text), + SqlHelper.CreateParameter("@alias", "group"), + SqlHelper.CreateParameter("@dtdefid", _datatype.DataTypeDefinitionId)); + } + + private void setupChildControls() + { + _group = new TextBox(); + _group.ID = "group"; + _group.CssClass = "umbEditorTextField"; + + // put the childcontrols in context - ensuring that + // the viewstate is persisted etc. + this.Controls.Add(_group); + + SortedList _prevalues = Prevalues; + + if (_prevalues.ContainsKey("group")) + _group.Text = _prevalues["group"].ToString(); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + } + + protected override void Render(HtmlTextWriter writer) + { + writer.WriteLine(""); + + writer.WriteLine(""); + writer.Write("
Tag group:"); + _group.RenderControl(writer); + writer.Write("
"); + } + + public SortedList Prevalues + { + get + { + SortedList retval = new SortedList(); + IRecordsReader dr = SqlHelper.ExecuteReader( + "Select alias, [value] from cmsDataTypeprevalues where DataTypeNodeId = " + _datatype.DataTypeDefinitionId + " order by sortorder"); + + while (dr.Read()) + { + if (!retval.ContainsKey(dr.GetString("alias"))) + { + retval.Add(dr.GetString("alias"), dr.GetString("value")); + } + } + + dr.Close(); + return retval; + } + } + } +} diff --git a/components/editorControls/tags/library.cs b/components/editorControls/tags/library.cs new file mode 100644 index 0000000000..027e947503 --- /dev/null +++ b/components/editorControls/tags/library.cs @@ -0,0 +1,464 @@ +using System; +using System.Text; +using System.Xml; +using System.Xml.XPath; +using umbraco.BusinessLogic; +using umbraco.cms.businesslogic; +using umbraco.cms.businesslogic.web; +using umbraco.DataLayer; + +using System.Collections.Generic; + +namespace umbraco.editorControls.tags +{ + public class library + { + + public static void addTagsToNode(int nodeId, string tags, string group) + { + string[] allTags = tags.Split(",".ToCharArray()); + for (int i = 0; i < allTags.Length; i++) + { + //if not found we'll get zero and handle that onsave instead... + int id = GetTagId(allTags[i], group); + if (id == 0) + id = AddTag(allTags[i], group); + + SqlHelper.ExecuteNonQuery("if not exists(select nodeId from cmsTagRelationShip where nodeId = @nodeId and tagId = @tagId) INSERT INTO cmsTagRelationShip(nodeId,tagId) VALUES (@nodeId, @tagId)", + SqlHelper.CreateParameter("@nodeId", nodeId), + SqlHelper.CreateParameter("@tagId", id) +); + + } + + } + + public static void RemoveTagFromNode(int nodeId, string tag, string group) + { + int tagId = GetTagId(tag, group); + if (tagId != 0) + { + SqlHelper.ExecuteNonQuery("DELETE FROM cmsTagRelationship WHERE (nodeId = @nodeId and tagId = @tagId)", + SqlHelper.CreateParameter("@nodeId", nodeId), + SqlHelper.CreateParameter("@tagId", tagId)); + } + } + + public static int AddTag(string tag, string group) + { + SqlHelper.ExecuteNonQuery("INSERT INTO cmsTags(tag,[group]) VALUES (@tag,@group)", + SqlHelper.CreateParameter("@tag", tag.Trim()), + SqlHelper.CreateParameter("@group", group)); + return GetTagId(tag, group); + } + + + public static int GetTagId(string tag, string group) + { + int retval = 0; + string sql = "SELECT id FROM cmsTags where tag=@tag AND [group]=@group;"; + object result = SqlHelper.ExecuteScalar(sql, + SqlHelper.CreateParameter("@tag", tag), + SqlHelper.CreateParameter("@group", group)); + + if (result != null) + retval = int.Parse(result.ToString()); + + return retval; + } + + public static ISqlHelper SqlHelper + { + get + { + return Application.SqlHelper; + } + } + + + /// + /// Gets everything (content, media, members) in Umbraco with the specified tags. + /// It returns the found nodes as: + /// + /// ... + /// ... + /// etc... + /// + /// + /// Commaseparated tags. + /// + /// A XpathNodeIterator + /// + public static XPathNodeIterator getEverythingWithTags(string tags) + { + string sql = @"SELECT DISTINCT cmsTagRelationShip.nodeid from cmsTagRelationShip + INNER JOIN cmsTags ON cmsTagRelationship.tagid = cmsTags.id WHERE (cmsTags.tag IN (" + GetSqlStringArray(tags) + "))"; + IRecordsReader rr = SqlHelper.ExecuteReader(sql); + + XmlDocument xmlDoc = new XmlDocument(); + XmlNode root = xmlDoc.CreateElement("root"); + while (rr.Read()) + { + CMSNode cnode = new CMSNode(rr.GetInt("nodeid")); + if (cnode != null) + root.AppendChild(cnode.ToXml(xmlDoc, true)); + } + rr.Close(); + + xmlDoc.AppendChild(root); + return xmlDoc.CreateNavigator().Select("."); + } + + /// + /// Gets all content nodes in Umbraco with the specified tag. + /// It returns the found nodes as: + /// + /// ... + /// ... + /// etc... + /// + /// + /// Commaseparated tags. + /// + /// A XpathNodeIterator + /// + public static XPathNodeIterator getContentsWithTags(string tags) + { + XmlDocument xmlDoc = new XmlDocument(); + string sql = @"SELECT DISTINCT cmsTagRelationShip.nodeid from cmsTagRelationShip + INNER JOIN cmsTags ON cmsTagRelationShip.tagid = cmsTags.id WHERE (cmsTags.tag IN (" + GetSqlStringArray(tags) + "))"; + try + { + IRecordsReader rr = SqlHelper.ExecuteReader(sql); + + XmlNode root = xmlDoc.CreateElement("root"); + while (rr.Read()) + { + Document cnode = new Document(rr.GetInt("nodeid")); + + if (cnode != null && cnode.Published) + root.AppendChild(cnode.ToXml(xmlDoc, true)); + } + rr.Close(); + xmlDoc.AppendChild(root); + } + catch (Exception ex) + { + Log.Add(LogTypes.Debug, -1, ex.ToString() + " SQL: " + sql + "TAGS: " + tags); + } + return xmlDoc.CreateNavigator().Select("."); + } + + /// + /// Returns all members (does not care about groups and types) in Umbraco with the specified tag. + /// It returns the found nodes as: + /// + /// ... + /// ... + /// etc... + /// + /// + /// Comma separated tags. + /// + /// A XpathNodeIterator + /// + public static XPathNodeIterator getMembersWithTags(string tags) + { + string sql = @"SELECT DISTINCT cmsTagRelationShip.nodeid from cmsTagRelationShip + INNER JOIN cmsTags ON cmsTagRelationShip.tagid = cmsTags.id WHERE (cmsTags.tag IN (" + GetSqlStringArray(tags) + "))"; + IRecordsReader rr = SqlHelper.ExecuteReader(sql); + + XmlDocument xmlDoc = new XmlDocument(); + XmlNode root = xmlDoc.CreateElement("root"); + while (rr.Read()) + { + CMSNode cnode = new CMSNode(rr.GetInt("nodeid")); + + if (cnode != null) + root.AppendChild(cnode.ToXml(xmlDoc, true)); + } + rr.Close(); + + xmlDoc.AppendChild(root); + return xmlDoc.CreateNavigator().Select("."); + } + + /// + /// Returns all media nodes in Umbraco with the specified tag. + /// It returns the found nodes as: + /// + /// ... + /// ... + /// etc... + /// + /// + /// Commaseparated tags. + /// + /// A XpathNodeIterator + /// + public static XPathNodeIterator getMediaWithTags(string tags) + { + string sql = @"SELECT DISTINCT cmsTagRelationShip.nodeid from cmsTagRelationShip + INNER JOIN cmsTags ON cmsTagRelationShip.tagid = cmsTags.id WHERE (cmsTags.tag IN (" + GetSqlStringArray(tags) + "))"; + IRecordsReader rr = SqlHelper.ExecuteReader(sql); + + XmlDocument xmlDoc = new XmlDocument(); + XmlNode root = xmlDoc.CreateElement("root"); + while (rr.Read()) + { + CMSNode cnode = new CMSNode(rr.GetInt("nodeid")); + + if (cnode != null) + root.AppendChild(cnode.ToXml(xmlDoc, true)); + } + rr.Close(); + + xmlDoc.AppendChild(root); + return xmlDoc.CreateNavigator().Select("."); + } + + /// + /// Converts the array to an SQL escaped array. + /// + /// An array of comma separated values. + /// SQL escaped array values. + private static string GetSqlStringArray(string commaSeparatedArray) + { + // create array + string[] array = commaSeparatedArray.Trim().Split(','); + + // build SQL array + StringBuilder sqlArray = new StringBuilder(); + foreach (string item in array) + { + string trimmedItem = item.Trim(); + if (trimmedItem.Length > 0) + { + sqlArray.Append("'").Append(SqlHelper.EscapeString(trimmedItem)).Append("',"); + } + } + + // remove last comma + if (sqlArray.Length > 0) + sqlArray.Remove(sqlArray.Length - 1, 1); + return sqlArray.ToString(); + } + + /// + /// Gets all tags + /// It returns the found nodes as: + /// + /// tagname + /// etc... + /// + /// Each tag node will contain it's numeric ID, number of nodes tagged with it, and the tags group. + /// + /// + /// A XpathNodeIterator + /// + public static XPathNodeIterator getAllTags() + { + string xmlVal = "\n"; + string sql = @"SELECT cmsTags.id, cmsTags.tag, cmsTags.[group], count(cmsTagRelationShip.tagid) AS nodeCount FROM cmsTags + INNER JOIN cmsTagRelationShip ON cmsTagRelationShip.tagid = cmsTags.id + Inner JOIN cmsContentXml ON cmsContentXml.nodeid = cmsTagRelationShip.nodeId + GROUP BY cmsTags.id, cmsTags.tag, cmsTags.[group]"; + + IRecordsReader rr = SqlHelper.ExecuteReader(sql); + + while (rr.Read()) + { + xmlVal += "" + rr.GetString("tag") + "\n"; + } + xmlVal += ""; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xmlVal); + + rr.Close(); + + + return doc.CreateNavigator().Select("."); + } + + /// + /// Gets all tags in a specific group + /// It returns the found nodes as: + /// + /// tagname + /// etc... + /// + /// Each tag node will contain it's numeric ID, number of nodes tagged with it, and the tags group. + /// + /// + /// A XpathNodeIterator + /// + public static XPathNodeIterator getAllTagsInGroup(string group) + { + string xmlVal = "\n"; + string sql = @"SELECT cmsTags.id, cmsTags.tag, cmsTags.[group], count(cmsTagRelationShip.tagid) AS nodeCount FROM cmsTags + INNER JOIN cmsTagRelationShip ON cmsTagRelationShip.tagid = cmsTags.id + INNER JOIN cmsContentXml ON cmsContentXml.nodeid = cmsTagRelationShip.nodeId + WHERE cmsTags.[group] = @group + GROUP BY cmsTags.id, cmsTags.tag, cmsTags.[group]"; + + IRecordsReader rr = SqlHelper.ExecuteReader(sql, SqlHelper.CreateParameter("@group", group)); + + while (rr.Read()) + { + xmlVal += "" + rr.GetString("tag") + "\n"; + } + xmlVal += ""; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xmlVal); + + rr.Close(); + + + return doc.CreateNavigator().Select("."); + } + + /// + /// Gets the tags from node as ITag objects. + /// + /// The node id. + /// + public static List GetTagsFromNodeAsITags(int nodeId) + { + + string sql = @"SELECT cmsTags.id, cmsTags.tag, cmsTags.[group], count(cmsTagRelationShip.tagid) AS nodeCount FROM cmsTags + INNER JOIN cmsTagRelationShip ON cmsTagRelationShip.tagid = cmsTags.id + WHERE cmsTagRelationShip.nodeid = @nodeId + GROUP BY cmsTags.id, cmsTags.tag, cmsTags.[group]"; + + List tags = convertSqlToTags(sql, SqlHelper.CreateParameter("@nodeId", nodeId)); + + return tags; + } + + /// + /// Gets the tags from group as ITag objects. + /// + /// The group. + /// + public static List GetTagsFromGroupAsITags(string group) + { + + string sql = @"SELECT cmsTags.id, cmsTags.tag, cmsTags.[group], count(cmsTagRelationShip.tagid) AS nodeCount FROM cmsTags + INNER JOIN cmsTagRelationShip ON cmsTagRelationShip.tagid = cmsTags.id + INNER JOIN cmsContentXml ON cmsContentXml.nodeid = cmsTagRelationShip.nodeId + WHERE cmsTags.[group] = @group + GROUP BY cmsTags.id, cmsTags.tag, cmsTags.[group]"; + + List tags = convertSqlToTags(sql, SqlHelper.CreateParameter("@group", group)); + + return tags; + } + + /// + /// Gets all the tags as ITag objects + /// + /// The node id. + /// + public static List GetTagsAsITags() + { + + string sql = @"SELECT cmsTags.id, cmsTags.tag, cmsTags.[group], count(cmsTagRelationShip.tagid) AS nodeCount FROM cmsTags + INNER JOIN cmsTagRelationShip ON cmsTagRelationShip.tagid = cmsTags.id + Inner JOIN cmsContentXml ON cmsContentXml.nodeid = cmsTagRelationShip.nodeId + GROUP BY cmsTags.id, cmsTags.tag, cmsTags.[group]"; + + List tags = convertSqlToTags(sql, SqlHelper.CreateParameter("@nodeId", "0")); + + return tags; + } + + private static List convertSqlToTags(string sql, IParameter param) + { + List tags = new List(); + IRecordsReader rr = SqlHelper.ExecuteReader(sql, param); + + while (rr.Read()) + { + tags.Add(new Tag( + rr.GetInt("id"), + rr.GetString("tag"), + rr.GetString("group"))); + } + + rr.Close(); + return tags; + } + + /// + /// Gets all tags associated with a specific node ID + /// It returns the found nodes as: + /// + /// tagname + /// etc... + /// + /// Each tag node will contain it's numeric ID, number of nodes tagged with it, and the tags group. + /// + /// + /// A XpathNodeIterator + /// + public static XPathNodeIterator getTagsFromNode(string nodeId) + { + string xmlVal = "\n"; + string sql = @"SELECT cmsTags.id, cmsTags.tag, cmsTags.[group], count(cmsTagRelationShip.tagid) AS nodeCount FROM cmsTags + INNER JOIN cmsTagRelationShip ON cmsTagRelationShip.tagid = cmsTags.id + WHERE cmsTagRelationShip.nodeid = @nodeId + GROUP BY cmsTags.id, cmsTags.tag, cmsTags.[group]"; + + IRecordsReader rr = SqlHelper.ExecuteReader(sql, SqlHelper.CreateParameter("@nodeId", nodeId)); + + while (rr.Read()) + { + xmlVal += "" + rr.GetString("tag") + "\n"; + } + xmlVal += ""; + + XmlDocument doc = new XmlDocument(); + doc.LoadXml(xmlVal); + + rr.Close(); + + return doc.CreateNavigator().Select("."); + } + } + + public class Tag : umbraco.interfaces.ITag + { + + public Tag() { } + public Tag(int id, string tag, string group) + { + Id = id; + TagCaption = tag; + Group = group; + } + + #region ITag Members + + public int Id + { + get; + set; + } + + public string TagCaption + { + get; + set; + } + + public string Group + { + get; + set; + } + + #endregion + } +} diff --git a/components/editorControls/textfield/TextFieldDataType.cs b/components/editorControls/textfield/TextFieldDataType.cs new file mode 100644 index 0000000000..0d6e11be71 --- /dev/null +++ b/components/editorControls/textfield/TextFieldDataType.cs @@ -0,0 +1,50 @@ +using System; + +namespace umbraco.editorControls.textfield +{ + public class TextFieldDataType : cms.businesslogic.datatype.BaseDataType,interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new TextFieldEditor(Data); + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + public override Guid Id + { + get {return new Guid("ec15c1e5-9d90-422a-aa52-4f7622c63bea");} + } + + public override string DataTypeName + { + get {return "Textbox";} + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new DefaultPrevalueEditor(this,false); + return _prevalueeditor; + } + } + } +} \ No newline at end of file diff --git a/components/editorControls/textfield/textFieldDataEditor.cs b/components/editorControls/textfield/textFieldDataEditor.cs new file mode 100644 index 0000000000..2b89be23e6 --- /dev/null +++ b/components/editorControls/textfield/textFieldDataEditor.cs @@ -0,0 +1,46 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.ComponentModel; +using System.Collections; + +namespace umbraco.editorControls.textfield +{ + public class TextFieldEditor : TextBox, interfaces.IDataEditor + { + private interfaces.IData _data; + + + public TextFieldEditor(interfaces.IData Data) { + _data = Data; + } + + public virtual bool TreatAsRichTextEditor + { + get {return false;} + } + + public bool ShowLabel + { + get {return true;} + } + + public Control Editor {get{return this;}} + + public void Save() + { + _data.Value = this.Text; + } + + protected override void OnInit(EventArgs e) + { + if (this.CssClass == "") + this.CssClass = "umbEditorTextField"; + + if (_data != null && _data.Value != null) + Text = _data.Value.ToString(); + + base.OnInit(e); + } + } +} \ No newline at end of file diff --git a/components/editorControls/textfield/textFieldDataEditor.resx b/components/editorControls/textfield/textFieldDataEditor.resx new file mode 100644 index 0000000000..dd0ea4d8e3 --- /dev/null +++ b/components/editorControls/textfield/textFieldDataEditor.resx @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.0.0.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + diff --git a/components/editorControls/textfieldmultiple/textfieldMultipleDataType.cs b/components/editorControls/textfieldmultiple/textfieldMultipleDataType.cs new file mode 100644 index 0000000000..12a09bbf6e --- /dev/null +++ b/components/editorControls/textfieldmultiple/textfieldMultipleDataType.cs @@ -0,0 +1,56 @@ +using System; + +namespace umbraco.editorControls.textfieldmultiple +{ + public class textfieldMultipleDataType : cms.businesslogic.datatype.BaseDataType,interfaces.IDataType + { + private textfield.TextFieldEditor _textFieldEditor; + private interfaces.IData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_textFieldEditor == null) + { + _textFieldEditor = new textfield.TextFieldEditor(Data); + _textFieldEditor.TextMode = System.Web.UI.WebControls.TextBoxMode.MultiLine; + _textFieldEditor.Rows = 10; + _textFieldEditor.Columns = 40; + _textFieldEditor.CssClass = "umbEditorTextFieldMultiple"; + } + return _textFieldEditor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + public override Guid Id + { + get {return new Guid("67db8357-ef57-493e-91ac-936d305e0f2a");} + } + + public override string DataTypeName + { + get {return "Textbox multiple";} + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new DefaultPrevalueEditor(this,false); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/tinyMCE3/TinyMCE.cs b/components/editorControls/tinyMCE3/TinyMCE.cs new file mode 100644 index 0000000000..b56bb4974f --- /dev/null +++ b/components/editorControls/tinyMCE3/TinyMCE.cs @@ -0,0 +1,586 @@ +using System; +using System.Collections; +using System.Text.RegularExpressions; +using System.Web; +using System.Web.UI; +using umbraco.BasePages; +using umbraco.BusinessLogic; +using umbraco.cms.businesslogic.web; +using umbraco.editorControls.wysiwyg; +using umbraco.interfaces; +using umbraco.uicontrols; +using umbraco.editorControls.tinymce; + +namespace umbraco.editorControls.tinyMCE3 { + public class TinyMCE : webcontrol.TinyMCEWebControl , IDataEditor, IMenuElement, ILiveEditingDataEditor { + private IData _data; + private bool m_isInLiveEditingMode = false; + private bool _enableContextMenu = false; + private string _editorButtons = ""; + private string _advancedUsers = ""; + private bool _fullWidth = false; + private int _width = 0; + private int _height = 0; + private bool _showLabel = false; + private string _plugins = ""; + private ArrayList _stylesheets = new ArrayList(); + + private ArrayList _menuIcons = new ArrayList(); + private SortedList _buttons = new SortedList(); + private SortedList _mceButtons = new SortedList(); + private bool _isInitialized = false; + private string _activateButtons = ""; + private string _disableButtons = "help,visualaid,"; + private int m_maxImageWidth = 500; + + + public virtual string Plugins { + get { return _plugins; } + set { _plugins = value; } + } + + public TinyMCE(IData Data, string Configuration) { + _data = Data; + try + { + string[] configSettings = Configuration.Split("|".ToCharArray()); + + if (configSettings.Length > 0) + { + _editorButtons = configSettings[0]; + + if (configSettings.Length > 1) + if (configSettings[1] == "1") + _enableContextMenu = true; + + if (configSettings.Length > 2) + _advancedUsers = configSettings[2]; + + if (configSettings.Length > 3) + { + if (configSettings[3] == "1") + _fullWidth = true; + else if (configSettings[4].Split(',').Length > 1) + { + _width = int.Parse(configSettings[4].Split(',')[0]); + _height = int.Parse(configSettings[4].Split(',')[1]); + } + } + + // default width/height + if (_width < 1) + _width = 500; + if (_height < 1) + _height = 400; + + // add stylesheets + if (configSettings.Length > 4) + { + foreach (string s in configSettings[5].Split(",".ToCharArray())) + _stylesheets.Add(s); + } + + if (configSettings.Length > 6 && configSettings[6] != "") + _showLabel = bool.Parse(configSettings[6]); + if (configSettings.Length > 7 && configSettings[7] != "") + m_maxImageWidth = int.Parse(configSettings[7].ToString()); + + // sizing + if (!_fullWidth) + { + config.Add("width", _width.ToString()); + config.Add("height", _height.ToString()); + } + + if (_enableContextMenu) + _plugins += ",contextmenu"; + + // safari compatibility + if (HttpContext.Current.Request.Browser.Browser.ToLower().Contains("safari")) + { + _plugins += ",safari"; + } + + // If the editor is used in umbraco, use umbraco's own toolbar + bool onFront = false; + if (GlobalSettings.RequestIsInUmbracoApplication(HttpContext.Current) || umbraco.presentation.UmbracoContext.Current.LiveEditingContext.Enabled) + { + config.Add("theme_umbraco_toolbar_location", "external"); + config.Add("skin", "umbraco"); + config.Add("inlinepopups_skin ", "umbraco"); + } + else + { + onFront = true; + config.Add("theme_umbraco_toolbar_location", "top"); + } + + // load plugins + IDictionaryEnumerator pluginEnum = umbraco.editorControls.tinymce.tinyMCEConfiguration.Plugins.GetEnumerator(); + while (pluginEnum.MoveNext()) + { + umbraco.editorControls.tinymce.tinyMCEPlugin plugin = (umbraco.editorControls.tinymce.tinyMCEPlugin)pluginEnum.Value; + if (plugin.UseOnFrontend || (!onFront && !plugin.UseOnFrontend)) + _plugins += "," + plugin.Name; + } + if (_plugins.StartsWith(",")) + _plugins = _plugins.Substring(1, _plugins.Length - 1); + if (_plugins.EndsWith(",")) + _plugins = _plugins.Substring(0, _plugins.Length - 1); + + config.Add("plugins", _plugins); + + // Check advanced settings + if (("," + _advancedUsers + ",").IndexOf("," + UmbracoEnsuredPage.CurrentUser.UserType.Id + ",") > -1) + config.Add("umbraco_advancedMode", "true"); + else + config.Add("umbraco_advancedMode", "false"); + + // Check maximum image width + config.Add("umbraco_maximumDefaultImageWidth", m_maxImageWidth.ToString()); + + // Styles + string cssFiles = String.Empty; + string styles = string.Empty; + foreach (string styleSheetId in _stylesheets) + { + if (styleSheetId.Trim() != "") + try + { + StyleSheet s = new StyleSheet(int.Parse(styleSheetId)); + if (s.nodeObjectType == StyleSheet.ModuleObjectType) + { + cssFiles += GlobalSettings.Path + "/../css/" + s.Text + ".css"; + + foreach (StylesheetProperty p in s.Properties) + { + if (styles != string.Empty) + { + styles += ";"; + } + if (p.Alias.StartsWith(".")) + styles += p.Text + "=" + p.Alias; + else + styles += p.Text + "=" + p.Alias; + } + + cssFiles += ","; + } + } + catch (Exception ee) + { + Log.Add(LogTypes.Error, -1, + string.Format( + string.Format("Error adding stylesheet to tinymce (id: {{0}}). {0}", ee), + styleSheetId)); + } + } + // remove any ending comma (,) + if (!string.IsNullOrEmpty(cssFiles)) + { + cssFiles = cssFiles.TrimEnd(','); + } + + // language + config.Add("language", User.GetCurrent().Language); + + config.Add("content_css", cssFiles); + config.Add("theme_umbraco_styles", styles); + + // Add buttons + IDictionaryEnumerator ide = umbraco.editorControls.tinymce.tinyMCEConfiguration.Commands.GetEnumerator(); + while (ide.MoveNext()) + { + umbraco.editorControls.tinymce.tinyMCECommand cmd = (umbraco.editorControls.tinymce.tinyMCECommand)ide.Value; + if (_editorButtons.IndexOf("," + cmd.Alias + ",") > -1) + _activateButtons += cmd.Alias + ","; + else + _disableButtons += cmd.Alias + ","; + } + + if (_activateButtons.Length > 0) + _activateButtons = _activateButtons.Substring(0, _activateButtons.Length - 1); + if (_disableButtons.Length > 0) + _disableButtons = _disableButtons.Substring(0, _disableButtons.Length - 1); + + // Add buttons + initButtons(); + _activateButtons = ""; + + int separatorPriority = 0; + ide = _mceButtons.GetEnumerator(); + while (ide.MoveNext()) + { + string mceCommand = ide.Value.ToString(); + int curPriority = (int)ide.Key; + + // Check priority + if (separatorPriority > 0 && + Math.Floor(decimal.Parse(curPriority.ToString()) / 10) > + Math.Floor(decimal.Parse(separatorPriority.ToString()) / 10)) + _activateButtons += "separator,"; + + _activateButtons += mceCommand + ","; + + separatorPriority = curPriority; + } + + + config.Add("theme_umbraco_buttons1", _activateButtons); + config.Add("theme_umbraco_buttons2", ""); + config.Add("theme_umbraco_buttons3", ""); + config.Add("theme_umbraco_toolbar_align", "left"); + config.Add("theme_umbraco_disable", _disableButtons); + + config.Add("theme_umbraco_path ", "true"); + config.Add("extended_valid_elements", "div[*]"); + config.Add("document_base_url", "/"); + config.Add("relative_urls", "false"); + config.Add("remove_script_host", "true"); + config.Add("event_elements", "div"); + config.Add("paste_auto_cleanup_on_paste", "true"); + + config.Add("valid_elements", tinyMCEConfiguration.ValidElements.Substring(1, tinyMCEConfiguration.ValidElements.Length-2)); + config.Add("invalid_elements", tinyMCEConfiguration.InvalidElements); + + // custom commands + if (tinyMCEConfiguration.ConfigOptions.Count > 0) + { + ide = tinyMCEConfiguration.ConfigOptions.GetEnumerator(); + while (ide.MoveNext()) + { + config.Add(ide.Key.ToString(), ide.Value.ToString()); + } + } + + //if (HttpContext.Current.Request.Path.IndexOf(GlobalSettings.Path) > -1) + // config.Add("language", User.GetUser(BasePage.GetUserId(BasePage.umbracoUserContextID)).Language); + //else + // config.Add("language", System.Threading.Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName); + + if (_fullWidth) + { + config.Add("auto_resize", "true"); + base.Columns = 30; + base.Rows = 30; + } + else + { + base.Columns = 0; + base.Rows = 0; + } + EnableViewState = false; + } + } + catch (Exception ex) + { + throw new ArgumentException("Incorrect TinyMCE configuration.", "Configuration", ex); + } + } + + #region IDataEditor Members + + #region TreatAsRichTextEditor + + public virtual bool TreatAsRichTextEditor { + get { return false; } + } + + #endregion + + #region ShowLabel + + public virtual bool ShowLabel { + get { return _showLabel; } + } + + #endregion + + #region Editor + + public Control Editor { + get { return this; } + } + + #endregion + + #region Save() + + public virtual void Save() { + string parsedString = base.Text.Trim(); + if (parsedString != string.Empty) { + parsedString = replaceMacroTags(parsedString).Trim(); + + // clean macros and add paragraph element for tidy + bool removeParagraphs = false; + if (parsedString.Length > 16 && parsedString.ToLower().Substring(0, 17) == "|||?umbraco_macro") { + removeParagraphs = true; + parsedString = "

" + parsedString + "

"; + } + + // tidy html + + if (UmbracoSettings.TidyEditorContent) { + string tidyTxt = library.Tidy(parsedString, false); + if (tidyTxt != "[error]") { + // compensate for breaking macro tags by tidy + parsedString = tidyTxt.Replace("/?>", "/>"); + if (removeParagraphs) { + if (parsedString.Length - parsedString.Replace("<", "").Length == 2) + parsedString = parsedString.Replace("

", "").Replace("

", ""); + } + } else { + // TODO + // How to log errors? _data.NodeId does not exist? + //BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, BusinessLogic.User.GetUser(0), _data.NodeId, "Error tidying txt from property: " + _data.PropertyId.ToString()); + } + } + + // rescue umbraco tags + parsedString = parsedString.Replace("|||?", "").Replace("|*|", "\""); + + // fix images + parsedString = umbraco.editorControls.tinymce.tinyMCEImageHelper.cleanImages(parsedString); + + // parse current domain and instances of slash before anchor (to fix anchor bug) + // NH 31-08-2007 + if (HttpContext.Current.Request.ServerVariables != null) { + parsedString = parsedString.Replace(helper.GetBaseUrl(HttpContext.Current) + "/#", "#"); + parsedString = parsedString.Replace(helper.GetBaseUrl(HttpContext.Current), ""); + } + + // if text is an empty parargraph, make it all empty + if (parsedString.ToLower() == "

") + parsedString = ""; + } + _data.Value = parsedString; + + // update internal webcontrol value with parsed result + base.Text = parsedString; + } + + #endregion + + protected override void OnLoad(EventArgs e) { + try { + // add current page info + base.NodeId = ((cms.businesslogic.datatype.DefaultData)_data).NodeId; + base.VersionId = ((cms.businesslogic.datatype.DefaultData)_data).Version; + config.Add("theme_umbraco_pageId", base.NodeId.ToString()); + config.Add("theme_umbraco_versionId", base.VersionId.ToString()); + + // we'll need to make an extra check for the liveediting as that value is set after the constructor have initialized + if (IsInLiveEditingMode) + { + if (config["theme_umbraco_toolbar_location"] == null) + config.Add("theme_umbraco_toolbar_location", ""); + config["theme_umbraco_toolbar_location"] = "external"; + config.Add("umbraco_toolbar_id", + "LiveEditingClientToolbar"); + + } + else { + config.Add("umbraco_toolbar_id", + ElementIdPreFix + ((cms.businesslogic.datatype.DefaultData)_data).PropertyId.ToString()); + + } + } catch { + // Empty catch as this is caused by the document doesn't exists yet, + // like when using this on an autoform + } + base.OnLoad(e); + + } + + protected override void OnInit(EventArgs e) { + base.OnInit(e); + if (_data != null && _data.Value != null) + base.Text = _data.Value.ToString(); + } + + private string replaceMacroTags(string text) { + while (findStartTag(text) > -1) { + string result = text.Substring(findStartTag(text), findEndTag(text) - findStartTag(text)); + text = text.Replace(result, generateMacroTag(result)); + } + return text; + } + + private string generateMacroTag(string macroContent) { + string macroAttr = macroContent.Substring(5, macroContent.IndexOf(">") - 5); + string macroTag = "|||?UMBRACO_MACRO "; + Hashtable attributes = ReturnAttributes(macroAttr); + IDictionaryEnumerator ide = attributes.GetEnumerator(); + while (ide.MoveNext()) { + if (ide.Key.ToString().IndexOf("umb_") != -1) { + // Hack to compensate for Firefox adding all attributes as lowercase + string orgKey = ide.Key.ToString(); + if (orgKey == "umb_macroalias") + orgKey = "umb_macroAlias"; + + macroTag += orgKey.Substring(4, orgKey.ToString().Length - 4) + "=|*|" + + ide.Value.ToString() + "|*| "; + } + } + macroTag += "/|||"; + + return macroTag; + } + + public static Hashtable ReturnAttributes(String tag) { + Hashtable ht = new Hashtable(); + MatchCollection m = + Regex.Matches(tag, "(?\\S*)=\"(?[^\"]*)\"", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match attributeSet in m) + ht.Add(attributeSet.Groups["attributeName"].Value.ToString(), + attributeSet.Groups["attributeValue"].Value.ToString()); + + return ht; + } + + private int findStartTag(string text) { + string temp = ""; + text = text.ToLower(); + if (text.IndexOf("ismacro=\"true\"") > -1) { + temp = text.Substring(0, text.IndexOf("ismacro=\"true\"")); + return temp.LastIndexOf("<"); + } + return -1; + } + + private int findEndTag(string text) { + string find = ""; + + int endMacroIndex = text.ToLower().IndexOf(find); + string tempText = text.ToLower().Substring(endMacroIndex + find.Length, text.Length - endMacroIndex - find.Length); + int finalEndPos = 0; + while (tempText.Length > 5) + if (tempText.Substring(finalEndPos, 6) == "") + break; + else + finalEndPos++; + + return endMacroIndex + find.Length + finalEndPos + 6; + } + + #endregion + + #region IDataFieldWithButtons Members + + public object[] MenuIcons { + get { + initButtons(); + + object[] tempIcons = new object[_menuIcons.Count]; + for (int i = 0; i < _menuIcons.Count; i++) + tempIcons[i] = _menuIcons[i]; + return tempIcons; + } + } + + private void initButtons() { + if (!_isInitialized) { + _isInitialized = true; + + // Add icons for the editor control: + // Html + // Preview + // Style picker, showstyles + // Bold, italic, Text Gen + // Align: left, center, right + // Lists: Bullet, Ordered, indent, undo indent + // Link, Anchor + // Insert: Image, macro, table, formular + + foreach (string button in _activateButtons.Split(',')) { + if (button.Trim() != "") { + try { + umbraco.editorControls.tinymce.tinyMCECommand cmd = (umbraco.editorControls.tinymce.tinyMCECommand)umbraco.editorControls.tinymce.tinyMCEConfiguration.Commands[button]; + + string appendValue = ""; + if (cmd.Value != "") + appendValue = ", '" + cmd.Value + "'"; + _mceButtons.Add(cmd.Priority, cmd.Command); + _buttons.Add(cmd.Priority, + new editorButton(cmd.Alias, ui.Text("buttons", cmd.Alias, null), cmd.Icon, + "tinyMCE.execInstanceCommand('" + ClientID + "', '" + + cmd.Command + "', " + cmd.UserInterface + appendValue + ")")); + } catch (Exception ee) { + Log.Add(LogTypes.Error, User.GetUser(0), -1, + string.Format("TinyMCE: Error initializing button '{0}': {1}", button, ee.ToString())); + } + } + } + + // add save icon + int separatorPriority = 0; + IDictionaryEnumerator ide = _buttons.GetEnumerator(); + while (ide.MoveNext()) { + object buttonObj = ide.Value; + int curPriority = (int)ide.Key; + + // Check priority + if (separatorPriority > 0 && + Math.Floor(decimal.Parse(curPriority.ToString()) / 10) > + Math.Floor(decimal.Parse(separatorPriority.ToString()) / 10)) + _menuIcons.Add("|"); + + try { + editorButton e = (editorButton)buttonObj; + + MenuIconI menuItem = new MenuIconClass(); + + menuItem.OnClickCommand = e.onClickCommand; + menuItem.ImageURL = e.imageUrl; + menuItem.AltText = e.alttag; + menuItem.ID = e.id; + _menuIcons.Add(menuItem); + } catch { + } + + separatorPriority = curPriority; + } + } + } + + #endregion + + #region IMenuElement Members + + public string ElementName { + get { return "div"; } + } + + public string ElementIdPreFix { + get { return "umbTinymceMenu"; } + } + + public string ElementClass { + get { return "tinymceMenuBar"; } + } + + public int ExtraMenuWidth { + get { + initButtons(); + return _buttons.Count * 40 + 300; + } + } + + #endregion + + #region ILiveEditingDataEditor Members + + public Control LiveEditingControl + { + get { + m_isInLiveEditingMode = true; + base.IsInLiveEditingMode = true; + return this; + + } + } + + #endregion + } +} \ No newline at end of file diff --git a/components/editorControls/tinyMCE3/tinymce3dataType.cs b/components/editorControls/tinyMCE3/tinymce3dataType.cs new file mode 100644 index 0000000000..11ee9a247a --- /dev/null +++ b/components/editorControls/tinyMCE3/tinymce3dataType.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace umbraco.editorControls.tinyMCE3 +{ + public class tinyMCE3dataType : umbraco.cms.businesslogic.datatype.BaseDataType, umbraco.interfaces.IDataType + { + private umbraco.interfaces.IDataEditor _Editor; + private umbraco.interfaces.IData _baseData; + private umbraco.interfaces.IDataPrevalue _prevalueeditor; + + public override umbraco.interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new TinyMCE(Data, ((umbraco.editorControls.tinymce.tinyMCEPreValueConfigurator)PrevalueEditor).Configuration); + return _Editor; + } + } + + public override umbraco.interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + public override Guid Id + { + get { return new Guid("{5E9B75AE-FACE-41c8-B47E-5F4B0FD82F83}"); } + } + + public override string DataTypeName + { + get { return "TinyMCE v3 wysiwyg"; } + } + + public override umbraco.interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new tinymce.tinyMCEPreValueConfigurator(this); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs b/components/editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs new file mode 100644 index 0000000000..cb0879d7da --- /dev/null +++ b/components/editorControls/tinyMCE3/webcontrol/TinyMCEWebControl.cs @@ -0,0 +1,498 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Collections; +using System.Collections.Specialized; +using System.IO; +using System.Text.RegularExpressions; + +using umbraco.BusinessLogic; +using umbraco.cms.businesslogic.macro; +using umbraco.cms.businesslogic.media; +using umbraco.cms.businesslogic.property; +using Content = umbraco.cms.businesslogic.Content; + +namespace umbraco.editorControls.tinyMCE3.webcontrol +{ + public class TinyMCEWebControl : System.Web.UI.WebControls.TextBox + { + + public NameValueCollection config = new NameValueCollection(); + private string temp; + + private int _nodeId = 0; + private Guid _versionId; + + public bool IsInLiveEditingMode { get; set; } + + public int NodeId + { + set { _nodeId = value; } + get { return _nodeId; } + } + + public Guid VersionId + { + set { _versionId = value; } + get { return _versionId; } + } + + public string InstallPath + { + get + { + if (installPath == null) + installPath = this.config["InstallPath"]; + + return installPath; + } + set { installPath = value; } + } + + #region private + private static readonly object TextChangedEvent = new object(); + private int rows = 10; + private int cols = 70; + private bool gzipEnabled, merged; + private string installPath, mode; + private System.Text.StringBuilder m_scriptInitBlock = new StringBuilder(); + #endregion + + public TinyMCEWebControl() + : base() + { + base.TextMode = TextBoxMode.MultiLine; + base.Attributes.Add("style", "visibility: hidden"); + config.Add("mode", "exact"); + config.Add("theme", "umbraco"); + config.Add("umbraco_path", GlobalSettings.Path); + CssClass = "tinymceContainer"; + plugin.ConfigSection configSection = (plugin.ConfigSection)System.Web.HttpContext.Current.GetSection("TinyMCE"); + + if (configSection != null) + { + this.installPath = configSection.InstallPath; + this.mode = configSection.Mode; + this.gzipEnabled = configSection.GzipEnabled; + + // Copy items into local config collection + foreach (string key in configSection.GlobalSettings.Keys) + this.config[key] = configSection.GlobalSettings[key]; + } + else + { + configSection = new plugin.ConfigSection(); + configSection.GzipExpiresOffset = TimeSpan.FromDays(10).Ticks; + this.gzipEnabled = false; + this.InstallPath = umbraco.editorControls.tinymce.tinyMCEConfiguration.JavascriptPath; + + } + + } + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + // update macro's and images in text + if (_nodeId != 0) + { + base.Text = parseMacrosToHtml(formatMedia(base.Text)); + } + + } + + protected override void Render(HtmlTextWriter writer) + { + base.Render(writer); + if (!IsInLiveEditingMode) + writer.Write(m_scriptInitBlock.ToString()); + else + // add a marker to tell Live Editing when a tinyMCE control is on the page + writer.Write(""); + } + + protected override void OnLoad(EventArgs args) + { + if (!IsInLiveEditingMode) + this.config["elements"] = this.ClientID; + + bool first = true; + + // Render HTML for TinyMCE instance + // in the liveediting mode we're always preloading tinymce script + if (!IsInLiveEditingMode) + { + ScriptManager.RegisterClientScriptInclude(this, this.GetType(), _versionId.ToString(), this.ScriptURI); + } + + // Write script tag start + m_scriptInitBlock.Append(HtmlTextWriter.TagLeftChar.ToString()); + m_scriptInitBlock.Append("script"); + m_scriptInitBlock.Append(" type=\"text/javascript\""); + m_scriptInitBlock.Append(HtmlTextWriter.TagRightChar.ToString()); + m_scriptInitBlock.Append("\n"); + + m_scriptInitBlock.Append("tinyMCE.init({\n"); + + // Write options + foreach (string key in this.config.Keys) + { + //TODO: This is a hack to test if we can prevent tinymce from automatically download languages + if (!IsInLiveEditingMode || (key != "language")) + { + string val = this.config[key]; + + if (!first) + m_scriptInitBlock.Append(",\n"); + else + first = false; + + // Is boolean state or string + if (val == "true" || val == "false") + m_scriptInitBlock.Append(key + ":" + this.config[key]); + else + m_scriptInitBlock.Append(key + ":'" + this.config[key] + "'"); + } + } + + m_scriptInitBlock.Append("\n});\n"); + // we're wrapping the tinymce init call in a load function when in live editing, + // so we'll need to close that function declaration + if (IsInLiveEditingMode) + { + m_scriptInitBlock.Append(@"(function() { var f = + function() { + if(document.getElementById('__umbraco_tinyMCE')) + tinyMCE.execCommand('mceAddControl',false,'").Append(ClientID).Append(@"'); + ItemEditing.remove_startEdit(f); + } + ItemEditing.add_startEdit(f);})();"); + m_scriptInitBlock.Append(@"(function() { var f = + function() { + tinyMCE.execCommand('mceRemoveControl',false,'").Append(ClientID).Append(@"'); + ItemEditing.remove_stopEdit(f); + } + ItemEditing.add_stopEdit(f);})();"); + } + + // Write script tag end + m_scriptInitBlock.Append(HtmlTextWriter.EndTagLeftChars); + m_scriptInitBlock.Append("script"); + m_scriptInitBlock.Append(HtmlTextWriter.TagRightChar.ToString()); + + // add to script manager + if (IsInLiveEditingMode) + { + ScriptManager.RegisterClientScriptBlock(this, this.GetType(), new Guid().ToString(), + m_scriptInitBlock.ToString(), false); + } + + } + + + string ScriptURI + { + get + { + string suffix = "", outURI; + + if (this.InstallPath == null) + throw new Exception("Required installPath setting is missing, add it to your web.config. You can also add it directly to your tinymce:TextArea element using InstallPath but the web.config method is recommended since it allows you to switch over to gzip compression."); + + if (this.mode != null) + suffix = "_" + this.mode; + + outURI = this.InstallPath + "/tiny_mce_src" + suffix + ".js"; + if (!File.Exists(this.Context.Server.MapPath(outURI))) + throw new Exception("Could not locate TinyMCE by URI:" + outURI + ", Physical path:" + this.Context.Server.MapPath(outURI) + ". Make sure that you configured the installPath to a valid location in your web.config. This path should be an relative or site absolute URI to where TinyMCE is located."); + + // Collect themes, languages and plugins and build gzip URI + // TODO: Make sure gzip is re-enabled + this.gzipEnabled = true; + if (this.gzipEnabled) + { + ArrayList themes = new ArrayList(), plugins = new ArrayList(), languages = new ArrayList(); + + // Add themes + if (config["theme"] == null) + config["theme"] = "simple"; + + foreach (string theme in config["theme"].Split(',')) + { + string themeVal = theme.Trim(); + + if (themes.IndexOf(themeVal) == -1) + themes.Add(themeVal); + } + + // Add plugins + if (config["plugins"] != null) + { + foreach (string plugin in config["plugins"].Split(',')) + { + string pluginVal = plugin.Trim(); + + if (plugins.IndexOf(pluginVal) == -1) + plugins.Add(pluginVal); + } + } + + // Add language + if (config["language"] == null) + config["language"] = "en"; + + if (languages.IndexOf(config["language"]) == -1) + languages.Add(config["language"]); + + // NH: No clue why these extra dashes are added, but the affect other parts of the implementation + // Skip loading of themes and plugins + // area.config["theme"] = "-" + area.config["theme"]; + + // if (area.config["plugins"] != null) + // area.config["plugins"] = "-" + String.Join(",-", area.config["plugins"].Split(',')); + + // Build output URI + // NH: Use versionId for randomize to ensure we don't download a new tinymce on every single call + outURI = umbraco.editorControls.tinymce.tinyMCEConfiguration.PluginPath + "/tinymce3tinymceCompress.aspx?rnd=" + this._versionId.ToString() + "&module=gzipmodule"; + + if (themes.Count > 0) + outURI += "&themes=" + String.Join(",", ((string[])themes.ToArray(typeof(string)))); + + if (plugins.Count > 0) + outURI += "&plugins=" + String.Join(",", ((string[])plugins.ToArray(typeof(string)))); + + if (languages.Count > 0) + outURI += "&languages=" + String.Join(",", ((string[])languages.ToArray(typeof(string)))); + } + + return outURI; + } + } + + + private string formatMedia(string html) + { + // Local media path + string localMediaPath = getLocalMediaPath(); + + // Find all media images + string pattern = "]*src=\"(?/media[^\"]*)\" [^>]*>"; + + MatchCollection tags = + Regex.Matches(html, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match tag in tags) + if (tag.Groups.Count > 0) + { + // Replace /> to ensure we're in old-school html mode + string tempTag = "", " >"), + "(?\\S*)=\"(?[^\"]*)\"|(?\\S*)=(?[^\"|\\s]*)\\s", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match attributeSet in m) + { + if (attributeSet.Groups["attributeName"].Value.ToString().ToLower() != "src") + ht.Add(attributeSet.Groups["attributeName"].Value.ToString(), + attributeSet.Groups["attributeValue"].Value.ToString()); + } + + // build the element + // Build image tag + IDictionaryEnumerator ide = ht.GetEnumerator(); + while (ide.MoveNext()) + tempTag += " " + ide.Key.ToString() + "=\"" + ide.Value.ToString() + "\""; + + // Find the original filename, by removing the might added width and height + orgSrc = + orgSrc.Replace( + "_" + helper.FindAttribute(ht, "width") + "x" + helper.FindAttribute(ht, "height"), ""). + Replace("%20", " "); + + // Check for either id or guid from media + string mediaId = getIdFromSource(orgSrc, localMediaPath); + + Media imageMedia = null; + + try + { + int mId = int.Parse(mediaId); + Property p = new Property(mId); + imageMedia = new Media(Content.GetContentFromVersion(p.VersionId).Id); + } + catch + { + try + { + imageMedia = new Media(Content.GetContentFromVersion(new Guid(mediaId)).Id); + } + catch + { + } + } + + // Check with the database if any media matches this url + if (imageMedia != null) + { + try + { + // Check extention + if (imageMedia.getProperty("umbracoExtension").Value.ToString() != orgSrc.Substring(orgSrc.LastIndexOf(".") + 1, orgSrc.Length - orgSrc.LastIndexOf(".") - 1)) + orgSrc = orgSrc.Substring(0, orgSrc.LastIndexOf(".") + 1) + + imageMedia.getProperty("umbracoExtension").Value.ToString(); + + // Format the tag + tempTag = tempTag + " rel=\"" + + imageMedia.getProperty("umbracoWidth").Value.ToString() + "," + + imageMedia.getProperty("umbracoHeight").Value.ToString() + "\" src=\"" + orgSrc + + "\""; + tempTag += "/>"; + + // Replace the tag + html = html.Replace(tag.Value, tempTag); + } + catch (Exception ee) + { + Log.Add(LogTypes.Error, User.GetUser(0), -1, + "Error reading size data from media: " + imageMedia.Id.ToString() + ", " + + ee.ToString()); + } + } + else + Log.Add(LogTypes.Error, User.GetUser(0), -1, + "Error reading size data from media (not found): " + orgSrc); + } + return html; + } + + private string getIdFromSource(string src, string localMediaPath) + { + // important - remove out the umbraco path + media! + src = src.Replace(localMediaPath, ""); + + string _id = ""; + + // Check for directory id naming + if (src.Length - src.Replace("/", "").Length > 0) + { + string[] dirSplit = src.Split("/".ToCharArray()); + string tempId = dirSplit[0]; + try + { + // id + _id = int.Parse(tempId).ToString(); + } + catch + { + // guid + _id = tempId; + } + } + else + { + string[] fileSplit = src.Replace("/media/", "").Split("-".ToCharArray()); + + // guid or id + if (fileSplit.Length > 3) + { + for (int i = 0; i < 5; i++) + _id += fileSplit[i] + "-"; + _id = _id.Substring(0, _id.Length - 1); + } + else + _id = fileSplit[0]; + } + + return _id; + } + + private string getLocalMediaPath() + { + string[] umbracoPathSplit = GlobalSettings.Path.Split("/".ToCharArray()); + string umbracoPath = ""; + for (int i = 0; i < umbracoPathSplit.Length - 1; i++) + umbracoPath += umbracoPathSplit[i] + "/"; + return umbracoPath + "media/"; + } + + + private string parseMacrosToHtml(string input) + { + int nodeId = _nodeId; + Guid versionId = _versionId; + string content = input; + + + string pattern = @"(<\?UMBRACO_MACRO\W*[^>]*/>)"; + MatchCollection tags = + Regex.Matches(content, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + + // Page for macro rendering + page p = new page(nodeId, versionId); + System.Web.HttpContext.Current.Items["macrosAdded"] = 0; + System.Web.HttpContext.Current.Items["pageID"] = nodeId.ToString(); + + foreach (Match tag in tags) + { + try + { + // Create div + Hashtable attributes = helper.ReturnAttributes(tag.Groups[1].Value); + string div = macro.renderMacroStartTag(attributes, nodeId, versionId); //.Replace(""", "&quot;"); + + // Insert macro contents here... + macro m; + if (helper.FindAttribute(attributes, "macroID") != "") + m = new macro(int.Parse(helper.FindAttribute(attributes, "macroID"))); + else + { + // legacy: Check if the macroAlias is typed in lowercasing + string macroAlias = helper.FindAttribute(attributes, "macroAlias"); + if (macroAlias == "") + { + macroAlias = helper.FindAttribute(attributes, "macroalias"); + attributes.Remove("macroalias"); + attributes.Add("macroAlias", macroAlias); + } + + if (macroAlias != "") + m = new macro(Macro.GetByAlias(macroAlias).Id); + else + throw new ArgumentException("umbraco is unable to identify the macro. No id or macroalias was provided for the macro in the macro tag.", tag.Groups[1].Value); + } + + if (helper.FindAttribute(attributes, "macroAlias") == "") + attributes.Add("macroAlias", m.Alias); + + + try + { + div += macro.MacroContentByHttp(nodeId, versionId, attributes); + } + catch + { + div += "No macro content available for WYSIWYG editing"; + } + + + div += macro.renderMacroEndTag(); + content = content.Replace(tag.Groups[1].Value, div); + } + catch (Exception ee) + { + Log.Add(LogTypes.Error, this._nodeId, "Macro Parsing Error: " + ee.ToString()); + string div = "

umbraco was unable to parse a macro tag, which means that parts of this content might be corrupt.

Best solution is to rollback to a previous version by right clicking the node in the tree and then try to insert the macro again.

Please report this to your system administrator as well - this error has been logged.

"; + content = content.Replace(tag.Groups[1].Value, div); + } + + } + return content; + } + } +} diff --git a/components/editorControls/tinyMCE3/webcontrol/plugin/ConfigSection.cs b/components/editorControls/tinyMCE3/webcontrol/plugin/ConfigSection.cs new file mode 100644 index 0000000000..ec4d7764cf --- /dev/null +++ b/components/editorControls/tinyMCE3/webcontrol/plugin/ConfigSection.cs @@ -0,0 +1,95 @@ +/* + * $Id: ConfigSection.cs 439 2007-11-26 13:26:10Z spocke $ + * + * @author Moxiecode + * @copyright Copyright 2004-2007, Moxiecode Systems AB, All rights reserved. + */ + +using System; +using System.Collections.Specialized; + +namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin +{ + /// + /// Description of ConfigSection. + /// + public class ConfigSection { + #region private + private NameValueCollection globalSettings; + private bool gzipEnabled, gzipDiskCache, gzipNoCompression; + private string installPath, mode, gzipCachePath; + private long gzipExpiresOffset; + #endregion + + /// + /// + /// + public ConfigSection() { + this.globalSettings = new NameValueCollection(); + } + + /// + /// + /// + public string InstallPath { + get { return installPath; } + set { installPath = value; } + } + + /// + /// + /// + public string Mode { + get { return mode; } + set { mode = value; } + } + + /// + /// + /// + public NameValueCollection GlobalSettings { + get { return globalSettings; } + set { globalSettings = value; } + } + + /// + /// + /// + public bool GzipEnabled { + get { return gzipEnabled; } + set { gzipEnabled = value; } + } + + /// + /// + /// + public long GzipExpiresOffset { + get { return gzipExpiresOffset; } + set { gzipExpiresOffset = value; } + } + + /// + /// + /// + public bool GzipDiskCache { + get { return gzipDiskCache; } + set { gzipDiskCache = value; } + } + + /// + /// + /// + public string GzipCachePath { + get { return gzipCachePath; } + set { gzipCachePath = value; } + } + + /// + /// + /// + public bool GzipNoCompression { + get { return gzipNoCompression; } + set { gzipNoCompression = value; } + } + } +} diff --git a/components/editorControls/tinyMCE3/webcontrol/plugin/GzipCompressor.cs b/components/editorControls/tinyMCE3/webcontrol/plugin/GzipCompressor.cs new file mode 100644 index 0000000000..f95d66c536 --- /dev/null +++ b/components/editorControls/tinyMCE3/webcontrol/plugin/GzipCompressor.cs @@ -0,0 +1,264 @@ +/* + * $Id: GzipCompressor.cs 439 2007-11-26 13:26:10Z spocke $ + * + * @author Moxiecode + * @copyright Copyright 2004-2007, Moxiecode Systems AB, All rights reserved. + */ + +using System; +using System.Web; +using System.Collections; +using System.IO; +using System.IO.Compression; +using System.Security.Cryptography; +using System.Text; + +namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin +{ + /// + /// Description of GzipCompressor. + /// + public class GzipCompressor { + #region private + private bool diskCache, noCompression; + private string cachePath; + private ArrayList items; + #endregion + + /// + /// + /// + public GzipCompressor() { + this.items = new ArrayList(); + } + + /// + /// + /// + public bool NoCompression { + get { return noCompression; } + set { noCompression = value; } + } + + /// + /// + /// + public bool DiskCache { + get { return diskCache; } + set { diskCache = value; } + } + + /// + /// + /// + public string CachePath { + get { return cachePath; } + set { cachePath = value; } + } + + /// + /// + /// + /// + public void AddFile(string path) { + //System.Web.HttpContext.Current.Response.Write(path + "\n"); + if (File.Exists(path)) + this.items.Add(new CompressItem(CompressItemType.File, path)); + else + throw new Exception("File could not be found \"" + path + "\", unable to add it for Gzip compression."); + } + + /// + /// + /// + /// + public void AddData(string data) { + this.items.Add(new CompressItem(CompressItemType.Chunk, data)); + } + + /// + /// + /// + /// + public void Compress(Stream to_stream) { + GZipStream gzipStream = null; + string key = ""; + byte[] bytes; + + // Build cache key + foreach (CompressItem item in this.items) { + if (item.Type == CompressItemType.File) + key += item.Data; + } + + key = MD5(key); + if (this.NoCompression) { + this.SendPlainText(key, to_stream); + return; + } + + // Check for cached file on disk, stream that one if it was found + if (this.DiskCache && File.Exists(Path.Combine(this.CachePath, key + ".gz"))) { + this.StreamFromTo(File.OpenRead(Path.Combine(this.CachePath, key + ".gz")), to_stream, 4096, CloseMode.InStream); + return; + } + + try { + // Build new gzipped stream + if (this.DiskCache) { + gzipStream = new GZipStream(File.OpenWrite(Path.Combine(this.CachePath, key + ".gz")), CompressionMode.Compress); + + // Compress all files into memory + foreach (CompressItem item in this.items) { + // Add file + if (item.Type == CompressItemType.File) + StreamFromTo(File.OpenRead(item.Data), gzipStream, 4096, CloseMode.InStream); + + // Add chunk + if (item.Type == CompressItemType.Chunk) { + bytes = Encoding.ASCII.GetBytes(item.Data.ToCharArray()); + gzipStream.Write(bytes, 0, bytes.Length); + } + } + + // Close gzip stream + gzipStream.Close(); + gzipStream = null; + + // Send cached file to user + this.StreamFromTo(File.OpenRead(Path.Combine(this.CachePath, key + ".gz")), to_stream, 4096, CloseMode.InStream); + } else { + gzipStream = new GZipStream(to_stream, CompressionMode.Compress); + + // Compress all files into output stream + foreach (CompressItem item in this.items) { + // Add file + if (item.Type == CompressItemType.File) + StreamFromTo(File.OpenRead(item.Data), gzipStream, 4096, CloseMode.InStream); + + // Add chunk + if (item.Type == CompressItemType.Chunk) { + bytes = Encoding.ASCII.GetBytes(item.Data.ToCharArray()); + gzipStream.Write(bytes, 0, bytes.Length); + } + } + } + } finally { + if (gzipStream != null) + gzipStream.Close(); + } + } + + #region private + + private void SendPlainText(string key, Stream to_stream) { + Stream fileStream = null; + byte[] bytes; + + // Check for cached file on disk, stream that one if it was found + if (this.DiskCache && File.Exists(Path.Combine(this.CachePath, key + ".js"))) { + this.StreamFromTo(File.OpenRead(Path.Combine(this.CachePath, key + ".js")), to_stream, 4096, CloseMode.InStream); + return; + } + + // Build new plain text stream + if (this.DiskCache) { + try { + fileStream = File.OpenWrite(Path.Combine(this.CachePath, key + ".js")); + + // Compress all files into memory + foreach (CompressItem item in this.items) { + // Add file + if (item.Type == CompressItemType.File) + StreamFromTo(File.OpenRead(item.Data), fileStream, 4096, CloseMode.InStream); + + // Add chunk + if (item.Type == CompressItemType.Chunk) { + bytes = Encoding.ASCII.GetBytes(item.Data.ToCharArray()); + fileStream.Write(bytes, 0, bytes.Length); + } + } + + // Close file stream + fileStream.Close(); + fileStream = null; + } finally { + // Close file stream + if (fileStream != null) + fileStream.Close(); + } + + // Send cached file to user + this.StreamFromTo(File.OpenRead(Path.Combine(this.CachePath, key + ".js")), to_stream, 4096, CloseMode.InStream); + } else { + // Concat all files into output stream + foreach (CompressItem item in this.items) { + // Add file + if (item.Type == CompressItemType.File) + StreamFromTo(File.OpenRead(item.Data), to_stream, 4096, CloseMode.InStream); + + // Add chunk + if (item.Type == CompressItemType.Chunk) { + bytes = Encoding.ASCII.GetBytes(item.Data.ToCharArray()); + to_stream.Write(bytes, 0, bytes.Length); + } + } + } + } + + private void StreamFromTo(Stream in_stream, Stream out_stream, int buff_size, CloseMode mode) { + byte[] buff = new byte[buff_size]; + int len; + + try { + while ((len = in_stream.Read(buff, 0, buff_size)) > 0) { + out_stream.Write(buff, 0, len); + out_stream.Flush(); + } + } finally { + if (in_stream != null && (mode == CloseMode.Both || mode == CloseMode.InStream)) + in_stream.Close(); + + if (out_stream != null && (mode == CloseMode.Both || mode == CloseMode.OutStream)) + out_stream.Close(); + } + } + + private string MD5(string str) { + MD5 md5 = new MD5CryptoServiceProvider(); + byte[] result = md5.ComputeHash(Encoding.ASCII.GetBytes(str)); + str = BitConverter.ToString(result); + + return str.Replace("-", ""); + } + + #endregion + } + + enum CloseMode { + None, InStream, OutStream, Both + } + + enum CompressItemType { + File, Chunk + } + + class CompressItem { + private string data; + private CompressItemType type; + + public CompressItem(CompressItemType type, string data) { + this.type = type; + this.data = data; + } + + public string Data { + get { return data; } + set { data = value; } + } + + public CompressItemType Type { + get { return type; } + } + } +} diff --git a/components/editorControls/tinyMCE3/webcontrol/plugin/GzipModule.cs b/components/editorControls/tinyMCE3/webcontrol/plugin/GzipModule.cs new file mode 100644 index 0000000000..d85df8c999 --- /dev/null +++ b/components/editorControls/tinyMCE3/webcontrol/plugin/GzipModule.cs @@ -0,0 +1,113 @@ +/* + * $Id: GzipModule.cs 439 2007-11-26 13:26:10Z spocke $ + * + * @author Moxiecode + * @copyright Copyright 2004-2007, Moxiecode Systems AB, All rights reserved. + */ + +using System; +using System.Web; +using System.Text.RegularExpressions; +using System.IO; + +namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin +{ + /// + /// Description of HttpHandler. + /// + public class GzipModule : IModule { + /// + /// Request context. + public void ProcessRequest(HttpContext context) { + HttpRequest request = context.Request; + HttpResponse response = context.Response; + HttpServerUtility server = context.Server; + GzipCompressor gzipCompressor = new GzipCompressor(); + ConfigSection configSection = (ConfigSection) System.Web.HttpContext.Current.GetSection("TinyMCE"); + string suffix = "", enc; + string[] languages = request.QueryString["languages"].Split(','); + bool supportsGzip; + + // Set response headers + response.ContentType = "text/javascript"; + response.Charset = "UTF-8"; + response.Buffer = false; + + // UMBRACO: Populate the configsection if it's empty + if (configSection == null) + { + configSection = new ConfigSection(); + configSection.GzipEnabled = true; + configSection.InstallPath = umbraco.editorControls.tinymce.tinyMCEConfiguration.JavascriptPath; + configSection.GzipExpiresOffset = TimeSpan.FromDays(10).Ticks; + } + + // Setup cache + response.Cache.SetExpires(DateTime.Now.AddTicks(configSection.GzipExpiresOffset)); + response.Cache.SetCacheability(HttpCacheability.Public); + response.Cache.SetValidUntilExpires(false); + + // Check if it supports gzip + enc = Regex.Replace("" + request.Headers["Accept-Encoding"], @"\s+", "").ToLower(); + supportsGzip = enc.IndexOf("gzip") != -1 || request.Headers["---------------"] != null; + enc = enc.IndexOf("x-gzip") != -1 ? "x-gzip" : "gzip"; + + // Handle mode/suffix + if (configSection.Mode != null) + suffix = "_" + configSection.Mode; + + gzipCompressor.AddData("var tinyMCEPreInit = {base : '" + new Uri(request.Url, configSection.InstallPath).ToString() + "', suffix : '" + suffix + "'};"); + + // Add core + gzipCompressor.AddFile(server.MapPath(configSection.InstallPath + "/tiny_mce" + suffix + ".js")); + + // Add core languages + foreach (string lang in languages) + gzipCompressor.AddFile(server.MapPath(configSection.InstallPath + "/langs/" + lang + ".js")); + + // Add themes + if (request.QueryString["themes"] != null) { + foreach (string theme in request.QueryString["themes"].Split(',')) { + gzipCompressor.AddFile(server.MapPath(configSection.InstallPath + "/themes/" + theme + "/editor_template" + suffix + ".js")); + + // Add theme languages + foreach (string lang in languages) { + string path = server.MapPath(configSection.InstallPath + "/themes/" + theme + "/langs/" + lang + ".js"); + + if (File.Exists(path)) + gzipCompressor.AddFile(path); + } + + gzipCompressor.AddData("tinymce.ThemeManager.urls['" + theme + "'] = tinymce.baseURL+'/themes/" + theme + "';"); + } + } + + // Add plugins + if (request.QueryString["plugins"] != null) { + foreach (string plugin in request.QueryString["plugins"].Split(',')) { + gzipCompressor.AddFile(server.MapPath(configSection.InstallPath + "/plugins/" + plugin + "/editor_plugin" + suffix + ".js")); + + // Add plugin languages + foreach (string lang in languages) { + string path = server.MapPath(configSection.InstallPath + "/plugins/" + plugin + "/langs/" + lang + ".js"); + + if (File.Exists(path)) + gzipCompressor.AddFile(path); + } + + gzipCompressor.AddData("tinymce.ThemeManager.urls['" + plugin + "'] = tinymce.baseURL+'/plugins/" + plugin + "';"); + } + } + + // Output compressed file + gzipCompressor.NoCompression = !supportsGzip || configSection.GzipNoCompression; + if (!gzipCompressor.NoCompression) + response.AppendHeader("Content-Encoding", enc); + + gzipCompressor.DiskCache = configSection.GzipDiskCache; + gzipCompressor.CachePath = configSection.GzipCachePath; + + gzipCompressor.Compress(response.OutputStream); + } + } +} diff --git a/components/editorControls/tinyMCE3/webcontrol/plugin/IModule.cs b/components/editorControls/tinyMCE3/webcontrol/plugin/IModule.cs new file mode 100644 index 0000000000..8666b82996 --- /dev/null +++ b/components/editorControls/tinyMCE3/webcontrol/plugin/IModule.cs @@ -0,0 +1,24 @@ +/* + * Created by SharpDevelop. + * User: spocke + * Date: 2007-11-22 + * Time: 14:32 + * + * To change this template use Tools | Options | Coding | Edit Standard Headers. + */ + +using System; +using System.Web; + +namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin { + /// + /// Description of IAction. + /// + public interface IModule { + /// + /// + /// + /// + void ProcessRequest(HttpContext context); + } +} diff --git a/components/editorControls/tinyMCE3/webcontrol/plugin/JSON.cs b/components/editorControls/tinyMCE3/webcontrol/plugin/JSON.cs new file mode 100644 index 0000000000..37449f5624 --- /dev/null +++ b/components/editorControls/tinyMCE3/webcontrol/plugin/JSON.cs @@ -0,0 +1,352 @@ +/* + * $Id: JSON.cs 439 2007-11-26 13:26:10Z spocke $ + * + * Copyright 2007, Moxiecode Systems AB, All rights reserved. + */ + +using System; +using System.IO; +using System.Collections; +using System.Collections.Specialized; + +namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin +{ + /// + /// Description of JSON. + /// + public class JSON { + /// + /// + /// + public static void SerializeRPC(string id, object error, object obj, Stream stream) { + JSONWriter writer = new JSONWriter(new StreamWriter(stream)); + + // Start JSON output + writer.WriteStartObject(); + writer.WritePropertyName("result"); + WriteValue(writer, obj); + + // Write id + writer.WritePropertyName("id"); + writer.WriteValue(id); + + // Write error + writer.WritePropertyName("error"); + writer.WriteValue(null); + + // Close + writer.WriteEndObject(); + writer.Close(); + } + + /// + /// + /// + /// + /// + public static void WriteObject(TextWriter writer, object obj) { + WriteValue(new JSONWriter(writer), obj); + writer.Flush(); + } + + private static void WriteValue(JSONWriter writer, object obj) { + if (obj == null) + writer.WriteNull(); + + if (obj is System.String) + writer.WriteValue((string) obj); + + if (obj is System.Boolean) + writer.WriteValue((bool) obj); + + if (obj is System.Double) + writer.WriteValue(Convert.ToDouble(obj)); + + if (obj is System.Int32) + writer.WriteValue(Convert.ToInt32(obj)); + + if (obj is System.Int64) + writer.WriteValue(Convert.ToInt64(obj)); + + if (obj is ArrayList) { + writer.WriteStartArray(); + + foreach (object val in ((ArrayList) obj)) + WriteValue(writer, val); + + writer.WriteEndArray(); + } + + if (obj is string[]) { + writer.WriteStartArray(); + + foreach (string val in ((string[]) obj)) + WriteValue(writer, val); + + writer.WriteEndArray(); + } + + if (obj is NameValueCollection) { + writer.WriteStartObject(); + + string[] keys = GetReversedKeys(obj); + foreach (string key in keys) { + writer.WritePropertyName(key); + WriteValue(writer, ((NameValueCollection) obj)[key]); + } + + writer.WriteEndObject(); + } + + if (obj is Hashtable) { + writer.WriteStartObject(); + + string[] keys = GetReversedKeys(obj); + foreach (string key in keys) { + writer.WritePropertyName((string) key); + WriteValue(writer, ((Hashtable) obj)[key]); + } + + writer.WriteEndObject(); + } + } + + private static string[] GetReversedKeys(object obj) { + ICollection keyCollection; + string[] keys; + int count; + + if (obj is Hashtable) + keyCollection = ((Hashtable) obj).Keys; + else + keyCollection = ((NameValueCollection) obj).AllKeys; + + count = keyCollection.Count; + keys = new string[count]; + + foreach (string key in keyCollection) + keys[--count] = key; + + Array.Sort(keys); + + return keys; + } + + /// + /// + /// + /// + /// + public static object ParseJSON(TextReader reader) { + return ReadValue(new JSONReader(reader)); + } + + /// + /// + /// + /// + /// + public static JSONRpcCall ParseRPC(TextReader reader) { + JSONRpcCall call = new JSONRpcCall(); + object obj = ParseJSON(reader); + Hashtable jsonRpc = (Hashtable) obj; + + call.Method = (string) jsonRpc["method"]; + call.Id = (string) jsonRpc["id"]; + call.Args = (ArrayList) jsonRpc["params"]; + + return call; + } + + #region private methods + +/* private static void Debug(string str) { + System.Web.HttpContext.Current.Trace.Write(str); + }*/ + + private static object ReadValue(JSONReader reader) { + Stack parents = new Stack(); + object cur = null; + string key = null; + object obj; + + while (reader.Read()) { + //Debug(reader.ToString()); + + switch (reader.TokenType) { + case JSONToken.Boolean: + case JSONToken.Integer: + case JSONToken.String: + case JSONToken.Float: + case JSONToken.Null: + if (cur is Hashtable) { + //Debug(key + "=" + reader.ToString()); + ((Hashtable) cur)[key] = reader.Value; + } else if (cur is ArrayList) + ((ArrayList) cur).Add(reader.Value); + else + return reader.Value; + + break; + + case JSONToken.PropertyName: + key = (string) reader.Value; + break; + + case JSONToken.StartArray: + case JSONToken.StartObject: + if (reader.TokenType == JSONToken.StartObject) + obj = new Hashtable(); + else + obj = new ArrayList(); + + if (cur is Hashtable) { + //Debug(key + "=" + reader.ToString()); + ((Hashtable) cur)[key] = obj; + } else if (cur is ArrayList) + ((ArrayList) cur).Add(obj); + + parents.Push(cur); + cur = obj; + + break; + + case JSONToken.EndArray: + case JSONToken.EndObject: + obj = parents.Pop(); + + if (obj != null) + cur = obj; + + break; + } + } + + return cur; + } + + private static object ReadValue2(JSONReader jsonReader) { + jsonReader.Read(); + + switch (jsonReader.TokenType) { + case JSONToken.Boolean: + return (bool) jsonReader.Value; + + case JSONToken.Integer: + return Convert.ToInt32(jsonReader.Value); + + case JSONToken.String: + return (string) jsonReader.Value; + + case JSONToken.Float: + return (double) jsonReader.Value; + + case JSONToken.Null: + return null; + + case JSONToken.StartObject: + Hashtable hash = new Hashtable(); + + while (jsonReader.TokenType != JSONToken.EndObject) { + if (jsonReader.TokenType == JSONToken.PropertyName) + hash[jsonReader.Value] = ReadValue(jsonReader); + else + jsonReader.Read(); + } + + return hash; + + case JSONToken.StartArray: + ArrayList list = new ArrayList(); + + while (jsonReader.TokenType != JSONToken.EndArray) { + if (jsonReader.TokenType == JSONToken.EndArray && jsonReader.Value == null) + break; + + list.Add(ReadValue(jsonReader)); + } + + return list; + } + + return null; + } + + private static bool FindNext(JSONReader reader, JSONToken token) { + if (reader.TokenType == token) + return true; + + while (reader.Read() && reader.TokenType != JSONToken.EndObject && reader.TokenType != JSONToken.EndArray) { + if (reader.TokenType == token) + return true; + } + + return false; + } + + private static bool FindNextValue(JSONReader reader) { + switch (reader.TokenType) { + case JSONToken.Boolean: + case JSONToken.Float: + case JSONToken.Integer: + case JSONToken.Null: + case JSONToken.String: + return true; + } + + while (reader.Read() && reader.TokenType != JSONToken.EndObject) { + switch (reader.TokenType) { + case JSONToken.Boolean: + case JSONToken.Float: + case JSONToken.Integer: + case JSONToken.Null: + case JSONToken.String: + return true; + } + } + + return false; + } + + #endregion + } + + /// + /// + /// + public class JSONRpcCall { + private string id, method; + private ArrayList args; + + /// + /// + /// + public JSONRpcCall() { + this.args = new ArrayList(); + } + + /// + /// + /// + public string Method { + get { return method; } + set { method = value; } + } + + /// + /// + /// + public string Id { + get { return id; } + set { id = value; } + } + + /// + /// + /// + public ArrayList Args { + get { return args; } + set { args = value; } + } + } +} diff --git a/components/editorControls/tinyMCE3/webcontrol/plugin/JSONReader.cs b/components/editorControls/tinyMCE3/webcontrol/plugin/JSONReader.cs new file mode 100644 index 0000000000..0a4c469515 --- /dev/null +++ b/components/editorControls/tinyMCE3/webcontrol/plugin/JSONReader.cs @@ -0,0 +1,387 @@ +/* + * $Id: JSONReader.cs 439 2007-11-26 13:26:10Z spocke $ + * + * Copyright 2007, Moxiecode Systems AB, All rights reserved. + */ + +using System; +using System.IO; +using System.Text; +using System.Collections; + +namespace umbraco.editorControls.tinyMCE3.webcontrol.plugin +{ + /// + /// + /// + public enum JSONToken { + /// + Boolean, + + /// + Integer, + + /// + String, + + /// + Null, + + /// + Float, + + /// + StartArray, + + /// + EndArray, + + /// + PropertyName, + + /// + StartObject, + + /// + EndObject + } + + /// + /// Description of JSONReader. + /// + public class JSONReader { + private TextReader reader; + private JSONToken token; + private object val; + private JSONLocation location; + private Stack lastLocations; + private bool needProp; + + /// + /// + /// + /// + public JSONReader(TextReader reader) { + this.reader = reader; + this.val = null; + this.token = JSONToken.Null; + this.location = JSONLocation.Normal; + this.lastLocations = new Stack(); + this.needProp = false; + } + + /// + /// + /// + public JSONLocation Location { + get { return location; } + } + + /// + /// + /// + public JSONToken TokenType { + get { + return this.token; + } + } + + /// + /// + /// + public object Value { + get { + return this.val; + } + } + + /// + /// + /// + /// + public bool Read() { + int chr = this.reader.Read(); + + if (chr != -1) { + switch ((char) chr) { + case '[': + this.lastLocations.Push(this.location); + this.location = JSONLocation.InArray; + this.token = JSONToken.StartArray; + this.val = null; + this.ReadAway(); + return true; + + case ']': + this.location = (JSONLocation) this.lastLocations.Pop(); + this.token = JSONToken.EndArray; + this.val = null; + this.ReadAway(); + + if (this.location == JSONLocation.InObject) + this.needProp = true; + + return true; + + case '{': + this.lastLocations.Push(this.location); + this.location = JSONLocation.InObject; + this.needProp = true; + this.token = JSONToken.StartObject; + this.val = null; + this.ReadAway(); + return true; + + case '}': + this.location = (JSONLocation) this.lastLocations.Pop(); + this.token = JSONToken.EndObject; + this.val = null; + this.ReadAway(); + + if (this.location == JSONLocation.InObject) + this.needProp = true; + + return true; + + // String + case '"': + case '\'': + return this.ReadString((char) chr); + + // Null + case 'n': + return this.ReadNull(); + + // Bool + case 't': + case 'f': + return this.ReadBool((char) chr); + + default: + // Is number + if (Char.IsNumber((char) chr) || (char) chr == '-' || (char) chr == '.') + return this.ReadNumber((char) chr); + + return true; + } + } + + return false; + } + + /// + /// + /// + /// + public override string ToString() { + switch (this.token) { + case JSONToken.Boolean: + return "[Boolean] = " + ((bool) this.Value ? "true" : "false"); + + case JSONToken.EndArray: + return "[EndArray]"; + + case JSONToken.EndObject: + return "[EndObject]"; + + case JSONToken.Float: + return "[Float] = " + Convert.ToDouble(this.Value); + + case JSONToken.Integer: + return "[Integer] = " + ((int) this.Value); + + case JSONToken.Null: + return "[Null]"; + + case JSONToken.StartArray: + return "[StartArray]"; + + case JSONToken.StartObject: + return "[StartObject]"; + + case JSONToken.String: + return "[String]" + (string) this.Value; + + case JSONToken.PropertyName: + return "[PropertyName]" + (string) this.Value; + } + + return base.ToString(); + } + + #region private methods + + private bool ReadString(char quote) { + StringBuilder buff = new StringBuilder(); + this.token = JSONToken.String; + bool endString = false; + int chr; + + while ((chr = this.reader.Peek()) != -1) { + switch (chr) { + case '\\': + // Read away slash + chr = this.reader.Read(); + + // Read escape code + chr = this.reader.Read(); + switch (chr) { + case 't': + buff.Append('\t'); + break; + + case 'b': + buff.Append('\b'); + break; + + case 'f': + buff.Append('\f'); + break; + + case 'r': + buff.Append('\r'); + break; + + case 'n': + buff.Append('\n'); + break; + + case 'u': + buff.Append((char) Convert.ToInt32(ReadLen(4), 16)); + break; + + default: + buff.Append((char) chr); + break; + } + + break; + + case '\'': + case '"': + if (chr == quote) + endString = true; + + chr = this.reader.Read(); + if (chr != -1 && chr != quote) + buff.Append((char) chr); + + break; + + default: + buff.Append((char) this.reader.Read()); + break; + } + + // String terminated + if (endString) + break; + } + + this.ReadAway(); + + this.val = buff.ToString(); + + // Needed a property + if (this.needProp) { + this.token = JSONToken.PropertyName; + this.needProp = false; + return true; + } + + if (this.location == JSONLocation.InObject && !this.needProp) + this.needProp = true; + + return true; + } + + private bool ReadNull() { + this.token = JSONToken.Null; + this.val = null; + + this.ReadAway(3); // ull + this.ReadAway(); + + if (this.location == JSONLocation.InObject && !this.needProp) + this.needProp = true; + + return true; + } + + private bool ReadNumber(char start) { + StringBuilder buff = new StringBuilder(); + int chr; + bool isFloat = false; + + this.token = JSONToken.Integer; + buff.Append(start); + + while ((chr = this.reader.Peek()) != -1) { + if (Char.IsNumber((char) chr) || (char) chr == '-' || (char) chr == '.') { + if (((char) chr) == '.') + isFloat = true; + + buff.Append((char) this.reader.Read()); + } else + break; + } + + this.ReadAway(); + + if (isFloat) { + this.token = JSONToken.Float; + this.val = Convert.ToDouble(buff.ToString().Replace('.', ',')); + } else + this.val = Convert.ToInt32(buff.ToString()); + + if (this.location == JSONLocation.InObject && !this.needProp) + this.needProp = true; + + return true; + } + + private bool ReadBool(char chr) { + this.token = JSONToken.Boolean; + this.val = chr == 't'; + + if (chr == 't') + this.ReadAway(3); // rue + else + this.ReadAway(4); // alse + + this.ReadAway(); + + if (this.location == JSONLocation.InObject && !this.needProp) + this.needProp = true; + + return true; + } + + private void ReadAway() { + int chr; + + while ((chr = this.reader.Peek()) != -1) { + if (chr != ':' && chr != ',' && !Char.IsWhiteSpace((char) chr)) + break; + + this.reader.Read(); + } + } + + private string ReadLen(int num) { + StringBuilder buff = new StringBuilder(); + int chr; + + for (int i=0; i + /// + /// + public enum JSONLocation { + /// + InArray, + + /// + InObject, + + /// + Normal + } + + /// + /// Description of JSONWriter. + /// + public class JSONWriter { + private TextWriter writer; + private JSONLocation location; + private Stack lastLocations; + private int index, lastIndex; + private bool isProp = false; + + /// + /// + /// + /// + public JSONWriter(TextWriter writer) { + this.writer = writer; + this.location = JSONLocation.Normal; + this.lastLocations = new Stack(); + this.index = 0; + this.lastIndex = 0; + } + + /// + /// + /// + public void WriteStartObject() { + this.WriteDelim(); + this.writer.Write('{'); + this.lastLocations.Push(this.location); + this.lastIndex = this.index; + this.location = JSONLocation.InObject; + this.index = 0; + } + + /// + /// + /// + public void WriteEndObject() { + this.writer.Write('}'); + this.location = (JSONLocation) lastLocations.Pop(); + this.index = this.lastIndex; + } + + /// + /// + /// + public void WriteStartArray() { + this.WriteDelim(); + this.writer.Write('['); + this.lastLocations.Push(this.location); + this.lastIndex = this.index; + this.location = JSONLocation.InArray; + this.index = 0; + } + + /// + /// + /// + public void WriteEndArray() { + this.writer.Write(']'); + this.location = (JSONLocation) lastLocations.Pop(); + this.index = this.lastIndex; + } + + /// + /// + /// + /// + public void WritePropertyName(string name) { + this.WriteDelim(); + this.isProp = true; + this.WriteObject(EncodeString(name)); + this.writer.Write(':'); + } + + /// + /// + /// + /// + /// + public void WriteProperty(string name, object obj) { + this.WritePropertyName(name); + this.WriteObject(obj); + } + + /// + /// + /// + /// + public void WriteValue(object obj) { + this.WriteDelim(); + this.WriteObject(obj); + } + + /// + /// + /// + public void WriteNull() { + this.WriteDelim(); + this.writer.Write("null"); + } + + /// + /// + /// + public void Close() { + this.writer.Close(); + } + + #region private methods + + private void WriteObject(object obj) { + if (obj == null) { + this.writer.Write("null"); + return; + } + + if (obj is bool) { + this.writer.Write(((bool) obj) == true ? "true" : "false"); + return; + } + + if (obj is int) { + this.writer.Write(((int) obj)); + return; + } + + if (obj is long) { + this.writer.Write(((long) obj)); + return; + } + + if (obj is float || obj is double) { + string str = Convert.ToString(obj); + this.writer.Write(str.Replace(',', '.')); + return; + } + + if (obj is string) { + this.writer.Write('"'); + this.writer.Write(EncodeString((string) obj)); + this.writer.Write('"'); + return; + } + } + + private void WriteDelim() { + if (this.index > 0 && !this.isProp) + this.writer.Write(','); + + this.isProp = false; + this.index++; + } + + /// + /// + /// + /// + /// + public static string EncodeString(string str) { + if (str == null) + return null; + + StringBuilder strBuilder = new StringBuilder(str.Length); + char[] chars = str.ToCharArray(); + + for (int i=0; i 128 || Char.IsControl(chars[i])) { + strBuilder.Append("\\u"); + strBuilder.Append(((int) chars[i]).ToString("X4")); + continue; + } + + switch (chars[i]) { + case '\'': + strBuilder.Append("\\\'"); + break; + + case '\"': + strBuilder.Append("\\\""); + break; + + case '\\': + strBuilder.Append("\\\\"); + break; + + default: + strBuilder.Append(chars[i]); + break; + } + } + + return strBuilder.ToString(); + } + + #endregion + } +} diff --git a/components/editorControls/tinymce/TinyMCE.cs b/components/editorControls/tinymce/TinyMCE.cs new file mode 100644 index 0000000000..3feeff840e --- /dev/null +++ b/components/editorControls/tinymce/TinyMCE.cs @@ -0,0 +1,506 @@ +using System; +using System.Collections; +using System.Text.RegularExpressions; +using System.Web; +using System.Web.UI; +using umbraco.BasePages; +using umbraco.BusinessLogic; +using umbraco.cms.businesslogic.web; +using umbraco.editorControls.wysiwyg; +using umbraco.interfaces; +using umbraco.uicontrols; + +namespace umbraco.editorControls.tinymce { + public class TinyMCE : webcontrol.TinyMCE, IDataEditor, IMenuElement { + private IData _data; + private bool _enableContextMenu = false; + private string _editorButtons = ""; + private string _advancedUsers = ""; + private bool _fullWidth = false; + private int _width = 0; + private int _height = 0; + private bool _showLabel = false; + private string _plugins = ""; + private ArrayList _stylesheets = new ArrayList(); + + private ArrayList _menuIcons = new ArrayList(); + private SortedList _buttons = new SortedList(); + private SortedList _mceButtons = new SortedList(); + private bool _isInitialized = false; + private string _activateButtons = ""; + private string _disableButtons = "help,visualaid,"; + private int m_maxImageWidth = 500; + + public virtual string Plugins { + get { return _plugins; } + set { _plugins = value; } + } + + public TinyMCE(IData Data, string Configuration) { + _data = Data; + string[] configSettings = Configuration.Split("|".ToCharArray()); + + if (configSettings.Length > 0) { + _editorButtons = configSettings[0]; + + if (configSettings.Length > 1) + if (configSettings[1] == "1") + _enableContextMenu = true; + + if (configSettings.Length > 2) + _advancedUsers = configSettings[2]; + + if (configSettings.Length > 3) { + if (configSettings[3] == "1") + _fullWidth = true; + else if (configSettings[4].Split(',').Length > 1) { + _width = int.Parse(configSettings[4].Split(',')[0]); + _height = int.Parse(configSettings[4].Split(',')[1]); + } + } + + // default width/height + if (_width < 1) + _width = 500; + if (_height < 1) + _height = 400; + + // add stylesheets + if (configSettings.Length > 4) { + foreach (string s in configSettings[5].Split(",".ToCharArray())) + _stylesheets.Add(s); + } + + if (configSettings.Length > 6 && configSettings[6] != "") + _showLabel = bool.Parse(configSettings[6]); + + if (configSettings.Length > 7 && configSettings[7] != "") + m_maxImageWidth = int.Parse(configSettings[7].ToString()); + + // sizing + if (!_fullWidth) { + config.Add("width", _width.ToString()); + config.Add("height", _height.ToString()); + } + + if (_enableContextMenu) + _plugins += ",contextmenu"; + + // config.Add("theme_advanced_statusbar_location", "none"); + + // If the editor is used in umbraco, use umbraco's own toolbar + bool onFront = false; + if (HttpContext.Current.Request.Path.ToLower().IndexOf(GlobalSettings.Path.ToLower()) > -1) + config.Add("theme_advanced_toolbar_location", "external"); + else { + onFront = true; + config.Add("theme_advanced_toolbar_location", "top"); + } + + // load plugins + IDictionaryEnumerator pluginEnum = tinyMCEConfiguration.Plugins.GetEnumerator(); + while (pluginEnum.MoveNext()) { + tinyMCEPlugin plugin = (tinyMCEPlugin)pluginEnum.Value; + if (plugin.UseOnFrontend || (!onFront && !plugin.UseOnFrontend)) + _plugins += "," + plugin.Name; + } + if (_plugins.StartsWith(",")) + _plugins = _plugins.Substring(1, _plugins.Length - 1); + if (_plugins.EndsWith(",")) + _plugins = _plugins.Substring(0, _plugins.Length - 1); + + config.Add("plugins", _plugins); + + // Check advanced settings + if (("," + _advancedUsers + ",").IndexOf("," + UmbracoEnsuredPage.CurrentUser.UserType.Id + ",") > -1) + config.Add("umbracoAdvancedMode", "true"); + else + config.Add("umbracoAdvancedMode", "false"); + + // Check maximum image width + config.Add("umbracoMaximumDefaultImageWidth", m_maxImageWidth.ToString()); + + // Styles + string cssFiles = String.Empty; + string styles = string.Empty; + foreach (string styleSheetId in _stylesheets) { + if (styleSheetId.Trim() != "") + try { + StyleSheet s = StyleSheet.GetStyleSheet(int.Parse(styleSheetId), false, false); + cssFiles += GlobalSettings.Path + "/../css/" + s.Text + ".css"; + + foreach (StylesheetProperty p in s.Properties) { + if (styles != string.Empty) { + styles += ";"; + } + if (p.Alias.StartsWith(".")) + styles += p.Text + "=" + p.Alias; + else + styles += p.Text + "=" + p.Alias; + } + + cssFiles += ","; + } catch (Exception ee) { + Log.Add(LogTypes.Error, -1, + string.Format( + string.Format("Error adding stylesheet to tinymce (id: {{0}}). {0}", ee), + styleSheetId)); + } + } + + config.Add("content_css", cssFiles); + config.Add("theme_advanced_styles", styles); + + // Add buttons + IDictionaryEnumerator ide = tinyMCEConfiguration.Commands.GetEnumerator(); + while (ide.MoveNext()) { + tinyMCECommand cmd = (tinyMCECommand)ide.Value; + if (_editorButtons.IndexOf("," + cmd.Alias + ",") > -1) + _activateButtons += cmd.Alias + ","; + else + _disableButtons += cmd.Alias + ","; + } + + if (_activateButtons.Length > 0) + _activateButtons = _activateButtons.Substring(0, _activateButtons.Length - 1); + if (_disableButtons.Length > 0) + _disableButtons = _disableButtons.Substring(0, _disableButtons.Length - 1); + + // Add buttons + initButtons(); + _activateButtons = ""; + + int separatorPriority = 0; + ide = _mceButtons.GetEnumerator(); + while (ide.MoveNext()) { + string mceCommand = ide.Value.ToString(); + int curPriority = (int)ide.Key; + + // Check priority + if (separatorPriority > 0 && + Math.Floor(decimal.Parse(curPriority.ToString()) / 10) > + Math.Floor(decimal.Parse(separatorPriority.ToString()) / 10)) + _activateButtons += "separator,"; + + _activateButtons += mceCommand + ","; + + separatorPriority = curPriority; + } + + + config.Add("theme_advanced_buttons1", _activateButtons); + config.Add("theme_advanced_buttons2", ""); + config.Add("theme_advanced_buttons3", ""); + config.Add("theme_advanced_toolbar_align", "left"); + config.Add("theme_advanced_disable", _disableButtons); + + config.Add("theme_advanced_path ", "true"); + config.Add("extended_valid_elements", "div[*]"); + config.Add("document_base_url", "/"); + config.Add("event_elements", "div"); + + + if (HttpContext.Current.Request.Path.IndexOf(GlobalSettings.Path) > -1) + config.Add("language", User.GetUser(BasePage.GetUserId(BasePage.umbracoUserContextID)).Language); + else + config.Add("language", System.Threading.Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName); + + if (_fullWidth) { + config.Add("auto_resize", "true"); + base.Cols = 30; + base.Rows = 30; + } else { + base.Cols = 0; + base.Rows = 0; + } + } + } + + #region IDataEditor Members + + #region TreatAsRichTextEditor + + public virtual bool TreatAsRichTextEditor { + get { return false; } + } + + #endregion + + #region ShowLabel + + public virtual bool ShowLabel { + get { return _showLabel; } + } + + #endregion + + #region Editor + + public Control Editor { + get { return this; } + } + + #endregion + + #region Save() + + public virtual void Save() { + string parsedString = base.Text.Trim(); + if (parsedString != string.Empty) { + parsedString = replaceMacroTags(parsedString).Trim(); + + // clean macros and add paragraph element for tidy + bool removeParagraphs = false; + if (parsedString.Length > 16 && parsedString.ToLower().Substring(0, 17) == "|||?umbraco_macro") { + removeParagraphs = true; + parsedString = "

" + parsedString + "

"; + } + + // tidy html + + if (UmbracoSettings.TidyEditorContent) { + string tidyTxt = library.Tidy(parsedString, false); + if (tidyTxt != "[error]") { + // compensate for breaking macro tags by tidy + parsedString = tidyTxt.Replace("/?>", "/>"); + if (removeParagraphs) { + if (parsedString.Length - parsedString.Replace("<", "").Length == 2) + parsedString = parsedString.Replace("

", "").Replace("

", ""); + } + } else { + // TODO + // How to log errors? _data.NodeId does not exist? + //BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, BusinessLogic.User.GetUser(0), _data.NodeId, "Error tidying txt from property: " + _data.PropertyId.ToString()); + } + } + + // rescue umbraco tags + parsedString = parsedString.Replace("|||?", "").Replace("|*|", "\""); + + // fix images + parsedString = tinyMCEImageHelper.cleanImages(parsedString); + + // parse current domain and instances of slash before anchor (to fix anchor bug) + // NH 31-08-2007 + if (HttpContext.Current.Request.ServerVariables != null) { + parsedString = parsedString.Replace(helper.GetBaseUrl(HttpContext.Current) + "/#", "#"); + parsedString = parsedString.Replace(helper.GetBaseUrl(HttpContext.Current), ""); + } + + // if text is an empty parargraph, make it all empty + if (parsedString.ToLower() == "

") + parsedString = ""; + } + _data.Value = parsedString; + + // update internal webcontrol value with parsed result + base.Text = parsedString; + } + + #endregion + + protected override void OnLoad(EventArgs e) { + base.OnLoad(e); + try { + base.NodeId = ((cms.businesslogic.datatype.DefaultData)_data).NodeId; + base.VersionId = ((cms.businesslogic.datatype.DefaultData)_data).Version; + config.Add("umbraco_toolbar_id", + ElementIdPreFix + ((cms.businesslogic.datatype.DefaultData)_data).PropertyId.ToString()); + } catch { + // Empty catch as this is caused by the document doesn't exists yet, + // like when using this on an autoform + } + Page.ClientScript.RegisterClientScriptBlock(GetType(), "tinymce", + ""); + Page.ClientScript.RegisterClientScriptBlock(GetType(), "tinymceUmbPasteCheck", + ""); + } + + protected override void Render(HtmlTextWriter output) { + base.JavascriptLocation = "/umbraco_client/tinymce/tiny_mce.js"; + base.Render(output); + } + + protected override void OnInit(EventArgs e) { + base.OnInit(e); + if (!Page.IsPostBack) { + if (_data != null && _data.Value != null) + base.Text = _data.Value.ToString(); + } + } + + private string replaceMacroTags(string text) { + while (findStartTag(text) > -1) { + string result = text.Substring(findStartTag(text), findEndTag(text) - findStartTag(text)); + text = text.Replace(result, generateMacroTag(result)); + } + return text; + } + + private string generateMacroTag(string macroContent) { + string macroAttr = macroContent.Substring(5, macroContent.IndexOf(">") - 5); + string macroTag = "|||?UMBRACO_MACRO "; + Hashtable attributes = ReturnAttributes(macroAttr); + IDictionaryEnumerator ide = attributes.GetEnumerator(); + while (ide.MoveNext()) { + if (ide.Key.ToString().IndexOf("umb_") != -1) { + // Hack to compensate for Firefox adding all attributes as lowercase + string orgKey = ide.Key.ToString(); + if (orgKey == "umb_macroalias") + orgKey = "umb_macroAlias"; + + macroTag += orgKey.Substring(4, orgKey.ToString().Length - 4) + "=|*|" + + ide.Value.ToString() + "|*| "; + } + } + macroTag += "/|||"; + + return macroTag; + } + + public static Hashtable ReturnAttributes(String tag) { + Hashtable ht = new Hashtable(); + MatchCollection m = + Regex.Matches(tag, "(?\\S*)=\"(?[^\"]*)\"", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match attributeSet in m) + ht.Add(attributeSet.Groups["attributeName"].Value.ToString(), + attributeSet.Groups["attributeValue"].Value.ToString()); + + return ht; + } + + private int findStartTag(string text) { + string temp = ""; + text = text.ToLower(); + if (text.IndexOf("ismacro=\"true\"") > -1) { + temp = text.Substring(0, text.IndexOf("ismacro=\"true\"")); + return temp.LastIndexOf("<"); + } + return -1; + } + + private int findEndTag(string text) { + string find = ""; + + int endMacroIndex = text.ToLower().IndexOf(find); + string tempText = text.ToLower().Substring(endMacroIndex + find.Length, text.Length - endMacroIndex - find.Length); + int finalEndPos = 0; + while (tempText.Length > 5) + if (tempText.Substring(finalEndPos, 6) == "") + break; + else + finalEndPos++; + + return endMacroIndex + find.Length + finalEndPos + 6; + } + + #endregion + + #region IDataFieldWithButtons Members + + public object[] MenuIcons { + get { + initButtons(); + + object[] tempIcons = new object[_menuIcons.Count]; + for (int i = 0; i < _menuIcons.Count; i++) + tempIcons[i] = _menuIcons[i]; + return tempIcons; + } + } + + private void initButtons() { + if (!_isInitialized) { + _isInitialized = true; + + // Add icons for the editor control: + // Html + // Preview + // Style picker, showstyles + // Bold, italic, Text Gen + // Align: left, center, right + // Lists: Bullet, Ordered, indent, undo indent + // Link, Anchor + // Insert: Image, macro, table, formular + + foreach (string button in _activateButtons.Split(',')) { + if (button.Trim() != "") { + try { + tinyMCECommand cmd = (tinyMCECommand)tinyMCEConfiguration.Commands[button]; + + string appendValue = ""; + if (cmd.Value != "") + appendValue = ", '" + cmd.Value + "'"; + _mceButtons.Add(cmd.Priority, cmd.Command); + _buttons.Add(cmd.Priority, + new editorButton(cmd.Alias, ui.Text("buttons", cmd.Alias, null), cmd.Icon, + "tinyMCE.execInstanceCommand('" + ClientID + "', '" + + cmd.Command + "', " + cmd.UserInterface + appendValue + ")")); + } catch (Exception ee) { + Log.Add(LogTypes.Error, User.GetUser(0), -1, + string.Format("TinyMCE: Error initializing button '{0}': {1}", button, ee.ToString())); + } + } + } + + // add save icon + int separatorPriority = 0; + IDictionaryEnumerator ide = _buttons.GetEnumerator(); + while (ide.MoveNext()) { + object buttonObj = ide.Value; + int curPriority = (int)ide.Key; + + // Check priority + if (separatorPriority > 0 && + Math.Floor(decimal.Parse(curPriority.ToString()) / 10) > + Math.Floor(decimal.Parse(separatorPriority.ToString()) / 10)) + _menuIcons.Add("|"); + + try { + editorButton e = (editorButton)buttonObj; + + MenuIconI menuItem = new MenuIconClass(); + + menuItem.OnClickCommand = e.onClickCommand; + menuItem.ImageURL = e.imageUrl; + menuItem.AltText = e.alttag; + menuItem.ID = e.id; + _menuIcons.Add(menuItem); + } catch { + } + + separatorPriority = curPriority; + } + } + } + + #endregion + + #region IMenuElement Members + + public string ElementName { + get { return "div"; } + } + + public string ElementIdPreFix { + get { return "umbTinymceMenu"; } + } + + public string ElementClass { + get { return "tinymceMenuBar"; } + } + + public int ExtraMenuWidth { + get { + initButtons(); + return _buttons.Count * 40 + 300; + } + } + + #endregion + } +} \ No newline at end of file diff --git a/components/editorControls/tinymce/TinyMCEDataType.cs b/components/editorControls/tinymce/TinyMCEDataType.cs new file mode 100644 index 0000000000..4cc85d45c6 --- /dev/null +++ b/components/editorControls/tinymce/TinyMCEDataType.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace umbraco.editorControls.tinymce +{ + public class TinyMCEDataType : umbraco.cms.businesslogic.datatype.BaseDataType, umbraco.interfaces.IDataType + { + private umbraco.interfaces.IDataEditor _Editor; + private umbraco.interfaces.IData _baseData; + private umbraco.interfaces.IDataPrevalue _prevalueeditor; + + public override umbraco.interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new TinyMCE(Data, ((tinyMCEPreValueConfigurator)PrevalueEditor).Configuration); + return _Editor; + } + } + + public override umbraco.interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + public override Guid Id + { + get { return new Guid("{83722133-F80C-4273-BDB6-1BEFAA04A612}"); } + } + + public override string DataTypeName + { + get { return "TinyMCE wysiwyg (deprecated, upgrade to tinymce v3!)"; } + } + + public override umbraco.interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new tinymce.tinyMCEPreValueConfigurator(this); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/tinymce/tinyMCEConfiguration.cs b/components/editorControls/tinymce/tinyMCEConfiguration.cs new file mode 100644 index 0000000000..8eab856483 --- /dev/null +++ b/components/editorControls/tinymce/tinyMCEConfiguration.cs @@ -0,0 +1,285 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Collections; +using System.Xml; + +namespace umbraco.editorControls.tinymce +{ + + public class tinyMCEConfiguration + { + private static bool _init = false; + + private static Hashtable _commands = new Hashtable(); + + private static string _validElements; + + private static Hashtable _configOptions = new Hashtable(); + + public static Hashtable ConfigOptions + { + get + { + if (!_init) + init(); + return _configOptions; + } + set + { + _configOptions = value; + } + } + + public static string ValidElements + { + get + { + if (!_init) + init(); + return _validElements; + } + set { _validElements = value; } + } + + public static string PluginPath = umbraco.GlobalSettings.Path + "/plugins/tinymce3"; + public static string JavascriptPath = umbraco.GlobalSettings.Path + "/../umbraco_client/tinymce3"; + + private static string _invalidElements; + + public static string InvalidElements + { + get + { + if (!_init) + init(); + return _invalidElements; + } + set { _invalidElements = value; } + } + + private static Hashtable _plugins = new Hashtable(); + + public static Hashtable Plugins + { + get + { + if (!_init) + init(); + return _plugins; + } + set { _plugins = value; } + } + + + + public static Hashtable Commands + { + get + { + if (!_init) + init(); + return _commands; + } + } + + public static SortedList SortedCommands + { + get + { + if (!_init) + init(); + + SortedList sc = new SortedList(); + IDictionaryEnumerator ide = _commands.GetEnumerator(); + while (ide.MoveNext()) + sc.Add(((tinyMCECommand)ide.Value).Priority, (tinyMCECommand)ide.Value); + return sc; + } + } + + private static void init() + { + // Load config + XmlDocument xd = new XmlDocument(); + xd.Load(GlobalSettings.FullpathToRoot + System.IO.Path.DirectorySeparatorChar + GlobalSettings.Path + System.IO.Path.DirectorySeparatorChar + ".." + System.IO.Path.DirectorySeparatorChar + "config" + System.IO.Path.DirectorySeparatorChar + "tinyMceConfig.config"); + foreach (XmlNode n in xd.DocumentElement.SelectNodes("//command")) + { + if (!_commands.ContainsKey(n.SelectSingleNode("./umbracoAlias").FirstChild.Value)) + { + bool isStyle = false; + if (n.Attributes.GetNamedItem("isStyle") != null) + isStyle = bool.Parse(n.Attributes.GetNamedItem("isStyle").Value); + + _commands.Add( + n.SelectSingleNode("./umbracoAlias").FirstChild.Value.ToLower(), + new tinyMCECommand( + isStyle, + n.SelectSingleNode("./icon").FirstChild.Value, + n.SelectSingleNode("./tinyMceCommand").FirstChild.Value, + n.SelectSingleNode("./umbracoAlias").FirstChild.Value.ToLower(), + n.SelectSingleNode("./tinyMceCommand").Attributes.GetNamedItem("userInterface").Value, + n.SelectSingleNode("./tinyMceCommand").Attributes.GetNamedItem("frontendCommand").Value, + n.SelectSingleNode("./tinyMceCommand").Attributes.GetNamedItem("value").Value, + int.Parse(n.SelectSingleNode("./priority").FirstChild.Value) + )); + } + } + + foreach (XmlNode n in xd.DocumentElement.SelectNodes("//plugin")) + { + if (!_plugins.ContainsKey(n.FirstChild.Value)) + { + bool useOnFrontend = false; + if (n.Attributes.GetNamedItem("loadOnFrontend") != null) + useOnFrontend = bool.Parse(n.Attributes.GetNamedItem("loadOnFrontend").Value); + + _plugins.Add( + n.FirstChild.Value.ToLower(), + new tinyMCEPlugin( + n.FirstChild.Value, + useOnFrontend)); + } + } + + foreach (XmlNode n in xd.DocumentElement.SelectNodes("//config")) + { + if (!_configOptions.ContainsKey(n.FirstChild.Value)) + { + _configOptions.Add( + n.Attributes["key"].FirstChild.Value.ToLower(), + n.FirstChild.Value); + } + } + + if (xd.DocumentElement.SelectSingleNode("./invalidElements") != null) + _invalidElements = xd.DocumentElement.SelectSingleNode("./invalidElements").FirstChild.Value; + if (xd.DocumentElement.SelectSingleNode("./validElements") != null) + { + string _val = xd.DocumentElement.SelectSingleNode("./validElements").FirstChild.Value.Replace("\r", ""); + foreach (string s in _val.Split("\n".ToCharArray())) + _validElements += "'" + s + "' + \n"; + _validElements = _validElements.Substring(0, _validElements.Length - 4); + + } + + _init = true; + } + } + + public class tinyMCEPlugin + { + public tinyMCEPlugin(string Name, bool UseOnFrontEnd) + { + _name = Name; + _useOnFrontend = UseOnFrontEnd; + } + + private string _name; + + public string Name + { + get { return _name; } + set { _name = value; } + } + + + private bool _useOnFrontend; + + public bool UseOnFrontend + { + get { return _useOnFrontend; } + set { _useOnFrontend = value; } + } + + } + + public class tinyMCECommand + { + + public tinyMCECommand(bool isStylePicker, string Icon, string Command, string Alias, string UserInterface, string FrontEndCommand, string Value, int Priority) + { + _isStylePicker = isStylePicker; + _icon = Icon; + _command = Command; + _alias = Alias; + _userInterface = UserInterface; + _frontEndCommand = FrontEndCommand; + _value = Value; + _priority = Priority; + } + + private bool _isStylePicker; + + public bool IsStylePicker + { + get { return _isStylePicker; } + set { _isStylePicker = value; } + } + + + private string _icon; + + public string Icon + { + get { return GlobalSettings.Path + "/" + _icon; } + set { _icon = value; } + } + + private string _command; + + public string Command + { + get { return _command; } + set { _command = value; } + } + + private string _alias; + + public string Alias + { + get { return _alias; } + set { _alias = value; } + } + + private string _userInterface; + + public string UserInterface + { + get { return _userInterface; } + set { _userInterface = value; } + } + + private string _frontEndCommand; + + public string FrontEndCommand + { + get { return _frontEndCommand; } + set { _frontEndCommand = value; } + } + + private string _value; + + public string Value + { + get { return _value; } + set { _value = value; } + } + + private int _priority; + + public int Priority + { + get { return _priority; } + set { _priority = value; } + } + + + + + + + + + } +} diff --git a/components/editorControls/tinymce/tinyMCEImageHelper.cs b/components/editorControls/tinymce/tinyMCEImageHelper.cs new file mode 100644 index 0000000000..bf6ce4df87 --- /dev/null +++ b/components/editorControls/tinymce/tinyMCEImageHelper.cs @@ -0,0 +1,204 @@ +using System; +using System.Collections; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Text.RegularExpressions; +using System.Web; +using umbraco.BusinessLogic; + +namespace umbraco.editorControls.tinymce +{ + internal class tinyMCEImageHelper + { + public static string cleanImages(string html) + { + string[] allowedAttributes = UmbracoSettings.ImageAllowedAttributes.ToLower().Split(','); + string pattern = @"]*>"; + MatchCollection tags = + Regex.Matches(html + " ", pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match tag in tags) + { + if (tag.Value.ToLower().IndexOf("umbraco_macro") == -1) + { + string cleanTag = "", " >"), + "(?\\S*)=\"(?[^\"]*)\"|(?\\S*)=(?[^\"|\\s]*)\\s", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match attributeSet in m) + { + ht.Add(attributeSet.Groups["attributeName"].Value.ToString().ToLower(), + attributeSet.Groups["attributeValue"].Value.ToString()); + if (attributeSet.Groups["attributeName"].Value.ToString().ToLower() == "width") + orgWidth = int.Parse(attributeSet.Groups["attributeValue"].Value.ToString()); + else if (attributeSet.Groups["attributeName"].Value.ToString().ToLower() == "height") + orgHeight = int.Parse(attributeSet.Groups["attributeValue"].Value.ToString()); + } + + // If rel attribute exists and if it's different from current sizing we should resize the image! + if (helper.FindAttribute(ht, "rel") != "") + { + int newWidth = 0, newHeight = 0; + + // if size has changed resize image serverside + string[] newDims = helper.FindAttribute(ht, "rel").Split(",".ToCharArray()); + if (newDims.Length > 0 && + (newDims[0] != helper.FindAttribute(ht, "width") || + newDims[1] != helper.FindAttribute(ht, "height"))) + { + try + { + cleanTag += doResize(ht, out newWidth, out newHeight); + } + catch (Exception err) + { + cleanTag += " src=\"" + helper.FindAttribute(ht, "src") + "\""; + if (helper.FindAttribute(ht, "width") != "") + { + cleanTag += " width=\"" + helper.FindAttribute(ht, "width") + "\""; + cleanTag += " height=\"" + helper.FindAttribute(ht, "height") + "\""; + } + Log.Add(LogTypes.Error, User.GetUser(0), -1, + "Error resizing image in editor: " + err.ToString()); + } + } else + { + cleanTag = StripSrc(cleanTag, ht); + + if (helper.FindAttribute(ht, "width") != "") + { + cleanTag += " width=\"" + helper.FindAttribute(ht, "width") + "\""; + cleanTag += " height=\"" + helper.FindAttribute(ht, "height") + "\""; + } + + } + } + else + { + // Add src, width and height properties + cleanTag = StripSrc(cleanTag, ht); + + + if (helper.FindAttribute(ht, "width") != "") + { + cleanTag += " width=\"" + helper.FindAttribute(ht, "width") + "\""; + cleanTag += " height=\"" + helper.FindAttribute(ht, "height") + "\""; + } + + } + + + // Build image tag + foreach (string attr in allowedAttributes) + { + if (helper.FindAttribute(ht, attr) != "") + { + string attrValue = helper.FindAttribute(ht, attr); + cleanTag += " " + attr + "=\"" + attrValue + "\""; + } + } + + + if (bool.Parse(GlobalSettings.EditXhtmlMode)) + cleanTag += "/"; + cleanTag += ">"; + html = html.Replace(tag.Value, cleanTag); + } + } + + return html; + } + + private static string StripSrc(string cleanTag, Hashtable ht) + { + string src = helper.FindAttribute(ht, "src"); + // update orgSrc to remove umbraco reference + if (src.IndexOf("/media/") > -1) + src = src.Substring(src.IndexOf("/media/"), src.Length - src.IndexOf("/media/")); + + cleanTag += " src=\"" + src + "\""; + return cleanTag; + } + + private static string doResize(Hashtable attributes, out int finalWidth, out int finalHeight) + { + string resizeDim = helper.FindAttribute(attributes, "width") + "," + + helper.FindAttribute(attributes, "height"); + string[] resizeDimSplit = resizeDim.Split(','); + string orgSrc = HttpContext.Current.Server.HtmlDecode(helper.FindAttribute(attributes, "src").Replace("%20", " ")); + string[] orgDim = helper.FindAttribute(attributes, "rel").Split(",".ToCharArray()); + float orgWidth = float.Parse(orgDim[0]); + float orgHeight = float.Parse(orgDim[1]); + string newSrc = ""; + int newWidth = int.Parse(resizeDimSplit[0]); + int newHeight = int.Parse(resizeDimSplit[1]); + + if (orgHeight > 0 && orgWidth > 0 && resizeDim != "" && orgSrc != "") + { + // Check dimensions + if (Math.Abs(orgWidth/newWidth) > Math.Abs(orgHeight/newHeight)) + { + newHeight = (int) Math.Round((float) newWidth*(orgHeight/orgWidth)); + } + else + { + newWidth = (int) Math.Round((float) newHeight*(orgWidth/orgHeight)); + } + + // update orgSrc to remove umbraco reference + if (orgSrc.IndexOf("/media/") > -1) + orgSrc = orgSrc.Substring(orgSrc.IndexOf("/media/"), orgSrc.Length - orgSrc.IndexOf("/media/")); + + string ext = orgSrc.Substring(orgSrc.LastIndexOf(".") + 1, orgSrc.Length - orgSrc.LastIndexOf(".") - 1); + newSrc = orgSrc.Replace("." + ext, "_" + newWidth.ToString() + "x" + newHeight.ToString() + ".jpg"); + + string fullSrc = HttpContext.Current.Server.MapPath(orgSrc); + string fullSrcNew = HttpContext.Current.Server.MapPath(newSrc); + + // Load original image + Image image = Image.FromFile(fullSrc); + + + // Create new image with best quality settings + Bitmap bp = new Bitmap(newWidth, newHeight); + Graphics g = Graphics.FromImage(bp); + g.SmoothingMode = SmoothingMode.HighQuality; + g.InterpolationMode = InterpolationMode.HighQualityBicubic; + g.PixelOffsetMode = PixelOffsetMode.HighQuality; + + // Copy the old image to the new and resized + Rectangle rect = new Rectangle(0, 0, newWidth, newHeight); + g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel); + + // Copy metadata + ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); + ImageCodecInfo codec = null; + for (int i = 0; i < codecs.Length; i++) + { + if (codecs[i].MimeType.Equals("image/jpeg")) + codec = codecs[i]; + } + + // Set compresion ratio to 90% + EncoderParameters ep = new EncoderParameters(); + ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L); + + // Save the new image + bp.Save(fullSrcNew, codec, ep); + } + + // return the new width and height + finalWidth = newWidth; + finalHeight = newHeight; + + return + " src=\"" + newSrc + "\" width=\"" + newWidth.ToString() + "\" height=\"" + newHeight.ToString() + + "\""; + } + } +} \ No newline at end of file diff --git a/components/editorControls/tinymce/tinyMCEPreValueConfigurator.cs b/components/editorControls/tinymce/tinyMCEPreValueConfigurator.cs new file mode 100644 index 0000000000..717d2b4c7a --- /dev/null +++ b/components/editorControls/tinymce/tinyMCEPreValueConfigurator.cs @@ -0,0 +1,317 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Collections; +using System.Web.UI; +using System.Web.UI.WebControls; + +using umbraco.BusinessLogic; +using umbraco.DataLayer; + +namespace umbraco.editorControls.tinymce +{ + public class tinyMCEPreValueConfigurator : System.Web.UI.WebControls.PlaceHolder, interfaces.IDataPrevalue + { + // UI controls + private CheckBoxList _editorButtons; + private CheckBox _enableRightClick; + private DropDownList _dropdownlist; + private CheckBoxList _advancedUsersList; + private CheckBoxList _stylesheetList; + private TextBox _width = new TextBox(); + private TextBox _height = new TextBox(); + private TextBox _maxImageWidth = new TextBox(); + private CheckBox _fullWidth = new CheckBox(); + private CheckBox _showLabel = new CheckBox(); + private RegularExpressionValidator _widthValidator = new RegularExpressionValidator(); + private RegularExpressionValidator _heightValidator = new RegularExpressionValidator(); + private RegularExpressionValidator _maxImageWidthValidator = new RegularExpressionValidator(); + + // referenced datatype + private cms.businesslogic.datatype.BaseDataType _datatype; + private string _selectedButtons = ""; + private string _advancedUsers = ""; + private string _stylesheets = ""; + + public static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + public tinyMCEPreValueConfigurator(cms.businesslogic.datatype.BaseDataType DataType) + { + // state it knows its datatypedefinitionid + _datatype = DataType; + setupChildControls(); + } + + private void setupChildControls() + { + _dropdownlist = new DropDownList(); + _dropdownlist.ID = "dbtype"; + _dropdownlist.Items.Add(DBTypes.Date.ToString()); + _dropdownlist.Items.Add(DBTypes.Integer.ToString()); + _dropdownlist.Items.Add(DBTypes.Ntext.ToString()); + _dropdownlist.Items.Add(DBTypes.Nvarchar.ToString()); + + _editorButtons = new CheckBoxList(); + _editorButtons.ID = "editorButtons"; + _editorButtons.RepeatColumns = 4; + _editorButtons.CellPadding = 3; + + _enableRightClick = new CheckBox(); + _enableRightClick.ID = "enableRightClick"; + + _advancedUsersList = new CheckBoxList(); + _advancedUsersList.ID = "advancedUsersList"; + + _stylesheetList = new CheckBoxList(); + _stylesheetList.ID = "stylesheetList"; + + _showLabel = new CheckBox(); + _showLabel.ID = "showLabel"; + + _maxImageWidth = new TextBox(); + _maxImageWidth.ID = "maxImageWidth"; + + // put the childcontrols in context - ensuring that + // the viewstate is persisted etc. + Controls.Add(_dropdownlist); + Controls.Add(_enableRightClick); + Controls.Add(_editorButtons); + Controls.Add(_advancedUsersList); + Controls.Add(_stylesheetList); + Controls.Add(_width); + Controls.Add(_widthValidator); + Controls.Add(_height); + Controls.Add(_heightValidator); + Controls.Add(_showLabel); + Controls.Add(_maxImageWidth); + Controls.Add(_maxImageWidthValidator); + // Controls.Add(_fullWidth); + + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad (e); + // add ids to controls + _width.ID = "width"; + _height.ID = "height"; + + + // initialize validators + _widthValidator.ValidationExpression = "0*[1-9][0-9]*"; + _widthValidator.ErrorMessage = ui.Text("errorHandling", "errorIntegerWithoutTab", ui.Text("width"), new BasePages.BasePage().getUser()); + _widthValidator.Display = ValidatorDisplay.Dynamic; + _widthValidator.ControlToValidate = _width.ID; + _heightValidator.ValidationExpression = "0*[1-9][0-9]*"; + _heightValidator.ErrorMessage = ui.Text("errorHandling", "errorIntegerWithoutTab", ui.Text("height"), new BasePages.BasePage().getUser()); + _heightValidator.ControlToValidate = _height.ID; + _heightValidator.Display = ValidatorDisplay.Dynamic; + _maxImageWidthValidator.ValidationExpression = "0*[1-9][0-9]*"; + _maxImageWidthValidator.ErrorMessage = ui.Text("errorHandling", "errorIntegerWithoutTab","'" + ui.Text("rteMaximumDefaultImgSize") + "'", new BasePages.BasePage().getUser()); + _maxImageWidthValidator.ControlToValidate = _maxImageWidth.ID; + _maxImageWidthValidator.Display = ValidatorDisplay.Dynamic; + + if (!Page.IsPostBack) + { + string[] config = Configuration.Split("|".ToCharArray()); + if (config.Length > 0) + { + _selectedButtons = config[0]; + + if (config.Length > 1) + if (config[1] == "1") + _enableRightClick.Checked = true; + + if (config.Length > 2) + _advancedUsers = config[2]; + + if (config.Length > 4 && config[4].Split(',').Length > 1) + { +// if (config[3] == "1") +// _fullWidth.Checked = true; +// else +// { + _width.Text = config[4].Split(',')[0]; + _height.Text = config[4].Split(',')[1]; +// } + } + + // if width and height are empty or lower than 0 then set default sizes: + int tempWidth, tempHeight; + int.TryParse(_width.Text, out tempWidth); + int.TryParse(_height.Text, out tempHeight); + if (_width.Text.Trim() == "" || tempWidth < 1) + _width.Text = "500"; + if (_height.Text.Trim() == "" || tempHeight < 1) + _height.Text = "400"; + + if (config.Length > 5) + _stylesheets = config[5]; + if (config.Length > 6 && config[6] != "") + _showLabel.Checked = bool.Parse(config[6]); + if (config.Length > 7 && config[7] != "") + _maxImageWidth.Text = config[7]; + else + _maxImageWidth.Text = "500"; + } + + // add editor buttons + IDictionaryEnumerator ide = tinyMCEConfiguration.SortedCommands.GetEnumerator(); + while (ide.MoveNext()) + { + tinyMCECommand cmd = (tinyMCECommand) ide.Value; + ListItem li = new ListItem(string.Format("\"{1}\" ", cmd.Icon, cmd.Alias), cmd.Alias); + if (_selectedButtons.IndexOf(cmd.Alias) > -1) + li.Selected = true; + + _editorButtons.Items.Add(li); + } + + // add users + foreach (BusinessLogic.UserType ut in BusinessLogic.UserType.getAll) + { + ListItem li = new ListItem(ut.Name, ut.Id.ToString()); + if (("," + _advancedUsers + ",").IndexOf("," + ut.Id.ToString() + ",") > -1) + li.Selected = true; + + _advancedUsersList.Items.Add(li); + } + + // add stylesheets + foreach (cms.businesslogic.web.StyleSheet st in cms.businesslogic.web.StyleSheet.GetAll()) + { + ListItem li = new ListItem(st.Text, st.Id.ToString()); + if (("," + _stylesheets + ",").IndexOf("," + st.Id.ToString() + ",") > -1) + li.Selected = true; + + _stylesheetList.Items.Add(li); + } + + + // Mark the current db type + _dropdownlist.SelectedValue = _datatype.DBType.ToString(); + + } + } + + public Control Editor + { + get + { + return this; + } + } + + public virtual void Save() + { + _datatype.DBType = (cms.businesslogic.datatype.DBTypes)Enum.Parse(typeof(cms.businesslogic.datatype.DBTypes), _dropdownlist.SelectedValue, true); + + // Generate data-string + string data = ","; + + foreach (ListItem li in _editorButtons.Items) + if (li.Selected) + data += li.Value + ","; + + data += "|"; + + if (_enableRightClick.Checked) + data += "1"; + else + data += "0"; + + data += "|"; + + foreach (ListItem li in _advancedUsersList.Items) + if (li.Selected) + data += li.Value + ","; + + data += "|"; + + // full width currenctly not useLiveEditing + data += "0|"; + /* + if (_fullWidth.Checked) + data += "1|"; + else + data += "0|"; + */ + + data += _width.Text + "," + _height.Text + "|"; + + foreach (ListItem li in _stylesheetList.Items) + if (li.Selected) + data += li.Value + ","; + data += "|"; + data += _showLabel.Checked.ToString() + "|"; + data += _maxImageWidth.Text + "|"; + + + // If the add new prevalue textbox is filled out - add the value to the collection. + IParameter[] SqlParams = new IParameter[] { + SqlHelper.CreateParameter("@value",data), + SqlHelper.CreateParameter("@dtdefid",_datatype.DataTypeDefinitionId)}; + SqlHelper.ExecuteNonQuery("delete from cmsDataTypePreValues where datatypenodeid = @dtdefid",SqlParams); + SqlHelper.ExecuteNonQuery("insert into cmsDataTypePreValues (datatypenodeid,[value],sortorder,alias) values (@dtdefid,@value,0,'')",SqlParams); + } + + protected override void Render(HtmlTextWriter writer) + { + writer.WriteLine(""); + writer.WriteLine(""); + writer.Write(""); + writer.Write(""); + writer.Write(""); + writer.Write(""); + writer.Write(""); + writer.Write(""); + writer.Write(""); + writer.Write("
" + ui.Text("editdatatype", "dataBaseDatatype") + ":"); + _dropdownlist.RenderControl(writer); + writer.Write("
" + ui.Text("editdatatype", "rteButtons") + ":"); + _editorButtons.RenderControl(writer); + writer.Write("
" + ui.Text("editdatatype", "rteRelatedStylesheets") + ":"); + _stylesheetList.RenderControl(writer); + writer.Write("
" + ui.Text("editdatatype", "rteEnableContextMenu") + ":"); + _enableRightClick.RenderControl(writer); + writer.Write("
" + ui.Text("editdatatype", "rteEnableAdvancedSettings") + ":"); + _advancedUsersList.RenderControl(writer); + writer.Write("
"); + //"Size:Maximum width and height: "); + // _fullWidth.RenderControl(writer); + + writer.Write(ui.Text("editdatatype", "rteWidthAndHeight") + ":"); + _width.RenderControl(writer); + _widthValidator.RenderControl(writer); + writer.Write(" x "); + _height.RenderControl(writer); + _heightValidator.RenderControl(writer); + writer.Write("
"); + writer.Write(ui.Text("editdatatype", "rteMaximumDefaultImgSize") + ":"); + _maxImageWidth.RenderControl(writer); + _maxImageWidthValidator.RenderControl(writer); + writer.Write("
" + ui.Text("editdatatype", "rteShowLabel") + ":"); + _showLabel.RenderControl(writer); + writer.Write("
"); + } + + public string Configuration + { + get + { + try + { + return SqlHelper.ExecuteScalar("select value from cmsDataTypePreValues where datatypenodeid = @datatypenodeid", SqlHelper.CreateParameter("@datatypenodeid", _datatype.DataTypeDefinitionId)); + } + catch + { + return ""; + } + } + } + + } +} diff --git a/components/editorControls/tinymce/webcontrol/TinyMCE.cs b/components/editorControls/tinymce/webcontrol/TinyMCE.cs new file mode 100644 index 0000000000..8f96a4110b --- /dev/null +++ b/components/editorControls/tinymce/webcontrol/TinyMCE.cs @@ -0,0 +1,403 @@ +using System; +using System.Collections; +using System.Collections.Specialized; +using System.Text.RegularExpressions; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; +using umbraco.BusinessLogic; +using umbraco.cms.businesslogic.macro; +using umbraco.cms.businesslogic.media; +using umbraco.cms.businesslogic.property; +using Content = umbraco.cms.businesslogic.Content; + +namespace umbraco.editorControls.tinymce.webcontrol { + public class TinyMCE : WebControl, IPostBackDataHandler { + private string _javascriptLocation = "/umbraco_client/tinymce"; + private string _coreFile = "/tiny_mce.js"; + private int _rows = 13; + private int _cols = 60; + public NameValueCollection config; + private string temp; + + private int _nodeId = -1; + private Guid _versionId; + + public int NodeId { + set { _nodeId = value; } + } + + public Guid VersionId { + set { _versionId = value; } + } + + public string CoreFile { + get { return _coreFile; } + } + + + public TinyMCE() { + config = new NameValueCollection(); + config.Add("mode", "exact"); + config.Add("theme", "advanced"); + + //content_css : "/mycontent.css" + temp = string.Empty; + + + //this._config.SetStringParam(TinyMCEConfig.StringParameter.mode, "exact"); + //this._config.SetStringParam(TinyMCEConfig.StringParameter.theme, "advanced"); + //this._config.SetStringParam(TinyMCEConfig.StringParameter.plugins, "advlink,noneditable,advimage,flash"); + //this._config.SetStringParam(TinyMCEConfig.StringParameter.theme_advanced_buttons3_add, "flash"); + } + + // + /// The text of the editor + /// + public string Text { + get { return (string)ViewState["text"]; } + set { ViewState["text"] = value; } + } + + // + /// The number of rows in the textarea that gets converted to the editor. + /// This affects the size of the editor. Default is 10 + /// + public int Rows { + get { return _rows; } + set { _rows = value; } + } + + // + /// The number of columns in the textarea that gets converted to the editor. + /// This affects the size of the editor. Default is 40. + /// + public int Cols { + get { return _cols; } + set { _cols = value; } + } + + // + /// Path to the TinyMCE javascript, default is "jscripts/tiny_mce/tiny_mce.js" + /// + public string JavascriptLocation { + get { return _javascriptLocation; } + set { _javascriptLocation = value; } + } + + /// + /// Draws the editor + /// + /// The writer to draw the editor to + protected override void Render(HtmlTextWriter writer) { + writer.WriteLine("\n"); + // writer.WriteLine("\n"); + writer.WriteLine("\n"); + + if (Cols > 0) + writer.Write(""); + } + + private string formatMedia(string html) { + // Local media path + string localMediaPath = getLocalMediaPath(); + + // Find all media images + string pattern = "]*src=\"(?/media[^\"]*)\" [^>]*>"; + + MatchCollection tags = + Regex.Matches(html, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match tag in tags) + if (tag.Groups.Count > 0) { + // Replace /> to ensure we're in old-school html mode + string tempTag = "", " >"), + "(?\\S*)=\"(?[^\"]*)\"|(?\\S*)=(?[^\"|\\s]*)\\s", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match attributeSet in m) { + if (attributeSet.Groups["attributeName"].Value.ToString().ToLower() != "src") + ht.Add(attributeSet.Groups["attributeName"].Value.ToString(), + attributeSet.Groups["attributeValue"].Value.ToString()); + } + + // build the element + // Build image tag + IDictionaryEnumerator ide = ht.GetEnumerator(); + while (ide.MoveNext()) + tempTag += " " + ide.Key.ToString() + "=\"" + ide.Value.ToString() + "\""; + + // Find the original filename, by removing the might added width and height + orgSrc = + orgSrc.Replace( + "_" + helper.FindAttribute(ht, "width") + "x" + helper.FindAttribute(ht, "height"), ""). + Replace("%20", " "); + + // Check for either id or guid from media + string mediaId = getIdFromSource(orgSrc, localMediaPath); + + Media imageMedia = null; + + try { + int mId = int.Parse(mediaId); + Property p = new Property(mId); + imageMedia = new Media(Content.GetContentFromVersion(p.VersionId).Id); + } catch { + try { + imageMedia = new Media(Content.GetContentFromVersion(new Guid(mediaId)).Id); + } catch { + } + } + + // Check with the database if any media matches this url + if (imageMedia != null) { + try { + // Check extention + if (imageMedia.getProperty("umbracoExtension").Value.ToString() != orgSrc.Substring(orgSrc.LastIndexOf(".") + 1, orgSrc.Length - orgSrc.LastIndexOf(".") - 1)) + orgSrc = orgSrc.Substring(0, orgSrc.LastIndexOf(".") + 1) + + imageMedia.getProperty("umbracoExtension").Value.ToString(); + + // Format the tag + tempTag = tempTag + " rel=\"" + + imageMedia.getProperty("umbracoWidth").Value.ToString() + "," + + imageMedia.getProperty("umbracoHeight").Value.ToString() + "\" src=\"" + orgSrc + + "\""; + tempTag += "/>"; + + // Replace the tag + html = html.Replace(tag.Value, tempTag); + } catch (Exception ee) { + Log.Add(LogTypes.Error, User.GetUser(0), -1, + "Error reading size data from media: " + imageMedia.Id.ToString() + ", " + + ee.ToString()); + } + } else + Log.Add(LogTypes.Error, User.GetUser(0), -1, + "Error reading size data from media (not found): " + orgSrc); + } + return html; + } + + private string getIdFromSource(string src, string localMediaPath) { + // important - remove out the umbraco path + media! + src = src.Replace(localMediaPath, ""); + + string _id = ""; + + // Check for directory id naming + if (src.Length - src.Replace("/", "").Length > 0) { + string[] dirSplit = src.Split("/".ToCharArray()); + string tempId = dirSplit[0]; + try { + // id + _id = int.Parse(tempId).ToString(); + } catch { + // guid + _id = tempId; + } + } else { + string[] fileSplit = src.Replace("/media/", "").Split("-".ToCharArray()); + + // guid or id + if (fileSplit.Length > 3) { + for (int i = 0; i < 5; i++) + _id += fileSplit[i] + "-"; + _id = _id.Substring(0, _id.Length - 1); + } else + _id = fileSplit[0]; + } + + return _id; + } + + private string getLocalMediaPath() { + string[] umbracoPathSplit = GlobalSettings.Path.Split("/".ToCharArray()); + string umbracoPath = ""; + for (int i = 0; i < umbracoPathSplit.Length - 1; i++) + umbracoPath += umbracoPathSplit[i] + "/"; + return umbracoPath + "media/"; + } + + + private string parseMacrosToHtml(string input) { + int nodeId = _nodeId; + Guid versionId = _versionId; + string content = input; + + + string pattern = @"(<\?UMBRACO_MACRO\W*[^>]*/>)"; + MatchCollection tags = + Regex.Matches(content, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + + // Page for macro rendering + page p = new page(nodeId, versionId); + HttpContext.Current.Items["macrosAdded"] = 0; + HttpContext.Current.Items["pageID"] = nodeId.ToString(); + + foreach (Match tag in tags) { + try { + // Create div + Hashtable attributes = helper.ReturnAttributes(tag.Groups[1].Value); + string div = macro.renderMacroStartTag(attributes, nodeId, versionId).Replace(""", "&quot;"); + + // Insert macro contents here... + macro m; + if (helper.FindAttribute(attributes, "macroID") != "") + m = new macro(int.Parse(helper.FindAttribute(attributes, "macroID"))); + else { + // legacy: Check if the macroAlias is typed in lowercasing + string macroAlias = helper.FindAttribute(attributes, "macroAlias"); + if (macroAlias == "") { + macroAlias = helper.FindAttribute(attributes, "macroalias"); + attributes.Remove("macroalias"); + attributes.Add("macroAlias", macroAlias); + } + + if (macroAlias != "") + m = new macro(Macro.GetByAlias(macroAlias).Id); + else + throw new ArgumentException("umbraco is unable to identify the macro. No id or macroalias was provided for the macro in the macro tag.", tag.Groups[1].Value); + } + + if (helper.FindAttribute(attributes, "macroAlias") == "") + attributes.Add("macroAlias", m.Alias); + + + try { + div += macro.MacroContentByHttp(nodeId, versionId, attributes); + } catch { + div += "No macro content available for WYSIWYG editing"; + } + + + div += macro.renderMacroEndTag(); + content = content.Replace(tag.Groups[1].Value, div); + } catch (Exception ee) { + Log.Add(LogTypes.Error, this._nodeId, "Macro Parsing Error: " + ee.ToString()); + string div = "

umbraco was unable to parse a macro tag, which means that parts of this content might be corrupt.

Best solution is to rollback to a previous version by right clicking the node in the tree and then try to insert the macro again.

Please report this to your system administrator as well - this error has been logged.

"; + content = content.Replace(tag.Groups[1].Value, div); + } + + } + return content; + } + + private static readonly object TextChangedEvent = new object(); + + /// + /// Raises an event when the text in the editor changes. + /// + public event EventHandler TextChanged { + add { Events.AddHandler(TextChangedEvent, value); } + remove { Events.RemoveHandler(TextChangedEvent, value); } + } + + /// + /// Event for text change. + /// + /// + protected virtual void OnTextChanged(EventArgs e) { + if (Events != null) { + EventHandler oEventHandler = (EventHandler)Events[TextChangedEvent]; + if (oEventHandler != null) { + oEventHandler(this, e); + } + } + } + + /// + /// Called when a postback occurs on the page the control is placed at + /// + /// The key of the editor data + /// All the posted data + /// + bool IPostBackDataHandler.LoadPostData(string postDataKey, NameValueCollection postCollection) { + string newText = postCollection[postDataKey]; + + if (newText != Text) { + Text = newText; + return true; + } + + return false; + } + + /// + /// Raises an event when postback occurs + /// + void IPostBackDataHandler.RaisePostDataChangedEvent() { + OnTextChanged(EventArgs.Empty); + } + } + + public enum TinyMceButtons { + code, + bold, + italic, + underline, + strikethrough, + justifyleft, + justifycenter, + justifyright, + justifyfull, + bullist, + numlist, + outdent, + indent, + cut, + copy, + pasteword, + undo, + redo, + link, + unlink, + image, + table, + hr, + removeformat, + sub, + sup, + charmap, + anchor, + umbracomacro + } +} \ No newline at end of file diff --git a/components/editorControls/ultimatepicker/ultimatePickerDataEditor.cs b/components/editorControls/ultimatepicker/ultimatePickerDataEditor.cs new file mode 100644 index 0000000000..d537e6351c --- /dev/null +++ b/components/editorControls/ultimatepicker/ultimatePickerDataEditor.cs @@ -0,0 +1,421 @@ +using System; +using System.Configuration; +using System.Web.UI; +using System.Web.UI.WebControls; +using AjaxControlToolkit; +using umbraco.cms.businesslogic; +using umbraco.interfaces; + +namespace umbraco.editorControls.ultimatepicker +{ + [ValidationProperty("IsValid")] + public class ultimatePickerDataEditor : UpdatePanel, IDataEditor + { + private IData _data; + string _configuration; + + private string[] config; + private string controlType; + + private string[] dataValues; + + private TextBox childtxt; + private DropDownList dropdownlistNodes; + private CheckBoxList checkboxlistNodes; + private RadioButtonList radiobuttonlistNodes; + private ListBox listboxNodes; + private Button clearRadiobuttonlist; + private CheckBox clearRadiobuttons; + + public ultimatePickerDataEditor(umbraco.interfaces.IData Data, string Configuration) + { + _data = Data; + _configuration = Configuration; + + config = _configuration.Split("|".ToCharArray()); + controlType = config[0]; + + RenderMode = UpdatePanelRenderMode.Inline; + } + + public virtual bool TreatAsRichTextEditor + { + get { return false; } + } + + public bool ShowLabel + { + get { return true; } + } + + /// + /// Internal logic for validation controls to detect whether or not it's valid (has to be public though) + /// + /// Am I valid? + public string IsValid + { + get + { + switch (controlType.ToLower()) + { + case "autocomplete": + if (childtxt.Text.Contains("|")) + { + return childtxt.Text; + } + + break; + case "checkboxlist": + foreach (ListItem item in checkboxlistNodes.Items) + { + if (item.Selected) + { + return "valid"; + } + } + break; + case "dropdownlist": + return dropdownlistNodes.SelectedValue; + break; + case "listbox": + foreach (ListItem item in listboxNodes.Items) + { + if (item.Selected) + { + return "valid"; + } + } + break; + case "radiobuttonlist": + foreach (ListItem item in radiobuttonlistNodes.Items) + { + if (item.Selected) + { + return "valid"; + } + } + + break; + + } + return ""; + } + } + + public Control Editor { get { return this; } } + + public void Save() + { + string dataToSave = string.Empty; + + switch (controlType) + { + case "AutoComplete": + if (childtxt.Text.Contains("|")) + { + dataToSave = childtxt.Text.Split("|".ToCharArray())[1]; + } + + + break; + case "auto-suggest": + goto case "AutoComplete"; + case "CheckBoxList": + + foreach (ListItem item in checkboxlistNodes.Items) + { + if (item.Selected) + { + dataToSave += item.Value + ","; + } + } + + if (dataToSave.Length > 0) + { + dataToSave = dataToSave.Substring(0, dataToSave.Length - 1); + } + + + break; + case "checkbox": + goto case "CheckBoxList"; + case "DropDownList": + dataToSave = dropdownlistNodes.SelectedValue; + break; + case "dropdown": + goto case "DropDownList"; + case "ListBox": + dataToSave = string.Empty; + foreach (ListItem item in listboxNodes.Items) + { + if (item.Selected) + { + dataToSave += item.Value + ","; + } + } + + if (dataToSave.Length > 0) + { + dataToSave = dataToSave.Substring(0, dataToSave.Length - 1); + } + break; + case "listbox": + goto case "ListBox"; + case "RadioButtonList": + dataToSave = string.Empty; + + if (!clearRadiobuttons.Checked) + { + foreach (ListItem item in radiobuttonlistNodes.Items) + { + if (item.Selected) + { + dataToSave += item.Value + ","; + } + } + + if (dataToSave.Length > 0) + { + dataToSave = dataToSave.Substring(0, dataToSave.Length - 1); + } + } + else + { + foreach (ListItem radiobutton in radiobuttonlistNodes.Items) + { + radiobutton.Selected = false; + } + + clearRadiobuttons.Checked = false; + } + + break; + case "radiobox": + goto case "RadioButtonList"; + + } + if (controlType != "auto-suggest" && controlType != "AutoComplete") + { + this._data.Value = dataToSave; + + } + else + { + if (dataToSave.Length > 0) + { + this._data.Value = dataToSave; + }else + { + if (childtxt.Text.Trim().Length == 0) + { + this._data.Value = ""; + } + } + } + } + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + + try + { + int parentNodeId = Convert.ToInt32(config[1]); + umbraco.cms.businesslogic.Content parentNode = new umbraco.cms.businesslogic.Content(parentNodeId); + string documentAliasFilter = config[2]; + string[] documentAliasFilters = documentAliasFilter.Split(",".ToCharArray()); + + bool showChildren = Convert.ToBoolean(config[3]); + + string[] datavalues = _data.Value.ToString().Split(",".ToCharArray()); + + switch (controlType) + { + case "AutoComplete": + setupAutoComplete(parentNodeId); + break; + case "auto-suggest": + goto case "AutoComplete"; + case "CheckBoxList": + checkboxlistNodes = new CheckBoxList(); + //checkboxlistNodes.ID = "nodes"; + addListControlNode(parentNode, 1, showChildren, checkboxlistNodes, documentAliasFilters); + base.ContentTemplateContainer.Controls.Add(checkboxlistNodes); + + break; + case "checkbox": + goto case "CheckBoxList"; + case "DropDownList": + dropdownlistNodes = new DropDownList(); + //dropdownlistNodes.ID = "nodes"; + ListItem empty = new ListItem(""); + dropdownlistNodes.Items.Add(empty); + addListControlNode(parentNode, 1, showChildren, dropdownlistNodes, documentAliasFilters); + foreach (string datavalue in datavalues) + { + dropdownlistNodes.SelectedValue = datavalue; + } + base.ContentTemplateContainer.Controls.Add(dropdownlistNodes); + break; + case "dropdown": + goto case "DropDownList"; + case "ListBox": + listboxNodes = new ListBox(); + //listboxNodes.ID = "nodes"; + listboxNodes.SelectionMode = ListSelectionMode.Multiple; + listboxNodes.Width = 300; + listboxNodes.Height = 200; + + addListControlNode(parentNode, 1, showChildren, listboxNodes, documentAliasFilters); + base.ContentTemplateContainer.Controls.Add(listboxNodes); + break; + case "listbox": + goto case "ListBox"; + case "RadioButtonList": + radiobuttonlistNodes = new RadioButtonList(); + radiobuttonlistNodes.AutoPostBack = true; + radiobuttonlistNodes.SelectedIndexChanged += new EventHandler(radiobuttonlistNodes_SelectedIndexChanged); + //radiobuttonlistNodes.ID = "nodes"; + addListControlNode(parentNode, 1, showChildren, radiobuttonlistNodes, documentAliasFilters); + + clearRadiobuttonlist = new Button(); + clearRadiobuttonlist.Click += new EventHandler(clearRadiobuttonlist_Click); + clearRadiobuttonlist.Text = "Clear"; + + clearRadiobuttons = new CheckBox(); + clearRadiobuttons.Visible = false; + + base.ContentTemplateContainer.Controls.Add(radiobuttonlistNodes); + base.ContentTemplateContainer.Controls.Add(clearRadiobuttonlist); + base.ContentTemplateContainer.Controls.Add(clearRadiobuttons); + break; + case "radiobox": + goto case "RadioButtonList"; + } + } + catch { } + } + + void radiobuttonlistNodes_SelectedIndexChanged(object sender, EventArgs e) + { + clearRadiobuttons.Checked = false; + } + + void clearRadiobuttonlist_Click(object sender, EventArgs e) + { + + + foreach (ListItem radiobutton in radiobuttonlistNodes.Items) + { + radiobutton.Selected = false; + } + + clearRadiobuttons.Checked = true; + } + + + + /// + /// Adds sub nodes to the ListControl object passed into the method, based on the Content node passed in + /// + /// The node whos sub nodes are to be added to the ListControl + /// The level of the current node + /// Boolean determining if grand children should be displayed as well + /// The ListControl the nodes must be added to + /// String representing the documentTypeAlias that should be filtered for. If empty no filter is applied + private void addListControlNode(umbraco.cms.businesslogic.Content node, int level, bool showGrandChildren, ListControl control, string[] documentAliasFilters) + { + if (node.HasChildren) + { + foreach (CMSNode child in node.Children) + { + umbraco.cms.businesslogic.Content doc = new umbraco.cms.businesslogic.Content(child.Id); + string preText = string.Empty; + + for (int i = 1; i < level; i++) + { + preText += "- "; + } + + //Run through the filters passed in + if (documentAliasFilters.Length > 0) + { + foreach (string filter in documentAliasFilters) + { + string trimmedFilter = filter.TrimStart(" ".ToCharArray()); + trimmedFilter = trimmedFilter.TrimEnd(" ".ToCharArray()); + + if (doc.ContentType.Alias == trimmedFilter || trimmedFilter == string.Empty) + { + ListItem item = new ListItem(preText + doc.Text, doc.Id.ToString()); + if (_data.Value.ToString().Contains(doc.Id.ToString())) + { + item.Selected = true; + } + control.Items.Add(item); + } + } + } + else + { + ListItem item = new ListItem(preText + doc.Text, doc.Id.ToString()); + if (_data.Value.ToString().Contains(doc.Id.ToString())) + { + item.Selected = true; + } + control.Items.Add(item); + } + + if (showGrandChildren) + { + addListControlNode(doc, level + 1, showGrandChildren, control, documentAliasFilters); + } + } + } + } + + /// + /// Sets up the autocomplete functionality + /// + private void setupAutoComplete(int parentNodeId) + { + string script = ""; + this.Page.ClientScript.RegisterClientScriptBlock(script.GetType(), "ultimatePickerCss", script); + childtxt = new TextBox(); + childtxt.ID = "ultimatePickerBox" + base.ID; + childtxt.AutoCompleteType = AutoCompleteType.Disabled; + childtxt.CssClass = "umbEditorTextField"; + AutoCompleteExtender extender = new AutoCompleteExtender(); + extender.TargetControlID = "ultimatePickerBox" + base.ID; + extender.ServiceMethod = "getNodes"; + + extender.ServicePath = ConfigurationManager.AppSettings["umbracoPath"] + "/webservices/ultimatePickerAutoSuggest.asmx"; + extender.MinimumPrefixLength = 2; + extender.CompletionInterval = 1000; + extender.EnableCaching = true; + extender.CompletionSetCount = 5; + extender.CompletionListCssClass = "autocomplete_completionListElement"; + extender.CompletionListItemCssClass = "autocomplete_listItem"; + extender.CompletionListHighlightedItemCssClass = "autocomplete_highlightedListItem"; + extender.DelimiterCharacters = ";, :"; + extender.UseContextKey = true; + extender.ContextKey = parentNodeId.ToString() + "|" + config[3] + "|" + config[2]; + + if (_data.Value.ToString().Length > 3) + { + try + { + CMSNode firstSaved = new CMSNode(Convert.ToInt32(_data.Value.ToString().Substring(0, 4))); + childtxt.Text = firstSaved.Text; + } + catch + { + + } + } + + base.ContentTemplateContainer.Controls.Add(childtxt); + base.ContentTemplateContainer.Controls.Add(extender); + } + } +} diff --git a/components/editorControls/ultimatepicker/ultimatePickerDataType.cs b/components/editorControls/ultimatepicker/ultimatePickerDataType.cs new file mode 100644 index 0000000000..c3185d6ec6 --- /dev/null +++ b/components/editorControls/ultimatepicker/ultimatePickerDataType.cs @@ -0,0 +1,58 @@ +using System; +using System.Data; +using System.Configuration; +using System.Web; +using System.Web.Security; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.WebControls.WebParts; +using System.Web.UI.HtmlControls; + +namespace umbraco.editorControls.ultimatepicker +{ + public class ultimatePickerDataType : umbraco.cms.businesslogic.datatype.BaseDataType, umbraco.interfaces.IDataType + { + private umbraco.interfaces.IDataEditor _Editor; + private umbraco.interfaces.IData _baseData; + private ultimatePickerPrevalueEditor _prevalueeditor; + + public override umbraco.interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new ultimatePickerDataEditor(Data, ((ultimatePickerPrevalueEditor)PrevalueEditor).Configuration); + return _Editor; + } + } + + public override umbraco.interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new umbraco.cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + public override Guid Id + { + get { return new Guid("cdbf0b5d-5cb2-445f-bc12-fcaaec07cf2c"); } + } + + public override string DataTypeName + { + get { return "Ultimate Picker"; } + } + + public override umbraco.interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new ultimatePickerPrevalueEditor(this); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/ultimatepicker/ultimatePickerPrevalueEditor.cs b/components/editorControls/ultimatepicker/ultimatePickerPrevalueEditor.cs new file mode 100644 index 0000000000..e04ea1912f --- /dev/null +++ b/components/editorControls/ultimatepicker/ultimatePickerPrevalueEditor.cs @@ -0,0 +1,203 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Web; +using System.Web.Security; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.WebControls.WebParts; +using System.Web.UI.HtmlControls; +using System.IO; + +using umbraco.DataLayer; +using umbraco.BusinessLogic; + +using umbraco.editorControls; + +namespace umbraco.editorControls.ultimatepicker +{ + public class ultimatePickerPrevalueEditor : System.Web.UI.WebControls.PlaceHolder, umbraco.interfaces.IDataPrevalue + { + public ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + #region IDataPrevalue Members + + // referenced datatype + private umbraco.cms.businesslogic.datatype.BaseDataType _datatype; + + private DropDownList _dropdownlist; + private DropDownList _dropdownlistType; + private TextBox _textboxParentNode; + private TextBox _textboxDocumentTypeFilter; + private CheckBox _checkboxShowGrandChildren; + + public ultimatePickerPrevalueEditor(umbraco.cms.businesslogic.datatype.BaseDataType DataType) + { + // state it knows its datatypedefinitionid + _datatype = DataType; + setupChildControls(); + + } + + private void setupChildControls() + { + _dropdownlist = new DropDownList(); + _dropdownlist.ID = "dbtype"; + _dropdownlist.Items.Add(DBTypes.Date.ToString()); + _dropdownlist.Items.Add(DBTypes.Integer.ToString()); + _dropdownlist.Items.Add(DBTypes.Ntext.ToString()); + _dropdownlist.Items.Add(DBTypes.Nvarchar.ToString()); + + _dropdownlistType = new DropDownList(); + _dropdownlistType.ID = "type"; + _dropdownlistType.Items.Add("AutoComplete"); + _dropdownlistType.Items.Add("CheckBoxList"); + _dropdownlistType.Items.Add("DropDownList"); + _dropdownlistType.Items.Add("ListBox"); + _dropdownlistType.Items.Add("RadioButtonList"); + + _textboxParentNode = new TextBox(); + _textboxParentNode.ID = "parentnode"; + _textboxParentNode.CssClass = "umbEditorTextField"; + + _textboxDocumentTypeFilter = new TextBox(); + _textboxDocumentTypeFilter.ID = "documentTypeFilter"; + _textboxDocumentTypeFilter.CssClass = "umbEditorTextField"; + + _checkboxShowGrandChildren = new CheckBox(); + _checkboxShowGrandChildren.ID = "showgrandchildren"; + + // put the childcontrols in context - ensuring that + // the viewstate is persisted etc. + Controls.Add(_dropdownlist); + Controls.Add(_dropdownlistType); + Controls.Add(_textboxParentNode); + Controls.Add(_textboxDocumentTypeFilter); + Controls.Add(_checkboxShowGrandChildren); + } + + + + public Control Editor + { + get + { + return this; + } + } + + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + if (!Page.IsPostBack) + { + string[] config = Configuration.Split("|".ToCharArray()); + if (config.Length > 1) + { + _dropdownlistType.SelectedValue = config[0]; + _textboxParentNode.Text = config[1]; + _textboxDocumentTypeFilter.Text = config[2]; + _checkboxShowGrandChildren.Checked = Convert.ToBoolean(config[3]); + + } + _dropdownlist.SelectedValue = _datatype.DBType.ToString(); + + } + + + } + + public void Save() + { + _datatype.DBType = (umbraco.cms.businesslogic.datatype.DBTypes)Enum.Parse(typeof(umbraco.cms.businesslogic.datatype.DBTypes), _dropdownlist.SelectedValue, true); + + + string validatedFilter = validateFilterInput(_textboxDocumentTypeFilter.Text); + + // Generate data-string + string data = _dropdownlistType.SelectedValue + "|" + _textboxParentNode.Text + "|" + validatedFilter + "|" + _checkboxShowGrandChildren.Checked.ToString(); + + // If the add new prevalue textbox is filled out - add the value to the collection. + IParameter[] SqlParams = new IParameter[] { + SqlHelper.CreateParameter("@value",data), + SqlHelper.CreateParameter("@dtdefid",_datatype.DataTypeDefinitionId)}; + SqlHelper.ExecuteNonQuery("delete from cmsDataTypePreValues where datatypenodeid = @dtdefid", SqlParams); + SqlHelper.ExecuteNonQuery("insert into cmsDataTypePreValues (datatypenodeid,[value],sortorder,alias) values (@dtdefid,@value,0,'')", SqlParams); + + + } + + protected override void Render(HtmlTextWriter writer) + { + writer.WriteLine(""); + writer.WriteLine(""); + writer.Write(""); + writer.Write(""); + writer.Write(""); + writer.Write(""); + writer.Write("
Database datatype:"); + _dropdownlist.RenderControl(writer); + writer.Write("
Type:"); + _dropdownlistType.RenderControl(writer); + writer.Write("
Parent nodeid:"); + _textboxParentNode.RenderControl(writer); + writer.Write("
Document Alias filter (comma-separated):"); + _textboxDocumentTypeFilter.RenderControl(writer); + writer.Write("
Show grandchildren:"); + _checkboxShowGrandChildren.RenderControl(writer); + writer.Write("
"); + } + + public string Configuration + { + get + { + object conf = + SqlHelper.ExecuteScalar("select value from cmsDataTypePreValues where datatypenodeid = @datatypenodeid", + SqlHelper.CreateParameter("@datatypenodeid", _datatype.DataTypeDefinitionId)); + if (conf != null) + return conf.ToString(); + else + return ""; + + } + } + + #endregion + + /// + /// Validates and clears the filter input from errorneous entries + /// + /// The filter string to be validated + /// A validated filtered comma separated string + public string validateFilterInput(string filterInput) + { + string[] filters = filterInput.Split(",".ToCharArray()); + string validatedFilter = string.Empty; + List validatedFilters = new List(); + + foreach (string filter in filters) + { + string trimmedFilter = filter.TrimStart(" ".ToCharArray()); + trimmedFilter = trimmedFilter.TrimEnd(" ".ToCharArray()); + + if (trimmedFilter != string.Empty) + { + validatedFilters.Add(trimmedFilter); + } + } + + for (int i = 0; i < validatedFilters.Count; i++) + { + if (i > 0) + validatedFilter += ","; + validatedFilter += validatedFilters[i]; + } + return validatedFilter; + } + } +} diff --git a/components/editorControls/ultraSimpleMailer/mailerConfiguratorPreValueEditor.cs b/components/editorControls/ultraSimpleMailer/mailerConfiguratorPreValueEditor.cs new file mode 100644 index 0000000000..d3f72e9774 --- /dev/null +++ b/components/editorControls/ultraSimpleMailer/mailerConfiguratorPreValueEditor.cs @@ -0,0 +1,130 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +using umbraco.BusinessLogic; +using umbraco.DataLayer; + +namespace umbraco.editorControls.ultraSimpleMailer +{ + /// + /// Summary description for mailerConfiguratorPreValueEditor. + /// + public class mailerConfiguratorPreValueEditor : umbraco.editorControls.tinymce.tinyMCEPreValueConfigurator + { + + // UI controls + private TextBox _textboxEmail; + private TextBox _textboxSender; + private DropDownList _dropdownlistMG; + + // referenced datatype + private cms.businesslogic.datatype.BaseDataType _datatype; + + public static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + public mailerConfiguratorPreValueEditor(cms.businesslogic.datatype.BaseDataType DataType) : base(DataType) + { + // state it knows its datatypedefinitionid + _datatype = DataType; + setupChildControls(); + + } + + private void setupChildControls() + { + + _dropdownlistMG = new DropDownList(); + _dropdownlistMG.ID = "memberGroup"; + + _textboxSender = new TextBox(); + _textboxSender.ID = "SenderName"; + _textboxEmail = new TextBox(); + _textboxEmail.ID = "SenderEmail"; + + // put the childcontrols in context - ensuring that + // the viewstate is persisted etc. + Controls.Add(_dropdownlistMG); + Controls.Add(_textboxSender); + Controls.Add(_textboxEmail); + + + // Get all membergroups + foreach(cms.businesslogic.member.MemberGroup mg in cms.businesslogic.member.MemberGroup.GetAll) + _dropdownlistMG.Items.Add(new ListItem(mg.Text, mg.Id.ToString())); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad (e); + if (!Page.IsPostBack) + { + string[] config = Configuration.Split("|".ToCharArray()); + if (config.Length > 9) + { + _textboxSender.Text = config[9]; + _textboxEmail.Text = config[10]; + _dropdownlistMG.SelectedValue = config[11]; + } + + } + } + + public Control Editor + { + get + { + return this; + } + } + + public override void Save() + { + base.Save(); + + // Generate data-string + string data = Configuration + "|" + _textboxSender.Text + "|"+ _textboxEmail.Text + "|" + _dropdownlistMG.SelectedValue; + // If the add new prevalue textbox is filled out - add the value to the collection. + IParameter[] SqlParams = new IParameter[] { + SqlHelper.CreateParameter("@value",data), + SqlHelper.CreateParameter("@dtdefid",_datatype.DataTypeDefinitionId)}; + SqlHelper.ExecuteNonQuery("delete from cmsDataTypePreValues where datatypenodeid = @dtdefid",SqlParams); + SqlHelper.ExecuteNonQuery("insert into cmsDataTypePreValues (datatypenodeid,[value],sortorder,alias) values (@dtdefid,@value,0,'')",SqlParams); + } + + protected override void Render(HtmlTextWriter writer) + { + writer.WriteLine(""); + writer.Write(""); + writer.Write(""); + writer.Write(""); + writer.Write("
Sender name:"); + _textboxSender.RenderControl(writer); + writer.Write("
Sender email:"); + _textboxEmail.RenderControl(writer); + writer.Write("
Membergroup to recieve mail:"); + _dropdownlistMG.RenderControl(writer); + writer.Write("
"); + base.Render(writer); + } + + public string Configuration + { + get + { + object conf = + SqlHelper.ExecuteScalar("select value from cmsDataTypePreValues where datatypenodeid = @datatypenodeid", + SqlHelper.CreateParameter("@datatypenodeid", _datatype.DataTypeDefinitionId)); + if (conf != null) + return conf.ToString(); + else + return ""; + + } + } + + } +} diff --git a/components/editorControls/ultraSimpleMailer/mailerHelper.cs b/components/editorControls/ultraSimpleMailer/mailerHelper.cs new file mode 100644 index 0000000000..b50330731d --- /dev/null +++ b/components/editorControls/ultraSimpleMailer/mailerHelper.cs @@ -0,0 +1,128 @@ +using System; +using System.IO; +using System.Collections; +using System.Text.RegularExpressions; +using DotNetOpenMail; /* http://dotnetopenmail.sourceforge.net/ */ + +namespace umbraco.editorControls.ultraSimpleMailer +{ + /// + /// Summary description for mailerHelper. + /// + public class mailerHelper + { + public mailerHelper() + { + // + // TODO: Add constructor logic here + // + } + + public static EmailMessage CreateEmbeddedEmail(string body, int newsletterId) + { + EmailMessage message = new EmailMessage(); + + Hashtable addedAtt = new Hashtable(); + + body = template.ParseInternalLinks(body); + + //string currentDomain = "http://" + System.Web.HttpContext.Current.Request.ServerVariables["SERVER_NAME"]; + //string pattern = "href=\"?([^\\\"' >]+)|src=\\\"?([^\\\"' >]+)"; + + string currentDomain = "http://" + System.Web.HttpContext.Current.Request.ServerVariables["SERVER_NAME"]; + string pattern = "href=\"?([^\\\"' >]+)|src=\\\"?([^\\\"' >]+)|background=\\\"?([^\\\"' >]+)"; + + string appendNewsletter = "umbNl=" + newsletterId.ToString(); + MatchCollection tags = Regex.Matches(body, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match tag in tags) + if (tag.Groups.Count > 0) + { + if (tag.Groups[1].Value.ToLower().IndexOf("http://") == -1 && + tag.Groups[2].Value.ToLower().IndexOf("http://") == -1 && + tag.Groups[1].Value.ToLower().IndexOf("mailto:") == -1 && + tag.Groups[2].Value.ToLower().IndexOf("mailto:") == -1) + { + // links + if (tag.Groups[1].Value != "") + { + if (tag.Groups[0].Value.ToLower() == "href=\"/") + { + if (tag.Groups[1].Value.IndexOf("?") == -1) + body = body.Replace(tag.Groups[0].Value + "\"", "href=\"" + currentDomain + tag.Groups[1].Value + "?" + appendNewsletter+ "\""); + else + body = body.Replace(tag.Groups[0].Value + "\"", "href=\"" + currentDomain + tag.Groups[1].Value + "&" + appendNewsletter + "\""); + } + else + { + if (tag.Groups[1].Value.IndexOf("?") == -1) + body = body.Replace("href=\"" + tag.Groups[1].Value + "\"", "href=\"" + currentDomain + tag.Groups[1].Value + "?" + appendNewsletter + "\""); + else + body = body.Replace("href=\"" + tag.Groups[1].Value + "\"", "href=\"" + currentDomain + tag.Groups[1].Value + "&" + appendNewsletter + "\""); + } + + } + // src + else + { + string imageExtextions = "jpg,jpeg,gif,png"; + string image = tag.Groups[2].Value; + if (image == "") + image = tag.Groups[3].Value; + string orgImage = image; + + string ext = image.Split(char.Parse("."))[image.Split(char.Parse(".")).Length -1].ToLower(); + + bool isImage = imageExtextions.IndexOf(ext) != -1; + + if (isImage) + { + string guid = Guid.NewGuid().ToString(); + FileAttachment attachment = CreateImageAttachment(image, ext, guid); + if (attachment != null) + { + if (addedAtt.ContainsKey(image)) + { + body = body.Replace(image, "cid:" + addedAtt[image].ToString()); + } + else + { + message.AddRelatedAttachment(attachment); + body = body.Replace(image, "cid:" + guid); + addedAtt.Add(image, guid); + } + } + else + { + body = body.Replace(orgImage, currentDomain + tag.Groups[2].Value); + } + // break; + } + else + { + body = body.Replace(orgImage, currentDomain + tag.Groups[2].Value); + } + + } + } + } + + message.HtmlPart = new HtmlAttachment(body); + + return message; + } + + private static FileAttachment CreateImageAttachment(string image, string ext, string contentId) + { + string path = System.Web.HttpContext.Current.Server.MapPath(image); + + if (!System.IO.File.Exists(path)) + return null; + + FileInfo file = new FileInfo(path); + FileAttachment attachment = new FileAttachment(file, contentId); + attachment.ContentType = "image/" + ext.ToLower().Replace("jpg", "jpeg"); + + return attachment; + } + } +} diff --git a/components/editorControls/ultraSimpleMailer/mailerLogic.cs b/components/editorControls/ultraSimpleMailer/mailerLogic.cs new file mode 100644 index 0000000000..ee7dcfd35e --- /dev/null +++ b/components/editorControls/ultraSimpleMailer/mailerLogic.cs @@ -0,0 +1,196 @@ +using System; +using System.IO; +using System.Text.RegularExpressions; +using DotNetOpenMail; /* http://dotnetopenmail.sourceforge.net/ */ +using System.Collections; + +using umbraco.DataLayer; +using umbraco.BusinessLogic; + +namespace umbraco.editorControls.ultraSimpleMailer +{ + /// + /// Summary description for mailerLogic. + /// + public class mailerLogic + { + public mailerLogic() + { + // + // TODO: Add constructor logic here + // + } + + public static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + public static int GetTotalReceiptients(umbraco.cms.businesslogic.member.MemberGroup Group) + { + return SqlHelper.ExecuteScalar("select count(*) from cmsMember inner join cmsMember2memberGroup on cmsmember.nodeId = cmsMember2MemberGroup.member where memberGroup = @memberGroupId", SqlHelper.CreateParameter("@memberGroupId", Group.Id)); + } + + public static void SendTestmail(string email, + umbraco.cms.businesslogic.property.Property Property, + string fromName, string fromEmail, bool IsHtml) + { + // version + string version = Property.VersionId.ToString(); + + // Get document + umbraco.cms.businesslogic.web.Document d = new umbraco.cms.businesslogic.web.Document(umbraco.cms.businesslogic.Content.GetContentFromVersion(Property.VersionId).Id); + System.Web.HttpContext.Current.Items["pageID"] = d.Id; + + // Format mail + string subject = d.Text; + string sender = "\"" + fromName + "\" <" + fromEmail + ">"; + + // Get template + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + System.IO.StringWriter sw = new StringWriter(sb); + System.Web.UI.HtmlTextWriter writer = new System.Web.UI.HtmlTextWriter(sw); + umbraco.template t = new template(d.Template); + t.ParseWithControls(new umbraco.page(d.Id, d.Version)).RenderControl(writer); + + // Embedded emails ;) added by DB, 2005-10-04 + + EmailMessage message = mailerHelper.CreateEmbeddedEmail(sb.ToString(), cms.businesslogic.web.Document.GetContentFromVersion(Property.VersionId).Id); + + message.FromAddress = new EmailAddress(fromEmail, fromName); + message.ToAddresses.Add(new EmailAddress(email)); + message.Subject = subject; + message.Send(new SmtpServer(GlobalSettings.SmtpServer)); + + } + + public static void SendMail(umbraco.cms.businesslogic.member.MemberGroup Group, umbraco.cms.businesslogic.property.Property Property, string fromName, string fromEmail, bool IsHtml) + { + // Create ArrayList with emails who've received the e-mail + ArrayList sent = new ArrayList(); + + // set timeout + System.Web.HttpContext.Current.Server.ScriptTimeout = 43200; // 12 hours + // version + string version = Property.VersionId.ToString(); + + // Get document + umbraco.cms.businesslogic.web.Document d = new umbraco.cms.businesslogic.web.Document(umbraco.cms.businesslogic.Content.GetContentFromVersion(Property.VersionId).Id); + int id = d.Id; + System.Web.HttpContext.Current.Items["pageID"] = id; + + // Format mail + string subject = d.Text; + string sender = "\"" + fromName + "\" <" + fromEmail + ">"; + + // Get template + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + System.IO.StringWriter sw = new StringWriter(sb); + System.Web.UI.HtmlTextWriter writer = new System.Web.UI.HtmlTextWriter(sw); + umbraco.template t = new template(d.Template); + t.ParseWithControls(new umbraco.page(d.Id, d.Version)).RenderControl(writer); + + + EmailMessage message = mailerHelper.CreateEmbeddedEmail(sb.ToString(), cms.businesslogic.web.Document.GetContentFromVersion(Property.VersionId).Id); + + message.FromAddress = new EmailAddress(fromEmail, fromName); + message.Subject = subject; + SmtpServer smtpServer = new SmtpServer(GlobalSettings.SmtpServer); + + // Bulk send mails + int counter = 0; + System.Text.StringBuilder sbStatus = new System.Text.StringBuilder(); + sbStatus.Append("The Newsletter '" + d.Text + "' was starting at " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString() + "\n"); + using(IRecordsReader dr = SqlHelper.ExecuteReader("select text, email from cmsMember inner join umbracoNode node on node.id = cmsMember.nodeId inner join cmsMember2memberGroup on cmsmember.nodeId = cmsMember2MemberGroup.member where memberGroup = @memberGroupId", SqlHelper.CreateParameter("@memberGroupId", Group.Id))) + { + while(dr.Read()) + { + try + { + if (!sent.Contains(dr.GetString("email"))) + { + message.ToAddresses.Clear(); + message.ToAddresses.Add(new EmailAddress(dr.GetString("email"), dr.GetString("text"))); + message.Send(smtpServer); + + // add to arraylist of receiptients + sent.Add(dr.GetString("email")); + + // Append to status + sbStatus.Append("Sent to " + dr.GetString("text") + " <" + dr.GetString("email") + "> \n\r"); + } + else + { + // Append to status + sbStatus.Append("E-mail has already been sent to email '" + dr.GetString("email") + ". You have a duplicate member: " + dr.GetString("text") + " <" + dr.GetString("email") + "> \n\r"); + } + } + catch(Exception ee) + { + sbStatus.Append("Error sending to " + dr.GetString("text") + " <" + dr.GetString("email") + ">: " + + ee.ToString() + " \n"); + } + + // For progress bar + counter++; + + if(counter % 5 == 0) + { + System.Web.HttpContext.Current.Application.Lock(); + System.Web.HttpContext.Current.Application["ultraSimpleMailerProgress" + id.ToString() + "Done"] = counter; + System.Web.HttpContext.Current.Application.UnLock(); + } + } + } + + sbStatus.Append("Finished at " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString() + "\n"); + + // Send status mail + library.SendMail(fromEmail, fromEmail, "Newsletter status", sbStatus.ToString(), false); + } + + private static string updateLocalUris(string body, int newsletterId) + { + string currentDomain = "http://" + System.Web.HttpContext.Current.Request.ServerVariables["SERVER_NAME"]; + string pattern = "href=\"?([^\\\"' >]+)|src=\\\"?([^\\\"' >]+)"; + string appendNewsletter = "umbNl=" + newsletterId.ToString(); + MatchCollection tags = Regex.Matches(body, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match tag in tags) + if (tag.Groups.Count > 0) + { + + if (tag.Groups[1].Value.ToLower().IndexOf("http://") == -1 && + tag.Groups[2].Value.ToLower().IndexOf("http://") == -1 && + tag.Groups[1].Value.ToLower().IndexOf("mailto:") == -1 && + tag.Groups[2].Value.ToLower().IndexOf("mailto:") == -1) + { + // links + if (tag.Groups[1].Value != "") + { + // Special case for root link ("/") + if (tag.Groups[0].Value.ToLower() == "href=\"/\"") + { + if (tag.Groups[1].Value.IndexOf("?") == -1) + body = body.Replace(tag.Groups[0].Value, "href=\"" + currentDomain + tag.Groups[1].Value + "?" + appendNewsletter+ "\""); + else + body = body.Replace(tag.Groups[0].Value, "href=\"" + currentDomain + tag.Groups[1].Value + "&" + appendNewsletter + "\""); + } + else + { + if (tag.Groups[1].Value.IndexOf("?") == -1) + body = body.Replace(tag.Groups[1].Value, currentDomain + tag.Groups[1].Value + "?" + appendNewsletter); + else + body = body.Replace(tag.Groups[1].Value, currentDomain + tag.Groups[1].Value + "&" + appendNewsletter); + } + + } + // src + else + body = body.Replace(tag.Groups[2].Value, currentDomain + tag.Groups[2].Value); + } + } + + return body; + } + } +} diff --git a/components/editorControls/ultraSimpleMailer/ultraSimpleMailerDataType.cs b/components/editorControls/ultraSimpleMailer/ultraSimpleMailerDataType.cs new file mode 100644 index 0000000000..f881063dec --- /dev/null +++ b/components/editorControls/ultraSimpleMailer/ultraSimpleMailerDataType.cs @@ -0,0 +1,56 @@ +using System; + +namespace umbraco.editorControls.ultraSimpleMailer +{ + /// + /// Summary description for ultraSimpleMailerDataType. + /// + public class ultraSimpleMailerDataType : cms.businesslogic.datatype.BaseDataType,interfaces.IDataType + { + private ultraSimpleMailerEditor _Editor; + private cms.businesslogic.datatype.DefaultData _baseData; + private mailerConfiguratorPreValueEditor _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + { + _Editor = new ultraSimpleMailerEditor((umbraco.cms.businesslogic.datatype.DefaultData)Data, ((mailerConfiguratorPreValueEditor)PrevalueEditor).Configuration); + + } + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + public override Guid Id + { + get {return new Guid("AABE748C-EFB6-4225-B7B2-DABC6FE36945");} + } + + public override string DataTypeName + { + get {return "UltraSimpleMailer(tm)";} + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new mailerConfiguratorPreValueEditor(this); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/ultraSimpleMailer/ultraSimpleMailerEditor.cs b/components/editorControls/ultraSimpleMailer/ultraSimpleMailerEditor.cs new file mode 100644 index 0000000000..a04672304c --- /dev/null +++ b/components/editorControls/ultraSimpleMailer/ultraSimpleMailerEditor.cs @@ -0,0 +1,162 @@ +using System; +using System.Collections; + +using umbraco.editorControls.wysiwyg; +using umbraco.uicontrols; +using System.Web.UI; + +namespace umbraco.editorControls.ultraSimpleMailer +{ + /// + /// Summary description for ultraSimpleMailerEditor. + /// + public class ultraSimpleMailerEditor : umbraco.editorControls.tinyMCE3.TinyMCE, interfaces.IDataFieldWithButtons + { + umbraco.cms.businesslogic.datatype.DefaultData _data; + string _configuration; + private controls.progressBar pb; + + public ultraSimpleMailerEditor(umbraco.cms.businesslogic.datatype.DefaultData Data, string Configuration) + : base(Data, Configuration) + { + _configuration = Configuration; + _data = Data; + } + + + protected override void OnLoad(EventArgs e) + { + base.OnLoad (e); + + // init progressbar + pb = new umbraco.controls.progressBar(); + Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "UltraSimpleMailerJs", ""); + string[] config = _configuration.Split("|".ToCharArray()); + cms.businesslogic.member.MemberGroup mg = new umbraco.cms.businesslogic.member.MemberGroup(int.Parse(config[11])); + string totalReceip = mailerLogic.GetTotalReceiptients(mg).ToString(); + Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "ultraSimpleMailerAjax", ""); + Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "progressBar", ""); + Page.ClientScript.RegisterClientScriptBlock(Page.GetType(), "progressBarCss", ""); + + // We need to make sure we have a reference to the legacy ajax calls in the scriptmanager + presentation.webservices.ajaxHelpers.EnsureLegacyCalls(base.Page); + + } + + protected override void Render(System.Web.UI.HtmlTextWriter writer) + { + + // Debug - needs logic + string[] config = _configuration.Split("|".ToCharArray()); + cms.businesslogic.member.MemberGroup mg = new umbraco.cms.businesslogic.member.MemberGroup(int.Parse(config[11])); + + writer.WriteLine(""); + writer.WriteLine(""); + + if (umbraco.helper.Request(this.ClientID + "_doTest") == "" && umbraco.helper.Request(this.ClientID + "_doSend") == "") + base.Render (writer); + else + { + writer.WriteLine("
"); + + if (umbraco.helper.Request(this.ClientID + "_sendButton") != "") + { + // Test mail + if (umbraco.helper.Request(this.ClientID + "_doTest") != "") + { + writer.WriteLine("

Send newsletter to test...


"); + mailerLogic.SendTestmail(umbraco.helper.Request(this.ClientID + "_test_rcp"), new cms.businesslogic.property.Property(_data.PropertyId), config[9], config[10], true); + writer.WriteLine("Test mail sent to: " + umbraco.helper.Request(this.ClientID + "_test_rcp") + "
"); + } + else + { + writer.WriteLine("

Send newsletter to all...


"); + mailerLogic.SendMail(mg, new cms.businesslogic.property.Property(_data.PropertyId), config[9], config[10], true); + writer.WriteLine("Sent...
"); + + } + } + else + { + if (umbraco.helper.Request(this.ClientID + "_doTest") != "") + { + writer.WriteLine("

Send newsletter to test...


"); + writer.WriteLine("Send test to: "); + writer.WriteLine(""); + } + else + { + string strScript = " alert('The MassMailer / UltraSimplerMailer is incompatible with Umbraco 4'); umbPgStep = 1;\n umbPgIgnoreSteps = true;\n"; + if (ScriptManager.GetCurrent(Page).IsInAsyncPostBack) + ScriptManager.RegisterClientScriptBlock(this, this.GetType(), this.ClientID, strScript, true); + else + Page.ClientScript.RegisterStartupScript(this.GetType(), this.ClientID, strScript, true); + + writer.WriteLine("


\"Sending
\n" + + " Sending mails...\n" + + "
\n" + + "
\n"); + + + + // Progressbar + pb.ID = "ultraSimpleMailerUpgradeStatus"; + pb.Width = 200; + pb.RenderControl(writer); + writer.WriteLine("


\n" + + "
"); + writer.WriteLine("

Send newsletter to all...


"); + writer.WriteLine("Please confirm that you want to send this message to " + mailerLogic.GetTotalReceiptients(mg).ToString() + " recipients
"); + writer.WriteLine(" Yes
"); + writer.WriteLine(""); + writer.WriteLine("
"); + } + + } + writer.WriteLine("
"); + } + + } + + + + public object[] MenuIcons + { + get + { + object[] _buttons = { }; + + ArrayList buttons = new ArrayList(); + for (int i=0;i<_buttons.Length;i++) + buttons.Add(_buttons[i]); + + // Add the two new buttons + MenuIconI menuItemSend = new MenuIconClass(); + menuItemSend.OnClickCommand = "ultraSimpleMailer_doSend('" + this.ClientID + "')"; + menuItemSend.ImageURL = "/umbraco_client/ultraSimpleMailer/images/newsletterSend.gif"; + menuItemSend.AltText = "Send newsletter to all"; + menuItemSend.ID = "sendToAll"; + buttons.Insert(0, menuItemSend); + + MenuIconI menuItemTest = new MenuIconClass(); + menuItemTest.OnClickCommand = "ultraSimpleMailer_doSendTest('" + this.ClientID + "')"; + menuItemTest.ImageURL = "/umbraco_client/ultraSimpleMailer/images/newsletterSendTest.gif"; + menuItemTest.AltText = "Test newsletter by sending to a mail address you specify"; + menuItemTest.ID = "sendToTest"; + buttons.Insert(1, menuItemTest); + buttons.Insert(2, "|"); + + // Re-create the button array + _buttons = new object[buttons.Count]; + for (int i=0;i + + Local + 9.0.30729 + 2.0 + {255F5DF1-4E43-4758-AC05-7A0B68EB021B} + Debug + AnyCPU + + + + + umbraco.editorControls + + + JScript + Grid + IE50 + false + Library + umbraco.editorControls + OnBuildSuccess + + + + + + + SAK + SAK + SAK + SAK + 2.0 + http://localhost/umbraco.editorControls/ + true + Web + true + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + true + false + true + + + ..\..\umbraco\presentation\bin\ + false + 285212672 + false + + + DEBUG;TRACE + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + ..\..\umbraco\presentation\bin\ + false + 285212672 + false + + + TRACE + ..\..\umbraco\presentation\bin\umbraco.editorControls.XML + false + 4096 + false + + + true + false + false + false + 4 + none + prompt + + + + False + ..\..\foreign dlls\AjaxControlToolkit.dll + + + DotNetOpenMail + ..\..\foreign dlls\DotNetOpenMail.dll + + + System + + + + System.Data + + + System.Drawing + + + System.Web + + + + System.Windows.Forms + + + System.XML + + + umbraco.businesslogic + {E469A9CE-1BEC-423F-AC44-713CD72457EA} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + umbraco.cms + {CCD75EC3-63DB-4184-B49D-51C1DD337230} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + {C7CB79F0-1C97-4B33-BFA7-00731B579AE2} + umbraco.datalayer + + + umbraco.interfaces + {511F6D8D-7717-440A-9A57-A507E9A8B27F} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + umbraco.presentation + {651E1350-91B6-44B7-BD60-7207006D7003} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + {6EDD2061-82F2-461B-BB6E-879245A832DE} + umbraco.controls + + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + + + + + Code + + + Code + + + + + + + Code + + + Code + + + Code + + + + + + + + + + + + + + + + + + + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + + + + + Code + + + Code + + + Code + + + Code + + + textFieldDataEditor.cs + Designer + + + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + + + + + + + + \ No newline at end of file diff --git a/components/editorControls/umbraco.editorControls.csproj.vspscc b/components/editorControls/umbraco.editorControls.csproj.vspscc new file mode 100644 index 0000000000..feffdecaa4 --- /dev/null +++ b/components/editorControls/umbraco.editorControls.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/components/editorControls/uploadfield/DataTypeUploadField.cs b/components/editorControls/uploadfield/DataTypeUploadField.cs new file mode 100644 index 0000000000..9ae372ddca --- /dev/null +++ b/components/editorControls/uploadfield/DataTypeUploadField.cs @@ -0,0 +1,54 @@ +using System; + +namespace umbraco.editorControls.uploadfield +{ + /// + /// Summary description for DataTypeUploadField. + /// + public class DataTypeUploadField : cms.businesslogic.datatype.BaseDataType,interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new uploadField(Data, ((uploadFieldPreValue)PrevalueEditor).Configuration); + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + + public override string DataTypeName + { + get {return "Upload field";} + } + + public override Guid Id + { + get {return new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c");} + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new uploadFieldPreValue(this); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/uploadfield/uploadField.cs b/components/editorControls/uploadfield/uploadField.cs new file mode 100644 index 0000000000..a76af35078 --- /dev/null +++ b/components/editorControls/uploadfield/uploadField.cs @@ -0,0 +1,366 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.ComponentModel; +using System.IO; +using System.Drawing; +using System.Drawing.Imaging; +using System.Drawing.Drawing2D; + +namespace umbraco.editorControls +{ + [ValidationProperty("IsValid")] + public class uploadField : System.Web.UI.HtmlControls.HtmlInputFile, interfaces.IDataEditor + { + private String _text; + private cms.businesslogic.datatype.DefaultData _data; + private String _thumbnails; + + const String _thumbnailext = ".jpg"; + + public uploadField(interfaces.IData Data, string ThumbnailSizes) + { + _data = (cms.businesslogic.datatype.DefaultData)Data; + _thumbnails = ThumbnailSizes; + } + + public Control Editor { get { return this; } } + + public virtual bool TreatAsRichTextEditor + { + get { return false; } + } + public bool ShowLabel + { + get { return true; } + } + + /// + /// Internal logic for validation controls to detect whether or not it's valid (has to be public though) + /// + /// Am I valid? + public string IsValid + { + get { + string tempText = Text; + bool isEmpty = String.IsNullOrEmpty(this.PostedFile.FileName); + // checkbox, if it's used the file will be deleted and we should throw a validation error + if (Page.Request[this.ClientID + "clear"] != null && Page.Request[this.ClientID + "clear"].ToString() != "") + return ""; + else if (!isEmpty) + return this.PostedFile.FileName; + else if (!String.IsNullOrEmpty(tempText)) + return tempText; + else + return ""; + } + } + + public String Text + { + get { return _text; } + set { _text = value; } + } + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + if (_data != null && _data.Value != null) + this.Text = _data.Value.ToString(); + } + + public void Save() + { + // Clear data + if (helper.Request(this.ClientID + "clear") == "1") + { + // delete file + deleteFile(_text); + + // set filename in db to nothing + _text = ""; + _data.Value = _text; + } + + if (this.PostedFile != null) + { + if (this.PostedFile.FileName != "") + { + //if (_text.Length > 0 && helper.Request(this.ClientID + "clear") != "1") + //{ + // //delete old file + // deleteFile(_text); + + //} + + // Find filename + _text = this.PostedFile.FileName; + string filename; + string _fullFilePath; + + cms.businesslogic.Content content = cms.businesslogic.Content.GetContentFromVersion(this._data.Version); + + if (umbraco.UmbracoSettings.UploadAllowDirectories) + { + filename = _text.Substring(_text.LastIndexOf("\\") + 1, _text.Length - _text.LastIndexOf("\\") - 1).ToLower(); + // Create a new folder in the /media folder with the name /media/propertyid + System.IO.Directory.CreateDirectory(System.Web.HttpContext.Current.Server.MapPath(umbraco.GlobalSettings.Path + "/../media/" + _data.PropertyId.ToString())); + _fullFilePath = System.Web.HttpContext.Current.Server.MapPath(umbraco.GlobalSettings.Path + "/../media/" + _data.PropertyId + "/" + filename); + this.PostedFile.SaveAs(_fullFilePath); + _data.Value = "/media/" + _data.PropertyId + "/" + filename; + } + else + { + //filename = this. + filename = System.IO.Path.GetFileName(this.PostedFile.FileName); + //filename = _text.Substring(_text.LastIndexOf("\\") + 1, _text.Length - _text.LastIndexOf("\\") - 1).ToLower(); + filename = _data.PropertyId + "-" + filename; + _fullFilePath = System.Web.HttpContext.Current.Server.MapPath(umbraco.GlobalSettings.Path + "/../media/" + filename); + this.PostedFile.SaveAs(_fullFilePath); + _data.Value = "/media/" + filename; + } + + // hack to find master page prefix client id + string masterpagePrefix = this.ClientID.Substring(0, this.ClientID.LastIndexOf("_") + 1); + + // Save extension + string orgExt = ((string)_text.Substring(_text.LastIndexOf(".") + 1, _text.Length - _text.LastIndexOf(".") - 1)); + orgExt = orgExt.ToLower(); + string ext = orgExt.ToLower(); + try + { + //cms.businesslogic.Content.GetContentFromVersion(_data.Version).getProperty("umbracoExtension").Value = ext; + content.getProperty("umbracoExtension").Value = ext; + noEdit extensionControl = uploadField.FindControlRecursive(this.Page, "umbracoExtension"); + if (extensionControl != null) + { + extensionControl.RefreshLabel(content.getProperty("umbracoExtension").Value.ToString()); + } + } + catch { } + + + + // Save file size + try + { + System.IO.FileInfo fi = new FileInfo(_fullFilePath); + //cms.businesslogic.Content.GetContentFromVersion(_data.Version).getProperty("umbracoBytes").Value = fi.Length.ToString(); + content.getProperty("umbracoBytes").Value = fi.Length.ToString(); + noEdit bytesControl = uploadField.FindControlRecursive(this.Page, "umbracoBytes"); + if (bytesControl != null) + { + bytesControl.RefreshLabel(content.getProperty("umbracoBytes").Value.ToString()); + } + } + catch { } + + // Check if image and then get sizes, make thumb and update database + if (",jpeg,jpg,gif,bmp,png,tiff,tif,".IndexOf("," + ext + ",") > -1) + { + int fileWidth; + int fileHeight; + + FileStream fs = new FileStream(_fullFilePath, + FileMode.Open, FileAccess.Read, FileShare.Read); + + System.Drawing.Image image = System.Drawing.Image.FromStream(fs); + fileWidth = image.Width; + fileHeight = image.Height; + fs.Close(); + try + { + //cms.businesslogic.Content.GetContentFromVersion(_data.Version).getProperty("umbracoWidth").Value = fileWidth.ToString(); + //cms.businesslogic.Content.GetContentFromVersion(_data.Version).getProperty("umbracoHeight").Value = fileHeight.ToString(); + content.getProperty("umbracoWidth").Value = fileWidth.ToString(); + noEdit widthControl = uploadField.FindControlRecursive(this.Page, "umbracoWidth"); + if (widthControl != null) + { + widthControl.RefreshLabel(content.getProperty("umbracoWidth").Value.ToString()); + } + content.getProperty("umbracoHeight").Value = fileHeight.ToString(); + noEdit heightControl = uploadField.FindControlRecursive(this.Page, "umbracoHeight"); + if (heightControl != null) + { + heightControl.RefreshLabel(content.getProperty("umbracoHeight").Value.ToString()); + } + } + catch { } + + + // Generate thumbnails + string fileNameThumb = _fullFilePath.Replace("." + orgExt, "_thumb"); + generateThumbnail(image, 100, fileWidth, fileHeight, _fullFilePath, ext, fileNameThumb + _thumbnailext); + + if (_thumbnails != "") + { + string[] thumbnailSizes = _thumbnails.Split(";".ToCharArray()); + foreach (string thumb in thumbnailSizes) + if (thumb != "") + generateThumbnail(image, int.Parse(thumb), fileWidth, fileHeight, _fullFilePath, ext, fileNameThumb + "_" + thumb + _thumbnailext); + } + + image.Dispose(); + } + } + this.Text = _data.Value.ToString(); + } + } + + private void deleteFile(string file) + { + if (file.Length > 0) + { + // delete old file + if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath(file))) + System.IO.File.Delete(System.Web.HttpContext.Current.Server.MapPath(file)); + + string extension = ((string)file.Substring(file.LastIndexOf(".") + 1, file.Length - file.LastIndexOf(".") - 1)); + extension = extension.ToLower(); + + //check for thumbnails + if (",jpeg,jpg,gif,bmp,png,tiff,tif,".IndexOf("," + extension + ",") > -1) + { + + + //delete thumbnails + string thumbnailfile = file.Replace("." + extension, "_thumb"); + + try + { + if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath(thumbnailfile + _thumbnailext))) + System.IO.File.Delete(System.Web.HttpContext.Current.Server.MapPath(thumbnailfile + _thumbnailext)); + } + catch { } + + if (_thumbnails != "") + { + string[] thumbnailSizes = _thumbnails.Split(";".ToCharArray()); + foreach (string thumb in thumbnailSizes) + { + if (thumb != "") + { + string thumbnailextra = thumbnailfile + "_" + thumb + _thumbnailext; + + try + { + if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath(thumbnailextra))) + System.IO.File.Delete(System.Web.HttpContext.Current.Server.MapPath(thumbnailextra)); + } + catch { } + } + } + + } + } + } + } + + private void generateThumbnail(System.Drawing.Image image, int maxWidthHeight, int fileWidth, int fileHeight, string fullFilePath, string ext, string thumbnailFileName) + { + // Generate thumbnail + float fx = (float)fileWidth / (float)maxWidthHeight; + float fy = (float)fileHeight / (float)maxWidthHeight; + // must fit in thumbnail size + float f = Math.Max(fx, fy); //if (f < 1) f = 1; + int widthTh = (int)Math.Round((float)fileWidth / f); int heightTh = (int)Math.Round((float)fileHeight / f); + + // fixes for empty width or height + if (widthTh == 0) + widthTh = 1; + if (heightTh == 0) + heightTh = 1; + + // Create new image with best quality settings + Bitmap bp = new Bitmap(widthTh, heightTh); + Graphics g = Graphics.FromImage(bp); + g.SmoothingMode = SmoothingMode.HighQuality; + g.InterpolationMode = InterpolationMode.HighQualityBicubic; + g.PixelOffsetMode = PixelOffsetMode.HighQuality; + + // Copy the old image to the new and resized + Rectangle rect = new Rectangle(0, 0, widthTh, heightTh); + g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel); + + // Copy metadata + ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); + ImageCodecInfo codec = null; + for (int i = 0; i < codecs.Length; i++) + { + if (codecs[i].MimeType.Equals("image/jpeg")) + codec = codecs[i]; + } + + // Set compresion ratio to 90% + EncoderParameters ep = new EncoderParameters(); + ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L); + + // Save the new image + bp.Save(thumbnailFileName, codec, ep); + bp.Dispose(); + g.Dispose(); + + } + + /// + /// Recursively finds a control with the specified identifier. + /// + /// + /// The type of control to be found. + /// + /// + /// The parent control from which the search will start. + /// + /// + /// The identifier of the control to be found. + /// + /// + /// The control with the specified identifier, otherwise if the control + /// is not found. + /// + private static T FindControlRecursive(Control parent, string id) where T : Control + { + if ((parent is T) && (parent.ID == id)) + { + return (T)parent; + } + + foreach (Control control in parent.Controls) + { + T foundControl = uploadField.FindControlRecursive(control, id); + if (foundControl != null) + { + return foundControl; + } + } + return default(T); + } + + /// + /// Render this control to the output parameter specified. + /// + /// The HTML writer to write out to + protected override void Render(HtmlTextWriter output) + { + if (this.Text != null && this.Text != "") + { + string ext = _text.Substring(_text.LastIndexOf(".") + 1, _text.Length - _text.LastIndexOf(".") - 1); + string fileNameThumb = umbraco.GlobalSettings.Path + "/.." + _text.Replace("." + ext, "_thumb.jpg"); + bool hasThumb = false; + try + { + hasThumb = File.Exists(System.Web.HttpContext.Current.Server.MapPath(fileNameThumb)); + } + catch { } + if (hasThumb) + { + output.WriteLine("
"); + } + else + output.WriteLine("" + this.Text + "
"); + output.WriteLine("
"); + } + base.Render(output); + } + } +} diff --git a/components/editorControls/uploadfield/uploadFieldPreValue.cs b/components/editorControls/uploadfield/uploadFieldPreValue.cs new file mode 100644 index 0000000000..86ac01c84b --- /dev/null +++ b/components/editorControls/uploadfield/uploadFieldPreValue.cs @@ -0,0 +1,115 @@ +using System; +using System.Collections; +using System.Web.UI; +using System.Web.UI.WebControls; + +using umbraco.BusinessLogic; +using umbraco.DataLayer; + +namespace umbraco.editorControls.uploadfield +{ + class uploadFieldPreValue : System.Web.UI.WebControls.PlaceHolder, interfaces.IDataPrevalue + { + + // UI controls + private TextBox _textboxThumbnails; + private DropDownList _dropdownlist; + + // referenced datatype + private cms.businesslogic.datatype.BaseDataType _datatype; + + public static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + public uploadFieldPreValue(cms.businesslogic.datatype.BaseDataType DataType) + { + // state it knows its datatypedefinitionid + _datatype = DataType; + setupChildControls(); + + } + + private void setupChildControls() + { + _dropdownlist = new DropDownList(); + _dropdownlist.ID = "dbtype"; + _dropdownlist.Items.Add(DBTypes.Date.ToString()); + _dropdownlist.Items.Add(DBTypes.Integer.ToString()); + _dropdownlist.Items.Add(DBTypes.Ntext.ToString()); + _dropdownlist.Items.Add(DBTypes.Nvarchar.ToString()); + + + _textboxThumbnails = new TextBox(); + _textboxThumbnails.ID = "thumbNailSizes"; + + // put the childcontrols in context - ensuring that + // the viewstate is persisted etc. + this.Controls.Add(_dropdownlist); + this.Controls.Add(_textboxThumbnails); + + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad (e); + if (!Page.IsPostBack) + { + string[] config = Configuration.Split("|".ToCharArray()); + if (config.Length > 0) + { + _textboxThumbnails.Text = config[0]; + } + _dropdownlist.SelectedValue = _datatype.DBType.ToString(); + } + } + + public Control Editor + { + get + { + return this; + } + } + + public void Save() + { + _datatype.DBType = (umbraco.cms.businesslogic.datatype.DBTypes)Enum.Parse(typeof(umbraco.cms.businesslogic.datatype.DBTypes), _dropdownlist.SelectedValue, true); + + // Generate data-string + string data = _textboxThumbnails.Text; + // If the add new prevalue textbox is filled out - add the value to the collection. + IParameter[] SqlParams = new IParameter[] { + SqlHelper.CreateParameter("@value",data), + SqlHelper.CreateParameter("@dtdefid",_datatype.DataTypeDefinitionId)}; + SqlHelper.ExecuteNonQuery("delete from cmsDataTypePreValues where datatypenodeid = @dtdefid",SqlParams); + SqlHelper.ExecuteNonQuery("insert into cmsDataTypePreValues (datatypenodeid,[value],sortorder,alias) values (@dtdefid,@value,0,'')",SqlParams); + } + + protected override void Render(HtmlTextWriter writer) + { + writer.WriteLine(""); + writer.WriteLine(""); + writer.Write(""); + writer.Write("
Database datatype"); + _dropdownlist.RenderControl(writer); + writer.Write("
Thumbnail sizes (max width/height, semicolon separated for multiples):"); + _textboxThumbnails.RenderControl(writer); + writer.Write("
"); + } + + public string Configuration + { + get + { + object configVal = SqlHelper.ExecuteScalar("select value from cmsDataTypePreValues where datatypenodeid = @datatypenodeid", SqlHelper.CreateParameter("@datatypenodeid", _datatype.DataTypeDefinitionId)); + if (configVal != null) + return configVal.ToString(); + else + return ""; + } + } + + } +} diff --git a/components/editorControls/userControlWrapper/IUsercontrolDataEditor.cs b/components/editorControls/userControlWrapper/IUsercontrolDataEditor.cs new file mode 100644 index 0000000000..36d7344045 --- /dev/null +++ b/components/editorControls/userControlWrapper/IUsercontrolDataEditor.cs @@ -0,0 +1,7 @@ +namespace umbraco.editorControls.userControlGrapper +{ + public interface IUsercontrolDataEditor + { + object value { get; set;} + } +} diff --git a/components/editorControls/userControlWrapper/usercontrolDataEditor.cs b/components/editorControls/userControlWrapper/usercontrolDataEditor.cs new file mode 100644 index 0000000000..0f7b4e8b91 --- /dev/null +++ b/components/editorControls/userControlWrapper/usercontrolDataEditor.cs @@ -0,0 +1,61 @@ +using System; +using System.Data; +using System.Configuration; +using System.Web; +using System.Web.Security; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.WebControls.WebParts; +using System.Web.UI.HtmlControls; + +using umbraco.interfaces; +using umbraco.editorControls; + +namespace umbraco.editorControls.userControlGrapper +{ + public class usercontrolDataEditor : System.Web.UI.WebControls.PlaceHolder, umbraco.interfaces.IDataEditor + { + private umbraco.interfaces.IData _data; + private string _usercontrolPath; + + + public usercontrolDataEditor(umbraco.interfaces.IData Data, string UsercontrolPath) + { + _data = Data; + _usercontrolPath = UsercontrolPath; + } + + public virtual bool TreatAsRichTextEditor + { + get {return false;} + } + + public bool ShowLabel + { + get {return true;} + } + + public Control Editor {get{return this;}} + + public void Save() + { + IUsercontrolDataEditor uc = + (IUsercontrolDataEditor)Controls[0] as IUsercontrolDataEditor; + + _data.Value = uc.value; + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + + this.Controls.Add( + new System.Web.UI.UserControl().LoadControl(_usercontrolPath)); + + if (!Page.IsPostBack) + ((IUsercontrolDataEditor)Controls[0] as IUsercontrolDataEditor).value = _data.Value; + + } + + } +} \ No newline at end of file diff --git a/components/editorControls/userControlWrapper/usercontrolDataType.cs b/components/editorControls/userControlWrapper/usercontrolDataType.cs new file mode 100644 index 0000000000..13db9418ee --- /dev/null +++ b/components/editorControls/userControlWrapper/usercontrolDataType.cs @@ -0,0 +1,58 @@ +using System; +using System.Data; +using System.Configuration; +using System.Web; +using System.Web.Security; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.WebControls.WebParts; +using System.Web.UI.HtmlControls; + +namespace umbraco.editorControls.userControlGrapper +{ + public class usercontrolDataType : umbraco.cms.businesslogic.datatype.BaseDataType, umbraco.interfaces.IDataType + { + private umbraco.interfaces.IDataEditor _Editor; + private umbraco.interfaces.IData _baseData; + private usercontrolPrevalueEditor _prevalueeditor; + + public override umbraco.interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new usercontrolDataEditor(Data, ((usercontrolPrevalueEditor) PrevalueEditor).Configuration ); + return _Editor; + } + } + + public override umbraco.interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new umbraco.cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + public override Guid Id + { + get { return new Guid("D15E1281-E456-4b24-AA86-1DDA3E4299D5"); } + } + + public override string DataTypeName + { + get { return "umbraco usercontrol wrapper"; } + } + + public override umbraco.interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new usercontrolPrevalueEditor(this); + return _prevalueeditor; + } + } + } +} \ No newline at end of file diff --git a/components/editorControls/userControlWrapper/usercontrolPrevalueEditor.cs b/components/editorControls/userControlWrapper/usercontrolPrevalueEditor.cs new file mode 100644 index 0000000000..b651dc210f --- /dev/null +++ b/components/editorControls/userControlWrapper/usercontrolPrevalueEditor.cs @@ -0,0 +1,146 @@ +using System; +using System.Configuration; +using System.Web; +using System.Web.Security; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.WebControls.WebParts; +using System.Web.UI.HtmlControls; +using System.IO; + +using umbraco.DataLayer; +using umbraco.BusinessLogic; + +using umbraco.editorControls; + +namespace umbraco.editorControls.userControlGrapper +{ + public class usercontrolPrevalueEditor : System.Web.UI.WebControls.PlaceHolder, umbraco.interfaces.IDataPrevalue + { + public ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + #region IDataPrevalue Members + + // referenced datatype + private umbraco.cms.businesslogic.datatype.BaseDataType _datatype; + + private DropDownList _dropdownlist; + private DropDownList _dropdownlistUserControl; + + + public usercontrolPrevalueEditor(umbraco.cms.businesslogic.datatype.BaseDataType DataType) + { + // state it knows its datatypedefinitionid + _datatype = DataType; + setupChildControls(); + + } + + private void setupChildControls() + { + _dropdownlist = new DropDownList(); + _dropdownlist.ID = "dbtype"; + _dropdownlist.Items.Add(DBTypes.Date.ToString()); + _dropdownlist.Items.Add(DBTypes.Integer.ToString()); + _dropdownlist.Items.Add(DBTypes.Ntext.ToString()); + _dropdownlist.Items.Add(DBTypes.Nvarchar.ToString()); + + _dropdownlistUserControl = new DropDownList(); + _dropdownlistUserControl.ID = "usercontrol"; + + // put the childcontrols in context - ensuring that + // the viewstate is persisted etc. + Controls.Add(_dropdownlist); + Controls.Add(_dropdownlistUserControl); + + // populate the usercontrol dropdown + _dropdownlistUserControl.Items.Add(new ListItem(ui.Text("choose"), "")); + populateUserControls(System.Web.HttpContext.Current.Server.MapPath("/usercontrols")); + + } + + private void populateUserControls(string path) + { + DirectoryInfo di = new DirectoryInfo(path); + foreach (FileInfo uc in di.GetFiles("*.ascx")) + { + _dropdownlistUserControl.Items.Add( + new ListItem(uc.FullName.Substring(uc.FullName.IndexOf("\\usercontrols"), uc.FullName.Length - uc.FullName.IndexOf("\\usercontrols")).Replace("\\", "/"))); + + } + foreach (DirectoryInfo dir in di.GetDirectories()) + populateUserControls(dir.FullName); + } + + public Control Editor + { + get + { + return this; + } + } + + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + if (!Page.IsPostBack) + { + string config = Configuration; + if (config != "") + { + _dropdownlistUserControl.SelectedValue = config; + } + _dropdownlist.SelectedValue = _datatype.DBType.ToString(); + + } + } + + public void Save() + { + _datatype.DBType = (umbraco.cms.businesslogic.datatype.DBTypes)Enum.Parse(typeof(umbraco.cms.businesslogic.datatype.DBTypes), _dropdownlist.SelectedValue, true); + + // Generate data-string + string data = _dropdownlistUserControl.SelectedValue; + + // If the add new prevalue textbox is filled out - add the value to the collection. + IParameter[] SqlParams = new IParameter[] { + SqlHelper.CreateParameter("@value",data), + SqlHelper.CreateParameter("@dtdefid",_datatype.DataTypeDefinitionId)}; + SqlHelper.ExecuteNonQuery("delete from cmsDataTypePreValues where datatypenodeid = @dtdefid", SqlParams); + SqlHelper.ExecuteNonQuery("insert into cmsDataTypePreValues (datatypenodeid,[value],sortorder,alias) values (@dtdefid,@value,0,'')", SqlParams); + } + + protected override void Render(HtmlTextWriter writer) + { + writer.WriteLine(""); + writer.WriteLine(""); + writer.Write(""); + writer.Write("
Database datatype"); + _dropdownlist.RenderControl(writer); + writer.Write("
Usercontrol:"); + _dropdownlistUserControl.RenderControl(writer); + writer.Write("
"); + } + + public string Configuration + { + get + { + object conf = + SqlHelper.ExecuteScalar("select value from cmsDataTypePreValues where datatypenodeid = @datatypenodeid", + SqlHelper.CreateParameter("@datatypenodeid", _datatype.DataTypeDefinitionId)); + if (conf != null) + return conf.ToString(); + else + return ""; + + } + } + + #endregion + } +} diff --git a/components/editorControls/wysiwyg/WysiwygDataType.cs b/components/editorControls/wysiwyg/WysiwygDataType.cs new file mode 100644 index 0000000000..2baa07007f --- /dev/null +++ b/components/editorControls/wysiwyg/WysiwygDataType.cs @@ -0,0 +1,56 @@ +using System; + +namespace umbraco.editorControls.wysiwyg +{ + /// + /// Summary description for WysiwygDataType. + /// + public class WysiwygDataType : cms.businesslogic.datatype.BaseDataType,interfaces.IDataType + { + private editor _Editor; + private cms.businesslogic.datatype.DefaultData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + { + _Editor = new editor((cms.businesslogic.datatype.DefaultData)Data); + + } + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + public override Guid Id + { + get {return new Guid("a3776494-0574-4d93-b7de-efdfdec6f2d1");} + } + + public override string DataTypeName + { + get {return "Editor";} + } + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new DefaultPrevalueEditor(this,false); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/wysiwyg/editor.cs b/components/editorControls/wysiwyg/editor.cs new file mode 100644 index 0000000000..ec554526dd --- /dev/null +++ b/components/editorControls/wysiwyg/editor.cs @@ -0,0 +1,577 @@ +using System; +using System.Collections; +using System.Drawing; +using System.Drawing.Drawing2D; +using System.Drawing.Imaging; +using System.Text.RegularExpressions; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; +using umbraco.BusinessLogic; +using umbraco.interfaces; +using umbraco.uicontrols; + +namespace umbraco.editorControls.wysiwyg +{ + /// + /// Generates a field for typing numeric data + /// + public class editor : HiddenField, IDataFieldWithButtons + { + private ArrayList _buttons = new ArrayList(); + private bool _isInitialized = false; + private String _text; + private ArrayList _menuIcons = new ArrayList(); + + private bool _browserIsCompatible = false; + + private cms.businesslogic.datatype.DefaultData _data; + + public editor(cms.businesslogic.datatype.DefaultData Data) + { + _data = Data; + + if (HttpContext.Current.Request.Browser.Win32 && + HttpContext.Current.Request.Browser.Browser == "IE") + _browserIsCompatible = true; + } + + public virtual bool TreatAsRichTextEditor + { + get { return true; } + } + + public bool ShowLabel + { + get { return false; } + } + + public Control Editor + { + get { return this; } + } + + public String Text + { + get + { + if (_text == null) return ""; + HttpContext.Current.Trace.Warn("return text", _text); + return _text; + } + set + { + _text = " " + value + " "; + if (_text.Trim() != "") + { + // Check for umbraco tags + string pattern = @"[^'](<\?UMBRACO_MACRO\W*[^>]*/>)[^']"; + MatchCollection tags = + Regex.Matches(_text, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match tag in tags) + { + _text = + _text.Replace(tag.Groups[1].Value, + "" + tag.Groups[1].Value + ""); + } + + // Clean urls + // _text = _text.Replace("http://" + System.Web.HttpContext.Current.Request.ServerVariables["SERVER_NAME"], "").Replace("HTTP://" + System.Web.HttpContext.Current.Request.ServerVariables["SERVER_NAME"], ""); + } + base.Value = _text.Trim(); + } + } + + + public virtual object[] MenuIcons + { + get + { + initButtons(); + + object[] tempIcons = new object[_menuIcons.Count]; + for (int i = 0; i < _menuIcons.Count; i++) + tempIcons[i] = _menuIcons[i]; + return tempIcons; + } + } + + public override string Value + { + get { return base.Value; } + set + { + base.Value = " " + value + " "; + // Check for umbraco tags + string pattern = @"[^'](<\?UMBRACO_MACRO\W*[^>]*/>)[^']"; + MatchCollection tags = + Regex.Matches(base.Value + " ", pattern, + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match tag in tags) + { + base.Value = + base.Value.Replace(tag.Groups[1].Value, + "" + tag.Groups[1].Value + ""); + } + + Text = base.Value.Trim(); + } + } + + private string cleanImages(string html) + { + string[] allowedAttributes = UmbracoSettings.ImageAllowedAttributes.ToLower().Split(','); + string pattern = @"]*>"; + MatchCollection tags = + Regex.Matches(html + " ", pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match tag in tags) + { + if (tag.Value.ToLower().IndexOf("umbraco_macro") == -1) + { + string cleanTag = "", " >"), + "(?\\S*)=\"(?[^\"]*)\"|(?\\S*)=(?[^\"|\\s]*)\\s", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match attributeSet in m) + ht.Add(attributeSet.Groups["attributeName"].Value.ToString().ToLower(), + attributeSet.Groups["attributeValue"].Value.ToString()); + + // Build image tag + foreach (string attr in allowedAttributes) + { + if (helper.FindAttribute(ht, attr) != "") + cleanTag += " " + attr + "=\"" + helper.FindAttribute(ht, attr) + "\""; + } + + // If umbracoResizeImage attribute exists we should resize the image! + if (helper.FindAttribute(ht, "umbracoresizeimage") != "") + { + try + { + cleanTag += doResize(ht); + } + catch (Exception err) + { + cleanTag += " src=\"" + helper.FindAttribute(ht, "src") + "\""; + if (helper.FindAttribute(ht, "width") != "") + { + cleanTag += " width=\"" + helper.FindAttribute(ht, "width") + "\""; + cleanTag += " height=\"" + helper.FindAttribute(ht, "height") + "\""; + } + Log.Add(LogTypes.Error, User.GetUser(0), -1, + "Error resizing image in editor: " + err.ToString()); + } + } + else + { + // Add src, width and height properties + cleanTag += " src=\"" + helper.FindAttribute(ht, "src") + "\""; + + if (helper.FindAttribute(ht, "width") != "") + { + cleanTag += " width=\"" + helper.FindAttribute(ht, "width") + "\""; + cleanTag += " height=\"" + helper.FindAttribute(ht, "height") + "\""; + } + } + + if (bool.Parse(GlobalSettings.EditXhtmlMode)) + cleanTag += "/"; + cleanTag += ">"; + html = html.Replace(tag.Value, cleanTag); + } + } + + return html; + } + + private string doResize(Hashtable attributes) + { + string resizeDim = helper.FindAttribute(attributes, "umbracoresizeimage"); + string[] resizeDimSplit = resizeDim.Split(','); + string orgSrc = helper.FindAttribute(attributes, "src").Replace("%20", " "); + int orgHeight = int.Parse(helper.FindAttribute(attributes, "umbracoorgheight")); + int orgWidth = int.Parse(helper.FindAttribute(attributes, "umbracoorgwidth")); + string beforeWidth = helper.FindAttribute(attributes, "umbracobeforeresizewidth"); + string beforeHeight = helper.FindAttribute(attributes, "umbracobeforeresizeheight"); + string newSrc = ""; + + if (orgHeight > 0 && orgWidth > 0 && resizeDim != "" && orgSrc != "") + { + // Check filename + if (beforeHeight != "" && beforeWidth != "") + { + orgSrc = orgSrc.Replace("_" + beforeWidth + "x" + beforeHeight, ""); + } + string ext = orgSrc.Substring(orgSrc.LastIndexOf(".") + 1, orgSrc.Length - orgSrc.LastIndexOf(".") - 1); + newSrc = orgSrc.Replace("." + ext, "_" + resizeDimSplit[0] + "x" + resizeDimSplit[1] + ".jpg"); + + string fullSrc = HttpContext.Current.Server.MapPath(orgSrc); + string fullSrcNew = HttpContext.Current.Server.MapPath(newSrc); + + // Load original image + System.Drawing.Image image = System.Drawing.Image.FromFile(fullSrc); + + // Create new image with best quality settings + Bitmap bp = new Bitmap(int.Parse(resizeDimSplit[0]), int.Parse(resizeDimSplit[1])); + Graphics g = Graphics.FromImage(bp); + g.SmoothingMode = SmoothingMode.HighQuality; + g.InterpolationMode = InterpolationMode.HighQualityBicubic; + g.PixelOffsetMode = PixelOffsetMode.HighQuality; + + // Copy the old image to the new and resized + Rectangle rect = new Rectangle(0, 0, int.Parse(resizeDimSplit[0]), int.Parse(resizeDimSplit[1])); + g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel); + + // Copy metadata + ImageCodecInfo[] codecs = ImageCodecInfo.GetImageEncoders(); + ImageCodecInfo codec = null; + for (int i = 0; i < codecs.Length; i++) + { + if (codecs[i].MimeType.Equals("image/jpeg")) + codec = codecs[i]; + } + + // Set compresion ratio to 90% + EncoderParameters ep = new EncoderParameters(); + ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L); + + // Save the new image + bp.Save(fullSrcNew, codec, ep); + orgSrc = newSrc; + } + + return " src=\"" + newSrc + "\" width=\"" + resizeDimSplit[0] + "\" height=\"" + resizeDimSplit[1] + "\""; + } + + public void Save() + { + if (Text.Trim() != "") + { + // Parse for servername + if (HttpContext.Current.Request.ServerVariables != null) + { + _text = _text.Replace(helper.GetBaseUrl(HttpContext.Current) + GlobalSettings.Path + "/", ""); + _text = _text.Replace(helper.GetBaseUrl(HttpContext.Current), ""); + } + + // Parse for editing scriptname + string pattern2 = GlobalSettings.Path + "/richTextHolder.aspx?[^#]*#"; + MatchCollection tags2 = + Regex.Matches(_text, pattern2, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match tag in tags2) + { + _text = _text.Replace(tag.Value, ""); + HttpContext.Current.Trace.Warn("editor-match", tag.Value); + } + + // Parse for macros inside images + string pattern = @"]*>)'[^>]*>"; + MatchCollection tags = + Regex.Matches(_text, pattern, RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match tag in tags) + if (tag.Groups.Count > 0) + { + string umbTag = tag.Groups[1].Value; + // Check for backwards compliance with old macro-tag format ( vs. new format with closed tags: ) + if (umbTag.IndexOf("/>") < 0) + umbTag = umbTag.Substring(0, umbTag.Length - 1) + "/>"; + + _text = _text.Replace(tag.Value, umbTag); + } + + + // check for image tags + _text = cleanImages(_text); + + _text = replaceMacroTags(_text).Trim(); + + // clean macros and add paragraph element for tidy + bool removeParagraphs = false; + if (_text.Length > 15 && _text.ToLower().Substring(0, 17) == "|||?umbraco_macro") + { + removeParagraphs = true; + _text = "

" + _text + "

"; + } + + // tidy html + + if (UmbracoSettings.TidyEditorContent) + { + string tidyTxt = library.Tidy(_text, false); + if (tidyTxt != "[error]") + { + // compensate for breaking macro tags by tidy + _text = tidyTxt.Replace("/?>", "/>"); + if (removeParagraphs) + { + if (_text.Length - _text.Replace("<", "").Length == 2) + _text = _text.Replace("

", "").Replace("

", ""); + } + } + else + Log.Add(LogTypes.Error, User.GetUser(0), _data.NodeId, + "Error tidying txt from property: " + _data.PropertyId.ToString()); + } + + // rescue umbraco tags + _text = _text.Replace("|||?", "").Replace("|*|", "\""); + + // if text is an empty parargraph, make it all empty + if (_text.ToLower() == "

") + _text = ""; + } + + // cms.businesslogic.Content.GetContentFromVersion(_version).getProperty(_alias).Value = Text; + + _data.Value = Text; + } + + private string replaceMacroTags(string text) + { + while (findStartTag(text) > -1) + { + string result = text.Substring(findStartTag(text), findEndTag(text) - findStartTag(text)); + text = text.Replace(result, generateMacroTag(result)); + } + return text; + } + + private string generateMacroTag(string macroContent) + { + string macroAttr = macroContent.Substring(5, macroContent.IndexOf(">") - 5); + string macroTag = "|||?UMBRACO_MACRO "; + Hashtable attributes = ReturnAttributes(macroAttr); + IDictionaryEnumerator ide = attributes.GetEnumerator(); + while (ide.MoveNext()) + { + if (ide.Key.ToString().IndexOf("umb_") != -1) + macroTag += ide.Key.ToString().Substring(4, ide.Key.ToString().Length - 4) + "=|*|" + + ide.Value.ToString() + "|*| "; + } + macroTag += "/|||"; + + return macroTag; + } + + public static Hashtable ReturnAttributes(String tag) + { + Hashtable ht = new Hashtable(); + MatchCollection m = + Regex.Matches(tag, "(?\\S*)=\"(?[^\"]*)\"", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match attributeSet in m) + ht.Add(attributeSet.Groups["attributeName"].Value.ToString(), + attributeSet.Groups["attributeValue"].Value.ToString()); + + return ht; + } + + private int findStartTag(string text) + { + string temp = ""; + text = text.ToLower(); + if (text.IndexOf("ismacro=\"true\"") > -1) + { + temp = text.Substring(0, text.IndexOf("ismacro=\"true\"")); + return temp.LastIndexOf("<"); + } + return -1; + } + + private int findEndTag(string text) + { + string find = ""; + return text.ToLower().IndexOf("") + find.Length; + } + + private void initButtons() + { + if (!_isInitialized) + { + _isInitialized = true; + + // Test for browser compliance + if (_browserIsCompatible) + { + // Add icons for the editor control: + // Html + // Preview + // Style picker, showstyles + // Bold, italic, Text Gen + // Align: left, center, right + // Lists: Bullet, Ordered, indent, undo indent + // Link, Anchor + // Insert: Image, macro, table, formular + _buttons.Add( + new editorButton("html", ui.Text("buttons", "htmlEdit", null), + GlobalSettings.Path + "/images/editor/html.gif", "viewHTML('" + ClientID + "')")); + _buttons.Add("split"); + _buttons.Add( + new editorButton("showstyles", ui.Text("buttons", "styleShow", null) + " (CTRL+SHIFT+V)", + GlobalSettings.Path + "/images/editor/showStyles.gif", + "umbracoShowStyles('" + ClientID + "')")); + _buttons.Add("split"); + _buttons.Add( + new editorButton("bold", ui.Text("buttons", "bold", null) + " (CTRL+B)", + GlobalSettings.Path + "/images/editor/bold.gif", + "umbracoEditorCommand('" + ClientID + "', 'bold', '')")); + _buttons.Add( + new editorButton("italic", ui.Text("buttons", "italic", null) + " (CTRL+I)", + GlobalSettings.Path + "/images/editor/italic.gif", + "umbracoEditorCommand('" + ClientID + "', 'italic', '')")); + _buttons.Add( + new editorButton("graphicheadline", ui.Text("buttons", "graphicHeadline", null) + "(CTRL+B)", + GlobalSettings.Path + "/images/editor/umbracoTextGen.gif", + "umbracoTextGen('" + ClientID + "')")); + _buttons.Add("split"); + _buttons.Add( + new editorButton("justifyleft", ui.Text("buttons", "justifyLeft", null), + GlobalSettings.Path + "/images/editor/left.gif", + "umbracoEditorCommand('" + ClientID + "', 'justifyleft', '')")); + _buttons.Add( + new editorButton("justifycenter", ui.Text("buttons", "justifyCenter", null), + GlobalSettings.Path + "/images/editor/center.gif", + "umbracoEditorCommand('" + ClientID + "', 'justifycenter', '')")); + _buttons.Add( + new editorButton("justifyright", ui.Text("buttons", "justifyRight", null), + GlobalSettings.Path + "/images/editor/right.gif", + "umbracoEditorCommand('" + ClientID + "', 'justifyright', '')")); + _buttons.Add("split"); + _buttons.Add( + new editorButton("listBullet", ui.Text("buttons", "listBullet", null), + GlobalSettings.Path + "/images/editor/bullist.gif", + "umbracoEditorCommand('" + ClientID + "', 'insertUnorderedList', '')")); + _buttons.Add( + new editorButton("listNumeric", ui.Text("buttons", "listNumeric", null), + GlobalSettings.Path + "/images/editor/numlist.gif", + "umbracoEditorCommand('" + ClientID + "', 'insertOrderedList', '')")); + _buttons.Add( + new editorButton("deindent", ui.Text("buttons", "deindent", null), + GlobalSettings.Path + "/images/editor/deindent.gif", + "umbracoEditorCommand('" + ClientID + "', 'Outdent', '')")); + _buttons.Add( + new editorButton("indent", ui.Text("buttons", "indent", null), + GlobalSettings.Path + "/images/editor/inindent.gif", + "umbracoEditorCommand('" + ClientID + "', 'Indent', '')")); + _buttons.Add("split"); + _buttons.Add( + new editorButton("linkInsert", ui.Text("buttons", "linkInsert", null), + GlobalSettings.Path + "/images/editor/link.gif", + "umbracoLink('" + ClientID + "')")); + _buttons.Add( + new editorButton("linkLocal", ui.Text("buttons", "linkLocal", null), + GlobalSettings.Path + "/images/editor/anchor.gif", + "umbracoAnchor('" + ClientID + "')")); + _buttons.Add("split"); + _buttons.Add( + new editorButton("pictureInsert", ui.Text("buttons", "pictureInsert", null), + GlobalSettings.Path + "/images/editor/image.gif", + "umbracoImage('" + ClientID + "')")); + _buttons.Add( + new editorButton("macroInsert", ui.Text("buttons", "macroInsert", null), + GlobalSettings.Path + "/images/editor/insMacro.gif", + "umbracoInsertMacro('" + ClientID + "', '" + GlobalSettings.Path + "')")); + _buttons.Add( + new editorButton("tableInsert", ui.Text("buttons", "tableInsert", null), + GlobalSettings.Path + "/images/editor/instable.gif", + "umbracoInsertTable('" + ClientID + "', '" + GlobalSettings.Path + "')")); + _buttons.Add( + new editorButton("formFieldInsert", ui.Text("buttons", "formFieldInsert", null), + GlobalSettings.Path + "/images/editor/form.gif", + "umbracoInsertForm('" + ClientID + "', '" + GlobalSettings.Path + "')")); + + // add save icon + foreach (object o in _buttons) + { + try + { + MenuIconI menuItem = new MenuIconClass(); + + editorButton e = (editorButton)o; + menuItem.OnClickCommand = e.onClickCommand; + menuItem.ImageURL = e.imageUrl; + menuItem.AltText = e.alttag; + menuItem.ID = e.id; + _menuIcons.Add(menuItem); + } + catch + { + _menuIcons.Add("|"); + } + } + } + } + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + Page.ClientScript.RegisterClientScriptInclude(Page.GetType(), "UMBRACO_EDITOR", GlobalSettings.Path + "/js/editorBarFunctions.js"); + } + + /// + /// Render this control to the output parameter specified. + /// + /// The HTML writer to write out to + protected override void Render(HtmlTextWriter output) + { + if (_browserIsCompatible) + { + base.Render(output); + output.Write(""); + output.Write(""); + + string strScript = "function umbracoRichTextSave" + ClientID + "() {\nif (document.frames[\"" + + ClientID + "_holder\"].document.getElementById(\"holder\")) document.getElementById(\"" + + ClientID + "\").value = document.frames[\"" + ClientID + + "_holder\"].document.getElementById(\"holder\").innerHTML;\n}" + + + "addSaveHandler('umbracoRichTextSave" + ClientID + "();');"; + try + { + if (ScriptManager.GetCurrent(Page).IsInAsyncPostBack) + ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "umbracoRichTextSave" + this.ClientID, strScript, true); + else + Page.ClientScript.RegisterStartupScript(this.GetType(), "umbracoRichTextSave" + this.ClientID, strScript, true); + } + catch + { + Page.ClientScript.RegisterStartupScript(this.GetType(), "umbracoRichTextSave" + this.ClientID, strScript, true); + } + } + else + { + output.WriteLine(""); + output.WriteLine( + "

(Unfortunately WYSIWYG editing is only useLiveEditing in Internet Explorer on Windows. More info)

"); + } + } + } + + internal class editorButton + { + public string imageUrl; + public string onClickCommand; + public string alttag; + public string id; + + public editorButton(string Id, string AltTag, string ImageUrl, string OnClickCommand) + { + id = Id; + alttag = AltTag; + imageUrl = ImageUrl; + onClickCommand = OnClickCommand; + } + } +} \ No newline at end of file diff --git a/components/editorControls/yesno/YesNoDataType.cs b/components/editorControls/yesno/YesNoDataType.cs new file mode 100644 index 0000000000..f9541da3ba --- /dev/null +++ b/components/editorControls/yesno/YesNoDataType.cs @@ -0,0 +1,54 @@ +using System; + +namespace umbraco.editorControls.yesno +{ + /// + /// Summary description for YesNoDataType. + /// + public class YesNoDataType : cms.businesslogic.datatype.BaseDataType,interfaces.IDataType + { + private interfaces.IDataEditor _Editor; + private interfaces.IData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + + public override interfaces.IDataEditor DataEditor + { + get + { + if (_Editor == null) + _Editor = new yesNo(Data); + return _Editor; + } + } + + public override interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new cms.businesslogic.datatype.DefaultData(this); + return _baseData; + } + } + + public override string DataTypeName + { + get {return "True/False (Ja/Nej)";} + } + public override Guid Id + { + get {return new Guid("38b352c1-e9f8-4fd8-9324-9a2eab06d97a");} + } + + + public override interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new DefaultPrevalueEditor(this,false); + return _prevalueeditor; + } + } + } +} diff --git a/components/editorControls/yesno/yesNo.cs b/components/editorControls/yesno/yesNo.cs new file mode 100644 index 0000000000..da805a92bc --- /dev/null +++ b/components/editorControls/yesno/yesNo.cs @@ -0,0 +1,68 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.ComponentModel; + +namespace umbraco.editorControls +{ + /// + /// Generates a radiolist of yes and no for boolean fields + /// + public class yesNo : System.Web.UI.WebControls.CheckBox, interfaces.IDataEditor + { + + private interfaces.IData _data; + public yesNo(interfaces.IData Data) { + _data = Data; + } + private String _text; + + public Control Editor { + get + { + return this; + } + } + public virtual bool TreatAsRichTextEditor + { + get {return false;} + } + public bool ShowLabel + { + get {return true;} + } + + public void Save() + { + string value = ""; + if (Checked) + value = "1"; + else + value = "0"; + _data.Value = value; + + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + this.Text = ui.Text("yes"); + } + + + /// + /// Render this control to the output parameter specified. + /// + /// The HTML writer to write out to + protected override void Render(HtmlTextWriter output) + { + if (!Page.IsPostBack && _data != null && _data.Value != null) + { + if (_data.Value.ToString() == "1") + this.Checked = true; + } + + base.Render(output); + } + } +} diff --git a/components/macroRenderings/AssemblyInfo.cs b/components/macroRenderings/AssemblyInfo.cs new file mode 100644 index 0000000000..177a4f0e70 --- /dev/null +++ b/components/macroRenderings/AssemblyInfo.cs @@ -0,0 +1,58 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.0.*")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/components/macroRenderings/autoForms.cs b/components/macroRenderings/autoForms.cs new file mode 100644 index 0000000000..58d6358797 --- /dev/null +++ b/components/macroRenderings/autoForms.cs @@ -0,0 +1,44 @@ +using System; + +namespace umbraco.macroRenderings +{ + /// + /// Summary description for autoForms. + /// + public class autoForms : System.Web.UI.HtmlControls.HtmlInputHidden, interfaces.IMacroGuiRendering + { + + private string _value; + public autoForms() + { + // + // TODO: Add constructor logic here + // + } + + protected override void Render(System.Web.UI.HtmlTextWriter writer) + { + writer.WriteLine(""); + } + + #region IMacroGuiRendering Members + + public override string Value + { + set + { + _value = value; + } + } + + public bool ShowCaption + { + get + { + return false; + } + } + + #endregion + } +} diff --git a/components/macroRenderings/content.cs b/components/macroRenderings/content.cs new file mode 100644 index 0000000000..ede5e2cf5f --- /dev/null +++ b/components/macroRenderings/content.cs @@ -0,0 +1,113 @@ +using System; +using System.Data; +using Microsoft.ApplicationBlocks.Data; +using System.Data.SqlClient; +using System.Web.UI; + +namespace umbraco.macroRenderings +{ + /// + /// Summary description for content. + /// + public class content : System.Web.UI.WebControls.WebControl, interfaces.IMacroGuiRendering + { + private string m_value = ""; + + public bool ShowCaption + { + get {return true;} + } + + public string Value + { + get { + if (Page.IsPostBack && !String.IsNullOrEmpty(System.Web.HttpContext.Current.Request[this.ClientID])) { + m_value = System.Web.HttpContext.Current.Request[this.ClientID]; + } + return m_value; + } + set { m_value = value; } + } + + protected override void OnInit(EventArgs e) { + base.OnInit(e); + base.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "ajax", ""); + base.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "ajax1", ""); + base.Page.ClientScript.RegisterClientScriptBlock(GetType(), "subModal", ""); + + // We need to make sure we have a reference to the legacy ajax calls in the scriptmanager + ScriptManager sm = ScriptManager.GetCurrent(Page); + ServiceReference legacyPath = new ServiceReference(GlobalSettings.Path + "/webservices/legacyAjaxCalls.asmx"); + if (!sm.Services.Contains(legacyPath)) + sm.Services.Add(legacyPath); + } + + public content() + { + // + // TODO: Add constructor logic here + // + } + + protected override void Render(System.Web.UI.HtmlTextWriter writer) { + + string tempTitle = ""; + string deleteLink = "   " + ui.Text("delete") + "   "; + try { + if (this.Value != "") { + tempTitle = new cms.businesslogic.CMSNode(int.Parse(this.Value)).Text; + } + } catch { } + + writer.WriteLine(""); + + // Clear remove link if text if empty + if (this.Value == "") + deleteLink = ""; + writer.WriteLine("" + tempTitle + "" + deleteLink + "" + ui.Text("choose") + "...   "); + base.Render(writer); + } + + + /* + protected override void Render(System.Web.UI.HtmlTextWriter writer) + { + string label = ""; + if (this.Value != "") + { + SqlDataReader pageName = SqlHelper.ExecuteReader(umbraco.GlobalSettings.DbDSN, + CommandType.Text, "select text as nodeName from umbracoNode where id = " + this.Value); + if (pageName.Read()) + label = pageName.GetString(pageName.GetOrdinal("nodeName")) + "
"; + pageName.Close(); + } + writer.WriteLine("" + label + ""); + + writer.WriteLine("Choose item"); + writer.WriteLine(""); + }*/ + + } +} diff --git a/components/macroRenderings/contentType.cs b/components/macroRenderings/contentType.cs new file mode 100644 index 0000000000..0d72c250d5 --- /dev/null +++ b/components/macroRenderings/contentType.cs @@ -0,0 +1,89 @@ +using System; +using System.Data; +using System.Data.SqlClient; + + +namespace umbraco.macroRenderings +{ + /// + /// Summary description for contentType. + /// + public class contentTypeSingle : System.Web.UI.WebControls.ListBox, interfaces.IMacroGuiRendering + { + string _value = ""; + bool _multiple = false; + + public bool ShowCaption + { + get {return true;} + } + + public virtual bool Multiple + { + set {_multiple = value;} + get {return _multiple;} + } + + public string Value + { + get { + string retVal = ""; + foreach(System.Web.UI.WebControls.ListItem i in base.Items) + if (i.Selected) + retVal += i.Value + ","; + + if (retVal != "") + retVal = retVal.Substring(0, retVal.Length-1); + + return retVal; + } + set + { + _value = value; + } + } + + public contentTypeSingle() + { + // + // TODO: Add constructor logic here + // + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + + int count = 0; + this.CssClass = "guiInputTextStandard"; + + // Check for multiple choises + if (_multiple) + { + this.SelectionMode = System.Web.UI.WebControls.ListSelectionMode.Multiple; + this.Rows = 5; + this.Multiple =true; + } + else + { + this.Rows = 1; + this.Items.Add(new System.Web.UI.WebControls.ListItem("", "")); + this.SelectionMode = System.Web.UI.WebControls.ListSelectionMode.Single; + count = 1; + } + + // This should be replaced by business logic, but right now it would cause a circular reference if + // umbRuntime was added as a reference to this project + foreach(cms.businesslogic.web.DocumentType dt in cms.businesslogic.web.DocumentType.GetAllAsList()) + { + System.Web.UI.WebControls.ListItem li = new System.Web.UI.WebControls.ListItem(dt.Text, dt.Id.ToString()); + if (((string) (", "+_value+",")).IndexOf(", "+dt.Id.ToString()+",") > -1) + li.Selected = true; + + this.Items.Add(li); + count++; + } + } + + } +} diff --git a/components/macroRenderings/contentTypeMultiple.cs b/components/macroRenderings/contentTypeMultiple.cs new file mode 100644 index 0000000000..7926a352b2 --- /dev/null +++ b/components/macroRenderings/contentTypeMultiple.cs @@ -0,0 +1,24 @@ +using System; + +namespace umbraco.macroRenderings +{ + /// + /// Summary description for contentTypeMultiple. + /// + public class contentTypeMultiple : contentTypeSingle + { + public contentTypeMultiple() + { + // + // TODO: Add constructor logic here + // + } + + protected override void OnInit(EventArgs e) + { + this.Multiple = true; + base.OnInit (e); + } + + } +} diff --git a/components/macroRenderings/media.cs b/components/macroRenderings/media.cs new file mode 100644 index 0000000000..eca95a86ef --- /dev/null +++ b/components/macroRenderings/media.cs @@ -0,0 +1,114 @@ +using System; +using System.Data; +using Microsoft.ApplicationBlocks.Data; +using System.Data.SqlClient; + +using System.Web.UI; + +namespace umbraco.macroRenderings +{ + /// + /// Summary description for content. + /// + public class media : System.Web.UI.WebControls.WebControl, interfaces.IMacroGuiRendering + { + private string m_value = ""; + + public bool ShowCaption + { + get {return true;} + } + + public string Value { + get { + if (Page.IsPostBack && !String.IsNullOrEmpty(System.Web.HttpContext.Current.Request[this.ClientID])) { + m_value = System.Web.HttpContext.Current.Request[this.ClientID]; + } + return m_value; + } + set { m_value = value; } + } + + public media() + { + // + // TODO: Add constructor logic here + // + } + + protected override void OnInit(EventArgs e) { + base.OnInit(e); + base.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "ajax", ""); + base.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "ajax1", ""); + base.Page.ClientScript.RegisterClientScriptBlock(GetType(), "subModal", ""); + + // We need to make sure we have a reference to the legacy ajax calls in the scriptmanager + ScriptManager sm = ScriptManager.GetCurrent(Page); + ServiceReference legacyPath = new ServiceReference(GlobalSettings.Path + "/webservices/legacyAjaxCalls.asmx"); + if (!sm.Services.Contains(legacyPath)) + sm.Services.Add(legacyPath); + } + + + protected override void Render(System.Web.UI.HtmlTextWriter writer) { + + string tempTitle = ""; + string deleteLink = "   " + ui.Text("delete") + "   "; + try { + if (this.Value != "") { + tempTitle = new cms.businesslogic.CMSNode(int.Parse(this.Value)).Text; + } + } catch { } + + writer.WriteLine(""); + + // Clear remove link if text if empty + if (this.Value == "") + deleteLink = ""; + writer.WriteLine("" + tempTitle + "" + deleteLink + "" + ui.Text("choose") + "...   "); + base.Render(writer); + } + + /* + protected override void Render(System.Web.UI.HtmlTextWriter writer) + { + string label = ""; + if (this.Value != "") + { + SqlDataReader pageName = SqlHelper.ExecuteReader(umbraco.GlobalSettings.DbDSN, + CommandType.Text, "select text as nodeName from umbracoNode where id = " + this.Value); + if (pageName.Read()) + label = pageName.GetString(pageName.GetOrdinal("nodeName")) + "
"; + pageName.Close(); + } + writer.WriteLine("" + label + ""); + + writer.WriteLine("Choose item"); + writer.WriteLine(""); + } + */ + + } +} diff --git a/components/macroRenderings/numeric.cs b/components/macroRenderings/numeric.cs new file mode 100644 index 0000000000..e60219e8af --- /dev/null +++ b/components/macroRenderings/numeric.cs @@ -0,0 +1,46 @@ +using System; + +namespace umbraco.macroRenderings +{ + /// + /// + /// + public class numeric : System.Web.UI.WebControls.TextBox, interfaces.IMacroGuiRendering + { + string _value = ""; + + public bool ShowCaption + { + get {return true;} + } + + public string Value + { + get { + return base.Text; + } + set + { + this.Text = value; + _value = value; + } + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + this.CssClass = "guiInputTextStandard"; + this.Attributes.Add("style", "width: 30%"); + } + + + public numeric() + { + // + // TODO: Add constructor logic here + // + } + + + } +} diff --git a/components/macroRenderings/propertyTypePicker.cs b/components/macroRenderings/propertyTypePicker.cs new file mode 100644 index 0000000000..9fd70e63b5 --- /dev/null +++ b/components/macroRenderings/propertyTypePicker.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections; + +namespace umbraco.macroRenderings +{ + /// + /// Summary description for propertyTypePicker. + /// + public class propertyTypePicker : System.Web.UI.WebControls.ListBox, interfaces.IMacroGuiRendering + { + string _value = ""; + bool _multiple = false; + + public bool ShowCaption + { + get {return true;} + } + + public virtual bool Multiple + { + set {_multiple = value;} + get {return _multiple;} + } + + public string Value + { + get + { + string retVal = ""; + foreach(System.Web.UI.WebControls.ListItem i in base.Items) + if (i.Selected) + retVal += i.Value + ","; + + if (retVal != "") + retVal = retVal.Substring(0, retVal.Length-1); + + return retVal; + } + set + { + _value = value; + } + } + + public propertyTypePicker() + { + // + // TODO: Add constructor logic here + // + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + + this.CssClass = "guiInputTextStandard"; + + // Check for multiple choises + if (_multiple) + { + this.SelectionMode = System.Web.UI.WebControls.ListSelectionMode.Multiple; + this.Rows = 5; + this.Multiple =true; + } + else + { + this.Rows = 1; + this.Items.Add(new System.Web.UI.WebControls.ListItem("", "")); + this.SelectionMode = System.Web.UI.WebControls.ListSelectionMode.Single; + } + + Hashtable ht = new Hashtable(); + foreach(cms.businesslogic.propertytype.PropertyType pt in cms.businesslogic.propertytype.PropertyType.GetAll()) + { + if (!ht.ContainsKey(pt.Alias)) + { + System.Web.UI.WebControls.ListItem li = new System.Web.UI.WebControls.ListItem(pt.Alias); + if (((string) (", "+_value+",")).IndexOf(", "+pt.Alias+",") > -1) + li.Selected = true; + ht.Add(pt.Alias, ""); + + this.Items.Add(li); + } + } + + } + + } +} diff --git a/components/macroRenderings/propertyTypePickerMultiple.cs b/components/macroRenderings/propertyTypePickerMultiple.cs new file mode 100644 index 0000000000..e2fe1e4591 --- /dev/null +++ b/components/macroRenderings/propertyTypePickerMultiple.cs @@ -0,0 +1,23 @@ +using System; + +namespace umbraco.macroRenderings +{ + /// + /// Summary description for propertyTypePickerMultiple. + /// + public class propertyTypePickerMultiple : propertyTypePicker + { + public propertyTypePickerMultiple() + { + // + // TODO: Add constructor logic here + // + } + protected override void OnInit(EventArgs e) + { + base.Multiple = true; + base.OnInit (e); + } + + } +} diff --git a/components/macroRenderings/tabPicker.cs b/components/macroRenderings/tabPicker.cs new file mode 100644 index 0000000000..ae030ddbdd --- /dev/null +++ b/components/macroRenderings/tabPicker.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Web; +using umbraco.DataLayer; +using umbraco.interfaces; + + +namespace umbraco.macroRenderings +{ + + /// + /// Summary description for tabPicker. + /// + public class tabPicker : System.Web.UI.WebControls.ListBox, interfaces.IMacroGuiRendering + { + string _value = ""; + bool _multiple = false; + private static ISqlHelper _sqlHelper; + private static string _ConnString = GlobalSettings.DbDSN; + + public bool ShowCaption + { + get {return true;} + } + + public virtual bool Multiple + { + set {_multiple = value;} + get {return _multiple;} + } + + public string Value + { + get + { + string retVal = ""; + foreach(System.Web.UI.WebControls.ListItem i in base.Items) + if (i.Selected) + retVal += i.Value + ","; + + if (retVal != "") + retVal = retVal.Substring(0, retVal.Length-1); + + return retVal; + } + set + { + _value = value; + } + } + + public static ISqlHelper SqlHelper { + get { + if (_sqlHelper == null) { + try { + _sqlHelper = DataLayerHelper.CreateSqlHelper(_ConnString); + } catch { } + } + return _sqlHelper; + } + } + + public tabPicker() + { + // + // TODO: Add constructor logic here + // + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + + this.CssClass = "guiInputTextStandard"; + + // Check for multiple choises + if (_multiple) + { + this.SelectionMode = System.Web.UI.WebControls.ListSelectionMode.Multiple; + this.Rows = 5; + this.Multiple =true; + } + else + { + this.Rows = 1; + this.Items.Add(new System.Web.UI.WebControls.ListItem("", "")); + this.SelectionMode = System.Web.UI.WebControls.ListSelectionMode.Single; + } + + //SqlDataReader dr = SqlHelper.ExecuteReader(GlobalSettings.DbDSN, CommandType.Text, "select distinct text from cmsTab order by text"); + + + + using (IRecordsReader dr = SqlHelper.ExecuteReader("select distinct text from cmsTab order by text")) { + while (dr.Read()) { + + System.Web.UI.WebControls.ListItem li = new System.Web.UI.WebControls.ListItem(dr.GetString("text"), dr.GetString("text").ToLower()); + + if (((string)(", " + _value + ",")).IndexOf(", " + dr.GetString("text").ToLower() + ",") > -1) + li.Selected = true; + + this.Items.Add(li); + + } + } + +/* + while (dr.Read()) + { + System.Web.UI.WebControls.ListItem li = new System.Web.UI.WebControls.ListItem(dr["text"].ToString(), dr["text"].ToString().ToLower()); + if (((string) (", "+_value+",")).IndexOf(", "+dr["text"].ToString().ToLower()+",") > -1) + li.Selected = true; + + this.Items.Add(li); + } + dr.Close();*/ + + } + + } + + +} diff --git a/components/macroRenderings/tabPickerMultiple.cs b/components/macroRenderings/tabPickerMultiple.cs new file mode 100644 index 0000000000..368342664a --- /dev/null +++ b/components/macroRenderings/tabPickerMultiple.cs @@ -0,0 +1,24 @@ +using System; + +namespace umbraco.macroRenderings +{ + /// + /// Summary description for tabPickerMultiple. + /// + public class tabPickerMultiple : tabPicker + { + public tabPickerMultiple() + { + // + // TODO: Add constructor logic here + // + } + + protected override void OnInit(EventArgs e) + { + base.Multiple = true; + base.OnInit (e); + } + + } +} diff --git a/components/macroRenderings/text.cs b/components/macroRenderings/text.cs new file mode 100644 index 0000000000..d7391dded7 --- /dev/null +++ b/components/macroRenderings/text.cs @@ -0,0 +1,44 @@ +using System; + +namespace umbraco.macroRenderings +{ + /// + /// + /// + public class text : System.Web.UI.WebControls.TextBox, interfaces.IMacroGuiRendering + { + string _value = ""; + + public bool ShowCaption + { + get {return true;} + } + + public string Value + { + get { + return base.Text; + } + set { + this.Text = value; + _value = value; + } + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + this.CssClass = "guiInputTextStandard"; + } + + + public text() + { + // + // TODO: Add constructor logic here + // + } + + + } +} diff --git a/components/macroRenderings/textMultiple.cs b/components/macroRenderings/textMultiple.cs new file mode 100644 index 0000000000..92175b1aa3 --- /dev/null +++ b/components/macroRenderings/textMultiple.cs @@ -0,0 +1,25 @@ +using System; + +namespace umbraco.macroRenderings +{ + /// + /// Summary description for textMultiple. + /// + public class textMultiple : text + { + public textMultiple() + { + // + // TODO: Add constructor logic here + // + } + + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + this.TextMode = System.Web.UI.WebControls.TextBoxMode.MultiLine; + this.Rows = 6; + } + + } +} diff --git a/components/macroRenderings/umbraco.macroRenderings.csproj b/components/macroRenderings/umbraco.macroRenderings.csproj new file mode 100644 index 0000000000..8bd049341f --- /dev/null +++ b/components/macroRenderings/umbraco.macroRenderings.csproj @@ -0,0 +1,169 @@ + + + Local + 9.0.30729 + 2.0 + {52AB8F1F-FB76-4E8C-885F-0747B6CE71EC} + Debug + AnyCPU + + + + + umbraco.macroRenderings + + + JScript + Grid + IE50 + false + Library + umbraco.macroRenderings + OnBuildSuccess + + + + + + + SAK + SAK + SAK + SAK + 2.0 + + + ..\..\umbraco\presentation\bin\ + false + 285212672 + false + + + DEBUG;TRACE + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + ..\..\umbraco\presentation\bin\ + false + 285212672 + false + + + TRACE + ..\..\umbraco\presentation\bin\umbraco.macroRenderings.XML + false + 4096 + false + + + true + false + false + false + 4 + none + prompt + + + + Microsoft.ApplicationBlocks.Data + ..\..\foreign dlls\Microsoft.ApplicationBlocks.Data.dll + + + System + + + System.Data + + + System.Web + + + + System.XML + + + umbraco.businesslogic + {E469A9CE-1BEC-423F-AC44-713CD72457EA} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + umbraco.cms + {CCD75EC3-63DB-4184-B49D-51C1DD337230} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + {C7CB79F0-1C97-4B33-BFA7-00731B579AE2} + umbraco.datalayer + + + umbraco.interfaces + {511F6D8D-7717-440A-9A57-A507E9A8B27F} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + Code + + + + + + + + + + \ No newline at end of file diff --git a/components/macroRenderings/umbraco.macroRenderings.csproj.vspscc b/components/macroRenderings/umbraco.macroRenderings.csproj.vspscc new file mode 100644 index 0000000000..feffdecaa4 --- /dev/null +++ b/components/macroRenderings/umbraco.macroRenderings.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/components/macroRenderings/yesNo.cs b/components/macroRenderings/yesNo.cs new file mode 100644 index 0000000000..e2b4ad3b98 --- /dev/null +++ b/components/macroRenderings/yesNo.cs @@ -0,0 +1,67 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.ComponentModel; + +namespace umbraco.macroRenderings +{ + /// + /// Generates a radiolist of yes and no for boolean fields + /// + [DefaultProperty("Text"), + ToolboxData("<{0}:yesNo runat=server Version=\"\" Alias=\"\">")] + public class yesNo : System.Web.UI.WebControls.CheckBox, interfaces.IMacroGuiRendering + { + string _value = ""; + + public bool ShowCaption + { + get {return true;} + } + + + [Bindable(true), + Category("Umbraco"), + DefaultValue(""), + Browsable(true)] + public String Value + { + get { + if (base.Checked) + return "1"; + + return "0"; + } + + set {_value = value;} + } + + protected override void OnInit(EventArgs e) + { + this.Text = "Yes"; + base.OnInit (e); + } + + + /// + /// Render this control to the output parameter specified. + /// + /// The HTML writer to write out to + protected override void Render(HtmlTextWriter output) + { + if (_value != null) + { + if (_value == "1") + { + this.Checked = true; + } + else + { + this.Checked = false; + } + } + + base.Render(output); + } + } +} diff --git a/components/standardFormhandlers/AssemblyInfo.cs b/components/standardFormhandlers/AssemblyInfo.cs new file mode 100644 index 0000000000..177a4f0e70 --- /dev/null +++ b/components/standardFormhandlers/AssemblyInfo.cs @@ -0,0 +1,58 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.0.*")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/components/standardFormhandlers/formMail.cs b/components/standardFormhandlers/formMail.cs new file mode 100644 index 0000000000..c46238c1ee --- /dev/null +++ b/components/standardFormhandlers/formMail.cs @@ -0,0 +1,149 @@ +using System; +using System.Web; +using System.Xml; +using System.Xml.XPath; +using System.Text; +using System.Web.Mail; +using System.IO; + +namespace umbraco.standardFormhandlers +{ + /// + /// Summary description for Class1. + /// + public class formMail : interfaces.IFormhandler + { + /// + /// Initializes a new instance of the class. + /// + public formMail() + { + // + // TODO: Add constructor logic here + // + } + #region IFormhandler Members + + private int _redirectID = -1; + + /// + /// Executes the specified formhandler node. + /// + /// The formhandler node. + /// + public bool Execute(XmlNode formhandlerNode) + { + StringBuilder builder = new StringBuilder(); + XmlDocument document = new XmlDocument(); + document.LoadXml(""); + if (helper.Request("umbHeader") != "") + { + builder.Append(helper.Request("umbheader")); + } + foreach (string text in HttpContext.Current.Request.Form.Keys) + { + if (text.StartsWith("umbForm")) + { + builder.Append("\n\n" + text.Replace("umbForm", "") + ": " + HttpContext.Current.Request.Form[text]); + document.DocumentElement.AppendChild(xmlHelper.addCDataNode(document, text.Replace("umbForm", ""), HttpContext.Current.Request.Form[text])); + } + } + if (helper.Request("umbFooter") != "") + { + builder.Append(helper.Request("umbFooter")); + } + string subject = helper.Request("umbSubject"); + if (subject.Trim() == "") + { + subject = formhandlerNode.SelectSingleNode("//parameter [@alias='subject']").FirstChild.Value; + } + if (helper.Request("umbFormNoXml") != "") + { + document = null; + } + this.sendMail(formhandlerNode.SelectSingleNode("//parameter [@alias='sender']").FirstChild.Value, HttpContext.Current.Request.Form["sendTo"], subject, builder.ToString(), formhandlerNode.SelectSingleNode("//parameter [@alias='debug']").FirstChild.Value, document); + if (helper.Request("umbExtraMailTo") != "") + { + this.sendMail(formhandlerNode.SelectSingleNode("//parameter [@alias='sender']").FirstChild.Value, helper.Request("umbExtraMailto"), subject, builder.ToString(), formhandlerNode.SelectSingleNode("//parameter [@alias='debug']").FirstChild.Value, document); + } + string redir = HttpContext.Current.Request["umbracoRedirect"].ToString(); + if ((redir != null) && (redir != "")) + { + this._redirectID = Convert.ToInt32(redir); + } + return true; + } + + + + + /// + /// Gets the redirect ID. + /// + /// The redirect ID. + public int redirectID + { + get + { + // TODO: Add formMail.redirectID getter implementation + return _redirectID; + } + } + + #endregion + + private void sendMail(string From, string To, string Subject, string Body, string Debug, XmlDocument XmlDoc) + { + System.Net.Mail.MailMessage message = new System.Net.Mail.MailMessage(From, To); + message.Subject = Subject; + message.Body = Body; + Guid guid = Guid.NewGuid(); + string fileName = HttpContext.Current.Server.MapPath(GlobalSettings.StorageDirectory) + @"\" + guid.ToString() + ".xml"; + if (XmlDoc != null) + { + FileStream stream = File.Open(fileName, FileMode.Create); + StreamWriter writer = new StreamWriter(stream); + writer.WriteLine(XmlDoc.OuterXml); + writer.Close(); + stream.Close(); + message.Attachments.Add(new System.Net.Mail.Attachment(fileName)); + } + System.Net.Mail.SmtpClient smtpClient = new System.Net.Mail.SmtpClient(); + + try + { + smtpClient.Send(message); + if (Debug == "true") + { + HttpContext.Current.Response.Write(string.Concat(new string[] { "" })); + } + HttpContext.Current.Trace.Write("sendMail", string.Concat(new string[] { "Mail send from ", message.From.Address, " to ", message.To[0].Address, " through ", GlobalSettings.SmtpServer })); + } + catch (Exception exception) + { + HttpContext.Current.Trace.Warn("sendMail", string.Concat(new string[] { "Error sending mail from ", message.From.Address, " to ", message.To[0].Address, " through ", GlobalSettings.SmtpServer, "." }), exception); + if (Debug == "true") + { + string exp = ""; + while (exception.InnerException != null) + { + exp = exp + "--------------------------------\n"; + exp = exp + exception.InnerException.ToString() + ", \n"; + exception = exception.InnerException; + } + HttpContext.Current.Response.Write(string.Concat(new string[] { "" })); + } + return; + } + finally + { + if (XmlDoc != null) + { + File.Delete(fileName); + } + } + } + + + } +} diff --git a/components/standardFormhandlers/memberLogoff.cs b/components/standardFormhandlers/memberLogoff.cs new file mode 100644 index 0000000000..ed41973763 --- /dev/null +++ b/components/standardFormhandlers/memberLogoff.cs @@ -0,0 +1,50 @@ +using System; +using System.Xml; + +namespace umbraco.standardFormhandlers +{ + /// + /// Summary description for memberLogoff. + /// + public class memberLogoff : interfaces.IFormhandler + { + /// + /// Initializes a new instance of the class. + /// + public memberLogoff() + { + } + + #region IFormhandler Members + + private int _redirectID = -1; + + /// + /// Executes the specified formhandler node. + /// + /// The formhandler node. + /// + public bool Execute(XmlNode formhandlerNode) + { + int _currentMemberId = cms.businesslogic.member.Member.CurrentMemberId(); + if (_currentMemberId > 0 ) + cms.businesslogic.member.Member.ClearMemberFromClient(_currentMemberId); + return true; + } + + /// + /// Gets the redirect ID. + /// + /// The redirect ID. + public int redirectID + { + get + { + // TODO: Add formMail.redirectID getter implementation + return _redirectID; + } + } + + #endregion + } +} diff --git a/components/standardFormhandlers/umbraco.standardFormhandlers.csproj b/components/standardFormhandlers/umbraco.standardFormhandlers.csproj new file mode 100644 index 0000000000..93cc0e72a1 --- /dev/null +++ b/components/standardFormhandlers/umbraco.standardFormhandlers.csproj @@ -0,0 +1,134 @@ + + + Local + 9.0.30729 + 2.0 + {F58B68F8-AB7F-4559-A37F-6A00AD86365E} + Debug + AnyCPU + + + + + umbraco.standardFormhandlers + + + JScript + Grid + IE50 + false + Library + standardFormhandlers + OnBuildSuccess + + + + + + + SAK + SAK + SAK + SAK + 2.0 + + + ..\..\umbraco\presentation\bin\ + false + 285212672 + false + + + DEBUG;TRACE + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + ..\..\umbraco\presentation\bin\ + false + 285212672 + false + + + TRACE + ..\..\umbraco\presentation\bin\umbraco.standardFormhandlers.XML + false + 4096 + false + + + true + false + false + false + 4 + none + prompt + AnyCPU + + + + System + + + System.Data + + + System.Web + + + System.XML + + + + + Code + + + Code + + + Code + + + Code + + + + + {E469A9CE-1BEC-423F-AC44-713CD72457EA} + umbraco.businesslogic + + + {CCD75EC3-63DB-4184-B49D-51C1DD337230} + umbraco.cms + + + {511F6D8D-7717-440A-9A57-A507E9A8B27F} + umbraco.interfaces + + + {651E1350-91B6-44B7-BD60-7207006D7003} + umbraco.presentation + + + + + + + + + + \ No newline at end of file diff --git a/components/standardFormhandlers/umbraco.standardFormhandlers.csproj.vspscc b/components/standardFormhandlers/umbraco.standardFormhandlers.csproj.vspscc new file mode 100644 index 0000000000..feffdecaa4 --- /dev/null +++ b/components/standardFormhandlers/umbraco.standardFormhandlers.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/components/standardFormhandlers/validateLogin.cs b/components/standardFormhandlers/validateLogin.cs new file mode 100644 index 0000000000..a4811b092c --- /dev/null +++ b/components/standardFormhandlers/validateLogin.cs @@ -0,0 +1,60 @@ +using System; +using System.Xml; + +namespace umbraco.standardFormhandlers +{ + /// + /// Summary description for validateLogin. + /// + public class validateLogin : interfaces.IFormhandler + { + /// + /// Initializes a new instance of the class. + /// + public validateLogin() + { + } + + #region IFormhandler Members + + private int _redirectID = -1; + + /// + /// Executes the specified formhandler node. + /// + /// The formhandler node. + /// + public bool Execute(XmlNode formhandlerNode) + { + bool temp = false; + if (helper.Request("umbracoMemberLogin") != "" && helper.Request("umbracoMemberPassword") != "") + { + cms.businesslogic.member.Member m = cms.businesslogic.member.Member.GetMemberFromLoginNameAndPassword(helper.Request("umbracoMemberLogin"), helper.Request("umbracoMemberPassword")); + if (m != null) + { + System.Web.HttpContext.Current.Trace.Write("validateLogin", "Member found..."); + cms.businesslogic.member.Member.AddMemberToCache(m); + temp = true; + } else + System.Web.HttpContext.Current.Trace.Write("validateLogin", "No member found..."); + } else + System.Web.HttpContext.Current.Trace.Write("validateLogin", "No login or password requested..."); + return temp; + } + + /// + /// Gets the redirect ID. + /// + /// The redirect ID. + public int redirectID + { + get + { + // TODO: Add formMail.redirectID getter implementation + return _redirectID; + } + } + + #endregion + } +} diff --git a/components/umbraco.controls/CodeArea.cs b/components/umbraco.controls/CodeArea.cs new file mode 100644 index 0000000000..06e2ce8325 --- /dev/null +++ b/components/umbraco.controls/CodeArea.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Web; +using System.Web.SessionState; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.HtmlControls; + +namespace umbraco.uicontrols { + + public class CodeArea : System.Web.UI.WebControls.TextBox { + + public CodeArea() { + this.Attributes.Add("class", "codepress"); + this.Attributes.Add("onclick", "storeCaret(this)"); + this.Attributes.Add("onselect", "storeCaret(this)"); + this.Attributes.Add("onkeyup", "storeCaret(this)"); + + this.Attributes.Add("wrap", "off"); + this.TextMode = TextBoxMode.MultiLine; + } + + + public bool AutoResize { get; set ; } + public int OffSetX { get; set; } + public int OffSetY { get; set; } + + protected override void OnInit(System.EventArgs e) { + + + //this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "CodeAreaStyles", ""); + this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "CodeAreaJavaScript", ""); + // this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "CodeAreaJavaScript_new", ""); + + + } + + protected override void Render(HtmlTextWriter writer) { + base.Render(writer); + + string jsEventCode = @""; + + writer.WriteLine(jsEventCode); + + //this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "CodeAreaEvents", jsEventCode); + } + } + +} \ No newline at end of file diff --git a/components/umbraco.controls/MenuButtonI.cs b/components/umbraco.controls/MenuButtonI.cs new file mode 100644 index 0000000000..fdb9904d40 --- /dev/null +++ b/components/umbraco.controls/MenuButtonI.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Web; +using System.Web.SessionState; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.HtmlControls; + +namespace umbraco.uicontrols { + public class MenuImageButton : System.Web.UI.WebControls.ImageButton, MenuIconI { + private string _OnClickCommand = ""; + + + public override string ID { + get { return base.ID; } + set { base.ID = value; } + } + + public string AltText { + get { return this.AlternateText; } + set { + this.AlternateText = value; + this.Attributes.Add("title", value); + } + } + public int IconWidth { + get { return (int)this.Width.Value; } + set { this.Width = value; } + } + public int IconHeight { + get { return (int)this.Height.Value; } + set { this.Height = value; } + } + + + public string ImageURL { + get { return base.ImageUrl; } + set { base.ImageUrl = value; } + } + + public string OnClickCommand { + get { return _OnClickCommand; } + set { _OnClickCommand = value; } + } + + protected override void OnLoad(System.EventArgs EventArguments) { + SetupClientScript(); + + this.Width = Unit.Pixel(22); + this.Height = Unit.Pixel(23); + this.Style.Add("border", "0px"); + this.Attributes.Add("class", "editorIcon"); + this.Attributes.Add("onMouseover", "this.className='editorIconOver'"); + this.Attributes.Add("onMouseout", "this.className='editorIcon'"); + this.Attributes.Add("onMouseup", "this.className='editorIconOver'"); + this.Attributes.Add("onMouseDown", "this.className='editorIconDown'"); + + if (_OnClickCommand != "") { + this.Attributes.Add("onClick", OnClickCommand); + } + } + + private void SetupClientScript() { + this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "MENUICONCSS", ""); + } + } +} \ No newline at end of file diff --git a/components/umbraco.controls/MenuIcon.cs b/components/umbraco.controls/MenuIcon.cs new file mode 100644 index 0000000000..440ab984f8 --- /dev/null +++ b/components/umbraco.controls/MenuIcon.cs @@ -0,0 +1,73 @@ +using System.ComponentModel; +using System.Web.UI; + +namespace umbraco.uicontrols { + internal class MenuIcon : System.Web.UI.WebControls.Image, MenuIconI { + private string _OnClickCommand = ""; + private string _AltText = "init"; + + + public string ID1 { + get { return this.ID; } + set { this.ID = value; } + } + + public string AltText { + get { return this.AlternateText; } + set { + _AltText = value; + this.AlternateText = value; + this.Attributes.Add("title", value); + } + } + public int IconWidth { + get { return (int)this.Width.Value; } + set { this.Width = value; } + } + public int IconHeight { + get { return (int)this.Height.Value; } + set { this.Height = value; } + } + + public string ImageURL { + get { return this.ImageUrl; } + set { this.ImageUrl = value; } + } + + public string OnClickCommand { + get { return _OnClickCommand; } + set { _OnClickCommand = value; } + } + + protected override void OnLoad(System.EventArgs EventArguments) { + SetupClientScript(); + + // NH 17-01-2007. Trying to avoid inline styling soup + // Me.Width = WebControls.Unit.Pixel(22) + // Me.Height = WebControls.Unit.Pixel(23) + //Me.Style.Add("border", "0px") + this.Attributes.Add("class", "editorIcon"); + this.Attributes.Add("onMouseover", "this.className='editorIconOver'"); + string holder = ""; +// if (this.ID != "") { + //holder = this.ID.Substring(0, this.ID.LastIndexOf("_")) + "_menu"; + this.Attributes.Add("onMouseout", "hoverIconOut('" + holder + "','" + this.ID + "');"); + this.Attributes.Add("onMouseup", "hoverIconOut('" + holder + "','" + this.ID + "');"); +// } else { + this.Attributes.Add("onMouseout", "this.className='editorIcon'"); + this.Attributes.Add("onMouseup", "this.className='editorIcon'"); +// } + this.Attributes.Add("onMouseDown", "this.className='editorIconDown'"); + this.AlternateText = _AltText; + this.Attributes.Add("title", _AltText); + + if (_OnClickCommand != "") { + this.Attributes.Add("onClick", OnClickCommand); + } + } + + private void SetupClientScript() { + this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "MENUICONCSS", ""); + } + } +} \ No newline at end of file diff --git a/components/umbraco.controls/MenuIconClass.cs b/components/umbraco.controls/MenuIconClass.cs new file mode 100644 index 0000000000..e45b424bbc --- /dev/null +++ b/components/umbraco.controls/MenuIconClass.cs @@ -0,0 +1,39 @@ +namespace umbraco.uicontrols { + public class MenuIconClass : MenuIconI { + + private string _id; + private string _imageURL; + private string _onClickCommand; + private string _AltText; + private int _width; + private int _height; + + + public string ID { + get { return _id; } + set { _id = value; } + } + + public string AltText { + get { return _AltText; } + set { _AltText = value; } + } + public int IconWidth { + get { return _width; } + set { _width = value; } + } + public int IconHeight { + get { return _height; } + set { _height = value; } + } + public string ImageURL { + get { return _imageURL; } + set { _imageURL = value; } + } + + public string OnClickCommand { + get { return _onClickCommand; } + set { _onClickCommand = value; } + } + } +} \ No newline at end of file diff --git a/components/umbraco.controls/MenuIconI.cs b/components/umbraco.controls/MenuIconI.cs new file mode 100644 index 0000000000..7c4aff85da --- /dev/null +++ b/components/umbraco.controls/MenuIconI.cs @@ -0,0 +1,28 @@ +namespace umbraco.uicontrols { + public interface MenuIconI { + string ImageURL { + get; + set; + } + string ID { + get; + set; + } + string OnClickCommand { + get; + set; + } + string AltText { + get; + set; + } + int IconWidth { + get; + set; + } + int IconHeight { + get; + set; + } + } +} diff --git a/components/umbraco.controls/Panel.cs b/components/umbraco.controls/Panel.cs new file mode 100644 index 0000000000..2382d62011 --- /dev/null +++ b/components/umbraco.controls/Panel.cs @@ -0,0 +1,137 @@ +using System; +using System.Collections; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Web; +using System.Web.SessionState; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.HtmlControls; + +namespace umbraco.uicontrols { + public class UmbracoPanel : System.Web.UI.WebControls.Panel { + private ScrollingMenu _menu = new ScrollingMenu(); + + public UmbracoPanel() { + + } + + protected override void OnInit(EventArgs e) { + setupMenu(); + } + + protected override void OnLoad(System.EventArgs EventArguments) { + helper.AddLinkToHeader("PanelStyles", "/umbraco_client/panel/style.css", this.Page); + helper.AddScriptToHeader("PanelScript", "/umbraco_client/panel/javascript.js", this.Page); + // this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "PanelStyles", ""); +// this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "PanelScript", ""); + + _menu.Visible = hasMenu; + + if(_autoResize) + this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "PanelEvents", ""); + //this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "PanelEvents", ""); + } + + private bool _hasMenu = false; + private string _StatusBarText = ""; + private string _text; + private bool _autoResize = true; + + public bool hasMenu { + get { return _hasMenu; } + set { _hasMenu = value; } + } + + public bool AutoResize { + get { return _autoResize; } + set { _autoResize = value; } + } + + public string Text { + get { + if (_text == "") { + _text = " "; + } + return _text; + + } + set { _text = value; } + } + + public string StatusBarText { + get { return _StatusBarText; } + set { _StatusBarText = value; } + } + + public ScrollingMenu Menu { + get { return _menu; } + } + + internal void setupMenu() { + _menu.ID = this.ID + "_menu"; + if (this.Width.Value < 20) + this.Width = Unit.Pixel(24); + _menu.Width = (int)Unit.Pixel((int)this.Width.Value - 20).Value; + this.Controls.Add(_menu); + + } + + protected override void Render(System.Web.UI.HtmlTextWriter writer) { + base.CreateChildControls(); + + try { + if (System.Web.HttpContext.Current == null) { + writer.WriteLine("Number of child controls : " + this.Controls.Count); + } + writer.WriteLine("
"); + writer.WriteLine("
"); + writer.WriteLine("

" + this.Text + "

"); + writer.WriteLine("
"); + writer.WriteLine("
"); + + if (this.hasMenu) { + writer.WriteLine("
"); + _menu.RenderControl(writer); + writer.WriteLine("
"); + } + + int upHeight = (int)this.Height.Value - 46; + int upWidth = (int)this.Width.Value - 5; + + if (this.hasMenu) + upHeight = upHeight - 34; + + writer.WriteLine("
"); + + string styleString = ""; + + foreach (string key in this.Style.Keys) { + styleString += key + ":" + this.Style[key] + ";"; + } + + writer.WriteLine("
"); + foreach (Control c in this.Controls) { + if (!(c.ID == _menu.ID)) { + c.RenderControl(writer); + } + } + + writer.WriteLine("
"); + writer.WriteLine("
"); + writer.WriteLine("
"); + writer.WriteLine("

" + this.StatusBarText + "

"); + writer.WriteLine("
"); + + /* + if(_autoResize) + writer.WriteLine(""); + */ + + } catch (Exception ex) { + this.Page.Trace.Warn("Error rendering umbracopanel control" + ex.ToString()); + } + } + } +} \ No newline at end of file diff --git a/components/umbraco.controls/Properties/AssemblyInfo.cs b/components/umbraco.controls/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..5cda516de5 --- /dev/null +++ b/components/umbraco.controls/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("umbraco.controls")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("netMedia.dk ApS")] +[assembly: AssemblyProduct("umbraco.controls")] +[assembly: AssemblyCopyright("Copyright © netMedia.dk ApS 2008")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("1292737a-7e2d-464a-9850-9380792f668e")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/components/umbraco.controls/Property.cs b/components/umbraco.controls/Property.cs new file mode 100644 index 0000000000..06aaecaddb --- /dev/null +++ b/components/umbraco.controls/Property.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace umbraco.uicontrols { + public class PropertyPanel : System.Web.UI.WebControls.Panel { + public PropertyPanel() { + + } + + private string m_Text = string.Empty; + public string Text + { + get { return m_Text; } + set { m_Text = value; } + } + + + protected override void OnLoad(System.EventArgs EventArguments) { + } + + protected override void Render(System.Web.UI.HtmlTextWriter writer) { + + this.CreateChildControls(); + string styleString = ""; + + foreach (string key in this.Style.Keys) { + styleString += key + ":" + this.Style[key] + ";"; + } + + writer.WriteLine("
"); + if (m_Text != string.Empty) { + writer.WriteLine("
" + m_Text + "
"); + writer.WriteLine("
"); + } + + try { + this.RenderChildren(writer); + } catch (Exception ex) { + writer.WriteLine("Error creating control
"); + writer.WriteLine(ex.ToString()); + } + + if (m_Text != string.Empty) + writer.WriteLine("
"); + + writer.WriteLine("
"); + + + } + + } + +} \ No newline at end of file diff --git a/components/umbraco.controls/ScrollingMenu.cs b/components/umbraco.controls/ScrollingMenu.cs new file mode 100644 index 0000000000..cb186df7a6 --- /dev/null +++ b/components/umbraco.controls/ScrollingMenu.cs @@ -0,0 +1,166 @@ +using System; +using System.Collections; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Web; +using System.Web.SessionState; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.HtmlControls; + +namespace umbraco.uicontrols { + [ToolboxData("<{0}:ScrollingMenu runat=server>")] + public class ScrollingMenu : System.Web.UI.WebControls.WebControl { + private ArrayList Icons = new ArrayList(); + private string iconIds; + private int extraMenuWidth = 0; + private string _ClientFilesPath = "/umbraco_client/scrollingmenu/"; + + public MenuIconI NewIcon(int Index) { + MenuIcon Icon = new MenuIcon(); + Icons.Insert(Index, Icon); + return Icon; + } + + public MenuIconI NewIcon() { + MenuIcon icon = new MenuIcon(); + Icons.Add(icon); + return icon; + } + + public MenuImageButton NewImageButton() { + MenuImageButton icon = new MenuImageButton(); + Icons.Add(icon); + return icon; + } + + public MenuImageButton NewImageButton(int Index) { + MenuImageButton icon = new MenuImageButton(); + Icons.Insert(Index, icon); + return icon; + } + + public System.Web.UI.WebControls.DropDownList NewDropDownList() { + DropDownList Icon = new DropDownList(); + Icons.Add(Icon); + return Icon; + } + public void NewElement(string ElementName, string ElementId, string ElementClass, int ExtraWidth) { + Icons.Add(new LiteralControl("<" + ElementName + " class=\"" + ElementClass + "\" id=\"" + ElementId + "\">")); + extraMenuWidth = extraMenuWidth + ExtraWidth; + } + + public void InsertSplitter() { + Splitter icon = new Splitter(); + Icons.Add(icon); + } + public void InsertSplitter(int Index) { + Splitter icon = new Splitter(); + Icons.Insert(Index, icon); + } + + + protected override void OnLoad(System.EventArgs EventArguments) { + if (base.Visible) + { + SetupMenu(); + SetupClientScript(); + } + } + + private void SetupClientScript() { + helper.AddLinkToHeader("SCROLLINGMENUCSS", "/umbraco_client/scrollingmenu/style.css", this.Page); + helper.AddScriptToHeader("SCROLLINGMENUJS", "/umbraco_client/scrollingmenu/javascript.js", this.Page); +// this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "SCROLLINGMENUCSS", ""); +// this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "SCROLLINGMENUJS", ""); + } + + private System.Web.UI.WebControls.Image scrollImage() { + System.Web.UI.WebControls.Image functionReturnValue = null; + functionReturnValue = new System.Web.UI.WebControls.Image(); + functionReturnValue.Width = Unit.Pixel(7); + functionReturnValue.Height = Unit.Pixel(20); + functionReturnValue.BorderWidth = Unit.Pixel(0); + functionReturnValue.Attributes.Add("align", "absMiddle"); + functionReturnValue.CssClass = "editorArrow"; + functionReturnValue.Attributes.Add("onMouseOut", "this.className = 'editorArrow'; scrollStop();"); + return functionReturnValue; + } + + private void SetupMenu() { + // Calculate innerlayer max width 32 pixel per icon + int ScrollingLayerWidth = Icons.Count * 26 + extraMenuWidth; + + Table Container = new Table(); + Container.ID = String.Format("{0}_tableContainer", this.ID); + TableRow tr = new TableRow(); + tr.ID = String.Format("{0}_tableContainerRow", this.ID); + Container.Rows.Add(tr); + + // // scroll-left image + TableCell td = new TableCell(); + td.ID = String.Format("{0}_tableContainerLeft", this.ID); + System.Web.UI.WebControls.Image scrollL = scrollImage(); + scrollL.ImageUrl = _ClientFilesPath + "images/arrawBack.gif"; + scrollL.Attributes.Add("onMouseOver", "this.className = 'editorArrowOver'; scrollR('" + this.ClientID + "_sl','" + this.ClientID + "_slh'," + ScrollingLayerWidth + ");"); + td.Controls.Add(scrollL); + tr.Cells.Add(td); + + // // Menulayers + td = new TableCell(); + td.ID = String.Format("{0}_tableContainerButtons", this.ID); + + HtmlGenericControl outerLayer = new HtmlGenericControl(); + outerLayer.TagName = "div"; + outerLayer.ID = this.ID + "_slh"; + outerLayer.Attributes.Add("class", "slh"); + outerLayer.Style.Add("height", "26px"); + string tmp = this.Width.ToString(); + + outerLayer.Style.Add("width", (this.Width.Value - 18).ToString() + "px"); + td.Controls.Add(outerLayer); + + HtmlGenericControl menuLayer = new HtmlGenericControl(); + menuLayer.TagName = "div"; + menuLayer.ID = this.ID + "_sl"; + menuLayer.Style.Add("top", "0px"); + menuLayer.Style.Add("left", "0px"); + menuLayer.Attributes.Add("class", "sl"); + menuLayer.Style.Add("height", "26px"); + menuLayer.Style.Add("width", ScrollingLayerWidth + "px"); + + HtmlGenericControl nobr = new HtmlGenericControl(); + nobr.TagName = "nobr"; + nobr.ID = String.Format("{0}_nobr", this.ID); + menuLayer.Controls.Add(nobr); + + // // add all icons to the menu layer + foreach (Control item in Icons) { + menuLayer.Controls.Add(item); + + if (item.ID != "") { + iconIds = iconIds + item.ID + ","; + } + } + + outerLayer.Controls.Add(new LiteralControl("")); + + outerLayer.Controls.Add(menuLayer); + + tr.Cells.Add(td); + + // // scroll-right image + td = new TableCell(); + td.ID = String.Format("{0}_tableContainerRight", this.ID); + System.Web.UI.WebControls.Image scrollR = scrollImage(); + scrollR.ImageUrl = _ClientFilesPath + "images/arrowForward.gif"; + scrollR.Attributes.Add("onMouseOver", "this.className = 'editorArrowOver'; scrollL('" + this.ClientID + "_sl','" + this.ClientID + "_slh'," + ScrollingLayerWidth + ");"); + td.Controls.Add(scrollR); + tr.Cells.Add(td); + + this.Controls.Add(Container); + } + + } +} \ No newline at end of file diff --git a/components/umbraco.controls/Splitter.cs b/components/umbraco.controls/Splitter.cs new file mode 100644 index 0000000000..f1cdfb971d --- /dev/null +++ b/components/umbraco.controls/Splitter.cs @@ -0,0 +1,14 @@ +using System.ComponentModel; +using System.Web.UI; + +namespace umbraco.uicontrols { + internal class Splitter : System.Web.UI.WebControls.Image { + + protected override void OnLoad(System.EventArgs EventArguments) { + this.Height = System.Web.UI.WebControls.Unit.Pixel(21); + this.Style.Add("border", "0px"); + this.Attributes.Add("class", "editorIconSplit"); + this.ImageUrl = "/umbraco_client/menuicon/images/split.gif"; + } + } +} \ No newline at end of file diff --git a/components/umbraco.controls/TabPage.cs b/components/umbraco.controls/TabPage.cs new file mode 100644 index 0000000000..ce11d37f84 --- /dev/null +++ b/components/umbraco.controls/TabPage.cs @@ -0,0 +1,108 @@ +using System; +using System.Collections; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Web; +using System.Web.SessionState; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.HtmlControls; + +namespace umbraco.uicontrols { + public class TabPage : System.Web.UI.WebControls.WebControl { + // Ensure that a TabPage cannot be instatiated outside + // this assembly -> New instances of a tabpage can only be retrieved through the tabview + private bool _hasMenu = true; + private ScrollingMenu _Menu = new ScrollingMenu(); + protected LiteralControl ErrorHeaderControl = new LiteralControl(); + private ValidationSummary _vs = new ValidationSummary(); + private Control _tempErr = new Control(); + internal TabPage() { + + } + + public ValidationSummary ValidationSummaryControl + { + get { return _vs; } + } + + public string ErrorHeader { get; set; } + public string CloseCaption { get; set; } + public Control ErrorControl { get { return _tempErr; } } + + protected override void OnLoad(EventArgs e) { + if (this.HasMenu) { + Menu.Width = System.Web.UI.WebControls.Unit.Pixel((int)this.Width.Value - 12); + _Menu.ID = this.ID + "_menu"; + this.Controls.Add(_Menu); + } + } + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + _vs.ShowSummary = true; + _vs.Attributes.Remove("style"); + _vs.Style.Clear(); + _vs.ForeColor = new Color(); + _vs.ID = String.Format("{0}_validationSummary", this.ID); + + // Add error pane + _tempErr.Visible = false; + _tempErr.ID = String.Format("{0}_errorPaneContainer", this.ID); + _tempErr.Controls.Add(new LiteralControl("

")); + _tempErr.Controls.Add(ErrorHeaderControl); + _tempErr.Controls.Add(new LiteralControl("

")); + _tempErr.Controls.Add(_vs); + _tempErr.Controls.Add(new LiteralControl("

")); + + this.Controls.Add(_tempErr); + } + + + public ScrollingMenu Menu { + get { return _Menu; } + } + + public bool HasMenu { + get { return _hasMenu; } + set { _hasMenu = value; } + } + + protected override void Render(System.Web.UI.HtmlTextWriter writer) { + ErrorHeaderControl.Text = ErrorHeader; + CreateChildControls(); + writer.WriteLine("
"); + if (HasMenu) { + writer.WriteLine(""); + } + int ScrollingLayerHeight = (int)((System.Web.UI.WebControls.WebControl)this.Parent).Height.Value - 22; + int ScrollingLayerWidth = (int)((System.Web.UI.WebControls.WebControl)this.Parent).Width.Value; + if (HasMenu) + ScrollingLayerHeight = ScrollingLayerHeight - 28; + writer.WriteLine("
"); + + string styleString = ""; + foreach (string key in this.Style.Keys) { + styleString += key + ":" + this.Style[key] + ";"; + } + + writer.WriteLine("
"); + + _tempErr.RenderControl(writer); + + foreach (System.Web.UI.Control C in this.Controls) { + if (C.ClientID != _Menu.ClientID && C.ClientID != _tempErr.ClientID ) { + C.RenderControl(writer); + } + } + writer.WriteLine("
"); + writer.WriteLine("
"); + writer.WriteLine("
"); + } + } +} diff --git a/components/umbraco.controls/TabView.cs b/components/umbraco.controls/TabView.cs new file mode 100644 index 0000000000..ec6cc3484c --- /dev/null +++ b/components/umbraco.controls/TabView.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Web; +using System.Web.SessionState; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.HtmlControls; + +namespace umbraco.uicontrols { + public class TabView : System.Web.UI.WebControls.WebControl { + private HtmlInputHidden tb = new HtmlInputHidden(); + private ArrayList Tabs = new ArrayList(); + private ArrayList Panels = new ArrayList(); + private string status = ""; + + public ArrayList GetPanels() { + return Panels; + } + + public TabPage NewTabPage(string text) { + Tabs.Add(text); + TabPage tp = new TabPage(); + tp.Width = this.Width; + tp.ID = this.ID + "_tab0" + (Panels.Count + 1) + "layer"; + Panels.Add(tp); + this.Controls.Add(tp); + return tp; + } + + + public string Status { + get { return status; } + set { status = value; } + } + + private bool _autoResize = true; + public bool AutoResize { + get { return _autoResize; } + set { _autoResize = value; } + } + + private string ActiveTabId { + get { + if (this.Parent.Page.IsPostBack) { + return this.Parent.Page.Request.Form[this.ClientID + "_activetab"]; + } + return this.ClientID + "_tab01"; + } + } + + protected override void OnPreRender(EventArgs e) { + base.OnPreRender(e); + SetupClientScript(); + } + + private void SetupClientScript() { + this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "TabviewCss", ""); + this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "TabviewJs", ""); + + string strTmp = ""; + for (int i = 1; i <= Tabs.Count; i++) { + if (i > 1) + strTmp += ","; + strTmp += "\"" + this.ClientID + "_tab0" + i + "\""; + } + this.Page.ClientScript.RegisterStartupScript(this.GetType(), this.ClientID + "TabCollection", ""); + this.Page.ClientScript.RegisterStartupScript(this.GetType(), this.ClientID + "TabviewStartUp", ""); + + if (_autoResize) + this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "TabviewEvents", ""); + } + + protected override void Render(HtmlTextWriter writer) { + writer.WriteLine("
"); + writer.WriteLine("
"); + writer.WriteLine(" "); + writer.WriteLine("
"); + writer.WriteLine("
"); + this.RenderChildren(writer); + writer.WriteLine("\t
"); + writer.WriteLine("\t"); + writer.WriteLine("
"); + writer.WriteLine(""); + } + } +} \ No newline at end of file diff --git a/components/umbraco.controls/dateTimePicker.cs b/components/umbraco.controls/dateTimePicker.cs new file mode 100644 index 0000000000..c40a18bf01 --- /dev/null +++ b/components/umbraco.controls/dateTimePicker.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web; +using System.Web.UI; +using System.Web.UI.WebControls; + +namespace umbraco.controls { + public class calendar : PlaceHolder { + + public bool ShowTime { get; set; } + public DateTime? SelectedDateTime { get; set; } + + private DateTime _date; + + public TextBox tb_hours = new TextBox(); + public TextBox tb_minutes = new TextBox(); + public TextBox tb_date = new TextBox(); + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + } + + protected override void OnPreRender(EventArgs e) + { + base.OnPreRender(e); + _date = System.DateTime.Now; + + + + if (SelectedDateTime.HasValue) + _date = SelectedDateTime.Value; + + if (ShowTime) { + tb_minutes.Columns = 2; + tb_hours.Columns = 2; + + tb_hours.Text = _date.Hour.ToString(); + tb_minutes.Text = fixTime(_date.Minute); + Literal lit = new Literal(); + lit.Text = ":"; + + this.Controls.Add(tb_hours); + this.Controls.Add(lit); + this.Controls.Add(tb_minutes); + } + + tb_date.ID = base.ID + "_datePickField"; + this.Controls.Add(tb_date); + + AjaxControlToolkit.CalendarExtender cal = new AjaxControlToolkit.CalendarExtender(); + cal.TargetControlID = tb_date.UniqueID; + cal.SelectedDate = _date; + this.Controls.Add(cal); + } + + private static string fixTime(int input){ + if (input.ToString().Length == 1) + return "0" + input.ToString(); + else + return input.ToString(); + } + + + + } + + +} diff --git a/components/umbraco.controls/feedback.cs b/components/umbraco.controls/feedback.cs new file mode 100644 index 0000000000..eb38cd9914 --- /dev/null +++ b/components/umbraco.controls/feedback.cs @@ -0,0 +1,54 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace umbraco.uicontrols { + public class Feedback : System.Web.UI.WebControls.Panel { + + public Feedback() { + + } + + protected override void OnInit(EventArgs e) { + } + + protected override void OnLoad(System.EventArgs EventArguments) { + } + + private bool _hasMenu = false; + private string _StatusBarText = ""; + + public feedbacktype type { get; set; } + + private string _text = string.Empty; + public string Text { + get { + + return _text; + + } + set { _text = value; } + } + + public enum feedbacktype{ + notice, + error, + success + } + + protected override void Render(System.Web.UI.HtmlTextWriter writer) { + if (_text != string.Empty) { + base.CreateChildControls(); + + string styleString = ""; + foreach (string key in this.Style.Keys) { + styleString += key + ":" + this.Style[key] + ";"; + } + + writer.WriteLine("

"); + writer.WriteLine(_text); + writer.WriteLine("

"); + } + } + } +} \ No newline at end of file diff --git a/components/umbraco.controls/helper.cs b/components/umbraco.controls/helper.cs new file mode 100644 index 0000000000..d80ed49845 --- /dev/null +++ b/components/umbraco.controls/helper.cs @@ -0,0 +1,46 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.HtmlControls; + +namespace umbraco.uicontrols +{ + public class helper + { + public static void AddLinkToHeader(string key, string src, Page page) + { + if (page.Header != null) + { + if (!page.ClientScript.IsClientScriptBlockRegistered(page.GetType(), key)) + { + page.ClientScript.RegisterClientScriptBlock(page.GetType(), key, String.Empty); + ((HtmlHead)page.Header).Controls.Add(new LiteralControl(String.Format("", src))); + } + } + else + { + // can't add to header, will failback to a simple register script + page.ClientScript.RegisterClientScriptBlock(page.GetType(), key, String.Format("", src)); + } + } + + public static void AddScriptToHeader(string key, string src, Page page) + { + if (page.Header != null) + { + if (!page.ClientScript.IsClientScriptBlockRegistered(page.GetType(), key)) + { + page.ClientScript.RegisterClientScriptBlock(page.GetType(), key, String.Empty); + ((HtmlHead)page.Header).Controls.Add(new LiteralControl(String.Format("", src))); + } + } + else + { + // can't add to header, will failback to a simple register script + page.ClientScript.RegisterClientScriptBlock(page.GetType(), key, String.Format("", src)); + } + } + } +} diff --git a/components/umbraco.controls/pane.cs b/components/umbraco.controls/pane.cs new file mode 100644 index 0000000000..dba7a21471 --- /dev/null +++ b/components/umbraco.controls/pane.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Web; +using System.Web.SessionState; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.HtmlControls; + +namespace umbraco.uicontrols { + public class Pane : System.Web.UI.WebControls.Panel { + + private TableRow tr = new TableRow(); + private TableCell td = new TableCell(); + private Table tbl = new Table(); + + public Pane() { + + } + + private string m_Text = string.Empty; + public string Text + { + get { return m_Text; } + set { m_Text = value; } + } + + + public void addProperty(string Caption, Control C) { + /* + tr = new TableRow(); + td = new TableCell(); + td.Text = Caption; + td.Attributes.Add("width", "15%"); + td.Attributes.Add("valign", "top"); + td.Attributes.Add("class", "propertyHeader"); + tr.Cells.Add(td); + + td = new TableCell(); + td.Attributes.Add("class", "propertyContent"); + td.Controls.Add(C); + tr.Cells.Add(td); + + tbl.Rows.Add(tr); + if (!this.Controls.Contains(tbl)) { + this.Controls.Add(tbl); + }*/ + PropertyPanel pp = new PropertyPanel(); + pp.Controls.Add(C); + pp.Text = Caption; + + this.Controls.Add(pp); + } + + public void addProperty(Control ctrl) { + /* + tr = new TableRow(); + td = new TableHeaderCell(); + td.ColumnSpan = 2; + td.Attributes.Add("width", "100%"); + td.Attributes.Add("valign", "top"); + td.Attributes.Add("class", "propertyContent"); + td.Controls.Add(ctrl); + tr.Cells.Add(td); + tbl.Rows.Add(tr); + if (!this.Controls.Contains(tbl)) { + this.Controls.Add(tbl); + } + */ + + PropertyPanel pp = new PropertyPanel(); + pp.Controls.Add(ctrl); + this.Controls.Add(pp); + } + + + protected override void OnLoad(System.EventArgs EventArguments) { + this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "propertypanestyles", ""); + } + + protected override void Render(System.Web.UI.HtmlTextWriter writer) { + + this.CreateChildControls(); + string styleString = ""; + + foreach (string key in this.Style.Keys) { + styleString += key + ":" + this.Style[key] + ";"; + } + + if (!string.IsNullOrEmpty(m_Text)) + writer.WriteLine("

" + m_Text + "

"); + + writer.WriteLine("
"); + writer.WriteLine("
"); + + try { + this.RenderChildren(writer); + } catch (Exception ex) { + writer.WriteLine("Error creating control
"); + writer.WriteLine(ex.ToString()); + } + + writer.WriteLine("
-
"); + + } + + } + +} \ No newline at end of file diff --git a/components/umbraco.controls/umbraco.controls.csproj b/components/umbraco.controls/umbraco.controls.csproj new file mode 100644 index 0000000000..70afed58e8 --- /dev/null +++ b/components/umbraco.controls/umbraco.controls.csproj @@ -0,0 +1,80 @@ + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {6EDD2061-82F2-461B-BB6E-879245A832DE} + Library + Properties + umbraco.controls + controls + SAK + SAK + SAK + SAK + + + 2.0 + + + + + true + full + false + ..\..\umbraco\presentation\bin\ + DEBUG;TRACE + prompt + 4 + + + + + pdbonly + true + ..\..\umbraco\presentation\bin\ + TRACE + prompt + 4 + ..\..\umbraco\presentation\bin\controls.XML + + + + False + ..\..\foreign dlls\AjaxControlToolkit.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/umbraco.controls/umbraco.controls.csproj.vspscc b/components/umbraco.controls/umbraco.controls.csproj.vspscc new file mode 100644 index 0000000000..feffdecaa4 --- /dev/null +++ b/components/umbraco.controls/umbraco.controls.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/components/umbraco.webservices/BaseWebService.cs b/components/umbraco.webservices/BaseWebService.cs new file mode 100644 index 0000000000..477c1b1ac2 --- /dev/null +++ b/components/umbraco.webservices/BaseWebService.cs @@ -0,0 +1,187 @@ +using System; +using System.Data; +using System.Configuration; +using System.Web; +using System.Web.Security; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.WebControls.WebParts; +using System.Web.UI.HtmlControls; +using System.Web.Services; +using System.Web.Services.Protocols; + +namespace umbraco.webservices +{ + /// + /// The base-class all webservices should inherit from + /// + /// + /// This class contains all basic methods for authenticating requests. Do not implement these functions yourself. + /// + public abstract class BaseWebService : System.Web.Services.WebService + { + public abstract Services Service + { + get; + } + + /// + /// Enum of services available + /// + public enum Services + { + DocumentService, + FileService, + StylesheetService, + MemberService, + MaintenanceService, + TemplateService, + MediaService + }; + + + /// + /// Gets the umbraco-user from username and password + /// + public umbraco.BusinessLogic.User GetUser(string username, string password) + { + try + { + umbraco.BusinessLogic.User u = + new umbraco.BusinessLogic.User(username, password); + if (u == null || u.Id == -1) + throw new ArgumentException("Invalid username/password"); + + return u; + } + catch + { + return null; + } + } + + + + + /// + /// Standart user-validation. All services must perform this + /// + public void Authenticate(string username, string password) + { + if (!WebservicesEnabled()) throw new Exception("Webservices not enabled"); + if (!UserAuthenticates(username, password)) throw new Exception("The user does not authenticate"); + if (!UserHasAccess(username)) throw new Exception("The user (" + username + ") does not have access to this service"); + } + + [WebMethod] + public bool WebservicesEnabled() + { + return umbraco.UmbracoSettings.Webservices.Enabled; + } + + [WebMethod] + public bool UserAuthenticates(string username, string password) + { + if (!WebservicesEnabled()) throw new Exception("Webservices not enabled"); + return GetUser(username, password) != null; + } + + /// + /// Checks if a user has access to a specific webservice + /// + [WebMethod] + public bool UserHasAccess(string username) + { + switch (Service) + { + case Services.DocumentService: + return -1 < Array.IndexOf(umbraco.UmbracoSettings.Webservices.documentServiceUsers, username); + case Services.FileService: + return -1 < Array.IndexOf(umbraco.UmbracoSettings.Webservices.fileServiceUsers, username); + case Services.StylesheetService: + return -1 < Array.IndexOf(umbraco.UmbracoSettings.Webservices.stylesheetServiceUsers, username); + case Services.MemberService: + return -1 < Array.IndexOf(umbraco.UmbracoSettings.Webservices.memberServiceUsers, username); + case Services.MaintenanceService: + return -1 < Array.IndexOf(umbraco.UmbracoSettings.Webservices.maintenanceServiceUsers, username); + case Services.TemplateService: + return -1 < Array.IndexOf(umbraco.UmbracoSettings.Webservices.templateServiceUsers, username); + case Services.MediaService: + return -1 < Array.IndexOf(umbraco.UmbracoSettings.Webservices.mediaServiceUsers, username); + default: + return false; + } + } + + + + public class FileIO + { + /// + /// Validates a filename. Must be used when user inputs a filename + /// + public static bool ValidFileName(string fileName) + { + // Check if a "levelup" string is included, so they dont move out of the folder + // Dont know if its necesary? + if (fileName.IndexOf("..") > -1) + return false; + return true; + } + + /// + /// Checks if user has access to a specific folder + /// + public static bool FolderAccess(String folderName) + { + // Check if the folder is in "fileServiceFolders" + if (Array.IndexOf(umbraco.UmbracoSettings.Webservices.fileServiceFolders, folderName) > -1) + { + return true; + } + else + { + return false; + } + } + + /// + /// Gets the webservers path for a file + /// + public static string GetFilePath(string folderName, string fileName) + { + string FullPath = GetFolderPath(folderName) + fileName; + return FullPath; + } + + /// + /// Gets the webservers path for a folder + /// + public static string GetFolderPath(string folderName) + { + if (string.IsNullOrEmpty(folderName)) + { + return AppRoot; + } + else + { + return AppRoot + folderName + @"\"; + } + } + + /// + /// Gets the webservers path for the application + /// + public static string AppRoot + { + get + { + return System.Web.HttpContext.Current.Server.MapPath("/"); + } + } + + } + + } + +} diff --git a/components/umbraco.webservices/Common.cs b/components/umbraco.webservices/Common.cs new file mode 100644 index 0000000000..cdd51f6762 --- /dev/null +++ b/components/umbraco.webservices/Common.cs @@ -0,0 +1,108 @@ +//using System; +//using System.Data; +//using System.Configuration; +//using System.Web; +//using System.Web.Security; +//using System.Web.UI; +//using System.Web.UI.WebControls; +//using System.Web.UI.WebControls.WebParts; +//using System.Web.UI.HtmlControls; +//using System.Xml.Serialization; +//using System.Xml; + +//namespace umbraco.webservices +//{ +// public class authentication +// { + + +// /// +// /// Standart user-validation. All services must perform this +// /// +// /// +// /// +// /// +// /// First checks if the webservices are enabled. Then checks if the user is valid +// /// (username and password). Finally it checks if the user has access to the specific service +// /// +// public static void StandartRequestCheck(string username, string password, authentication.EService service) +// { +// // We check if services are enabled and user has access +// if (!umbraco.UmbracoSettings.Webservices.Enabled) +// throw new Exception("webservices not enabled"); + +// // Validating the user +// GetUser(username, password); + +// // Checking if user can use that specific service +// if (!authentication.UserHasAccess(username, service)) +// throw new Exception("user has not access to this service"); +// } + +// /// +// /// Gets the umbraco-user from username and password +// /// +// /// +// /// +// /// +// public static umbraco.BusinessLogic.User GetUser(string username, string password) +// { +// umbraco.BusinessLogic.User user; +// try +// { +// user = new umbraco.BusinessLogic.User(username, password); + +// if (user == null) +// throw new Exception("Incorrect credentials. No user found. Call aborted"); +// } +// catch (Exception ex) +// { +// throw new Exception("Incorrect credentials. Call aborted (error: " + ex.Message + Environment.NewLine + Environment.NewLine + ex.StackTrace + ")"); +// } +// return user; +// } + + +// /// +// /// List of accesible the services +// /// +// public enum EService +// { +// DocumentService, +// FileService, +// StylesheetService, +// MemberService, +// MaintenanceService, +// TemplateService +// }; + +// /// +// /// Checks if a user has access to a specific webservice +// /// +// /// user to check +// /// the webservice to check for +// /// true, if user has access otherwise false +// public static bool UserHasAccess(string username, EService service) +// { +// switch (service) +// { +// case EService.DocumentService: +// return -1 < Array.IndexOf(umbraco.UmbracoSettings.Webservices.documentServiceUsers, username); +// case EService.FileService: +// return -1 < Array.IndexOf(umbraco.UmbracoSettings.Webservices.fileServiceUsers, username); +// case EService.StylesheetService: +// return -1 < Array.IndexOf(umbraco.UmbracoSettings.Webservices.stylesheetServiceUsers, username); +// case EService.MemberService : +// return -1 < Array.IndexOf(umbraco.UmbracoSettings.Webservices.memberServiceUsers, username); +// case EService.MaintenanceService: +// return -1 < Array.IndexOf(umbraco.UmbracoSettings.Webservices.maintenanceServiceUsers, username); +// case EService.TemplateService : +// return -1 < Array.IndexOf(umbraco.UmbracoSettings.Webservices.templateServiceUsers, username); +// default: +// return false; +// } +// } + + +// } +//} diff --git a/components/umbraco.webservices/DocumentService.asmx b/components/umbraco.webservices/DocumentService.asmx new file mode 100644 index 0000000000..dcb6614dda --- /dev/null +++ b/components/umbraco.webservices/DocumentService.asmx @@ -0,0 +1 @@ +<%@ WebService Language="C#" CodeBehind="DocumentService.asmx.cs" Class=umbraco.webservices.documents.documentService %> \ No newline at end of file diff --git a/components/umbraco.webservices/DocumentService.asmx.cs b/components/umbraco.webservices/DocumentService.asmx.cs new file mode 100644 index 0000000000..9c00bb7d63 --- /dev/null +++ b/components/umbraco.webservices/DocumentService.asmx.cs @@ -0,0 +1,429 @@ +using System; +using System.Data; +using System.Web; +using System.Collections; +using System.Web.Services; +using System.Web.Services.Protocols; +using System.ComponentModel; +using System.Xml.Serialization; +using System.Collections.Generic; +using umbraco.cms.businesslogic.web; +using umbraco.cms; +using umbraco; + +namespace umbraco.webservices.documents +{ + + /// + /// Service managing documents in umbraco + /// + [WebService(Namespace = "http://umbraco.org/webservices/")] + [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] + [ToolboxItem(false)] + public class documentService : BaseWebService + { + + override public Services Service + { + get + { + return Services.DocumentService; + } + } + + [WebMethod] + public int create(documentCarrier carrier, string username, string password) + { + Authenticate(username, password); + + // Some validation + if (carrier == null) throw new Exception("No carrier specified"); + if (carrier.ParentID == 0) throw new Exception("Document needs a parent"); + if (carrier.DocumentTypeID == 0) throw new Exception("Documenttype must be specified"); + if (carrier.Id != 0) throw new Exception("ID cannot be specifed when creating. Must be 0"); + if (carrier.Name == null || carrier.Name.Length == 0) carrier.Name = "unnamed"; + + umbraco.BusinessLogic.User user = GetUser(username, password); + + // We get the documenttype + umbraco.cms.businesslogic.web.DocumentType docType = new umbraco.cms.businesslogic.web.DocumentType(carrier.DocumentTypeID); + if (docType == null) throw new Exception("DocumenttypeID " + carrier.DocumentTypeID + " not found"); + + // We create the document + Document newDoc = Document.MakeNew(carrier.Name, docType, user, carrier.ParentID); + newDoc.ReleaseDate = carrier.ReleaseDate; + newDoc.ExpireDate = carrier.ExpireDate; + + // We iterate the properties in the carrier + if (carrier.DocumentProperties != null) + { + foreach (documentProperty updatedproperty in carrier.DocumentProperties) + { + umbraco.cms.businesslogic.property.Property property = newDoc.getProperty(updatedproperty.Key); + if (property == null) throw new Exception("property " + updatedproperty.Key + " was not found"); + property.Value = updatedproperty.PropertyValue; + } + } + + // We check the publishaction and do the appropiate + handlePublishing(newDoc, carrier, user); + + // We return the ID of the document..65 + return newDoc.Id; + } + + [WebMethod] + public documentCarrier read(int id, string username, string password) + { + Authenticate(username, password); + + umbraco.cms.businesslogic.web.Document doc = null; + + try + { + doc = new umbraco.cms.businesslogic.web.Document(id); + } + catch + {} + + if (doc == null) + throw new Exception("Could not load Document with ID: " + id); + + documentCarrier carrier = createCarrier(doc); + return carrier; + } + + + [WebMethod] + public List readList(int parentid, string username, string password) + { + Authenticate(username, password); + + umbraco.cms.businesslogic.web.Document[] docList; + umbraco.cms.businesslogic.web.Document doc = null ; + List carriers = new List(); + + if (parentid == 0) + { + docList = Document.GetRootDocuments(); + } + else + { + try + { + doc = new umbraco.cms.businesslogic.web.Document(parentid); + } + catch + {} + + if (doc == null) + throw new Exception("Parent document with ID " + parentid + " not found"); + + try + { + if (!doc.HasChildren) + return carriers; + + docList = doc.Children; + } + catch (Exception exception) + { + throw new Exception("Could not load children: " + exception.Message); + } + } + + // Loop the nodes in docList + foreach (Document childdoc in docList) + { + carriers.Add(createCarrier(childdoc)); + } + return carriers; + } + + + [WebMethod] + public void update(documentCarrier carrier, string username, string password) + { + Authenticate(username, password); + + if (carrier.Id == 0) throw new Exception("ID must be specifed when updating"); + if (carrier == null) throw new Exception("No carrier specified"); + + umbraco.BusinessLogic.User user = GetUser(username, password); + + Document doc = null; + try + { + doc = new Document(carrier.Id); + } + catch {} + if (doc == null ) + + + + // We assign the new values: + doc.ReleaseDate = carrier.ReleaseDate; + doc.ExpireDate = carrier.ExpireDate; + if (carrier.ParentID != 0) + { + doc.Move(carrier.ParentID); + } + + if (carrier.Name.Length != 0) + { + doc.Text = carrier.Name; + } + + // We iterate the properties in the carrier + if (carrier.DocumentProperties != null) + { + foreach (documentProperty updatedproperty in carrier.DocumentProperties) + { + umbraco.cms.businesslogic.property.Property property = doc.getProperty(updatedproperty.Key); + + if (property == null) + { + } + else + { + property.Value = updatedproperty.PropertyValue; + } + } + } + handlePublishing(doc, carrier, user); + } + + + [WebMethod] + public void delete(int id, string username, string password) + { + Authenticate(username, password); + + // Some validation, to prevent deletion of system-documents.. (nessecary?) + if (id < 0) + { + throw new Exception("Cannot delete documents with id lower than 1"); + } + + // We load the document + Document doc = null; + try + { + doc = new Document(id); + } + catch + {} + + if (doc == null) + throw new Exception("Document not found"); + + try + { + doc.delete(); + } + catch (Exception ex) + { + throw new Exception("Document could not be deleted" + ex.Message); + } + } + + + private void handlePublishing(Document doc, documentCarrier carrier, umbraco.BusinessLogic.User user) + { + switch (carrier.PublishAction) + { + case documentCarrier.EPublishAction.Publish: + if (doc.PublishWithResult(user)) { + umbraco.library.UpdateDocumentCache(doc.Id); + } + break; + case documentCarrier.EPublishAction.Unpublish: + if (doc.PublishWithResult(user)) { + umbraco.library.UnPublishSingleNode(doc.Id); + } + break; + case documentCarrier.EPublishAction.Ignore: + if (doc.Published) + { + if (doc.PublishWithResult(user)) { + umbraco.library.UpdateDocumentCache(doc.Id); + } + } + else + { + if (doc.PublishWithResult(user)) { + umbraco.library.UpdateDocumentCache(doc.Id); + } + } + break; + } + } + + + private documentCarrier createCarrier(Document doc) + { + documentCarrier carrier = new documentCarrier(); + carrier.ExpireDate = doc.ExpireDate; + carrier.ReleaseDate = doc.ReleaseDate; + carrier.Id = doc.Id; + carrier.Name = doc.Text; + + try + { + carrier.ParentID = doc.Parent.Id; + } + catch + { + } + + carrier.Published = doc.Published; + carrier.HasChildren = doc.HasChildren; + + foreach (umbraco.cms.businesslogic.property.Property prop in doc.getProperties) + { + documentProperty carrierprop = new documentProperty(); + + if (prop.Value == System.DBNull.Value) + { + carrierprop.PropertyValue = null; + } + else + { + carrierprop.PropertyValue = prop.Value; + } + + carrierprop.Key = prop.PropertyType.Alias; + carrier.DocumentProperties.Add(carrierprop); + } + return carrier; + + } + + } + + [Serializable] + [XmlType(Namespace = "http://umbraco.org/webservices/")] + public class documentCarrier + { + + public enum EPublishAction + { + Ignore, + Publish, + Unpublish + }; + + public enum EPublishStatus + { + Published, + NotPublished + }; + + public documentCarrier() + { + DocumentProperties = new List(); + } + + private int id; + private string name; + private List documentProperties; + private int documentTypeID; + private int parentID; + private bool hasChildren; + + private EPublishAction publishAction; + private bool published; + private DateTime releaseDate; + private DateTime expireDate; + + public int Id + { + get { return id; } + set { id = value; } + } + + public string Name + { + get { return name; } + set { name = value; } + } + + public List DocumentProperties + { + get { return documentProperties; } + set { documentProperties = value; } + } + + public int DocumentTypeID + { + get { return documentTypeID; } + set { documentTypeID = value; } + } + + public int ParentID + { + get { return parentID; } + set { parentID = value; } + } + + public bool HasChildren + { + get { return hasChildren; } + set { hasChildren = value; } + } + + public EPublishAction PublishAction + { + get { return publishAction; } + set { publishAction = value; } + } + + public bool Published + { + get { return published; } + set { published = value; } + } + + public DateTime ReleaseDate + { + get { return releaseDate; } + set { releaseDate = value; } + } + + public DateTime ExpireDate + { + get { return expireDate; } + set { expireDate = value; } + } + + + + } + + [Serializable] + [XmlType(Namespace = "http://umbraco.org/webservices/")] + public class documentProperty + { + private string key; + private object propertyValue; + + public documentProperty() + { + } + + public object PropertyValue + { + get { return propertyValue; } + set { propertyValue = value; } + } + + public string Key + { + get { return key; } + set { key = value; } + } + } + +} + + diff --git a/components/umbraco.webservices/FileService.asmx b/components/umbraco.webservices/FileService.asmx new file mode 100644 index 0000000000..e8a68ff354 --- /dev/null +++ b/components/umbraco.webservices/FileService.asmx @@ -0,0 +1 @@ +<%@ WebService Language="C#" CodeBehind="FileService.asmx.cs" Class="umbraco.webservices.files.fileService" %> diff --git a/components/umbraco.webservices/FileService.asmx.cs b/components/umbraco.webservices/FileService.asmx.cs new file mode 100644 index 0000000000..d4bc139e68 --- /dev/null +++ b/components/umbraco.webservices/FileService.asmx.cs @@ -0,0 +1,196 @@ +using System; +using System.Data; +using System.Web; +using System.Collections; +using System.Web.Services; +using System.Web.Services.Protocols; +using System.ComponentModel; +using System.Collections.Generic; +using umbraco.cms.businesslogic.web; +using umbraco.cms; +using System.IO; + +namespace umbraco.webservices.files +{ + /// + /// Summary description for FileService + /// + [WebService(Namespace = "http://umbraco.org/webservices/")] + [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] + [ToolboxItem(false)] + public class fileService : BaseWebService + { + + override public Services Service + { + get + { + return Services.FileService; + } + } + + [WebMethod] + public void DeleteFile(String folderName, string fileName, string username, string password) + { + + Authenticate(username, password); + + // Check if folder is accessible + if (FileIO.FolderAccess(folderName)) + { + // Check if the filename is valid + if (!FileIO.ValidFileName(fileName)) + throw new ArgumentException(String.Format("Filename {0} not valid", fileName)); + + // Check if the file exists. If it does, we delete it + if (System.IO.File.Exists(FileIO.GetFilePath(folderName, fileName))) + { + System.IO.File.Delete(FileIO.GetFilePath(folderName, fileName)); + } + else + { + throw new FileNotFoundException(); + } + } + else + { + throw new ArgumentException("no access to specified folder"); + } + } + [WebMethod] + public Byte[] DownloadFile(String folderName, string fileName, string username, string password) + { + + Authenticate(username, password); + + // Check if folder is accessible + if (FileIO.FolderAccess(folderName)) + { + // Check if the filename is valid + if (!FileIO.ValidFileName(fileName)) + throw new ArgumentException(String.Format("Filename {0} not valid", fileName)); + + // Check if the file even exists + if (!System.IO.File.Exists(FileIO.GetFilePath(folderName, fileName))) + { + throw new FileNotFoundException("Could not find file to delete"); + } + + // Create a stream, and send it to the client + FileStream objfilestream = new FileStream(FileIO.GetFilePath(folderName, fileName), FileMode.Open, FileAccess.Read); + int len = (int)objfilestream.Length; + Byte[] documentcontents = new Byte[len]; + objfilestream.Read(documentcontents, 0, len); + objfilestream.Close(); + return documentcontents; + } + else + { + throw new ArgumentException("no access to specified folder"); + } + } + + [WebMethod] + public void UploadFile(Byte[] docbinaryarray, String folderName, string fileName, string username, string password, bool deleteOld) + { + Authenticate( username, password); + + // Check if folder is accessible + if (FileIO.FolderAccess(folderName)) + { + // Check if the filename is valid + if (FileIO.ValidFileName(fileName)) + throw new ArgumentException(String.Format("Filename {0} not valid", fileName)); + + // Check if the file exists. If it does, we delete it first .. + // TODO: Maybe we should have "deleted files, folder for this? + if (System.IO.File.Exists(FileIO.GetFilePath(folderName, fileName))) + { + if (deleteOld) + { + System.IO.File.Delete(FileIO.GetFilePath(folderName, fileName)); + } + else + { + throw new ArgumentException("Cannot save. File allready exist"); + } + } + + // Open a filestream, and write the data from the client to it + FileStream objfilestream = new FileStream(FileIO.GetFilePath(folderName, fileName), FileMode.Create, FileAccess.ReadWrite); + objfilestream.Write(docbinaryarray, 0, docbinaryarray.Length); + objfilestream.Close(); + } + else + { + throw new ArgumentException("no access to specified folder"); + } + } + + + /// + /// To download a file, we need to know how big its going to be + /// + [WebMethod] + public int GetFileSize(String folderName, string fileName, string username, string password) + { + Authenticate(username, password); + + // Check if folder is accessible + if (FileIO.FolderAccess(folderName)) + { + + // Check if the filename is valid + if (!FileIO.ValidFileName(fileName)) + throw new ArgumentException(String.Format("Filename {0} not valid", fileName)); + + string strdocPath; + strdocPath = FileIO.GetFilePath(folderName, fileName); + + // Load file into stream + FileStream objfilestream = new FileStream(strdocPath, FileMode.Open, FileAccess.Read); + + // Find and return the lenght of the stream + int len = (int)objfilestream.Length; + objfilestream.Close(); + return len; + } + else + { + throw new ArgumentException("no access to specified folder"); + } + } + + + /// + /// Get all files in a specific folder + /// + /// + [WebMethod] + public string[] GetFilesList(String folderName, string username, string password) + { + Authenticate(username, password); + + if (FileIO.FolderAccess(folderName)) + { + string fullPath = FileIO.GetFolderPath(folderName); + + DirectoryInfo folder = new DirectoryInfo(fullPath); + FileInfo[] files = folder.GetFiles(); + List shortNames = new List ( ); + + foreach (FileInfo file in files) + { + shortNames.Add(file.Name); + } + return shortNames.ToArray(); + + } + else + { + throw new ArgumentException("no access to specified folder"); + } + } + + } +} diff --git a/components/umbraco.webservices/MaintanceService.asmx b/components/umbraco.webservices/MaintanceService.asmx new file mode 100644 index 0000000000..fc9f8aba21 --- /dev/null +++ b/components/umbraco.webservices/MaintanceService.asmx @@ -0,0 +1 @@ +<%@ WebService Language="C#" CodeBehind="MaintanceService.asmx.cs" Class="umbraco.webservices.maintenance.maintenanceService" %> diff --git a/components/umbraco.webservices/MaintanceService.asmx.cs b/components/umbraco.webservices/MaintanceService.asmx.cs new file mode 100644 index 0000000000..7ac03c8894 --- /dev/null +++ b/components/umbraco.webservices/MaintanceService.asmx.cs @@ -0,0 +1,46 @@ +using System; +using System.Data; +using System.Web; +using System.Collections; +using System.Web.Services; +using System.Web.Services.Protocols; +using System.ComponentModel; + +namespace umbraco.webservices.maintenance +{ + + [WebService(Namespace = "http://umbraco.org/webservices/")] + [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] + [ToolboxItem(false)] + public class maintenanceService : BaseWebService + { + + override public Services Service + { + get + { + return Services.MaintenanceService; + } + } + + [WebMethod] + public string getWebservicesVersion(string username, string password) + { + // We check if services are enabled and user has access + Authenticate(username, password); + + Version thisVersion = new Version(0, 9); + return Convert.ToString(thisVersion); + } + + [WebMethod] + public void restartApplication(string username, string password) + { + // We check if services are enabled and user has access + Authenticate(username, password); + + System.Web.HttpRuntime.UnloadAppDomain(); + } + + } +} diff --git a/components/umbraco.webservices/MediaService.asmx b/components/umbraco.webservices/MediaService.asmx new file mode 100644 index 0000000000..cfaded1cb1 --- /dev/null +++ b/components/umbraco.webservices/MediaService.asmx @@ -0,0 +1 @@ +<%@ WebService Language="C#" CodeBehind="MediaService.asmx.cs" Class="umbraco.webservices.media.mediaService" %> diff --git a/components/umbraco.webservices/MediaService.asmx.cs b/components/umbraco.webservices/MediaService.asmx.cs new file mode 100644 index 0000000000..46f023a2a2 --- /dev/null +++ b/components/umbraco.webservices/MediaService.asmx.cs @@ -0,0 +1,33 @@ +using System; +using System.Data; +using System.Web; +using System.Collections; +using System.Web.Services; +using System.Web.Services.Protocols; +using System.ComponentModel; +using System.Collections.Generic; +using System.Xml.Serialization; +using System.Xml; +using umbraco.cms.businesslogic.web; +using umbraco.cms; +using umbraco.cms.businesslogic.member; + +namespace umbraco.webservices.media +{ + + [WebService(Namespace = "http://umbraco.org/webservices/")] + [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] + [ToolboxItem(false)] + public class mediaService : BaseWebService + { + + override public Services Service + { + get + { + return Services.MediaService; + } + } + + } +} diff --git a/components/umbraco.webservices/MemberService.asmx b/components/umbraco.webservices/MemberService.asmx new file mode 100644 index 0000000000..f65beb00c6 --- /dev/null +++ b/components/umbraco.webservices/MemberService.asmx @@ -0,0 +1 @@ +<%@ WebService Language="C#" CodeBehind="MemberService.asmx.cs" Class="umbraco.webservices.members.memberService" %> diff --git a/components/umbraco.webservices/MemberService.asmx.cs b/components/umbraco.webservices/MemberService.asmx.cs new file mode 100644 index 0000000000..bd4cdc7d3a --- /dev/null +++ b/components/umbraco.webservices/MemberService.asmx.cs @@ -0,0 +1,389 @@ +using System; +using System.Data; +using System.Web; +using System.Collections; +using System.Web.Services; +using System.Web.Services.Protocols; +using System.ComponentModel; +using System.Collections.Generic; +using umbraco.cms.businesslogic.web; +using umbraco.cms; +using System.Xml.Serialization; +using System.Xml; +using umbraco.cms.businesslogic.member; + + +namespace umbraco.webservices.members +{ + + [WebService(Namespace = "http://umbraco.org/webservices/")] + [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] + [ToolboxItem(false)] + public class memberService : BaseWebService + { + + override public Services Service + { + get + { + return Services.MemberService; + } + } + + + /// + /// Reads the user with the specified memberId + /// + /// + [WebMethod] + public memberCarrier readByLogin(string memberLoginName, string memberPassword, string username, string password) + { + Authenticate (username, password); + + umbraco.cms.businesslogic.member.Member foundMember = umbraco.cms.businesslogic.member.Member.GetMemberFromLoginNameAndPassword(memberLoginName, memberPassword); + if (foundMember == null) + return null; + + return CreateMemberCarrier(foundMember); + } + + /// + /// Reads the user with the specified memberId + /// + /// + [WebMethod] + public memberCarrier readById(int memberId, string username, string password) + { + Authenticate(username, password); + + umbraco.cms.businesslogic.member.Member foundMember = new umbraco.cms.businesslogic.member.Member(memberId); + if (foundMember == null) + return null; + + return CreateMemberCarrier(foundMember); + } + + /// + /// Reads the full list of members + /// + /// + [WebMethod] + public List readList(string username, string password) + { + Authenticate(username, password); + + Member[] members = Member.GetAll; + List Members = new List(); + + foreach (umbraco.cms.businesslogic.member.Member member in members) + { + Members.Add(CreateMemberCarrier(member)); + } + + return Members; + } + + + [WebMethod] + public void update(memberCarrier carrier, string username, string password) + { + Authenticate(username, password); + + // Some validation + if (carrier.Id == 0) throw new Exception("ID must be specifed when updating"); + if (carrier == null) throw new Exception("No carrier specified"); + + // Get the user + umbraco.BusinessLogic.User user = GetUser(username, password); + + // We load the member + Member member = new Member(carrier.Id); + + // We assign the new values: + member.LoginName = carrier.LoginName; + member.Text = carrier.DisplayedName; + member.Email = carrier.Email; + member.Password = carrier.Password; + + // We iterate the properties in the carrier + if (carrier.MemberProperties != null) + { + foreach (memberProperty updatedproperty in carrier.MemberProperties) + { + umbraco.cms.businesslogic.property.Property property = member.getProperty(updatedproperty.Key); + if (property != null) + { + property.Value = updatedproperty.PropertyValue; + } + } + } + } + + + [WebMethod] + public int create(memberCarrier carrier, int memberTypeId, string username, string password) + { + Authenticate(username, password); + + // Some validation + if (carrier == null) throw new Exception("No carrier specified"); + if (carrier.Id != 0) throw new Exception("ID cannot be specifed when creating. Must be 0"); + if (string.IsNullOrEmpty(carrier.DisplayedName)) carrier.DisplayedName = "unnamed"; + + // we fetch the membertype + umbraco.cms.businesslogic.member.MemberType mtype = new umbraco.cms.businesslogic.member.MemberType(memberTypeId); + + // Check if the membertype exists + if (mtype == null) throw new Exception("Membertype " + memberTypeId + " not found"); + + // Get the user that creates + umbraco.BusinessLogic.User user = GetUser(username, password); + + // Create the new member + umbraco.cms.businesslogic.member.Member newMember = umbraco.cms.businesslogic.member.Member.MakeNew(carrier.DisplayedName, mtype, user); + + // We iterate the properties in the carrier + if (carrier.MemberProperties != null) + { + foreach (memberProperty updatedproperty in carrier.MemberProperties) + { + umbraco.cms.businesslogic.property.Property property = newMember.getProperty(updatedproperty.Key); + if (property != null) + { + property.Value = updatedproperty.PropertyValue; + } + } + } + return newMember.Id; + } + + + + + /// + /// Deletes the document with the specified ID + /// + /// + /// + /// + [WebMethod] + public void delete(int id, string username, string password) + { + + Authenticate(username, password); + + // We load the member + umbraco.cms.businesslogic.member.Member deleteMember; + try + { + deleteMember = new umbraco.cms.businesslogic.member.Member(id); + } + catch (Exception ex) + { + throw new Exception("Member not found" + ex.Message); + } + + // We delete him (cruel world) + try + { + deleteMember.delete(); + } + catch (Exception ex) + { + throw new Exception("Member could not be deleted" + ex.Message); + } + } + + + + /// + /// Creates container-object for member + /// + /// + /// + private memberCarrier CreateMemberCarrier(umbraco.cms.businesslogic.member.Member member) + { + memberCarrier carrier = new memberCarrier(); + + carrier.Id = member.Id; + + carrier.LoginName = member.LoginName; + carrier.DisplayedName = member.Text; + carrier.Email = member.Email; + carrier.Password = member.Password; + + carrier.MembertypeId = member.ContentType.Id; + carrier.MembertypeName = member.ContentType.Text; + + // Adding groups to member-carrier + IDictionaryEnumerator Enumerator; + Enumerator = member.Groups.GetEnumerator(); + while (Enumerator.MoveNext()) + { + memberGroup group = new memberGroup(Convert.ToInt32(Enumerator.Key), ((umbraco.cms.businesslogic.member.MemberGroup)Enumerator.Value).Text); + carrier.Groups.Add(group); + } + + // Loading properties to carrier + foreach (umbraco.cms.businesslogic.property.Property prop in member.getProperties) + { + memberProperty carrierprop = new memberProperty(); + + if (prop.Value == System.DBNull.Value) + { + carrierprop.PropertyValue = null; + } + else + { + carrierprop.PropertyValue = prop.Value; + } + + carrierprop.Key = prop.PropertyType.Alias; + carrier.MemberProperties.Add(carrierprop); + } + return carrier; + } + + } + + [Serializable] + public class memberGroup + { + int groupID; + string groupName; + + public memberGroup() + { + } + + public memberGroup(int groupID, string groupName) + { + GroupID = groupID; + GroupName = groupName; + } + + public int GroupID + { + get { return groupID; } + set { groupID = value; } + } + + public string GroupName + { + get { return groupName; } + set { groupName = value; } + } + + } + + [Serializable] + [XmlType(Namespace = "http://umbraco.org/webservices/")] + public class memberCarrier + { + + public memberCarrier() + { + memberProperties = new List(); + groups = new List(); + } + + #region Fields + private int id; + + private string password; + private string email; + private string displayedName; + private string loginName; + + private int membertypeId; + private string membertypeName; + + private List groups; + private List memberProperties; + #endregion + + #region Properties + + public int Id + { + get { return id; } + set { id = value; } + } + + public string DisplayedName + { + get { return displayedName; } + set { displayedName = value; } + } + + public string Password + { + get { return password; } + set { password = value; } + } + + public string Email + { + get { return email; } + set { email = value; } + } + + public string LoginName + { + get { return loginName; } + set { loginName = value; } + } + + public int MembertypeId + { + get { return membertypeId; } + set { membertypeId = value; } + } + + + public string MembertypeName + { + get { return membertypeName; } + set { membertypeName = value; } + } + + public List Groups + { + get { return groups; } + set { groups = value; } + } + + public List MemberProperties + { + get { return memberProperties; } + set { memberProperties = value; } + } + + #endregion + } + + [Serializable] + [XmlType(Namespace = "http://umbraco.org/webservices/")] + public class memberProperty + { + private string key; + private object propertyValue; + + public memberProperty() + { + } + + public object PropertyValue + { + get { return propertyValue; } + set { propertyValue = value; } + } + + public string Key + { + get { return key; } + set { key = value; } + } + } + +} diff --git a/components/umbraco.webservices/Properties/AssemblyInfo.cs b/components/umbraco.webservices/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..662c5136de --- /dev/null +++ b/components/umbraco.webservices/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("umbraco.webservices")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("umbraco.webservices")] +[assembly: AssemblyCopyright("Copyright © 2008")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("58e13174-1338-40a8-b864-f47c7678a976")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/components/umbraco.webservices/StylesheetService.asmx b/components/umbraco.webservices/StylesheetService.asmx new file mode 100644 index 0000000000..4d98082f6c --- /dev/null +++ b/components/umbraco.webservices/StylesheetService.asmx @@ -0,0 +1 @@ +<%@ WebService Language="C#" CodeBehind="StylesheetService.asmx.cs" Class="umbraco.webservices.stylesheets.stylesheetService" %> diff --git a/components/umbraco.webservices/StylesheetService.asmx.cs b/components/umbraco.webservices/StylesheetService.asmx.cs new file mode 100644 index 0000000000..c0f3af9c8f --- /dev/null +++ b/components/umbraco.webservices/StylesheetService.asmx.cs @@ -0,0 +1,143 @@ +using System; +using System.Data; +using System.Web; +using System.Collections; +using System.Web.Services; +using System.Web.Services.Protocols; +using System.ComponentModel; +using umbraco.cms.businesslogic.web; +using umbraco.cms; +using umbraco; +using System.Collections.Generic; + +namespace umbraco.webservices.stylesheets +{ + /// + /// Summary description for StylesheetService + /// + [WebService(Namespace = "http://umbraco.org/webservices/")] + [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] + [ToolboxItem(false)] + public class stylesheetService : BaseWebService + { + + override public Services Service + { + get + { + return Services.StylesheetService; + } + } + + + [WebMethod] + public int create(stylesheetCarrier carrier, string username, string password) + { + Authenticate(username, password); + umbraco.BusinessLogic.User user = GetUser(username, password); + + StyleSheet stylesheet = StyleSheet.MakeNew(user, carrier.Name, (carrier.Name + ".css"), carrier.Content ); + stylesheet.saveCssToFile(); + + return stylesheet.Id; + } + + + [WebMethod] + public stylesheetCarrier read(int id, string username, string password) + { + Authenticate(username, password); + + StyleSheet stylesheet; + try + { + stylesheet = new StyleSheet(id); + } + catch (Exception) + { + throw new Exception("Could not load stylesheet with id: " + id + ", not found"); + } + + if (stylesheet == null) + throw new Exception("Could not load stylesheet with id: " + id + ", not found"); + + return createCarrier(stylesheet); + } + + + [WebMethod] + public List readList(string username, string password) + { + Authenticate(username, password); + + List stylesheets = new List(); + + StyleSheet[] foundstylesheets = StyleSheet.GetAll(); + + foreach (StyleSheet stylesheet in foundstylesheets) + { + stylesheets.Add(createCarrier(stylesheet)); + } + + return stylesheets; + } + + + [WebMethod] + public void update(stylesheetCarrier carrier, string username, string password) + { + Authenticate(username, password); + + StyleSheet stylesheet = null; + try + { + stylesheet = new StyleSheet(carrier.Id); + } + catch + {} + + if (stylesheet == null) + throw new Exception("Could not load stylesheet with id: " + carrier.Id ); + + stylesheet.Content = carrier.Content; + stylesheet.saveCssToFile(); + } + + + private stylesheetCarrier createCarrier(StyleSheet stylesheet) + { + stylesheetCarrier carrier = new stylesheetCarrier(); + carrier.Id = stylesheet.Id; + carrier.Name = stylesheet.Text; + carrier.Content = stylesheet.Content; + return carrier; + } + + + + public class stylesheetCarrier + { + private int id; + private string name; + private string content; + + public int Id + { + get { return id; } + set { id = value; } + } + + public string Name + { + get { return name; } + set { name = value; } + } + + public string Content + { + get { return content; } + set { content = value; } + } + } + } +} diff --git a/components/umbraco.webservices/TemplateService.asmx b/components/umbraco.webservices/TemplateService.asmx new file mode 100644 index 0000000000..8af78e62dd --- /dev/null +++ b/components/umbraco.webservices/TemplateService.asmx @@ -0,0 +1 @@ +<%@ WebService Language="C#" CodeBehind="TemplateService.asmx.cs" Class="umbraco.webservices.templates.templateService" %> diff --git a/components/umbraco.webservices/TemplateService.asmx.cs b/components/umbraco.webservices/TemplateService.asmx.cs new file mode 100644 index 0000000000..be9e95680e --- /dev/null +++ b/components/umbraco.webservices/TemplateService.asmx.cs @@ -0,0 +1,225 @@ +using System; +using System.Data; +using System.Web; +using System.Collections; +using System.Web.Services; +using System.Web.Services.Protocols; +using System.ComponentModel; +using System.Collections.Generic; +using umbraco.cms.businesslogic.web; +using umbraco.cms; +using umbraco; + + +namespace umbraco.webservices.templates +{ + /// + /// Summary description for TemplateService + /// + [WebService(Namespace = "http://umbraco.org/webservices/")] + [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] + [ToolboxItem(false)] + public class templateService : BaseWebService + { + + override public Services Service + { + get + { + return Services.TemplateService; + } + } + + [WebMethod] + public int readIdFromAlias(string alias ,string username, string password) + { + Authenticate(username, password); + + cms.businesslogic.template.Template template ; + + try + { + template = cms.businesslogic.template.Template.GetByAlias(alias); + } + catch ( Exception ) + { + throw new Exception( "Could not load template from alias: " + alias); + } + if (template == null) + { + throw new Exception( "Could not load template from alias: " + alias); + } + + return template.Id; + } + + + [WebMethod] + public List readList(string username, string password) + { + List templateCarriers = new List(); + + Authenticate(username, password); + + foreach (cms.businesslogic.template.Template template in cms.businesslogic.template.Template.GetAllAsList()) + { + templateCarriers.Add(createTemplateCarrier(template)); + } + return templateCarriers; + } + + + + [WebMethod] + public void delete(int id, string username, string password) + { + Authenticate(username, password); + + if (id == 0) throw new Exception("ID must be specifed when updating"); + + cms.businesslogic.template.Template template = new cms.businesslogic.template.Template(id); + template.delete(); + } + + [WebMethod] + public int create(templateCarrier carrier, string username, string password) + { + Authenticate(username, password); + + if (carrier.Id != 0) throw new Exception("ID may not be specified when creating"); + if (carrier == null) throw new Exception("No carrier specified"); + + // Get the user + umbraco.BusinessLogic.User user = GetUser(username, password); + + // Create template + cms.businesslogic.template.Template template = cms.businesslogic.template.Template.MakeNew(carrier.Name, user); + + template.MasterTemplate = carrier.MastertemplateId; + template.Alias = carrier.Alias; + template.Text = carrier.Name; + template.Design = carrier.Design; + template.Save(); + clearCachedTemplate(template); + return template.Id; + } + + [WebMethod] + public void update(templateCarrier carrier, string username, string password) + { + if (carrier.Id == 0) throw new Exception("ID must be specifed when updating"); + if (carrier == null) throw new Exception("No carrier specified"); + + cms.businesslogic.template.Template template; + try + { + template = new cms.businesslogic.template.Template(carrier.Id); + } + catch (Exception) + { + throw new Exception("Template with ID " + carrier.Id + " not found"); + } + + template.MasterTemplate = carrier.MastertemplateId; + template.Alias = carrier.Alias; + template.Text = carrier.Name ; + template.Design = carrier.Design; + template.Save(); + + + clearCachedTemplate(template); + } + + [WebMethod] + public templateCarrier read(int id, string username, string password) + { + Authenticate(username, password); + + cms.businesslogic.template.Template template; + try + { + template = new cms.businesslogic.template.Template(id); + } + catch (Exception) + { + throw new Exception("Template with ID " + id + " not found"); + } + if (template == null) + { + throw new Exception("Template with ID " + id + " not found"); + } + + return createTemplateCarrier(template); + } + + public templateCarrier createTemplateCarrier(cms.businesslogic.template.Template template) + { + templateCarrier carrier = new templateCarrier(); + carrier.Id = template.Id; + carrier.MastertemplateId = template.MasterTemplate; + carrier.Alias = template.Alias; + carrier.Name = template.Text; + carrier.Design = template.Design; + carrier.MasterPageFile = template.MasterPageFile; + return carrier; + } + + + public class templateCarrier + { + private int id; + private int mastertemplateId; + private string name; + private string alias; + private string design; + private string masterPageFile; + + public int Id + { + get { return id; } + set { id = value; } + } + + public int MastertemplateId + { + get { return mastertemplateId; } + set { mastertemplateId = value; } + } + + public string MasterPageFile { + get { return masterPageFile; } + set { masterPageFile = value; } + } + + public string Name + { + get { return name; } + set { name = value; } + } + + public string Alias + { + get { return alias; } + set { alias = value; } + } + + public string Design + { + get { return design; } + set { design = value; } + } + } + + private void clearCachedTemplate(cms.businesslogic.template.Template cachedTemplate) + { + // Clear cache in rutime + if (UmbracoSettings.UseDistributedCalls) + umbraco.presentation.cache.dispatcher.Refresh( + new Guid("dd12b6a0-14b9-46e8-8800-c154f74047c8"), + cachedTemplate.Id); + else + umbraco.template.ClearCachedTemplate(cachedTemplate.Id); + } + + } +} diff --git a/components/umbraco.webservices/umbraco.webservices.csproj b/components/umbraco.webservices/umbraco.webservices.csproj new file mode 100644 index 0000000000..755342dfac --- /dev/null +++ b/components/umbraco.webservices/umbraco.webservices.csproj @@ -0,0 +1,114 @@ + + + + Debug + AnyCPU + 9.0.30729 + 2.0 + {CBDB56AC-FF02-4421-9FD4-ED82E339D8E2} + Library + Properties + umbraco.webservices + umbraco.webservices + v2.0 + 512 + SAK + SAK + SAK + SAK + + + true + full + false + ..\..\umbraco\presentation\bin\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + ..\..\umbraco\presentation\bin\ + TRACE + prompt + 4 + ..\..\umbraco\presentation\bin\umbraco.webservices.XML + + + + + + + + + + + Component + + + + DocumentService.asmx + Component + + + FileService.asmx + Component + + + MaintanceService.asmx + Component + + + MediaService.asmx + Component + + + MemberService.asmx + Component + + + + StylesheetService.asmx + Component + + + TemplateService.asmx + Component + + + + + {E469A9CE-1BEC-423F-AC44-713CD72457EA} + umbraco.businesslogic + + + {CCD75EC3-63DB-4184-B49D-51C1DD337230} + umbraco.cms + + + {651E1350-91B6-44B7-BD60-7207006D7003} + umbraco.presentation + + + + + + + + + + + + + + + xcopy "$(ProjectDir)*.asmx" "$(ProjectDir)..\..\umbraco\presentation\umbraco\webservices\api\" /Y + + \ No newline at end of file diff --git a/components/umbraco.webservices/umbraco.webservices.csproj.vspscc b/components/umbraco.webservices/umbraco.webservices.csproj.vspscc new file mode 100644 index 0000000000..feffdecaa4 --- /dev/null +++ b/components/umbraco.webservices/umbraco.webservices.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/config templates/UI.xml b/config templates/UI.xml new file mode 100644 index 0000000000..516080e551 --- /dev/null +++ b/config templates/UI.xml @@ -0,0 +1,297 @@ + + + +
Nodetype
+ /create/nodeType.ascx + + + +
+ +
Nodetype
+ /create/simple.ascx + + + +
+ +
Template
+ /create/simple.ascx + + + +
+ +
Template
+ /create/simple.ascx + + + +
+ +
Macro
+ /create/simple.ascx + + + +
+ +
Macro
+ /create/simple.ascx + + + +
+ +
Macro
+ /create/xslt.ascx + + + +
+ +
Page
+ /create/content.ascx + + + + + +
+ +
User
+ /create/simple.ascx + + + + +
+ +
User
+ /create/simple.ascx + + + +
+ +
Datatype
+ /create/simple.ascx + + + +
+ +
Datatype
+ /create/simple.ascx + + + +
+ +
membertype
+ /create/simple.ascx + + + +
+ +
membergroup
+ /create/simple.ascx + + + +
+ +
Stylesheet
+ /create/simple.ascx + + + +
+ +
XSLT file
+ /create/xslt.ascx + + + +
+ +
mediatype
+ /create/simple.ascx + + + +
+ +
Medie type
+ + + +
+ +
Media
+ /create/media.ascx + + + + +
+ +
member
+ /create/member.ascx + + + +
+ +
member
+ /create/member.ascx + + + +
+ +
member
+ /create/member.ascx + + + +
+ +
membertype
+ /create/member.ascx + + + +
+ +
membergroup
+ /create/simple.ascx + + + +
+ +
Indholdselemtent type
+ /create/simple.ascx + + + +
+ +
Indholdselemtent type
+ /create/simple.ascx + + + +
+ +
Indholdselemtent type
+ /create/simple.ascx + + + +
+ +
Stylesheet editor egenskab
+ /create/simple.ascx + + + + +
+ +
Stylesheet editor egenskab
+ /create/simple.ascx + + + +
+ +
Dictionary editor egenskab
+ /create/simple.ascx + + + +
+ +
Dictionary editor egenskab
+ /create/simple.ascx + + + + +
+ +
Language
+ /create/language.ascx + + + +
+ +
Language
+ /create/language.ascx + + + +
+ + + + + + +
Python file
+ /create/simple.ascx + + + +
+ +
Macro
+ /create/simple.ascx + + + +
+ +
Script file
+ /create/script.ascx + + + +
+ +
Script file
+ /create/script.ascx + + + + +
+ +
Macro
+ /create/script.ascx + + + +
+ + +
Package
+ /create/simple.ascx + + + +
+ + +
Package
+ /create/simple.ascx + + + +
+ +
diff --git a/config templates/access.xml b/config templates/access.xml new file mode 100644 index 0000000000..6783b7473e --- /dev/null +++ b/config templates/access.xml @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/config templates/config/404handlers.config b/config templates/config/404handlers.config new file mode 100644 index 0000000000..69bf6f1dd0 --- /dev/null +++ b/config templates/config/404handlers.config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/config templates/config/Dashboard.config b/config templates/config/Dashboard.config new file mode 100644 index 0000000000..c961a0a52c --- /dev/null +++ b/config templates/config/Dashboard.config @@ -0,0 +1,21 @@ + + + + diff --git a/config templates/config/UI.xml b/config templates/config/UI.xml new file mode 100644 index 0000000000..7719c41abc --- /dev/null +++ b/config templates/config/UI.xml @@ -0,0 +1,311 @@ + + + +
Nodetype
+ /create/nodeType.ascx + + + +
+ +
Nodetype
+ /create/simple.ascx + + + +
+ +
Template
+ /create/simple.ascx + + + + +
+ +
Template
+ /create/simple.ascx + + + +
+ +
Macro
+ /create/simple.ascx + + + +
+ +
Macro
+ /create/simple.ascx + + + +
+ +
Macro
+ /create/xslt.ascx + + + +
+ +
Page
+ /create/content.ascx + + + + + +
+ +
User
+ /create/simple.ascx + + + + +
+ +
User
+ /create/simple.ascx + + + +
+ +
Datatype
+ /create/simple.ascx + + + +
+ +
Datatype
+ /create/simple.ascx + + + +
+ +
membertype
+ /create/simple.ascx + + + +
+ +
membergroup
+ /create/simple.ascx + + + +
+ +
Stylesheet
+ /create/simple.ascx + + + +
+ +
XSLT file
+ /create/xslt.ascx + + + +
+ +
mediatype
+ /create/simple.ascx + + + +
+ +
Medie type
+ + + +
+ +
Media
+ /create/media.ascx + + + + +
+ +
member
+ /create/member.ascx + + + +
+ +
member
+ /create/member.ascx + + + +
+ +
member
+ /create/member.ascx + + + +
+ +
membertype
+ /create/member.ascx + + + +
+ +
membergroup
+ /create/simple.ascx + + + +
+ +
Indholdselemtent type
+ /create/simple.ascx + + + +
+ +
Indholdselemtent type
+ /create/simple.ascx + + + +
+ +
Indholdselemtent type
+ /create/simple.ascx + + + +
+ +
Stylesheet editor egenskab
+ /create/simple.ascx + + + + +
+ +
Stylesheet editor egenskab
+ /create/simple.ascx + + + +
+ +
Dictionary editor egenskab
+ /create/simple.ascx + + + +
+ +
Dictionary editor egenskab
+ /create/simple.ascx + + + + +
+ +
Language
+ /create/language.ascx + + + +
+ +
Language
+ /create/language.ascx + + + +
+ + + + + + +
Python file
+ /create/simple.ascx + + + +
+ +
Macro
+ /create/simple.ascx + + + +
+ +
Script file
+ /create/script.ascx + + + +
+ +
Script file
+ /create/script.ascx + + + + +
+ +
Macro
+ /create/script.ascx + + + +
+ + +
Package
+ /create/simple.ascx + + + +
+ +
Package
+ /create/simple.ascx + + + +
+ +
Package
+ /create/simple.ascx + + + +
+ +
User Types
+ /create/simple.ascx + + + + +
+
\ No newline at end of file diff --git a/config templates/config/UrlRewriting.config b/config templates/config/UrlRewriting.config new file mode 100644 index 0000000000..a4740dfcd3 --- /dev/null +++ b/config templates/config/UrlRewriting.config @@ -0,0 +1,32 @@ + + + + + diff --git a/config templates/config/formHandlers.config b/config templates/config/formHandlers.config new file mode 100644 index 0000000000..96072f451e --- /dev/null +++ b/config templates/config/formHandlers.config @@ -0,0 +1,15 @@ + + + + + + + + youremail@domain.com + Content + Subject + true + 127.0.0.1 + + + diff --git a/config templates/config/metablogConfig.config b/config templates/config/metablogConfig.config new file mode 100644 index 0000000000..a714b2cbe9 --- /dev/null +++ b/config templates/config/metablogConfig.config @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/config templates/config/restExtensions.config b/config templates/config/restExtensions.config new file mode 100644 index 0000000000..991dde0bc7 --- /dev/null +++ b/config templates/config/restExtensions.config @@ -0,0 +1,13 @@ + + + + \ No newline at end of file diff --git a/config templates/config/tinyMceConfig.config b/config templates/config/tinyMceConfig.config new file mode 100644 index 0000000000..f4bfbd8f7b --- /dev/null +++ b/config templates/config/tinyMceConfig.config @@ -0,0 +1,233 @@ + + + + + + + code + images/editor/code.gif + code + 1 + + + removeformat + images/editor/cleanup.gif + removeformat + 2 + + + + Undo + images/editor/undo.gif + undo + 11 + + + Redo + images/editor/redo.gif + redo + 12 + + + Cut + images/editor/cut.gif + cut + 13 + + + Copy + images/editor/copy.gif + copy + 14 + + + mcePasteWord + images/editor/paste.gif + pasteword + 15 + + + + stylePicker + images/editor/showStyles.png + umbracocss + 20 + + + bold + images/editor/bold.gif + bold + 21 + + + italic + images/editor/italic.gif + italic + 22 + + + Underline + images/editor/underline.gif + underline + 23 + + + Strikethrough + images/editor/strikethrough.gif + strikethrough + 24 + + + + JustifyLeft + images/editor/justifyleft.gif + justifyleft + 31 + + + JustifyCenter + images/editor/justifycenter.gif + justifycenter + 32 + + + JustifyRight + images/editor/justifyright.gif + justifyright + 33 + + + JustifyFull + images/editor/justifyfull.gif + justifyfull + 34 + + + + bullist + images/editor/bullist.gif + bullist + 41 + + + numlist + images/editor/numlist.gif + numlist + 42 + + + Outdent + images/editor/outdent.gif + outdent + 43 + + + Indent + images/editor/indent.gif + indent + 44 + + + + mceLink + images/editor/link.gif + link + 51 + + + unlink + images/editor/unLink.gif + unlink + 52 + + + mceInsertAnchor + images/editor/anchor.gif + anchor + 53 + + + + mceImage + images/editor/image.gif + image + 61 + + + umbracomacro + images/editor/insMacro.gif + umbracomacro + 62 + + + mceInsertTable + images/editor/table.gif + table + 63 + + + media + images/editor/media.gif + media + 65 + + + + inserthorizontalrule + images/editor/hr.gif + hr + 71 + + + subscript + images/editor/sub.gif + sub + 72 + + + superscript + images/editor/sup.gif + sup + 73 + + + mceCharMap + images/editor/charmap.gif + charmap + 74 + + + + + paste + inlinepopups + noneditable + table + umbracomacro + advimage + advlink + umbracocss + media + + + + + font + + + + + raw + + \ No newline at end of file diff --git a/config templates/config/umbracoSettings.config b/config templates/config/umbracoSettings.config new file mode 100644 index 0000000000..31112cda8c --- /dev/null +++ b/config templates/config/umbracoSettings.config @@ -0,0 +1,141 @@ + + + + + + jpeg,jpg,gif,bmp,png,tiff,tif + + alt,border,class,style,align,id,name,onclick,usemap + + + + /scripts + + js,xml + + true + + + + True + + + + + 1 + + + + robot@umbraco.dk + + + + True + + + gif + + + True + + + UTF8 + + + True + + + True + + + False + + + text + + + + + false + + - + + + + + + plus + star + + + ae + oe + aa + ae + oe + ue + ss + ae + oe + + + + + true + + + + + + + true + true + + + + + + + + + + + + + + + 0 + + + + + + + + + + + your-username + your-username + your-username + your-username + your-username + + css,xslt + + + + + + + + + + + + + UsersMembershipProvider + + + diff --git a/config templates/config/xsltExtensions.config b/config templates/config/xsltExtensions.config new file mode 100644 index 0000000000..51b95bffca --- /dev/null +++ b/config templates/config/xsltExtensions.config @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/config templates/packages/createdPackages.config b/config templates/packages/createdPackages.config new file mode 100644 index 0000000000..7be527318c --- /dev/null +++ b/config templates/packages/createdPackages.config @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/config templates/packages/installedPackages.config b/config templates/packages/installedPackages.config new file mode 100644 index 0000000000..7be527318c --- /dev/null +++ b/config templates/packages/installedPackages.config @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/config templates/umbraco.config b/config templates/umbraco.config new file mode 100644 index 0000000000..e69de29bb2 diff --git a/config templates/web.config b/config templates/web.config new file mode 100644 index 0000000000..e09c4095d9 --- /dev/null +++ b/config templates/web.config @@ -0,0 +1,184 @@ + + + + + + +
+ + + +
+ +
+
+
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + http://regexlib.com/WebServices.asmx + + + + + + diff --git a/docs/Umbraco 4 beta 2 update.docx b/docs/Umbraco 4 beta 2 update.docx new file mode 100644 index 0000000000..6ab209aa86 Binary files /dev/null and b/docs/Umbraco 4 beta 2 update.docx differ diff --git a/foreign dlls/AjaxControlToolkit.dll b/foreign dlls/AjaxControlToolkit.dll new file mode 100644 index 0000000000..1ff944f5b2 Binary files /dev/null and b/foreign dlls/AjaxControlToolkit.dll differ diff --git a/foreign dlls/CookComputing.XmlRpcV2.dll b/foreign dlls/CookComputing.XmlRpcV2.dll new file mode 100644 index 0000000000..eb03a61f33 Binary files /dev/null and b/foreign dlls/CookComputing.XmlRpcV2.dll differ diff --git a/foreign dlls/DotNetOpenMail.dll b/foreign dlls/DotNetOpenMail.dll new file mode 100644 index 0000000000..2a9447cbed Binary files /dev/null and b/foreign dlls/DotNetOpenMail.dll differ diff --git a/foreign dlls/ICSharpCode.SharpZipLib.dll b/foreign dlls/ICSharpCode.SharpZipLib.dll new file mode 100644 index 0000000000..bcdb00ea38 Binary files /dev/null and b/foreign dlls/ICSharpCode.SharpZipLib.dll differ diff --git a/foreign dlls/ImageManipulation.dll b/foreign dlls/ImageManipulation.dll new file mode 100644 index 0000000000..b0d8364529 Binary files /dev/null and b/foreign dlls/ImageManipulation.dll differ diff --git a/foreign dlls/IronMath.dll b/foreign dlls/IronMath.dll new file mode 100644 index 0000000000..aca8253d2e Binary files /dev/null and b/foreign dlls/IronMath.dll differ diff --git a/foreign dlls/IronPython.dll b/foreign dlls/IronPython.dll new file mode 100644 index 0000000000..9f7b47d728 Binary files /dev/null and b/foreign dlls/IronPython.dll differ diff --git a/foreign dlls/Lucene.Net.dll b/foreign dlls/Lucene.Net.dll new file mode 100644 index 0000000000..f10fb3b077 Binary files /dev/null and b/foreign dlls/Lucene.Net.dll differ diff --git a/foreign dlls/Microsoft.ApplicationBlocks.Data.dll b/foreign dlls/Microsoft.ApplicationBlocks.Data.dll new file mode 100644 index 0000000000..c431985632 Binary files /dev/null and b/foreign dlls/Microsoft.ApplicationBlocks.Data.dll differ diff --git a/foreign dlls/MySql.Data.dll b/foreign dlls/MySql.Data.dll new file mode 100644 index 0000000000..35235ef497 Binary files /dev/null and b/foreign dlls/MySql.Data.dll differ diff --git a/foreign dlls/TidyDll.dll b/foreign dlls/TidyDll.dll new file mode 100644 index 0000000000..ece5d743b8 Binary files /dev/null and b/foreign dlls/TidyDll.dll differ diff --git a/foreign dlls/TidyNet.dll b/foreign dlls/TidyNet.dll new file mode 100644 index 0000000000..d31dcc3409 Binary files /dev/null and b/foreign dlls/TidyNet.dll differ diff --git a/foreign dlls/UrlRewritingNet.UrlRewriter.dll b/foreign dlls/UrlRewritingNet.UrlRewriter.dll new file mode 100644 index 0000000000..3cb5c398d9 Binary files /dev/null and b/foreign dlls/UrlRewritingNet.UrlRewriter.dll differ diff --git a/foreign dlls/VistaDB For Umbraco.dll b/foreign dlls/VistaDB For Umbraco.dll new file mode 100644 index 0000000000..87a95906e4 Binary files /dev/null and b/foreign dlls/VistaDB For Umbraco.dll differ diff --git a/foreign dlls/VistaDB.NET20.dll b/foreign dlls/VistaDB.NET20.dll new file mode 100644 index 0000000000..36da27d87f Binary files /dev/null and b/foreign dlls/VistaDB.NET20.dll differ diff --git a/umbraco weekly.build b/umbraco weekly.build new file mode 100644 index 0000000000..e5897e1218 --- /dev/null +++ b/umbraco weekly.build @@ -0,0 +1,200 @@ + + + Build the umbraco 4.x Application + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/umbraco.build b/umbraco.build new file mode 100644 index 0000000000..2439460216 --- /dev/null +++ b/umbraco.build @@ -0,0 +1,246 @@ + + + Build the umbraco 3.1.x Application + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/umbraco.sln b/umbraco.sln new file mode 100644 index 0000000000..3885a3f0af --- /dev/null +++ b/umbraco.sln @@ -0,0 +1,188 @@ +Microsoft Visual Studio Solution File, Format Version 10.00 +# Visual Studio 2008 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F0242771-6DE6-4E03-BD3A-7B79BA79105B}" + ProjectSection(SolutionItems) = preProject + foreign dlls\AjaxControlToolkit.dll = foreign dlls\AjaxControlToolkit.dll + build.xml = build.xml + foreign dlls\CookComputing.XmlRpcV2.dll = foreign dlls\CookComputing.XmlRpcV2.dll + foreign dlls\DotNetOpenMail.dll = foreign dlls\DotNetOpenMail.dll + foreign dlls\ICSharpCode.SharpZipLib.dll = foreign dlls\ICSharpCode.SharpZipLib.dll + foreign dlls\IronMath.dll = foreign dlls\IronMath.dll + IronPython License.Rtf = IronPython License.Rtf + foreign dlls\IronPython.dll = foreign dlls\IronPython.dll + License.txt = License.txt + foreign dlls\Lucene.Net.dll = foreign dlls\Lucene.Net.dll + foreign dlls\Microsoft.ApplicationBlocks.Data.dll = foreign dlls\Microsoft.ApplicationBlocks.Data.dll + foreign dlls\MySql.Data.dll = foreign dlls\MySql.Data.dll + foreign dlls\TidyNet.dll = foreign dlls\TidyNet.dll + umbraco weekly.build = umbraco weekly.build + umbraco.build = umbraco.build + foreign dlls\UrlRewritingNet.UrlRewriter.dll = foreign dlls\UrlRewritingNet.UrlRewriter.dll + foreign dlls\VistaDB For Umbraco.dll = foreign dlls\VistaDB For Umbraco.dll + foreign dlls\VistaDB.NET20.dll = foreign dlls\VistaDB.NET20.dll + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "StandardConfig", "StandardConfig", "{B8ECDB8B-BF44-462C-B6DA-22421B3EC4D7}" + ProjectSection(SolutionItems) = preProject + config templates\access.xml = config templates\access.xml + aspnet35.config = aspnet35.config + config templates\config\UI.xml = config templates\config\UI.xml + config templates\umbraco.config = config templates\umbraco.config + config templates\web.config = config templates\web.config + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Packages", "Packages", "{5BB61485-B480-4A03-A8DD-1636A5AF575C}" + ProjectSection(SolutionItems) = preProject + config templates\packages\createdPackages.config = config templates\packages\createdPackages.config + config templates\packages\installedPackages.config = config templates\packages\installedPackages.config + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "config", "config", "{05329DB0-5C47-44A1-B7B8-BF377446BCD1}" + ProjectSection(SolutionItems) = preProject + config templates\config\404handlers.config = config templates\config\404handlers.config + config templates\config\Dashboard.config = config templates\config\Dashboard.config + config templates\config\formHandlers.config = config templates\config\formHandlers.config + config templates\config\metablogConfig.config = config templates\config\metablogConfig.config + config templates\config\restExtensions.config = config templates\config\restExtensions.config + config templates\config\tinyMceConfig.config = config templates\config\tinyMceConfig.config + config templates\config\umbracoSettings.config = config templates\config\umbracoSettings.config + config templates\config\UrlRewriting.config = config templates\config\UrlRewriting.config + config templates\config\xsltExtensions.config = config templates\config\xsltExtensions.config + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.presentation", "umbraco\presentation\umbraco.presentation.csproj", "{651E1350-91B6-44B7-BD60-7207006D7003}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.businesslogic", "umbraco\businesslogic\umbraco.businesslogic.csproj", "{E469A9CE-1BEC-423F-AC44-713CD72457EA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.cms", "umbraco\cms\umbraco.cms.csproj", "{CCD75EC3-63DB-4184-B49D-51C1DD337230}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.interfaces", "umbraco\interfaces\umbraco.interfaces.csproj", "{511F6D8D-7717-440A-9A57-A507E9A8B27F}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.editorControls", "components\editorControls\umbraco.editorControls.csproj", "{255F5DF1-4E43-4758-AC05-7A0B68EB021B}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.macroRenderings", "components\macroRenderings\umbraco.macroRenderings.csproj", "{52AB8F1F-FB76-4E8C-885F-0747B6CE71EC}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.standardFormhandlers", "components\standardFormhandlers\umbraco.standardFormhandlers.csproj", "{F58B68F8-AB7F-4559-A37F-6A00AD86365E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.providers", "umbraco\providers\umbraco.providers.csproj", "{D7636876-0756-43CB-A192-138C6F0D5E42}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.datalayer", "umbraco\datalayer\umbraco.datalayer.csproj", "{C7CB79F0-1C97-4B33-BFA7-00731B579AE2}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.controls", "components\umbraco.controls\umbraco.controls.csproj", "{6EDD2061-82F2-461B-BB6E-879245A832DE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.webservices", "components\umbraco.webservices\umbraco.webservices.csproj", "{CBDB56AC-FF02-4421-9FD4-ED82E339D8E2}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{58072405-85D0-45CA-8F5C-EA8928C32A6A}" + ProjectSection(SolutionItems) = preProject + docs\Umbraco 4 beta 2 update.docx = docs\Umbraco 4 beta 2 update.docx + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "umbraco.presentation.ClientDependency", "umbraco\presentation.ClientDependency\umbraco.presentation.ClientDependency.csproj", "{EA35B06D-0CC8-4830-A3F7-9BB3D36D0FAF}" +EndProject +Global + GlobalSection(TeamFoundationVersionControl) = preSolution + SccNumberOfProjects = 13 + SccEnterpriseProvider = {4CA58AB2-18FA-4F8D-95D4-32DDF27D184C} + SccTeamFoundationServer = https://tfs01.codeplex.com/ + SccLocalPath0 = . + SccProjectUniqueName1 = umbraco\\presentation\\umbraco.presentation.csproj + SccProjectName1 = umbraco/presentation + SccLocalPath1 = umbraco\\presentation + SccProjectUniqueName2 = umbraco\\businesslogic\\umbraco.businesslogic.csproj + SccProjectName2 = umbraco/businesslogic + SccLocalPath2 = umbraco\\businesslogic + SccProjectUniqueName3 = umbraco\\cms\\umbraco.cms.csproj + SccProjectName3 = umbraco/cms + SccLocalPath3 = umbraco\\cms + SccProjectUniqueName4 = umbraco\\interfaces\\umbraco.interfaces.csproj + SccProjectName4 = umbraco/interfaces + SccLocalPath4 = umbraco\\interfaces + SccProjectUniqueName5 = components\\editorControls\\umbraco.editorControls.csproj + SccProjectName5 = components/editorControls + SccLocalPath5 = components\\editorControls + SccProjectUniqueName6 = components\\macroRenderings\\umbraco.macroRenderings.csproj + SccProjectName6 = components/macroRenderings + SccLocalPath6 = components\\macroRenderings + SccProjectUniqueName7 = components\\standardFormhandlers\\umbraco.standardFormhandlers.csproj + SccProjectName7 = components/standardFormhandlers + SccLocalPath7 = components\\standardFormhandlers + SccProjectUniqueName8 = umbraco\\providers\\umbraco.providers.csproj + SccProjectName8 = umbraco/providers + SccLocalPath8 = umbraco\\providers + SccProjectUniqueName9 = umbraco\\datalayer\\umbraco.datalayer.csproj + SccProjectName9 = umbraco/datalayer + SccLocalPath9 = umbraco\\datalayer + SccProjectUniqueName10 = components\\umbraco.controls\\umbraco.controls.csproj + SccProjectName10 = components/umbraco.controls + SccLocalPath10 = components\\umbraco.controls + SccProjectUniqueName11 = components\\umbraco.webservices\\umbraco.webservices.csproj + SccProjectName11 = components/umbraco.webservices + SccLocalPath11 = components\\umbraco.webservices + SccProjectUniqueName12 = umbraco\\presentation.ClientDependency\\umbraco.presentation.ClientDependency.csproj + SccProjectName12 = umbraco/presentation.ClientDependency + SccLocalPath12 = umbraco\\presentation.ClientDependency + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {651E1350-91B6-44B7-BD60-7207006D7003}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {651E1350-91B6-44B7-BD60-7207006D7003}.Debug|Any CPU.Build.0 = Debug|Any CPU + {651E1350-91B6-44B7-BD60-7207006D7003}.Release|Any CPU.ActiveCfg = Release|Any CPU + {651E1350-91B6-44B7-BD60-7207006D7003}.Release|Any CPU.Build.0 = Release|Any CPU + {E469A9CE-1BEC-423F-AC44-713CD72457EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E469A9CE-1BEC-423F-AC44-713CD72457EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E469A9CE-1BEC-423F-AC44-713CD72457EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E469A9CE-1BEC-423F-AC44-713CD72457EA}.Release|Any CPU.Build.0 = Release|Any CPU + {CCD75EC3-63DB-4184-B49D-51C1DD337230}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CCD75EC3-63DB-4184-B49D-51C1DD337230}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CCD75EC3-63DB-4184-B49D-51C1DD337230}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CCD75EC3-63DB-4184-B49D-51C1DD337230}.Release|Any CPU.Build.0 = Release|Any CPU + {511F6D8D-7717-440A-9A57-A507E9A8B27F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {511F6D8D-7717-440A-9A57-A507E9A8B27F}.Debug|Any CPU.Build.0 = Debug|Any CPU + {511F6D8D-7717-440A-9A57-A507E9A8B27F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {511F6D8D-7717-440A-9A57-A507E9A8B27F}.Release|Any CPU.Build.0 = Release|Any CPU + {255F5DF1-4E43-4758-AC05-7A0B68EB021B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {255F5DF1-4E43-4758-AC05-7A0B68EB021B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {255F5DF1-4E43-4758-AC05-7A0B68EB021B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {255F5DF1-4E43-4758-AC05-7A0B68EB021B}.Release|Any CPU.Build.0 = Release|Any CPU + {52AB8F1F-FB76-4E8C-885F-0747B6CE71EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {52AB8F1F-FB76-4E8C-885F-0747B6CE71EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {52AB8F1F-FB76-4E8C-885F-0747B6CE71EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {52AB8F1F-FB76-4E8C-885F-0747B6CE71EC}.Release|Any CPU.Build.0 = Release|Any CPU + {F58B68F8-AB7F-4559-A37F-6A00AD86365E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F58B68F8-AB7F-4559-A37F-6A00AD86365E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F58B68F8-AB7F-4559-A37F-6A00AD86365E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F58B68F8-AB7F-4559-A37F-6A00AD86365E}.Release|Any CPU.Build.0 = Release|Any CPU + {D7636876-0756-43CB-A192-138C6F0D5E42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D7636876-0756-43CB-A192-138C6F0D5E42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D7636876-0756-43CB-A192-138C6F0D5E42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D7636876-0756-43CB-A192-138C6F0D5E42}.Release|Any CPU.Build.0 = Release|Any CPU + {C7CB79F0-1C97-4B33-BFA7-00731B579AE2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C7CB79F0-1C97-4B33-BFA7-00731B579AE2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C7CB79F0-1C97-4B33-BFA7-00731B579AE2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C7CB79F0-1C97-4B33-BFA7-00731B579AE2}.Release|Any CPU.Build.0 = Release|Any CPU + {6EDD2061-82F2-461B-BB6E-879245A832DE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6EDD2061-82F2-461B-BB6E-879245A832DE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6EDD2061-82F2-461B-BB6E-879245A832DE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6EDD2061-82F2-461B-BB6E-879245A832DE}.Release|Any CPU.Build.0 = Release|Any CPU + {CBDB56AC-FF02-4421-9FD4-ED82E339D8E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CBDB56AC-FF02-4421-9FD4-ED82E339D8E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CBDB56AC-FF02-4421-9FD4-ED82E339D8E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CBDB56AC-FF02-4421-9FD4-ED82E339D8E2}.Release|Any CPU.Build.0 = Release|Any CPU + {EA35B06D-0CC8-4830-A3F7-9BB3D36D0FAF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EA35B06D-0CC8-4830-A3F7-9BB3D36D0FAF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EA35B06D-0CC8-4830-A3F7-9BB3D36D0FAF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EA35B06D-0CC8-4830-A3F7-9BB3D36D0FAF}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {B8ECDB8B-BF44-462C-B6DA-22421B3EC4D7} = {F0242771-6DE6-4E03-BD3A-7B79BA79105B} + {58072405-85D0-45CA-8F5C-EA8928C32A6A} = {F0242771-6DE6-4E03-BD3A-7B79BA79105B} + {5BB61485-B480-4A03-A8DD-1636A5AF575C} = {B8ECDB8B-BF44-462C-B6DA-22421B3EC4D7} + {05329DB0-5C47-44A1-B7B8-BF377446BCD1} = {B8ECDB8B-BF44-462C-B6DA-22421B3EC4D7} + EndGlobalSection +EndGlobal diff --git a/umbraco.vssscc b/umbraco.vssscc new file mode 100644 index 0000000000..794f014c92 --- /dev/null +++ b/umbraco.vssscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROJECT" +} diff --git a/umbraco/businesslogic/App/Data.cs b/umbraco/businesslogic/App/Data.cs new file mode 100644 index 0000000000..b3085c0dcc --- /dev/null +++ b/umbraco/businesslogic/App/Data.cs @@ -0,0 +1,135 @@ + +namespace umbraco.businesslogic.app +{ + public class Data + { + public Data() + { + + } + + public Data(bool HasChildren, string App, string Id, string[] Actions, string Name, string IconOpen, string IconClosed, string Description, string Url, DataProperty[] Properties) + { + _hasChildren = HasChildren; + _app = App; + _id = Id; + _actions = Actions; + _name = Name; + _iconOpen = IconOpen; + _iconClosed = IconClosed; + _description = Description; + _url = Url; + _properties = Properties; + } + + private string _app; + + public string App + { + get { return _app; } + set { _app = value; } + } + + private string _id; + + public string Id + { + get { return _id; } + set { _id = value; } + } + + private string[] _actions; + + public string[] Actions + { + get { return _actions; } + set { _actions = value; } + } + + private string _name; + + public string Name + { + get { return _name; } + set { _name = value; } + } + + private bool _hasChildren; + + public bool HasChildren + { + get { return _hasChildren; } + set { _hasChildren = value; } + } + + private string _iconOpen; + + public string IconOpen + { + get { return _iconOpen; } + set { _iconOpen = value; } + } + + private string _iconClosed; + + public string IconClosed + { + get { return _iconClosed; } + set { _iconClosed = value; } + } + + private string _description; + + public string Description + { + get { return _description; } + set { _description = value; } + } + + private string _url; + + public string Url + { + get { return _url; } + set { _url = value; } + } + + private DataProperty[] _properties; + + public DataProperty[] Properties + { + get { return _properties; } + set { _properties = value; } + } + + } + + public class DataProperty + { + public DataProperty() {} + + public DataProperty(string Key, string Value) + { + _key = Key; + _value = Value; + } + + private string _key; + + public string Key + { + get { return _key; } + set { _key = value; } + } + + private string _value; + + public string Value + { + get { return _value; } + set { _value = value; } + } + + + } +} diff --git a/umbraco/businesslogic/Application.cs b/umbraco/businesslogic/Application.cs new file mode 100644 index 0000000000..c60b75efa8 --- /dev/null +++ b/umbraco/businesslogic/Application.cs @@ -0,0 +1,278 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Data.SqlClient; +using System.Web; +using umbraco.DataLayer; +using umbraco.interfaces; +using umbraco.BusinessLogic.Utils; + +namespace umbraco.BusinessLogic +{ + /// + /// Class for handling all registered applications in Umbraco. + /// + public class Application + { + //Applications found through reflection + private static readonly List _applications = new List(); + private static string _ConnString = GlobalSettings.DbDSN; + private static ISqlHelper _sqlHelper; + /*Use this declaration to log SQL queries: + private static ISqlHelper _sqlHelper= new SqlHelperExtender( + DataLayerHelper.CreateSqlHelper(_ConnString), + new Logger(@"c:\temp\sql.log"));*/ + + private const string CACHE_KEY = "ApplicationCache"; + + /// + /// The cache storage for all applications + /// + private static List Apps + { + get + { + //ensure cache exists + if (HttpRuntime.Cache[CACHE_KEY] == null) + ReCache(); + return HttpRuntime.Cache[CACHE_KEY] as List; + } + set + { + HttpRuntime.Cache.Insert(CACHE_KEY, value); + } + } + + private string _name; + private string _alias; + private string _icon; + + + /// + /// Gets the SQL helper. + /// + /// The SQL helper. + public static ISqlHelper SqlHelper + { + get + { + if (_sqlHelper == null) + { + try + { + _sqlHelper = DataLayerHelper.CreateSqlHelper(_ConnString); + } + catch { } + } + return _sqlHelper; + } + } + + /// + /// A static constructor that will cache all application trees + /// + static Application() + { + RegisterIApplications(); + Cache(); + } + + /// + /// Initializes a new instance of the class. + /// + public Application() + { } + + /// + /// Initializes a new instance of the class. + /// + /// The application name. + /// The application alias. + /// The application icon. + public Application(string name, string alias, string icon) + { + this.name = name; + this.alias = alias; + this.icon = icon; + } + + /// + /// Gets or sets the application name. + /// + /// The name. + public string name + { + get { return _name; } + set { _name = value; } + } + + /// + /// Gets or sets the application alias. + /// + /// The alias. + public string alias + { + get { return _alias; } + set { _alias = value; } + } + + /// + /// Gets or sets the application icon. + /// + /// The application icon. + public string icon + { + get { return _icon; } + set { _icon = value; } + } + + /// + /// Creates a new applcation if no application with the specified alias is found. + /// + /// The application name. + /// The application alias. + /// The application icon, which has to be located in umbraco/images/tray folder. + public static void MakeNew(string name, string alias, string icon) + { + bool exist = false; + foreach (Application app in getAll()) + { + if (app.alias == alias) + exist = true; + } + + if (!exist) + { + int sortOrder = (1 + SqlHelper.ExecuteScalar("SELECT MAX(sortOrder) FROM umbracoApp")); + + SqlHelper.ExecuteNonQuery(@" + insert into umbracoApp + (appAlias,appIcon,appName, sortOrder) + values (@alias,@icon,@name,@sortOrder)", + SqlHelper.CreateParameter("@alias", alias), + SqlHelper.CreateParameter("@icon", icon), + SqlHelper.CreateParameter("@name", name), + SqlHelper.CreateParameter("@sortOrder", sortOrder)); + + ReCache(); + } + + } + + + public static void MakeNew(IApplication Iapp, bool installAppTrees) { + + MakeNew(Iapp.Name, Iapp.Alias, Iapp.Icon); + + if (installAppTrees) { + + } + } + + + /// + /// Gets the application by its alias. + /// + /// The application alias. + /// + public static Application getByAlias(string appAlias) { + return Apps.Find( + delegate(Application t) { + return (t.alias == appAlias); + } + ); + + } + + /// + /// Deletes this instance. + /// + public void Delete() { + SqlHelper.ExecuteNonQuery("delete from umbracoApp where appAlias = @appAlias", + SqlHelper.CreateParameter("@appAlias", this._alias)); + + ReCache(); + } + + /// + /// Gets all applications registered in umbraco from the umbracoApp table.. + /// + /// Returns a Application Array + public static List getAll() + { + return Apps; + } + + /// + /// Stores all references to classes that are of type IApplication + /// + public static void RegisterIApplications() + { + if (GlobalSettings.Configured) { + + List types = TypeFinder.FindClassesOfType(false); + + foreach (Type t in types) { + try + { + IApplication typeInstance = Activator.CreateInstance(t) as IApplication; + if (typeInstance != null) + { + _applications.Add(typeInstance); + + if (HttpContext.Current != null) + HttpContext.Current.Trace.Write("registerIapplications", " + Adding application '" + typeInstance.Alias); + } + } + catch (Exception ee) { + Log.Add(LogTypes.Error, -1, "Error loading IApplication: " + ee.ToString()); + } + } + } + } + + /// + /// Removes the Application cache and re-reads the data from the db. + /// + private static void ReCache() + { + HttpRuntime.Cache.Remove(CACHE_KEY); + Cache(); + } + + /// + /// Read all Application data and store it in cache. + /// + private static void Cache() + { + //don't query the database is the cache is not null + if (HttpRuntime.Cache[CACHE_KEY] != null) + return; + + try + { + List tmp = new List(); + + using (IRecordsReader dr = + SqlHelper.ExecuteReader("Select appAlias, appIcon, appName from umbracoApp")) + { + while (dr.Read()) + { + tmp.Add(new Application(dr.GetString("appName"), dr.GetString("appAlias"), dr.GetString("appIcon"))); + } + } + + Apps = tmp; + } + catch + { + //this is a bit of a hack that just ensures the application doesn't crash when the + //installer is run and there is no database or connection string defined. + //the reason this method may get called during the installation is that the + //SqlHelper of this class is shared amongst everything "Application" wide. + } + + } + } +} diff --git a/umbraco/businesslogic/ApplicationBase.cs b/umbraco/businesslogic/ApplicationBase.cs new file mode 100644 index 0000000000..ceea2600cf --- /dev/null +++ b/umbraco/businesslogic/ApplicationBase.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace umbraco.BusinessLogic { + /// + /// ApplicationBase provides an easy to use base class to install event handlers in umbraco. + /// Class inhiriting from ApplcationBase are automaticly registered and instantiated by umbraco on application start. + /// To use, inhirite the ApplicationBase Class and add an empty constructor. + /// + public abstract class ApplicationBase : umbraco.interfaces.IApplication { + #region IApplication Members + + /// + /// Gets the application alias. By Default it returns the full name of the application class. + /// The Alias must be unique. + /// + /// The application alias. + public virtual string Alias{ + get { return GetType().FullName; } + } + + /// + /// Gets the application name. By default it returns the application Classname + /// + /// The name. + public virtual string Name { + get { return GetType().Name; } + } + + /// + /// Gets the application icon. For use with application installation which is currently not implemented. + /// The icon is a path to an image file in the /umbraco/images/tray folder + /// + /// The path to the application icon. + public virtual string Icon { + get { return string.Empty; } + } + + /// + /// Gets the application sortorder. For use with application installation which is currently not implemented. + /// Sets the sortorder for the Icon in the section tray. By default it returns the value 0 + /// + /// The sort order. + public virtual int SortOrder { + get { return 0; } + } + + /// + /// Gets the application visibility. For use with application installation which is currently not implemented. + /// Determines if the application is installed as a visible section in umbraco or just a service running. + /// + /// true if visible; otherwise, false. + public virtual bool Visible { + get { return false; } + } + + /// + /// The alias of a application tree to be initialized when section is opened in the backend. + /// Should only be set if a applcation tree needs to loaded right away. + /// + /// The init tree alias. + public virtual string InitTreeAlias { + get { return string.Empty; } + } + + /// + /// Collection of application trees. For use with application installation which is currently not implemented. + /// Contains the collection of application trees to be installed along with the application itself. + /// Return null by default. + /// + /// The application trees. + public virtual List ApplicationTrees { + get { return null; } + } + + #endregion + } +} diff --git a/umbraco/businesslogic/ApplicationTree.cs b/umbraco/businesslogic/ApplicationTree.cs new file mode 100644 index 0000000000..d37103320b --- /dev/null +++ b/umbraco/businesslogic/ApplicationTree.cs @@ -0,0 +1,385 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web; +using umbraco.DataLayer; + +namespace umbraco.BusinessLogic +{ + /// + /// umbraco.BusinessLogic.ApplicationTree provides access to the application tree structure in umbraco. + /// An application tree is a collection of nodes belonging to one or more application(s). + /// Through this class new application trees can be created, modified and deleted. + /// + public class ApplicationTree + { + + private const string CACHE_KEY = "ApplicationTreeCache"; + + /// + /// The cache storage for all application trees + /// + private static List AppTrees + { + get + { + //ensure cache exists + if (HttpRuntime.Cache[CACHE_KEY] == null) + ReCache(); + return HttpRuntime.Cache[CACHE_KEY] as List; + } + set + { + HttpRuntime.Cache.Insert(CACHE_KEY, value); + } + } + + private static string _ConnString = GlobalSettings.DbDSN; + private static ISqlHelper _sqlHelper = DataLayerHelper.CreateSqlHelper(_ConnString); + + /// + /// Gets the SQL helper. + /// + /// The SQL helper. + public static ISqlHelper SqlHelper + { + get { return _sqlHelper; } + } + + private bool _silent; + /// + /// Gets or sets a value indicating whether this is silent. + /// + /// true if silent; otherwise, false. + public bool Silent + { + get { return _silent; } + set { _silent = value; } + } + + private bool _initialize; + /// + /// Gets or sets a value indicating whether this should initialize. + /// + /// true if initialize; otherwise, false. + public bool Initialize + { + get { return _initialize; } + set { _initialize = value; } + } + + private byte _sortOrder; + /// + /// Gets or sets the sort order. + /// + /// The sort order. + public byte SortOrder + { + get { return _sortOrder; } + set { _sortOrder = value; } + } + + private string _applicationAlias; + /// + /// Gets the application alias. + /// + /// The application alias. + public string ApplicationAlias + { + get { return _applicationAlias; } + } + + private string _alias; + /// + /// Gets the tree alias. + /// + /// The alias. + public string Alias + { + get { return _alias; } + } + + private string _title; + /// + /// Gets or sets the tree title. + /// + /// The title. + public string Title + { + get { return _title; } + set { _title = value; } + } + + private string _iconClosed; + /// + /// Gets or sets the icon closed. + /// + /// The icon closed. + public string IconClosed + { + get { return _iconClosed; } + set { _iconClosed = value; } + } + + private string _iconOpened; + /// + /// Gets or sets the icon opened. + /// + /// The icon opened. + public string IconOpened + { + get { return _iconOpened; } + set { _iconOpened = value; } + } + + private string _assemblyName; + /// + /// Gets or sets the name of the assembly. + /// + /// The name of the assembly. + public string AssemblyName + { + get { return _assemblyName; } + set { _assemblyName = value; } + } + + private string _type; + /// + /// Gets or sets the tree type. + /// + /// The type. + public string Type + { + get { return _type; } + set { _type = value; } + } + + private string _action; + /// + /// Gets or sets the default tree action. + /// + /// The action. + public string Action + { + get { return _action; } + set { _action = value; } + } + + /// + /// A static constructor that will cache all application trees + /// + static ApplicationTree() + { + Cache(); + } + + /// + /// Initializes a new instance of the class. + /// + public ApplicationTree() { } + + + /// + /// Initializes a new instance of the class. + /// + /// if set to true [silent]. + /// if set to true [initialize]. + /// The sort order. + /// The application alias. + /// The tree alias. + /// The tree title. + /// The icon closed. + /// The icon opened. + /// Name of the assembly. + /// The tree type. + /// The default tree action. + public ApplicationTree(bool silent, bool initialize, byte sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string assemblyName, string type, string action) + { + this._silent = silent; + this._initialize = initialize; + this._sortOrder = sortOrder; + this._applicationAlias = applicationAlias; + this._alias = alias; + this._title = title; + this._iconClosed = iconClosed; + this._iconOpened = iconOpened; + this._assemblyName = assemblyName; + this._type = type; + this._action = action; + } + + + /// + /// Creates a new application tree. + /// + /// if set to true [silent]. + /// if set to true [initialize]. + /// The sort order. + /// The application alias. + /// The alias. + /// The title. + /// The icon closed. + /// The icon opened. + /// Name of the assembly. + /// The type. + /// The action. + public static void MakeNew(bool silent, bool initialize, byte sortOrder, string applicationAlias, string alias, string title, string iconClosed, string iconOpened, string assemblyName, string type, string action) + { + + SqlHelper.ExecuteNonQuery(@"insert into umbracoAppTree(treeSilent, treeInitialize, treeSortOrder, appAlias, treeAlias, treeTitle, + treeIconClosed, treeIconOpen, treeHandlerAssembly, treeHandlerType, action) + values(@treeSilent, @treeInitialize, @treeSortOrder, @appAlias, @treeAlias, @treeTitle, @treeIconClosed, @treeIconOpen, @treeHandlerAssembly, @treeHandlerType, @action)" + , + SqlHelper.CreateParameter("@treeSilent", silent), + SqlHelper.CreateParameter("@treeInitialize", initialize), + SqlHelper.CreateParameter("@treeSortOrder", sortOrder), + SqlHelper.CreateParameter("@treeAlias", alias), + SqlHelper.CreateParameter("@appAlias", applicationAlias), + SqlHelper.CreateParameter("@treeTitle", title), + SqlHelper.CreateParameter("@treeIconClosed", iconClosed), + SqlHelper.CreateParameter("@treeIconOpen", iconOpened), + SqlHelper.CreateParameter("@treeHandlerAssembly", assemblyName), + SqlHelper.CreateParameter("@treeHandlerType", type), + SqlHelper.CreateParameter("@action", action) + ); + + ReCache(); + } + + /// + /// Saves this instance. + /// + public void Save() + { + SqlHelper.ExecuteNonQuery(@"Update umbracoAppTree set treeSilent = @treeSilent, treeInitialize = @treeInitialize, treeSortOrder = @treeSortOrder, treeTitle = @treeTitle, + treeIconClosed = @treeIconClosed, treeIconOpen = @treeIconOpen, treeHandlerAssembly = @treeHandlerAssembly, treeHandlerType = @treeHandlerType, action = @action + where treeAlias = @treeAlias AND appAlias = @appAlias", + SqlHelper.CreateParameter("@treeSilent", this.Silent), + SqlHelper.CreateParameter("@treeInitialize", this.Initialize), + SqlHelper.CreateParameter("@treeSortOrder", this.SortOrder), + SqlHelper.CreateParameter("@treeTitle", this.Title), + SqlHelper.CreateParameter("@treeIconClosed", this.IconClosed), + SqlHelper.CreateParameter("@treeIconOpen", this.IconOpened), + SqlHelper.CreateParameter("@treeHandlerAssembly", this.AssemblyName), + SqlHelper.CreateParameter("@treeHandlerType", this.Type), + SqlHelper.CreateParameter("@treeAlias", this.Alias), + SqlHelper.CreateParameter("@appAlias", this.ApplicationAlias), + SqlHelper.CreateParameter("@action", this.Action) + ); + ReCache(); + } + + /// + /// Deletes this instance. + /// + public void Delete() + { + SqlHelper.ExecuteNonQuery("delete from umbracoAppTree where appAlias = @appAlias AND treeAlias = @treeAlias", + SqlHelper.CreateParameter("@appAlias", this.ApplicationAlias), SqlHelper.CreateParameter("@treeAlias", this.Alias)); + ReCache(); + } + + + /// + /// Gets an ApplicationTree by it's tree alias. + /// + /// The tree alias. + /// An ApplicationTree instance + public static ApplicationTree getByAlias(string treeAlias) + { + return AppTrees.Find( + delegate(ApplicationTree t) + { + return (t.Alias == treeAlias); + } + ); + + } + + /// + /// Gets all applicationTrees registered in umbraco from the umbracoAppTree table.. + /// + /// Returns a ApplicationTree Array + public static ApplicationTree[] getAll() + { + return AppTrees.ToArray(); + } + + /// + /// Gets the application tree for the applcation with the specified alias + /// + /// The application alias. + /// Returns a ApplicationTree Array + public static ApplicationTree[] getApplicationTree(string applicationAlias) + { + return getApplicationTree(applicationAlias, false); + } + + /// + /// Gets the application tree for the applcation with the specified alias + /// + /// The application alias. + /// + /// Returns a ApplicationTree Array + public static ApplicationTree[] getApplicationTree(string applicationAlias, bool onlyInitializedApplications) + { + List list = AppTrees.FindAll( + delegate(ApplicationTree t) + { + if (onlyInitializedApplications) + return (t.ApplicationAlias == applicationAlias && t.Initialize); + else + return (t.ApplicationAlias == applicationAlias); + } + ); + + return list.ToArray(); + } + + /// + /// Removes the ApplicationTree cache and re-reads the data from the db. + /// + private static void ReCache() + { + HttpRuntime.Cache.Remove(CACHE_KEY); + Cache(); + } + + /// + /// Read all ApplicationTree data and store it in cache. + /// + private static void Cache() + { + //don't query the database is the cache is not null + if (HttpRuntime.Cache[CACHE_KEY] != null) + return; + + List list = new List(); + + using (IRecordsReader dr = SqlHelper.ExecuteReader(@"Select treeSilent, treeInitialize, treeSortOrder, appAlias, treeAlias, treeTitle, treeIconClosed, + treeIconOpen, treeHandlerAssembly, treeHandlerType, action from umbracoAppTree order by treeSortOrder")) + { + while (dr.Read()) + { + + list.Add(new ApplicationTree( + dr.GetBoolean("treeSilent"), + dr.GetBoolean("treeInitialize"), + dr.GetByte("treeSortOrder"), + dr.GetString("appAlias"), + dr.GetString("treeAlias"), + dr.GetString("treeTitle"), + dr.GetString("treeIconClosed"), + dr.GetString("treeIconOpen"), + dr.GetString("treeHandlerAssembly"), + dr.GetString("treeHandlerType"), + dr.GetString("action"))); + + } + } + + AppTrees = list; + } + + } +} diff --git a/umbraco/businesslogic/AssemblyInfo.cs b/umbraco/businesslogic/AssemblyInfo.cs new file mode 100644 index 0000000000..177a4f0e70 --- /dev/null +++ b/umbraco/businesslogic/AssemblyInfo.cs @@ -0,0 +1,58 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.0.*")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/umbraco/businesslogic/BasePages/BasePage.cs b/umbraco/businesslogic/BasePages/BasePage.cs new file mode 100644 index 0000000000..68ec132df6 --- /dev/null +++ b/umbraco/businesslogic/BasePages/BasePage.cs @@ -0,0 +1,313 @@ +using System; +using System.Data; +using System.Web; + +using umbraco.BusinessLogic; +using umbraco.DataLayer; + +namespace umbraco.BasePages { + /// + /// umbraco.BasePages.BasePage is the default page type for the umbraco backend. + /// The basepage keeps track of the current user and the page context. But does not + /// Restrict access to the page itself. + /// The keep the page secure, the umbracoEnsuredPage class should be used instead + /// + public class BasePage : System.Web.UI.Page { + private User _user; + private bool _userisValidated = false; + private ClientTools m_clientTools; + + // ticks per minute 600,000,000 + private static long _ticksPrMinute = 600000000; + private static int _umbracoTimeOutInMinutes = GlobalSettings.TimeOutInMinutes; + + /// + /// The path to the umbraco root folder + /// + protected string UmbracoPath = GlobalSettings.Path; + + /// + /// The current user ID + /// + protected int uid = 0; + + /// + /// The page timeout in seconds. + /// + protected long timeout = 0; + + /// + /// Gets the SQL helper. + /// + /// The SQL helper. + protected static ISqlHelper SqlHelper { + get { return umbraco.BusinessLogic.Application.SqlHelper; } + } + + /// + /// Initializes a new instance of the class. + /// + public BasePage() { + } + + /// + /// Returns the current BasePage for the current request. + /// This assumes that the current page is a BasePage, otherwise, returns null; + /// + public static BasePage Current + { + get + { + return HttpContext.Current.CurrentHandler as BasePage; + } + } + + /// + /// Returns a refernce of an instance of ClientTools for access to the pages client API + /// + public ClientTools ClientTools + { + get + { + if (m_clientTools == null) + m_clientTools = new ClientTools(this); + return m_clientTools; + } + } + + [Obsolete("Use ClientTools instead")] + public void RefreshPage(int Seconds) + { + ClientTools.RefreshAdmin(Seconds); + } + + private void validateUser() { + if ((umbracoUserContextID != "")) { + uid = GetUserId(umbracoUserContextID); + timeout = GetTimeout(umbracoUserContextID); + + if (timeout > DateTime.Now.Ticks) { + _user = BusinessLogic.User.GetUser(uid); + + // Check for console access + if (_user.NoConsole && GlobalSettings.RequestIsInUmbracoApplication(HttpContext.Current) && !GlobalSettings.RequestIsLiveEditRedirector(HttpContext.Current)) + { + throw new ArgumentException("You have no priviledges to the umbraco console. Please contact your administrator"); + } + else + { + _userisValidated = true; + updateLogin(); + } + + } else { + throw new ArgumentException("User has timed out!!"); + } + } else + throw new ArgumentException("The user has no umbraco contextid - try logging in"); + } + + /// + /// Gets the user id. + /// + /// The umbraco user context ID. + /// + public static int GetUserId(string umbracoUserContextID) { + try { + if (System.Web.HttpRuntime.Cache["UmbracoUserContext" + umbracoUserContextID] == null) { + System.Web.HttpRuntime.Cache.Insert( + "UmbracoUserContext" + umbracoUserContextID, + SqlHelper.ExecuteScalar("select userID from umbracoUserLogins where contextID = @contextId", + SqlHelper.CreateParameter("@contextId", new Guid(umbracoUserContextID)) + ), + null, + System.Web.Caching.Cache.NoAbsoluteExpiration, + new TimeSpan(0, (int)(_umbracoTimeOutInMinutes / 10), 0)); + + + } + + return (int)System.Web.HttpRuntime.Cache["UmbracoUserContext" + umbracoUserContextID]; + + } catch { + return -1; + } + } + + + // Added by NH to use with webservices authentications + /// + /// Validates the user context ID. + /// + /// The umbraco user context ID. + /// + public static bool ValidateUserContextID(string umbracoUserContextID) { + if ((umbracoUserContextID != "")) { + int uid = GetUserId(umbracoUserContextID); + long timeout = GetTimeout(umbracoUserContextID); + + if (timeout > DateTime.Now.Ticks) { + return true; + } else { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Logout, BusinessLogic.User.GetUser(uid), -1, ""); + + return false; + } + } else + return false; + } + + private static long GetTimeout(string umbracoUserContextID) { + if (System.Web.HttpRuntime.Cache["UmbracoUserContextTimeout" + umbracoUserContextID] == null) { + System.Web.HttpRuntime.Cache.Insert( + "UmbracoUserContextTimeout" + umbracoUserContextID, + SqlHelper.ExecuteScalar("select timeout from umbracoUserLogins where contextId=@contextId", + SqlHelper.CreateParameter("@contextId", new Guid(umbracoUserContextID)) + ), + null, + DateTime.Now.AddMinutes(_umbracoTimeOutInMinutes / 10), System.Web.Caching.Cache.NoSlidingExpiration); + + + } + + return (long)System.Web.HttpRuntime.Cache["UmbracoUserContextTimeout" + umbracoUserContextID]; + + } + + // Changed to public by NH to help with webservice authentication + /// + /// Gets or sets the umbraco user context ID. + /// + /// The umbraco user context ID. + public static string umbracoUserContextID { + get { + if (System.Web.HttpContext.Current.Request.Cookies.Get("UserContext") != null) + return System.Web.HttpContext.Current.Request.Cookies.Get("UserContext").Value; + else + return ""; + } + set { + // Clearing all old cookies before setting a new one. + try { + if (System.Web.HttpContext.Current.Request.Cookies["UserContext"] != null) { + System.Web.HttpContext.Current.Response.Cookies.Clear(); + } + } catch { + } + // Create new cookie. + System.Web.HttpCookie c = new System.Web.HttpCookie("UserContext"); + c.Name = "UserContext"; + c.Value = value; + c.Expires = DateTime.Now.AddDays(1); + System.Web.HttpContext.Current.Response.Cookies.Add(c); + } + } + + + /// + /// Clears the login. + /// + public void ClearLogin() { + umbracoUserContextID = ""; + } + + private void updateLogin() { + // only call update if more than 1/10 of the timeout has passed + if (timeout - (((_ticksPrMinute * _umbracoTimeOutInMinutes) * 0.8)) < DateTime.Now.Ticks) + SqlHelper.ExecuteNonQuery( + "UPDATE umbracoUserLogins SET timeout = @timeout WHERE contextId = @contextId", + SqlHelper.CreateParameter("@timeout", DateTime.Now.Ticks + (_ticksPrMinute * _umbracoTimeOutInMinutes)), + SqlHelper.CreateParameter("@contextId", umbracoUserContextID)); + } + + /// + /// Logs a user in. + /// + /// The user + public static void doLogin(User u) { + Guid retVal = Guid.NewGuid(); + SqlHelper.ExecuteNonQuery( + "insert into umbracoUserLogins (contextID, userID, timeout) values (@contextId,'" + u.Id + "','" + + (DateTime.Now.Ticks + (_ticksPrMinute * _umbracoTimeOutInMinutes)).ToString() + + "') ", + SqlHelper.CreateParameter("@contextId", retVal)); + umbracoUserContextID = retVal.ToString(); + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Login, u, -1, ""); + } + + + /// + /// Gets the user. + /// + /// + public User getUser() { + if (!_userisValidated) validateUser(); + return _user; + } + + /// + /// Ensures the page context. + /// + public void ensureContext() { + validateUser(); + } + + [Obsolete("Use ClientTools instead")] + public void speechBubble(speechBubbleIcon i, string header, string body) + { + ClientTools.ShowSpeechBubble(i, header, body); + } + + //[Obsolete("Use ClientTools instead")] + //public void reloadParentNode() + //{ + // ClientTools.ReloadParentNode(true); + //} + + /// + /// a collection of available speechbubble icons + /// + public enum speechBubbleIcon { + /// + /// Save icon + /// + save, + /// + /// Info icon + /// + info, + /// + /// Error icon + /// + error, + /// + /// Success icon + /// + success, + /// + /// Warning icon + /// + warning + } + + /// + /// Raises the event. + /// + /// The object that contains the event data. + protected override void OnLoad(EventArgs e) { + base.OnLoad(e); + if (OverrideClientTarget) + ClientTarget = "uplevel"; + + if (!Request.IsSecureConnection && GlobalSettings.UseSSL) { + string serverName = HttpUtility.UrlEncode(Request.ServerVariables["SERVER_NAME"]); + Response.Redirect(string.Format("https://{0}{1}", serverName, Request.FilePath)); + } + } + + /// + /// Override client target. + /// + public bool OverrideClientTarget = true; + } +} diff --git a/umbraco/businesslogic/BasePages/ClientTools.cs b/umbraco/businesslogic/BasePages/ClientTools.cs new file mode 100644 index 0000000000..50a42e3b59 --- /dev/null +++ b/umbraco/businesslogic/BasePages/ClientTools.cs @@ -0,0 +1,242 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web; +using umbraco.BasePages; +using System.Web.UI; + +namespace umbraco.BasePages +{ + + /// + /// Renders the client side code necessary to interact with the Umbraco client side API. + /// Each method returns an instance of this class so you can chain calls together. + /// + public sealed class ClientTools + { + + public ClientTools(Page page) + { + m_page = page; + } + + /// + /// Returns the string markup for the JavaScript that is rendered. + /// If referencing JavaScript scripts in the backend, this class should be used + /// in case future changes to the client code is change, this will remain intact. + /// + public static class Scripts + { + internal const string ClientMgrScript = "UmbClientMgr"; + public static string GetAppActions { get { return string.Format("{0}.appActions()", ClientMgrScript); } } + public static string GetMainWindow { get { return string.Format("{0}.mainWindow()", ClientMgrScript); } } + public static string GetMainTree { get { return string.Format("{0}.mainTree()", ClientMgrScript); } } + public static string GetContentFrame() { return string.Format("{0}.contentFrame()", ClientMgrScript); } + public static string ShiftApp(string appAlias, string appName, bool ignoreDashboard) + { + return string.Format(GetAppActions + ".shiftApp('{0}','{1}',{2})", appAlias, appName, ignoreDashboard.ToString().ToLower()); + } + public static string OpenDashboard(string app) + { + return string.Format(GetAppActions + ".openDashboard('{0}');", app); + } + public static string RefreshAdmin { get { return "setTimeout('" + GetMainWindow + ".location.reload()', {0});"; } } + public static string ShowSpeechBubble { get { return GetMainWindow + ".UmbSpeechBubble.ShowMessage('{0}','{1}', '{2}');"; } } + public static string ChangeContentFrameUrl(string url) { + return string.Format(ClientMgrScript + ".contentFrame('{0}');", url); + } + public static string ChildNodeCreated = GetMainTree + ".childNodeCreated();"; + public static string SyncTree { get { return GetMainTree + ".syncTree('{0}', {1});"; } } + public static string ReloadActionNode { get { return GetMainTree + ".reloadActionNode({0}, {1}, null);"; } } + public static string SetActiveTreeType { get { return GetMainTree + ".setActiveTreeType('{0}');"; } } + public static string CloseModalWindow { get { return GetMainWindow + ".closeModal();"; } } + public static string OpenModalWindow(string url, string name, int height, int width) + { + return string.Format(GetMainWindow + ".openModal('{0}','{1}',{2},{3});", url, name, height, width); + } + } + + private Page m_page; + + /// + /// Change applications + /// + /// + /// + /// if true, will not load the dashboard for the specified application + /// + public ClientTools ShiftApp(string appAlias, string appName, bool ignoreDashboard) + { + RegisterClientScript(Scripts.ShiftApp(appAlias, appName, ignoreDashboard)); + return this; + } + + /// + /// Refresh the entire administration console after a specified amount of time. + /// + /// + /// + public ClientTools RefreshAdmin(int seconds) + { + RegisterClientScript(string.Format(Scripts.RefreshAdmin, seconds * 1000)); + return this; + } + + /// + /// A reference to the umbraco UI component "speechbubble". The speechbubble appears in the lower right corner of the screen, notifying users of events + /// + /// The speechbubble icon. + /// The speechbubble header. + /// The body text + public ClientTools ShowSpeechBubble(BasePage.speechBubbleIcon i, string header, string body) + { + RegisterClientScript(string.Format(Scripts.ShowSpeechBubble, i.ToString(), header.Replace("'", "\\'"), body.Replace("'", "\\'"))); + return this; + } + + /// + /// Changes the content in the content frame to the specified URL + /// + /// + public ClientTools ChangeContentFrameUrl(string url) + { + //don't load if there is no url + if (string.IsNullOrEmpty(url)) return this; + + if (!url.StartsWith("/") || !url.StartsWith(GlobalSettings.Path)) + { + url = GlobalSettings.Path + "/" + url; + } + RegisterClientScript(Scripts.ChangeContentFrameUrl(url)); + return this; + } + + /// + /// Reloads the children of the current action node and selects the node that didn't exist there before. + /// If the client side system cannot determine which node is new, then no node is selected. + /// + /// + /// This is used by many create dialogs, however the sync method should be used based on the full path of the + /// node but because the current Umbraco implementation of ITask only returns a url to load, there's no way + /// to determine what the full path of the new child is. + /// + /// + public ClientTools ChildNodeCreated() + { + RegisterClientScript(Scripts.ChildNodeCreated); + return this; + } + + /// + /// Synchronizes the tree to the path specified. + /// + /// + /// + /// If set to true, will ensure that the node to be synced has it's data + /// reloaded from the server. Otherwise, if the node already exists, the tree will simply sync to the node + /// that is already there. + /// + /// + /// This will work for any tree, however you would need to know the path of the node. Currently, media and content + /// are the only trees that store a path, however, if you were working in the template tree for example, a path to a + /// node could be "init,1090" and this method would still work. + /// + /// Sync tree will works by syncing the active tree type. This can be specified explicitly by calling SetActiveTreeType. + /// This will allow developers to sync many trees in one application at one time if needed. + /// + /// + /// + /// + public ClientTools SyncTree(string path, bool forceReload) + { + RegisterClientScript(string.Format(Scripts.SyncTree, path, forceReload.ToString().ToLower())); + return this; + } + + /// + /// Reloads only the active node in the tree. + /// + /// + /// + /// + /// If for whatever reason the client side system cannot just refresh the one node, the system will use jsTree's built in + /// refresh tool, this however won't allow for reselect or reloadChildren. Most trees will work with the single node + /// refresh but 3rd party tools may have poorly built tree data models. + /// + public ClientTools ReloadActionNode(bool reselect, bool reloadChildren) + { + RegisterClientScript(string.Format(Scripts.ReloadActionNode, (!reselect).ToString().ToLower(), (!reloadChildren).ToString().ToLower())); + return this; + } + + /// + /// When the application searches for a node, it searches for nodes in specific tree types. + /// If SyncTree is used, it will sync the tree nodes with the active tree type, therefore if + /// a developer wants to sync a specific tree, they can call this method to set the type to sync. + /// + /// + /// Each branch of a particular tree should theoretically be the same type, however, developers can + /// override the type of each branch in their BaseTree's but this is not standard practice. If there + /// are multiple types of branches in one tree, then only those branches that have the Active tree type + /// will be searched for syncing. + /// + /// + /// + public ClientTools SetActiveTreeType(string treeType) + { + RegisterClientScript(string.Format(Scripts.SetActiveTreeType, treeType)); + return this; + } + + /// + /// Closes the Umbraco dialog window if it is open + /// + public ClientTools CloseModalWindow() + { + RegisterClientScript(Scripts.CloseModalWindow); + return this; + } + + /// + /// Opens a modal window + /// + /// + /// + /// + /// + /// + public ClientTools OpenModalWindow(string url, string name, int height, int width) + { + RegisterClientScript(Scripts.OpenModalWindow(url, name, height, width)); + return this; + } + + + + private Page GetCurrentPage() + { + return HttpContext.Current.CurrentHandler as Page; + } + + private void RegisterClientScript(string script) + { + //use the hash code of the script to generate the key, this way, the exact same script won't be + //inserted more than once. + //m_page.ClientScript.RegisterClientScriptBlock(m_page.GetType(), script.GetHashCode().ToString(), script, true); + m_page.ClientScript.RegisterStartupScript(m_page.GetType(), script.GetHashCode().ToString(), script, true); + + } + + + + + } +} diff --git a/umbraco/businesslogic/BasePages/DialogPage.cs b/umbraco/businesslogic/BasePages/DialogPage.cs new file mode 100644 index 0000000000..8c7e5c5d87 --- /dev/null +++ b/umbraco/businesslogic/BasePages/DialogPage.cs @@ -0,0 +1,17 @@ +using System; + +namespace umbraco.BasePages +{ + /// + /// Summary description for DialogPage. + /// + public class DialogPage + { + public DialogPage() + { + // + // TODO: Add constructor logic here + // + } + } +} diff --git a/umbraco/businesslogic/BasePages/UmbracoBasePage.cs b/umbraco/businesslogic/BasePages/UmbracoBasePage.cs new file mode 100644 index 0000000000..6085437213 --- /dev/null +++ b/umbraco/businesslogic/BasePages/UmbracoBasePage.cs @@ -0,0 +1,93 @@ +using System; +using umbraco.BusinessLogic; + +namespace umbraco.BasePages +{ + /// + /// UmbracoEnsuredPage is the standard protected page in the umbraco backend, and forces authentication. + /// + public class UmbracoEnsuredPage : BasePage + { + /// + /// Initializes a new instance of the class. + /// + public UmbracoEnsuredPage() + { + + } + + private bool _redirectToUmbraco; + /// + /// If true then umbraco will force any window/frame to reload umbraco in the main window + /// + public bool RedirectToUmbraco + { + get { return _redirectToUmbraco; } + set { _redirectToUmbraco = value; } + } + + /// + /// Validates the user for access to a certain application + /// + /// The application alias. + /// + public bool ValidateUserApp(string app) + { + + foreach(Application uApp in getUser().Applications) + if (uApp.alias == app) + return true; + return false; + } + + /// + /// Validates the user node tree permissions. + /// + /// The path. + /// The action. + /// + public bool ValidateUserNodeTreePermissions(string Path, string Action) + { + string permissions = getUser().GetPermissions(Path); + if (permissions.IndexOf(Action) > -1 && (Path.Contains("-20") || (","+Path+",").Contains("," + getUser().StartNodeId.ToString() + ","))) + return true; + + Log.Add(LogTypes.LoginFailure, getUser(), -1, "Insufient permissions in UmbracoEnsuredPage: '" + Path + "', '" + permissions + "', '" + Action + "'"); + return false; + } + + /// + /// Gets the current user. + /// + /// The current user. + public static BusinessLogic.User CurrentUser { + get + { + return BusinessLogic.User.GetCurrent(); + } + } + + /// + /// Raises the event to initialize the page. + /// + /// An that contains the event data. + protected override void OnInit(EventArgs e) + { + base.OnInit (e); + try { + ensureContext(); + } + catch + { + // Some umbraco pages should not be loaded on timeout, but instead reload the main application in the top window. Like the treeview for instance + if (RedirectToUmbraco) + Response.Redirect(GlobalSettings.Path+"/logout.aspx?"); + else + Response.Redirect(GlobalSettings.Path + "/logout.aspx?redir=" + Server.UrlEncode(Request.RawUrl)); + } + + System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(ui.Culture(this.getUser())); + System.Threading.Thread.CurrentThread.CurrentUICulture = System.Threading.Thread.CurrentThread.CurrentCulture; + } + } +} \ No newline at end of file diff --git a/umbraco/businesslogic/CacheHelper.cs b/umbraco/businesslogic/CacheHelper.cs new file mode 100644 index 0000000000..243da8eadd --- /dev/null +++ b/umbraco/businesslogic/CacheHelper.cs @@ -0,0 +1,31 @@ +//using System; +//using System.Web.Caching; + +//namespace umbraco.BusinessLogic +//{ +// internal class CacheHelper +// { +// public delegate TT GetCacheItemDelegate(); +// public static TT GetCacheItem(string cacheKey, object syncLock, +// CacheItemPriority priority, CacheItemRemovedCallback refreshAction, +// CacheDependency cacheDependency, TimeSpan timeout, GetCacheItemDelegate getCacheItem) +// { +// object result = System.Web.HttpRuntime.Cache.Get(cacheKey); +// if (result == null) +// { +// lock (syncLock) +// { +// result = System.Web.HttpRuntime.Cache.Get(cacheKey); +// if (result == null) +// { +// result = getCacheItem(); +// System.Web.HttpRuntime.Cache.Add(cacheKey, result, cacheDependency, +// DateTime.Now.Add(timeout), TimeSpan.Zero, priority, refreshAction); +// } +// } +// } +// return (TT)result; +// } + +// } +//} diff --git a/umbraco/businesslogic/GlobalSettings.cs b/umbraco/businesslogic/GlobalSettings.cs new file mode 100644 index 0000000000..25d54d9a77 --- /dev/null +++ b/umbraco/businesslogic/GlobalSettings.cs @@ -0,0 +1,821 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Web; +using System.Xml; + +using umbraco.BusinessLogic; + +namespace umbraco +{ + /// + /// The GlobalSettings Class contains general settings information for the entire Umbraco instance based on information from web.config appsettings + /// + public class GlobalSettings + { + #region Private static fields + // CURRENT UMBRACO VERSION ID + private static string _currentVersion = "4.0.2.1"; + + private static string _reservedUrlsCache; + private static string _reservedPathsCache; + private static StartsWithContainer _reservedList = new StartsWithContainer(); + #endregion + + /// + /// Initializes a new instance of the class. + /// + public GlobalSettings() + { + } + + /// + /// Gets the reserved urls from web.config. + /// + /// The reserved urls. + public static string ReservedUrls + { + get + { + if (HttpContext.Current != null) + return ConfigurationManager.AppSettings["umbracoReservedUrls"]; + return String.Empty; + } + } + + /// + /// Gets the reserved paths from web.config + /// + /// The reserved paths. + public static string ReservedPaths + { + get + { + if (HttpContext.Current != null) + return ConfigurationManager.AppSettings["umbracoReservedPaths"]; + return String.Empty; + } + } + + /// + /// Gets the name of the content XML file. + /// + /// The content XML. + public static string ContentXML + { + get + { + try + { + return ConfigurationManager.AppSettings["umbracoContentXML"]; + } + catch + { + return String.Empty; + } + } + } + + /// + /// Gets the path to the storage directory (/data by default). + /// + /// The storage directory. + public static string StorageDirectory + { + get + { + try + { + return ConfigurationManager.AppSettings["umbracoStorageDirectory"]; + } + catch + { + return String.Empty; + } + } + } + + /// + /// Gets the path to umbraco's root directory (/umbraco by default). + /// + /// The path. + public static string Path + { + get + { + try + { + return ConfigurationManager.AppSettings["umbracoPath"]; + } + catch + { + return String.Empty; + } + } + } + + /// + /// Gets the database connection string + /// + /// The database connection string. + public static string DbDSN + { + get + { + try + { + return ConfigurationManager.AppSettings["umbracoDbDSN"]; + } + catch + { + return String.Empty; + } + } + set + { + if(DbDSN!=value) + SaveSetting("umbracoDbDSN", value); + } + } + + /// + /// Gets or sets the configuration status. This will return the version number of the currently installed umbraco instance. + /// + /// The configuration status. + public static string ConfigurationStatus + { + get + { + try + { + return ConfigurationManager.AppSettings["umbracoConfigurationStatus"]; + } + catch + { + return String.Empty; + } + } + set + { + SaveSetting("umbracoConfigurationStatus", value); + } + } + + private static AspNetHostingPermissionLevel m_ApplicationTrustLevel; + public static AspNetHostingPermissionLevel ApplicationTrustLevel { + get{ + if (m_ApplicationTrustLevel != AspNetHostingPermissionLevel.None) { + + foreach (AspNetHostingPermissionLevel trustLevel in + new AspNetHostingPermissionLevel[] { + AspNetHostingPermissionLevel.Unrestricted, + AspNetHostingPermissionLevel.High, + AspNetHostingPermissionLevel.Medium, + AspNetHostingPermissionLevel.Low, + AspNetHostingPermissionLevel.Minimal + }) { + try { + new AspNetHostingPermission(trustLevel).Demand(); + } catch (System.Security.SecurityException) { + continue; + } + + m_ApplicationTrustLevel = trustLevel; + } + + m_ApplicationTrustLevel = AspNetHostingPermissionLevel.None; + } + + return m_ApplicationTrustLevel; + } + } + + + /// + /// Forces umbraco to be medium trust compatible + /// + /// If true, umbraco will be medium-trust compatible, no matter what Permission level the server is on. + public static bool UseMediumTrust { + get { + try { + if (ApplicationTrustLevel == AspNetHostingPermissionLevel.High || ApplicationTrustLevel == AspNetHostingPermissionLevel.Unrestricted) + return false; + else + return bool.Parse(ConfigurationManager.AppSettings["umbracoUseMediumTrust"]); + }catch { + return false; + } + } + } + + /// + /// Saves a setting into the configuration file. + /// + /// Key of the setting to be saved. + /// Value of the setting to be saved. + protected static void SaveSetting(string key, string value) + { + ExeConfigurationFileMap webConfig = new ExeConfigurationFileMap(); + webConfig.ExeConfigFilename = FullpathToRoot + "web.config"; + + Configuration config = + ConfigurationManager.OpenMappedExeConfiguration(webConfig, ConfigurationUserLevel.None); + config.AppSettings.Settings[key].Value = value; + config.Save(); + ConfigurationManager.RefreshSection("appSettings"); + } + + /// + /// Gets the full path to root. + /// + /// The fullpath to root. + public static string FullpathToRoot + { + get { return HttpRuntime.AppDomainAppPath; } + } + + /// + /// Stats database connection string. This can be used instead of the normal umbraco connection string to store umbracoStats data. + /// + /// The stat db DSN. + public static string StatDbDSN + { + get + { + string statdb = ConfigurationManager.AppSettings["umbracoStatDbDSN"]; + if (string.IsNullOrEmpty(statdb)) + return DbDSN; + return statdb.Trim(); + } + } + + /// + /// Gets a value indicating whether umbraco is running in [debug mode]. + /// + /// true if [debug mode]; otherwise, false. + public static bool DebugMode + { + get + { + try + { + return bool.Parse(ConfigurationManager.AppSettings["umbracoDebugMode"]); + } + catch + { + return false; + } + } + } + + /// + /// Gets a value indicating whether the current version of umbraco is configured. + /// + /// true if configured; otherwise, false. + public static bool Configured + { + get + { + try + { + string configStatus = ConfigurationStatus; + string currentVersion = CurrentVersion; + + + if (currentVersion != configStatus) + Log.Add(LogTypes.Debug, User.GetUser(0), -1, + "CurrentVersion different from configStatus: '" + currentVersion + "','" + configStatus + + "'"); + + return (configStatus == currentVersion); + } + catch + { + return false; + } + } + } + + /// + /// Gets the time out in minutes. + /// + /// The time out in minutes. + public static int TimeOutInMinutes + { + get + { + try + { + return int.Parse(ConfigurationManager.AppSettings["umbracoTimeOutInMinutes"]); + } + catch + { + return 20; + } + } + } + + /// + /// Gets a value indicating whether umbraco uses directory urls. + /// + /// true if umbraco uses directory urls; otherwise, false. + public static bool UseDirectoryUrls + { + get + { + try + { + return bool.Parse(ConfigurationManager.AppSettings["umbracoUseDirectoryUrls"]); + } + catch + { + return false; + } + } + } + + /// + /// Returns a string value to determine if umbraco should skip version-checking. + /// + /// The version check period in days (0 = never). + public static int VersionCheckPeriod + { + get + { + int versionCheckPeriod = 7; + if (HttpContext.Current != null) + { + if (int.TryParse(ConfigurationManager.AppSettings["umbracoVersionCheckPeriod"], out versionCheckPeriod)) + return versionCheckPeriod; + + } + return versionCheckPeriod; + } + } + + /// + /// Gets the URL forbitten characters. + /// + /// The URL forbitten characters. + public static string UrlForbittenCharacters + { + get + { + if (HttpContext.Current != null) + return ConfigurationManager.AppSettings["umbracoUrlForbittenCharacters"]; + return ""; + } + } + + /// + /// Gets the URL space character. + /// + /// The URL space character. + public static string UrlSpaceCharacter + { + get + { + if (HttpContext.Current != null) + return ConfigurationManager.AppSettings["umbracoUrlSpaceCharacter"]; + return ""; + } + } + + /// + /// Gets the SMTP server IP-address or hostname. + /// + /// The SMTP server. + public static string SmtpServer + { + get + { + try + { + System.Net.Configuration.MailSettingsSectionGroup mailSettings = ConfigurationManager.GetSection("system.net/mailSettings") as System.Net.Configuration.MailSettingsSectionGroup; + + if (mailSettings != null) + return mailSettings.Smtp.Network.Host; + else + return ConfigurationManager.AppSettings["umbracoSmtpServer"]; + } + catch + { + return ""; + } + } + } + + /// + /// Returns a string value to determine if umbraco should disbable xslt extensions + /// + /// "true" if version xslt extensions are disabled, otherwise, "false" + public static string DisableXsltExtensions + { + get + { + if (HttpContext.Current != null) + return ConfigurationManager.AppSettings["umbracoDisableXsltExtensions"]; + return ""; + } + } + + /// + /// Returns a string value to determine if umbraco should use Xhtml editing mode in the wysiwyg editor + /// + /// "true" if Xhtml mode is enable, otherwise, "false" + public static string EditXhtmlMode + { + get + { + if (HttpContext.Current != null) + return ConfigurationManager.AppSettings["umbracoEditXhtmlMode"]; + return ""; + } + } + + /// + /// Gets the default UI language. + /// + /// The default UI language. + public static string DefaultUILanguage + { + get + { + if (HttpContext.Current != null) + return ConfigurationManager.AppSettings["umbracoDefaultUILanguage"]; + return ""; + } + } + + /// + /// Gets the profile URL. + /// + /// The profile URL. + public static string ProfileUrl + { + get + { + if (HttpContext.Current != null) + return ConfigurationManager.AppSettings["umbracoProfileUrl"]; + return ""; + } + } + + /// + /// Gets a value indicating whether umbraco should hide top level nodes from generated urls. + /// + /// + /// true if umbraco hides top level nodes from urls; otherwise, false. + /// + public static bool HideTopLevelNodeFromPath + { + get + { + if (HttpContext.Current != null) + return bool.Parse(ConfigurationManager.AppSettings["umbracoHideTopLevelNodeFromPath"]); + return false; + } + } + + /// + /// Gets a value indicating whether stat is enabled. + /// + /// true if enabled; otherwise, false. + public static bool EnableStat + { + get + { + string value = ConfigurationManager.AppSettings["umbracoEnableStat"]; + bool result; + if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result)) + return result; + return false; + } + } + + /// + /// Gets a value indicating whether statistic logging happens async. + /// + /// true if async stats logging is enabled; otherwise, false. + public static bool EnableAsyncStatLogging { + get { + string value = ConfigurationManager.AppSettings["umbracoAsyncStatLogging"]; + bool result; + if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result)) + return result; + return false; + } + } + + /// + /// Gets the current version. + /// + /// The current version. + public static string CurrentVersion + { + get + { + // change this to be hardcoded in the binary + return _currentVersion; + } + } + + /// + /// Gets the major version number. + /// + /// The major version number. + public static int VersionMajor + { + get + { + string[] version = CurrentVersion.Split(".".ToCharArray()); + return int.Parse(version[0]); + } + } + + /// + /// Gets the minor version number. + /// + /// The minor version number. + public static int VersionMinor + { + get + { + string[] version = CurrentVersion.Split(".".ToCharArray()); + return int.Parse(version[1]); + } + } + + /// + /// Gets the patch version number. + /// + /// The patch version number. + public static int VersionPatch + { + get + { + string[] version = CurrentVersion.Split(".".ToCharArray()); + return int.Parse(version[2]); + } + } + + /// + /// Gets the version comment (like beta or RC). + /// + /// The version comment. + public static string VersionComment + { + get + { + string[] version = CurrentVersion.Split(".".ToCharArray()); + if (version.Length > 3) + return version[3]; + else + return ""; + } + } + + + /// + /// Requests the is in umbraco application directory structure. + /// + /// The context. + /// + public static bool RequestIsInUmbracoApplication(HttpContext context) + { + return context.Request.Path.ToLower().IndexOf(GlobalSettings.Path.ToLower()) > -1; + } + + public static bool RequestIsLiveEditRedirector(HttpContext context) + { + return context.Request.Path.ToLower().IndexOf(GlobalSettings.Path.ToLower() + "/liveediting.aspx") > -1; + } + + /// + /// Gets a value indicating whether umbraco should force a secure (https) connection to the backoffice. + /// + /// true if [use SSL]; otherwise, false. + public static bool UseSSL + { + get + { + try + { + return bool.Parse(ConfigurationManager.AppSettings["umbracoUseSSL"]); + } + catch + { + return false; + } + } + } + + /// + /// Gets the umbraco license. + /// + /// The license. + public static string License + { + get + { + string license = + "the open source license MIT. The umbraco UI is freeware licensed under the umbraco license."; + if (HttpContext.Current != null) + { + XmlDocument versionDoc = new XmlDocument(); + XmlTextReader versionReader = + new XmlTextReader(HttpContext.Current.Server.MapPath(Path + "/version.xml")); + versionDoc.Load(versionReader); + versionReader.Close(); + + // check for license + try + { + string licenseUrl = + versionDoc.SelectSingleNode("/version/licensing/licenseUrl").FirstChild.Value; + string licenseValidation = + versionDoc.SelectSingleNode("/version/licensing/licenseValidation").FirstChild.Value; + string licensedTo = + versionDoc.SelectSingleNode("/version/licensing/licensedTo").FirstChild.Value; + + if (licensedTo != "" && licenseUrl != "") + { + license = "umbraco Commercial License
Registered to:
" + + licensedTo.Replace("\n", "
") + "
For use with domain:
" + + licenseUrl; + } + } + catch + { + } + } + return license; + } + } + + + /// + /// Developer method to test if configuration settings are loaded properly. + /// + /// true if succesfull; otherwise, false. + public static bool test + { + get + { + try + { + HttpContext.Current.Response.Write("ContentXML :" + ContentXML + "\n"); + HttpContext.Current.Response.Write("DbDSN :" + DbDSN + "\n"); + HttpContext.Current.Response.Write("DebugMode :" + DebugMode + "\n"); + HttpContext.Current.Response.Write("DefaultUILanguage :" + DefaultUILanguage + "\n"); + HttpContext.Current.Response.Write("VersionCheckPeriod :" + VersionCheckPeriod + "\n"); + HttpContext.Current.Response.Write("DisableXsltExtensions :" + DisableXsltExtensions + "\n"); + HttpContext.Current.Response.Write("EditXhtmlMode :" + EditXhtmlMode + "\n"); + HttpContext.Current.Response.Write("HideTopLevelNodeFromPath :" + HideTopLevelNodeFromPath + "\n"); + HttpContext.Current.Response.Write("Path :" + Path + "\n"); + HttpContext.Current.Response.Write("ProfileUrl :" + ProfileUrl + "\n"); + HttpContext.Current.Response.Write("ReservedPaths :" + ReservedPaths + "\n"); + HttpContext.Current.Response.Write("ReservedUrls :" + ReservedUrls + "\n"); + HttpContext.Current.Response.Write("StorageDirectory :" + StorageDirectory + "\n"); + HttpContext.Current.Response.Write("TimeOutInMinutes :" + TimeOutInMinutes + "\n"); + HttpContext.Current.Response.Write("UrlForbittenCharacters :" + UrlForbittenCharacters + "\n"); + HttpContext.Current.Response.Write("UrlSpaceCharacter :" + UrlSpaceCharacter + "\n"); + HttpContext.Current.Response.Write("UseDirectoryUrls :" + UseDirectoryUrls + "\n"); + return true; + } + catch + { + } + return false; + } + } + + + /// + /// Determines whether the specified URL is reserved or is inside a reserved path. + /// + /// The URL to check. + /// + /// true if the specified URL is reserved; otherwise, false. + /// + public static bool IsReservedPathOrUrl(string url) + { + // check if GlobalSettings.ReservedPaths and GlobalSettings.ReservedUrls are unchanged + if (!object.ReferenceEquals(_reservedPathsCache, GlobalSettings.ReservedPaths) + || !object.ReferenceEquals(_reservedUrlsCache, GlobalSettings.ReservedUrls)) + { + // store references to strings to determine changes + _reservedPathsCache = GlobalSettings.ReservedPaths; + _reservedUrlsCache = GlobalSettings.ReservedUrls; + + // add URLs and paths to a new list + StartsWithContainer _newReservedList = new StartsWithContainer(); + foreach (string reservedUrl in _reservedUrlsCache.Split(',')) + { + string reservedUrlTrimmed = reservedUrl.Trim().ToLower(); + if (reservedUrlTrimmed.Length > 0) + _newReservedList.Add(reservedUrlTrimmed); + } + foreach (string reservedPath in _reservedPathsCache.Split(',')) + { + string reservedPathTrimmed = reservedPath.Trim().ToLower(); + if (reservedPathTrimmed.Length > 0) + _newReservedList.Add(reservedPathTrimmed + (reservedPathTrimmed.EndsWith("/") ? "" : "/")); + } + + // use the new list from now on + _reservedList = _newReservedList; + } + // return true if url starts with an element of the reserved list + return _reservedList.StartsWith(url.ToLower()); + } + } + + + + /// + /// Structure that checks in logarithmic time + /// if a given string starts with one of the added keys. + /// + public class StartsWithContainer + { + /// Internal sorted list of keys. + private SortedList _list + = new SortedList(StartsWithComparator.Instance); + + /// + /// Adds the specified new key. + /// + /// The new key. + public void Add(string newKey) + { + // if the list already contains an element that begins with newKey, return + if (String.IsNullOrEmpty(newKey) || StartsWith(newKey)) + return; + + // create a new collection, so the old one can still be accessed + SortedList newList + = new SortedList(_list.Count + 1, StartsWithComparator.Instance); + + // add only keys that don't already start with newKey, others are unnecessary + foreach (string key in _list.Keys) + if (!key.StartsWith(newKey)) + newList.Add(key, null); + // add the new key + newList.Add(newKey, null); + + // update the list (thread safe, _list was never in incomplete state) + _list = newList; + } + + /// + /// Checks if the given string starts with any of the added keys. + /// + /// The target. + /// true if a key is found that matches the start of target + /// + /// Runs in O(s*log(n)), with n the number of keys and s the length of target. + /// + public bool StartsWith(string target) + { + return _list.ContainsKey(target); + } + + /// Comparator that tests if a string starts with another. + /// Not a real comparator, since it is not reflexive. (x==y does not imply y==x) + private sealed class StartsWithComparator : IComparer + { + /// Default string comparer. + private readonly static Comparer _stringComparer = Comparer.Default; + + /// Gets an instance of the StartsWithComparator. + public static readonly StartsWithComparator Instance = new StartsWithComparator(); + + /// + /// Tests if whole begins with all characters of part. + /// + /// The part. + /// The whole. + /// + /// Returns 0 if whole starts with part, otherwise performs standard string comparison. + /// + public int Compare(string part, string whole) + { + // let the default string comparer deal with null or when part is not smaller then whole + if (part == null || whole == null || part.Length >= whole.Length) + return _stringComparer.Compare(part, whole); + + // loop through all characters that part and whole have in common + int pos = 0; + bool match; + do + { + match = (part[pos] == whole[pos]); + } while (match && ++pos < part.Length); + + // return result of last comparison + return match ? 0 : (part[pos] < whole[pos] ? -1 : 1); + } + } + } +} diff --git a/umbraco/businesslogic/IconI.cs b/umbraco/businesslogic/IconI.cs new file mode 100644 index 0000000000..b48e6f6c0b --- /dev/null +++ b/umbraco/businesslogic/IconI.cs @@ -0,0 +1,19 @@ +using System; + +namespace umbraco.BusinessLogic.console +{ + /// + /// Interface for internally handling CmsNodes. + /// + public interface IconI + { + Guid UniqueId{get;} + int Id{get;} + MenuItemI[] MenuItems {get;} + IconI[] Children {get;} + string DefaultEditorURL{get;} + string Text{get;set;} + string OpenImage {get;} + string Image {get;} + } +} \ No newline at end of file diff --git a/umbraco/businesslogic/Log.cs b/umbraco/businesslogic/Log.cs new file mode 100644 index 0000000000..75ccd52fe0 --- /dev/null +++ b/umbraco/businesslogic/Log.cs @@ -0,0 +1,490 @@ +using System; +using System.Data; +using System.Diagnostics; +using System.Threading; + +using umbraco.DataLayer; + +namespace umbraco.BusinessLogic +{ + /// + /// Summary description for Log. + /// + public class Log + { + #region Statics + + private static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + /// + /// Adds the specified log item to the log. + /// + /// The log type. + /// The user adding the item. + /// The affected node id. + /// Comment. + public static void Add(LogTypes type, User user, int nodeId, string comment) + { + if(!UmbracoSettings.EnableLogging) return; + + if (UmbracoSettings.DisabledLogTypes != null && + UmbracoSettings.DisabledLogTypes.SelectSingleNode(String.Format("//logTypeAlias [. = '{0}']", type.ToString().ToLower())) == null) { + + if (comment.Length > 3999) + comment = comment.Substring(0, 3955) + "..."; + + if (UmbracoSettings.EnableAsyncLogging) { + ThreadPool.QueueUserWorkItem( + delegate { AddSynced(type, user == null ? 0 : user.Id, nodeId, comment); }); + return; + } + + AddSynced(type, user == null ? 0 : user.Id, nodeId, comment); + } + } + + /// + /// Adds the specified log item to the log without any user information attached. + /// + /// The log type. + /// The affected node id. + /// Comment. + public static void Add(LogTypes type, int nodeId, string comment) + { + Add(type, null, nodeId, comment); + } + + /// + /// Adds a log item to the log immidiately instead of Queuing it as a work item. + /// + /// The type. + /// The user id. + /// The node id. + /// The comment. + public static void AddSynced(LogTypes type, int userId, int nodeId, string comment) + { + try + { + SqlHelper.ExecuteNonQuery( + "insert into umbracoLog (userId, nodeId, logHeader, logComment) values (@userId, @nodeId, @logHeader, @comment)", + SqlHelper.CreateParameter("@userId", userId), + SqlHelper.CreateParameter("@nodeId", nodeId), + SqlHelper.CreateParameter("@logHeader", type.ToString()), + SqlHelper.CreateParameter("@comment", comment)); + } + catch(Exception e) + { + Debug.WriteLine(e.ToString(), "Error"); + Trace.WriteLine(e.ToString()); + } + } + + #region New GetLog methods - DataLayer layer compatible + /// + /// Gets a reader for the audit log. + /// + /// The node id. + /// A reader for the audit log. + public static IRecordsReader GetAuditLogReader(int NodeId) + { + return SqlHelper.ExecuteReader( + "select u.userName as [User], logHeader as Action, DateStamp as Date, logComment as Comment from umbracoLog inner join umbracoUser u on u.id = userId where nodeId = @id and logHeader not in ('open','system') order by DateStamp desc", + SqlHelper.CreateParameter("@id", NodeId)); + } + + /// + /// Gets a reader for the log for the specified types. + /// + /// The type of log message. + /// The start date. + /// A reader for the log. + public static IRecordsReader GetLogReader(LogTypes Type, DateTime SinceDate) + { + return SqlHelper.ExecuteReader( + "select userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where logHeader = @logHeader and DateStamp >= @dateStamp order by dateStamp desc", + SqlHelper.CreateParameter("@logHeader", Type.ToString()), + SqlHelper.CreateParameter("@dateStamp", SinceDate)); + } + + /// + /// Gets a reader for the log of the specified node. + /// + /// The node id. + /// A reader for the log. + public static IRecordsReader GetLogReader(int NodeId) + { + return SqlHelper.ExecuteReader( + "select u.userName, DateStamp, logHeader, logComment from umbracoLog inner join umbracoUser u on u.id = userId where nodeId = @id", + SqlHelper.CreateParameter("@id", NodeId)); + } + + /// + /// Gets a reader for the log for the specified user. + /// + /// The user. + /// The start date. + /// A reader for the log. + public static IRecordsReader GetLogReader(User user, DateTime SinceDate) + { + return SqlHelper.ExecuteReader( + "select userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where UserId = @user and DateStamp >= @dateStamp order by dateStamp desc", + SqlHelper.CreateParameter("@user", user.Id), + SqlHelper.CreateParameter("@dateStamp", SinceDate)); + } + + /// + /// Gets a reader of specific for the log for specific types and a specified user. + /// + /// The user. + /// The type of log message. + /// The since date. + /// A reader for the log. + public static IRecordsReader GetLogReader(User user, LogTypes Type, DateTime SinceDate) + { + return SqlHelper.ExecuteReader( + "select userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where UserId = @user and logHeader = @logHeader and DateStamp >= @dateStamp order by dateStamp desc", + SqlHelper.CreateParameter("@logHeader", Type.ToString()), + SqlHelper.CreateParameter("@user", user.Id), + SqlHelper.CreateParameter("@dateStamp", SinceDate)); + } + #endregion + + #region Old GetLog methods - DataLayer incompatible + #pragma warning disable 618 // ConvertToDataSet is obsolete + + /// + /// Gets the log. + /// + /// The type. + /// The start date. + /// The log. + /// Only guaranteed to work with SQL Server. Obsolete. + [Obsolete("Not compatible with the data layer. Use GetLogReader instead.", true)] + public static DataSet GetLog(LogTypes Type, DateTime SinceDate) + { + try + { + return ConvertToDataSet(GetLogReader(Type, SinceDate)); + } + catch (Exception) + { + throw new Exception("The GetLog method is not compatible with the data layer."); + } + } + + /// + /// Returns a dataset of Log items with a specific type since a specific date. + /// + /// The type. + /// The start date. + /// Maximum number of results. + /// The log. + /// Only guaranteed to work with SQL Server. Obsolete. + [Obsolete("Not compatible with the data layer. Use GetLogReader instead.", true)] + public static DataSet GetLog(LogTypes Type, DateTime SinceDate, int Limit) + { + try + { + return ConvertToDataSet(SqlHelper.ExecuteReader( + "select top " + Limit + + " userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where logHeader = @logHeader and DateStamp >= @dateStamp order by dateStamp desc", + SqlHelper.CreateParameter("@logHeader", Type.ToString()), + SqlHelper.CreateParameter("@dateStamp", SinceDate))); + } + catch (Exception) + { + throw new Exception("The GetLog method is not compatible with the data layer."); + } + } + + /// + /// Returns a dataset of Log items for a specific node + /// + /// The node id. + /// The log. + /// Only guaranteed to work with SQL Server. Obsolete. + [Obsolete("Not compatible with the data layer. Use GetLogReader instead.", true)] + public static DataSet GetLog(int NodeId) + { + try + { + return ConvertToDataSet(GetLogReader(NodeId)); + } + catch (Exception) + { + throw new Exception("The GetLog method is not compatible with the data layer."); + } + } + + /// + /// Returns a dataset of audit Log items for a specific node with more detailed user information + /// + /// The node id. + /// The log. + /// Only guaranteed to work with SQL Server. Obsolete. + [Obsolete("Not compatible with the data layer. Use GetAuditLogReader instead.", true)] + public static DataSet GetAuditLog(int NodeId) + { + try + { + return ConvertToDataSet(GetAuditLogReader(NodeId)); + } + catch (Exception) + { + throw new Exception("The GetAuditLog method is not compatible with the data layer."); + } + } + + /// + /// Returns a dataset of Log items for a specific user, since a specific date + /// + /// The user. + /// The start date. + /// The log. + /// Only guaranteed to work with SQL Server. Obsolete. + [Obsolete("Not compatible with the data layer. Use GetAuditLogReader instead.", true)] + public static DataSet GetLog(User u, DateTime SinceDate) + { + try + { + return ConvertToDataSet(GetLogReader(u, SinceDate)); + } + catch (Exception) + { + throw new Exception("The GetLog method is not compatible with the data layer."); + } + } + + /// + /// Returns a dataset of Log items for a specific user of a specific type, since a specific date + /// + /// The user. + /// The type. + /// The start date. + /// The log. + /// Only guaranteed to work with SQL Server. Obsolete. + [Obsolete("Not compatible with the data layer. Use GetLogReader instead.", true)] + public static DataSet GetLog(User u, LogTypes Type, DateTime SinceDate) + { + try + { + return ConvertToDataSet(GetLogReader(u, Type, SinceDate)); + } + catch (Exception) + { + throw new Exception("The GetLog method is not compatible with the data layer."); + } + } + + /// + /// Returns a dataset of Log items for a specific user of a specific type, since a specific date + /// + /// The user. + /// The type. + /// The since date. + /// The limit. + /// The log. + /// Only guaranteed to work with SQL Server. Obsolete. + [Obsolete("Not compatible with the data layer. Use GetLogReader instead.", true)] + public static DataSet GetLog(User u, LogTypes Type, DateTime SinceDate, int Limit) + { + try + { + return ConvertToDataSet(SqlHelper.ExecuteReader( + "select top " + Limit + + " userId, NodeId, DateStamp, logHeader, logComment from umbracoLog where UserId = @user and logHeader = @logHeader and DateStamp >= @dateStamp order by dateStamp desc", + SqlHelper.CreateParameter("@logHeader", Type.ToString()), + SqlHelper.CreateParameter("@user", u.Id), + SqlHelper.CreateParameter("@dateStamp", SinceDate))); + } + catch (Exception) + { + throw new Exception("The GetLog method is not compatible with the data layer."); + } + } + + /// + /// Converts a records reader to a data set. + /// + /// The records reader. + /// The data set + /// Only works with DataLayer.SqlHelpers.SqlServer.SqlServerDataReader. + /// When not an DataLayer.SqlHelpers.SqlServer.SqlServerDataReader. + [Obsolete("Temporary workaround for old GetLog methods.", false)] + private static DataSet ConvertToDataSet(IRecordsReader recordsReader) + { + // Get the internal RawDataReader (obsolete) + System.Data.SqlClient.SqlDataReader reader + = ((DataLayer.SqlHelpers.SqlServer.SqlServerDataReader)recordsReader).RawDataReader; + DataSet dataSet = new DataSet(); + do + { + DataTable dataTable = new DataTable(); + DataTable schemaTable = reader.GetSchemaTable(); + + if (schemaTable != null) + { + // A query returning records was executed + foreach (DataRow dataRow in schemaTable.Rows) + { + // Create a column name that is unique in the data table + string columnName = (string)dataRow["ColumnName"]; + // Add the column definition to the data table + DataColumn column = new DataColumn(columnName, (Type)dataRow["DataType"]); + dataTable.Columns.Add(column); + } + + dataSet.Tables.Add(dataTable); + + // Fill the data table we just created + while (reader.Read()) + { + DataRow dataRow = dataTable.NewRow(); + for (int i = 0; i < reader.FieldCount; i++) + dataRow[i] = reader.GetValue(i); + dataTable.Rows.Add(dataRow); + } + } + else + { + // No records were returned, return number of rows affected + dataTable.Columns.Add(new DataColumn("RowsAffected")); + dataSet.Tables.Add(dataTable); + DataRow rowsAffectedRow = dataTable.NewRow(); + rowsAffectedRow[0] = reader.RecordsAffected; + dataTable.Rows.Add(rowsAffectedRow); + } + } + // Go trough all result sets + while (reader.NextResult()); + + // Close the data reader so the underlying connection is closed + recordsReader.Close(); + + return dataSet; + } + #pragma warning restore 618 + + #endregion + + #endregion + } + + /// + /// The collection of available log types. + /// + public enum LogTypes + { + /// + /// Used when new nodes are added + /// + New, + /// + /// Used when nodes are saved + /// + Save, + /// + /// Used when nodes are opened + /// + Open, + /// + /// Used when nodes are deleted + /// + Delete, + /// + /// Used when nodes are published + /// + Publish, + /// + /// Used when nodes are send to publishing + /// + SendToPublish, + /// + /// Used when nodes are unpublished + /// + UnPublish, + /// + /// Used when nodes are moved + /// + Move, + /// + /// Used when nodes are copied + /// + Copy, + /// + /// Used when nodes are assgned a domain + /// + AssignDomain, + /// + /// Used when public access are changed for a node + /// + PublicAccess, + /// + /// Used when nodes are sorted + /// + Sort, + /// + /// Used when a notification are send to a user + /// + Notify, + /// + /// Used when a user logs into the umbraco back-end + /// + Login, + /// + /// Used when a user logs out of the umbraco back-end + /// + Logout, + /// + /// Used when a user login fails + /// + LoginFailure, + /// + /// General system notification + /// + System, + /// + /// System debugging notification + /// + Debug, + /// + /// System error notification + /// + Error, + /// + /// Notfound error notification + /// + NotFound, + /// + /// Used when a node's content is rolled back to a previous version + /// + RollBack, + /// + /// Used when a package is installed + /// + PackagerInstall, + /// + /// Used when a package is uninstalled + /// + PackagerUninstall, + /// + /// Used when a ping is send to/from the system + /// + Ping, + /// + /// Used when a node is send to translation + /// + SendToTranslate, + /// + /// Notification from a Scheduled task. + /// + ScheduledTask, + /// + /// Use this log action for custom log messages that should be shown in the audit trail + /// + Custom + } +} \ No newline at end of file diff --git a/umbraco/businesslogic/MenuItemI.cs b/umbraco/businesslogic/MenuItemI.cs new file mode 100644 index 0000000000..1bf7581d48 --- /dev/null +++ b/umbraco/businesslogic/MenuItemI.cs @@ -0,0 +1,18 @@ +using System; + +namespace umbraco.BusinessLogic.console +{ + /// + /// Summary description for MenuItemI. + /// + public interface MenuItemI + { + EditorBehavior behavior {get;} + string EditorURL {get;} + string Text {get;} + } + + public enum EditorBehavior { + modal, external, standard, command + } +} diff --git a/umbraco/businesslogic/StateHelper.cs b/umbraco/businesslogic/StateHelper.cs new file mode 100644 index 0000000000..a276b9fc1b --- /dev/null +++ b/umbraco/businesslogic/StateHelper.cs @@ -0,0 +1,291 @@ +using System; +using System.Reflection; +using System.Web; +using System.Web.UI; + +namespace umbraco.BusinessLogic +{ + /// + /// The StateHelper class provides general helper methods for handling sessions, context, viewstate and cookies. + /// + public class StateHelper + { + #region Session Helpers + + /// + /// Gets the session value. + /// + /// + /// The key. + /// + public static T GetSessionValue(string key) + { + return GetSessionValue(HttpContext.Current, key); + } + + /// + /// Gets the session value. + /// + /// + /// The context. + /// The key. + /// + public static T GetSessionValue(HttpContext context, string key) + { + if (context == null) + return default(T); + object o = context.Session[key]; + if (o == null) + return default(T); + return (T)o; + } + + /// + /// Sets a session value. + /// + /// The key. + /// The value. + public static void SetSessionValue(string key, object value) + { + SetSessionValue(HttpContext.Current, key, value); + } + + /// + /// Sets the session value. + /// + /// The context. + /// The key. + /// The value. + public static void SetSessionValue(HttpContext context, string key, object value) + { + if (context == null) + return; + context.Session[key] = value; + } + + #endregion + + #region Context Helpers + + /// + /// Gets the context value. + /// + /// + /// The key. + /// + public static T GetContextValue(string key) + { + return GetContextValue(HttpContext.Current, key); + } + + /// + /// Gets the context value. + /// + /// + /// The context. + /// The key. + /// + public static T GetContextValue(HttpContext context, string key) + { + if (context == null) + return default(T); + object o = context.Items[key]; + if (o == null) + return default(T); + return (T)o; + } + + /// + /// Sets the context value. + /// + /// The key. + /// The value. + public static void SetContextValue(string key, object value) + { + SetContextValue(HttpContext.Current, key, value); + } + + /// + /// Sets the context value. + /// + /// The context. + /// The key. + /// The value. + public static void SetContextValue(HttpContext context, string key, object value) + { + if (context == null) + return; + context.Items[key] = value; + } + + #endregion + + #region ViewState Helpers + + /// + /// Gets the state bag. + /// + /// + private static StateBag GetStateBag() + { + if (HttpContext.Current == null) + return null; + + Page page = HttpContext.Current.CurrentHandler as Page; + if (page == null) + return null; + + Type pageType = typeof(Page); + PropertyInfo viewState = pageType.GetProperty("ViewState", BindingFlags.GetProperty | BindingFlags.Instance); + if (viewState == null) + return null; + + return viewState.GetValue(page, null) as StateBag; + } + + /// + /// Gets the view state value. + /// + /// + /// The key. + /// + public static T GetViewStateValue(string key) + { + return GetViewStateValue(GetStateBag(), key); + } + + /// + /// Gets a view-state value. + /// + /// + /// The bag. + /// The key. + /// + public static T GetViewStateValue(StateBag bag, string key) + { + if (bag == null) + return default(T); + object o = bag[key]; + if (o == null) + return default(T); + return (T)o; + } + + /// + /// Sets the view state value. + /// + /// The key. + /// The value. + public static void SetViewStateValue(string key, object value) + { + SetViewStateValue(GetStateBag(), key, value); + } + + /// + /// Sets the view state value. + /// + /// The bag. + /// The key. + /// The value. + public static void SetViewStateValue(StateBag bag, string key, object value) + { + if (bag != null) + bag[key] = value; + } + + #endregion + + #region Cookie Helpers + + /// + /// Determines whether a cookie has a value with a specified key. + /// + /// The key. + /// + /// true if the cookie has a value with the specified key; otherwise, false. + /// + public static bool HasCookieValue(string key) + { + return !string.IsNullOrEmpty(GetCookieValue(HttpContext.Current, key)); + } + + /// + /// Gets the cookie value. + /// + /// The key. + /// + public static string GetCookieValue(string key) + { + return GetCookieValue(HttpContext.Current, key); + } + + /// + /// Gets the cookie value. + /// + /// The context. + /// The key. + /// + public static string GetCookieValue(HttpContext context, string key) + { + // Updated by NH to check against session values as well, which is an optional switch used by members + string tempValue = null; + if (context == null || context.Request == null) + return null; + + HttpCookie cookie = context.Request.Cookies[key]; + if (cookie == null) { + // Check for session + if (context.Session[key] != null) + if (context.Session[key].ToString() != "0") + tempValue = context.Session[key].ToString(); + } + else + tempValue = cookie.Value; + + return tempValue; + } + + /// + /// Sets the cookie value. + /// + /// The key. + /// The value. + public static void SetCookieValue(string key, string value) + { + SetCookieValue(HttpContext.Current, key, value); + } + + public static void ClearCookie(string key) { + HttpContext ctx = HttpContext.Current; + + if (ctx.Request.Cookies[key] != null) + ctx.Request.Cookies[key].Expires = DateTime.Now; + } + + /// + /// Sets the cookie value. + /// + /// The context. + /// The key. + /// The value. + public static void SetCookieValue(HttpContext context, string key, string value) + { + if (context == null || context.Request == null) + return; + HttpCookie cookie = context.Request.Cookies[key]; + + if (cookie == null) + cookie = new HttpCookie(key); + + cookie.Value = value; + + // add default exp on a month + cookie.Expires = DateTime.Now.AddMonths(1); + + // if cookie exists, remove + context.Response.Cookies.Add(cookie); + } + + #endregion + } +} diff --git a/umbraco/businesslogic/UmbracoSettings.cs b/umbraco/businesslogic/UmbracoSettings.cs new file mode 100644 index 0000000000..1a49ba3b43 --- /dev/null +++ b/umbraco/businesslogic/UmbracoSettings.cs @@ -0,0 +1,750 @@ +using System; +using System.IO; +using System.Web; +using System.Web.Caching; +using System.Xml; +using umbraco.BusinessLogic; + +namespace umbraco +{ + /// + /// The UmbracoSettings Class contains general settings information for the entire Umbraco instance based on information from the /config/umbracoSettings.config file + /// + public class UmbracoSettings + { + /// + /// Gets the umbraco settings document. + /// + /// The _umbraco settings. + public static XmlDocument _umbracoSettings + { + get + { + XmlDocument us = (XmlDocument) HttpRuntime.Cache["umbracoSettingsFile"]; + if (us == null) + us = ensureSettingsDocument(); + return us; + } + } + + private static string _path = GlobalSettings.FullpathToRoot + Path.DirectorySeparatorChar + "config" + + Path.DirectorySeparatorChar; + + private static string _filename = "umbracoSettings.config"; + + private static XmlDocument ensureSettingsDocument() + { + object settingsFile = HttpRuntime.Cache["umbracoSettingsFile"]; + + // Check for language file in cache + if (settingsFile == null) + { + XmlDocument temp = new XmlDocument(); + XmlTextReader settingsReader = new XmlTextReader(_path + _filename); + try + { + temp.Load(settingsReader); + HttpRuntime.Cache.Insert("umbracoSettingsFile", temp, + new CacheDependency(_path + _filename)); + } + catch (Exception e) + { + Log.Add(LogTypes.Error, new User(0), -1, "Error reading umbracoSettings file: " + e.ToString()); + } + settingsReader.Close(); + return temp; + } + else + return (XmlDocument) settingsFile; + } + + private static void save() + { + _umbracoSettings.Save(_path + _filename); + } + + + /// + /// Selects a xml node in the umbraco settings config file. + /// + /// The xpath query to the specific node. + /// If found, it returns the specific configuration xml node. + public static XmlNode GetKeyAsNode(string Key) + { + if (Key == null) + throw new ArgumentException("Key cannot be null"); + ensureSettingsDocument(); + if (_umbracoSettings == null || _umbracoSettings.DocumentElement == null) + return null; + return _umbracoSettings.DocumentElement.SelectSingleNode(Key); + } + + /// + /// Gets the value of configuration xml node with the specified key. + /// + /// The key. + /// + public static string GetKey(string Key) + { + ensureSettingsDocument(); + + XmlNode node = _umbracoSettings.DocumentElement.SelectSingleNode(Key); + if (node == null || node.FirstChild == null || node.FirstChild.Value == null) + return string.Empty; + return node.FirstChild.Value; + } + + /// + /// Gets a value indicating whether the media library will create new directories in the /media directory. + /// + /// + /// true if new directories are allowed otherwise, false. + /// + public static bool UploadAllowDirectories + { + get { return bool.Parse(GetKey("/settings/content/UploadAllowDirectories")); } + } + + /// + /// Gets a value indicating whether logging is enabled in umbracoSettings.config (/settings/logging/enableLogging). + /// + /// true if logging is enabled; otherwise, false. + public static bool EnableLogging { + get { + // We return true if no enable logging element is present in + // umbracoSettings (to enable default behaviour when upgrading) + string m_EnableLogging = GetKey("/settings/logging/enableLogging"); + if (String.IsNullOrEmpty(m_EnableLogging)) + return true; + else + return bool.Parse(m_EnableLogging); } + } + + /// + /// Gets a value indicating whether logging happens async. + /// + /// true if async logging is enabled; otherwise, false. + public static bool EnableAsyncLogging { + get { + string value = GetKey("/settings/logging/enableAsyncLogging"); + bool result; + if (!string.IsNullOrEmpty(value) && bool.TryParse(value, out result)) + return result; + return false; + } + } + + /// + /// Gets the disabled log types. + /// + /// The disabled log types. + public static XmlNode DisabledLogTypes { + get { return GetKeyAsNode("/settings/logging/disabledLogTypes"); } + } + + /// + /// Gets the package server url. + /// + /// The package server url. + public static string PackageServer + { + get { return "packages.umbraco.org"; } + } + + /// + /// Gets a value indicating whether umbraco will use domain prefixes. + /// + /// true if umbraco will use domain prefixes; otherwise, false. + public static bool UseDomainPrefixes { + get { + try { + bool result; + if (bool.TryParse(GetKey("/settings/requestHandler/useDomainPrefixes"), out result)) + return result; + return false; + } catch { + return false; + } + } + } + + /// + /// Gets a value indicating whether umbraco will use ASP.NET MasterPages for rendering instead of its propriatary templating system. + /// + /// true if umbraco will use ASP.NET MasterPages; otherwise, false. + public static bool UseAspNetMasterPages { + get { + try { + bool result; + if (bool.TryParse(GetKey("/settings/templates/useAspNetMasterPages"), out result)) + return result; + return false; + } catch { + return false; + } + } + } + + /// + /// Gets a value indicating whether umbraco will clone XML cache on publish. + /// + /// + /// true if umbraco will clone XML cache on publish; otherwise, false. + /// + public static bool CloneXmlCacheOnPublish + { + get + { + try + { + bool result; + if (bool.TryParse(GetKey("/settings/content/cloneXmlContent"), out result)) + return result; + return false; + } + catch + { + return false; + } + } + } + + /// + /// Gets a value indicating whether rich text editor content should be parsed by tidy. + /// + /// true if content is parsed; otherwise, false. + public static bool TidyEditorContent + { + get { return bool.Parse(GetKey("/settings/content/TidyEditorContent")); } + } + + /// + /// Gets the encoding type for the tidyied content. + /// + /// The encoding type as string. + public static string TidyCharEncoding + { + get { + string encoding = GetKey("/settings/content/TidyCharEncoding"); + if (String.IsNullOrEmpty(encoding)) + { + encoding = "UTF8"; + } + return encoding; + } + } + + /// + /// Gets the property context help option, this can either be 'text', 'icon' or 'none' + /// + /// The property context help option. + public static string PropertyContextHelpOption + { + get { return GetKey("/settings/content/PropertyContextHelpOption").ToLower(); } + } + + public static string DefaultBackofficeProvider { + get + { + string defaultProvider = GetKey("/settings/providers/users/DefaultBackofficeProvider"); + if (String.IsNullOrEmpty(defaultProvider)) + defaultProvider = "UsersMembershipProvider"; + + return defaultProvider; + } + } + + /// + /// Gets the allowed image file types. + /// + /// The allowed image file types. + public static string ImageFileTypes + { + get { return GetKey("/settings/content/imaging/imageFileTypes"); } + } + + /// + /// Gets the allowed script file types. + /// + /// The allowed script file types. + public static string ScriptFileTypes + { + get { return GetKey("/settings/content/scripteditor/scriptFileTypes"); } + } + + /// + /// Gets the path to the scripts folder used by the script editor. + /// + /// The script folder path. + public static string ScriptFolderPath + { + get { return GetKey("/settings/content/scripteditor/scriptFolderPath"); } + } + + /// + /// Gets a value indicating whether the rich-text script editor should be disabled for editing templates, css, xslt and scripts + /// The current editor is based on Codepress (codepress.org) which is not compatible with internet explorer + /// The editor is therefor turned off by default and a standard Textarea is used instead + /// + /// true if the scripteditor is disabled; otherwise, false. + public static bool ScriptDisableEditor + { + get + { + string _tempValue = GetKey("/settings/content/scripteditor/scriptDisableEditor"); + if (_tempValue != String.Empty) + return bool.Parse(_tempValue); + else + return false; + } + } + + /// + /// Gets the graphic headline format - png or gif + /// + /// The graphic headline format. + public static string GraphicHeadlineFormat + { + get { return GetKey("/settings/content/graphicHeadlineFormat"); } + } + + /// + /// Gets a value indicating whether umbraco will ensure unique node naming. + /// This will ensure that nodes cannot have the same url, but will add extra characters to a url. + /// ex: existingnodename.aspx would become existingnodename(1).aspx if a node with the same name is found + /// + /// true if umbraco ensures unique node naming; otherwise, false. + public static bool EnsureUniqueNaming + { + get + { + try + { + return bool.Parse(GetKey("/settings/content/ensureUniqueNaming")); + } + catch + { + return false; + } + } + } + + /// + /// Gets the notification email sender. + /// + /// The notification email sender. + public static string NotificationEmailSender + { + get { return GetKey("/settings/content/notifications/email"); } + } + + /// + /// Gets a value indicating whether notification-emails are HTML. + /// + /// + /// true if html notification-emails are disabled; otherwise, false. + /// + public static bool NotificationDisableHtmlEmail + { + get + { + string _tempValue = GetKey("/settings/content/notifications/disableHtmlEmail"); + if (_tempValue != String.Empty) + return bool.Parse(_tempValue); + else + return false; + } + } + + /// + /// Gets the allowed attributes on images. + /// + /// The allowed attributes on images. + public static string ImageAllowedAttributes + { + get { return GetKey("/settings/content/imaging/allowedAttributes"); } + } + + /// + /// Gets the scheduled tasks as XML + /// + /// The scheduled tasks. + public static XmlNode ScheduledTasks + { + get { return GetKeyAsNode("/settings/scheduledTasks"); } + } + + /// + /// Gets a list of characters that will be replaced when generating urls + /// + /// The URL replacement characters. + public static XmlNode UrlReplaceCharacters + { + get { return GetKeyAsNode("/settings/requestHandler/urlReplacing"); } + } + + /// + /// Gets a value indicating whether umbraco will use distributed calls. + /// This enables umbraco to share cache and content across multiple servers. + /// Used for load-balancing high-traffic sites. + /// + /// true if umbraco uses distributed calls; otherwise, false. + public static bool UseDistributedCalls + { + get + { + try + { + return bool.Parse(GetKeyAsNode("/settings/distributedCall").Attributes.GetNamedItem("enable").Value); + } + catch + { + return false; + } + } + } + + + /// + /// Gets the ID of the user with access rights to perform the distributed calls. + /// + /// The distributed call user. + public static int DistributedCallUser + { + get + { + try + { + return int.Parse(GetKey("/settings/distributedCall/user")); + } + catch + { + return -1; + } + } + } + + /// + /// Gets IP or hostnames of the distribution servers. + /// These servers will receive a call everytime content is created/deleted/removed + /// and update their content cache accordingly, ensuring a consistent cache on all servers + /// + /// The distribution servers. + public static XmlNode DistributionServers + { + get + { + try + { + return GetKeyAsNode("/settings/distributedCall/servers"); + } + catch + { + return null; + } + } + } + + /// + /// Gets all repositories registered, and returns them as XmlNodes, containing name, alias and webservice url. + /// These repositories are used by the build-in package installer and uninstaller to install new packages and check for updates. + /// All repositories should have a unique alias. + /// All packages installed from a repository gets the repository alias included in the install information + /// + /// The repository servers. + public static XmlNode Repositories { + get { + try { + return GetKeyAsNode("/settings/repositories"); + } catch { + return null; + } + } + } + + /// + /// Gets a value indicating whether umbraco will use the viewstate mover module. + /// The viewstate mover will move all asp.net viewstate information to the bottom of the aspx page + /// to ensure that search engines will index text instead of javascript viewstate information. + /// + /// + /// true if umbraco will use the viewstate mover module; otherwise, false. + /// + public static bool UseViewstateMoverModule + { + get + { + try + { + return + bool.Parse( + GetKeyAsNode("/settings/viewstateMoverModule").Attributes.GetNamedItem("enable").Value); + } + catch + { + return false; + } + } + } + + + /// + /// Tells us whether the Xml Content cache is disabled or not + /// Default is enabled + /// + public static bool isXmlContentCacheDisabled + { + get + { + try + { + bool xmlCacheEnabled; + string value = GetKey("/settings/content/XmlCacheEnabled"); + if (bool.TryParse(value, out xmlCacheEnabled)) + return !xmlCacheEnabled; + // Return default + return false; + } + catch + { + return false; + } + } + } + + /// + /// Tells us whether the Xml to always update disk cache, when changes are made to content + /// Default is enabled + /// + public static bool continouslyUpdateXmlDiskCache + { + get + { + try + { + bool updateDiskCache; + string value = GetKey("/settings/content/ContinouslyUpdateXmlDiskCache"); + if (bool.TryParse(value, out updateDiskCache)) + return updateDiskCache; + // Return default + return false; + } + catch + { + return true; + } + } + } + + /// + /// Tells us whether to use a splash page while umbraco is initializing content. + /// If not, requests are queued while umbraco loads content. For very large sites (+10k nodes) it might be usefull to + /// have a splash page + /// Default is disabled + /// + public static bool EnableSplashWhileLoading + { + get + { + try + { + bool updateDiskCache; + string value = GetKey("/settings/content/EnableSplashWhileLoading"); + if (bool.TryParse(value, out updateDiskCache)) + return updateDiskCache; + // Return default + return false; + } + catch + { + return false; + } + } + } + + /// + /// Configuration regarding webservices + /// + /// Put in seperate class for more logik/seperation + public class Webservices + { + /// + /// Gets a value indicating whether this is enabled. + /// + /// true if enabled; otherwise, false. + public static bool Enabled + { + get + { + try + { + return + bool.Parse(GetKeyAsNode("/settings/webservices").Attributes.GetNamedItem("enabled").Value); + } + catch + { + return false; + } + } + } + + #region "Webservice configuration" + + /// + /// Gets the document service users who have access to use the document web service + /// + /// The document service users. + public static string[] documentServiceUsers + { + get + { + try + { + return GetKey("/settings/webservices/documentServiceUsers").Split(','); + } + catch + { + return new string[0]; + } + } + } + + /// + /// Gets the file service users who have access to use the file web service + /// + /// The file service users. + public static string[] fileServiceUsers + { + get + { + try + { + return GetKey("/settings/webservices/fileServiceUsers").Split(','); + } + catch + { + return new string[0]; + } + } + } + + + /// + /// Gets the folders used by the file web service + /// + /// The file service folders. + public static string[] fileServiceFolders + { + get + { + try + { + return GetKey("/settings/webservices/fileServiceFolders").Split(','); + } + catch + { + return new string[0]; + } + } + } + + /// + /// Gets the member service users who have access to use the member web service + /// + /// The member service users. + public static string[] memberServiceUsers + { + get + { + try + { + return GetKey("/settings/webservices/memberServiceUsers").Split(','); + } + catch + { + return new string[0]; + } + } + } + + /// + /// Gets the stylesheet service users who have access to use the stylesheet web service + /// + /// The stylesheet service users. + public static string[] stylesheetServiceUsers + { + get + { + try + { + return GetKey("/settings/webservices/stylesheetServiceUsers").Split(','); + } + catch + { + return new string[0]; + } + } + } + + /// + /// Gets the template service users who have access to use the template web service + /// + /// The template service users. + public static string[] templateServiceUsers + { + get + { + try + { + return GetKey("/settings/webservices/templateServiceUsers").Split(','); + } + catch + { + return new string[0]; + } + } + } + + /// + /// Gets the media service users who have access to use the media web service + /// + /// The media service users. + public static string[] mediaServiceUsers + { + get + { + try + { + return GetKey("/settings/webservices/mediaServiceUsers").Split(','); + } + catch + { + return new string[0]; + } + } + } + + + /// + /// Gets the maintenance service users who have access to use the maintance web service + /// + /// The maintenance service users. + public static string[] maintenanceServiceUsers + { + get + { + try + { + return GetKey("/settings/webservices/maintenanceServiceUsers").Split(','); + } + catch + { + return new string[0]; + } + } + } + + #endregion + } + } +} \ No newline at end of file diff --git a/umbraco/businesslogic/User.cs b/umbraco/businesslogic/User.cs new file mode 100644 index 0000000000..725208fb49 --- /dev/null +++ b/umbraco/businesslogic/User.cs @@ -0,0 +1,844 @@ +using System; +using System.Data; +using System.Configuration; +using System.Collections; +using umbraco.DataLayer; + +namespace umbraco.BusinessLogic { + /// + /// represents a Umbraco back end user + /// + public class User { + // private SqlConnection _conn = new SqlConnection(GlobalSettings.DbDSN); + + + private int _id; + private bool _isInitialized; + private string _name; + private string _loginname; + private int _startnodeid; + private int _startmediaid; + private string _email; + private string _language = ""; + private UserType _usertype; + private bool _userNoConsole; + private bool _userDisabled; + private bool _defaultToLiveEditing; + + private Hashtable _cruds = new Hashtable(); + private bool _crudsInitialized = false; + + private Hashtable _notifications = new Hashtable(); + private bool _notificationsInitialized = false; + + private static ISqlHelper SqlHelper { + get { return Application.SqlHelper; } + } + + /// + /// Initializes a new instance of the class. + /// + /// The ID. + public User(int ID) { + setupUser(ID); + } + + /// + /// Initializes a new instance of the class. + /// + /// The ID. + /// if set to true [no setup]. + public User(int ID, bool noSetup) { + _id = ID; + } + + /// + /// Initializes a new instance of the class. + /// + /// The login. + /// The password. + public User(string Login, string Password) { + setupUser(getUserId(Login, Password)); + } + + /// + /// Initializes a new instance of the class. + /// + /// The login. + public User(string Login) { + setupUser(getUserId(Login)); + } + + private void setupUser(int ID) { + _id = ID; + + using (IRecordsReader dr = SqlHelper.ExecuteReader( + "Select userNoConsole, userDisabled, userType,startStructureID, startMediaId, userName,userLogin,userEmail,userDefaultPermissions, userLanguage, defaultToLiveEditing from umbracoUser where id = @id", + SqlHelper.CreateParameter("@id", ID))) { + if (dr.Read()) { + _userNoConsole = dr.GetBoolean("usernoconsole"); + _userDisabled = dr.GetBoolean("userDisabled"); + _name = dr.GetString("userName"); + _loginname = dr.GetString("userLogin"); + _email = dr.GetString("userEmail"); + _language = dr.GetString("userLanguage"); + _startnodeid = dr.GetInt("startStructureID"); + if (!dr.IsNull("startMediaId")) + _startmediaid = dr.GetInt("startMediaID"); + _usertype = UserType.GetUserType(dr.GetShort("UserType")); + _defaultToLiveEditing = dr.GetBoolean("defaultToLiveEditing"); + } + } + _isInitialized = true; + } + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public void Save() { + OnSaving(EventArgs.Empty); + } + + /// + /// Gets or sets the users name. + /// + /// The name. + public string Name { + get { + if (!_isInitialized) + setupUser(_id); + return _name; + } + set { + _name = value; + SqlHelper.ExecuteNonQuery("Update umbracoUser set UserName = @userName where id = @id", SqlHelper.CreateParameter("@userName", value), SqlHelper.CreateParameter("@id", Id)); + FlushFromCache(); + } + } + + /// + /// Gets or sets the users email. + /// + /// The email. + public string Email { + get { + if (!_isInitialized) + setupUser(_id); + return _email; + } + set { + _email = value; + SqlHelper.ExecuteNonQuery("Update umbracoUser set UserEmail = @email where id = @id", SqlHelper.CreateParameter("@id", this.Id), SqlHelper.CreateParameter("@email", value)); + FlushFromCache(); + } + } + + /// + /// Gets or sets the users language. + /// + /// The language. + public string Language { + get { + if (!_isInitialized) + setupUser(_id); + return _language; + } + set { + _language = value; + SqlHelper.ExecuteNonQuery("Update umbracoUser set userLanguage = @language where id = @id", SqlHelper.CreateParameter("@language", value), SqlHelper.CreateParameter("@id", Id)); + FlushFromCache(); + } + } + + /// + /// Gets or sets the users password. + /// + /// The password. + public string Password { + get { + return GetPassword(); + } + set { + SqlHelper.ExecuteNonQuery("Update umbracoUser set UserPassword = @pw where id = @id", SqlHelper.CreateParameter("@pw", value), SqlHelper.CreateParameter("@id", Id)); + FlushFromCache(); + } + } + + /// + /// Gets the password. + /// + /// + public string GetPassword() { + return + SqlHelper.ExecuteScalar("select UserPassword from umbracoUser where id = @id", + SqlHelper.CreateParameter("@id", this.Id)); + } + static string _connstring = GlobalSettings.DbDSN; + + /// + /// Determines whether this user is an admin. + /// + /// + /// true if this user is admin; otherwise, false. + /// + public bool IsAdmin() { + return UserType.Alias == "admin"; + } + + public bool ValidatePassword(string password) { + string userLogin = + SqlHelper.ExecuteScalar("select userLogin from umbracoUser where userLogin = @login and UserPassword = @pw", + SqlHelper.CreateParameter("@pw", password), + SqlHelper.CreateParameter("@login", LoginName) + ); + return userLogin == this.LoginName; + } + + /// + /// Determines whether this user is the root (super user). + /// + /// + /// true if this user is root; otherwise, false. + /// + public bool IsRoot() { + return Id == 0; + } + + /// + /// Gets the applications which the user has access to. + /// + /// The users applications. + public Application[] Applications { + get { + if (!_isInitialized) + setupUser(_id); + ArrayList al = new ArrayList(); + + using (IRecordsReader appIcons = SqlHelper.ExecuteReader("select appAlias, appIcon, appname from umbracoApp app join umbracoUser2app u2a on u2a.app = app.appAlias and u2a.[user] = @userID order by app.sortOrder", SqlHelper.CreateParameter("@userID", this.Id))) { + while (appIcons.Read()) { + Application tmp = new Application(); + tmp.name = appIcons.GetString("appName"); + tmp.icon = appIcons.GetString("appIcon"); + tmp.alias = appIcons.GetString("appAlias"); + al.Add(tmp); + } + } + + Application[] retVal = new Application[al.Count]; + + for (int i = 0; i < al.Count; i++) { + retVal[i] = (Application)al[i]; + } + return retVal; + } + } + + /// + /// Gets or sets the users login name + /// + /// The loginname. + public string LoginName { + get { + if (!_isInitialized) + setupUser(_id); + return _loginname; + } + set { + if (!ensureUniqueLoginName(value, this)) + throw new Exception(String.Format("A user with the login '{0}' already exists", value)); + _loginname = value; + SqlHelper.ExecuteNonQuery("Update umbracoUser set UserLogin = @login where id = @id", SqlHelper.CreateParameter("@login", value), SqlHelper.CreateParameter("@id", Id)); + FlushFromCache(); + } + } + + private static bool ensureUniqueLoginName(string loginName, User currentUser) { + User[] u = User.getAllByLoginName(loginName); + if (u.Length != 0) + { + if (u[0].Id != currentUser.Id) + return false; + } + + return true; + } + + /// + /// Validates the users credentials. + /// + /// The login name. + /// The password. + /// + public static bool validateCredentials(string lname, string passw) { + return validateCredentials(lname, passw, true); + } + + /// + /// Validates the users credentials. + /// + /// The login name. + /// The password. + /// if set to true [check for umbraco console access]. + /// + public static bool validateCredentials(string lname, string passw, bool checkForUmbracoConsoleAccess) { + string consoleCheckSql = ""; + if (checkForUmbracoConsoleAccess) + consoleCheckSql = "and userNoConsole = 0 "; + + object tmp = SqlHelper.ExecuteScalar( + "select id from umbracoUser where userDisabled = 0 " + consoleCheckSql + " and userLogin = @login and userPassword = @pw", SqlHelper.CreateParameter("@login", lname), SqlHelper.CreateParameter("@pw", passw) + ); + + // Logging + if (tmp == null) + BusinessLogic.Log.Add(BusinessLogic.LogTypes.LoginFailure, BusinessLogic.User.GetUser(0), -1, "Login: '" + lname + "' failed, from IP: " + System.Web.HttpContext.Current.Request.UserHostAddress); + return (tmp != null); + } + + /// + /// Gets or sets the type of the user. + /// + /// The type of the user. + public UserType UserType { + get { + if (!_isInitialized) + setupUser(_id); + return _usertype; + } + set { + _usertype = value; + SqlHelper.ExecuteNonQuery( + @"Update umbracoUser set userType = @type where id = @id", + SqlHelper.CreateParameter("@type", value.Id), + SqlHelper.CreateParameter("@id", Id)); + FlushFromCache(); + } + } + + + /// + /// Gets all users + /// + /// + public static User[] getAll() { + System.Collections.ArrayList tmpContainer = new System.Collections.ArrayList(); + + IRecordsReader dr; + dr = SqlHelper.ExecuteReader("Select id from umbracoUser"); + + while (dr.Read()) { + tmpContainer.Add(BusinessLogic.User.GetUser(dr.GetInt("id"))); + } + dr.Close(); + User[] retVal = new User[tmpContainer.Count]; + + int c = 0; + foreach (User u in tmpContainer) { + retVal[c] = u; + c++; + } + return retVal; + } + + + /// + /// Gets the current user (logged in) + /// + /// A user or null + public static User GetCurrent() + { + if (umbraco.BasePages.BasePage.umbracoUserContextID != "") + return BusinessLogic.User.GetUser(umbraco.BasePages.BasePage.GetUserId(umbraco.BasePages.BasePage.umbracoUserContextID)); + else + return null; + + } + + /// + /// Gets all users by email. + /// + /// The email. + /// + public static User[] getAllByEmail(string email) { + System.Collections.ArrayList tmpContainer = new System.Collections.ArrayList(); + + IRecordsReader dr; + dr = SqlHelper.ExecuteReader( + "Select id from umbracoUser where userEmail LIKE %@email%", SqlHelper.CreateParameter("@email", email)); + + while (dr.Read()) { + tmpContainer.Add(BusinessLogic.User.GetUser(dr.GetInt("id"))); + } + dr.Close(); + User[] retVal = new User[tmpContainer.Count]; + + int c = 0; + foreach (User u in tmpContainer) { + retVal[c] = u; + c++; + } + return retVal; + } + + /// + /// Gets all users by login name. + /// + /// The login. + /// + public static User[] getAllByLoginName(string login) { + System.Collections.ArrayList tmpContainer = new System.Collections.ArrayList(); + + IRecordsReader dr; + dr = SqlHelper.ExecuteReader( + "Select id from umbracoUser where userLogin LIKE @login", SqlHelper.CreateParameter("@login", String.Format("%{0}%", login))); + + while (dr.Read()) { + tmpContainer.Add(BusinessLogic.User.GetUser(dr.GetInt("id"))); + } + dr.Close(); + User[] retVal = new User[tmpContainer.Count]; + + int c = 0; + foreach (User u in tmpContainer) { + retVal[c] = u; + c++; + } + return retVal; + } + + /// + /// Create a new user. + /// + /// The full name. + /// The login name. + /// The password. + /// The user type. + public static void MakeNew(string name, string lname, string passw, UserType ut) { + + SqlHelper.ExecuteNonQuery(@" + insert into umbracoUser + (UserType,startStructureId,startMediaId, UserName, userLogin, userPassword, userEmail,userLanguage) + values (@type,-1,-1,@name,@lname,@pw,'',@lang)", + SqlHelper.CreateParameter("@lang", GlobalSettings.DefaultUILanguage), + SqlHelper.CreateParameter("@name", name), + SqlHelper.CreateParameter("@lname", lname), + SqlHelper.CreateParameter("@type", ut.Id), + SqlHelper.CreateParameter("@pw", passw)); + + new User(lname).OnNew(EventArgs.Empty); + } + + + /// + /// Creates a new user. + /// + /// The name. + /// The lname. + /// The passw. + /// The email. + /// The ut. + public static void MakeNew(string name, string lname, string passw, string email, UserType ut) { + SqlHelper.ExecuteNonQuery(@" + insert into umbracoUser + (UserType,startStructureId,startMediaId, UserName, userLogin, userPassword, userEmail,userLanguage) + values (@type,-1,-1,@name,@lname,@pw,@email,@lang)", + SqlHelper.CreateParameter("@lang", GlobalSettings.DefaultUILanguage), + SqlHelper.CreateParameter("@name", name), + SqlHelper.CreateParameter("@lname", lname), + SqlHelper.CreateParameter("@email", email), + SqlHelper.CreateParameter("@type", ut.Id), + SqlHelper.CreateParameter("@pw", passw)); + + new User(lname).OnNew(EventArgs.Empty); + } + + + /// + /// Updates the name, login name and password for the user with the specified id. + /// + /// The id. + /// The name. + /// The lname. + /// The email. + /// The ut. + public static void Update(int id, string name, string lname, string email, UserType ut) { + if (!ensureUniqueLoginName(lname, User.GetUser(id))) + throw new Exception(String.Format("A user with the login '{0}' already exists", lname)); + + + SqlHelper.ExecuteNonQuery(@"Update umbracoUser set userName=@name, userLogin=@lname, userEmail=@email, UserType=@type where id = @id", + SqlHelper.CreateParameter("@name", name), + SqlHelper.CreateParameter("@lname", lname), + SqlHelper.CreateParameter("@email", email), + SqlHelper.CreateParameter("@type", ut.Id), + SqlHelper.CreateParameter("@id", id)); + } + + /// + /// Gets the ID from the user with the specified login name and password + /// + /// The login name. + /// The password. + /// a user ID + public static int getUserId(string lname, string passw) { + return getUserId("select id from umbracoUser where userDisabled = 0 and userNoConsole = 0 and userLogin = @login and userPassword = @pw", + SqlHelper.CreateParameter("@login", lname), + SqlHelper.CreateParameter("@pw", passw)); + } + + /// + /// Gets the ID from the user with the specified login name + /// + /// The login name. + /// a user ID + public static int getUserId(string lname) { + return getUserId("select id from umbracoUser where userLogin = @login", + SqlHelper.CreateParameter("@login", lname)); + } + + private static int getUserId(string query, params IParameter[] parameterValues) { + object userId = SqlHelper.ExecuteScalar(query, parameterValues); + return (userId != null && userId!=DBNull.Value) ? int.Parse(userId.ToString()) : -1; + } + + /// + /// Deletes this instance. + /// + public void delete() { + OnDeleting(EventArgs.Empty); + + SqlHelper.ExecuteNonQuery("delete from umbracoUser where id = @id", SqlHelper.CreateParameter("@id", Id)); + FlushFromCache(); + } + + /// + /// Disables this instance. + /// + public void disable() { + OnDisabling(EventArgs.Empty); + this.Disabled = true; + } + + /// + /// Gets the users permissions based on a nodes path + /// + /// The path. + /// + public string GetPermissions(string Path) { + if (!_isInitialized) + setupUser(_id); + string cruds = UserType.DefaultPermissions; + + if (!_crudsInitialized) + initCruds(); + + foreach (string nodeId in Path.Split(',')) { + if (_cruds.ContainsKey(int.Parse(nodeId))) + cruds = _cruds[int.Parse(nodeId)].ToString(); + } + + return cruds; + } + + /// + /// Initializes the user node permissions + /// + public void initCruds() { + if (!_isInitialized) + setupUser(_id); + + // clear cruds + System.Web.HttpContext.Current.Application.Lock(); + _cruds.Clear(); + System.Web.HttpContext.Current.Application.UnLock(); + + using (IRecordsReader dr = SqlHelper.ExecuteReader("select * from umbracoUser2NodePermission where userId = @userId order by nodeId", SqlHelper.CreateParameter("@userId", this.Id))) { + // int currentId = -1; + while (dr.Read()) { + if (!_cruds.ContainsKey(dr.GetInt("nodeId"))) + _cruds.Add(dr.GetInt("nodeId"), String.Empty); + + _cruds[dr.GetInt("nodeId")] += dr.GetString("permission"); + } + } + _crudsInitialized = true; + } + + /// + /// Gets a users notifications for a specified node path. + /// + /// The node path. + /// + public string GetNotifications(string Path) { + string notifications = ""; + + if (!_notificationsInitialized) + initNotifications(); + + foreach (string nodeId in Path.Split(',')) { + if (_notifications.ContainsKey(int.Parse(nodeId))) + notifications = _notifications[int.Parse(nodeId)].ToString(); + } + + return notifications; + } + + /// + /// Clears the internal hashtable containing cached information about notifications for the user + /// + public void resetNotificationCache() { + _notificationsInitialized = false; + _notifications.Clear(); + } + + /// + /// Initializes the notifications and caches them. + /// + public void initNotifications() { + if (!_isInitialized) + setupUser(_id); + + using (IRecordsReader dr = SqlHelper.ExecuteReader("select * from umbracoUser2NodeNotify where userId = @userId order by nodeId", SqlHelper.CreateParameter("@userId", this.Id))) { + while (dr.Read()) { + int nodeId = dr.GetInt("nodeId"); + if (!_notifications.ContainsKey(nodeId)) + _notifications.Add(nodeId, String.Empty); + + _notifications[nodeId] += dr.GetString("action"); + } + } + _notificationsInitialized = true; + } + + /// + /// Gets the user id. + /// + /// The id. + public int Id { + get { return _id; } + } + + /// + /// Clears the list of applications the user has access to. + /// + public void clearApplications() { + SqlHelper.ExecuteNonQuery("delete from umbracoUser2app where [user] = @id", SqlHelper.CreateParameter("@id", this.Id)); + } + + /// + /// Adds a application to the list of allowed applications + /// + /// The app alias. + public void addApplication(string AppAlias) { + SqlHelper.ExecuteNonQuery("insert into umbracoUser2app ([user],app) values (@id, @app)", SqlHelper.CreateParameter("@id", this.Id), SqlHelper.CreateParameter("@app", AppAlias)); + } + + /// + /// Gets or sets a value indicating whether the user has access to the Umbraco back end. + /// + /// true if the user has access to the back end; otherwise, false. + public bool NoConsole { + get { + if (!_isInitialized) + setupUser(_id); + return _userNoConsole; + } + set { + _userNoConsole = value; + SqlHelper.ExecuteNonQuery("update umbracoUser set userNoConsole = @userNoConsole where id = @id", SqlHelper.CreateParameter("@id", this.Id), SqlHelper.CreateParameter("@userNoConsole", _userNoConsole)); + FlushFromCache(); + } + } + + /// + /// Gets or sets a value indicating whether this is disabled. + /// + /// true if disabled; otherwise, false. + public bool Disabled + { + get + { + if (!_isInitialized) + setupUser(_id); + return _userDisabled; + } + set + { + _userDisabled = value; + SqlHelper.ExecuteNonQuery("update umbracoUser set userDisabled = @userDisabled where id = @id", SqlHelper.CreateParameter("@id", this.Id), SqlHelper.CreateParameter("@userDisabled", _userDisabled)); + FlushFromCache(); + } + } + + /// + /// Gets or sets a value indicating whether a user should be redirected to liveediting by default. + /// + /// + /// true if defaults to live editing; otherwise, false. + /// + public bool DefaultToLiveEditing + { + get + { + if (!_isInitialized) + setupUser(_id); + return _defaultToLiveEditing; + } + set + { + _defaultToLiveEditing = value; + SqlHelper.ExecuteNonQuery("update umbracoUser set defaultToLiveEditing = @defaultToLiveEditing where id = @id", SqlHelper.CreateParameter("@id", this.Id), SqlHelper.CreateParameter("@defaultToLiveEditing", _defaultToLiveEditing)); + FlushFromCache(); + } + } + + /// + /// Gets or sets the start content node id. + /// + /// The start node id. + public int StartNodeId { + get { + if (!_isInitialized) + setupUser(_id); + return _startnodeid; + } + set { + + _startnodeid = value; + SqlHelper.ExecuteNonQuery("update umbracoUser set startStructureId = @start where id = @id", SqlHelper.CreateParameter("@start", value), SqlHelper.CreateParameter("@id", this.Id)); + FlushFromCache(); + } + } + + /// + /// Gets or sets the start media id. + /// + /// The start media id. + public int StartMediaId { + get { + if (!_isInitialized) + setupUser(_id); + return _startmediaid; + } + set { + + _startmediaid = value; + SqlHelper.ExecuteNonQuery("update umbracoUser set startMediaId = @start where id = @id", SqlHelper.CreateParameter("@start", value), SqlHelper.CreateParameter("@id", this.Id)); + FlushFromCache(); + } + } + + /// + /// Flushes the user from cache. + /// + protected void FlushFromCache() { + OnFlushingFromCache(EventArgs.Empty); + + if (System.Web.HttpRuntime.Cache[string.Format("UmbracoUser{0}", Id.ToString())] != null) + System.Web.HttpRuntime.Cache.Remove(string.Format("UmbracoUser{0}", Id.ToString())); + } + + /// + /// Gets the user with a specified ID + /// + /// The id. + /// + public static User GetUser(int id) { + if (System.Web.HttpRuntime.Cache[string.Format("UmbracoUser{0}", id.ToString())] == null) { + User u = new User(id); + System.Web.HttpRuntime.Cache.Insert(string.Format("UmbracoUser{0}", id.ToString()), u); + } + return (User)System.Web.HttpRuntime.Cache[string.Format("UmbracoUser{0}", id.ToString())]; + } + + + //EVENTS + /// + /// The save event handler + /// + public delegate void SavingEventHandler(User sender, EventArgs e); + /// + /// The new event handler + /// + public delegate void NewEventHandler(User sender, EventArgs e); + /// + /// The disable event handler + /// + public delegate void DisablingEventHandler(User sender, EventArgs e); + /// + /// The delete event handler + /// + public delegate void DeletingEventHandler(User sender, EventArgs e); + /// + /// The Flush User from cache event handler + /// + public delegate void FlushingFromCacheEventHandler(User sender, EventArgs e); + + /// + /// Occurs when [saving]. + /// + public static event SavingEventHandler Saving; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnSaving(EventArgs e) { + if (Saving != null) + Saving(this, e); + } + + /// + /// Occurs when [new]. + /// + public static event NewEventHandler New; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnNew(EventArgs e) { + if (New != null) + New(this, e); + } + + /// + /// Occurs when [disabling]. + /// + public static event DisablingEventHandler Disabling; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnDisabling(EventArgs e) { + if (Disabling != null) + Disabling(this, e); + } + + /// + /// Occurs when [deleting]. + /// + public static event DeletingEventHandler Deleting; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnDeleting(EventArgs e) { + if (Deleting != null) + Deleting(this, e); + } + + /// + /// Occurs when [flushing from cache]. + /// + public static event FlushingFromCacheEventHandler FlushingFromCache; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnFlushingFromCache(EventArgs e) { + if (FlushingFromCache != null) + FlushingFromCache(this, e); + } + + + } +} diff --git a/umbraco/businesslogic/UserType.cs b/umbraco/businesslogic/UserType.cs new file mode 100644 index 0000000000..bec238a49f --- /dev/null +++ b/umbraco/businesslogic/UserType.cs @@ -0,0 +1,308 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Web; +using System.Web.Caching; + +using umbraco.DataLayer; + +namespace umbraco.BusinessLogic +{ + /// + /// Represents a umbraco Usertype + /// + public class UserType + { + + /// + /// Creates a new empty instance of a UserType + /// + public UserType() { } + + /// + /// Creates a new instance of a UserType and attempts to + /// load it's values from the database cache. + /// + /// + /// If the UserType is not found in the existing ID list, then this object + /// will remain an empty object + /// + /// The UserType id to find + public UserType(int id) + { + Cache(); + this.LoadByPrimaryKey(id); + } + + /// + /// Initializes a new instance of the class. + /// + /// The user type id. + /// The name. + public UserType(int id, string name) + { + m_id = id; + m_name = name; + } + + /// + /// Creates a new instance of UserType with all parameters + /// + /// + /// + /// + /// + public UserType(int id, string name, string defaultPermissions, string alias) + { + m_name = name; + m_id = id; + m_defaultPermissions = defaultPermissions; + m_alias = alias; + } + + /// + /// A static constructor that will Cache the current UserTypes + /// + static UserType() + { + Cache(); + } + + private const string CACHE_KEY = "UserTypeCache"; + private static string _connstring = GlobalSettings.DbDSN; + + private int m_id; + private string m_name; + private string m_defaultPermissions; + private string m_alias; + + /// + /// The cache storage for all user types + /// + private static List UserTypes + { + get + { + //ensure cache exists + if (HttpRuntime.Cache[CACHE_KEY] == null) + ReCache(); + return HttpRuntime.Cache[CACHE_KEY] as List; + } + set + { + HttpRuntime.Cache[CACHE_KEY] = value; + } + } + + private static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + #region Public Properties + /// + /// Gets or sets the user type alias. + /// + public string Alias + { + get { return m_alias; } + set { m_alias = value; } + } + + /// + /// Gets the name of the user type. + /// + public string Name + { + get { return m_name; } + set { m_name = value; } + } + + /// + /// Gets the id the user type + /// + public int Id + { + get { return m_id; } + } + + /// + /// Gets the default permissions of the user type + /// + public string DefaultPermissions + { + get { return m_defaultPermissions; } + set { m_defaultPermissions = value; } + } + + /// + /// Returns an array of UserTypes + /// + [Obsolete("Use the GetAll method instead")] + public static UserType[] getAll + { + get { return GetAllUserTypes().ToArray(); } + } + #endregion + + /// + /// Saves this instance. + /// + public void Save() + { + //ensure that this object has an ID specified (it exists in the database) + if (m_id == null || m_id <= 0) + throw new Exception("The current UserType object does not exist in the database. New UserTypes should be created with the MakeNew method"); + + SqlHelper.ExecuteNonQuery(@" + update umbracoUserType set + userTypeAlias=@alias,userTypeName=@name,userTypeDefaultPermissions=@permissions + where id=@id", + SqlHelper.CreateParameter("@alias", m_alias), + SqlHelper.CreateParameter("@name", m_name), + SqlHelper.CreateParameter("@permissions", m_defaultPermissions), + SqlHelper.CreateParameter("@id", m_id) + ); + + ReCache(); + } + + /// + /// Deletes this instance. + /// + public void Delete() + { + //ensure that this object has an ID specified (it exists in the database) + if (m_id == null || m_id <= 0) + throw new Exception("The current UserType object does not exist in the database. New UserTypes should be created with the MakeNew method"); + + SqlHelper.ExecuteNonQuery(@" + delete from umbracoUserType where id=@id", + SqlHelper.CreateParameter("@id", m_id)); + + ReCache(); + } + + /// + /// Load the data for the current UserType by it's id + /// + /// + /// Returns true if the UserType id was found + /// and the data was loaded, false if it wasn't + public bool LoadByPrimaryKey(int id) + { + UserType userType = GetUserType(id); + if (userType == null) + return false; + + this.m_id = userType.Id; + this.m_alias = userType.Alias; + this.m_defaultPermissions = userType.DefaultPermissions; + this.m_name = userType.Name; + + return true; + } + + /// + /// Creates a new user type + /// + /// + /// + /// + public static UserType MakeNew(string name, string defaultPermissions, string alias) + { + //ensure that the current alias does not exist + //get the id for the new user type + UserType existing = UserTypes.Find( + delegate(UserType ut) + { + return (ut.Alias == alias); + } + ); + if (existing != null) + throw new Exception("The UserType alias specified already exists"); + + SqlHelper.ExecuteNonQuery(@" + insert into umbracoUserType + (userTypeAlias,userTypeName,userTypeDefaultPermissions) + values (@alias,@name,@permissions)", + SqlHelper.CreateParameter("@alias", alias), + SqlHelper.CreateParameter("@name", name), + SqlHelper.CreateParameter("@permissions", defaultPermissions)); + + ReCache(); + + //find the new user type + existing = UserTypes.Find( + delegate(UserType ut) + { + return (ut.Alias == alias); + } + ); + + return existing; + } + + /// + /// Gets the user type with the specied ID + /// + /// The id. + /// + public static UserType GetUserType(int id) + { + return UserTypes.Find( + delegate(UserType ut) + { + return (ut.Id == id); + } + ); + } + + /// + /// Returns all UserType's + /// + /// + public static List GetAllUserTypes() + { + return UserTypes; + } + + /// + /// Removes the UserType cache and re-reads the data from the db. + /// + private static void ReCache() + { + HttpRuntime.Cache.Remove(CACHE_KEY); + Cache(); + } + + /// + /// Read all UserType data and store it in cache. + /// + private static void Cache() + { + //don't query the database is the cache is not null + if (HttpRuntime.Cache[CACHE_KEY] != null) + return; + + List tmp = new List(); + using (IRecordsReader dr = + SqlHelper.ExecuteReader("select id, userTypeName, userTypeAlias, userTypeDefaultPermissions from umbracoUserType")) + { + while (dr.Read()) + { + tmp.Add(new UserType( + dr.GetShort("id"), + dr.GetString("userTypeName"), + dr.GetString("userTypeDefaultPermissions"), + dr.GetString("userTypeAlias"))); + } + } + + UserTypes = tmp; + + } + + + } +} \ No newline at end of file diff --git a/umbraco/businesslogic/Utils/EncodedStringWriter.cs b/umbraco/businesslogic/Utils/EncodedStringWriter.cs new file mode 100644 index 0000000000..6c0dcef3b7 --- /dev/null +++ b/umbraco/businesslogic/Utils/EncodedStringWriter.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; + +namespace umbraco.BusinessLogic.Utils +{ + + /// + /// A TextWriter class based on the StringWriter that can support any encoding, not just UTF-16 + /// as is the default of the normal StringWriter class + /// + public class EncodedStringWriter : StringWriter + { + + /// + /// Initializes a new instance of the class. + /// + /// The sb. + /// The enc. + public EncodedStringWriter(StringBuilder sb, Encoding enc) + : base(sb) + { + m_encoding = enc; + } + + private Encoding m_encoding; + + /// + /// Gets the in which the output is written. + /// + /// + /// The Encoding in which the output is written. + public override Encoding Encoding + { + get + { + return m_encoding; + } + } + } +} diff --git a/umbraco/businesslogic/Utils/JSONSerializer.cs b/umbraco/businesslogic/Utils/JSONSerializer.cs new file mode 100644 index 0000000000..b2d1336c01 --- /dev/null +++ b/umbraco/businesslogic/Utils/JSONSerializer.cs @@ -0,0 +1,85 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web.Script.Serialization; +using System.Text.RegularExpressions; + +namespace umbraco.businesslogic.Utils +{ + /// + /// The built in JavaScriptSerializer does not allow you to export real JavaScript + /// objects, functions, etc... only string values which isn't always what you want. + /// See + /// + /// Override the JavaScriptSerializer serialization process and look for any + /// custom "tags" strings such as a @ symbol which depicts that the string value + /// should really be a JSON value, therefore the output removes the double quotes. + /// + /// + /// + /// If you want to output: + /// {"myFunction": function() {alert('hello');}} + /// The JavaScriptSerializer will not let you do this, it will render: + /// {"myFunction": "function() {alert('hello');}"} + /// which means that JavaScript will interpret it as a string. + /// This class allows you to output JavaScript objects, amongst other things. + /// + public class JSONSerializer : JavaScriptSerializer + { + + public new string Serialize(object obj) + { + string output = base.Serialize(obj); + + //replaces all strings beginning with this prefix to have no double quotes + Regex regex1 = new Regex(string.Format("(\"{0}(.*?)\")+", PrefixJavaScriptObject), + RegexOptions.Multiline + | RegexOptions.CultureInvariant + | RegexOptions.Compiled + ); + string result = regex1.Replace(output, "$2"); + + //replaces all strings beginning with this prefix to have no single instead of double + Regex regex2 = new Regex(string.Format("(\"{0}(.*?)\")+", PrefixSingleQuotes), + RegexOptions.Multiline + | RegexOptions.CultureInvariant + | RegexOptions.Compiled + ); + result = regex2.Replace(result, "'$2'"); + + return result; + } + + private const string PrefixJavaScriptObject = "@@@@"; + private const string PrefixSingleQuotes = "!!!!"; + + /// + /// method for a string to be converted to a json object. + /// + /// + /// A string formatted with a special prefix + /// + /// This essentially just prefixes the string with a special key that we will use + /// to parse with later during serialization. + /// + public static string ToJSONObject(string s) + { + return PrefixJavaScriptObject + s; + } + + /// + /// method to use so that the serializer outputs a string with single quotes instead + /// of double quotes. + /// + /// + /// + public static string ToSingleQuotedString(string s) + { + return PrefixSingleQuotes + s; + } + } + + + +} + diff --git a/umbraco/businesslogic/Utils/SerializableData.cs b/umbraco/businesslogic/Utils/SerializableData.cs new file mode 100644 index 0000000000..2536ef5181 --- /dev/null +++ b/umbraco/businesslogic/Utils/SerializableData.cs @@ -0,0 +1,53 @@ +using System; +using System.Xml.Serialization; +using System.Collections; +using System.Xml.Schema; +using System.ComponentModel; +using System.IO; +using System.Xml; +using System.Text; + +namespace umbraco.BusinessLogic.Utils +{ + /// + /// A generic class to inherit from or use by itself so that the serialize/deserialize methods are available to it + /// + public class SerializableData + { + public static object Deserialize(string strXML, Type objectType) + { + StringReader sr = new StringReader(strXML); + XmlSerializer xSer = new XmlSerializer(objectType); + object objSerialized = xSer.Deserialize(sr); + sr.Close(); + return objSerialized; + } + + /// + /// Generic Serialization method that will serialize object without the default namespaces: + /// http://www.w3.org/2001/XMLSchema + /// http://www.w3.org/2001/XMLSchema-instance + /// This also ensures that the returned XML is always encoded in UTF-8. + /// + /// + /// + /// + public static string Serialize(object objDeserialized, Type objectType) + { + //create empty namespaces so as to not render the default: + //xmlns:xsd="http://www.w3.org/2001/XMLSchema" + //xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + XmlSerializerNamespaces ns = new XmlSerializerNamespaces(); + ns.Add("", ""); + + XmlSerializer xSer = new XmlSerializer(objectType); + EncodedStringWriter sw = new EncodedStringWriter(new StringBuilder(), Encoding.UTF8); + xSer.Serialize(sw, objDeserialized, ns); + string str = sw.ToString(); + sw.Close(); + return str; + + } + + } +} diff --git a/umbraco/businesslogic/Utils/TypeFinder.cs b/umbraco/businesslogic/Utils/TypeFinder.cs new file mode 100644 index 0000000000..68987c63cf --- /dev/null +++ b/umbraco/businesslogic/Utils/TypeFinder.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Reflection; +using System.Web; +using System.IO; + +namespace umbraco.BusinessLogic.Utils +{ + /// + /// A utility class to find all classes of a certain type by reflection in the current bin folder + /// of the web application. + /// + public static class TypeFinder + { + + /// + /// Searches all loaded assemblies for classes of the type passed in. + /// + /// The type of object to search for + /// true if a seperate app domain should be used to query the types. This is safer as it is able to clear memory after loading the types. + /// A list of found types + public static List FindClassesOfType(bool useSeperateAppDomain) + { + if (useSeperateAppDomain) + { + string binFolder = Path.Combine(HttpContext.Current.Request.PhysicalApplicationPath, "bin"); + string[] strTypes = TypeResolver.GetAssignablesFromType(binFolder, "*.dll"); + + List types = new List(); + + foreach (string type in strTypes) + types.Add(Type.GetType(type)); + + return types; + } + else + return FindClassesOfType(typeof(T)); + } + + /// + /// Finds all classes with the specified type + /// + /// The type. + /// A list of found classes + private static List FindClassesOfType(Type type) + { + bool searchGAC = false; + + List classesOfType = new List(); + + foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) + { + //don't check any types if the assembly is part of the GAC + if (!searchGAC && assembly.GlobalAssemblyCache) + continue; + + Type[] publicTypes; + //need try catch block as some assemblies do not support this (i.e.RefEmit_InMemoryManifestModule) + try + { + publicTypes = assembly.GetExportedTypes(); + } + catch { continue; } + + List listOfTypes = new List(); + listOfTypes.AddRange(publicTypes); + List foundTypes = listOfTypes.FindAll( + delegate(Type t) { return (type.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract); } + ); + Type[] outputTypes = new Type[foundTypes.Count]; + foundTypes.CopyTo(outputTypes); + classesOfType.AddRange(outputTypes); + } + + return classesOfType; + } + + } +} diff --git a/umbraco/businesslogic/Utils/TypeResolver.cs b/umbraco/businesslogic/Utils/TypeResolver.cs new file mode 100644 index 0000000000..75e2c9a1c0 --- /dev/null +++ b/umbraco/businesslogic/Utils/TypeResolver.cs @@ -0,0 +1,138 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Collections.Generic; +using System.Reflection; + +namespace umbraco.BusinessLogic.Utils +{ + /// + /// Represents the Umbraco Typeresolver class. + /// The typeresolver is a collection of utillities for finding and determining types and classes with reflection. + /// + [Serializable] + public class TypeResolver : MarshalByRefObject + { + /// + /// Gets a collection of assignables of type T from a collection of a specific file type from a specified path. + /// + /// The Type + /// The path. + /// The file pattern. + /// + public static string[] GetAssignablesFromType(string path, string filePattern) + { + FileInfo[] fis = Array.ConvertAll( + Directory.GetFiles(path, filePattern), + delegate(string s) { return new FileInfo(s); }); + string[] absoluteFiles = Array.ConvertAll( + fis, delegate(FileInfo fi) { return fi.FullName; }); + return GetAssignablesFromType(absoluteFiles); + } + + /// + /// Gets a collection of assignables of type T from a collection of files + /// + /// + /// The files. + /// + public static string[] GetAssignablesFromType(string[] files) + { + + AppDomain sandbox = AppDomain.CurrentDomain; + + if (!GlobalSettings.UseMediumTrust) { + AppDomainSetup domainSetup = new AppDomainSetup(); + domainSetup.ApplicationBase = AppDomain.CurrentDomain.SetupInformation.ApplicationBase; + domainSetup.ApplicationName = "Umbraco_Sandbox_" + Guid.NewGuid(); + domainSetup.ConfigurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile; + domainSetup.DynamicBase = AppDomain.CurrentDomain.SetupInformation.DynamicBase; + domainSetup.LicenseFile = AppDomain.CurrentDomain.SetupInformation.LicenseFile; + domainSetup.LoaderOptimization = AppDomain.CurrentDomain.SetupInformation.LoaderOptimization; + domainSetup.PrivateBinPath = AppDomain.CurrentDomain.SetupInformation.PrivateBinPath; + domainSetup.PrivateBinPathProbe = AppDomain.CurrentDomain.SetupInformation.PrivateBinPathProbe; + domainSetup.ShadowCopyFiles = "false"; + + sandbox = AppDomain.CreateDomain("Sandbox", AppDomain.CurrentDomain.Evidence, domainSetup); + } + + try + { + TypeResolver typeResolver = (TypeResolver)sandbox.CreateInstanceAndUnwrap( + typeof(TypeResolver).Assembly.GetName().Name, + typeof(TypeResolver).FullName); + + return typeResolver.GetTypes(typeof(T), files); + } + catch(Exception ex) + { + Debug.WriteLine(ex.ToString()); + } + finally + { + if (!GlobalSettings.UseMediumTrust) + AppDomain.Unload(sandbox); + } + + + return new string[0]; + } + + /// + /// Returns of a collection of type names from a collection of assembky files. + /// + /// The assign type. + /// The assembly files. + /// + public string[] GetTypes(Type assignTypeFrom, string[] assemblyFiles) + { + List result = new List(); + foreach(string fileName in assemblyFiles) + { + if(!File.Exists(fileName)) + continue; + try + { + Assembly assembly = Assembly.LoadFile(fileName); + + if (assembly != null) { + foreach (Type t in assembly.GetTypes()) { + if (!t.IsInterface && assignTypeFrom.IsAssignableFrom(t)) + result.Add(t.AssemblyQualifiedName); + } + } + } + catch(Exception e) + { + Debug.WriteLine(string.Format("Error loading assembly: {0}\n{1}", fileName, e)); + } + } + + /* + try{ + System.Collections.IList list = System.Web.Compilation.BuildManager.CodeAssemblies; + if (list != null && list.Count > 0) { + Assembly asm; + foreach (object o in list) { + asm = o as Assembly; + + Log.Add(LogTypes.Debug, -1, "assembly " + asm.ToString() ); + if (asm != null) { + foreach (Type t in asm.GetTypes()) { + if (!t.IsInterface && assignTypeFrom.IsAssignableFrom(t)) + result.Add(t.AssemblyQualifiedName); + } + } + } + } else { + Log.Add(LogTypes.Debug, -1, "No assemblies"); + } + } catch(Exception ee) { + Log.Add(LogTypes.Debug, -1, ee.ToString()); + } + */ + + return result.ToArray(); + } + } +} diff --git a/umbraco/businesslogic/Utils/fileHelper.cs b/umbraco/businesslogic/Utils/fileHelper.cs new file mode 100644 index 0000000000..6dac4ed113 --- /dev/null +++ b/umbraco/businesslogic/Utils/fileHelper.cs @@ -0,0 +1,37 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Security; +using System.IO; +using System.Security.AccessControl; +using System.Security.Authentication; +using System.Security.Cryptography; +using System.Security.Permissions; +using System.Security.Policy; +using System.Security.Principal; + +namespace umbraco.Utils { + public class fileHelper { + + public static bool TestReadWriteAccces(string filePath) { + FileInfo fi = new FileInfo(filePath); + if (!fi.IsReadOnly) + return HasAccces(fi, FileSystemRights.Modify); + else + return false; + } + + public static bool HasAccces(FileInfo fileInfo, FileSystemRights fileSystemRights) { + string identityName = System.Security.Principal.WindowsIdentity.GetCurrent().Name.ToUpper(); + + AuthorizationRuleCollection authorizationRuleCollection = fileInfo.GetAccessControl().GetAccessRules(true, true, typeof(NTAccount)); + + foreach (FileSystemAccessRule fileSystemAccessRule in authorizationRuleCollection) { + if (identityName == fileSystemAccessRule.IdentityReference.Value.ToUpper()) + return AccessControlType.Allow == fileSystemAccessRule.AccessControlType && fileSystemRights == (fileSystemAccessRule.FileSystemRights & fileSystemRights); + } + + return false; + } + } +} diff --git a/umbraco/businesslogic/ui.cs b/umbraco/businesslogic/ui.cs new file mode 100644 index 0000000000..ff5cf40238 --- /dev/null +++ b/umbraco/businesslogic/ui.cs @@ -0,0 +1,316 @@ +using System; +using System.Text.RegularExpressions; +using System.Threading; +using System.Web; +using System.Web.Caching; +using System.Xml; +using umbraco.BasePages; +using umbraco.BusinessLogic; + +namespace umbraco +{ + /// + /// The ui class handles the multilingual text in the umbraco back-end. + /// Provides access to language settings and language files used in the umbraco back-end. + /// + public class ui + { + private static readonly string umbracoDefaultUILanguage = GlobalSettings.DefaultUILanguage; + private static readonly string umbracoPath = GlobalSettings.Path; + + /// + /// Gets the current Culture for the logged-in users + /// + /// The user. + /// + public static string Culture(User u) + { + XmlDocument langFile = getLanguageFile(u.Language); + try + { + return langFile.SelectSingleNode("/language").Attributes.GetNamedItem("culture").Value; + } + catch + { + return string.Empty; + } + } + + private static string getLanguage() { + if (UmbracoEnsuredPage.CurrentUser != null) { + return UmbracoEnsuredPage.CurrentUser.Language; + } else { + return umbracoDefaultUILanguage; + } + } + + /// + /// Returns translated UI text with a specific key based on the specified user's language settings + /// + /// The key. + /// The user. + /// + public static string Text(string Key, User u) + { + return GetText(Key); + } + + /// + /// Returns translated UI text with a specific key based on the logged-in user's language settings + /// + /// The key. + /// + public static string Text(string Key) + { + return GetText(Key); + } + + /// + /// Returns translated UI text with a specific key and area, based on the specified users language settings + /// + /// The area. + /// The key. + /// The user. + /// + public static string Text(string Area, string Key, User u) + { + return GetText(Area, Key); + } + + /// + /// Returns translated UI text with a specific key and area, based on the logged-in users language settings + /// + /// The area. + /// The key. + /// + public static string Text(string Area, string Key) + { + return GetText(Area, Key, getLanguage()); + } + + /// + /// Returns translated UI text with a specific area and key. based on the specified users language settings and variables array passed to the method + /// + /// The area. + /// The key. + /// The variables array. + /// The user. + /// + public static string Text(string Area, string Key, string[] Variables, User u) + { + // Check if user is null (AutoForm) + string _culture = ""; + if (u == null) + _culture = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName; + else + _culture = new System.Globalization.CultureInfo(Culture(u)).TwoLetterISOLanguageName; + + return GetText(Area, Key, Variables, _culture); + } + + /// + /// Returns translated UI text with a specific key and area based on the specified users language settings and single variable passed to the method + /// + /// The area. + /// The key. + /// The variable. + /// The u. + /// + public static string Text(string Area, string Key, string Variable, User u) + { + return GetText(Area, Key, Variable); + } + + /// + /// Returns translated UI text with a specific key based on the logged-in user's language settings + /// + /// The key. + /// + public static string GetText(string key) + { + if (key == null) + return string.Empty; + + string language = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName; + if (string.IsNullOrEmpty(language)) + language = umbracoDefaultUILanguage; + + XmlDocument langFile = getLanguageFile(language); + if (langFile != null) + { + XmlNode node = langFile.SelectSingleNode(string.Format("//key [@alias = '{0}']", key)); + if (node != null && node.FirstChild != null) + return node.FirstChild.Value; + } + return "[" + key + "]"; + } + + /// + /// Returns translated UI text with a specific key and area based on the logged-in users language settings + /// + /// The area. + /// The key. + /// + public static string GetText(string area, string key) + { + if (string.IsNullOrEmpty(area) || string.IsNullOrEmpty(key)) + return string.Empty; + + string language = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName; + if (string.IsNullOrEmpty(language)) + language = umbracoDefaultUILanguage; + + XmlDocument langFile = getLanguageFile(language); + if (langFile != null) + { + XmlNode node = + langFile.SelectSingleNode(string.Format("//area [@alias = '{0}']/key [@alias = '{1}']", area, key)); + if (node != null) + return xmlHelper.GetNodeValue(node); + } + return "[" + key + "]"; + } + + /// + /// Returns translated UI text with a specific key and area based on the logged-in users language settings and variables array send to the method. + /// + /// The area. + /// The key. + /// The variables. + /// + public static string GetText(string area, string key, string[] variables) + { + if (string.IsNullOrEmpty(area) || string.IsNullOrEmpty(key) || variables == null) + return string.Empty; + + string language = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName; + if (string.IsNullOrEmpty(language)) + language = umbracoDefaultUILanguage; + + XmlDocument langFile = getLanguageFile(language); + if (langFile != null) + { + XmlNode node = langFile.SelectSingleNode(string.Format("//area [@alias = '{0}']/key [@alias = '{1}']", + area, key)); + if (node != null) + { + string stringWithVars = GetStringWithVars(node, variables); + return stringWithVars; + } + } + return "[" + key + "]"; + } + + /// + /// Returns translated UI text with a specific key, area and language matching the variables send to the method. + /// + /// The area. + /// The key. + /// The variables. + /// The language. + /// + public static string GetText(string area, string key, string[] variables, string language) + { + if (string.IsNullOrEmpty(area) || string.IsNullOrEmpty(key) || variables == null) + return string.Empty; + + XmlDocument langFile = getLanguageFile(language); + if (langFile != null) + { + XmlNode node = langFile.SelectSingleNode(string.Format("//area [@alias = '{0}']/key [@alias = '{1}']", + area, key)); + if (node != null) + { + string stringWithVars = GetStringWithVars(node, variables); + return stringWithVars; + } + } + return "[" + key + "]"; + } + + private static string GetStringWithVars(XmlNode node, string[] variables) + { + string stringWithVars = xmlHelper.GetNodeValue(node); + MatchCollection vars = + Regex.Matches(stringWithVars, @"\%(\d)\%", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + foreach (Match var in vars) + { + stringWithVars = + stringWithVars.Replace(var.Value, + variables[Convert.ToInt32(var.Groups[0].Value.Replace("%", ""))]); + } + return stringWithVars; + } + + /// + /// Returns translated UI text with a specific key and area matching the variable send to the method. + /// + /// The area. + /// The key. + /// The variable. + /// + public static string GetText(string area, string key, string variable) + { + if (string.IsNullOrEmpty(area) || string.IsNullOrEmpty(key) || string.IsNullOrEmpty(variable)) + return string.Empty; + + string language = Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName; + if (string.IsNullOrEmpty(language)) + language = umbracoDefaultUILanguage; + + XmlDocument langFile = getLanguageFile(language); + if (langFile != null) + { + XmlNode node = langFile.SelectSingleNode(string.Format("//area [@alias = '{0}']/key [@alias = '{1}']", + area, key)); + if (node != null) + return xmlHelper.GetNodeValue(node).Replace("%0%", variable); + } + return "[" + key + "]"; + } + + /// + /// Gets the language file as a xml document. + /// + /// The language. + /// + public static XmlDocument getLanguageFile(string language) + { + XmlDocument langFile = new XmlDocument(); + + string cacheKey = "uitext_" + language; + + // Check for language file in cache + if (HttpRuntime.Cache[cacheKey] == null) + { + using (XmlTextReader langReader = + new XmlTextReader( + HttpContext.Current.Server.MapPath(umbracoPath + "/config/lang/" + language + ".xml"))) + { + try + { + langFile.Load(langReader); + HttpRuntime.Cache.Insert(cacheKey, langFile, + new CacheDependency( + HttpContext.Current.Server.MapPath(umbracoPath + "/config/lang/" + + language + ".xml"))); + } + catch (Exception e) + { + HttpContext.Current.Trace.Warn("ui", + "Error reading umbraco language xml source (" + language + ")", e); + } + } + } + else + langFile = (XmlDocument) HttpRuntime.Cache["uitext_" + language]; + + return langFile; + } + + private void insertKey(string key, string area, string language) { + + } + } +} \ No newline at end of file diff --git a/umbraco/businesslogic/umbraco.businesslogic.csproj b/umbraco/businesslogic/umbraco.businesslogic.csproj new file mode 100644 index 0000000000..d67b075ac7 --- /dev/null +++ b/umbraco/businesslogic/umbraco.businesslogic.csproj @@ -0,0 +1,203 @@ + + + Local + 9.0.30729 + 2.0 + {E469A9CE-1BEC-423F-AC44-713CD72457EA} + Debug + AnyCPU + + + + + businesslogic + + + JScript + Grid + IE50 + false + Library + umbraco.businesslogic + OnBuildSuccess + + + + + + + SAK + SAK + SAK + SAK + 2.0 + http://localhost/businesslogic/ + true + Web + true + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + true + false + true + + + bin\Debug\ + false + 285212672 + false + + + DEBUG;TRACE + + + true + 4096 + false + + + false + false + false + false + 4 + full + prompt + + + bin\release\ + false + 285212672 + false + + + TRACE + bin\release\businesslogic.XML + false + 4096 + false + + + true + false + false + false + 4 + none + prompt + + + + System + + + + System.Data + + + System.Web + + + + System.XML + + + {C7CB79F0-1C97-4B33-BFA7-00731B579AE2} + umbraco.datalayer + + + umbraco.interfaces + {511F6D8D-7717-440A-9A57-A507E9A8B27F} + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + + + + + Code + + + + + Code + + + ASPXCodeBehind + + + + ASPXCodeBehind + + + + Code + + + Code + + + Code + + + Code + + + + Code + + + Code + + + Code + + + Code + + + Code + + + + + + Code + + + + Code + + + + + False + .NET Framework 2.0 %28x86%29 + true + + + False + .NET Framework 3.0 %28x86%29 + false + + + False + .NET Framework 3.5 + false + + + + + + + + + + + + + \ No newline at end of file diff --git a/umbraco/businesslogic/umbraco.businesslogic.csproj.vspscc b/umbraco/businesslogic/umbraco.businesslogic.csproj.vspscc new file mode 100644 index 0000000000..feffdecaa4 --- /dev/null +++ b/umbraco/businesslogic/umbraco.businesslogic.csproj.vspscc @@ -0,0 +1,10 @@ +"" +{ +"FILE_VERSION" = "9237" +"ENLISTMENT_CHOICE" = "NEVER" +"PROJECT_FILE_RELATIVE_PATH" = "" +"NUMBER_OF_EXCLUDED_FILES" = "0" +"ORIGINAL_PROJECT_FILE_PATH" = "" +"NUMBER_OF_NESTED_PROJECTS" = "0" +"SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" +} diff --git a/umbraco/businesslogic/xmlHelper.cs b/umbraco/businesslogic/xmlHelper.cs new file mode 100644 index 0000000000..4889919723 --- /dev/null +++ b/umbraco/businesslogic/xmlHelper.cs @@ -0,0 +1,96 @@ +using System; +using System.Xml; + +namespace umbraco +{ + /// + /// The xmlHelper class contains general helper methods for working with xml in umbraco. + /// + public class xmlHelper + { + /// + /// Imports a XML node from text. + /// + /// The text. + /// The XML doc. + /// + public static XmlNode ImportXmlNodeFromText (string text, ref XmlDocument xmlDoc) + { + xmlDoc.LoadXml(text); + return xmlDoc.FirstChild; + } + + /// + /// Opens a file as a XmlDocument. + /// + /// The relative file path. ei. /config/umbraco.config + /// Returns a XmlDocument class + public static XmlDocument OpenAsXmlDocument(string filePath) { + + XmlTextReader reader = new XmlTextReader(System.Web.HttpContext.Current.Server.MapPath(filePath)); + + reader.WhitespaceHandling = WhitespaceHandling.All; + XmlDocument xmlDoc = new XmlDocument(); + //Load the file into the XmlDocument + xmlDoc.Load(reader); + //Close off the connection to the file. + reader.Close(); + + return xmlDoc; + } + + /// + /// creates a XmlAttribute with the specified name and value + /// + /// The xmldocument. + /// The name of the attribute. + /// The value of the attribute. + /// a XmlAttribute + public static XmlAttribute addAttribute(XmlDocument Xd, string Name, string Value) + { + XmlAttribute temp = Xd.CreateAttribute(Name); + temp.Value = Value; + return temp; + } + + /// + /// Creates a text XmlNode with the specified name and value + /// + /// The xmldocument. + /// The node name. + /// The node value. + /// a XmlNode + public static XmlNode addTextNode(XmlDocument Xd, string Name, string Value) + { + XmlNode temp = Xd.CreateNode(XmlNodeType.Element, Name, ""); + temp.AppendChild(Xd.CreateTextNode(Value)); + return temp; + } + + /// + /// Creates a cdata XmlNode with the specified name and value + /// + /// The xmldocument. + /// The node name. + /// The node value. + /// A XmlNode + public static XmlNode addCDataNode(XmlDocument Xd, string Name, string Value) + { + XmlNode temp = Xd.CreateNode(XmlNodeType.Element, Name, ""); + temp.AppendChild(Xd.CreateCDataSection(Value)); + return temp; + } + + /// + /// Gets the value of a XmlNode + /// + /// The XmlNode. + /// the value as a string + public static string GetNodeValue(XmlNode n) + { + if (n == null || n.FirstChild == null) + return string.Empty; + return n.FirstChild.Value; + } + } +} diff --git a/umbraco/cms/Actions/Action.cs b/umbraco/cms/Actions/Action.cs new file mode 100644 index 0000000000..fbe8144cd1 --- /dev/null +++ b/umbraco/cms/Actions/Action.cs @@ -0,0 +1,269 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Web; +using System.Reflection; +using umbraco.BasePages; +using umbraco.BusinessLogic.Utils; +using umbraco.cms.businesslogic.web; +using umbraco.cms.businesslogic.workflow; +using umbraco.interfaces; + +namespace umbraco.BusinessLogic.Actions +{ + /// + /// Actions and Actionhandlers are a key concept to umbraco and a developer whom wish to apply + /// businessrules whenever data is changed within umbraco, by implementing the IActionHandler + /// interface it's possible to invoke methods (foreign to umbraco) - this can be used whenever + /// there is a specific rule which needs to be applied to content. + /// + /// The Action class itself has responsibility for registering actions and actionhandlers, + /// and contains methods which will be invoked whenever a change is made to ex. a document, media or member + /// + /// An action/actionhandler will automatically be registered, using reflection + /// which is enabling thirdparty developers to extend the core functionality of + /// umbraco without changing the codebase. + /// + public class Action + { + private static readonly List _actions = new List(); + private static readonly Dictionary _actionJs = new Dictionary(); + private static readonly List _actionHandlers = new List(); + private static readonly List _actionJSReference = new List(); + + static Action() + { + RegisterIActions(); + RegisterIActionHandlers(); + } + + /// + /// Stores all IActionHandlers that have been loaded into memory into a list + /// + private static void RegisterIActionHandlers() + { + if (_actionHandlers.Count > 0) + return; + + List foundIActionHandlers = TypeFinder.FindClassesOfType(true); + foreach (Type type in foundIActionHandlers) + { + IActionHandler typeInstance; + typeInstance = Activator.CreateInstance(type) as IActionHandler; + if (typeInstance != null) + _actionHandlers.Add(typeInstance); + } + } + + /// + /// Stores all IActions that have been loaded into memory into a list + /// + private static void RegisterIActions() + { + if (_actions.Count > 0) + return; + + List foundIActions = TypeFinder.FindClassesOfType(true); + foreach (Type type in foundIActions) + { + IAction typeInstance; + PropertyInfo instance = type.GetProperty("Instance", BindingFlags.Public | BindingFlags.Static); + //if the singletone initializer is not found, try simply creating an instance of the IAction if it supports public constructors + if (instance == null) + typeInstance = Activator.CreateInstance(type) as IAction; + else + typeInstance = instance.GetValue(null, null) as IAction; + + if (typeInstance != null) + { + if (!string.IsNullOrEmpty(typeInstance.JsSource)) + _actionJSReference.Add(typeInstance.JsSource); + _actions.Add(typeInstance); + } + + } + } + + /// + /// Whenever an action is performed upon a document/media/member, this method is executed, ensuring that + /// all registered handlers will have an oppotunity to handle the action. + /// + /// The document being operated on + /// The action triggered + public static void RunActionHandlers(Document d, IAction action) + { + foreach (IActionHandler ia in _actionHandlers) + { + try + { + foreach (IAction a in ia.ReturnActions()) + { + if (a.Alias == action.Alias) + { + // Uncommented for auto publish support + // System.Web.HttpContext.Current.Trace.Write("BusinessLogic.Action.RunActionHandlers", "Running " + ia.HandlerName() + " (matching action: " + a.Alias + ")"); + ia.Execute(d, action); + } + } + } + catch (Exception iaExp) + { + Log.Add(LogTypes.Error, User.GetUser(0), -1, string.Format("Error loading actionhandler '{0}': {1}", + ia.HandlerName(), iaExp)); + } + } + + // Run notification + // Find current user + User u; + try + { + u = new UmbracoEnsuredPage().getUser(); + } + catch + { + u = User.GetUser(0); + } + Notification.GetNotifications(d, u, action); + } + + /// + /// Jacascript for the contextmenu + /// Suggestion: this method should be moved to the presentation layer. + /// + /// + /// String representation + public string ReturnJavascript(string language) + { + return findActions(language); + } + + /// + /// Returns a list of JavaScript file paths. + /// + /// + public static List GetJavaScriptFileReferences() + { + return _actionJSReference; + } + + /// + /// Javascript menuitems - tree contextmenu + /// Umbraco console + /// + /// Suggestion: this method should be moved to the presentation layer. + /// + /// + /// + private static string findActions(string language) + { + if (!_actionJs.ContainsKey(language)) + { + string _actionJsList = ""; + + foreach (IAction action in _actions) + { + // Adding try/catch so this rutine doesn't fail if one of the actions fail + // Add to language JsList + try + { + // NH: Add support for css sprites + string icon = action.Icon; + if (!string.IsNullOrEmpty(icon) && icon.StartsWith(".")) + icon = icon.Substring(1, icon.Length - 1); + else + icon = "images/" + icon; + + _actionJsList += string.Format(",\n\tmenuItem(\"{0}\", \"{1}\", \"{2}\", \"{3}\")", + action.Letter, icon, ui.GetText("actions", action.Alias, language), action.JsFunctionName); + } + catch (Exception ee) + { + Log.Add(LogTypes.Error, -1, "Error registrering action to javascript: " + ee.ToString()); + } + } + + if (_actionJsList.Length > 0) + _actionJsList = _actionJsList.Substring(2, _actionJsList.Length - 2); + + _actionJsList = "\nvar menuMethods = new Array(\n" + _actionJsList + "\n)\n"; + _actionJs.Add(language, _actionJsList); + } + + return _actionJs[language]; + + } + + /// + /// + /// + /// An arraylist containing all javascript variables for the contextmenu in the tree + public static ArrayList GetAll() + { + return new ArrayList(_actions); + } + + /// + /// This method will return a list of IAction's based on a string list. Each character in the list may represent + /// an IAction. This will associate any found IActions based on the Letter property of the IAction with the character being referenced. + /// + /// + /// returns a list of actions that have an associated letter found in the action string list + public static List FromString(string actions) + { + List list = new List(); + foreach (char c in actions.ToCharArray()) + { + IAction action = _actions.Find( + delegate(IAction a) + { + return a.Letter == c; + } + ); + if (action != null) + list.Add(action); + } + return list; + } + + /// + /// Returns the string representation of the actions that make up the actions collection + /// + /// + public static string ToString(List actions) + { + string[] strMenu = Array.ConvertAll(actions.ToArray(), delegate(IAction a) { return (a.Letter.ToString()); }); + return string.Join("", strMenu); + } + + /// + /// Returns a list of IActions that are permission assignable + /// + /// + public static List GetPermissionAssignable() + { + return _actions.FindAll( + delegate(IAction a) + { + return (a.CanBePermissionAssigned); + } + ); + } + } + + /// + /// Implement the IActionHandler interface in order to automatically get code + /// run whenever a document, member or media changed, deleted, created etc. + /// The Clases implementing IActionHandler are loaded at runtime which means + /// that there are no other setup when creating a custom actionhandler. + /// + /// + /// + /// + public interface IActionHandler + { + bool Execute(Document documentObject, IAction action); + IAction[] ReturnActions(); + string HandlerName(); + } +} diff --git a/umbraco/cms/Actions/defaultActions.cs b/umbraco/cms/Actions/defaultActions.cs new file mode 100644 index 0000000000..f078be3953 --- /dev/null +++ b/umbraco/cms/Actions/defaultActions.cs @@ -0,0 +1,2498 @@ +using System; +using umbraco.interfaces; +using umbraco.BasePages; + +namespace umbraco.BusinessLogic.Actions +{ + + /// + /// This permission is assigned to a node when there are no permissions assigned to the node. + /// This is used internally to assign no permissions to a node for a user and shouldn't be used in code. + /// + public class ActionNull : IAction + { + //create singleton + private static readonly ActionNull instance = new ActionNull(); + private ActionNull() { } + public static ActionNull Instance + { + get { return instance; } + } + + #region IAction Members + + public char Letter + { + get { return '-'; } + } + + public bool ShowInNotifier + { + get { return false; } + } + + public bool CanBePermissionAssigned + { + get { return false; } + } + + public string Icon + { + get { return string.Empty; } + } + + public string Alias + { + get { return string.Empty; } + } + + public string JsFunctionName + { + get { return string.Empty; } + } + + public string JsSource + { + get { return string.Empty; } + } + + #endregion + } + + /// + /// This action is used as a security constraint that grants a user the ability to view nodes in a tree + /// that has permissions applied to it. + /// + /// + /// This action should not be invoked. It is used as the minimum required permission to view nodes in the content tree. By + /// granting a user this permission, the user is able to see the node in the tree but not edit the document. This may be used by other trees + /// that support permissions in the future. + /// + public class ActionBrowse : IAction + { + //create singleton + private static readonly ActionBrowse instance = new ActionBrowse(); + private ActionBrowse() { } + public static ActionBrowse Instance + { + get { return instance; } + } + + #region IAction Members + + public char Letter + { + get { return 'F'; } + } + + public bool ShowInNotifier + { + get { return false; } + } + + public bool CanBePermissionAssigned + { + get { return true; } + } + + public string Icon + { + get { return ""; } + } + + public string Alias + { + get { return "browse"; } + } + + public string JsFunctionName + { + get { return ""; } + } + + public string JsSource + { + get { return ""; } + } + + #endregion + } + + + public class ActionLiveEdit : IAction + { + //create singleton + private static readonly ActionLiveEdit instance = new ActionLiveEdit(); + private ActionLiveEdit() { } + public static ActionLiveEdit Instance + { + get { return instance; } + } + + #region IAction Members + + public char Letter + { + get { return ':'; } + } + + public bool ShowInNotifier + { + get { return false; } + } + + public bool CanBePermissionAssigned + { + get { return true; } + } + + public string Icon + { + get { return ".sprLiveEdit"; } + } + + public string Alias + { + get { return "liveEdit"; } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionLiveEdit()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get { return ""; } + } + + #endregion + } + + /// + /// Used simply to define context menu seperator items. + /// This should not be used directly in any code except for creating menus. + /// + public class ContextMenuSeperator : IAction + { + //create singleton + private static readonly ContextMenuSeperator instance = new ContextMenuSeperator(); + private ContextMenuSeperator() { } + public static ContextMenuSeperator Instance + { + get { return instance; } + } + + #region IAction Members + + public char Letter + { + get { return ','; } + } + + public string JsFunctionName + { + get { return string.Empty; } + } + public string JsSource + { + get { return string.Empty; } + } + public string Alias + { + get { return string.Empty; } + } + public string Icon + { + get { return string.Empty; } + } + public bool ShowInNotifier + { + get { return false; } + } + public bool CanBePermissionAssigned + { + get { return false; } + } + + #endregion + } + + /// + /// This action is invoked upon creation of a document + /// + public class ActionNew : IAction { + //create singleton + private static readonly ActionNew m_instance = new ActionNew(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionNew() { } + + public static ActionNew Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter { + get { + return 'C'; + } + } + + public string JsFunctionName { + get + { + return string.Format("{0}.actionNew()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource { + get { + return null; + } + } + + public string Alias { + get { + return "create"; + } + } + + public string Icon { + get { + return ".sprNew"; + } + } + + public bool ShowInNotifier { + get { + return true; + } + } + public bool CanBePermissionAssigned { + get { + return true; + } + } + + #endregion + } + + /// + /// This action is invoked upon creation of a document + /// + public class ActionNewFolder : IAction { + //create singleton + private static readonly ActionNewFolder m_instance = new ActionNewFolder(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionNewFolder() { } + + public static ActionNewFolder Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter { + get { + return '!'; + } + } + + public string JsFunctionName { + get { + return string.Format("{0}.actionNewFolder()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource { + get { + return null; + } + } + + public string Alias { + get { + return "createFolder"; + } + } + + public string Icon { + get { + return ".sprCreateFolder"; + } + } + + public bool ShowInNotifier { + get { + return false; + } + } + public bool CanBePermissionAssigned { + get { + return false; + } + } + + #endregion + } + + /// + /// This action is invoked when a send to translate request occurs + /// + public class ActionSendToTranslate : IAction + { + //create singleton + private static readonly ActionSendToTranslate m_instance = new ActionSendToTranslate(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionSendToTranslate() { } + + public static ActionSendToTranslate Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return '5'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionSendToTranslate()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "sendToTranslate"; + } + } + + public string Icon + { + get + { + return ".sprSendToTranslate"; + } + } + + public bool ShowInNotifier + { + get + { + return true; + } + } + public bool CanBePermissionAssigned + { + get + { + return true; + } + } + + #endregion + } + + /// + /// This action is invoked when the trash can is emptied + /// + public class ActionEmptyTranscan : IAction + { + //create singleton + private static readonly ActionEmptyTranscan m_instance = new ActionEmptyTranscan(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionEmptyTranscan() { } + + public static ActionEmptyTranscan Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return 'N'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionEmptyTranscan()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "emptyTrashcan"; + } + } + + public string Icon + { + get + { + return ".sprBinEmpty"; + } + } + + public bool ShowInNotifier + { + get + { + return false; + } + } + public bool CanBePermissionAssigned + { + get + { + return false; + } + } + + #endregion + } + + /// + /// This action is invoked when a translation occurs + /// + public class ActionTranslate : IAction + { + //create singleton + private static readonly ActionTranslate m_instance = new ActionTranslate(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionTranslate() { } + + public static ActionTranslate Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return '4'; + } + } + + public string JsFunctionName + { + get + { + return ""; + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "translate"; + } + } + + public string Icon + { + get + { + return "sprTranslate"; + } + } + + public bool ShowInNotifier + { + get + { + return true; + } + } + public bool CanBePermissionAssigned + { + get + { + return true; + } + } + + #endregion + } + + /// + /// This action is invoked upon saving of a document, media, member + /// + public class ActionSave : IAction + { + //create singleton + private static readonly ActionSave m_instance = new ActionSave(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionSave() { } + + public static ActionSave Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return '0'; + } + } + + public string JsFunctionName + { + get + { + return ""; + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "save"; + } + } + + public string Icon + { + get + { + return ".sprSave"; + } + } + + public bool ShowInNotifier + { + get + { + return false; + } + } + public bool CanBePermissionAssigned + { + get + { + return false; + } + } + + #endregion + } + + /// + /// This action is invoked when importing a document type + /// + public class ActionImport : IAction + { + //create singleton + private static readonly ActionImport m_instance = new ActionImport(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionImport() { } + + public static ActionImport Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return '8'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionImport()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "importDocumentType"; + } + } + + public string Icon + { + get + { + return ".sprImportDocumentType"; + } + } + + public bool ShowInNotifier + { + get + { + return false; + } + } + public bool CanBePermissionAssigned + { + get + { + return false; + } + } + + #endregion + } + + /// + /// This action is invoked when exporting a document type + /// + public class ActionExport : IAction + { + //create singleton + private static readonly ActionExport m_instance = new ActionExport(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionExport() { } + + public static ActionExport Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return '9'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionExport()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "exportDocumentType"; + } + } + + public string Icon + { + get + { + return ".sprExportDocumentType"; + } + } + + public bool ShowInNotifier + { + get + { + return false; + } + } + public bool CanBePermissionAssigned + { + get + { + return false; + } + } + + #endregion + } + + /// + /// This action is invoked upon viewing audittrailing on a document + /// + public class ActionAudit : IAction + { + //create singleton + private static readonly ActionAudit m_instance = new ActionAudit(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionAudit() { } + + public static ActionAudit Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return 'Z'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionAudit()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "auditTrail"; + } + } + + public string Icon + { + get + { + return ".sprAudit"; + } + } + + public bool ShowInNotifier + { + get + { + return false; + } + } + public bool CanBePermissionAssigned + { + get + { + return true; + } + } + + #endregion + } + + /// + /// This action is invoked upon creation of a document, media, member + /// + public class ActionPackage : IAction + { + //create singleton + private static readonly ActionPackage m_instance = new ActionPackage(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionPackage() { } + + public static ActionPackage Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return 'X'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionPackage()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return ""; + } + } + + public string Alias + { + get + { + return "importPackage"; + } + } + + public string Icon + { + get + { + return ".sprPackage2"; + } + } + + public bool ShowInNotifier + { + get + { + return false; + } + } + public bool CanBePermissionAssigned + { + get + { + return false; + } + } + + #endregion + } + + /// + /// This action is invoked upon creation of a document, media, member + /// + public class ActionPackageCreate : IAction + { + //create singleton + private static readonly ActionPackageCreate m_instance = new ActionPackageCreate(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionPackageCreate() { } + + public static ActionPackageCreate Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return 'Y'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionPackageCreate()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "createPackage"; + } + } + + public string Icon + { + get + { + return ".sprPackage2"; + } + } + + public bool ShowInNotifier + { + get + { + return false; + } + } + public bool CanBePermissionAssigned + { + get + { + return false; + } + } + + #endregion + } + + /// + /// This action is invoked when a document, media, member is deleted + /// + public class ActionDelete : IAction + { + //create singleton + private static readonly ActionDelete m_instance = new ActionDelete(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionDelete() { } + + public static ActionDelete Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return 'D'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionDelete()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "delete"; + } + } + + public string Icon + { + get + { + return ".sprDelete"; + } + } + + public bool ShowInNotifier + { + get + { + return true; + } + } + public bool CanBePermissionAssigned + { + get + { + return true; + } + } + #endregion + } + + /// + /// This action is invoked when a document is disabled. + /// + public class ActionDisable : IAction + { + //create singleton + private static readonly ActionDisable m_instance = new ActionDisable(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionDisable() { } + + public static ActionDisable Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return 'E'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionDisable()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + + return "disable"; + } + } + + public string Icon + { + get + { + + return ".sprDelete"; + } + } + + public bool ShowInNotifier + { + get + { + + return false; + } + } + public bool CanBePermissionAssigned + { + get + { + + return false; + } + } + #endregion + } + + /// + /// This action is invoked upon creation of a document, media, member + /// + public class ActionMove : IAction + { + //create singleton + private static readonly ActionMove m_instance = new ActionMove(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionMove() { } + + public static ActionMove Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + + return 'M'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionMove()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + + return null; + } + } + + public string Alias + { + get + { + + return "move"; + } + } + + public string Icon + { + get + { + + return ".sprMove"; + } + } + + public bool ShowInNotifier + { + get + { + + return true; + } + } + public bool CanBePermissionAssigned + { + get + { + + return true; + } + } + #endregion + } + + /// + /// This action is invoked when copying a document, media, member + /// + public class ActionCopy : IAction + { + //create singleton + private static readonly ActionCopy m_instance = new ActionCopy(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionCopy() { } + + public static ActionCopy Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + + return 'O'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionCopy()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + + return null; + } + } + + public string Alias + { + get + { + + return "copy"; + } + } + + public string Icon + { + get + { + + return ".sprCopy"; + } + } + + public bool ShowInNotifier + { + get + { + + return true; + } + } + public bool CanBePermissionAssigned + { + get + { + + return true; + } + } + #endregion + } + + /// + /// This action is invoked when children to a document, media, member is being sorted + /// + public class ActionSort : IAction + { + //create singleton + private static readonly ActionSort m_instance = new ActionSort(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionSort() { } + + public static ActionSort Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + + return 'S'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionSort()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + + return null; + } + } + + public string Alias + { + get + { + + return "sort"; + } + } + + public string Icon + { + get + { + + return ".sprSort"; + } + } + + public bool ShowInNotifier + { + get + { + + return true; + } + } + public bool CanBePermissionAssigned + { + get + { + + return true; + } + } + #endregion + } + + /// + /// This action is invoked when rights are changed on a document + /// + public class ActionRights : IAction + { + //create singleton + private static readonly ActionRights m_instance = new ActionRights(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionRights() { } + + public static ActionRights Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + + return 'R'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionRights()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + + return null; + } + } + + public string Alias + { + get + { + + return "rights"; + } + } + + public string Icon + { + get + { + + return ".sprPermission"; + } + } + + public bool ShowInNotifier + { + get + { + + return true; + } + } + public bool CanBePermissionAssigned + { + get + { + + return true; + } + } + #endregion + } + + /// + /// This action is invoked when a document is protected or unprotected + /// + public class ActionProtect : IAction + { + //create singleton + private static readonly ActionProtect m_instance = new ActionProtect(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionProtect() { } + + public static ActionProtect Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + + return 'P'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionProtect()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + + return null; + } + } + + public string Alias + { + get + { + + return "protect"; + } + } + + public string Icon + { + get + { + + return ".sprProtect"; + } + } + + public bool ShowInNotifier + { + get + { + + return true; + } + } + public bool CanBePermissionAssigned + { + get + { + + return true; + } + } + #endregion + } + + /// + /// This action is invoked when copying a document is being rolled back + /// + public class ActionRollback : IAction + { + //create singleton + private static readonly ActionRollback m_instance = new ActionRollback(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionRollback() { } + + public static ActionRollback Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + + return 'K'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionRollback()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return ""; + } + } + + public string Alias + { + get + { + + return "rollback"; + } + } + + public string Icon + { + get + { + + return ".sprRollback"; + } + } + + public bool ShowInNotifier + { + get + { + + return true; + } + } + public bool CanBePermissionAssigned + { + get + { + + return true; + } + } + #endregion + } + + /// + /// This action is invoked when a node reloads its children + /// Concerns only the tree itself and thus you should not handle + /// this action from without umbraco. + /// + public class ActionRefresh : IAction + { + //create singleton + private static readonly ActionRefresh m_instance = new ActionRefresh(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionRefresh() { } + + public static ActionRefresh Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + + return 'L'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionRefresh()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + + return null; + } + } + + public string Alias + { + get + { + + return "refreshNode"; + } + } + + public string Icon + { + get + { + + return ".sprRefresh"; + } + } + + public bool ShowInNotifier + { + get + { + + return false; + } + } + public bool CanBePermissionAssigned + { + get + { + + return false; + } + } + #endregion + } + + /// + /// This action is invoked when a notification is sent + /// + public class ActionNotify : IAction + { + //create singleton + private static readonly ActionNotify m_instance = new ActionNotify(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionNotify() { } + + public static ActionNotify Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + + return 'T'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionNotify()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + + return null; + } + } + + public string Alias + { + get + { + return "notify"; + } + } + + public string Icon + { + get + { + return ".sprNotify"; + } + } + + public bool ShowInNotifier + { + get + { + return false; + } + } + public bool CanBePermissionAssigned + { + get + { + return false; + } + } + #endregion + } + + /// + /// This action is invoked when copying a document or media + /// + public class ActionUpdate : IAction + { + //create singleton + private static readonly ActionUpdate m_instance = new ActionUpdate(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionUpdate() { } + + public static ActionUpdate Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return 'A'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionUpdate()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "update"; + } + } + + public string Icon + { + get + { + return ".sprUpdate"; + } + } + + public bool ShowInNotifier + { + get + { + return true; + } + } + public bool CanBePermissionAssigned + { + get + { + return true; + } + } + #endregion + } + + /// + /// This action is invoked when a document is being published + /// + public class ActionPublish : IAction + { + //create singleton + private static readonly ActionPublish m_instance = new ActionPublish(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionPublish() { } + + public static ActionPublish Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return 'U'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionPublish()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "publish"; + } + } + + public string Icon + { + get + { + return ".sprPublish"; + } + } + + public bool ShowInNotifier + { + get + { + return true; + } + } + public bool CanBePermissionAssigned + { + get + { + return true; + } + } + #endregion + } + + /// + /// This action is invoked when children to a document is being sent to published (by an editor without publishrights) + /// + public class ActionToPublish : IAction + { + //create singleton + private static readonly ActionToPublish m_instance = new ActionToPublish(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionToPublish() { } + + public static ActionToPublish Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return 'H'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionToPublish()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "sendtopublish"; + } + } + + public string Icon + { + get + { + return ".sprToPublish"; + } + } + + public bool ShowInNotifier + { + get + { + return true; + } + } + public bool CanBePermissionAssigned + { + get + { + //SD: Changed this to true so that any user may be able to perform this action, not just a writer + return true; + } + } + #endregion + } + + /// + /// This action is invoked when a user logs out + /// + public class ActionQuit : IAction + { + //create singleton + private static readonly ActionQuit m_instance = new ActionQuit(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionQuit() { } + + public static ActionQuit Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return 'Q'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionQuit()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "logout"; + } + } + + public string Icon + { + get + { + return ".sprLogout"; + } + } + + public bool ShowInNotifier + { + get + { + return false; + } + } + public bool CanBePermissionAssigned + { + get + { + return false; + } + } + #endregion + } + + /// + /// This action is invoked when all documents are being republished + /// + public class ActionRePublish : IAction + { + //create singleton + private static readonly ActionRePublish m_instance = new ActionRePublish(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionRePublish() { } + + public static ActionRePublish Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return 'B'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionRePublish()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "republish"; + } + } + + public string Icon + { + get + { + return ".sprPublish"; + } + } + + public bool ShowInNotifier + { + get + { + return false; + } + } + public bool CanBePermissionAssigned + { + get + { + return false; + } + } + #endregion + } + + /// + /// This action is invoked when a domain is being assigned to a document + /// + public class ActionAssignDomain : IAction + { + //create singleton + private static readonly ActionAssignDomain m_instance = new ActionAssignDomain(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance) + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionAssignDomain() { } + + public static ActionAssignDomain Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return 'I'; + } + } + + public string JsFunctionName + { + get + { + return string.Format("{0}.actionAssignDomain()", ClientTools.Scripts.GetAppActions); + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "assignDomain"; + } + } + + public string Icon + { + get + { + return ".sprDomain"; + } + } + + public bool ShowInNotifier + { + get + { + return false; + } + } + public bool CanBePermissionAssigned + { + get + { + return true; + } + } + #endregion + } + + + + /// + /// This action is invoked when a document is being unpublished + /// + public class ActionUnPublish : IAction + { + //create singleton + private static readonly ActionUnPublish m_instance = new ActionUnPublish(); + + /// + /// A public constructor exists ONLY for backwards compatibility in regards to 3rd party add-ons. + /// All Umbraco assemblies should use the singleton instantiation (this.Instance). + /// When this applicatio is refactored, this constuctor should be made private. + /// + [Obsolete("Use the singleton instantiation instead of a constructor")] + public ActionUnPublish() { } + + public static ActionUnPublish Instance + { + get { return m_instance; } + } + + #region IAction Members + + public char Letter + { + get + { + return 'Z'; + } + } + + public string JsFunctionName + { + get + { + return ""; + } + } + + public string JsSource + { + get + { + return null; + } + } + + public string Alias + { + get + { + return "unpublish"; + } + } + + public string Icon + { + get + { + return ".sprDelete"; + } + } + + public bool ShowInNotifier + { + get + { + return false; + } + } + public bool CanBePermissionAssigned + { + get + { + return false; + } + } + #endregion + } + +} diff --git a/umbraco/cms/AssemblyInfo.cs b/umbraco/cms/AssemblyInfo.cs new file mode 100644 index 0000000000..177a4f0e70 --- /dev/null +++ b/umbraco/cms/AssemblyInfo.cs @@ -0,0 +1,58 @@ +using System.Reflection; +using System.Runtime.CompilerServices; + +// +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +// +[assembly: AssemblyTitle("")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Revision and Build Numbers +// by using the '*' as shown below: + +[assembly: AssemblyVersion("1.0.*")] + +// +// In order to sign your assembly you must specify a key to use. Refer to the +// Microsoft .NET Framework documentation for more information on assembly signing. +// +// Use the attributes below to control which key is used for signing. +// +// Notes: +// (*) If no key is specified, the assembly is not signed. +// (*) KeyName refers to a key that has been installed in the Crypto Service +// Provider (CSP) on your machine. KeyFile refers to a file which contains +// a key. +// (*) If the KeyFile and the KeyName values are both specified, the +// following processing occurs: +// (1) If the KeyName can be found in the CSP, that key is used. +// (2) If the KeyName does not exist and the KeyFile does exist, the key +// in the KeyFile is installed into the CSP and used. +// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility. +// When specifying the KeyFile, the location of the KeyFile should be +// relative to the project output directory which is +// %Project Directory%\obj\. For example, if your KeyFile is +// located in the project directory, you would specify the AssemblyKeyFile +// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")] +// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework +// documentation for more information on this. +// +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyFile("")] +[assembly: AssemblyKeyName("")] diff --git a/umbraco/cms/ClassDiagram1.cd b/umbraco/cms/ClassDiagram1.cd new file mode 100644 index 0000000000..60abc85680 --- /dev/null +++ b/umbraco/cms/ClassDiagram1.cd @@ -0,0 +1,379 @@ + + + + + + + businesslogic\CMSNode.cs + iAIDQAAAEIwCEBIFAABEYQAARAwAKBgNAAgBGAAAUAI= + + + + + + + + + + + + businesslogic\Content.cs + IAAAABABAAgAZAAAAAAQAYEBBAgAEAgEAAAQAASADAA= + + + + + + + + businesslogic\ContentType.cs + AAAAAAAIAAIAAAAAACAAAQAABhgAAkAIAgAQAAQQCBA= + + + + + + + + + + businesslogic\ContentType.cs + + + + + businesslogic\ContentType.cs + + + + + + + + + businesslogic\datatype\DataType.cs + AAAAAAAAAAICEEAAAAAAAAAAIAAAAAAAAgAAACAAAAA= + + + + + + + + businesslogic\media\Media.cs + AAAAAAAAAAAAEEAAAAAEAQAABAAAAAAAAAQAAAAAAAA= + + + + + + + + businesslogic\media\MediaType.cs + AAAAAAAAAAAAEEAAAAAAAQAAAgAAAAAAAgAAAAAAAAA= + + + + + + + + businesslogic\member\Member.cs + AWgCAFAAQCAAEEEAAIAAQYQgBAAgAQguAgICCAFAAAA= + + + + + + + + businesslogic\member\MemberGroup.cs + AAAAAAAAAAAAEEAAAAAAAAAAAAAAAAAAAgAAAAAAAAg= + + + + + + + + businesslogic\member\MemberType.cs + AAACAAABAAAAEEAAEAAAAQAAAgAAAAAQAiAAAAAAAAA= + + + + + + + + businesslogic\web\Document.cs + AAAEEOAAA8CIEECBOEAECYgABgAAAAgMAAEACiAAQJA= + + + + + + + + businesslogic\web\DocumentType.cs + AABQACAAAAAAEEAAAgECAQAACgAAAAAEAgAAAAAAAAA= + + + + + + + + businesslogic\relation\Relation.cs + AAACAAAUEAAAEIAAAABAYAAAABECAAAAgIABAAAAAAA= + + + + + + + + businesslogic\relation\RelationType.cs + EAICYAAAAAIAAAAAAABAAAwAAgAAAAAAAAAAAAAQAAA= + + + + + + + + Actions\defaultActions.cs + AAAAAAAAAIIAAAIAAAAAAAQAQAAAAAAAgAAAAAEAAAA= + + + + + + + Actions\defaultActions.cs + AAAAAAAAAIIAAAIAAAAAAAQAQAAAAAAAgAAAAAEAAAA= + + + + + + + Actions\defaultActions.cs + AAAAAAAAAIIAAAIAAAAAAAQAQAAAAAAAgAAAAAEAAAA= + + + + + + + Actions\defaultActions.cs + AAAAAAAAAIIAAAIAAAAAAAQAQAAAAAAAgAAAAAEAAAA= + + + + + + + Actions\defaultActions.cs + AAAAAAAAAIIAAAIAAAAAAAQAQAAAAAAAgAAAAAEAAAA= + + + + + + + Actions\defaultActions.cs + AAAAAAAAAIIAAAIAAAAAAAQAQAAAAAAAgAAAAAEAAAA= + + + + + + + Actions\defaultActions.cs + AAAAAAAAAIIAAAIAAAAAAAQAQAAAAAAAgAAAAAEAAAA= + + + + + + + Actions\defaultActions.cs + AAAAAAAAAIIAAAIAAAAAAAQAQAAAAAAAgAAAAAEAAAA= + + + + + + + Actions\defaultActions.cs + AAAAAAAAAIIAAAIAAAAAAAQAQAAAAAAAgAAAAAEAAAA= + + + + + + + Actions\defaultActions.cs + AAAAAAAAAIIAAAIAAAAAAAQAQAAAAAAAgAAAAAEAAAA= + + + + + + + Actions\defaultActions.cs + AAAAAAAAAIIAAAIAAAAAAAQAQAAAAAAAgAAAAAEAAAA= + + + + + + + Actions\defaultActions.cs + AAAAAAAAAIIAAAIAAAAAAAQAQAAAAAAAgAAAAAEAAAA= + + + + + + + businesslogic\Property\Property.cs + CAACAAAABAAAEACAAABAAQAAAAAAAAAEAEAiAAAAAAA= + + + + + + + + businesslogic\propertytype\propertytype.cs + AAEDNAAAAAIgEQCEACRACQQAAAAAAAAAAgAAAAQQAAE= + + + + + + + + + + + + + + + + + + + + Actions\Action.cs + AAAAAAAAAAAAAAQAAAAAAAAAAgAAAAAAAAAACAAAAAA= + + + + + + + + + + + \ No newline at end of file diff --git a/umbraco/cms/businesslogic/CMSModuleI.cs b/umbraco/cms/businesslogic/CMSModuleI.cs new file mode 100644 index 0000000000..f0300becb1 --- /dev/null +++ b/umbraco/cms/businesslogic/CMSModuleI.cs @@ -0,0 +1,15 @@ +using System; + +namespace umbraco.cms.businesslogic +{ + /// + /// Not implemented yet + /// + public interface CMSModuleI + { + /// + /// Not implemented yet + /// + Guid UniqueId {get;} + } +} \ No newline at end of file diff --git a/umbraco/cms/businesslogic/CMSNode.cs b/umbraco/cms/businesslogic/CMSNode.cs new file mode 100644 index 0000000000..8c80a3df59 --- /dev/null +++ b/umbraco/cms/businesslogic/CMSNode.cs @@ -0,0 +1,807 @@ +using System; +using System.Collections.Generic; +using System.Data; + +using System.Xml; +using umbraco.cms.businesslogic.index; +using umbraco.cms.businesslogic.web; +using umbraco.DataLayer; +using umbraco.BusinessLogic; +using System.IO; +using System.Text.RegularExpressions; +using System.ComponentModel; + +namespace umbraco.cms.businesslogic { + /// + /// CMSNode class serves as the base class for many of the other components in the cms.businesslogic.xx namespaces. + /// Providing the basic hierarchical data structure and properties Text (name), Creator, Createdate, updatedate etc. + /// which are shared by most umbraco objects. + /// + /// The child classes are required to implement an identifier (Guid) which is used as the objecttype identifier, for + /// distinguishing the different types of CMSNodes (ex. Documents/Medias/Stylesheets/documenttypes and so forth). + /// + public class CMSNode : BusinessLogic.console.IconI { + private string _text; + private int _id = 0; + private Guid _uniqueID; + /// + /// Private connectionstring + /// + protected static readonly string _ConnString = GlobalSettings.DbDSN; + private int _parentid; + private Guid _nodeObjectType; + private int _level; + private string _path; + private bool _hasChildren; + private int _sortOrder; + private int _userId; + private DateTime _createDate; + private bool _hasChildrenInitialized; + private string m_image = "default.png"; + private static readonly string m_DefaultIconCssFile = GlobalSettings.FullpathToRoot + GlobalSettings.Path + System.IO.Path.DirectorySeparatorChar + "css" + System.IO.Path.DirectorySeparatorChar + "treeIcons.css"; + private static List m_DefaultIconClasses = new List(); + + /// + /// Gets the default icon classes. + /// + /// The default icon classes. + public static List DefaultIconClasses { + get { + if (m_DefaultIconClasses.Count == 0) + initializeIconClasses(); + + return m_DefaultIconClasses; + } + } + + private static void initializeIconClasses() { + StreamReader re = File.OpenText(m_DefaultIconCssFile); + string content = string.Empty; + string input = null; + while ((input = re.ReadLine()) != null) { + content += input.Replace("\n", "") + "\n"; + } + re.Close(); + + // parse the classes + MatchCollection m = Regex.Matches(content, "([^{]*){([^}]*)}", RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + + foreach (Match match in m) { + GroupCollection groups = match.Groups; + string cssClass = groups[1].Value.Replace("\n", "").Replace("\r", "").Trim().Trim(Environment.NewLine.ToCharArray()); + m_DefaultIconClasses.Add(cssClass); + } + } + + /// + /// Gets the SQL helper. + /// + /// The SQL helper. + protected static ISqlHelper SqlHelper { + get { return Application.SqlHelper; } + } + + + /// + /// Initializes a new instance of the class. + /// + /// The id. + public CMSNode(int Id) { + _id = Id; + setupNode(); + } + + + /// + /// Initializes a new instance of the class. + /// + /// The id. + /// if set to true [no setup]. + public CMSNode(int id, bool noSetup) { + _id = id; + + //TODO: add the following as noSetup currenlty doesn't actuall do anything!?? This can't happen until + //inheriting classes can override setupNode instead of using their own implementation (i.e. Document: setupDocument) + //if (!noSetup) + //setupNode(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The unique ID. + public CMSNode(Guid uniqueID) { + _id = SqlHelper.ExecuteScalar("SELECT id FROM umbracoNode WHERE uniqueID = @uniqueId", SqlHelper.CreateParameter("@uniqueId", uniqueID)); + setupNode(); + } + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public virtual void Save() { + SaveEventArgs e = new SaveEventArgs(); + this.FireBeforeSave(e); + if (!e.Cancel) { + //In the future there will be SQL stuff happening here... + this.FireAfterSave(e); + } + } + + + /// + /// Sets up the internal data of the CMSNode, used by the various constructors + /// + protected void setupNode() { + IRecordsReader dr = SqlHelper.ExecuteReader( + "SELECT createDate, trashed, parentId, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text FROM umbracoNode WHERE id = " + this.Id + ); + + bool noRecord = false; + + if (dr.Read()) + { + // testing purposes only > original umbraco data hasn't any unique values ;) + // And we need to have a parent in order to create a new node .. + // Should automatically add an unique value if no exists (or throw a decent exception) + if (dr.IsNull("uniqueID")) _uniqueID = Guid.NewGuid(); + else _uniqueID = dr.GetGuid("uniqueID"); + + _nodeObjectType = dr.GetGuid("nodeObjectType"); + _level = dr.GetShort("level"); + _path = dr.GetString("path"); + _parentid = dr.GetInt("parentId"); + _text = dr.GetString("text"); + _sortOrder = dr.GetInt("sortOrder"); + _userId = dr.GetInt("nodeUser"); + _createDate = dr.GetDateTime("createDate"); + } + else + noRecord = true; + + dr.Close(); + + if (noRecord) { + throw new ArgumentException(string.Format("No node exists with id '{0}'", Id)); + } + } + + /// + /// Sets up the node for the content tree. + /// + /// The unique ID. + /// Type of the node object. + /// The level. + /// The parent id. + /// The user id. + /// The path. + /// The text. + /// The create date. + /// if set to true [has children]. + protected void SetupNodeForTree(Guid uniqueID, Guid nodeObjectType, int Level, int ParentId, int UserId, string Path, string Text, + DateTime CreateDate, bool hasChildren) { + _uniqueID = uniqueID; + _nodeObjectType = nodeObjectType; + _level = Level; + _parentid = ParentId; + _userId = UserId; + _path = Path; + _text = Text; + _createDate = CreateDate; + HasChildren = hasChildren; + } + + + /// + /// Gets or sets the sort order. + /// + /// The sort order. + public int sortOrder { + get { return _sortOrder; } + set { + _sortOrder = value; + SqlHelper.ExecuteNonQuery("update umbracoNode set sortOrder = '" + value + "' where id = " + this.Id.ToString()); + } + } + + + /// + /// Gets or sets the create date time. + /// + /// The create date time. + public DateTime CreateDateTime { + get { return _createDate; } + set { + _createDate = value; + SqlHelper.ExecuteNonQuery("update umbracoNode set createDate = @createDate where id = " + this.Id.ToString(), SqlHelper.CreateParameter("@createDate", _createDate)); + } + } + + + /// + /// Gets the creator + /// + /// The user. + public BusinessLogic.User User { + get { + return BusinessLogic.User.GetUser(_userId); + } + } + + /// + /// Method for checking if a CMSNode exits with the given Guid + /// + /// Identifier + /// True if there is a CMSNode with the given Guid + static public bool IsNode(Guid uniqueID) { + return (SqlHelper.ExecuteScalar("select count(id) from umbracoNode where uniqueID = @uniqueID", SqlHelper.CreateParameter("@uniqueId", uniqueID)) > 0); + } + + /// + /// Method for checking if a CMSNode exits with the given id + /// + /// Identifier + /// True if there is a CMSNode with the given id + static public bool IsNode(int Id) { + return (SqlHelper.ExecuteScalar("select count(id) from umbracoNode where id = '" + Id + "'") > 0); + } + + + + /// + /// Gets the id. + /// + /// The id. + public int Id { + get { return _id; } + } + + + /// + /// Given the hierarchical tree structure a CMSNode has only one parent but can have many children + /// + /// The parent. + public CMSNode Parent { + get { + if (Level == 1) throw new ArgumentException("No parent node"); + return new CMSNode(_parentid); + } + set { + _parentid = value.Id; + SqlHelper.ExecuteNonQuery("update umbracoNode set parentId = " + value.Id.ToString() + " where id = " + this.Id.ToString()); + } + } + + #region IconI members + + // Unique identifier of the given node + /// + /// Unique identifier of the CMSNode, used when locating data. + /// + public Guid UniqueId { + get { return _uniqueID; } + } + + /// + /// Human readable name/label + /// + public virtual string Text { + get { return _text; } + set { + _text = value; + SqlHelper.ExecuteNonQuery("UPDATE umbracoNode SET text = @text WHERE id = @id", + SqlHelper.CreateParameter("@text", value), + SqlHelper.CreateParameter("@id", this.Id)); + + } + } + + /// + /// The menu items used in the tree view + /// + public virtual BusinessLogic.console.MenuItemI[] MenuItems { + get { return new BusinessLogic.console.MenuItemI[0]; } + } + + /// + /// Not implemented, always returns "about:blank" + /// + public virtual string DefaultEditorURL { + get { return "about:blank"; } + } + + /// + /// The icon in the tree + /// + public virtual string Image { + get { return m_image; } + set { m_image = value; } + + } + + /// + /// The "open/active" icon in the tree + /// + public virtual string OpenImage { + get { return ""; } + } + + #endregion + + + /// + /// An comma separated string consisting of integer node id's + /// that indicates the path from the topmost node to the given node + /// + /// The path. + public string Path { + get { return _path; } + set { + _path = value; + SqlHelper.ExecuteNonQuery("update umbracoNode set path = '" + _path + "' where id = " + this.Id.ToString()); + } + } + + + /// + /// Updates the temp path for the content tree. + /// + /// The path. + protected void UpdateTempPathForTree(string Path) { + this._path = Path; + } + + + + /// + /// Moves the CMSNode from the current position in the hierarchy to the target + /// + /// Target CMSNode id + public void Move(int NewParentId) { + MoveEventArgs e = new MoveEventArgs(); + FireBeforeMove(e); + + if (!e.Cancel) { + int maxSortOrder = SqlHelper.ExecuteScalar( + "select coalesce(max(sortOrder),0) from umbracoNode where parentid = @parentId", + SqlHelper.CreateParameter("@parentId", NewParentId)); + + + CMSNode n = new CMSNode(NewParentId); + this.Parent = n; + this.Level = n.Level + 1; + this.Path = n.Path + "," + this.Id.ToString(); + + this.sortOrder = maxSortOrder + 1; + + + if (n.nodeObjectType == web.Document._objectType) { + Document d = + new umbraco.cms.businesslogic.web.Document(n.Id); + d.XmlGenerate(new XmlDocument()); + d.Index(true); + } else if (n.nodeObjectType == media.Media._objectType) + new umbraco.cms.businesslogic.media.Media(n.Id).XmlGenerate(new XmlDocument()); + + foreach (CMSNode c in this.Children) + c.Move(this.Id); + + FireAfterMove(e); + } + } + + + + /// + /// Returns an integer value that indicates in which level of the + /// tree structure the given node is + /// + /// The level. + public int Level { + get { return _level; } + set { + _level = value; + SqlHelper.ExecuteNonQuery("update umbracoNode set level = " + _level.ToString() + " where id = " + this.Id.ToString()); + } + } + + /// + /// All CMSNodes has an objecttype ie. Webpage, StyleSheet etc., used to distinguish between the different + /// object types for for fast loading children to the tree. + /// + /// The type of the node object. + public Guid nodeObjectType { + get { return _nodeObjectType; } + } + + /// + /// Besides the hierarchy it's possible to relate one CMSNode to another, use this for alternative + /// non-strict hierarchy + /// + /// The relations. + public relation.Relation[] Relations { + get { return relation.Relation.GetRelations(this.Id); } + } + + /// + /// Does the current CMSNode have any child nodes. + /// + /// + /// true if this instance has children; otherwise, false. + /// + public virtual bool HasChildren { + get { + if (!_hasChildrenInitialized) { + int tmpChildrenCount = SqlHelper.ExecuteScalar("select count(id) from umbracoNode where ParentId = " + _id); + HasChildren = (tmpChildrenCount > 0); + } + return _hasChildren; + } + set { + _hasChildrenInitialized = true; + _hasChildren = value; + } + } + + /// + /// The basic recursive tree pattern + /// + /// The children. + public virtual BusinessLogic.console.IconI[] Children { + get { + System.Collections.ArrayList tmp = new System.Collections.ArrayList(); + IRecordsReader dr = SqlHelper.ExecuteReader("select id from umbracoNode where ParentID = " + this.Id + " And nodeObjectType = @type order by sortOrder", + SqlHelper.CreateParameter("@type", this.nodeObjectType)); + + while (dr.Read()) + tmp.Add(dr.GetInt("Id")); + + dr.Close(); + + CMSNode[] retval = new CMSNode[tmp.Count]; + + for (int i = 0; i < tmp.Count; i++) + retval[i] = new CMSNode((int)tmp[i]); + + return retval; + } + } + + /// + /// Retrieve all CMSNodes in the umbraco installation + /// Use with care. + /// + /// The children of all object types. + public BusinessLogic.console.IconI[] ChildrenOfAllObjectTypes { + get { + System.Collections.ArrayList tmp = new System.Collections.ArrayList(); + IRecordsReader dr = SqlHelper.ExecuteReader("select id from umbracoNode where ParentID = " + this.Id + " order by sortOrder"); + + while (dr.Read()) + tmp.Add(dr.GetInt("Id")); + + dr.Close(); + + CMSNode[] retval = new CMSNode[tmp.Count]; + + for (int i = 0; i < tmp.Count; i++) + retval[i] = new CMSNode((int)tmp[i]); + + return retval; + } + } + + /// + /// Retrieves the top level nodes in the hierarchy + /// + /// The Guid identifier of the type of objects + /// + /// A list of all top level nodes given the objecttype + /// + protected static Guid[] TopMostNodeIds(Guid ObjectType) { + IRecordsReader dr = SqlHelper.ExecuteReader("Select uniqueID from umbracoNode where nodeObjectType = @type And parentId = -1 order by sortOrder", + SqlHelper.CreateParameter("@type", ObjectType)); + System.Collections.ArrayList tmp = new System.Collections.ArrayList(); + + while (dr.Read()) tmp.Add(dr.GetGuid("uniqueID")); + dr.Close(); + + Guid[] retval = new Guid[tmp.Count]; + for (int i = 0; i < tmp.Count; i++) retval[i] = (Guid)tmp[i]; + return retval; + } + + /// + /// Given the protected modifier the CMSNode.MakeNew method can only be accessed by + /// derived classes > who by definition knows of its own objectType. + /// + /// The parent CMSNode id + /// The objecttype identifier + /// Creator + /// The level in the tree hieararchy + /// The name of the CMSNode + /// The unique identifier + /// + protected static CMSNode MakeNew(int parentId, Guid objectType, int userId, int level, string text, Guid uniqueID) { + CMSNode parent; + string path = ""; + int sortOrder = 0; + + if (level > 0) { + parent = new CMSNode(parentId); + sortOrder = parent.Children.Length + 1; + path = parent.Path; + } else + path = "-1"; + + // Ruben 8/1/2007: I replace this with a parameterized version. + // But does anyone know what the 'level++' is supposed to be doing there? + // Nothing obviously, since it's a postfix. + + SqlHelper.ExecuteNonQuery("INSERT INTO umbracoNode(trashed, parentID, nodeObjectType, nodeUser, level, path, sortOrder, uniqueID, text) VALUES(@trashed, @parentID, @nodeObjectType, @nodeUser, @level, @path, @sortOrder, @uniqueID, @text)", + SqlHelper.CreateParameter("@trashed", 0), + SqlHelper.CreateParameter("@parentID", parentId), + SqlHelper.CreateParameter("@nodeObjectType", objectType), + SqlHelper.CreateParameter("@nodeUser", userId), + SqlHelper.CreateParameter("@level", level++), + SqlHelper.CreateParameter("@path", path), + SqlHelper.CreateParameter("@sortOrder", sortOrder), + SqlHelper.CreateParameter("@uniqueID", uniqueID), + SqlHelper.CreateParameter("@text", text)); + + CMSNode retVal = new CMSNode(uniqueID); + retVal.Path = path + "," + retVal.Id.ToString(); + + //event + NewEventArgs e = new NewEventArgs(); + retVal.FireAfterNew(e); + + return retVal; + } + + /// + /// Retrieve a list of the unique id's of all CMSNodes given the objecttype + /// + /// The objecttype identifier + /// + /// A list of all unique identifiers which each are associated to a CMSNode + /// + public static Guid[] getAllUniquesFromObjectType(Guid objectType) { + IRecordsReader dr = SqlHelper.ExecuteReader("Select uniqueID from umbracoNode where nodeObjectType = @type", + SqlHelper.CreateParameter("@type", objectType)); + System.Collections.ArrayList tmp = new System.Collections.ArrayList(); + + while (dr.Read()) tmp.Add(dr.GetGuid("uniqueID")); + dr.Close(); + + Guid[] retval = new Guid[tmp.Count]; + for (int i = 0; i < tmp.Count; i++) retval[i] = (Guid)tmp[i]; + return retval; + } + + /// + /// Retrieve a list of the node id's of all CMSNodes given the objecttype + /// + /// The objecttype identifier + /// + /// A list of all node ids which each are associated to a CMSNode + /// + public static int[] getAllUniqueNodeIdsFromObjectType(Guid objectType) { + IRecordsReader dr = SqlHelper.ExecuteReader("Select id from umbracoNode where nodeObjectType = @type", + SqlHelper.CreateParameter("@type", objectType)); + System.Collections.ArrayList tmp = new System.Collections.ArrayList(); + + while (dr.Read()) tmp.Add(dr.GetInt("id")); + dr.Close(); + + return (int[])tmp.ToArray(typeof(int)); + } + + + /// + /// Retrieve a list of the id's of all CMSNodes given the objecttype and the first letter of the name. + /// + /// The objecttype identifier + /// Firstletter + /// + /// A list of all CMSNodes which has the objecttype and a name that starts with the given letter + /// + protected static int[] getUniquesFromObjectTypeAndFirstLetter(Guid objectType, char letter) { + using (IRecordsReader dr = SqlHelper.ExecuteReader("Select id from umbracoNode where nodeObjectType = @objectType AND text like @letter", SqlHelper.CreateParameter("@objectType", objectType), SqlHelper.CreateParameter("@letter", letter.ToString() + "%"))) { + List tmp = new List(); + while (dr.Read()) tmp.Add(dr.GetInt("id")); + return tmp.ToArray(); + } + } + + + /// + /// Deletes this instance. + /// + public void delete() { + DeleteEventArgs e = new DeleteEventArgs(); + FireBeforeDelete(e); + if (!e.Cancel) { + index.Indexer.RemoveNode(this.Id); + + // remove relations + foreach (relation.Relation rel in Relations) + { + rel.Delete(); + } + + SqlHelper.ExecuteNonQuery("DELETE FROM umbracoNode WHERE uniqueID= @uniqueId", SqlHelper.CreateParameter("@uniqueId", _uniqueID)); + FireAfterDelete(e); + } + } + + /// + /// Get a count on all CMSNodes given the objecttype + /// + /// The objecttype identifier + /// + /// The number of CMSNodes of the given objecttype + /// + public static int CountByObjectType(Guid objectType) { + return SqlHelper.ExecuteScalar("SELECT COUNT(*) from umbracoNode WHERE nodeObjectType = @type", SqlHelper.CreateParameter("@type", objectType)); + } + + /// + /// Number of children of the current CMSNode + /// + /// The CMSNode Id + /// + /// The number of children from the given CMSNode + /// + public static int CountSubs(int Id) { + return SqlHelper.ExecuteScalar("SELECT COUNT(*) FROM umbracoNode WHERE ','+path+',' LIKE '%," + Id.ToString() + ",%'"); + } + + /// + /// An xml representation of the CMSNOde + /// + /// Xmldocument context + /// If true the xml will append the CMSNodes child xml + /// The CMSNode Xmlrepresentation + public virtual XmlNode ToXml(XmlDocument xd, bool Deep) { + XmlNode x = xd.CreateNode(XmlNodeType.Element, "node", ""); + XmlPopulate(xd, x, Deep); + return x; + } + + private void XmlPopulate(XmlDocument xd, XmlNode x, bool Deep) { + // attributes + x.Attributes.Append(xmlHelper.addAttribute(xd, "id", this.Id.ToString())); + if (this.Level > 1) + x.Attributes.Append(xmlHelper.addAttribute(xd, "parentID", this.Parent.Id.ToString())); + else + x.Attributes.Append(xmlHelper.addAttribute(xd, "parentID", "-1")); + x.Attributes.Append(xmlHelper.addAttribute(xd, "level", this.Level.ToString())); + x.Attributes.Append(xmlHelper.addAttribute(xd, "writerID", this.User.Id.ToString())); + x.Attributes.Append(xmlHelper.addAttribute(xd, "sortOrder", this.sortOrder.ToString())); + x.Attributes.Append(xmlHelper.addAttribute(xd, "createDate", this.CreateDateTime.ToString("s"))); + x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeName", this.Text)); + x.Attributes.Append(xmlHelper.addAttribute(xd, "path", this.Path)); + + if (Deep) { + foreach (Content c in this.Children) + x.AppendChild(c.ToXml(xd, true)); + } + } + + /// + /// Calls the subscribers of a cancelable event handler, + /// stopping at the event handler which cancels the event (if any). + /// + /// Type of the event arguments. + /// The event to fire. + /// Sender of the event. + /// Event arguments. + protected virtual void FireCancelableEvent(EventHandler cancelableEvent, object sender, T eventArgs) where T : CancelEventArgs + { + if (cancelableEvent != null) + { + foreach (Delegate invocation in cancelableEvent.GetInvocationList()) + { + invocation.DynamicInvoke(sender, eventArgs); + if (eventArgs.Cancel) + break; + } + } + } + + /// + /// Occurs before a node is saved. + /// + public static event EventHandler BeforeSave; + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void FireBeforeSave(SaveEventArgs e) { + FireCancelableEvent(BeforeSave, this, e); + } + + /// + /// Occurs after a node is saved. + /// + public static event EventHandler AfterSave; + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void FireAfterSave(SaveEventArgs e) { + if (AfterSave!=null) + AfterSave(this, e); + } + + /// + /// Occurs after a new node is created. + /// + public static event EventHandler AfterNew; + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void FireAfterNew(NewEventArgs e) { + if (AfterNew != null) + AfterNew(this, e); + } + + /// + /// Occurs before a node is deleted. + /// + public static event EventHandler BeforeDelete; + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void FireBeforeDelete(DeleteEventArgs e) { + FireCancelableEvent(BeforeDelete, this, e); + } + + /// + /// Occurs after a node is deleted. + /// + public static event EventHandler AfterDelete; + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void FireAfterDelete(DeleteEventArgs e) { + if (AfterDelete != null) + AfterDelete(this, e); + } + + /// + /// Occurs before a node is moved. + /// + public static event EventHandler BeforeMove; + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void FireBeforeMove(MoveEventArgs e) { + FireCancelableEvent(BeforeMove, this, e); + } + + /// + /// Occurs after a node is moved. + /// + public static event EventHandler AfterMove; + + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void FireAfterMove(MoveEventArgs e) { + if (AfterMove != null) + AfterMove(this, e); + } + } +} diff --git a/umbraco/cms/businesslogic/Content.cs b/umbraco/cms/businesslogic/Content.cs new file mode 100644 index 0000000000..0a9dc60df1 --- /dev/null +++ b/umbraco/cms/businesslogic/Content.cs @@ -0,0 +1,530 @@ +using System; +using System.Collections.Generic; + + +using System.Data; +using System.Xml; +using umbraco.cms.businesslogic.property; +using umbraco.cms.businesslogic.propertytype; +using umbraco.DataLayer; +using System.Runtime.CompilerServices; + +namespace umbraco.cms.businesslogic +{ + /// + /// Content is an intermediate layer between CMSNode and class'es which will use generic data. + /// + /// Content is a datastructure that holds generic data defined in its corresponding ContentType. Content can in some + /// sence be compared to a row in a database table, it's contenttype hold a definition of the columns and the Content + /// contains the data + /// + /// Note that Content data in umbraco is *not* tablular but in a treestructure. + /// + /// + public class Content : CMSNode + { + private Guid _version; + private DateTime _versionDate; + private XmlNode _xml; + private bool _versionDateInitialized; + private string _contentTypeIcon; + private ContentType _contentType; + private bool _propertiesInitialized = false; + private Properties _properties = new Properties(); + + /// + /// + /// + /// + public Content(int id) : base(id) { } + + /// + /// + /// + /// + /// + protected Content(int id, bool noSetup) : base(id, noSetup) { } + + /// + /// + /// + /// + protected Content(Guid id) : base(id) { } + + protected void InitializeContent(int InitContentType, Guid InitVersion, DateTime InitVersionDate, string InitContentTypeIcon) + { + _contentType = ContentType.GetContentType(InitContentType); + _version = InitVersion; + _versionDate = InitVersionDate; + _contentTypeIcon = InitContentTypeIcon; + } + + /// + /// The current Content objects ContentType, which defines the Properties of the Content (data) + /// + public ContentType ContentType + { + get + { + if (_contentType == null) + { + object o = SqlHelper.ExecuteScalar( + "Select ContentType from cmsContent where nodeId=@nodeid", + SqlHelper.CreateParameter("@nodeid", this.Id)); + if (o == null) + return null; + int contentTypeId; + if(!int.TryParse(o.ToString(), out contentTypeId)) + return null; + try + { + _contentType = new ContentType(contentTypeId); + } + catch + { + return null; + } + } + return _contentType; + } + set + { + _contentType = value; + } + } + + public Properties GenericProperties + { + get + { + if (!_propertiesInitialized) + InitializeProperties(); + + return _properties; + } + } + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public override void Save() + { + base.Save(); + } + + + // This is for performance only (used in tree) + /// + /// The icon used in the tree - placed in this layer for performance reasons. + /// + public string ContentTypeIcon + { + get + { + if (_contentTypeIcon == null && this.ContentType != null) + _contentTypeIcon = this.ContentType.IconUrl; + return _contentTypeIcon; + } + set + { + _contentTypeIcon = value; + } + } + + /// + /// Retrieve a Property given the alias + /// + /// Propertyalias (defined in the documenttype) + /// The property with the given alias + public Property getProperty(string alias) + { + ContentType ct = this.ContentType; + if(ct == null) + return null; + propertytype.PropertyType pt = ct.getPropertyType(alias); + if(pt == null) + return null; + return getProperty(pt); + } + + /// + /// Retrieve a property given the propertytype + /// + /// PropertyType + /// The property with the given propertytype + public Property getProperty(propertytype.PropertyType pt) + { + object o = SqlHelper.ExecuteScalar( + "select id from cmsPropertyData where versionId=@version and propertyTypeId=@propertyTypeId", + SqlHelper.CreateParameter("@version", this.Version), + SqlHelper.CreateParameter("@propertyTypeId", pt.Id)); + if(o == null) + return null; + int propertyId; + if(!int.TryParse(o.ToString(), out propertyId)) + return null; + try + { + return new Property(propertyId, pt); + } + catch + { + return null; + } + } + + /// + /// The createtimestamp on this version + /// + public DateTime VersionDate + { + get + { + if(!_versionDateInitialized) + { + object o = SqlHelper.ExecuteScalar( + "select VersionDate from cmsContentVersion where versionId = '" + this.Version.ToString() + "'"); + if(o == null) + { + _versionDate = DateTime.Now; + } + else + { + _versionDateInitialized = DateTime.TryParse(o.ToString(), out _versionDate); + } + } + return _versionDate; + } + set + { + _versionDate = value; + _versionDateInitialized = true; + } + } + + + /// + /// Optimized method for bulk deletion of propertieson a Content object. + /// + private void deleteAllProperties() + { + SqlHelper.ExecuteNonQuery("Delete from cmsPropertyData where contentNodeId = @nodeId", SqlHelper.CreateParameter("@nodeId", this.Id)); + } + + /// + /// Retrieve a list of generic properties of the content + /// + public Property[] getProperties + { + get + { + if (this.ContentType == null) + return new Property[0]; + + List result = new List(); + foreach(PropertyType prop in this.ContentType.PropertyTypes) + { + if (prop == null) + continue; + Property p = getProperty(prop); + if(p == null) + continue; + result.Add(p); + } + + return result.ToArray(); + } + } + + + private void InitializeProperties() + { + using(IRecordsReader dr = SqlHelper.ExecuteReader("select id from cmsPropertyData where versionId = @versionId", + SqlHelper.CreateParameter("@versionId", Version))) + { + while(dr.Read()) + _properties.Add(new Property(dr.GetInt("id"))); + } + } + + + /// + /// Retrive a list of Content sharing the ContentType + /// + /// The ContentType + /// A list of Content objects sharing the ContentType defined. + public static Content[] getContentOfContentType(ContentType ct) { + IRecordsReader dr = SqlHelper.ExecuteReader("Select nodeId from cmsContent INNER JOIN umbracoNode ON cmsContent.nodeId = umbracoNode.id where ContentType = " + ct.Id + " ORDER BY umbracoNode.text "); + System.Collections.ArrayList tmp = new System.Collections.ArrayList(); + + while (dr.Read()) tmp.Add(dr.GetInt("nodeId")); + dr.Close(); + + Content[] retval = new Content[tmp.Count]; + for (int i = 0;i < tmp.Count; i++) retval[i] = new Content((int) tmp[i]); + + return retval; + } + + /// + /// Add a property to the Content + /// + /// The PropertyType of the Property + /// The version of the document on which the property should be add'ed + /// The new Property + public property.Property addProperty(propertytype.PropertyType pt, Guid versionId) { + return property.Property.MakeNew(pt, this, versionId); + } + + /// + /// Content is under version control, you are able to programatically create new versions + /// + public Guid Version { + get{ + if (_version == Guid.Empty) + { + string sql = "Select versionId from cmsContentVersion where contentID = " + this.Id + + " order by id desc "; + + using (IRecordsReader dr = SqlHelper.ExecuteReader(sql)) + { + if (!dr.Read()) + _version = Guid.Empty; + else + _version = dr.GetGuid("versionId"); + } + } + return _version; + } + set{_version = value;} + } + + /// + /// Creates a new Content object from the ContentType. + /// + /// + protected void CreateContent(ContentType ct) { + SqlHelper.ExecuteNonQuery("insert into cmsContent (nodeId,ContentType) values ("+this.Id+","+ct.Id+")"); + createNewVersion(); + } + + /// + /// Indication if the Content exists in at least one version. + /// + /// Returns true if the Content has a version + private bool hasVersion() + { + int versionCount = SqlHelper.ExecuteScalar("select Count(Id) as tmp from cmsContentVersion where contentId = " + this.Id.ToString()); + return (versionCount > 0); + } + + /// + /// Method for creating a new version of the data associated to the Content. + /// + /// + /// The new version Id + protected Guid createNewVersion() { + Guid newVersion = Guid.NewGuid(); + bool tempHasVersion = hasVersion(); + foreach (propertytype.PropertyType pt in this.ContentType.PropertyTypes) + { + object oldValue = ""; + if (tempHasVersion) + { + try + { + oldValue = this.getProperty(pt.Alias).Value; + } + catch {} + } + property.Property p = this.addProperty(pt, newVersion); + if (oldValue != null && oldValue.ToString() != "") p.Value = oldValue; + } + SqlHelper.ExecuteNonQuery("Insert into cmsContentVersion (ContentId,versionId) values ("+ this.Id +",'"+newVersion+"')"); + this.Version = newVersion; + return newVersion; + } + + /// + /// Deletes the current Content object, must be overridden in the child class. + /// + protected new void delete() { + + // Delete all data associated with this content + this.deleteAllProperties(); + + // Delete version history + SqlHelper.ExecuteNonQuery("Delete from cmsContentVersion where ContentId = " + this.Id); + + // Delete Contentspecific data () + SqlHelper.ExecuteNonQuery("Delete from cmsContent where NodeId = " + this.Id); + + // Delete xml + SqlHelper.ExecuteNonQuery("delete from cmsContentXml where nodeID = @nodeId", SqlHelper.CreateParameter("@nodeId", this.Id)); + + // Delete Nodeinformation!! + base.delete(); + } + + /// + /// Initialize a contentobject given a version. + /// + /// The version identifier + /// The Content object from the given version + public static Content GetContentFromVersion(Guid version) { + int tmpContentId = SqlHelper.ExecuteScalar("Select ContentId from cmsContentVersion where versionId = '" + version.ToString() + "'"); + return new Content(tmpContentId); + } + + + private XmlNode importXml() + { + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.Load(SqlHelper.ExecuteXmlReader("select xml from cmsContentXml where nodeID = " + this.Id.ToString())); + + return xmlDoc.FirstChild; + } + + /// + /// An Xmlrepresentation of a Content object. + /// + /// Xmldocument context + /// If true, the Contents children are appended to the Xmlnode recursive + /// The Xmlrepresentation of the data on the Content object + public new virtual XmlNode ToXml(XmlDocument xd, bool Deep) + { + if (_xml == null) + { + XmlDocument xmlDoc = new XmlDocument(); + // we add a try/catch clause here, as the xmlreader will throw an exception if there's no xml in the table + // after the empty catch we'll generate the xml which is why we don't do anything in the catch part + try + { + XmlReader xr = SqlHelper.ExecuteXmlReader("select xml from cmsContentXml where nodeID = " + this.Id.ToString()); + if (xr.MoveToContent() != System.Xml.XmlNodeType.None) + { + xmlDoc.Load(xr); + _xml = xmlDoc.FirstChild; + } + xr.Close(); + } + catch + { + } + + + // Generate xml if xml still null (then it hasn't been initialized before) + if (_xml == null) + { + this.XmlGenerate(new XmlDocument()); + _xml = importXml(); + } + + } + + XmlNode x = xd.ImportNode(_xml, true); + + if (Deep) + { + foreach(BusinessLogic.console.IconI c in this.Children) + try + { + x.AppendChild(new Content(c.Id).ToXml(xd, true)); + } + catch (Exception mExp) + { + System.Web.HttpContext.Current.Trace.Warn("Content", "Error adding node to xml: " + mExp.ToString()); + } + } + + return x; + + } + + /// + /// Removes the Xml cached in the database - unpublish and cleaning + /// + public virtual void XmlRemoveFromDB() + { + SqlHelper.ExecuteNonQuery("delete from cmsContentXml where nodeId = @nodeId", SqlHelper.CreateParameter("@nodeId", this.Id)); + } + + /// + /// Generates the Content XmlNode + /// + /// + public virtual void XmlGenerate(XmlDocument xd) + { + XmlNode node = xd.CreateNode(XmlNodeType.Element, "node", String.Empty); + XmlPopulate(xd, ref node, false); + SaveXmlDocument(node); + } + + public virtual void XmlPopulate(XmlDocument xd, ref XmlNode x, bool Deep) + { + foreach (property.Property p in this.getProperties) + if (p != null) + x.AppendChild(p.ToXml(xd)); + + // attributes + x.Attributes.Append(xmlHelper.addAttribute(xd, "id", this.Id.ToString())); + x.Attributes.Append(xmlHelper.addAttribute(xd, "version", this.Version.ToString())); + if (this.Level > 1) + x.Attributes.Append(xmlHelper.addAttribute(xd, "parentID", this.Parent.Id.ToString())); + else + x.Attributes.Append(xmlHelper.addAttribute(xd, "parentID", "-1")); + x.Attributes.Append(xmlHelper.addAttribute(xd, "level", this.Level.ToString())); + x.Attributes.Append(xmlHelper.addAttribute(xd, "writerID", this.User.Id.ToString())); + if (this.ContentType != null) + x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeType", this.ContentType.Id.ToString())); + x.Attributes.Append(xmlHelper.addAttribute( xd, "template", "0")); + x.Attributes.Append(xmlHelper.addAttribute(xd, "sortOrder", this.sortOrder.ToString())); + x.Attributes.Append(xmlHelper.addAttribute(xd, "createDate", this.CreateDateTime.ToString("s"))); + x.Attributes.Append(xmlHelper.addAttribute(xd, "updateDate", this.VersionDate.ToString("s"))); + x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeName", this.Text)); + if (this.Text != null) + x.Attributes.Append(xmlHelper.addAttribute(xd, "urlName", this.Text.Replace(" ", "").ToLower())); + x.Attributes.Append(xmlHelper.addAttribute(xd, "writerName", this.User.Name)); + if (this.ContentType != null) + x.Attributes.Append(xmlHelper.addAttribute(xd, "nodeTypeAlias", this.ContentType.Alias)); + x.Attributes.Append(xmlHelper.addAttribute(xd, "path", this.Path)); + + if (Deep) + { + foreach(Content c in this.Children) + x.AppendChild(c.ToXml(xd, true)); + } + } + + /// + /// Saves the XML document to the data source. + /// + /// The XML Document. + [MethodImpl(MethodImplOptions.Synchronized)] + protected virtual void SaveXmlDocument(XmlNode node) + { + // Method is synchronized so exists remains consistent (avoiding race condition) + bool exists = SqlHelper.ExecuteScalar("SELECT COUNT(nodeId) FROM cmsContentXml WHERE nodeId = @nodeId", + SqlHelper.CreateParameter("@nodeId", Id)) > 0; + string query; + if (exists) + query = "UPDATE cmsContentXml SET xml = @xml WHERE nodeId = @nodeId"; + else + query = "INSERT INTO cmsContentXml(nodeId, xml) VALUES (@nodeId, @xml)"; + SqlHelper.ExecuteNonQuery(query, + SqlHelper.CreateParameter("@nodeId", Id), + SqlHelper.CreateParameter("@xml", node.OuterXml)); + } + } + + /// + /// Not implemented + /// + public interface ISaveHandlerContents + { + /// + /// Not implemented + /// + bool Execute(cms.businesslogic.Content contentObject); + } +} \ No newline at end of file diff --git a/umbraco/cms/businesslogic/ContentItem/ContentItem.cs b/umbraco/cms/businesslogic/ContentItem/ContentItem.cs new file mode 100644 index 0000000000..97fe4c5a0d --- /dev/null +++ b/umbraco/cms/businesslogic/ContentItem/ContentItem.cs @@ -0,0 +1,84 @@ +using System; + +namespace umbraco.cms.businesslogic.contentitem +{ + /// + /// Summary description for ContentItem. + /// + public class ContentItem : Content + { + private static Guid _objectType = new Guid("10e2b09f-c28b-476d-b77a-aa686435e44a"); + + public ContentItem(int id) : base(id) + { + // + // TODO: Add constructor logic here + // + } + public ContentItem(Guid id) : base(id) + { + // + // TODO: Add constructor logic here + // + } + + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + + public override void Save() + { + base.Save(); + } + + + + public static void DeleteFromType(ContentItemType cit) + { + foreach (Content c in Content.getContentOfContentType(cit)) + { + // due to recursive structure document might already been deleted.. + if (CMSNode.IsNode(c.UniqueId)) + { + ContentItem tmp = new ContentItem(c.UniqueId); + tmp.delete(); + } + } + } + + public static ContentItem MakeNew(string Name, ContentItemType cit, BusinessLogic.User u, int ParentId) + { + Guid newId = Guid.NewGuid(); + // Updated to match level from base node + CMSNode n = new CMSNode(ParentId); + int newLevel = n.Level; + newLevel++; + CMSNode.MakeNew(ParentId,_objectType, u.Id, newLevel, Name, newId); + ContentItem tmp = new ContentItem(newId); + tmp.CreateContent(cit); + return tmp; + } + + + new public void delete() + { + foreach (ContentItem d in this.Children) + { + d.delete(); + } + base.delete(); + } + + new public ContentItem[] Children + { + get + { + BusinessLogic.console.IconI[] tmp = base.Children; + ContentItem[] retval = new ContentItem[tmp.Length]; + for (int i = 0; i < tmp.Length; i++) retval[i] = new ContentItem(tmp[i].UniqueId); + return retval; + } + } + } +} diff --git a/umbraco/cms/businesslogic/ContentItem/ContentItemType.cs b/umbraco/cms/businesslogic/ContentItem/ContentItemType.cs new file mode 100644 index 0000000000..786fe95d83 --- /dev/null +++ b/umbraco/cms/businesslogic/ContentItem/ContentItemType.cs @@ -0,0 +1,67 @@ +using System; + +namespace umbraco.cms.businesslogic.contentitem +{ + /// + /// Summary description for ContentItemType. + /// + public class ContentItemType : ContentType + { + private static Guid _objectType = new Guid("7a333c54-6f43-40a4-86a2-18688dc7e532 "); + public ContentItemType(int id) : base(id) + { + // + // TODO: Add constructor logic here + // + } + public ContentItemType(Guid id) : base(id) + { + // + // TODO: Add constructor logic here + // + } + + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public override void Save() + { + } + + + + + public static ContentItemType MakeNew( BusinessLogic.User u,string Text) + { + + int ParentId= -1; + int level = 1; + Guid uniqueId = Guid.NewGuid(); + CMSNode n = CMSNode.MakeNew(ParentId, _objectType, u.Id, level,Text, uniqueId); + + ContentType.Create(n.Id, Text,""); + + return new ContentItemType(n.Id); + } + + new public static ContentItemType[] GetAll + { + get + { + Guid[] Ids = CMSNode.getAllUniquesFromObjectType(_objectType); + ContentItemType[] retVal = new ContentItemType[Ids.Length]; + for (int i = 0; i < Ids.Length; i++) retVal[i] = new ContentItemType(Ids[i]); + return retVal; + } + } + + new public void delete() + { + // delete all documents of this type + ContentItem.DeleteFromType(this); + // Delete contentType + base.delete(); + } + } +} diff --git a/umbraco/cms/businesslogic/ContentType.cs b/umbraco/cms/businesslogic/ContentType.cs new file mode 100644 index 0000000000..d3d8631de4 --- /dev/null +++ b/umbraco/cms/businesslogic/ContentType.cs @@ -0,0 +1,1035 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Threading; +using System.Web; +using System.Runtime.CompilerServices; + +using umbraco.cms.businesslogic.cache; +using umbraco.cms.businesslogic.datatype; +using umbraco.cms.businesslogic.language; +using umbraco.cms.businesslogic.propertytype; +using umbraco.DataLayer; + +namespace umbraco.cms.businesslogic +{ + /// + /// ContentTypes defines the datafields of Content objects of that type, it's similar to defining columns + /// in a database table, where the PropertyTypes on the ContentType each responds to a Column, and the Content + /// objects is similar to a row of data, where the Properties on the Content object corresponds to the PropertyTypes + /// on the ContentType. + /// + /// Besides data definition, the ContentType also defines the sorting and grouping (in tabs) of Properties/Datafields + /// on the Content and which Content (by ContentType) can be created as child to the Content of the ContentType. + /// + public class ContentType : CMSNode + { + private bool _optimizedMode = false; + private string _alias; + private string _iconurl; + private static Hashtable _analyzedContentTypes = new Hashtable(); + private static Hashtable _optimizedContentTypes = new Hashtable(); + + private string _description; + + /// + /// Gets or sets the description. + /// + /// The description. + public string Description + { + get { return _description; } + set + { + _description = value; + SqlHelper.ExecuteNonQuery( + "update cmsContentType set description = @description where nodeId = @id", + SqlHelper.CreateParameter("@description", value), + SqlHelper.CreateParameter("@id", Id)); + + FlushFromCache(Id); + } + } + + private string _thumbnail; + + /// + /// Gets or sets the thumbnail. + /// + /// The thumbnail. + public string Thumbnail + { + get { return _thumbnail; } + set + { + _thumbnail = value; + SqlHelper.ExecuteNonQuery( + "update cmsContentType set thumbnail = @thumbnail where nodeId = @id", + SqlHelper.CreateParameter("@thumbnail", value), + SqlHelper.CreateParameter("@id", Id)); + + FlushFromCache(Id); + } + } + + + /// + /// Gets or sets a value indicating whether [optimized mode]. + /// + /// true if [optimized mode]; otherwise, false. + public bool OptimizedMode + { + get { return _optimizedMode; } + set { _optimizedMode = value; } + } + + /// + /// + /// + /// + public ContentType(int id) : base(id) + { + setupContentType(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The id. + public ContentType(Guid id) : base(id) + { + setupContentType(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The id. + /// if set to true [use optimized mode]. + public ContentType(int id, bool UseOptimizedMode) : base(id, true) + { + } + + /// + /// Gets the raw text. + /// + /// + public string GetRawText() + { + return base.Text; + } + + /// + /// Human readable name/label + /// + /// + public override string Text + { + get + { + string tempText = base.Text; + if (!tempText.StartsWith("#")) + return tempText; + else + { + Language lang = + Language.GetByCultureCode(Thread.CurrentThread.CurrentCulture.Name); + if (lang != null) + { + if (Dictionary.DictionaryItem.hasKey(tempText.Substring(1, tempText.Length - 1))) + { + Dictionary.DictionaryItem di = + new Dictionary.DictionaryItem(tempText.Substring(1, tempText.Length - 1)); + return di.Value(lang.id); + } + } + + return "[" + tempText + "]"; + } + } + set + { + base.Text = value; + + // Remove from cache + FlushFromCache(Id); + } + } + + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public override void Save() + { + base.Save(); + + // Remove from all doctypes from cache + FlushAllFromCache(); + } + + /// + /// Initializes a ContentType object given the Alias. + /// + /// Alias of the content type + /// + /// The ContentType with the corrosponding Alias + /// + public static ContentType GetByAlias(string Alias) + { + return new ContentType(SqlHelper.ExecuteScalar("SELECT nodeid FROM cmsContentType WHERE alias = @alias", + SqlHelper.CreateParameter("@alias", Alias))); + } + + /// + /// Set up the internal data of the ContentType + /// + protected void setupContentType() + { + using (IRecordsReader dr = + SqlHelper.ExecuteReader("Select masterContentType,Alias,icon,thumbnail,description from cmsContentType where nodeid=" + Id) + ) + { + if (!dr.Read()) + throw new ArgumentException("No Contenttype with id: " + Id); + _alias = dr.GetString("Alias"); + _iconurl = dr.GetString("icon"); + if (!dr.IsNull("masterContentType")) + m_masterContentType = dr.GetInt("masterContentType"); + + if (!dr.IsNull("thumbnail")) + _thumbnail = dr.GetString("thumbnail"); + if (!dr.IsNull("description")) + _description = dr.GetString("description"); + } + } + + /// + /// Retrieve a list of all ContentTypes + /// + /// The list of all ContentTypes + public ContentType[] GetAll() + { + // Fetch contenttypes current objectType + Guid[] Ids = getAllUniquesFromObjectType(base.nodeObjectType); + SortedList initRetVal = new SortedList(); + for (int i = 0; i < Ids.Length; i++) + { + ContentType dt = new ContentType(Ids[i]); + initRetVal.Add(dt.Text + dt.UniqueId, dt); + } + + ContentType[] retVal = new ContentType[Ids.Length]; + + IDictionaryEnumerator ide = initRetVal.GetEnumerator(); + + int count = 0; + while (ide.MoveNext()) + { + retVal[count] = (ContentType) ide.Value; + count++; + } + + return retVal; + } + + + /// + /// The "datafield/column" definitions, a Content object of this type will have an equivalent + /// list of Properties. + /// + private static readonly object propertyTypesCacheSyncLock = new object(); + public List PropertyTypes + { + get + { + string cacheKey = "ContentType_PropertyTypes_Content:" + this.Id; + return Cache.GetCacheItem>(cacheKey, propertyTypesCacheSyncLock, + TimeSpan.FromMinutes(15), + delegate + { + List result = new List(); + using(IRecordsReader dr = + SqlHelper.ExecuteReader( + "select id from cmsPropertyType where contentTypeId = @ctId order by sortOrder", + SqlHelper.CreateParameter("@ctId", Id))) + { + while(dr.Read()) + { + int id = dr.GetInt("id"); + PropertyType pt = PropertyType.GetPropertyType(id); + if(pt != null) + result.Add(pt); + } + } + + // Get Property Types from the master content type + if (MasterContentType != 0) + { + foreach (PropertyType pt in ContentType.GetContentType(MasterContentType).PropertyTypes) + { + result.Add(pt); + } + } + return result; + }); + } + } + + /// + /// The Alias of the ContentType, is used for import/export and more human readable initialization see: GetByAlias + /// method. + /// + public string Alias + { + get { return _alias; } + set + { + SqlHelper.ExecuteNonQuery( + "update cmsContentType set alias = '" + value + "' where nodeId = " + + Id.ToString()); + _alias = value; + + // Remove from cache + FlushFromCache(Id); + } + } + + /// + /// A Content object is often (always) represented in the treeview in the Umbraco console, the ContentType defines + /// which Icon the Content of this type is representated with. + /// + public string IconUrl + { + get { return _iconurl; } + set + { + _iconurl = value; + SqlHelper.ExecuteNonQuery( + "update cmsContentType set icon='" + value + "' where nodeid = " + Id); + // Remove from cache + FlushFromCache(Id); + } + } + + private int m_masterContentType = 0; + /// + /// Gets or sets the Master Content Type for inheritance of tabs and properties. + /// + /// The ID of the Master Content Type + public int MasterContentType { + get { + return m_masterContentType; + } + set + { + m_masterContentType = value; + SqlHelper.ExecuteNonQuery("update cmsContentType set masterContentType = @masterContentType where nodeId = @nodeId", + SqlHelper.CreateParameter("@masterContentType", value), + SqlHelper.CreateParameter("@nodeId", Id)); + + // Remove from cache + FlushFromCache(Id); + } + } + + /// + /// Adding a PropertyType to the ContentType, will add a new datafield/Property on all Documents of this Type. + /// + /// The DataTypeDefinition of the PropertyType + /// The Alias of the PropertyType + /// The userfriendly name + public void AddPropertyType(DataTypeDefinition dt, string Alias, string Name) + { + PropertyType pt = PropertyType.MakeNew(dt, this, Name, Alias); + + // Optimized call + populatePropertyData(pt, this.Id); + + // Inherited content types (document types only) + populateMasterContentTypes(pt, this.Id); + +// foreach (Content c in Content.getContentOfContentType(this)) +// c.addProperty(pt,c.Version); + + // Remove from cache + FlushFromCache(Id); + } + + private void populateMasterContentTypes(PropertyType pt, int docTypeId) + { + foreach (web.DocumentType docType in web.DocumentType.GetAllAsList()) + { + if (docType.MasterContentType == docTypeId) + { + populatePropertyData(pt, docType.Id); + populateMasterContentTypes(pt, docType.Id); + } + } + } + + private void populatePropertyData(PropertyType pt, int contentTypeId) + { + SqlHelper.ExecuteNonQuery( + "insert into cmsPropertyData (contentNodeId, versionId, propertyTypeId) select contentId, versionId, @propertyTypeId from cmsContent inner join cmsContentVersion on cmsContent.nodeId = cmsContentVersion.contentId where contentType = @contentTypeId", + SqlHelper.CreateParameter("@propertyTypeId", pt.Id), + SqlHelper.CreateParameter("@contentTypeId", contentTypeId)); + } + + /// + /// Adding a PropertyType to a Tab, the Tabs are primarily used for making the + /// editing interface more userfriendly. + /// + /// + /// The PropertyType + /// The Id of the Tab + public void SetTabOnPropertyType(PropertyType pt, int TabId) + { + SqlHelper.ExecuteNonQuery( + "update cmsPropertyType set tabId = " + TabId.ToString() + " where id = " + + pt.Id.ToString()); + + // Remove from cache + FlushFromCache(Id); + foreach (TabI t in getVirtualTabs) + FlushTabCache(t.Id, pt.ContentTypeId); + } + + /// + /// Removing a PropertyType from the associated Tab + /// + /// The PropertyType which should be freed from its tab + public void removePropertyTypeFromTab(PropertyType pt) + { + SqlHelper.ExecuteNonQuery( + "update cmsPropertyType set tabId = NULL where id = " + pt.Id.ToString()); + + // Remove from cache + FlushFromCache(Id); + } + + /// + /// Creates a new Tab on the Content + /// + /// Returns the Id of the new Tab + /// + [MethodImpl(MethodImplOptions.Synchronized)] + public int AddVirtualTab(string Caption) + { + // Remove from cache + FlushFromCache(Id); + + // Get tab count + int tabCount = SqlHelper.ExecuteScalar("SELECT COUNT(*) FROM cmsTab WHERE contenttypeNodeId = @nodeId", + SqlHelper.CreateParameter("@nodeId", Id)); + + // The method is synchronized + SqlHelper.ExecuteNonQuery("INSERT INTO cmsTab (contenttypeNodeId,text,sortorder) VALUES (@nodeId,@text,@sortorder)", + SqlHelper.CreateParameter("@nodeId", Id), + SqlHelper.CreateParameter("@text", Caption), + SqlHelper.CreateParameter("@sortorder", tabCount + 1)); + return SqlHelper.ExecuteScalar("SELECT MAX(id) FROM cmsTab"); + } + + /// + /// Helper method for getting the Tab id from a given PropertyType + /// + /// The PropertyType from which to get the Tab Id + /// The Id of the Tab on which the PropertyType is placed + public static int getTabIdFromPropertyType(PropertyType pt) + { + object tmp = SqlHelper.ExecuteScalar("Select tabId from cmsPropertyType where id = " + pt.Id.ToString()); + if (tmp == DBNull.Value) + return 0; + else return int.Parse(tmp.ToString()); + } + + /// + /// Releases all PropertyTypes on tab (this does not delete the PropertyTypes) and then Deletes the Tab + /// + /// The Id of the Tab to be deleted. + public void DeleteVirtualTab(int id) + { + SqlHelper.ExecuteNonQuery( + "Update cmsPropertyType set tabId = NULL where tabId =" + id); + SqlHelper.ExecuteNonQuery( "delete from cmsTab where id =" + id); + + // Remove from cache + FlushFromCache(Id); + } + + /// + /// Retrieve a list of all Tabs on the current ContentType + /// + public TabI[] getVirtualTabs + { + get + { + List tmp = new List(); + using (IRecordsReader dr = SqlHelper.ExecuteReader( + string.Format( + "Select Id,text,sortOrder from cmsTab where contenttypeNodeId = {0} order by sortOrder", + Id))) + { + while (dr.Read()) + { + tmp.Add(new Tab(dr.GetInt("id"), dr.GetString("text"), dr.GetInt("sortOrder"), this)); + } + } + + // Master Content Type + if (MasterContentType != 0) + { + foreach (TabI t in ContentType.GetContentType(MasterContentType).getVirtualTabs) + { + tmp.Add(t); + } + } + + // sort all tabs + tmp.Sort((a, b) => a.SortOrder.CompareTo(b.SortOrder)); + + return tmp.ToArray(); + } + } + + /// + /// Updates the caption of the Tab + /// + /// The Id of the Tab to be updated + /// The new Caption + public void SetTabName(int tabId, string Caption) + { + SqlHelper.ExecuteNonQuery( + "Update cmsTab set text = '" + Caption + "' where id = " + tabId); + + // Remove from cache + FlushFromCache(Id); + } + + /// + /// Updates the sort order of the Tab + /// + /// The Id of the Tab to be updated + /// The new order number + public void SetTabSortOrder(int tabId, int sortOrder) + { + SqlHelper.ExecuteNonQuery( + "Update cmsTab set sortOrder = " + sortOrder + " where id = " + tabId); + + // Remove from cache + FlushFromCache(Id); + } + + + /// + /// An interface for the tabs, should be refactored + /// + public interface TabI + { + /// + /// Public identifier + /// + int Id { get; } + + /// + /// The text on the tab + /// + string Caption { get; } + + /// + /// The sortorder of the tab + /// + int SortOrder { get; } + + /// + /// A list of all PropertyTypes on the Tab + /// + PropertyType[] PropertyTypes { get; } + + /// + /// The contenttype + /// + int ContentType { get; } + + /// + /// Method for moving the tab up + /// + void MoveUp(); + + /// + /// Method for retrieving the original, non processed name from the db + /// + /// The original, non processed name from the db + string GetRawCaption(); + + /// + /// Method for moving the tab down + /// + void MoveDown(); + } + + + /// + /// A tab is merely a way to organize data on a ContentType to make it more + /// human friendly + /// + protected class Tab : TabI + { + private ContentType _contenttype; + private static object propertyTypesCacheSyncLock = new object(); + public static readonly string CacheKey = "Tab_PropertyTypes_Content:"; + + /// + /// Initializes a new instance of the class. + /// + /// The id. + /// The caption. + /// The sort order. + /// Type of the c. + public Tab(int id, string caption, int sortOrder, ContentType cType) + { + _id = id; + _caption = caption; + _sortOrder = sortOrder; + _contenttype = cType; + + // NH: the cachekey needs to combine the tab and the content type id, due to master content types enables sharing of tabs between child types + string cacheKey = generateCacheKey(id, cType.Id); + _propertytypes = + Cache.GetCacheItem(cacheKey, propertyTypesCacheSyncLock, TimeSpan.FromMinutes(10), + delegate + { + List tmp = new List(); + + using ( + IRecordsReader dr = + SqlHelper.ExecuteReader(string.Format( + "Select id from cmsPropertyType where tabid = {0} and contentTypeId = {1} order by sortOrder", + _id, cType.Id))) + { + while (dr.Read()) + { + tmp.Add( + PropertyType.GetPropertyType( + dr.GetInt("id"))); + } + } + return tmp.ToArray(); + }); + } + + /// + /// Flushes the cache. + /// + /// The id. + public static void FlushCache(int Id, int ContentTypeId) + { + Cache.ClearCacheItem(generateCacheKey(Id, ContentTypeId)); + } + + private static string generateCacheKey(int tabId, int contentTypeId) { + return String.Format("{0}_{1}_{2}", CacheKey, tabId, contentTypeId); + } + + /// + /// Deletes this instance. + /// + public void Delete() + { + SqlHelper.ExecuteNonQuery( "delete from cmsTab where id = @id", + SqlHelper.CreateParameter("@id", Id)); + } + + /// + /// Gets the tab caption by id. + /// + /// The id. + /// + public static string GetCaptionById(int id) + { + try + { + string tempCaption = SqlHelper.ExecuteScalar("Select text from cmsTab where id = " + id.ToString()); + if (!tempCaption.StartsWith("#")) + return tempCaption; + else + { + Language lang = + Language.GetByCultureCode(Thread.CurrentThread.CurrentCulture.Name); + if (lang != null) + return + new Dictionary.DictionaryItem(tempCaption.Substring(1, tempCaption.Length - 1)).Value( + lang.id); + else + return "[" + tempCaption + "]"; + } + } + catch + { + return null; + } + } + + private int _id; + + private int _sortOrder; + + /// + /// The sortorder of the tab + /// + /// + public int SortOrder + { + get + { + return SqlHelper.ExecuteScalar("select sortOrder from cmsTab where id = " + _id); + } + set + { + SqlHelper.ExecuteNonQuery("update cmsTab set sortOrder = " + value + " where id =" + _id); + } + } + + /// + /// Moves the Tab up + /// + public void MoveUp() + { + FixTabOrder(); + // If this tab is not the first we can switch places with the previous tab + // hence moving it up. + if (SortOrder > 0) + { + int newsortorder = SortOrder - 1; + // Find the tab to switch with + TabI[] Tabs = _contenttype.getVirtualTabs; + foreach (Tab t in Tabs) + { + if (t.SortOrder == newsortorder) + t.SortOrder = SortOrder; + } + SortOrder = newsortorder; + } + } + + /// + /// Moves the Tab down + /// + public void MoveDown() + { + FixTabOrder(); + // If this tab is not the last tab we can switch places with the next tab + // hence moving it down. + TabI[] Tabs = _contenttype.getVirtualTabs; + if (SortOrder < Tabs.Length - 1) + { + int newsortorder = SortOrder + 1; + // Find the tab to switch with + foreach (Tab t in Tabs) + { + if (t.SortOrder == newsortorder) + t.SortOrder = SortOrder; + } + SortOrder = newsortorder; + } + } + + /// + /// Method for retrieving the original, non processed name from the db + /// + /// + /// The original, non processed name from the db + /// + public string GetRawCaption() + { + return _caption; + } + + + /// + /// Fixes the tab order. + /// + private void FixTabOrder() + { + TabI[] Tabs = _contenttype.getVirtualTabs; + for (int i = 0; i < Tabs.Length; i++) + { + Tab t = (Tab) Tabs[i]; + t.SortOrder = i; + } + } + + + /// + /// Public identifier + /// + /// + public int Id + { + get { return _id; } + } + + private PropertyType[] _propertytypes; + + /// + /// A list of PropertyTypes on the Tab + /// + public PropertyType[] PropertyTypes + { + get { return _propertytypes; } + } + + public int ContentType + { + get { return _contenttype.Id; } + } + + private string _caption; + + /// + /// The text on the tab + /// + /// + public string Caption + { + get + { + if (!_caption.StartsWith("#")) + return _caption; + else + { + Language lang = + Language.GetByCultureCode(Thread.CurrentThread.CurrentCulture.Name); + if (lang != null) + { + if (Dictionary.DictionaryItem.hasKey(_caption.Substring(1, _caption.Length - 1))) + { + Dictionary.DictionaryItem di = + new Dictionary.DictionaryItem(_caption.Substring(1, _caption.Length - 1)); + if (di != null) + return di.Value(lang.id); + } + } + + return "[" + _caption + "]"; + } + } + } + } + + + /// + /// Retrieve a PropertyType by it's alias + /// + /// PropertyType alias + /// The PropertyType with the given Alias + public PropertyType getPropertyType(string alias) + { + // NH 22-08-08, Get from the property type stack to ensure support of master document types + object o = this.PropertyTypes.Find(delegate(PropertyType pt) { return pt.Alias == alias; }); + + //object o = SqlHelper.ExecuteScalar( + // "Select id from cmsPropertyType where contentTypeId=@contentTypeId And Alias=@alias", + // SqlHelper.CreateParameter("@contentTypeId", this.Id), + // SqlHelper.CreateParameter("@alias", alias)); + + if (o == null) + { + return null; + } + else + { + return (PropertyType)o; + } + + //int propertyTypeId; + //if (!int.TryParse(o.ToString(), out propertyTypeId)) + // return null; + + //return PropertyType.GetPropertyType(propertyTypeId); + } + + /// + /// Creates a new ContentType + /// + /// The CMSNode Id of the ContentType + /// The Alias of the ContentType + /// The Iconurl of Contents of this ContentType + protected static void Create(int NodeId, string Alias, string IconUrl) + { + SqlHelper.ExecuteNonQuery( + "Insert into cmsContentType (nodeId,alias,icon) values (" + NodeId + ",'" + Alias + + "','" + IconUrl + "')"); + } + + /// + /// Deletes the current ContentType + /// + protected new void delete() + { + // Remove from cache + FlushFromCache(Id); + + // Delete all propertyTypes + foreach (PropertyType pt in PropertyTypes) + { + if (pt.ContentTypeId == this.Id) + { + pt.delete(); + } + } + + // delete all tabs + foreach (Tab t in getVirtualTabs) + { + if (t.ContentType == this.Id) + { + t.Delete(); + } + } + + // delete contenttype entrance + SqlHelper.ExecuteNonQuery( "Delete from cmsContentType where NodeId = " + Id); + + // delete CMSNode entrance + base.delete(); + } + + /// + /// The list of ContentType Id's that defines which Content (by ContentType) can be created as child + /// to the Content of this ContentType + /// + public int[] AllowedChildContentTypeIDs + { + get + { + List tmp = new List(); + using (IRecordsReader dr = SqlHelper.ExecuteReader( + "Select AllowedId from cmsContentTypeAllowedContentType where id=" + + Id)) + { + while (dr.Read()) + { + tmp.Add(dr.GetInt("AllowedId")); + } + } + return tmp.ToArray(); + } + set + { + // + SqlHelper.ExecuteNonQuery( + "delete from cmsContentTypeAllowedContentType where id=" + Id); + foreach (int i in value) + { + SqlHelper.ExecuteNonQuery( + "insert into cmsContentTypeAllowedContentType (id,AllowedId) values (" + + Id + "," + i + ")"); + } + } + } + + /// + /// Gets the type of the content. + /// + /// The id. + /// + public static ContentType GetContentType(int id) + { + if (HttpRuntime.Cache[string.Format("UmbracoContentType{0}", id.ToString())] == null) + { + ContentType ct = new ContentType(id); + HttpRuntime.Cache.Insert(string.Format("UmbracoContentType{0}", id.ToString()), ct); + } + return (ContentType) HttpRuntime.Cache[string.Format("UmbracoContentType{0}", id.ToString())]; + } + + + /// + /// Flushes the cache. + /// + /// The id. + protected void FlushFromCache(int Id) + { + if (HttpRuntime.Cache[string.Format("UmbracoContentType{0}", Id.ToString())] != null) + HttpRuntime.Cache.Remove(string.Format("UmbracoContentType{0}", Id.ToString())); + + if (HttpRuntime.Cache[string.Format("ContentType_PropertyTypes_Content:{0}", Id.ToString())] != null) + HttpRuntime.Cache.Remove(string.Format("ContentType_PropertyTypes_Content:{0}", Id.ToString())); + } + + protected void FlushAllFromCache() + { + cache.Cache.ClearCacheByKeySearch("UmbracoContentType"); + cache.Cache.ClearCacheByKeySearch("ContentType_PropertyTypes_Content"); + } + + // This is needed, because the Tab class is protected and as such it's not possible for + // the PropertyType class to easily access the cache flusher + /// + /// Flushes the tab cache. + /// + /// The tab id. + public static void FlushTabCache(int TabId, int ContentTypeId) + { + Tab.FlushCache(TabId, ContentTypeId); + } + + /// + /// Analyzes the content types. + /// + /// Type of the object. + /// if set to true [force update]. + protected void AnalyzeContentTypes(Guid ObjectType, bool ForceUpdate) + { + if (!_analyzedContentTypes.ContainsKey(ObjectType) || ForceUpdate) + { + using (IRecordsReader dr = SqlHelper.ExecuteReader( + "select id from umbracoNode where nodeObjectType = @objectType", + SqlHelper.CreateParameter("@objectType", ObjectType))) + { + while (dr.Read()) + { + ContentType ct = new ContentType(dr.GetInt("id")); + if (!_optimizedContentTypes.ContainsKey(ct.UniqueId)) + _optimizedContentTypes.Add(ct.UniqueId, false); + + _optimizedContentTypes[ct.UniqueId] = usesUmbracoDataOnly(ct); + } + } + } + } + + /// + /// Determines whether this instance is optimized. + /// + /// + /// true if this instance is optimized; otherwise, false. + /// + protected bool IsOptimized() + { + return (bool) _optimizedContentTypes[UniqueId]; + } + + /// + /// If true, this instance uses default umbraco data only. + /// + /// The ct. + /// + private static bool usesUmbracoDataOnly(ContentType ct) + { + bool retVal = true; + foreach (PropertyType pt in ct.PropertyTypes) + { + if (!DataTypeDefinition.IsDefaultData(pt.DataTypeDefinition.DataType.Data)) + { + retVal = false; + break; + } + } + return retVal; + } + } +} diff --git a/umbraco/cms/businesslogic/Dictionary.cs b/umbraco/cms/businesslogic/Dictionary.cs new file mode 100644 index 0000000000..43a10599a3 --- /dev/null +++ b/umbraco/cms/businesslogic/Dictionary.cs @@ -0,0 +1,426 @@ +using System; +using System.Collections; +using System.Data; +using System.Xml; + +using umbraco.cms.businesslogic.language; +using umbraco.DataLayer; +using umbraco.BusinessLogic; + +namespace umbraco.cms.businesslogic +{ + /// + /// The Dictionary is used for storing and retrieving language translated textpieces in Umbraco. It uses + /// umbraco.cms.businesslogic.language.Item class as storage and can be used from the public website of umbraco + /// all text are cached in memory. + /// + public class Dictionary + { + private static bool cacheIsEnsured = false; + private static Hashtable DictionaryItems = new Hashtable(); + private static string _ConnString = GlobalSettings.DbDSN; + private static Guid topLevelParent = new Guid("41c7638d-f529-4bff-853e-59a0c2fb1bde"); + + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + private static void ensureCache() + { + if (!cacheIsEnsured) + { + IRecordsReader dr = + SqlHelper.ExecuteReader("Select id, [key] from cmsDictionary"); + + while (dr.Read()) + { + Guid tmp = dr.GetGuid("id"); + string key = dr.GetString("key"); + DictionaryItems.Add(key, tmp); + } + dr.Close(); + cacheIsEnsured = true; + } + } + + /// + /// Retrieve a list of toplevel DictionaryItems + /// + public static DictionaryItem[] getTopMostItems + { + get + { + ArrayList tmp = new ArrayList(); + IRecordsReader dr = + SqlHelper.ExecuteReader("Select [Key] from cmsDictionary where parent = '" + + topLevelParent.ToString() + "' order by [key]"); + while (dr.Read()) + { + tmp.Add(dr.GetString("key")); + } + dr.Close(); + DictionaryItem[] retval = new DictionaryItem[tmp.Count]; + for (int i = 0; i < tmp.Count; i++) retval[i] = new DictionaryItem(tmp[i].ToString()); + return retval; + } + } + + /// + /// A DictionaryItem is basically a key/value pair (key/language key/value) which holds the data + /// associated to a key in various language translations + /// + public class DictionaryItem + { + private Guid _uniqueID; + private string _key; + + + public DictionaryItem(string key) + { + ensureCache(); + if (hasKey(key)) + { + _uniqueID = (Guid)DictionaryItems[key]; + _key = key; + } + else throw new ArgumentException("No key " + key + " exists in dictionary"); + } + + public DictionaryItem(Guid id) + { + string key = + SqlHelper.ExecuteScalar("Select [key] from cmsDictionary where id = @id", + SqlHelper.CreateParameter("@id", id)); + + ensureCache(); + if (hasKey(key)) + { + _uniqueID = (Guid)DictionaryItems[key]; + _key = key; + } + else throw new ArgumentException("No key " + key + " exists in dictionary"); + } + + public DictionaryItem(int id) + { + string key = + SqlHelper.ExecuteScalar("Select [key] from cmsDictionary where pk = " + id.ToString()); + + ensureCache(); + if (hasKey(key)) + { + _uniqueID = (Guid)DictionaryItems[key]; + _key = key; + } + else throw new ArgumentException("No key " + key + " exists in dictionary"); + } + + private DictionaryItem _parent; + + /// + /// Returns if the dictionaryItem is the root item. + /// Modified by Richard Soeteman on 3-4-2009. The execute scalar throws an error because a Guid instead of string is returned + /// Solves issue http://umbraco.codeplex.com/WorkItem/View.aspx?WorkItemId=21902 + /// + public bool IsTopMostItem() + { + return (SqlHelper.ExecuteScalar("Select parent from cmsDictionary where pk = " + + id) == topLevelParent); + } + + /// + /// Returns the parent. + /// Modified by Richard Soeteman on 3-4-2009. The execute scalar throws an error because a Guid instead of string is returned + /// Solves issue http://umbraco.codeplex.com/WorkItem/View.aspx?WorkItemId=21903 + /// + public DictionaryItem Parent + { + get + { + if (_parent == null) + { + Guid parentGuid = + SqlHelper.ExecuteScalar("Select parent from cmsDictionary where pk = " + + id.ToString()); + if (parentGuid != topLevelParent) + _parent = + new DictionaryItem(parentGuid); + else + throw new ArgumentException("Top most dictionary items doesn't have a parent"); + } + + return _parent; + } + } + + public int id + { + get + { + return SqlHelper.ExecuteScalar("Select pk from cmsDictionary where [key] = '" + key + "'"); + } + } + + public DictionaryItem[] Children + { + get + { + ArrayList tmp = new ArrayList(); + IRecordsReader dr = + SqlHelper.ExecuteReader("Select [Key] from cmsDictionary where parent=@uniqueId order by [Key]", SqlHelper.CreateParameter("@uniqueId", _uniqueID)); + while (dr.Read()) + { + tmp.Add(dr.GetString("key")); + } + dr.Close(); + DictionaryItem[] retval = new DictionaryItem[tmp.Count]; + for (int i = 0; i < tmp.Count; i++) retval[i] = new DictionaryItem(tmp[i].ToString()); + return retval; + } + } + + public static bool hasKey(string key) + { + ensureCache(); + return DictionaryItems.ContainsKey(key); + } + + public bool hasChildren + { + get + { + return (SqlHelper.ExecuteScalar("select count([key]) as tmp from cmsDictionary where parent=@uniqueId", SqlHelper.CreateParameter("@uniqueId", _uniqueID)) > 0); + } + } + + /// + /// Returns or sets the key. + /// Modified by Richard Soeteman on 3-4-2009 + /// Solves issue http://umbraco.codeplex.com/WorkItem/View.aspx?WorkItemId=21927 + /// + public string key + { + get { return _key; } + set + { + if (!hasKey(value)) + { + object tmp = DictionaryItems[key]; + + DictionaryItems.Remove(key); + SqlHelper.ExecuteNonQuery("Update cmsDictionary set [key] = @key WHERE pk = @Id", SqlHelper.CreateParameter("@key", value), SqlHelper.CreateParameter("@Id", id)); + _key = value; + DictionaryItems.Add(key, tmp); + + } + else + throw new ArgumentException("New value of key already exists (is key)"); + } + } + + public string Value(int languageId) + { + if (languageId == 0) + return Value(); + + if (Item.hasText(_uniqueID, languageId)) + return Item.Text(_uniqueID, languageId); + + return ""; + } + + public void setValue(int languageId, string value) + { + if (Item.hasText(_uniqueID, languageId)) + Item.setText(languageId, _uniqueID, value); + else + Item.addText(languageId, _uniqueID, value); + } + + public string Value() + { + return Item.Text(_uniqueID, 1); + } + + public void setValue(string value) + { + if (Item.hasText(_uniqueID, 0)) + Item.setText(0, _uniqueID, value); + else + Item.addText(0, _uniqueID, value); + } + + public static int addKey(string key, string defaultValue, string parentKey) + { + ensureCache(); + if (hasKey(parentKey)) + { + int retval = createKey(key, new DictionaryItem(parentKey)._uniqueID, defaultValue); + return retval; + } + else + throw new ArgumentException("Parentkey doesnt exist"); + } + + public static int addKey(string key, string defaultValue) + { + ensureCache(); + int retval = createKey(key, topLevelParent, defaultValue); + return retval; + } + + public void delete() + { + OnDeleting(EventArgs.Empty); + + // delete recursive + foreach (DictionaryItem dd in Children) + dd.delete(); + + // remove all language values from key + Item.removeText(_uniqueID); + + // Remove key from cache + DictionaryItems.Remove(key); + + // remove key from database + SqlHelper.ExecuteNonQuery("delete from cmsDictionary where [key] ='" + key + "'"); + } + + public void Save() + { + OnSaving(EventArgs.Empty); + } + + + public System.Xml.XmlNode ToXml(XmlDocument xd) + { + + XmlNode dictionaryItem = xd.CreateElement("DictionaryItem"); + dictionaryItem.Attributes.Append(xmlHelper.addAttribute(xd, "Key", this.key)); + foreach (Language lang in Language.getAll) + { + XmlNode itemValue = xmlHelper.addCDataNode(xd, "Value", this.Value(lang.id)); + itemValue.Attributes.Append(xmlHelper.addAttribute(xd, "LanguageId", lang.id.ToString())); + itemValue.Attributes.Append(xmlHelper.addAttribute(xd, "LanguageCultureAlias", lang.CultureAlias)); + dictionaryItem.AppendChild(itemValue); + } + + if (this.hasChildren) + { + foreach (DictionaryItem di in this.Children) + { + dictionaryItem.AppendChild(di.ToXml(xd)); + } + } + + + return dictionaryItem; + } + + public static DictionaryItem Import(XmlNode xmlData) + { + return Import(xmlData, null); + } + + public static DictionaryItem Import(XmlNode xmlData, DictionaryItem parent) + { + string key = xmlData.Attributes["Key"].Value; + + XmlNodeList values = xmlData.SelectNodes("./Value"); + XmlNodeList childItems = xmlData.SelectNodes("./DictionaryItem"); + DictionaryItem newItem; + bool retVal = false; + + if (!DictionaryItem.hasKey(key)) + { + if (parent != null) + DictionaryItem.addKey(key, " ", parent.key); + else + DictionaryItem.addKey(key, " "); + + if (values.Count > 0) + { + //Set language values on the dictionary item + newItem = new DictionaryItem(key); + foreach (XmlNode xn in values) + { + string cA = xn.Attributes["LanguageCultureAlias"].Value; + string keyValue = xmlHelper.GetNodeValue(xn); + + Language valueLang = Language.GetByCultureCode(cA); + + if (valueLang != null) + { + newItem.setValue(valueLang.id, keyValue); + } + } + } + + if (parent == null) + retVal = true; + } + + newItem = new DictionaryItem(key); + + foreach (XmlNode childItem in childItems) + { + Import(childItem, newItem); + } + + if (retVal) + return newItem; + else + return null; + } + + private static int createKey(string key, Guid parentId, string defaultValue) + { + if (!hasKey(key)) + { + Guid newId = Guid.NewGuid(); + SqlHelper.ExecuteNonQuery("Insert into cmsDictionary (id,parent,[key]) values (@id,@parentId,'" + key + "')", + SqlHelper.CreateParameter("@id", newId), + SqlHelper.CreateParameter("@parentId", parentId)); + DictionaryItems.Add(key, newId); + DictionaryItem di = new DictionaryItem(key); + di.setValue(defaultValue); + + di.OnNew(EventArgs.Empty); + + return di.id; + } + else + { + throw new ArgumentException("Key being added already exists!"); + } + } + + public delegate void SaveEventHandler(DictionaryItem sender, EventArgs e); + public delegate void NewEventHandler(DictionaryItem sender, EventArgs e); + public delegate void DeleteEventHandler(DictionaryItem sender, EventArgs e); + + public static event SaveEventHandler Saving; + protected virtual void OnSaving(EventArgs e) + { + if (Saving != null) + Saving(this, e); + } + + public static event NewEventHandler New; + protected virtual void OnNew(EventArgs e) + { + if (New != null) + New(this, e); + } + + public static event DeleteEventHandler Deleting; + protected virtual void OnDeleting(EventArgs e) + { + if (Deleting != null) + Deleting(this, e); + } + } + } +} \ No newline at end of file diff --git a/umbraco/cms/businesslogic/Packager/Installer.cs b/umbraco/cms/businesslogic/Packager/Installer.cs new file mode 100644 index 0000000000..fcfb27f07d --- /dev/null +++ b/umbraco/cms/businesslogic/Packager/Installer.cs @@ -0,0 +1,1118 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.IO; +using System.Web; +using System.Xml; +using System.Xml.XPath; +using System.Reflection; +using System.Runtime.CompilerServices; + +using ICSharpCode.SharpZipLib; +using ICSharpCode.SharpZipLib.Zip; +using ICSharpCode.SharpZipLib.Zip.Compression; +using ICSharpCode.SharpZipLib.Zip.Compression.Streams; + +using umbraco.cms.businesslogic.web; +using umbraco.cms.businesslogic.propertytype; +using umbraco.BusinessLogic; +using umbraco.DataLayer; +using System.Diagnostics; + +namespace umbraco.cms.businesslogic.packager +{ + /// + /// The packager is a component which enables sharing of both data and functionality components between different umbraco installations. + /// + /// The output is a .umb (a zip compressed file) which contains the exported documents/medias/macroes/documenttypes (etc.) + /// in a Xml document, along with the physical files used (images/usercontrols/xsl documents etc.) + /// + /// Partly implemented, import of packages is done, the export is *under construction*. + /// + /// + /// Ruben Verborgh 31/12/2007: I had to change some code, I marked my changes with "DATALAYER". + /// Reason: @@IDENTITY can't be used with the new datalayer. + /// I wasn't able to test the code, since I'm not aware how the code functions. + /// + public class Installer + { + private string _name; + private string _version; + private string _url; + private string _license; + private string _licenseUrl; + private int _reqMajor; + private int _reqMinor; + private int _reqPatch; + private string _authorName; + private string _authorUrl; + private string _readme; + private string _control; + private bool _containUnsecureFiles = false; + private List _unsecureFiles = new List(); + + private ArrayList _macros = new ArrayList(); + private XmlDocument _packageConfig; + + public string Name { get { return _name; } } + public string Version { get { return _version; } } + public string Url { get { return _url; } } + public string License { get { return _license; } } + public string LicenseUrl { get { return _licenseUrl; } } + public string Author { get { return _authorName; } } + public string AuthorUrl { get { return _authorUrl; } } + public string ReadMe { get { return _readme; } } + public string Control { get { return _control; } } + + public bool ContainsUnsecureFiles { get { return _containUnsecureFiles; } } + public List UnsecureFiles { get { return _unsecureFiles; } } + + public int RequirementsMajor { get { return _reqMajor; } } + public int RequirementsMinor { get { return _reqMinor; } } + public int RequirementsPatch { get { return _reqPatch; } } + + /// + /// The xmldocument, describing the contents of a package. + /// + public XmlDocument Config + { + get { return _packageConfig; } + } + + /// + /// Constructor + /// + public Installer() + { + } + + /// + /// Constructor + /// + /// The name of the package + /// The version of the package + /// The url to a descriptionpage + /// The license under which the package is released (preferably GPL ;)) + /// The url to a licensedescription + /// The original author of the package + /// The url to the Authors website + /// Umbraco version major + /// Umbraco version minor + /// Umbraco version patch + /// The readme text + /// The name of the usercontrol used to configure the package after install + public Installer(string Name, string Version, string Url, string License, string LicenseUrl, string Author, string AuthorUrl, int RequirementsMajor, int RequirementsMinor, int RequirementsPatch, string Readme, string Control) + { + _name = Name; + _version = Version; + _url = Url; + _license = License; + _licenseUrl = LicenseUrl; + _reqMajor = RequirementsMajor; + _reqMinor = RequirementsMinor; + _reqPatch = RequirementsPatch; + _authorName = Author; + _authorUrl = AuthorUrl; + _readme = Readme; + _control = Control; + } + + /// + /// Adds the macro to the package + /// + /// Macro to add + public void AddMacro(businesslogic.macro.Macro MacroToAdd) + { + _macros.Add(MacroToAdd); + } + + + + /// + /// Imports the specified package + /// + /// Filename of the umbracopackage + /// + public string Import(string InputFile) + { + string tempDir = ""; + if (File.Exists(HttpContext.Current.Server.MapPath(GlobalSettings.StorageDirectory + Path.DirectorySeparatorChar + InputFile))) + { + FileInfo fi = new FileInfo(HttpContext.Current.Server.MapPath(GlobalSettings.StorageDirectory + Path.DirectorySeparatorChar + InputFile)); + // Check if the file is a valid package + if (fi.Extension.ToLower() == ".umb") + { + try + { + tempDir = unPack(fi.FullName); + LoadConfig(tempDir); + } + catch (Exception unpackE) + { + throw new Exception("Error unpacking extension...", unpackE); + } + } + else + throw new Exception("Error - file isn't a package (doesn't have a .umb extension). Check if the file automatically got named '.zip' upon download."); + } + else + throw new Exception("Error - file not found. Could find file named '" + HttpContext.Current.Server.MapPath(GlobalSettings.StorageDirectory + Path.DirectorySeparatorChar + InputFile) + "'"); + return tempDir; + } + + + public int CreateManifest(string tempDir, string guid, string repoGuid) { + //This is the new improved install rutine, which chops up the process into 3 steps, creating the manifest, moving files, and finally handling umb objects + string _packName = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/name")); + string _packAuthor = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/author/name")); + string _packAuthorUrl = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/author/website")); + string _packVersion = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/version")); + string _packReadme = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/readme")); + string _packLicense = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/license ")); + + + //Create a new package instance to record all the installed package adds - this is the same format as the created packages has. + //save the package meta data + packager.InstalledPackage insPack = packager.InstalledPackage.MakeNew(_packName); + insPack.Data.Author = _packAuthor; + insPack.Data.AuthorUrl = _packAuthorUrl; + insPack.Data.Version = _packVersion; + insPack.Data.Readme = _packReadme; + insPack.Data.License = _packLicense; + insPack.Data.PackageGuid = guid; //the package unique key. + insPack.Data.RepositoryGuid = repoGuid; //the repository unique key, if the package is a file install, the repository will not get logged. + insPack.Save(); + + return insPack.Data.Id; + } + + public void InstallFiles(int packageId, string tempDir) { + + //retrieve the manifest to continue installation + packager.InstalledPackage insPack = packager.InstalledPackage.GetById(packageId); + + // Move files + string virtualBasePath = System.Web.HttpContext.Current.Request.ApplicationPath; + string basePath = HttpContext.Current.Server.MapPath(virtualBasePath); + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//file")) { + //we enclose the whole file-moving to ensure that the entire installer doesn't crash + try { + String destPath = getFileName(basePath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgPath"))); + String sourceFile = getFileName(tempDir, xmlHelper.GetNodeValue(n.SelectSingleNode("guid"))); + String destFile = getFileName(destPath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); + + // Create the destination directory if it doesn't exist + if (!Directory.Exists(destPath)) + Directory.CreateDirectory(destPath); + //If a file with this name exists, delete it + else if (File.Exists(destFile)) + File.Delete(destFile); + + // Move the file + File.Move(sourceFile, destFile); + + //PPH log file install + insPack.Data.Files.Add(xmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")) + "/" + xmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); + } catch (Exception ex) { + Log.Add(LogTypes.Error, -1, "Package install error: " + ex.ToString()); + } + } + + insPack.Save(); + } + + + public void InstallBusinessLogic(int packageId, string tempDir) { + + //retrieve the manifest to continue installation + packager.InstalledPackage insPack = packager.InstalledPackage.GetById(packageId); + bool saveNeeded = false; + + //Install DataTypes + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//DataType")) { + cms.businesslogic.datatype.DataTypeDefinition newDtd = cms.businesslogic.datatype.DataTypeDefinition.Import(n); + + if (newDtd != null) { + insPack.Data.DataTypes.Add(newDtd.Id.ToString()); + saveNeeded = true; + } + } + + if (saveNeeded) {insPack.Save(); saveNeeded = false;} + + //Install languages + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//Language")) { + language.Language newLang = language.Language.Import(n); + + if (newLang != null) { + insPack.Data.Languages.Add(newLang.id.ToString()); + saveNeeded = true; + } + } + + if (saveNeeded) { insPack.Save(); saveNeeded = false; } + + //Install dictionary items + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("./DictionaryItems/DictionaryItem")) { + Dictionary.DictionaryItem newDi = Dictionary.DictionaryItem.Import(n); + + if (newDi != null) { + insPack.Data.DictionaryItems.Add(newDi.id.ToString()); + saveNeeded = true; + } + } + + if (saveNeeded) { insPack.Save(); saveNeeded = false; } + + // Install macros + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//macro")) { + cms.businesslogic.macro.Macro m = cms.businesslogic.macro.Macro.Import(n); + + if (m != null) { + insPack.Data.Macros.Add(m.Id.ToString()); + saveNeeded = true; + } + } + + if (saveNeeded) { insPack.Save(); saveNeeded = false; } + + // Get current user, with a fallback + User u = new User(0); + if (!string.IsNullOrEmpty(BasePages.UmbracoEnsuredPage.umbracoUserContextID)) { + if (BasePages.UmbracoEnsuredPage.ValidateUserContextID(BasePages.UmbracoEnsuredPage.umbracoUserContextID)) { + BasePages.UmbracoEnsuredPage uep = new umbraco.BasePages.UmbracoEnsuredPage(); + u = uep.getUser(); + } + } + + + // Add Templates + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Templates/Template")) { + template.Template t = template.Template.MakeNew(xmlHelper.GetNodeValue(n.SelectSingleNode("Name")), u); + t.Alias = xmlHelper.GetNodeValue(n.SelectSingleNode("Alias")); + + t.ImportDesign(xmlHelper.GetNodeValue(n.SelectSingleNode("Design"))); + + insPack.Data.Templates.Add(t.Id.ToString()); + + saveNeeded = true; + } + + if (saveNeeded) { insPack.Save(); saveNeeded = false; } + + + // Add master templates + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Templates/Template")) { + string master = xmlHelper.GetNodeValue(n.SelectSingleNode("Master")); + template.Template t = template.Template.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Alias"))); + if (master.Trim() != "") { + template.Template masterTemplate = template.Template.GetByAlias(master); + if (masterTemplate != null) { + t.MasterTemplate = template.Template.GetByAlias(master).Id; + if (UmbracoSettings.UseAspNetMasterPages) + t.SaveMasterPageFile(t.Design); + } + } + // Master templates can only be generated when their master is known + if (UmbracoSettings.UseAspNetMasterPages) { + t.ImportDesign(xmlHelper.GetNodeValue(n.SelectSingleNode("Design"))); + t.SaveMasterPageFile(t.Design); + } + } + + // Add documenttypes + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("DocumentTypes/DocumentType")) { + ImportDocumentType(n, u, false); + saveNeeded = true; + } + + if (saveNeeded) { insPack.Save(); saveNeeded = false; } + + + // Add documenttype structure + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("DocumentTypes/DocumentType")) { + DocumentType dt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Alias"))); + if (dt != null) { + ArrayList allowed = new ArrayList(); + foreach (XmlNode structure in n.SelectNodes("Structure/DocumentType")) { + DocumentType dtt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(structure)); + allowed.Add(dtt.Id); + } + int[] adt = new int[allowed.Count]; + for (int i = 0; i < allowed.Count; i++) + adt[i] = (int)allowed[i]; + dt.AllowedChildContentTypeIDs = adt; + + //PPH we log the document type install here. + insPack.Data.Documenttypes.Add(dt.Id.ToString()); + saveNeeded = true; + } + } + + if (saveNeeded) { insPack.Save(); saveNeeded = false; } + + // Stylesheets + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Stylesheets/Stylesheet")) { + StyleSheet s = StyleSheet.MakeNew( + u, + xmlHelper.GetNodeValue(n.SelectSingleNode("Name")), + xmlHelper.GetNodeValue(n.SelectSingleNode("FileName")), + xmlHelper.GetNodeValue(n.SelectSingleNode("Content"))); + + foreach (XmlNode prop in n.SelectNodes("Properties/Property")) { + StylesheetProperty sp = StylesheetProperty.MakeNew( + xmlHelper.GetNodeValue(prop.SelectSingleNode("Name")), + s, + u); + sp.Alias = xmlHelper.GetNodeValue(prop.SelectSingleNode("Alias")); + sp.value = xmlHelper.GetNodeValue(prop.SelectSingleNode("Value")); + } + s.saveCssToFile(); + + insPack.Data.Stylesheets.Add(s.Id.ToString()); + saveNeeded = true; + } + + if (saveNeeded) { insPack.Save(); saveNeeded = false; } + + // Documents + foreach (XmlElement n in _packageConfig.DocumentElement.SelectNodes("Documents/DocumentSet [@importMode = 'root']/node")) { + insPack.Data.ContentNodeId = cms.businesslogic.web.Document.Import(-1, u, n).ToString(); + } + + //Package Actions + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Actions/Action")) { + + if (n.Attributes["undo"] == null || n.Attributes["undo"].Value == "false") { + insPack.Data.Actions += n.OuterXml; + Log.Add(LogTypes.Debug, -1, HttpUtility.HtmlEncode(n.OuterXml)); + } + + if (n.Attributes["runat"] != null && n.Attributes["runat"].Value == "install") { + try { + packager.PackageAction.RunPackageAction(insPack.Data.Name, n.Attributes["alias"].Value, n); + } catch { + + } + } + } + + insPack.Save(); + } + + public void InstallCleanUp(int packageId, string tempDir) { + + //this will contain some logic to clean up all those old folders + + } + + /// + /// Invoking this method installs the entire current package + /// + /// Temporary folder where the package's content are extracted to + public void Install(string tempDir, string guid, string repoGuid) + { + //PPH added logging of installs, this adds all install info in the installedPackages config file. + string _packName = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/name")); + string _packAuthor= xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/author/name")); + string _packAuthorUrl = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/author/website")); + string _packVersion = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/version")); + string _packReadme = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/readme")); + string _packLicense = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/license ")); + + + //Create a new package instance to record all the installed package adds - this is the same format as the created packages has. + //save the package meta data + packager.InstalledPackage insPack = packager.InstalledPackage.MakeNew(_packName); + insPack.Data.Author = _packAuthor; + insPack.Data.AuthorUrl = _packAuthorUrl; + insPack.Data.Version = _packVersion; + insPack.Data.Readme = _packReadme; + insPack.Data.License = _packLicense; + insPack.Data.PackageGuid = guid; //the package unique key. + insPack.Data.RepositoryGuid = repoGuid; //the repository unique key, if the package is a file install, the repository will not get logged. + + + //Install languages + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//Language")) { + language.Language newLang = language.Language.Import(n); + + if (newLang != null) + insPack.Data.Languages.Add(newLang.id.ToString()); + } + + //Install dictionary items + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("./DictionaryItems/DictionaryItem")) { + Dictionary.DictionaryItem newDi = Dictionary.DictionaryItem.Import(n); + + if (newDi != null) + insPack.Data.DictionaryItems.Add(newDi.id.ToString()); + } + + // Install macros + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//macro")) + { + cms.businesslogic.macro.Macro m = cms.businesslogic.macro.Macro.Import(n); + + if(m != null) + insPack.Data.Macros.Add(m.Id.ToString()); + } + + // Move files + string virtualBasePath = System.Web.HttpContext.Current.Request.ApplicationPath; + string basePath = HttpContext.Current.Server.MapPath(virtualBasePath); + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//file")) + { + String destPath = getFileName(basePath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgPath"))); + String sourceFile = getFileName(tempDir, xmlHelper.GetNodeValue(n.SelectSingleNode("guid"))); + String destFile = getFileName(destPath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); + + // Create the destination directory if it doesn't exist + if (!Directory.Exists(destPath)) + Directory.CreateDirectory(destPath); + // If a file with this name exists, delete it + else if (File.Exists(destFile)) + File.Delete(destFile); + // Move the file + File.Move(sourceFile, destFile); + + //PPH log file install + insPack.Data.Files.Add(xmlHelper.GetNodeValue(n.SelectSingleNode("orgPath")) + "/" + xmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); + } + + + // Get current user + BasePages.UmbracoEnsuredPage uep = new umbraco.BasePages.UmbracoEnsuredPage(); + BusinessLogic.User u = uep.getUser(); + + // Add Templates + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Templates/Template")) + { + template.Template t = template.Template.MakeNew(xmlHelper.GetNodeValue(n.SelectSingleNode("Name")), u); + t.Alias = xmlHelper.GetNodeValue(n.SelectSingleNode("Alias")); + + t.ImportDesign( xmlHelper.GetNodeValue(n.SelectSingleNode("Design")) ); + + insPack.Data.Templates.Add(t.Id.ToString()); + } + + // Add master templates + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Templates/Template")) + { + string master = xmlHelper.GetNodeValue(n.SelectSingleNode("Master")); + template.Template t = template.Template.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Alias"))); + if (master.Trim() != "") + { + template.Template masterTemplate = template.Template.GetByAlias(master); + if (masterTemplate != null) { + t.MasterTemplate = template.Template.GetByAlias(master).Id; + if (UmbracoSettings.UseAspNetMasterPages) + t.SaveMasterPageFile(t.Design); + } + } + // Master templates can only be generated when their master is known + if (UmbracoSettings.UseAspNetMasterPages) { + t.ImportDesign(xmlHelper.GetNodeValue(n.SelectSingleNode("Design"))); + t.SaveMasterPageFile(t.Design); + } + } + + // Add documenttypes + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("DocumentTypes/DocumentType")) + { + ImportDocumentType(n, u, false); + } + + // Add documenttype structure + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("DocumentTypes/DocumentType")) + { + DocumentType dt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Alias"))); + if (dt != null) + { + ArrayList allowed = new ArrayList(); + foreach (XmlNode structure in n.SelectNodes("Structure/DocumentType")) + { + DocumentType dtt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(structure)); + allowed.Add(dtt.Id); + } + int[] adt = new int[allowed.Count]; + for (int i = 0; i < allowed.Count; i++) + adt[i] = (int)allowed[i]; + dt.AllowedChildContentTypeIDs = adt; + + //PPH we log the document type install here. + insPack.Data.Documenttypes.Add(dt.Id.ToString()); + } + } + + // Stylesheets + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Stylesheets/Stylesheet")) + { + StyleSheet s = StyleSheet.MakeNew( + u, + xmlHelper.GetNodeValue(n.SelectSingleNode("Name")), + xmlHelper.GetNodeValue(n.SelectSingleNode("FileName")), + xmlHelper.GetNodeValue(n.SelectSingleNode("Content"))); + + foreach (XmlNode prop in n.SelectNodes("Properties/Property")) + { + StylesheetProperty sp = StylesheetProperty.MakeNew( + xmlHelper.GetNodeValue(prop.SelectSingleNode("Name")), + s, + u); + sp.Alias = xmlHelper.GetNodeValue(prop.SelectSingleNode("Alias")); + sp.value = xmlHelper.GetNodeValue(prop.SelectSingleNode("Value")); + } + s.saveCssToFile(); + + insPack.Data.Stylesheets.Add(s.Id.ToString()); + } + + // Documents + foreach (XmlElement n in _packageConfig.DocumentElement.SelectNodes("Documents/DocumentSet [@importMode = 'root']/node")) { + cms.businesslogic.web.Document.Import(-1, u, n); + + //PPH todo log document install... + } + + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Actions/Action [@runat != 'uninstall']")) { + try { + packager.PackageAction.RunPackageAction(_packName, n.Attributes["alias"].Value, n); + } catch { } + } + + //saving the uninstall actions untill the package is uninstalled. + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("Actions/Action [@undo != false()]")) { + insPack.Data.Actions += n.OuterXml; + } + + + insPack.Save(); + + + } + + public static void ImportDocumentType(XmlNode n, BusinessLogic.User u, bool ImportStructure) + { + DocumentType dt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Alias"))); + if (dt == null) + { + dt = DocumentType.MakeNew(u, xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Name"))); + dt.Alias = xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Alias")); + + + //Master content type + DocumentType mdt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Master"))); + if (mdt != null) + dt.MasterContentType = mdt.Id; + } + else + { + dt.Text = xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Name")); + } + + + // Info + dt.IconUrl = xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Icon")); + dt.Thumbnail = xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Thumbnail")); + dt.Description = xmlHelper.GetNodeValue(n.SelectSingleNode("Info/Description")); + + // Templates + ArrayList templates = new ArrayList(); + foreach (XmlNode tem in n.SelectNodes("Info/AllowedTemplates/Template")) + { + template.Template t = template.Template.GetByAlias(xmlHelper.GetNodeValue(tem)); + if (t != null) + templates.Add(t); + } + + try + { + template.Template[] at = new template.Template[templates.Count]; + for (int i = 0; i < templates.Count; i++) + at[i] = (template.Template)templates[i]; + dt.allowedTemplates = at; + } + catch (Exception ee) + { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, u, dt.Id, "Packager: Error handling allowed templates: " + ee.ToString()); + } + + // Default template + try + { + if (xmlHelper.GetNodeValue(n.SelectSingleNode("Info/DefaultTemplate")) != "") + dt.DefaultTemplate = template.Template.GetByAlias(xmlHelper.GetNodeValue(n.SelectSingleNode("Info/DefaultTemplate"))).Id; + } + catch (Exception ee) + { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, u, dt.Id, "Packager: Error assigning default template: " + ee.ToString()); + } + + // Tabs + cms.businesslogic.ContentType.TabI[] tabs = dt.getVirtualTabs; + string tabNames = ";"; + for (int t = 0; t < tabs.Length; t++) + tabNames += tabs[t].Caption + ";"; + + Hashtable ht = new Hashtable(); + foreach (XmlNode t in n.SelectNodes("Tabs/Tab")) + { + if (tabNames.IndexOf(";" + xmlHelper.GetNodeValue(t.SelectSingleNode("Caption")) + ";") == -1) + { + ht.Add(int.Parse(xmlHelper.GetNodeValue(t.SelectSingleNode("Id"))), + dt.AddVirtualTab(xmlHelper.GetNodeValue(t.SelectSingleNode("Caption")))); + } + } + + + // Get all tabs in hashtable + Hashtable tabList = new Hashtable(); + foreach (cms.businesslogic.ContentType.TabI t in dt.getVirtualTabs) + { + if (!tabList.ContainsKey(t.Caption)) + tabList.Add(t.Caption, t.Id); + } + + // Generic Properties + datatype.controls.Factory f = new datatype.controls.Factory(); + foreach (XmlNode gp in n.SelectNodes("GenericProperties/GenericProperty")) + { + int dfId = 0; + Guid dtId = new Guid(xmlHelper.GetNodeValue(gp.SelectSingleNode("Type"))); + + if (gp.SelectSingleNode("Definition") != null && !string.IsNullOrEmpty(xmlHelper.GetNodeValue(gp.SelectSingleNode("Definition")))) { + Guid dtdId = new Guid(xmlHelper.GetNodeValue(gp.SelectSingleNode("Definition"))); + if (CMSNode.IsNode(dtdId)) + dfId = new CMSNode(dtdId).Id; + } + if (dfId == 0) { + try { + dfId = findDataTypeDefinitionFromType(ref dtId); + } catch { + throw new Exception(String.Format("Could not find datatype with id {0}.", dtId)); + } + } + + // Fix for rich text editor backwards compatibility + if (dfId == 0 && dtId == new Guid("a3776494-0574-4d93-b7de-efdfdec6f2d1")) + { + dtId = new Guid("83722133-f80c-4273-bdb6-1befaa04a612"); + dfId = findDataTypeDefinitionFromType(ref dtId); + } + + if (dfId != 0) + { + PropertyType pt = dt.getPropertyType(xmlHelper.GetNodeValue(gp.SelectSingleNode("Alias"))); + if (pt == null) + { + dt.AddPropertyType( + datatype.DataTypeDefinition.GetDataTypeDefinition(dfId), + xmlHelper.GetNodeValue(gp.SelectSingleNode("Alias")), + xmlHelper.GetNodeValue(gp.SelectSingleNode("Name")) + ); + pt = dt.getPropertyType(xmlHelper.GetNodeValue(gp.SelectSingleNode("Alias"))); + } + else + { + pt.DataTypeDefinition = datatype.DataTypeDefinition.GetDataTypeDefinition(dfId); + pt.Name = xmlHelper.GetNodeValue(gp.SelectSingleNode("Name")); + } + + pt.Mandatory = bool.Parse(xmlHelper.GetNodeValue(gp.SelectSingleNode("Mandatory"))); + pt.ValidationRegExp = xmlHelper.GetNodeValue(gp.SelectSingleNode("Validation")); + pt.Description = xmlHelper.GetNodeValue(gp.SelectSingleNode("Description")); + + // tab + try + { + if (tabList.ContainsKey(xmlHelper.GetNodeValue(gp.SelectSingleNode("Tab")))) + pt.TabId = (int)tabList[xmlHelper.GetNodeValue(gp.SelectSingleNode("Tab"))]; + } + catch (Exception ee) + { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, u, dt.Id, "Packager: Error assigning property to tab: " + ee.ToString()); + } + } + } + + if (ImportStructure) + { + if (dt != null) + { + ArrayList allowed = new ArrayList(); + foreach (XmlNode structure in n.SelectNodes("Structure/DocumentType")) + { + DocumentType dtt = DocumentType.GetByAlias(xmlHelper.GetNodeValue(structure)); + if (dtt != null) + allowed.Add(dtt.Id); + } + int[] adt = new int[allowed.Count]; + for (int i = 0; i < allowed.Count; i++) + adt[i] = (int)allowed[i]; + dt.AllowedChildContentTypeIDs = adt; + } + } + + // clear caching + foreach(DocumentType.TabI t in dt.getVirtualTabs) + DocumentType.FlushTabCache(t.Id, dt.Id); + + } + + /// + /// Gets the name of the file in the specified path. + /// Corrects possible problems with slashes that would result from a simple concatenation. + /// Can also be used to concatenate paths. + /// + /// The path. + /// Name of the file. + /// The name of the file in the specified path. + private static String getFileName(String path, string fileName) + { + Debug.Assert(path != null && path.Length >= 1); + Debug.Assert(fileName != null && fileName.Length >= 1); + + path = path.Replace('/', '\\'); + fileName = fileName.Replace('/','\\'); + + // Does filename start with a slash? Does path end with one? + bool fileNameStartsWithSlash = (fileName[0] == Path.DirectorySeparatorChar); + bool pathEndsWithSlash = (path[path.Length-1] == Path.DirectorySeparatorChar); + + // Path ends with a slash + if (pathEndsWithSlash) + { + if(!fileNameStartsWithSlash) + // No double slash, just concatenate + return path + fileName; + else + // Double slash, exclude that of the file + return path + fileName.Substring(1); + } + else + { + if (fileNameStartsWithSlash) + // Required slash specified, just concatenate + return path + fileName; + else + // Required slash missing, add it + return path + Path.DirectorySeparatorChar + fileName; + } + } + + private static int findDataTypeDefinitionFromType(ref Guid dtId) + { + int dfId = 0; + foreach (datatype.DataTypeDefinition df in datatype.DataTypeDefinition.GetAll()) + if (df.DataType.Id == dtId) + { + dfId = df.Id; + break; + } + return dfId; + } + + /// + /// Reads the configuration of the package from the configuration xmldocument + /// + /// The folder to which the contents of the package is extracted + public void LoadConfig(string tempDir) + { + _packageConfig = new XmlDocument(); + _packageConfig.Load(tempDir + Path.DirectorySeparatorChar + "package.xml"); + + _name = _packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/name").FirstChild.Value; + _version = _packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/version").FirstChild.Value; + _url = _packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/url").FirstChild.Value; + _license = _packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/license").FirstChild.Value; + _licenseUrl = _packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/license").Attributes.GetNamedItem("url").Value; + _reqMajor = int.Parse(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/requirements/major").FirstChild.Value); + _reqMinor = int.Parse(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/requirements/major").FirstChild.Value); + _reqPatch = int.Parse(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/package/requirements/patch").FirstChild.Value); + _authorName = _packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/author/name").FirstChild.Value; + _authorUrl = _packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/author/website").FirstChild.Value; + + string virtualBasePath = System.Web.HttpContext.Current.Request.ApplicationPath; + string basePath = HttpContext.Current.Server.MapPath(virtualBasePath); + + foreach (XmlNode n in _packageConfig.DocumentElement.SelectNodes("//file")) { + bool badFile = false; + string destPath = getFileName(basePath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgPath"))); + string destFile = getFileName(destPath, xmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); + + if (destPath.ToLower().Contains("\\app_code")) + badFile = true; + + if (destPath.ToLower().Contains("\\bin")) + badFile = true; + + if (destFile.ToLower().EndsWith(".dll")) + badFile = true; + + if (badFile) { + _containUnsecureFiles = true; + _unsecureFiles.Add(xmlHelper.GetNodeValue(n.SelectSingleNode("orgName"))); + } + } + + + try + { + _readme = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/info/readme")); + } + catch { } + try + { + _control = xmlHelper.GetNodeValue(_packageConfig.DocumentElement.SelectSingleNode("/umbPackage/control")); + } + catch { } + } + + private string unPack(string ZipName) + { + // Unzip + string tempDir = HttpContext.Current.Server.MapPath(GlobalSettings.StorageDirectory) + Path.DirectorySeparatorChar + Guid.NewGuid().ToString(); + Directory.CreateDirectory(tempDir); + + ZipInputStream s = new ZipInputStream(File.OpenRead(ZipName)); + + ZipEntry theEntry; + while ((theEntry = s.GetNextEntry()) != null) + { + string directoryName = Path.GetDirectoryName(theEntry.Name); + string fileName = Path.GetFileName(theEntry.Name); + + if (fileName != String.Empty) + { + FileStream streamWriter = File.Create(tempDir + Path.DirectorySeparatorChar + fileName); + + int size = 2048; + byte[] data = new byte[2048]; + while (true) + { + size = s.Read(data, 0, data.Length); + if (size > 0) + { + streamWriter.Write(data, 0, size); + } + else + { + break; + } + } + + streamWriter.Close(); + + } + } + + // Clean up + s.Close(); + File.Delete(ZipName); + + return tempDir; + + } + + //this uses the old method of fetching and only supports the packages.umbraco.org repository. + public string Fetch(Guid Package) + { + + // Check for package directory + if (!System.IO.Directory.Exists(System.Web.HttpContext.Current.Server.MapPath(umbraco.GlobalSettings.StorageDirectory + "\\packages"))) + System.IO.Directory.CreateDirectory(System.Web.HttpContext.Current.Server.MapPath(umbraco.GlobalSettings.StorageDirectory + "\\packages")); + + System.Net.WebClient wc = new System.Net.WebClient(); + + wc.DownloadFile( + "http://" + UmbracoSettings.PackageServer + "/fetch?package=" + Package.ToString(), + System.Web.HttpContext.Current.Server.MapPath(umbraco.GlobalSettings.StorageDirectory + "\\packages\\" + Package.ToString() + ".umb")); + + return "packages\\" + Package.ToString() + ".umb"; + } + + + public static void updatePackageInfo(Guid Package, int VersionMajor, int VersionMinor, int VersionPatch, User User) { + + } + } + + public class Package + { + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + public Package() + { + } + + /// + /// Initialize package install status object by specifying the internal id of the installation. + /// The id is specific to the local umbraco installation and cannot be used to identify the package in general. + /// Use the Package(Guid) constructor to check whether a package has been installed + /// + /// The internal id. + public Package(int Id) + { + initialize(Id); + } + + public Package(Guid Id) + { + int installStatusId = SqlHelper.ExecuteScalar( + "select id from umbracoInstalledPackages where package = @package and upgradeId = 0", + SqlHelper.CreateParameter("@package", Id)); + + if (installStatusId > 0) + initialize(installStatusId); + else + throw new ArgumentException("Package with id '" + Id.ToString() + "' is not installed"); + } + + private void initialize(int id) + { + + IRecordsReader dr = + SqlHelper.ExecuteReader( + "select id, uninstalled, upgradeId, installDate, userId, package, versionMajor, versionMinor, versionPatch from umbracoInstalledPackages where id = @id", + SqlHelper.CreateParameter("@id", id)); + + if (dr.Read()) + { + Id = id; + Uninstalled = dr.GetBoolean("uninstalled"); + UpgradeId = dr.GetInt("upgradeId"); + InstallDate = dr.GetDateTime("installDate"); + User = User.GetUser(dr.GetInt("userId")); + PackageId = dr.GetGuid("package"); + VersionMajor = dr.GetInt("versionMajor"); + VersionMinor = dr.GetInt("versionMinor"); + VersionPatch = dr.GetInt("versionPatch"); + } + dr.Close(); + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public void Save() + { + + IParameter[] values = { + SqlHelper.CreateParameter("@uninstalled", Uninstalled), + SqlHelper.CreateParameter("@upgradeId", UpgradeId), + SqlHelper.CreateParameter("@installDate", InstallDate), + SqlHelper.CreateParameter("@userId", User.Id), + SqlHelper.CreateParameter("@versionMajor", VersionMajor), + SqlHelper.CreateParameter("@versionMinor", VersionMinor), + SqlHelper.CreateParameter("@versionPatch", VersionPatch), + SqlHelper.CreateParameter("@id", Id) + }; + + // check if package status exists + if (Id == 0) + { + // The method is synchronized + SqlHelper.ExecuteNonQuery("INSERT INTO umbracoInstalledPackages (uninstalled, upgradeId, installDate, userId, versionMajor, versionMinor, versionPatch) VALUES (@uninstalled, @upgradeId, @installDate, @userId, @versionMajor, @versionMinor, @versionPatch)",values); + Id = SqlHelper.ExecuteScalar("SELECT MAX(id) FROM umbracoInstalledPackages"); + } + + SqlHelper.ExecuteNonQuery( + "update umbracoInstalledPackages set " + + "uninstalled = @uninstalled, " + + "upgradeId = @upgradeId, " + + "installDate = @installDate, " + + "userId = @userId, " + + "versionMajor = @versionMajor, " + + "versionMinor = @versionMinor, " + + "versionPatch = @versionPatch " + + "where id = @id", + values); + } + + private bool _uninstalled; + + public bool Uninstalled + { + get { return _uninstalled; } + set { _uninstalled = value; } + } + + + private User _user; + + public User User + { + get { return _user; } + set { _user = value; } + } + + + private DateTime _installDate; + + public DateTime InstallDate + { + get { return _installDate; } + set { _installDate = value; } + } + + + private int _id; + + public int Id + { + get { return _id; } + set { _id = value; } + } + + + private int _upgradeId; + + public int UpgradeId + { + get { return _upgradeId; } + set { _upgradeId = value; } + } + + + private Guid _packageId; + + public Guid PackageId + { + get { return _packageId; } + set { _packageId = value; } + } + + + private int _versionPatch; + + public int VersionPatch + { + get { return _versionPatch; } + set { _versionPatch = value; } + } + + + private int _versionMinor; + + public int VersionMinor + { + get { return _versionMinor; } + set { _versionMinor = value; } + } + + + private int _versionMajor; + + public int VersionMajor + { + get { return _versionMajor; } + set { _versionMajor = value; } + } + + + + } +} diff --git a/umbraco/cms/businesslogic/Packager/PackageActions/StandardPackageActions.cs b/umbraco/cms/businesslogic/Packager/PackageActions/StandardPackageActions.cs new file mode 100644 index 0000000000..307f0f2c5d --- /dev/null +++ b/umbraco/cms/businesslogic/Packager/PackageActions/StandardPackageActions.cs @@ -0,0 +1,852 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.Xml; + +namespace umbraco.cms.businesslogic.packager.standardPackageActions { + /*Build in standard actions */ + + /// + /// This class implements the IPackageAction Interface, used to execute code when packages are installed. + /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. + /// + public class addApplicationTree : umbraco.interfaces.IPackageAction { + + #region IPackageAction Members + + /// + /// Executes the specified package action. + /// + /// Name of the package. + /// The XML data. + /// + /// + /// + /// + public bool Execute(string packageName, XmlNode xmlData) { + bool silent = bool.Parse(xmlData.Attributes["silent"].Value); + bool initialize = bool.Parse(xmlData.Attributes["initialize"].Value); + byte sortOrder = byte.Parse(xmlData.Attributes["sortOrder"].Value); + + string applicationAlias = xmlData.Attributes["applicationAlias"].Value; + string treeAlias = xmlData.Attributes["treeAlias"].Value; + string treeTitle = xmlData.Attributes["treeTitle"].Value; + string iconOpened = xmlData.Attributes["iconOpened"].Value; + string iconClosed = xmlData.Attributes["iconClosed"].Value; + + string assemblyName = xmlData.Attributes["assemblyName"].Value; + string type = xmlData.Attributes["treeHandlerType"].Value; + string action = xmlData.Attributes["action"].Value; + + + BusinessLogic.ApplicationTree.MakeNew(silent, initialize, sortOrder, applicationAlias, treeAlias, treeTitle, iconClosed, iconOpened, assemblyName, type, action); + + return true; + } + + /// + /// Undoes the action + /// + /// Name of the package. + /// The XML data. + /// + public bool Undo(string packageName, XmlNode xmlData) { + string treeAlias = xmlData.Attributes["treeAlias"].Value; + BusinessLogic.ApplicationTree.getByAlias(treeAlias).Delete(); + return true; + } + + /// + /// Action alias. + /// + /// + public string Alias() { + return "addApplicationTree"; + } + + #endregion + + + + public XmlNode SampleXml() { + + string sample = ""; + return helper.parseStringToXmlNode(sample); + } + + + } + + /// + /// This class implements the IPackageAction Interface, used to execute code when packages are installed. + /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. + /// + public class addApplication : umbraco.interfaces.IPackageAction { + + #region IPackageAction Members + + /// + /// Installs a new application in umbraco. + /// + /// Name of the package. + /// The XML data. + /// + /// + /// + /// true if successfull + public bool Execute(string packageName, XmlNode xmlData) { + string name = xmlData.Attributes["appName"].Value; + string alias = xmlData.Attributes["appAlias"].Value; + string icon = xmlData.Attributes["appIcon"].Value; + + BusinessLogic.Application.MakeNew(name, alias, icon); + + return true; + } + + public bool Undo(string packageName, XmlNode xmlData) { + string alias = xmlData.Attributes["appAlias"].Value; + BusinessLogic.Application.getByAlias(alias).Delete(); + return true; + } + /// + /// Action alias. + /// + /// + public string Alias() { + return "addApplication"; + } + + #endregion + + public XmlNode SampleXml() { + throw new NotImplementedException(); + } + + } + + /// + /// + /// + public class addDashboardSection : umbraco.interfaces.IPackageAction { + #region IPackageAction Members + + /// + /// Installs a dashboard section. This action reuses the action XML, so it has to be valid dashboard markup. + /// + /// Name of the package. + /// The XML data. + /// true if successfull + /// + /// + /// + ///
+ /// + /// default + /// content + /// + /// + /// /usercontrols/dashboard/latestEdits.ascx + /// /usercontrols/umbracoBlog/dashboardBlogPostCreate.ascx + /// + /// + /// /usercontrols/umbracoBlog/dashboardBlogPostCreate.ascx + /// + ///
+ ///
+ ///
+ ///
+ public bool Execute(string packageName, XmlNode xmlData) { + //this will need a complete section node to work... + + if (xmlData.HasChildNodes) { + string sectionAlias = xmlData.Attributes["dashboardAlias"].Value; + + XmlNode section = xmlData.SelectSingleNode("./section"); + XmlDocument dashboardFile = xmlHelper.OpenAsXmlDocument("/config/dashboard.config"); + XmlNode importedSection = dashboardFile.ImportNode(section, true); + XmlAttribute alias = xmlHelper.addAttribute(dashboardFile, "alias", sectionAlias); + importedSection.Attributes.Append(alias); + + dashboardFile.DocumentElement.AppendChild( dashboardFile.ImportNode(section, true) ); + + dashboardFile.Save(System.Web.HttpContext.Current.Server.MapPath("/config/dashboard.config")); + + return true; + } + + return false; + } + + + public string Alias() { + return "addDashboardSection"; + } + + public bool Undo(string packageName, XmlNode xmlData) { + + string sectionAlias = xmlData.Attributes["dashboardAlias"].Value; + XmlDocument dashboardFile = xmlHelper.OpenAsXmlDocument("/config/dashboard.config"); + + XmlNode section = dashboardFile.SelectSingleNode("//section [@alias = '" + sectionAlias + "']"); + + if(section != null){ + dashboardFile.RemoveChild(section); + dashboardFile.Save(System.Web.HttpContext.Current.Server.MapPath("/config/dashboard.config")); + } + + return true; + } + + #endregion + + public XmlNode SampleXml() { + throw new NotImplementedException(); + } + + } + /// + /// This class implements the IPackageAction Interface, used to execute code when packages are installed. + /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. + /// + public class allowDoctype : umbraco.interfaces.IPackageAction { + + #region IPackageAction Members + + /// + /// Allows a documentType to be created below another documentType. + /// + /// Name of the package. + /// The XML data. + /// + /// + /// + /// Returns true on success + public bool Execute(string packageName, XmlNode xmlData) { + string doctypeName = xmlData.Attributes["documentTypeAlias"].Value; + string parentDoctypeName = xmlData.Attributes["parentDocumentTypeAlias"].Value; + + cms.businesslogic.ContentType ct = cms.businesslogic.ContentType.GetByAlias(doctypeName); + cms.businesslogic.ContentType parentct = cms.businesslogic.ContentType.GetByAlias(parentDoctypeName); + + if (ct != null && parentct != null) { + bool containsId = false; + ArrayList tmp = new ArrayList(); + + foreach (int i in parentct.AllowedChildContentTypeIDs) { + tmp.Add(i); + if (i == ct.Id) + containsId = true; + } + + if (!containsId) { + + int[] ids = new int[tmp.Count + 1]; + for (int i = 0; i < tmp.Count; i++) ids[i] = (int)tmp[i]; + ids[ids.Length - 1] = ct.Id; + + parentct.AllowedChildContentTypeIDs = ids; + parentct.Save(); + return true; + } + } + return false; + } + + //this has no undo. + /// + /// This action has no undo. + /// + /// Name of the package. + /// The XML data. + /// + public bool Undo(string packageName, XmlNode xmlData) { + return true; + } + + /// + /// Action Alias. + /// + /// + public string Alias() { + return "allowDocumenttype"; + } + + #endregion + + public XmlNode SampleXml() { + throw new NotImplementedException(); + } + + } + + public class addXsltExtension : umbraco.interfaces.IPackageAction { + #region IPackageAction Members + + public bool Execute(string packageName, XmlNode xmlData) { + + string _assembly = xmlData.Attributes["assembly"].Value; + string _type = xmlData.Attributes["type"].Value; + string _alias = xmlData.Attributes["extensionAlias"].Value; + + XmlDocument xdoc = new XmlDocument(); + xdoc.PreserveWhitespace = true; + xdoc = xmlHelper.OpenAsXmlDocument("/config/xsltExtensions.config"); + + XmlNode xn = xdoc.SelectSingleNode("//XsltExtensions"); + + if (xn != null) { + bool insertExt = true; + if (xn.HasChildNodes) { + foreach (XmlNode ext in xn.SelectNodes("//ext")) { + if (ext.Attributes["alias"] != null && ext.Attributes["alias"].Value == _alias) + insertExt = false; + } + } + if (insertExt) { + XmlNode newExt = umbraco.xmlHelper.addTextNode(xdoc, "ext", ""); + newExt.Attributes.Append(umbraco.xmlHelper.addAttribute(xdoc, "assembly", _assembly)); + newExt.Attributes.Append(umbraco.xmlHelper.addAttribute(xdoc, "type", _type)); + newExt.Attributes.Append(umbraco.xmlHelper.addAttribute(xdoc, "alias", _alias)); + xn.AppendChild(newExt); + + + xdoc.Save(System.Web.HttpContext.Current.Server.MapPath("/config/xsltExtensions.config")); + return true; + } + } + return false; + } + + public string Alias() { + return "addXsltExtension"; + } + + public bool Undo(string packageName, XmlNode xmlData) { + string _assembly = xmlData.Attributes["assembly"].Value; + string _type = xmlData.Attributes["type"].Value; + string _alias = xmlData.Attributes["extensionAlias"].Value; + + XmlDocument xdoc = new XmlDocument(); + xdoc.PreserveWhitespace = true; + xdoc = xmlHelper.OpenAsXmlDocument("/config/xsltExtensions.config"); + + XmlNode xn = xdoc.SelectSingleNode("//XsltExtensions"); + + if (xn != null) { + bool inserted = false; + if (xn.HasChildNodes) { + foreach (XmlNode ext in xn.SelectNodes("//ext")) { + if (ext.Attributes["alias"] != null && ext.Attributes["alias"].Value == _alias) { + xn.RemoveChild(ext); + inserted = true; + } + } + } + + if (inserted) { + xdoc.Save(System.Web.HttpContext.Current.Server.MapPath("/config/xsltExtensions.config")); + return true; + } + } + return false; + } + + #endregion + + public XmlNode SampleXml() { + throw new NotImplementedException(); + } + + } + + public class addRestExtension : umbraco.interfaces.IPackageAction { + #region IPackageAction Members + + public bool Execute(string packageName, XmlNode xmlData) { + + XmlNodeList _newExts = xmlData.SelectNodes("//ext"); + + if (_newExts.Count > 0) { + XmlDocument xdoc = new XmlDocument(); + xdoc.PreserveWhitespace = true; + xdoc.Load("/config/restExtensions.config"); + + XmlNode xn = xdoc.SelectSingleNode("//RestExtensions"); + + if (xn != null) { + for (int i = 0; i < _newExts.Count; i++) { + XmlNode newExt = _newExts[i]; + string _alias = newExt.Attributes["alias"].Value; + + bool insertExt = true; + if (xn.HasChildNodes) { + foreach (XmlNode ext in xn.SelectNodes("//ext")) { + if (ext.Attributes["alias"] != null && ext.Attributes["alias"].Value == _alias) + insertExt = false; + } + } + + if (insertExt) { + xn.AppendChild(xdoc.ImportNode(newExt, true)); + } + } + + xdoc.Save("/config/restExtensions.config"); + return true; + } + } + return false; + } + + public string Alias() { + return "addRestExtension"; + } + + public bool Undo(string packageName, XmlNode xmlData) { + + XmlNodeList _newExts = xmlData.SelectNodes("//ext"); + + if (_newExts.Count > 0) { + XmlDocument xdoc = new XmlDocument(); + xdoc.PreserveWhitespace = true; + xdoc.Load("/config/restExtensions.config"); + + XmlNode xn = xdoc.SelectSingleNode("//RestExtensions"); + + if (xn != null) { + bool inserted = false; + + for (int i = 0; i < _newExts.Count; i++) { + XmlNode newExt = _newExts[i]; + string _alias = newExt.Attributes["alias"].Value; + if (xn.HasChildNodes) { + foreach (XmlNode ext in xn.SelectNodes("//ext")) { + if (ext.Attributes["alias"] != null && ext.Attributes["alias"].Value == _alias) { + xn.RemoveChild(ext); + inserted = true; + } + } + } + } + + if (inserted) { + xdoc.Save("/config/xsltExtensions.config"); + return true; + } + } + } + return false; + } + + #endregion + + public XmlNode SampleXml() { + throw new NotImplementedException(); + } + + } + + /// + /// This class implements the IPackageAction Interface, used to execute code when packages are installed. + /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. + /// + public class moveRootDocument : umbraco.interfaces.IPackageAction { + #region IPackageAction Members + + /// + /// Executes the specified package action. + /// + /// Name of the package. + /// The XML data. + /// + /// + /// + /// True if executed succesfully + public bool Execute(string packageName, XmlNode xmlData) { + + string documentName = xmlData.Attributes["documentName"].Value; + string parentDocumentType = xmlData.Attributes["parentDocumentType"].Value; + string parentDocumentName = ""; + + if (xmlData.Attributes["parentDocumentName"] != null) + parentDocumentName = xmlData.Attributes["parentDocumentName"].Value; + + int parentDocid = 0; + + ContentType ct = ContentType.GetByAlias(parentDocumentType); + Content[] docs = web.Document.getContentOfContentType(ct); + + if (docs.Length > 0) { + if (String.IsNullOrEmpty(parentDocumentName)) + parentDocid = docs[0].Id; + else { + foreach (Content doc in docs) { + if (doc.Text == parentDocumentName) + parentDocid = doc.Id; + } + } + } + + if (parentDocid > 0) { + web.Document[] rootDocs = web.Document.GetRootDocuments(); + + foreach (web.Document rootDoc in rootDocs) { + if (rootDoc.Text == documentName) { + rootDoc.Move(parentDocid); + rootDoc.PublishWithSubs(new umbraco.BusinessLogic.User(0)); + } + } + } + + + return true; + } + + //this has no undo. + /// + /// This action has no undo. + /// + /// Name of the package. + /// The XML data. + /// + public bool Undo(string packageName, XmlNode xmlData) { + return true; + } + + /// + /// Action alias + /// + /// + public string Alias() { + return "moveRootDocument"; + } + + #endregion + + public XmlNode SampleXml() { + throw new NotImplementedException(); + } + + } + + /// + /// This class implements the IPackageAction Interface, used to execute code when packages are installed. + /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. + /// + public class publishRootDocument : umbraco.interfaces.IPackageAction { + #region IPackageAction Members + + /// + /// Executes the specified package action. + /// + /// Name of the package. + /// The XML data. + /// + /// + /// + /// True if executed succesfully + public bool Execute(string packageName, XmlNode xmlData) { + + string documentName = xmlData.Attributes["documentName"].Value; + + int parentDocid = 0; + + web.Document[] rootDocs = web.Document.GetRootDocuments(); + + foreach (web.Document rootDoc in rootDocs) { + if (rootDoc.Text.Trim() == documentName.Trim() && rootDoc != null && rootDoc.ContentType != null) { + + rootDoc.PublishWithChildrenWithResult(umbraco.BusinessLogic.User.GetUser(0)); + + + break; + } + } + return true; + } + + //this has no undo. + /// + /// This action has no undo. + /// + /// Name of the package. + /// The XML data. + /// + public bool Undo(string packageName, XmlNode xmlData) { + return true; + } + + /// + /// Action alias + /// + /// + public string Alias() { + return "publishRootDocument"; + } + #endregion + + public XmlNode SampleXml() { + throw new NotImplementedException(); + } + + } + + /// + /// This class implements the IPackageAction Interface, used to execute code when packages are installed. + /// All IPackageActions only takes a PackageName and a XmlNode as input, and executes based on the data in the xmlnode. + /// addStringToHtmlElement adds a string to specific HTML element in a specific template, and can either append or prepend it. + /// It uses the action xml node to do this, exemple action xml node: + /// + /// The above will add the string "hello world!" to the first html element with the id "newsSection" in the template "news" + /// + public class addStringToHtmlElement : umbraco.interfaces.IPackageAction { + #region IPackageAction Members + + /// + /// Executes the specified package action. + /// + /// Name of the package. + /// The XML data. + /// + /// + /// + /// True if executed successfully + public bool Execute(string packageName, XmlNode xmlData) { + + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, BusinessLogic.User.GetUser(0), -1, "executing addStringToHtmlElement"); + + string templateAlias = xmlData.Attributes["templateAlias"].Value; + string htmlElementId = xmlData.Attributes["htmlElementId"].Value; + string position = xmlData.Attributes["position"].Value; + string value = xmlHelper.GetNodeValue(xmlData); + template.Template tmp = template.Template.GetByAlias(templateAlias); + + if (UmbracoSettings.UseAspNetMasterPages) + value = tmp.EnsureMasterPageSyntax(value); + + _addStringToHtmlElement(tmp, value, templateAlias, htmlElementId, position); + + return true; + } + + + /// + /// Undoes the addStringToHtml Execute() method, by removing the same string from the same template. + /// + /// Name of the package. + /// The XML data. + /// + public bool Undo(string packageName, XmlNode xmlData) { + string templateAlias = xmlData.Attributes["templateAlias"].Value; + string htmlElementId = xmlData.Attributes["htmlElementId"].Value; + string value = xmlHelper.GetNodeValue(xmlData); + template.Template tmp = template.Template.GetByAlias(templateAlias); + + if (UmbracoSettings.UseAspNetMasterPages) + value = tmp.EnsureMasterPageSyntax(value); + + _removeStringFromHtmlElement(tmp, value, templateAlias, htmlElementId); + return true; + } + + /// + /// Action alias. + /// + /// + public string Alias() { + return "addStringToHtmlElement"; + } + + private void _addStringToHtmlElement(template.Template tmp, string value, string templateAlias, string htmlElementId, string position) { + bool hasAspNetContentBeginning = false; + string design = ""; + string directive = ""; + + if (tmp != null) { + try { + XmlDocument templateXml = new XmlDocument(); + templateXml.PreserveWhitespace = true; + + //Make sure that directive is remove before hacked non html4 compatiple replacement action... + design = tmp.Design; + + + splitDesignAndDirective(ref design, ref directive); + + //making sure that the template xml has a root node... + if (tmp.MasterTemplate > 0) + templateXml.LoadXml( helper.parseToValidXml(tmp, ref hasAspNetContentBeginning, "" + design + "", true)); + else + templateXml.LoadXml(helper.parseToValidXml(tmp, ref hasAspNetContentBeginning, design, true)); + + XmlNode xmlElement = templateXml.SelectSingleNode("//* [@id = '" + htmlElementId + "']"); + + if (xmlElement != null) { + + if (position == "beginning") { + xmlElement.InnerXml = "\n" + helper.parseToValidXml(tmp, ref hasAspNetContentBeginning, value, true) + "\n" + xmlElement.InnerXml; + } else { + xmlElement.InnerXml = xmlElement.InnerXml + "\n" + helper.parseToValidXml(tmp, ref hasAspNetContentBeginning, value, true) + "\n"; + } + } + + tmp.Design = directive + "\n" + helper.parseToValidXml(tmp, ref hasAspNetContentBeginning, templateXml.OuterXml, false); + tmp.Save(); + } catch (Exception ex) { + umbraco.BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Debug, -1, ex.ToString()); + } + } else { + umbraco.BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Debug, -1, "template not found"); + } + } + + private void _removeStringFromHtmlElement(template.Template tmp, string value, string templateAlias, string htmlElementId) { + bool hasAspNetContentBeginning = false; + string design = ""; + string directive = ""; + + + if (tmp != null) { + try { + XmlDocument templateXml = new XmlDocument(); + templateXml.PreserveWhitespace = true; + + //Make sure that directive is remove before hacked non html4 compatiple replacement action... + design = tmp.Design; + splitDesignAndDirective(ref design, ref directive); + + //making sure that the template xml has a root node... + if (tmp.MasterTemplate > 0) + templateXml.LoadXml( helper.parseToValidXml(tmp, ref hasAspNetContentBeginning, "" + design + "", true)); + else + templateXml.LoadXml( helper.parseToValidXml(tmp, ref hasAspNetContentBeginning, design, true)); + + XmlNode xmlElement = templateXml.SelectSingleNode("//* [@id = '" + htmlElementId + "']"); + + + + if (xmlElement != null) { + string repValue = helper.parseToValidXml(tmp, ref hasAspNetContentBeginning, value, true); + xmlElement.InnerXml = xmlElement.InnerXml.Replace(repValue , ""); + } + + tmp.Design = directive + "\n" + helper.parseToValidXml(tmp, ref hasAspNetContentBeginning, templateXml.OuterXml, false); + tmp.Save(); + } catch (Exception ex) { + umbraco.BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Debug, -1, ex.ToString() ); + } + } else { + umbraco.BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Debug, -1, "template not found"); + } + } + + + + private void splitDesignAndDirective(ref string design, ref string directive) { + if (design.StartsWith("<%@")) { + directive = design.Substring(0, design.IndexOf("%>") + 2).Trim(Environment.NewLine.ToCharArray()); + design = design.Substring(design.IndexOf("%>") + 3).Trim(Environment.NewLine.ToCharArray()); + } + } + + #endregion + + public XmlNode SampleXml() { + throw new NotImplementedException(); + } + + } + + public class removeStringFromTemplate : umbraco.interfaces.IPackageAction { + #region IPackageAction Members + + public bool Execute(string packageName, XmlNode xmlData) { + addStringToHtmlElement ast = new addStringToHtmlElement(); + return ast.Undo(packageName, xmlData); + } + + public string Alias() { + return "removeStringFromHtmlElement"; + } + + public bool Undo(string packageName, XmlNode xmlData) { + return true; + } + + public XmlNode SampleXml() { + throw new NotImplementedException(); + } + + #endregion + } + + + public class helper { + //Helper method to replace umbraco tags that breaks the xml format.. + public static string parseToValidXml(template.Template templateObj, ref bool hasAspNetContentBeginning, string template, bool toValid) { + string retVal = template; + if (toValid) { + // test for asp:content as the first part of the design + if (retVal.StartsWith("") + 1); + retVal = retVal.Substring(0, retVal.Length - 14); + } + //shorten empty macro tags.. + retVal = retVal.Replace(">", " />"); + retVal = retVal.Replace(">", " />"); + + retVal = retVal.Replace("", ""); + retVal = retVal.Replace("", ""); + retVal = retVal.Replace("", ""); + + // add asp content element + if (hasAspNetContentBeginning) { + retVal = templateObj.GetMasterContentElement(templateObj.MasterTemplate) + retVal + ""; + } + } + + return retVal; + } + + public static XmlNode parseStringToXmlNode(string value) { + XmlDocument doc = new XmlDocument(); + XmlNode node = xmlHelper.addTextNode(doc, "error", ""); + + try { + doc.LoadXml(value); + return doc.SelectSingleNode("."); + } catch { + return node; + } + + return node; + } + } +} diff --git a/umbraco/cms/businesslogic/Packager/PackageInstance/CreatedPackage.cs b/umbraco/cms/businesslogic/Packager/PackageInstance/CreatedPackage.cs new file mode 100644 index 0000000000..a10d60d02a --- /dev/null +++ b/umbraco/cms/businesslogic/Packager/PackageInstance/CreatedPackage.cs @@ -0,0 +1,314 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; +using System.Web; + +using umbraco.cms.businesslogic.template; +using umbraco.cms.businesslogic.web; +using umbraco.cms.businesslogic.macro; + + +namespace umbraco.cms.businesslogic.packager { + public class CreatedPackage { + + public static CreatedPackage GetById(int id) { + CreatedPackage pack = new CreatedPackage(); + pack.Data = data.Package(id, HttpContext.Current.Server.MapPath(Settings.CreatedPackagesSettings)); + return pack; + } + + public static CreatedPackage MakeNew(string name) { + CreatedPackage pack = new CreatedPackage(); + pack.Data = data.MakeNew(name, HttpContext.Current.Server.MapPath(Settings.CreatedPackagesSettings)); + + NewEventArgs e = new NewEventArgs(); + pack.OnNew(e); + + return pack; + } + + public void Save() { + SaveEventArgs e = new SaveEventArgs(); + FireBeforeSave(e); + + if (!e.Cancel) { + data.Save(this.Data, HttpContext.Current.Server.MapPath(Settings.CreatedPackagesSettings)); + FireAfterSave(e); + } + } + + public void Delete() { + DeleteEventArgs e = new DeleteEventArgs(); + FireBeforeDelete(e); + + if (!e.Cancel) { + data.Delete(this.Data.Id, HttpContext.Current.Server.MapPath(Settings.CreatedPackagesSettings)); + FireAfterDelete(e); + } + } + + private PackageInstance m_data; + public PackageInstance Data { + get { return m_data; } + set { m_data = value; } + } + + public static List GetAllCreatedPackages() { + List val = new List(); + + foreach (PackageInstance pack in data.GetAllPackages(HttpContext.Current.Server.MapPath(Settings.CreatedPackagesSettings))) { + CreatedPackage crPack = new CreatedPackage(); + crPack.Data = pack; + val.Add(crPack); + } + + return val; + } + + private static XmlDocument _packageManifest; + private static void createPackageManifest() { + _packageManifest = new XmlDocument(); + XmlDeclaration xmldecl = _packageManifest.CreateXmlDeclaration("1.0", "UTF-8", "no"); + + _packageManifest.AppendChild(xmldecl); + + //root node + XmlNode umbPackage = _packageManifest.CreateElement("umbPackage"); + _packageManifest.AppendChild(umbPackage); + //Files node + umbPackage.AppendChild(_packageManifest.CreateElement("files")); + } + + private static void appendElement(XmlNode node) { + XmlNode root = _packageManifest.SelectSingleNode("/umbPackage"); + root.AppendChild(node); + } + + + public void Publish() { + + CreatedPackage package = this; + PackageInstance pack = package.Data; + + try { + + PublishEventArgs e = new PublishEventArgs(); + package.FireBeforePublish(e); + + if (!e.Cancel) { + int outInt = 0; + + //Path checking... + string localPath = HttpContext.Current.Server.MapPath(Settings.PackagesStorage + "/" + pack.Folder); + + if (!System.IO.Directory.Exists(localPath)) + System.IO.Directory.CreateDirectory(localPath); + + //Init package file... + createPackageManifest(); + //Info section.. + appendElement(utill.PackageInfo(pack, _packageManifest)); + + //Documents... + int _contentNodeID = 0; + if (!String.IsNullOrEmpty(pack.ContentNodeId) && int.TryParse(pack.ContentNodeId, out _contentNodeID)) { + XmlNode documents = _packageManifest.CreateElement("Documents"); + + XmlNode documentSet = _packageManifest.CreateElement("DocumentSet"); + XmlAttribute importMode = _packageManifest.CreateAttribute("importMode", ""); + importMode.Value = "root"; + documentSet.Attributes.Append(importMode); + documents.AppendChild(documentSet); + + //load content from umbraco. + cms.businesslogic.web.Document umbDocument = new Document(_contentNodeID); + documentSet.AppendChild(umbDocument.ToXml(_packageManifest, pack.ContentLoadChildNodes)); + + appendElement(documents); + } + + //Document types.. + XmlNode docTypes = _packageManifest.CreateElement("DocumentTypes"); + foreach (string dtId in pack.Documenttypes) { + if (int.TryParse(dtId, out outInt)) { + DocumentType docT = new DocumentType(outInt); + docTypes.AppendChild(docT.ToXml(_packageManifest)); + } + } + appendElement(docTypes); + + //Templates + XmlNode templates = _packageManifest.CreateElement("Templates"); + foreach (string templateId in pack.Templates) { + if (int.TryParse(templateId, out outInt)) { + Template t = new Template(outInt); + templates.AppendChild(t.ToXml(_packageManifest)); + } + } + appendElement(templates); + + //Stylesheets + XmlNode stylesheets = _packageManifest.CreateElement("Stylesheets"); + foreach (string ssId in pack.Stylesheets) { + if (int.TryParse(ssId, out outInt)) { + StyleSheet s = new StyleSheet(outInt); + stylesheets.AppendChild(s.ToXml(_packageManifest)); + } + } + appendElement(stylesheets); + + //Macros + XmlNode macros = _packageManifest.CreateElement("Macros"); + foreach (string macroId in pack.Macros) { + if (int.TryParse(macroId, out outInt)) { + macros.AppendChild(utill.Macro(int.Parse(macroId), true, localPath, _packageManifest)); + } + } + appendElement(macros); + + //Dictionary Items + XmlNode dictionaryItems = _packageManifest.CreateElement("DictionaryItems"); + foreach (string dictionaryId in pack.DictionaryItems) { + if (int.TryParse(dictionaryId, out outInt)) { + Dictionary.DictionaryItem di = new Dictionary.DictionaryItem(outInt); + dictionaryItems.AppendChild(di.ToXml(_packageManifest)); + } + } + appendElement(dictionaryItems); + + //Languages + XmlNode languages = _packageManifest.CreateElement("Languages"); + foreach (string langId in pack.Languages) { + if (int.TryParse(langId, out outInt)) { + language.Language lang = new umbraco.cms.businesslogic.language.Language(outInt); + + languages.AppendChild(lang.ToXml(_packageManifest)); + } + } + appendElement(languages); + + //Datatypes + XmlNode dataTypes = _packageManifest.CreateElement("DataTypes"); + foreach (string dtId in pack.DataTypes) { + if (int.TryParse(dtId, out outInt)) { + cms.businesslogic.datatype.DataTypeDefinition dtd = new umbraco.cms.businesslogic.datatype.DataTypeDefinition(outInt); + dataTypes.AppendChild(dtd.ToXml(_packageManifest)); + } + } + appendElement(dataTypes); + + //Files + foreach (string fileName in pack.Files) { + utill.AppendFileToManifest(fileName, localPath, _packageManifest); + } + + //Load control on install... + if (!string.IsNullOrEmpty(pack.LoadControl)) { + XmlNode control = _packageManifest.CreateElement("control"); + control.InnerText = pack.LoadControl; + utill.AppendFileToManifest(pack.LoadControl, localPath, _packageManifest); + appendElement(control); + } + + //Actions + if (!string.IsNullOrEmpty(pack.Actions)) { + try { + XmlDocument xd_actions = new XmlDocument(); + xd_actions.LoadXml("" + pack.Actions + ""); + XmlNode actions = xd_actions.DocumentElement.SelectSingleNode("."); + + + if (actions != null) { + actions = _packageManifest.ImportNode(actions, true).Clone(); + appendElement(actions); + } + } catch { } + } + + string manifestFileName = localPath + "/package.xml"; + + if (System.IO.File.Exists(manifestFileName)) + System.IO.File.Delete(manifestFileName); + + _packageManifest.Save(manifestFileName); + _packageManifest = null; + + + string packPath = Settings.PackagerRoot.Replace(System.IO.Path.DirectorySeparatorChar.ToString(), "/") + "/" + pack.Name.Replace(' ', '_') + "_" + pack.Version.Replace(' ', '_') + "." + Settings.PackageFileExtension; + utill.ZipPackage(localPath, System.Web.HttpContext.Current.Server.MapPath(packPath)); + + pack.PackagePath = packPath; + + if (pack.PackageGuid.Trim() == "") + pack.PackageGuid = Guid.NewGuid().ToString(); + + package.Save(); + + //Clean up.. + System.IO.File.Delete(localPath + "/package.xml"); + System.IO.Directory.Delete(localPath, true); + + package.FireAfterPublish(e); + } + + } catch (Exception ex) { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, new BusinessLogic.User(0), -1, "CreatedPackage.cs " + ex.ToString()); + } + } + + + //EVENTS + public delegate void SaveEventHandler(CreatedPackage sender, SaveEventArgs e); + public delegate void NewEventHandler(CreatedPackage sender, NewEventArgs e); + public delegate void PublishEventHandler(CreatedPackage sender, PublishEventArgs e); + public delegate void DeleteEventHandler(CreatedPackage sender, DeleteEventArgs e); + + /// + /// Occurs when a macro is saved. + /// + public static event SaveEventHandler BeforeSave; + protected virtual void FireBeforeSave(SaveEventArgs e) { + if (BeforeSave != null) + BeforeSave(this, e); + } + + public static event SaveEventHandler AfterSave; + protected virtual void FireAfterSave(SaveEventArgs e) { + if (AfterSave != null) + AfterSave(this, e); + } + + public static event NewEventHandler New; + protected virtual void OnNew(NewEventArgs e) { + if (New != null) + New(this, e); + } + + public static event DeleteEventHandler BeforeDelete; + protected virtual void FireBeforeDelete(DeleteEventArgs e) { + if (BeforeDelete != null) + BeforeDelete(this, e); + } + + public static event DeleteEventHandler AfterDelete; + protected virtual void FireAfterDelete(DeleteEventArgs e) { + if (AfterDelete != null) + AfterDelete(this, e); + } + + public static event PublishEventHandler BeforePublish; + protected virtual void FireBeforePublish(PublishEventArgs e) { + if (BeforePublish != null) + BeforePublish(this, e); + } + + public static event PublishEventHandler AfterPublish; + protected virtual void FireAfterPublish(PublishEventArgs e) { + if (AfterPublish != null) + AfterPublish(this, e); + } + + + } +} diff --git a/umbraco/cms/businesslogic/Packager/PackageInstance/IPackageInstance.cs b/umbraco/cms/businesslogic/Packager/PackageInstance/IPackageInstance.cs new file mode 100644 index 0000000000..29e53339d6 --- /dev/null +++ b/umbraco/cms/businesslogic/Packager/PackageInstance/IPackageInstance.cs @@ -0,0 +1,28 @@ +using System; +namespace umbraco.cms.businesslogic.packager{ + public interface IPackageInstance { + string Actions { get; set; } + string Author { get; set; } + string AuthorUrl { get; set; } + bool ContentLoadChildNodes { get; set; } + string ContentNodeId { get; set; } + System.Collections.Generic.List Documenttypes { get; set; } + System.Collections.Generic.List Files { get; set; } + string Folder { get; set; } + bool HasUpdate { get; set; } + int Id { get; set; } + string License { get; set; } + string LicenseUrl { get; set; } + string LoadControl { get; set; } + System.Collections.Generic.List Macros { get; set; } + string Name { get; set; } + string PackageGuid { get; set; } + string PackagePath { get; set; } + string Readme { get; set; } + string RepositoryGuid { get; set; } + System.Collections.Generic.List Stylesheets { get; set; } + System.Collections.Generic.List Templates { get; set; } + string Url { get; set; } + string Version { get; set; } + } +} diff --git a/umbraco/cms/businesslogic/Packager/PackageInstance/InstalledPackage.cs b/umbraco/cms/businesslogic/Packager/PackageInstance/InstalledPackage.cs new file mode 100644 index 0000000000..d544d2ac53 --- /dev/null +++ b/umbraco/cms/businesslogic/Packager/PackageInstance/InstalledPackage.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web; + +namespace umbraco.cms.businesslogic.packager { + public class InstalledPackage { + + public static InstalledPackage GetById(int id) { + InstalledPackage pack = new InstalledPackage(); + pack.Data = data.Package(id, HttpContext.Current.Server.MapPath(Settings.InstalledPackagesSettings)); + return pack; + } + + public static InstalledPackage GetByGuid(string packageGuid) { + InstalledPackage pack = new InstalledPackage(); + pack.Data = data.Package(packageGuid, HttpContext.Current.Server.MapPath(Settings.InstalledPackagesSettings)); + return pack; + } + + public static InstalledPackage MakeNew(string name) { + InstalledPackage pack = new InstalledPackage(); + pack.Data = data.MakeNew(name, HttpContext.Current.Server.MapPath(Settings.InstalledPackagesSettings)); + pack.OnNew(EventArgs.Empty); + return pack; + } + + public void Save() { + this.FireBeforeSave(EventArgs.Empty); + data.Save(this.Data, HttpContext.Current.Server.MapPath(Settings.InstalledPackagesSettings)); + this.FireAfterSave(EventArgs.Empty); + } + + public static List GetAllInstalledPackages() { + + List val = new List(); + + foreach (PackageInstance pack in data.GetAllPackages(HttpContext.Current.Server.MapPath(Settings.InstalledPackagesSettings))) { + InstalledPackage insPackage = new InstalledPackage(); + insPackage.Data = pack; + val.Add(insPackage); + } + + return val; + } + + private PackageInstance m_data; + public PackageInstance Data { + get { return m_data; } + set { m_data = value; } + } + + + public void Delete() { + this.FireBeforeDelete(EventArgs.Empty); + data.Delete(this.Data.Id, HttpContext.Current.Server.MapPath(Settings.InstalledPackagesSettings)); + this.FireAfterDelete(EventArgs.Empty); + } + + public static bool isPackageInstalled(string packageGuid) { + try { + if (data.GetFromGuid(packageGuid, HttpContext.Current.Server.MapPath(Settings.InstalledPackagesSettings), true) == null) + return false; + else + return true; + } catch (Exception ex) { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, 0, ex.ToString()); + return false; + } + } + + //EVENTS + public delegate void SaveEventHandler(InstalledPackage sender, EventArgs e); + public delegate void NewEventHandler(InstalledPackage sender, EventArgs e); + public delegate void DeleteEventHandler(InstalledPackage sender, EventArgs e); + + /// + /// Occurs when a macro is saved. + /// + public static event SaveEventHandler BeforeSave; + protected virtual void FireBeforeSave(EventArgs e) { + if (BeforeSave != null) + BeforeSave(this, e); + } + + public static event SaveEventHandler AfterSave; + protected virtual void FireAfterSave(EventArgs e) { + if (AfterSave != null) + AfterSave(this, e); + } + + public static event NewEventHandler New; + protected virtual void OnNew(EventArgs e) { + if (New != null) + New(this, e); + } + + public static event DeleteEventHandler BeforeDelete; + protected virtual void FireBeforeDelete(EventArgs e) { + if (BeforeDelete != null) + BeforeDelete(this, e); + } + + public static event DeleteEventHandler AfterDelete; + protected virtual void FireAfterDelete(EventArgs e) { + if (AfterDelete != null) + AfterDelete(this, e); + } + } +} diff --git a/umbraco/cms/businesslogic/Packager/PackageInstance/PackageActions.cs b/umbraco/cms/businesslogic/Packager/PackageInstance/PackageActions.cs new file mode 100644 index 0000000000..1b93dae4be --- /dev/null +++ b/umbraco/cms/businesslogic/Packager/PackageInstance/PackageActions.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Web; +using System.Xml; + +using umbraco.BasePages; +using umbraco.BusinessLogic.Utils; +using umbraco.cms.businesslogic.web; +using umbraco.cms.businesslogic.workflow; +using umbraco.interfaces; + + +namespace umbraco.cms.businesslogic.packager { + + /// + /// Package actions are executed on packge install / uninstall. + /// + public class PackageAction { + private static readonly List _packageActions = new List(); + + /// + /// Initializes the class. + /// + static PackageAction(){ + RegisterPackageActions(); + } + + private static void RegisterPackageActions() + { + List types = TypeFinder.FindClassesOfType(true); + foreach (Type t in types) + { + IPackageAction typeInstance = Activator.CreateInstance(t) as IPackageAction; + if (typeInstance != null) + { + _packageActions.Add(typeInstance); + + if (HttpContext.Current != null) + HttpContext.Current.Trace.Write("registerPackageActions", " + Adding package action '" + typeInstance.Alias()); + } + } + } + + /// + /// Runs the package action with the specified action alias. + /// + /// Name of the package. + /// The action alias. + /// The action XML. + public static void RunPackageAction(string packageName, string actionAlias, System.Xml.XmlNode actionXml) { + + foreach (IPackageAction ipa in _packageActions) { + try { + if (ipa.Alias() == actionAlias) { + + ipa.Execute(packageName, actionXml); + } + } catch (Exception ipaExp) { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, BusinessLogic.User.GetUser(0), -1, string.Format("Error loading package action '{0}' for package {1}: {2}", + ipa.Alias(), packageName, ipaExp)); + } + } + } + + /// + /// Undos the package action with the specified action alias. + /// + /// Name of the package. + /// The action alias. + /// The action XML. + public static void UndoPackageAction(string packageName, string actionAlias, System.Xml.XmlNode actionXml) { + + foreach (IPackageAction ipa in _packageActions) { + try { + if (ipa.Alias() == actionAlias) { + + ipa.Undo(packageName, actionXml); + } + } catch (Exception ipaExp) { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, BusinessLogic.User.GetUser(0), -1, string.Format("Error undoing package action '{0}' for package {1}: {2}", + ipa.Alias(), packageName, ipaExp)); + } + } + } + + } +} diff --git a/umbraco/cms/businesslogic/Packager/PackageInstance/PackageInstance.cs b/umbraco/cms/businesslogic/Packager/PackageInstance/PackageInstance.cs new file mode 100644 index 0000000000..badfd3e366 --- /dev/null +++ b/umbraco/cms/businesslogic/Packager/PackageInstance/PackageInstance.cs @@ -0,0 +1,260 @@ +using System; + +using System.Xml; +using System.Xml.XPath; +using System.Collections.Generic; + +namespace umbraco.cms.businesslogic.packager +{ + public class PackageInstance + { + private int _id; + + private string _name = ""; + private string _url = ""; + private string _folder = ""; + private string _packagePath = ""; + private string _version = ""; + + private string _author = ""; + private string _authorUrl = ""; + + private string _license = ""; + private string _licenseUrl = ""; + + private string _readMe = ""; + + private bool _contentLoadChildNodes = false; + private string _contentNodeId = ""; + + private List _macros = new List(); + private List _templates = new List(); + private List _documentTypes = new List(); + private List _stylesheets = new List(); + private List _files = new List(); + private List _languages = new List(); + private List _dictionaryItems = new List(); + private List _dataTypes = new List(); + + private string _loadControl = ""; + private string _repoGuid; + private string _packageGuid; + private bool _hasUpdate; + private string _actions; + + public int Id + { + get { return _id; } + set {_id = value; } + } + + public String RepositoryGuid { + get { return _repoGuid; } + set { _repoGuid = value; } + } + + public String PackageGuid { + get { return _packageGuid; } + set { _packageGuid = value; } + } + + public bool HasUpdate { + get { return _hasUpdate; } + set { _hasUpdate = value; } + } + + public String Name + { + get { return _name; } + set + { + _name = value; + } + } + + public String Url + { + get { return _url; } + set + { + _url = value; + } + } + + public String Folder + { + get { return _folder; } + set + { + _folder = value; + } + } + + public String PackagePath + { + get { return _packagePath; } + set + { + _packagePath = value; + } + } + + public String Version + { + get { return _version; } + set + { + _version = value; + } + } + + public String Author + { + get { return _author; } + set + { + _author = value; + } + } + + public String AuthorUrl + { + get { return _authorUrl; } + set + { + _authorUrl = value; + } + } + + + public String License + { + get { return _license; } + set + { + _license = value; + } + } + + public String LicenseUrl + { + get { return _licenseUrl; } + set + { + _licenseUrl = value; + } + } + + public String Readme + { + get { return _readMe ; } + set + { + _readMe = value; + } + } + + public bool ContentLoadChildNodes + { + get { return _contentLoadChildNodes; } + set + { + _contentLoadChildNodes = value; + } + } + public string ContentNodeId + { + get { return _contentNodeId; } + set + { + _contentNodeId = value; + } + } + + public List Macros + { + get { return _macros; } + set + { + _macros = value; + } + } + + public List Languages { + get { return _languages; } + set { + _languages = value; + } + } + + public List DictionaryItems { + get { return _dictionaryItems; } + set { + _dictionaryItems = value; + } + } + + public List Templates + { + get { return _templates; } + set + { + _templates = value; + } + } + + public List Documenttypes + { + get { return _documentTypes; } + set + { + _documentTypes = value; + } + } + + public List Stylesheets + { + get { return _stylesheets; } + set + { + _stylesheets = value; + } + } + + public List Files + { + get { return _files; } + set + { + _files = value; + } + } + + public String LoadControl + { + get { return _loadControl; } + set + { + _loadControl = value; + } + } + + public String Actions + { + get { return _actions; } + set + { + _actions = value; + } + } + + public List DataTypes { + get { return _dataTypes; } + set { + _dataTypes = value; + } + } + + public PackageInstance() {} + } +} diff --git a/umbraco/cms/businesslogic/Packager/PackageInstance/utill.cs b/umbraco/cms/businesslogic/Packager/PackageInstance/utill.cs new file mode 100644 index 0000000000..14c9091efd --- /dev/null +++ b/umbraco/cms/businesslogic/Packager/PackageInstance/utill.cs @@ -0,0 +1,322 @@ +using System; +using System.Data; +using System.Collections; +using System.Collections.Generic; + +using System.Configuration; +using System.Web; +using System.Web.Security; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.WebControls.WebParts; +using System.Web.UI.HtmlControls; + +using System.IO; +using System.Xml; + +using umbraco.cms.businesslogic.template; +using umbraco.cms.businesslogic.web; +using umbraco.cms.businesslogic.macro; +using ICSharpCode.SharpZipLib.Zip; + +namespace umbraco.cms.businesslogic.packager { + /// + /// A utillity class for working with packager data. + /// It provides basic methods for adding new items to a package manifest, moving files and other misc. + /// + public class utill { + + /// + /// Creates a package manifest containing name, license, version and other meta data. + /// + /// The packinstance. + /// The xml document. + /// + public static XmlNode PackageInfo(PackageInstance pack, XmlDocument doc) { + + XmlNode info = doc.CreateElement("info"); + + //Package info + XmlNode package = doc.CreateElement("package"); + package.AppendChild(_node("name", pack.Name, doc)); + package.AppendChild(_node("version", pack.Version, doc)); + + XmlNode license = _node("license", pack.License, doc); + license.Attributes.Append(_attribute("url", pack.LicenseUrl, doc)); + package.AppendChild(license); + + package.AppendChild(_node("url", pack.Url, doc)); + + XmlNode Requirements = doc.CreateElement("requirements"); + Requirements.AppendChild(_node("major", "3", doc)); + Requirements.AppendChild(_node("minor", "0", doc)); + Requirements.AppendChild(_node("patch", "0", doc)); + package.AppendChild(Requirements); + info.AppendChild(package); + + //Author + XmlNode author = _node("author", "", doc); + author.AppendChild(_node("name", pack.Author, doc)); + author.AppendChild(_node("website", pack.AuthorUrl, doc)); + info.AppendChild(author); + + info.AppendChild(_node("readme", "", doc)); + + return info; + } + + + /// + /// Converts an umbraco template to a package xml node + /// + /// The template id. + /// The xml doc. + /// + public static XmlNode Template(int templateId, XmlDocument doc) { + + Template tmpl = new Template(templateId); + + XmlNode template = doc.CreateElement("Template"); + template.AppendChild(_node("Name", tmpl.Text, doc)); + template.AppendChild(_node("Alias", tmpl.Alias, doc)); + + if (tmpl.MasterTemplate != null && tmpl.MasterTemplate != 0) { + template.AppendChild(_node("Master", new Template(tmpl.MasterTemplate).Alias, doc)); + } + template.AppendChild(_node("Design", "", doc)); + + return template; + } + + + /// + /// Converts a umbraco stylesheet to a package xml node + /// + /// The ss id. + /// if set to true [incluce properties]. + /// The doc. + /// + public static XmlNode Stylesheet(int ssId, bool incluceProperties, XmlDocument doc) { + + StyleSheet sts = new StyleSheet(ssId); + XmlNode stylesheet = doc.CreateElement("Stylesheet"); + stylesheet.AppendChild(_node("Name", sts.Text, doc)); + stylesheet.AppendChild(_node("FileName", sts.Filename, doc)); + stylesheet.AppendChild(_node("Content", "", doc)); + if (incluceProperties) { + XmlNode properties = doc.CreateElement("Properties"); + foreach (StylesheetProperty ssP in sts.Properties) { + XmlNode property = doc.CreateElement("Property"); + property.AppendChild(_node("Name", ssP.Text, doc)); + property.AppendChild(_node("Alias", ssP.Alias, doc)); + property.AppendChild(_node("Value", ssP.value, doc)); + + //xnode += "" + ssP.Text + "" + ssP.Alias + "" + ssP.value + "\n"; + } + stylesheet.AppendChild(properties); + } + return stylesheet; + } + + + /// + /// Converts a macro to a package xml node + /// + /// The macro id. + /// if set to true [append file]. + /// The package directory. + /// The doc. + /// + public static XmlNode Macro(int macroId, bool appendFile, string packageDirectory, XmlDocument doc) { + + Macro mcr = new Macro(macroId); + + if (appendFile) { + if (!string.IsNullOrEmpty(mcr.Xslt)) + AppendFileToManifest("/xslt/" + mcr.Xslt, packageDirectory, doc); + + if (!string.IsNullOrEmpty(mcr.Type)) + AppendFileToManifest(mcr.Type, packageDirectory, doc); + } + + return mcr.ToXml(doc); + } + + + /// + /// Appends a file to package manifest and copies the file to the correct folder. + /// + /// The path. + /// The package directory. + /// The doc. + public static void AppendFileToManifest(string path, string packageDirectory, XmlDocument doc) { + string serverPath = HttpContext.Current.Server.MapPath(path); + + if (System.IO.File.Exists(serverPath)) { + + AppendFileXml(path, packageDirectory, doc); + + } else if(System.IO.Directory.Exists(serverPath)){ + + ProcessDirectory(path, packageDirectory, doc); + } + } + + + + //Process files in directory and add them to package + private static void ProcessDirectory(string path, string packageDirectory, XmlDocument doc) { + string serverPath = HttpContext.Current.Server.MapPath(path); + if (System.IO.Directory.Exists(serverPath)) { + + System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(serverPath); + + foreach (System.IO.FileInfo file in di.GetFiles()) { + AppendFileXml(path + "/" + file.Name, packageDirectory, doc); + } + + foreach (System.IO.DirectoryInfo dir in di.GetDirectories()) { + ProcessDirectory(path + "/" + dir.Name, packageDirectory, doc); + } + } + } + + private static void AppendFileXml(string path, string packageDirectory, XmlDocument doc) { + + string serverPath = HttpContext.Current.Server.MapPath(path); + + string orgPath = path.Substring(0, (path.LastIndexOf('/'))); + string orgName = path.Substring((path.LastIndexOf('/') + 1)); + string newFileName = orgName; + + if (System.IO.File.Exists(packageDirectory + "/" + orgName)) { + string fileGuid = System.Guid.NewGuid().ToString(); + newFileName = fileGuid + "_" + newFileName; + } + + //Copy file to directory for zipping... + System.IO.File.Copy(serverPath, packageDirectory + "/" + newFileName, true); + + //Append file info to files xml node + XmlNode files = doc.SelectSingleNode("/umbPackage/files"); + + XmlNode file = doc.CreateElement("file"); + file.AppendChild(_node("guid", newFileName, doc)); + file.AppendChild(_node("orgPath", orgPath, doc)); + file.AppendChild(_node("orgName", orgName, doc)); + + files.AppendChild(file); + } + + /// + /// Determines whether the file is in the package manifest + /// + /// The GUID. + /// The doc. + /// + /// true if [is file in manifest]; otherwise, false. + /// + public static bool IsFileInManifest(string guid, XmlDocument doc) { + return false; + } + + private static XmlNode _node(string name, string value, XmlDocument doc) { + XmlNode node = doc.CreateElement(name); + node.InnerXml = value; + return node; + } + + private static XmlAttribute _attribute(string name, string value, XmlDocument doc) { + XmlAttribute attribute = doc.CreateAttribute(name); + attribute.Value = value; + return attribute; + } + + /// + /// Zips the package. + /// + /// The path. + /// The save path. + public static void ZipPackage(string Path, string savePath) { + string OutPath = savePath; + + ArrayList ar = GenerateFileList(Path); + // generate file list + // find number of chars to remove from orginal file path + int TrimLength = (Directory.GetParent(Path)).ToString().Length; + + TrimLength += 1; + + //remove '\' + FileStream ostream; + + byte[] obuffer; + + ZipOutputStream oZipStream = new ZipOutputStream(System.IO.File.Create(OutPath)); + // create zip stream + + + oZipStream.SetLevel(9); + // 9 = maximum compression level + ZipEntry oZipEntry; + + foreach (string Fil in ar) // for each file, generate a zipentry + { + oZipEntry = new ZipEntry(Fil.Remove(0, TrimLength)); + oZipStream.PutNextEntry(oZipEntry); + + + if (!Fil.EndsWith(@"/")) // if a file ends with '/' its a directory + { + ostream = File.OpenRead(Fil); + + obuffer = new byte[ostream.Length]; + + // byte buffer + ostream.Read(obuffer, 0, obuffer.Length); + + oZipStream.Write(obuffer, 0, obuffer.Length); + ostream.Close(); + } + } + oZipStream.Finish(); + oZipStream.Close(); + oZipStream.Dispose(); + oZipStream = null; + + oZipEntry = null; + + + ostream = null; + ar.Clear(); + ar = null; + } + + private static ArrayList GenerateFileList(string Dir) { + ArrayList mid = new ArrayList(); + + bool Empty = true; + + foreach (string file in Directory.GetFiles(Dir)) // add each file in directory + { + mid.Add(file); + Empty = false; + } + + if (Empty) { + if (Directory.GetDirectories(Dir).Length == 0) // if directory is completely empty, add it + { + mid.Add(Dir + @"/"); + } + } + + foreach (string dirs in Directory.GetDirectories(Dir)) // do this recursively + { + foreach (object obj in GenerateFileList(dirs)) { + mid.Add(obj); + } + } + return mid; // return file list + } + } +} diff --git a/umbraco/cms/businesslogic/Packager/Repositories/Repository.cs b/umbraco/cms/businesslogic/Packager/Repositories/Repository.cs new file mode 100644 index 0000000000..602957f334 --- /dev/null +++ b/umbraco/cms/businesslogic/Packager/Repositories/Repository.cs @@ -0,0 +1,215 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Xml; +using System.IO; +using System.Net; + +namespace umbraco.cms.businesslogic.packager.repositories { + public class Repository { + + private string m_guid; + private string m_name; + + //this is our standard urls. + private string m_repositoryUrl = "http://packages.umbraco.org"; + private string m_webserviceUrl = "/umbraco/webservices/api/repository.asmx"; + + + private static XmlNode m_repositories = UmbracoSettings.Repositories; + + public string Guid { + get { return m_guid; } + } + + public string Name { + get { return m_name; } + } + + public string RepositoryUrl { + get { return m_repositoryUrl; } + } + + public string WebserviceUrl { + get { return m_webserviceUrl; } + } + + + public RepositoryWebservice Webservice { + get { + + if (!m_webserviceUrl.Contains("://")) { + m_webserviceUrl = m_repositoryUrl.Trim('/') + "/" + m_webserviceUrl.Trim('/'); + } + + RepositoryWebservice repo = new RepositoryWebservice(m_webserviceUrl); + return repo; + } + } + + public SubmitStatus SubmitPackage(string authorGuid, PackageInstance package, byte[] doc) { + + string packageName = package.Name; + string packageGuid = package.PackageGuid; + string description = package.Readme; + string packageFile = package.PackagePath; + + + System.IO.FileStream fs1 = null; + + try { + + byte[] pack = new byte[0]; + fs1 = System.IO.File.Open(System.Web.HttpContext.Current.Server.MapPath(packageFile), FileMode.Open, FileAccess.Read); + pack = new byte[fs1.Length]; + fs1.Read(pack, 0, (int)fs1.Length); + fs1.Close(); + fs1 = null; + + byte[] thumb = new byte[0]; //todo upload thumbnail... + + return Webservice.SubmitPackage(m_guid, authorGuid, packageGuid, pack, doc, thumb, packageName, "", "", description); + } catch (Exception ex) { + umbraco.BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Debug, -1, ex.ToString()); + + return SubmitStatus.Error; + } + } + + public static List getAll() { + + List repositories = new List(); + + XmlNodeList repositoriesXml = m_repositories.SelectNodes("./repository"); + + foreach (XmlNode repositoryXml in repositoriesXml) { + Repository repository = new Repository(); + repository.m_guid = repositoryXml.Attributes["guid"].Value; + repository.m_name = repositoryXml.Attributes["name"].Value; + + if (repositoryXml.Attributes["repositoryurl"] != null) { + repository.m_repositoryUrl = repositoryXml.Attributes["repositoryurl"].Value; + repository.m_webserviceUrl = repository.m_repositoryUrl.Trim('/') + "/" + repository.m_webserviceUrl.Trim('/'); + } + + if (repositoryXml.Attributes["webserviceurl"] != null) { + string wsUrl = repositoryXml.Attributes["webserviceurl"].Value; + + if (wsUrl.Contains("://")) { + repository.m_webserviceUrl = repositoryXml.Attributes["webserviceurl"].Value; + } else { + repository.m_webserviceUrl = repository.m_repositoryUrl.Trim('/') + "/" + wsUrl.Trim('/'); + } + } + + repositories.Add(repository); + } + + return repositories; + } + + public static Repository getByGuid(string repositoryGuid) { + Repository repository = new Repository(); + + XmlNode repositoryXml = m_repositories.SelectSingleNode("./repository [@guid = '" + repositoryGuid + "']"); + if (repositoryXml != null) { + repository.m_guid = repositoryXml.Attributes["guid"].Value; + repository.m_name = repositoryXml.Attributes["name"].Value; + + if (repositoryXml.Attributes["repositoryurl"] != null) { + repository.m_repositoryUrl = repositoryXml.Attributes["repositoryurl"].Value; + repository.m_webserviceUrl = repository.m_repositoryUrl.Trim('/') + "/" + repository.m_webserviceUrl.Trim('/'); + } + + if (repositoryXml.Attributes["webserviceurl"] != null) { + string wsUrl = repositoryXml.Attributes["webserviceurl"].Value; + + if (wsUrl.Contains("://")) { + repository.m_webserviceUrl = repositoryXml.Attributes["webserviceurl"].Value; + } else { + repository.m_webserviceUrl = repository.m_repositoryUrl.Trim('/') + "/" + wsUrl.Trim('/'); + } + } + } + + return repository; + } + + //shortcut method to download pack from repo and place it on the server... + public string fetch(string packageGuid) { + + return fetch(packageGuid, string.Empty); + + } + + public bool HasConnection() { + + string strServer = this.RepositoryUrl; + + try { + + HttpWebRequest reqFP = (HttpWebRequest)HttpWebRequest.Create(strServer); + HttpWebResponse rspFP = (HttpWebResponse)reqFP.GetResponse(); + + if (HttpStatusCode.OK == rspFP.StatusCode) { + + // HTTP = 200 - Internet connection available, server online + rspFP.Close(); + + return true; + + } else { + + // Other status - Server or connection not available + + rspFP.Close(); + + return false; + + } + + } catch (WebException) { + + // Exception - connection not available + + return false; + + } + } + + public string fetch(string packageGuid, string key) { + + byte[] fileByteArray = new byte[0]; + + if (key == string.Empty) { + fileByteArray = this.Webservice.fetchPackage(packageGuid); + } else { + fileByteArray = this.Webservice.fetchProtectedPackage(packageGuid, key); + } + + //successfull + if (fileByteArray.Length > 0) { + + // Check for package directory + if (!System.IO.Directory.Exists(System.Web.HttpContext.Current.Server.MapPath(packager.Settings.PackagerRoot))) + System.IO.Directory.CreateDirectory(System.Web.HttpContext.Current.Server.MapPath(packager.Settings.PackagerRoot)); + + + System.IO.FileStream fs1 = null; + fs1 = new FileStream(System.Web.HttpContext.Current.Server.MapPath(packager.Settings.PackagerRoot + System.IO.Path.DirectorySeparatorChar.ToString() + packageGuid + ".umb"), FileMode.Create); + fs1.Write(fileByteArray, 0, fileByteArray.Length); + fs1.Close(); + fs1 = null; + + return "packages\\" + packageGuid + ".umb"; + + } else { + + return ""; + } + } + + + + } +} diff --git a/umbraco/cms/businesslogic/Packager/Repositories/RepositoryWebservice.cs b/umbraco/cms/businesslogic/Packager/Repositories/RepositoryWebservice.cs new file mode 100644 index 0000000000..ccb464fc42 --- /dev/null +++ b/umbraco/cms/businesslogic/Packager/Repositories/RepositoryWebservice.cs @@ -0,0 +1,891 @@ +using System; +using System.ComponentModel; +using System.Diagnostics; +using System.Web.Services; +using System.Web.Services.Protocols; +using System.Xml.Serialization; + +namespace umbraco.cms.businesslogic.packager.repositories { + + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Web.Services.WebServiceBindingAttribute(Name = "RepositorySoap", Namespace = "http://packages.umbraco.org/webservices/")] + public partial class RepositoryWebservice : System.Web.Services.Protocols.SoapHttpClientProtocol { + + private System.Threading.SendOrPostCallback CategoriesOperationCompleted; + private System.Threading.SendOrPostCallback NitrosOperationCompleted; + private System.Threading.SendOrPostCallback NitrosCategorizedOperationCompleted; + private System.Threading.SendOrPostCallback authenticateOperationCompleted; + private System.Threading.SendOrPostCallback fetchPackageOperationCompleted; + private System.Threading.SendOrPostCallback fetchProtectedPackageOperationCompleted; + private System.Threading.SendOrPostCallback SubmitPackageOperationCompleted; + private System.Threading.SendOrPostCallback PackageByGuidOperationCompleted; + + /// + public RepositoryWebservice(string url) { + this.Url = url; //"http://packages.umbraco.org/umbraco/webservices/api/repository.asmx"; + } + + /// + public event CategoriesCompletedEventHandler CategoriesCompleted; + + /// + public event NitrosCompletedEventHandler NitrosCompleted; + + /// + public event NitrosCategorizedCompletedEventHandler NitrosCategorizedCompleted; + + /// + public event authenticateCompletedEventHandler authenticateCompleted; + + /// + public event fetchPackageCompletedEventHandler fetchPackageCompleted; + + /// + public event fetchProtectedPackageCompletedEventHandler fetchProtectedPackageCompleted; + + /// + public event SubmitPackageCompletedEventHandler SubmitPackageCompleted; + + /// + public event PackageByGuidCompletedEventHandler PackageByGuidCompleted; + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://packages.umbraco.org/webservices/Categories", RequestNamespace = "http://packages.umbraco.org/webservices/", ResponseNamespace = "http://packages.umbraco.org/webservices/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public Category[] Categories(string repositoryGuid) { + object[] results = this.Invoke("Categories", new object[] { + repositoryGuid}); + return ((Category[])(results[0])); + } + + /// + public System.IAsyncResult BeginCategories(string repositoryGuid, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("Categories", new object[] { + repositoryGuid}, callback, asyncState); + } + + /// + public Category[] EndCategories(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((Category[])(results[0])); + } + + /// + public void CategoriesAsync(string repositoryGuid) { + this.CategoriesAsync(repositoryGuid, null); + } + + /// + public void CategoriesAsync(string repositoryGuid, object userState) { + if ((this.CategoriesOperationCompleted == null)) { + this.CategoriesOperationCompleted = new System.Threading.SendOrPostCallback(this.OnCategoriesOperationCompleted); + } + this.InvokeAsync("Categories", new object[] { + repositoryGuid}, this.CategoriesOperationCompleted, userState); + } + + private void OnCategoriesOperationCompleted(object arg) { + if ((this.CategoriesCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.CategoriesCompleted(this, new CategoriesCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://packages.umbraco.org/webservices/Nitros", RequestNamespace = "http://packages.umbraco.org/webservices/", ResponseNamespace = "http://packages.umbraco.org/webservices/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public Package[] Nitros() { + object[] results = this.Invoke("Nitros", new object[0]); + return ((Package[])(results[0])); + } + + /// + public System.IAsyncResult BeginNitros(System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("Nitros", new object[0], callback, asyncState); + } + + /// + public Package[] EndNitros(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((Package[])(results[0])); + } + + /// + public void NitrosAsync() { + this.NitrosAsync(null); + } + + /// + public void NitrosAsync(object userState) { + if ((this.NitrosOperationCompleted == null)) { + this.NitrosOperationCompleted = new System.Threading.SendOrPostCallback(this.OnNitrosOperationCompleted); + } + this.InvokeAsync("Nitros", new object[0], this.NitrosOperationCompleted, userState); + } + + private void OnNitrosOperationCompleted(object arg) { + if ((this.NitrosCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.NitrosCompleted(this, new NitrosCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://packages.umbraco.org/webservices/NitrosCategorized", RequestNamespace = "http://packages.umbraco.org/webservices/", ResponseNamespace = "http://packages.umbraco.org/webservices/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public Category[] NitrosCategorized() { + object[] results = this.Invoke("NitrosCategorized", new object[0]); + return ((Category[])(results[0])); + } + + /// + public System.IAsyncResult BeginNitrosCategorized(System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("NitrosCategorized", new object[0], callback, asyncState); + } + + /// + public Category[] EndNitrosCategorized(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((Category[])(results[0])); + } + + /// + public void NitrosCategorizedAsync() { + this.NitrosCategorizedAsync(null); + } + + /// + public void NitrosCategorizedAsync(object userState) { + if ((this.NitrosCategorizedOperationCompleted == null)) { + this.NitrosCategorizedOperationCompleted = new System.Threading.SendOrPostCallback(this.OnNitrosCategorizedOperationCompleted); + } + this.InvokeAsync("NitrosCategorized", new object[0], this.NitrosCategorizedOperationCompleted, userState); + } + + private void OnNitrosCategorizedOperationCompleted(object arg) { + if ((this.NitrosCategorizedCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.NitrosCategorizedCompleted(this, new NitrosCategorizedCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://packages.umbraco.org/webservices/authenticate", RequestNamespace = "http://packages.umbraco.org/webservices/", ResponseNamespace = "http://packages.umbraco.org/webservices/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public string authenticate(string email, string md5Password) { + object[] results = this.Invoke("authenticate", new object[] { + email, + md5Password}); + return ((string)(results[0])); + } + + /// + public System.IAsyncResult Beginauthenticate(string email, string md5Password, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("authenticate", new object[] { + email, + md5Password}, callback, asyncState); + } + + /// + public string Endauthenticate(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((string)(results[0])); + } + + /// + public void authenticateAsync(string email, string md5Password) { + this.authenticateAsync(email, md5Password, null); + } + + /// + public void authenticateAsync(string email, string md5Password, object userState) { + if ((this.authenticateOperationCompleted == null)) { + this.authenticateOperationCompleted = new System.Threading.SendOrPostCallback(this.OnauthenticateOperationCompleted); + } + this.InvokeAsync("authenticate", new object[] { + email, + md5Password}, this.authenticateOperationCompleted, userState); + } + + private void OnauthenticateOperationCompleted(object arg) { + if ((this.authenticateCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.authenticateCompleted(this, new authenticateCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://packages.umbraco.org/webservices/fetchPackage", RequestNamespace = "http://packages.umbraco.org/webservices/", ResponseNamespace = "http://packages.umbraco.org/webservices/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + [return: System.Xml.Serialization.XmlElementAttribute(DataType = "base64Binary")] + public byte[] fetchPackage(string packageGuid) { + object[] results = this.Invoke("fetchPackage", new object[] { + packageGuid}); + return ((byte[])(results[0])); + } + + /// + public System.IAsyncResult BeginfetchPackage(string packageGuid, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("fetchPackage", new object[] { + packageGuid}, callback, asyncState); + } + + /// + public byte[] EndfetchPackage(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((byte[])(results[0])); + } + + /// + public void fetchPackageAsync(string packageGuid) { + this.fetchPackageAsync(packageGuid, null); + } + + /// + public void fetchPackageAsync(string packageGuid, object userState) { + if ((this.fetchPackageOperationCompleted == null)) { + this.fetchPackageOperationCompleted = new System.Threading.SendOrPostCallback(this.OnfetchPackageOperationCompleted); + } + this.InvokeAsync("fetchPackage", new object[] { + packageGuid}, this.fetchPackageOperationCompleted, userState); + } + + private void OnfetchPackageOperationCompleted(object arg) { + if ((this.fetchPackageCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.fetchPackageCompleted(this, new fetchPackageCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://packages.umbraco.org/webservices/fetchProtectedPackage", RequestNamespace = "http://packages.umbraco.org/webservices/", ResponseNamespace = "http://packages.umbraco.org/webservices/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + [return: System.Xml.Serialization.XmlElementAttribute(DataType = "base64Binary")] + public byte[] fetchProtectedPackage(string packageGuid, string memberKey) { + object[] results = this.Invoke("fetchProtectedPackage", new object[] { + packageGuid, + memberKey}); + return ((byte[])(results[0])); + } + + /// + public System.IAsyncResult BeginfetchProtectedPackage(string packageGuid, string memberKey, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("fetchProtectedPackage", new object[] { + packageGuid, + memberKey}, callback, asyncState); + } + + /// + public byte[] EndfetchProtectedPackage(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((byte[])(results[0])); + } + + /// + public void fetchProtectedPackageAsync(string packageGuid, string memberKey) { + this.fetchProtectedPackageAsync(packageGuid, memberKey, null); + } + + /// + public void fetchProtectedPackageAsync(string packageGuid, string memberKey, object userState) { + if ((this.fetchProtectedPackageOperationCompleted == null)) { + this.fetchProtectedPackageOperationCompleted = new System.Threading.SendOrPostCallback(this.OnfetchProtectedPackageOperationCompleted); + } + this.InvokeAsync("fetchProtectedPackage", new object[] { + packageGuid, + memberKey}, this.fetchProtectedPackageOperationCompleted, userState); + } + + private void OnfetchProtectedPackageOperationCompleted(object arg) { + if ((this.fetchProtectedPackageCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.fetchProtectedPackageCompleted(this, new fetchProtectedPackageCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://packages.umbraco.org/webservices/SubmitPackage", RequestNamespace = "http://packages.umbraco.org/webservices/", ResponseNamespace = "http://packages.umbraco.org/webservices/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public SubmitStatus SubmitPackage(string repositoryGuid, string authorGuid, string packageGuid, [System.Xml.Serialization.XmlElementAttribute(DataType = "base64Binary")] byte[] packageFile, [System.Xml.Serialization.XmlElementAttribute(DataType = "base64Binary")] byte[] packageDoc, [System.Xml.Serialization.XmlElementAttribute(DataType = "base64Binary")] byte[] packageThumbnail, string name, string author, string authorUrl, string description) { + object[] results = this.Invoke("SubmitPackage", new object[] { + repositoryGuid, + authorGuid, + packageGuid, + packageFile, + packageDoc, + packageThumbnail, + name, + author, + authorUrl, + description}); + return ((SubmitStatus)(results[0])); + } + + /// + public System.IAsyncResult BeginSubmitPackage(string repositoryGuid, string authorGuid, string packageGuid, byte[] packageFile, byte[] packageDoc, byte[] packageThumbnail, string name, string author, string authorUrl, string description, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("SubmitPackage", new object[] { + repositoryGuid, + authorGuid, + packageGuid, + packageFile, + packageDoc, + packageThumbnail, + name, + author, + authorUrl, + description}, callback, asyncState); + } + + /// + public SubmitStatus EndSubmitPackage(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((SubmitStatus)(results[0])); + } + + /// + public void SubmitPackageAsync(string repositoryGuid, string authorGuid, string packageGuid, byte[] packageFile, byte[] packageDoc, byte[] packageThumbnail, string name, string author, string authorUrl, string description) { + this.SubmitPackageAsync(repositoryGuid, authorGuid, packageGuid, packageFile, packageDoc, packageThumbnail, name, author, authorUrl, description, null); + } + + /// + public void SubmitPackageAsync(string repositoryGuid, string authorGuid, string packageGuid, byte[] packageFile, byte[] packageDoc, byte[] packageThumbnail, string name, string author, string authorUrl, string description, object userState) { + if ((this.SubmitPackageOperationCompleted == null)) { + this.SubmitPackageOperationCompleted = new System.Threading.SendOrPostCallback(this.OnSubmitPackageOperationCompleted); + } + this.InvokeAsync("SubmitPackage", new object[] { + repositoryGuid, + authorGuid, + packageGuid, + packageFile, + packageDoc, + packageThumbnail, + name, + author, + authorUrl, + description}, this.SubmitPackageOperationCompleted, userState); + } + + private void OnSubmitPackageOperationCompleted(object arg) { + if ((this.SubmitPackageCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.SubmitPackageCompleted(this, new SubmitPackageCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://packages.umbraco.org/webservices/PackageByGuid", RequestNamespace = "http://packages.umbraco.org/webservices/", ResponseNamespace = "http://packages.umbraco.org/webservices/", Use = System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle = System.Web.Services.Protocols.SoapParameterStyle.Wrapped)] + public Package PackageByGuid(string packageGuid) { + object[] results = this.Invoke("PackageByGuid", new object[] { + packageGuid}); + return ((Package)(results[0])); + } + + /// + public System.IAsyncResult BeginPackageByGuid(string packageGuid, System.AsyncCallback callback, object asyncState) { + return this.BeginInvoke("PackageByGuid", new object[] { + packageGuid}, callback, asyncState); + } + + /// + public Package EndPackageByGuid(System.IAsyncResult asyncResult) { + object[] results = this.EndInvoke(asyncResult); + return ((Package)(results[0])); + } + + /// + public void PackageByGuidAsync(string packageGuid) { + this.PackageByGuidAsync(packageGuid, null); + } + + /// + public void PackageByGuidAsync(string packageGuid, object userState) { + if ((this.PackageByGuidOperationCompleted == null)) { + this.PackageByGuidOperationCompleted = new System.Threading.SendOrPostCallback(this.OnPackageByGuidOperationCompleted); + } + this.InvokeAsync("PackageByGuid", new object[] { + packageGuid}, this.PackageByGuidOperationCompleted, userState); + } + + private void OnPackageByGuidOperationCompleted(object arg) { + if ((this.PackageByGuidCompleted != null)) { + System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg)); + this.PackageByGuidCompleted(this, new PackageByGuidCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState)); + } + } + + /// + public new void CancelAsync(object userState) { + base.CancelAsync(userState); + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://packages.umbraco.org/webservices/")] + public partial class Category { + + private string textField; + + private string descriptionField; + + private string urlField; + + private int idField; + + private Package[] packagesField; + + /// + public string Text { + get { + return this.textField; + } + set { + this.textField = value; + } + } + + /// + public string Description { + get { + return this.descriptionField; + } + set { + this.descriptionField = value; + } + } + + /// + public string Url { + get { + return this.urlField; + } + set { + this.urlField = value; + } + } + + /// + public int Id { + get { + return this.idField; + } + set { + this.idField = value; + } + } + + /// + public Package[] Packages { + get { + return this.packagesField; + } + set { + this.packagesField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://packages.umbraco.org/webservices/")] + public partial class Package { + + private System.Guid repoGuidField; + + private string textField; + + private string descriptionField; + + private string iconField; + + private string thumbnailField; + + private string documentationField; + + private string demoField; + + private bool acceptedField; + + private bool editorsPickField; + + private bool protectedField; + + private bool hasUpgradeField; + + private string upgradeVersionField; + + private string upgradeReadMeField; + + private string urlField; + + /// + public System.Guid RepoGuid { + get { + return this.repoGuidField; + } + set { + this.repoGuidField = value; + } + } + + /// + public string Text { + get { + return this.textField; + } + set { + this.textField = value; + } + } + + /// + public string Description { + get { + return this.descriptionField; + } + set { + this.descriptionField = value; + } + } + + /// + public string Icon { + get { + return this.iconField; + } + set { + this.iconField = value; + } + } + + /// + public string Thumbnail { + get { + return this.thumbnailField; + } + set { + this.thumbnailField = value; + } + } + + /// + public string Documentation { + get { + return this.documentationField; + } + set { + this.documentationField = value; + } + } + + /// + public string Demo { + get { + return this.demoField; + } + set { + this.demoField = value; + } + } + + /// + public bool Accepted { + get { + return this.acceptedField; + } + set { + this.acceptedField = value; + } + } + + /// + public bool EditorsPick { + get { + return this.editorsPickField; + } + set { + this.editorsPickField = value; + } + } + + /// + public bool Protected { + get { + return this.protectedField; + } + set { + this.protectedField = value; + } + } + + /// + public bool HasUpgrade { + get { + return this.hasUpgradeField; + } + set { + this.hasUpgradeField = value; + } + } + + /// + public string UpgradeVersion { + get { + return this.upgradeVersionField; + } + set { + this.upgradeVersionField = value; + } + } + + /// + public string UpgradeReadMe { + get { + return this.upgradeReadMeField; + } + set { + this.upgradeReadMeField = value; + } + } + + /// + public string Url { + get { + return this.urlField; + } + set { + this.urlField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://packages.umbraco.org/webservices/")] + public enum SubmitStatus { + + /// + Complete, + + /// + Exists, + + /// + NoAccess, + + /// + Error, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + public delegate void CategoriesCompletedEventHandler(object sender, CategoriesCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class CategoriesCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal CategoriesCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public Category[] Result { + get { + this.RaiseExceptionIfNecessary(); + return ((Category[])(this.results[0])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + public delegate void NitrosCompletedEventHandler(object sender, NitrosCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class NitrosCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal NitrosCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public Package[] Result { + get { + this.RaiseExceptionIfNecessary(); + return ((Package[])(this.results[0])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + public delegate void NitrosCategorizedCompletedEventHandler(object sender, NitrosCategorizedCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class NitrosCategorizedCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal NitrosCategorizedCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public Category[] Result { + get { + this.RaiseExceptionIfNecessary(); + return ((Category[])(this.results[0])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + public delegate void authenticateCompletedEventHandler(object sender, authenticateCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class authenticateCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal authenticateCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public string Result { + get { + this.RaiseExceptionIfNecessary(); + return ((string)(this.results[0])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + public delegate void fetchPackageCompletedEventHandler(object sender, fetchPackageCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class fetchPackageCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal fetchPackageCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public byte[] Result { + get { + this.RaiseExceptionIfNecessary(); + return ((byte[])(this.results[0])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + public delegate void fetchProtectedPackageCompletedEventHandler(object sender, fetchProtectedPackageCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class fetchProtectedPackageCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal fetchProtectedPackageCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public byte[] Result { + get { + this.RaiseExceptionIfNecessary(); + return ((byte[])(this.results[0])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + public delegate void SubmitPackageCompletedEventHandler(object sender, SubmitPackageCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class SubmitPackageCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal SubmitPackageCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public SubmitStatus Result { + get { + this.RaiseExceptionIfNecessary(); + return ((SubmitStatus)(this.results[0])); + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + public delegate void PackageByGuidCompletedEventHandler(object sender, PackageByGuidCompletedEventArgs e); + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl", "2.0.50727.42")] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + public partial class PackageByGuidCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs { + + private object[] results; + + internal PackageByGuidCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : + base(exception, cancelled, userState) { + this.results = results; + } + + /// + public Package Result { + get { + this.RaiseExceptionIfNecessary(); + return ((Package)(this.results[0])); + } + } + } +} \ No newline at end of file diff --git a/umbraco/cms/businesslogic/Packager/Settings.cs b/umbraco/cms/businesslogic/Packager/Settings.cs new file mode 100644 index 0000000000..5c367d963b --- /dev/null +++ b/umbraco/cms/businesslogic/Packager/Settings.cs @@ -0,0 +1,82 @@ +using System; +using System.Data; +using System.Configuration; +using System.Web; +using System.Web.Security; +using System.Web.UI; +using System.Web.UI.WebControls; +using System.Web.UI.WebControls.WebParts; +using System.Web.UI.HtmlControls; +using System.IO; + +namespace umbraco.cms.businesslogic.packager +{ + public class Settings + { + + public static string PackagerRoot + { + get { return GlobalSettings.StorageDirectory + System.IO.Path.DirectorySeparatorChar.ToString() + "packages"; } + } + + public static string PackagesStorage + { + get { return GlobalSettings.StorageDirectory + System.IO.Path.DirectorySeparatorChar.ToString() + "packages" + System.IO.Path.DirectorySeparatorChar.ToString() + "created"; } + } + + public static string InstalledPackagesStorage + { + get { return GlobalSettings.StorageDirectory + System.IO.Path.DirectorySeparatorChar.ToString() + "packages" + System.IO.Path.DirectorySeparatorChar.ToString() + "installed"; } + } + + public static string InstalledPackagesSettings + { + get { return GlobalSettings.StorageDirectory + System.IO.Path.DirectorySeparatorChar.ToString() + "packages" + System.IO.Path.DirectorySeparatorChar.ToString() + "installed" + System.IO.Path.DirectorySeparatorChar.ToString() + "installedPackages.config"; } + } + + public static string CreatedPackagesSettings + { + get { return GlobalSettings.StorageDirectory + System.IO.Path.DirectorySeparatorChar.ToString() + "packages" + System.IO.Path.DirectorySeparatorChar.ToString() + "created" + System.IO.Path.DirectorySeparatorChar.ToString() + "createdPackages.config"; } + } + + public static string PackageFileExtension + { + get { return "zip"; } + } + + public static bool HasFileAccess(ref Exception exp) + { + bool hasAccess = false; + StreamWriter sw1 = null; + StreamWriter sw2 = null; + try + { + sw1 = System.IO.File.AppendText(HttpContext.Current.Server.MapPath(InstalledPackagesSettings)); + sw1.Close(); + + sw2 = System.IO.File.AppendText(HttpContext.Current.Server.MapPath(CreatedPackagesSettings)); + sw1.Close(); + + System.IO.Directory.CreateDirectory(HttpContext.Current.Server.MapPath(PackagesStorage) + "\\__testFolder__"); + System.IO.Directory.CreateDirectory(HttpContext.Current.Server.MapPath(InstalledPackagesStorage) + "\\__testFolder__"); + + System.IO.Directory.Delete(HttpContext.Current.Server.MapPath(PackagesStorage) + "\\__testFolder__", true); + System.IO.Directory.Delete(HttpContext.Current.Server.MapPath(InstalledPackagesStorage) + "\\__testFolder__", true); + + hasAccess = true; + } + finally + { + if (sw1 != null) + sw1.Close(); + if (sw2 != null) + sw2.Close(); + } + + return hasAccess; + } + + + } + +} diff --git a/umbraco/cms/businesslogic/Packager/data.cs b/umbraco/cms/businesslogic/Packager/data.cs new file mode 100644 index 0000000000..aee9b0c841 --- /dev/null +++ b/umbraco/cms/businesslogic/Packager/data.cs @@ -0,0 +1,333 @@ +using System; +using System.Xml; +using System.Xml.XPath; +using System.Collections.Generic; + +namespace umbraco.cms.businesslogic.packager +{ + public class data + { + //public virtual string sourcePath = System.Web.HttpContext.Current.Server.MapPath(Settings.PackagerSettings); + private static XmlDocument _source; + + public static XmlDocument Source + { + get + { + return _source; + } + } + + public static void Reload(string dataSource) + { + if (_source == null) + _source = new XmlDocument(); + try { + + _source.Load(dataSource); + + } catch { + + if (!System.IO.File.Exists(dataSource)) { + System.IO.StreamWriter sw = System.IO.File.CreateText(dataSource); + sw.WriteLine(""); + sw.WriteLine(""); + sw.Flush(); + sw.Close(); + } + _source.Load(dataSource); + } + } + + public static XmlNode GetFromId(int Id, string dataSource, bool reload) + { + if(reload) + Reload(dataSource); + + return Source.SelectSingleNode("/packages/package [@id = '" + Id.ToString().ToUpper() + "']"); + } + + public static XmlNode GetFromGuid(string guid, string dataSource, bool reload) { + if (reload) + Reload(dataSource); + + return Source.SelectSingleNode("/packages/package [@packageGuid = '" + guid + "']"); + } + + public static PackageInstance MakeNew(string Name, string dataSource) + { + PackageInstance retVal = new PackageInstance(); + + try + { + Reload(dataSource); + + int _maxId = 1; + // Find max id + foreach (XmlNode n in Source.SelectNodes("packages/package")) + { + if (int.Parse(n.Attributes.GetNamedItem("id").Value) >= _maxId) + _maxId = int.Parse(n.Attributes.GetNamedItem("id").Value) + 1; + } + + XmlElement instance = Source.CreateElement("package"); + instance.Attributes.Append(xmlHelper.addAttribute(Source, "id", _maxId.ToString())); + instance.Attributes.Append(xmlHelper.addAttribute(Source, "version", "")); + instance.Attributes.Append(xmlHelper.addAttribute(Source, "url", "")); + instance.Attributes.Append(xmlHelper.addAttribute(Source, "name", Name)); + instance.Attributes.Append(xmlHelper.addAttribute(Source, "folder", System.Guid.NewGuid().ToString())); + instance.Attributes.Append(xmlHelper.addAttribute(Source, "packagepath", "")); + instance.Attributes.Append(xmlHelper.addAttribute(Source, "repositoryGuid", "")); + instance.Attributes.Append(xmlHelper.addAttribute(Source, "packageGuid", System.Guid.NewGuid().ToString())); + instance.Attributes.Append(xmlHelper.addAttribute(Source, "hasUpdate", "false")); + + XmlElement license = Source.CreateElement("license"); + license.InnerText = "MIT license"; + license.Attributes.Append(xmlHelper.addAttribute(Source, "url", "http://www.opensource.org/licenses/mit-license.php")); + instance.AppendChild(license); + + XmlElement author = Source.CreateElement("author"); + author.InnerText = ""; + author.Attributes.Append(xmlHelper.addAttribute(Source, "url", "")); + instance.AppendChild(author); + + instance.AppendChild(xmlHelper.addTextNode(Source, "readme", "")); + instance.AppendChild(xmlHelper.addTextNode(Source, "actions", "")); + + instance.AppendChild(xmlHelper.addTextNode(Source, "datatypes", "")); + + XmlElement content = Source.CreateElement("content"); + content.InnerText = ""; + content.Attributes.Append(xmlHelper.addAttribute(Source, "nodeId", "")); + content.Attributes.Append(xmlHelper.addAttribute(Source, "loadChildNodes", "false")); + instance.AppendChild(content); + + instance.AppendChild(xmlHelper.addTextNode(Source, "templates", "")); + instance.AppendChild(xmlHelper.addTextNode(Source, "stylesheets", "")); + instance.AppendChild(xmlHelper.addTextNode(Source, "documenttypes", "")); + instance.AppendChild(xmlHelper.addTextNode(Source, "macros", "")); + instance.AppendChild(xmlHelper.addTextNode(Source, "files", "")); + instance.AppendChild(xmlHelper.addTextNode(Source, "languages", "")); + instance.AppendChild(xmlHelper.addTextNode(Source, "dictionaryitems", "")); + instance.AppendChild(xmlHelper.addTextNode(Source, "loadcontrol", "")); + + Source.SelectSingleNode("packages").AppendChild(instance); + Source.Save(dataSource); + retVal = data.Package(_maxId, dataSource); + } + catch (Exception ex) + { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, 0, ex.ToString()); + } + + return retVal; + } + + public static PackageInstance Package(int id, string datasource) { + return ConvertXmlToPackage( GetFromId(id, datasource, true) ); + } + + public static PackageInstance Package(string guid, string datasource) { + try { + XmlNode node = GetFromGuid(guid, datasource, true); + if(node != null) + return ConvertXmlToPackage(node); + else + return new PackageInstance(); + } catch(Exception ex) { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, 0, ex.ToString()); + return new PackageInstance(); + } + } + + public static List GetAllPackages(string dataSource) { + Reload(dataSource); + XmlNodeList nList = data.Source.SelectNodes("packages/package"); + + List retVal = new List(); + + for (int i = 0; i < nList.Count; i++) { + try { + retVal.Add(ConvertXmlToPackage(nList[i])); + } catch (Exception ex) { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Debug, new BusinessLogic.User(0), -1, ex.ToString()); + } + } + + return retVal; + } + + private static PackageInstance ConvertXmlToPackage(XmlNode n) { + PackageInstance retVal = new PackageInstance(); + + if (n != null) { + retVal.Id = int.Parse(safeAttribute("id",n)); + retVal.Name = safeAttribute("name",n); + retVal.Folder = safeAttribute("folder", n); + retVal.PackagePath = safeAttribute("packagepath", n); + retVal.Version = safeAttribute("version", n); + retVal.Url = safeAttribute("url", n); + retVal.RepositoryGuid = safeAttribute("repositoryGuid", n); + retVal.PackageGuid = safeAttribute("packageGuid", n); + retVal.HasUpdate = bool.Parse(safeAttribute("hasUpdate",n)); + + retVal.License = safeNodeValue(n.SelectSingleNode("license")); + retVal.LicenseUrl = n.SelectSingleNode("license").Attributes.GetNamedItem("url").Value; + + retVal.Author = safeNodeValue(n.SelectSingleNode("author")); + retVal.AuthorUrl = safeAttribute("url", n.SelectSingleNode("author")); + + retVal.Readme = safeNodeValue(n.SelectSingleNode("readme")); + retVal.Actions = safeNodeInnerXml(n.SelectSingleNode("actions")); + + retVal.ContentNodeId = safeAttribute("nodeId", n.SelectSingleNode("content")); + retVal.ContentLoadChildNodes = bool.Parse(safeAttribute("loadChildNodes",n.SelectSingleNode("content"))); + + + retVal.Macros = new List(safeNodeValue(n.SelectSingleNode("macros")).Trim(',').Split(',')); + retVal.Macros = new List(safeNodeValue(n.SelectSingleNode("macros")).Trim(',').Split(',')); + retVal.Templates = new List(safeNodeValue(n.SelectSingleNode("templates")).Trim(',').Split(',')); + retVal.Stylesheets = new List(safeNodeValue(n.SelectSingleNode("stylesheets")).Trim(',').Split(',')); + retVal.Documenttypes = new List(safeNodeValue(n.SelectSingleNode("documenttypes")).Trim(',').Split(',')); + retVal.Languages = new List(safeNodeValue(n.SelectSingleNode("languages")).Trim(',').Split(',')); + retVal.DictionaryItems = new List(safeNodeValue(n.SelectSingleNode("dictionaryitems")).Trim(',').Split(',')); + retVal.DataTypes = new List(safeNodeValue(n.SelectSingleNode("datatypes")).Trim(',').Split(',')); + + XmlNodeList xmlFiles = n.SelectNodes("files/file"); + retVal.Files = new List(); + + for (int i = 0; i < xmlFiles.Count; i++) + retVal.Files.Add(xmlFiles[i].InnerText); + + retVal.LoadControl = safeNodeValue(n.SelectSingleNode("loadcontrol")); + } + + return retVal; + } + + public static void Delete(int Id, string dataSource) + { + Reload(dataSource); + // Remove physical xml file if any + //PackageInstance p = new PackageInstance(Id); + + //TODO DELETE PACKAGE FOLDER... + //p.Folder + + XmlNode n = data.GetFromId(Id, dataSource, true); + data.Source.SelectSingleNode("/packages").RemoveChild(n); + data.Source.Save(dataSource); + } + + public static void UpdateValue(XmlNode n, string Value) + { + if (n.FirstChild != null) + n.FirstChild.Value = Value; + else + { + n.AppendChild(Source.CreateTextNode(Value)); + } + //Save(); + } + + public static void Save(PackageInstance package, string dataSource) + { + try + { + Reload(dataSource); + XmlNode _xmlDef = GetFromId(package.Id, dataSource, false); + _xmlDef.Attributes.GetNamedItem("name").Value = package.Name; + _xmlDef.Attributes.GetNamedItem("version").Value = package.Version; + _xmlDef.Attributes.GetNamedItem("url").Value = package.Url; + _xmlDef.Attributes.GetNamedItem("packagepath").Value = package.PackagePath; + _xmlDef.Attributes.GetNamedItem("repositoryGuid").Value = package.RepositoryGuid; + _xmlDef.Attributes.GetNamedItem("packageGuid").Value = package.PackageGuid; + + _xmlDef.Attributes.GetNamedItem("hasUpdate").Value = package.HasUpdate.ToString(); + + _xmlDef.SelectSingleNode("license").FirstChild.Value = package.License; + _xmlDef.SelectSingleNode("license").Attributes.GetNamedItem("url").Value = package.LicenseUrl; + + _xmlDef.SelectSingleNode("author").InnerText = package.Author; + _xmlDef.SelectSingleNode("author").Attributes.GetNamedItem("url").Value = package.AuthorUrl; + + _xmlDef.SelectSingleNode("readme").InnerXml = ""; + + if(_xmlDef.SelectSingleNode("actions") == null) + _xmlDef.AppendChild(xmlHelper.addTextNode(Source, "actions", "")); + + _xmlDef.SelectSingleNode("actions").InnerXml = package.Actions; + + _xmlDef.SelectSingleNode("content").Attributes.GetNamedItem("nodeId").Value = package.ContentNodeId.ToString(); + _xmlDef.SelectSingleNode("content").Attributes.GetNamedItem("loadChildNodes").Value = package.ContentLoadChildNodes.ToString(); + + _xmlDef.SelectSingleNode("macros").InnerText = joinList(package.Macros, ','); + _xmlDef.SelectSingleNode("templates").InnerText = joinList(package.Templates, ','); + _xmlDef.SelectSingleNode("stylesheets").InnerText = joinList(package.Stylesheets, ','); + _xmlDef.SelectSingleNode("documenttypes").InnerText = joinList(package.Documenttypes, ','); + + _xmlDef.SelectSingleNode("languages").InnerText = joinList(package.Languages, ','); + _xmlDef.SelectSingleNode("dictionaryitems").InnerText = joinList(package.DictionaryItems, ','); + _xmlDef.SelectSingleNode("datatypes").InnerText = joinList(package.DataTypes, ','); + + _xmlDef.SelectSingleNode("files").InnerXml = ""; + + foreach (string fileStr in package.Files) { + if(!string.IsNullOrEmpty(fileStr.Trim())) + _xmlDef.SelectSingleNode("files").AppendChild(xmlHelper.addTextNode(data.Source, "file", fileStr)); + } + + _xmlDef.SelectSingleNode("loadcontrol").InnerText = package.LoadControl; + + Source.Save(dataSource); + + + } + catch(Exception F) + { + BusinessLogic.User myUser = new BusinessLogic.User(0); + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, myUser, 0, F.ToString()); + } + + } + + private static string safeAttribute(string name, XmlNode n) { + try { + return n.Attributes.GetNamedItem(name).Value; + } catch { + return ""; + } + } + + private static string safeNodeValue(XmlNode n) { + try { + return xmlHelper.GetNodeValue(n); + } catch { + return ""; + } + } + + private static string safeNodeInnerXml(XmlNode n) { + try { + return n.InnerXml; + } catch { + return ""; + } + } + + + private static string joinList(List list, char seperator) { + string retVal = ""; + foreach (string str in list) { + retVal += str + seperator.ToString(); + } + + return retVal.Trim(seperator); + } + + public data() + { + + } + } +} diff --git a/umbraco/cms/businesslogic/Permission.cs b/umbraco/cms/businesslogic/Permission.cs new file mode 100644 index 0000000000..afbb6366cc --- /dev/null +++ b/umbraco/cms/businesslogic/Permission.cs @@ -0,0 +1,50 @@ +using System; +using System.Collections; +using System.Collections.Specialized; +using System.Data; +using System.Runtime.CompilerServices; + +using umbraco.DataLayer; + +namespace umbraco.BusinessLogic +{ + /// + /// Summary description for Permission. + /// + public class Permission + { + public Permission() + { + } + + private static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public static void MakeNew(BusinessLogic.User User, cms.businesslogic.CMSNode Node, char PermissionKey) + { + IParameter[] parameters = new IParameter[] { SqlHelper.CreateParameter("@userId", User.Id), + SqlHelper.CreateParameter("@nodeId", Node.Id), + SqlHelper.CreateParameter("@permission", PermissionKey.ToString()) }; + + // Method is synchronized so exists remains consistent (avoiding race condition) + bool exists = SqlHelper.ExecuteScalar("SELECT COUNT(userId) FROM umbracoUser2nodePermission WHERE userId = @userId AND nodeId = @nodeId AND permission = @permission", + parameters) > 0; + if (!exists) + SqlHelper.ExecuteNonQuery("INSERT INTO umbracoUser2nodePermission (userId, nodeId, permission) VALUES (@userId, @nodeId, @permission)", + parameters); + } + + public static void UpdateCruds(BusinessLogic.User User, cms.businesslogic.CMSNode Node, string Permissions) + { + // delete all settings on the node for this user + SqlHelper.ExecuteNonQuery("delete from umbracoUser2NodePermission where userId = @userId and nodeId = @nodeId", SqlHelper.CreateParameter("@userId", User.Id), SqlHelper.CreateParameter("@nodeId", Node.Id)); + + // Loop through the permissions and create them + foreach (char c in Permissions.ToCharArray()) + MakeNew(User, Node, c); + } + } +} \ No newline at end of file diff --git a/umbraco/cms/businesslogic/Property/Property.cs b/umbraco/cms/businesslogic/Property/Property.cs new file mode 100644 index 0000000000..6a7cfce9fd --- /dev/null +++ b/umbraco/cms/businesslogic/Property/Property.cs @@ -0,0 +1,116 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Runtime.CompilerServices; +using System.Xml; + +using umbraco.DataLayer; +using umbraco.BusinessLogic; + +namespace umbraco.cms.businesslogic.property +{ + /// + /// Property class encapsulates property factory, ensuring that the work + /// with umbraco generic properties stays nice and easy.. + /// + public class Property + { + private static string _connstring = GlobalSettings.DbDSN; + propertytype.PropertyType _pt; + interfaces.IData _data; + private int _id; + + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + public Property(int Id, propertytype.PropertyType pt) + { + + _pt = pt; + _id = Id; + _data = _pt.DataTypeDefinition.DataType.Data; + _data.PropertyId = Id; + } + + public Property(int Id) + { + _id = Id; + _pt = umbraco.cms.businesslogic.propertytype.PropertyType.GetPropertyType( + SqlHelper.ExecuteScalar("select propertytypeid from cmsPropertyData where id = @id", SqlHelper.CreateParameter("@id", Id))); + _data = _pt.DataTypeDefinition.DataType.Data; + _data.PropertyId = Id; + } + + public Guid VersionId + { + get + { + IRecordsReader dr = SqlHelper.ExecuteReader("Select versionId from cmsPropertyData where id = " + _id.ToString()); + dr.Read(); + return dr.GetGuid("versionId"); + } + } + public int Id { + get {return _id;} + } + public propertytype.PropertyType PropertyType { + get{return _pt;} + } + + public object Value { + get { + return _data.Value; + } + set { + _data.Value = value; + } + } + + public void delete() { + int contentId = SqlHelper.ExecuteScalar("Select contentNodeId from cmsPropertyData where Id = " + _id); + SqlHelper.ExecuteNonQuery( "Delete from cmsPropertyData where PropertyTypeId =" + _pt.Id + " And contentNodeId = "+ contentId); + _data.Delete(); + } + + public XmlNode ToXml(XmlDocument xd) + { + XmlNode x = xd.CreateNode(XmlNodeType.Element, "data", ""); + + // Version not necessary after sql publishing has been removed + + // Alias + XmlAttribute alias = xd.CreateAttribute("alias"); + alias.Value = this.PropertyType.Alias; + x.Attributes.Append(alias); + + // Check for cdata section + // x.AppendChild(xd.CreateCDataSection(this.Value.ToString())); + x.AppendChild(_data.ToXMl(xd)); + + return x; + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public static Property MakeNew(propertytype.PropertyType pt, Content c, Guid versionId) + { + int newPropertyId = 0; + // The method is synchronized + SqlHelper.ExecuteNonQuery("INSERT INTO cmsPropertyData (contentNodeId, versionId, propertyTypeId) VALUES(@contentNodeId, @versionId, @propertyTypeId)", + SqlHelper.CreateParameter("@contentNodeId", c.Id), + SqlHelper.CreateParameter("@versionId", versionId), + SqlHelper.CreateParameter("@propertyTypeId", pt.Id)); + newPropertyId = SqlHelper.ExecuteScalar("SELECT MAX(id) FROM cmsPropertyData"); + interfaces.IData d = pt.DataTypeDefinition.DataType.Data; + d.MakeNew(newPropertyId); + return new Property(newPropertyId, pt); + } + } + + public class Properties : List + { + + } + +} \ No newline at end of file diff --git a/umbraco/cms/businesslogic/cache/Cache.cs b/umbraco/cms/businesslogic/cache/Cache.cs new file mode 100644 index 0000000000..694117619a --- /dev/null +++ b/umbraco/cms/businesslogic/cache/Cache.cs @@ -0,0 +1,156 @@ +using System; +using System.Web.Caching; + +namespace umbraco.cms.businesslogic.cache +{ + /// + /// Summary description for Cache. + /// + public class Cache + { + + /// + /// Clears everything in umbraco's runtime cache, which means that not only + /// umbraco content is removed, but also other cache items from pages running in + /// the same application / website. Use with care :-) + /// + public static void ClearAllCache() + { + System.Web.Caching.Cache c = System.Web.HttpRuntime.Cache; + if (c != null) + { + System.Collections.IDictionaryEnumerator cacheEnumerator = c.GetEnumerator(); + while ( cacheEnumerator.MoveNext() ) + { + c.Remove(cacheEnumerator.Key.ToString()); + } + } + } + + /// + /// Clears the item in umbraco's runtime cache with the given key + /// + /// Key + public static void ClearCacheItem(string Key) + { + if (System.Web.HttpRuntime.Cache[Key] != null) + { + System.Web.HttpRuntime.Cache.Remove(Key); + System.Web.HttpContext.Current.Trace.Warn("Cache", "Item " + Key + " removed from cache"); + } + } + + + /// + /// Clears all objects in the System.Web.Cache with the System.Type name as the + /// input parameter. (using [object].GetType()) + /// + /// The name of the System.Type which should be cleared from cache ex "System.Xml.XmlDocument" + public static void ClearCacheObjectTypes(string TypeName) + { + System.Web.Caching.Cache c = System.Web.HttpRuntime.Cache; + try + { + if (c != null) + { + System.Collections.IDictionaryEnumerator cacheEnumerator = c.GetEnumerator(); + while ( cacheEnumerator.MoveNext() ) + if (cacheEnumerator.Key != null && c[cacheEnumerator.Key.ToString()] != null && c[cacheEnumerator.Key.ToString()].GetType() != null && c[cacheEnumerator.Key.ToString()].GetType().ToString() == TypeName) + c.Remove(cacheEnumerator.Key.ToString()); + + } + } + catch (Exception CacheE) + { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, BusinessLogic.User.GetUser(0), -1, "CacheClearing : " + CacheE.ToString()); + } + } + + /// + /// Clears all cache items that starts with the key passed. + /// + /// The start of the key + public static void ClearCacheByKeySearch(string KeyStartsWith) + { + System.Web.Caching.Cache c = System.Web.HttpRuntime.Cache; + if (c != null) + { + System.Collections.IDictionaryEnumerator cacheEnumerator = c.GetEnumerator(); + while (cacheEnumerator.MoveNext()) + { + if (cacheEnumerator.Key is string && ((string)cacheEnumerator.Key).StartsWith(KeyStartsWith)) + { + Cache.ClearCacheItem((string)cacheEnumerator.Key); + } + } + } + + } + + /// + /// Retrieve all cached items + /// + /// A hastable containing all cacheitems + public static System.Collections.Hashtable ReturnCacheItemsOrdred() + { + System.Collections.Hashtable ht = new System.Collections.Hashtable(); + System.Web.Caching.Cache c = System.Web.HttpRuntime.Cache; + if (c != null) + { + System.Collections.IDictionaryEnumerator cacheEnumerator = c.GetEnumerator(); + while ( cacheEnumerator.MoveNext() ) + { + if (ht[c[cacheEnumerator.Key.ToString()].GetType().ToString()] == null) + ht.Add(c[cacheEnumerator.Key.ToString()].GetType().ToString(), new System.Collections.ArrayList()); + + ((System.Collections.ArrayList) ht[c[cacheEnumerator.Key.ToString()].GetType().ToString()]).Add(cacheEnumerator.Key.ToString()); + } + } + return ht; + } + + + public delegate TT GetCacheItemDelegate(); + + public static TT GetCacheItem(string cacheKey, object syncLock, + TimeSpan timeout, GetCacheItemDelegate getCacheItem) + { + return GetCacheItem(cacheKey, syncLock, null, timeout, getCacheItem); + } + + public static TT GetCacheItem(string cacheKey, object syncLock, + CacheItemRemovedCallback refreshAction, TimeSpan timeout, + GetCacheItemDelegate getCacheItem) + { + return GetCacheItem(cacheKey, syncLock, CacheItemPriority.Normal, refreshAction, timeout, getCacheItem); + } + + public static TT GetCacheItem(string cacheKey, object syncLock, + CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan timeout, + GetCacheItemDelegate getCacheItem) + { + return GetCacheItem(cacheKey, syncLock, priority, refreshAction, null, timeout, getCacheItem); + } + + public static TT GetCacheItem(string cacheKey, object syncLock, + CacheItemPriority priority, CacheItemRemovedCallback refreshAction, + CacheDependency cacheDependency, TimeSpan timeout, GetCacheItemDelegate getCacheItem) + { + object result = System.Web.HttpRuntime.Cache.Get(cacheKey); + if (result == null) + { + lock (syncLock) + { + result = System.Web.HttpRuntime.Cache.Get(cacheKey); + if (result == null) + { + result = getCacheItem(); + System.Web.HttpRuntime.Cache.Add(cacheKey, result, cacheDependency, + DateTime.Now.Add(timeout), TimeSpan.Zero, priority, refreshAction); + } + } + } + return (TT)result; + } + } +} diff --git a/umbraco/cms/businesslogic/datatype/AbstractDataEditor.cs b/umbraco/cms/businesslogic/datatype/AbstractDataEditor.cs new file mode 100644 index 0000000000..d388985cb3 --- /dev/null +++ b/umbraco/cms/businesslogic/datatype/AbstractDataEditor.cs @@ -0,0 +1,147 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace umbraco.cms.businesslogic.datatype +{ + /// + /// A much easier way to build custom datatypes. Inherit from this class + /// and change Id and DataTypeName and then set the RenderControl property + /// to your .NET webcontrol to be displayed + /// Made by NH in flight SK 925 on his way to MIX09 + /// + public abstract class AbstractDataEditor : BaseDataType, interfaces.IDataType + { + private interfaces.IData _baseData; + private interfaces.IDataPrevalue _prevalueeditor; + private AbstractDataEditorControl m_editor = new AbstractDataEditorControl(); + + /// + /// The data editor control is the 'real' IDataEditor control. Hook into the + /// OnSave event in your inherited class' constructor and update the + /// base.Data.Value property to save a value + /// + /// The data editor control. + public AbstractDataEditorControl DataEditorControl + { + get { return m_editor; } + } + + #region IDataEditor Members + /// + /// The RenderControl the control that's rendered when editing. This should be + /// *your* control, so set this property to the WebControl that you're creating + /// + /// The render control. + public System.Web.UI.Control RenderControl + { + set + { + m_editor.Control = value; + } + } + + public override umbraco.interfaces.IDataEditor DataEditor + { + get { return m_editor; } + } + + public override umbraco.interfaces.IData Data + { + get + { + if (_baseData == null) + _baseData = new DefaultData(this); + return _baseData; + } + } + + public override umbraco.interfaces.IDataPrevalue PrevalueEditor + { + get + { + if (_prevalueeditor == null) + _prevalueeditor = new DefaultPreValueEditor(this, false); + return _prevalueeditor; + } + } + + public override string DataTypeName + { + get { throw new NotImplementedException(); } + } + + public override Guid Id + { + get { throw new NotImplementedException(); } + } + + + } + + public class AbstractDataEditorControl : System.Web.UI.WebControls.WebControl, interfaces.IDataEditor + { + public AbstractDataEditorControl() + { + } + + public System.Web.UI.Control Control + { + get; + set; + } + + public virtual void Save() + { + FireOnSave(new EventArgs()); + } + + public virtual bool ShowLabel + { + get { return true; } + } + + [Obsolete("This is legacy and should be left to false")] + public virtual bool TreatAsRichTextEditor + { + get { return false; } + } + + public virtual System.Web.UI.Control Editor + { + get { return this; } + } + + protected override void OnInit(EventArgs e) + { + base.OnInit(e); + this.Controls.Add(Control); + } + + #endregion + + // events + + + /// + /// The save event handler + /// + public delegate void SaveEventHandler(EventArgs e); + /// + /// Occurs when [after save]. + /// + public event SaveEventHandler OnSave; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void FireOnSave(EventArgs e) + { + if (OnSave != null) + { + OnSave(e); + } + } + + } +} diff --git a/umbraco/cms/businesslogic/datatype/BaseDataType.cs b/umbraco/cms/businesslogic/datatype/BaseDataType.cs new file mode 100644 index 0000000000..fc35d269df --- /dev/null +++ b/umbraco/cms/businesslogic/datatype/BaseDataType.cs @@ -0,0 +1,93 @@ +using System; +using System.Data; + +using umbraco.DataLayer; +using umbraco.BusinessLogic; + + +namespace umbraco.cms.businesslogic.datatype +{ + public abstract class BaseDataType + { + private int _datatypedefinitionid; + private string _datafield = ""; + private DBTypes _DBType; + + private static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + public BaseDataType() + {} + + #region IDataType Members + public abstract Guid Id {get;} + public abstract string DataTypeName{get;} + public abstract interfaces.IDataEditor DataEditor{get;} + public abstract interfaces.IDataPrevalue PrevalueEditor {get;} + public abstract interfaces.IData Data{get;} + + public int DataTypeDefinitionId { + set { + _datatypedefinitionid = value; + } + get { + return _datatypedefinitionid; + } + } + + public DBTypes DBType { + get { + string test= ""; + if (_datafield == "") + test = DataFieldName; + return _DBType; + } + set { + _DBType = value; + SqlHelper.ExecuteNonQuery("update cmsDataType set dbType = '" + value.ToString() + "' where nodeId = @datadefinitionid", SqlHelper.CreateParameter("@datadefinitionid",_datatypedefinitionid)); + } + } + // Umbraco legacy - get the datafield - the columnname of the cmsPropertyData table + // where to find the data, since it's configurable - there is no way of telling if + // its a bit, nvarchar, ntext or datetime field. + // get it by lookup the value associated to the datatypedefinition id. + public string DataFieldName + { + get { + if (_datafield == "") + { + string dbtypestr = SqlHelper.ExecuteScalar("select dbType from cmsDataType where nodeId = @datadefinitionid", SqlHelper.CreateParameter("@datadefinitionid", _datatypedefinitionid)); + DBTypes DataTypeSQLType = (DBTypes) Enum.Parse(typeof(DBTypes),dbtypestr,true); + _DBType = DataTypeSQLType; + switch (DataTypeSQLType) + { + case DBTypes.Date : + _datafield = "dataDate"; + break; + case DBTypes.Integer : + _datafield = "DataInt"; + break; + case DBTypes.Ntext : + _datafield = "dataNtext"; + break; + case DBTypes.Nvarchar : + _datafield = "dataNvarchar"; + break; + } + return _datafield; + } + return _datafield; + } + } + #endregion + } + public enum DBTypes + { + Integer, + Date, + Nvarchar, + Ntext + } +} diff --git a/umbraco/cms/businesslogic/datatype/ClientDependencyAttribute.cs b/umbraco/cms/businesslogic/datatype/ClientDependencyAttribute.cs new file mode 100644 index 0000000000..d9973b08ce --- /dev/null +++ b/umbraco/cms/businesslogic/datatype/ClientDependencyAttribute.cs @@ -0,0 +1,98 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace umbraco.cms.businesslogic.datatype +{ + /// + /// This attribute is used for data types that uses client assets like Javascript and CSS for liveediting. + /// The Live Editing feature in umbraco will look for this attribute and preload all dependencies to the page + /// to ensure that all client events and assets gets loaded + /// + [AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] + public class ClientDependencyAttribute : Attribute + { + /// + /// Gets or sets the priority. + /// + /// The priority. + public int Priority { get; set; } + + /// + /// Gets or sets the file path. + /// + /// The file path. + public string FilePath { get; set; } + + /// + /// Gets or sets the type of the dependency. + /// + /// The type of the dependency. + public ClientDependencyType DependencyType { get; set; } + + /// + /// Gets or sets the name of an optional javascript method that should be called on load. + /// + /// The name of the method. + public string InvokeJavascriptMethodOnLoad { get; set; } + + /// + /// Initializes a new instance of the class. + /// + /// The priority. + /// Type of the dependency. + /// The file path to the dependency. + public ClientDependencyAttribute(int priority, ClientDependencyType dependencyType, string filePath) + : this(priority, dependencyType, filePath, false, string.Empty) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The priority. + /// Type of the dependency. + /// The file path to the dependency. + /// The name of the Javascript method to invoke when the dependency is loaded. + public ClientDependencyAttribute(int priority, ClientDependencyType dependencyType, string filePath, string invokeJavascriptMethodOnLoad) + : this(priority, dependencyType, filePath, false, invokeJavascriptMethodOnLoad) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The priority. + /// Type of the dependency. + /// The file path to the dependency. + /// if set to true the current umbraco path will be prefixed to the filePath. + public ClientDependencyAttribute(int priority, ClientDependencyType dependencyType, string filePath, bool appendUmbracoPath) + : this(priority, dependencyType, filePath, appendUmbracoPath, String.Empty) + { } + + /// + /// Initializes a new instance of the class. + /// + /// The priority. + /// Type of the dependency. + /// The file path to the dependency. + /// if set to true the current umbraco path will be prefixed to the filePath. + /// The name of the Javascript method to invoke when the dependency is loaded. + public ClientDependencyAttribute(int priority, ClientDependencyType dependencyType, string filePath, bool appendUmbracoPath, string invokeJavascriptMethodOnLoad) + { + if (String.IsNullOrEmpty(filePath)) + throw new ArgumentException("filePath"); + + Priority = priority; + FilePath = appendUmbracoPath ? GlobalSettings.Path + "/" + filePath : filePath; + DependencyType = dependencyType; + InvokeJavascriptMethodOnLoad = invokeJavascriptMethodOnLoad ?? String.Empty; + } + } + + /// + /// The type of client file + /// + public enum ClientDependencyType + { + Javascript, Css + } +} diff --git a/umbraco/cms/businesslogic/datatype/ClientDependencyHelper.cs b/umbraco/cms/businesslogic/datatype/ClientDependencyHelper.cs new file mode 100644 index 0000000000..053bdd801b --- /dev/null +++ b/umbraco/cms/businesslogic/datatype/ClientDependencyHelper.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.Web.UI; +using System.Web; + +namespace umbraco.cms.businesslogic.datatype +{ + public class ClientDependencyHelper + { + /// Path to the dependency loader we need for adding control dependencies. + protected const string DependencyLoaderScriptFile = "{0}/js/UmbracoDependencyLoader.js"; + + /// + /// Adds the client dependencies to the passed page's client script manager. + /// + public static void AddClientDependencies(Control control) { + Type controlType = control.GetType(); + + // find dependencies + List dependencies = new List(); + foreach (Attribute attribute in Attribute.GetCustomAttributes(controlType)) + { + if (attribute is ClientDependencyAttribute) + { + dependencies.Add((ClientDependencyAttribute)attribute); + } + } + // sort by priority + dependencies.Sort((a, b) => a.Priority.CompareTo(b.Priority)); + + if (dependencies.Count > 0) + { + // register loader script + if (!HttpContext.Current.Items.Contains(DependencyLoaderScriptFile)) + { + ScriptManager.RegisterClientScriptInclude(control, controlType, "DependencyLoader", + String.Format(DependencyLoaderScriptFile, GlobalSettings.Path)); + HttpContext.Current.Items[DependencyLoaderScriptFile] = true; + } + + // create Javascript calls + StringBuilder dependencyCalls = new StringBuilder("UmbDependencyLoader"); + foreach (ClientDependencyAttribute dependency in dependencies) + { + switch (dependency.DependencyType) + { + case ClientDependencyType.Css: + dependencyCalls.AppendFormat(".AddCss('{0}')", dependency.FilePath); + break; + case ClientDependencyType.Javascript: + dependencyCalls.AppendFormat(".AddJs('{0}','{1}')", + dependency.FilePath, dependency.InvokeJavascriptMethodOnLoad); + break; + } + } + dependencyCalls.Append(';'); + + // register Javascript calls + ScriptManager.RegisterClientScriptBlock(control, controlType, new Guid().ToString(), + dependencyCalls.ToString(), true); + } + + // add child dependencies + foreach (Control child in control.Controls) + { + AddClientDependencies(child); + } + } + } +} diff --git a/umbraco/cms/businesslogic/datatype/DataType.cs b/umbraco/cms/businesslogic/datatype/DataType.cs new file mode 100644 index 0000000000..131408e39f --- /dev/null +++ b/umbraco/cms/businesslogic/datatype/DataType.cs @@ -0,0 +1,315 @@ +using System; +using System.Data; + +using System.Collections; +using umbraco.DataLayer; +using System.Xml; + +namespace umbraco.cms.businesslogic.datatype +{ + /// + /// Datatypedefinitions is the basic buildingblocks of umbraco's documents/medias/members generic datastructure + /// + /// A datatypedefinition encapsulates an object which implements the interface IDataType, and are used when defining + /// the properties of a document in the documenttype. This extra layer between IDataType and a documenttypes propertytype + /// are used amongst other for enabling shared prevalues. + /// + /// + public class DataTypeDefinition : CMSNode + { + private Guid _controlId; + + private static Guid _objectType = new Guid("30a2a501-1978-4ddb-a57b-f7efed43ba3c"); + + + /// + /// Initialization of the datatypedefinition + /// + /// Datattypedefininition id + public DataTypeDefinition(int id) : base(id) + { + setupDataTypeDefinition(); + } + + public void Delete() + { + delete(); + cache.Cache.ClearCacheItem(string.Format("UmbracoDataTypeDefinition{0}", Id)); + } + + /// + /// Initialization of the datatypedefinition + /// + /// Datattypedefininition id + public DataTypeDefinition(Guid id) : base(id) + { + setupDataTypeDefinition(); + } + + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public override void Save() + { + OnSaving(EventArgs.Empty); + } + + + + private void setupDataTypeDefinition() { + IRecordsReader dr = SqlHelper.ExecuteReader( "select dbType, controlId from cmsDataType where nodeId = '" + this.Id.ToString() + "'"); + if (dr.Read()) + { + _controlId = dr.GetGuid("controlId"); + } + else + throw new ArgumentException("No dataType with id = " + this.Id.ToString() + " found"); + dr.Close(); + } + + + /// + /// The associated datatype, which delivers the methods for editing data, editing prevalues see: umbraco.interfaces.IDataType + /// + public interfaces.IDataType DataType + { + get { + cms.businesslogic.datatype.controls.Factory f = new cms.businesslogic.datatype.controls.Factory(); + interfaces.IDataType dt = f.DataType(_controlId); + dt.DataTypeDefinitionId = Id; + + return dt; + } + set + { + SqlHelper.ExecuteNonQuery( "update cmsDataType set controlId = @id where nodeID = " + this.Id.ToString(), + SqlHelper.CreateParameter("@id",value.Id)); + _controlId = value.Id; + } + } + + + public XmlElement ToXml(XmlDocument xd) { + XmlElement dt = xd.CreateElement("DataType"); + dt.Attributes.Append(xmlHelper.addAttribute(xd, "Name", Text)); + dt.Attributes.Append(xmlHelper.addAttribute(xd, "Id", this.DataType.Id.ToString())); + dt.Attributes.Append(xmlHelper.addAttribute(xd, "Definition", this.UniqueId.ToString())); + + // templates + XmlElement prevalues = xd.CreateElement("PreValues"); + foreach (DictionaryEntry item in PreValues.GetPreValues(this.Id)) { + XmlElement prevalue = xd.CreateElement("PreValue"); + prevalue.Attributes.Append(xmlHelper.addAttribute(xd, "Id", ((umbraco.cms.businesslogic.datatype.PreValue) item.Value).Id.ToString() )); + prevalue.Attributes.Append(xmlHelper.addAttribute(xd, "Value", ((umbraco.cms.businesslogic.datatype.PreValue) item.Value).Value )); + + prevalues.AppendChild(prevalue); + } + + dt.AppendChild(prevalues); + + return dt; + } + + public static DataTypeDefinition Import(XmlNode xmlData) { + string _name = xmlData.Attributes["Name"].Value; + string _id = xmlData.Attributes["Id"].Value; + string _def = xmlData.Attributes["Definition"].Value; + + + //Make sure that the dtd is not already present + if (!CMSNode.IsNode(new Guid(_def)) + ) { + + BasePages.UmbracoEnsuredPage uep = new umbraco.BasePages.UmbracoEnsuredPage(); + BusinessLogic.User u = uep.getUser(); + + if(u == null) + u = BusinessLogic.User.GetUser(0); + + cms.businesslogic.datatype.controls.Factory f = new umbraco.cms.businesslogic.datatype.controls.Factory(); + + + DataTypeDefinition dtd = MakeNew(u, _name, new Guid(_def)); + dtd.DataType = f.DataType(new Guid(_id)); + dtd.Save(); + + //add prevalues + foreach (XmlNode xmlPv in xmlData.SelectNodes("PreValues/PreValue")) + { + + + XmlAttribute val = xmlPv.Attributes["Value"]; + + if (val != null && !string.IsNullOrEmpty(val.Value)) { + PreValue p = new PreValue(0, 0, val.Value); + p.DataTypeId = dtd.Id; + p.Save(); + } + } + + return dtd; + } + + return null; + } + + + /* + public SortedList PreValues { + get { + SortedList retVal = new SortedList(); + SqlDataReader dr = SqlHelper.ExecuteReader("select id, value from cmsDataTypePreValues where dataTypeNodeId = @nodeId order by sortOrder", SqlHelper.CreateParameter("@nodeId", this.Id)); + while (dr.Read()) + { + retVal.Add(dr.GetString("id"), dr.GetString("value")); + } + dr.Close(); + + return retVal; + } + } + */ + + /// + /// Retrieves a list of all datatypedefinitions + /// + /// A list of all datatypedefinitions + public static DataTypeDefinition[] GetAll() + { + SortedList retvalSort = new SortedList(); + Guid[] tmp = CMSNode.getAllUniquesFromObjectType(_objectType); + DataTypeDefinition[] retval = new DataTypeDefinition[tmp.Length]; + for(int i = 0; i < tmp.Length; i++) { + DataTypeDefinition dt = DataTypeDefinition.GetDataTypeDefinition(tmp[i]); + retvalSort.Add(dt.Text + "|||" + Guid.NewGuid().ToString(), dt); + } + + IDictionaryEnumerator ide = retvalSort.GetEnumerator(); + int counter = 0; + while (ide.MoveNext()) + { + retval[counter] = (DataTypeDefinition) ide.Value; + counter++; + } + return retval; + } + + /// + /// Creates a new datatypedefinition given its name and the user which creates it. + /// + /// The user who creates the datatypedefinition + /// The name of the DataTypeDefinition + /// + public static DataTypeDefinition MakeNew(BusinessLogic.User u, string Text) + { + return MakeNew(u, Text, Guid.NewGuid()); + } + + /// + /// Creates a new datatypedefinition given its name and the user which creates it. + /// + /// The user who creates the datatypedefinition + /// The name of the DataTypeDefinition + /// Overrides the CMSnodes uniqueID + /// + public static DataTypeDefinition MakeNew(BusinessLogic.User u, string Text, Guid UniqueId) { + + int newId = CMSNode.MakeNew(-1, _objectType, u.Id, 1, Text, UniqueId).Id; + cms.businesslogic.datatype.controls.Factory f = new cms.businesslogic.datatype.controls.Factory(); + Guid FirstcontrolId = f.GetAll()[0].Id; + SqlHelper.ExecuteNonQuery("Insert into cmsDataType (nodeId, controlId, dbType) values (" + newId.ToString() + ",@controlId,'Ntext')", + SqlHelper.CreateParameter("@controlId", FirstcontrolId)); + + DataTypeDefinition dtd = new DataTypeDefinition(newId); + dtd.OnNew(EventArgs.Empty); + + return dtd; + } + + /// + /// Retrieve a list of datatypedefinitions which share the same IDataType datatype + /// + /// The unique id of the IDataType + /// A list of datatypedefinitions which are based on the IDataType specified + public static DataTypeDefinition GetByDataTypeId(Guid DataTypeId) + { + int dfId = 0; + foreach(DataTypeDefinition df in DataTypeDefinition.GetAll()) + if (df.DataType.Id == DataTypeId) + { + dfId = df.Id; + break; + } + + if (dfId == 0) + return null; + else + return new DataTypeDefinition(dfId); + } + + /// + /// Analyzes an object to see if its basetype is umbraco.editorControls.DefaultData + /// + /// The Data object to analyze + /// True if the basetype is the DefaultData class + public static bool IsDefaultData(object Data) + { + Type typeOfData = Data.GetType(); + + while (typeOfData.BaseType != new Object().GetType()) + typeOfData = typeOfData.BaseType; + + return (typeOfData.FullName == "umbraco.cms.businesslogic.datatype.DefaultData"); + } + + public static DataTypeDefinition GetDataTypeDefinition(int id) + { + if (System.Web.HttpRuntime.Cache[string.Format("UmbracoDataTypeDefinition{0}", id.ToString())] == null) + { + DataTypeDefinition dt = new DataTypeDefinition(id); + System.Web.HttpRuntime.Cache.Insert(string.Format("UmbracoDataTypeDefinition{0}", id.ToString()), dt); + } + return (DataTypeDefinition)System.Web.HttpRuntime.Cache[string.Format("UmbracoDataTypeDefinition{0}", id.ToString())]; + } + + [Obsolete("Use GetDataTypeDefinition(int id) instead", false)] + public static DataTypeDefinition GetDataTypeDefinition(Guid id) + { + if (System.Web.HttpRuntime.Cache[string.Format("UmbracoDataTypeDefinition{0}", id.ToString())] == null) + { + DataTypeDefinition dt = new DataTypeDefinition(id); + System.Web.HttpRuntime.Cache.Insert(string.Format("UmbracoDataTypeDefinition{0}", id.ToString()), dt); + } + return (DataTypeDefinition)System.Web.HttpRuntime.Cache[string.Format("UmbracoDataTypeDefinition{0}", id.ToString())]; + } + + + //EVENTS + public delegate void SaveEventHandler(DataTypeDefinition sender, EventArgs e); + public delegate void NewEventHandler(DataTypeDefinition sender, EventArgs e); + public delegate void DeleteEventHandler(DataTypeDefinition sender, EventArgs e); + + /// + /// Occurs when a macro is saved. + /// + public static event SaveEventHandler Saving; + protected virtual void OnSaving(EventArgs e) { + if (Saving != null) + Saving(this, e); + } + + public static event NewEventHandler New; + protected virtual void OnNew(EventArgs e) { + if (New != null) + New(this, e); + } + + public static event DeleteEventHandler Deleting; + protected virtual void OnDeleting(EventArgs e) { + if (Deleting != null) + Deleting(this, e); + } + + } +} \ No newline at end of file diff --git a/umbraco/cms/businesslogic/datatype/DefaultData.cs b/umbraco/cms/businesslogic/datatype/DefaultData.cs new file mode 100644 index 0000000000..a020f77915 --- /dev/null +++ b/umbraco/cms/businesslogic/datatype/DefaultData.cs @@ -0,0 +1,196 @@ +using System; +using System.Data; + +using umbraco.DataLayer; +using umbraco.BusinessLogic; +using umbraco.interfaces; +using System.Xml; + +namespace umbraco.cms.businesslogic.datatype +{ + /// + /// Default implementation of the IData interface that stores data inside the Umbraco database. + /// + public class DefaultData : IData, IDataWithPreview + { + private int m_PropertyId; + private object m_Value; + protected BaseDataType _dataType; + private bool m_PreviewMode; + + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + /// + /// Initializes a new instance of the class. + /// + /// Type of the data. + public DefaultData(BaseDataType DataType) + { + _dataType = DataType; + } + + /// + /// Initializes the object. + /// + /// The init value. + /// The init property id. + public virtual void Initialize(object InitValue, int InitPropertyId) + { + m_PropertyId = InitPropertyId; + m_Value = InitValue; + } + + /// + /// Loads the data value from the database. + /// + protected virtual void LoadValueFromDatabase() + { + m_Value = SqlHelper.ExecuteScalar("SELECT " + _dataType.DataFieldName + " FROM cmsPropertyData WHERE id = " + m_PropertyId); + } + + #region IData Members + + /// + /// Converts the data to XML. + /// + /// The data. + /// The data as XML. + public virtual XmlNode ToXMl(XmlDocument data) + { + string sValue = Value!=null ? Value.ToString() : String.Empty; + if (this._dataType.DBType == DBTypes.Ntext) + return data.CreateCDataSection(sValue); + return data.CreateTextNode(sValue); + } + + /// + /// Gets or sets the value. + /// + /// The value. + public virtual object Value + { + get + { + return m_Value; + } + set + { + if (!PreviewMode) + { + // Try to set null values if possible + try + { + if (value == null) + SqlHelper.ExecuteNonQuery("update cmsPropertyData set " + _dataType.DataFieldName + " = NULL where id = " + m_PropertyId); + else + SqlHelper.ExecuteNonQuery("update cmsPropertyData set " + _dataType.DataFieldName + " = @value where id = " + m_PropertyId, SqlHelper.CreateParameter("@value", value)); + } + catch (Exception e) + { + umbraco.BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Debug, umbraco.BusinessLogic.User.GetUser(0), -1, "Error updating item: " + e.ToString()); + if (value == null) value = ""; + SqlHelper.ExecuteNonQuery("update cmsPropertyData set " + _dataType.DataFieldName + " = @value where id = " + m_PropertyId, SqlHelper.CreateParameter("@value", value)); + } + } + m_Value = value; + } + } + + /// + /// Creates a new value. + /// + /// The property id. + public virtual void MakeNew(int PropertyId) + { + // this default implementation of makenew does not do anything snce + // it uses the default datastorage of umbraco, and the row is already populated by the "property" object + // If the datatype needs to have a default value, inherit this class and override this method. + } + + /// + /// Deletes this instance. + /// + public virtual void Delete() + { + // this default implementation of delete does not do anything snce + // it uses the default datastorage of umbraco, and the row is already deleted by the "property" object + } + + /// + /// Gets or sets the property id. + /// + /// The property id. + public virtual int PropertyId + { + get + { + return m_PropertyId; + } + set + { + m_PropertyId = value; + LoadValueFromDatabase(); + } + } + + // TODO: clean up Legacy - these are needed by the wysiwyeditor, in order to feed the richtextholder with version and nodeid + // solution, create a new version of the richtextholder, which does not depend on these. + public virtual Guid Version + { + get + { + using (IRecordsReader dr = SqlHelper.ExecuteReader("SELECT versionId FROM cmsPropertyData WHERE id = " + PropertyId)) + { + dr.Read(); + return dr.GetGuid("versionId"); + } + } + } + + /// + /// Gets the node id. + /// + /// The node id. + public virtual int NodeId + { + get + { + return SqlHelper.ExecuteScalar("Select contentNodeid from cmsPropertyData where id = " + PropertyId); + } + } + + #endregion + + #region IDataWithPreview Members + + /// + /// Gets or sets a value indicating whether preview mode is switched on. + /// In preview mode, the setter saves to a temporary location + /// instead of persistent storage, which the getter also reads from on subsequent access. + /// Switching off preview mode restores the persistent value. + /// + /// true if preview mode is switched on; otherwise, false. + public virtual bool PreviewMode + { + get + { + return m_PreviewMode; + } + set + { + if (m_PreviewMode != value) + { + // if preview mode is switched off, reload the value from persistent storage + if (!value) + LoadValueFromDatabase(); + m_PreviewMode = value; + } + } + } + + #endregion + } +} diff --git a/umbraco/cms/businesslogic/datatype/DefaultPreValueEditor.cs b/umbraco/cms/businesslogic/datatype/DefaultPreValueEditor.cs new file mode 100644 index 0000000000..b9e045f4bf --- /dev/null +++ b/umbraco/cms/businesslogic/datatype/DefaultPreValueEditor.cs @@ -0,0 +1,204 @@ +using System; +using System.Web.UI; +using System.Web.UI.WebControls; + +using umbraco.interfaces; +using umbraco.BusinessLogic; +using umbraco.DataLayer; + +namespace umbraco.cms.businesslogic.datatype +{ + public class DefaultPreValueEditor : PlaceHolder, interfaces.IDataPrevalue + { + // UI controls + private TextBox _textbox; + private DropDownList _dropdownlist; + + // referenced datatype + private cms.businesslogic.datatype.BaseDataType _datatype; + private BaseDataType _datatypeOld; + + private bool _isEnsured = false; + private string _prevalue; + private bool _displayTextBox; + + public static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + /// + /// The default editor for editing the build-in pre values in umbraco + /// + /// The DataType to be parsed + /// Whether to use the default text box + public DefaultPreValueEditor(cms.businesslogic.datatype.BaseDataType DataType, bool DisplayTextBox) + { + // state it knows its datatypedefinitionid + _displayTextBox = DisplayTextBox; + _datatype = DataType; + setupChildControls(); + } + + + private void setupChildControls() + { + _dropdownlist = new DropDownList(); + _dropdownlist.ID = "dbtype"; + + _textbox = new TextBox(); + _textbox.ID = "prevalues"; + _textbox.Visible = _displayTextBox; + + // put the childcontrols in context - ensuring that + // the viewstate is persisted etc. + Controls.Add(_textbox); + Controls.Add(_dropdownlist); + + _dropdownlist.Items.Add(DBTypes.Date.ToString()); + _dropdownlist.Items.Add(DBTypes.Integer.ToString()); + _dropdownlist.Items.Add(DBTypes.Ntext.ToString()); + _dropdownlist.Items.Add(DBTypes.Nvarchar.ToString()); + } + + protected override void OnLoad(EventArgs e) + { + base.OnLoad(e); + if (!Page.IsPostBack) + { + if (_datatype != null) + _dropdownlist.SelectedValue = _datatype.DBType.ToString(); + else + _dropdownlist.SelectedValue = _datatypeOld.DBType.ToString(); + + _textbox.Text = Prevalue; + } + } + + public string Prevalue + { + get + { + ensurePrevalue(); + if (_prevalue == null) + { + int defId; + if (_datatype != null) + defId = _datatype.DataTypeDefinitionId; + else if (_datatypeOld != null) + defId = _datatypeOld.DataTypeDefinitionId; + else + throw new ArgumentException("Datatype is not initialized"); + + _prevalue = + SqlHelper.ExecuteScalar("Select [value] from cmsDataTypePreValues where DataTypeNodeId = " + defId); + } + return _prevalue; + } + set + { + int defId; + if (_datatype != null) + defId = _datatype.DataTypeDefinitionId; + else if (_datatypeOld != null) + defId = _datatypeOld.DataTypeDefinitionId; + else + throw new ArgumentException("Datatype is not initialized"); + + _prevalue = value; + ensurePrevalue(); + IParameter[] SqlParams = new IParameter[] + { + SqlHelper.CreateParameter("@value", _textbox.Text), + SqlHelper.CreateParameter("@dtdefid", defId) + }; + // update prevalue + SqlHelper.ExecuteNonQuery("update cmsDataTypePreValues set [value] = @value where datatypeNodeId = @dtdefid", SqlParams); + } + } + + private void ensurePrevalue() + { + if (!_isEnsured) + { + + int defId; + if (_datatype != null) + defId = _datatype.DataTypeDefinitionId; + else if (_datatypeOld != null) + defId = _datatypeOld.DataTypeDefinitionId; + else + throw new ArgumentException("Datatype is not initialized"); + + + bool hasPrevalue = (SqlHelper.ExecuteScalar("select count(id) from cmsDataTypePreValues where dataTypeNodeId = " + defId) > 0); + IParameter[] SqlParams = new IParameter[] + { + SqlHelper.CreateParameter("@value", _textbox.Text), + SqlHelper.CreateParameter("@dtdefid", defId) + }; + if (!hasPrevalue) + { + SqlHelper.ExecuteNonQuery("insert into cmsDataTypePreValues (datatypenodeid,[value],sortorder,alias) values (@dtdefid,@value,0,'')", + SqlParams); + } + _isEnsured = true; + } + } + + public Control Editor + { + get { return this; } + } + + public void Save() + { + // save the prevalue data and get on with you life ;) + if (_datatype != null) + _datatype.DBType = (cms.businesslogic.datatype.DBTypes)Enum.Parse(typeof(cms.businesslogic.datatype.DBTypes), _dropdownlist.SelectedValue, true); + else if (_datatypeOld != null) + _datatypeOld.DBType = (DBTypes)Enum.Parse(typeof(DBTypes), _dropdownlist.SelectedValue, true); + + + if (_displayTextBox) + { + // If the prevalue editor has an prevalue textbox - save the textbox value as the prevalue + Prevalue = _textbox.Text; + } + } + + protected override void Render(HtmlTextWriter writer) + { + writer.Write("
" + ui.Text("dataBaseDatatype") + "
"); + _dropdownlist.RenderControl(writer); + writer.Write("
"); + + + if (_displayTextBox) + { + writer.Write("
" + ui.Text("prevalue") + "
"); + _textbox.RenderControl(writer); + writer.Write("
"); + } + + /* + writer.WriteLine("
"); + writer.WriteLine("Database datatype"); + _dropdownlist.RenderControl(writer); + writer.Write(""); + if (_displayTextBox) + writer.WriteLine("Prevalue: "); + _textbox.RenderControl(writer); + writer.WriteLine(""); + writer.Write("
"); + */ + + } + + public static string GetPrevalueFromId(int Id) + { + return SqlHelper.ExecuteScalar("Select [value] from cmsDataTypePreValues where id = @id", + SqlHelper.CreateParameter("@id", Id)); + } + } +} diff --git a/umbraco/cms/businesslogic/datatype/PreValues.cs b/umbraco/cms/businesslogic/datatype/PreValues.cs new file mode 100644 index 0000000000..da098627c0 --- /dev/null +++ b/umbraco/cms/businesslogic/datatype/PreValues.cs @@ -0,0 +1,208 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Text; +using System.Runtime.CompilerServices; + +using umbraco.DataLayer; +using umbraco.BusinessLogic; + + +namespace umbraco.cms.businesslogic.datatype +{ + /// + /// Any data type in umbraco can have PreValues, which is a simple Key/Value collection of items attached to a specific instance of the data type. + /// + public class PreValues + { + private static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + /// + /// Gets the pre values collection. + /// + /// The data type id. + /// + public static SortedList GetPreValues(int DataTypeId) + { + SortedList retval = new SortedList(); + IRecordsReader dr = SqlHelper.ExecuteReader( + "Select id, sortorder, [value] from cmsDataTypePreValues where DataTypeNodeId = @dataTypeId order by sortorder", + SqlHelper.CreateParameter("@dataTypeId", DataTypeId)); + + int counter = 0; + while (dr.Read()) + { + retval.Add(counter, new PreValue(dr.GetInt("id"), dr.GetInt("sortorder"), dr.GetString("value"))); + counter++; + } + dr.Close(); + return retval; + } + + } + + /// + /// A simple class for storing predefined values on a datatype. + /// A prevalue contains a value, a unique key and sort order. + /// + public class PreValue + { + private static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + /// + /// Initializes a new instance of the class. + /// + public PreValue() + { + + } + + /// + /// Saves this instance. + /// + [MethodImpl(MethodImplOptions.Synchronized)] + public void Save() + { + // Check for new + if (Id == 0) + { + // Update sortOrder + object tempSortOrder = SqlHelper.ExecuteScalar("select max(sortorder) from cmsDataTypePreValues where datatypenodeid = @dataTypeId", SqlHelper.CreateParameter("@dataTypeId", DataTypeId)); + int _sortOrder = 0; + + if (tempSortOrder!=null && int.TryParse(tempSortOrder.ToString(), out _sortOrder)) + SortOrder = _sortOrder + 1; + else + SortOrder = 1; + + IParameter[] SqlParams = new IParameter[] { + SqlHelper.CreateParameter("@value",Value), + SqlHelper.CreateParameter("@dtdefid",DataTypeId)}; + // The method is synchronized + SqlHelper.ExecuteNonQuery("INSERT INTO cmsDataTypePreValues (datatypenodeid,[value],sortorder,alias) VALUES (@dtdefid,@value,0,'')", SqlParams); + _id = SqlHelper.ExecuteScalar("SELECT MAX(id) FROM cmsDataTypePreValues"); + } + + SqlHelper.ExecuteNonQuery( + "update cmsDataTypePreValues set sortorder = @sortOrder, [value] = @value where id = @id", + SqlHelper.CreateParameter("@sortOrder", SortOrder), + SqlHelper.CreateParameter("@value", Value), + SqlHelper.CreateParameter("@id", Id)); + } + + /// + /// Initializes a new instance of the class. + /// + /// The id. + /// The sort order. + /// The value. + public PreValue(int Id, int SortOrder, string Value) + { + _id = Id; + _sortOrder = SortOrder; + _value = Value; + } + + /// + /// Initializes a new instance of the class. + /// + /// The id. + public PreValue(int Id) + { + _id = Id; + initialize(); + } + + /// + /// Initializes a new instance of the class. + /// + /// The data type id. + /// The value. + public PreValue(int DataTypeId, string Value) + { + object id = SqlHelper.ExecuteScalar( + "Select id from cmsDataTypePreValues where [Value] = @value and DataTypeNodeId = @dataTypeId", + SqlHelper.CreateParameter("@dataTypeId", DataTypeId), + SqlHelper.CreateParameter("@value", Value)); + if (id != null) + _id = int.Parse(id.ToString()); + + initialize(); + } + + /// + /// Initializes this instance. + /// + private void initialize() + { + IRecordsReader dr = SqlHelper.ExecuteReader( + "Select id, sortorder, [value] from cmsDataTypePreValues where id = @id order by sortorder", + SqlHelper.CreateParameter("@id", _id)); + if (dr.Read()) + { + _sortOrder = dr.GetInt("sortorder"); + _value = dr.GetString("value"); + } + dr.Close(); + } + + private int _dataTypeId; + + /// + /// Gets or sets the data type id. + /// + /// The data type id. + public int DataTypeId + { + get { return _dataTypeId; } + set { _dataTypeId = value; } + } + + + private int _id; + + /// + /// Gets or sets the id. + /// + /// The id. + public int Id + { + get { return _id; } + set { _id = value; } + } + + + private string _value; + + /// + /// Gets or sets the value. + /// + /// The value. + public string Value + { + get { return _value; } + set { _value = value; } + } + + + private int _sortOrder; + + /// + /// Gets or sets the sort order. + /// + /// The sort order. + public int SortOrder + { + get { return _sortOrder; } + set { _sortOrder = value; } + } + + } +} diff --git a/umbraco/cms/businesslogic/datatype/factory.cs b/umbraco/cms/businesslogic/datatype/factory.cs new file mode 100644 index 0000000000..b3e5b3dc0f --- /dev/null +++ b/umbraco/cms/businesslogic/datatype/factory.cs @@ -0,0 +1,106 @@ +using System; +using System.Collections; +using System.Web; + +using umbraco.BusinessLogic.Utils; +using umbraco.interfaces; +using System.Collections.Generic; + +namespace umbraco.cms.businesslogic.datatype.controls +{ + /// + /// IDataType factory, handles the registering and retrieval of IDatatypes. + /// + /// Then registering is done using reflection. + /// + public class Factory + { + #region Declarations + + private static readonly Dictionary _controls = new Dictionary(); + + #endregion + + #region Constructors + + static Factory() + { + Initialize(); + } + + #endregion + + /// + /// Retrieves the IDataType specified by it's unique ID + /// + /// The IDataType id + /// + public IDataType DataType(Guid DataTypeId) + { + return GetNewObject(DataTypeId); + } + + /// + /// Retrieves the IDataType specified by it's unique ID + /// + /// The IDataType id + /// + public IDataType GetNewObject(Guid DataEditorId) + { + IDataType newObject = Activator.CreateInstance(_controls[DataEditorId]) as IDataType; + return newObject; + } + + /// + /// Retrieve a complete list of all registered IDataType's + /// + /// A list of IDataType's + public IDataType[] GetAll() + { + IDataType[] retVal = new IDataType[_controls.Count]; + int c = 0; + + foreach (Guid id in _controls.Keys) + { + retVal[c] = GetNewObject(id); + c++; + } + + return retVal; + } + + private static void Initialize() + { + // Get all datatypes from interface + List types = TypeFinder.FindClassesOfType(true); + getDataTypes(types); + } + + private static void getDataTypes(List types) + { + foreach (Type t in types) + { + IDataType typeInstance = null; + try + { + if (t.IsVisible) + { + typeInstance = Activator.CreateInstance(t) as IDataType; + } + } + catch { } + if (typeInstance != null) + { + try + { + _controls.Add(typeInstance.Id, t); + } + catch (Exception ee) + { + BusinessLogic.Log.Add(umbraco.BusinessLogic.LogTypes.Error, -1, "Can't import datatype '" + t.FullName + "': " + ee.ToString()); + } + } + } + } + } +} \ No newline at end of file diff --git a/umbraco/cms/businesslogic/events/EventArgs.cs b/umbraco/cms/businesslogic/events/EventArgs.cs new file mode 100644 index 0000000000..928a59b2d6 --- /dev/null +++ b/umbraco/cms/businesslogic/events/EventArgs.cs @@ -0,0 +1,43 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace umbraco.cms.businesslogic { + //Content Event args + public class PublishEventArgs : System.ComponentModel.CancelEventArgs { } + public class MoveEventArgs : System.ComponentModel.CancelEventArgs { } + public class CopyEventArgs : System.ComponentModel.CancelEventArgs { } + public class AddToIndexEventArgs : System.ComponentModel.CancelEventArgs { } + public class UnPublishEventArgs : System.ComponentModel.CancelEventArgs { } + public class RollBackEventArgs : System.ComponentModel.CancelEventArgs { } + public class SendToPublishEventArgs : System.ComponentModel.CancelEventArgs { } + public class MoveToTrashEventArgs : System.ComponentModel.CancelEventArgs { } + + //Content Cache Event args + public class DocumentCacheEventArgs : System.ComponentModel.CancelEventArgs { } + public class RefreshContentEventArgs : System.ComponentModel.CancelEventArgs { } + + //Generel eventArgs + public class DeleteEventArgs : System.ComponentModel.CancelEventArgs { } + public class SaveEventArgs : System.ComponentModel.CancelEventArgs { } + public class NewEventArgs : System.ComponentModel.CancelEventArgs { } + + //Special Members Event args + public class AddToCacheEventArgs : System.ComponentModel.CancelEventArgs { } + public class RemoveFromCacheEventArgs : System.ComponentModel.CancelEventArgs { } + public class AddGroupEventArgs : System.ComponentModel.CancelEventArgs { } + public class RemoveGroupEventArgs : System.ComponentModel.CancelEventArgs { } + + //Tree node event args + public class NodeRenderEventArgs : System.ComponentModel.CancelEventArgs { } + + //Access event args + public class AddProtectionEventArgs : System.ComponentModel.CancelEventArgs { } + public class RemoveProtectionEventArgs : System.ComponentModel.CancelEventArgs { } + public class AddMemberShipRoleToDocumentEventArgs : System.ComponentModel.CancelEventArgs { } + public class RemoveMemberShipRoleFromDocumentEventArgs : System.ComponentModel.CancelEventArgs { } + public class RemoveMemberShipUserFromDocumentEventArgs : System.ComponentModel.CancelEventArgs { } + public class AddMembershipUserToDocumentEventArgs : System.ComponentModel.CancelEventArgs { } + + +} diff --git a/umbraco/cms/businesslogic/index/Indexer.cs b/umbraco/cms/businesslogic/index/Indexer.cs new file mode 100644 index 0000000000..1b92994ac6 --- /dev/null +++ b/umbraco/cms/businesslogic/index/Indexer.cs @@ -0,0 +1,263 @@ +using System; + +using Lucene.Net.Analysis; +using Lucene.Net.Analysis.Standard; +using Lucene.Net.Index; +using Lucene.Net.Documents; +using System.Collections; + +namespace umbraco.cms.businesslogic.index +{ + /// + /// Indexer contains methods for populating data to the internal search of the umbraco console + /// + /// + /// + public class Indexer + { + + private static string _indexDirectory = ""; + /// + /// The relative path tto the folder where umbraco stores the files used by the Lucene searchcomponent + /// + public static string RelativeIndexDir = umbraco.GlobalSettings.StorageDirectory + "/_systemUmbracoIndexDontDelete"; + + /// + /// The physical path to the folder where umbraco stores the files used by the Lucene searchcomponent + /// + public static string IndexDirectory + { + get + { + try + { + if (_indexDirectory == "") + _indexDirectory = GlobalSettings.FullpathToRoot + RelativeIndexDir; + return _indexDirectory; + } + catch + { + return ""; + } + } + set + { + _indexDirectory = value; + } + } + + + + /// + /// Method for accesing the Lucene indexwriter in the internal search + /// + /// If set to true, a new index is created + /// The lucene indexwriter + public static IndexWriter ContentIndex(bool ForceRecreation) + { + if (!ForceRecreation && System.IO.Directory.Exists(IndexDirectory) && + new System.IO.DirectoryInfo(IndexDirectory).GetFiles().Length > 1) + return new IndexWriter(IndexDirectory, new StandardAnalyzer(), false); + else + { + IndexWriter iw = new IndexWriter(IndexDirectory, new StandardAnalyzer(), true); + return iw; + } + } + + /// + /// Method for accessing the Lucene indexreader + /// + /// + public static IndexReader ContentIndexReader() + { + return IndexReader.Open(IndexDirectory); + } + + /// + /// Method for reindexing data in all documents of umbraco, this is a performaceheavy invocation and should be + /// used with care! + /// + public static void ReIndex(System.Web.HttpApplication context) + { + + if (context != null) + context.Application["indexerReindexing"] = "true"; + // Create new index + IndexWriter w = ContentIndex(true); + w.Close(); + + Guid[] documents = cms.businesslogic.web.Document.getAllUniquesFromObjectType(cms.businesslogic.web.Document._objectType); + + ResetIndexCounter(context, documents.Length.ToString()); + + foreach (Guid g in documents) + { + cms.businesslogic.web.Document d = + new cms.businesslogic.web.Document(g); + d.Index(true); + if (context != null) + { + context.Application["umbIndexerInfo"] = d.Text; + context.Application["umbIndexerCount"] = + ((int)context.Application["umbIndexerCount"]) + 1; + } + } + if (context != null) + { + context.Application["indexerReindexing"] = "done"; + context.Application["umbIndexerTotal"] = ""; + context.Application["umbIndexerCount"] = ""; + context.Application["umbIndexerInfo"] = "Done reindexing at " + DateTime.Now.ToShortDateString() + " " + DateTime.Now.ToShortTimeString(); + } + } + + public static void ResetIndexCounter(System.Web.HttpApplication context, string documents) + { + if (context != null) + { + context.Application["umbIndexerTotal"] = documents; + context.Application["umbIndexerCount"] = 0; + context.Application["umbIndexerInfo"] = ""; + } + } + + /// + /// Determines whether this instance is reindexing. + /// + /// + /// true if this instance is reindexing; otherwise, false. + /// + public static bool IsReindexing() + { + if (System.Web.HttpContext.Current != null) + if (System.Web.HttpContext.Current.Application["indexerReindexing"] != null && System.Web.HttpContext.Current.Application["indexerReindexing"].ToString() != "") + return true; + + return false; + } + + /// + /// Indexes the node. + /// + /// Type of the object. + /// The id. + /// The text. + /// Name of the user. + /// The create date. + /// The fields. + /// if set to true [optimize]. + public static void IndexNode(Guid ObjectType, int Id, string Text, string UserName, DateTime CreateDate, Hashtable Fields, bool Optimize) + { + // remove node if exists + RemoveNode(Id); + + // Add node + Document d = new Document(); // Lucene document, not umbraco Document + d.Add(new Field("Id", Id.ToString(), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + d.Add(new Field("Text", Text, Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.YES)); + d.Add(new Field("ObjectType", ObjectType.ToString(), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + d.Add(new Field("User", UserName, Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + d.Add(new Field("CreateDate", convertDate(CreateDate), Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + + // Icons + string icon = "default.png"; + if (ObjectType == cms.businesslogic.web.Document._objectType || + ObjectType == cms.businesslogic.media.Media._objectType || + ObjectType == cms.businesslogic.member.Member._objectType) + { + icon = new umbraco.cms.businesslogic.Content(Id).ContentType.IconUrl; + } + + // add icon + d.Add(new Field("Icon", icon, Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + + // Sort key + d.Add(new Field("SortText", Text, Field.Store.YES, Field.Index.UN_TOKENIZED, Field.TermVector.NO)); + + System.Text.StringBuilder total = new System.Text.StringBuilder(); + total.Append(Text + " "); + + // Add all fields + if (Fields != null) + { + IDictionaryEnumerator ide = Fields.GetEnumerator(); + while (ide.MoveNext()) + { + d.Add(new Field("field_" + ide.Key.ToString(), ide.Value.ToString(), Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.YES)); + total.Append(ide.Value.ToString()); + total.Append(" "); + } + } + total.Append(" id" + Id.ToString() + " "); + + IndexWriter writer = ContentIndex(false); + try + { + d.Add(new Field("Content", total.ToString(), Field.Store.YES, Field.Index.TOKENIZED, Field.TermVector.YES)); + writer.AddDocument(d); + writer.Optimize(); + writer.Close(); + } + catch (Exception ee) + { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, BusinessLogic.User.GetUser(0), Id, "Error indexing node: (" + ee.ToString() + ")"); + } + finally + { + writer.Close(); + } + + } + + /// + /// Removes the node from the index. + /// + /// The id. + public static void RemoveNode(int Id) + { + IndexReader ir = null; + try + { + ir = ContentIndexReader(); + ir.DeleteDocuments(new Term("Id", Id.ToString())); + } + catch (Exception ee) + { + BusinessLogic.Log.Add( + BusinessLogic.LogTypes.Error, + BusinessLogic.User.GetUser(0), + Id, + "Error removing node from umbraco index: '" + ee.ToString() + "'"); + } + finally + { + if (ir != null) + ir.Close(); + } + } + + private static string convertDate(DateTime Date) + { + try + { + string thisYear = Date.Year.ToString(); + if (thisYear.Length == 1) + thisYear = "0" + thisYear; + string thisMonth = Date.Month.ToString(); + if (thisMonth.Length == 1) + thisMonth = "0" + thisMonth; + string thisDay = Date.Day.ToString(); + if (thisDay.Length == 1) + thisDay = "0" + thisDay; + + return thisYear + thisMonth + thisDay; + } + catch + { + return ""; + } + } + } + +} diff --git a/umbraco/cms/businesslogic/index/SearchItem.cs b/umbraco/cms/businesslogic/index/SearchItem.cs new file mode 100644 index 0000000000..586acd6629 --- /dev/null +++ b/umbraco/cms/businesslogic/index/SearchItem.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace umbraco.cms.businesslogic.index { + + /// + /// Serializable access to items in the umbraco lucene index + /// + [Serializable] + public class SearchItem { + + /// + /// Initializes a new instance of the class. + /// + public SearchItem() { + } + + /// + /// Initializes a new instance of the class. + /// + /// The node id. + /// The title. + /// The icon. + /// The description. + /// The author. + /// The change date. + /// Type of the object. + /// The tags. + public SearchItem(int nodeId, string title, string icon, string description, string author, DateTime changeDate, Guid objectType, string[] tags) { + m_nodeId = nodeId; + m_Title = title; + m_icon = icon; + m_description = description; + m_author = author; + m_tags = tags; + } + + private int m_nodeId; + + /// + /// Gets or sets the node id. + /// + /// The node id. + public int NodeId { + get { return m_nodeId; } + set { m_nodeId = value; } + } + + private string m_Title; + + /// + /// Gets or sets the title. + /// + /// The title. + public string Title { + get { return m_Title; } + set { m_Title = value; } + } + + private Guid m_objectType; + + /// + /// Gets or sets the type of the object. + /// + /// The type of the object. + public Guid ObjectType { + get { return m_objectType; } + set { m_objectType = value; } + } + + private DateTime m_changeDate; + + /// + /// Gets or sets the change date. + /// + /// The change date. + public DateTime ChangeDate { + get { return m_changeDate; } + set { m_changeDate = value; } + } + + + private string m_icon; + + /// + /// Gets or sets the icon. + /// + /// The icon. + public string Icon { + get { return m_icon; } + set { m_icon = value; } + } + + private string m_description; + + /// + /// Gets or sets the description. + /// + /// The description. + public string Description { + get { return m_description; } + set { m_description = value; } + } + + private string m_author; + + /// + /// Gets or sets the author. + /// + /// The author. + public string Author { + get { return m_author; } + set { m_author = value; } + } + + private string[] m_tags; + + /// + /// Gets or sets the tags. + /// + /// The tags. + public string[] Tags { + get { return m_tags; } + set { m_tags = value; } + } + + + + + + + } + +} diff --git a/umbraco/cms/businesslogic/index/searcher.cs b/umbraco/cms/businesslogic/index/searcher.cs new file mode 100644 index 0000000000..45289d98c4 --- /dev/null +++ b/umbraco/cms/businesslogic/index/searcher.cs @@ -0,0 +1,93 @@ +using System; + +using System.Collections; +using Lucene.Net.Search; +using Lucene.Net.QueryParsers; +using Lucene.Net.Analysis; +using Lucene.Net.Analysis.Standard; +using System.Collections.Generic; +using System.Xml; + +namespace umbraco.cms.businesslogic.index { + /// + /// Searcher is used in the internal search (autosuggestion) in the umbraco administration console + /// + public class searcher { + + public static XmlDocument SearchAsXml(Guid ObjectType, string Keyword, int Max) + { + XmlDocument result = new XmlDocument(); + result.LoadXml(""); + List s = Search(ObjectType, Keyword, Max); + foreach(SearchItem si in s) { + XmlNode x = xmlHelper.addTextNode(result, "result", si.Description); + x.Attributes.Append(xmlHelper.addAttribute(result, "id", si.NodeId.ToString())); + x.Attributes.Append(xmlHelper.addAttribute(result, "icon", si.Icon)); + x.Attributes.Append(xmlHelper.addAttribute(result, "title", si.Title)); + x.Attributes.Append(xmlHelper.addAttribute(result, "author", si.Author)); + x.Attributes.Append(xmlHelper.addAttribute(result, "changeDate", si.ChangeDate.ToString("t"))); + result.DocumentElement.AppendChild(x); + } + + return result; + } + + /// + /// Method for retrieving a list of documents where the keyword is present + /// + /// [not implemented] search only available for documents + /// The word being searched for + /// The maximum limit on results returned + /// A list of documentnames indexed by the id of the document + public static List Search(Guid ObjectType, string Keyword, int Max) { + List items = new List(); + + IndexSearcher searcher = null; + try { + searcher = new IndexSearcher(index.Indexer.IndexDirectory); + QueryParser parser = new QueryParser("Content", new StandardAnalyzer()); + Query query = parser.Parse(Keyword); + + Hits hits; + + // Sorting + SortField[] sf = { new SortField("SortText") }; + hits = searcher.Search(query, new Sort(sf)); + if (hits.Length() < Max) + Max = hits.Length(); + + for (int i = 0; i < Max; i++) { + try { + string CreateDate = hits.Doc(i).Get("CreateDate"); + DateTime itemDate = new DateTime(1900, 1, 1); + DateTime.TryParse(CreateDate, out itemDate); + items.Add(new SearchItem( + int.Parse(hits.Doc(i).Get("Id")), + hits.Doc(i).Get("Text"), + "doc.png", + "", + "", + itemDate, + new Guid(hits.Doc(i).Get("ObjectType")), + null)); + } catch (Exception ee) { + + umbraco.cms.businesslogic.index.Indexer.ReIndex((System.Web.HttpApplication)System.Web.HttpContext.Current.ApplicationInstance); + throw new Exception("Error adding search item", ee); + } + } + + } catch (Exception ee) { + // index is broken, fix + + throw ee; + } finally { + if (searcher != null) + searcher.Close(); + } + + return items; + + } + } +} diff --git a/umbraco/cms/businesslogic/language/Language.cs b/umbraco/cms/businesslogic/language/Language.cs new file mode 100644 index 0000000000..acae904212 --- /dev/null +++ b/umbraco/cms/businesslogic/language/Language.cs @@ -0,0 +1,324 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Globalization; +using System.Xml; +using umbraco.cms.businesslogic.cache; +using umbraco.DataLayer; +using umbraco.BusinessLogic; + +namespace umbraco.cms.businesslogic.language +{ + /// + /// The language class contains methods for creating and modifing installed languages. + /// + /// A language is used internal in the umbraco console for displaying languagespecific text and + /// in the public website for language/country specific representation of ex. date/time, currencies. + /// + /// Besides by using the built in Dictionary you are able to store language specific bits and pieces of translated text + /// for use in templates. + /// + public class Language + { + private int _id; + private string _name = ""; + private string _friendlyName; + private string _cultureAlias; + + + private static string _ConnString = GlobalSettings.DbDSN; + private static object getLanguageSyncLock = new object(); + + private static readonly string UmbracoLanguageCacheKey = "UmbracoPropertyTypeCache"; + + + /// + /// Gets the SQL helper. + /// + /// The SQL helper. + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + + /// + /// Initializes a new instance of the class. + /// + /// The id. + public Language(int id) + { + _id = id; + _cultureAlias = Cache.GetCacheItem("UmbracoLanguage" + id, getLanguageSyncLock, TimeSpan.FromMinutes(60), + delegate + { + return SqlHelper.ExecuteScalar( + "select languageISOCode from umbracoLanguage where id = @LanguageId", SqlHelper.CreateParameter("@LanguageId", id)); + }); + + updateNames(); + } + + + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public virtual void Save() + { + SaveEventArgs e = new SaveEventArgs(); + FireBeforeSave(e); + + if (!e.Cancel) + { + Cache.ClearCacheItem("UmbracoLanguage" + id); + FireAfterSave(e); + } + } + + private void updateNames() + { + try + { + CultureInfo ci = new CultureInfo(_cultureAlias); + _friendlyName = ci.DisplayName; + } + catch + { + _friendlyName = _name + "(unknown Culture)"; + } + } + + /// + /// Creates a new language given the culture code - ie. da-dk (denmark) + /// + /// Culturecode of the language + public static void MakeNew(string CultureCode) + { + if (new CultureInfo(CultureCode) != null) + { + SqlHelper.ExecuteNonQuery( + "insert into umbracoLanguage (languageISOCode) values (@CultureCode)", + SqlHelper.CreateParameter("@CultureCode", CultureCode)); + + NewEventArgs e = new NewEventArgs(); + GetByCultureCode(CultureCode).OnNew(e); + + } + } + + /// + /// Deletes the current Language. + /// + /// Notice: this can have various sideeffects - use with care. + /// + public void Delete() + { + DeleteEventArgs e = new DeleteEventArgs(); + FireBeforeDelete(e); + + if (!e.Cancel) + { + Cache.ClearCacheItem("UmbracoLanguage" + id); + SqlHelper.ExecuteNonQuery("delete from umbracoLanguage where id = @id", + SqlHelper.CreateParameter("@id", id)); + FireAfterDelete(e); + } + } + + /// + /// Method for accessing all installed languagess + /// + public static Language[] getAll + { + get + { + List tmp = new List(); + + using (IRecordsReader dr = SqlHelper.ExecuteReader("select id from umbracoLanguage")) + { + while (dr.Read()) + tmp.Add(new Language(dr.GetShort("id"))); + } + + return tmp.ToArray(); + } + } + + /// + /// Gets the language by its culture code, if no language is found, null is returned + /// + /// The culture code. + /// + public static Language GetByCultureCode(String CultureCode) + { + if (new CultureInfo(CultureCode) != null) + { + return Cache.GetCacheItem(GetCacheKeyByCultureAlias(CultureCode), getLanguageSyncLock, + TimeSpan.FromHours(6), + delegate + { + try + { + object sqlLangId = + SqlHelper.ExecuteScalar( + "select id from umbracoLanguage where languageISOCode = @CultureCode", + SqlHelper.CreateParameter("@CultureCode", CultureCode)); + if (sqlLangId != null) + { + int langId; + if (int.TryParse(sqlLangId.ToString(), out langId)) + { + return new Language(langId); + } + } + return null; + } + catch + { + return null; + } + }); + } + + return null; + } + + /// + /// The id used by umbraco to identify the language + /// + public int id + { + get { return _id; } + } + + /// + /// The culture code of the language: ie. Danish/Denmark da-dk + /// + public string CultureAlias + { + get { return _cultureAlias; } + set + { + _cultureAlias = value; + SqlHelper.ExecuteNonQuery( + "update umbracoLanguage set languageISOCode = @cultureAlias where id = @id", SqlHelper.CreateParameter("@id", id), + SqlHelper.CreateParameter("@cultureAlias", _cultureAlias)); + updateNames(); + } + } + + /// + /// The user friendly name of the language/country + /// + public string FriendlyName + { + get { return _friendlyName; } + } + + /// + /// Converts the instance to XML + /// + /// The xml document. + /// + public System.Xml.XmlNode ToXml(XmlDocument xd) + { + XmlNode language = xd.CreateElement("Language"); + language.Attributes.Append(xmlHelper.addAttribute(xd, "Id", this.id.ToString())); + language.Attributes.Append(xmlHelper.addAttribute(xd, "CultureAlias", this.CultureAlias)); + language.Attributes.Append(xmlHelper.addAttribute(xd, "FriendlyName", this.FriendlyName)); + + return language; + } + + + /// + /// Imports a language from XML + /// + /// The XML data. + /// + public static Language Import(XmlNode xmlData) + { + string cA = xmlData.Attributes["CultureAlias"].Value; + if (Language.GetByCultureCode(cA) == null) + { + Language.MakeNew(cA); + return Language.GetByCultureCode(cA); + } + else + { + return null; + } + } + + + private void InvalidateCache() + { + Cache.ClearCacheItem(GetCacheKey(this.id)); + Cache.ClearCacheItem(GetCacheKeyByCultureAlias(this.CultureAlias)); + } + + private static string GetCacheKey(int id) + { + return UmbracoLanguageCacheKey + id; + } + + private static string GetCacheKeyByCultureAlias(string cultureAlias) + { + return UmbracoLanguageCacheKey + cultureAlias; + } + + //EVENTS + /// + /// The save event handler + /// + public delegate void SaveEventHandler(Language sender, SaveEventArgs e); + /// + /// The new event handler + /// + public delegate void NewEventHandler(Language sender, NewEventArgs e); + /// + /// The delete event handler + /// + public delegate void DeleteEventHandler(Language sender, DeleteEventArgs e); + + + /// + /// Occurs when a language is saved. + /// + public static event SaveEventHandler BeforeSave; + protected virtual void FireBeforeSave(SaveEventArgs e) + { + if (BeforeSave != null) + BeforeSave(this, e); + } + + public static event SaveEventHandler AfterSave; + protected virtual void FireAfterSave(SaveEventArgs e) + { + if (AfterSave != null) + AfterSave(this, e); + } + + public static event NewEventHandler New; + protected virtual void OnNew(NewEventArgs e) + { + if (New != null) + New(this, e); + } + + public static event DeleteEventHandler BeforeDelete; + protected virtual void FireBeforeDelete(DeleteEventArgs e) + { + if (BeforeDelete != null) + BeforeDelete(this, e); + } + + public static event DeleteEventHandler AfterDelete; + protected virtual void FireAfterDelete(DeleteEventArgs e) + { + if (AfterDelete != null) + AfterDelete(this, e); + } + } +} \ No newline at end of file diff --git a/umbraco/cms/businesslogic/language/Text.cs b/umbraco/cms/businesslogic/language/Text.cs new file mode 100644 index 0000000000..e704c664f9 --- /dev/null +++ b/umbraco/cms/businesslogic/language/Text.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections; +using System.Data; + +using umbraco.DataLayer; +using umbraco.BusinessLogic; + +namespace umbraco.cms.businesslogic.language +{ + /// + /// Item class contains method for accessing language translated text, its a generic component which + /// can be used for storing language translated content, all items are associated to an unique identifier (Guid) + /// + /// The data is cached and are usable in the public website. + /// + /// Primarily used by the built-in dictionary + /// + /// + public class Item + { + private static Hashtable _items = Hashtable.Synchronized(new Hashtable()); + private static bool isInitialized = false; + private static string _Connstring = GlobalSettings.DbDSN; + + /// + /// Gets the SQL helper. + /// + /// The SQL helper. + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + private static void ensureData() + { + if (!isInitialized) + { + // load all data + IRecordsReader dr = SqlHelper.ExecuteReader("Select LanguageId, UniqueId,[value] from cmsLanguageText order by UniqueId"); + + while (dr.Read()) + { + int LanguageId = dr.GetInt("LanguageId"); + Guid UniqueId = dr.GetGuid("UniqueId"); + string text = dr.GetString("value"); + updateCache(LanguageId, UniqueId, text); + } + isInitialized = true; + dr.Close(); + } + } + + private static void updateCache(int LanguageId, Guid key, string text) + { + // test if item already exist in items and update internal data or insert new internal data + if (_items.ContainsKey(key)) + { + System.Collections.Hashtable languagevalues = (System.Collections.Hashtable)_items[key]; + // check if the current language key is used + if (languagevalues.ContainsKey(LanguageId)) + { + languagevalues[LanguageId] = text; + } + else + { + languagevalues.Add(LanguageId, text); + } + } + else + { + // insert + Hashtable languagevalues = Hashtable.Synchronized(new Hashtable()); + languagevalues.Add(LanguageId, text); + _items.Add(key, languagevalues); + } + } + + + /// + /// Retrieves the value of a languagetranslated item given the key + /// + /// Unique identifier + /// Umbraco languageid + /// The language translated text + public static string Text(Guid key, int LanguageId) + { + if (hasText(key, LanguageId)) + return ((System.Collections.Hashtable)_items[key])[LanguageId].ToString(); + else + throw new ArgumentException("Key being requested does not exist"); + } + + /// + /// + /// + /// Unique identifier + /// Umbraco language id + /// returns True if there is a value associated to the unique identifier with the specified language + public static bool hasText(Guid key, int LanguageId) + { + ensureData(); + if (_items.ContainsKey(key)) + { + System.Collections.Hashtable tmp = (System.Collections.Hashtable)_items[key]; + return tmp.ContainsKey(LanguageId); + } + return false; + } + /// + /// Updates the value of the language translated item, throws an exeption if the + /// key does not exist + /// + /// Umbraco language id + /// Unique identifier + /// The new dictionaryvalue + + public static void setText(int LanguageId, Guid key, string value) + { + ensureData(); + if (!hasText(key, LanguageId)) throw new ArgumentException("Key does not exist"); + + updateCache(LanguageId, key, value); + SqlHelper.ExecuteNonQuery("Update cmsLanguageText set [value] = @value where LanguageId = @languageId And UniqueId = @key", + SqlHelper.CreateParameter("@value", value), + SqlHelper.CreateParameter("@languageId", LanguageId), + SqlHelper.CreateParameter("@key", key)); + } + + /// + /// Adds a new languagetranslated item to the collection + /// + /// + /// Umbraco languageid + /// Unique identifier + /// + public static void addText(int LanguageId, Guid key, string value) + { + ensureData(); + if (hasText(key, LanguageId)) throw new ArgumentException("Key being add'ed already exists"); + updateCache(LanguageId, key, value); + SqlHelper.ExecuteNonQuery("Insert Into cmsLanguageText (languageId,UniqueId,[value]) values (@languageId, @key, @value)", + SqlHelper.CreateParameter("@languageId", LanguageId), + SqlHelper.CreateParameter("@key", key), + SqlHelper.CreateParameter("@value", value)); + } + /// + /// Removes all languagetranslated texts associated to the unique identifier. + /// + /// Unique identifier + public static void removeText(Guid key) + { + // remove from cache + _items.Remove(key); + // remove from database + SqlHelper.ExecuteNonQuery("Delete from cmsLanguageText where UniqueId = @key", + SqlHelper.CreateParameter("@key", key)); + } + } +} \ No newline at end of file diff --git a/umbraco/cms/businesslogic/macro/Macro.cs b/umbraco/cms/businesslogic/macro/Macro.cs new file mode 100644 index 0000000000..c138846a4b --- /dev/null +++ b/umbraco/cms/businesslogic/macro/Macro.cs @@ -0,0 +1,472 @@ +using System; +using System.Data; +using System.Xml; +using System.Runtime.CompilerServices; + +using umbraco.DataLayer; +using umbraco.BusinessLogic; + + +namespace umbraco.cms.businesslogic.macro +{ + /// + /// The Macro component are one of the umbraco essentials, used for drawing dynamic content in the public website of umbraco. + /// + /// A Macro is a placeholder for either a xsl transformation, a custom .net control or a .net usercontrol. + /// + /// The Macro is representated in templates and content as a special html element, which are being parsed out and replaced with the + /// output of either the .net control or the xsl transformation when a page is being displayed to the visitor. + /// + /// A macro can have a variety of properties which are used to transfer userinput to either the usercontrol/custom control or the xsl + /// + /// + public class Macro + { + + int _id; + bool _useInEditor; + bool _renderContent; + bool _cachePersonalized; + bool _cacheByPage; + + int _refreshRate; + string _alias; + string _name; + string _assembly; + string _type; + string _xslt; + string _python; + + MacroProperty[] _properties; + + bool m_propertiesLoaded = false; + + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + /// + /// id + /// + public int Id + { + get {return _id;} + } + + /// + /// If set to true, the macro can be inserted on documents using the richtexteditor. + /// + public bool UseInEditor + { + get {return _useInEditor;} + set + { + _useInEditor = value; + SqlHelper.ExecuteNonQuery("update cmsMacro set macroUseInEditor = @macroAlias where id = @id", SqlHelper.CreateParameter("@macroAlias", value), SqlHelper.CreateParameter("@id", this.Id)); + } + } + + /// + /// The cache refreshrate - the maximum amount of time the macro should remain cached in the umbraco + /// runtime layer. + /// + /// The macro caches are refreshed whenever a document is changed + /// + public int RefreshRate + { + get {return _refreshRate;} + set + { + _refreshRate = value; + SqlHelper.ExecuteNonQuery("update cmsMacro set macroRefreshRate = @macroAlias where id = @id", SqlHelper.CreateParameter("@macroAlias", value), SqlHelper.CreateParameter("@id", this.Id)); + } + } + + /// + /// The alias of the macro - are used for retrieving the macro when parsing the element, + /// by using the alias instead of the Id, it's possible to distribute macroes from one installation to another - since the id + /// is given by an autoincrementation in the database table, and might be used by another macro in the foreing umbraco + /// + public string Alias + { + get {return _alias;} + set + { + _alias = value; + SqlHelper.ExecuteNonQuery("update cmsMacro set macroAlias = @macroAlias where id = @id", SqlHelper.CreateParameter("@macroAlias", value), SqlHelper.CreateParameter("@id", this.Id)); + } + } + + /// + /// The userfriendly name + /// + public string Name + { + get {return _name;} + set + { + _name = value; + SqlHelper.ExecuteNonQuery("update cmsMacro set macroName = @macroAlias where id = @id", SqlHelper.CreateParameter("@macroAlias", value), SqlHelper.CreateParameter("@id", this.Id)); + } + } + + /// + /// If the macro is a wrapper for a custom control, this is the assemly name from which to load the macro + /// + /// specified like: /bin/mydll (without the .dll extension) + /// + public string Assembly + { + get {return _assembly;} + set + { + _assembly = value; + SqlHelper.ExecuteNonQuery("update cmsMacro set macroScriptAssembly = @macroAlias where id = @id", SqlHelper.CreateParameter("@macroAlias", value), SqlHelper.CreateParameter("@id", this.Id)); + } + } + + /// + /// The relative path to the usercontrol + /// + /// Specified like: /usercontrols/myusercontrol.ascx (with the .ascx postfix) + /// + public string Type + { + get {return _type;} + set + { + _type = value; + SqlHelper.ExecuteNonQuery("update cmsMacro set macroScriptType = @macroAlias where id = @id", SqlHelper.CreateParameter("@macroAlias", value), SqlHelper.CreateParameter("@id", this.Id)); + } + } + + /// + /// The xsl file used to transform content + /// + /// Umbraco assumes that the xslfile is present in the "/xslt" folder + /// + public string Xslt + { + get {return _xslt;} + set + { + _xslt = value; + SqlHelper.ExecuteNonQuery("update cmsMacro set macroXSLT = @macroXslt where id = @id", SqlHelper.CreateParameter("@macroXslt", value), SqlHelper.CreateParameter("@id", this.Id)); + } + } + + /// + /// The python file used to be executed + /// + /// Umbraco assumes that the python file is present in the "/python" folder + /// + public string Python { + get { return _python; } + set { + _python = value; + SqlHelper.ExecuteNonQuery("update cmsMacro set macroPython = @macroPython where id = @id", SqlHelper.CreateParameter("@macroPython", value), SqlHelper.CreateParameter("@id", this.Id)); + } + } + + /// + /// The python file used to be executed + /// + /// Umbraco assumes that the python file is present in the "/python" folder + /// + public bool RenderContent { + get { return _renderContent; } + set { + _renderContent = value; + SqlHelper.ExecuteNonQuery("update cmsMacro set macroDontRender = @macroDontRender where id = @id", SqlHelper.CreateParameter("@macroDontRender", !value), SqlHelper.CreateParameter("@id", this.Id)); + } + } + + /// + /// Gets or sets a value indicating whether [cache personalized]. + /// + /// true if [cache personalized]; otherwise, false. + public bool CachePersonalized { + get { return _cachePersonalized; } + set { + _cachePersonalized = value; + SqlHelper.ExecuteNonQuery("update cmsMacro set macroCachePersonalized = @macroCachePersonalized where id = @id", SqlHelper.CreateParameter("@macroCachePersonalized", value), SqlHelper.CreateParameter("@id", this.Id)); + } + } + + /// + /// Gets or sets a value indicating whether the macro is cached for each individual page. + /// + /// true if [cache by page]; otherwise, false. + public bool CacheByPage { + get { return _cacheByPage; } + set { + _cacheByPage = value; + SqlHelper.ExecuteNonQuery("update cmsMacro set macroCacheByPage = @macroCacheByPage where id = @id", SqlHelper.CreateParameter("@macroCacheByPage", value), SqlHelper.CreateParameter("@id", this.Id)); + } + } + + /// + /// Properties which are used to send parameters to the xsl/usercontrol/customcontrol of the macro + /// + public MacroProperty[] Properties + { + get { + // Add lazy loading + if (!m_propertiesLoaded) + { + _properties = MacroProperty.GetProperties(Id); + m_propertiesLoaded = true; + } + return _properties; + } + } + + /// + /// Macro initializer + /// + public Macro() {} + + /// + /// Macro initializer + /// + /// The id of the macro + public Macro(int Id) + { + _id = Id; + setup(); + } + + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public virtual void Save() + { + //event + SaveEventArgs e = new SaveEventArgs(); + FireBeforeSave(e); + + //Stub for now.. + + if (!e.Cancel) { + FireAfterSave(e); + } + } + + + /// + /// Deletes the current macro + /// + public void Delete() + { + //event + DeleteEventArgs e = new DeleteEventArgs(); + FireBeforeDelete(e); + + if (!e.Cancel) { + foreach (MacroProperty p in this.Properties) + p.Delete(); + SqlHelper.ExecuteNonQuery("delete from cmsMacro where id = @id", SqlHelper.CreateParameter("@id", this._id)); + + FireAfterDelete(e); + } + } + + public static Macro Import(XmlNode n) { + + Macro m = MakeNew(xmlHelper.GetNodeValue(n.SelectSingleNode("name"))); + try { + + + m.Alias = xmlHelper.GetNodeValue(n.SelectSingleNode("alias")); + m.Assembly = xmlHelper.GetNodeValue(n.SelectSingleNode("scriptAssembly")); + m.Type = xmlHelper.GetNodeValue(n.SelectSingleNode("scriptType")); + m.Xslt = xmlHelper.GetNodeValue(n.SelectSingleNode("xslt")); + m.RefreshRate = int.Parse(xmlHelper.GetNodeValue(n.SelectSingleNode("refreshRate"))); + try { + m.UseInEditor = bool.Parse(xmlHelper.GetNodeValue(n.SelectSingleNode("useInEditor"))); + } catch (Exception macroExp) { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, BusinessLogic.User.GetUser(0), -1, "Error creating macro property: " + macroExp.ToString()); + } + + // macro properties + foreach (XmlNode mp in n.SelectNodes("properties/property")) { + try { + cms.businesslogic.macro.MacroProperty.MakeNew( + m, + bool.Parse(mp.Attributes.GetNamedItem("show").Value), + mp.Attributes.GetNamedItem("alias").Value, + mp.Attributes.GetNamedItem("name").Value, + new cms.businesslogic.macro.MacroPropertyType(mp.Attributes.GetNamedItem("propertyType").Value) + ); + } catch (Exception macroPropertyExp) { + BusinessLogic.Log.Add(BusinessLogic.LogTypes.Error, BusinessLogic.User.GetUser(0), -1, "Error creating macro property: " + macroPropertyExp.ToString()); + } + } + + m.Save(); + } catch { return null; } + + return m; + } + + private void setup() + { + using (IRecordsReader dr = SqlHelper.ExecuteReader("select macroUseInEditor, macroRefreshRate, macroAlias, macroName, macroScriptType, macroScriptAssembly, macroXSLT, macroPython, macroDontRender, macroCacheByPage, macroCachePersonalized from cmsMacro where id = @id", SqlHelper.CreateParameter("@id", _id))) + { + if(dr.Read()) + { + _useInEditor = dr.GetBoolean("macroUseInEditor"); + _refreshRate = dr.GetInt("macroRefreshRate"); + _alias = dr.GetString("macroAlias"); + _name = dr.GetString("macroName"); + _assembly = dr.GetString("macroScriptAssembly"); + _type = dr.GetString("macroScriptType"); + _xslt = dr.GetString("macroXSLT"); + _python = dr.GetString("macroPython"); + + _cacheByPage = dr.GetBoolean("macroCacheByPage"); + _cachePersonalized = dr.GetBoolean("macroCachePersonalized"); + _renderContent = !dr.GetBoolean("macroDontRender"); + } + } + } + + /// + /// Get an xmlrepresentation of the macro, used for exporting the macro to a package for distribution + /// + /// Current xmldocument context + /// An xmlrepresentation of the macro + public XmlNode ToXml(XmlDocument xd) { + + XmlNode doc = xd.CreateElement("macro"); + + // info section + doc.AppendChild(xmlHelper.addTextNode(xd, "name", this.Name)); + doc.AppendChild(xmlHelper.addTextNode(xd, "alias", this.Alias)); + doc.AppendChild(xmlHelper.addTextNode(xd, "scriptType", this.Type)); + doc.AppendChild(xmlHelper.addTextNode(xd, "scriptAssembly", this.Assembly)); + doc.AppendChild(xmlHelper.addTextNode(xd, "xslt", this.Xslt)); + doc.AppendChild(xmlHelper.addTextNode(xd, "useInEditor", this.UseInEditor.ToString())); + doc.AppendChild(xmlHelper.addTextNode(xd, "refreshRate", this.RefreshRate.ToString())); + + // properties + XmlNode props = xd.CreateElement("properties"); + foreach (MacroProperty p in this.Properties) + props.AppendChild(p.ToXml(xd)); + doc.AppendChild(props); + + return doc; + } + + public void RefreshProperties() + { + m_propertiesLoaded = false; + } + + + #region STATICS + + /// + /// Creates a new macro given the name + /// + /// Userfriendly name + /// The newly macro + [MethodImpl(MethodImplOptions.Synchronized)] + public static Macro MakeNew(string Name) + { + int macroId = 0; + // The method is synchronized + SqlHelper.ExecuteNonQuery("INSERT INTO cmsMacro (macroAlias, macroName) values (@macroAlias, @macroName)", + SqlHelper.CreateParameter("@macroAlias", Name.Replace(" ", String.Empty)), + SqlHelper.CreateParameter("@macroName", Name)); + macroId = SqlHelper.ExecuteScalar("SELECT MAX(id) FROM cmsMacro"); + + Macro newMacro = new Macro(macroId); + + //fire new event + NewEventArgs e = new NewEventArgs(); + newMacro.OnNew(e); + + return newMacro; + } + + /// + /// Retrieve all macroes + /// + /// A list of all macroes + public static Macro[] GetAll() + { + int total = SqlHelper.ExecuteScalar("select count(*) from cmsMacro"); + int count = 0; + IRecordsReader dr = SqlHelper.ExecuteReader("select id from cmsMacro order by macroName"); + Macro[] retval = new Macro[total]; + while (dr.Read()) + { + retval[count] = new Macro(dr.GetInt("id")); + count++; + } + dr.Close(); + return retval; + } + + /// + /// Static contructor for retrieving a macro given an alias + /// + /// The alias of the macro + /// If the macro with the given alias exists, it returns the macro, else null + public static Macro GetByAlias(string Alias) + { + try + { + return new Macro(SqlHelper.ExecuteScalar("select id from cmsMacro where macroAlias = @alias", SqlHelper.CreateParameter("@alias", Alias))); + } + catch + { + return null; + } + } + + //Macro events + + //Delegates + public delegate void SaveEventHandler(Macro sender, SaveEventArgs e); + public delegate void NewEventHandler(Macro sender, NewEventArgs e); + public delegate void DeleteEventHandler(Macro sender, DeleteEventArgs e); + + /// + /// Occurs when a macro is saved. + /// + public static event SaveEventHandler BeforeSave; + protected virtual void FireBeforeSave(SaveEventArgs e) { + if (BeforeSave != null) + BeforeSave(this, e); + } + + public static event SaveEventHandler AfterSave; + protected virtual void FireAfterSave(SaveEventArgs e) { + if (AfterSave != null) + AfterSave(this, e); + } + + public static event NewEventHandler New; + protected virtual void OnNew(NewEventArgs e) { + if (New != null) + New(this, e); + } + + public static event DeleteEventHandler BeforeDelete; + protected virtual void FireBeforeDelete(DeleteEventArgs e) { + if (BeforeDelete != null) + BeforeDelete(this, e); + } + + public static event DeleteEventHandler AfterDelete; + protected virtual void FireAfterDelete(DeleteEventArgs e) { + if (AfterDelete != null) + AfterDelete(this, e); + } + #endregion + } +} diff --git a/umbraco/cms/businesslogic/macro/MacroComment.cs b/umbraco/cms/businesslogic/macro/MacroComment.cs new file mode 100644 index 0000000000..8fb5665f7f --- /dev/null +++ b/umbraco/cms/businesslogic/macro/MacroComment.cs @@ -0,0 +1,36 @@ +using System; + +namespace umbraco.cms.businesslogic.macro +{ + /// + /// Not implemented + /// + + [AttributeUsage(AttributeTargets.Class | + AttributeTargets.Constructor | + AttributeTargets.Field | + AttributeTargets.Method | + AttributeTargets.Property, + AllowMultiple = true)] + public class MacroComment : System.Attribute + { + private string _comment; + + /// + /// Not implemented + /// + public string Comment + { + set {_comment = value;} + get {return _comment;} + } + /// + /// Not implemented + /// + /// Not implemented + public MacroComment(string Comment) + { + _comment = Comment; + } + } +} diff --git a/umbraco/cms/businesslogic/macro/MacroProperty.cs b/umbraco/cms/businesslogic/macro/MacroProperty.cs new file mode 100644 index 0000000000..5ed291f1b1 --- /dev/null +++ b/umbraco/cms/businesslogic/macro/MacroProperty.cs @@ -0,0 +1,233 @@ +using System; +using System.Data; +using System.Xml; +using System.Runtime.CompilerServices; + +using umbraco.DataLayer; +using umbraco.BusinessLogic; + + +namespace umbraco.cms.businesslogic.macro +{ + /// + /// The macro property is used by macroes to communicate/transfer userinput to an instance of a macro. + /// + /// It contains information on which type of data is inputted aswell as the userinterface used to input data + /// + /// A MacroProperty uses it's MacroPropertyType to define which underlaying component should be used when + /// rendering the MacroProperty editor aswell as which datatype its containing. + /// + public class MacroProperty + { + + int _id; + int _sortOrder; + bool _public; + string _alias; + string _name; + cms.businesslogic.macro.Macro m_macro; + cms.businesslogic.macro.MacroPropertyType _type; + + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + /// + /// Initializes a new instance of the class. + /// + public MacroProperty() + { + } + + /// + /// Constructor + /// + /// Id + public MacroProperty(int Id) + { + _id = Id; + setup(); + } + + /// + /// The sortorder + /// + public int SortOrder + { + get { return _sortOrder; } + set { _sortOrder = value; } + } + + /// + /// If set to true, the user will be presented with an editor to input data. + /// + /// If not, the field can be manipulated by a default value given by the MacroPropertyType, this is s + /// + public bool Public + { + get { return _public; } + set { _public = value; } + } + + /// + /// The alias if of the macroproperty, this is used in the special macro element + /// + /// + /// + public string Alias + { + get { return _alias; } + set { _alias = value; } + } + + /// + /// The userfriendly name + /// + public string Name + { + get { return _name; } + set { _name = value; } + } + + /// + /// Gets the id. + /// + /// The id. + public int Id + { + get { return _id; } + } + + /// + /// Gets or sets the macro. + /// + /// The macro. + public Macro Macro + { + get { return m_macro; } + set { m_macro = value; } + } + + /// + /// The basetype which defines which component is used in the UI for editing content + /// + public MacroPropertyType Type + { + get { return _type; } + set { _type = value; } + } + + + private void setup() + { + using (IRecordsReader dr = SqlHelper.ExecuteReader("select macro, macroPropertyHidden, macroPropertyType, macroPropertySortOrder, macroPropertyAlias, macroPropertyName from cmsMacroProperty where id = @id", SqlHelper.CreateParameter("@id", _id))) + { + if (dr.Read()) + { + m_macro = new Macro(dr.GetInt("macro")); + _public = dr.GetBoolean("macroPropertyHidden"); + _sortOrder = (int)dr.GetByte("macroPropertySortOrder"); + _alias = dr.GetString("macroPropertyAlias"); + _name = dr.GetString("macroPropertyName"); + _type = new MacroPropertyType(dr.GetShort("macroPropertyType")); + } + } + } + + /// + /// Deletes the current macroproperty + /// + public void Delete() + { + SqlHelper.ExecuteNonQuery("delete from cmsMacroProperty where id = @id", SqlHelper.CreateParameter("@id", this._id)); + } + + public void Save() + { + if (_id == 0) + { + MacroProperty mp = + MakeNew(m_macro, Public, Alias, Name, Type); + _id = mp.Id; + + } + else + { + SqlHelper.ExecuteNonQuery("UPDATE cmsMacroProperty set macro = @macro, macroPropertyHidden = @show, macropropertyAlias = @alias, macroPropertyName = @name, macroPropertyType = @type WHERE id = @id", + SqlHelper.CreateParameter("@id", Id), + SqlHelper.CreateParameter("@macro", Macro.Id), + SqlHelper.CreateParameter("@show", Public), + SqlHelper.CreateParameter("@alias", Alias), + SqlHelper.CreateParameter("@name", Name), + SqlHelper.CreateParameter("@type", Type.Id)); + } + } + + /// + /// Retrieve a Xmlrepresentation of the MacroProperty used for exporting the Macro to the package + /// + /// XmlDocument context + /// A xmlrepresentation of the object + public XmlElement ToXml(XmlDocument xd) + { + XmlElement doc = xd.CreateElement("property"); + + doc.Attributes.Append(xmlHelper.addAttribute(xd, "name", this.Name)); + doc.Attributes.Append(xmlHelper.addAttribute(xd, "alias", this.Alias)); + doc.Attributes.Append(xmlHelper.addAttribute(xd, "show", this.Public.ToString())); + doc.Attributes.Append(xmlHelper.addAttribute(xd, "propertyType", this.Type.Alias)); + + return doc; + } + + #region STATICS + + /// + /// Retieve all MacroProperties of a macro + /// + /// Macro identifier + /// All MacroProperties of a macro + public static MacroProperty[] GetProperties(int MacroId) + { + int totalProperties = SqlHelper.ExecuteScalar("select count(*) from cmsMacroProperty where macro = @macroID", SqlHelper.CreateParameter("@macroID", MacroId)); + int count = 0; + using (IRecordsReader dr = SqlHelper.ExecuteReader("select id from cmsMacroProperty where macro = @macroId order by macroPropertySortOrder, id ASC", SqlHelper.CreateParameter("@macroId", MacroId))) + { + MacroProperty[] retval = new MacroProperty[totalProperties]; + while (dr.Read()) + { + retval[count] = new MacroProperty(dr.GetInt("id")); + count++; + } + return retval; + } + } + + /// + /// Creates a new MacroProperty on a macro + /// + /// The macro + /// Will the editor be able to input data + /// The alias of the property + /// Userfriendly MacroProperty name + /// The MacroPropertyType of the property + [MethodImpl(MethodImplOptions.Synchronized)] + public static MacroProperty MakeNew(Macro M, bool show, string alias, string name, MacroPropertyType propertyType) + { + int macroPropertyId = 0; + // The method is synchronized + SqlHelper.ExecuteNonQuery("INSERT INTO cmsMacroProperty (macro, macroPropertyHidden, macropropertyAlias, macroPropertyName, macroPropertyType) VALUES (@macro, @show, @alias, @name, @type)", + SqlHelper.CreateParameter("@macro", M.Id), + SqlHelper.CreateParameter("@show", show), + SqlHelper.CreateParameter("@alias", alias), + SqlHelper.CreateParameter("@name", name), + SqlHelper.CreateParameter("@type", propertyType.Id)); + macroPropertyId = SqlHelper.ExecuteScalar("SELECT MAX(id) FROM cmsMacroProperty"); + return new MacroProperty(macroPropertyId); + } + + #endregion + + } +} diff --git a/umbraco/cms/businesslogic/macro/macroPropertyType.cs b/umbraco/cms/businesslogic/macro/macroPropertyType.cs new file mode 100644 index 0000000000..7ca19115eb --- /dev/null +++ b/umbraco/cms/businesslogic/macro/macroPropertyType.cs @@ -0,0 +1,103 @@ +using System; +using System.Data; +using umbraco.DataLayer; +using umbraco.BusinessLogic; +using System.Collections.Generic; + +namespace umbraco.cms.businesslogic.macro { + /// + /// The MacroPropertyType class contains information on the assembly and class of the + /// IMacroGuiRendering component and basedatatype + /// + /// TODO: implement interface/abstract factory pattern + /// + public class MacroPropertyType { + int _id; + string _alias; + string _assembly; + string _type; + string _baseType; + private static List m_allPropertyTypes = new List(); + + protected static ISqlHelper SqlHelper { + get { return Application.SqlHelper; } + } + + public static List GetAll { + get { + if (m_allPropertyTypes.Count == 0) { + using (IRecordsReader dr = SqlHelper.ExecuteReader("select id from cmsMacroPropertyType order by macroPropertyTypeAlias")) { + while (dr.Read()) { + m_allPropertyTypes.Add(new MacroPropertyType(dr.GetShort("id"))); + } + } + } + + return m_allPropertyTypes; + } + } + + + /// + /// Identifier + /// + public int Id { + get { return _id; } + } + + /// + /// The alias of the MacroPropertyType + /// + public string Alias { get { return _alias; } } + + /// + /// The assembly (without the .dll extension) used to retrieve the component at runtime + /// + public string Assembly { get { return _assembly; } } + + /// + /// The MacroPropertyType + /// + public string Type { get { return _type; } } + + /// + /// The IMacroGuiRendering component (namespace.namespace.Classname) + /// + public string BaseType { get { return _baseType; } } + + + /// + /// Constructor + /// + /// Identifier + public MacroPropertyType(int Id) { + _id = Id; + setup(); + } + + public MacroPropertyType() { + } + + /// + /// Constructor + /// + /// The alias of the MacroPropertyType + public MacroPropertyType(string Alias) { + _id = SqlHelper.ExecuteScalar("select id from cmsMacroPropertyType where macroPropertyTypeAlias = @alias", SqlHelper.CreateParameter("@alias", Alias)); + setup(); + } + + private void setup() { + using (IRecordsReader dr = SqlHelper.ExecuteReader("select macroPropertyTypeAlias, macroPropertyTypeRenderAssembly, macroPropertyTypeRenderType, macroPropertyTypeBaseType from cmsMacroPropertyType where id = @id", SqlHelper.CreateParameter("@id", _id))) { + if (dr.Read()) { + _alias = dr.GetString("macroPropertyTypeAlias"); + _assembly = dr.GetString("macroPropertyTypeRenderAssembly"); + _type = dr.GetString("macroPropertyTypeRenderType"); + _baseType = dr.GetString("macroPropertyTypeBaseType"); + } + } + } + + + } +} diff --git a/umbraco/cms/businesslogic/media/Media.cs b/umbraco/cms/businesslogic/media/Media.cs new file mode 100644 index 0000000000..c259496b39 --- /dev/null +++ b/umbraco/cms/businesslogic/media/Media.cs @@ -0,0 +1,257 @@ +using System; + +namespace umbraco.cms.businesslogic.media +{ + /// + /// A media represents a physical file and metadata on the file. + /// + /// By inheriting the Content class it has a generic datafields which enables custumization + /// + public class Media : Content + { + /// + /// Contructs a media object given the Id + /// + /// Identifier + public Media(int id) : base(id) + { + } + + /// + /// Contructs a media object given the Id + /// + /// Identifier + public Media(Guid id) : base(id) + {} + + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public override void Save() + { + SaveEventArgs e = new SaveEventArgs(); + FireBeforeSave(e); + + if (!e.Cancel) { + + base.Save(); + + + FireAfterSave(e); + } + } + + + /// + /// - + /// + public static Guid _objectType = new Guid("b796f64c-1f99-4ffb-b886-4bf4bc011a9c"); + + /// + /// Creates a new Media + /// + /// The name of the media + /// The type of the media + /// The user creating the media + /// The id of the folder under which the media is created + /// + public static Media MakeNew(string Name, MediaType dct, BusinessLogic.User u, int ParentId) + { + Guid newId = Guid.NewGuid(); + // Updated to match level from base node + CMSNode n = new CMSNode(ParentId); + int newLevel = n.Level; + newLevel++; + CMSNode.MakeNew(ParentId,_objectType, u.Id, newLevel, Name, newId); + Media tmp = new Media(newId); + tmp.CreateContent(dct); + + NewEventArgs e = new NewEventArgs(); + tmp.OnNew(e); + + return tmp; + } + + /// + /// Retrieve a list of all toplevel medias and folders + /// + /// + public static Media[] GetRootMedias() + { + Guid[] topNodeIds = CMSNode.TopMostNodeIds(_objectType); + + Media[] retval = new Media[topNodeIds.Length]; + for (int i = 0;i < topNodeIds.Length;i++) + { + Media d = new Media(topNodeIds[i]); + retval[i] = d; + } + return retval; + } + + + /// + /// Retrieve a list of all medias underneath the current + /// + new public Media[] Children + { + get + { + BusinessLogic.console.IconI[] tmp = base.Children; + Media[] retval = new Media[tmp.Length]; + for (int i = 0; i < tmp.Length; i++) retval[i] = new Media(tmp[i].UniqueId); + return retval; + } + } + + /// + /// Deletes all medias of the given type, used when deleting a mediatype + /// + /// Use with care. + /// + /// + public static void DeleteFromType(MediaType dt) + { + foreach (Content c in Media.getContentOfContentType(dt)) + { + // due to recursive structure document might already been deleted.. + if (CMSNode.IsNode(c.UniqueId)) + { + Media tmp = new Media(c.UniqueId); + tmp.delete(); + } + } + } + /// + /// Deletes the current media and all children. + /// + new public void delete() + { + DeleteEventArgs e = new DeleteEventArgs(); + + FireBeforeDelete(e); + + if (!e.Cancel) { + foreach (Media d in this.Children) { + d.delete(); + } + + // Remove all files + interfaces.IDataType uploadField = new cms.businesslogic.datatype.controls.Factory().GetNewObject(new Guid("5032a6e6-69e3-491d-bb28-cd31cd11086c")); + foreach (cms.businesslogic.property.Property p in this.getProperties) + if (p.PropertyType.DataTypeDefinition.DataType.Id == uploadField.Id && + p.Value.ToString() != "" && + System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath(p.Value.ToString())) + ) + { + + System.IO.File.Delete(System.Web.HttpContext.Current.Server.MapPath(p.Value.ToString())); + + string file = p.Value.ToString(); + string extension = ((string)file.Substring(file.LastIndexOf(".") + 1, file.Length - file.LastIndexOf(".") - 1)).ToLower(); + + //check for thumbnail + if (",jpeg,jpg,gif,bmp,png,tiff,tif,".IndexOf("," + extension + ",") > -1) + { + string thumbnailfile = file.Replace("." + extension, "_thumb"); + + if (System.IO.File.Exists(System.Web.HttpContext.Current.Server.MapPath(thumbnailfile + ".jpg"))) + System.IO.File.Delete(System.Web.HttpContext.Current.Server.MapPath(thumbnailfile + ".jpg")); + + //should also delete extra thumbnails + } + + } + + + + base.delete(); + + FireAfterDelete(e); + } + } + + + //EVENTS + /// + /// The save event handler + /// + public new delegate void SaveEventHandler(Media sender, SaveEventArgs e); + /// + /// The new event handler + /// + public new delegate void NewEventHandler(Media sender, NewEventArgs e); + /// + /// The delete event handler + /// + public new delegate void DeleteEventHandler(Media sender, DeleteEventArgs e); + + + /// + /// Occurs when [before save]. + /// + public new static event SaveEventHandler BeforeSave; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected new virtual void FireBeforeSave(SaveEventArgs e) { + if (BeforeSave != null) + BeforeSave(this, e); + } + + /// + /// Occurs when [after save]. + /// + public new static event SaveEventHandler AfterSave; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected new virtual void FireAfterSave(SaveEventArgs e) { + if (AfterSave != null) + AfterSave(this, e); + } + + /// + /// Occurs when [new]. + /// + public new static event NewEventHandler New; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected new virtual void OnNew(NewEventArgs e) { + if (New != null) + New(this, e); + } + + /// + /// Occurs when [before delete]. + /// + public new static event DeleteEventHandler BeforeDelete; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected new virtual void FireBeforeDelete(DeleteEventArgs e) { + if (BeforeDelete != null) + BeforeDelete(this, e); + } + + /// + /// Occurs when [after delete]. + /// + public new static event DeleteEventHandler AfterDelete; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected new virtual void FireAfterDelete(DeleteEventArgs e) { + if (AfterDelete != null) + AfterDelete(this, e); + } + + } +} diff --git a/umbraco/cms/businesslogic/media/MediaType.cs b/umbraco/cms/businesslogic/media/MediaType.cs new file mode 100644 index 0000000000..c1291a3400 --- /dev/null +++ b/umbraco/cms/businesslogic/media/MediaType.cs @@ -0,0 +1,198 @@ +using System; +using System.Data; + + +namespace umbraco.cms.businesslogic.media +{ + /// + /// The Mediatype + /// + /// Due to the inheritance of the ContentType class,it enables definition of generic datafields on a Media. + /// + public class MediaType : ContentType + { + + /// + /// Constructs a MediaTypeobject given the id + /// + /// Id of the mediatype + public MediaType(int id) : base(id) + { + } + + /// + /// Constructs a MediaTypeobject given the id + /// + /// Id of the mediatype + public MediaType(Guid id) : base(id) + { + } + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public override void Save() + { + SaveEventArgs e = new SaveEventArgs(); + FireBeforeSave(e); + + if (!e.Cancel) { + base.Save(); + + FireBeforeSave(e); + } + } + + + /// + /// Retrieve a MediaType by it's alias + /// + /// The alias of the MediaType + /// The MediaType with the alias + public static new MediaType GetByAlias(string Alias) + { + return new MediaType(SqlHelper.ExecuteScalar("SELECT nodeid from cmsContentType where alias = @alias", + SqlHelper.CreateParameter("@alias",Alias))); + } + + + private static Guid _objectType = new Guid("4ea4382b-2f5a-4c2b-9587-ae9b3cf3602e"); + + /// + /// Retrieve all MediaTypes in the umbraco installation + /// + new public static MediaType[] GetAll + { + get + { + Guid[] Ids = CMSNode.getAllUniquesFromObjectType(_objectType); + MediaType[] retVal = new MediaType[Ids.Length]; + for (int i = 0; i < Ids.Length; i++) retVal[i] = new MediaType(Ids[i]); + return retVal; + } + } + + /// + /// Create a new Mediatype + /// + /// The Umbraco user context + /// The name of the MediaType + /// The new MediaType + public static MediaType MakeNew( BusinessLogic.User u,string Text) + { + + int ParentId= -1; + int level = 1; + Guid uniqueId = Guid.NewGuid(); + CMSNode n = CMSNode.MakeNew(ParentId, _objectType, u.Id, level,Text, uniqueId); + + ContentType.Create(n.Id, Text,""); + + MediaType mt = new MediaType(n.Id); + NewEventArgs e = new NewEventArgs(); + mt.OnNew(e); + + return mt; + } + + + /// + /// Deletes the current MediaType and all created Medias of the type. + /// + new public void delete() + { + DeleteEventArgs e = new DeleteEventArgs(); + FireBeforeDelete(e); + + if (!e.Cancel) { + // delete all documents of this type + Media.DeleteFromType(this); + // Delete contentType + base.delete(); + + FireAfterDelete(e); + } + } + + //EVENTS + /// + /// The save event handler + /// + public delegate void SaveEventHandler(MediaType sender, SaveEventArgs e); + /// + /// The new event handler + /// + public delegate void NewEventHandler(MediaType sender, NewEventArgs e); + /// + /// The delete event handler + /// + public delegate void DeleteEventHandler(MediaType sender, DeleteEventArgs e); + + + /// + /// Occurs when [before save]. + /// + public static event SaveEventHandler BeforeSave; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void FireBeforeSave(SaveEventArgs e) { + if (BeforeSave != null) + BeforeSave(this, e); + } + + /// + /// Occurs when [after save]. + /// + public static event SaveEventHandler AfterSave; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void FireAfterSave(SaveEventArgs e) { + if (AfterSave != null) + AfterSave(this, e); + } + + /// + /// Occurs when [new]. + /// + public static event NewEventHandler New; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void OnNew(NewEventArgs e) { + if (New != null) + New(this, e); + } + + /// + /// Occurs when [before delete]. + /// + public static event DeleteEventHandler BeforeDelete; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void FireBeforeDelete(DeleteEventArgs e) { + if (BeforeDelete != null) + BeforeDelete(this, e); + } + + /// + /// Occurs when [after delete]. + /// + public static event DeleteEventHandler AfterDelete; + /// + /// Raises the event. + /// + /// The instance containing the event data. + protected virtual void FireAfterDelete(DeleteEventArgs e) { + if (AfterDelete != null) + AfterDelete(this, e); + } + + } +} diff --git a/umbraco/cms/businesslogic/member/Member.cs b/umbraco/cms/businesslogic/member/Member.cs new file mode 100644 index 0000000000..313bf52bd5 --- /dev/null +++ b/umbraco/cms/businesslogic/member/Member.cs @@ -0,0 +1,1319 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Web; +using System.Web.Caching; +using System.Xml; + +using umbraco.cms.businesslogic.cache; + +using umbraco.BusinessLogic; +using umbraco.DataLayer; + +using System.Web.Security; +using System.Text; +using System.Security.Cryptography; + +namespace umbraco.cms.businesslogic.member +{ + /// + /// The Member class represents a member of the public website (not to be confused with umbraco users) + /// + /// Members are used when creating communities and collaborative applications using umbraco, or if there are a + /// need for identifying or authentifying the visitor. (extranets, protected/private areas of the public website) + /// + /// Inherits generic datafields from it's baseclass content. + /// + public class Member : Content + { + public static readonly string UmbracoMemberProviderName = "UmbracoMembershipProvider"; + public static readonly string UmbracoRoleProviderName = "UmbracoRoleProvider"; + public static readonly Guid _objectType = new Guid("39eb0f98-b348-42a1-8662-e7eb18487560"); + private static readonly System.Web.Caching.Cache _memberCache = HttpRuntime.Cache; + private static object memberCacheSyncLock = new object(); + private static readonly string memberLookupCacheKey = "memberLookupId_"; + private static readonly string UmbracoMemberIdCookieKey = "umbracoMemberId"; + private static readonly string UmbracoMemberGuidCookieKey = "umbracoMemberGuid"; + private static readonly string UmbracoMemberLoginCookieKey = "umbracoMemberLogin"; + private string _text; + + private Hashtable _groups = null; + + /// + /// Initializes a new instance of the Member class. + /// + /// Identifier + public Member(int id) + : base(id) + { + } + + /// + /// Initializes a new instance of the Member class. + /// + /// Identifier + public Member(Guid id) + : base(id) + { + } + + /// + /// Initializes a new instance of the Member class, with an option to only initialize + /// the data used by the tree in the umbraco console. + /// + /// Performace + /// + /// Identifier + /// + public Member(int id, bool noSetup) + : base(id, noSetup) + { + } + + /// + /// The name of the member + /// + public new string Text + { + get + { + if (string.IsNullOrEmpty(_text)) + _text = SqlHelper.ExecuteScalar( + "select text from umbracoNode where id = @id", + SqlHelper.CreateParameter("@id", Id)); + return _text; + } + set + { + _text = value; + base.Text = value; + } + } + + /// + /// A list of all members in the current umbraco install + /// + /// Note: is ressource intensive, use with care. + /// + public static Member[] GetAll + { + get + { + Guid[] tmp = getAllUniquesFromObjectType(_objectType); + + return Array.ConvertAll(tmp, delegate(Guid g) { return new Member(g); }); + } + } + + /// + /// The members password, used when logging in on the public website + /// + public string Password + { + get + { + return SqlHelper.ExecuteScalar( + "select Password from cmsMember where nodeId = @id", + SqlHelper.CreateParameter("@id", Id)); + } + set + { + // We need to use the provider for this in order for hashing, etc. support + // To write directly to the db use the ChangePassword method + // this is not pretty but nessecary due to a design flaw (the membership provider should have been a part of the cms project) + MemberShipHelper helper = new MemberShipHelper(); + ChangePassword(helper.EncodePassword(value, Membership.Provider.PasswordFormat)); + } + } + + /// + /// The loginname of the member, used when logging in + /// + public string LoginName + { + get + { + return SqlHelper.ExecuteScalar( + "select LoginName from cmsMember where nodeId = @id", + SqlHelper.CreateParameter("@id", Id)); + } + set + { + SqlHelper.ExecuteNonQuery( + "update cmsMember set LoginName = @loginName where nodeId = @id", + SqlHelper.CreateParameter("@loginName", value), + SqlHelper.CreateParameter("@id", Id)); + } + } + + /// + /// A list of groups the member are member of + /// + public Hashtable Groups + { + get + { + if (_groups == null) + populateGroups(); + return _groups; + } + } + + /// + /// The members email + /// + public string Email + { + get + { + return SqlHelper.ExecuteScalar( + "select Email from cmsMember where nodeId = @id", + SqlHelper.CreateParameter("@id", Id)); + } + set + { + SqlHelper.ExecuteNonQuery( + "update cmsMember set Email = @email where nodeId = @id", + SqlHelper.CreateParameter("@id", Id), SqlHelper.CreateParameter("@email", value)); + } + } + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public override void Save() + { + SaveEventArgs e = new SaveEventArgs(); + FireBeforeSave(e); + + if (!e.Cancel) + { + // re-generate xml + XmlGenerate(new XmlDocument()); + + FireAfterSave(e); + } + } + + /// + /// Retrieves a list of members thats not start with a-z + /// + /// array of members + public static Member[] getAllOtherMembers() + { + string query = + "SELECT id, text FROM umbracoNode WHERE (nodeObjectType = @nodeObjectType) AND (ASCII(SUBSTRING(text, 1, 1)) NOT BETWEEN ASCII('a') AND ASCII('z')) AND (ASCII(SUBSTRING(text, 1, 1)) NOT BETWEEN ASCII('A') AND ASCII('Z'))"; + List m = new List(); + using (IRecordsReader dr = SqlHelper.ExecuteReader(query, + SqlHelper.CreateParameter("@nodeObjectType", _objectType))) + { + while (dr.Read()) + { + Member newMember = new Member(dr.GetInt("id"), true); + newMember._text = dr.GetString("text"); + m.Add(new Member(newMember.Id)); + } + } + + return m.ToArray(); + } + + /// + /// Retrieves a list of members by the first letter in their name. + /// + /// The first letter + /// + public static Member[] getMemberFromFirstLetter(char letter) + { + return GetMemberByName(letter.ToString(), true); + } + + public static Member[] GetMemberByName(string usernameToMatch, bool matchByNameInsteadOfLogin) + { + string field = matchByNameInsteadOfLogin ? "text" : "loginName"; + string query = + String.Format( + "Select id, text from umbracoNode inner join cmsMember on cmsMember.nodeId = umbracoNode.id where nodeObjectType = @objectType and {0} like @letter order by text", + field); + List m = new List(); + using (IRecordsReader dr = SqlHelper.ExecuteReader(query, + SqlHelper.CreateParameter("@objectType", _objectType), + SqlHelper.CreateParameter("@field", field), + SqlHelper.CreateParameter("@letter", usernameToMatch + "%"))) + { + while (dr.Read()) + { + Member newMember = new Member(dr.GetInt("id"), true); + newMember._text = dr.GetString("text"); + m.Add(new Member(newMember.Id)); + } + } + return m.ToArray(); + + } + + /// + /// Creates a new member + /// + /// Membername + /// Member type + /// The umbraco usercontext + /// The new member + public static Member MakeNew(string Name, MemberType mbt, User u) + { + return MakeNew(Name, "", mbt, u); + /* + Guid newId = Guid.NewGuid(); + MakeNew(-1, _objectType, u.Id, 1, Name, newId); + + Member tmp = new Member(newId); + + tmp.CreateContent(mbt); + // Create member specific data .. + SqlHelper.ExecuteNonQuery( + "insert into cmsMember (nodeId,Email,LoginName,Password) values (@id,'',@text,'')", + SqlHelper.CreateParameter("@id", tmp.Id), + SqlHelper.CreateParameter("@text", tmp.Text)); + + NewEventArgs e = new NewEventArgs(); + tmp.OnNew(e); + + return tmp;*/ + } + + /// + /// Creates a new member + /// + /// Membername + /// Member type + /// The umbraco usercontext + /// The email of the user + /// The new member + public static Member MakeNew(string Name, string Email, MemberType mbt, User u) + { + // Test for e-mail + if (Email != "" && Member.GetMemberFromEmail(Email) != null) + throw new Exception(String.Format("Duplicate Email! A member with the e-mail {0} already exists", Email)); + else if (Member.GetMemberFromLoginName(Name) != null) + throw new Exception(String.Format("Duplicate User name! A member with the user name {0} already exists", Name)); + + Guid newId = Guid.NewGuid(); + MakeNew(-1, _objectType, u.Id, 1, Name, newId); + + Member tmp = new Member(newId); + + tmp.CreateContent(mbt); + // Create member specific data .. + SqlHelper.ExecuteNonQuery( + "insert into cmsMember (nodeId,Email,LoginName,Password) values (@id,@email,@text,'')", + SqlHelper.CreateParameter("@id", tmp.Id), + SqlHelper.CreateParameter("@text", tmp.Text), + SqlHelper.CreateParameter("@email", Email)); + + NewEventArgs e = new NewEventArgs(); + tmp.OnNew(e); + + tmp.Save(); + + return tmp; + } + + /// + /// Generates the xmlrepresentation of a member + /// + /// + public override void XmlGenerate(XmlDocument xd) + { + XmlNode node = xd.CreateNode(XmlNodeType.Element, "node", ""); + XmlPopulate(xd, ref node, false); + node.Attributes.Append(xmlHelper.addAttribute(xd, "loginName", LoginName)); + node.Attributes.Append(xmlHelper.addAttribute(xd, "email", Email)); + SaveXmlDocument(node); + } + + /// + /// Xmlrepresentation of a member + /// + /// The xmldocument context + /// Recursive - should always be set to false + /// A the xmlrepresentation of the current member + public override XmlNode ToXml(XmlDocument xd, bool Deep) + { + XmlNode x = base.ToXml(xd, Deep); + if (x.Attributes["loginName"] == null) + { + x.Attributes.Append(xmlHelper.addAttribute(xd, "loginName", LoginName)); + x.Attributes.Append(xmlHelper.addAttribute(xd, "email", Email)); + } + return x; + } + + /// + /// Deltes the current member + /// + public new void delete() + { + DeleteEventArgs e = new DeleteEventArgs(); + FireBeforeDelete(e); + + if (!e.Cancel) + { + // Remove from cache (if exists) + umbraco.cms.businesslogic.cache.Cache.ClearCacheItem(memberLookupCacheKey + Id); + + // delete memeberspecific data! + SqlHelper.ExecuteNonQuery("Delete from cmsMember where nodeId = @id", + SqlHelper.CreateParameter("@id", Id)); + + // delete all relations to groups + foreach (int groupId in this.Groups.Keys) + { + RemoveGroup(groupId); + } + + // Delete all content and cmsnode specific data! + base.delete(); + + FireAfterDelete(e); + } + } + + /// + /// Deletes all members of the membertype specified + /// + /// Used when a membertype is deleted + /// + /// Use with care + /// + /// The membertype which are being deleted + public static void DeleteFromType(MemberType dt) + { + foreach (Content c in getContentOfContentType(dt)) + { + // due to recursive structure document might already been deleted.. + if (IsNode(c.UniqueId)) + { + Member tmp = new Member(c.UniqueId); + tmp.delete(); + } + } + } + + public void ChangePassword(string newPassword) + { + SqlHelper.ExecuteNonQuery( + "update cmsMember set Password = @password where nodeId = @id", + SqlHelper.CreateParameter("@password", newPassword), + SqlHelper.CreateParameter("@id", Id)); + } + + /// + /// Adds the member to group with the specified id + /// + /// The id of the group which the member is being added to + [MethodImpl(MethodImplOptions.Synchronized)] + public void AddGroup(int GroupId) + { + AddGroupEventArgs e = new AddGroupEventArgs(); + FireBeforeAddGroup(e); + + if (!e.Cancel) + { + IParameter[] parameters = new IParameter[] { SqlHelper.CreateParameter("@id", Id), + SqlHelper.CreateParameter("@groupId", GroupId) }; + bool exists = SqlHelper.ExecuteScalar("SELECT COUNT(member) FROM cmsMember2MemberGroup WHERE member = @id AND memberGroup = @groupId", + parameters) > 0; + if (!exists) + SqlHelper.ExecuteNonQuery("INSERT INTO cmsMember2MemberGroup (member, memberGroup) values (@id, @groupId)", + parameters); + populateGroups(); + + FireAfterAddGroup(e); + } + } + + /// + /// Removes the member from the MemberGroup specified + /// + /// The MemberGroup from which the Member is removed + public void RemoveGroup(int GroupId) + { + RemoveGroupEventArgs e = new RemoveGroupEventArgs(); + FireBeforeRemoveGroup(e); + + if (!e.Cancel) + { + SqlHelper.ExecuteNonQuery( + "delete from cmsMember2MemberGroup where member = @id and Membergroup = @groupId", + SqlHelper.CreateParameter("@id", Id), SqlHelper.CreateParameter("@groupId", GroupId)); + populateGroups(); + FireAfterRemoveGroup(e); + } + } + + private void populateGroups() + { + Hashtable temp = new Hashtable(); + using (IRecordsReader dr = SqlHelper.ExecuteReader( + "select memberGroup from cmsMember2MemberGroup where member = @id", + SqlHelper.CreateParameter("@id", Id))) + { + while (dr.Read()) + temp.Add(dr.GetInt("memberGroup"), + new MemberGroup(dr.GetInt("memberGroup"))); + } + _groups = temp; + } + + /// + /// Retrieve a member given the loginname + /// + /// Used when authentifying the Member + /// + /// The unique Loginname + /// The member with the specified loginname - null if no Member with the login exists + public static Member GetMemberFromLoginName(string loginName) + { + if (IsMember(loginName)) + { + object o = SqlHelper.ExecuteScalar( + "select nodeID from cmsMember where LoginName = @loginName", + SqlHelper.CreateParameter("@loginName", loginName)); + + if (o == null) + return null; + + int tmpId; + if (!int.TryParse(o.ToString(), out tmpId)) + return null; + + return new Member(tmpId); + } + else + HttpContext.Current.Trace.Warn("No member with loginname: " + loginName + " Exists"); + + return null; + } + + /// + /// Retrieve a Member given an email + /// + /// Used when authentifying the Member + /// + /// The email of the member + /// The member with the specified email - null if no Member with the email exists + public static Member GetMemberFromEmail(string email) + { + if (string.IsNullOrEmpty(email)) + return null; + + object o = SqlHelper.ExecuteScalar( + "select nodeID from cmsMember where Email = @email", + SqlHelper.CreateParameter("@email", email)); + + if (o == null) + return null; + + int tmpId; + if (!int.TryParse(o.ToString(), out tmpId)) + return null; + + return new Member(tmpId); + } + + /// + /// Retrieve a Member given the credentials + /// + /// Used when authentifying the member + /// + /// Member login + /// Member password + /// The member with the credentials - null if none exists + public static Member GetMemberFromLoginNameAndPassword(string loginName, string password) + { + if (IsMember(loginName)) + { + // validate user via provider + if (Membership.ValidateUser(loginName, password)) + { + return GetMemberFromLoginName(loginName); + } + else + { + HttpContext.Current.Trace.Warn("Incorrect login/password"); + return null; + } + } + else + { + HttpContext.Current.Trace.Warn("No member with loginname: " + loginName + " Exists"); + // throw new ArgumentException("No member with Loginname: " + LoginName + " exists"); + return null; + } + } + + public static Member GetMemberFromLoginAndEncodedPassword(string loginName, string password) + { + object o = SqlHelper.ExecuteScalar( + "select nodeID from cmsMember where LoginName = @loginName and Password = @password", + SqlHelper.CreateParameter("loginName", loginName), + SqlHelper.CreateParameter("password", password)); + + if (o == null) + return null; + + int tmpId; + if (!int.TryParse(o.ToString(), out tmpId)) + return null; + + return new Member(tmpId); + } + + public static bool InUmbracoMemberMode() + { + return Membership.Provider.Name == UmbracoMemberProviderName; + } + + public static bool IsUsingUmbracoRoles() + { + return Roles.Provider.Name == UmbracoRoleProviderName; + } + + + /// + /// Helper method - checks if a Member with the LoginName exists + /// + /// Member login + /// True if the member exists + public static bool IsMember(string loginName) + { + Debug.Assert(loginName != null, "loginName cannot be null"); + object o = SqlHelper.ExecuteScalar( + "select count(nodeID) as tmp from cmsMember where LoginName = @loginName", + SqlHelper.CreateParameter("@loginName", loginName)); + if (o == null) + return false; + int count; + if (!int.TryParse(o.ToString(), out count)) + return false; + return count > 0; + } + + /* + public contentitem.ContentItem[] CreatedContent() { + return new contentitem.ContentItem[0]; + } + */ + + + + #region MemberHandle functions + + /// + /// Method is used when logging a member in. + /// + /// Adds the member to the cache of logged in members + /// + /// Uses cookiebased recognition + /// + /// Can be used in the runtime + /// + /// The member to log in + public static void AddMemberToCache(Member m) + { + + if (m != null) + { + AddToCacheEventArgs e = new AddToCacheEventArgs(); + m.FireBeforeAddToCache(e); + + if (!e.Cancel) + { + + Hashtable umbracoMembers = CachedMembers(); + + // Check if member already exists + if (umbracoMembers[m.Id] == null) + umbracoMembers.Add(m.Id, m); + + removeCookie("umbracoMemberId"); + + // Add cookie with member-id, guid and loginname + addCookie("umbracoMemberId", m.Id.ToString(), 365); + addCookie("umbracoMemberGuid", m.UniqueId.ToString(), 365); + addCookie("umbracoMemberLogin", m.LoginName, 365); + + // Debug information + HttpContext.Current.Trace.Write("member", + "Member added to cache: " + m.Text + "/" + m.LoginName + " (" + + m.Id + ")"); + + _memberCache["umbracoMembers"] = umbracoMembers; + + FormsAuthentication.SetAuthCookie(m.LoginName, true); + + m.FireAfterAddToCache(e); + } + } + + } + + + + #region cookieHelperMethods + + private static void removeCookie(string Name) + { + HttpCookie c = HttpContext.Current.Request.Cookies[Name]; + if (c != null) + { + c.Expires = DateTime.Now.AddDays(-1); + HttpContext.Current.Response.Cookies.Add(c); + } + } + + private static void addCookie(string Name, object Value, int NumberOfDaysToLast) + { + HttpCookie c = new HttpCookie(Name, Value.ToString()); + c.Value = Value.ToString(); + c.Expires = DateTime.Now.AddDays(NumberOfDaysToLast); + HttpContext.Current.Response.Cookies.Add(c); + } + + private static void addCookie(string Name, object Value, TimeSpan timeout) + { + HttpCookie c = new HttpCookie(Name, Value.ToString()); + c.Value = Value.ToString(); + c.Expires = DateTime.Now.Add(timeout); + HttpContext.Current.Response.Cookies.Add(c); + } + + private static string getCookieValue(string Name) + { + string tempValue = ""; + + if (HttpContext.Current.Session[Name] != null) + if (HttpContext.Current.Session[Name].ToString() != "0") + tempValue = HttpContext.Current.Session[Name].ToString(); + + if (tempValue == "") + { + if (Array.IndexOf(HttpContext.Current.Response.Cookies.AllKeys, Name) == -1) + { + if (HttpContext.Current.Request.Cookies[Name] != null) + if (HttpContext.Current.Request.Cookies[Name].Value != "") + { + tempValue = HttpContext.Current.Request.Cookies[Name].Value; + } + } + else + { + tempValue = HttpContext.Current.Response.Cookies[Name].Value; + } + } + + return tempValue; + } + + #endregion + + /// + /// Method is used when logging a member in. + /// + /// Adds the member to the cache of logged in members + /// + /// Uses cookie or session based recognition + /// + /// Can be used in the runtime + /// + /// The member to log in + /// Use sessionbased recognition + /// The live time of the cookie + public static void AddMemberToCache(Member m, bool UseSession, TimeSpan TimespanForCookie) + { + if (m != null) + { + AddToCacheEventArgs e = new AddToCacheEventArgs(); + m.FireBeforeAddToCache(e); + + if (!e.Cancel) + { + + + Hashtable umbracoMembers = CachedMembers(); + + // Check if member already exists + if (umbracoMembers[m.Id] == null) + umbracoMembers.Add(m.Id, m); + + if (!UseSession) + { + removeCookie("umbracoMemberId"); + + // Add cookie with member-id + addCookie("umbracoMemberId", m.Id.ToString(), TimespanForCookie); + addCookie("umbracoMemberGuid", m.UniqueId.ToString(), TimespanForCookie); + addCookie("umbracoMemberLogin", m.LoginName, TimespanForCookie); + } + else + { + HttpContext.Current.Session["umbracoMemberId"] = m.Id.ToString(); + HttpContext.Current.Session["umbracoMemberGuid"] = m.UniqueId.ToString(); + HttpContext.Current.Session["umbracoMemberLogin"] = m.LoginName; + } + + // Debug information + HttpContext.Current.Trace.Write("member", + string.Format("Member added to cache: {0}/{1} ({2})", + m.Text, m.LoginName, m.Id)); + + _memberCache["umbracoMembers"] = umbracoMembers; + + + FormsAuthentication.SetAuthCookie(m.LoginName, false); + + m.FireAfterAddToCache(e); + } + + } + } + + /// + /// Removes the member from the cache + /// + /// Can be used in the public website + /// + /// Member to remove + [Obsolete("Deprecated, use the RemoveMemberFromCache(int NodeId) instead", false)] + public static void RemoveMemberFromCache(Member m) + { + RemoveMemberFromCache(m.Id); + } + + /// + /// Removes the member from the cache + /// + /// Can be used in the public website + /// + /// Node Id of the member to remove + public static void RemoveMemberFromCache(int NodeId) + { + Hashtable umbracoMembers = CachedMembers(); + if (umbracoMembers.ContainsKey(NodeId)) + umbracoMembers.Remove(NodeId); + + _memberCache["umbracoMembers"] = umbracoMembers; + } + + /// + /// Deletes the member cookie from the browser + /// + /// Can be used in the public website + /// + /// Member + [Obsolete("Deprecated, use the ClearMemberFromClient(int NodeId) instead", false)] + public static void ClearMemberFromClient(Member m) + { + + if (m != null) + ClearMemberFromClient(m.Id); + else + { + // If the member doesn't exists as an object, we'll just make sure that cookies are cleared + removeCookie("umbracoMemberId"); + removeCookie("umbracoMemberGuid"); + removeCookie("umbracoMemberLogin"); + } + + FormsAuthentication.SignOut(); + } + + /// + /// Deletes the member cookie from the browser + /// + /// Can be used in the public website + /// + /// The Node id of the member to clear + public static void ClearMemberFromClient(int NodeId) + { + + removeCookie("umbracoMemberId"); + removeCookie("umbracoMemberGuid"); + removeCookie("umbracoMemberLogin"); + + RemoveMemberFromCache(NodeId); + + + FormsAuthentication.SignOut(); + } + + /// + /// Retrieve a collection of members in the cache + /// + /// Can be used from the public website + /// + /// A collection of cached members + public static Hashtable CachedMembers() + { + Hashtable umbracoMembers; + + // Check for member hashtable in cache + if (_memberCache["umbracoMembers"] == null) + umbracoMembers = new Hashtable(); + else + umbracoMembers = (Hashtable)_memberCache["umbracoMembers"]; + + return umbracoMembers; + } + + /// + /// Retrieve a member from the cache + /// + /// Can be used from the public website + /// + /// Id of the member + /// If the member is cached it returns the member - else null + public static Member GetMemberFromCache(int id) + { + Hashtable members = CachedMembers(); + if (members.ContainsKey(id)) + return (Member)members[id]; + else + return null; + } + + /// + /// An indication if the current visitor is logged in + /// + /// Can be used from the public website + /// + /// True if the the current visitor is logged in + public static bool IsLoggedOn() + { + if (HttpContext.Current.User == null) + return false; + + + //if member is not auth'd , but still might have a umb cookie saying otherwise... + if (!HttpContext.Current.User.Identity.IsAuthenticated) + { + int _currentMemberId = CurrentMemberId(); + + //if we have a cookie... + if (_currentMemberId > 0) + { + //log in the member so .net knows about the member.. + FormsAuthentication.SetAuthCookie(new Member(_currentMemberId).LoginName, true); + + //making sure that the correct status is returned first time around... + return true; + } + + } + + + return HttpContext.Current.User.Identity.IsAuthenticated; + } + + + /// + /// Make a lookup in the database to verify if a member truely exists + /// + /// The node id of the member + /// True is a record exists in db + private static bool memberExists(int NodeId) + { + return SqlHelper.ExecuteScalar("select count(nodeId) from cmsMember where nodeId = @nodeId", SqlHelper.CreateParameter("@nodeId", NodeId)) == 1; + } + + + /// + /// Gets the current visitors memberid + /// + /// The current visitors members id, if the visitor is not logged in it returns 0 + public static int CurrentMemberId() + { + int _currentMemberId = 0; + string _currentGuid = ""; + + // For backwards compatibility between umbraco members and .net membership + if (HttpContext.Current.User.Identity.IsAuthenticated) + { + int.TryParse(Membership.GetUser().ProviderUserKey.ToString(), out _currentMemberId); + } + else if (StateHelper.HasCookieValue(UmbracoMemberIdCookieKey) && + StateHelper.HasCookieValue(UmbracoMemberGuidCookieKey) && + StateHelper.HasCookieValue(UmbracoMemberLoginCookieKey)) + { + int.TryParse(StateHelper.GetCookieValue(UmbracoMemberIdCookieKey), out _currentMemberId); + _currentGuid = StateHelper.GetCookieValue(UmbracoMemberGuidCookieKey); + } + + if (_currentMemberId > 0 && !memberExists(_currentMemberId)) + { + _currentMemberId = 0; + + StateHelper.ClearCookie(UmbracoMemberGuidCookieKey); + StateHelper.ClearCookie(UmbracoMemberLoginCookieKey); + StateHelper.ClearCookie(UmbracoMemberIdCookieKey); + + } + + return _currentMemberId; + } + + /// + /// Get the current member + /// + /// Returns the member, if visitor is not logged in: null + public static Member GetCurrentMember() + { + try + { + int _currentMemberId = CurrentMemberId(); + if (_currentMemberId != 0) + { + // return member from cache + Member m = GetMemberFromCache(_currentMemberId); + if (m == null) + m = new Member(_currentMemberId); + + if (HttpContext.Current.User.Identity.IsAuthenticated || (m.UniqueId == new Guid(getCookieValue("umbracoMemberGuid")) && + m.LoginName == getCookieValue("umbracoMemberLogin"))) + return m; + + return null; + } + else + return null; + } + catch + { + return null; + } + } + + #endregion + + + //EVENTS + /// + /// The save event handler + /// + new public delegate void SaveEventHandler(Member sender, SaveEventArgs e); + + /// + /// The new event handler + /// + new public delegate void NewEventHandler(Member sender, NewEventArgs e); + + /// + /// The delete event handler + /// + new public delegate void DeleteEventHandler(Member sender, DeleteEventArgs e); + + /// + /// The add to cache event handler + /// + public delegate void AddingToCacheEventHandler(Member sender, AddToCacheEventArgs e); + + /// + /// The add group event handler + /// + public delegate void AddingGroupEventHandler(Member sender, AddGroupEventArgs e); + + /// + /// The remove group event handler + /// + public delegate void RemovingGroupEventHandler(Member sender, RemoveGroupEventArgs e); + + + /// + /// Occurs when [before save]. + /// + new public static event SaveEventHandler BeforeSave; + /// + /// Raises the event. + /// + /// The instance containing the event data. + new protected virtual void FireBeforeSave(SaveEventArgs e) + { + if (BeforeSave != null) + { + BeforeSave(this, e); + } + } + + + new public static event SaveEventHandler AfterSave; + new protected virtual void FireAfterSave(SaveEventArgs e) + { + if (AfterSave != null) + { + AfterSave(this, e); + } + } + + + new public static event NewEventHandler New; + new protected virtual void OnNew(NewEventArgs e) + { + if (New != null) + { + New(this, e); + } + } + + + public static event AddingGroupEventHandler BeforeAddGroup; + protected virtual void FireBeforeAddGroup(AddGroupEventArgs e) + { + if (BeforeAddGroup != null) + { + BeforeAddGroup(this, e); + } + } + public static event AddingGroupEventHandler AfterAddGroup; + protected virtual void FireAfterAddGroup(AddGroupEventArgs e) + { + if (AfterAddGroup != null) + { + AfterAddGroup(this, e); + } + } + + + public static event RemovingGroupEventHandler BeforeRemoveGroup; + protected virtual void FireBeforeRemoveGroup(RemoveGroupEventArgs e) + { + if (BeforeRemoveGroup != null) + { + BeforeRemoveGroup(this, e); + } + } + + public static event RemovingGroupEventHandler AfterRemoveGroup; + protected virtual void FireAfterRemoveGroup(RemoveGroupEventArgs e) + { + if (AfterRemoveGroup != null) + { + AfterRemoveGroup(this, e); + } + } + + + public static event AddingToCacheEventHandler BeforeAddToCache; + protected virtual void FireBeforeAddToCache(AddToCacheEventArgs e) + { + if (BeforeAddToCache != null) + { + BeforeAddToCache(this, e); + } + } + + + public static event AddingToCacheEventHandler AfterAddToCache; + protected virtual void FireAfterAddToCache(AddToCacheEventArgs e) + { + if (AfterAddToCache != null) + { + AfterAddToCache(this, e); + } + } + + new public static event DeleteEventHandler BeforeDelete; + new protected virtual void FireBeforeDelete(DeleteEventArgs e) + { + if (BeforeDelete != null) + { + BeforeDelete(this, e); + } + } + + new public static event DeleteEventHandler AfterDelete; + new protected virtual void FireAfterDelete(DeleteEventArgs e) + { + if (AfterDelete != null) + { + AfterDelete(this, e); + } + } + } + + /// + /// ONLY FOR INTERNAL USE. + /// This is needed due to a design flaw where the Umbraco membership provider is located + /// in a separate project referencing this project, which means we can't call special methods + /// directly on the UmbracoMemberShipMember class. + /// This is a helper implementation only to be able to use the encryption functionality + /// of the membership provides (which are protected). + /// + public class MemberShipHelper : MembershipProvider + { + public override string ApplicationName + { + get + { + throw new NotImplementedException(); + } + set + { + throw new NotImplementedException(); + } + } + + public override bool ChangePassword(string username, string oldPassword, string newPassword) + { + throw new NotImplementedException(); + } + + public override bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer) + { + throw new NotImplementedException(); + } + + public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) + { + throw new NotImplementedException(); + } + + public override bool DeleteUser(string username, bool deleteAllRelatedData) + { + throw new NotImplementedException(); + } + + public string EncodePassword(string password, MembershipPasswordFormat pwFormat) + { + string encodedPassword = password; + switch (pwFormat) + { + case MembershipPasswordFormat.Clear: + break; + case MembershipPasswordFormat.Encrypted: + encodedPassword = + Convert.ToBase64String(EncryptPassword(Encoding.Unicode.GetBytes(password))); + break; + case MembershipPasswordFormat.Hashed: + HMACSHA1 hash = new HMACSHA1(); + hash.Key = Encoding.Unicode.GetBytes(password); + encodedPassword = + Convert.ToBase64String(hash.ComputeHash(Encoding.Unicode.GetBytes(password))); + break; + } + return encodedPassword; + } + + public override bool EnablePasswordReset + { + get { throw new NotImplementedException(); } + } + + public override bool EnablePasswordRetrieval + { + get { throw new NotImplementedException(); } + } + + public override MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords) + { + throw new NotImplementedException(); + } + + public override MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords) + { + throw new NotImplementedException(); + } + + public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords) + { + throw new NotImplementedException(); + } + + public override int GetNumberOfUsersOnline() + { + throw new NotImplementedException(); + } + + public override string GetPassword(string username, string answer) + { + throw new NotImplementedException(); + } + + public override MembershipUser GetUser(string username, bool userIsOnline) + { + throw new NotImplementedException(); + } + + public override MembershipUser GetUser(object providerUserKey, bool userIsOnline) + { + throw new NotImplementedException(); + } + + public override string GetUserNameByEmail(string email) + { + throw new NotImplementedException(); + } + + public override int MaxInvalidPasswordAttempts + { + get { throw new NotImplementedException(); } + } + + public override int MinRequiredNonAlphanumericCharacters + { + get { throw new NotImplementedException(); } + } + + public override int MinRequiredPasswordLength + { + get { throw new NotImplementedException(); } + } + + public override int PasswordAttemptWindow + { + get { throw new NotImplementedException(); } + } + + public override MembershipPasswordFormat PasswordFormat + { + get { throw new NotImplementedException(); } + } + + public override string PasswordStrengthRegularExpression + { + get { throw new NotImplementedException(); } + } + + public override bool RequiresQuestionAndAnswer + { + get { throw new NotImplementedException(); } + } + + public override bool RequiresUniqueEmail + { + get { throw new NotImplementedException(); } + } + + public override string ResetPassword(string username, string answer) + { + throw new NotImplementedException(); + } + + public override bool UnlockUser(string userName) + { + throw new NotImplementedException(); + } + + public override void UpdateUser(MembershipUser user) + { + throw new NotImplementedException(); + } + + public override bool ValidateUser(string username, string password) + { + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/umbraco/cms/businesslogic/member/MemberGroup.cs b/umbraco/cms/businesslogic/member/MemberGroup.cs new file mode 100644 index 0000000000..7deec1ddcb --- /dev/null +++ b/umbraco/cms/businesslogic/member/MemberGroup.cs @@ -0,0 +1,217 @@ +using System; +using System.Data; +using umbraco.DataLayer; +using System.Collections; + +namespace umbraco.cms.businesslogic.member +{ + /// + /// Membergroups are used for grouping Umbraco Members + /// + /// A Member can exist in multiple groups. + /// + /// It's possible to protect webpages/documents by membergroup. + /// + public class MemberGroup : CMSNode + { + private static Guid _objectType = new Guid("366e63b9-880f-4e13-a61c-98069b029728"); + + /// + /// Initialize a new object of the MemberGroup class + /// + /// Membergroup id + public MemberGroup(int id): base(id) + { + + } + + /// + /// Initialize a new object of the MemberGroup class + /// + /// Membergroup id + public MemberGroup(Guid id) : base(id) + { + + } + + /// + /// Deltes the current membergroup + /// + public new void delete() + { + DeleteEventArgs e = new DeleteEventArgs(); + FireBeforeDelete(e); + if (!e.Cancel) { + // delete member specific data! + SqlHelper.ExecuteNonQuery("Delete from cmsMember2MemberGroup where memberGroup = @id", + SqlHelper.CreateParameter("@id", Id)); + + // Delete all content and cmsnode specific data! + base.delete(); + FireAfterDelete(e); + } + } + + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public override void Save() + { + SaveEventArgs e = new SaveEventArgs(); + FireBeforeSave(e); + + if (!e.Cancel) { + FireAfterSave(e); + } + } + + /// + /// Retrieve a list of all existing MemberGroups + /// + public static MemberGroup[] GetAll + { + get + { + Guid[] tmp = getAllUniquesFromObjectType(_objectType); + MemberGroup[] retval = new MemberGroup[tmp.Length]; + + int i = 0; + foreach(Guid g in tmp) + { + retval[i]= new MemberGroup(g); + i++; + } + return retval; + } + } + + public int[] GetMembersAsIds() { + ArrayList retval = new ArrayList(); + IRecordsReader dr = SqlHelper.ExecuteReader("select member from cmsMember2MemberGroup where memberGroup = @memberGroup", + SqlHelper.CreateParameter("@memberGroup", Id)); + while (dr.Read()) { + retval.Add(dr.GetInt("member")); + } + dr.Close(); + + return (int[])retval.ToArray(typeof(int)); + } + + public Member[] GetMembers() { + ArrayList retval = new ArrayList(); + IRecordsReader dr = SqlHelper.ExecuteReader("select member from cmsMember2MemberGroup where memberGroup = @memberGroup", + SqlHelper.CreateParameter("@memberGroup", Id)); + while (dr.Read()) { + retval.Add(new Member(dr.GetInt("member"))); + } + dr.Close(); + + return (Member[])retval.ToArray(typeof(Member)); + } + + public Member[] GetMembers(string usernameToMatch) { + ArrayList retval = new ArrayList(); + IRecordsReader dr = SqlHelper.ExecuteReader("select member from cmsMember2MemberGroup inner join cmsMember on cmsMember.nodeId = cmsMember2MemberGroup.member where loginName like @username and memberGroup = @memberGroup", + SqlHelper.CreateParameter("@memberGroup", Id), SqlHelper.CreateParameter("@username", usernameToMatch + "%")); + while (dr.Read()) { + retval.Add(new Member(dr.GetInt("member"))); + } + dr.Close(); + + return (Member[])retval.ToArray(typeof(Member)); + } + + public bool HasMember(int memberId) { + return SqlHelper.ExecuteScalar("select count(member) from cmsMember2MemberGroup where member = @member and memberGroup = @membergroup", + SqlHelper.CreateParameter("@member", memberId), + SqlHelper.CreateParameter("@memberGroup", Id)) > 0; + } + + /// + /// Get a membergroup by it's name + /// + /// Name of the membergroup + /// If a MemberGroup with the given name exists, it will return this, else: null + public static MemberGroup GetByName(string Name) + { + try + { + return + new MemberGroup(SqlHelper.ExecuteScalar( + "select id from umbracoNode where Text = @text and nodeObjectType = @objectType", + SqlHelper.CreateParameter("@text", Name), + SqlHelper.CreateParameter("@objectType", _objectType))); + } + catch + { + return null; + } + } + + + /// + /// Create a new MemberGroup + /// + /// The name of the MemberGroup + /// The creator of the MemberGroup + /// The new MemberGroup + public static MemberGroup MakeNew(string Name, BusinessLogic.User u) + { + Guid newId = Guid.NewGuid(); + CMSNode.MakeNew(-1,_objectType, u.Id, 1, Name, newId); + MemberGroup mg = new MemberGroup(newId); + NewEventArgs e = new NewEventArgs(); + mg.OnNew(e); + return mg; + } + + //EVENTS + /// + /// The save event handler + /// + public delegate void SaveEventHandler(MemberGroup sender, SaveEventArgs e); + /// + /// The new event handler + /// + public delegate void NewEventHandler(MemberGroup sender, NewEventArgs e); + /// + /// The delete event handler + /// + public delegate void DeleteEventHandler(MemberGroup sender, DeleteEventArgs e); + + + /// + /// Occurs when a language is saved. + /// + public static event SaveEventHandler BeforeSave; + protected virtual void FireBeforeSave(SaveEventArgs e) { + if (BeforeSave != null) + BeforeSave(this, e); + } + + public static event SaveEventHandler AfterSave; + protected virtual void FireAfterSave(SaveEventArgs e) { + if (AfterSave != null) + AfterSave(this, e); + } + + public static event NewEventHandler New; + protected virtual void OnNew(NewEventArgs e) { + if (New != null) + New(this, e); + } + + public static event DeleteEventHandler BeforeDelete; + protected virtual void FireBeforeDelete(DeleteEventArgs e) { + if (BeforeDelete != null) + BeforeDelete(this, e); + } + + public static event DeleteEventHandler AfterDelete; + protected virtual void FireAfterDelete(DeleteEventArgs e) { + if (AfterDelete != null) + AfterDelete(this, e); + } + } +} diff --git a/umbraco/cms/businesslogic/member/MemberType.cs b/umbraco/cms/businesslogic/member/MemberType.cs new file mode 100644 index 0000000000..6f9f3a3f2d --- /dev/null +++ b/umbraco/cms/businesslogic/member/MemberType.cs @@ -0,0 +1,228 @@ +using System; +using System.Data; + + +namespace umbraco.cms.businesslogic.member +{ + /// MemberType + /// + /// Due to the inheritance of the ContentType class, it enables definition of generic datafields on a Members. + /// + public class MemberType : ContentType + { + private static Guid _objectType = new Guid("9b5416fb-e72f-45a9-a07b-5a9a2709ce43"); + + /// + /// Initializes a new instance of the MemberType class. + /// + /// MemberType id + public MemberType(int id) : base(id) + { + } + /// + /// Initializes a new instance of the MemberType class. + /// + /// MemberType id + public MemberType(Guid id) : base(id) + { + } + + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public override void Save() + { + SaveEventArgs e = new SaveEventArgs(); + FireBeforeSave(e); + + if(!e.Cancel){ + FireAfterSave(e); + } + } + + + /// + /// Create a new MemberType + /// + /// The name of the MemberType + /// Creator of the MemberType + public static MemberType MakeNew( BusinessLogic.User u,string Text) + { + + int ParentId= -1; + int level = 1; + Guid uniqueId = Guid.NewGuid(); + CMSNode n = CMSNode.MakeNew(ParentId, _objectType, u.Id, level,Text, uniqueId); + + ContentType.Create(n.Id, Text,""); + MemberType mt = new MemberType(n.Id); + NewEventArgs e = new NewEventArgs(); + mt.OnNew(e); + + return mt; + } + + /// + /// Retrieve a list of all MemberTypes + /// + new public static MemberType[] GetAll { + get + { + Guid[] Ids = CMSNode.getAllUniquesFromObjectType(_objectType); + + MemberType[] retVal = new MemberType[Ids.Length]; + for (int i = 0; i < Ids.Length; i++) retVal[i] = new MemberType(Ids[i]); + return retVal; + } + } + + /// + /// Get an true/false if the Member can edit the given data defined in the propertytype + /// + /// Propertytype to edit + /// True if the Member can edit the data + public bool MemberCanEdit(propertytype.PropertyType pt) { + if(propertyTypeRegistered(pt)) { + return (SqlHelper.ExecuteScalar("Select memberCanEdit from cmsMemberType where NodeId = " + this.Id +" And propertytypeId = "+pt.Id)); + } + return false; + } + + /// + /// Get a MemberType by it's alias + /// + /// The alias of the MemberType + /// The MemberType with the given Alias + public static new MemberType GetByAlias(string Alias) + { + return new MemberType(SqlHelper.ExecuteScalar("SELECT nodeid from cmsContentType where alias = @alias", + SqlHelper.CreateParameter("@alias", Alias))); + } + + + /// + /// Get an true/false if the given data defined in the propertytype, should be visible on the members profile page + /// + /// Propertytype + /// True if the data should be displayed on the profilepage + public bool ViewOnProfile(propertytype.PropertyType pt) + { + if(propertyTypeRegistered(pt)) + { + return SqlHelper.ExecuteScalar("Select viewOnProfile from cmsMemberType where NodeId = " + this.Id +" And propertytypeId = "+pt.Id); + } + return false; + } + + /// + /// Set if the member should be able to edit the data defined by its propertytype + /// + /// PropertyType + /// True/False if Members of the type shold be able to edit the data + public void setMemberCanEdit(propertytype.PropertyType pt, bool value) { + int tmpval = 0; + if (value) tmpval = 1; + if (propertyTypeRegistered(pt)) + SqlHelper.ExecuteNonQuery("Update cmsMemberType set memberCanEdit = " + tmpval + " where NodeId = " + this.Id +" And propertytypeId = "+pt.Id); + else + SqlHelper.ExecuteNonQuery("insert into cmsMemberType (NodeId, propertytypeid, memberCanEdit,viewOnProfile) values ("+this.Id+","+pt.Id+", "+tmpval+",0)"); + + } + + private bool propertyTypeRegistered(propertytype.PropertyType pt) { + return (SqlHelper.ExecuteScalar("Select count(pk) as tmp from cmsMemberType where NodeId = " + this.Id +" And propertytypeId = "+pt.Id) > 0); + } + + + /// + /// Set if the data should be displayed on members of this type's profilepage + /// + /// PropertyType + /// True/False if the data should be displayed + public void setMemberViewOnProfile(propertytype.PropertyType pt, bool value) + { + int tmpval = 0; + if (value) tmpval = 1; + if (propertyTypeRegistered(pt)) + SqlHelper.ExecuteNonQuery("Update cmsMemberType set viewOnProfile = " + tmpval + " where NodeId = " + this.Id +" And propertytypeId = "+pt.Id); + else + SqlHelper.ExecuteNonQuery("insert into cmsMemberType (NodeId, propertytypeid, viewOnProfile) values ("+this.Id+","+pt.Id+", "+tmpval+")"); + } + + /// + /// Delete the current MemberType. + /// + /// Deletes all Members of the type + /// + /// Use with care + /// + new public void delete() + { + DeleteEventArgs e = new DeleteEventArgs(); + + FireBeforeDelete(e); + + if (!e.Cancel) { + // delete all documents of this type + Member.DeleteFromType(this); + // delete membertype specific data + SqlHelper.ExecuteNonQuery("Delete from cmsMemberType where nodeId = " + this.Id); + + // Delete contentType + base.delete(); + FireAfterDelete(e); + } + } + + //EVENTS + /// + /// The save event handler + /// + public delegate void SaveEventHandler(MemberType sender, SaveEventArgs e); + /// + /// The new event handler + /// + public delegate void NewEventHandler(MemberType sender, NewEventArgs e); + /// + /// The delete event handler + /// + public delegate void DeleteEventHandler(MemberType sender, DeleteEventArgs e); + + + /// + /// Occurs when a language is saved. + /// + public static event SaveEventHandler BeforeSave; + protected virtual void FireBeforeSave(SaveEventArgs e) { + if (BeforeSave != null) + BeforeSave(this, e); + } + + public static event SaveEventHandler AfterSave; + protected virtual void FireAfterSave(SaveEventArgs e) { + if (AfterSave != null) + AfterSave(this, e); + } + + public static event NewEventHandler New; + protected virtual void OnNew(NewEventArgs e) { + if (New != null) + New(this, e); + } + + public static event DeleteEventHandler BeforeDelete; + protected virtual void FireBeforeDelete(DeleteEventArgs e) { + if (BeforeDelete != null) + BeforeDelete(this, e); + } + + public static event DeleteEventHandler AfterDelete; + protected virtual void FireAfterDelete(DeleteEventArgs e) { + if (AfterDelete != null) + AfterDelete(this, e); + } + + + } +} \ No newline at end of file diff --git a/umbraco/cms/businesslogic/propertytype/propertytype.cs b/umbraco/cms/businesslogic/propertytype/propertytype.cs new file mode 100644 index 0000000000..b6bbf53688 --- /dev/null +++ b/umbraco/cms/businesslogic/propertytype/propertytype.cs @@ -0,0 +1,365 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Web.UI; + +using umbraco.cms.businesslogic.cache; +using umbraco.cms.businesslogic.datatype; +using umbraco.cms.businesslogic.language; +using umbraco.interfaces; +using umbraco.DataLayer; +using umbraco.BusinessLogic; + +namespace umbraco.cms.businesslogic.propertytype +{ + /// + /// Summary description for propertytype. + /// + public class PropertyType + { + #region Declarations + + private string _alias; + private string _name; + private int _id; + private int _DataTypeId; + private int _contenttypeid; + private int _sortOrder; + private bool _mandatory = false; + private string _validationRegExp = ""; + private string _description = ""; + private int _tabId = 0; + private static string _connstring = GlobalSettings.DbDSN; + + private static object propertyTypeCacheSyncLock = new object(); + private static readonly string UmbracoPropertyTypeCacheKey = "UmbracoPropertyTypeCache"; + + #endregion + + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + #region Constructors + + public PropertyType(int id) + { + using (IRecordsReader dr = SqlHelper.ExecuteReader( + "Select mandatory, DataTypeId, tabId, ContentTypeId, sortOrder, alias, name, validationRegExp, description from cmsPropertyType where id=@id", + SqlHelper.CreateParameter("@id", id))) + { + if(!dr.Read()) + throw new ArgumentException("Propertytype with id: " + id + " doesnt exist!"); + _mandatory = dr.GetBoolean("mandatory"); + _id = id; + if(!dr.IsNull("tabId")) + _tabId = dr.GetInt("tabId"); + _sortOrder = dr.GetInt("sortOrder"); + _alias = dr.GetString("alias"); + _name = dr.GetString("Name"); + _validationRegExp = dr.GetString("validationRegExp"); + _DataTypeId = dr.GetInt("DataTypeId"); + _contenttypeid = dr.GetInt("contentTypeId"); + _description = dr.GetString("description"); + } + } + + #endregion + + #region Properties + + public DataTypeDefinition DataTypeDefinition + { + get { return DataTypeDefinition.GetDataTypeDefinition(_DataTypeId); } + set + { + _DataTypeId = value.Id; + this.InvalidateCache(); + SqlHelper.ExecuteNonQuery( + "Update cmsPropertyType set DataTypeId = " + value.Id + " where id=" + this.Id); + } + } + + public int Id + { + get { return _id; } + } + + public int TabId + { + get { return _tabId; } + set + { + _tabId = value; + this.InvalidateCache(); + SqlHelper.ExecuteNonQuery( "Update cmsPropertyType set tabId = @tabId where id = @id", + SqlHelper.CreateParameter("@tabId", value), SqlHelper.CreateParameter("@id", this.Id)); + } + } + + public bool Mandatory + { + get { return _mandatory; } + set + { + _mandatory = value; + this.InvalidateCache(); + SqlHelper.ExecuteNonQuery( + "Update cmsPropertyType set mandatory = @mandatory where id = @id", SqlHelper.CreateParameter("@mandatory", value), + SqlHelper.CreateParameter("@id", this.Id)); + } + } + + public string ValidationRegExp + { + get { return _validationRegExp; } + set + { + _validationRegExp = value; + this.InvalidateCache(); + SqlHelper.ExecuteNonQuery( + "Update cmsPropertyType set validationRegExp = @validationRegExp where id = @id", + SqlHelper.CreateParameter("@validationRegExp", value), SqlHelper.CreateParameter("@id", this.Id)); + } + } + + public string Description + { + get { + if (_description != null) { + if (!_description.StartsWith("#")) + return _description; + else { + Language lang = Language.GetByCultureCode(Thread.CurrentThread.CurrentCulture.Name); + if (lang != null) { + if (Dictionary.DictionaryItem.hasKey(_description.Substring(1, _description.Length - 1))) { + Dictionary.DictionaryItem di = new Dictionary.DictionaryItem(_description.Substring(1, _description.Length - 1)); + return di.Value(lang.id); + } + } + } + + return "[" + _description + "]"; + } else + return _description; + } + set + { + _description = value; + this.InvalidateCache(); + SqlHelper.ExecuteNonQuery( + "Update cmsPropertyType set description = @description where id = @id", SqlHelper.CreateParameter("@description", value), + SqlHelper.CreateParameter("@id", this.Id)); + } + } + + public int SortOrder + { + get { return _sortOrder; } + set + { + _sortOrder = value; + this.InvalidateCache(); + SqlHelper.ExecuteNonQuery( + "Update cmsPropertyType set sortOrder = @sortOrder where id = @id", SqlHelper.CreateParameter("@sortOrder", value), + SqlHelper.CreateParameter("@id", this.Id)); + } + } + + public string Alias + { + get { return _alias; } + set + { + _alias = value; + this.InvalidateCache(); + SqlHelper.ExecuteNonQuery("Update cmsPropertyType set alias = @alias where id= @id", + SqlHelper.CreateParameter("@alias", _alias), + SqlHelper.CreateParameter("@id", Id)); + } + } + + public int ContentTypeId + { + get { return _contenttypeid; } + } + + public string Name + { + get + { + if(!_name.StartsWith("#")) + return _name; + else + { + Language lang = Language.GetByCultureCode(Thread.CurrentThread.CurrentCulture.Name); + if(lang != null) + { + if(Dictionary.DictionaryItem.hasKey(_name.Substring(1, _name.Length - 1))) + { + Dictionary.DictionaryItem di = new Dictionary.DictionaryItem(_name.Substring(1, _name.Length - 1)); + return di.Value(lang.id); + } + } + + return "[" + _name + "]"; + } + } + set + { + _name = value; + InvalidateCache(); + SqlHelper.ExecuteNonQuery( + "UPDATE cmsPropertyType SET name=@name WHERE id=@id", + SqlHelper.CreateParameter("@name", _name), + SqlHelper.CreateParameter("@id", Id)); + } + } + + #endregion + + #region Methods + + public string GetRawName() + { + return _name; + } + public string GetRawDescription() { + return _description; + } + [MethodImpl(MethodImplOptions.Synchronized)] + public static PropertyType MakeNew(DataTypeDefinition dt, ContentType ct, string Name, string Alias) + { + PropertyType pt; + try + { + // The method is synchronized + SqlHelper.ExecuteNonQuery("INSERT INTO cmsPropertyType (DataTypeId, ContentTypeId, alias, name) VALUES (@DataTypeId, @ContentTypeId, @alias, @name)", + SqlHelper.CreateParameter("@DataTypeId", dt.Id), + SqlHelper.CreateParameter("@ContentTypeId", ct.Id), + SqlHelper.CreateParameter("@alias", Alias), + SqlHelper.CreateParameter("@name", Name)); + pt = new PropertyType(SqlHelper.ExecuteScalar("SELECT MAX(id) FROM cmsPropertyType")); + } + finally + { + // Clear cached items + System.Web.Caching.Cache c = System.Web.HttpRuntime.Cache; + if (c != null) + { + System.Collections.IDictionaryEnumerator cacheEnumerator = c.GetEnumerator(); + while (cacheEnumerator.MoveNext()) + { + if (cacheEnumerator.Key is string && ((string)cacheEnumerator.Key).StartsWith(UmbracoPropertyTypeCacheKey)) + { + Cache.ClearCacheItem((string)cacheEnumerator.Key); + } + } + } + } + + return pt; + } + + public static PropertyType[] GetAll() + { + List result = new List(); + using (IRecordsReader dr = + SqlHelper.ExecuteReader("select id, Name from cmsPropertyType order by Name")) + { + while(dr.Read()) + { + PropertyType pt = GetPropertyType(dr.GetInt("id")); + if(pt != null) + result.Add(pt); + } + return result.ToArray(); + } + } + + public void delete() + { + // flush cache + FlushCache(); + + // Delete all properties of propertytype + foreach(Content c in Content.getContentOfContentType(new ContentType(_contenttypeid))) + { + c.getProperty(this).delete(); + } + // Delete PropertyType .. + SqlHelper.ExecuteNonQuery("Delete from cmsPropertyType where id = " + this.Id); + this.InvalidateCache(); + } + + public IDataType GetEditControl(object Value, bool IsPostBack) + { + IDataType dt = this.DataTypeDefinition.DataType; + dt.DataEditor.Editor.ID = this.Alias; + IData df = this.DataTypeDefinition.DataType.Data; + ((Control)dt.DataEditor.Editor).ID = this.Alias; + + if(!IsPostBack) + { + if(Value != null) + dt.Data.Value = Value; + else + dt.Data.Value = ""; + } + + return dt; + } + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public virtual void Save() + { + FlushCache(); + } + + protected virtual void FlushCache() + { + // clear local cache + cache.Cache.ClearCacheItem(GetCacheKey(Id)); + + // clear cache in contentype + Cache.ClearCacheItem("ContentType_PropertyTypes_Content:" + this._contenttypeid.ToString()); + + // clear cache in tab + ContentType.FlushTabCache(_tabId, ContentTypeId); + } + + public static PropertyType GetPropertyType(int id) + { + return Cache.GetCacheItem(GetCacheKey(id), propertyTypeCacheSyncLock, + TimeSpan.FromMinutes(30), + delegate + { + try + { + return new PropertyType(id); + } + catch + { + return null; + } + }); + } + + private void InvalidateCache() + { + Cache.ClearCacheItem(GetCacheKey(this.Id)); + } + + private static string GetCacheKey(int id) + { + return UmbracoPropertyTypeCacheKey + id; + } + + #endregion + } +} diff --git a/umbraco/cms/businesslogic/recycleBin.cs b/umbraco/cms/businesslogic/recycleBin.cs new file mode 100644 index 0000000000..307df59984 --- /dev/null +++ b/umbraco/cms/businesslogic/recycleBin.cs @@ -0,0 +1,63 @@ +using System; +using System.Collections.Generic; +using System.Text; + +using umbraco.DataLayer; + +namespace umbraco.cms.businesslogic +{ + public class RecycleBin : CMSNode + { + private Guid _nodeObjectType; + + public RecycleBin(Guid nodeObjectType) : base(-20) { + _nodeObjectType = nodeObjectType; + } + + /// + /// If I smell, I'm not empty + /// + public bool Smells() + { + return (SqlHelper.ExecuteScalar( + "select count(id) from umbracoNode where nodeObjectType = @nodeObjectType and parentId = @parentId", + SqlHelper.CreateParameter("@parentId", this.Id), + SqlHelper.CreateParameter("@nodeObjectType", _nodeObjectType)) > 0); + + } + + public override umbraco.BusinessLogic.console.IconI[] Children + { + get + { + System.Collections.ArrayList tmp = new System.Collections.ArrayList(); + + IRecordsReader dr = SqlHelper.ExecuteReader( "select id from umbracoNode where ParentID = " + this.Id + " And nodeObjectType = @type order by sortOrder", + SqlHelper.CreateParameter("@type",_nodeObjectType)); + + while (dr.Read()) + tmp.Add(dr.GetInt("Id")); + + dr.Close(); + + CMSNode[] retval = new CMSNode[tmp.Count]; + + for (int i = 0; i < tmp.Count; i++) + retval[i] = new CMSNode((int)tmp[i]); + + return retval; + } + } + + /// + /// Get the number of items in the Recycle Bin + /// + /// The number of all items in the Recycle Bin + public static int Count() + { + return SqlHelper.ExecuteScalar("select count(id) from umbracoNode where path like '%,-20,%'"); + } + + + } +} diff --git a/umbraco/cms/businesslogic/relation/Relation.cs b/umbraco/cms/businesslogic/relation/Relation.cs new file mode 100644 index 0000000000..fa51a742da --- /dev/null +++ b/umbraco/cms/businesslogic/relation/Relation.cs @@ -0,0 +1,177 @@ +using System; +using System.Data; +using System.Runtime.CompilerServices; +using System.Collections.Generic; + +using umbraco.DataLayer; +using umbraco.BusinessLogic; + +namespace umbraco.cms.businesslogic.relation +{ + /// + /// Summary description for Relation. + /// + public class Relation + { + private int _id; + private CMSNode _parentNode; + private CMSNode _childNode; + private string _comment; + private DateTime _datetime; + private RelationType _relType; + + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + public CMSNode Parent + { + get {return _parentNode;} + set + { + SqlHelper.ExecuteNonQuery("update umbracoRelation set parentId = @parent where id = " + this.Id, SqlHelper.CreateParameter("@parent", value.Id)); + _parentNode = value; + } + } + + public CMSNode Child + { + get {return _childNode;} + set + { + SqlHelper.ExecuteNonQuery("update umbracoRelation set childId = @child where id = " + this.Id, SqlHelper.CreateParameter("@child", value.Id)); + _childNode = value; + } + } + + public string Comment + { + get {return _comment;} + set + { + SqlHelper.ExecuteNonQuery("update umbracoRelation set comment = @comment where id = " + this.Id, SqlHelper.CreateParameter("@comment", value)); + _comment = value; + } + } + + public DateTime CreateDate + { + get {return _datetime;} + } + + public RelationType RelType + { + get {return _relType;} + set + { + SqlHelper.ExecuteNonQuery("update umbracoRelation set relType = @relType where id = " + this.Id, SqlHelper.CreateParameter("@relType", value.Id)); + _relType = value; + } + } + + public int Id + { + get {return _id;} + } + + public Relation(int Id) + { + using (IRecordsReader dr = SqlHelper.ExecuteReader("select * from umbracoRelation where id = @id", SqlHelper.CreateParameter("@id", Id))) + { + if(dr.Read()) + { + this._id = dr.GetInt("id"); + this._parentNode = new CMSNode(dr.GetInt("parentId")); + this._childNode = new CMSNode(dr.GetInt("childId")); + this._relType = RelationType.GetById(dr.GetInt("relType")); + this._comment = dr.GetString("comment"); + this._datetime = dr.GetDateTime("datetime"); + } + } + } + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public virtual void Save() + { + } + + + public void Delete() + { + SqlHelper.ExecuteNonQuery("delete from umbracoRelation where id = @id", SqlHelper.CreateParameter("@id", this.Id)); + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public static Relation MakeNew(int ParentId, int ChildId, RelationType RelType, string Comment) + { + // The method is synchronized + SqlHelper.ExecuteNonQuery("INSERT INTO umbracoRelation (childId, parentId, relType, comment) VALUES (@childId, @parentId, @relType, @comment)", + SqlHelper.CreateParameter("@childId", ChildId), + SqlHelper.CreateParameter("@parentId", ParentId), + SqlHelper.CreateParameter("@relType", RelType.Id), + SqlHelper.CreateParameter("@comment", Comment)); + return new Relation(SqlHelper.ExecuteScalar("SELECT MAX(id) FROM umbracoRelation")); + } + + + + public static List GetRelationsAsList(int NodeId) + { + List _rels = new List(); + System.Collections.ArrayList tmp = new System.Collections.ArrayList(); + using (IRecordsReader dr = SqlHelper.ExecuteReader("select umbracoRelation.id from umbracoRelation inner join umbracoRelationType on umbracoRelationType.id = umbracoRelation.relType where umbracoRelation.parentId = @id or (umbracoRelation.childId = @id and umbracoRelationType.[dual] = 1)", SqlHelper.CreateParameter("@id", NodeId))) + { + while(dr.Read()) + { + _rels.Add(new Relation(dr.GetInt("id"))); + } + } + + return _rels; + } + +public static bool IsRelated(int ParentID, int ChildId) { + int count = SqlHelper.ExecuteScalar("SELECT count(*) FROM umbracoRelation WHERE childId = @childId AND parentId = @parentId", + SqlHelper.CreateParameter("@childId", ChildId), + SqlHelper.CreateParameter("@parentId", ParentID)); + + return (count > 0); + } + + public static bool IsRelated(int ParentID, int ChildId, RelationType Filter) { + + int count = SqlHelper.ExecuteScalar("SELECT count(*) FROM umbracoRelation WHERE childId = @childId AND parentId = @parentId AND relType = @relType", + SqlHelper.CreateParameter("@childId", ChildId), + SqlHelper.CreateParameter("@parentId", ParentID), + SqlHelper.CreateParameter("@relType", Filter.Id) + ); + + return (count > 0); + } + + public static Relation[] GetRelations(int NodeId) + { + return GetRelationsAsList(NodeId).ToArray(); + } + + public static Relation[] GetRelations(int NodeId, RelationType Filter) + { + System.Collections.ArrayList tmp = new System.Collections.ArrayList(); + using (IRecordsReader dr = SqlHelper.ExecuteReader("select umbracoRelation.id from umbracoRelation inner join umbracoRelationType on umbracoRelationType.id = umbracoRelation.relType and umbracoRelationType.id = @relTypeId where umbracoRelation.parentId = @id or (umbracoRelation.childId = @id and umbracoRelationType.[dual] = 1)", SqlHelper.CreateParameter("@id", NodeId), SqlHelper.CreateParameter("@relTypeId", Filter.Id))) + { + while(dr.Read()) + { + tmp.Add(dr.GetInt("id")); + } + } + + Relation[] retval = new Relation[tmp.Count]; + + for (int i = 0; i < tmp.Count; i++) retval[i] = new Relation((int)tmp[i]); + return retval; + } + } +} diff --git a/umbraco/cms/businesslogic/relation/RelationType.cs b/umbraco/cms/businesslogic/relation/RelationType.cs new file mode 100644 index 0000000000..c3259e8c61 --- /dev/null +++ b/umbraco/cms/businesslogic/relation/RelationType.cs @@ -0,0 +1,148 @@ +using System; +using System.Data; +using System.Web; + +using umbraco.BusinessLogic; +using umbraco.DataLayer; + +namespace umbraco.cms.businesslogic.relation +{ + /// + /// Summary description for RelationType. + /// + public class RelationType + { + #region Declarations + + private int _id; + private bool _dual; + private string _name; + //private Guid _parentObjectType; + //private Guid _childObjectType; + private string _alias; + + private static object relationTypeSyncLock = new object(); + + #endregion + + private static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + #region Constructors + + public RelationType(int Id) + { + using (IRecordsReader dr = SqlHelper.ExecuteReader( + "select id, dual, name, alias from umbracoRelationType where id = @id", SqlHelper.CreateParameter("@id", Id))) + { + if(dr.Read()) + { + this._id = dr.GetInt("id"); + this._dual = dr.GetBoolean("dual"); + //this._parentObjectType = dr.GetGuid("parentObjectType"); + //this._childObjectType = dr.GetGuid("childObjectType"); + this._name = dr.GetString("name"); + this._alias = dr.GetString("alias"); + } + } + } + + #endregion + + #region Properties + + public int Id + { + get { return _id; } + } + + public string Name + { + get { return _name; } + set + { + _name = value; + SqlHelper.ExecuteNonQuery( + "update umbracoRelationType set name = @name where id = " + this.Id.ToString(), SqlHelper.CreateParameter("@name", value)); + this.InvalidateCache(); + } + } + + public string Alias + { + get { return _alias; } + set + { + _alias = value; + SqlHelper.ExecuteNonQuery( + "update umbracoRelationType set alias = @alias where id = " + this.Id.ToString(), SqlHelper.CreateParameter("@alias", value)); + this.InvalidateCache(); + } + } + + public bool Dual + { + get { return _dual; } + set + { + _dual = value; + SqlHelper.ExecuteNonQuery( + "update umbracoRelationType set [dual] = @dual where id = " + this.Id.ToString(), SqlHelper.CreateParameter("@dual", value)); + this.InvalidateCache(); + } + } + + #endregion + + #region Methods + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public virtual void Save() + { + } + + public static RelationType GetById(int id) + { + try + { + return umbraco.cms.businesslogic.cache.Cache.GetCacheItem( + GetCacheKey(id), relationTypeSyncLock, TimeSpan.FromMinutes(30), + delegate { return new RelationType(id); }); + } + catch + { + return null; + } + } + + public static RelationType GetByAlias(string Alias) + { + try + { + return GetById(SqlHelper.ExecuteScalar( + "select id from umbracoRelationType where alias = @alias", + SqlHelper.CreateParameter("@alias", Alias))); + } + catch + { + return null; + } + } + + protected virtual void InvalidateCache() + { + umbraco.cms.businesslogic.cache.Cache.ClearCacheItem(GetCacheKey(this.Id)); + } + + private static string GetCacheKey(int id) + { + return string.Format("RelationTypeCacheItem_{0}", id); + } + + #endregion + } +} \ No newline at end of file diff --git a/umbraco/cms/businesslogic/stat/Entry.cs b/umbraco/cms/businesslogic/stat/Entry.cs new file mode 100644 index 0000000000..05c6c08baf --- /dev/null +++ b/umbraco/cms/businesslogic/stat/Entry.cs @@ -0,0 +1,38 @@ +using System; + +namespace umbraco.cms.businesslogic.stat +{ + /// + /// Summary description for Entry. + /// + public class Entry + { + private int _currentPage; + private int _lastPage; + private System.DateTime _entryTime; + + public Entry(int CurrentPage, int LastPage) + { + _entryTime = System.DateTime.Now; + _currentPage = CurrentPage; + _lastPage = LastPage; + } + + public int CurrentPage + { + get {return _currentPage;} + set {_currentPage = value;} + } + public int LastPage + { + get {return _lastPage;} + set {_lastPage = value;} + } + public DateTime EntryTime + { + get {return _entryTime;} + set {_entryTime = value;} + } + + } +} diff --git a/umbraco/cms/businesslogic/stat/Session.cs b/umbraco/cms/businesslogic/stat/Session.cs new file mode 100644 index 0000000000..62ae34536b --- /dev/null +++ b/umbraco/cms/businesslogic/stat/Session.cs @@ -0,0 +1,330 @@ +using System; +using System.Collections; +using System.Data; +using System.Diagnostics; +using System.Text.RegularExpressions; +using System.Threading; +using System.Web; + +using umbraco.cms.businesslogic.member; +using umbraco.DataLayer; +using umbraco.BusinessLogic; + +namespace umbraco.cms.businesslogic.stat +{ + /// + /// Summary description for Session. + /// + /// + public class Session + { + #region Declarations + + private static Hashtable _sessions = Hashtable.Synchronized(new Hashtable()); + + private ArrayList _entries = new ArrayList(); + private Guid _sessionId = Guid.NewGuid(); + private Guid _member; + private int _newsletter = 0; + private bool _returningUser = false; + private bool _cookies = false; + private DateTime _sessionStart; + private string _language = ""; + private string _userAgent = ""; + private string _browserBrand = "unknown"; + private string _browserVersion = "unknown"; + private string _browserType = "unknown"; + private string _os = "unknown"; + private string _ip = ""; + private string _referrer = ""; + private string _referrerKeyword = ""; + private int _sqlSessionId; + private string _visitorId; + private bool _isHuman = true; + + #endregion + + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + public static string Request(string key) + { + if(HttpContext.Current.Request[key] != null) + return HttpContext.Current.Request[key]; + else + return ""; + } + + public Session() + { + + HttpRequest currentRequest = HttpContext.Current.Request; + + // Update member id + if(Member.IsLoggedOn()) + _member = new Member(Member.CurrentMemberId()).UniqueId; + + // TODO: Newsletter id + + if(Request("umbNl") != "") + _newsletter = int.Parse(Request("umbNl")); + + // Add session start time + _sessionStart = DateTime.Now; + + // Returning user + if(currentRequest.Cookies["umbracoReturningUser"] != null) + if(bool.Parse(currentRequest.Cookies["umbracoReturningUser"].Value)) + _returningUser = true; + + // User id + if(currentRequest.Cookies["umbracoVisitorId"] != null && !string.IsNullOrEmpty(currentRequest.Cookies["umbracoVisitorId"].Value)) + _visitorId = currentRequest.Cookies["umbracoVisitorId"].Value; + else + _visitorId = Guid.NewGuid().ToString(); + + // Useragent + if(currentRequest.UserAgent == null) + _userAgent = "Unknown"; + else + _userAgent = currentRequest.UserAgent.ToLower(); + + // System OS and Browser (based on useragent) + if(currentRequest.Browser != null) + { + _os = currentRequest.Browser.Platform; + _browserBrand = currentRequest.Browser.Browser; + _browserVersion = currentRequest.Browser.Version; + _browserType = currentRequest.Browser.Type; + + // Cookies + if(currentRequest.Browser.Cookies) + _cookies = true; + } + + // Detect bots + if(_userAgent.IndexOf("bot") > -1 || _browserBrand.ToLower() == "unknown") + _isHuman = false; + + // Language + if(currentRequest.UserLanguages != null) + { + if(currentRequest.UserLanguages.Length > -1) + _language = currentRequest.UserLanguages[0]; + } + + // IP + _ip = currentRequest.UserHostAddress; + + // Referer and keyword + if(currentRequest.UrlReferrer != null) + { + _referrer = currentRequest.UrlReferrer.ToString(); + _referrerKeyword = findKeyword(_referrer); + } + + this.LogStatSession(); + + // Add cookies + if(Array.IndexOf(HttpContext.Current.Response.Cookies.AllKeys, "umbracoVisitorId") > -1) + HttpContext.Current.Response.Cookies.Remove("umbracoVisitorId"); + if(Array.IndexOf(HttpContext.Current.Response.Cookies.AllKeys, "umbracoReturningUser") > -1) + HttpContext.Current.Response.Cookies.Remove("umbracoReturningUser"); + + // Add cookie with visitor-id + HttpCookie c = new HttpCookie("umbracoVisitorId", _visitorId); + c.Value = _visitorId; + c.Expires = DateTime.Now.AddYears(1); + HttpContext.Current.Response.Cookies.Add(c); + + // Add cookie with returning user + HttpCookie c2 = new HttpCookie("umbracoReturningUser", "true"); + c2.Value = "true"; + c2.Expires = DateTime.Now.AddYears(1); + HttpContext.Current.Response.Cookies.Add(c2); + + // Check for old session id + if(HttpContext.Current.Session["umbracoSessionId"] != null) + { + _sessionId = new Guid(HttpContext.Current.Session["umbracoSessionId"].ToString()); + + // If it exists in the servers session collection, we need to remove it + if(_sessions.ContainsKey(_sessionId)) + _sessions.Remove(_sessionId); + } + else + { + // Add guid to visitor + HttpContext.Current.Session.Add("umbracoSessionId", _sessionId.ToString()); + /* System.Web.HttpCookie c = new System.Web.HttpCookie("umbracoSessionId"); + c.Expires = DateTime.Now.AddDays(1); + c.Value = _sessionId.ToString(); + System.Web.HttpContext.Current.Response.Cookies.Add(c); + */ + } + + _sessions.Add(_sessionId, this); + } + + private void LogStatSession() + { + // Save to db + IParameter[] sqlParams = { + SqlHelper.CreateParameter("@MemberId", this._member), + SqlHelper.CreateParameter("@NewsletterId", this._newsletter), + SqlHelper.CreateParameter("@ReturningUser", this._returningUser), + SqlHelper.CreateParameter("@SessionStart", this._sessionStart), + SqlHelper.CreateParameter("@Language", this._language), + SqlHelper.CreateParameter("@UserAgent", this._userAgent), + SqlHelper.CreateParameter("@Browser", this._browserBrand), + SqlHelper.CreateParameter("@BrowserVersion", this._browserVersion), + SqlHelper.CreateParameter("@OperatingSystem", this._os), + SqlHelper.CreateParameter("@Cookies", this._cookies), + SqlHelper.CreateParameter("@Ip", this._ip), + SqlHelper.CreateParameter("@Referrer", this._referrer), + SqlHelper.CreateParameter("@ReferrerKeyword", this._referrerKeyword), + SqlHelper.CreateParameter("@visitorId", this._visitorId), + SqlHelper.CreateParameter("@browserType", this._browserType), + SqlHelper.CreateParameter("@isHuman", this._isHuman) + }; + + WaitCallback callback = + delegate + { + try + { + // cannot synchronize inline delegate, so lock on type + lock (GetType()) + { + SqlHelper.ExecuteNonQuery("INSERT INTO umbracoStatSession (MemberId, NewsletterId, ReturningUser, SessionStart, [Language], UserAgent, Browser, BrowserVersion, OperatingSystem, Ip, Referrer, ReferrerKeyword, allowCookies, browserType, visitorId, isHuman) VALUES (@MemberId, @NewsletterId, @ReturningUser, @SessionStart, @Language, @UserAgent, @Browser, @BrowserVersion, @OperatingSystem, @Ip, @Referrer, @ReferrerKeyword, @Cookies, @browserType, @visitorId, @isHuman)", sqlParams); + this._sqlSessionId = SqlHelper.ExecuteScalar("SELECT MAX(id) FROM umbracoStatSession"); + } + } + catch(Exception e) + { + Debug.WriteLine("Error writing to db - umbracoStatSession: " + e); + } + }; + if (GlobalSettings.EnableAsyncStatLogging) + { + ThreadPool.QueueUserWorkItem(callback); + } + else + { + callback(null); + } + } + + public void EndSession() + { + updateSessionTime(); + + // Remove from hashtable + _sessions.Remove(this._sessionId); + } + + private void updateSessionTime() + { + WaitCallback callback = + delegate + { + try + { + SqlHelper.ExecuteNonQuery( + "update umbracoStatSession set sessionEnd = @sessionEnd where id = @id", + SqlHelper.CreateParameter("@sessionEnd", DateTime.Now), + SqlHelper.CreateParameter("@id", _sqlSessionId)); + } + catch(Exception e) + { + Debug.WriteLine("Error writing to db - umbracoStatSession: " + e); + } + }; + // Save end time to db + if(GlobalSettings.EnableAsyncStatLogging) + ThreadPool.QueueUserWorkItem(callback); + else + callback(null); + } + + private string findKeyword(string refString) + { + Match keyword = Regex.Match(refString, @"[\?|\&]q=([^\&]*)|[\?|\&]query=([^\&]*)|[\?|\&]p=([^\&]*)", + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + if(keyword.Success) + if(keyword.Groups[0].Value != "") + return keyword.Groups[0].Value.Trim().Replace("?q=", "").Replace("&q=", ""); + else if(keyword.Groups[1].Value != "") + return keyword.Groups[1].Value.Trim().Replace("?query=", "").Replace("&query=", ""); + else if(keyword.Groups[2].Value != "") + return keyword.Groups[2].Value.Trim().Replace("?p=", "").Replace("&p=", ""); + else + // will never be called + return ""; + else + return ""; + } + + public void AddEntry(int CurrentPage) + { + int LastPage; + if(_entries.Count > 0) + LastPage = ((Entry)_entries[_entries.Count - 1]).CurrentPage; + else + LastPage = 0; + + Entry e = new Entry(CurrentPage, LastPage); + _entries.Add(e); + + WaitCallback callback = + delegate + { + try + { + SqlHelper.ExecuteNonQuery( + "insert into umbracoStatEntry (SessionId, EntryTime, RefNodeId, NodeId) values (@SessionId, @EntryTime, @RefNodeId, @NodeId)", + SqlHelper.CreateParameter("@SessionId", _sqlSessionId), + SqlHelper.CreateParameter("@EntryTime", e.EntryTime), + SqlHelper.CreateParameter("@RefNodeId", e.LastPage), + SqlHelper.CreateParameter("@NodeId", e.CurrentPage)); + } + catch(Exception e1) + { + Debug.WriteLine("Error writing to db - umbracoStatEntry: " + e1); + } + }; + + // Save to db + if (GlobalSettings.EnableAsyncStatLogging) + ThreadPool.QueueUserWorkItem(callback); + else + callback(null); + + updateSessionTime(); + } + + public static void AddEntry(Guid SessionId, int CurrentPage) + { + // If session doesn't exists then add it + if(_sessions.ContainsKey(SessionId)) + { + Session session = _sessions[SessionId] as Session; + if(session != null) + session.AddEntry(CurrentPage); + } + } + + public static void EndSession(Guid SessionId) + { + // If session doesn't exists then add it + if(_sessions.ContainsKey(SessionId)) + { + Session session = _sessions[SessionId] as Session; + if(session != null) + session.EndSession(); + } + } + } +} \ No newline at end of file diff --git a/umbraco/cms/businesslogic/task/Task.cs b/umbraco/cms/businesslogic/task/Task.cs new file mode 100644 index 0000000000..8eb680dd40 --- /dev/null +++ b/umbraco/cms/businesslogic/task/Task.cs @@ -0,0 +1,284 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Data; +using System.Text; +using System.Runtime.CompilerServices; + +using umbraco.BusinessLogic; +using umbraco.DataLayer; + +namespace umbraco.cms.businesslogic.task +{ + /// + /// An umbraco task is currently only used with the translation workflow in umbraco. But is extendable to cover other taskbased system as well. + /// A task represent a simple job, it will always be assigned to a user, related to a node, and contain a comment about the task. + /// The user attached to the task can complete the task, and the author of the task can reopen tasks that are not complete correct. + /// + /// Tasks can in umbraco be used for setting up simple workflows, and contains basic controls structures to determine if the task is completed or not. + /// + public class Task + { + + #region Properties + private int _id; + + /// + /// Gets or sets the id. + /// + /// The id. + public int Id + { + get { return _id; } + set { _id = value; } + } + + private bool _closed; + + /// + /// Gets or sets a value indicating whether this is closed. + /// + /// true if closed; otherwise, false. + public bool Closed + { + get { return _closed; } + set { _closed = value; } + } + + + private CMSNode _node; + + /// + /// Gets or sets the node. + /// + /// The node. + public CMSNode Node + { + get { return _node; } + set { _node = value; } + } + + private TaskType _type; + + /// + /// Gets or sets the type. + /// + /// The type. + public TaskType Type + { + get { return _type; } + set { _type = value; } + } + + + private User _parentUser; + + /// + /// Gets or sets the parent user. + /// + /// The parent user. + public User ParentUser + { + get { return _parentUser; } + set { _parentUser = value; } + } + + private string _comment; + + /// + /// Gets or sets the comment. + /// + /// The comment. + public string Comment + { + get { return _comment; } + set { _comment = value; } + } + + + private DateTime _date; + + /// + /// Gets or sets the date. + /// + /// The date. + public DateTime Date + { + get { return _date; } + set { _date = value; } + } + + private User _user; + + /// + /// Gets or sets the user. + /// + /// The user. + public User User + { + get { return _user; } + set { _user = value; } + } + + /// + /// Gets the SQL helper. + /// + /// The SQL helper. + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + #endregion + + #region Constructors + + /// + /// Initializes a new instance of the class. + /// + public Task() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The task id. + public Task(int TaskId) + { + using (IRecordsReader dr = + SqlHelper.ExecuteReader( + "select taskTypeId, nodeId, parentUserId, userId, DateTime, comment, closed from cmsTask where id = @id", + SqlHelper.CreateParameter("@id", TaskId))) + { + if(dr.Read()) + { + _id = TaskId; + Type = new TaskType( (int)dr.GetByte("taskTypeId") ); + Node = new CMSNode(dr.GetInt("nodeId")); + ParentUser = User.GetUser(dr.GetInt("parentUserId")); + User = User.GetUser(dr.GetInt("userId")); + Date = dr.GetDateTime("DateTime"); + Comment = dr.GetString("comment"); + Closed = dr.GetBoolean("closed"); + } + else + throw new ArgumentException("Task with id: '" + TaskId + "' not found"); + } + } + + #endregion + + #region Public Methods + + /// + /// Saves this instance. + /// + [MethodImpl(MethodImplOptions.Synchronized)] + public void Save() + { + if (Id == 0) + { + // The method is synchronized + SqlHelper.ExecuteNonQuery( + "insert into cmsTask (closed, taskTypeId, nodeId, parentUserId, userId, comment) values (@closed, @taskTypeId, @nodeId, @parentUserId, @userId, @comment)", + SqlHelper.CreateParameter("@closed", Closed), + SqlHelper.CreateParameter("@taskTypeId", Type.Id), + SqlHelper.CreateParameter("@nodeId", Node.Id), + SqlHelper.CreateParameter("@parentUserId", ParentUser.Id), + SqlHelper.CreateParameter("@userId", User.Id), + SqlHelper.CreateParameter("@comment", Comment)); + Id = SqlHelper.ExecuteScalar("SELECT MAX(id) FROM cmsTask"); + } + else + { + SqlHelper.ExecuteNonQuery( + "update cmsTask set closed = @closed, taskTypeId = @taskTypeId, nodeId = @nodeId, parentUserId = @parentUserId, userId = @userId, comment = @comment where id = @id", + SqlHelper.CreateParameter("@closed", Closed), + SqlHelper.CreateParameter("@taskTypeId", Type.Id), + SqlHelper.CreateParameter("@nodeId", Node.Id), + SqlHelper.CreateParameter("@parentUserId", ParentUser.Id), + SqlHelper.CreateParameter("@userId", User.Id), + SqlHelper.CreateParameter("@comment", Comment), + SqlHelper.CreateParameter("@id", Id)); + } + } + + #endregion + + #region static methods + + /// + /// Retrieves a collection of open tasks assigned to the user + /// + /// The User who have the tasks assigned + /// If true both open and closed tasks will be returned + /// A collections of tasks + public static Tasks GetTasks(User User, bool IncludeClosed) { + string sql = "select id from cmsTask where userId = @userId"; + if (!IncludeClosed) + sql += " and closed = 0"; + sql += " order by DateTime desc"; + + Tasks t = new Tasks(); + using (IRecordsReader dr = SqlHelper.ExecuteReader( + sql, + SqlHelper.CreateParameter("@userId", User.Id))) + { + while(dr.Read()) + t.Add( new Task(dr.GetInt("id")) ); + } + + return t; + } + + /// + /// Retrieves a collection of open tasks assigned to the user + /// + /// The User who have the tasks assigned + /// If true both open and closed tasks will be returned + /// A collections of tasks + public static Tasks GetOwnedTasks(User User, bool IncludeClosed) { + string sql = "select id from cmsTask where parentUserId = @userId"; + if (!IncludeClosed) + sql += " and closed = 0"; + sql += " order by DateTime desc"; + + Tasks t = new Tasks(); + using (IRecordsReader dr = SqlHelper.ExecuteReader( + sql, + SqlHelper.CreateParameter("@userId", User.Id))) { + while (dr.Read()) + t.Add(new Task(dr.GetInt("id"))); + } + + return t; + } + + #endregion + } + + /// + /// A collection of tasks. + /// + public class Tasks : CollectionBase + { + /// + /// Adds the specified new task. + /// + /// The new task. + public virtual void Add(Task NewTask) + { + this.List.Add(NewTask); + } + + /// + /// Gets the at the specified index. + /// + /// + public virtual Task this[int Index] + { + get { return (Task) this.List[Index]; } + } + } +} diff --git a/umbraco/cms/businesslogic/task/TaskType.cs b/umbraco/cms/businesslogic/task/TaskType.cs new file mode 100644 index 0000000000..4e1368a5a9 --- /dev/null +++ b/umbraco/cms/businesslogic/task/TaskType.cs @@ -0,0 +1,88 @@ +using System; +using System.Collections.Generic; +using System.Data; +using System.Text; +using System.Runtime.CompilerServices; + +using umbraco.BusinessLogic; +using umbraco.DataLayer; + + +namespace umbraco.cms.businesslogic.task +{ + public class TaskType + { + private int _id; + + public int Id + { + get { return _id; } + set { _id = value; } + } + + private string _alias; + + public string Alias + { + get { return _alias; } + set { _alias = value; } + } + + protected static ISqlHelper SqlHelper + { + get { return Application.SqlHelper; } + } + + public TaskType() + { + } + + public TaskType(string TypeAlias) + { + Id = SqlHelper.ExecuteScalar( + "select id from cmsTaskType where alias = @alias", + SqlHelper.CreateParameter("@alias", TypeAlias)); + setup(); + } + + public TaskType(int TaskTypeId) + { + Id = TaskTypeId; + setup(); + } + + private void setup() + { + using (IRecordsReader dr = + SqlHelper.ExecuteReader("select alias from cmsTaskType where id = @id", + SqlHelper.CreateParameter("@id", Id))) + { + if(dr.Read()) + { + _id = Id; + Alias = dr.GetString("alias"); + } + } + } + + [MethodImpl(MethodImplOptions.Synchronized)] + public void Save() + { + if (Id == 0) + { + // The method is synchronized + SqlHelper.ExecuteNonQuery("INSERT INO cmsTaskType (alias) values (@alias)", + SqlHelper.CreateParameter("@alias", Alias)); + Id = SqlHelper.ExecuteScalar("SELECT MAX(id) FROM cmsTaskType"); + } + else + { + SqlHelper.ExecuteNonQuery( + "update cmsTaskType set alias = @alias where id = @id", + SqlHelper.CreateParameter("@alias", Alias), + SqlHelper.CreateParameter("@id", Id)); + } + } + + } +} diff --git a/umbraco/cms/businesslogic/template/Template.cs b/umbraco/cms/businesslogic/template/Template.cs new file mode 100644 index 0000000000..9fa17e7988 --- /dev/null +++ b/umbraco/cms/businesslogic/template/Template.cs @@ -0,0 +1,734 @@ +using System; +using System.Data; + +using System.Collections; +using System.Xml; +using umbraco.DataLayer; +using System.Text.RegularExpressions; +using System.IO; +using System.Collections.Generic; +using umbraco.cms.businesslogic.cache; + +namespace umbraco.cms.businesslogic.template +{ + /// + /// Summary description for Template. + /// + public class Template : CMSNode + { + private static Guid _objectType = new Guid("6fbde604-4178-42ce-a10b-8a2600a2f07d"); + private string _OutputContentType; + private string _design; + + private string _alias; + private string _oldAlias; + + private int _mastertemplate; + private static bool _templateAliasesInitialized = false; + public static readonly string UmbracoMasterTemplate = GlobalSettings.Path + "/masterpages/default.master"; + private static Hashtable _templateAliases = new Hashtable(); + + private static object templateCacheSyncLock = new object(); + private static readonly string UmbracoTemplateCacheKey = "UmbracoTemplateCache"; + + public string MasterPageFile + { + get { return GlobalSettings.FullpathToRoot + "masterpages" + System.IO.Path.DirectorySeparatorChar + Alias.Replace(" ", "") + ".master"; } + } + + public static Hashtable TemplateAliases + { + get { return _templateAliases; } + set { _templateAliases = value; } + } + + + public Template(int id) + : base(id) + { + // + // TODO: Add constructor logic here + // + setupTemplate(); + } + + public Template(Guid id) + : base(id) + { + // + // TODO: Add constructor logic here + // + setupTemplate(); + } + + /// + /// Used to persist object changes to the database. In Version3.0 it's just a stub for future compatibility + /// + public override void Save() + { + SaveEventArgs e = new SaveEventArgs(); + FireBeforeSave(e); + + if (!e.Cancel) { + FlushCache(); + base.Save(); + FireAfterSave(e); + } + } + + public string GetRawText() + { + return base.Text; + } + + + public override string Text + { + get + { + string tempText = base.Text; + if (!tempText.StartsWith("#")) + return tempText; + else + { + language.Language lang = language.Language.GetByCultureCode(System.Threading.Thread.CurrentThread.CurrentCulture.Name); + if (lang != null) + { + if (Dictionary.DictionaryItem.hasKey(tempText.Substring(1, tempText.Length - 1))) + { + Dictionary.DictionaryItem di = new Dictionary.DictionaryItem(tempText.Substring(1, tempText.Length - 1)); + if (di != null) + return di.Value(lang.id); + } + } + + return "[" + tempText + "]"; + } + } + set + { + FlushCache(); + base.Text = value; + } + } + + public string OutputContentType + { + get { return _OutputContentType; } + set { _OutputContentType = value; } + } + + private void setupTemplate() + { + IRecordsReader dr = SqlHelper.ExecuteReader("Select alias,design,master from cmsTemplate where nodeId = " + this.Id); + if (dr.HasRecords) + { + dr.Read(); + _alias = dr.GetString("alias"); + _design = dr.GetString("design"); + _mastertemplate = dr.GetInt("master"); + } + dr.Close(); + + // test for masterpages + if (UmbracoSettings.UseAspNetMasterPages) + { + _design = getMasterPageContent(); + } + } + + private bool isMasterPageSyntax(string code) + { + return code.Contains("<%@ Master") || code.Contains(" 0); } + } + + public override bool HasChildren + { + get + { + return + SqlHelper.ExecuteScalar("select count(NodeId) as tmp from cmsTemplate where master = " + Id) > 0; + } + set + { + base.HasChildren = value; + } + } + + public int MasterTemplate + { + get { return _mastertemplate; } + set + { + FlushCache(); + _mastertemplate = value; + SqlHelper.ExecuteNonQuery("Update cmsTemplate set master = " + value + " where NodeId = " + this.Id); + } + } + + public string Design + { + get { return _design; } + set + { + FlushCache(); + _design = value.Trim(Environment.NewLine.ToCharArray()); + // NH: Removing an generating the directive can mess up code behind + // We don't store the masterpage directive in the design value + // if (_design.StartsWith("<%@")) + // _design = _design.Substring(_design.IndexOf("%>") + 3).Trim(Environment.NewLine.ToCharArray()); + + if (UmbracoSettings.UseAspNetMasterPages && isMasterPageSyntax(_design)) + { + SaveMasterPageFile(_design); + SqlHelper.ExecuteNonQuery("Update cmsTemplate set design = @design where NodeId = @id", + SqlHelper.CreateParameter("@design", value), + SqlHelper.CreateParameter("@id", Id)); + + } + else + SqlHelper.ExecuteNonQuery("Update cmsTemplate set design = @design where NodeId = @id", + SqlHelper.CreateParameter("@design", value), + SqlHelper.CreateParameter("@id", Id)); + } + } + + public XmlNode ToXml(XmlDocument doc) + { + XmlNode template = doc.CreateElement("Template"); + template.AppendChild(xmlHelper.addTextNode(doc, "Name", this.Text)); + template.AppendChild(xmlHelper.addTextNode(doc, "Alias", this.Alias)); + + if (this.MasterTemplate != 0) + { + template.AppendChild(xmlHelper.addTextNode(doc, "Master", new Template(this.MasterTemplate).Alias)); + } + + template.AppendChild(xmlHelper.addCDataNode(doc, "Design", this.Design)); + + return template; + } + + /// + /// Removes any references to this templates from child templates + /// + public void RemoveAllReferences() { + if (HasChildren) + { + foreach (Template t in Template.GetAllAsList().FindAll(delegate(Template t) { return t.MasterTemplate == this.Id; })) + { + t.MasterTemplate = 0; + } + } + } + + public static Template MakeNew(string Name, BusinessLogic.User u, Template master) { + Template t = MakeNew(Name, u); + t.MasterTemplate = master.Id; + t.Design = ""; + + if (UmbracoSettings.UseAspNetMasterPages) { + string design = t.getMasterPageHeader() + "\n"; + + foreach (string cpId in master.contentPlaceholderIds()) { + design += "\n\t\n\n\n"; + } + + t.Design = design; + } + + t.Save(); + return t; + } + + public static Template MakeNew(string Name, BusinessLogic.User u) + { + // CMSNode MakeNew(int parentId, Guid objectType, int userId, int level, string text, Guid uniqueID) + CMSNode n = CMSNode.MakeNew(-1, _objectType, u.Id, 1, Name, Guid.NewGuid()); + Name = Name.Replace("/", ".").Replace("\\",""); + + if (Name.Length > 100) + Name = Name.Substring(0, 95) + "..."; + + + SqlHelper.ExecuteNonQuery("INSERT INTO cmsTemplate (NodeId, Alias, design, master) VALUES (@nodeId, @alias, @design, @master)", + SqlHelper.CreateParameter("@nodeId", n.Id), + SqlHelper.CreateParameter("@alias", Name), + SqlHelper.CreateParameter("@design", ' '), + SqlHelper.CreateParameter("@master", 0)); + + Template t = new Template(n.Id); + NewEventArgs e = new NewEventArgs(); + t.OnNew(e); + + return t; + } + + public static Template GetByAlias(string Alias) + { + try + { + return new Template(SqlHelper.ExecuteScalar("select nodeId from cmsTemplate where alias = @alias", SqlHelper.CreateParameter("@alias", Alias))); + } + catch + { + return null; + } + } + + [Obsolete("Obsolete, please use GetAllAsList() method instead", true)] + public static Template[] getAll() + { + return GetAllAsList().ToArray(); + } + + public static List